• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     Py_ssize_t norm_len;
4556     wchar_t *norm_path = _Py_normpath_and_size(buffer, len, &norm_len);
4557     PyObject *result = PyUnicode_FromWideChar(norm_path, norm_len);
4558     PyMem_Free(buffer);
4559     return result;
4560 }
4561 
4562 /*[clinic input]
4563 os.mkdir
4564 
4565     path : path_t
4566 
4567     mode: int = 0o777
4568 
4569     *
4570 
4571     dir_fd : dir_fd(requires='mkdirat') = None
4572 
4573 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4574 
4575 Create a directory.
4576 
4577 If dir_fd is not None, it should be a file descriptor open to a directory,
4578   and path should be relative; path will then be relative to that directory.
4579 dir_fd may not be implemented on your platform.
4580   If it is unavailable, using it will raise a NotImplementedError.
4581 
4582 The mode argument is ignored on Windows. Where it is used, the current umask
4583 value is first masked out.
4584 [clinic start generated code]*/
4585 
4586 static PyObject *
os_mkdir_impl(PyObject * module,path_t * path,int mode,int dir_fd)4587 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4588 /*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
4589 {
4590     int result;
4591 #ifdef HAVE_MKDIRAT
4592     int mkdirat_unavailable = 0;
4593 #endif
4594 
4595     if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4596                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4597         return NULL;
4598     }
4599 
4600 #ifdef MS_WINDOWS
4601     Py_BEGIN_ALLOW_THREADS
4602     result = CreateDirectoryW(path->wide, NULL);
4603     Py_END_ALLOW_THREADS
4604 
4605     if (!result)
4606         return path_error(path);
4607 #else
4608     Py_BEGIN_ALLOW_THREADS
4609 #if HAVE_MKDIRAT
4610     if (dir_fd != DEFAULT_DIR_FD) {
4611       if (HAVE_MKDIRAT_RUNTIME) {
4612         result = mkdirat(dir_fd, path->narrow, mode);
4613 
4614       } else {
4615         mkdirat_unavailable = 1;
4616       }
4617     } else
4618 #endif
4619 #if defined(__WATCOMC__) && !defined(__QNX__)
4620         result = mkdir(path->narrow);
4621 #else
4622         result = mkdir(path->narrow, mode);
4623 #endif
4624     Py_END_ALLOW_THREADS
4625 
4626 #if HAVE_MKDIRAT
4627     if (mkdirat_unavailable) {
4628         argument_unavailable_error(NULL, "dir_fd");
4629         return NULL;
4630     }
4631 #endif
4632 
4633     if (result < 0)
4634         return path_error(path);
4635 #endif /* MS_WINDOWS */
4636     Py_RETURN_NONE;
4637 }
4638 
4639 
4640 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4641 #if defined(HAVE_SYS_RESOURCE_H)
4642 #include <sys/resource.h>
4643 #endif
4644 
4645 
4646 #ifdef HAVE_NICE
4647 /*[clinic input]
4648 os.nice
4649 
4650     increment: int
4651     /
4652 
4653 Add increment to the priority of process and return the new priority.
4654 [clinic start generated code]*/
4655 
4656 static PyObject *
os_nice_impl(PyObject * module,int increment)4657 os_nice_impl(PyObject *module, int increment)
4658 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4659 {
4660     int value;
4661 
4662     /* There are two flavours of 'nice': one that returns the new
4663        priority (as required by almost all standards out there) and the
4664        Linux/FreeBSD one, which returns '0' on success and advices
4665        the use of getpriority() to get the new priority.
4666 
4667        If we are of the nice family that returns the new priority, we
4668        need to clear errno before the call, and check if errno is filled
4669        before calling posix_error() on a returnvalue of -1, because the
4670        -1 may be the actual new priority! */
4671 
4672     errno = 0;
4673     value = nice(increment);
4674 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4675     if (value == 0)
4676         value = getpriority(PRIO_PROCESS, 0);
4677 #endif
4678     if (value == -1 && errno != 0)
4679         /* either nice() or getpriority() returned an error */
4680         return posix_error();
4681     return PyLong_FromLong((long) value);
4682 }
4683 #endif /* HAVE_NICE */
4684 
4685 
4686 #ifdef HAVE_GETPRIORITY
4687 /*[clinic input]
4688 os.getpriority
4689 
4690     which: int
4691     who: int
4692 
4693 Return program scheduling priority.
4694 [clinic start generated code]*/
4695 
4696 static PyObject *
os_getpriority_impl(PyObject * module,int which,int who)4697 os_getpriority_impl(PyObject *module, int which, int who)
4698 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4699 {
4700     int retval;
4701 
4702     errno = 0;
4703     retval = getpriority(which, who);
4704     if (errno != 0)
4705         return posix_error();
4706     return PyLong_FromLong((long)retval);
4707 }
4708 #endif /* HAVE_GETPRIORITY */
4709 
4710 
4711 #ifdef HAVE_SETPRIORITY
4712 /*[clinic input]
4713 os.setpriority
4714 
4715     which: int
4716     who: int
4717     priority: int
4718 
4719 Set program scheduling priority.
4720 [clinic start generated code]*/
4721 
4722 static PyObject *
os_setpriority_impl(PyObject * module,int which,int who,int priority)4723 os_setpriority_impl(PyObject *module, int which, int who, int priority)
4724 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4725 {
4726     int retval;
4727 
4728     retval = setpriority(which, who, priority);
4729     if (retval == -1)
4730         return posix_error();
4731     Py_RETURN_NONE;
4732 }
4733 #endif /* HAVE_SETPRIORITY */
4734 
4735 
4736 static PyObject *
internal_rename(path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int is_replace)4737 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4738 {
4739     const char *function_name = is_replace ? "replace" : "rename";
4740     int dir_fd_specified;
4741 
4742 #ifdef HAVE_RENAMEAT
4743     int renameat_unavailable = 0;
4744 #endif
4745 
4746 #ifdef MS_WINDOWS
4747     BOOL result;
4748     int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4749 #else
4750     int result;
4751 #endif
4752 
4753     dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4754                        (dst_dir_fd != DEFAULT_DIR_FD);
4755 #ifndef HAVE_RENAMEAT
4756     if (dir_fd_specified) {
4757         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4758         return NULL;
4759     }
4760 #endif
4761 
4762     if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
4763                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4764                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4765         return NULL;
4766     }
4767 
4768 #ifdef MS_WINDOWS
4769     Py_BEGIN_ALLOW_THREADS
4770     result = MoveFileExW(src->wide, dst->wide, flags);
4771     Py_END_ALLOW_THREADS
4772 
4773     if (!result)
4774         return path_error2(src, dst);
4775 
4776 #else
4777     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4778         PyErr_Format(PyExc_ValueError,
4779                      "%s: src and dst must be the same type", function_name);
4780         return NULL;
4781     }
4782 
4783     Py_BEGIN_ALLOW_THREADS
4784 #ifdef HAVE_RENAMEAT
4785     if (dir_fd_specified) {
4786         if (HAVE_RENAMEAT_RUNTIME) {
4787             result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4788         } else {
4789             renameat_unavailable = 1;
4790         }
4791     } else
4792 #endif
4793     result = rename(src->narrow, dst->narrow);
4794     Py_END_ALLOW_THREADS
4795 
4796 
4797 #ifdef HAVE_RENAMEAT
4798     if (renameat_unavailable) {
4799         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4800         return NULL;
4801     }
4802 #endif
4803 
4804     if (result)
4805         return path_error2(src, dst);
4806 #endif
4807     Py_RETURN_NONE;
4808 }
4809 
4810 
4811 /*[clinic input]
4812 os.rename
4813 
4814     src : path_t
4815     dst : path_t
4816     *
4817     src_dir_fd : dir_fd = None
4818     dst_dir_fd : dir_fd = None
4819 
4820 Rename a file or directory.
4821 
4822 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4823   descriptor open to a directory, and the respective path string (src or dst)
4824   should be relative; the path will then be relative to that directory.
4825 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4826   If they are unavailable, using them will raise a NotImplementedError.
4827 [clinic start generated code]*/
4828 
4829 static PyObject *
os_rename_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4830 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4831                int dst_dir_fd)
4832 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4833 {
4834     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4835 }
4836 
4837 
4838 /*[clinic input]
4839 os.replace = os.rename
4840 
4841 Rename a file or directory, overwriting the destination.
4842 
4843 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4844   descriptor open to a directory, and the respective path string (src or dst)
4845   should be relative; the path will then be relative to that directory.
4846 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4847   If they are unavailable, using them will raise a NotImplementedError.
4848 [clinic start generated code]*/
4849 
4850 static PyObject *
os_replace_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4851 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4852                 int dst_dir_fd)
4853 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4854 {
4855     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4856 }
4857 
4858 
4859 /*[clinic input]
4860 os.rmdir
4861 
4862     path: path_t
4863     *
4864     dir_fd: dir_fd(requires='unlinkat') = None
4865 
4866 Remove a directory.
4867 
4868 If dir_fd is not None, it should be a file descriptor open to a directory,
4869   and path should be relative; path will then be relative to that directory.
4870 dir_fd may not be implemented on your platform.
4871   If it is unavailable, using it will raise a NotImplementedError.
4872 [clinic start generated code]*/
4873 
4874 static PyObject *
os_rmdir_impl(PyObject * module,path_t * path,int dir_fd)4875 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4876 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4877 {
4878     int result;
4879 #ifdef HAVE_UNLINKAT
4880     int unlinkat_unavailable = 0;
4881 #endif
4882 
4883     if (PySys_Audit("os.rmdir", "Oi", path->object,
4884                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4885         return NULL;
4886     }
4887 
4888     Py_BEGIN_ALLOW_THREADS
4889 #ifdef MS_WINDOWS
4890     /* Windows, success=1, UNIX, success=0 */
4891     result = !RemoveDirectoryW(path->wide);
4892 #else
4893 #ifdef HAVE_UNLINKAT
4894     if (dir_fd != DEFAULT_DIR_FD) {
4895       if (HAVE_UNLINKAT_RUNTIME) {
4896         result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4897       } else {
4898         unlinkat_unavailable = 1;
4899         result = -1;
4900       }
4901     } else
4902 #endif
4903         result = rmdir(path->narrow);
4904 #endif
4905     Py_END_ALLOW_THREADS
4906 
4907 #ifdef HAVE_UNLINKAT
4908     if (unlinkat_unavailable) {
4909         argument_unavailable_error("rmdir", "dir_fd");
4910         return NULL;
4911     }
4912 #endif
4913 
4914     if (result)
4915         return path_error(path);
4916 
4917     Py_RETURN_NONE;
4918 }
4919 
4920 
4921 #ifdef HAVE_SYSTEM
4922 #ifdef MS_WINDOWS
4923 /*[clinic input]
4924 os.system -> long
4925 
4926     command: Py_UNICODE
4927 
4928 Execute the command in a subshell.
4929 [clinic start generated code]*/
4930 
4931 static long
os_system_impl(PyObject * module,const Py_UNICODE * command)4932 os_system_impl(PyObject *module, const Py_UNICODE *command)
4933 /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4934 {
4935     long result;
4936 
4937     if (PySys_Audit("os.system", "(u)", command) < 0) {
4938         return -1;
4939     }
4940 
4941     Py_BEGIN_ALLOW_THREADS
4942     _Py_BEGIN_SUPPRESS_IPH
4943     result = _wsystem(command);
4944     _Py_END_SUPPRESS_IPH
4945     Py_END_ALLOW_THREADS
4946     return result;
4947 }
4948 #else /* MS_WINDOWS */
4949 /*[clinic input]
4950 os.system -> long
4951 
4952     command: FSConverter
4953 
4954 Execute the command in a subshell.
4955 [clinic start generated code]*/
4956 
4957 static long
os_system_impl(PyObject * module,PyObject * command)4958 os_system_impl(PyObject *module, PyObject *command)
4959 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4960 {
4961     long result;
4962     const char *bytes = PyBytes_AsString(command);
4963 
4964     if (PySys_Audit("os.system", "(O)", command) < 0) {
4965         return -1;
4966     }
4967 
4968     Py_BEGIN_ALLOW_THREADS
4969     result = system(bytes);
4970     Py_END_ALLOW_THREADS
4971     return result;
4972 }
4973 #endif
4974 #endif /* HAVE_SYSTEM */
4975 
4976 
4977 #ifdef HAVE_UMASK
4978 /*[clinic input]
4979 os.umask
4980 
4981     mask: int
4982     /
4983 
4984 Set the current numeric umask and return the previous umask.
4985 [clinic start generated code]*/
4986 
4987 static PyObject *
os_umask_impl(PyObject * module,int mask)4988 os_umask_impl(PyObject *module, int mask)
4989 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4990 {
4991     int i = (int)umask(mask);
4992     if (i < 0)
4993         return posix_error();
4994     return PyLong_FromLong((long)i);
4995 }
4996 #endif
4997 
4998 #ifdef MS_WINDOWS
4999 
5000 /* override the default DeleteFileW behavior so that directory
5001 symlinks can be removed with this function, the same as with
5002 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)5003 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
5004 {
5005     WIN32_FILE_ATTRIBUTE_DATA info;
5006     WIN32_FIND_DATAW find_data;
5007     HANDLE find_data_handle;
5008     int is_directory = 0;
5009     int is_link = 0;
5010 
5011     if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
5012         is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
5013 
5014         /* Get WIN32_FIND_DATA structure for the path to determine if
5015            it is a symlink */
5016         if(is_directory &&
5017            info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
5018             find_data_handle = FindFirstFileW(lpFileName, &find_data);
5019 
5020             if(find_data_handle != INVALID_HANDLE_VALUE) {
5021                 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
5022                    IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
5023                 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
5024                           find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
5025                 FindClose(find_data_handle);
5026             }
5027         }
5028     }
5029 
5030     if (is_directory && is_link)
5031         return RemoveDirectoryW(lpFileName);
5032 
5033     return DeleteFileW(lpFileName);
5034 }
5035 #endif /* MS_WINDOWS */
5036 
5037 
5038 /*[clinic input]
5039 os.unlink
5040 
5041     path: path_t
5042     *
5043     dir_fd: dir_fd(requires='unlinkat')=None
5044 
5045 Remove a file (same as remove()).
5046 
5047 If dir_fd is not None, it should be a file descriptor open to a directory,
5048   and path should be relative; path will then be relative to that directory.
5049 dir_fd may not be implemented on your platform.
5050   If it is unavailable, using it will raise a NotImplementedError.
5051 
5052 [clinic start generated code]*/
5053 
5054 static PyObject *
os_unlink_impl(PyObject * module,path_t * path,int dir_fd)5055 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
5056 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
5057 {
5058     int result;
5059 #ifdef HAVE_UNLINKAT
5060     int unlinkat_unavailable = 0;
5061 #endif
5062 
5063     if (PySys_Audit("os.remove", "Oi", path->object,
5064                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5065         return NULL;
5066     }
5067 
5068     Py_BEGIN_ALLOW_THREADS
5069     _Py_BEGIN_SUPPRESS_IPH
5070 #ifdef MS_WINDOWS
5071     /* Windows, success=1, UNIX, success=0 */
5072     result = !Py_DeleteFileW(path->wide);
5073 #else
5074 #ifdef HAVE_UNLINKAT
5075     if (dir_fd != DEFAULT_DIR_FD) {
5076       if (HAVE_UNLINKAT_RUNTIME) {
5077 
5078         result = unlinkat(dir_fd, path->narrow, 0);
5079       } else {
5080         unlinkat_unavailable = 1;
5081       }
5082     } else
5083 #endif /* HAVE_UNLINKAT */
5084         result = unlink(path->narrow);
5085 #endif
5086     _Py_END_SUPPRESS_IPH
5087     Py_END_ALLOW_THREADS
5088 
5089 #ifdef HAVE_UNLINKAT
5090     if (unlinkat_unavailable) {
5091         argument_unavailable_error(NULL, "dir_fd");
5092         return NULL;
5093     }
5094 #endif
5095 
5096     if (result)
5097         return path_error(path);
5098 
5099     Py_RETURN_NONE;
5100 }
5101 
5102 
5103 /*[clinic input]
5104 os.remove = os.unlink
5105 
5106 Remove a file (same as unlink()).
5107 
5108 If dir_fd is not None, it should be a file descriptor open to a directory,
5109   and path should be relative; path will then be relative to that directory.
5110 dir_fd may not be implemented on your platform.
5111   If it is unavailable, using it will raise a NotImplementedError.
5112 [clinic start generated code]*/
5113 
5114 static PyObject *
os_remove_impl(PyObject * module,path_t * path,int dir_fd)5115 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
5116 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
5117 {
5118     return os_unlink_impl(module, path, dir_fd);
5119 }
5120 
5121 
5122 static PyStructSequence_Field uname_result_fields[] = {
5123     {"sysname",    "operating system name"},
5124     {"nodename",   "name of machine on network (implementation-defined)"},
5125     {"release",    "operating system release"},
5126     {"version",    "operating system version"},
5127     {"machine",    "hardware identifier"},
5128     {NULL}
5129 };
5130 
5131 PyDoc_STRVAR(uname_result__doc__,
5132 "uname_result: Result from os.uname().\n\n\
5133 This object may be accessed either as a tuple of\n\
5134   (sysname, nodename, release, version, machine),\n\
5135 or via the attributes sysname, nodename, release, version, and machine.\n\
5136 \n\
5137 See os.uname for more information.");
5138 
5139 static PyStructSequence_Desc uname_result_desc = {
5140     MODNAME ".uname_result", /* name */
5141     uname_result__doc__, /* doc */
5142     uname_result_fields,
5143     5
5144 };
5145 
5146 #ifdef HAVE_UNAME
5147 /*[clinic input]
5148 os.uname
5149 
5150 Return an object identifying the current operating system.
5151 
5152 The object behaves like a named tuple with the following fields:
5153   (sysname, nodename, release, version, machine)
5154 
5155 [clinic start generated code]*/
5156 
5157 static PyObject *
os_uname_impl(PyObject * module)5158 os_uname_impl(PyObject *module)
5159 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
5160 {
5161     struct utsname u;
5162     int res;
5163     PyObject *value;
5164 
5165     Py_BEGIN_ALLOW_THREADS
5166     res = uname(&u);
5167     Py_END_ALLOW_THREADS
5168     if (res < 0)
5169         return posix_error();
5170 
5171     PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
5172     value = PyStructSequence_New((PyTypeObject *)UnameResultType);
5173     if (value == NULL)
5174         return NULL;
5175 
5176 #define SET(i, field) \
5177     { \
5178     PyObject *o = PyUnicode_DecodeFSDefault(field); \
5179     if (!o) { \
5180         Py_DECREF(value); \
5181         return NULL; \
5182     } \
5183     PyStructSequence_SET_ITEM(value, i, o); \
5184     } \
5185 
5186     SET(0, u.sysname);
5187     SET(1, u.nodename);
5188     SET(2, u.release);
5189     SET(3, u.version);
5190     SET(4, u.machine);
5191 
5192 #undef SET
5193 
5194     return value;
5195 }
5196 #endif /* HAVE_UNAME */
5197 
5198 
5199 
5200 typedef struct {
5201     int    now;
5202     time_t atime_s;
5203     long   atime_ns;
5204     time_t mtime_s;
5205     long   mtime_ns;
5206 } utime_t;
5207 
5208 /*
5209  * these macros assume that "ut" is a pointer to a utime_t
5210  * they also intentionally leak the declaration of a pointer named "time"
5211  */
5212 #define UTIME_TO_TIMESPEC \
5213     struct timespec ts[2]; \
5214     struct timespec *time; \
5215     if (ut->now) \
5216         time = NULL; \
5217     else { \
5218         ts[0].tv_sec = ut->atime_s; \
5219         ts[0].tv_nsec = ut->atime_ns; \
5220         ts[1].tv_sec = ut->mtime_s; \
5221         ts[1].tv_nsec = ut->mtime_ns; \
5222         time = ts; \
5223     } \
5224 
5225 #define UTIME_TO_TIMEVAL \
5226     struct timeval tv[2]; \
5227     struct timeval *time; \
5228     if (ut->now) \
5229         time = NULL; \
5230     else { \
5231         tv[0].tv_sec = ut->atime_s; \
5232         tv[0].tv_usec = ut->atime_ns / 1000; \
5233         tv[1].tv_sec = ut->mtime_s; \
5234         tv[1].tv_usec = ut->mtime_ns / 1000; \
5235         time = tv; \
5236     } \
5237 
5238 #define UTIME_TO_UTIMBUF \
5239     struct utimbuf u; \
5240     struct utimbuf *time; \
5241     if (ut->now) \
5242         time = NULL; \
5243     else { \
5244         u.actime = ut->atime_s; \
5245         u.modtime = ut->mtime_s; \
5246         time = &u; \
5247     }
5248 
5249 #define UTIME_TO_TIME_T \
5250     time_t timet[2]; \
5251     time_t *time; \
5252     if (ut->now) \
5253         time = NULL; \
5254     else { \
5255         timet[0] = ut->atime_s; \
5256         timet[1] = ut->mtime_s; \
5257         time = timet; \
5258     } \
5259 
5260 
5261 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5262 
5263 static int
utime_dir_fd(utime_t * ut,int dir_fd,const char * path,int follow_symlinks)5264 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
5265 {
5266 #if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
5267     if (HAVE_UTIMENSAT_RUNTIME) {
5268         int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5269         UTIME_TO_TIMESPEC;
5270         return utimensat(dir_fd, path, time, flags);
5271     }  else {
5272         errno = ENOSYS;
5273         return -1;
5274     }
5275 #elif defined(HAVE_UTIMENSAT)
5276     int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5277     UTIME_TO_TIMESPEC;
5278     return utimensat(dir_fd, path, time, flags);
5279 #elif defined(HAVE_FUTIMESAT)
5280     UTIME_TO_TIMEVAL;
5281     /*
5282      * follow_symlinks will never be false here;
5283      * we only allow !follow_symlinks and dir_fd together
5284      * if we have utimensat()
5285      */
5286     assert(follow_symlinks);
5287     return futimesat(dir_fd, path, time);
5288 #endif
5289 }
5290 
5291     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
5292 #else
5293     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
5294 #endif
5295 
5296 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5297 
5298 static int
utime_fd(utime_t * ut,int fd)5299 utime_fd(utime_t *ut, int fd)
5300 {
5301 #ifdef HAVE_FUTIMENS
5302 
5303     if (HAVE_FUTIMENS_RUNTIME) {
5304 
5305     UTIME_TO_TIMESPEC;
5306     return futimens(fd, time);
5307 
5308     } else
5309 #ifndef HAVE_FUTIMES
5310     {
5311         /* Not sure if this can happen */
5312         PyErr_SetString(
5313             PyExc_RuntimeError,
5314             "neither futimens nor futimes are supported"
5315             " on this system");
5316         return -1;
5317     }
5318 #endif
5319 
5320 #endif
5321 #ifdef HAVE_FUTIMES
5322     {
5323     UTIME_TO_TIMEVAL;
5324     return futimes(fd, time);
5325     }
5326 #endif
5327 }
5328 
5329     #define PATH_UTIME_HAVE_FD 1
5330 #else
5331     #define PATH_UTIME_HAVE_FD 0
5332 #endif
5333 
5334 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
5335 #  define UTIME_HAVE_NOFOLLOW_SYMLINKS
5336 #endif
5337 
5338 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5339 
5340 static int
utime_nofollow_symlinks(utime_t * ut,const char * path)5341 utime_nofollow_symlinks(utime_t *ut, const char *path)
5342 {
5343 #ifdef HAVE_UTIMENSAT
5344     if (HAVE_UTIMENSAT_RUNTIME) {
5345         UTIME_TO_TIMESPEC;
5346         return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
5347     } else
5348 #ifndef HAVE_LUTIMES
5349     {
5350         /* Not sure if this can happen */
5351         PyErr_SetString(
5352             PyExc_RuntimeError,
5353             "neither utimensat nor lutimes are supported"
5354             " on this system");
5355         return -1;
5356     }
5357 #endif
5358 #endif
5359 
5360 #ifdef HAVE_LUTIMES
5361     {
5362     UTIME_TO_TIMEVAL;
5363     return lutimes(path, time);
5364     }
5365 #endif
5366 }
5367 
5368 #endif
5369 
5370 #ifndef MS_WINDOWS
5371 
5372 static int
utime_default(utime_t * ut,const char * path)5373 utime_default(utime_t *ut, const char *path)
5374 {
5375 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5376     if (HAVE_UTIMENSAT_RUNTIME) {
5377         UTIME_TO_TIMESPEC;
5378         return utimensat(DEFAULT_DIR_FD, path, time, 0);
5379     } else {
5380         UTIME_TO_TIMEVAL;
5381         return utimes(path, time);
5382     }
5383 #elif defined(HAVE_UTIMENSAT)
5384     UTIME_TO_TIMESPEC;
5385     return utimensat(DEFAULT_DIR_FD, path, time, 0);
5386 #elif defined(HAVE_UTIMES)
5387     UTIME_TO_TIMEVAL;
5388     return utimes(path, time);
5389 #elif defined(HAVE_UTIME_H)
5390     UTIME_TO_UTIMBUF;
5391     return utime(path, time);
5392 #else
5393     UTIME_TO_TIME_T;
5394     return utime(path, time);
5395 #endif
5396 }
5397 
5398 #endif
5399 
5400 static int
split_py_long_to_s_and_ns(PyObject * module,PyObject * py_long,time_t * s,long * ns)5401 split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5402 {
5403     int result = 0;
5404     PyObject *divmod;
5405     divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5406     if (!divmod)
5407         goto exit;
5408     if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
5409         PyErr_Format(PyExc_TypeError,
5410                      "%.200s.__divmod__() must return a 2-tuple, not %.200s",
5411                      _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
5412         goto exit;
5413     }
5414     *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5415     if ((*s == -1) && PyErr_Occurred())
5416         goto exit;
5417     *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5418     if ((*ns == -1) && PyErr_Occurred())
5419         goto exit;
5420 
5421     result = 1;
5422 exit:
5423     Py_XDECREF(divmod);
5424     return result;
5425 }
5426 
5427 
5428 /*[clinic input]
5429 os.utime
5430 
5431     path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
5432     times: object = None
5433     *
5434     ns: object = NULL
5435     dir_fd: dir_fd(requires='futimensat') = None
5436     follow_symlinks: bool=True
5437 
5438 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
5439 
5440 Set the access and modified time of path.
5441 
5442 path may always be specified as a string.
5443 On some platforms, path may also be specified as an open file descriptor.
5444   If this functionality is unavailable, using it raises an exception.
5445 
5446 If times is not None, it must be a tuple (atime, mtime);
5447     atime and mtime should be expressed as float seconds since the epoch.
5448 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
5449     atime_ns and mtime_ns should be expressed as integer nanoseconds
5450     since the epoch.
5451 If times is None and ns is unspecified, utime uses the current time.
5452 Specifying tuples for both times and ns is an error.
5453 
5454 If dir_fd is not None, it should be a file descriptor open to a directory,
5455   and path should be relative; path will then be relative to that directory.
5456 If follow_symlinks is False, and the last element of the path is a symbolic
5457   link, utime will modify the symbolic link itself instead of the file the
5458   link points to.
5459 It is an error to use dir_fd or follow_symlinks when specifying path
5460   as an open file descriptor.
5461 dir_fd and follow_symlinks may not be available on your platform.
5462   If they are unavailable, using them will raise a NotImplementedError.
5463 
5464 [clinic start generated code]*/
5465 
5466 static PyObject *
os_utime_impl(PyObject * module,path_t * path,PyObject * times,PyObject * ns,int dir_fd,int follow_symlinks)5467 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
5468               int dir_fd, int follow_symlinks)
5469 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
5470 {
5471 #ifdef MS_WINDOWS
5472     HANDLE hFile;
5473     FILETIME atime, mtime;
5474 #else
5475     int result;
5476 #endif
5477 
5478     utime_t utime;
5479 
5480     memset(&utime, 0, sizeof(utime_t));
5481 
5482     if (times != Py_None && ns) {
5483         PyErr_SetString(PyExc_ValueError,
5484                      "utime: you may specify either 'times'"
5485                      " or 'ns' but not both");
5486         return NULL;
5487     }
5488 
5489     if (times != Py_None) {
5490         time_t a_sec, m_sec;
5491         long a_nsec, m_nsec;
5492         if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
5493             PyErr_SetString(PyExc_TypeError,
5494                          "utime: 'times' must be either"
5495                          " a tuple of two ints or None");
5496             return NULL;
5497         }
5498         utime.now = 0;
5499         if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
5500                                      &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
5501             _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
5502                                      &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
5503             return NULL;
5504         }
5505         utime.atime_s = a_sec;
5506         utime.atime_ns = a_nsec;
5507         utime.mtime_s = m_sec;
5508         utime.mtime_ns = m_nsec;
5509     }
5510     else if (ns) {
5511         if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
5512             PyErr_SetString(PyExc_TypeError,
5513                          "utime: 'ns' must be a tuple of two ints");
5514             return NULL;
5515         }
5516         utime.now = 0;
5517         if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
5518                                       &utime.atime_s, &utime.atime_ns) ||
5519             !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
5520                                        &utime.mtime_s, &utime.mtime_ns)) {
5521             return NULL;
5522         }
5523     }
5524     else {
5525         /* times and ns are both None/unspecified. use "now". */
5526         utime.now = 1;
5527     }
5528 
5529 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
5530     if (follow_symlinks_specified("utime", follow_symlinks))
5531         return NULL;
5532 #endif
5533 
5534     if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
5535         dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
5536         fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
5537         return NULL;
5538 
5539 #if !defined(HAVE_UTIMENSAT)
5540     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
5541         PyErr_SetString(PyExc_ValueError,
5542                      "utime: cannot use dir_fd and follow_symlinks "
5543                      "together on this platform");
5544         return NULL;
5545     }
5546 #endif
5547 
5548     if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
5549                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5550         return NULL;
5551     }
5552 
5553 #ifdef MS_WINDOWS
5554     Py_BEGIN_ALLOW_THREADS
5555     hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
5556                         NULL, OPEN_EXISTING,
5557                         FILE_FLAG_BACKUP_SEMANTICS, NULL);
5558     Py_END_ALLOW_THREADS
5559     if (hFile == INVALID_HANDLE_VALUE) {
5560         path_error(path);
5561         return NULL;
5562     }
5563 
5564     if (utime.now) {
5565         GetSystemTimeAsFileTime(&mtime);
5566         atime = mtime;
5567     }
5568     else {
5569         _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
5570         _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
5571     }
5572     if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
5573         /* Avoid putting the file name into the error here,
5574            as that may confuse the user into believing that
5575            something is wrong with the file, when it also
5576            could be the time stamp that gives a problem. */
5577         PyErr_SetFromWindowsErr(0);
5578         CloseHandle(hFile);
5579         return NULL;
5580     }
5581     CloseHandle(hFile);
5582 #else /* MS_WINDOWS */
5583     Py_BEGIN_ALLOW_THREADS
5584 
5585 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5586     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
5587         result = utime_nofollow_symlinks(&utime, path->narrow);
5588     else
5589 #endif
5590 
5591 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5592     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
5593         result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
5594 
5595     } else
5596 #endif
5597 
5598 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5599     if (path->fd != -1)
5600         result = utime_fd(&utime, path->fd);
5601     else
5602 #endif
5603 
5604     result = utime_default(&utime, path->narrow);
5605 
5606     Py_END_ALLOW_THREADS
5607 
5608 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5609     /* See utime_dir_fd implementation */
5610     if (result == -1 && errno == ENOSYS) {
5611         argument_unavailable_error(NULL, "dir_fd");
5612         return NULL;
5613     }
5614 #endif
5615 
5616     if (result < 0) {
5617         /* see previous comment about not putting filename in error here */
5618         posix_error();
5619         return NULL;
5620     }
5621 
5622 #endif /* MS_WINDOWS */
5623 
5624     Py_RETURN_NONE;
5625 }
5626 
5627 /* Process operations */
5628 
5629 
5630 /*[clinic input]
5631 os._exit
5632 
5633     status: int
5634 
5635 Exit to the system with specified status, without normal exit processing.
5636 [clinic start generated code]*/
5637 
5638 static PyObject *
os__exit_impl(PyObject * module,int status)5639 os__exit_impl(PyObject *module, int status)
5640 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5641 {
5642     _exit(status);
5643     return NULL; /* Make gcc -Wall happy */
5644 }
5645 
5646 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5647 #define EXECV_CHAR wchar_t
5648 #else
5649 #define EXECV_CHAR char
5650 #endif
5651 
5652 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5653 static void
free_string_array(EXECV_CHAR ** array,Py_ssize_t count)5654 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5655 {
5656     Py_ssize_t i;
5657     for (i = 0; i < count; i++)
5658         PyMem_Free(array[i]);
5659     PyMem_Free(array);
5660 }
5661 
5662 static int
fsconvert_strdup(PyObject * o,EXECV_CHAR ** out)5663 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5664 {
5665     Py_ssize_t size;
5666     PyObject *ub;
5667     int result = 0;
5668 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5669     if (!PyUnicode_FSDecoder(o, &ub))
5670         return 0;
5671     *out = PyUnicode_AsWideCharString(ub, &size);
5672     if (*out)
5673         result = 1;
5674 #else
5675     if (!PyUnicode_FSConverter(o, &ub))
5676         return 0;
5677     size = PyBytes_GET_SIZE(ub);
5678     *out = PyMem_Malloc(size + 1);
5679     if (*out) {
5680         memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5681         result = 1;
5682     } else
5683         PyErr_NoMemory();
5684 #endif
5685     Py_DECREF(ub);
5686     return result;
5687 }
5688 #endif
5689 
5690 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5691 static EXECV_CHAR**
parse_envlist(PyObject * env,Py_ssize_t * envc_ptr)5692 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5693 {
5694     Py_ssize_t i, pos, envc;
5695     PyObject *keys=NULL, *vals=NULL;
5696     PyObject *key, *val, *key2, *val2, *keyval;
5697     EXECV_CHAR **envlist;
5698 
5699     i = PyMapping_Size(env);
5700     if (i < 0)
5701         return NULL;
5702     envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5703     if (envlist == NULL) {
5704         PyErr_NoMemory();
5705         return NULL;
5706     }
5707     envc = 0;
5708     keys = PyMapping_Keys(env);
5709     if (!keys)
5710         goto error;
5711     vals = PyMapping_Values(env);
5712     if (!vals)
5713         goto error;
5714     if (!PyList_Check(keys) || !PyList_Check(vals)) {
5715         PyErr_Format(PyExc_TypeError,
5716                      "env.keys() or env.values() is not a list");
5717         goto error;
5718     }
5719 
5720     for (pos = 0; pos < i; pos++) {
5721         key = PyList_GetItem(keys, pos);
5722         val = PyList_GetItem(vals, pos);
5723         if (!key || !val)
5724             goto error;
5725 
5726 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5727         if (!PyUnicode_FSDecoder(key, &key2))
5728             goto error;
5729         if (!PyUnicode_FSDecoder(val, &val2)) {
5730             Py_DECREF(key2);
5731             goto error;
5732         }
5733         /* Search from index 1 because on Windows starting '=' is allowed for
5734            defining hidden environment variables. */
5735         if (PyUnicode_GET_LENGTH(key2) == 0 ||
5736             PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5737         {
5738             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5739             Py_DECREF(key2);
5740             Py_DECREF(val2);
5741             goto error;
5742         }
5743         keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5744 #else
5745         if (!PyUnicode_FSConverter(key, &key2))
5746             goto error;
5747         if (!PyUnicode_FSConverter(val, &val2)) {
5748             Py_DECREF(key2);
5749             goto error;
5750         }
5751         if (PyBytes_GET_SIZE(key2) == 0 ||
5752             strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5753         {
5754             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5755             Py_DECREF(key2);
5756             Py_DECREF(val2);
5757             goto error;
5758         }
5759         keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5760                                              PyBytes_AS_STRING(val2));
5761 #endif
5762         Py_DECREF(key2);
5763         Py_DECREF(val2);
5764         if (!keyval)
5765             goto error;
5766 
5767         if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5768             Py_DECREF(keyval);
5769             goto error;
5770         }
5771 
5772         Py_DECREF(keyval);
5773     }
5774     Py_DECREF(vals);
5775     Py_DECREF(keys);
5776 
5777     envlist[envc] = 0;
5778     *envc_ptr = envc;
5779     return envlist;
5780 
5781 error:
5782     Py_XDECREF(keys);
5783     Py_XDECREF(vals);
5784     free_string_array(envlist, envc);
5785     return NULL;
5786 }
5787 
5788 static EXECV_CHAR**
parse_arglist(PyObject * argv,Py_ssize_t * argc)5789 parse_arglist(PyObject* argv, Py_ssize_t *argc)
5790 {
5791     int i;
5792     EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5793     if (argvlist == NULL) {
5794         PyErr_NoMemory();
5795         return NULL;
5796     }
5797     for (i = 0; i < *argc; i++) {
5798         PyObject* item = PySequence_ITEM(argv, i);
5799         if (item == NULL)
5800             goto fail;
5801         if (!fsconvert_strdup(item, &argvlist[i])) {
5802             Py_DECREF(item);
5803             goto fail;
5804         }
5805         Py_DECREF(item);
5806     }
5807     argvlist[*argc] = NULL;
5808     return argvlist;
5809 fail:
5810     *argc = i;
5811     free_string_array(argvlist, *argc);
5812     return NULL;
5813 }
5814 
5815 #endif
5816 
5817 
5818 #ifdef HAVE_EXECV
5819 /*[clinic input]
5820 os.execv
5821 
5822     path: path_t
5823         Path of executable file.
5824     argv: object
5825         Tuple or list of strings.
5826     /
5827 
5828 Execute an executable path with arguments, replacing current process.
5829 [clinic start generated code]*/
5830 
5831 static PyObject *
os_execv_impl(PyObject * module,path_t * path,PyObject * argv)5832 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5833 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5834 {
5835     EXECV_CHAR **argvlist;
5836     Py_ssize_t argc;
5837 
5838     /* execv has two arguments: (path, argv), where
5839        argv is a list or tuple of strings. */
5840 
5841     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5842         PyErr_SetString(PyExc_TypeError,
5843                         "execv() arg 2 must be a tuple or list");
5844         return NULL;
5845     }
5846     argc = PySequence_Size(argv);
5847     if (argc < 1) {
5848         PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5849         return NULL;
5850     }
5851 
5852     argvlist = parse_arglist(argv, &argc);
5853     if (argvlist == NULL) {
5854         return NULL;
5855     }
5856     if (!argvlist[0][0]) {
5857         PyErr_SetString(PyExc_ValueError,
5858             "execv() arg 2 first element cannot be empty");
5859         free_string_array(argvlist, argc);
5860         return NULL;
5861     }
5862 
5863     if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5864         free_string_array(argvlist, argc);
5865         return NULL;
5866     }
5867 
5868     _Py_BEGIN_SUPPRESS_IPH
5869 #ifdef HAVE_WEXECV
5870     _wexecv(path->wide, argvlist);
5871 #else
5872     execv(path->narrow, argvlist);
5873 #endif
5874     _Py_END_SUPPRESS_IPH
5875 
5876     /* If we get here it's definitely an error */
5877 
5878     free_string_array(argvlist, argc);
5879     return posix_error();
5880 }
5881 
5882 
5883 /*[clinic input]
5884 os.execve
5885 
5886     path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5887         Path of executable file.
5888     argv: object
5889         Tuple or list of strings.
5890     env: object
5891         Dictionary of strings mapping to strings.
5892 
5893 Execute an executable path with arguments, replacing current process.
5894 [clinic start generated code]*/
5895 
5896 static PyObject *
os_execve_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env)5897 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5898 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5899 {
5900     EXECV_CHAR **argvlist = NULL;
5901     EXECV_CHAR **envlist;
5902     Py_ssize_t argc, envc;
5903 
5904     /* execve has three arguments: (path, argv, env), where
5905        argv is a list or tuple of strings and env is a dictionary
5906        like posix.environ. */
5907 
5908     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5909         PyErr_SetString(PyExc_TypeError,
5910                         "execve: argv must be a tuple or list");
5911         goto fail_0;
5912     }
5913     argc = PySequence_Size(argv);
5914     if (argc < 1) {
5915         PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5916         return NULL;
5917     }
5918 
5919     if (!PyMapping_Check(env)) {
5920         PyErr_SetString(PyExc_TypeError,
5921                         "execve: environment must be a mapping object");
5922         goto fail_0;
5923     }
5924 
5925     argvlist = parse_arglist(argv, &argc);
5926     if (argvlist == NULL) {
5927         goto fail_0;
5928     }
5929     if (!argvlist[0][0]) {
5930         PyErr_SetString(PyExc_ValueError,
5931             "execve: argv first element cannot be empty");
5932         goto fail_0;
5933     }
5934 
5935     envlist = parse_envlist(env, &envc);
5936     if (envlist == NULL)
5937         goto fail_0;
5938 
5939     if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5940         goto fail_1;
5941     }
5942 
5943     _Py_BEGIN_SUPPRESS_IPH
5944 #ifdef HAVE_FEXECVE
5945     if (path->fd > -1)
5946         fexecve(path->fd, argvlist, envlist);
5947     else
5948 #endif
5949 #ifdef HAVE_WEXECV
5950         _wexecve(path->wide, argvlist, envlist);
5951 #else
5952         execve(path->narrow, argvlist, envlist);
5953 #endif
5954     _Py_END_SUPPRESS_IPH
5955 
5956     /* If we get here it's definitely an error */
5957 
5958     posix_path_error(path);
5959   fail_1:
5960     free_string_array(envlist, envc);
5961   fail_0:
5962     if (argvlist)
5963         free_string_array(argvlist, argc);
5964     return NULL;
5965 }
5966 
5967 #endif /* HAVE_EXECV */
5968 
5969 #ifdef HAVE_POSIX_SPAWN
5970 
5971 enum posix_spawn_file_actions_identifier {
5972     POSIX_SPAWN_OPEN,
5973     POSIX_SPAWN_CLOSE,
5974     POSIX_SPAWN_DUP2
5975 };
5976 
5977 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
5978 static int
5979 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
5980 #endif
5981 
5982 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)5983 parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
5984                         int resetids, int setsid, PyObject *setsigmask,
5985                         PyObject *setsigdef, PyObject *scheduler,
5986                         posix_spawnattr_t *attrp)
5987 {
5988     long all_flags = 0;
5989 
5990     errno = posix_spawnattr_init(attrp);
5991     if (errno) {
5992         posix_error();
5993         return -1;
5994     }
5995 
5996     if (setpgroup) {
5997         pid_t pgid = PyLong_AsPid(setpgroup);
5998         if (pgid == (pid_t)-1 && PyErr_Occurred()) {
5999             goto fail;
6000         }
6001         errno = posix_spawnattr_setpgroup(attrp, pgid);
6002         if (errno) {
6003             posix_error();
6004             goto fail;
6005         }
6006         all_flags |= POSIX_SPAWN_SETPGROUP;
6007     }
6008 
6009     if (resetids) {
6010         all_flags |= POSIX_SPAWN_RESETIDS;
6011     }
6012 
6013     if (setsid) {
6014 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
6015         if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
6016 #endif
6017 #ifdef POSIX_SPAWN_SETSID
6018         all_flags |= POSIX_SPAWN_SETSID;
6019 #elif defined(POSIX_SPAWN_SETSID_NP)
6020         all_flags |= POSIX_SPAWN_SETSID_NP;
6021 #else
6022         argument_unavailable_error(func_name, "setsid");
6023         return -1;
6024 #endif
6025 
6026 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
6027         } else {
6028             argument_unavailable_error(func_name, "setsid");
6029             return -1;
6030         }
6031 #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
6032 
6033     }
6034 
6035 #ifdef HAVE_SIGSET_T
6036    if (setsigmask) {
6037         sigset_t set;
6038         if (!_Py_Sigset_Converter(setsigmask, &set)) {
6039             goto fail;
6040         }
6041         errno = posix_spawnattr_setsigmask(attrp, &set);
6042         if (errno) {
6043             posix_error();
6044             goto fail;
6045         }
6046         all_flags |= POSIX_SPAWN_SETSIGMASK;
6047     }
6048 
6049     if (setsigdef) {
6050         sigset_t set;
6051         if (!_Py_Sigset_Converter(setsigdef, &set)) {
6052             goto fail;
6053         }
6054         errno = posix_spawnattr_setsigdefault(attrp, &set);
6055         if (errno) {
6056             posix_error();
6057             goto fail;
6058         }
6059         all_flags |= POSIX_SPAWN_SETSIGDEF;
6060     }
6061 #else
6062     if (setsigmask || setsigdef) {
6063         PyErr_SetString(PyExc_NotImplementedError,
6064                         "sigset is not supported on this platform");
6065         goto fail;
6066     }
6067 #endif
6068 
6069     if (scheduler) {
6070 #ifdef POSIX_SPAWN_SETSCHEDULER
6071         PyObject *py_schedpolicy;
6072         PyObject *schedparam_obj;
6073         struct sched_param schedparam;
6074 
6075         if (!PyArg_ParseTuple(scheduler, "OO"
6076                         ";A scheduler tuple must have two elements",
6077                         &py_schedpolicy, &schedparam_obj)) {
6078             goto fail;
6079         }
6080         if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
6081             goto fail;
6082         }
6083         if (py_schedpolicy != Py_None) {
6084             int schedpolicy = _PyLong_AsInt(py_schedpolicy);
6085 
6086             if (schedpolicy == -1 && PyErr_Occurred()) {
6087                 goto fail;
6088             }
6089             errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
6090             if (errno) {
6091                 posix_error();
6092                 goto fail;
6093             }
6094             all_flags |= POSIX_SPAWN_SETSCHEDULER;
6095         }
6096         errno = posix_spawnattr_setschedparam(attrp, &schedparam);
6097         if (errno) {
6098             posix_error();
6099             goto fail;
6100         }
6101         all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
6102 #else
6103         PyErr_SetString(PyExc_NotImplementedError,
6104                 "The scheduler option is not supported in this system.");
6105         goto fail;
6106 #endif
6107     }
6108 
6109     errno = posix_spawnattr_setflags(attrp, all_flags);
6110     if (errno) {
6111         posix_error();
6112         goto fail;
6113     }
6114 
6115     return 0;
6116 
6117 fail:
6118     (void)posix_spawnattr_destroy(attrp);
6119     return -1;
6120 }
6121 
6122 static int
parse_file_actions(PyObject * file_actions,posix_spawn_file_actions_t * file_actionsp,PyObject * temp_buffer)6123 parse_file_actions(PyObject *file_actions,
6124                    posix_spawn_file_actions_t *file_actionsp,
6125                    PyObject *temp_buffer)
6126 {
6127     PyObject *seq;
6128     PyObject *file_action = NULL;
6129     PyObject *tag_obj;
6130 
6131     seq = PySequence_Fast(file_actions,
6132                           "file_actions must be a sequence or None");
6133     if (seq == NULL) {
6134         return -1;
6135     }
6136 
6137     errno = posix_spawn_file_actions_init(file_actionsp);
6138     if (errno) {
6139         posix_error();
6140         Py_DECREF(seq);
6141         return -1;
6142     }
6143 
6144     for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
6145         file_action = PySequence_Fast_GET_ITEM(seq, i);
6146         Py_INCREF(file_action);
6147         if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
6148             PyErr_SetString(PyExc_TypeError,
6149                 "Each file_actions element must be a non-empty tuple");
6150             goto fail;
6151         }
6152         long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
6153         if (tag == -1 && PyErr_Occurred()) {
6154             goto fail;
6155         }
6156 
6157         /* Populate the file_actions object */
6158         switch (tag) {
6159             case POSIX_SPAWN_OPEN: {
6160                 int fd, oflag;
6161                 PyObject *path;
6162                 unsigned long mode;
6163                 if (!PyArg_ParseTuple(file_action, "OiO&ik"
6164                         ";A open file_action tuple must have 5 elements",
6165                         &tag_obj, &fd, PyUnicode_FSConverter, &path,
6166                         &oflag, &mode))
6167                 {
6168                     goto fail;
6169                 }
6170                 if (PyList_Append(temp_buffer, path)) {
6171                     Py_DECREF(path);
6172                     goto fail;
6173                 }
6174                 errno = posix_spawn_file_actions_addopen(file_actionsp,
6175                         fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
6176                 Py_DECREF(path);
6177                 if (errno) {
6178                     posix_error();
6179                     goto fail;
6180                 }
6181                 break;
6182             }
6183             case POSIX_SPAWN_CLOSE: {
6184                 int fd;
6185                 if (!PyArg_ParseTuple(file_action, "Oi"
6186                         ";A close file_action tuple must have 2 elements",
6187                         &tag_obj, &fd))
6188                 {
6189                     goto fail;
6190                 }
6191                 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
6192                 if (errno) {
6193                     posix_error();
6194                     goto fail;
6195                 }
6196                 break;
6197             }
6198             case POSIX_SPAWN_DUP2: {
6199                 int fd1, fd2;
6200                 if (!PyArg_ParseTuple(file_action, "Oii"
6201                         ";A dup2 file_action tuple must have 3 elements",
6202                         &tag_obj, &fd1, &fd2))
6203                 {
6204                     goto fail;
6205                 }
6206                 errno = posix_spawn_file_actions_adddup2(file_actionsp,
6207                                                          fd1, fd2);
6208                 if (errno) {
6209                     posix_error();
6210                     goto fail;
6211                 }
6212                 break;
6213             }
6214             default: {
6215                 PyErr_SetString(PyExc_TypeError,
6216                                 "Unknown file_actions identifier");
6217                 goto fail;
6218             }
6219         }
6220         Py_DECREF(file_action);
6221     }
6222 
6223     Py_DECREF(seq);
6224     return 0;
6225 
6226 fail:
6227     Py_DECREF(seq);
6228     Py_DECREF(file_action);
6229     (void)posix_spawn_file_actions_destroy(file_actionsp);
6230     return -1;
6231 }
6232 
6233 
6234 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)6235 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
6236                PyObject *env, PyObject *file_actions,
6237                PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
6238                PyObject *setsigdef, PyObject *scheduler)
6239 {
6240     const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
6241     EXECV_CHAR **argvlist = NULL;
6242     EXECV_CHAR **envlist = NULL;
6243     posix_spawn_file_actions_t file_actions_buf;
6244     posix_spawn_file_actions_t *file_actionsp = NULL;
6245     posix_spawnattr_t attr;
6246     posix_spawnattr_t *attrp = NULL;
6247     Py_ssize_t argc, envc;
6248     PyObject *result = NULL;
6249     PyObject *temp_buffer = NULL;
6250     pid_t pid;
6251     int err_code;
6252 
6253     /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
6254        argv is a list or tuple of strings and env is a dictionary
6255        like posix.environ. */
6256 
6257     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6258         PyErr_Format(PyExc_TypeError,
6259                      "%s: argv must be a tuple or list", func_name);
6260         goto exit;
6261     }
6262     argc = PySequence_Size(argv);
6263     if (argc < 1) {
6264         PyErr_Format(PyExc_ValueError,
6265                      "%s: argv must not be empty", func_name);
6266         return NULL;
6267     }
6268 
6269     if (!PyMapping_Check(env)) {
6270         PyErr_Format(PyExc_TypeError,
6271                      "%s: environment must be a mapping object", func_name);
6272         goto exit;
6273     }
6274 
6275     argvlist = parse_arglist(argv, &argc);
6276     if (argvlist == NULL) {
6277         goto exit;
6278     }
6279     if (!argvlist[0][0]) {
6280         PyErr_Format(PyExc_ValueError,
6281                      "%s: argv first element cannot be empty", func_name);
6282         goto exit;
6283     }
6284 
6285     envlist = parse_envlist(env, &envc);
6286     if (envlist == NULL) {
6287         goto exit;
6288     }
6289 
6290     if (file_actions != NULL && file_actions != Py_None) {
6291         /* There is a bug in old versions of glibc that makes some of the
6292          * helper functions for manipulating file actions not copy the provided
6293          * buffers. The problem is that posix_spawn_file_actions_addopen does not
6294          * copy the value of path for some old versions of glibc (<2.20).
6295          * The use of temp_buffer here is a workaround that keeps the
6296          * python objects that own the buffers alive until posix_spawn gets called.
6297          * Check https://bugs.python.org/issue33630 and
6298          * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
6299         temp_buffer = PyList_New(0);
6300         if (!temp_buffer) {
6301             goto exit;
6302         }
6303         if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
6304             goto exit;
6305         }
6306         file_actionsp = &file_actions_buf;
6307     }
6308 
6309     if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
6310                                 setsigmask, setsigdef, scheduler, &attr)) {
6311         goto exit;
6312     }
6313     attrp = &attr;
6314 
6315     if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
6316         goto exit;
6317     }
6318 
6319     _Py_BEGIN_SUPPRESS_IPH
6320 #ifdef HAVE_POSIX_SPAWNP
6321     if (use_posix_spawnp) {
6322         err_code = posix_spawnp(&pid, path->narrow,
6323                                 file_actionsp, attrp, argvlist, envlist);
6324     }
6325     else
6326 #endif /* HAVE_POSIX_SPAWNP */
6327     {
6328         err_code = posix_spawn(&pid, path->narrow,
6329                                file_actionsp, attrp, argvlist, envlist);
6330     }
6331     _Py_END_SUPPRESS_IPH
6332 
6333     if (err_code) {
6334         errno = err_code;
6335         PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
6336         goto exit;
6337     }
6338 #ifdef _Py_MEMORY_SANITIZER
6339     __msan_unpoison(&pid, sizeof(pid));
6340 #endif
6341     result = PyLong_FromPid(pid);
6342 
6343 exit:
6344     if (file_actionsp) {
6345         (void)posix_spawn_file_actions_destroy(file_actionsp);
6346     }
6347     if (attrp) {
6348         (void)posix_spawnattr_destroy(attrp);
6349     }
6350     if (envlist) {
6351         free_string_array(envlist, envc);
6352     }
6353     if (argvlist) {
6354         free_string_array(argvlist, argc);
6355     }
6356     Py_XDECREF(temp_buffer);
6357     return result;
6358 }
6359 
6360 
6361 /*[clinic input]
6362 
6363 os.posix_spawn
6364     path: path_t
6365         Path of executable file.
6366     argv: object
6367         Tuple or list of strings.
6368     env: object
6369         Dictionary of strings mapping to strings.
6370     /
6371     *
6372     file_actions: object(c_default='NULL') = ()
6373         A sequence of file action tuples.
6374     setpgroup: object = NULL
6375         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6376     resetids: bool(accept={int}) = False
6377         If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
6378     setsid: bool(accept={int}) = False
6379         If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6380     setsigmask: object(c_default='NULL') = ()
6381         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6382     setsigdef: object(c_default='NULL') = ()
6383         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6384     scheduler: object = NULL
6385         A tuple with the scheduler policy (optional) and parameters.
6386 
6387 Execute the program specified by path in a new process.
6388 [clinic start generated code]*/
6389 
6390 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)6391 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
6392                     PyObject *env, PyObject *file_actions,
6393                     PyObject *setpgroup, int resetids, int setsid,
6394                     PyObject *setsigmask, PyObject *setsigdef,
6395                     PyObject *scheduler)
6396 /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
6397 {
6398     return py_posix_spawn(0, module, path, argv, env, file_actions,
6399                           setpgroup, resetids, setsid, setsigmask, setsigdef,
6400                           scheduler);
6401 }
6402  #endif /* HAVE_POSIX_SPAWN */
6403 
6404 
6405 
6406 #ifdef HAVE_POSIX_SPAWNP
6407 /*[clinic input]
6408 
6409 os.posix_spawnp
6410     path: path_t
6411         Path of executable file.
6412     argv: object
6413         Tuple or list of strings.
6414     env: object
6415         Dictionary of strings mapping to strings.
6416     /
6417     *
6418     file_actions: object(c_default='NULL') = ()
6419         A sequence of file action tuples.
6420     setpgroup: object = NULL
6421         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6422     resetids: bool(accept={int}) = False
6423         If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
6424     setsid: bool(accept={int}) = False
6425         If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6426     setsigmask: object(c_default='NULL') = ()
6427         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6428     setsigdef: object(c_default='NULL') = ()
6429         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6430     scheduler: object = NULL
6431         A tuple with the scheduler policy (optional) and parameters.
6432 
6433 Execute the program specified by path in a new process.
6434 [clinic start generated code]*/
6435 
6436 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)6437 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
6438                      PyObject *env, PyObject *file_actions,
6439                      PyObject *setpgroup, int resetids, int setsid,
6440                      PyObject *setsigmask, PyObject *setsigdef,
6441                      PyObject *scheduler)
6442 /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
6443 {
6444     return py_posix_spawn(1, module, path, argv, env, file_actions,
6445                           setpgroup, resetids, setsid, setsigmask, setsigdef,
6446                           scheduler);
6447 }
6448 #endif /* HAVE_POSIX_SPAWNP */
6449 
6450 #ifdef HAVE_RTPSPAWN
6451 static intptr_t
_rtp_spawn(int mode,const char * rtpFileName,const char * argv[],const char * envp[])6452 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
6453                const char  *envp[])
6454 {
6455      RTP_ID rtpid;
6456      int status;
6457      pid_t res;
6458      int async_err = 0;
6459 
6460      /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
6461         uStackSize=0 cannot be used, the default stack size is too small for
6462         Python. */
6463      if (envp) {
6464          rtpid = rtpSpawn(rtpFileName, argv, envp,
6465                           100, 0x1000000, 0, VX_FP_TASK);
6466      }
6467      else {
6468          rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
6469                           100, 0x1000000, 0, VX_FP_TASK);
6470      }
6471      if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
6472          do {
6473              res = waitpid((pid_t)rtpid, &status, 0);
6474          } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6475 
6476          if (res < 0)
6477              return RTP_ID_ERROR;
6478          return ((intptr_t)status);
6479      }
6480      return ((intptr_t)rtpid);
6481 }
6482 #endif
6483 
6484 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
6485 /*[clinic input]
6486 os.spawnv
6487 
6488     mode: int
6489         Mode of process creation.
6490     path: path_t
6491         Path of executable file.
6492     argv: object
6493         Tuple or list of strings.
6494     /
6495 
6496 Execute the program specified by path in a new process.
6497 [clinic start generated code]*/
6498 
6499 static PyObject *
os_spawnv_impl(PyObject * module,int mode,path_t * path,PyObject * argv)6500 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
6501 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
6502 {
6503     EXECV_CHAR **argvlist;
6504     int i;
6505     Py_ssize_t argc;
6506     intptr_t spawnval;
6507     PyObject *(*getitem)(PyObject *, Py_ssize_t);
6508 
6509     /* spawnv has three arguments: (mode, path, argv), where
6510        argv is a list or tuple of strings. */
6511 
6512     if (PyList_Check(argv)) {
6513         argc = PyList_Size(argv);
6514         getitem = PyList_GetItem;
6515     }
6516     else if (PyTuple_Check(argv)) {
6517         argc = PyTuple_Size(argv);
6518         getitem = PyTuple_GetItem;
6519     }
6520     else {
6521         PyErr_SetString(PyExc_TypeError,
6522                         "spawnv() arg 2 must be a tuple or list");
6523         return NULL;
6524     }
6525     if (argc == 0) {
6526         PyErr_SetString(PyExc_ValueError,
6527             "spawnv() arg 2 cannot be empty");
6528         return NULL;
6529     }
6530 
6531     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6532     if (argvlist == NULL) {
6533         return PyErr_NoMemory();
6534     }
6535     for (i = 0; i < argc; i++) {
6536         if (!fsconvert_strdup((*getitem)(argv, i),
6537                               &argvlist[i])) {
6538             free_string_array(argvlist, i);
6539             PyErr_SetString(
6540                 PyExc_TypeError,
6541                 "spawnv() arg 2 must contain only strings");
6542             return NULL;
6543         }
6544         if (i == 0 && !argvlist[0][0]) {
6545             free_string_array(argvlist, i + 1);
6546             PyErr_SetString(
6547                 PyExc_ValueError,
6548                 "spawnv() arg 2 first element cannot be empty");
6549             return NULL;
6550         }
6551     }
6552     argvlist[argc] = NULL;
6553 
6554 #if !defined(HAVE_RTPSPAWN)
6555     if (mode == _OLD_P_OVERLAY)
6556         mode = _P_OVERLAY;
6557 #endif
6558 
6559     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
6560                     Py_None) < 0) {
6561         free_string_array(argvlist, argc);
6562         return NULL;
6563     }
6564 
6565     Py_BEGIN_ALLOW_THREADS
6566     _Py_BEGIN_SUPPRESS_IPH
6567 #ifdef HAVE_WSPAWNV
6568     spawnval = _wspawnv(mode, path->wide, argvlist);
6569 #elif defined(HAVE_RTPSPAWN)
6570     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
6571 #else
6572     spawnval = _spawnv(mode, path->narrow, argvlist);
6573 #endif
6574     _Py_END_SUPPRESS_IPH
6575     Py_END_ALLOW_THREADS
6576 
6577     free_string_array(argvlist, argc);
6578 
6579     if (spawnval == -1)
6580         return posix_error();
6581     else
6582         return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6583 }
6584 
6585 /*[clinic input]
6586 os.spawnve
6587 
6588     mode: int
6589         Mode of process creation.
6590     path: path_t
6591         Path of executable file.
6592     argv: object
6593         Tuple or list of strings.
6594     env: object
6595         Dictionary of strings mapping to strings.
6596     /
6597 
6598 Execute the program specified by path in a new process.
6599 [clinic start generated code]*/
6600 
6601 static PyObject *
os_spawnve_impl(PyObject * module,int mode,path_t * path,PyObject * argv,PyObject * env)6602 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
6603                 PyObject *env)
6604 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
6605 {
6606     EXECV_CHAR **argvlist;
6607     EXECV_CHAR **envlist;
6608     PyObject *res = NULL;
6609     Py_ssize_t argc, i, envc;
6610     intptr_t spawnval;
6611     PyObject *(*getitem)(PyObject *, Py_ssize_t);
6612     Py_ssize_t lastarg = 0;
6613 
6614     /* spawnve has four arguments: (mode, path, argv, env), where
6615        argv is a list or tuple of strings and env is a dictionary
6616        like posix.environ. */
6617 
6618     if (PyList_Check(argv)) {
6619         argc = PyList_Size(argv);
6620         getitem = PyList_GetItem;
6621     }
6622     else if (PyTuple_Check(argv)) {
6623         argc = PyTuple_Size(argv);
6624         getitem = PyTuple_GetItem;
6625     }
6626     else {
6627         PyErr_SetString(PyExc_TypeError,
6628                         "spawnve() arg 2 must be a tuple or list");
6629         goto fail_0;
6630     }
6631     if (argc == 0) {
6632         PyErr_SetString(PyExc_ValueError,
6633             "spawnve() arg 2 cannot be empty");
6634         goto fail_0;
6635     }
6636     if (!PyMapping_Check(env)) {
6637         PyErr_SetString(PyExc_TypeError,
6638                         "spawnve() arg 3 must be a mapping object");
6639         goto fail_0;
6640     }
6641 
6642     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6643     if (argvlist == NULL) {
6644         PyErr_NoMemory();
6645         goto fail_0;
6646     }
6647     for (i = 0; i < argc; i++) {
6648         if (!fsconvert_strdup((*getitem)(argv, i),
6649                               &argvlist[i]))
6650         {
6651             lastarg = i;
6652             goto fail_1;
6653         }
6654         if (i == 0 && !argvlist[0][0]) {
6655             lastarg = i + 1;
6656             PyErr_SetString(
6657                 PyExc_ValueError,
6658                 "spawnv() arg 2 first element cannot be empty");
6659             goto fail_1;
6660         }
6661     }
6662     lastarg = argc;
6663     argvlist[argc] = NULL;
6664 
6665     envlist = parse_envlist(env, &envc);
6666     if (envlist == NULL)
6667         goto fail_1;
6668 
6669 #if !defined(HAVE_RTPSPAWN)
6670     if (mode == _OLD_P_OVERLAY)
6671         mode = _P_OVERLAY;
6672 #endif
6673 
6674     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6675         goto fail_2;
6676     }
6677 
6678     Py_BEGIN_ALLOW_THREADS
6679     _Py_BEGIN_SUPPRESS_IPH
6680 #ifdef HAVE_WSPAWNV
6681     spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6682 #elif defined(HAVE_RTPSPAWN)
6683     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6684                            (const char **)envlist);
6685 #else
6686     spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6687 #endif
6688     _Py_END_SUPPRESS_IPH
6689     Py_END_ALLOW_THREADS
6690 
6691     if (spawnval == -1)
6692         (void) posix_error();
6693     else
6694         res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6695 
6696   fail_2:
6697     while (--envc >= 0) {
6698         PyMem_Free(envlist[envc]);
6699     }
6700     PyMem_Free(envlist);
6701   fail_1:
6702     free_string_array(argvlist, lastarg);
6703   fail_0:
6704     return res;
6705 }
6706 
6707 #endif /* HAVE_SPAWNV */
6708 
6709 #ifdef HAVE_FORK
6710 
6711 /* Helper function to validate arguments.
6712    Returns 0 on success.  non-zero on failure with a TypeError raised.
6713    If obj is non-NULL it must be callable.  */
6714 static int
check_null_or_callable(PyObject * obj,const char * obj_name)6715 check_null_or_callable(PyObject *obj, const char* obj_name)
6716 {
6717     if (obj && !PyCallable_Check(obj)) {
6718         PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6719                      obj_name, _PyType_Name(Py_TYPE(obj)));
6720         return -1;
6721     }
6722     return 0;
6723 }
6724 
6725 /*[clinic input]
6726 os.register_at_fork
6727 
6728     *
6729     before: object=NULL
6730         A callable to be called in the parent before the fork() syscall.
6731     after_in_child: object=NULL
6732         A callable to be called in the child after fork().
6733     after_in_parent: object=NULL
6734         A callable to be called in the parent after fork().
6735 
6736 Register callables to be called when forking a new process.
6737 
6738 'before' callbacks are called in reverse order.
6739 'after_in_child' and 'after_in_parent' callbacks are called in order.
6740 
6741 [clinic start generated code]*/
6742 
6743 static PyObject *
os_register_at_fork_impl(PyObject * module,PyObject * before,PyObject * after_in_child,PyObject * after_in_parent)6744 os_register_at_fork_impl(PyObject *module, PyObject *before,
6745                          PyObject *after_in_child, PyObject *after_in_parent)
6746 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6747 {
6748     PyInterpreterState *interp;
6749 
6750     if (!before && !after_in_child && !after_in_parent) {
6751         PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6752         return NULL;
6753     }
6754     if (check_null_or_callable(before, "before") ||
6755         check_null_or_callable(after_in_child, "after_in_child") ||
6756         check_null_or_callable(after_in_parent, "after_in_parent")) {
6757         return NULL;
6758     }
6759     interp = _PyInterpreterState_GET();
6760 
6761     if (register_at_forker(&interp->before_forkers, before)) {
6762         return NULL;
6763     }
6764     if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6765         return NULL;
6766     }
6767     if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6768         return NULL;
6769     }
6770     Py_RETURN_NONE;
6771 }
6772 #endif /* HAVE_FORK */
6773 
6774 
6775 #ifdef HAVE_FORK1
6776 /*[clinic input]
6777 os.fork1
6778 
6779 Fork a child process with a single multiplexed (i.e., not bound) thread.
6780 
6781 Return 0 to child process and PID of child to parent process.
6782 [clinic start generated code]*/
6783 
6784 static PyObject *
os_fork1_impl(PyObject * module)6785 os_fork1_impl(PyObject *module)
6786 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6787 {
6788     pid_t pid;
6789 
6790     if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
6791         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6792         return NULL;
6793     }
6794     PyOS_BeforeFork();
6795     pid = fork1();
6796     if (pid == 0) {
6797         /* child: this clobbers and resets the import lock. */
6798         PyOS_AfterFork_Child();
6799     } else {
6800         /* parent: release the import lock. */
6801         PyOS_AfterFork_Parent();
6802     }
6803     if (pid == -1)
6804         return posix_error();
6805     return PyLong_FromPid(pid);
6806 }
6807 #endif /* HAVE_FORK1 */
6808 
6809 
6810 #ifdef HAVE_FORK
6811 /*[clinic input]
6812 os.fork
6813 
6814 Fork a child process.
6815 
6816 Return 0 to child process and PID of child to parent process.
6817 [clinic start generated code]*/
6818 
6819 static PyObject *
os_fork_impl(PyObject * module)6820 os_fork_impl(PyObject *module)
6821 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6822 {
6823     pid_t pid;
6824     PyInterpreterState *interp = _PyInterpreterState_GET();
6825     if (interp->config._isolated_interpreter) {
6826         PyErr_SetString(PyExc_RuntimeError,
6827                         "fork not supported for isolated subinterpreters");
6828         return NULL;
6829     }
6830     if (PySys_Audit("os.fork", NULL) < 0) {
6831         return NULL;
6832     }
6833     PyOS_BeforeFork();
6834     pid = fork();
6835     if (pid == 0) {
6836         /* child: this clobbers and resets the import lock. */
6837         PyOS_AfterFork_Child();
6838     } else {
6839         /* parent: release the import lock. */
6840         PyOS_AfterFork_Parent();
6841     }
6842     if (pid == -1)
6843         return posix_error();
6844     return PyLong_FromPid(pid);
6845 }
6846 #endif /* HAVE_FORK */
6847 
6848 
6849 #ifdef HAVE_SCHED_H
6850 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6851 /*[clinic input]
6852 os.sched_get_priority_max
6853 
6854     policy: int
6855 
6856 Get the maximum scheduling priority for policy.
6857 [clinic start generated code]*/
6858 
6859 static PyObject *
os_sched_get_priority_max_impl(PyObject * module,int policy)6860 os_sched_get_priority_max_impl(PyObject *module, int policy)
6861 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6862 {
6863     int max;
6864 
6865     max = sched_get_priority_max(policy);
6866     if (max < 0)
6867         return posix_error();
6868     return PyLong_FromLong(max);
6869 }
6870 
6871 
6872 /*[clinic input]
6873 os.sched_get_priority_min
6874 
6875     policy: int
6876 
6877 Get the minimum scheduling priority for policy.
6878 [clinic start generated code]*/
6879 
6880 static PyObject *
os_sched_get_priority_min_impl(PyObject * module,int policy)6881 os_sched_get_priority_min_impl(PyObject *module, int policy)
6882 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6883 {
6884     int min = sched_get_priority_min(policy);
6885     if (min < 0)
6886         return posix_error();
6887     return PyLong_FromLong(min);
6888 }
6889 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6890 
6891 
6892 #ifdef HAVE_SCHED_SETSCHEDULER
6893 /*[clinic input]
6894 os.sched_getscheduler
6895     pid: pid_t
6896     /
6897 
6898 Get the scheduling policy for the process identified by pid.
6899 
6900 Passing 0 for pid returns the scheduling policy for the calling process.
6901 [clinic start generated code]*/
6902 
6903 static PyObject *
os_sched_getscheduler_impl(PyObject * module,pid_t pid)6904 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6905 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
6906 {
6907     int policy;
6908 
6909     policy = sched_getscheduler(pid);
6910     if (policy < 0)
6911         return posix_error();
6912     return PyLong_FromLong(policy);
6913 }
6914 #endif /* HAVE_SCHED_SETSCHEDULER */
6915 
6916 
6917 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6918 /*[clinic input]
6919 class os.sched_param "PyObject *" "SchedParamType"
6920 
6921 @classmethod
6922 os.sched_param.__new__
6923 
6924     sched_priority: object
6925         A scheduling parameter.
6926 
6927 Currently has only one field: sched_priority
6928 [clinic start generated code]*/
6929 
6930 static PyObject *
os_sched_param_impl(PyTypeObject * type,PyObject * sched_priority)6931 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6932 /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
6933 {
6934     PyObject *res;
6935 
6936     res = PyStructSequence_New(type);
6937     if (!res)
6938         return NULL;
6939     Py_INCREF(sched_priority);
6940     PyStructSequence_SET_ITEM(res, 0, sched_priority);
6941     return res;
6942 }
6943 
6944 PyDoc_VAR(os_sched_param__doc__);
6945 
6946 static PyStructSequence_Field sched_param_fields[] = {
6947     {"sched_priority", "the scheduling priority"},
6948     {0}
6949 };
6950 
6951 static PyStructSequence_Desc sched_param_desc = {
6952     "sched_param", /* name */
6953     os_sched_param__doc__, /* doc */
6954     sched_param_fields,
6955     1
6956 };
6957 
6958 static int
convert_sched_param(PyObject * module,PyObject * param,struct sched_param * res)6959 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
6960 {
6961     long priority;
6962 
6963     if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
6964         PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
6965         return 0;
6966     }
6967     priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
6968     if (priority == -1 && PyErr_Occurred())
6969         return 0;
6970     if (priority > INT_MAX || priority < INT_MIN) {
6971         PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
6972         return 0;
6973     }
6974     res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
6975     return 1;
6976 }
6977 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
6978 
6979 
6980 #ifdef HAVE_SCHED_SETSCHEDULER
6981 /*[clinic input]
6982 os.sched_setscheduler
6983 
6984     pid: pid_t
6985     policy: int
6986     param as param_obj: object
6987     /
6988 
6989 Set the scheduling policy for the process identified by pid.
6990 
6991 If pid is 0, the calling process is changed.
6992 param is an instance of sched_param.
6993 [clinic start generated code]*/
6994 
6995 static PyObject *
os_sched_setscheduler_impl(PyObject * module,pid_t pid,int policy,PyObject * param_obj)6996 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
6997                            PyObject *param_obj)
6998 /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
6999 {
7000     struct sched_param param;
7001     if (!convert_sched_param(module, param_obj, &param)) {
7002         return NULL;
7003     }
7004 
7005     /*
7006     ** sched_setscheduler() returns 0 in Linux, but the previous
7007     ** scheduling policy under Solaris/Illumos, and others.
7008     ** On error, -1 is returned in all Operating Systems.
7009     */
7010     if (sched_setscheduler(pid, policy, &param) == -1)
7011         return posix_error();
7012     Py_RETURN_NONE;
7013 }
7014 #endif  /* HAVE_SCHED_SETSCHEDULER*/
7015 
7016 
7017 #ifdef HAVE_SCHED_SETPARAM
7018 /*[clinic input]
7019 os.sched_getparam
7020     pid: pid_t
7021     /
7022 
7023 Returns scheduling parameters for the process identified by pid.
7024 
7025 If pid is 0, returns parameters for the calling process.
7026 Return value is an instance of sched_param.
7027 [clinic start generated code]*/
7028 
7029 static PyObject *
os_sched_getparam_impl(PyObject * module,pid_t pid)7030 os_sched_getparam_impl(PyObject *module, pid_t pid)
7031 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
7032 {
7033     struct sched_param param;
7034     PyObject *result;
7035     PyObject *priority;
7036 
7037     if (sched_getparam(pid, &param))
7038         return posix_error();
7039     PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
7040     result = PyStructSequence_New((PyTypeObject *)SchedParamType);
7041     if (!result)
7042         return NULL;
7043     priority = PyLong_FromLong(param.sched_priority);
7044     if (!priority) {
7045         Py_DECREF(result);
7046         return NULL;
7047     }
7048     PyStructSequence_SET_ITEM(result, 0, priority);
7049     return result;
7050 }
7051 
7052 
7053 /*[clinic input]
7054 os.sched_setparam
7055     pid: pid_t
7056     param as param_obj: object
7057     /
7058 
7059 Set scheduling parameters for the process identified by pid.
7060 
7061 If pid is 0, sets parameters for the calling process.
7062 param should be an instance of sched_param.
7063 [clinic start generated code]*/
7064 
7065 static PyObject *
os_sched_setparam_impl(PyObject * module,pid_t pid,PyObject * param_obj)7066 os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
7067 /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
7068 {
7069     struct sched_param param;
7070     if (!convert_sched_param(module, param_obj, &param)) {
7071         return NULL;
7072     }
7073 
7074     if (sched_setparam(pid, &param))
7075         return posix_error();
7076     Py_RETURN_NONE;
7077 }
7078 #endif /* HAVE_SCHED_SETPARAM */
7079 
7080 
7081 #ifdef HAVE_SCHED_RR_GET_INTERVAL
7082 /*[clinic input]
7083 os.sched_rr_get_interval -> double
7084     pid: pid_t
7085     /
7086 
7087 Return the round-robin quantum for the process identified by pid, in seconds.
7088 
7089 Value returned is a float.
7090 [clinic start generated code]*/
7091 
7092 static double
os_sched_rr_get_interval_impl(PyObject * module,pid_t pid)7093 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
7094 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
7095 {
7096     struct timespec interval;
7097     if (sched_rr_get_interval(pid, &interval)) {
7098         posix_error();
7099         return -1.0;
7100     }
7101 #ifdef _Py_MEMORY_SANITIZER
7102     __msan_unpoison(&interval, sizeof(interval));
7103 #endif
7104     return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
7105 }
7106 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
7107 
7108 
7109 /*[clinic input]
7110 os.sched_yield
7111 
7112 Voluntarily relinquish the CPU.
7113 [clinic start generated code]*/
7114 
7115 static PyObject *
os_sched_yield_impl(PyObject * module)7116 os_sched_yield_impl(PyObject *module)
7117 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
7118 {
7119     int result;
7120     Py_BEGIN_ALLOW_THREADS
7121     result = sched_yield();
7122     Py_END_ALLOW_THREADS
7123     if (result < 0) {
7124         return posix_error();
7125     }
7126     Py_RETURN_NONE;
7127 }
7128 
7129 #ifdef HAVE_SCHED_SETAFFINITY
7130 /* The minimum number of CPUs allocated in a cpu_set_t */
7131 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
7132 
7133 /*[clinic input]
7134 os.sched_setaffinity
7135     pid: pid_t
7136     mask : object
7137     /
7138 
7139 Set the CPU affinity of the process identified by pid to mask.
7140 
7141 mask should be an iterable of integers identifying CPUs.
7142 [clinic start generated code]*/
7143 
7144 static PyObject *
os_sched_setaffinity_impl(PyObject * module,pid_t pid,PyObject * mask)7145 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
7146 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
7147 {
7148     int ncpus;
7149     size_t setsize;
7150     cpu_set_t *cpu_set = NULL;
7151     PyObject *iterator = NULL, *item;
7152 
7153     iterator = PyObject_GetIter(mask);
7154     if (iterator == NULL)
7155         return NULL;
7156 
7157     ncpus = NCPUS_START;
7158     setsize = CPU_ALLOC_SIZE(ncpus);
7159     cpu_set = CPU_ALLOC(ncpus);
7160     if (cpu_set == NULL) {
7161         PyErr_NoMemory();
7162         goto error;
7163     }
7164     CPU_ZERO_S(setsize, cpu_set);
7165 
7166     while ((item = PyIter_Next(iterator))) {
7167         long cpu;
7168         if (!PyLong_Check(item)) {
7169             PyErr_Format(PyExc_TypeError,
7170                         "expected an iterator of ints, "
7171                         "but iterator yielded %R",
7172                         Py_TYPE(item));
7173             Py_DECREF(item);
7174             goto error;
7175         }
7176         cpu = PyLong_AsLong(item);
7177         Py_DECREF(item);
7178         if (cpu < 0) {
7179             if (!PyErr_Occurred())
7180                 PyErr_SetString(PyExc_ValueError, "negative CPU number");
7181             goto error;
7182         }
7183         if (cpu > INT_MAX - 1) {
7184             PyErr_SetString(PyExc_OverflowError, "CPU number too large");
7185             goto error;
7186         }
7187         if (cpu >= ncpus) {
7188             /* Grow CPU mask to fit the CPU number */
7189             int newncpus = ncpus;
7190             cpu_set_t *newmask;
7191             size_t newsetsize;
7192             while (newncpus <= cpu) {
7193                 if (newncpus > INT_MAX / 2)
7194                     newncpus = cpu + 1;
7195                 else
7196                     newncpus = newncpus * 2;
7197             }
7198             newmask = CPU_ALLOC(newncpus);
7199             if (newmask == NULL) {
7200                 PyErr_NoMemory();
7201                 goto error;
7202             }
7203             newsetsize = CPU_ALLOC_SIZE(newncpus);
7204             CPU_ZERO_S(newsetsize, newmask);
7205             memcpy(newmask, cpu_set, setsize);
7206             CPU_FREE(cpu_set);
7207             setsize = newsetsize;
7208             cpu_set = newmask;
7209             ncpus = newncpus;
7210         }
7211         CPU_SET_S(cpu, setsize, cpu_set);
7212     }
7213     if (PyErr_Occurred()) {
7214         goto error;
7215     }
7216     Py_CLEAR(iterator);
7217 
7218     if (sched_setaffinity(pid, setsize, cpu_set)) {
7219         posix_error();
7220         goto error;
7221     }
7222     CPU_FREE(cpu_set);
7223     Py_RETURN_NONE;
7224 
7225 error:
7226     if (cpu_set)
7227         CPU_FREE(cpu_set);
7228     Py_XDECREF(iterator);
7229     return NULL;
7230 }
7231 
7232 
7233 /*[clinic input]
7234 os.sched_getaffinity
7235     pid: pid_t
7236     /
7237 
7238 Return the affinity of the process identified by pid (or the current process if zero).
7239 
7240 The affinity is returned as a set of CPU identifiers.
7241 [clinic start generated code]*/
7242 
7243 static PyObject *
os_sched_getaffinity_impl(PyObject * module,pid_t pid)7244 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
7245 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
7246 {
7247     int cpu, ncpus, count;
7248     size_t setsize;
7249     cpu_set_t *mask = NULL;
7250     PyObject *res = NULL;
7251 
7252     ncpus = NCPUS_START;
7253     while (1) {
7254         setsize = CPU_ALLOC_SIZE(ncpus);
7255         mask = CPU_ALLOC(ncpus);
7256         if (mask == NULL)
7257             return PyErr_NoMemory();
7258         if (sched_getaffinity(pid, setsize, mask) == 0)
7259             break;
7260         CPU_FREE(mask);
7261         if (errno != EINVAL)
7262             return posix_error();
7263         if (ncpus > INT_MAX / 2) {
7264             PyErr_SetString(PyExc_OverflowError, "could not allocate "
7265                             "a large enough CPU set");
7266             return NULL;
7267         }
7268         ncpus = ncpus * 2;
7269     }
7270 
7271     res = PySet_New(NULL);
7272     if (res == NULL)
7273         goto error;
7274     for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7275         if (CPU_ISSET_S(cpu, setsize, mask)) {
7276             PyObject *cpu_num = PyLong_FromLong(cpu);
7277             --count;
7278             if (cpu_num == NULL)
7279                 goto error;
7280             if (PySet_Add(res, cpu_num)) {
7281                 Py_DECREF(cpu_num);
7282                 goto error;
7283             }
7284             Py_DECREF(cpu_num);
7285         }
7286     }
7287     CPU_FREE(mask);
7288     return res;
7289 
7290 error:
7291     if (mask)
7292         CPU_FREE(mask);
7293     Py_XDECREF(res);
7294     return NULL;
7295 }
7296 
7297 #endif /* HAVE_SCHED_SETAFFINITY */
7298 
7299 #endif /* HAVE_SCHED_H */
7300 
7301 
7302 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
7303 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
7304 #  define DEV_PTY_FILE "/dev/ptc"
7305 #  define HAVE_DEV_PTMX
7306 #else
7307 #  define DEV_PTY_FILE "/dev/ptmx"
7308 #endif
7309 
7310 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
7311 #ifdef HAVE_PTY_H
7312 #include <pty.h>
7313 #ifdef HAVE_UTMP_H
7314 #include <utmp.h>
7315 #endif /* HAVE_UTMP_H */
7316 #elif defined(HAVE_LIBUTIL_H)
7317 #include <libutil.h>
7318 #elif defined(HAVE_UTIL_H)
7319 #include <util.h>
7320 #endif /* HAVE_PTY_H */
7321 #ifdef HAVE_STROPTS_H
7322 #include <stropts.h>
7323 #endif
7324 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
7325 
7326 
7327 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7328 /*[clinic input]
7329 os.openpty
7330 
7331 Open a pseudo-terminal.
7332 
7333 Return a tuple of (master_fd, slave_fd) containing open file descriptors
7334 for both the master and slave ends.
7335 [clinic start generated code]*/
7336 
7337 static PyObject *
os_openpty_impl(PyObject * module)7338 os_openpty_impl(PyObject *module)
7339 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
7340 {
7341     int master_fd = -1, slave_fd = -1;
7342 #ifndef HAVE_OPENPTY
7343     char * slave_name;
7344 #endif
7345 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
7346     PyOS_sighandler_t sig_saved;
7347 #if defined(__sun) && defined(__SVR4)
7348     extern char *ptsname(int fildes);
7349 #endif
7350 #endif
7351 
7352 #ifdef HAVE_OPENPTY
7353     if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
7354         goto posix_error;
7355 
7356     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7357         goto error;
7358     if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
7359         goto error;
7360 
7361 #elif defined(HAVE__GETPTY)
7362     slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
7363     if (slave_name == NULL)
7364         goto posix_error;
7365     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7366         goto error;
7367 
7368     slave_fd = _Py_open(slave_name, O_RDWR);
7369     if (slave_fd < 0)
7370         goto error;
7371 
7372 #else
7373     master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
7374     if (master_fd < 0)
7375         goto posix_error;
7376 
7377     sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
7378 
7379     /* change permission of slave */
7380     if (grantpt(master_fd) < 0) {
7381         PyOS_setsig(SIGCHLD, sig_saved);
7382         goto posix_error;
7383     }
7384 
7385     /* unlock slave */
7386     if (unlockpt(master_fd) < 0) {
7387         PyOS_setsig(SIGCHLD, sig_saved);
7388         goto posix_error;
7389     }
7390 
7391     PyOS_setsig(SIGCHLD, sig_saved);
7392 
7393     slave_name = ptsname(master_fd); /* get name of slave */
7394     if (slave_name == NULL)
7395         goto posix_error;
7396 
7397     slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
7398     if (slave_fd == -1)
7399         goto error;
7400 
7401     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7402         goto posix_error;
7403 
7404 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
7405     ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
7406     ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
7407 #ifndef __hpux
7408     ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
7409 #endif /* __hpux */
7410 #endif /* HAVE_CYGWIN */
7411 #endif /* HAVE_OPENPTY */
7412 
7413     return Py_BuildValue("(ii)", master_fd, slave_fd);
7414 
7415 posix_error:
7416     posix_error();
7417 error:
7418     if (master_fd != -1)
7419         close(master_fd);
7420     if (slave_fd != -1)
7421         close(slave_fd);
7422     return NULL;
7423 }
7424 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
7425 
7426 
7427 #if defined(HAVE_SETSID) && defined(TIOCSCTTY)
7428 #define HAVE_FALLBACK_LOGIN_TTY 1
7429 #endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
7430 
7431 #if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
7432 /*[clinic input]
7433 os.login_tty
7434 
7435     fd: fildes
7436     /
7437 
7438 Prepare the tty of which fd is a file descriptor for a new login session.
7439 
7440 Make the calling process a session leader; make the tty the
7441 controlling tty, the stdin, the stdout, and the stderr of the
7442 calling process; close fd.
7443 [clinic start generated code]*/
7444 
7445 static PyObject *
os_login_tty_impl(PyObject * module,int fd)7446 os_login_tty_impl(PyObject *module, int fd)
7447 /*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
7448 {
7449 #ifdef HAVE_LOGIN_TTY
7450     if (login_tty(fd) == -1) {
7451         return posix_error();
7452     }
7453 #else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
7454     /* Establish a new session. */
7455     if (setsid() == -1) {
7456         return posix_error();
7457     }
7458 
7459     /* The tty becomes the controlling terminal. */
7460     if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
7461         return posix_error();
7462     }
7463 
7464     /* The tty becomes stdin/stdout/stderr */
7465     if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
7466         return posix_error();
7467     }
7468     if (fd > 2) {
7469         close(fd);
7470     }
7471 #endif /* HAVE_LOGIN_TTY */
7472     Py_RETURN_NONE;
7473 }
7474 #endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
7475 
7476 
7477 #ifdef HAVE_FORKPTY
7478 /*[clinic input]
7479 os.forkpty
7480 
7481 Fork a new process with a new pseudo-terminal as controlling tty.
7482 
7483 Returns a tuple of (pid, master_fd).
7484 Like fork(), return pid of 0 to the child process,
7485 and pid of child to the parent process.
7486 To both, return fd of newly opened pseudo-terminal.
7487 [clinic start generated code]*/
7488 
7489 static PyObject *
os_forkpty_impl(PyObject * module)7490 os_forkpty_impl(PyObject *module)
7491 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
7492 {
7493     int master_fd = -1;
7494     pid_t pid;
7495 
7496     if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
7497         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
7498         return NULL;
7499     }
7500     if (PySys_Audit("os.forkpty", NULL) < 0) {
7501         return NULL;
7502     }
7503     PyOS_BeforeFork();
7504     pid = forkpty(&master_fd, NULL, NULL, NULL);
7505     if (pid == 0) {
7506         /* child: this clobbers and resets the import lock. */
7507         PyOS_AfterFork_Child();
7508     } else {
7509         /* parent: release the import lock. */
7510         PyOS_AfterFork_Parent();
7511     }
7512     if (pid == -1) {
7513         return posix_error();
7514     }
7515     return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
7516 }
7517 #endif /* HAVE_FORKPTY */
7518 
7519 
7520 #ifdef HAVE_GETEGID
7521 /*[clinic input]
7522 os.getegid
7523 
7524 Return the current process's effective group id.
7525 [clinic start generated code]*/
7526 
7527 static PyObject *
os_getegid_impl(PyObject * module)7528 os_getegid_impl(PyObject *module)
7529 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
7530 {
7531     return _PyLong_FromGid(getegid());
7532 }
7533 #endif /* HAVE_GETEGID */
7534 
7535 
7536 #ifdef HAVE_GETEUID
7537 /*[clinic input]
7538 os.geteuid
7539 
7540 Return the current process's effective user id.
7541 [clinic start generated code]*/
7542 
7543 static PyObject *
os_geteuid_impl(PyObject * module)7544 os_geteuid_impl(PyObject *module)
7545 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
7546 {
7547     return _PyLong_FromUid(geteuid());
7548 }
7549 #endif /* HAVE_GETEUID */
7550 
7551 
7552 #ifdef HAVE_GETGID
7553 /*[clinic input]
7554 os.getgid
7555 
7556 Return the current process's group id.
7557 [clinic start generated code]*/
7558 
7559 static PyObject *
os_getgid_impl(PyObject * module)7560 os_getgid_impl(PyObject *module)
7561 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
7562 {
7563     return _PyLong_FromGid(getgid());
7564 }
7565 #endif /* HAVE_GETGID */
7566 
7567 
7568 #ifdef HAVE_GETPID
7569 /*[clinic input]
7570 os.getpid
7571 
7572 Return the current process id.
7573 [clinic start generated code]*/
7574 
7575 static PyObject *
os_getpid_impl(PyObject * module)7576 os_getpid_impl(PyObject *module)
7577 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
7578 {
7579     return PyLong_FromPid(getpid());
7580 }
7581 #endif /* HAVE_GETPID */
7582 
7583 #ifdef NGROUPS_MAX
7584 #define MAX_GROUPS NGROUPS_MAX
7585 #else
7586     /* defined to be 16 on Solaris7, so this should be a small number */
7587 #define MAX_GROUPS 64
7588 #endif
7589 
7590 #ifdef HAVE_GETGROUPLIST
7591 
7592 #ifdef __APPLE__
7593 /*[clinic input]
7594 os.getgrouplist
7595 
7596     user: str
7597         username to lookup
7598     group as basegid: int
7599         base group id of the user
7600     /
7601 
7602 Returns a list of groups to which a user belongs.
7603 [clinic start generated code]*/
7604 
7605 static PyObject *
os_getgrouplist_impl(PyObject * module,const char * user,int basegid)7606 os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
7607 /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
7608 #else
7609 /*[clinic input]
7610 os.getgrouplist
7611 
7612     user: str
7613         username to lookup
7614     group as basegid: gid_t
7615         base group id of the user
7616     /
7617 
7618 Returns a list of groups to which a user belongs.
7619 [clinic start generated code]*/
7620 
7621 static PyObject *
7622 os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
7623 /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
7624 #endif
7625 {
7626     int i, ngroups;
7627     PyObject *list;
7628 #ifdef __APPLE__
7629     int *groups;
7630 #else
7631     gid_t *groups;
7632 #endif
7633 
7634     /*
7635      * NGROUPS_MAX is defined by POSIX.1 as the maximum
7636      * number of supplimental groups a users can belong to.
7637      * We have to increment it by one because
7638      * getgrouplist() returns both the supplemental groups
7639      * and the primary group, i.e. all of the groups the
7640      * user belongs to.
7641      */
7642     ngroups = 1 + MAX_GROUPS;
7643 
7644     while (1) {
7645 #ifdef __APPLE__
7646         groups = PyMem_New(int, ngroups);
7647 #else
7648         groups = PyMem_New(gid_t, ngroups);
7649 #endif
7650         if (groups == NULL) {
7651             return PyErr_NoMemory();
7652         }
7653 
7654         int old_ngroups = ngroups;
7655         if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
7656             /* Success */
7657             break;
7658         }
7659 
7660         /* getgrouplist() fails if the group list is too small */
7661         PyMem_Free(groups);
7662 
7663         if (ngroups > old_ngroups) {
7664             /* If the group list is too small, the glibc implementation of
7665                getgrouplist() sets ngroups to the total number of groups and
7666                returns -1. */
7667         }
7668         else {
7669             /* Double the group list size */
7670             if (ngroups > INT_MAX / 2) {
7671                 return PyErr_NoMemory();
7672             }
7673             ngroups *= 2;
7674         }
7675 
7676         /* Retry getgrouplist() with a larger group list */
7677     }
7678 
7679 #ifdef _Py_MEMORY_SANITIZER
7680     /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
7681     __msan_unpoison(&ngroups, sizeof(ngroups));
7682     __msan_unpoison(groups, ngroups*sizeof(*groups));
7683 #endif
7684 
7685     list = PyList_New(ngroups);
7686     if (list == NULL) {
7687         PyMem_Free(groups);
7688         return NULL;
7689     }
7690 
7691     for (i = 0; i < ngroups; i++) {
7692 #ifdef __APPLE__
7693         PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7694 #else
7695         PyObject *o = _PyLong_FromGid(groups[i]);
7696 #endif
7697         if (o == NULL) {
7698             Py_DECREF(list);
7699             PyMem_Free(groups);
7700             return NULL;
7701         }
7702         PyList_SET_ITEM(list, i, o);
7703     }
7704 
7705     PyMem_Free(groups);
7706 
7707     return list;
7708 }
7709 #endif /* HAVE_GETGROUPLIST */
7710 
7711 
7712 #ifdef HAVE_GETGROUPS
7713 /*[clinic input]
7714 os.getgroups
7715 
7716 Return list of supplemental group IDs for the process.
7717 [clinic start generated code]*/
7718 
7719 static PyObject *
os_getgroups_impl(PyObject * module)7720 os_getgroups_impl(PyObject *module)
7721 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
7722 {
7723     // Call getgroups with length 0 to get the actual number of groups
7724     int n = getgroups(0, NULL);
7725     if (n < 0) {
7726         return posix_error();
7727     }
7728 
7729     if (n == 0) {
7730         return PyList_New(0);
7731     }
7732 
7733     gid_t *grouplist = PyMem_New(gid_t, n);
7734     if (grouplist == NULL) {
7735         return PyErr_NoMemory();
7736     }
7737 
7738     n = getgroups(n, grouplist);
7739     if (n == -1) {
7740         PyMem_Free(grouplist);
7741         return posix_error();
7742     }
7743 
7744     PyObject *result = PyList_New(n);
7745     if (result == NULL) {
7746         goto error;
7747     }
7748 
7749     for (int i = 0; i < n; ++i) {
7750         PyObject *group = _PyLong_FromGid(grouplist[i]);
7751         if (group == NULL) {
7752             goto error;
7753         }
7754         PyList_SET_ITEM(result, i, group);
7755     }
7756     PyMem_Free(grouplist);
7757 
7758     return result;
7759 
7760 error:
7761     PyMem_Free(grouplist);
7762     Py_XDECREF(result);
7763     return NULL;
7764 }
7765 #endif /* HAVE_GETGROUPS */
7766 
7767 #ifdef HAVE_INITGROUPS
7768 #ifdef __APPLE__
7769 /*[clinic input]
7770 os.initgroups
7771 
7772     username as oname: FSConverter
7773     gid: int
7774     /
7775 
7776 Initialize the group access list.
7777 
7778 Call the system initgroups() to initialize the group access list with all of
7779 the groups of which the specified username is a member, plus the specified
7780 group id.
7781 [clinic start generated code]*/
7782 
7783 static PyObject *
os_initgroups_impl(PyObject * module,PyObject * oname,int gid)7784 os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
7785 /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
7786 #else
7787 /*[clinic input]
7788 os.initgroups
7789 
7790     username as oname: FSConverter
7791     gid: gid_t
7792     /
7793 
7794 Initialize the group access list.
7795 
7796 Call the system initgroups() to initialize the group access list with all of
7797 the groups of which the specified username is a member, plus the specified
7798 group id.
7799 [clinic start generated code]*/
7800 
7801 static PyObject *
7802 os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
7803 /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
7804 #endif
7805 {
7806     const char *username = PyBytes_AS_STRING(oname);
7807 
7808     if (initgroups(username, gid) == -1)
7809         return PyErr_SetFromErrno(PyExc_OSError);
7810 
7811     Py_RETURN_NONE;
7812 }
7813 #endif /* HAVE_INITGROUPS */
7814 
7815 
7816 #ifdef HAVE_GETPGID
7817 /*[clinic input]
7818 os.getpgid
7819 
7820     pid: pid_t
7821 
7822 Call the system call getpgid(), and return the result.
7823 [clinic start generated code]*/
7824 
7825 static PyObject *
os_getpgid_impl(PyObject * module,pid_t pid)7826 os_getpgid_impl(PyObject *module, pid_t pid)
7827 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7828 {
7829     pid_t pgid = getpgid(pid);
7830     if (pgid < 0)
7831         return posix_error();
7832     return PyLong_FromPid(pgid);
7833 }
7834 #endif /* HAVE_GETPGID */
7835 
7836 
7837 #ifdef HAVE_GETPGRP
7838 /*[clinic input]
7839 os.getpgrp
7840 
7841 Return the current process group id.
7842 [clinic start generated code]*/
7843 
7844 static PyObject *
os_getpgrp_impl(PyObject * module)7845 os_getpgrp_impl(PyObject *module)
7846 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7847 {
7848 #ifdef GETPGRP_HAVE_ARG
7849     return PyLong_FromPid(getpgrp(0));
7850 #else /* GETPGRP_HAVE_ARG */
7851     return PyLong_FromPid(getpgrp());
7852 #endif /* GETPGRP_HAVE_ARG */
7853 }
7854 #endif /* HAVE_GETPGRP */
7855 
7856 
7857 #ifdef HAVE_SETPGRP
7858 /*[clinic input]
7859 os.setpgrp
7860 
7861 Make the current process the leader of its process group.
7862 [clinic start generated code]*/
7863 
7864 static PyObject *
os_setpgrp_impl(PyObject * module)7865 os_setpgrp_impl(PyObject *module)
7866 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7867 {
7868 #ifdef SETPGRP_HAVE_ARG
7869     if (setpgrp(0, 0) < 0)
7870 #else /* SETPGRP_HAVE_ARG */
7871     if (setpgrp() < 0)
7872 #endif /* SETPGRP_HAVE_ARG */
7873         return posix_error();
7874     Py_RETURN_NONE;
7875 }
7876 #endif /* HAVE_SETPGRP */
7877 
7878 #ifdef HAVE_GETPPID
7879 
7880 #ifdef MS_WINDOWS
7881 #include <tlhelp32.h>
7882 
7883 static PyObject*
win32_getppid()7884 win32_getppid()
7885 {
7886     HANDLE snapshot;
7887     pid_t mypid;
7888     PyObject* result = NULL;
7889     BOOL have_record;
7890     PROCESSENTRY32 pe;
7891 
7892     mypid = getpid(); /* This function never fails */
7893 
7894     snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7895     if (snapshot == INVALID_HANDLE_VALUE)
7896         return PyErr_SetFromWindowsErr(GetLastError());
7897 
7898     pe.dwSize = sizeof(pe);
7899     have_record = Process32First(snapshot, &pe);
7900     while (have_record) {
7901         if (mypid == (pid_t)pe.th32ProcessID) {
7902             /* We could cache the ulong value in a static variable. */
7903             result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7904             break;
7905         }
7906 
7907         have_record = Process32Next(snapshot, &pe);
7908     }
7909 
7910     /* If our loop exits and our pid was not found (result will be NULL)
7911      * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7912      * error anyway, so let's raise it. */
7913     if (!result)
7914         result = PyErr_SetFromWindowsErr(GetLastError());
7915 
7916     CloseHandle(snapshot);
7917 
7918     return result;
7919 }
7920 #endif /*MS_WINDOWS*/
7921 
7922 
7923 /*[clinic input]
7924 os.getppid
7925 
7926 Return the parent's process id.
7927 
7928 If the parent process has already exited, Windows machines will still
7929 return its id; others systems will return the id of the 'init' process (1).
7930 [clinic start generated code]*/
7931 
7932 static PyObject *
os_getppid_impl(PyObject * module)7933 os_getppid_impl(PyObject *module)
7934 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7935 {
7936 #ifdef MS_WINDOWS
7937     return win32_getppid();
7938 #else
7939     return PyLong_FromPid(getppid());
7940 #endif
7941 }
7942 #endif /* HAVE_GETPPID */
7943 
7944 
7945 #ifdef HAVE_GETLOGIN
7946 /*[clinic input]
7947 os.getlogin
7948 
7949 Return the actual login name.
7950 [clinic start generated code]*/
7951 
7952 static PyObject *
os_getlogin_impl(PyObject * module)7953 os_getlogin_impl(PyObject *module)
7954 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7955 {
7956     PyObject *result = NULL;
7957 #ifdef MS_WINDOWS
7958     wchar_t user_name[UNLEN + 1];
7959     DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7960 
7961     if (GetUserNameW(user_name, &num_chars)) {
7962         /* num_chars is the number of unicode chars plus null terminator */
7963         result = PyUnicode_FromWideChar(user_name, num_chars - 1);
7964     }
7965     else
7966         result = PyErr_SetFromWindowsErr(GetLastError());
7967 #else
7968     char *name;
7969     int old_errno = errno;
7970 
7971     errno = 0;
7972     name = getlogin();
7973     if (name == NULL) {
7974         if (errno)
7975             posix_error();
7976         else
7977             PyErr_SetString(PyExc_OSError, "unable to determine login name");
7978     }
7979     else
7980         result = PyUnicode_DecodeFSDefault(name);
7981     errno = old_errno;
7982 #endif
7983     return result;
7984 }
7985 #endif /* HAVE_GETLOGIN */
7986 
7987 
7988 #ifdef HAVE_GETUID
7989 /*[clinic input]
7990 os.getuid
7991 
7992 Return the current process's user id.
7993 [clinic start generated code]*/
7994 
7995 static PyObject *
os_getuid_impl(PyObject * module)7996 os_getuid_impl(PyObject *module)
7997 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7998 {
7999     return _PyLong_FromUid(getuid());
8000 }
8001 #endif /* HAVE_GETUID */
8002 
8003 
8004 #ifdef MS_WINDOWS
8005 #define HAVE_KILL
8006 #endif /* MS_WINDOWS */
8007 
8008 #ifdef HAVE_KILL
8009 /*[clinic input]
8010 os.kill
8011 
8012     pid: pid_t
8013     signal: Py_ssize_t
8014     /
8015 
8016 Kill a process with a signal.
8017 [clinic start generated code]*/
8018 
8019 static PyObject *
os_kill_impl(PyObject * module,pid_t pid,Py_ssize_t signal)8020 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
8021 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
8022 {
8023     if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
8024         return NULL;
8025     }
8026 #ifndef MS_WINDOWS
8027     if (kill(pid, (int)signal) == -1) {
8028         return posix_error();
8029     }
8030 
8031     // Check immediately if the signal was sent to the current process.
8032     // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
8033     // is cheap.
8034     if (PyErr_CheckSignals()) {
8035         return NULL;
8036     }
8037 
8038     Py_RETURN_NONE;
8039 #else /* !MS_WINDOWS */
8040     PyObject *result;
8041     DWORD sig = (DWORD)signal;
8042     DWORD err;
8043     HANDLE handle;
8044 
8045     /* Console processes which share a common console can be sent CTRL+C or
8046        CTRL+BREAK events, provided they handle said events. */
8047     if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
8048         if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
8049             err = GetLastError();
8050             PyErr_SetFromWindowsErr(err);
8051         }
8052         else
8053             Py_RETURN_NONE;
8054     }
8055 
8056     /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
8057        attempt to open and terminate the process. */
8058     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
8059     if (handle == NULL) {
8060         err = GetLastError();
8061         return PyErr_SetFromWindowsErr(err);
8062     }
8063 
8064     if (TerminateProcess(handle, sig) == 0) {
8065         err = GetLastError();
8066         result = PyErr_SetFromWindowsErr(err);
8067     } else {
8068         Py_INCREF(Py_None);
8069         result = Py_None;
8070     }
8071 
8072     CloseHandle(handle);
8073     return result;
8074 #endif /* !MS_WINDOWS */
8075 }
8076 #endif /* HAVE_KILL */
8077 
8078 
8079 #ifdef HAVE_KILLPG
8080 /*[clinic input]
8081 os.killpg
8082 
8083     pgid: pid_t
8084     signal: int
8085     /
8086 
8087 Kill a process group with a signal.
8088 [clinic start generated code]*/
8089 
8090 static PyObject *
os_killpg_impl(PyObject * module,pid_t pgid,int signal)8091 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
8092 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
8093 {
8094     if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
8095         return NULL;
8096     }
8097     /* XXX some man pages make the `pgid` parameter an int, others
8098        a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
8099        take the same type. Moreover, pid_t is always at least as wide as
8100        int (else compilation of this module fails), which is safe. */
8101     if (killpg(pgid, signal) == -1)
8102         return posix_error();
8103     Py_RETURN_NONE;
8104 }
8105 #endif /* HAVE_KILLPG */
8106 
8107 
8108 #ifdef HAVE_PLOCK
8109 #ifdef HAVE_SYS_LOCK_H
8110 #include <sys/lock.h>
8111 #endif
8112 
8113 /*[clinic input]
8114 os.plock
8115     op: int
8116     /
8117 
8118 Lock program segments into memory.");
8119 [clinic start generated code]*/
8120 
8121 static PyObject *
os_plock_impl(PyObject * module,int op)8122 os_plock_impl(PyObject *module, int op)
8123 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
8124 {
8125     if (plock(op) == -1)
8126         return posix_error();
8127     Py_RETURN_NONE;
8128 }
8129 #endif /* HAVE_PLOCK */
8130 
8131 
8132 #ifdef HAVE_SETUID
8133 /*[clinic input]
8134 os.setuid
8135 
8136     uid: uid_t
8137     /
8138 
8139 Set the current process's user id.
8140 [clinic start generated code]*/
8141 
8142 static PyObject *
os_setuid_impl(PyObject * module,uid_t uid)8143 os_setuid_impl(PyObject *module, uid_t uid)
8144 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
8145 {
8146     if (setuid(uid) < 0)
8147         return posix_error();
8148     Py_RETURN_NONE;
8149 }
8150 #endif /* HAVE_SETUID */
8151 
8152 
8153 #ifdef HAVE_SETEUID
8154 /*[clinic input]
8155 os.seteuid
8156 
8157     euid: uid_t
8158     /
8159 
8160 Set the current process's effective user id.
8161 [clinic start generated code]*/
8162 
8163 static PyObject *
os_seteuid_impl(PyObject * module,uid_t euid)8164 os_seteuid_impl(PyObject *module, uid_t euid)
8165 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
8166 {
8167     if (seteuid(euid) < 0)
8168         return posix_error();
8169     Py_RETURN_NONE;
8170 }
8171 #endif /* HAVE_SETEUID */
8172 
8173 
8174 #ifdef HAVE_SETEGID
8175 /*[clinic input]
8176 os.setegid
8177 
8178     egid: gid_t
8179     /
8180 
8181 Set the current process's effective group id.
8182 [clinic start generated code]*/
8183 
8184 static PyObject *
os_setegid_impl(PyObject * module,gid_t egid)8185 os_setegid_impl(PyObject *module, gid_t egid)
8186 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
8187 {
8188     if (setegid(egid) < 0)
8189         return posix_error();
8190     Py_RETURN_NONE;
8191 }
8192 #endif /* HAVE_SETEGID */
8193 
8194 
8195 #ifdef HAVE_SETREUID
8196 /*[clinic input]
8197 os.setreuid
8198 
8199     ruid: uid_t
8200     euid: uid_t
8201     /
8202 
8203 Set the current process's real and effective user ids.
8204 [clinic start generated code]*/
8205 
8206 static PyObject *
os_setreuid_impl(PyObject * module,uid_t ruid,uid_t euid)8207 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
8208 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
8209 {
8210     if (setreuid(ruid, euid) < 0) {
8211         return posix_error();
8212     } else {
8213         Py_RETURN_NONE;
8214     }
8215 }
8216 #endif /* HAVE_SETREUID */
8217 
8218 
8219 #ifdef HAVE_SETREGID
8220 /*[clinic input]
8221 os.setregid
8222 
8223     rgid: gid_t
8224     egid: gid_t
8225     /
8226 
8227 Set the current process's real and effective group ids.
8228 [clinic start generated code]*/
8229 
8230 static PyObject *
os_setregid_impl(PyObject * module,gid_t rgid,gid_t egid)8231 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
8232 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
8233 {
8234     if (setregid(rgid, egid) < 0)
8235         return posix_error();
8236     Py_RETURN_NONE;
8237 }
8238 #endif /* HAVE_SETREGID */
8239 
8240 
8241 #ifdef HAVE_SETGID
8242 /*[clinic input]
8243 os.setgid
8244     gid: gid_t
8245     /
8246 
8247 Set the current process's group id.
8248 [clinic start generated code]*/
8249 
8250 static PyObject *
os_setgid_impl(PyObject * module,gid_t gid)8251 os_setgid_impl(PyObject *module, gid_t gid)
8252 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
8253 {
8254     if (setgid(gid) < 0)
8255         return posix_error();
8256     Py_RETURN_NONE;
8257 }
8258 #endif /* HAVE_SETGID */
8259 
8260 
8261 #ifdef HAVE_SETGROUPS
8262 /*[clinic input]
8263 os.setgroups
8264 
8265     groups: object
8266     /
8267 
8268 Set the groups of the current process to list.
8269 [clinic start generated code]*/
8270 
8271 static PyObject *
os_setgroups(PyObject * module,PyObject * groups)8272 os_setgroups(PyObject *module, PyObject *groups)
8273 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
8274 {
8275     if (!PySequence_Check(groups)) {
8276         PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
8277         return NULL;
8278     }
8279     Py_ssize_t len = PySequence_Size(groups);
8280     if (len < 0) {
8281         return NULL;
8282     }
8283     if (len > MAX_GROUPS) {
8284         PyErr_SetString(PyExc_ValueError, "too many groups");
8285         return NULL;
8286     }
8287 
8288     gid_t *grouplist = PyMem_New(gid_t, len);
8289     for (Py_ssize_t i = 0; i < len; i++) {
8290         PyObject *elem;
8291         elem = PySequence_GetItem(groups, i);
8292         if (!elem) {
8293             PyMem_Free(grouplist);
8294             return NULL;
8295         }
8296         if (!PyLong_Check(elem)) {
8297             PyErr_SetString(PyExc_TypeError,
8298                             "groups must be integers");
8299             Py_DECREF(elem);
8300             PyMem_Free(grouplist);
8301             return NULL;
8302         } else {
8303             if (!_Py_Gid_Converter(elem, &grouplist[i])) {
8304                 Py_DECREF(elem);
8305                 PyMem_Free(grouplist);
8306                 return NULL;
8307             }
8308         }
8309         Py_DECREF(elem);
8310     }
8311 
8312     if (setgroups(len, grouplist) < 0) {
8313         PyMem_Free(grouplist);
8314         return posix_error();
8315     }
8316     PyMem_Free(grouplist);
8317     Py_RETURN_NONE;
8318 }
8319 #endif /* HAVE_SETGROUPS */
8320 
8321 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
8322 static PyObject *
wait_helper(PyObject * module,pid_t pid,int status,struct rusage * ru)8323 wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
8324 {
8325     PyObject *result;
8326     PyObject *struct_rusage;
8327 
8328     if (pid == -1)
8329         return posix_error();
8330 
8331     // If wait succeeded but no child was ready to report status, ru will not
8332     // have been populated.
8333     if (pid == 0) {
8334         memset(ru, 0, sizeof(*ru));
8335     }
8336 
8337     PyObject *m = PyImport_ImportModule("resource");
8338     if (m == NULL)
8339         return NULL;
8340     struct_rusage = PyObject_GetAttr(m, get_posix_state(module)->struct_rusage);
8341     Py_DECREF(m);
8342     if (struct_rusage == NULL)
8343         return NULL;
8344 
8345     /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
8346     result = PyStructSequence_New((PyTypeObject*) struct_rusage);
8347     Py_DECREF(struct_rusage);
8348     if (!result)
8349         return NULL;
8350 
8351 #ifndef doubletime
8352 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
8353 #endif
8354 
8355     PyStructSequence_SET_ITEM(result, 0,
8356                               PyFloat_FromDouble(doubletime(ru->ru_utime)));
8357     PyStructSequence_SET_ITEM(result, 1,
8358                               PyFloat_FromDouble(doubletime(ru->ru_stime)));
8359 #define SET_INT(result, index, value)\
8360         PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
8361     SET_INT(result, 2, ru->ru_maxrss);
8362     SET_INT(result, 3, ru->ru_ixrss);
8363     SET_INT(result, 4, ru->ru_idrss);
8364     SET_INT(result, 5, ru->ru_isrss);
8365     SET_INT(result, 6, ru->ru_minflt);
8366     SET_INT(result, 7, ru->ru_majflt);
8367     SET_INT(result, 8, ru->ru_nswap);
8368     SET_INT(result, 9, ru->ru_inblock);
8369     SET_INT(result, 10, ru->ru_oublock);
8370     SET_INT(result, 11, ru->ru_msgsnd);
8371     SET_INT(result, 12, ru->ru_msgrcv);
8372     SET_INT(result, 13, ru->ru_nsignals);
8373     SET_INT(result, 14, ru->ru_nvcsw);
8374     SET_INT(result, 15, ru->ru_nivcsw);
8375 #undef SET_INT
8376 
8377     if (PyErr_Occurred()) {
8378         Py_DECREF(result);
8379         return NULL;
8380     }
8381 
8382     return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
8383 }
8384 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
8385 
8386 
8387 #ifdef HAVE_WAIT3
8388 /*[clinic input]
8389 os.wait3
8390 
8391     options: int
8392 Wait for completion of a child process.
8393 
8394 Returns a tuple of information about the child process:
8395   (pid, status, rusage)
8396 [clinic start generated code]*/
8397 
8398 static PyObject *
os_wait3_impl(PyObject * module,int options)8399 os_wait3_impl(PyObject *module, int options)
8400 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
8401 {
8402     pid_t pid;
8403     struct rusage ru;
8404     int async_err = 0;
8405     WAIT_TYPE status;
8406     WAIT_STATUS_INT(status) = 0;
8407 
8408     do {
8409         Py_BEGIN_ALLOW_THREADS
8410         pid = wait3(&status, options, &ru);
8411         Py_END_ALLOW_THREADS
8412     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8413     if (pid < 0)
8414         return (!async_err) ? posix_error() : NULL;
8415 
8416     return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
8417 }
8418 #endif /* HAVE_WAIT3 */
8419 
8420 
8421 #ifdef HAVE_WAIT4
8422 /*[clinic input]
8423 
8424 os.wait4
8425 
8426     pid: pid_t
8427     options: int
8428 
8429 Wait for completion of a specific child process.
8430 
8431 Returns a tuple of information about the child process:
8432   (pid, status, rusage)
8433 [clinic start generated code]*/
8434 
8435 static PyObject *
os_wait4_impl(PyObject * module,pid_t pid,int options)8436 os_wait4_impl(PyObject *module, pid_t pid, int options)
8437 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
8438 {
8439     pid_t res;
8440     struct rusage ru;
8441     int async_err = 0;
8442     WAIT_TYPE status;
8443     WAIT_STATUS_INT(status) = 0;
8444 
8445     do {
8446         Py_BEGIN_ALLOW_THREADS
8447         res = wait4(pid, &status, options, &ru);
8448         Py_END_ALLOW_THREADS
8449     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8450     if (res < 0)
8451         return (!async_err) ? posix_error() : NULL;
8452 
8453     return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
8454 }
8455 #endif /* HAVE_WAIT4 */
8456 
8457 
8458 #if defined(HAVE_WAITID) && !defined(__APPLE__)
8459 /*[clinic input]
8460 os.waitid
8461 
8462     idtype: idtype_t
8463         Must be one of be P_PID, P_PGID or P_ALL.
8464     id: id_t
8465         The id to wait on.
8466     options: int
8467         Constructed from the ORing of one or more of WEXITED, WSTOPPED
8468         or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
8469     /
8470 
8471 Returns the result of waiting for a process or processes.
8472 
8473 Returns either waitid_result or None if WNOHANG is specified and there are
8474 no children in a waitable state.
8475 [clinic start generated code]*/
8476 
8477 static PyObject *
os_waitid_impl(PyObject * module,idtype_t idtype,id_t id,int options)8478 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
8479 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
8480 {
8481     PyObject *result;
8482     int res;
8483     int async_err = 0;
8484     siginfo_t si;
8485     si.si_pid = 0;
8486 
8487     do {
8488         Py_BEGIN_ALLOW_THREADS
8489         res = waitid(idtype, id, &si, options);
8490         Py_END_ALLOW_THREADS
8491     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8492     if (res < 0)
8493         return (!async_err) ? posix_error() : NULL;
8494 
8495     if (si.si_pid == 0)
8496         Py_RETURN_NONE;
8497 
8498     PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
8499     result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
8500     if (!result)
8501         return NULL;
8502 
8503     PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
8504     PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
8505     PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
8506     PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
8507     PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
8508     if (PyErr_Occurred()) {
8509         Py_DECREF(result);
8510         return NULL;
8511     }
8512 
8513     return result;
8514 }
8515 #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
8516 
8517 
8518 #if defined(HAVE_WAITPID)
8519 /*[clinic input]
8520 os.waitpid
8521     pid: pid_t
8522     options: int
8523     /
8524 
8525 Wait for completion of a given child process.
8526 
8527 Returns a tuple of information regarding the child process:
8528     (pid, status)
8529 
8530 The options argument is ignored on Windows.
8531 [clinic start generated code]*/
8532 
8533 static PyObject *
os_waitpid_impl(PyObject * module,pid_t pid,int options)8534 os_waitpid_impl(PyObject *module, pid_t pid, int options)
8535 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
8536 {
8537     pid_t res;
8538     int async_err = 0;
8539     WAIT_TYPE status;
8540     WAIT_STATUS_INT(status) = 0;
8541 
8542     do {
8543         Py_BEGIN_ALLOW_THREADS
8544         res = waitpid(pid, &status, options);
8545         Py_END_ALLOW_THREADS
8546     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8547     if (res < 0)
8548         return (!async_err) ? posix_error() : NULL;
8549 
8550     return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
8551 }
8552 #elif defined(HAVE_CWAIT)
8553 /* MS C has a variant of waitpid() that's usable for most purposes. */
8554 /*[clinic input]
8555 os.waitpid
8556     pid: intptr_t
8557     options: int
8558     /
8559 
8560 Wait for completion of a given process.
8561 
8562 Returns a tuple of information regarding the process:
8563     (pid, status << 8)
8564 
8565 The options argument is ignored on Windows.
8566 [clinic start generated code]*/
8567 
8568 static PyObject *
os_waitpid_impl(PyObject * module,intptr_t pid,int options)8569 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
8570 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
8571 {
8572     int status;
8573     intptr_t res;
8574     int async_err = 0;
8575 
8576     do {
8577         Py_BEGIN_ALLOW_THREADS
8578         _Py_BEGIN_SUPPRESS_IPH
8579         res = _cwait(&status, pid, options);
8580         _Py_END_SUPPRESS_IPH
8581         Py_END_ALLOW_THREADS
8582     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8583     if (res < 0)
8584         return (!async_err) ? posix_error() : NULL;
8585 
8586     unsigned long long ustatus = (unsigned int)status;
8587 
8588     /* shift the status left a byte so this is more like the POSIX waitpid */
8589     return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
8590 }
8591 #endif
8592 
8593 
8594 #ifdef HAVE_WAIT
8595 /*[clinic input]
8596 os.wait
8597 
8598 Wait for completion of a child process.
8599 
8600 Returns a tuple of information about the child process:
8601     (pid, status)
8602 [clinic start generated code]*/
8603 
8604 static PyObject *
os_wait_impl(PyObject * module)8605 os_wait_impl(PyObject *module)
8606 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
8607 {
8608     pid_t pid;
8609     int async_err = 0;
8610     WAIT_TYPE status;
8611     WAIT_STATUS_INT(status) = 0;
8612 
8613     do {
8614         Py_BEGIN_ALLOW_THREADS
8615         pid = wait(&status);
8616         Py_END_ALLOW_THREADS
8617     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8618     if (pid < 0)
8619         return (!async_err) ? posix_error() : NULL;
8620 
8621     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
8622 }
8623 #endif /* HAVE_WAIT */
8624 
8625 #if defined(__linux__) && defined(__NR_pidfd_open)
8626 /*[clinic input]
8627 os.pidfd_open
8628   pid: pid_t
8629   flags: unsigned_int = 0
8630 
8631 Return a file descriptor referring to the process *pid*.
8632 
8633 The descriptor can be used to perform process management without races and
8634 signals.
8635 [clinic start generated code]*/
8636 
8637 static PyObject *
os_pidfd_open_impl(PyObject * module,pid_t pid,unsigned int flags)8638 os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
8639 /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
8640 {
8641     int fd = syscall(__NR_pidfd_open, pid, flags);
8642     if (fd < 0) {
8643         return posix_error();
8644     }
8645     return PyLong_FromLong(fd);
8646 }
8647 #endif
8648 
8649 
8650 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
8651 /*[clinic input]
8652 os.readlink
8653 
8654     path: path_t
8655     *
8656     dir_fd: dir_fd(requires='readlinkat') = None
8657 
8658 Return a string representing the path to which the symbolic link points.
8659 
8660 If dir_fd is not None, it should be a file descriptor open to a directory,
8661 and path should be relative; path will then be relative to that directory.
8662 
8663 dir_fd may not be implemented on your platform.  If it is unavailable,
8664 using it will raise a NotImplementedError.
8665 [clinic start generated code]*/
8666 
8667 static PyObject *
os_readlink_impl(PyObject * module,path_t * path,int dir_fd)8668 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
8669 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
8670 {
8671 #if defined(HAVE_READLINK)
8672     char buffer[MAXPATHLEN+1];
8673     ssize_t length;
8674 #ifdef HAVE_READLINKAT
8675     int readlinkat_unavailable = 0;
8676 #endif
8677 
8678     Py_BEGIN_ALLOW_THREADS
8679 #ifdef HAVE_READLINKAT
8680     if (dir_fd != DEFAULT_DIR_FD) {
8681         if (HAVE_READLINKAT_RUNTIME) {
8682             length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
8683         } else {
8684             readlinkat_unavailable = 1;
8685         }
8686     } else
8687 #endif
8688         length = readlink(path->narrow, buffer, MAXPATHLEN);
8689     Py_END_ALLOW_THREADS
8690 
8691 #ifdef HAVE_READLINKAT
8692     if (readlinkat_unavailable) {
8693         argument_unavailable_error(NULL, "dir_fd");
8694         return NULL;
8695     }
8696 #endif
8697 
8698     if (length < 0) {
8699         return path_error(path);
8700     }
8701     buffer[length] = '\0';
8702 
8703     if (PyUnicode_Check(path->object))
8704         return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
8705     else
8706         return PyBytes_FromStringAndSize(buffer, length);
8707 #elif defined(MS_WINDOWS)
8708     DWORD n_bytes_returned;
8709     DWORD io_result = 0;
8710     HANDLE reparse_point_handle;
8711     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
8712     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
8713     PyObject *result = NULL;
8714 
8715     /* First get a handle to the reparse point */
8716     Py_BEGIN_ALLOW_THREADS
8717     reparse_point_handle = CreateFileW(
8718         path->wide,
8719         0,
8720         0,
8721         0,
8722         OPEN_EXISTING,
8723         FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
8724         0);
8725     if (reparse_point_handle != INVALID_HANDLE_VALUE) {
8726         /* New call DeviceIoControl to read the reparse point */
8727         io_result = DeviceIoControl(
8728             reparse_point_handle,
8729             FSCTL_GET_REPARSE_POINT,
8730             0, 0, /* in buffer */
8731             target_buffer, sizeof(target_buffer),
8732             &n_bytes_returned,
8733             0 /* we're not using OVERLAPPED_IO */
8734             );
8735         CloseHandle(reparse_point_handle);
8736     }
8737     Py_END_ALLOW_THREADS
8738 
8739     if (io_result == 0) {
8740         return path_error(path);
8741     }
8742 
8743     wchar_t *name = NULL;
8744     Py_ssize_t nameLen = 0;
8745     if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
8746     {
8747         name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
8748                            rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
8749         nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8750     }
8751     else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
8752     {
8753         name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8754                            rdb->MountPointReparseBuffer.SubstituteNameOffset);
8755         nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8756     }
8757     else
8758     {
8759         PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8760     }
8761     if (name) {
8762         if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8763             /* Our buffer is mutable, so this is okay */
8764             name[1] = L'\\';
8765         }
8766         result = PyUnicode_FromWideChar(name, nameLen);
8767         if (result && path->narrow) {
8768             Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8769         }
8770     }
8771     return result;
8772 #endif
8773 }
8774 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8775 
8776 #if defined(MS_WINDOWS)
8777 
8778 /* Remove the last portion of the path - return 0 on success */
8779 static int
_dirnameW(WCHAR * path)8780 _dirnameW(WCHAR *path)
8781 {
8782     WCHAR *ptr;
8783     size_t length = wcsnlen_s(path, MAX_PATH);
8784     if (length == MAX_PATH) {
8785         return -1;
8786     }
8787 
8788     /* walk the path from the end until a backslash is encountered */
8789     for(ptr = path + length; ptr != path; ptr--) {
8790         if (*ptr == L'\\' || *ptr == L'/') {
8791             break;
8792         }
8793     }
8794     *ptr = 0;
8795     return 0;
8796 }
8797 
8798 #endif
8799 
8800 #ifdef HAVE_SYMLINK
8801 
8802 #if defined(MS_WINDOWS)
8803 
8804 /* Is this path absolute? */
8805 static int
_is_absW(const WCHAR * path)8806 _is_absW(const WCHAR *path)
8807 {
8808     return path[0] == L'\\' || path[0] == L'/' ||
8809         (path[0] && path[1] == L':');
8810 }
8811 
8812 /* join root and rest with a backslash - return 0 on success */
8813 static int
_joinW(WCHAR * dest_path,const WCHAR * root,const WCHAR * rest)8814 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8815 {
8816     if (_is_absW(rest)) {
8817         return wcscpy_s(dest_path, MAX_PATH, rest);
8818     }
8819 
8820     if (wcscpy_s(dest_path, MAX_PATH, root)) {
8821         return -1;
8822     }
8823 
8824     if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8825         return -1;
8826     }
8827 
8828     return wcscat_s(dest_path, MAX_PATH, rest);
8829 }
8830 
8831 /* Return True if the path at src relative to dest is a directory */
8832 static int
_check_dirW(LPCWSTR src,LPCWSTR dest)8833 _check_dirW(LPCWSTR src, LPCWSTR dest)
8834 {
8835     WIN32_FILE_ATTRIBUTE_DATA src_info;
8836     WCHAR dest_parent[MAX_PATH];
8837     WCHAR src_resolved[MAX_PATH] = L"";
8838 
8839     /* dest_parent = os.path.dirname(dest) */
8840     if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8841         _dirnameW(dest_parent)) {
8842         return 0;
8843     }
8844     /* src_resolved = os.path.join(dest_parent, src) */
8845     if (_joinW(src_resolved, dest_parent, src)) {
8846         return 0;
8847     }
8848     return (
8849         GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8850         && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8851     );
8852 }
8853 #endif
8854 
8855 
8856 /*[clinic input]
8857 os.symlink
8858     src: path_t
8859     dst: path_t
8860     target_is_directory: bool = False
8861     *
8862     dir_fd: dir_fd(requires='symlinkat')=None
8863 
8864 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8865 
8866 Create a symbolic link pointing to src named dst.
8867 
8868 target_is_directory is required on Windows if the target is to be
8869   interpreted as a directory.  (On Windows, symlink requires
8870   Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8871   target_is_directory is ignored on non-Windows platforms.
8872 
8873 If dir_fd is not None, it should be a file descriptor open to a directory,
8874   and path should be relative; path will then be relative to that directory.
8875 dir_fd may not be implemented on your platform.
8876   If it is unavailable, using it will raise a NotImplementedError.
8877 
8878 [clinic start generated code]*/
8879 
8880 static PyObject *
os_symlink_impl(PyObject * module,path_t * src,path_t * dst,int target_is_directory,int dir_fd)8881 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8882                 int target_is_directory, int dir_fd)
8883 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8884 {
8885 #ifdef MS_WINDOWS
8886     DWORD result;
8887     DWORD flags = 0;
8888 
8889     /* Assumed true, set to false if detected to not be available. */
8890     static int windows_has_symlink_unprivileged_flag = TRUE;
8891 #else
8892     int result;
8893 #ifdef HAVE_SYMLINKAT
8894     int symlinkat_unavailable = 0;
8895 #endif
8896 #endif
8897 
8898     if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8899                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8900         return NULL;
8901     }
8902 
8903 #ifdef MS_WINDOWS
8904 
8905     if (windows_has_symlink_unprivileged_flag) {
8906         /* Allow non-admin symlinks if system allows it. */
8907         flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8908     }
8909 
8910     Py_BEGIN_ALLOW_THREADS
8911     _Py_BEGIN_SUPPRESS_IPH
8912     /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8913     if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8914         flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8915     }
8916 
8917     result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8918     _Py_END_SUPPRESS_IPH
8919     Py_END_ALLOW_THREADS
8920 
8921     if (windows_has_symlink_unprivileged_flag && !result &&
8922         ERROR_INVALID_PARAMETER == GetLastError()) {
8923 
8924         Py_BEGIN_ALLOW_THREADS
8925         _Py_BEGIN_SUPPRESS_IPH
8926         /* This error might be caused by
8927         SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8928         Try again, and update windows_has_symlink_unprivileged_flag if we
8929         are successful this time.
8930 
8931         NOTE: There is a risk of a race condition here if there are other
8932         conditions than the flag causing ERROR_INVALID_PARAMETER, and
8933         another process (or thread) changes that condition in between our
8934         calls to CreateSymbolicLink.
8935         */
8936         flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8937         result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8938         _Py_END_SUPPRESS_IPH
8939         Py_END_ALLOW_THREADS
8940 
8941         if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8942             windows_has_symlink_unprivileged_flag = FALSE;
8943         }
8944     }
8945 
8946     if (!result)
8947         return path_error2(src, dst);
8948 
8949 #else
8950 
8951     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8952         PyErr_SetString(PyExc_ValueError,
8953             "symlink: src and dst must be the same type");
8954         return NULL;
8955     }
8956 
8957     Py_BEGIN_ALLOW_THREADS
8958 #ifdef HAVE_SYMLINKAT
8959     if (dir_fd != DEFAULT_DIR_FD) {
8960         if (HAVE_SYMLINKAT_RUNTIME) {
8961             result = symlinkat(src->narrow, dir_fd, dst->narrow);
8962         } else {
8963             symlinkat_unavailable = 1;
8964         }
8965     } else
8966 #endif
8967         result = symlink(src->narrow, dst->narrow);
8968     Py_END_ALLOW_THREADS
8969 
8970 #ifdef HAVE_SYMLINKAT
8971     if (symlinkat_unavailable) {
8972           argument_unavailable_error(NULL, "dir_fd");
8973           return NULL;
8974     }
8975 #endif
8976 
8977     if (result)
8978         return path_error2(src, dst);
8979 #endif
8980 
8981     Py_RETURN_NONE;
8982 }
8983 #endif /* HAVE_SYMLINK */
8984 
8985 
8986 
8987 
8988 static PyStructSequence_Field times_result_fields[] = {
8989     {"user",    "user time"},
8990     {"system",   "system time"},
8991     {"children_user",    "user time of children"},
8992     {"children_system",    "system time of children"},
8993     {"elapsed",    "elapsed time since an arbitrary point in the past"},
8994     {NULL}
8995 };
8996 
8997 PyDoc_STRVAR(times_result__doc__,
8998 "times_result: Result from os.times().\n\n\
8999 This object may be accessed either as a tuple of\n\
9000   (user, system, children_user, children_system, elapsed),\n\
9001 or via the attributes user, system, children_user, children_system,\n\
9002 and elapsed.\n\
9003 \n\
9004 See os.times for more information.");
9005 
9006 static PyStructSequence_Desc times_result_desc = {
9007     "times_result", /* name */
9008     times_result__doc__, /* doc */
9009     times_result_fields,
9010     5
9011 };
9012 
9013 #ifdef MS_WINDOWS
9014 #define HAVE_TIMES  /* mandatory, for the method table */
9015 #endif
9016 
9017 #ifdef HAVE_TIMES
9018 
9019 static PyObject *
build_times_result(PyObject * module,double user,double system,double children_user,double children_system,double elapsed)9020 build_times_result(PyObject *module, double user, double system,
9021     double children_user, double children_system,
9022     double elapsed)
9023 {
9024     PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
9025     PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
9026     if (value == NULL)
9027         return NULL;
9028 
9029 #define SET(i, field) \
9030     { \
9031     PyObject *o = PyFloat_FromDouble(field); \
9032     if (!o) { \
9033         Py_DECREF(value); \
9034         return NULL; \
9035     } \
9036     PyStructSequence_SET_ITEM(value, i, o); \
9037     } \
9038 
9039     SET(0, user);
9040     SET(1, system);
9041     SET(2, children_user);
9042     SET(3, children_system);
9043     SET(4, elapsed);
9044 
9045 #undef SET
9046 
9047     return value;
9048 }
9049 
9050 
9051 #ifndef MS_WINDOWS
9052 #define NEED_TICKS_PER_SECOND
9053 static long ticks_per_second = -1;
9054 #endif /* MS_WINDOWS */
9055 
9056 /*[clinic input]
9057 os.times
9058 
9059 Return a collection containing process timing information.
9060 
9061 The object returned behaves like a named tuple with these fields:
9062   (utime, stime, cutime, cstime, elapsed_time)
9063 All fields are floating point numbers.
9064 [clinic start generated code]*/
9065 
9066 static PyObject *
os_times_impl(PyObject * module)9067 os_times_impl(PyObject *module)
9068 /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
9069 #ifdef MS_WINDOWS
9070 {
9071     FILETIME create, exit, kernel, user;
9072     HANDLE hProc;
9073     hProc = GetCurrentProcess();
9074     GetProcessTimes(hProc, &create, &exit, &kernel, &user);
9075     /* The fields of a FILETIME structure are the hi and lo part
9076        of a 64-bit value expressed in 100 nanosecond units.
9077        1e7 is one second in such units; 1e-7 the inverse.
9078        429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
9079     */
9080     return build_times_result(module,
9081         (double)(user.dwHighDateTime*429.4967296 +
9082                  user.dwLowDateTime*1e-7),
9083         (double)(kernel.dwHighDateTime*429.4967296 +
9084                  kernel.dwLowDateTime*1e-7),
9085         (double)0,
9086         (double)0,
9087         (double)0);
9088 }
9089 #else /* MS_WINDOWS */
9090 {
9091 
9092 
9093     struct tms t;
9094     clock_t c;
9095     errno = 0;
9096     c = times(&t);
9097     if (c == (clock_t) -1)
9098         return posix_error();
9099     return build_times_result(module,
9100                          (double)t.tms_utime / ticks_per_second,
9101                          (double)t.tms_stime / ticks_per_second,
9102                          (double)t.tms_cutime / ticks_per_second,
9103                          (double)t.tms_cstime / ticks_per_second,
9104                          (double)c / ticks_per_second);
9105 }
9106 #endif /* MS_WINDOWS */
9107 #endif /* HAVE_TIMES */
9108 
9109 
9110 #ifdef HAVE_GETSID
9111 /*[clinic input]
9112 os.getsid
9113 
9114     pid: pid_t
9115     /
9116 
9117 Call the system call getsid(pid) and return the result.
9118 [clinic start generated code]*/
9119 
9120 static PyObject *
os_getsid_impl(PyObject * module,pid_t pid)9121 os_getsid_impl(PyObject *module, pid_t pid)
9122 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
9123 {
9124     int sid;
9125     sid = getsid(pid);
9126     if (sid < 0)
9127         return posix_error();
9128     return PyLong_FromLong((long)sid);
9129 }
9130 #endif /* HAVE_GETSID */
9131 
9132 
9133 #ifdef HAVE_SETSID
9134 /*[clinic input]
9135 os.setsid
9136 
9137 Call the system call setsid().
9138 [clinic start generated code]*/
9139 
9140 static PyObject *
os_setsid_impl(PyObject * module)9141 os_setsid_impl(PyObject *module)
9142 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
9143 {
9144     if (setsid() < 0)
9145         return posix_error();
9146     Py_RETURN_NONE;
9147 }
9148 #endif /* HAVE_SETSID */
9149 
9150 
9151 #ifdef HAVE_SETPGID
9152 /*[clinic input]
9153 os.setpgid
9154 
9155     pid: pid_t
9156     pgrp: pid_t
9157     /
9158 
9159 Call the system call setpgid(pid, pgrp).
9160 [clinic start generated code]*/
9161 
9162 static PyObject *
os_setpgid_impl(PyObject * module,pid_t pid,pid_t pgrp)9163 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
9164 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
9165 {
9166     if (setpgid(pid, pgrp) < 0)
9167         return posix_error();
9168     Py_RETURN_NONE;
9169 }
9170 #endif /* HAVE_SETPGID */
9171 
9172 
9173 #ifdef HAVE_TCGETPGRP
9174 /*[clinic input]
9175 os.tcgetpgrp
9176 
9177     fd: int
9178     /
9179 
9180 Return the process group associated with the terminal specified by fd.
9181 [clinic start generated code]*/
9182 
9183 static PyObject *
os_tcgetpgrp_impl(PyObject * module,int fd)9184 os_tcgetpgrp_impl(PyObject *module, int fd)
9185 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
9186 {
9187     pid_t pgid = tcgetpgrp(fd);
9188     if (pgid < 0)
9189         return posix_error();
9190     return PyLong_FromPid(pgid);
9191 }
9192 #endif /* HAVE_TCGETPGRP */
9193 
9194 
9195 #ifdef HAVE_TCSETPGRP
9196 /*[clinic input]
9197 os.tcsetpgrp
9198 
9199     fd: int
9200     pgid: pid_t
9201     /
9202 
9203 Set the process group associated with the terminal specified by fd.
9204 [clinic start generated code]*/
9205 
9206 static PyObject *
os_tcsetpgrp_impl(PyObject * module,int fd,pid_t pgid)9207 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
9208 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
9209 {
9210     if (tcsetpgrp(fd, pgid) < 0)
9211         return posix_error();
9212     Py_RETURN_NONE;
9213 }
9214 #endif /* HAVE_TCSETPGRP */
9215 
9216 /* Functions acting on file descriptors */
9217 
9218 #ifdef O_CLOEXEC
9219 extern int _Py_open_cloexec_works;
9220 #endif
9221 
9222 
9223 /*[clinic input]
9224 os.open -> int
9225     path: path_t
9226     flags: int
9227     mode: int = 0o777
9228     *
9229     dir_fd: dir_fd(requires='openat') = None
9230 
9231 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
9232 
9233 Open a file for low level IO.  Returns a file descriptor (integer).
9234 
9235 If dir_fd is not None, it should be a file descriptor open to a directory,
9236   and path should be relative; path will then be relative to that directory.
9237 dir_fd may not be implemented on your platform.
9238   If it is unavailable, using it will raise a NotImplementedError.
9239 [clinic start generated code]*/
9240 
9241 static int
os_open_impl(PyObject * module,path_t * path,int flags,int mode,int dir_fd)9242 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
9243 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
9244 {
9245     int fd;
9246     int async_err = 0;
9247 #ifdef HAVE_OPENAT
9248     int openat_unavailable = 0;
9249 #endif
9250 
9251 #ifdef O_CLOEXEC
9252     int *atomic_flag_works = &_Py_open_cloexec_works;
9253 #elif !defined(MS_WINDOWS)
9254     int *atomic_flag_works = NULL;
9255 #endif
9256 
9257 #ifdef MS_WINDOWS
9258     flags |= O_NOINHERIT;
9259 #elif defined(O_CLOEXEC)
9260     flags |= O_CLOEXEC;
9261 #endif
9262 
9263     if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
9264         return -1;
9265     }
9266 
9267     _Py_BEGIN_SUPPRESS_IPH
9268     do {
9269         Py_BEGIN_ALLOW_THREADS
9270 #ifdef MS_WINDOWS
9271         fd = _wopen(path->wide, flags, mode);
9272 #else
9273 #ifdef HAVE_OPENAT
9274         if (dir_fd != DEFAULT_DIR_FD) {
9275             if (HAVE_OPENAT_RUNTIME) {
9276                 fd = openat(dir_fd, path->narrow, flags, mode);
9277 
9278             } else {
9279                 openat_unavailable = 1;
9280                 fd = -1;
9281             }
9282         } else
9283 #endif /* HAVE_OPENAT */
9284             fd = open(path->narrow, flags, mode);
9285 #endif /* !MS_WINDOWS */
9286         Py_END_ALLOW_THREADS
9287     } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9288     _Py_END_SUPPRESS_IPH
9289 
9290 #ifdef HAVE_OPENAT
9291     if (openat_unavailable) {
9292         argument_unavailable_error(NULL, "dir_fd");
9293         return -1;
9294     }
9295 #endif
9296 
9297     if (fd < 0) {
9298         if (!async_err)
9299             PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
9300         return -1;
9301     }
9302 
9303 #ifndef MS_WINDOWS
9304     if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
9305         close(fd);
9306         return -1;
9307     }
9308 #endif
9309 
9310     return fd;
9311 }
9312 
9313 
9314 /*[clinic input]
9315 os.close
9316 
9317     fd: int
9318 
9319 Close a file descriptor.
9320 [clinic start generated code]*/
9321 
9322 static PyObject *
os_close_impl(PyObject * module,int fd)9323 os_close_impl(PyObject *module, int fd)
9324 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
9325 {
9326     int res;
9327     /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
9328      * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
9329      * for more details.
9330      */
9331     Py_BEGIN_ALLOW_THREADS
9332     _Py_BEGIN_SUPPRESS_IPH
9333     res = close(fd);
9334     _Py_END_SUPPRESS_IPH
9335     Py_END_ALLOW_THREADS
9336     if (res < 0)
9337         return posix_error();
9338     Py_RETURN_NONE;
9339 }
9340 
9341 /*[clinic input]
9342 os.closerange
9343 
9344     fd_low: int
9345     fd_high: int
9346     /
9347 
9348 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
9349 [clinic start generated code]*/
9350 
9351 static PyObject *
os_closerange_impl(PyObject * module,int fd_low,int fd_high)9352 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
9353 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
9354 {
9355     Py_BEGIN_ALLOW_THREADS
9356     _Py_closerange(fd_low, fd_high - 1);
9357     Py_END_ALLOW_THREADS
9358     Py_RETURN_NONE;
9359 }
9360 
9361 
9362 /*[clinic input]
9363 os.dup -> int
9364 
9365     fd: int
9366     /
9367 
9368 Return a duplicate of a file descriptor.
9369 [clinic start generated code]*/
9370 
9371 static int
os_dup_impl(PyObject * module,int fd)9372 os_dup_impl(PyObject *module, int fd)
9373 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
9374 {
9375     return _Py_dup(fd);
9376 }
9377 
9378 // dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
9379 // dup2.c provides working dup2() if and only if F_DUPFD is available.
9380 #if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
9381 /*[clinic input]
9382 os.dup2 -> int
9383     fd: int
9384     fd2: int
9385     inheritable: bool=True
9386 
9387 Duplicate file descriptor.
9388 [clinic start generated code]*/
9389 
9390 static int
os_dup2_impl(PyObject * module,int fd,int fd2,int inheritable)9391 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
9392 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
9393 {
9394     int res = 0;
9395 #if defined(HAVE_DUP3) && \
9396     !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
9397     /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
9398     static int dup3_works = -1;
9399 #endif
9400 
9401     /* dup2() can fail with EINTR if the target FD is already open, because it
9402      * then has to be closed. See os_close_impl() for why we don't handle EINTR
9403      * upon close(), and therefore below.
9404      */
9405 #ifdef MS_WINDOWS
9406     Py_BEGIN_ALLOW_THREADS
9407     _Py_BEGIN_SUPPRESS_IPH
9408     res = dup2(fd, fd2);
9409     _Py_END_SUPPRESS_IPH
9410     Py_END_ALLOW_THREADS
9411     if (res < 0) {
9412         posix_error();
9413         return -1;
9414     }
9415     res = fd2; // msvcrt dup2 returns 0 on success.
9416 
9417     /* Character files like console cannot be make non-inheritable */
9418     if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9419         close(fd2);
9420         return -1;
9421     }
9422 
9423 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
9424     Py_BEGIN_ALLOW_THREADS
9425     if (!inheritable)
9426         res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
9427     else
9428         res = dup2(fd, fd2);
9429     Py_END_ALLOW_THREADS
9430     if (res < 0) {
9431         posix_error();
9432         return -1;
9433     }
9434 
9435 #else
9436 
9437 #ifdef HAVE_DUP3
9438     if (!inheritable && dup3_works != 0) {
9439         Py_BEGIN_ALLOW_THREADS
9440         res = dup3(fd, fd2, O_CLOEXEC);
9441         Py_END_ALLOW_THREADS
9442         if (res < 0) {
9443             if (dup3_works == -1)
9444                 dup3_works = (errno != ENOSYS);
9445             if (dup3_works) {
9446                 posix_error();
9447                 return -1;
9448             }
9449         }
9450     }
9451 
9452     if (inheritable || dup3_works == 0)
9453     {
9454 #endif
9455         Py_BEGIN_ALLOW_THREADS
9456         res = dup2(fd, fd2);
9457         Py_END_ALLOW_THREADS
9458         if (res < 0) {
9459             posix_error();
9460             return -1;
9461         }
9462 
9463         if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9464             close(fd2);
9465             return -1;
9466         }
9467 #ifdef HAVE_DUP3
9468     }
9469 #endif
9470 
9471 #endif
9472 
9473     return res;
9474 }
9475 #endif
9476 
9477 
9478 #ifdef HAVE_LOCKF
9479 /*[clinic input]
9480 os.lockf
9481 
9482     fd: int
9483         An open file descriptor.
9484     command: int
9485         One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
9486     length: Py_off_t
9487         The number of bytes to lock, starting at the current position.
9488     /
9489 
9490 Apply, test or remove a POSIX lock on an open file descriptor.
9491 
9492 [clinic start generated code]*/
9493 
9494 static PyObject *
os_lockf_impl(PyObject * module,int fd,int command,Py_off_t length)9495 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
9496 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
9497 {
9498     int res;
9499 
9500     if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
9501         return NULL;
9502     }
9503 
9504     Py_BEGIN_ALLOW_THREADS
9505     res = lockf(fd, command, length);
9506     Py_END_ALLOW_THREADS
9507 
9508     if (res < 0)
9509         return posix_error();
9510 
9511     Py_RETURN_NONE;
9512 }
9513 #endif /* HAVE_LOCKF */
9514 
9515 
9516 /*[clinic input]
9517 os.lseek -> Py_off_t
9518 
9519     fd: int
9520     position: Py_off_t
9521     how: int
9522     /
9523 
9524 Set the position of a file descriptor.  Return the new position.
9525 
9526 Return the new cursor position in number of bytes
9527 relative to the beginning of the file.
9528 [clinic start generated code]*/
9529 
9530 static Py_off_t
os_lseek_impl(PyObject * module,int fd,Py_off_t position,int how)9531 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
9532 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
9533 {
9534     Py_off_t result;
9535 
9536 #ifdef SEEK_SET
9537     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
9538     switch (how) {
9539         case 0: how = SEEK_SET; break;
9540         case 1: how = SEEK_CUR; break;
9541         case 2: how = SEEK_END; break;
9542     }
9543 #endif /* SEEK_END */
9544 
9545     Py_BEGIN_ALLOW_THREADS
9546     _Py_BEGIN_SUPPRESS_IPH
9547 #ifdef MS_WINDOWS
9548     result = _lseeki64(fd, position, how);
9549 #else
9550     result = lseek(fd, position, how);
9551 #endif
9552     _Py_END_SUPPRESS_IPH
9553     Py_END_ALLOW_THREADS
9554     if (result < 0)
9555         posix_error();
9556 
9557     return result;
9558 }
9559 
9560 
9561 /*[clinic input]
9562 os.read
9563     fd: int
9564     length: Py_ssize_t
9565     /
9566 
9567 Read from a file descriptor.  Returns a bytes object.
9568 [clinic start generated code]*/
9569 
9570 static PyObject *
os_read_impl(PyObject * module,int fd,Py_ssize_t length)9571 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
9572 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
9573 {
9574     Py_ssize_t n;
9575     PyObject *buffer;
9576 
9577     if (length < 0) {
9578         errno = EINVAL;
9579         return posix_error();
9580     }
9581 
9582     length = Py_MIN(length, _PY_READ_MAX);
9583 
9584     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9585     if (buffer == NULL)
9586         return NULL;
9587 
9588     n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
9589     if (n == -1) {
9590         Py_DECREF(buffer);
9591         return NULL;
9592     }
9593 
9594     if (n != length)
9595         _PyBytes_Resize(&buffer, n);
9596 
9597     return buffer;
9598 }
9599 
9600 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
9601                                 || defined(__APPLE__))) \
9602     || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
9603     || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9604 static int
iov_setup(struct iovec ** iov,Py_buffer ** buf,PyObject * seq,Py_ssize_t cnt,int type)9605 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
9606 {
9607     Py_ssize_t i, j;
9608 
9609     *iov = PyMem_New(struct iovec, cnt);
9610     if (*iov == NULL) {
9611         PyErr_NoMemory();
9612         return -1;
9613     }
9614 
9615     *buf = PyMem_New(Py_buffer, cnt);
9616     if (*buf == NULL) {
9617         PyMem_Free(*iov);
9618         PyErr_NoMemory();
9619         return -1;
9620     }
9621 
9622     for (i = 0; i < cnt; i++) {
9623         PyObject *item = PySequence_GetItem(seq, i);
9624         if (item == NULL)
9625             goto fail;
9626         if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
9627             Py_DECREF(item);
9628             goto fail;
9629         }
9630         Py_DECREF(item);
9631         (*iov)[i].iov_base = (*buf)[i].buf;
9632         (*iov)[i].iov_len = (*buf)[i].len;
9633     }
9634     return 0;
9635 
9636 fail:
9637     PyMem_Free(*iov);
9638     for (j = 0; j < i; j++) {
9639         PyBuffer_Release(&(*buf)[j]);
9640     }
9641     PyMem_Free(*buf);
9642     return -1;
9643 }
9644 
9645 static void
iov_cleanup(struct iovec * iov,Py_buffer * buf,int cnt)9646 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9647 {
9648     int i;
9649     PyMem_Free(iov);
9650     for (i = 0; i < cnt; i++) {
9651         PyBuffer_Release(&buf[i]);
9652     }
9653     PyMem_Free(buf);
9654 }
9655 #endif
9656 
9657 
9658 #ifdef HAVE_READV
9659 /*[clinic input]
9660 os.readv -> Py_ssize_t
9661 
9662     fd: int
9663     buffers: object
9664     /
9665 
9666 Read from a file descriptor fd into an iterable of buffers.
9667 
9668 The buffers should be mutable buffers accepting bytes.
9669 readv will transfer data into each buffer until it is full
9670 and then move on to the next buffer in the sequence to hold
9671 the rest of the data.
9672 
9673 readv returns the total number of bytes read,
9674 which may be less than the total capacity of all the buffers.
9675 [clinic start generated code]*/
9676 
9677 static Py_ssize_t
os_readv_impl(PyObject * module,int fd,PyObject * buffers)9678 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9679 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9680 {
9681     Py_ssize_t cnt, n;
9682     int async_err = 0;
9683     struct iovec *iov;
9684     Py_buffer *buf;
9685 
9686     if (!PySequence_Check(buffers)) {
9687         PyErr_SetString(PyExc_TypeError,
9688             "readv() arg 2 must be a sequence");
9689         return -1;
9690     }
9691 
9692     cnt = PySequence_Size(buffers);
9693     if (cnt < 0)
9694         return -1;
9695 
9696     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9697         return -1;
9698 
9699     do {
9700         Py_BEGIN_ALLOW_THREADS
9701         n = readv(fd, iov, cnt);
9702         Py_END_ALLOW_THREADS
9703     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9704 
9705     iov_cleanup(iov, buf, cnt);
9706     if (n < 0) {
9707         if (!async_err)
9708             posix_error();
9709         return -1;
9710     }
9711 
9712     return n;
9713 }
9714 #endif /* HAVE_READV */
9715 
9716 
9717 #ifdef HAVE_PREAD
9718 /*[clinic input]
9719 os.pread
9720 
9721     fd: int
9722     length: Py_ssize_t
9723     offset: Py_off_t
9724     /
9725 
9726 Read a number of bytes from a file descriptor starting at a particular offset.
9727 
9728 Read length bytes from file descriptor fd, starting at offset bytes from
9729 the beginning of the file.  The file offset remains unchanged.
9730 [clinic start generated code]*/
9731 
9732 static PyObject *
os_pread_impl(PyObject * module,int fd,Py_ssize_t length,Py_off_t offset)9733 os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
9734 /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
9735 {
9736     Py_ssize_t n;
9737     int async_err = 0;
9738     PyObject *buffer;
9739 
9740     if (length < 0) {
9741         errno = EINVAL;
9742         return posix_error();
9743     }
9744     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9745     if (buffer == NULL)
9746         return NULL;
9747 
9748     do {
9749         Py_BEGIN_ALLOW_THREADS
9750         _Py_BEGIN_SUPPRESS_IPH
9751         n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9752         _Py_END_SUPPRESS_IPH
9753         Py_END_ALLOW_THREADS
9754     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9755 
9756     if (n < 0) {
9757         Py_DECREF(buffer);
9758         return (!async_err) ? posix_error() : NULL;
9759     }
9760     if (n != length)
9761         _PyBytes_Resize(&buffer, n);
9762     return buffer;
9763 }
9764 #endif /* HAVE_PREAD */
9765 
9766 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9767 /*[clinic input]
9768 os.preadv -> Py_ssize_t
9769 
9770     fd: int
9771     buffers: object
9772     offset: Py_off_t
9773     flags: int = 0
9774     /
9775 
9776 Reads from a file descriptor into a number of mutable bytes-like objects.
9777 
9778 Combines the functionality of readv() and pread(). As readv(), it will
9779 transfer data into each buffer until it is full and then move on to the next
9780 buffer in the sequence to hold the rest of the data. Its fourth argument,
9781 specifies the file offset at which the input operation is to be performed. It
9782 will return the total number of bytes read (which can be less than the total
9783 capacity of all the objects).
9784 
9785 The flags argument contains a bitwise OR of zero or more of the following flags:
9786 
9787 - RWF_HIPRI
9788 - RWF_NOWAIT
9789 
9790 Using non-zero flags requires Linux 4.6 or newer.
9791 [clinic start generated code]*/
9792 
9793 static Py_ssize_t
os_preadv_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9794 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9795                int flags)
9796 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9797 {
9798     Py_ssize_t cnt, n;
9799     int async_err = 0;
9800     struct iovec *iov;
9801     Py_buffer *buf;
9802 
9803     if (!PySequence_Check(buffers)) {
9804         PyErr_SetString(PyExc_TypeError,
9805             "preadv2() arg 2 must be a sequence");
9806         return -1;
9807     }
9808 
9809     cnt = PySequence_Size(buffers);
9810     if (cnt < 0) {
9811         return -1;
9812     }
9813 
9814 #ifndef HAVE_PREADV2
9815     if(flags != 0) {
9816         argument_unavailable_error("preadv2", "flags");
9817         return -1;
9818     }
9819 #endif
9820 
9821     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9822         return -1;
9823     }
9824 #ifdef HAVE_PREADV2
9825     do {
9826         Py_BEGIN_ALLOW_THREADS
9827         _Py_BEGIN_SUPPRESS_IPH
9828         n = preadv2(fd, iov, cnt, offset, flags);
9829         _Py_END_SUPPRESS_IPH
9830         Py_END_ALLOW_THREADS
9831     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9832 #else
9833     do {
9834 #if defined(__APPLE__) && defined(__clang__)
9835 /* This entire function will be removed from the module dict when the API
9836  * is not available.
9837  */
9838 #pragma clang diagnostic push
9839 #pragma clang diagnostic ignored "-Wunguarded-availability"
9840 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
9841 #endif
9842         Py_BEGIN_ALLOW_THREADS
9843         _Py_BEGIN_SUPPRESS_IPH
9844         n = preadv(fd, iov, cnt, offset);
9845         _Py_END_SUPPRESS_IPH
9846         Py_END_ALLOW_THREADS
9847     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9848 
9849 #if defined(__APPLE__) && defined(__clang__)
9850 #pragma clang diagnostic pop
9851 #endif
9852 
9853 #endif
9854 
9855     iov_cleanup(iov, buf, cnt);
9856     if (n < 0) {
9857         if (!async_err) {
9858             posix_error();
9859         }
9860         return -1;
9861     }
9862 
9863     return n;
9864 }
9865 #endif /* HAVE_PREADV */
9866 
9867 
9868 /*[clinic input]
9869 os.write -> Py_ssize_t
9870 
9871     fd: int
9872     data: Py_buffer
9873     /
9874 
9875 Write a bytes object to a file descriptor.
9876 [clinic start generated code]*/
9877 
9878 static Py_ssize_t
os_write_impl(PyObject * module,int fd,Py_buffer * data)9879 os_write_impl(PyObject *module, int fd, Py_buffer *data)
9880 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9881 {
9882     return _Py_write(fd, data->buf, data->len);
9883 }
9884 
9885 #ifdef HAVE_SENDFILE
9886 #ifdef __APPLE__
9887 /*[clinic input]
9888 os.sendfile
9889 
9890     out_fd: int
9891     in_fd: int
9892     offset: Py_off_t
9893     count as sbytes: Py_off_t
9894     headers: object(c_default="NULL") = ()
9895     trailers: object(c_default="NULL") = ()
9896     flags: int = 0
9897 
9898 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9899 [clinic start generated code]*/
9900 
9901 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)9902 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9903                  Py_off_t sbytes, PyObject *headers, PyObject *trailers,
9904                  int flags)
9905 /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
9906 #elif defined(__FreeBSD__) || defined(__DragonFly__)
9907 /*[clinic input]
9908 os.sendfile
9909 
9910     out_fd: int
9911     in_fd: int
9912     offset: Py_off_t
9913     count: Py_ssize_t
9914     headers: object(c_default="NULL") = ()
9915     trailers: object(c_default="NULL") = ()
9916     flags: int = 0
9917 
9918 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9919 [clinic start generated code]*/
9920 
9921 static PyObject *
9922 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9923                  Py_ssize_t count, PyObject *headers, PyObject *trailers,
9924                  int flags)
9925 /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
9926 #else
9927 /*[clinic input]
9928 os.sendfile
9929 
9930     out_fd: int
9931     in_fd: int
9932     offset as offobj: object
9933     count: Py_ssize_t
9934 
9935 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9936 [clinic start generated code]*/
9937 
9938 static PyObject *
9939 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
9940                  Py_ssize_t count)
9941 /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
9942 #endif
9943 {
9944     Py_ssize_t ret;
9945     int async_err = 0;
9946 
9947 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9948 #ifndef __APPLE__
9949     off_t sbytes;
9950 #endif
9951     Py_buffer *hbuf, *tbuf;
9952     struct sf_hdtr sf;
9953 
9954     sf.headers = NULL;
9955     sf.trailers = NULL;
9956 
9957     if (headers != NULL) {
9958         if (!PySequence_Check(headers)) {
9959             PyErr_SetString(PyExc_TypeError,
9960                 "sendfile() headers must be a sequence");
9961             return NULL;
9962         } else {
9963             Py_ssize_t i = PySequence_Size(headers);
9964             if (i < 0)
9965                 return NULL;
9966             if (i > INT_MAX) {
9967                 PyErr_SetString(PyExc_OverflowError,
9968                     "sendfile() header is too large");
9969                 return NULL;
9970             }
9971             if (i > 0) {
9972                 sf.hdr_cnt = (int)i;
9973                 if (iov_setup(&(sf.headers), &hbuf,
9974                               headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9975                     return NULL;
9976 #ifdef __APPLE__
9977                 for (i = 0; i < sf.hdr_cnt; i++) {
9978                     Py_ssize_t blen = sf.headers[i].iov_len;
9979 # define OFF_T_MAX 0x7fffffffffffffff
9980                     if (sbytes >= OFF_T_MAX - blen) {
9981                         PyErr_SetString(PyExc_OverflowError,
9982                             "sendfile() header is too large");
9983                         return NULL;
9984                     }
9985                     sbytes += blen;
9986                 }
9987 #endif
9988             }
9989         }
9990     }
9991     if (trailers != NULL) {
9992         if (!PySequence_Check(trailers)) {
9993             PyErr_SetString(PyExc_TypeError,
9994                 "sendfile() trailers must be a sequence");
9995             return NULL;
9996         } else {
9997             Py_ssize_t i = PySequence_Size(trailers);
9998             if (i < 0)
9999                 return NULL;
10000             if (i > INT_MAX) {
10001                 PyErr_SetString(PyExc_OverflowError,
10002                     "sendfile() trailer is too large");
10003                 return NULL;
10004             }
10005             if (i > 0) {
10006                 sf.trl_cnt = (int)i;
10007                 if (iov_setup(&(sf.trailers), &tbuf,
10008                               trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
10009                     return NULL;
10010             }
10011         }
10012     }
10013 
10014     _Py_BEGIN_SUPPRESS_IPH
10015     do {
10016         Py_BEGIN_ALLOW_THREADS
10017 #ifdef __APPLE__
10018         ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
10019 #else
10020         ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
10021 #endif
10022         Py_END_ALLOW_THREADS
10023     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10024     _Py_END_SUPPRESS_IPH
10025 
10026     if (sf.headers != NULL)
10027         iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
10028     if (sf.trailers != NULL)
10029         iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
10030 
10031     if (ret < 0) {
10032         if ((errno == EAGAIN) || (errno == EBUSY)) {
10033             if (sbytes != 0) {
10034                 // some data has been sent
10035                 goto done;
10036             }
10037             else {
10038                 // no data has been sent; upper application is supposed
10039                 // to retry on EAGAIN or EBUSY
10040                 return posix_error();
10041             }
10042         }
10043         return (!async_err) ? posix_error() : NULL;
10044     }
10045     goto done;
10046 
10047 done:
10048     #if !defined(HAVE_LARGEFILE_SUPPORT)
10049         return Py_BuildValue("l", sbytes);
10050     #else
10051         return Py_BuildValue("L", sbytes);
10052     #endif
10053 
10054 #else
10055 #ifdef __linux__
10056     if (offobj == Py_None) {
10057         do {
10058             Py_BEGIN_ALLOW_THREADS
10059             ret = sendfile(out_fd, in_fd, NULL, count);
10060             Py_END_ALLOW_THREADS
10061         } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10062         if (ret < 0)
10063             return (!async_err) ? posix_error() : NULL;
10064         return Py_BuildValue("n", ret);
10065     }
10066 #endif
10067     off_t offset;
10068     if (!Py_off_t_converter(offobj, &offset))
10069         return NULL;
10070 
10071 #if defined(__sun) && defined(__SVR4)
10072     // On Solaris, sendfile raises EINVAL rather than returning 0
10073     // when the offset is equal or bigger than the in_fd size.
10074     struct stat st;
10075 
10076     do {
10077         Py_BEGIN_ALLOW_THREADS
10078         ret = fstat(in_fd, &st);
10079         Py_END_ALLOW_THREADS
10080     } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10081     if (ret < 0)
10082         return (!async_err) ? posix_error() : NULL;
10083 
10084     if (offset >= st.st_size) {
10085         return Py_BuildValue("i", 0);
10086     }
10087 
10088     // On illumos specifically sendfile() may perform a partial write but
10089     // return -1/an error (in one confirmed case the destination socket
10090     // had a 5 second timeout set and errno was EAGAIN) and it's on the client
10091     // code to check if the offset parameter was modified by sendfile().
10092     //
10093     // We need this variable to track said change.
10094     off_t original_offset = offset;
10095 #endif
10096 
10097     do {
10098         Py_BEGIN_ALLOW_THREADS
10099         ret = sendfile(out_fd, in_fd, &offset, count);
10100 #if defined(__sun) && defined(__SVR4)
10101         // This handles illumos-specific sendfile() partial write behavior,
10102         // see a comment above for more details.
10103         if (ret < 0 && offset != original_offset) {
10104             ret = offset - original_offset;
10105         }
10106 #endif
10107         Py_END_ALLOW_THREADS
10108     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10109     if (ret < 0)
10110         return (!async_err) ? posix_error() : NULL;
10111     return Py_BuildValue("n", ret);
10112 #endif
10113 }
10114 #endif /* HAVE_SENDFILE */
10115 
10116 
10117 #if defined(__APPLE__)
10118 /*[clinic input]
10119 os._fcopyfile
10120 
10121     in_fd: int
10122     out_fd: int
10123     flags: int
10124     /
10125 
10126 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
10127 [clinic start generated code]*/
10128 
10129 static PyObject *
os__fcopyfile_impl(PyObject * module,int in_fd,int out_fd,int flags)10130 os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
10131 /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
10132 {
10133     int ret;
10134 
10135     Py_BEGIN_ALLOW_THREADS
10136     ret = fcopyfile(in_fd, out_fd, NULL, flags);
10137     Py_END_ALLOW_THREADS
10138     if (ret < 0)
10139         return posix_error();
10140     Py_RETURN_NONE;
10141 }
10142 #endif
10143 
10144 
10145 /*[clinic input]
10146 os.fstat
10147 
10148     fd : int
10149 
10150 Perform a stat system call on the given file descriptor.
10151 
10152 Like stat(), but for an open file descriptor.
10153 Equivalent to os.stat(fd).
10154 [clinic start generated code]*/
10155 
10156 static PyObject *
os_fstat_impl(PyObject * module,int fd)10157 os_fstat_impl(PyObject *module, int fd)
10158 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
10159 {
10160     STRUCT_STAT st;
10161     int res;
10162     int async_err = 0;
10163 
10164     do {
10165         Py_BEGIN_ALLOW_THREADS
10166         res = FSTAT(fd, &st);
10167         Py_END_ALLOW_THREADS
10168     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10169     if (res != 0) {
10170 #ifdef MS_WINDOWS
10171         return PyErr_SetFromWindowsErr(0);
10172 #else
10173         return (!async_err) ? posix_error() : NULL;
10174 #endif
10175     }
10176 
10177     return _pystat_fromstructstat(module, &st);
10178 }
10179 
10180 
10181 /*[clinic input]
10182 os.isatty -> bool
10183     fd: int
10184     /
10185 
10186 Return True if the fd is connected to a terminal.
10187 
10188 Return True if the file descriptor is an open file descriptor
10189 connected to the slave end of a terminal.
10190 [clinic start generated code]*/
10191 
10192 static int
os_isatty_impl(PyObject * module,int fd)10193 os_isatty_impl(PyObject *module, int fd)
10194 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
10195 {
10196     int return_value;
10197     Py_BEGIN_ALLOW_THREADS
10198     _Py_BEGIN_SUPPRESS_IPH
10199     return_value = isatty(fd);
10200     _Py_END_SUPPRESS_IPH
10201     Py_END_ALLOW_THREADS
10202     return return_value;
10203 }
10204 
10205 
10206 #ifdef HAVE_PIPE
10207 /*[clinic input]
10208 os.pipe
10209 
10210 Create a pipe.
10211 
10212 Returns a tuple of two file descriptors:
10213   (read_fd, write_fd)
10214 [clinic start generated code]*/
10215 
10216 static PyObject *
os_pipe_impl(PyObject * module)10217 os_pipe_impl(PyObject *module)
10218 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
10219 {
10220     int fds[2];
10221 #ifdef MS_WINDOWS
10222     HANDLE read, write;
10223     SECURITY_ATTRIBUTES attr;
10224     BOOL ok;
10225 #else
10226     int res;
10227 #endif
10228 
10229 #ifdef MS_WINDOWS
10230     attr.nLength = sizeof(attr);
10231     attr.lpSecurityDescriptor = NULL;
10232     attr.bInheritHandle = FALSE;
10233 
10234     Py_BEGIN_ALLOW_THREADS
10235     ok = CreatePipe(&read, &write, &attr, 0);
10236     if (ok) {
10237         fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY);
10238         fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY);
10239         if (fds[0] == -1 || fds[1] == -1) {
10240             CloseHandle(read);
10241             CloseHandle(write);
10242             ok = 0;
10243         }
10244     }
10245     Py_END_ALLOW_THREADS
10246 
10247     if (!ok)
10248         return PyErr_SetFromWindowsErr(0);
10249 #else
10250 
10251 #ifdef HAVE_PIPE2
10252     Py_BEGIN_ALLOW_THREADS
10253     res = pipe2(fds, O_CLOEXEC);
10254     Py_END_ALLOW_THREADS
10255 
10256     if (res != 0 && errno == ENOSYS)
10257     {
10258 #endif
10259         Py_BEGIN_ALLOW_THREADS
10260         res = pipe(fds);
10261         Py_END_ALLOW_THREADS
10262 
10263         if (res == 0) {
10264             if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
10265                 close(fds[0]);
10266                 close(fds[1]);
10267                 return NULL;
10268             }
10269             if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
10270                 close(fds[0]);
10271                 close(fds[1]);
10272                 return NULL;
10273             }
10274         }
10275 #ifdef HAVE_PIPE2
10276     }
10277 #endif
10278 
10279     if (res != 0)
10280         return PyErr_SetFromErrno(PyExc_OSError);
10281 #endif /* !MS_WINDOWS */
10282     return Py_BuildValue("(ii)", fds[0], fds[1]);
10283 }
10284 #endif  /* HAVE_PIPE */
10285 
10286 
10287 #ifdef HAVE_PIPE2
10288 /*[clinic input]
10289 os.pipe2
10290 
10291     flags: int
10292     /
10293 
10294 Create a pipe with flags set atomically.
10295 
10296 Returns a tuple of two file descriptors:
10297   (read_fd, write_fd)
10298 
10299 flags can be constructed by ORing together one or more of these values:
10300 O_NONBLOCK, O_CLOEXEC.
10301 [clinic start generated code]*/
10302 
10303 static PyObject *
os_pipe2_impl(PyObject * module,int flags)10304 os_pipe2_impl(PyObject *module, int flags)
10305 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
10306 {
10307     int fds[2];
10308     int res;
10309 
10310     res = pipe2(fds, flags);
10311     if (res != 0)
10312         return posix_error();
10313     return Py_BuildValue("(ii)", fds[0], fds[1]);
10314 }
10315 #endif /* HAVE_PIPE2 */
10316 
10317 
10318 #ifdef HAVE_WRITEV
10319 /*[clinic input]
10320 os.writev -> Py_ssize_t
10321     fd: int
10322     buffers: object
10323     /
10324 
10325 Iterate over buffers, and write the contents of each to a file descriptor.
10326 
10327 Returns the total number of bytes written.
10328 buffers must be a sequence of bytes-like objects.
10329 [clinic start generated code]*/
10330 
10331 static Py_ssize_t
os_writev_impl(PyObject * module,int fd,PyObject * buffers)10332 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
10333 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
10334 {
10335     Py_ssize_t cnt;
10336     Py_ssize_t result;
10337     int async_err = 0;
10338     struct iovec *iov;
10339     Py_buffer *buf;
10340 
10341     if (!PySequence_Check(buffers)) {
10342         PyErr_SetString(PyExc_TypeError,
10343             "writev() arg 2 must be a sequence");
10344         return -1;
10345     }
10346     cnt = PySequence_Size(buffers);
10347     if (cnt < 0)
10348         return -1;
10349 
10350     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10351         return -1;
10352     }
10353 
10354     do {
10355         Py_BEGIN_ALLOW_THREADS
10356         result = writev(fd, iov, cnt);
10357         Py_END_ALLOW_THREADS
10358     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10359 
10360     iov_cleanup(iov, buf, cnt);
10361     if (result < 0 && !async_err)
10362         posix_error();
10363 
10364     return result;
10365 }
10366 #endif /* HAVE_WRITEV */
10367 
10368 
10369 #ifdef HAVE_PWRITE
10370 /*[clinic input]
10371 os.pwrite -> Py_ssize_t
10372 
10373     fd: int
10374     buffer: Py_buffer
10375     offset: Py_off_t
10376     /
10377 
10378 Write bytes to a file descriptor starting at a particular offset.
10379 
10380 Write buffer to fd, starting at offset bytes from the beginning of
10381 the file.  Returns the number of bytes writte.  Does not change the
10382 current file offset.
10383 [clinic start generated code]*/
10384 
10385 static Py_ssize_t
os_pwrite_impl(PyObject * module,int fd,Py_buffer * buffer,Py_off_t offset)10386 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
10387 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
10388 {
10389     Py_ssize_t size;
10390     int async_err = 0;
10391 
10392     do {
10393         Py_BEGIN_ALLOW_THREADS
10394         _Py_BEGIN_SUPPRESS_IPH
10395         size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
10396         _Py_END_SUPPRESS_IPH
10397         Py_END_ALLOW_THREADS
10398     } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10399 
10400     if (size < 0 && !async_err)
10401         posix_error();
10402     return size;
10403 }
10404 #endif /* HAVE_PWRITE */
10405 
10406 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
10407 /*[clinic input]
10408 os.pwritev -> Py_ssize_t
10409 
10410     fd: int
10411     buffers: object
10412     offset: Py_off_t
10413     flags: int = 0
10414     /
10415 
10416 Writes the contents of bytes-like objects to a file descriptor at a given offset.
10417 
10418 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
10419 of bytes-like objects. Buffers are processed in array order. Entire contents of first
10420 buffer is written before proceeding to second, and so on. The operating system may
10421 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
10422 This function writes the contents of each object to the file descriptor and returns
10423 the total number of bytes written.
10424 
10425 The flags argument contains a bitwise OR of zero or more of the following flags:
10426 
10427 - RWF_DSYNC
10428 - RWF_SYNC
10429 - RWF_APPEND
10430 
10431 Using non-zero flags requires Linux 4.7 or newer.
10432 [clinic start generated code]*/
10433 
10434 static Py_ssize_t
os_pwritev_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)10435 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
10436                 int flags)
10437 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
10438 {
10439     Py_ssize_t cnt;
10440     Py_ssize_t result;
10441     int async_err = 0;
10442     struct iovec *iov;
10443     Py_buffer *buf;
10444 
10445     if (!PySequence_Check(buffers)) {
10446         PyErr_SetString(PyExc_TypeError,
10447             "pwritev() arg 2 must be a sequence");
10448         return -1;
10449     }
10450 
10451     cnt = PySequence_Size(buffers);
10452     if (cnt < 0) {
10453         return -1;
10454     }
10455 
10456 #ifndef HAVE_PWRITEV2
10457     if(flags != 0) {
10458         argument_unavailable_error("pwritev2", "flags");
10459         return -1;
10460     }
10461 #endif
10462 
10463     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10464         return -1;
10465     }
10466 #ifdef HAVE_PWRITEV2
10467     do {
10468         Py_BEGIN_ALLOW_THREADS
10469         _Py_BEGIN_SUPPRESS_IPH
10470         result = pwritev2(fd, iov, cnt, offset, flags);
10471         _Py_END_SUPPRESS_IPH
10472         Py_END_ALLOW_THREADS
10473     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10474 #else
10475 
10476 #if defined(__APPLE__) && defined(__clang__)
10477 /* This entire function will be removed from the module dict when the API
10478  * is not available.
10479  */
10480 #pragma clang diagnostic push
10481 #pragma clang diagnostic ignored "-Wunguarded-availability"
10482 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
10483 #endif
10484     do {
10485         Py_BEGIN_ALLOW_THREADS
10486         _Py_BEGIN_SUPPRESS_IPH
10487         result = pwritev(fd, iov, cnt, offset);
10488         _Py_END_SUPPRESS_IPH
10489         Py_END_ALLOW_THREADS
10490     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10491 
10492 #if defined(__APPLE__) && defined(__clang__)
10493 #pragma clang diagnostic pop
10494 #endif
10495 
10496 #endif
10497 
10498     iov_cleanup(iov, buf, cnt);
10499     if (result < 0) {
10500         if (!async_err) {
10501             posix_error();
10502         }
10503         return -1;
10504     }
10505 
10506     return result;
10507 }
10508 #endif /* HAVE_PWRITEV */
10509 
10510 #ifdef HAVE_COPY_FILE_RANGE
10511 /*[clinic input]
10512 
10513 os.copy_file_range
10514     src: int
10515         Source file descriptor.
10516     dst: int
10517         Destination file descriptor.
10518     count: Py_ssize_t
10519         Number of bytes to copy.
10520     offset_src: object = None
10521         Starting offset in src.
10522     offset_dst: object = None
10523         Starting offset in dst.
10524 
10525 Copy count bytes from one file descriptor to another.
10526 
10527 If offset_src is None, then src is read from the current position;
10528 respectively for offset_dst.
10529 [clinic start generated code]*/
10530 
10531 static PyObject *
os_copy_file_range_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst)10532 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10533                         PyObject *offset_src, PyObject *offset_dst)
10534 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
10535 {
10536     off_t offset_src_val, offset_dst_val;
10537     off_t *p_offset_src = NULL;
10538     off_t *p_offset_dst = NULL;
10539     Py_ssize_t ret;
10540     int async_err = 0;
10541     /* The flags argument is provided to allow
10542      * for future extensions and currently must be to 0. */
10543     int flags = 0;
10544 
10545 
10546     if (count < 0) {
10547         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10548         return NULL;
10549     }
10550 
10551     if (offset_src != Py_None) {
10552         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10553             return NULL;
10554         }
10555         p_offset_src = &offset_src_val;
10556     }
10557 
10558     if (offset_dst != Py_None) {
10559         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10560             return NULL;
10561         }
10562         p_offset_dst = &offset_dst_val;
10563     }
10564 
10565     do {
10566         Py_BEGIN_ALLOW_THREADS
10567         ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
10568         Py_END_ALLOW_THREADS
10569     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10570 
10571     if (ret < 0) {
10572         return (!async_err) ? posix_error() : NULL;
10573     }
10574 
10575     return PyLong_FromSsize_t(ret);
10576 }
10577 #endif /* HAVE_COPY_FILE_RANGE*/
10578 
10579 #if (defined(HAVE_SPLICE) && !defined(_AIX))
10580 /*[clinic input]
10581 
10582 os.splice
10583     src: int
10584         Source file descriptor.
10585     dst: int
10586         Destination file descriptor.
10587     count: Py_ssize_t
10588         Number of bytes to copy.
10589     offset_src: object = None
10590         Starting offset in src.
10591     offset_dst: object = None
10592         Starting offset in dst.
10593     flags: unsigned_int = 0
10594         Flags to modify the semantics of the call.
10595 
10596 Transfer count bytes from one pipe to a descriptor or vice versa.
10597 
10598 If offset_src is None, then src is read from the current position;
10599 respectively for offset_dst. The offset associated to the file
10600 descriptor that refers to a pipe must be None.
10601 [clinic start generated code]*/
10602 
10603 static PyObject *
os_splice_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst,unsigned int flags)10604 os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10605                PyObject *offset_src, PyObject *offset_dst,
10606                unsigned int flags)
10607 /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
10608 {
10609     off_t offset_src_val, offset_dst_val;
10610     off_t *p_offset_src = NULL;
10611     off_t *p_offset_dst = NULL;
10612     Py_ssize_t ret;
10613     int async_err = 0;
10614 
10615     if (count < 0) {
10616         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10617         return NULL;
10618     }
10619 
10620     if (offset_src != Py_None) {
10621         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10622             return NULL;
10623         }
10624         p_offset_src = &offset_src_val;
10625     }
10626 
10627     if (offset_dst != Py_None) {
10628         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10629             return NULL;
10630         }
10631         p_offset_dst = &offset_dst_val;
10632     }
10633 
10634     do {
10635         Py_BEGIN_ALLOW_THREADS
10636         ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
10637         Py_END_ALLOW_THREADS
10638     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10639 
10640     if (ret < 0) {
10641         return (!async_err) ? posix_error() : NULL;
10642     }
10643 
10644     return PyLong_FromSsize_t(ret);
10645 }
10646 #endif /* HAVE_SPLICE*/
10647 
10648 #ifdef HAVE_MKFIFO
10649 /*[clinic input]
10650 os.mkfifo
10651 
10652     path: path_t
10653     mode: int=0o666
10654     *
10655     dir_fd: dir_fd(requires='mkfifoat')=None
10656 
10657 Create a "fifo" (a POSIX named pipe).
10658 
10659 If dir_fd is not None, it should be a file descriptor open to a directory,
10660   and path should be relative; path will then be relative to that directory.
10661 dir_fd may not be implemented on your platform.
10662   If it is unavailable, using it will raise a NotImplementedError.
10663 [clinic start generated code]*/
10664 
10665 static PyObject *
os_mkfifo_impl(PyObject * module,path_t * path,int mode,int dir_fd)10666 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
10667 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
10668 {
10669     int result;
10670     int async_err = 0;
10671 #ifdef HAVE_MKFIFOAT
10672     int mkfifoat_unavailable = 0;
10673 #endif
10674 
10675     do {
10676         Py_BEGIN_ALLOW_THREADS
10677 #ifdef HAVE_MKFIFOAT
10678         if (dir_fd != DEFAULT_DIR_FD) {
10679             if (HAVE_MKFIFOAT_RUNTIME) {
10680                 result = mkfifoat(dir_fd, path->narrow, mode);
10681 
10682             } else {
10683                 mkfifoat_unavailable = 1;
10684                 result = 0;
10685             }
10686         } else
10687 #endif
10688             result = mkfifo(path->narrow, mode);
10689         Py_END_ALLOW_THREADS
10690     } while (result != 0 && errno == EINTR &&
10691              !(async_err = PyErr_CheckSignals()));
10692 
10693 #ifdef HAVE_MKFIFOAT
10694     if (mkfifoat_unavailable) {
10695         argument_unavailable_error(NULL, "dir_fd");
10696         return NULL;
10697     }
10698 #endif
10699 
10700     if (result != 0)
10701         return (!async_err) ? posix_error() : NULL;
10702 
10703     Py_RETURN_NONE;
10704 }
10705 #endif /* HAVE_MKFIFO */
10706 
10707 
10708 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
10709 /*[clinic input]
10710 os.mknod
10711 
10712     path: path_t
10713     mode: int=0o600
10714     device: dev_t=0
10715     *
10716     dir_fd: dir_fd(requires='mknodat')=None
10717 
10718 Create a node in the file system.
10719 
10720 Create a node in the file system (file, device special file or named pipe)
10721 at path.  mode specifies both the permissions to use and the
10722 type of node to be created, being combined (bitwise OR) with one of
10723 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
10724 device defines the newly created device special file (probably using
10725 os.makedev()).  Otherwise device is ignored.
10726 
10727 If dir_fd is not None, it should be a file descriptor open to a directory,
10728   and path should be relative; path will then be relative to that directory.
10729 dir_fd may not be implemented on your platform.
10730   If it is unavailable, using it will raise a NotImplementedError.
10731 [clinic start generated code]*/
10732 
10733 static PyObject *
os_mknod_impl(PyObject * module,path_t * path,int mode,dev_t device,int dir_fd)10734 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
10735               int dir_fd)
10736 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
10737 {
10738     int result;
10739     int async_err = 0;
10740 #ifdef HAVE_MKNODAT
10741     int mknodat_unavailable = 0;
10742 #endif
10743 
10744     do {
10745         Py_BEGIN_ALLOW_THREADS
10746 #ifdef HAVE_MKNODAT
10747         if (dir_fd != DEFAULT_DIR_FD) {
10748             if (HAVE_MKNODAT_RUNTIME) {
10749                 result = mknodat(dir_fd, path->narrow, mode, device);
10750 
10751             } else {
10752                 mknodat_unavailable = 1;
10753                 result = 0;
10754             }
10755         } else
10756 #endif
10757             result = mknod(path->narrow, mode, device);
10758         Py_END_ALLOW_THREADS
10759     } while (result != 0 && errno == EINTR &&
10760              !(async_err = PyErr_CheckSignals()));
10761 #ifdef HAVE_MKNODAT
10762     if (mknodat_unavailable) {
10763         argument_unavailable_error(NULL, "dir_fd");
10764         return NULL;
10765     }
10766 #endif
10767     if (result != 0)
10768         return (!async_err) ? posix_error() : NULL;
10769 
10770     Py_RETURN_NONE;
10771 }
10772 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
10773 
10774 
10775 #ifdef HAVE_DEVICE_MACROS
10776 /*[clinic input]
10777 os.major -> unsigned_int
10778 
10779     device: dev_t
10780     /
10781 
10782 Extracts a device major number from a raw device number.
10783 [clinic start generated code]*/
10784 
10785 static unsigned int
os_major_impl(PyObject * module,dev_t device)10786 os_major_impl(PyObject *module, dev_t device)
10787 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
10788 {
10789     return major(device);
10790 }
10791 
10792 
10793 /*[clinic input]
10794 os.minor -> unsigned_int
10795 
10796     device: dev_t
10797     /
10798 
10799 Extracts a device minor number from a raw device number.
10800 [clinic start generated code]*/
10801 
10802 static unsigned int
os_minor_impl(PyObject * module,dev_t device)10803 os_minor_impl(PyObject *module, dev_t device)
10804 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10805 {
10806     return minor(device);
10807 }
10808 
10809 
10810 /*[clinic input]
10811 os.makedev -> dev_t
10812 
10813     major: int
10814     minor: int
10815     /
10816 
10817 Composes a raw device number from the major and minor device numbers.
10818 [clinic start generated code]*/
10819 
10820 static dev_t
os_makedev_impl(PyObject * module,int major,int minor)10821 os_makedev_impl(PyObject *module, int major, int minor)
10822 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10823 {
10824     return makedev(major, minor);
10825 }
10826 #endif /* HAVE_DEVICE_MACROS */
10827 
10828 
10829 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10830 /*[clinic input]
10831 os.ftruncate
10832 
10833     fd: int
10834     length: Py_off_t
10835     /
10836 
10837 Truncate a file, specified by file descriptor, to a specific length.
10838 [clinic start generated code]*/
10839 
10840 static PyObject *
os_ftruncate_impl(PyObject * module,int fd,Py_off_t length)10841 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10842 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10843 {
10844     int result;
10845     int async_err = 0;
10846 
10847     if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10848         return NULL;
10849     }
10850 
10851     do {
10852         Py_BEGIN_ALLOW_THREADS
10853         _Py_BEGIN_SUPPRESS_IPH
10854 #ifdef MS_WINDOWS
10855         result = _chsize_s(fd, length);
10856 #else
10857         result = ftruncate(fd, length);
10858 #endif
10859         _Py_END_SUPPRESS_IPH
10860         Py_END_ALLOW_THREADS
10861     } while (result != 0 && errno == EINTR &&
10862              !(async_err = PyErr_CheckSignals()));
10863     if (result != 0)
10864         return (!async_err) ? posix_error() : NULL;
10865     Py_RETURN_NONE;
10866 }
10867 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10868 
10869 
10870 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10871 /*[clinic input]
10872 os.truncate
10873     path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10874     length: Py_off_t
10875 
10876 Truncate a file, specified by path, to a specific length.
10877 
10878 On some platforms, path may also be specified as an open file descriptor.
10879   If this functionality is unavailable, using it raises an exception.
10880 [clinic start generated code]*/
10881 
10882 static PyObject *
os_truncate_impl(PyObject * module,path_t * path,Py_off_t length)10883 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10884 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10885 {
10886     int result;
10887 #ifdef MS_WINDOWS
10888     int fd;
10889 #endif
10890 
10891     if (path->fd != -1)
10892         return os_ftruncate_impl(module, path->fd, length);
10893 
10894     if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10895         return NULL;
10896     }
10897 
10898     Py_BEGIN_ALLOW_THREADS
10899     _Py_BEGIN_SUPPRESS_IPH
10900 #ifdef MS_WINDOWS
10901     fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10902     if (fd < 0)
10903         result = -1;
10904     else {
10905         result = _chsize_s(fd, length);
10906         close(fd);
10907         if (result < 0)
10908             errno = result;
10909     }
10910 #else
10911     result = truncate(path->narrow, length);
10912 #endif
10913     _Py_END_SUPPRESS_IPH
10914     Py_END_ALLOW_THREADS
10915     if (result < 0)
10916         return posix_path_error(path);
10917 
10918     Py_RETURN_NONE;
10919 }
10920 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10921 
10922 
10923 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10924    and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10925    defined, which is the case in Python on AIX. AIX bug report:
10926    http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10927 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10928 #  define POSIX_FADVISE_AIX_BUG
10929 #endif
10930 
10931 
10932 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10933 /*[clinic input]
10934 os.posix_fallocate
10935 
10936     fd: int
10937     offset: Py_off_t
10938     length: Py_off_t
10939     /
10940 
10941 Ensure a file has allocated at least a particular number of bytes on disk.
10942 
10943 Ensure that the file specified by fd encompasses a range of bytes
10944 starting at offset bytes from the beginning and continuing for length bytes.
10945 [clinic start generated code]*/
10946 
10947 static PyObject *
os_posix_fallocate_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length)10948 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10949                         Py_off_t length)
10950 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10951 {
10952     int result;
10953     int async_err = 0;
10954 
10955     do {
10956         Py_BEGIN_ALLOW_THREADS
10957         result = posix_fallocate(fd, offset, length);
10958         Py_END_ALLOW_THREADS
10959     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10960 
10961     if (result == 0)
10962         Py_RETURN_NONE;
10963 
10964     if (async_err)
10965         return NULL;
10966 
10967     errno = result;
10968     return posix_error();
10969 }
10970 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
10971 
10972 
10973 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
10974 /*[clinic input]
10975 os.posix_fadvise
10976 
10977     fd: int
10978     offset: Py_off_t
10979     length: Py_off_t
10980     advice: int
10981     /
10982 
10983 Announce an intention to access data in a specific pattern.
10984 
10985 Announce an intention to access data in a specific pattern, thus allowing
10986 the kernel to make optimizations.
10987 The advice applies to the region of the file specified by fd starting at
10988 offset and continuing for length bytes.
10989 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
10990 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
10991 POSIX_FADV_DONTNEED.
10992 [clinic start generated code]*/
10993 
10994 static PyObject *
os_posix_fadvise_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length,int advice)10995 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
10996                       Py_off_t length, int advice)
10997 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
10998 {
10999     int result;
11000     int async_err = 0;
11001 
11002     do {
11003         Py_BEGIN_ALLOW_THREADS
11004         result = posix_fadvise(fd, offset, length, advice);
11005         Py_END_ALLOW_THREADS
11006     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
11007 
11008     if (result == 0)
11009         Py_RETURN_NONE;
11010 
11011     if (async_err)
11012         return NULL;
11013 
11014     errno = result;
11015     return posix_error();
11016 }
11017 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
11018 
11019 
11020 #ifdef MS_WINDOWS
11021 static PyObject*
win32_putenv(PyObject * name,PyObject * value)11022 win32_putenv(PyObject *name, PyObject *value)
11023 {
11024     /* Search from index 1 because on Windows starting '=' is allowed for
11025        defining hidden environment variables. */
11026     if (PyUnicode_GET_LENGTH(name) == 0 ||
11027         PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
11028     {
11029         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11030         return NULL;
11031     }
11032     PyObject *unicode;
11033     if (value != NULL) {
11034         unicode = PyUnicode_FromFormat("%U=%U", name, value);
11035     }
11036     else {
11037         unicode = PyUnicode_FromFormat("%U=", name);
11038     }
11039     if (unicode == NULL) {
11040         return NULL;
11041     }
11042 
11043     Py_ssize_t size;
11044     /* PyUnicode_AsWideCharString() rejects embedded null characters */
11045     wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
11046     Py_DECREF(unicode);
11047 
11048     if (env == NULL) {
11049         return NULL;
11050     }
11051     if (size > _MAX_ENV) {
11052         PyErr_Format(PyExc_ValueError,
11053                      "the environment variable is longer than %u characters",
11054                      _MAX_ENV);
11055         PyMem_Free(env);
11056         return NULL;
11057     }
11058 
11059     /* _wputenv() and SetEnvironmentVariableW() update the environment in the
11060        Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
11061        and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
11062 
11063        Prefer _wputenv() to be compatible with C libraries using CRT
11064        variables and CRT functions using these variables (ex: getenv()). */
11065     int err = _wputenv(env);
11066     PyMem_Free(env);
11067 
11068     if (err) {
11069         posix_error();
11070         return NULL;
11071     }
11072 
11073     Py_RETURN_NONE;
11074 }
11075 #endif
11076 
11077 
11078 #ifdef MS_WINDOWS
11079 /*[clinic input]
11080 os.putenv
11081 
11082     name: unicode
11083     value: unicode
11084     /
11085 
11086 Change or add an environment variable.
11087 [clinic start generated code]*/
11088 
11089 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)11090 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11091 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
11092 {
11093     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11094         return NULL;
11095     }
11096     return win32_putenv(name, value);
11097 }
11098 #else
11099 /*[clinic input]
11100 os.putenv
11101 
11102     name: FSConverter
11103     value: FSConverter
11104     /
11105 
11106 Change or add an environment variable.
11107 [clinic start generated code]*/
11108 
11109 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)11110 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11111 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
11112 {
11113     const char *name_string = PyBytes_AS_STRING(name);
11114     const char *value_string = PyBytes_AS_STRING(value);
11115 
11116     if (strchr(name_string, '=') != NULL) {
11117         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11118         return NULL;
11119     }
11120 
11121     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11122         return NULL;
11123     }
11124 
11125     if (setenv(name_string, value_string, 1)) {
11126         return posix_error();
11127     }
11128     Py_RETURN_NONE;
11129 }
11130 #endif  /* !defined(MS_WINDOWS) */
11131 
11132 
11133 #ifdef MS_WINDOWS
11134 /*[clinic input]
11135 os.unsetenv
11136     name: unicode
11137     /
11138 
11139 Delete an environment variable.
11140 [clinic start generated code]*/
11141 
11142 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)11143 os_unsetenv_impl(PyObject *module, PyObject *name)
11144 /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
11145 {
11146     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11147         return NULL;
11148     }
11149     return win32_putenv(name, NULL);
11150 }
11151 #else
11152 /*[clinic input]
11153 os.unsetenv
11154     name: FSConverter
11155     /
11156 
11157 Delete an environment variable.
11158 [clinic start generated code]*/
11159 
11160 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)11161 os_unsetenv_impl(PyObject *module, PyObject *name)
11162 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
11163 {
11164     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11165         return NULL;
11166     }
11167 #ifdef HAVE_BROKEN_UNSETENV
11168     unsetenv(PyBytes_AS_STRING(name));
11169 #else
11170     int err = unsetenv(PyBytes_AS_STRING(name));
11171     if (err) {
11172         return posix_error();
11173     }
11174 #endif
11175 
11176     Py_RETURN_NONE;
11177 }
11178 #endif /* !MS_WINDOWS */
11179 
11180 
11181 /*[clinic input]
11182 os.strerror
11183 
11184     code: int
11185     /
11186 
11187 Translate an error code to a message string.
11188 [clinic start generated code]*/
11189 
11190 static PyObject *
os_strerror_impl(PyObject * module,int code)11191 os_strerror_impl(PyObject *module, int code)
11192 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
11193 {
11194     char *message = strerror(code);
11195     if (message == NULL) {
11196         PyErr_SetString(PyExc_ValueError,
11197                         "strerror() argument out of range");
11198         return NULL;
11199     }
11200     return PyUnicode_DecodeLocale(message, "surrogateescape");
11201 }
11202 
11203 
11204 #ifdef HAVE_SYS_WAIT_H
11205 #ifdef WCOREDUMP
11206 /*[clinic input]
11207 os.WCOREDUMP -> bool
11208 
11209     status: int
11210     /
11211 
11212 Return True if the process returning status was dumped to a core file.
11213 [clinic start generated code]*/
11214 
11215 static int
os_WCOREDUMP_impl(PyObject * module,int status)11216 os_WCOREDUMP_impl(PyObject *module, int status)
11217 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
11218 {
11219     WAIT_TYPE wait_status;
11220     WAIT_STATUS_INT(wait_status) = status;
11221     return WCOREDUMP(wait_status);
11222 }
11223 #endif /* WCOREDUMP */
11224 
11225 
11226 #ifdef WIFCONTINUED
11227 /*[clinic input]
11228 os.WIFCONTINUED -> bool
11229 
11230     status: int
11231 
11232 Return True if a particular process was continued from a job control stop.
11233 
11234 Return True if the process returning status was continued from a
11235 job control stop.
11236 [clinic start generated code]*/
11237 
11238 static int
os_WIFCONTINUED_impl(PyObject * module,int status)11239 os_WIFCONTINUED_impl(PyObject *module, int status)
11240 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
11241 {
11242     WAIT_TYPE wait_status;
11243     WAIT_STATUS_INT(wait_status) = status;
11244     return WIFCONTINUED(wait_status);
11245 }
11246 #endif /* WIFCONTINUED */
11247 
11248 
11249 #ifdef WIFSTOPPED
11250 /*[clinic input]
11251 os.WIFSTOPPED -> bool
11252 
11253     status: int
11254 
11255 Return True if the process returning status was stopped.
11256 [clinic start generated code]*/
11257 
11258 static int
os_WIFSTOPPED_impl(PyObject * module,int status)11259 os_WIFSTOPPED_impl(PyObject *module, int status)
11260 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
11261 {
11262     WAIT_TYPE wait_status;
11263     WAIT_STATUS_INT(wait_status) = status;
11264     return WIFSTOPPED(wait_status);
11265 }
11266 #endif /* WIFSTOPPED */
11267 
11268 
11269 #ifdef WIFSIGNALED
11270 /*[clinic input]
11271 os.WIFSIGNALED -> bool
11272 
11273     status: int
11274 
11275 Return True if the process returning status was terminated by a signal.
11276 [clinic start generated code]*/
11277 
11278 static int
os_WIFSIGNALED_impl(PyObject * module,int status)11279 os_WIFSIGNALED_impl(PyObject *module, int status)
11280 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
11281 {
11282     WAIT_TYPE wait_status;
11283     WAIT_STATUS_INT(wait_status) = status;
11284     return WIFSIGNALED(wait_status);
11285 }
11286 #endif /* WIFSIGNALED */
11287 
11288 
11289 #ifdef WIFEXITED
11290 /*[clinic input]
11291 os.WIFEXITED -> bool
11292 
11293     status: int
11294 
11295 Return True if the process returning status exited via the exit() system call.
11296 [clinic start generated code]*/
11297 
11298 static int
os_WIFEXITED_impl(PyObject * module,int status)11299 os_WIFEXITED_impl(PyObject *module, int status)
11300 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
11301 {
11302     WAIT_TYPE wait_status;
11303     WAIT_STATUS_INT(wait_status) = status;
11304     return WIFEXITED(wait_status);
11305 }
11306 #endif /* WIFEXITED */
11307 
11308 
11309 #ifdef WEXITSTATUS
11310 /*[clinic input]
11311 os.WEXITSTATUS -> int
11312 
11313     status: int
11314 
11315 Return the process return code from status.
11316 [clinic start generated code]*/
11317 
11318 static int
os_WEXITSTATUS_impl(PyObject * module,int status)11319 os_WEXITSTATUS_impl(PyObject *module, int status)
11320 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
11321 {
11322     WAIT_TYPE wait_status;
11323     WAIT_STATUS_INT(wait_status) = status;
11324     return WEXITSTATUS(wait_status);
11325 }
11326 #endif /* WEXITSTATUS */
11327 
11328 
11329 #ifdef WTERMSIG
11330 /*[clinic input]
11331 os.WTERMSIG -> int
11332 
11333     status: int
11334 
11335 Return the signal that terminated the process that provided the status value.
11336 [clinic start generated code]*/
11337 
11338 static int
os_WTERMSIG_impl(PyObject * module,int status)11339 os_WTERMSIG_impl(PyObject *module, int status)
11340 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
11341 {
11342     WAIT_TYPE wait_status;
11343     WAIT_STATUS_INT(wait_status) = status;
11344     return WTERMSIG(wait_status);
11345 }
11346 #endif /* WTERMSIG */
11347 
11348 
11349 #ifdef WSTOPSIG
11350 /*[clinic input]
11351 os.WSTOPSIG -> int
11352 
11353     status: int
11354 
11355 Return the signal that stopped the process that provided the status value.
11356 [clinic start generated code]*/
11357 
11358 static int
os_WSTOPSIG_impl(PyObject * module,int status)11359 os_WSTOPSIG_impl(PyObject *module, int status)
11360 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
11361 {
11362     WAIT_TYPE wait_status;
11363     WAIT_STATUS_INT(wait_status) = status;
11364     return WSTOPSIG(wait_status);
11365 }
11366 #endif /* WSTOPSIG */
11367 #endif /* HAVE_SYS_WAIT_H */
11368 
11369 
11370 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
11371 #ifdef _SCO_DS
11372 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
11373    needed definitions in sys/statvfs.h */
11374 #define _SVID3
11375 #endif
11376 #include <sys/statvfs.h>
11377 
11378 static PyObject*
_pystatvfs_fromstructstatvfs(PyObject * module,struct statvfs st)11379 _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
11380     PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
11381     PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
11382     if (v == NULL)
11383         return NULL;
11384 
11385 #if !defined(HAVE_LARGEFILE_SUPPORT)
11386     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11387     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11388     PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
11389     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
11390     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
11391     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
11392     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
11393     PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
11394     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11395     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11396 #else
11397     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11398     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11399     PyStructSequence_SET_ITEM(v, 2,
11400                               PyLong_FromLongLong((long long) st.f_blocks));
11401     PyStructSequence_SET_ITEM(v, 3,
11402                               PyLong_FromLongLong((long long) st.f_bfree));
11403     PyStructSequence_SET_ITEM(v, 4,
11404                               PyLong_FromLongLong((long long) st.f_bavail));
11405     PyStructSequence_SET_ITEM(v, 5,
11406                               PyLong_FromLongLong((long long) st.f_files));
11407     PyStructSequence_SET_ITEM(v, 6,
11408                               PyLong_FromLongLong((long long) st.f_ffree));
11409     PyStructSequence_SET_ITEM(v, 7,
11410                               PyLong_FromLongLong((long long) st.f_favail));
11411     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11412     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11413 #endif
11414 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
11415  * (issue #32390). */
11416 #if defined(_AIX) && defined(_ALL_SOURCE)
11417     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
11418 #else
11419     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
11420 #endif
11421     if (PyErr_Occurred()) {
11422         Py_DECREF(v);
11423         return NULL;
11424     }
11425 
11426     return v;
11427 }
11428 
11429 
11430 /*[clinic input]
11431 os.fstatvfs
11432     fd: int
11433     /
11434 
11435 Perform an fstatvfs system call on the given fd.
11436 
11437 Equivalent to statvfs(fd).
11438 [clinic start generated code]*/
11439 
11440 static PyObject *
os_fstatvfs_impl(PyObject * module,int fd)11441 os_fstatvfs_impl(PyObject *module, int fd)
11442 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
11443 {
11444     int result;
11445     int async_err = 0;
11446     struct statvfs st;
11447 
11448     do {
11449         Py_BEGIN_ALLOW_THREADS
11450         result = fstatvfs(fd, &st);
11451         Py_END_ALLOW_THREADS
11452     } while (result != 0 && errno == EINTR &&
11453              !(async_err = PyErr_CheckSignals()));
11454     if (result != 0)
11455         return (!async_err) ? posix_error() : NULL;
11456 
11457     return _pystatvfs_fromstructstatvfs(module, st);
11458 }
11459 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
11460 
11461 
11462 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
11463 #include <sys/statvfs.h>
11464 /*[clinic input]
11465 os.statvfs
11466 
11467     path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
11468 
11469 Perform a statvfs system call on the given path.
11470 
11471 path may always be specified as a string.
11472 On some platforms, path may also be specified as an open file descriptor.
11473   If this functionality is unavailable, using it raises an exception.
11474 [clinic start generated code]*/
11475 
11476 static PyObject *
os_statvfs_impl(PyObject * module,path_t * path)11477 os_statvfs_impl(PyObject *module, path_t *path)
11478 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
11479 {
11480     int result;
11481     struct statvfs st;
11482 
11483     Py_BEGIN_ALLOW_THREADS
11484 #ifdef HAVE_FSTATVFS
11485     if (path->fd != -1) {
11486         result = fstatvfs(path->fd, &st);
11487     }
11488     else
11489 #endif
11490         result = statvfs(path->narrow, &st);
11491     Py_END_ALLOW_THREADS
11492 
11493     if (result) {
11494         return path_error(path);
11495     }
11496 
11497     return _pystatvfs_fromstructstatvfs(module, st);
11498 }
11499 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
11500 
11501 
11502 #ifdef MS_WINDOWS
11503 /*[clinic input]
11504 os._getdiskusage
11505 
11506     path: path_t
11507 
11508 Return disk usage statistics about the given path as a (total, free) tuple.
11509 [clinic start generated code]*/
11510 
11511 static PyObject *
os__getdiskusage_impl(PyObject * module,path_t * path)11512 os__getdiskusage_impl(PyObject *module, path_t *path)
11513 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
11514 {
11515     BOOL retval;
11516     ULARGE_INTEGER _, total, free;
11517     DWORD err = 0;
11518 
11519     Py_BEGIN_ALLOW_THREADS
11520     retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
11521     Py_END_ALLOW_THREADS
11522     if (retval == 0) {
11523         if (GetLastError() == ERROR_DIRECTORY) {
11524             wchar_t *dir_path = NULL;
11525 
11526             dir_path = PyMem_New(wchar_t, path->length + 1);
11527             if (dir_path == NULL) {
11528                 return PyErr_NoMemory();
11529             }
11530 
11531             wcscpy_s(dir_path, path->length + 1, path->wide);
11532 
11533             if (_dirnameW(dir_path) != -1) {
11534                 Py_BEGIN_ALLOW_THREADS
11535                 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
11536                 Py_END_ALLOW_THREADS
11537             }
11538             /* Record the last error in case it's modified by PyMem_Free. */
11539             err = GetLastError();
11540             PyMem_Free(dir_path);
11541             if (retval) {
11542                 goto success;
11543             }
11544         }
11545         return PyErr_SetFromWindowsErr(err);
11546     }
11547 
11548 success:
11549     return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
11550 }
11551 #endif /* MS_WINDOWS */
11552 
11553 
11554 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
11555  * It maps strings representing configuration variable names to
11556  * integer values, allowing those functions to be called with the
11557  * magic names instead of polluting the module's namespace with tons of
11558  * rarely-used constants.  There are three separate tables that use
11559  * these definitions.
11560  *
11561  * This code is always included, even if none of the interfaces that
11562  * need it are included.  The #if hackery needed to avoid it would be
11563  * sufficiently pervasive that it's not worth the loss of readability.
11564  */
11565 struct constdef {
11566     const char *name;
11567     int value;
11568 };
11569 
11570 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)11571 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
11572               size_t tablesize)
11573 {
11574     if (PyLong_Check(arg)) {
11575         int value = _PyLong_AsInt(arg);
11576         if (value == -1 && PyErr_Occurred())
11577             return 0;
11578         *valuep = value;
11579         return 1;
11580     }
11581     else {
11582         /* look up the value in the table using a binary search */
11583         size_t lo = 0;
11584         size_t mid;
11585         size_t hi = tablesize;
11586         int cmp;
11587         const char *confname;
11588         if (!PyUnicode_Check(arg)) {
11589             PyErr_SetString(PyExc_TypeError,
11590                 "configuration names must be strings or integers");
11591             return 0;
11592         }
11593         confname = PyUnicode_AsUTF8(arg);
11594         if (confname == NULL)
11595             return 0;
11596         while (lo < hi) {
11597             mid = (lo + hi) / 2;
11598             cmp = strcmp(confname, table[mid].name);
11599             if (cmp < 0)
11600                 hi = mid;
11601             else if (cmp > 0)
11602                 lo = mid + 1;
11603             else {
11604                 *valuep = table[mid].value;
11605                 return 1;
11606             }
11607         }
11608         PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
11609         return 0;
11610     }
11611 }
11612 
11613 
11614 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11615 static struct constdef  posix_constants_pathconf[] = {
11616 #ifdef _PC_ABI_AIO_XFER_MAX
11617     {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
11618 #endif
11619 #ifdef _PC_ABI_ASYNC_IO
11620     {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
11621 #endif
11622 #ifdef _PC_ASYNC_IO
11623     {"PC_ASYNC_IO",     _PC_ASYNC_IO},
11624 #endif
11625 #ifdef _PC_CHOWN_RESTRICTED
11626     {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
11627 #endif
11628 #ifdef _PC_FILESIZEBITS
11629     {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
11630 #endif
11631 #ifdef _PC_LAST
11632     {"PC_LAST", _PC_LAST},
11633 #endif
11634 #ifdef _PC_LINK_MAX
11635     {"PC_LINK_MAX",     _PC_LINK_MAX},
11636 #endif
11637 #ifdef _PC_MAX_CANON
11638     {"PC_MAX_CANON",    _PC_MAX_CANON},
11639 #endif
11640 #ifdef _PC_MAX_INPUT
11641     {"PC_MAX_INPUT",    _PC_MAX_INPUT},
11642 #endif
11643 #ifdef _PC_NAME_MAX
11644     {"PC_NAME_MAX",     _PC_NAME_MAX},
11645 #endif
11646 #ifdef _PC_NO_TRUNC
11647     {"PC_NO_TRUNC",     _PC_NO_TRUNC},
11648 #endif
11649 #ifdef _PC_PATH_MAX
11650     {"PC_PATH_MAX",     _PC_PATH_MAX},
11651 #endif
11652 #ifdef _PC_PIPE_BUF
11653     {"PC_PIPE_BUF",     _PC_PIPE_BUF},
11654 #endif
11655 #ifdef _PC_PRIO_IO
11656     {"PC_PRIO_IO",      _PC_PRIO_IO},
11657 #endif
11658 #ifdef _PC_SOCK_MAXBUF
11659     {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
11660 #endif
11661 #ifdef _PC_SYNC_IO
11662     {"PC_SYNC_IO",      _PC_SYNC_IO},
11663 #endif
11664 #ifdef _PC_VDISABLE
11665     {"PC_VDISABLE",     _PC_VDISABLE},
11666 #endif
11667 #ifdef _PC_ACL_ENABLED
11668     {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
11669 #endif
11670 #ifdef _PC_MIN_HOLE_SIZE
11671     {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
11672 #endif
11673 #ifdef _PC_ALLOC_SIZE_MIN
11674     {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
11675 #endif
11676 #ifdef _PC_REC_INCR_XFER_SIZE
11677     {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
11678 #endif
11679 #ifdef _PC_REC_MAX_XFER_SIZE
11680     {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
11681 #endif
11682 #ifdef _PC_REC_MIN_XFER_SIZE
11683     {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
11684 #endif
11685 #ifdef _PC_REC_XFER_ALIGN
11686     {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
11687 #endif
11688 #ifdef _PC_SYMLINK_MAX
11689     {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
11690 #endif
11691 #ifdef _PC_XATTR_ENABLED
11692     {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
11693 #endif
11694 #ifdef _PC_XATTR_EXISTS
11695     {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
11696 #endif
11697 #ifdef _PC_TIMESTAMP_RESOLUTION
11698     {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
11699 #endif
11700 };
11701 
11702 static int
conv_path_confname(PyObject * arg,int * valuep)11703 conv_path_confname(PyObject *arg, int *valuep)
11704 {
11705     return conv_confname(arg, valuep, posix_constants_pathconf,
11706                          sizeof(posix_constants_pathconf)
11707                            / sizeof(struct constdef));
11708 }
11709 #endif
11710 
11711 
11712 #ifdef HAVE_FPATHCONF
11713 /*[clinic input]
11714 os.fpathconf -> long
11715 
11716     fd: fildes
11717     name: path_confname
11718     /
11719 
11720 Return the configuration limit name for the file descriptor fd.
11721 
11722 If there is no limit, return -1.
11723 [clinic start generated code]*/
11724 
11725 static long
os_fpathconf_impl(PyObject * module,int fd,int name)11726 os_fpathconf_impl(PyObject *module, int fd, int name)
11727 /*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
11728 {
11729     long limit;
11730 
11731     errno = 0;
11732     limit = fpathconf(fd, name);
11733     if (limit == -1 && errno != 0)
11734         posix_error();
11735 
11736     return limit;
11737 }
11738 #endif /* HAVE_FPATHCONF */
11739 
11740 
11741 #ifdef HAVE_PATHCONF
11742 /*[clinic input]
11743 os.pathconf -> long
11744     path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
11745     name: path_confname
11746 
11747 Return the configuration limit name for the file or directory path.
11748 
11749 If there is no limit, return -1.
11750 On some platforms, path may also be specified as an open file descriptor.
11751   If this functionality is unavailable, using it raises an exception.
11752 [clinic start generated code]*/
11753 
11754 static long
os_pathconf_impl(PyObject * module,path_t * path,int name)11755 os_pathconf_impl(PyObject *module, path_t *path, int name)
11756 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
11757 {
11758     long limit;
11759 
11760     errno = 0;
11761 #ifdef HAVE_FPATHCONF
11762     if (path->fd != -1)
11763         limit = fpathconf(path->fd, name);
11764     else
11765 #endif
11766         limit = pathconf(path->narrow, name);
11767     if (limit == -1 && errno != 0) {
11768         if (errno == EINVAL)
11769             /* could be a path or name problem */
11770             posix_error();
11771         else
11772             path_error(path);
11773     }
11774 
11775     return limit;
11776 }
11777 #endif /* HAVE_PATHCONF */
11778 
11779 #ifdef HAVE_CONFSTR
11780 static struct constdef posix_constants_confstr[] = {
11781 #ifdef _CS_ARCHITECTURE
11782     {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
11783 #endif
11784 #ifdef _CS_GNU_LIBC_VERSION
11785     {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
11786 #endif
11787 #ifdef _CS_GNU_LIBPTHREAD_VERSION
11788     {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
11789 #endif
11790 #ifdef _CS_HOSTNAME
11791     {"CS_HOSTNAME",     _CS_HOSTNAME},
11792 #endif
11793 #ifdef _CS_HW_PROVIDER
11794     {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
11795 #endif
11796 #ifdef _CS_HW_SERIAL
11797     {"CS_HW_SERIAL",    _CS_HW_SERIAL},
11798 #endif
11799 #ifdef _CS_INITTAB_NAME
11800     {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11801 #endif
11802 #ifdef _CS_LFS64_CFLAGS
11803     {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11804 #endif
11805 #ifdef _CS_LFS64_LDFLAGS
11806     {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
11807 #endif
11808 #ifdef _CS_LFS64_LIBS
11809     {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
11810 #endif
11811 #ifdef _CS_LFS64_LINTFLAGS
11812     {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
11813 #endif
11814 #ifdef _CS_LFS_CFLAGS
11815     {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
11816 #endif
11817 #ifdef _CS_LFS_LDFLAGS
11818     {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
11819 #endif
11820 #ifdef _CS_LFS_LIBS
11821     {"CS_LFS_LIBS",     _CS_LFS_LIBS},
11822 #endif
11823 #ifdef _CS_LFS_LINTFLAGS
11824     {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
11825 #endif
11826 #ifdef _CS_MACHINE
11827     {"CS_MACHINE",      _CS_MACHINE},
11828 #endif
11829 #ifdef _CS_PATH
11830     {"CS_PATH", _CS_PATH},
11831 #endif
11832 #ifdef _CS_RELEASE
11833     {"CS_RELEASE",      _CS_RELEASE},
11834 #endif
11835 #ifdef _CS_SRPC_DOMAIN
11836     {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
11837 #endif
11838 #ifdef _CS_SYSNAME
11839     {"CS_SYSNAME",      _CS_SYSNAME},
11840 #endif
11841 #ifdef _CS_VERSION
11842     {"CS_VERSION",      _CS_VERSION},
11843 #endif
11844 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11845     {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
11846 #endif
11847 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11848     {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
11849 #endif
11850 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11851     {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
11852 #endif
11853 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11854     {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11855 #endif
11856 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11857     {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11858 #endif
11859 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11860     {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11861 #endif
11862 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11863     {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
11864 #endif
11865 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11866     {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11867 #endif
11868 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11869     {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
11870 #endif
11871 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11872     {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
11873 #endif
11874 #ifdef _CS_XBS5_LP64_OFF64_LIBS
11875     {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11876 #endif
11877 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11878     {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
11879 #endif
11880 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11881     {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11882 #endif
11883 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11884     {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11885 #endif
11886 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11887     {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
11888 #endif
11889 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11890     {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11891 #endif
11892 #ifdef _MIPS_CS_AVAIL_PROCESSORS
11893     {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
11894 #endif
11895 #ifdef _MIPS_CS_BASE
11896     {"MIPS_CS_BASE",    _MIPS_CS_BASE},
11897 #endif
11898 #ifdef _MIPS_CS_HOSTID
11899     {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
11900 #endif
11901 #ifdef _MIPS_CS_HW_NAME
11902     {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11903 #endif
11904 #ifdef _MIPS_CS_NUM_PROCESSORS
11905     {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
11906 #endif
11907 #ifdef _MIPS_CS_OSREL_MAJ
11908     {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
11909 #endif
11910 #ifdef _MIPS_CS_OSREL_MIN
11911     {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
11912 #endif
11913 #ifdef _MIPS_CS_OSREL_PATCH
11914     {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
11915 #endif
11916 #ifdef _MIPS_CS_OS_NAME
11917     {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11918 #endif
11919 #ifdef _MIPS_CS_OS_PROVIDER
11920     {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
11921 #endif
11922 #ifdef _MIPS_CS_PROCESSORS
11923     {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
11924 #endif
11925 #ifdef _MIPS_CS_SERIAL
11926     {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
11927 #endif
11928 #ifdef _MIPS_CS_VENDOR
11929     {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
11930 #endif
11931 };
11932 
11933 static int
conv_confstr_confname(PyObject * arg,int * valuep)11934 conv_confstr_confname(PyObject *arg, int *valuep)
11935 {
11936     return conv_confname(arg, valuep, posix_constants_confstr,
11937                          sizeof(posix_constants_confstr)
11938                            / sizeof(struct constdef));
11939 }
11940 
11941 
11942 /*[clinic input]
11943 os.confstr
11944 
11945     name: confstr_confname
11946     /
11947 
11948 Return a string-valued system configuration variable.
11949 [clinic start generated code]*/
11950 
11951 static PyObject *
os_confstr_impl(PyObject * module,int name)11952 os_confstr_impl(PyObject *module, int name)
11953 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11954 {
11955     PyObject *result = NULL;
11956     char buffer[255];
11957     size_t len;
11958 
11959     errno = 0;
11960     len = confstr(name, buffer, sizeof(buffer));
11961     if (len == 0) {
11962         if (errno) {
11963             posix_error();
11964             return NULL;
11965         }
11966         else {
11967             Py_RETURN_NONE;
11968         }
11969     }
11970 
11971     if (len >= sizeof(buffer)) {
11972         size_t len2;
11973         char *buf = PyMem_Malloc(len);
11974         if (buf == NULL)
11975             return PyErr_NoMemory();
11976         len2 = confstr(name, buf, len);
11977         assert(len == len2);
11978         result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11979         PyMem_Free(buf);
11980     }
11981     else
11982         result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11983     return result;
11984 }
11985 #endif /* HAVE_CONFSTR */
11986 
11987 
11988 #ifdef HAVE_SYSCONF
11989 static struct constdef posix_constants_sysconf[] = {
11990 #ifdef _SC_2_CHAR_TERM
11991     {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
11992 #endif
11993 #ifdef _SC_2_C_BIND
11994     {"SC_2_C_BIND",     _SC_2_C_BIND},
11995 #endif
11996 #ifdef _SC_2_C_DEV
11997     {"SC_2_C_DEV",      _SC_2_C_DEV},
11998 #endif
11999 #ifdef _SC_2_C_VERSION
12000     {"SC_2_C_VERSION",  _SC_2_C_VERSION},
12001 #endif
12002 #ifdef _SC_2_FORT_DEV
12003     {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
12004 #endif
12005 #ifdef _SC_2_FORT_RUN
12006     {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
12007 #endif
12008 #ifdef _SC_2_LOCALEDEF
12009     {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
12010 #endif
12011 #ifdef _SC_2_SW_DEV
12012     {"SC_2_SW_DEV",     _SC_2_SW_DEV},
12013 #endif
12014 #ifdef _SC_2_UPE
12015     {"SC_2_UPE",        _SC_2_UPE},
12016 #endif
12017 #ifdef _SC_2_VERSION
12018     {"SC_2_VERSION",    _SC_2_VERSION},
12019 #endif
12020 #ifdef _SC_ABI_ASYNCHRONOUS_IO
12021     {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
12022 #endif
12023 #ifdef _SC_ACL
12024     {"SC_ACL",  _SC_ACL},
12025 #endif
12026 #ifdef _SC_AIO_LISTIO_MAX
12027     {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
12028 #endif
12029 #ifdef _SC_AIO_MAX
12030     {"SC_AIO_MAX",      _SC_AIO_MAX},
12031 #endif
12032 #ifdef _SC_AIO_PRIO_DELTA_MAX
12033     {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
12034 #endif
12035 #ifdef _SC_ARG_MAX
12036     {"SC_ARG_MAX",      _SC_ARG_MAX},
12037 #endif
12038 #ifdef _SC_ASYNCHRONOUS_IO
12039     {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
12040 #endif
12041 #ifdef _SC_ATEXIT_MAX
12042     {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
12043 #endif
12044 #ifdef _SC_AUDIT
12045     {"SC_AUDIT",        _SC_AUDIT},
12046 #endif
12047 #ifdef _SC_AVPHYS_PAGES
12048     {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
12049 #endif
12050 #ifdef _SC_BC_BASE_MAX
12051     {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
12052 #endif
12053 #ifdef _SC_BC_DIM_MAX
12054     {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
12055 #endif
12056 #ifdef _SC_BC_SCALE_MAX
12057     {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
12058 #endif
12059 #ifdef _SC_BC_STRING_MAX
12060     {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
12061 #endif
12062 #ifdef _SC_CAP
12063     {"SC_CAP",  _SC_CAP},
12064 #endif
12065 #ifdef _SC_CHARCLASS_NAME_MAX
12066     {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
12067 #endif
12068 #ifdef _SC_CHAR_BIT
12069     {"SC_CHAR_BIT",     _SC_CHAR_BIT},
12070 #endif
12071 #ifdef _SC_CHAR_MAX
12072     {"SC_CHAR_MAX",     _SC_CHAR_MAX},
12073 #endif
12074 #ifdef _SC_CHAR_MIN
12075     {"SC_CHAR_MIN",     _SC_CHAR_MIN},
12076 #endif
12077 #ifdef _SC_CHILD_MAX
12078     {"SC_CHILD_MAX",    _SC_CHILD_MAX},
12079 #endif
12080 #ifdef _SC_CLK_TCK
12081     {"SC_CLK_TCK",      _SC_CLK_TCK},
12082 #endif
12083 #ifdef _SC_COHER_BLKSZ
12084     {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
12085 #endif
12086 #ifdef _SC_COLL_WEIGHTS_MAX
12087     {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
12088 #endif
12089 #ifdef _SC_DCACHE_ASSOC
12090     {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
12091 #endif
12092 #ifdef _SC_DCACHE_BLKSZ
12093     {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
12094 #endif
12095 #ifdef _SC_DCACHE_LINESZ
12096     {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
12097 #endif
12098 #ifdef _SC_DCACHE_SZ
12099     {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
12100 #endif
12101 #ifdef _SC_DCACHE_TBLKSZ
12102     {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
12103 #endif
12104 #ifdef _SC_DELAYTIMER_MAX
12105     {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
12106 #endif
12107 #ifdef _SC_EQUIV_CLASS_MAX
12108     {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
12109 #endif
12110 #ifdef _SC_EXPR_NEST_MAX
12111     {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
12112 #endif
12113 #ifdef _SC_FSYNC
12114     {"SC_FSYNC",        _SC_FSYNC},
12115 #endif
12116 #ifdef _SC_GETGR_R_SIZE_MAX
12117     {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
12118 #endif
12119 #ifdef _SC_GETPW_R_SIZE_MAX
12120     {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
12121 #endif
12122 #ifdef _SC_ICACHE_ASSOC
12123     {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
12124 #endif
12125 #ifdef _SC_ICACHE_BLKSZ
12126     {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
12127 #endif
12128 #ifdef _SC_ICACHE_LINESZ
12129     {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
12130 #endif
12131 #ifdef _SC_ICACHE_SZ
12132     {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
12133 #endif
12134 #ifdef _SC_INF
12135     {"SC_INF",  _SC_INF},
12136 #endif
12137 #ifdef _SC_INT_MAX
12138     {"SC_INT_MAX",      _SC_INT_MAX},
12139 #endif
12140 #ifdef _SC_INT_MIN
12141     {"SC_INT_MIN",      _SC_INT_MIN},
12142 #endif
12143 #ifdef _SC_IOV_MAX
12144     {"SC_IOV_MAX",      _SC_IOV_MAX},
12145 #endif
12146 #ifdef _SC_IP_SECOPTS
12147     {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
12148 #endif
12149 #ifdef _SC_JOB_CONTROL
12150     {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
12151 #endif
12152 #ifdef _SC_KERN_POINTERS
12153     {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
12154 #endif
12155 #ifdef _SC_KERN_SIM
12156     {"SC_KERN_SIM",     _SC_KERN_SIM},
12157 #endif
12158 #ifdef _SC_LINE_MAX
12159     {"SC_LINE_MAX",     _SC_LINE_MAX},
12160 #endif
12161 #ifdef _SC_LOGIN_NAME_MAX
12162     {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
12163 #endif
12164 #ifdef _SC_LOGNAME_MAX
12165     {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
12166 #endif
12167 #ifdef _SC_LONG_BIT
12168     {"SC_LONG_BIT",     _SC_LONG_BIT},
12169 #endif
12170 #ifdef _SC_MAC
12171     {"SC_MAC",  _SC_MAC},
12172 #endif
12173 #ifdef _SC_MAPPED_FILES
12174     {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
12175 #endif
12176 #ifdef _SC_MAXPID
12177     {"SC_MAXPID",       _SC_MAXPID},
12178 #endif
12179 #ifdef _SC_MB_LEN_MAX
12180     {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
12181 #endif
12182 #ifdef _SC_MEMLOCK
12183     {"SC_MEMLOCK",      _SC_MEMLOCK},
12184 #endif
12185 #ifdef _SC_MEMLOCK_RANGE
12186     {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
12187 #endif
12188 #ifdef _SC_MEMORY_PROTECTION
12189     {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
12190 #endif
12191 #ifdef _SC_MESSAGE_PASSING
12192     {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
12193 #endif
12194 #ifdef _SC_MMAP_FIXED_ALIGNMENT
12195     {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
12196 #endif
12197 #ifdef _SC_MQ_OPEN_MAX
12198     {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
12199 #endif
12200 #ifdef _SC_MQ_PRIO_MAX
12201     {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
12202 #endif
12203 #ifdef _SC_NACLS_MAX
12204     {"SC_NACLS_MAX",    _SC_NACLS_MAX},
12205 #endif
12206 #ifdef _SC_NGROUPS_MAX
12207     {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
12208 #endif
12209 #ifdef _SC_NL_ARGMAX
12210     {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
12211 #endif
12212 #ifdef _SC_NL_LANGMAX
12213     {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
12214 #endif
12215 #ifdef _SC_NL_MSGMAX
12216     {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
12217 #endif
12218 #ifdef _SC_NL_NMAX
12219     {"SC_NL_NMAX",      _SC_NL_NMAX},
12220 #endif
12221 #ifdef _SC_NL_SETMAX
12222     {"SC_NL_SETMAX",    _SC_NL_SETMAX},
12223 #endif
12224 #ifdef _SC_NL_TEXTMAX
12225     {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
12226 #endif
12227 #ifdef _SC_NPROCESSORS_CONF
12228     {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
12229 #endif
12230 #ifdef _SC_NPROCESSORS_ONLN
12231     {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
12232 #endif
12233 #ifdef _SC_NPROC_CONF
12234     {"SC_NPROC_CONF",   _SC_NPROC_CONF},
12235 #endif
12236 #ifdef _SC_NPROC_ONLN
12237     {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
12238 #endif
12239 #ifdef _SC_NZERO
12240     {"SC_NZERO",        _SC_NZERO},
12241 #endif
12242 #ifdef _SC_OPEN_MAX
12243     {"SC_OPEN_MAX",     _SC_OPEN_MAX},
12244 #endif
12245 #ifdef _SC_PAGESIZE
12246     {"SC_PAGESIZE",     _SC_PAGESIZE},
12247 #endif
12248 #ifdef _SC_PAGE_SIZE
12249     {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
12250 #endif
12251 #ifdef _SC_AIX_REALMEM
12252     {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
12253 #endif
12254 #ifdef _SC_PASS_MAX
12255     {"SC_PASS_MAX",     _SC_PASS_MAX},
12256 #endif
12257 #ifdef _SC_PHYS_PAGES
12258     {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
12259 #endif
12260 #ifdef _SC_PII
12261     {"SC_PII",  _SC_PII},
12262 #endif
12263 #ifdef _SC_PII_INTERNET
12264     {"SC_PII_INTERNET", _SC_PII_INTERNET},
12265 #endif
12266 #ifdef _SC_PII_INTERNET_DGRAM
12267     {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
12268 #endif
12269 #ifdef _SC_PII_INTERNET_STREAM
12270     {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
12271 #endif
12272 #ifdef _SC_PII_OSI
12273     {"SC_PII_OSI",      _SC_PII_OSI},
12274 #endif
12275 #ifdef _SC_PII_OSI_CLTS
12276     {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
12277 #endif
12278 #ifdef _SC_PII_OSI_COTS
12279     {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
12280 #endif
12281 #ifdef _SC_PII_OSI_M
12282     {"SC_PII_OSI_M",    _SC_PII_OSI_M},
12283 #endif
12284 #ifdef _SC_PII_SOCKET
12285     {"SC_PII_SOCKET",   _SC_PII_SOCKET},
12286 #endif
12287 #ifdef _SC_PII_XTI
12288     {"SC_PII_XTI",      _SC_PII_XTI},
12289 #endif
12290 #ifdef _SC_POLL
12291     {"SC_POLL", _SC_POLL},
12292 #endif
12293 #ifdef _SC_PRIORITIZED_IO
12294     {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
12295 #endif
12296 #ifdef _SC_PRIORITY_SCHEDULING
12297     {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
12298 #endif
12299 #ifdef _SC_REALTIME_SIGNALS
12300     {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
12301 #endif
12302 #ifdef _SC_RE_DUP_MAX
12303     {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
12304 #endif
12305 #ifdef _SC_RTSIG_MAX
12306     {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
12307 #endif
12308 #ifdef _SC_SAVED_IDS
12309     {"SC_SAVED_IDS",    _SC_SAVED_IDS},
12310 #endif
12311 #ifdef _SC_SCHAR_MAX
12312     {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
12313 #endif
12314 #ifdef _SC_SCHAR_MIN
12315     {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
12316 #endif
12317 #ifdef _SC_SELECT
12318     {"SC_SELECT",       _SC_SELECT},
12319 #endif
12320 #ifdef _SC_SEMAPHORES
12321     {"SC_SEMAPHORES",   _SC_SEMAPHORES},
12322 #endif
12323 #ifdef _SC_SEM_NSEMS_MAX
12324     {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
12325 #endif
12326 #ifdef _SC_SEM_VALUE_MAX
12327     {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
12328 #endif
12329 #ifdef _SC_SHARED_MEMORY_OBJECTS
12330     {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
12331 #endif
12332 #ifdef _SC_SHRT_MAX
12333     {"SC_SHRT_MAX",     _SC_SHRT_MAX},
12334 #endif
12335 #ifdef _SC_SHRT_MIN
12336     {"SC_SHRT_MIN",     _SC_SHRT_MIN},
12337 #endif
12338 #ifdef _SC_SIGQUEUE_MAX
12339     {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
12340 #endif
12341 #ifdef _SC_SIGRT_MAX
12342     {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
12343 #endif
12344 #ifdef _SC_SIGRT_MIN
12345     {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
12346 #endif
12347 #ifdef _SC_SOFTPOWER
12348     {"SC_SOFTPOWER",    _SC_SOFTPOWER},
12349 #endif
12350 #ifdef _SC_SPLIT_CACHE
12351     {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
12352 #endif
12353 #ifdef _SC_SSIZE_MAX
12354     {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
12355 #endif
12356 #ifdef _SC_STACK_PROT
12357     {"SC_STACK_PROT",   _SC_STACK_PROT},
12358 #endif
12359 #ifdef _SC_STREAM_MAX
12360     {"SC_STREAM_MAX",   _SC_STREAM_MAX},
12361 #endif
12362 #ifdef _SC_SYNCHRONIZED_IO
12363     {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
12364 #endif
12365 #ifdef _SC_THREADS
12366     {"SC_THREADS",      _SC_THREADS},
12367 #endif
12368 #ifdef _SC_THREAD_ATTR_STACKADDR
12369     {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
12370 #endif
12371 #ifdef _SC_THREAD_ATTR_STACKSIZE
12372     {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
12373 #endif
12374 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
12375     {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
12376 #endif
12377 #ifdef _SC_THREAD_KEYS_MAX
12378     {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
12379 #endif
12380 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
12381     {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
12382 #endif
12383 #ifdef _SC_THREAD_PRIO_INHERIT
12384     {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
12385 #endif
12386 #ifdef _SC_THREAD_PRIO_PROTECT
12387     {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
12388 #endif
12389 #ifdef _SC_THREAD_PROCESS_SHARED
12390     {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
12391 #endif
12392 #ifdef _SC_THREAD_SAFE_FUNCTIONS
12393     {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
12394 #endif
12395 #ifdef _SC_THREAD_STACK_MIN
12396     {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
12397 #endif
12398 #ifdef _SC_THREAD_THREADS_MAX
12399     {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
12400 #endif
12401 #ifdef _SC_TIMERS
12402     {"SC_TIMERS",       _SC_TIMERS},
12403 #endif
12404 #ifdef _SC_TIMER_MAX
12405     {"SC_TIMER_MAX",    _SC_TIMER_MAX},
12406 #endif
12407 #ifdef _SC_TTY_NAME_MAX
12408     {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
12409 #endif
12410 #ifdef _SC_TZNAME_MAX
12411     {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
12412 #endif
12413 #ifdef _SC_T_IOV_MAX
12414     {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
12415 #endif
12416 #ifdef _SC_UCHAR_MAX
12417     {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
12418 #endif
12419 #ifdef _SC_UINT_MAX
12420     {"SC_UINT_MAX",     _SC_UINT_MAX},
12421 #endif
12422 #ifdef _SC_UIO_MAXIOV
12423     {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
12424 #endif
12425 #ifdef _SC_ULONG_MAX
12426     {"SC_ULONG_MAX",    _SC_ULONG_MAX},
12427 #endif
12428 #ifdef _SC_USHRT_MAX
12429     {"SC_USHRT_MAX",    _SC_USHRT_MAX},
12430 #endif
12431 #ifdef _SC_VERSION
12432     {"SC_VERSION",      _SC_VERSION},
12433 #endif
12434 #ifdef _SC_WORD_BIT
12435     {"SC_WORD_BIT",     _SC_WORD_BIT},
12436 #endif
12437 #ifdef _SC_XBS5_ILP32_OFF32
12438     {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
12439 #endif
12440 #ifdef _SC_XBS5_ILP32_OFFBIG
12441     {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
12442 #endif
12443 #ifdef _SC_XBS5_LP64_OFF64
12444     {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
12445 #endif
12446 #ifdef _SC_XBS5_LPBIG_OFFBIG
12447     {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
12448 #endif
12449 #ifdef _SC_XOPEN_CRYPT
12450     {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
12451 #endif
12452 #ifdef _SC_XOPEN_ENH_I18N
12453     {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
12454 #endif
12455 #ifdef _SC_XOPEN_LEGACY
12456     {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
12457 #endif
12458 #ifdef _SC_XOPEN_REALTIME
12459     {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
12460 #endif
12461 #ifdef _SC_XOPEN_REALTIME_THREADS
12462     {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
12463 #endif
12464 #ifdef _SC_XOPEN_SHM
12465     {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
12466 #endif
12467 #ifdef _SC_XOPEN_UNIX
12468     {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
12469 #endif
12470 #ifdef _SC_XOPEN_VERSION
12471     {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
12472 #endif
12473 #ifdef _SC_XOPEN_XCU_VERSION
12474     {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
12475 #endif
12476 #ifdef _SC_XOPEN_XPG2
12477     {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
12478 #endif
12479 #ifdef _SC_XOPEN_XPG3
12480     {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
12481 #endif
12482 #ifdef _SC_XOPEN_XPG4
12483     {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
12484 #endif
12485 #ifdef _SC_MINSIGSTKSZ
12486     {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
12487 #endif
12488 };
12489 
12490 static int
conv_sysconf_confname(PyObject * arg,int * valuep)12491 conv_sysconf_confname(PyObject *arg, int *valuep)
12492 {
12493     return conv_confname(arg, valuep, posix_constants_sysconf,
12494                          sizeof(posix_constants_sysconf)
12495                            / sizeof(struct constdef));
12496 }
12497 
12498 
12499 /*[clinic input]
12500 os.sysconf -> long
12501     name: sysconf_confname
12502     /
12503 
12504 Return an integer-valued system configuration variable.
12505 [clinic start generated code]*/
12506 
12507 static long
os_sysconf_impl(PyObject * module,int name)12508 os_sysconf_impl(PyObject *module, int name)
12509 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
12510 {
12511     long value;
12512 
12513     errno = 0;
12514     value = sysconf(name);
12515     if (value == -1 && errno != 0)
12516         posix_error();
12517     return value;
12518 }
12519 #endif /* HAVE_SYSCONF */
12520 
12521 
12522 /* This code is used to ensure that the tables of configuration value names
12523  * are in sorted order as required by conv_confname(), and also to build
12524  * the exported dictionaries that are used to publish information about the
12525  * names available on the host platform.
12526  *
12527  * Sorting the table at runtime ensures that the table is properly ordered
12528  * when used, even for platforms we're not able to test on.  It also makes
12529  * it easier to add additional entries to the tables.
12530  */
12531 
12532 static int
cmp_constdefs(const void * v1,const void * v2)12533 cmp_constdefs(const void *v1,  const void *v2)
12534 {
12535     const struct constdef *c1 =
12536     (const struct constdef *) v1;
12537     const struct constdef *c2 =
12538     (const struct constdef *) v2;
12539 
12540     return strcmp(c1->name, c2->name);
12541 }
12542 
12543 static int
setup_confname_table(struct constdef * table,size_t tablesize,const char * tablename,PyObject * module)12544 setup_confname_table(struct constdef *table, size_t tablesize,
12545                      const char *tablename, PyObject *module)
12546 {
12547     PyObject *d = NULL;
12548     size_t i;
12549 
12550     qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
12551     d = PyDict_New();
12552     if (d == NULL)
12553         return -1;
12554 
12555     for (i=0; i < tablesize; ++i) {
12556         PyObject *o = PyLong_FromLong(table[i].value);
12557         if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
12558             Py_XDECREF(o);
12559             Py_DECREF(d);
12560             return -1;
12561         }
12562         Py_DECREF(o);
12563     }
12564     return PyModule_AddObject(module, tablename, d);
12565 }
12566 
12567 /* Return -1 on failure, 0 on success. */
12568 static int
setup_confname_tables(PyObject * module)12569 setup_confname_tables(PyObject *module)
12570 {
12571 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12572     if (setup_confname_table(posix_constants_pathconf,
12573                              sizeof(posix_constants_pathconf)
12574                                / sizeof(struct constdef),
12575                              "pathconf_names", module))
12576         return -1;
12577 #endif
12578 #ifdef HAVE_CONFSTR
12579     if (setup_confname_table(posix_constants_confstr,
12580                              sizeof(posix_constants_confstr)
12581                                / sizeof(struct constdef),
12582                              "confstr_names", module))
12583         return -1;
12584 #endif
12585 #ifdef HAVE_SYSCONF
12586     if (setup_confname_table(posix_constants_sysconf,
12587                              sizeof(posix_constants_sysconf)
12588                                / sizeof(struct constdef),
12589                              "sysconf_names", module))
12590         return -1;
12591 #endif
12592     return 0;
12593 }
12594 
12595 
12596 /*[clinic input]
12597 os.abort
12598 
12599 Abort the interpreter immediately.
12600 
12601 This function 'dumps core' or otherwise fails in the hardest way possible
12602 on the hosting operating system.  This function never returns.
12603 [clinic start generated code]*/
12604 
12605 static PyObject *
os_abort_impl(PyObject * module)12606 os_abort_impl(PyObject *module)
12607 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
12608 {
12609     abort();
12610     /*NOTREACHED*/
12611 #ifndef __clang__
12612     /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
12613        GCC emits a warning without "return NULL;" (compiler bug?), but Clang
12614        is smarter and emits a warning on the return. */
12615     Py_FatalError("abort() called from Python code didn't abort!");
12616     return NULL;
12617 #endif
12618 }
12619 
12620 #ifdef MS_WINDOWS
12621 /* Grab ShellExecute dynamically from shell32 */
12622 static int has_ShellExecute = -1;
12623 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
12624                                               LPCWSTR, INT);
12625 static int
check_ShellExecute()12626 check_ShellExecute()
12627 {
12628     HINSTANCE hShell32;
12629 
12630     /* only recheck */
12631     if (-1 == has_ShellExecute) {
12632         Py_BEGIN_ALLOW_THREADS
12633         /* Security note: this call is not vulnerable to "DLL hijacking".
12634            SHELL32 is part of "KnownDLLs" and so Windows always load
12635            the system SHELL32.DLL, even if there is another SHELL32.DLL
12636            in the DLL search path. */
12637         hShell32 = LoadLibraryW(L"SHELL32");
12638         if (hShell32) {
12639             *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
12640                                             "ShellExecuteW");
12641             has_ShellExecute = Py_ShellExecuteW != NULL;
12642         } else {
12643             has_ShellExecute = 0;
12644         }
12645         Py_END_ALLOW_THREADS
12646     }
12647     return has_ShellExecute;
12648 }
12649 
12650 
12651 /*[clinic input]
12652 os.startfile
12653     filepath: path_t
12654     operation: Py_UNICODE = NULL
12655     arguments: Py_UNICODE = NULL
12656     cwd: path_t(nullable=True) = None
12657     show_cmd: int = 1
12658 
12659 Start a file with its associated application.
12660 
12661 When "operation" is not specified or "open", this acts like
12662 double-clicking the file in Explorer, or giving the file name as an
12663 argument to the DOS "start" command: the file is opened with whatever
12664 application (if any) its extension is associated.
12665 When another "operation" is given, it specifies what should be done with
12666 the file.  A typical operation is "print".
12667 
12668 "arguments" is passed to the application, but should be omitted if the
12669 file is a document.
12670 
12671 "cwd" is the working directory for the operation. If "filepath" is
12672 relative, it will be resolved against this directory. This argument
12673 should usually be an absolute path.
12674 
12675 "show_cmd" can be used to override the recommended visibility option.
12676 See the Windows ShellExecute documentation for values.
12677 
12678 startfile returns as soon as the associated application is launched.
12679 There is no option to wait for the application to close, and no way
12680 to retrieve the application's exit status.
12681 
12682 The filepath is relative to the current directory.  If you want to use
12683 an absolute path, make sure the first character is not a slash ("/");
12684 the underlying Win32 ShellExecute function doesn't work if it is.
12685 [clinic start generated code]*/
12686 
12687 static PyObject *
os_startfile_impl(PyObject * module,path_t * filepath,const Py_UNICODE * operation,const Py_UNICODE * arguments,path_t * cwd,int show_cmd)12688 os_startfile_impl(PyObject *module, path_t *filepath,
12689                   const Py_UNICODE *operation, const Py_UNICODE *arguments,
12690                   path_t *cwd, int show_cmd)
12691 /*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/
12692 {
12693     HINSTANCE rc;
12694 
12695     if(!check_ShellExecute()) {
12696         /* If the OS doesn't have ShellExecute, return a
12697            NotImplementedError. */
12698         return PyErr_Format(PyExc_NotImplementedError,
12699             "startfile not available on this platform");
12700     }
12701 
12702     if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
12703         return NULL;
12704     }
12705     if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
12706                     arguments, cwd->object ? cwd->object : Py_None,
12707                     show_cmd) < 0) {
12708         return NULL;
12709     }
12710 
12711     Py_BEGIN_ALLOW_THREADS
12712     rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
12713                           arguments, cwd->wide, show_cmd);
12714     Py_END_ALLOW_THREADS
12715 
12716     if (rc <= (HINSTANCE)32) {
12717         win32_error_object("startfile", filepath->object);
12718         return NULL;
12719     }
12720     Py_RETURN_NONE;
12721 }
12722 #endif /* MS_WINDOWS */
12723 
12724 
12725 #ifdef HAVE_GETLOADAVG
12726 /*[clinic input]
12727 os.getloadavg
12728 
12729 Return average recent system load information.
12730 
12731 Return the number of processes in the system run queue averaged over
12732 the last 1, 5, and 15 minutes as a tuple of three floats.
12733 Raises OSError if the load average was unobtainable.
12734 [clinic start generated code]*/
12735 
12736 static PyObject *
os_getloadavg_impl(PyObject * module)12737 os_getloadavg_impl(PyObject *module)
12738 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
12739 {
12740     double loadavg[3];
12741     if (getloadavg(loadavg, 3)!=3) {
12742         PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
12743         return NULL;
12744     } else
12745         return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
12746 }
12747 #endif /* HAVE_GETLOADAVG */
12748 
12749 
12750 /*[clinic input]
12751 os.device_encoding
12752     fd: int
12753 
12754 Return a string describing the encoding of a terminal's file descriptor.
12755 
12756 The file descriptor must be attached to a terminal.
12757 If the device is not a terminal, return None.
12758 [clinic start generated code]*/
12759 
12760 static PyObject *
os_device_encoding_impl(PyObject * module,int fd)12761 os_device_encoding_impl(PyObject *module, int fd)
12762 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
12763 {
12764     return _Py_device_encoding(fd);
12765 }
12766 
12767 
12768 #ifdef HAVE_SETRESUID
12769 /*[clinic input]
12770 os.setresuid
12771 
12772     ruid: uid_t
12773     euid: uid_t
12774     suid: uid_t
12775     /
12776 
12777 Set the current process's real, effective, and saved user ids.
12778 [clinic start generated code]*/
12779 
12780 static PyObject *
os_setresuid_impl(PyObject * module,uid_t ruid,uid_t euid,uid_t suid)12781 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
12782 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
12783 {
12784     if (setresuid(ruid, euid, suid) < 0)
12785         return posix_error();
12786     Py_RETURN_NONE;
12787 }
12788 #endif /* HAVE_SETRESUID */
12789 
12790 
12791 #ifdef HAVE_SETRESGID
12792 /*[clinic input]
12793 os.setresgid
12794 
12795     rgid: gid_t
12796     egid: gid_t
12797     sgid: gid_t
12798     /
12799 
12800 Set the current process's real, effective, and saved group ids.
12801 [clinic start generated code]*/
12802 
12803 static PyObject *
os_setresgid_impl(PyObject * module,gid_t rgid,gid_t egid,gid_t sgid)12804 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
12805 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
12806 {
12807     if (setresgid(rgid, egid, sgid) < 0)
12808         return posix_error();
12809     Py_RETURN_NONE;
12810 }
12811 #endif /* HAVE_SETRESGID */
12812 
12813 
12814 #ifdef HAVE_GETRESUID
12815 /*[clinic input]
12816 os.getresuid
12817 
12818 Return a tuple of the current process's real, effective, and saved user ids.
12819 [clinic start generated code]*/
12820 
12821 static PyObject *
os_getresuid_impl(PyObject * module)12822 os_getresuid_impl(PyObject *module)
12823 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12824 {
12825     uid_t ruid, euid, suid;
12826     if (getresuid(&ruid, &euid, &suid) < 0)
12827         return posix_error();
12828     return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12829                                   _PyLong_FromUid(euid),
12830                                   _PyLong_FromUid(suid));
12831 }
12832 #endif /* HAVE_GETRESUID */
12833 
12834 
12835 #ifdef HAVE_GETRESGID
12836 /*[clinic input]
12837 os.getresgid
12838 
12839 Return a tuple of the current process's real, effective, and saved group ids.
12840 [clinic start generated code]*/
12841 
12842 static PyObject *
os_getresgid_impl(PyObject * module)12843 os_getresgid_impl(PyObject *module)
12844 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12845 {
12846     gid_t rgid, egid, sgid;
12847     if (getresgid(&rgid, &egid, &sgid) < 0)
12848         return posix_error();
12849     return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12850                                   _PyLong_FromGid(egid),
12851                                   _PyLong_FromGid(sgid));
12852 }
12853 #endif /* HAVE_GETRESGID */
12854 
12855 
12856 #ifdef USE_XATTRS
12857 /*[clinic input]
12858 os.getxattr
12859 
12860     path: path_t(allow_fd=True)
12861     attribute: path_t
12862     *
12863     follow_symlinks: bool = True
12864 
12865 Return the value of extended attribute attribute on path.
12866 
12867 path may be either a string, a path-like object, or an open file descriptor.
12868 If follow_symlinks is False, and the last element of the path is a symbolic
12869   link, getxattr will examine the symbolic link itself instead of the file
12870   the link points to.
12871 
12872 [clinic start generated code]*/
12873 
12874 static PyObject *
os_getxattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12875 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12876                  int follow_symlinks)
12877 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12878 {
12879     Py_ssize_t i;
12880     PyObject *buffer = NULL;
12881 
12882     if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12883         return NULL;
12884 
12885     if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12886         return NULL;
12887     }
12888 
12889     for (i = 0; ; i++) {
12890         void *ptr;
12891         ssize_t result;
12892         static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12893         Py_ssize_t buffer_size = buffer_sizes[i];
12894         if (!buffer_size) {
12895             path_error(path);
12896             return NULL;
12897         }
12898         buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12899         if (!buffer)
12900             return NULL;
12901         ptr = PyBytes_AS_STRING(buffer);
12902 
12903         Py_BEGIN_ALLOW_THREADS;
12904         if (path->fd >= 0)
12905             result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12906         else if (follow_symlinks)
12907             result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12908         else
12909             result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12910         Py_END_ALLOW_THREADS;
12911 
12912         if (result < 0) {
12913             Py_DECREF(buffer);
12914             if (errno == ERANGE)
12915                 continue;
12916             path_error(path);
12917             return NULL;
12918         }
12919 
12920         if (result != buffer_size) {
12921             /* Can only shrink. */
12922             _PyBytes_Resize(&buffer, result);
12923         }
12924         break;
12925     }
12926 
12927     return buffer;
12928 }
12929 
12930 
12931 /*[clinic input]
12932 os.setxattr
12933 
12934     path: path_t(allow_fd=True)
12935     attribute: path_t
12936     value: Py_buffer
12937     flags: int = 0
12938     *
12939     follow_symlinks: bool = True
12940 
12941 Set extended attribute attribute on path to value.
12942 
12943 path may be either a string, a path-like object,  or an open file descriptor.
12944 If follow_symlinks is False, and the last element of the path is a symbolic
12945   link, setxattr will modify the symbolic link itself instead of the file
12946   the link points to.
12947 
12948 [clinic start generated code]*/
12949 
12950 static PyObject *
os_setxattr_impl(PyObject * module,path_t * path,path_t * attribute,Py_buffer * value,int flags,int follow_symlinks)12951 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12952                  Py_buffer *value, int flags, int follow_symlinks)
12953 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12954 {
12955     ssize_t result;
12956 
12957     if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12958         return NULL;
12959 
12960     if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12961                     value->buf, value->len, flags) < 0) {
12962         return NULL;
12963     }
12964 
12965     Py_BEGIN_ALLOW_THREADS;
12966     if (path->fd > -1)
12967         result = fsetxattr(path->fd, attribute->narrow,
12968                            value->buf, value->len, flags);
12969     else if (follow_symlinks)
12970         result = setxattr(path->narrow, attribute->narrow,
12971                            value->buf, value->len, flags);
12972     else
12973         result = lsetxattr(path->narrow, attribute->narrow,
12974                            value->buf, value->len, flags);
12975     Py_END_ALLOW_THREADS;
12976 
12977     if (result) {
12978         path_error(path);
12979         return NULL;
12980     }
12981 
12982     Py_RETURN_NONE;
12983 }
12984 
12985 
12986 /*[clinic input]
12987 os.removexattr
12988 
12989     path: path_t(allow_fd=True)
12990     attribute: path_t
12991     *
12992     follow_symlinks: bool = True
12993 
12994 Remove extended attribute attribute on path.
12995 
12996 path may be either a string, a path-like object, or an open file descriptor.
12997 If follow_symlinks is False, and the last element of the path is a symbolic
12998   link, removexattr will modify the symbolic link itself instead of the file
12999   the link points to.
13000 
13001 [clinic start generated code]*/
13002 
13003 static PyObject *
os_removexattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)13004 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
13005                     int follow_symlinks)
13006 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
13007 {
13008     ssize_t result;
13009 
13010     if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
13011         return NULL;
13012 
13013     if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
13014         return NULL;
13015     }
13016 
13017     Py_BEGIN_ALLOW_THREADS;
13018     if (path->fd > -1)
13019         result = fremovexattr(path->fd, attribute->narrow);
13020     else if (follow_symlinks)
13021         result = removexattr(path->narrow, attribute->narrow);
13022     else
13023         result = lremovexattr(path->narrow, attribute->narrow);
13024     Py_END_ALLOW_THREADS;
13025 
13026     if (result) {
13027         return path_error(path);
13028     }
13029 
13030     Py_RETURN_NONE;
13031 }
13032 
13033 
13034 /*[clinic input]
13035 os.listxattr
13036 
13037     path: path_t(allow_fd=True, nullable=True) = None
13038     *
13039     follow_symlinks: bool = True
13040 
13041 Return a list of extended attributes on path.
13042 
13043 path may be either None, a string, a path-like object, or an open file descriptor.
13044 if path is None, listxattr will examine the current directory.
13045 If follow_symlinks is False, and the last element of the path is a symbolic
13046   link, listxattr will examine the symbolic link itself instead of the file
13047   the link points to.
13048 [clinic start generated code]*/
13049 
13050 static PyObject *
os_listxattr_impl(PyObject * module,path_t * path,int follow_symlinks)13051 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
13052 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
13053 {
13054     Py_ssize_t i;
13055     PyObject *result = NULL;
13056     const char *name;
13057     char *buffer = NULL;
13058 
13059     if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
13060         goto exit;
13061 
13062     if (PySys_Audit("os.listxattr", "(O)",
13063                     path->object ? path->object : Py_None) < 0) {
13064         return NULL;
13065     }
13066 
13067     name = path->narrow ? path->narrow : ".";
13068 
13069     for (i = 0; ; i++) {
13070         const char *start, *trace, *end;
13071         ssize_t length;
13072         static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
13073         Py_ssize_t buffer_size = buffer_sizes[i];
13074         if (!buffer_size) {
13075             /* ERANGE */
13076             path_error(path);
13077             break;
13078         }
13079         buffer = PyMem_Malloc(buffer_size);
13080         if (!buffer) {
13081             PyErr_NoMemory();
13082             break;
13083         }
13084 
13085         Py_BEGIN_ALLOW_THREADS;
13086         if (path->fd > -1)
13087             length = flistxattr(path->fd, buffer, buffer_size);
13088         else if (follow_symlinks)
13089             length = listxattr(name, buffer, buffer_size);
13090         else
13091             length = llistxattr(name, buffer, buffer_size);
13092         Py_END_ALLOW_THREADS;
13093 
13094         if (length < 0) {
13095             if (errno == ERANGE) {
13096                 PyMem_Free(buffer);
13097                 buffer = NULL;
13098                 continue;
13099             }
13100             path_error(path);
13101             break;
13102         }
13103 
13104         result = PyList_New(0);
13105         if (!result) {
13106             goto exit;
13107         }
13108 
13109         end = buffer + length;
13110         for (trace = start = buffer; trace != end; trace++) {
13111             if (!*trace) {
13112                 int error;
13113                 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
13114                                                                  trace - start);
13115                 if (!attribute) {
13116                     Py_DECREF(result);
13117                     result = NULL;
13118                     goto exit;
13119                 }
13120                 error = PyList_Append(result, attribute);
13121                 Py_DECREF(attribute);
13122                 if (error) {
13123                     Py_DECREF(result);
13124                     result = NULL;
13125                     goto exit;
13126                 }
13127                 start = trace + 1;
13128             }
13129         }
13130     break;
13131     }
13132 exit:
13133     if (buffer)
13134         PyMem_Free(buffer);
13135     return result;
13136 }
13137 #endif /* USE_XATTRS */
13138 
13139 
13140 /*[clinic input]
13141 os.urandom
13142 
13143     size: Py_ssize_t
13144     /
13145 
13146 Return a bytes object containing random bytes suitable for cryptographic use.
13147 [clinic start generated code]*/
13148 
13149 static PyObject *
os_urandom_impl(PyObject * module,Py_ssize_t size)13150 os_urandom_impl(PyObject *module, Py_ssize_t size)
13151 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
13152 {
13153     PyObject *bytes;
13154     int result;
13155 
13156     if (size < 0)
13157         return PyErr_Format(PyExc_ValueError,
13158                             "negative argument not allowed");
13159     bytes = PyBytes_FromStringAndSize(NULL, size);
13160     if (bytes == NULL)
13161         return NULL;
13162 
13163     result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
13164     if (result == -1) {
13165         Py_DECREF(bytes);
13166         return NULL;
13167     }
13168     return bytes;
13169 }
13170 
13171 #ifdef HAVE_MEMFD_CREATE
13172 /*[clinic input]
13173 os.memfd_create
13174 
13175     name: FSConverter
13176     flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
13177 
13178 [clinic start generated code]*/
13179 
13180 static PyObject *
os_memfd_create_impl(PyObject * module,PyObject * name,unsigned int flags)13181 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
13182 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
13183 {
13184     int fd;
13185     const char *bytes = PyBytes_AS_STRING(name);
13186     Py_BEGIN_ALLOW_THREADS
13187     fd = memfd_create(bytes, flags);
13188     Py_END_ALLOW_THREADS
13189     if (fd == -1) {
13190         return PyErr_SetFromErrno(PyExc_OSError);
13191     }
13192     return PyLong_FromLong(fd);
13193 }
13194 #endif
13195 
13196 #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
13197 /*[clinic input]
13198 os.eventfd
13199 
13200     initval: unsigned_int
13201     flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
13202 
13203 Creates and returns an event notification file descriptor.
13204 [clinic start generated code]*/
13205 
13206 static PyObject *
os_eventfd_impl(PyObject * module,unsigned int initval,int flags)13207 os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
13208 /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
13209 
13210 {
13211     /* initval is limited to uint32_t, internal counter is uint64_t */
13212     int fd;
13213     Py_BEGIN_ALLOW_THREADS
13214     fd = eventfd(initval, flags);
13215     Py_END_ALLOW_THREADS
13216     if (fd == -1) {
13217         return PyErr_SetFromErrno(PyExc_OSError);
13218     }
13219     return PyLong_FromLong(fd);
13220 }
13221 
13222 /*[clinic input]
13223 os.eventfd_read
13224 
13225     fd: fildes
13226 
13227 Read eventfd value
13228 [clinic start generated code]*/
13229 
13230 static PyObject *
os_eventfd_read_impl(PyObject * module,int fd)13231 os_eventfd_read_impl(PyObject *module, int fd)
13232 /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
13233 {
13234     eventfd_t value;
13235     int result;
13236     Py_BEGIN_ALLOW_THREADS
13237     result = eventfd_read(fd, &value);
13238     Py_END_ALLOW_THREADS
13239     if (result == -1) {
13240         return PyErr_SetFromErrno(PyExc_OSError);
13241     }
13242     return PyLong_FromUnsignedLongLong(value);
13243 }
13244 
13245 /*[clinic input]
13246 os.eventfd_write
13247 
13248     fd: fildes
13249     value: unsigned_long_long
13250 
13251 Write eventfd value.
13252 [clinic start generated code]*/
13253 
13254 static PyObject *
os_eventfd_write_impl(PyObject * module,int fd,unsigned long long value)13255 os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
13256 /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
13257 {
13258     int result;
13259     Py_BEGIN_ALLOW_THREADS
13260     result = eventfd_write(fd, value);
13261     Py_END_ALLOW_THREADS
13262     if (result == -1) {
13263         return PyErr_SetFromErrno(PyExc_OSError);
13264     }
13265     Py_RETURN_NONE;
13266 }
13267 #endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
13268 
13269 /* Terminal size querying */
13270 
13271 PyDoc_STRVAR(TerminalSize_docstring,
13272     "A tuple of (columns, lines) for holding terminal window size");
13273 
13274 static PyStructSequence_Field TerminalSize_fields[] = {
13275     {"columns", "width of the terminal window in characters"},
13276     {"lines", "height of the terminal window in characters"},
13277     {NULL, NULL}
13278 };
13279 
13280 static PyStructSequence_Desc TerminalSize_desc = {
13281     "os.terminal_size",
13282     TerminalSize_docstring,
13283     TerminalSize_fields,
13284     2,
13285 };
13286 
13287 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
13288 /*[clinic input]
13289 os.get_terminal_size
13290 
13291     fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
13292     /
13293 
13294 Return the size of the terminal window as (columns, lines).
13295 
13296 The optional argument fd (default standard output) specifies
13297 which file descriptor should be queried.
13298 
13299 If the file descriptor is not connected to a terminal, an OSError
13300 is thrown.
13301 
13302 This function will only be defined if an implementation is
13303 available for this system.
13304 
13305 shutil.get_terminal_size is the high-level function which should
13306 normally be used, os.get_terminal_size is the low-level implementation.
13307 [clinic start generated code]*/
13308 
13309 static PyObject *
os_get_terminal_size_impl(PyObject * module,int fd)13310 os_get_terminal_size_impl(PyObject *module, int fd)
13311 /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
13312 {
13313     int columns, lines;
13314     PyObject *termsize;
13315 
13316     /* Under some conditions stdout may not be connected and
13317      * fileno(stdout) may point to an invalid file descriptor. For example
13318      * GUI apps don't have valid standard streams by default.
13319      *
13320      * If this happens, and the optional fd argument is not present,
13321      * the ioctl below will fail returning EBADF. This is what we want.
13322      */
13323 
13324 #ifdef TERMSIZE_USE_IOCTL
13325     {
13326         struct winsize w;
13327         if (ioctl(fd, TIOCGWINSZ, &w))
13328             return PyErr_SetFromErrno(PyExc_OSError);
13329         columns = w.ws_col;
13330         lines = w.ws_row;
13331     }
13332 #endif /* TERMSIZE_USE_IOCTL */
13333 
13334 #ifdef TERMSIZE_USE_CONIO
13335     {
13336         DWORD nhandle;
13337         HANDLE handle;
13338         CONSOLE_SCREEN_BUFFER_INFO csbi;
13339         switch (fd) {
13340         case 0: nhandle = STD_INPUT_HANDLE;
13341             break;
13342         case 1: nhandle = STD_OUTPUT_HANDLE;
13343             break;
13344         case 2: nhandle = STD_ERROR_HANDLE;
13345             break;
13346         default:
13347             return PyErr_Format(PyExc_ValueError, "bad file descriptor");
13348         }
13349         handle = GetStdHandle(nhandle);
13350         if (handle == NULL)
13351             return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
13352         if (handle == INVALID_HANDLE_VALUE)
13353             return PyErr_SetFromWindowsErr(0);
13354 
13355         if (!GetConsoleScreenBufferInfo(handle, &csbi))
13356             return PyErr_SetFromWindowsErr(0);
13357 
13358         columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
13359         lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
13360     }
13361 #endif /* TERMSIZE_USE_CONIO */
13362 
13363     PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
13364     termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
13365     if (termsize == NULL)
13366         return NULL;
13367     PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
13368     PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
13369     if (PyErr_Occurred()) {
13370         Py_DECREF(termsize);
13371         return NULL;
13372     }
13373     return termsize;
13374 }
13375 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
13376 
13377 
13378 /*[clinic input]
13379 os.cpu_count
13380 
13381 Return the number of CPUs in the system; return None if indeterminable.
13382 
13383 This number is not equivalent to the number of CPUs the current process can
13384 use.  The number of usable CPUs can be obtained with
13385 ``len(os.sched_getaffinity(0))``
13386 [clinic start generated code]*/
13387 
13388 static PyObject *
os_cpu_count_impl(PyObject * module)13389 os_cpu_count_impl(PyObject *module)
13390 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
13391 {
13392     int ncpu = 0;
13393 #ifdef MS_WINDOWS
13394     ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
13395 #elif defined(__hpux)
13396     ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
13397 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
13398     ncpu = sysconf(_SC_NPROCESSORS_ONLN);
13399 #elif defined(__VXWORKS__)
13400     ncpu = _Py_popcount32(vxCpuEnabledGet());
13401 #elif defined(__DragonFly__) || \
13402       defined(__OpenBSD__)   || \
13403       defined(__FreeBSD__)   || \
13404       defined(__NetBSD__)    || \
13405       defined(__APPLE__)
13406     int mib[2];
13407     size_t len = sizeof(ncpu);
13408     mib[0] = CTL_HW;
13409     mib[1] = HW_NCPU;
13410     if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
13411         ncpu = 0;
13412 #endif
13413     if (ncpu >= 1)
13414         return PyLong_FromLong(ncpu);
13415     else
13416         Py_RETURN_NONE;
13417 }
13418 
13419 
13420 /*[clinic input]
13421 os.get_inheritable -> bool
13422 
13423     fd: int
13424     /
13425 
13426 Get the close-on-exe flag of the specified file descriptor.
13427 [clinic start generated code]*/
13428 
13429 static int
os_get_inheritable_impl(PyObject * module,int fd)13430 os_get_inheritable_impl(PyObject *module, int fd)
13431 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
13432 {
13433     int return_value;
13434     _Py_BEGIN_SUPPRESS_IPH
13435     return_value = _Py_get_inheritable(fd);
13436     _Py_END_SUPPRESS_IPH
13437     return return_value;
13438 }
13439 
13440 
13441 /*[clinic input]
13442 os.set_inheritable
13443     fd: int
13444     inheritable: int
13445     /
13446 
13447 Set the inheritable flag of the specified file descriptor.
13448 [clinic start generated code]*/
13449 
13450 static PyObject *
os_set_inheritable_impl(PyObject * module,int fd,int inheritable)13451 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
13452 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
13453 {
13454     int result;
13455 
13456     _Py_BEGIN_SUPPRESS_IPH
13457     result = _Py_set_inheritable(fd, inheritable, NULL);
13458     _Py_END_SUPPRESS_IPH
13459     if (result < 0)
13460         return NULL;
13461     Py_RETURN_NONE;
13462 }
13463 
13464 
13465 #ifdef MS_WINDOWS
13466 /*[clinic input]
13467 os.get_handle_inheritable -> bool
13468     handle: intptr_t
13469     /
13470 
13471 Get the close-on-exe flag of the specified file descriptor.
13472 [clinic start generated code]*/
13473 
13474 static int
os_get_handle_inheritable_impl(PyObject * module,intptr_t handle)13475 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
13476 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
13477 {
13478     DWORD flags;
13479 
13480     if (!GetHandleInformation((HANDLE)handle, &flags)) {
13481         PyErr_SetFromWindowsErr(0);
13482         return -1;
13483     }
13484 
13485     return flags & HANDLE_FLAG_INHERIT;
13486 }
13487 
13488 
13489 /*[clinic input]
13490 os.set_handle_inheritable
13491     handle: intptr_t
13492     inheritable: bool
13493     /
13494 
13495 Set the inheritable flag of the specified handle.
13496 [clinic start generated code]*/
13497 
13498 static PyObject *
os_set_handle_inheritable_impl(PyObject * module,intptr_t handle,int inheritable)13499 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
13500                                int inheritable)
13501 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
13502 {
13503     DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
13504     if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
13505         PyErr_SetFromWindowsErr(0);
13506         return NULL;
13507     }
13508     Py_RETURN_NONE;
13509 }
13510 #endif /* MS_WINDOWS */
13511 
13512 #ifndef MS_WINDOWS
13513 /*[clinic input]
13514 os.get_blocking -> bool
13515     fd: int
13516     /
13517 
13518 Get the blocking mode of the file descriptor.
13519 
13520 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
13521 [clinic start generated code]*/
13522 
13523 static int
os_get_blocking_impl(PyObject * module,int fd)13524 os_get_blocking_impl(PyObject *module, int fd)
13525 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
13526 {
13527     int blocking;
13528 
13529     _Py_BEGIN_SUPPRESS_IPH
13530     blocking = _Py_get_blocking(fd);
13531     _Py_END_SUPPRESS_IPH
13532     return blocking;
13533 }
13534 
13535 /*[clinic input]
13536 os.set_blocking
13537     fd: int
13538     blocking: bool(accept={int})
13539     /
13540 
13541 Set the blocking mode of the specified file descriptor.
13542 
13543 Set the O_NONBLOCK flag if blocking is False,
13544 clear the O_NONBLOCK flag otherwise.
13545 [clinic start generated code]*/
13546 
13547 static PyObject *
os_set_blocking_impl(PyObject * module,int fd,int blocking)13548 os_set_blocking_impl(PyObject *module, int fd, int blocking)
13549 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
13550 {
13551     int result;
13552 
13553     _Py_BEGIN_SUPPRESS_IPH
13554     result = _Py_set_blocking(fd, blocking);
13555     _Py_END_SUPPRESS_IPH
13556     if (result < 0)
13557         return NULL;
13558     Py_RETURN_NONE;
13559 }
13560 #endif   /* !MS_WINDOWS */
13561 
13562 
13563 /*[clinic input]
13564 class os.DirEntry "DirEntry *" "DirEntryType"
13565 [clinic start generated code]*/
13566 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
13567 
13568 typedef struct {
13569     PyObject_HEAD
13570     PyObject *name;
13571     PyObject *path;
13572     PyObject *stat;
13573     PyObject *lstat;
13574 #ifdef MS_WINDOWS
13575     struct _Py_stat_struct win32_lstat;
13576     uint64_t win32_file_index;
13577     int got_file_index;
13578 #else /* POSIX */
13579 #ifdef HAVE_DIRENT_D_TYPE
13580     unsigned char d_type;
13581 #endif
13582     ino_t d_ino;
13583     int dir_fd;
13584 #endif
13585 } DirEntry;
13586 
13587 static void
DirEntry_dealloc(DirEntry * entry)13588 DirEntry_dealloc(DirEntry *entry)
13589 {
13590     PyTypeObject *tp = Py_TYPE(entry);
13591     Py_XDECREF(entry->name);
13592     Py_XDECREF(entry->path);
13593     Py_XDECREF(entry->stat);
13594     Py_XDECREF(entry->lstat);
13595     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13596     free_func(entry);
13597     Py_DECREF(tp);
13598 }
13599 
13600 /* Forward reference */
13601 static int
13602 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13603                    int follow_symlinks, unsigned short mode_bits);
13604 
13605 /*[clinic input]
13606 os.DirEntry.is_symlink -> bool
13607     defining_class: defining_class
13608     /
13609 
13610 Return True if the entry is a symbolic link; cached per entry.
13611 [clinic start generated code]*/
13612 
13613 static int
os_DirEntry_is_symlink_impl(DirEntry * self,PyTypeObject * defining_class)13614 os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
13615 /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
13616 {
13617 #ifdef MS_WINDOWS
13618     return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13619 #elif defined(HAVE_DIRENT_D_TYPE)
13620     /* POSIX */
13621     if (self->d_type != DT_UNKNOWN)
13622         return self->d_type == DT_LNK;
13623     else
13624         return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13625 #else
13626     /* POSIX without d_type */
13627     return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13628 #endif
13629 }
13630 
13631 static PyObject *
DirEntry_fetch_stat(PyObject * module,DirEntry * self,int follow_symlinks)13632 DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
13633 {
13634     int result;
13635     STRUCT_STAT st;
13636     PyObject *ub;
13637 
13638 #ifdef MS_WINDOWS
13639     if (!PyUnicode_FSDecoder(self->path, &ub))
13640         return NULL;
13641 #if USE_UNICODE_WCHAR_CACHE
13642 _Py_COMP_DIAG_PUSH
13643 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13644     const wchar_t *path = PyUnicode_AsUnicode(ub);
13645 _Py_COMP_DIAG_POP
13646 #else /* USE_UNICODE_WCHAR_CACHE */
13647     wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
13648     Py_DECREF(ub);
13649 #endif /* USE_UNICODE_WCHAR_CACHE */
13650 #else /* POSIX */
13651     if (!PyUnicode_FSConverter(self->path, &ub))
13652         return NULL;
13653     const char *path = PyBytes_AS_STRING(ub);
13654     if (self->dir_fd != DEFAULT_DIR_FD) {
13655 #ifdef HAVE_FSTATAT
13656       if (HAVE_FSTATAT_RUNTIME) {
13657         Py_BEGIN_ALLOW_THREADS
13658         result = fstatat(self->dir_fd, path, &st,
13659                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
13660         Py_END_ALLOW_THREADS
13661       } else
13662 
13663 #endif /* HAVE_FSTATAT */
13664       {
13665         Py_DECREF(ub);
13666         PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
13667         return NULL;
13668       }
13669     }
13670     else
13671 #endif
13672     {
13673         Py_BEGIN_ALLOW_THREADS
13674         if (follow_symlinks) {
13675             result = STAT(path, &st);
13676         }
13677         else {
13678             result = LSTAT(path, &st);
13679         }
13680         Py_END_ALLOW_THREADS
13681     }
13682 #if defined(MS_WINDOWS) && !USE_UNICODE_WCHAR_CACHE
13683     PyMem_Free(path);
13684 #else /* USE_UNICODE_WCHAR_CACHE */
13685     Py_DECREF(ub);
13686 #endif /* USE_UNICODE_WCHAR_CACHE */
13687 
13688     if (result != 0)
13689         return path_object_error(self->path);
13690 
13691     return _pystat_fromstructstat(module, &st);
13692 }
13693 
13694 static PyObject *
DirEntry_get_lstat(PyTypeObject * defining_class,DirEntry * self)13695 DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
13696 {
13697     if (!self->lstat) {
13698         PyObject *module = PyType_GetModule(defining_class);
13699 #ifdef MS_WINDOWS
13700         self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
13701 #else /* POSIX */
13702         self->lstat = DirEntry_fetch_stat(module, self, 0);
13703 #endif
13704     }
13705     Py_XINCREF(self->lstat);
13706     return self->lstat;
13707 }
13708 
13709 /*[clinic input]
13710 os.DirEntry.stat
13711     defining_class: defining_class
13712     /
13713     *
13714     follow_symlinks: bool = True
13715 
13716 Return stat_result object for the entry; cached per entry.
13717 [clinic start generated code]*/
13718 
13719 static PyObject *
os_DirEntry_stat_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13720 os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
13721                       int follow_symlinks)
13722 /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
13723 {
13724     if (!follow_symlinks) {
13725         return DirEntry_get_lstat(defining_class, self);
13726     }
13727 
13728     if (!self->stat) {
13729         int result = os_DirEntry_is_symlink_impl(self, defining_class);
13730         if (result == -1) {
13731             return NULL;
13732         }
13733         if (result) {
13734             PyObject *module = PyType_GetModule(defining_class);
13735             self->stat = DirEntry_fetch_stat(module, self, 1);
13736         }
13737         else {
13738             self->stat = DirEntry_get_lstat(defining_class, self);
13739         }
13740     }
13741 
13742     Py_XINCREF(self->stat);
13743     return self->stat;
13744 }
13745 
13746 /* Set exception and return -1 on error, 0 for False, 1 for True */
13747 static int
DirEntry_test_mode(PyTypeObject * defining_class,DirEntry * self,int follow_symlinks,unsigned short mode_bits)13748 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13749                    int follow_symlinks, unsigned short mode_bits)
13750 {
13751     PyObject *stat = NULL;
13752     PyObject *st_mode = NULL;
13753     long mode;
13754     int result;
13755 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13756     int is_symlink;
13757     int need_stat;
13758 #endif
13759 #ifdef MS_WINDOWS
13760     unsigned long dir_bits;
13761 #endif
13762 
13763 #ifdef MS_WINDOWS
13764     is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13765     need_stat = follow_symlinks && is_symlink;
13766 #elif defined(HAVE_DIRENT_D_TYPE)
13767     is_symlink = self->d_type == DT_LNK;
13768     need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
13769 #endif
13770 
13771 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13772     if (need_stat) {
13773 #endif
13774         stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
13775         if (!stat) {
13776             if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
13777                 /* If file doesn't exist (anymore), then return False
13778                    (i.e., say it's not a file/directory) */
13779                 PyErr_Clear();
13780                 return 0;
13781             }
13782             goto error;
13783         }
13784         _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
13785         st_mode = PyObject_GetAttr(stat, state->st_mode);
13786         if (!st_mode)
13787             goto error;
13788 
13789         mode = PyLong_AsLong(st_mode);
13790         if (mode == -1 && PyErr_Occurred())
13791             goto error;
13792         Py_CLEAR(st_mode);
13793         Py_CLEAR(stat);
13794         result = (mode & S_IFMT) == mode_bits;
13795 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13796     }
13797     else if (is_symlink) {
13798         assert(mode_bits != S_IFLNK);
13799         result = 0;
13800     }
13801     else {
13802         assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
13803 #ifdef MS_WINDOWS
13804         dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
13805         if (mode_bits == S_IFDIR)
13806             result = dir_bits != 0;
13807         else
13808             result = dir_bits == 0;
13809 #else /* POSIX */
13810         if (mode_bits == S_IFDIR)
13811             result = self->d_type == DT_DIR;
13812         else
13813             result = self->d_type == DT_REG;
13814 #endif
13815     }
13816 #endif
13817 
13818     return result;
13819 
13820 error:
13821     Py_XDECREF(st_mode);
13822     Py_XDECREF(stat);
13823     return -1;
13824 }
13825 
13826 /*[clinic input]
13827 os.DirEntry.is_dir -> bool
13828     defining_class: defining_class
13829     /
13830     *
13831     follow_symlinks: bool = True
13832 
13833 Return True if the entry is a directory; cached per entry.
13834 [clinic start generated code]*/
13835 
13836 static int
os_DirEntry_is_dir_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13837 os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
13838                         int follow_symlinks)
13839 /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
13840 {
13841     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
13842 }
13843 
13844 /*[clinic input]
13845 os.DirEntry.is_file -> bool
13846     defining_class: defining_class
13847     /
13848     *
13849     follow_symlinks: bool = True
13850 
13851 Return True if the entry is a file; cached per entry.
13852 [clinic start generated code]*/
13853 
13854 static int
os_DirEntry_is_file_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13855 os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
13856                          int follow_symlinks)
13857 /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
13858 {
13859     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
13860 }
13861 
13862 /*[clinic input]
13863 os.DirEntry.inode
13864 
13865 Return inode of the entry; cached per entry.
13866 [clinic start generated code]*/
13867 
13868 static PyObject *
os_DirEntry_inode_impl(DirEntry * self)13869 os_DirEntry_inode_impl(DirEntry *self)
13870 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
13871 {
13872 #ifdef MS_WINDOWS
13873     if (!self->got_file_index) {
13874         PyObject *unicode;
13875         STRUCT_STAT stat;
13876         int result;
13877 
13878         if (!PyUnicode_FSDecoder(self->path, &unicode))
13879             return NULL;
13880 #if USE_UNICODE_WCHAR_CACHE
13881 _Py_COMP_DIAG_PUSH
13882 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13883         const wchar_t *path = PyUnicode_AsUnicode(unicode);
13884         result = LSTAT(path, &stat);
13885         Py_DECREF(unicode);
13886 _Py_COMP_DIAG_POP
13887 #else /* USE_UNICODE_WCHAR_CACHE */
13888         wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
13889         Py_DECREF(unicode);
13890         result = LSTAT(path, &stat);
13891         PyMem_Free(path);
13892 #endif /* USE_UNICODE_WCHAR_CACHE */
13893 
13894         if (result != 0)
13895             return path_object_error(self->path);
13896 
13897         self->win32_file_index = stat.st_ino;
13898         self->got_file_index = 1;
13899     }
13900     static_assert(sizeof(unsigned long long) >= sizeof(self->win32_file_index),
13901                   "DirEntry.win32_file_index is larger than unsigned long long");
13902     return PyLong_FromUnsignedLongLong(self->win32_file_index);
13903 #else /* POSIX */
13904     static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
13905                   "DirEntry.d_ino is larger than unsigned long long");
13906     return PyLong_FromUnsignedLongLong(self->d_ino);
13907 #endif
13908 }
13909 
13910 static PyObject *
DirEntry_repr(DirEntry * self)13911 DirEntry_repr(DirEntry *self)
13912 {
13913     return PyUnicode_FromFormat("<DirEntry %R>", self->name);
13914 }
13915 
13916 /*[clinic input]
13917 os.DirEntry.__fspath__
13918 
13919 Returns the path for the entry.
13920 [clinic start generated code]*/
13921 
13922 static PyObject *
os_DirEntry___fspath___impl(DirEntry * self)13923 os_DirEntry___fspath___impl(DirEntry *self)
13924 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
13925 {
13926     Py_INCREF(self->path);
13927     return self->path;
13928 }
13929 
13930 static PyMemberDef DirEntry_members[] = {
13931     {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
13932      "the entry's base filename, relative to scandir() \"path\" argument"},
13933     {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
13934      "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
13935     {NULL}
13936 };
13937 
13938 #include "clinic/posixmodule.c.h"
13939 
13940 static PyMethodDef DirEntry_methods[] = {
13941     OS_DIRENTRY_IS_DIR_METHODDEF
13942     OS_DIRENTRY_IS_FILE_METHODDEF
13943     OS_DIRENTRY_IS_SYMLINK_METHODDEF
13944     OS_DIRENTRY_STAT_METHODDEF
13945     OS_DIRENTRY_INODE_METHODDEF
13946     OS_DIRENTRY___FSPATH___METHODDEF
13947     {"__class_getitem__",       Py_GenericAlias,
13948     METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
13949     {NULL}
13950 };
13951 
13952 static PyType_Slot DirEntryType_slots[] = {
13953     {Py_tp_dealloc, DirEntry_dealloc},
13954     {Py_tp_repr, DirEntry_repr},
13955     {Py_tp_methods, DirEntry_methods},
13956     {Py_tp_members, DirEntry_members},
13957     {0, 0},
13958 };
13959 
13960 static PyType_Spec DirEntryType_spec = {
13961     MODNAME ".DirEntry",
13962     sizeof(DirEntry),
13963     0,
13964     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
13965     DirEntryType_slots
13966 };
13967 
13968 
13969 #ifdef MS_WINDOWS
13970 
13971 static wchar_t *
join_path_filenameW(const wchar_t * path_wide,const wchar_t * filename)13972 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
13973 {
13974     Py_ssize_t path_len;
13975     Py_ssize_t size;
13976     wchar_t *result;
13977     wchar_t ch;
13978 
13979     if (!path_wide) { /* Default arg: "." */
13980         path_wide = L".";
13981         path_len = 1;
13982     }
13983     else {
13984         path_len = wcslen(path_wide);
13985     }
13986 
13987     /* The +1's are for the path separator and the NUL */
13988     size = path_len + 1 + wcslen(filename) + 1;
13989     result = PyMem_New(wchar_t, size);
13990     if (!result) {
13991         PyErr_NoMemory();
13992         return NULL;
13993     }
13994     wcscpy(result, path_wide);
13995     if (path_len > 0) {
13996         ch = result[path_len - 1];
13997         if (ch != SEP && ch != ALTSEP && ch != L':')
13998             result[path_len++] = SEP;
13999         wcscpy(result + path_len, filename);
14000     }
14001     return result;
14002 }
14003 
14004 static PyObject *
DirEntry_from_find_data(PyObject * module,path_t * path,WIN32_FIND_DATAW * dataW)14005 DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
14006 {
14007     DirEntry *entry;
14008     BY_HANDLE_FILE_INFORMATION file_info;
14009     ULONG reparse_tag;
14010     wchar_t *joined_path;
14011 
14012     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
14013     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
14014     if (!entry)
14015         return NULL;
14016     entry->name = NULL;
14017     entry->path = NULL;
14018     entry->stat = NULL;
14019     entry->lstat = NULL;
14020     entry->got_file_index = 0;
14021 
14022     entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
14023     if (!entry->name)
14024         goto error;
14025     if (path->narrow) {
14026         Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
14027         if (!entry->name)
14028             goto error;
14029     }
14030 
14031     joined_path = join_path_filenameW(path->wide, dataW->cFileName);
14032     if (!joined_path)
14033         goto error;
14034 
14035     entry->path = PyUnicode_FromWideChar(joined_path, -1);
14036     PyMem_Free(joined_path);
14037     if (!entry->path)
14038         goto error;
14039     if (path->narrow) {
14040         Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
14041         if (!entry->path)
14042             goto error;
14043     }
14044 
14045     find_data_to_file_info(dataW, &file_info, &reparse_tag);
14046     _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
14047 
14048     return (PyObject *)entry;
14049 
14050 error:
14051     Py_DECREF(entry);
14052     return NULL;
14053 }
14054 
14055 #else /* POSIX */
14056 
14057 static char *
join_path_filename(const char * path_narrow,const char * filename,Py_ssize_t filename_len)14058 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
14059 {
14060     Py_ssize_t path_len;
14061     Py_ssize_t size;
14062     char *result;
14063 
14064     if (!path_narrow) { /* Default arg: "." */
14065         path_narrow = ".";
14066         path_len = 1;
14067     }
14068     else {
14069         path_len = strlen(path_narrow);
14070     }
14071 
14072     if (filename_len == -1)
14073         filename_len = strlen(filename);
14074 
14075     /* The +1's are for the path separator and the NUL */
14076     size = path_len + 1 + filename_len + 1;
14077     result = PyMem_New(char, size);
14078     if (!result) {
14079         PyErr_NoMemory();
14080         return NULL;
14081     }
14082     strcpy(result, path_narrow);
14083     if (path_len > 0 && result[path_len - 1] != '/')
14084         result[path_len++] = '/';
14085     strcpy(result + path_len, filename);
14086     return result;
14087 }
14088 
14089 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)14090 DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
14091                          Py_ssize_t name_len, ino_t d_ino
14092 #ifdef HAVE_DIRENT_D_TYPE
14093                          , unsigned char d_type
14094 #endif
14095                          )
14096 {
14097     DirEntry *entry;
14098     char *joined_path;
14099 
14100     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
14101     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
14102     if (!entry)
14103         return NULL;
14104     entry->name = NULL;
14105     entry->path = NULL;
14106     entry->stat = NULL;
14107     entry->lstat = NULL;
14108 
14109     if (path->fd != -1) {
14110         entry->dir_fd = path->fd;
14111         joined_path = NULL;
14112     }
14113     else {
14114         entry->dir_fd = DEFAULT_DIR_FD;
14115         joined_path = join_path_filename(path->narrow, name, name_len);
14116         if (!joined_path)
14117             goto error;
14118     }
14119 
14120     if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
14121         entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
14122         if (joined_path)
14123             entry->path = PyUnicode_DecodeFSDefault(joined_path);
14124     }
14125     else {
14126         entry->name = PyBytes_FromStringAndSize(name, name_len);
14127         if (joined_path)
14128             entry->path = PyBytes_FromString(joined_path);
14129     }
14130     PyMem_Free(joined_path);
14131     if (!entry->name)
14132         goto error;
14133 
14134     if (path->fd != -1) {
14135         entry->path = entry->name;
14136         Py_INCREF(entry->path);
14137     }
14138     else if (!entry->path)
14139         goto error;
14140 
14141 #ifdef HAVE_DIRENT_D_TYPE
14142     entry->d_type = d_type;
14143 #endif
14144     entry->d_ino = d_ino;
14145 
14146     return (PyObject *)entry;
14147 
14148 error:
14149     Py_XDECREF(entry);
14150     return NULL;
14151 }
14152 
14153 #endif
14154 
14155 
14156 typedef struct {
14157     PyObject_HEAD
14158     path_t path;
14159 #ifdef MS_WINDOWS
14160     HANDLE handle;
14161     WIN32_FIND_DATAW file_data;
14162     int first_time;
14163 #else /* POSIX */
14164     DIR *dirp;
14165 #endif
14166 #ifdef HAVE_FDOPENDIR
14167     int fd;
14168 #endif
14169 } ScandirIterator;
14170 
14171 #ifdef MS_WINDOWS
14172 
14173 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14174 ScandirIterator_is_closed(ScandirIterator *iterator)
14175 {
14176     return iterator->handle == INVALID_HANDLE_VALUE;
14177 }
14178 
14179 static void
ScandirIterator_closedir(ScandirIterator * iterator)14180 ScandirIterator_closedir(ScandirIterator *iterator)
14181 {
14182     HANDLE handle = iterator->handle;
14183 
14184     if (handle == INVALID_HANDLE_VALUE)
14185         return;
14186 
14187     iterator->handle = INVALID_HANDLE_VALUE;
14188     Py_BEGIN_ALLOW_THREADS
14189     FindClose(handle);
14190     Py_END_ALLOW_THREADS
14191 }
14192 
14193 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14194 ScandirIterator_iternext(ScandirIterator *iterator)
14195 {
14196     WIN32_FIND_DATAW *file_data = &iterator->file_data;
14197     BOOL success;
14198     PyObject *entry;
14199 
14200     /* Happens if the iterator is iterated twice, or closed explicitly */
14201     if (iterator->handle == INVALID_HANDLE_VALUE)
14202         return NULL;
14203 
14204     while (1) {
14205         if (!iterator->first_time) {
14206             Py_BEGIN_ALLOW_THREADS
14207             success = FindNextFileW(iterator->handle, file_data);
14208             Py_END_ALLOW_THREADS
14209             if (!success) {
14210                 /* Error or no more files */
14211                 if (GetLastError() != ERROR_NO_MORE_FILES)
14212                     path_error(&iterator->path);
14213                 break;
14214             }
14215         }
14216         iterator->first_time = 0;
14217 
14218         /* Skip over . and .. */
14219         if (wcscmp(file_data->cFileName, L".") != 0 &&
14220             wcscmp(file_data->cFileName, L"..") != 0)
14221         {
14222             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14223             entry = DirEntry_from_find_data(module, &iterator->path, file_data);
14224             if (!entry)
14225                 break;
14226             return entry;
14227         }
14228 
14229         /* Loop till we get a non-dot directory or finish iterating */
14230     }
14231 
14232     /* Error or no more files */
14233     ScandirIterator_closedir(iterator);
14234     return NULL;
14235 }
14236 
14237 #else /* POSIX */
14238 
14239 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14240 ScandirIterator_is_closed(ScandirIterator *iterator)
14241 {
14242     return !iterator->dirp;
14243 }
14244 
14245 static void
ScandirIterator_closedir(ScandirIterator * iterator)14246 ScandirIterator_closedir(ScandirIterator *iterator)
14247 {
14248     DIR *dirp = iterator->dirp;
14249 
14250     if (!dirp)
14251         return;
14252 
14253     iterator->dirp = NULL;
14254     Py_BEGIN_ALLOW_THREADS
14255 #ifdef HAVE_FDOPENDIR
14256     if (iterator->path.fd != -1)
14257         rewinddir(dirp);
14258 #endif
14259     closedir(dirp);
14260     Py_END_ALLOW_THREADS
14261     return;
14262 }
14263 
14264 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14265 ScandirIterator_iternext(ScandirIterator *iterator)
14266 {
14267     struct dirent *direntp;
14268     Py_ssize_t name_len;
14269     int is_dot;
14270     PyObject *entry;
14271 
14272     /* Happens if the iterator is iterated twice, or closed explicitly */
14273     if (!iterator->dirp)
14274         return NULL;
14275 
14276     while (1) {
14277         errno = 0;
14278         Py_BEGIN_ALLOW_THREADS
14279         direntp = readdir(iterator->dirp);
14280         Py_END_ALLOW_THREADS
14281 
14282         if (!direntp) {
14283             /* Error or no more files */
14284             if (errno != 0)
14285                 path_error(&iterator->path);
14286             break;
14287         }
14288 
14289         /* Skip over . and .. */
14290         name_len = NAMLEN(direntp);
14291         is_dot = direntp->d_name[0] == '.' &&
14292                  (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
14293         if (!is_dot) {
14294             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14295             entry = DirEntry_from_posix_info(module,
14296                                              &iterator->path, direntp->d_name,
14297                                              name_len, direntp->d_ino
14298 #ifdef HAVE_DIRENT_D_TYPE
14299                                              , direntp->d_type
14300 #endif
14301                                             );
14302             if (!entry)
14303                 break;
14304             return entry;
14305         }
14306 
14307         /* Loop till we get a non-dot directory or finish iterating */
14308     }
14309 
14310     /* Error or no more files */
14311     ScandirIterator_closedir(iterator);
14312     return NULL;
14313 }
14314 
14315 #endif
14316 
14317 static PyObject *
ScandirIterator_close(ScandirIterator * self,PyObject * args)14318 ScandirIterator_close(ScandirIterator *self, PyObject *args)
14319 {
14320     ScandirIterator_closedir(self);
14321     Py_RETURN_NONE;
14322 }
14323 
14324 static PyObject *
ScandirIterator_enter(PyObject * self,PyObject * args)14325 ScandirIterator_enter(PyObject *self, PyObject *args)
14326 {
14327     Py_INCREF(self);
14328     return self;
14329 }
14330 
14331 static PyObject *
ScandirIterator_exit(ScandirIterator * self,PyObject * args)14332 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
14333 {
14334     ScandirIterator_closedir(self);
14335     Py_RETURN_NONE;
14336 }
14337 
14338 static void
ScandirIterator_finalize(ScandirIterator * iterator)14339 ScandirIterator_finalize(ScandirIterator *iterator)
14340 {
14341     PyObject *error_type, *error_value, *error_traceback;
14342 
14343     /* Save the current exception, if any. */
14344     PyErr_Fetch(&error_type, &error_value, &error_traceback);
14345 
14346     if (!ScandirIterator_is_closed(iterator)) {
14347         ScandirIterator_closedir(iterator);
14348 
14349         if (PyErr_ResourceWarning((PyObject *)iterator, 1,
14350                                   "unclosed scandir iterator %R", iterator)) {
14351             /* Spurious errors can appear at shutdown */
14352             if (PyErr_ExceptionMatches(PyExc_Warning)) {
14353                 PyErr_WriteUnraisable((PyObject *) iterator);
14354             }
14355         }
14356     }
14357 
14358     path_cleanup(&iterator->path);
14359 
14360     /* Restore the saved exception. */
14361     PyErr_Restore(error_type, error_value, error_traceback);
14362 }
14363 
14364 static void
ScandirIterator_dealloc(ScandirIterator * iterator)14365 ScandirIterator_dealloc(ScandirIterator *iterator)
14366 {
14367     PyTypeObject *tp = Py_TYPE(iterator);
14368     if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
14369         return;
14370 
14371     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
14372     free_func(iterator);
14373     Py_DECREF(tp);
14374 }
14375 
14376 static PyMethodDef ScandirIterator_methods[] = {
14377     {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
14378     {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
14379     {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
14380     {NULL}
14381 };
14382 
14383 static PyType_Slot ScandirIteratorType_slots[] = {
14384     {Py_tp_dealloc, ScandirIterator_dealloc},
14385     {Py_tp_finalize, ScandirIterator_finalize},
14386     {Py_tp_iter, PyObject_SelfIter},
14387     {Py_tp_iternext, ScandirIterator_iternext},
14388     {Py_tp_methods, ScandirIterator_methods},
14389     {0, 0},
14390 };
14391 
14392 static PyType_Spec ScandirIteratorType_spec = {
14393     MODNAME ".ScandirIterator",
14394     sizeof(ScandirIterator),
14395     0,
14396     // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
14397     // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
14398     (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
14399         | Py_TPFLAGS_DISALLOW_INSTANTIATION),
14400     ScandirIteratorType_slots
14401 };
14402 
14403 /*[clinic input]
14404 os.scandir
14405 
14406     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
14407 
14408 Return an iterator of DirEntry objects for given path.
14409 
14410 path can be specified as either str, bytes, or a path-like object.  If path
14411 is bytes, the names of yielded DirEntry objects will also be bytes; in
14412 all other circumstances they will be str.
14413 
14414 If path is None, uses the path='.'.
14415 [clinic start generated code]*/
14416 
14417 static PyObject *
os_scandir_impl(PyObject * module,path_t * path)14418 os_scandir_impl(PyObject *module, path_t *path)
14419 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
14420 {
14421     ScandirIterator *iterator;
14422 #ifdef MS_WINDOWS
14423     wchar_t *path_strW;
14424 #else
14425     const char *path_str;
14426 #ifdef HAVE_FDOPENDIR
14427     int fd = -1;
14428 #endif
14429 #endif
14430 
14431     if (PySys_Audit("os.scandir", "O",
14432                     path->object ? path->object : Py_None) < 0) {
14433         return NULL;
14434     }
14435 
14436     PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
14437     iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
14438     if (!iterator)
14439         return NULL;
14440 
14441 #ifdef MS_WINDOWS
14442     iterator->handle = INVALID_HANDLE_VALUE;
14443 #else
14444     iterator->dirp = NULL;
14445 #endif
14446 
14447     /* Move the ownership to iterator->path */
14448     memcpy(&iterator->path, path, sizeof(path_t));
14449     memset(path, 0, sizeof(path_t));
14450 
14451 #ifdef MS_WINDOWS
14452     iterator->first_time = 1;
14453 
14454     path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
14455     if (!path_strW)
14456         goto error;
14457 
14458     Py_BEGIN_ALLOW_THREADS
14459     iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
14460     Py_END_ALLOW_THREADS
14461 
14462     PyMem_Free(path_strW);
14463 
14464     if (iterator->handle == INVALID_HANDLE_VALUE) {
14465         path_error(&iterator->path);
14466         goto error;
14467     }
14468 #else /* POSIX */
14469     errno = 0;
14470 #ifdef HAVE_FDOPENDIR
14471     if (iterator->path.fd != -1) {
14472       if (HAVE_FDOPENDIR_RUNTIME) {
14473         /* closedir() closes the FD, so we duplicate it */
14474         fd = _Py_dup(iterator->path.fd);
14475         if (fd == -1)
14476             goto error;
14477 
14478         Py_BEGIN_ALLOW_THREADS
14479         iterator->dirp = fdopendir(fd);
14480         Py_END_ALLOW_THREADS
14481       } else {
14482         PyErr_SetString(PyExc_TypeError,
14483             "scandir: path should be string, bytes, os.PathLike or None, not int");
14484         return NULL;
14485       }
14486     }
14487     else
14488 #endif
14489     {
14490         if (iterator->path.narrow)
14491             path_str = iterator->path.narrow;
14492         else
14493             path_str = ".";
14494 
14495         Py_BEGIN_ALLOW_THREADS
14496         iterator->dirp = opendir(path_str);
14497         Py_END_ALLOW_THREADS
14498     }
14499 
14500     if (!iterator->dirp) {
14501         path_error(&iterator->path);
14502 #ifdef HAVE_FDOPENDIR
14503         if (fd != -1) {
14504             Py_BEGIN_ALLOW_THREADS
14505             close(fd);
14506             Py_END_ALLOW_THREADS
14507         }
14508 #endif
14509         goto error;
14510     }
14511 #endif
14512 
14513     return (PyObject *)iterator;
14514 
14515 error:
14516     Py_DECREF(iterator);
14517     return NULL;
14518 }
14519 
14520 /*
14521     Return the file system path representation of the object.
14522 
14523     If the object is str or bytes, then allow it to pass through with
14524     an incremented refcount. If the object defines __fspath__(), then
14525     return the result of that method. All other types raise a TypeError.
14526 */
14527 PyObject *
PyOS_FSPath(PyObject * path)14528 PyOS_FSPath(PyObject *path)
14529 {
14530     /* For error message reasons, this function is manually inlined in
14531        path_converter(). */
14532     PyObject *func = NULL;
14533     PyObject *path_repr = NULL;
14534 
14535     if (PyUnicode_Check(path) || PyBytes_Check(path)) {
14536         Py_INCREF(path);
14537         return path;
14538     }
14539 
14540     func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
14541     if (NULL == func) {
14542         return PyErr_Format(PyExc_TypeError,
14543                             "expected str, bytes or os.PathLike object, "
14544                             "not %.200s",
14545                             _PyType_Name(Py_TYPE(path)));
14546     }
14547 
14548     path_repr = _PyObject_CallNoArgs(func);
14549     Py_DECREF(func);
14550     if (NULL == path_repr) {
14551         return NULL;
14552     }
14553 
14554     if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
14555         PyErr_Format(PyExc_TypeError,
14556                      "expected %.200s.__fspath__() to return str or bytes, "
14557                      "not %.200s", _PyType_Name(Py_TYPE(path)),
14558                      _PyType_Name(Py_TYPE(path_repr)));
14559         Py_DECREF(path_repr);
14560         return NULL;
14561     }
14562 
14563     return path_repr;
14564 }
14565 
14566 /*[clinic input]
14567 os.fspath
14568 
14569     path: object
14570 
14571 Return the file system path representation of the object.
14572 
14573 If the object is str or bytes, then allow it to pass through as-is. If the
14574 object defines __fspath__(), then return the result of that method. All other
14575 types raise a TypeError.
14576 [clinic start generated code]*/
14577 
14578 static PyObject *
os_fspath_impl(PyObject * module,PyObject * path)14579 os_fspath_impl(PyObject *module, PyObject *path)
14580 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
14581 {
14582     return PyOS_FSPath(path);
14583 }
14584 
14585 #ifdef HAVE_GETRANDOM_SYSCALL
14586 /*[clinic input]
14587 os.getrandom
14588 
14589     size: Py_ssize_t
14590     flags: int=0
14591 
14592 Obtain a series of random bytes.
14593 [clinic start generated code]*/
14594 
14595 static PyObject *
os_getrandom_impl(PyObject * module,Py_ssize_t size,int flags)14596 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
14597 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
14598 {
14599     PyObject *bytes;
14600     Py_ssize_t n;
14601 
14602     if (size < 0) {
14603         errno = EINVAL;
14604         return posix_error();
14605     }
14606 
14607     bytes = PyBytes_FromStringAndSize(NULL, size);
14608     if (bytes == NULL) {
14609         PyErr_NoMemory();
14610         return NULL;
14611     }
14612 
14613     while (1) {
14614         n = syscall(SYS_getrandom,
14615                     PyBytes_AS_STRING(bytes),
14616                     PyBytes_GET_SIZE(bytes),
14617                     flags);
14618         if (n < 0 && errno == EINTR) {
14619             if (PyErr_CheckSignals() < 0) {
14620                 goto error;
14621             }
14622 
14623             /* getrandom() was interrupted by a signal: retry */
14624             continue;
14625         }
14626         break;
14627     }
14628 
14629     if (n < 0) {
14630         PyErr_SetFromErrno(PyExc_OSError);
14631         goto error;
14632     }
14633 
14634     if (n != size) {
14635         _PyBytes_Resize(&bytes, n);
14636     }
14637 
14638     return bytes;
14639 
14640 error:
14641     Py_DECREF(bytes);
14642     return NULL;
14643 }
14644 #endif   /* HAVE_GETRANDOM_SYSCALL */
14645 
14646 #ifdef MS_WINDOWS
14647 /* bpo-36085: Helper functions for managing DLL search directories
14648  * on win32
14649  */
14650 
14651 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
14652 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
14653 
14654 /*[clinic input]
14655 os._add_dll_directory
14656 
14657     path: path_t
14658 
14659 Add a path to the DLL search path.
14660 
14661 This search path is used when resolving dependencies for imported
14662 extension modules (the module itself is resolved through sys.path),
14663 and also by ctypes.
14664 
14665 Returns an opaque value that may be passed to os.remove_dll_directory
14666 to remove this directory from the search path.
14667 [clinic start generated code]*/
14668 
14669 static PyObject *
os__add_dll_directory_impl(PyObject * module,path_t * path)14670 os__add_dll_directory_impl(PyObject *module, path_t *path)
14671 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
14672 {
14673     HMODULE hKernel32;
14674     PAddDllDirectory AddDllDirectory;
14675     DLL_DIRECTORY_COOKIE cookie = 0;
14676     DWORD err = 0;
14677 
14678     if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
14679         return NULL;
14680     }
14681 
14682     /* For Windows 7, we have to load this. As this will be a fairly
14683        infrequent operation, just do it each time. Kernel32 is always
14684        loaded. */
14685     Py_BEGIN_ALLOW_THREADS
14686     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14687         !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
14688             hKernel32, "AddDllDirectory")) ||
14689         !(cookie = (*AddDllDirectory)(path->wide))) {
14690         err = GetLastError();
14691     }
14692     Py_END_ALLOW_THREADS
14693 
14694     if (err) {
14695         return win32_error_object_err("add_dll_directory",
14696                                       path->object, err);
14697     }
14698 
14699     return PyCapsule_New(cookie, "DLL directory cookie", NULL);
14700 }
14701 
14702 /*[clinic input]
14703 os._remove_dll_directory
14704 
14705     cookie: object
14706 
14707 Removes a path from the DLL search path.
14708 
14709 The parameter is an opaque value that was returned from
14710 os.add_dll_directory. You can only remove directories that you added
14711 yourself.
14712 [clinic start generated code]*/
14713 
14714 static PyObject *
os__remove_dll_directory_impl(PyObject * module,PyObject * cookie)14715 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
14716 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
14717 {
14718     HMODULE hKernel32;
14719     PRemoveDllDirectory RemoveDllDirectory;
14720     DLL_DIRECTORY_COOKIE cookieValue;
14721     DWORD err = 0;
14722 
14723     if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
14724         PyErr_SetString(PyExc_TypeError,
14725             "Provided cookie was not returned from os.add_dll_directory");
14726         return NULL;
14727     }
14728 
14729     cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
14730         cookie, "DLL directory cookie");
14731 
14732     /* For Windows 7, we have to load this. As this will be a fairly
14733        infrequent operation, just do it each time. Kernel32 is always
14734        loaded. */
14735     Py_BEGIN_ALLOW_THREADS
14736     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14737         !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
14738             hKernel32, "RemoveDllDirectory")) ||
14739         !(*RemoveDllDirectory)(cookieValue)) {
14740         err = GetLastError();
14741     }
14742     Py_END_ALLOW_THREADS
14743 
14744     if (err) {
14745         return win32_error_object_err("remove_dll_directory",
14746                                       NULL, err);
14747     }
14748 
14749     if (PyCapsule_SetName(cookie, NULL)) {
14750         return NULL;
14751     }
14752 
14753     Py_RETURN_NONE;
14754 }
14755 
14756 #endif
14757 
14758 
14759 /* Only check if WIFEXITED is available: expect that it comes
14760    with WEXITSTATUS, WIFSIGNALED, etc.
14761 
14762    os.waitstatus_to_exitcode() is implemented in C and not in Python, so
14763    subprocess can safely call it during late Python finalization without
14764    risking that used os attributes were set to None by finalize_modules(). */
14765 #if defined(WIFEXITED) || defined(MS_WINDOWS)
14766 /*[clinic input]
14767 os.waitstatus_to_exitcode
14768 
14769     status as status_obj: object
14770 
14771 Convert a wait status to an exit code.
14772 
14773 On Unix:
14774 
14775 * If WIFEXITED(status) is true, return WEXITSTATUS(status).
14776 * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
14777 * Otherwise, raise a ValueError.
14778 
14779 On Windows, return status shifted right by 8 bits.
14780 
14781 On Unix, if the process is being traced or if waitpid() was called with
14782 WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
14783 This function must not be called if WIFSTOPPED(status) is true.
14784 [clinic start generated code]*/
14785 
14786 static PyObject *
os_waitstatus_to_exitcode_impl(PyObject * module,PyObject * status_obj)14787 os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
14788 /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
14789 {
14790 #ifndef MS_WINDOWS
14791     int status = _PyLong_AsInt(status_obj);
14792     if (status == -1 && PyErr_Occurred()) {
14793         return NULL;
14794     }
14795 
14796     WAIT_TYPE wait_status;
14797     WAIT_STATUS_INT(wait_status) = status;
14798     int exitcode;
14799     if (WIFEXITED(wait_status)) {
14800         exitcode = WEXITSTATUS(wait_status);
14801         /* Sanity check to provide warranty on the function behavior.
14802            It should not occur in practice */
14803         if (exitcode < 0) {
14804             PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
14805             return NULL;
14806         }
14807     }
14808     else if (WIFSIGNALED(wait_status)) {
14809         int signum = WTERMSIG(wait_status);
14810         /* Sanity check to provide warranty on the function behavior.
14811            It should not occurs in practice */
14812         if (signum <= 0) {
14813             PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
14814             return NULL;
14815         }
14816         exitcode = -signum;
14817     } else if (WIFSTOPPED(wait_status)) {
14818         /* Status only received if the process is being traced
14819            or if waitpid() was called with WUNTRACED option. */
14820         int signum = WSTOPSIG(wait_status);
14821         PyErr_Format(PyExc_ValueError,
14822                      "process stopped by delivery of signal %i",
14823                      signum);
14824         return NULL;
14825     }
14826     else {
14827         PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
14828         return NULL;
14829     }
14830     return PyLong_FromLong(exitcode);
14831 #else
14832     /* Windows implementation: see os.waitpid() implementation
14833        which uses _cwait(). */
14834     unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
14835     if (status == (unsigned long long)-1 && PyErr_Occurred()) {
14836         return NULL;
14837     }
14838 
14839     unsigned long long exitcode = (status >> 8);
14840     /* ExitProcess() accepts an UINT type:
14841        reject exit code which doesn't fit in an UINT */
14842     if (exitcode > UINT_MAX) {
14843         PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
14844         return NULL;
14845     }
14846     return PyLong_FromUnsignedLong((unsigned long)exitcode);
14847 #endif
14848 }
14849 #endif
14850 
14851 
14852 static PyMethodDef posix_methods[] = {
14853 
14854     OS_STAT_METHODDEF
14855     OS_ACCESS_METHODDEF
14856     OS_TTYNAME_METHODDEF
14857     OS_CHDIR_METHODDEF
14858     OS_CHFLAGS_METHODDEF
14859     OS_CHMOD_METHODDEF
14860     OS_FCHMOD_METHODDEF
14861     OS_LCHMOD_METHODDEF
14862     OS_CHOWN_METHODDEF
14863     OS_FCHOWN_METHODDEF
14864     OS_LCHOWN_METHODDEF
14865     OS_LCHFLAGS_METHODDEF
14866     OS_CHROOT_METHODDEF
14867     OS_CTERMID_METHODDEF
14868     OS_GETCWD_METHODDEF
14869     OS_GETCWDB_METHODDEF
14870     OS_LINK_METHODDEF
14871     OS_LISTDIR_METHODDEF
14872     OS_LSTAT_METHODDEF
14873     OS_MKDIR_METHODDEF
14874     OS_NICE_METHODDEF
14875     OS_GETPRIORITY_METHODDEF
14876     OS_SETPRIORITY_METHODDEF
14877     OS_POSIX_SPAWN_METHODDEF
14878     OS_POSIX_SPAWNP_METHODDEF
14879     OS_READLINK_METHODDEF
14880     OS_COPY_FILE_RANGE_METHODDEF
14881     OS_SPLICE_METHODDEF
14882     OS_RENAME_METHODDEF
14883     OS_REPLACE_METHODDEF
14884     OS_RMDIR_METHODDEF
14885     OS_SYMLINK_METHODDEF
14886     OS_SYSTEM_METHODDEF
14887     OS_UMASK_METHODDEF
14888     OS_UNAME_METHODDEF
14889     OS_UNLINK_METHODDEF
14890     OS_REMOVE_METHODDEF
14891     OS_UTIME_METHODDEF
14892     OS_TIMES_METHODDEF
14893     OS__EXIT_METHODDEF
14894     OS__FCOPYFILE_METHODDEF
14895     OS_EXECV_METHODDEF
14896     OS_EXECVE_METHODDEF
14897     OS_SPAWNV_METHODDEF
14898     OS_SPAWNVE_METHODDEF
14899     OS_FORK1_METHODDEF
14900     OS_FORK_METHODDEF
14901     OS_REGISTER_AT_FORK_METHODDEF
14902     OS_SCHED_GET_PRIORITY_MAX_METHODDEF
14903     OS_SCHED_GET_PRIORITY_MIN_METHODDEF
14904     OS_SCHED_GETPARAM_METHODDEF
14905     OS_SCHED_GETSCHEDULER_METHODDEF
14906     OS_SCHED_RR_GET_INTERVAL_METHODDEF
14907     OS_SCHED_SETPARAM_METHODDEF
14908     OS_SCHED_SETSCHEDULER_METHODDEF
14909     OS_SCHED_YIELD_METHODDEF
14910     OS_SCHED_SETAFFINITY_METHODDEF
14911     OS_SCHED_GETAFFINITY_METHODDEF
14912     OS_OPENPTY_METHODDEF
14913     OS_LOGIN_TTY_METHODDEF
14914     OS_FORKPTY_METHODDEF
14915     OS_GETEGID_METHODDEF
14916     OS_GETEUID_METHODDEF
14917     OS_GETGID_METHODDEF
14918     OS_GETGROUPLIST_METHODDEF
14919     OS_GETGROUPS_METHODDEF
14920     OS_GETPID_METHODDEF
14921     OS_GETPGRP_METHODDEF
14922     OS_GETPPID_METHODDEF
14923     OS_GETUID_METHODDEF
14924     OS_GETLOGIN_METHODDEF
14925     OS_KILL_METHODDEF
14926     OS_KILLPG_METHODDEF
14927     OS_PLOCK_METHODDEF
14928     OS_STARTFILE_METHODDEF
14929     OS_SETUID_METHODDEF
14930     OS_SETEUID_METHODDEF
14931     OS_SETREUID_METHODDEF
14932     OS_SETGID_METHODDEF
14933     OS_SETEGID_METHODDEF
14934     OS_SETREGID_METHODDEF
14935     OS_SETGROUPS_METHODDEF
14936     OS_INITGROUPS_METHODDEF
14937     OS_GETPGID_METHODDEF
14938     OS_SETPGRP_METHODDEF
14939     OS_WAIT_METHODDEF
14940     OS_WAIT3_METHODDEF
14941     OS_WAIT4_METHODDEF
14942     OS_WAITID_METHODDEF
14943     OS_WAITPID_METHODDEF
14944     OS_PIDFD_OPEN_METHODDEF
14945     OS_GETSID_METHODDEF
14946     OS_SETSID_METHODDEF
14947     OS_SETPGID_METHODDEF
14948     OS_TCGETPGRP_METHODDEF
14949     OS_TCSETPGRP_METHODDEF
14950     OS_OPEN_METHODDEF
14951     OS_CLOSE_METHODDEF
14952     OS_CLOSERANGE_METHODDEF
14953     OS_DEVICE_ENCODING_METHODDEF
14954     OS_DUP_METHODDEF
14955     OS_DUP2_METHODDEF
14956     OS_LOCKF_METHODDEF
14957     OS_LSEEK_METHODDEF
14958     OS_READ_METHODDEF
14959     OS_READV_METHODDEF
14960     OS_PREAD_METHODDEF
14961     OS_PREADV_METHODDEF
14962     OS_WRITE_METHODDEF
14963     OS_WRITEV_METHODDEF
14964     OS_PWRITE_METHODDEF
14965     OS_PWRITEV_METHODDEF
14966     OS_SENDFILE_METHODDEF
14967     OS_FSTAT_METHODDEF
14968     OS_ISATTY_METHODDEF
14969     OS_PIPE_METHODDEF
14970     OS_PIPE2_METHODDEF
14971     OS_MKFIFO_METHODDEF
14972     OS_MKNOD_METHODDEF
14973     OS_MAJOR_METHODDEF
14974     OS_MINOR_METHODDEF
14975     OS_MAKEDEV_METHODDEF
14976     OS_FTRUNCATE_METHODDEF
14977     OS_TRUNCATE_METHODDEF
14978     OS_POSIX_FALLOCATE_METHODDEF
14979     OS_POSIX_FADVISE_METHODDEF
14980     OS_PUTENV_METHODDEF
14981     OS_UNSETENV_METHODDEF
14982     OS_STRERROR_METHODDEF
14983     OS_FCHDIR_METHODDEF
14984     OS_FSYNC_METHODDEF
14985     OS_SYNC_METHODDEF
14986     OS_FDATASYNC_METHODDEF
14987     OS_WCOREDUMP_METHODDEF
14988     OS_WIFCONTINUED_METHODDEF
14989     OS_WIFSTOPPED_METHODDEF
14990     OS_WIFSIGNALED_METHODDEF
14991     OS_WIFEXITED_METHODDEF
14992     OS_WEXITSTATUS_METHODDEF
14993     OS_WTERMSIG_METHODDEF
14994     OS_WSTOPSIG_METHODDEF
14995     OS_FSTATVFS_METHODDEF
14996     OS_STATVFS_METHODDEF
14997     OS_CONFSTR_METHODDEF
14998     OS_SYSCONF_METHODDEF
14999     OS_FPATHCONF_METHODDEF
15000     OS_PATHCONF_METHODDEF
15001     OS_ABORT_METHODDEF
15002     OS__GETFULLPATHNAME_METHODDEF
15003     OS__GETDISKUSAGE_METHODDEF
15004     OS__GETFINALPATHNAME_METHODDEF
15005     OS__GETVOLUMEPATHNAME_METHODDEF
15006     OS__PATH_SPLITROOT_METHODDEF
15007     OS__PATH_NORMPATH_METHODDEF
15008     OS_GETLOADAVG_METHODDEF
15009     OS_URANDOM_METHODDEF
15010     OS_SETRESUID_METHODDEF
15011     OS_SETRESGID_METHODDEF
15012     OS_GETRESUID_METHODDEF
15013     OS_GETRESGID_METHODDEF
15014 
15015     OS_GETXATTR_METHODDEF
15016     OS_SETXATTR_METHODDEF
15017     OS_REMOVEXATTR_METHODDEF
15018     OS_LISTXATTR_METHODDEF
15019 
15020     OS_GET_TERMINAL_SIZE_METHODDEF
15021     OS_CPU_COUNT_METHODDEF
15022     OS_GET_INHERITABLE_METHODDEF
15023     OS_SET_INHERITABLE_METHODDEF
15024     OS_GET_HANDLE_INHERITABLE_METHODDEF
15025     OS_SET_HANDLE_INHERITABLE_METHODDEF
15026     OS_GET_BLOCKING_METHODDEF
15027     OS_SET_BLOCKING_METHODDEF
15028     OS_SCANDIR_METHODDEF
15029     OS_FSPATH_METHODDEF
15030     OS_GETRANDOM_METHODDEF
15031     OS_MEMFD_CREATE_METHODDEF
15032     OS_EVENTFD_METHODDEF
15033     OS_EVENTFD_READ_METHODDEF
15034     OS_EVENTFD_WRITE_METHODDEF
15035     OS__ADD_DLL_DIRECTORY_METHODDEF
15036     OS__REMOVE_DLL_DIRECTORY_METHODDEF
15037     OS_WAITSTATUS_TO_EXITCODE_METHODDEF
15038     {NULL,              NULL}            /* Sentinel */
15039 };
15040 
15041 static int
all_ins(PyObject * m)15042 all_ins(PyObject *m)
15043 {
15044 #ifdef F_OK
15045     if (PyModule_AddIntMacro(m, F_OK)) return -1;
15046 #endif
15047 #ifdef R_OK
15048     if (PyModule_AddIntMacro(m, R_OK)) return -1;
15049 #endif
15050 #ifdef W_OK
15051     if (PyModule_AddIntMacro(m, W_OK)) return -1;
15052 #endif
15053 #ifdef X_OK
15054     if (PyModule_AddIntMacro(m, X_OK)) return -1;
15055 #endif
15056 #ifdef NGROUPS_MAX
15057     if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
15058 #endif
15059 #ifdef TMP_MAX
15060     if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
15061 #endif
15062 #ifdef WCONTINUED
15063     if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
15064 #endif
15065 #ifdef WNOHANG
15066     if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
15067 #endif
15068 #ifdef WUNTRACED
15069     if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
15070 #endif
15071 #ifdef O_RDONLY
15072     if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
15073 #endif
15074 #ifdef O_WRONLY
15075     if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
15076 #endif
15077 #ifdef O_RDWR
15078     if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
15079 #endif
15080 #ifdef O_NDELAY
15081     if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
15082 #endif
15083 #ifdef O_NONBLOCK
15084     if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
15085 #endif
15086 #ifdef O_APPEND
15087     if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
15088 #endif
15089 #ifdef O_DSYNC
15090     if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
15091 #endif
15092 #ifdef O_RSYNC
15093     if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
15094 #endif
15095 #ifdef O_SYNC
15096     if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
15097 #endif
15098 #ifdef O_NOCTTY
15099     if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
15100 #endif
15101 #ifdef O_CREAT
15102     if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
15103 #endif
15104 #ifdef O_EXCL
15105     if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
15106 #endif
15107 #ifdef O_TRUNC
15108     if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
15109 #endif
15110 #ifdef O_BINARY
15111     if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
15112 #endif
15113 #ifdef O_TEXT
15114     if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
15115 #endif
15116 #ifdef O_XATTR
15117     if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
15118 #endif
15119 #ifdef O_LARGEFILE
15120     if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
15121 #endif
15122 #ifndef __GNU__
15123 #ifdef O_SHLOCK
15124     if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
15125 #endif
15126 #ifdef O_EXLOCK
15127     if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
15128 #endif
15129 #endif
15130 #ifdef O_EXEC
15131     if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
15132 #endif
15133 #ifdef O_SEARCH
15134     if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
15135 #endif
15136 #ifdef O_PATH
15137     if (PyModule_AddIntMacro(m, O_PATH)) return -1;
15138 #endif
15139 #ifdef O_TTY_INIT
15140     if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
15141 #endif
15142 #ifdef O_TMPFILE
15143     if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
15144 #endif
15145 #ifdef PRIO_PROCESS
15146     if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
15147 #endif
15148 #ifdef PRIO_PGRP
15149     if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
15150 #endif
15151 #ifdef PRIO_USER
15152     if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
15153 #endif
15154 #ifdef O_CLOEXEC
15155     if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
15156 #endif
15157 #ifdef O_ACCMODE
15158     if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
15159 #endif
15160 #ifdef O_EVTONLY
15161     if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
15162 #endif
15163 #ifdef O_FSYNC
15164     if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
15165 #endif
15166 #ifdef O_SYMLINK
15167     if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
15168 #endif
15169 
15170 #ifdef SEEK_HOLE
15171     if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
15172 #endif
15173 #ifdef SEEK_DATA
15174     if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
15175 #endif
15176 
15177 /* MS Windows */
15178 #ifdef O_NOINHERIT
15179     /* Don't inherit in child processes. */
15180     if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
15181 #endif
15182 #ifdef _O_SHORT_LIVED
15183     /* Optimize for short life (keep in memory). */
15184     /* MS forgot to define this one with a non-underscore form too. */
15185     if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
15186 #endif
15187 #ifdef O_TEMPORARY
15188     /* Automatically delete when last handle is closed. */
15189     if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
15190 #endif
15191 #ifdef O_RANDOM
15192     /* Optimize for random access. */
15193     if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
15194 #endif
15195 #ifdef O_SEQUENTIAL
15196     /* Optimize for sequential access. */
15197     if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
15198 #endif
15199 
15200 /* GNU extensions. */
15201 #ifdef O_ASYNC
15202     /* Send a SIGIO signal whenever input or output
15203        becomes available on file descriptor */
15204     if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
15205 #endif
15206 #ifdef O_DIRECT
15207     /* Direct disk access. */
15208     if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
15209 #endif
15210 #ifdef O_DIRECTORY
15211     /* Must be a directory.      */
15212     if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
15213 #endif
15214 #ifdef O_NOFOLLOW
15215     /* Do not follow links.      */
15216     if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
15217 #endif
15218 #ifdef O_NOFOLLOW_ANY
15219     if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
15220 #endif
15221 #ifdef O_NOLINKS
15222     /* Fails if link count of the named file is greater than 1 */
15223     if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
15224 #endif
15225 #ifdef O_NOATIME
15226     /* Do not update the access time. */
15227     if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
15228 #endif
15229 
15230     /* These come from sysexits.h */
15231 #ifdef EX_OK
15232     if (PyModule_AddIntMacro(m, EX_OK)) return -1;
15233 #endif /* EX_OK */
15234 #ifdef EX_USAGE
15235     if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
15236 #endif /* EX_USAGE */
15237 #ifdef EX_DATAERR
15238     if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
15239 #endif /* EX_DATAERR */
15240 #ifdef EX_NOINPUT
15241     if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
15242 #endif /* EX_NOINPUT */
15243 #ifdef EX_NOUSER
15244     if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
15245 #endif /* EX_NOUSER */
15246 #ifdef EX_NOHOST
15247     if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
15248 #endif /* EX_NOHOST */
15249 #ifdef EX_UNAVAILABLE
15250     if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
15251 #endif /* EX_UNAVAILABLE */
15252 #ifdef EX_SOFTWARE
15253     if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
15254 #endif /* EX_SOFTWARE */
15255 #ifdef EX_OSERR
15256     if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
15257 #endif /* EX_OSERR */
15258 #ifdef EX_OSFILE
15259     if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
15260 #endif /* EX_OSFILE */
15261 #ifdef EX_CANTCREAT
15262     if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
15263 #endif /* EX_CANTCREAT */
15264 #ifdef EX_IOERR
15265     if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
15266 #endif /* EX_IOERR */
15267 #ifdef EX_TEMPFAIL
15268     if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
15269 #endif /* EX_TEMPFAIL */
15270 #ifdef EX_PROTOCOL
15271     if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
15272 #endif /* EX_PROTOCOL */
15273 #ifdef EX_NOPERM
15274     if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
15275 #endif /* EX_NOPERM */
15276 #ifdef EX_CONFIG
15277     if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
15278 #endif /* EX_CONFIG */
15279 #ifdef EX_NOTFOUND
15280     if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
15281 #endif /* EX_NOTFOUND */
15282 
15283     /* statvfs */
15284 #ifdef ST_RDONLY
15285     if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
15286 #endif /* ST_RDONLY */
15287 #ifdef ST_NOSUID
15288     if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
15289 #endif /* ST_NOSUID */
15290 
15291        /* GNU extensions */
15292 #ifdef ST_NODEV
15293     if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
15294 #endif /* ST_NODEV */
15295 #ifdef ST_NOEXEC
15296     if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
15297 #endif /* ST_NOEXEC */
15298 #ifdef ST_SYNCHRONOUS
15299     if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
15300 #endif /* ST_SYNCHRONOUS */
15301 #ifdef ST_MANDLOCK
15302     if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
15303 #endif /* ST_MANDLOCK */
15304 #ifdef ST_WRITE
15305     if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
15306 #endif /* ST_WRITE */
15307 #ifdef ST_APPEND
15308     if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
15309 #endif /* ST_APPEND */
15310 #ifdef ST_NOATIME
15311     if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
15312 #endif /* ST_NOATIME */
15313 #ifdef ST_NODIRATIME
15314     if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
15315 #endif /* ST_NODIRATIME */
15316 #ifdef ST_RELATIME
15317     if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
15318 #endif /* ST_RELATIME */
15319 
15320     /* FreeBSD sendfile() constants */
15321 #ifdef SF_NODISKIO
15322     if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
15323 #endif
15324     /* is obsolete since the 11.x release */
15325 #ifdef SF_MNOWAIT
15326     if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
15327 #endif
15328 #ifdef SF_SYNC
15329     if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
15330 #endif
15331 #ifdef SF_NOCACHE
15332     if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
15333 #endif
15334 
15335     /* constants for posix_fadvise */
15336 #ifdef POSIX_FADV_NORMAL
15337     if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
15338 #endif
15339 #ifdef POSIX_FADV_SEQUENTIAL
15340     if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
15341 #endif
15342 #ifdef POSIX_FADV_RANDOM
15343     if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
15344 #endif
15345 #ifdef POSIX_FADV_NOREUSE
15346     if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
15347 #endif
15348 #ifdef POSIX_FADV_WILLNEED
15349     if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
15350 #endif
15351 #ifdef POSIX_FADV_DONTNEED
15352     if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
15353 #endif
15354 
15355     /* constants for waitid */
15356 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
15357     if (PyModule_AddIntMacro(m, P_PID)) return -1;
15358     if (PyModule_AddIntMacro(m, P_PGID)) return -1;
15359     if (PyModule_AddIntMacro(m, P_ALL)) return -1;
15360 #ifdef P_PIDFD
15361     if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
15362 #endif
15363 #endif
15364 #ifdef WEXITED
15365     if (PyModule_AddIntMacro(m, WEXITED)) return -1;
15366 #endif
15367 #ifdef WNOWAIT
15368     if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
15369 #endif
15370 #ifdef WSTOPPED
15371     if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
15372 #endif
15373 #ifdef CLD_EXITED
15374     if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
15375 #endif
15376 #ifdef CLD_KILLED
15377     if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
15378 #endif
15379 #ifdef CLD_DUMPED
15380     if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
15381 #endif
15382 #ifdef CLD_TRAPPED
15383     if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
15384 #endif
15385 #ifdef CLD_STOPPED
15386     if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
15387 #endif
15388 #ifdef CLD_CONTINUED
15389     if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
15390 #endif
15391 
15392     /* constants for lockf */
15393 #ifdef F_LOCK
15394     if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
15395 #endif
15396 #ifdef F_TLOCK
15397     if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
15398 #endif
15399 #ifdef F_ULOCK
15400     if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
15401 #endif
15402 #ifdef F_TEST
15403     if (PyModule_AddIntMacro(m, F_TEST)) return -1;
15404 #endif
15405 
15406 #ifdef RWF_DSYNC
15407     if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
15408 #endif
15409 #ifdef RWF_HIPRI
15410     if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
15411 #endif
15412 #ifdef RWF_SYNC
15413     if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
15414 #endif
15415 #ifdef RWF_NOWAIT
15416     if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
15417 #endif
15418 #ifdef RWF_APPEND
15419     if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
15420 #endif
15421 
15422 /* constants for splice */
15423 #if defined(HAVE_SPLICE) && defined(__linux__)
15424     if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
15425     if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
15426     if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
15427 #endif
15428 
15429 /* constants for posix_spawn */
15430 #ifdef HAVE_POSIX_SPAWN
15431     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
15432     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
15433     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
15434 #endif
15435 
15436 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
15437     if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
15438     if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
15439     if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
15440 #endif
15441 #ifdef HAVE_SPAWNV
15442     if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
15443     if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
15444 #endif
15445 
15446 #ifdef HAVE_SCHED_H
15447 #ifdef SCHED_OTHER
15448     if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
15449 #endif
15450 #ifdef SCHED_FIFO
15451     if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
15452 #endif
15453 #ifdef SCHED_RR
15454     if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
15455 #endif
15456 #ifdef SCHED_SPORADIC
15457     if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
15458 #endif
15459 #ifdef SCHED_BATCH
15460     if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
15461 #endif
15462 #ifdef SCHED_IDLE
15463     if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
15464 #endif
15465 #ifdef SCHED_RESET_ON_FORK
15466     if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
15467 #endif
15468 #ifdef SCHED_SYS
15469     if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
15470 #endif
15471 #ifdef SCHED_IA
15472     if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
15473 #endif
15474 #ifdef SCHED_FSS
15475     if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
15476 #endif
15477 #ifdef SCHED_FX
15478     if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
15479 #endif
15480 #endif
15481 
15482 #ifdef USE_XATTRS
15483     if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
15484     if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
15485     if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
15486 #endif
15487 
15488 #if HAVE_DECL_RTLD_LAZY
15489     if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
15490 #endif
15491 #if HAVE_DECL_RTLD_NOW
15492     if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
15493 #endif
15494 #if HAVE_DECL_RTLD_GLOBAL
15495     if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
15496 #endif
15497 #if HAVE_DECL_RTLD_LOCAL
15498     if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
15499 #endif
15500 #if HAVE_DECL_RTLD_NODELETE
15501     if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
15502 #endif
15503 #if HAVE_DECL_RTLD_NOLOAD
15504     if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
15505 #endif
15506 #if HAVE_DECL_RTLD_DEEPBIND
15507     if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
15508 #endif
15509 #if HAVE_DECL_RTLD_MEMBER
15510     if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
15511 #endif
15512 
15513 #ifdef HAVE_GETRANDOM_SYSCALL
15514     if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
15515     if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
15516 #endif
15517 #ifdef HAVE_MEMFD_CREATE
15518     if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
15519     if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
15520 #ifdef MFD_HUGETLB
15521     if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
15522 #endif
15523 #ifdef MFD_HUGE_SHIFT
15524     if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
15525 #endif
15526 #ifdef MFD_HUGE_MASK
15527     if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
15528 #endif
15529 #ifdef MFD_HUGE_64KB
15530     if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
15531 #endif
15532 #ifdef MFD_HUGE_512KB
15533     if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
15534 #endif
15535 #ifdef MFD_HUGE_1MB
15536     if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
15537 #endif
15538 #ifdef MFD_HUGE_2MB
15539     if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
15540 #endif
15541 #ifdef MFD_HUGE_8MB
15542     if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
15543 #endif
15544 #ifdef MFD_HUGE_16MB
15545     if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
15546 #endif
15547 #ifdef MFD_HUGE_32MB
15548     if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
15549 #endif
15550 #ifdef MFD_HUGE_256MB
15551     if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
15552 #endif
15553 #ifdef MFD_HUGE_512MB
15554     if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
15555 #endif
15556 #ifdef MFD_HUGE_1GB
15557     if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
15558 #endif
15559 #ifdef MFD_HUGE_2GB
15560     if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
15561 #endif
15562 #ifdef MFD_HUGE_16GB
15563     if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
15564 #endif
15565 #endif /* HAVE_MEMFD_CREATE */
15566 
15567 #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15568     if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
15569 #ifdef EFD_NONBLOCK
15570     if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
15571 #endif
15572 #ifdef EFD_SEMAPHORE
15573     if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
15574 #endif
15575 #endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15576 
15577 #if defined(__APPLE__)
15578     if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
15579     if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
15580     if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
15581     if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
15582 #endif
15583 
15584 #ifdef MS_WINDOWS
15585     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
15586     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
15587     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
15588     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
15589     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
15590 #endif
15591 
15592     return 0;
15593 }
15594 
15595 
15596 
15597 #define PROBE(name, test) \
15598    static int name(void)  \
15599    {                      \
15600       if (test) {        \
15601           return 1;       \
15602       } else {            \
15603           return 0;       \
15604       }                   \
15605    }
15606 
15607 #ifdef HAVE_FSTATAT
15608 PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
15609 #endif
15610 
15611 #ifdef HAVE_FACCESSAT
15612 PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
15613 #endif
15614 
15615 #ifdef HAVE_FCHMODAT
15616 PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
15617 #endif
15618 
15619 #ifdef HAVE_FCHOWNAT
15620 PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
15621 #endif
15622 
15623 #ifdef HAVE_LINKAT
15624 PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
15625 #endif
15626 
15627 #ifdef HAVE_FDOPENDIR
15628 PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
15629 #endif
15630 
15631 #ifdef HAVE_MKDIRAT
15632 PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
15633 #endif
15634 
15635 #ifdef HAVE_MKFIFOAT
15636 PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
15637 #endif
15638 
15639 #ifdef HAVE_MKNODAT
15640 PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
15641 #endif
15642 
15643 #ifdef HAVE_RENAMEAT
15644 PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
15645 #endif
15646 
15647 #ifdef HAVE_UNLINKAT
15648 PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
15649 #endif
15650 
15651 #ifdef HAVE_OPENAT
15652 PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
15653 #endif
15654 
15655 #ifdef HAVE_READLINKAT
15656 PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
15657 #endif
15658 
15659 #ifdef HAVE_SYMLINKAT
15660 PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
15661 #endif
15662 
15663 #ifdef HAVE_FUTIMENS
15664 PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
15665 #endif
15666 
15667 #ifdef HAVE_UTIMENSAT
15668 PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
15669 #endif
15670 
15671 
15672 
15673 
15674 static const struct have_function {
15675     const char * const label;
15676     int (*probe)(void);
15677 } have_functions[] = {
15678 
15679 #ifdef HAVE_EVENTFD
15680     {"HAVE_EVENTFD", NULL},
15681 #endif
15682 
15683 #ifdef HAVE_FACCESSAT
15684     { "HAVE_FACCESSAT", probe_faccessat },
15685 #endif
15686 
15687 #ifdef HAVE_FCHDIR
15688     { "HAVE_FCHDIR", NULL },
15689 #endif
15690 
15691 #ifdef HAVE_FCHMOD
15692     { "HAVE_FCHMOD", NULL },
15693 #endif
15694 
15695 #ifdef HAVE_FCHMODAT
15696     { "HAVE_FCHMODAT", probe_fchmodat },
15697 #endif
15698 
15699 #ifdef HAVE_FCHOWN
15700     { "HAVE_FCHOWN", NULL },
15701 #endif
15702 
15703 #ifdef HAVE_FCHOWNAT
15704     { "HAVE_FCHOWNAT", probe_fchownat },
15705 #endif
15706 
15707 #ifdef HAVE_FEXECVE
15708     { "HAVE_FEXECVE", NULL },
15709 #endif
15710 
15711 #ifdef HAVE_FDOPENDIR
15712     { "HAVE_FDOPENDIR", probe_fdopendir },
15713 #endif
15714 
15715 #ifdef HAVE_FPATHCONF
15716     { "HAVE_FPATHCONF", NULL },
15717 #endif
15718 
15719 #ifdef HAVE_FSTATAT
15720     { "HAVE_FSTATAT", probe_fstatat },
15721 #endif
15722 
15723 #ifdef HAVE_FSTATVFS
15724     { "HAVE_FSTATVFS", NULL },
15725 #endif
15726 
15727 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
15728     { "HAVE_FTRUNCATE", NULL },
15729 #endif
15730 
15731 #ifdef HAVE_FUTIMENS
15732     { "HAVE_FUTIMENS", probe_futimens },
15733 #endif
15734 
15735 #ifdef HAVE_FUTIMES
15736     { "HAVE_FUTIMES", NULL },
15737 #endif
15738 
15739 #ifdef HAVE_FUTIMESAT
15740     { "HAVE_FUTIMESAT", NULL },
15741 #endif
15742 
15743 #ifdef HAVE_LINKAT
15744     { "HAVE_LINKAT", probe_linkat },
15745 #endif
15746 
15747 #ifdef HAVE_LCHFLAGS
15748     { "HAVE_LCHFLAGS", NULL },
15749 #endif
15750 
15751 #ifdef HAVE_LCHMOD
15752     { "HAVE_LCHMOD", NULL },
15753 #endif
15754 
15755 #ifdef HAVE_LCHOWN
15756     { "HAVE_LCHOWN", NULL },
15757 #endif
15758 
15759 #ifdef HAVE_LSTAT
15760     { "HAVE_LSTAT", NULL },
15761 #endif
15762 
15763 #ifdef HAVE_LUTIMES
15764     { "HAVE_LUTIMES", NULL },
15765 #endif
15766 
15767 #ifdef HAVE_MEMFD_CREATE
15768     { "HAVE_MEMFD_CREATE", NULL },
15769 #endif
15770 
15771 #ifdef HAVE_MKDIRAT
15772     { "HAVE_MKDIRAT", probe_mkdirat },
15773 #endif
15774 
15775 #ifdef HAVE_MKFIFOAT
15776     { "HAVE_MKFIFOAT", probe_mkfifoat },
15777 #endif
15778 
15779 #ifdef HAVE_MKNODAT
15780     { "HAVE_MKNODAT", probe_mknodat },
15781 #endif
15782 
15783 #ifdef HAVE_OPENAT
15784     { "HAVE_OPENAT", probe_openat },
15785 #endif
15786 
15787 #ifdef HAVE_READLINKAT
15788     { "HAVE_READLINKAT", probe_readlinkat },
15789 #endif
15790 
15791 #ifdef HAVE_RENAMEAT
15792     { "HAVE_RENAMEAT", probe_renameat },
15793 #endif
15794 
15795 #ifdef HAVE_SYMLINKAT
15796     { "HAVE_SYMLINKAT", probe_symlinkat },
15797 #endif
15798 
15799 #ifdef HAVE_UNLINKAT
15800     { "HAVE_UNLINKAT", probe_unlinkat },
15801 #endif
15802 
15803 #ifdef HAVE_UTIMENSAT
15804     { "HAVE_UTIMENSAT", probe_utimensat },
15805 #endif
15806 
15807 #ifdef MS_WINDOWS
15808     { "MS_WINDOWS", NULL },
15809 #endif
15810 
15811     { NULL, NULL }
15812 };
15813 
15814 
15815 static int
posixmodule_exec(PyObject * m)15816 posixmodule_exec(PyObject *m)
15817 {
15818     _posixstate *state = get_posix_state(m);
15819 
15820 #if defined(HAVE_PWRITEV)
15821     if (HAVE_PWRITEV_RUNTIME) {} else {
15822         PyObject* dct = PyModule_GetDict(m);
15823 
15824         if (dct == NULL) {
15825             return -1;
15826         }
15827 
15828         if (PyDict_DelItemString(dct, "pwritev") == -1) {
15829             PyErr_Clear();
15830         }
15831         if (PyDict_DelItemString(dct, "preadv") == -1) {
15832             PyErr_Clear();
15833         }
15834     }
15835 #endif
15836 
15837     /* Initialize environ dictionary */
15838     PyObject *v = convertenviron();
15839     Py_XINCREF(v);
15840     if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
15841         return -1;
15842     Py_DECREF(v);
15843 
15844     if (all_ins(m))
15845         return -1;
15846 
15847     if (setup_confname_tables(m))
15848         return -1;
15849 
15850     Py_INCREF(PyExc_OSError);
15851     PyModule_AddObject(m, "error", PyExc_OSError);
15852 
15853 #if defined(HAVE_WAITID) && !defined(__APPLE__)
15854     waitid_result_desc.name = MODNAME ".waitid_result";
15855     PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
15856     if (WaitidResultType == NULL) {
15857         return -1;
15858     }
15859     Py_INCREF(WaitidResultType);
15860     PyModule_AddObject(m, "waitid_result", WaitidResultType);
15861     state->WaitidResultType = WaitidResultType;
15862 #endif
15863 
15864     stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
15865     stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
15866     stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
15867     stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
15868     PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
15869     if (StatResultType == NULL) {
15870         return -1;
15871     }
15872     Py_INCREF(StatResultType);
15873     PyModule_AddObject(m, "stat_result", StatResultType);
15874     state->StatResultType = StatResultType;
15875     structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15876     ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
15877 
15878     statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
15879     PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
15880     if (StatVFSResultType == NULL) {
15881         return -1;
15882     }
15883     Py_INCREF(StatVFSResultType);
15884     PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
15885     state->StatVFSResultType = StatVFSResultType;
15886 #ifdef NEED_TICKS_PER_SECOND
15887 #  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15888     ticks_per_second = sysconf(_SC_CLK_TCK);
15889 #  elif defined(HZ)
15890     ticks_per_second = HZ;
15891 #  else
15892     ticks_per_second = 60; /* magic fallback value; may be bogus */
15893 #  endif
15894 #endif
15895 
15896 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
15897     sched_param_desc.name = MODNAME ".sched_param";
15898     PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
15899     if (SchedParamType == NULL) {
15900         return -1;
15901     }
15902     Py_INCREF(SchedParamType);
15903     PyModule_AddObject(m, "sched_param", SchedParamType);
15904     state->SchedParamType = SchedParamType;
15905     ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
15906 #endif
15907 
15908     /* initialize TerminalSize_info */
15909     PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
15910     if (TerminalSizeType == NULL) {
15911         return -1;
15912     }
15913     Py_INCREF(TerminalSizeType);
15914     PyModule_AddObject(m, "terminal_size", TerminalSizeType);
15915     state->TerminalSizeType = TerminalSizeType;
15916 
15917     /* initialize scandir types */
15918     PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
15919     if (ScandirIteratorType == NULL) {
15920         return -1;
15921     }
15922     state->ScandirIteratorType = ScandirIteratorType;
15923 
15924     PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
15925     if (DirEntryType == NULL) {
15926         return -1;
15927     }
15928     Py_INCREF(DirEntryType);
15929     PyModule_AddObject(m, "DirEntry", DirEntryType);
15930     state->DirEntryType = DirEntryType;
15931 
15932     times_result_desc.name = MODNAME ".times_result";
15933     PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
15934     if (TimesResultType == NULL) {
15935         return -1;
15936     }
15937     Py_INCREF(TimesResultType);
15938     PyModule_AddObject(m, "times_result", TimesResultType);
15939     state->TimesResultType = TimesResultType;
15940 
15941     PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
15942     if (UnameResultType == NULL) {
15943         return -1;
15944     }
15945     Py_INCREF(UnameResultType);
15946     PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
15947     state->UnameResultType = (PyObject *)UnameResultType;
15948 
15949     if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
15950         return -1;
15951 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
15952     state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
15953     if (state->struct_rusage == NULL)
15954         return -1;
15955 #endif
15956     state->st_mode = PyUnicode_InternFromString("st_mode");
15957     if (state->st_mode == NULL)
15958         return -1;
15959 
15960     /* suppress "function not used" warnings */
15961     {
15962     int ignored;
15963     fd_specified("", -1);
15964     follow_symlinks_specified("", 1);
15965     dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
15966     dir_fd_converter(Py_None, &ignored);
15967     dir_fd_unavailable(Py_None, &ignored);
15968     }
15969 
15970     /*
15971      * provide list of locally available functions
15972      * so os.py can populate support_* lists
15973      */
15974     PyObject *list = PyList_New(0);
15975     if (!list) {
15976         return -1;
15977     }
15978     for (const struct have_function *trace = have_functions; trace->label; trace++) {
15979         PyObject *unicode;
15980         if (trace->probe && !trace->probe()) continue;
15981         unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
15982         if (!unicode)
15983             return -1;
15984         if (PyList_Append(list, unicode))
15985             return -1;
15986         Py_DECREF(unicode);
15987     }
15988 
15989     PyModule_AddObject(m, "_have_functions", list);
15990 
15991     return 0;
15992 }
15993 
15994 
15995 static PyModuleDef_Slot posixmodile_slots[] = {
15996     {Py_mod_exec, posixmodule_exec},
15997     {0, NULL}
15998 };
15999 
16000 static struct PyModuleDef posixmodule = {
16001     PyModuleDef_HEAD_INIT,
16002     .m_name = MODNAME,
16003     .m_doc = posix__doc__,
16004     .m_size = sizeof(_posixstate),
16005     .m_methods = posix_methods,
16006     .m_slots = posixmodile_slots,
16007     .m_traverse = _posix_traverse,
16008     .m_clear = _posix_clear,
16009     .m_free = _posix_free,
16010 };
16011 
16012 PyMODINIT_FUNC
INITFUNC(void)16013 INITFUNC(void)
16014 {
16015     return PyModuleDef_Init(&posixmodule);
16016 }
16017 
16018 #ifdef __cplusplus
16019 }
16020 #endif
16021