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 #endif
20 
21 #ifdef __VXWORKS__
22 #  include "pycore_bitutils.h"    // _Py_popcount32()
23 #endif
24 #include "pycore_call.h"          // _PyObject_CallNoArgs()
25 #include "pycore_fileutils.h"     // _Py_closerange()
26 #include "pycore_moduleobject.h"  // _PyModule_GetState()
27 #include "pycore_ceval.h"         // _PyEval_ReInitThreads()
28 #include "pycore_import.h"        // _PyImport_ReInitLock()
29 #include "pycore_initconfig.h"    // _PyStatus_EXCEPTION()
30 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
31 
32 #include "structmember.h"         // PyMemberDef
33 #ifndef MS_WINDOWS
34 #  include "posixmodule.h"
35 #else
36 #  include "winreparse.h"
37 #endif
38 
39 #if !defined(EX_OK) && defined(EXIT_SUCCESS)
40 #  define EX_OK EXIT_SUCCESS
41 #endif
42 
43 /* On android API level 21, 'AT_EACCESS' is not declared although
44  * HAVE_FACCESSAT is defined. */
45 #ifdef __ANDROID__
46 #  undef HAVE_FACCESSAT
47 #endif
48 
49 #include <stdio.h>                // ctermid()
50 #include <stdlib.h>               // system()
51 
52 /*
53  * A number of APIs are available on macOS from a certain macOS version.
54  * To support building with a new SDK while deploying to older versions
55  * the availability test is split into two:
56  *   - HAVE_<FUNCTION>:  The configure check for compile time availability
57  *   - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
58  *
59  * The latter is always true when not on macOS, or when using a compiler
60  * that does not support __has_builtin (older versions of Xcode).
61  *
62  * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
63  *    if (HAVE_<FUNCTION>_RUNTIME) { ... }
64  *
65  * In mixing the test with other tests or using negations will result in compile
66  * errors.
67  */
68 #if defined(__APPLE__)
69 
70 #if defined(__has_builtin)
71 #if __has_builtin(__builtin_available)
72 #define HAVE_BUILTIN_AVAILABLE 1
73 #endif
74 #endif
75 
76 #ifdef HAVE_BUILTIN_AVAILABLE
77 #  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
78 #  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
79 #  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
80 #  define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
81 #  define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
82 #  define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
83 #  define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
84 #  define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
85 #  define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
86 #  define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
87 #  define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
88 #  define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
89 #  define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
90 #  define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
91 #  define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
92 
93 #  define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
94 
95 #else /* Xcode 8 or earlier */
96 
97    /* __builtin_available is not present in these compilers, but
98     * some of the symbols might be weak linked (10.10 SDK or later
99     * deploying on 10.9.
100     *
101     * Fall back to the older style of availability checking for
102     * symbols introduced in macOS 10.10.
103     */
104 
105 #  ifdef HAVE_FSTATAT
106 #    define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
107 #  endif
108 
109 #  ifdef HAVE_FACCESSAT
110 #    define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
111 #  endif
112 
113 #  ifdef HAVE_FCHMODAT
114 #    define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
115 #  endif
116 
117 #  ifdef HAVE_FCHOWNAT
118 #    define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
119 #  endif
120 
121 #  ifdef HAVE_LINKAT
122 #    define HAVE_LINKAT_RUNTIME (linkat != NULL)
123 #  endif
124 
125 #  ifdef HAVE_FDOPENDIR
126 #    define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
127 #  endif
128 
129 #  ifdef HAVE_MKDIRAT
130 #    define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
131 #  endif
132 
133 #  ifdef HAVE_RENAMEAT
134 #    define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
135 #  endif
136 
137 #  ifdef HAVE_UNLINKAT
138 #    define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
139 #  endif
140 
141 #  ifdef HAVE_OPENAT
142 #    define HAVE_OPENAT_RUNTIME (openat != NULL)
143 #  endif
144 
145 #  ifdef HAVE_READLINKAT
146 #    define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
147 #  endif
148 
149 #  ifdef HAVE_SYMLINKAT
150 #    define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
151 #  endif
152 
153 #endif
154 
155 #ifdef HAVE_FUTIMESAT
156 /* Some of the logic for weak linking depends on this assertion */
157 # error "HAVE_FUTIMESAT unexpectedly defined"
158 #endif
159 
160 #else
161 #  define HAVE_FSTATAT_RUNTIME 1
162 #  define HAVE_FACCESSAT_RUNTIME 1
163 #  define HAVE_FCHMODAT_RUNTIME 1
164 #  define HAVE_FCHOWNAT_RUNTIME 1
165 #  define HAVE_LINKAT_RUNTIME 1
166 #  define HAVE_FDOPENDIR_RUNTIME 1
167 #  define HAVE_MKDIRAT_RUNTIME 1
168 #  define HAVE_RENAMEAT_RUNTIME 1
169 #  define HAVE_UNLINKAT_RUNTIME 1
170 #  define HAVE_OPENAT_RUNTIME 1
171 #  define HAVE_READLINKAT_RUNTIME 1
172 #  define HAVE_SYMLINKAT_RUNTIME 1
173 #  define HAVE_FUTIMENS_RUNTIME 1
174 #  define HAVE_UTIMENSAT_RUNTIME 1
175 #  define HAVE_PWRITEV_RUNTIME 1
176 #endif
177 
178 
179 #ifdef __cplusplus
180 extern "C" {
181 #endif
182 
183 PyDoc_STRVAR(posix__doc__,
184 "This module provides access to operating system functionality that is\n\
185 standardized by the C Standard and the POSIX standard (a thinly\n\
186 disguised Unix interface).  Refer to the library manual and\n\
187 corresponding Unix manual entries for more information on calls.");
188 
189 
190 #ifdef HAVE_SYS_UIO_H
191 #  include <sys/uio.h>
192 #endif
193 
194 #ifdef HAVE_SYS_SYSMACROS_H
195 /* GNU C Library: major(), minor(), makedev() */
196 #  include <sys/sysmacros.h>
197 #endif
198 
199 #ifdef HAVE_SYS_TYPES_H
200 #  include <sys/types.h>
201 #endif /* HAVE_SYS_TYPES_H */
202 
203 #ifdef HAVE_SYS_STAT_H
204 #  include <sys/stat.h>
205 #endif /* HAVE_SYS_STAT_H */
206 
207 #ifdef HAVE_SYS_WAIT_H
208 #  include <sys/wait.h>           // WNOHANG
209 #endif
210 #ifdef HAVE_LINUX_WAIT_H
211 #  include <linux/wait.h>         // P_PIDFD
212 #endif
213 
214 #ifdef HAVE_SIGNAL_H
215 #  include <signal.h>
216 #endif
217 
218 #ifdef HAVE_FCNTL_H
219 #  include <fcntl.h>
220 #endif
221 
222 #ifdef HAVE_GRP_H
223 #  include <grp.h>
224 #endif
225 
226 #ifdef HAVE_SYSEXITS_H
227 #  include <sysexits.h>
228 #endif
229 
230 #ifdef HAVE_SYS_LOADAVG_H
231 #  include <sys/loadavg.h>
232 #endif
233 
234 #ifdef HAVE_SYS_SENDFILE_H
235 #  include <sys/sendfile.h>
236 #endif
237 
238 #if defined(__APPLE__)
239 #  include <copyfile.h>
240 #endif
241 
242 #ifdef HAVE_SCHED_H
243 #  include <sched.h>
244 #endif
245 
246 #ifdef HAVE_COPY_FILE_RANGE
247 #  include <unistd.h>
248 #endif
249 
250 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
251 #  undef HAVE_SCHED_SETAFFINITY
252 #endif
253 
254 #if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
255 #  define USE_XATTRS
256 #endif
257 
258 #ifdef USE_XATTRS
259 #  include <sys/xattr.h>
260 #endif
261 
262 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
263 #  ifdef HAVE_SYS_SOCKET_H
264 #    include <sys/socket.h>
265 #  endif
266 #endif
267 
268 #ifdef HAVE_DLFCN_H
269 #  include <dlfcn.h>
270 #endif
271 
272 #ifdef __hpux
273 #  include <sys/mpctl.h>
274 #endif
275 
276 #if defined(__DragonFly__) || \
277     defined(__OpenBSD__)   || \
278     defined(__FreeBSD__)   || \
279     defined(__NetBSD__)    || \
280     defined(__APPLE__)
281 #  include <sys/sysctl.h>
282 #endif
283 
284 #ifdef HAVE_LINUX_RANDOM_H
285 #  include <linux/random.h>
286 #endif
287 #ifdef HAVE_GETRANDOM_SYSCALL
288 #  include <sys/syscall.h>
289 #endif
290 
291 #if defined(MS_WINDOWS)
292 #  define TERMSIZE_USE_CONIO
293 #elif defined(HAVE_SYS_IOCTL_H)
294 #  include <sys/ioctl.h>
295 #  if defined(HAVE_TERMIOS_H)
296 #    include <termios.h>
297 #  endif
298 #  if defined(TIOCGWINSZ)
299 #    define TERMSIZE_USE_IOCTL
300 #  endif
301 #endif /* MS_WINDOWS */
302 
303 /* Various compilers have only certain posix functions */
304 /* XXX Gosh I wish these were all moved into pyconfig.h */
305 #if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
306 #  define HAVE_OPENDIR    1
307 #  define HAVE_SYSTEM     1
308 #  include <process.h>
309 #else
310 #  ifdef _MSC_VER
311      /* Microsoft compiler */
312 #    define HAVE_GETPPID    1
313 #    define HAVE_GETLOGIN   1
314 #    define HAVE_SPAWNV     1
315 #    define HAVE_EXECV      1
316 #    define HAVE_WSPAWNV    1
317 #    define HAVE_WEXECV     1
318 #    define HAVE_PIPE       1
319 #    define HAVE_SYSTEM     1
320 #    define HAVE_CWAIT      1
321 #    define HAVE_FSYNC      1
322 #    define fsync _commit
323 #  endif  /* _MSC_VER */
324 #endif  /* ! __WATCOMC__ || __QNX__ */
325 
326 _Py_IDENTIFIER(__fspath__);
327 
328 /*[clinic input]
329 # one of the few times we lie about this name!
330 module os
331 [clinic start generated code]*/
332 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
333 
334 #ifndef _MSC_VER
335 
336 #if defined(__sgi)&&_COMPILER_VERSION>=700
337 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
338    (default) */
339 extern char        *ctermid_r(char *);
340 #endif
341 
342 #endif /* !_MSC_VER */
343 
344 #if defined(__VXWORKS__)
345 #  include <vxCpuLib.h>
346 #  include <rtpLib.h>
347 #  include <wait.h>
348 #  include <taskLib.h>
349 #  ifndef _P_WAIT
350 #    define _P_WAIT          0
351 #    define _P_NOWAIT        1
352 #    define _P_NOWAITO       1
353 #  endif
354 #endif /* __VXWORKS__ */
355 
356 #ifdef HAVE_POSIX_SPAWN
357 #  include <spawn.h>
358 #endif
359 
360 #ifdef HAVE_UTIME_H
361 #  include <utime.h>
362 #endif /* HAVE_UTIME_H */
363 
364 #ifdef HAVE_SYS_UTIME_H
365 #  include <sys/utime.h>
366 #  define HAVE_UTIME_H /* pretend we do for the rest of this file */
367 #endif /* HAVE_SYS_UTIME_H */
368 
369 #ifdef HAVE_SYS_TIMES_H
370 #  include <sys/times.h>
371 #endif /* HAVE_SYS_TIMES_H */
372 
373 #ifdef HAVE_SYS_PARAM_H
374 #  include <sys/param.h>
375 #endif /* HAVE_SYS_PARAM_H */
376 
377 #ifdef HAVE_SYS_UTSNAME_H
378 #  include <sys/utsname.h>
379 #endif /* HAVE_SYS_UTSNAME_H */
380 
381 #ifdef HAVE_DIRENT_H
382 #  include <dirent.h>
383 #  define NAMLEN(dirent) strlen((dirent)->d_name)
384 #else
385 #  if defined(__WATCOMC__) && !defined(__QNX__)
386 #    include <direct.h>
387 #    define NAMLEN(dirent) strlen((dirent)->d_name)
388 #  else
389 #    define dirent direct
390 #    define NAMLEN(dirent) (dirent)->d_namlen
391 #  endif
392 #  ifdef HAVE_SYS_NDIR_H
393 #    include <sys/ndir.h>
394 #  endif
395 #  ifdef HAVE_SYS_DIR_H
396 #    include <sys/dir.h>
397 #  endif
398 #  ifdef HAVE_NDIR_H
399 #    include <ndir.h>
400 #  endif
401 #endif
402 
403 #ifdef _MSC_VER
404 #  ifdef HAVE_DIRECT_H
405 #    include <direct.h>
406 #  endif
407 #  ifdef HAVE_IO_H
408 #    include <io.h>
409 #  endif
410 #  ifdef HAVE_PROCESS_H
411 #    include <process.h>
412 #  endif
413 #  ifndef IO_REPARSE_TAG_SYMLINK
414 #    define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
415 #  endif
416 #  ifndef IO_REPARSE_TAG_MOUNT_POINT
417 #    define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
418 #  endif
419 #  include "osdefs.h"             // SEP
420 #  include <malloc.h>
421 #  include <windows.h>
422 #  include <shellapi.h>           // ShellExecute()
423 #  include <lmcons.h>             // UNLEN
424 #  define HAVE_SYMLINK
425 #endif /* _MSC_VER */
426 
427 #ifndef MAXPATHLEN
428 #  if defined(PATH_MAX) && PATH_MAX > 1024
429 #    define MAXPATHLEN PATH_MAX
430 #  else
431 #    define MAXPATHLEN 1024
432 #  endif
433 #endif /* MAXPATHLEN */
434 
435 #ifdef UNION_WAIT
436    /* Emulate some macros on systems that have a union instead of macros */
437 #  ifndef WIFEXITED
438 #    define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
439 #  endif
440 #  ifndef WEXITSTATUS
441 #    define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
442 #  endif
443 #  ifndef WTERMSIG
444 #    define WTERMSIG(u_wait) ((u_wait).w_termsig)
445 #  endif
446 #  define WAIT_TYPE union wait
447 #  define WAIT_STATUS_INT(s) (s.w_status)
448 #else
449    /* !UNION_WAIT */
450 #  define WAIT_TYPE int
451 #  define WAIT_STATUS_INT(s) (s)
452 #endif /* UNION_WAIT */
453 
454 /* Don't use the "_r" form if we don't need it (also, won't have a
455    prototype for it, at least on Solaris -- maybe others as well?). */
456 #if defined(HAVE_CTERMID_R)
457 #  define USE_CTERMID_R
458 #endif
459 
460 /* choose the appropriate stat and fstat functions and return structs */
461 #undef STAT
462 #undef FSTAT
463 #undef STRUCT_STAT
464 #ifdef MS_WINDOWS
465 #  define STAT win32_stat
466 #  define LSTAT win32_lstat
467 #  define FSTAT _Py_fstat_noraise
468 #  define STRUCT_STAT struct _Py_stat_struct
469 #else
470 #  define STAT stat
471 #  define LSTAT lstat
472 #  define FSTAT fstat
473 #  define STRUCT_STAT struct stat
474 #endif
475 
476 #if defined(MAJOR_IN_MKDEV)
477 #  include <sys/mkdev.h>
478 #else
479 #  if defined(MAJOR_IN_SYSMACROS)
480 #    include <sys/sysmacros.h>
481 #  endif
482 #  if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
483 #    include <sys/mkdev.h>
484 #  endif
485 #endif
486 
487 #ifdef MS_WINDOWS
488 #  define INITFUNC PyInit_nt
489 #  define MODNAME "nt"
490 #else
491 #  define INITFUNC PyInit_posix
492 #  define MODNAME "posix"
493 #endif
494 
495 #if defined(__sun)
496 /* Something to implement in autoconf, not present in autoconf 2.69 */
497 #  define HAVE_STRUCT_STAT_ST_FSTYPE 1
498 #endif
499 
500 /* memfd_create is either defined in sys/mman.h or sys/memfd.h
501  * linux/memfd.h defines additional flags
502  */
503 #ifdef HAVE_SYS_MMAN_H
504 #  include <sys/mman.h>
505 #endif
506 #ifdef HAVE_SYS_MEMFD_H
507 #  include <sys/memfd.h>
508 #endif
509 #ifdef HAVE_LINUX_MEMFD_H
510 #  include <linux/memfd.h>
511 #endif
512 
513 /* eventfd() */
514 #ifdef HAVE_SYS_EVENTFD_H
515 #  include <sys/eventfd.h>
516 #endif
517 
518 #ifdef _Py_MEMORY_SANITIZER
519 #  include <sanitizer/msan_interface.h>
520 #endif
521 
522 #ifdef HAVE_FORK
523 static void
run_at_forkers(PyObject * lst,int reverse)524 run_at_forkers(PyObject *lst, int reverse)
525 {
526     Py_ssize_t i;
527     PyObject *cpy;
528 
529     if (lst != NULL) {
530         assert(PyList_CheckExact(lst));
531 
532         /* Use a list copy in case register_at_fork() is called from
533          * one of the callbacks.
534          */
535         cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
536         if (cpy == NULL)
537             PyErr_WriteUnraisable(lst);
538         else {
539             if (reverse)
540                 PyList_Reverse(cpy);
541             for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
542                 PyObject *func, *res;
543                 func = PyList_GET_ITEM(cpy, i);
544                 res = _PyObject_CallNoArgs(func);
545                 if (res == NULL)
546                     PyErr_WriteUnraisable(func);
547                 else
548                     Py_DECREF(res);
549             }
550             Py_DECREF(cpy);
551         }
552     }
553 }
554 
555 void
PyOS_BeforeFork(void)556 PyOS_BeforeFork(void)
557 {
558     run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1);
559 
560     _PyImport_AcquireLock();
561 }
562 
563 void
PyOS_AfterFork_Parent(void)564 PyOS_AfterFork_Parent(void)
565 {
566     if (_PyImport_ReleaseLock() <= 0)
567         Py_FatalError("failed releasing import lock after fork");
568 
569     run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0);
570 }
571 
572 void
PyOS_AfterFork_Child(void)573 PyOS_AfterFork_Child(void)
574 {
575     PyStatus status;
576     _PyRuntimeState *runtime = &_PyRuntime;
577 
578     status = _PyGILState_Reinit(runtime);
579     if (_PyStatus_EXCEPTION(status)) {
580         goto fatal_error;
581     }
582 
583     PyThreadState *tstate = _PyThreadState_GET();
584     _Py_EnsureTstateNotNULL(tstate);
585 
586     status = _PyEval_ReInitThreads(tstate);
587     if (_PyStatus_EXCEPTION(status)) {
588         goto fatal_error;
589     }
590 
591     status = _PyImport_ReInitLock();
592     if (_PyStatus_EXCEPTION(status)) {
593         goto fatal_error;
594     }
595 
596     _PySignal_AfterFork();
597 
598     status = _PyRuntimeState_ReInitThreads(runtime);
599     if (_PyStatus_EXCEPTION(status)) {
600         goto fatal_error;
601     }
602 
603     status = _PyInterpreterState_DeleteExceptMain(runtime);
604     if (_PyStatus_EXCEPTION(status)) {
605         goto fatal_error;
606     }
607     assert(_PyThreadState_GET() == tstate);
608 
609     run_at_forkers(tstate->interp->after_forkers_child, 0);
610     return;
611 
612 fatal_error:
613     Py_ExitStatusException(status);
614 }
615 
616 static int
register_at_forker(PyObject ** lst,PyObject * func)617 register_at_forker(PyObject **lst, PyObject *func)
618 {
619     if (func == NULL)  /* nothing to register? do nothing. */
620         return 0;
621     if (*lst == NULL) {
622         *lst = PyList_New(0);
623         if (*lst == NULL)
624             return -1;
625     }
626     return PyList_Append(*lst, func);
627 }
628 #endif  /* HAVE_FORK */
629 
630 
631 /* Legacy wrapper */
632 void
PyOS_AfterFork(void)633 PyOS_AfterFork(void)
634 {
635 #ifdef HAVE_FORK
636     PyOS_AfterFork_Child();
637 #endif
638 }
639 
640 
641 #ifdef MS_WINDOWS
642 /* defined in fileutils.c */
643 void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
644 void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
645                                             ULONG, struct _Py_stat_struct *);
646 #endif
647 
648 
649 #ifndef MS_WINDOWS
650 PyObject *
_PyLong_FromUid(uid_t uid)651 _PyLong_FromUid(uid_t uid)
652 {
653     if (uid == (uid_t)-1)
654         return PyLong_FromLong(-1);
655     return PyLong_FromUnsignedLong(uid);
656 }
657 
658 PyObject *
_PyLong_FromGid(gid_t gid)659 _PyLong_FromGid(gid_t gid)
660 {
661     if (gid == (gid_t)-1)
662         return PyLong_FromLong(-1);
663     return PyLong_FromUnsignedLong(gid);
664 }
665 
666 int
_Py_Uid_Converter(PyObject * obj,uid_t * p)667 _Py_Uid_Converter(PyObject *obj, uid_t *p)
668 {
669     uid_t uid;
670     PyObject *index;
671     int overflow;
672     long result;
673     unsigned long uresult;
674 
675     index = _PyNumber_Index(obj);
676     if (index == NULL) {
677         PyErr_Format(PyExc_TypeError,
678                      "uid should be integer, not %.200s",
679                      _PyType_Name(Py_TYPE(obj)));
680         return 0;
681     }
682 
683     /*
684      * Handling uid_t is complicated for two reasons:
685      *  * Although uid_t is (always?) unsigned, it still
686      *    accepts -1.
687      *  * We don't know its size in advance--it may be
688      *    bigger than an int, or it may be smaller than
689      *    a long.
690      *
691      * So a bit of defensive programming is in order.
692      * Start with interpreting the value passed
693      * in as a signed long and see if it works.
694      */
695 
696     result = PyLong_AsLongAndOverflow(index, &overflow);
697 
698     if (!overflow) {
699         uid = (uid_t)result;
700 
701         if (result == -1) {
702             if (PyErr_Occurred())
703                 goto fail;
704             /* It's a legitimate -1, we're done. */
705             goto success;
706         }
707 
708         /* Any other negative number is disallowed. */
709         if (result < 0)
710             goto underflow;
711 
712         /* Ensure the value wasn't truncated. */
713         if (sizeof(uid_t) < sizeof(long) &&
714             (long)uid != result)
715             goto underflow;
716         goto success;
717     }
718 
719     if (overflow < 0)
720         goto underflow;
721 
722     /*
723      * Okay, the value overflowed a signed long.  If it
724      * fits in an *unsigned* long, it may still be okay,
725      * as uid_t may be unsigned long on this platform.
726      */
727     uresult = PyLong_AsUnsignedLong(index);
728     if (PyErr_Occurred()) {
729         if (PyErr_ExceptionMatches(PyExc_OverflowError))
730             goto overflow;
731         goto fail;
732     }
733 
734     uid = (uid_t)uresult;
735 
736     /*
737      * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
738      * but this value would get interpreted as (uid_t)-1  by chown
739      * and its siblings.   That's not what the user meant!  So we
740      * throw an overflow exception instead.   (We already
741      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
742      */
743     if (uid == (uid_t)-1)
744         goto overflow;
745 
746     /* Ensure the value wasn't truncated. */
747     if (sizeof(uid_t) < sizeof(long) &&
748         (unsigned long)uid != uresult)
749         goto overflow;
750     /* fallthrough */
751 
752 success:
753     Py_DECREF(index);
754     *p = uid;
755     return 1;
756 
757 underflow:
758     PyErr_SetString(PyExc_OverflowError,
759                     "uid is less than minimum");
760     goto fail;
761 
762 overflow:
763     PyErr_SetString(PyExc_OverflowError,
764                     "uid is greater than maximum");
765     /* fallthrough */
766 
767 fail:
768     Py_DECREF(index);
769     return 0;
770 }
771 
772 int
_Py_Gid_Converter(PyObject * obj,gid_t * p)773 _Py_Gid_Converter(PyObject *obj, gid_t *p)
774 {
775     gid_t gid;
776     PyObject *index;
777     int overflow;
778     long result;
779     unsigned long uresult;
780 
781     index = _PyNumber_Index(obj);
782     if (index == NULL) {
783         PyErr_Format(PyExc_TypeError,
784                      "gid should be integer, not %.200s",
785                      _PyType_Name(Py_TYPE(obj)));
786         return 0;
787     }
788 
789     /*
790      * Handling gid_t is complicated for two reasons:
791      *  * Although gid_t is (always?) unsigned, it still
792      *    accepts -1.
793      *  * We don't know its size in advance--it may be
794      *    bigger than an int, or it may be smaller than
795      *    a long.
796      *
797      * So a bit of defensive programming is in order.
798      * Start with interpreting the value passed
799      * in as a signed long and see if it works.
800      */
801 
802     result = PyLong_AsLongAndOverflow(index, &overflow);
803 
804     if (!overflow) {
805         gid = (gid_t)result;
806 
807         if (result == -1) {
808             if (PyErr_Occurred())
809                 goto fail;
810             /* It's a legitimate -1, we're done. */
811             goto success;
812         }
813 
814         /* Any other negative number is disallowed. */
815         if (result < 0) {
816             goto underflow;
817         }
818 
819         /* Ensure the value wasn't truncated. */
820         if (sizeof(gid_t) < sizeof(long) &&
821             (long)gid != result)
822             goto underflow;
823         goto success;
824     }
825 
826     if (overflow < 0)
827         goto underflow;
828 
829     /*
830      * Okay, the value overflowed a signed long.  If it
831      * fits in an *unsigned* long, it may still be okay,
832      * as gid_t may be unsigned long on this platform.
833      */
834     uresult = PyLong_AsUnsignedLong(index);
835     if (PyErr_Occurred()) {
836         if (PyErr_ExceptionMatches(PyExc_OverflowError))
837             goto overflow;
838         goto fail;
839     }
840 
841     gid = (gid_t)uresult;
842 
843     /*
844      * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
845      * but this value would get interpreted as (gid_t)-1  by chown
846      * and its siblings.   That's not what the user meant!  So we
847      * throw an overflow exception instead.   (We already
848      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
849      */
850     if (gid == (gid_t)-1)
851         goto overflow;
852 
853     /* Ensure the value wasn't truncated. */
854     if (sizeof(gid_t) < sizeof(long) &&
855         (unsigned long)gid != uresult)
856         goto overflow;
857     /* fallthrough */
858 
859 success:
860     Py_DECREF(index);
861     *p = gid;
862     return 1;
863 
864 underflow:
865     PyErr_SetString(PyExc_OverflowError,
866                     "gid is less than minimum");
867     goto fail;
868 
869 overflow:
870     PyErr_SetString(PyExc_OverflowError,
871                     "gid is greater than maximum");
872     /* fallthrough */
873 
874 fail:
875     Py_DECREF(index);
876     return 0;
877 }
878 #endif /* MS_WINDOWS */
879 
880 
881 #define _PyLong_FromDev PyLong_FromLongLong
882 
883 
884 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
885 static int
_Py_Dev_Converter(PyObject * obj,void * p)886 _Py_Dev_Converter(PyObject *obj, void *p)
887 {
888     *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
889     if (PyErr_Occurred())
890         return 0;
891     return 1;
892 }
893 #endif /* HAVE_MKNOD && HAVE_MAKEDEV */
894 
895 
896 #ifdef AT_FDCWD
897 /*
898  * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
899  * without the int cast, the value gets interpreted as uint (4291925331),
900  * which doesn't play nicely with all the initializer lines in this file that
901  * look like this:
902  *      int dir_fd = DEFAULT_DIR_FD;
903  */
904 #define DEFAULT_DIR_FD (int)AT_FDCWD
905 #else
906 #define DEFAULT_DIR_FD (-100)
907 #endif
908 
909 static int
_fd_converter(PyObject * o,int * p)910 _fd_converter(PyObject *o, int *p)
911 {
912     int overflow;
913     long long_value;
914 
915     PyObject *index = _PyNumber_Index(o);
916     if (index == NULL) {
917         return 0;
918     }
919 
920     assert(PyLong_Check(index));
921     long_value = PyLong_AsLongAndOverflow(index, &overflow);
922     Py_DECREF(index);
923     assert(!PyErr_Occurred());
924     if (overflow > 0 || long_value > INT_MAX) {
925         PyErr_SetString(PyExc_OverflowError,
926                         "fd is greater than maximum");
927         return 0;
928     }
929     if (overflow < 0 || long_value < INT_MIN) {
930         PyErr_SetString(PyExc_OverflowError,
931                         "fd is less than minimum");
932         return 0;
933     }
934 
935     *p = (int)long_value;
936     return 1;
937 }
938 
939 static int
dir_fd_converter(PyObject * o,void * p)940 dir_fd_converter(PyObject *o, void *p)
941 {
942     if (o == Py_None) {
943         *(int *)p = DEFAULT_DIR_FD;
944         return 1;
945     }
946     else if (PyIndex_Check(o)) {
947         return _fd_converter(o, (int *)p);
948     }
949     else {
950         PyErr_Format(PyExc_TypeError,
951                      "argument should be integer or None, not %.200s",
952                      _PyType_Name(Py_TYPE(o)));
953         return 0;
954     }
955 }
956 
957 typedef struct {
958     PyObject *billion;
959     PyObject *DirEntryType;
960     PyObject *ScandirIteratorType;
961 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
962     PyObject *SchedParamType;
963 #endif
964     PyObject *StatResultType;
965     PyObject *StatVFSResultType;
966     PyObject *TerminalSizeType;
967     PyObject *TimesResultType;
968     PyObject *UnameResultType;
969 #if defined(HAVE_WAITID) && !defined(__APPLE__)
970     PyObject *WaitidResultType;
971 #endif
972 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
973     PyObject *struct_rusage;
974 #endif
975     PyObject *st_mode;
976 } _posixstate;
977 
978 
979 static inline _posixstate*
get_posix_state(PyObject * module)980 get_posix_state(PyObject *module)
981 {
982     void *state = _PyModule_GetState(module);
983     assert(state != NULL);
984     return (_posixstate *)state;
985 }
986 
987 /*
988  * A PyArg_ParseTuple "converter" function
989  * that handles filesystem paths in the manner
990  * preferred by the os module.
991  *
992  * path_converter accepts (Unicode) strings and their
993  * subclasses, and bytes and their subclasses.  What
994  * it does with the argument depends on the platform:
995  *
996  *   * On Windows, if we get a (Unicode) string we
997  *     extract the wchar_t * and return it; if we get
998  *     bytes we decode to wchar_t * and return that.
999  *
1000  *   * On all other platforms, strings are encoded
1001  *     to bytes using PyUnicode_FSConverter, then we
1002  *     extract the char * from the bytes object and
1003  *     return that.
1004  *
1005  * path_converter also optionally accepts signed
1006  * integers (representing open file descriptors) instead
1007  * of path strings.
1008  *
1009  * Input fields:
1010  *   path.nullable
1011  *     If nonzero, the path is permitted to be None.
1012  *   path.allow_fd
1013  *     If nonzero, the path is permitted to be a file handle
1014  *     (a signed int) instead of a string.
1015  *   path.function_name
1016  *     If non-NULL, path_converter will use that as the name
1017  *     of the function in error messages.
1018  *     (If path.function_name is NULL it omits the function name.)
1019  *   path.argument_name
1020  *     If non-NULL, path_converter will use that as the name
1021  *     of the parameter in error messages.
1022  *     (If path.argument_name is NULL it uses "path".)
1023  *
1024  * Output fields:
1025  *   path.wide
1026  *     Points to the path if it was expressed as Unicode
1027  *     and was not encoded.  (Only used on Windows.)
1028  *   path.narrow
1029  *     Points to the path if it was expressed as bytes,
1030  *     or it was Unicode and was encoded to bytes. (On Windows,
1031  *     is a non-zero integer if the path was expressed as bytes.
1032  *     The type is deliberately incompatible to prevent misuse.)
1033  *   path.fd
1034  *     Contains a file descriptor if path.accept_fd was true
1035  *     and the caller provided a signed integer instead of any
1036  *     sort of string.
1037  *
1038  *     WARNING: if your "path" parameter is optional, and is
1039  *     unspecified, path_converter will never get called.
1040  *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1041  *     yourself!
1042  *   path.length
1043  *     The length of the path in characters, if specified as
1044  *     a string.
1045  *   path.object
1046  *     The original object passed in (if get a PathLike object,
1047  *     the result of PyOS_FSPath() is treated as the original object).
1048  *     Own a reference to the object.
1049  *   path.cleanup
1050  *     For internal use only.  May point to a temporary object.
1051  *     (Pay no attention to the man behind the curtain.)
1052  *
1053  *   At most one of path.wide or path.narrow will be non-NULL.
1054  *   If path was None and path.nullable was set,
1055  *     or if path was an integer and path.allow_fd was set,
1056  *     both path.wide and path.narrow will be NULL
1057  *     and path.length will be 0.
1058  *
1059  *   path_converter takes care to not write to the path_t
1060  *   unless it's successful.  However it must reset the
1061  *   "cleanup" field each time it's called.
1062  *
1063  * Use as follows:
1064  *      path_t path;
1065  *      memset(&path, 0, sizeof(path));
1066  *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1067  *      // ... use values from path ...
1068  *      path_cleanup(&path);
1069  *
1070  * (Note that if PyArg_Parse fails you don't need to call
1071  * path_cleanup().  However it is safe to do so.)
1072  */
1073 typedef struct {
1074     const char *function_name;
1075     const char *argument_name;
1076     int nullable;
1077     int allow_fd;
1078     const wchar_t *wide;
1079 #ifdef MS_WINDOWS
1080     BOOL narrow;
1081 #else
1082     const char *narrow;
1083 #endif
1084     int fd;
1085     Py_ssize_t length;
1086     PyObject *object;
1087     PyObject *cleanup;
1088 } path_t;
1089 
1090 #ifdef MS_WINDOWS
1091 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1092     {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
1093 #else
1094 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1095     {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
1096 #endif
1097 
1098 static void
path_cleanup(path_t * path)1099 path_cleanup(path_t *path)
1100 {
1101 #if !USE_UNICODE_WCHAR_CACHE
1102     wchar_t *wide = (wchar_t *)path->wide;
1103     path->wide = NULL;
1104     PyMem_Free(wide);
1105 #endif /* USE_UNICODE_WCHAR_CACHE */
1106     Py_CLEAR(path->object);
1107     Py_CLEAR(path->cleanup);
1108 }
1109 
1110 static int
path_converter(PyObject * o,void * p)1111 path_converter(PyObject *o, void *p)
1112 {
1113     path_t *path = (path_t *)p;
1114     PyObject *bytes = NULL;
1115     Py_ssize_t length = 0;
1116     int is_index, is_buffer, is_bytes, is_unicode;
1117     const char *narrow;
1118 #ifdef MS_WINDOWS
1119     PyObject *wo = NULL;
1120     wchar_t *wide = NULL;
1121 #endif
1122 
1123 #define FORMAT_EXCEPTION(exc, fmt) \
1124     PyErr_Format(exc, "%s%s" fmt, \
1125         path->function_name ? path->function_name : "", \
1126         path->function_name ? ": "                : "", \
1127         path->argument_name ? path->argument_name : "path")
1128 
1129     /* Py_CLEANUP_SUPPORTED support */
1130     if (o == NULL) {
1131         path_cleanup(path);
1132         return 1;
1133     }
1134 
1135     /* Ensure it's always safe to call path_cleanup(). */
1136     path->object = path->cleanup = NULL;
1137     /* path->object owns a reference to the original object */
1138     Py_INCREF(o);
1139 
1140     if ((o == Py_None) && path->nullable) {
1141         path->wide = NULL;
1142 #ifdef MS_WINDOWS
1143         path->narrow = FALSE;
1144 #else
1145         path->narrow = NULL;
1146 #endif
1147         path->fd = -1;
1148         goto success_exit;
1149     }
1150 
1151     /* Only call this here so that we don't treat the return value of
1152        os.fspath() as an fd or buffer. */
1153     is_index = path->allow_fd && PyIndex_Check(o);
1154     is_buffer = PyObject_CheckBuffer(o);
1155     is_bytes = PyBytes_Check(o);
1156     is_unicode = PyUnicode_Check(o);
1157 
1158     if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
1159         /* Inline PyOS_FSPath() for better error messages. */
1160         PyObject *func, *res;
1161 
1162         func = _PyObject_LookupSpecial(o, &PyId___fspath__);
1163         if (NULL == func) {
1164             goto error_format;
1165         }
1166         res = _PyObject_CallNoArgs(func);
1167         Py_DECREF(func);
1168         if (NULL == res) {
1169             goto error_exit;
1170         }
1171         else if (PyUnicode_Check(res)) {
1172             is_unicode = 1;
1173         }
1174         else if (PyBytes_Check(res)) {
1175             is_bytes = 1;
1176         }
1177         else {
1178             PyErr_Format(PyExc_TypeError,
1179                  "expected %.200s.__fspath__() to return str or bytes, "
1180                  "not %.200s", _PyType_Name(Py_TYPE(o)),
1181                  _PyType_Name(Py_TYPE(res)));
1182             Py_DECREF(res);
1183             goto error_exit;
1184         }
1185 
1186         /* still owns a reference to the original object */
1187         Py_DECREF(o);
1188         o = res;
1189     }
1190 
1191     if (is_unicode) {
1192 #ifdef MS_WINDOWS
1193 #if USE_UNICODE_WCHAR_CACHE
1194 _Py_COMP_DIAG_PUSH
1195 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1196         wide = PyUnicode_AsUnicodeAndSize(o, &length);
1197 _Py_COMP_DIAG_POP
1198 #else /* USE_UNICODE_WCHAR_CACHE */
1199         wide = PyUnicode_AsWideCharString(o, &length);
1200 #endif /* USE_UNICODE_WCHAR_CACHE */
1201         if (!wide) {
1202             goto error_exit;
1203         }
1204         if (length > 32767) {
1205             FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1206             goto error_exit;
1207         }
1208         if (wcslen(wide) != length) {
1209             FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1210             goto error_exit;
1211         }
1212 
1213         path->wide = wide;
1214         path->narrow = FALSE;
1215         path->fd = -1;
1216 #if !USE_UNICODE_WCHAR_CACHE
1217         wide = NULL;
1218 #endif /* USE_UNICODE_WCHAR_CACHE */
1219         goto success_exit;
1220 #else
1221         if (!PyUnicode_FSConverter(o, &bytes)) {
1222             goto error_exit;
1223         }
1224 #endif
1225     }
1226     else if (is_bytes) {
1227         bytes = o;
1228         Py_INCREF(bytes);
1229     }
1230     else if (is_buffer) {
1231         /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1232            after removing support of non-bytes buffer objects. */
1233         if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
1234             "%s%s%s should be %s, not %.200s",
1235             path->function_name ? path->function_name : "",
1236             path->function_name ? ": "                : "",
1237             path->argument_name ? path->argument_name : "path",
1238             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1239                                                "integer or None" :
1240             path->allow_fd ? "string, bytes, os.PathLike or integer" :
1241             path->nullable ? "string, bytes, os.PathLike or None" :
1242                              "string, bytes or os.PathLike",
1243             _PyType_Name(Py_TYPE(o)))) {
1244             goto error_exit;
1245         }
1246         bytes = PyBytes_FromObject(o);
1247         if (!bytes) {
1248             goto error_exit;
1249         }
1250     }
1251     else if (is_index) {
1252         if (!_fd_converter(o, &path->fd)) {
1253             goto error_exit;
1254         }
1255         path->wide = NULL;
1256 #ifdef MS_WINDOWS
1257         path->narrow = FALSE;
1258 #else
1259         path->narrow = NULL;
1260 #endif
1261         goto success_exit;
1262     }
1263     else {
1264  error_format:
1265         PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1266             path->function_name ? path->function_name : "",
1267             path->function_name ? ": "                : "",
1268             path->argument_name ? path->argument_name : "path",
1269             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1270                                                "integer or None" :
1271             path->allow_fd ? "string, bytes, os.PathLike or integer" :
1272             path->nullable ? "string, bytes, os.PathLike or None" :
1273                              "string, bytes or os.PathLike",
1274             _PyType_Name(Py_TYPE(o)));
1275         goto error_exit;
1276     }
1277 
1278     length = PyBytes_GET_SIZE(bytes);
1279     narrow = PyBytes_AS_STRING(bytes);
1280     if ((size_t)length != strlen(narrow)) {
1281         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1282         goto error_exit;
1283     }
1284 
1285 #ifdef MS_WINDOWS
1286     wo = PyUnicode_DecodeFSDefaultAndSize(
1287         narrow,
1288         length
1289     );
1290     if (!wo) {
1291         goto error_exit;
1292     }
1293 
1294 #if USE_UNICODE_WCHAR_CACHE
1295 _Py_COMP_DIAG_PUSH
1296 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1297     wide = PyUnicode_AsUnicodeAndSize(wo, &length);
1298 _Py_COMP_DIAG_POP
1299 #else /* USE_UNICODE_WCHAR_CACHE */
1300     wide = PyUnicode_AsWideCharString(wo, &length);
1301     Py_DECREF(wo);
1302 #endif /* USE_UNICODE_WCHAR_CACHE */
1303     if (!wide) {
1304         goto error_exit;
1305     }
1306     if (length > 32767) {
1307         FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1308         goto error_exit;
1309     }
1310     if (wcslen(wide) != length) {
1311         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1312         goto error_exit;
1313     }
1314     path->wide = wide;
1315     path->narrow = TRUE;
1316     Py_DECREF(bytes);
1317 #if USE_UNICODE_WCHAR_CACHE
1318     path->cleanup = wo;
1319 #else /* USE_UNICODE_WCHAR_CACHE */
1320     wide = NULL;
1321 #endif /* USE_UNICODE_WCHAR_CACHE */
1322 #else
1323     path->wide = NULL;
1324     path->narrow = narrow;
1325     if (bytes == o) {
1326         /* Still a reference owned by path->object, don't have to
1327            worry about path->narrow is used after free. */
1328         Py_DECREF(bytes);
1329     }
1330     else {
1331         path->cleanup = bytes;
1332     }
1333 #endif
1334     path->fd = -1;
1335 
1336  success_exit:
1337     path->length = length;
1338     path->object = o;
1339     return Py_CLEANUP_SUPPORTED;
1340 
1341  error_exit:
1342     Py_XDECREF(o);
1343     Py_XDECREF(bytes);
1344 #ifdef MS_WINDOWS
1345 #if USE_UNICODE_WCHAR_CACHE
1346     Py_XDECREF(wo);
1347 #else /* USE_UNICODE_WCHAR_CACHE */
1348     PyMem_Free(wide);
1349 #endif /* USE_UNICODE_WCHAR_CACHE */
1350 #endif
1351     return 0;
1352 }
1353 
1354 static void
argument_unavailable_error(const char * function_name,const char * argument_name)1355 argument_unavailable_error(const char *function_name, const char *argument_name)
1356 {
1357     PyErr_Format(PyExc_NotImplementedError,
1358         "%s%s%s unavailable on this platform",
1359         (function_name != NULL) ? function_name : "",
1360         (function_name != NULL) ? ": ": "",
1361         argument_name);
1362 }
1363 
1364 static int
dir_fd_unavailable(PyObject * o,void * p)1365 dir_fd_unavailable(PyObject *o, void *p)
1366 {
1367     int dir_fd;
1368     if (!dir_fd_converter(o, &dir_fd))
1369         return 0;
1370     if (dir_fd != DEFAULT_DIR_FD) {
1371         argument_unavailable_error(NULL, "dir_fd");
1372         return 0;
1373     }
1374     *(int *)p = dir_fd;
1375     return 1;
1376 }
1377 
1378 static int
fd_specified(const char * function_name,int fd)1379 fd_specified(const char *function_name, int fd)
1380 {
1381     if (fd == -1)
1382         return 0;
1383 
1384     argument_unavailable_error(function_name, "fd");
1385     return 1;
1386 }
1387 
1388 static int
follow_symlinks_specified(const char * function_name,int follow_symlinks)1389 follow_symlinks_specified(const char *function_name, int follow_symlinks)
1390 {
1391     if (follow_symlinks)
1392         return 0;
1393 
1394     argument_unavailable_error(function_name, "follow_symlinks");
1395     return 1;
1396 }
1397 
1398 static int
path_and_dir_fd_invalid(const char * function_name,path_t * path,int dir_fd)1399 path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1400 {
1401     if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1402 #ifndef MS_WINDOWS
1403         && !path->narrow
1404 #endif
1405     ) {
1406         PyErr_Format(PyExc_ValueError,
1407                      "%s: can't specify dir_fd without matching path",
1408                      function_name);
1409         return 1;
1410     }
1411     return 0;
1412 }
1413 
1414 static int
dir_fd_and_fd_invalid(const char * function_name,int dir_fd,int fd)1415 dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1416 {
1417     if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1418         PyErr_Format(PyExc_ValueError,
1419                      "%s: can't specify both dir_fd and fd",
1420                      function_name);
1421         return 1;
1422     }
1423     return 0;
1424 }
1425 
1426 static int
fd_and_follow_symlinks_invalid(const char * function_name,int fd,int follow_symlinks)1427 fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1428                                int follow_symlinks)
1429 {
1430     if ((fd > 0) && (!follow_symlinks)) {
1431         PyErr_Format(PyExc_ValueError,
1432                      "%s: cannot use fd and follow_symlinks together",
1433                      function_name);
1434         return 1;
1435     }
1436     return 0;
1437 }
1438 
1439 static int
dir_fd_and_follow_symlinks_invalid(const char * function_name,int dir_fd,int follow_symlinks)1440 dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1441                                    int follow_symlinks)
1442 {
1443     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1444         PyErr_Format(PyExc_ValueError,
1445                      "%s: cannot use dir_fd and follow_symlinks together",
1446                      function_name);
1447         return 1;
1448     }
1449     return 0;
1450 }
1451 
1452 #ifdef MS_WINDOWS
1453     typedef long long Py_off_t;
1454 #else
1455     typedef off_t Py_off_t;
1456 #endif
1457 
1458 static int
Py_off_t_converter(PyObject * arg,void * addr)1459 Py_off_t_converter(PyObject *arg, void *addr)
1460 {
1461 #ifdef HAVE_LARGEFILE_SUPPORT
1462     *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1463 #else
1464     *((Py_off_t *)addr) = PyLong_AsLong(arg);
1465 #endif
1466     if (PyErr_Occurred())
1467         return 0;
1468     return 1;
1469 }
1470 
1471 static PyObject *
PyLong_FromPy_off_t(Py_off_t offset)1472 PyLong_FromPy_off_t(Py_off_t offset)
1473 {
1474 #ifdef HAVE_LARGEFILE_SUPPORT
1475     return PyLong_FromLongLong(offset);
1476 #else
1477     return PyLong_FromLong(offset);
1478 #endif
1479 }
1480 
1481 #ifdef HAVE_SIGSET_T
1482 /* Convert an iterable of integers to a sigset.
1483    Return 1 on success, return 0 and raise an exception on error. */
1484 int
_Py_Sigset_Converter(PyObject * obj,void * addr)1485 _Py_Sigset_Converter(PyObject *obj, void *addr)
1486 {
1487     sigset_t *mask = (sigset_t *)addr;
1488     PyObject *iterator, *item;
1489     long signum;
1490     int overflow;
1491 
1492     // The extra parens suppress the unreachable-code warning with clang on MacOS
1493     if (sigemptyset(mask) < (0)) {
1494         /* Probably only if mask == NULL. */
1495         PyErr_SetFromErrno(PyExc_OSError);
1496         return 0;
1497     }
1498 
1499     iterator = PyObject_GetIter(obj);
1500     if (iterator == NULL) {
1501         return 0;
1502     }
1503 
1504     while ((item = PyIter_Next(iterator)) != NULL) {
1505         signum = PyLong_AsLongAndOverflow(item, &overflow);
1506         Py_DECREF(item);
1507         if (signum <= 0 || signum >= NSIG) {
1508             if (overflow || signum != -1 || !PyErr_Occurred()) {
1509                 PyErr_Format(PyExc_ValueError,
1510                              "signal number %ld out of range", signum);
1511             }
1512             goto error;
1513         }
1514         if (sigaddset(mask, (int)signum)) {
1515             if (errno != EINVAL) {
1516                 /* Probably impossible */
1517                 PyErr_SetFromErrno(PyExc_OSError);
1518                 goto error;
1519             }
1520             /* For backwards compatibility, allow idioms such as
1521              * `range(1, NSIG)` but warn about invalid signal numbers
1522              */
1523             const char msg[] =
1524                 "invalid signal number %ld, please use valid_signals()";
1525             if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1526                 goto error;
1527             }
1528         }
1529     }
1530     if (!PyErr_Occurred()) {
1531         Py_DECREF(iterator);
1532         return 1;
1533     }
1534 
1535 error:
1536     Py_DECREF(iterator);
1537     return 0;
1538 }
1539 #endif /* HAVE_SIGSET_T */
1540 
1541 #ifdef MS_WINDOWS
1542 
1543 static int
win32_get_reparse_tag(HANDLE reparse_point_handle,ULONG * reparse_tag)1544 win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1545 {
1546     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1547     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1548     DWORD n_bytes_returned;
1549 
1550     if (0 == DeviceIoControl(
1551         reparse_point_handle,
1552         FSCTL_GET_REPARSE_POINT,
1553         NULL, 0, /* in buffer */
1554         target_buffer, sizeof(target_buffer),
1555         &n_bytes_returned,
1556         NULL)) /* we're not using OVERLAPPED_IO */
1557         return FALSE;
1558 
1559     if (reparse_tag)
1560         *reparse_tag = rdb->ReparseTag;
1561 
1562     return TRUE;
1563 }
1564 
1565 #endif /* MS_WINDOWS */
1566 
1567 /* Return a dictionary corresponding to the POSIX environment table */
1568 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1569 /* On Darwin/MacOSX a shared library or framework has no access to
1570 ** environ directly, we must obtain it with _NSGetEnviron(). See also
1571 ** man environ(7).
1572 */
1573 #include <crt_externs.h>
1574 #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1575 extern char **environ;
1576 #endif /* !_MSC_VER */
1577 
1578 static PyObject *
convertenviron(void)1579 convertenviron(void)
1580 {
1581     PyObject *d;
1582 #ifdef MS_WINDOWS
1583     wchar_t **e;
1584 #else
1585     char **e;
1586 #endif
1587 
1588     d = PyDict_New();
1589     if (d == NULL)
1590         return NULL;
1591 #ifdef MS_WINDOWS
1592     /* _wenviron must be initialized in this way if the program is started
1593        through main() instead of wmain(). */
1594     _wgetenv(L"");
1595     e = _wenviron;
1596 #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1597     /* environ is not accessible as an extern in a shared object on OSX; use
1598        _NSGetEnviron to resolve it. The value changes if you add environment
1599        variables between calls to Py_Initialize, so don't cache the value. */
1600     e = *_NSGetEnviron();
1601 #else
1602     e = environ;
1603 #endif
1604     if (e == NULL)
1605         return d;
1606     for (; *e != NULL; e++) {
1607         PyObject *k;
1608         PyObject *v;
1609 #ifdef MS_WINDOWS
1610         const wchar_t *p = wcschr(*e, L'=');
1611 #else
1612         const char *p = strchr(*e, '=');
1613 #endif
1614         if (p == NULL)
1615             continue;
1616 #ifdef MS_WINDOWS
1617         k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1618 #else
1619         k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1620 #endif
1621         if (k == NULL) {
1622             Py_DECREF(d);
1623             return NULL;
1624         }
1625 #ifdef MS_WINDOWS
1626         v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1627 #else
1628         v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1629 #endif
1630         if (v == NULL) {
1631             Py_DECREF(k);
1632             Py_DECREF(d);
1633             return NULL;
1634         }
1635         if (PyDict_SetDefault(d, k, v) == NULL) {
1636             Py_DECREF(v);
1637             Py_DECREF(k);
1638             Py_DECREF(d);
1639             return NULL;
1640         }
1641         Py_DECREF(k);
1642         Py_DECREF(v);
1643     }
1644     return d;
1645 }
1646 
1647 /* Set a POSIX-specific error from errno, and return NULL */
1648 
1649 static PyObject *
posix_error(void)1650 posix_error(void)
1651 {
1652     return PyErr_SetFromErrno(PyExc_OSError);
1653 }
1654 
1655 #ifdef MS_WINDOWS
1656 static PyObject *
win32_error(const char * function,const char * filename)1657 win32_error(const char* function, const char* filename)
1658 {
1659     /* XXX We should pass the function name along in the future.
1660        (winreg.c also wants to pass the function name.)
1661        This would however require an additional param to the
1662        Windows error object, which is non-trivial.
1663     */
1664     errno = GetLastError();
1665     if (filename)
1666         return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1667     else
1668         return PyErr_SetFromWindowsErr(errno);
1669 }
1670 
1671 static PyObject *
win32_error_object_err(const char * function,PyObject * filename,DWORD err)1672 win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1673 {
1674     /* XXX - see win32_error for comments on 'function' */
1675     if (filename)
1676         return PyErr_SetExcFromWindowsErrWithFilenameObject(
1677                     PyExc_OSError,
1678                     err,
1679                     filename);
1680     else
1681         return PyErr_SetFromWindowsErr(err);
1682 }
1683 
1684 static PyObject *
win32_error_object(const char * function,PyObject * filename)1685 win32_error_object(const char* function, PyObject* filename)
1686 {
1687     errno = GetLastError();
1688     return win32_error_object_err(function, filename, errno);
1689 }
1690 
1691 #endif /* MS_WINDOWS */
1692 
1693 static PyObject *
posix_path_object_error(PyObject * path)1694 posix_path_object_error(PyObject *path)
1695 {
1696     return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1697 }
1698 
1699 static PyObject *
path_object_error(PyObject * path)1700 path_object_error(PyObject *path)
1701 {
1702 #ifdef MS_WINDOWS
1703     return PyErr_SetExcFromWindowsErrWithFilenameObject(
1704                 PyExc_OSError, 0, path);
1705 #else
1706     return posix_path_object_error(path);
1707 #endif
1708 }
1709 
1710 static PyObject *
path_object_error2(PyObject * path,PyObject * path2)1711 path_object_error2(PyObject *path, PyObject *path2)
1712 {
1713 #ifdef MS_WINDOWS
1714     return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1715                 PyExc_OSError, 0, path, path2);
1716 #else
1717     return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1718 #endif
1719 }
1720 
1721 static PyObject *
path_error(path_t * path)1722 path_error(path_t *path)
1723 {
1724     return path_object_error(path->object);
1725 }
1726 
1727 static PyObject *
posix_path_error(path_t * path)1728 posix_path_error(path_t *path)
1729 {
1730     return posix_path_object_error(path->object);
1731 }
1732 
1733 static PyObject *
path_error2(path_t * path,path_t * path2)1734 path_error2(path_t *path, path_t *path2)
1735 {
1736     return path_object_error2(path->object, path2->object);
1737 }
1738 
1739 
1740 /* POSIX generic methods */
1741 
1742 static PyObject *
posix_fildes_fd(int fd,int (* func)(int))1743 posix_fildes_fd(int fd, int (*func)(int))
1744 {
1745     int res;
1746     int async_err = 0;
1747 
1748     do {
1749         Py_BEGIN_ALLOW_THREADS
1750         _Py_BEGIN_SUPPRESS_IPH
1751         res = (*func)(fd);
1752         _Py_END_SUPPRESS_IPH
1753         Py_END_ALLOW_THREADS
1754     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1755     if (res != 0)
1756         return (!async_err) ? posix_error() : NULL;
1757     Py_RETURN_NONE;
1758 }
1759 
1760 
1761 #ifdef MS_WINDOWS
1762 /* This is a reimplementation of the C library's chdir function,
1763    but one that produces Win32 errors instead of DOS error codes.
1764    chdir is essentially a wrapper around SetCurrentDirectory; however,
1765    it also needs to set "magic" environment variables indicating
1766    the per-drive current directory, which are of the form =<drive>: */
1767 static BOOL __stdcall
win32_wchdir(LPCWSTR path)1768 win32_wchdir(LPCWSTR path)
1769 {
1770     wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1771     int result;
1772     wchar_t env[4] = L"=x:";
1773 
1774     if(!SetCurrentDirectoryW(path))
1775         return FALSE;
1776     result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1777     if (!result)
1778         return FALSE;
1779     if (result > Py_ARRAY_LENGTH(path_buf)) {
1780         new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1781         if (!new_path) {
1782             SetLastError(ERROR_OUTOFMEMORY);
1783             return FALSE;
1784         }
1785         result = GetCurrentDirectoryW(result, new_path);
1786         if (!result) {
1787             PyMem_RawFree(new_path);
1788             return FALSE;
1789         }
1790     }
1791     int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1792                             wcsncmp(new_path, L"//", 2) == 0);
1793     if (!is_unc_like_path) {
1794         env[1] = new_path[0];
1795         result = SetEnvironmentVariableW(env, new_path);
1796     }
1797     if (new_path != path_buf)
1798         PyMem_RawFree(new_path);
1799     return result ? TRUE : FALSE;
1800 }
1801 #endif
1802 
1803 #ifdef MS_WINDOWS
1804 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1805    - time stamps are restricted to second resolution
1806    - file modification times suffer from forth-and-back conversions between
1807      UTC and local time
1808    Therefore, we implement our own stat, based on the Win32 API directly.
1809 */
1810 #define HAVE_STAT_NSEC 1
1811 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1812 #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1813 
1814 static void
find_data_to_file_info(WIN32_FIND_DATAW * pFileData,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1815 find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1816                        BY_HANDLE_FILE_INFORMATION *info,
1817                        ULONG *reparse_tag)
1818 {
1819     memset(info, 0, sizeof(*info));
1820     info->dwFileAttributes = pFileData->dwFileAttributes;
1821     info->ftCreationTime   = pFileData->ftCreationTime;
1822     info->ftLastAccessTime = pFileData->ftLastAccessTime;
1823     info->ftLastWriteTime  = pFileData->ftLastWriteTime;
1824     info->nFileSizeHigh    = pFileData->nFileSizeHigh;
1825     info->nFileSizeLow     = pFileData->nFileSizeLow;
1826 /*  info->nNumberOfLinks   = 1; */
1827     if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1828         *reparse_tag = pFileData->dwReserved0;
1829     else
1830         *reparse_tag = 0;
1831 }
1832 
1833 static BOOL
attributes_from_dir(LPCWSTR pszFile,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1834 attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1835 {
1836     HANDLE hFindFile;
1837     WIN32_FIND_DATAW FileData;
1838     LPCWSTR filename = pszFile;
1839     size_t n = wcslen(pszFile);
1840     if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
1841         // cannot use PyMem_Malloc here because we do not hold the GIL
1842         filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
1843         wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
1844         while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
1845             ((LPWSTR)filename)[n] = L'\0';
1846         }
1847         if (!n || (n == 1 && filename[1] == L':')) {
1848             // Nothing left to query
1849             free((void *)filename);
1850             return FALSE;
1851         }
1852     }
1853     hFindFile = FindFirstFileW(filename, &FileData);
1854     if (pszFile != filename) {
1855         free((void *)filename);
1856     }
1857     if (hFindFile == INVALID_HANDLE_VALUE) {
1858         return FALSE;
1859     }
1860     FindClose(hFindFile);
1861     find_data_to_file_info(&FileData, info, reparse_tag);
1862     return TRUE;
1863 }
1864 
1865 static int
win32_xstat_impl(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1866 win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1867                  BOOL traverse)
1868 {
1869     HANDLE hFile;
1870     BY_HANDLE_FILE_INFORMATION fileInfo;
1871     FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1872     DWORD fileType, error;
1873     BOOL isUnhandledTag = FALSE;
1874     int retval = 0;
1875 
1876     DWORD access = FILE_READ_ATTRIBUTES;
1877     DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1878     if (!traverse) {
1879         flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1880     }
1881 
1882     hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1883     if (hFile == INVALID_HANDLE_VALUE) {
1884         /* Either the path doesn't exist, or the caller lacks access. */
1885         error = GetLastError();
1886         switch (error) {
1887         case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
1888         case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1889             /* Try reading the parent directory. */
1890             if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1891                 /* Cannot read the parent directory. */
1892                 SetLastError(error);
1893                 return -1;
1894             }
1895             if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1896                 if (traverse ||
1897                     !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1898                     /* The stat call has to traverse but cannot, so fail. */
1899                     SetLastError(error);
1900                     return -1;
1901                 }
1902             }
1903             break;
1904 
1905         case ERROR_INVALID_PARAMETER:
1906             /* \\.\con requires read or write access. */
1907             hFile = CreateFileW(path, access | GENERIC_READ,
1908                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1909                         OPEN_EXISTING, flags, NULL);
1910             if (hFile == INVALID_HANDLE_VALUE) {
1911                 SetLastError(error);
1912                 return -1;
1913             }
1914             break;
1915 
1916         case ERROR_CANT_ACCESS_FILE:
1917             /* bpo37834: open unhandled reparse points if traverse fails. */
1918             if (traverse) {
1919                 traverse = FALSE;
1920                 isUnhandledTag = TRUE;
1921                 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1922                             flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1923             }
1924             if (hFile == INVALID_HANDLE_VALUE) {
1925                 SetLastError(error);
1926                 return -1;
1927             }
1928             break;
1929 
1930         default:
1931             return -1;
1932         }
1933     }
1934 
1935     if (hFile != INVALID_HANDLE_VALUE) {
1936         /* Handle types other than files on disk. */
1937         fileType = GetFileType(hFile);
1938         if (fileType != FILE_TYPE_DISK) {
1939             if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1940                 retval = -1;
1941                 goto cleanup;
1942             }
1943             DWORD fileAttributes = GetFileAttributesW(path);
1944             memset(result, 0, sizeof(*result));
1945             if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1946                 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1947                 /* \\.\pipe\ or \\.\mailslot\ */
1948                 result->st_mode = _S_IFDIR;
1949             } else if (fileType == FILE_TYPE_CHAR) {
1950                 /* \\.\nul */
1951                 result->st_mode = _S_IFCHR;
1952             } else if (fileType == FILE_TYPE_PIPE) {
1953                 /* \\.\pipe\spam */
1954                 result->st_mode = _S_IFIFO;
1955             }
1956             /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1957             goto cleanup;
1958         }
1959 
1960         /* Query the reparse tag, and traverse a non-link. */
1961         if (!traverse) {
1962             if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
1963                     &tagInfo, sizeof(tagInfo))) {
1964                 /* Allow devices that do not support FileAttributeTagInfo. */
1965                 switch (GetLastError()) {
1966                 case ERROR_INVALID_PARAMETER:
1967                 case ERROR_INVALID_FUNCTION:
1968                 case ERROR_NOT_SUPPORTED:
1969                     tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1970                     tagInfo.ReparseTag = 0;
1971                     break;
1972                 default:
1973                     retval = -1;
1974                     goto cleanup;
1975                 }
1976             } else if (tagInfo.FileAttributes &
1977                          FILE_ATTRIBUTE_REPARSE_POINT) {
1978                 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1979                     if (isUnhandledTag) {
1980                         /* Traversing previously failed for either this link
1981                            or its target. */
1982                         SetLastError(ERROR_CANT_ACCESS_FILE);
1983                         retval = -1;
1984                         goto cleanup;
1985                     }
1986                 /* Traverse a non-link, but not if traversing already failed
1987                    for an unhandled tag. */
1988                 } else if (!isUnhandledTag) {
1989                     CloseHandle(hFile);
1990                     return win32_xstat_impl(path, result, TRUE);
1991                 }
1992             }
1993         }
1994 
1995         if (!GetFileInformationByHandle(hFile, &fileInfo)) {
1996             switch (GetLastError()) {
1997             case ERROR_INVALID_PARAMETER:
1998             case ERROR_INVALID_FUNCTION:
1999             case ERROR_NOT_SUPPORTED:
2000                 /* Volumes and physical disks are block devices, e.g.
2001                    \\.\C: and \\.\PhysicalDrive0. */
2002                 memset(result, 0, sizeof(*result));
2003                 result->st_mode = 0x6000; /* S_IFBLK */
2004                 goto cleanup;
2005             }
2006             retval = -1;
2007             goto cleanup;
2008         }
2009     }
2010 
2011     _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
2012 
2013     if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
2014         /* Fix the file execute permissions. This hack sets S_IEXEC if
2015            the filename has an extension that is commonly used by files
2016            that CreateProcessW can execute. A real implementation calls
2017            GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2018            AccessCheck to check for generic read, write, and execute
2019            access. */
2020         const wchar_t *fileExtension = wcsrchr(path, '.');
2021         if (fileExtension) {
2022             if (_wcsicmp(fileExtension, L".exe") == 0 ||
2023                 _wcsicmp(fileExtension, L".bat") == 0 ||
2024                 _wcsicmp(fileExtension, L".cmd") == 0 ||
2025                 _wcsicmp(fileExtension, L".com") == 0) {
2026                 result->st_mode |= 0111;
2027             }
2028         }
2029     }
2030 
2031 cleanup:
2032     if (hFile != INVALID_HANDLE_VALUE) {
2033         /* Preserve last error if we are failing */
2034         error = retval ? GetLastError() : 0;
2035         if (!CloseHandle(hFile)) {
2036             retval = -1;
2037         } else if (retval) {
2038             /* Restore last error */
2039             SetLastError(error);
2040         }
2041     }
2042 
2043     return retval;
2044 }
2045 
2046 static int
win32_xstat(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)2047 win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2048 {
2049     /* Protocol violation: we explicitly clear errno, instead of
2050        setting it to a POSIX error. Callers should use GetLastError. */
2051     int code = win32_xstat_impl(path, result, traverse);
2052     errno = 0;
2053     return code;
2054 }
2055 /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2056 
2057    In Posix, stat automatically traverses symlinks and returns the stat
2058    structure for the target.  In Windows, the equivalent GetFileAttributes by
2059    default does not traverse symlinks and instead returns attributes for
2060    the symlink.
2061 
2062    Instead, we will open the file (which *does* traverse symlinks by default)
2063    and GetFileInformationByHandle(). */
2064 
2065 static int
win32_lstat(const wchar_t * path,struct _Py_stat_struct * result)2066 win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2067 {
2068     return win32_xstat(path, result, FALSE);
2069 }
2070 
2071 static int
win32_stat(const wchar_t * path,struct _Py_stat_struct * result)2072 win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2073 {
2074     return win32_xstat(path, result, TRUE);
2075 }
2076 
2077 #endif /* MS_WINDOWS */
2078 
2079 PyDoc_STRVAR(stat_result__doc__,
2080 "stat_result: Result from stat, fstat, or lstat.\n\n\
2081 This object may be accessed either as a tuple of\n\
2082   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2083 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2084 \n\
2085 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2086 or st_flags, they are available as attributes only.\n\
2087 \n\
2088 See os.stat for more information.");
2089 
2090 static PyStructSequence_Field stat_result_fields[] = {
2091     {"st_mode",    "protection bits"},
2092     {"st_ino",     "inode"},
2093     {"st_dev",     "device"},
2094     {"st_nlink",   "number of hard links"},
2095     {"st_uid",     "user ID of owner"},
2096     {"st_gid",     "group ID of owner"},
2097     {"st_size",    "total size, in bytes"},
2098     /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2099     {NULL,   "integer time of last access"},
2100     {NULL,   "integer time of last modification"},
2101     {NULL,   "integer time of last change"},
2102     {"st_atime",   "time of last access"},
2103     {"st_mtime",   "time of last modification"},
2104     {"st_ctime",   "time of last change"},
2105     {"st_atime_ns",   "time of last access in nanoseconds"},
2106     {"st_mtime_ns",   "time of last modification in nanoseconds"},
2107     {"st_ctime_ns",   "time of last change in nanoseconds"},
2108 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2109     {"st_blksize", "blocksize for filesystem I/O"},
2110 #endif
2111 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2112     {"st_blocks",  "number of blocks allocated"},
2113 #endif
2114 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2115     {"st_rdev",    "device type (if inode device)"},
2116 #endif
2117 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2118     {"st_flags",   "user defined flags for file"},
2119 #endif
2120 #ifdef HAVE_STRUCT_STAT_ST_GEN
2121     {"st_gen",    "generation number"},
2122 #endif
2123 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2124     {"st_birthtime",   "time of creation"},
2125 #endif
2126 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2127     {"st_file_attributes", "Windows file attribute bits"},
2128 #endif
2129 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2130     {"st_fstype",  "Type of filesystem"},
2131 #endif
2132 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2133     {"st_reparse_tag", "Windows reparse tag"},
2134 #endif
2135     {0}
2136 };
2137 
2138 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2139 #define ST_BLKSIZE_IDX 16
2140 #else
2141 #define ST_BLKSIZE_IDX 15
2142 #endif
2143 
2144 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2145 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2146 #else
2147 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2148 #endif
2149 
2150 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2151 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2152 #else
2153 #define ST_RDEV_IDX ST_BLOCKS_IDX
2154 #endif
2155 
2156 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2157 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2158 #else
2159 #define ST_FLAGS_IDX ST_RDEV_IDX
2160 #endif
2161 
2162 #ifdef HAVE_STRUCT_STAT_ST_GEN
2163 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
2164 #else
2165 #define ST_GEN_IDX ST_FLAGS_IDX
2166 #endif
2167 
2168 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2169 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2170 #else
2171 #define ST_BIRTHTIME_IDX ST_GEN_IDX
2172 #endif
2173 
2174 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2175 #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
2176 #else
2177 #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
2178 #endif
2179 
2180 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2181 #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2182 #else
2183 #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2184 #endif
2185 
2186 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2187 #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2188 #else
2189 #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2190 #endif
2191 
2192 static PyStructSequence_Desc stat_result_desc = {
2193     "stat_result", /* name */
2194     stat_result__doc__, /* doc */
2195     stat_result_fields,
2196     10
2197 };
2198 
2199 PyDoc_STRVAR(statvfs_result__doc__,
2200 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
2201 This object may be accessed either as a tuple of\n\
2202   (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2203 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2204 \n\
2205 See os.statvfs for more information.");
2206 
2207 static PyStructSequence_Field statvfs_result_fields[] = {
2208     {"f_bsize",  },
2209     {"f_frsize", },
2210     {"f_blocks", },
2211     {"f_bfree",  },
2212     {"f_bavail", },
2213     {"f_files",  },
2214     {"f_ffree",  },
2215     {"f_favail", },
2216     {"f_flag",   },
2217     {"f_namemax",},
2218     {"f_fsid",   },
2219     {0}
2220 };
2221 
2222 static PyStructSequence_Desc statvfs_result_desc = {
2223     "statvfs_result", /* name */
2224     statvfs_result__doc__, /* doc */
2225     statvfs_result_fields,
2226     10
2227 };
2228 
2229 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2230 PyDoc_STRVAR(waitid_result__doc__,
2231 "waitid_result: Result from waitid.\n\n\
2232 This object may be accessed either as a tuple of\n\
2233   (si_pid, si_uid, si_signo, si_status, si_code),\n\
2234 or via the attributes si_pid, si_uid, and so on.\n\
2235 \n\
2236 See os.waitid for more information.");
2237 
2238 static PyStructSequence_Field waitid_result_fields[] = {
2239     {"si_pid",  },
2240     {"si_uid", },
2241     {"si_signo", },
2242     {"si_status",  },
2243     {"si_code", },
2244     {0}
2245 };
2246 
2247 static PyStructSequence_Desc waitid_result_desc = {
2248     "waitid_result", /* name */
2249     waitid_result__doc__, /* doc */
2250     waitid_result_fields,
2251     5
2252 };
2253 #endif
2254 static newfunc structseq_new;
2255 
2256 static PyObject *
statresult_new(PyTypeObject * type,PyObject * args,PyObject * kwds)2257 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2258 {
2259     PyStructSequence *result;
2260     int i;
2261 
2262     result = (PyStructSequence*)structseq_new(type, args, kwds);
2263     if (!result)
2264         return NULL;
2265     /* If we have been initialized from a tuple,
2266        st_?time might be set to None. Initialize it
2267        from the int slots.  */
2268     for (i = 7; i <= 9; i++) {
2269         if (result->ob_item[i+3] == Py_None) {
2270             Py_DECREF(Py_None);
2271             Py_INCREF(result->ob_item[i]);
2272             result->ob_item[i+3] = result->ob_item[i];
2273         }
2274     }
2275     return (PyObject*)result;
2276 }
2277 
2278 static int
_posix_clear(PyObject * module)2279 _posix_clear(PyObject *module)
2280 {
2281     _posixstate *state = get_posix_state(module);
2282     Py_CLEAR(state->billion);
2283     Py_CLEAR(state->DirEntryType);
2284     Py_CLEAR(state->ScandirIteratorType);
2285 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2286     Py_CLEAR(state->SchedParamType);
2287 #endif
2288     Py_CLEAR(state->StatResultType);
2289     Py_CLEAR(state->StatVFSResultType);
2290     Py_CLEAR(state->TerminalSizeType);
2291     Py_CLEAR(state->TimesResultType);
2292     Py_CLEAR(state->UnameResultType);
2293 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2294     Py_CLEAR(state->WaitidResultType);
2295 #endif
2296 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2297     Py_CLEAR(state->struct_rusage);
2298 #endif
2299     Py_CLEAR(state->st_mode);
2300     return 0;
2301 }
2302 
2303 static int
_posix_traverse(PyObject * module,visitproc visit,void * arg)2304 _posix_traverse(PyObject *module, visitproc visit, void *arg)
2305 {
2306     _posixstate *state = get_posix_state(module);
2307     Py_VISIT(state->billion);
2308     Py_VISIT(state->DirEntryType);
2309     Py_VISIT(state->ScandirIteratorType);
2310 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2311     Py_VISIT(state->SchedParamType);
2312 #endif
2313     Py_VISIT(state->StatResultType);
2314     Py_VISIT(state->StatVFSResultType);
2315     Py_VISIT(state->TerminalSizeType);
2316     Py_VISIT(state->TimesResultType);
2317     Py_VISIT(state->UnameResultType);
2318 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2319     Py_VISIT(state->WaitidResultType);
2320 #endif
2321 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2322     Py_VISIT(state->struct_rusage);
2323 #endif
2324     Py_VISIT(state->st_mode);
2325     return 0;
2326 }
2327 
2328 static void
_posix_free(void * module)2329 _posix_free(void *module)
2330 {
2331    _posix_clear((PyObject *)module);
2332 }
2333 
2334 static void
fill_time(PyObject * module,PyObject * v,int index,time_t sec,unsigned long nsec)2335 fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)
2336 {
2337     PyObject *s = _PyLong_FromTime_t(sec);
2338     PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2339     PyObject *s_in_ns = NULL;
2340     PyObject *ns_total = NULL;
2341     PyObject *float_s = NULL;
2342 
2343     if (!(s && ns_fractional))
2344         goto exit;
2345 
2346     s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2347     if (!s_in_ns)
2348         goto exit;
2349 
2350     ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2351     if (!ns_total)
2352         goto exit;
2353 
2354     float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2355     if (!float_s) {
2356         goto exit;
2357     }
2358 
2359     PyStructSequence_SET_ITEM(v, index, s);
2360     PyStructSequence_SET_ITEM(v, index+3, float_s);
2361     PyStructSequence_SET_ITEM(v, index+6, ns_total);
2362     s = NULL;
2363     float_s = NULL;
2364     ns_total = NULL;
2365 exit:
2366     Py_XDECREF(s);
2367     Py_XDECREF(ns_fractional);
2368     Py_XDECREF(s_in_ns);
2369     Py_XDECREF(ns_total);
2370     Py_XDECREF(float_s);
2371 }
2372 
2373 /* pack a system stat C structure into the Python stat tuple
2374    (used by posix_stat() and posix_fstat()) */
2375 static PyObject*
_pystat_fromstructstat(PyObject * module,STRUCT_STAT * st)2376 _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2377 {
2378     unsigned long ansec, mnsec, cnsec;
2379     PyObject *StatResultType = get_posix_state(module)->StatResultType;
2380     PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2381     if (v == NULL)
2382         return NULL;
2383 
2384     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2385     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(st->st_ino));
2386     PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2387 #ifdef MS_WINDOWS
2388     PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
2389 #else
2390     PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2391 #endif
2392     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2393 #if defined(MS_WINDOWS)
2394     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2395     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2396 #else
2397     PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2398     PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2399 #endif
2400     Py_BUILD_ASSERT(sizeof(long long) >= sizeof(st->st_size));
2401     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2402 
2403 #if defined(HAVE_STAT_TV_NSEC)
2404     ansec = st->st_atim.tv_nsec;
2405     mnsec = st->st_mtim.tv_nsec;
2406     cnsec = st->st_ctim.tv_nsec;
2407 #elif defined(HAVE_STAT_TV_NSEC2)
2408     ansec = st->st_atimespec.tv_nsec;
2409     mnsec = st->st_mtimespec.tv_nsec;
2410     cnsec = st->st_ctimespec.tv_nsec;
2411 #elif defined(HAVE_STAT_NSEC)
2412     ansec = st->st_atime_nsec;
2413     mnsec = st->st_mtime_nsec;
2414     cnsec = st->st_ctime_nsec;
2415 #else
2416     ansec = mnsec = cnsec = 0;
2417 #endif
2418     fill_time(module, v, 7, st->st_atime, ansec);
2419     fill_time(module, v, 8, st->st_mtime, mnsec);
2420     fill_time(module, v, 9, st->st_ctime, cnsec);
2421 
2422 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2423     PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2424                               PyLong_FromLong((long)st->st_blksize));
2425 #endif
2426 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2427     PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2428                               PyLong_FromLong((long)st->st_blocks));
2429 #endif
2430 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2431     PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2432                               PyLong_FromLong((long)st->st_rdev));
2433 #endif
2434 #ifdef HAVE_STRUCT_STAT_ST_GEN
2435     PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2436                               PyLong_FromLong((long)st->st_gen));
2437 #endif
2438 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2439     {
2440       PyObject *val;
2441       unsigned long bsec,bnsec;
2442       bsec = (long)st->st_birthtime;
2443 #ifdef HAVE_STAT_TV_NSEC2
2444       bnsec = st->st_birthtimespec.tv_nsec;
2445 #else
2446       bnsec = 0;
2447 #endif
2448       val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2449       PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2450                                 val);
2451     }
2452 #endif
2453 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2454     PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2455                               PyLong_FromLong((long)st->st_flags));
2456 #endif
2457 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2458     PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2459                               PyLong_FromUnsignedLong(st->st_file_attributes));
2460 #endif
2461 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2462    PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2463                               PyUnicode_FromString(st->st_fstype));
2464 #endif
2465 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2466     PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2467                               PyLong_FromUnsignedLong(st->st_reparse_tag));
2468 #endif
2469 
2470     if (PyErr_Occurred()) {
2471         Py_DECREF(v);
2472         return NULL;
2473     }
2474 
2475     return v;
2476 }
2477 
2478 /* POSIX methods */
2479 
2480 
2481 static PyObject *
posix_do_stat(PyObject * module,const char * function_name,path_t * path,int dir_fd,int follow_symlinks)2482 posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2483               int dir_fd, int follow_symlinks)
2484 {
2485     STRUCT_STAT st;
2486     int result;
2487 
2488 #ifdef HAVE_FSTATAT
2489     int fstatat_unavailable = 0;
2490 #endif
2491 
2492 #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2493     if (follow_symlinks_specified(function_name, follow_symlinks))
2494         return NULL;
2495 #endif
2496 
2497     if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2498         dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2499         fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2500         return NULL;
2501 
2502     Py_BEGIN_ALLOW_THREADS
2503     if (path->fd != -1)
2504         result = FSTAT(path->fd, &st);
2505 #ifdef MS_WINDOWS
2506     else if (follow_symlinks)
2507         result = win32_stat(path->wide, &st);
2508     else
2509         result = win32_lstat(path->wide, &st);
2510 #else
2511     else
2512 #if defined(HAVE_LSTAT)
2513     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2514         result = LSTAT(path->narrow, &st);
2515     else
2516 #endif /* HAVE_LSTAT */
2517 #ifdef HAVE_FSTATAT
2518     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2519         if (HAVE_FSTATAT_RUNTIME) {
2520             result = fstatat(dir_fd, path->narrow, &st,
2521                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2522 
2523         } else {
2524             fstatat_unavailable = 1;
2525         }
2526     } else
2527 #endif /* HAVE_FSTATAT */
2528         result = STAT(path->narrow, &st);
2529 #endif /* MS_WINDOWS */
2530     Py_END_ALLOW_THREADS
2531 
2532 #ifdef HAVE_FSTATAT
2533     if (fstatat_unavailable) {
2534         argument_unavailable_error("stat", "dir_fd");
2535         return NULL;
2536     }
2537 #endif
2538 
2539     if (result != 0) {
2540         return path_error(path);
2541     }
2542 
2543     return _pystat_fromstructstat(module, &st);
2544 }
2545 
2546 /*[python input]
2547 
2548 for s in """
2549 
2550 FACCESSAT
2551 FCHMODAT
2552 FCHOWNAT
2553 FSTATAT
2554 LINKAT
2555 MKDIRAT
2556 MKFIFOAT
2557 MKNODAT
2558 OPENAT
2559 READLINKAT
2560 SYMLINKAT
2561 UNLINKAT
2562 
2563 """.strip().split():
2564     s = s.strip()
2565     print("""
2566 #ifdef HAVE_{s}
2567     #define {s}_DIR_FD_CONVERTER dir_fd_converter
2568 #else
2569     #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2570 #endif
2571 """.rstrip().format(s=s))
2572 
2573 for s in """
2574 
2575 FCHDIR
2576 FCHMOD
2577 FCHOWN
2578 FDOPENDIR
2579 FEXECVE
2580 FPATHCONF
2581 FSTATVFS
2582 FTRUNCATE
2583 
2584 """.strip().split():
2585     s = s.strip()
2586     print("""
2587 #ifdef HAVE_{s}
2588     #define PATH_HAVE_{s} 1
2589 #else
2590     #define PATH_HAVE_{s} 0
2591 #endif
2592 
2593 """.rstrip().format(s=s))
2594 [python start generated code]*/
2595 
2596 #ifdef HAVE_FACCESSAT
2597     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2598 #else
2599     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2600 #endif
2601 
2602 #ifdef HAVE_FCHMODAT
2603     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2604 #else
2605     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2606 #endif
2607 
2608 #ifdef HAVE_FCHOWNAT
2609     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2610 #else
2611     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2612 #endif
2613 
2614 #ifdef HAVE_FSTATAT
2615     #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2616 #else
2617     #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2618 #endif
2619 
2620 #ifdef HAVE_LINKAT
2621     #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2622 #else
2623     #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2624 #endif
2625 
2626 #ifdef HAVE_MKDIRAT
2627     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2628 #else
2629     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2630 #endif
2631 
2632 #ifdef HAVE_MKFIFOAT
2633     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2634 #else
2635     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2636 #endif
2637 
2638 #ifdef HAVE_MKNODAT
2639     #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2640 #else
2641     #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2642 #endif
2643 
2644 #ifdef HAVE_OPENAT
2645     #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2646 #else
2647     #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2648 #endif
2649 
2650 #ifdef HAVE_READLINKAT
2651     #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2652 #else
2653     #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2654 #endif
2655 
2656 #ifdef HAVE_SYMLINKAT
2657     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2658 #else
2659     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2660 #endif
2661 
2662 #ifdef HAVE_UNLINKAT
2663     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2664 #else
2665     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2666 #endif
2667 
2668 #ifdef HAVE_FCHDIR
2669     #define PATH_HAVE_FCHDIR 1
2670 #else
2671     #define PATH_HAVE_FCHDIR 0
2672 #endif
2673 
2674 #ifdef HAVE_FCHMOD
2675     #define PATH_HAVE_FCHMOD 1
2676 #else
2677     #define PATH_HAVE_FCHMOD 0
2678 #endif
2679 
2680 #ifdef HAVE_FCHOWN
2681     #define PATH_HAVE_FCHOWN 1
2682 #else
2683     #define PATH_HAVE_FCHOWN 0
2684 #endif
2685 
2686 #ifdef HAVE_FDOPENDIR
2687     #define PATH_HAVE_FDOPENDIR 1
2688 #else
2689     #define PATH_HAVE_FDOPENDIR 0
2690 #endif
2691 
2692 #ifdef HAVE_FEXECVE
2693     #define PATH_HAVE_FEXECVE 1
2694 #else
2695     #define PATH_HAVE_FEXECVE 0
2696 #endif
2697 
2698 #ifdef HAVE_FPATHCONF
2699     #define PATH_HAVE_FPATHCONF 1
2700 #else
2701     #define PATH_HAVE_FPATHCONF 0
2702 #endif
2703 
2704 #ifdef HAVE_FSTATVFS
2705     #define PATH_HAVE_FSTATVFS 1
2706 #else
2707     #define PATH_HAVE_FSTATVFS 0
2708 #endif
2709 
2710 #ifdef HAVE_FTRUNCATE
2711     #define PATH_HAVE_FTRUNCATE 1
2712 #else
2713     #define PATH_HAVE_FTRUNCATE 0
2714 #endif
2715 /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2716 
2717 #ifdef MS_WINDOWS
2718     #undef PATH_HAVE_FTRUNCATE
2719     #define PATH_HAVE_FTRUNCATE 1
2720 #endif
2721 
2722 /*[python input]
2723 
2724 class path_t_converter(CConverter):
2725 
2726     type = "path_t"
2727     impl_by_reference = True
2728     parse_by_reference = True
2729 
2730     converter = 'path_converter'
2731 
2732     def converter_init(self, *, allow_fd=False, nullable=False):
2733         # right now path_t doesn't support default values.
2734         # to support a default value, you'll need to override initialize().
2735         if self.default not in (unspecified, None):
2736             fail("Can't specify a default to the path_t converter!")
2737 
2738         if self.c_default not in (None, 'Py_None'):
2739             raise RuntimeError("Can't specify a c_default to the path_t converter!")
2740 
2741         self.nullable = nullable
2742         self.allow_fd = allow_fd
2743 
2744     def pre_render(self):
2745         def strify(value):
2746             if isinstance(value, str):
2747                 return value
2748             return str(int(bool(value)))
2749 
2750         # add self.py_name here when merging with posixmodule conversion
2751         self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2752             self.function.name,
2753             self.name,
2754             strify(self.nullable),
2755             strify(self.allow_fd),
2756             )
2757 
2758     def cleanup(self):
2759         return "path_cleanup(&" + self.name + ");\n"
2760 
2761 
2762 class dir_fd_converter(CConverter):
2763     type = 'int'
2764 
2765     def converter_init(self, requires=None):
2766         if self.default in (unspecified, None):
2767             self.c_default = 'DEFAULT_DIR_FD'
2768         if isinstance(requires, str):
2769             self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2770         else:
2771             self.converter = 'dir_fd_converter'
2772 
2773 class uid_t_converter(CConverter):
2774     type = "uid_t"
2775     converter = '_Py_Uid_Converter'
2776 
2777 class gid_t_converter(CConverter):
2778     type = "gid_t"
2779     converter = '_Py_Gid_Converter'
2780 
2781 class dev_t_converter(CConverter):
2782     type = 'dev_t'
2783     converter = '_Py_Dev_Converter'
2784 
2785 class dev_t_return_converter(unsigned_long_return_converter):
2786     type = 'dev_t'
2787     conversion_fn = '_PyLong_FromDev'
2788     unsigned_cast = '(dev_t)'
2789 
2790 class FSConverter_converter(CConverter):
2791     type = 'PyObject *'
2792     converter = 'PyUnicode_FSConverter'
2793     def converter_init(self):
2794         if self.default is not unspecified:
2795             fail("FSConverter_converter does not support default values")
2796         self.c_default = 'NULL'
2797 
2798     def cleanup(self):
2799         return "Py_XDECREF(" + self.name + ");\n"
2800 
2801 class pid_t_converter(CConverter):
2802     type = 'pid_t'
2803     format_unit = '" _Py_PARSE_PID "'
2804 
2805 class idtype_t_converter(int_converter):
2806     type = 'idtype_t'
2807 
2808 class id_t_converter(CConverter):
2809     type = 'id_t'
2810     format_unit = '" _Py_PARSE_PID "'
2811 
2812 class intptr_t_converter(CConverter):
2813     type = 'intptr_t'
2814     format_unit = '" _Py_PARSE_INTPTR "'
2815 
2816 class Py_off_t_converter(CConverter):
2817     type = 'Py_off_t'
2818     converter = 'Py_off_t_converter'
2819 
2820 class Py_off_t_return_converter(long_return_converter):
2821     type = 'Py_off_t'
2822     conversion_fn = 'PyLong_FromPy_off_t'
2823 
2824 class path_confname_converter(CConverter):
2825     type="int"
2826     converter="conv_path_confname"
2827 
2828 class confstr_confname_converter(path_confname_converter):
2829     converter='conv_confstr_confname'
2830 
2831 class sysconf_confname_converter(path_confname_converter):
2832     converter="conv_sysconf_confname"
2833 
2834 [python start generated code]*/
2835 /*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/
2836 
2837 /*[clinic input]
2838 
2839 os.stat
2840 
2841     path : path_t(allow_fd=True)
2842         Path to be examined; can be string, bytes, a path-like object or
2843         open-file-descriptor int.
2844 
2845     *
2846 
2847     dir_fd : dir_fd(requires='fstatat') = None
2848         If not None, it should be a file descriptor open to a directory,
2849         and path should be a relative string; path will then be relative to
2850         that directory.
2851 
2852     follow_symlinks: bool = True
2853         If False, and the last element of the path is a symbolic link,
2854         stat will examine the symbolic link itself instead of the file
2855         the link points to.
2856 
2857 Perform a stat system call on the given path.
2858 
2859 dir_fd and follow_symlinks may not be implemented
2860   on your platform.  If they are unavailable, using them will raise a
2861   NotImplementedError.
2862 
2863 It's an error to use dir_fd or follow_symlinks when specifying path as
2864   an open file descriptor.
2865 
2866 [clinic start generated code]*/
2867 
2868 static PyObject *
os_stat_impl(PyObject * module,path_t * path,int dir_fd,int follow_symlinks)2869 os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2870 /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2871 {
2872     return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
2873 }
2874 
2875 
2876 /*[clinic input]
2877 os.lstat
2878 
2879     path : path_t
2880 
2881     *
2882 
2883     dir_fd : dir_fd(requires='fstatat') = None
2884 
2885 Perform a stat system call on the given path, without following symbolic links.
2886 
2887 Like stat(), but do not follow symbolic links.
2888 Equivalent to stat(path, follow_symlinks=False).
2889 [clinic start generated code]*/
2890 
2891 static PyObject *
os_lstat_impl(PyObject * module,path_t * path,int dir_fd)2892 os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2893 /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2894 {
2895     int follow_symlinks = 0;
2896     return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
2897 }
2898 
2899 
2900 /*[clinic input]
2901 os.access -> bool
2902 
2903     path: path_t
2904         Path to be tested; can be string, bytes, or a path-like object.
2905 
2906     mode: int
2907         Operating-system mode bitfield.  Can be F_OK to test existence,
2908         or the inclusive-OR of R_OK, W_OK, and X_OK.
2909 
2910     *
2911 
2912     dir_fd : dir_fd(requires='faccessat') = None
2913         If not None, it should be a file descriptor open to a directory,
2914         and path should be relative; path will then be relative to that
2915         directory.
2916 
2917     effective_ids: bool = False
2918         If True, access will use the effective uid/gid instead of
2919         the real uid/gid.
2920 
2921     follow_symlinks: bool = True
2922         If False, and the last element of the path is a symbolic link,
2923         access will examine the symbolic link itself instead of the file
2924         the link points to.
2925 
2926 Use the real uid/gid to test for access to a path.
2927 
2928 {parameters}
2929 dir_fd, effective_ids, and follow_symlinks may not be implemented
2930   on your platform.  If they are unavailable, using them will raise a
2931   NotImplementedError.
2932 
2933 Note that most operations will use the effective uid/gid, therefore this
2934   routine can be used in a suid/sgid environment to test if the invoking user
2935   has the specified access to the path.
2936 
2937 [clinic start generated code]*/
2938 
2939 static int
os_access_impl(PyObject * module,path_t * path,int mode,int dir_fd,int effective_ids,int follow_symlinks)2940 os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2941                int effective_ids, int follow_symlinks)
2942 /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
2943 {
2944     int return_value;
2945 
2946 #ifdef MS_WINDOWS
2947     DWORD attr;
2948 #else
2949     int result;
2950 #endif
2951 
2952 #ifdef HAVE_FACCESSAT
2953     int faccessat_unavailable = 0;
2954 #endif
2955 
2956 #ifndef HAVE_FACCESSAT
2957     if (follow_symlinks_specified("access", follow_symlinks))
2958         return -1;
2959 
2960     if (effective_ids) {
2961         argument_unavailable_error("access", "effective_ids");
2962         return -1;
2963     }
2964 #endif
2965 
2966 #ifdef MS_WINDOWS
2967     Py_BEGIN_ALLOW_THREADS
2968     attr = GetFileAttributesW(path->wide);
2969     Py_END_ALLOW_THREADS
2970 
2971     /*
2972      * Access is possible if
2973      *   * we didn't get a -1, and
2974      *     * write access wasn't requested,
2975      *     * or the file isn't read-only,
2976      *     * or it's a directory.
2977      * (Directories cannot be read-only on Windows.)
2978     */
2979     return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
2980             (!(mode & 2) ||
2981             !(attr & FILE_ATTRIBUTE_READONLY) ||
2982             (attr & FILE_ATTRIBUTE_DIRECTORY));
2983 #else
2984 
2985     Py_BEGIN_ALLOW_THREADS
2986 #ifdef HAVE_FACCESSAT
2987     if ((dir_fd != DEFAULT_DIR_FD) ||
2988         effective_ids ||
2989         !follow_symlinks) {
2990 
2991         if (HAVE_FACCESSAT_RUNTIME) {
2992             int flags = 0;
2993             if (!follow_symlinks)
2994                 flags |= AT_SYMLINK_NOFOLLOW;
2995             if (effective_ids)
2996                 flags |= AT_EACCESS;
2997             result = faccessat(dir_fd, path->narrow, mode, flags);
2998         } else {
2999             faccessat_unavailable = 1;
3000         }
3001     }
3002     else
3003 #endif
3004         result = access(path->narrow, mode);
3005     Py_END_ALLOW_THREADS
3006 
3007 #ifdef HAVE_FACCESSAT
3008     if (faccessat_unavailable) {
3009         if (dir_fd != DEFAULT_DIR_FD) {
3010             argument_unavailable_error("access", "dir_fd");
3011             return -1;
3012         }
3013         if (follow_symlinks_specified("access", follow_symlinks))
3014             return -1;
3015 
3016         if (effective_ids) {
3017             argument_unavailable_error("access", "effective_ids");
3018             return -1;
3019         }
3020         /* should be unreachable */
3021         return -1;
3022     }
3023 #endif
3024     return_value = !result;
3025 #endif
3026 
3027     return return_value;
3028 }
3029 
3030 #ifndef F_OK
3031 #define F_OK 0
3032 #endif
3033 #ifndef R_OK
3034 #define R_OK 4
3035 #endif
3036 #ifndef W_OK
3037 #define W_OK 2
3038 #endif
3039 #ifndef X_OK
3040 #define X_OK 1
3041 #endif
3042 
3043 
3044 #ifdef HAVE_TTYNAME
3045 /*[clinic input]
3046 os.ttyname
3047 
3048     fd: int
3049         Integer file descriptor handle.
3050 
3051     /
3052 
3053 Return the name of the terminal device connected to 'fd'.
3054 [clinic start generated code]*/
3055 
3056 static PyObject *
os_ttyname_impl(PyObject * module,int fd)3057 os_ttyname_impl(PyObject *module, int fd)
3058 /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3059 {
3060 
3061     long size = sysconf(_SC_TTY_NAME_MAX);
3062     if (size == -1) {
3063         return posix_error();
3064     }
3065     char *buffer = (char *)PyMem_RawMalloc(size);
3066     if (buffer == NULL) {
3067         return PyErr_NoMemory();
3068     }
3069     int ret = ttyname_r(fd, buffer, size);
3070     if (ret != 0) {
3071         PyMem_RawFree(buffer);
3072         errno = ret;
3073         return posix_error();
3074     }
3075     PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3076     PyMem_RawFree(buffer);
3077     return res;
3078 }
3079 #endif
3080 
3081 #ifdef HAVE_CTERMID
3082 /*[clinic input]
3083 os.ctermid
3084 
3085 Return the name of the controlling terminal for this process.
3086 [clinic start generated code]*/
3087 
3088 static PyObject *
os_ctermid_impl(PyObject * module)3089 os_ctermid_impl(PyObject *module)
3090 /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3091 {
3092     char *ret;
3093     char buffer[L_ctermid];
3094 
3095 #ifdef USE_CTERMID_R
3096     ret = ctermid_r(buffer);
3097 #else
3098     ret = ctermid(buffer);
3099 #endif
3100     if (ret == NULL)
3101         return posix_error();
3102     return PyUnicode_DecodeFSDefault(buffer);
3103 }
3104 #endif /* HAVE_CTERMID */
3105 
3106 
3107 /*[clinic input]
3108 os.chdir
3109 
3110     path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3111 
3112 Change the current working directory to the specified path.
3113 
3114 path may always be specified as a string.
3115 On some platforms, path may also be specified as an open file descriptor.
3116   If this functionality is unavailable, using it raises an exception.
3117 [clinic start generated code]*/
3118 
3119 static PyObject *
os_chdir_impl(PyObject * module,path_t * path)3120 os_chdir_impl(PyObject *module, path_t *path)
3121 /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3122 {
3123     int result;
3124 
3125     if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3126         return NULL;
3127     }
3128 
3129     Py_BEGIN_ALLOW_THREADS
3130 #ifdef MS_WINDOWS
3131     /* on unix, success = 0, on windows, success = !0 */
3132     result = !win32_wchdir(path->wide);
3133 #else
3134 #ifdef HAVE_FCHDIR
3135     if (path->fd != -1)
3136         result = fchdir(path->fd);
3137     else
3138 #endif
3139         result = chdir(path->narrow);
3140 #endif
3141     Py_END_ALLOW_THREADS
3142 
3143     if (result) {
3144         return path_error(path);
3145     }
3146 
3147     Py_RETURN_NONE;
3148 }
3149 
3150 
3151 #ifdef HAVE_FCHDIR
3152 /*[clinic input]
3153 os.fchdir
3154 
3155     fd: fildes
3156 
3157 Change to the directory of the given file descriptor.
3158 
3159 fd must be opened on a directory, not a file.
3160 Equivalent to os.chdir(fd).
3161 
3162 [clinic start generated code]*/
3163 
3164 static PyObject *
os_fchdir_impl(PyObject * module,int fd)3165 os_fchdir_impl(PyObject *module, int fd)
3166 /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3167 {
3168     if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3169         return NULL;
3170     }
3171     return posix_fildes_fd(fd, fchdir);
3172 }
3173 #endif /* HAVE_FCHDIR */
3174 
3175 
3176 /*[clinic input]
3177 os.chmod
3178 
3179     path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3180         Path to be modified.  May always be specified as a str, bytes, or a path-like object.
3181         On some platforms, path may also be specified as an open file descriptor.
3182         If this functionality is unavailable, using it raises an exception.
3183 
3184     mode: int
3185         Operating-system mode bitfield.
3186 
3187     *
3188 
3189     dir_fd : dir_fd(requires='fchmodat') = None
3190         If not None, it should be a file descriptor open to a directory,
3191         and path should be relative; path will then be relative to that
3192         directory.
3193 
3194     follow_symlinks: bool = True
3195         If False, and the last element of the path is a symbolic link,
3196         chmod will modify the symbolic link itself instead of the file
3197         the link points to.
3198 
3199 Change the access permissions of a file.
3200 
3201 It is an error to use dir_fd or follow_symlinks when specifying path as
3202   an open file descriptor.
3203 dir_fd and follow_symlinks may not be implemented on your platform.
3204   If they are unavailable, using them will raise a NotImplementedError.
3205 
3206 [clinic start generated code]*/
3207 
3208 static PyObject *
os_chmod_impl(PyObject * module,path_t * path,int mode,int dir_fd,int follow_symlinks)3209 os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3210               int follow_symlinks)
3211 /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
3212 {
3213     int result;
3214 
3215 #ifdef MS_WINDOWS
3216     DWORD attr;
3217 #endif
3218 
3219 #ifdef HAVE_FCHMODAT
3220     int fchmodat_nofollow_unsupported = 0;
3221     int fchmodat_unsupported = 0;
3222 #endif
3223 
3224 #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
3225     if (follow_symlinks_specified("chmod", follow_symlinks))
3226         return NULL;
3227 #endif
3228 
3229     if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3230                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3231         return NULL;
3232     }
3233 
3234 #ifdef MS_WINDOWS
3235     Py_BEGIN_ALLOW_THREADS
3236     attr = GetFileAttributesW(path->wide);
3237     if (attr == INVALID_FILE_ATTRIBUTES)
3238         result = 0;
3239     else {
3240         if (mode & _S_IWRITE)
3241             attr &= ~FILE_ATTRIBUTE_READONLY;
3242         else
3243             attr |= FILE_ATTRIBUTE_READONLY;
3244         result = SetFileAttributesW(path->wide, attr);
3245     }
3246     Py_END_ALLOW_THREADS
3247 
3248     if (!result) {
3249         return path_error(path);
3250     }
3251 #else /* MS_WINDOWS */
3252     Py_BEGIN_ALLOW_THREADS
3253 #ifdef HAVE_FCHMOD
3254     if (path->fd != -1)
3255         result = fchmod(path->fd, mode);
3256     else
3257 #endif /* HAVE_CHMOD */
3258 #ifdef HAVE_LCHMOD
3259     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3260         result = lchmod(path->narrow, mode);
3261     else
3262 #endif /* HAVE_LCHMOD */
3263 #ifdef HAVE_FCHMODAT
3264     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3265         if (HAVE_FCHMODAT_RUNTIME) {
3266             /*
3267              * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3268              * The documentation specifically shows how to use it,
3269              * and then says it isn't implemented yet.
3270              * (true on linux with glibc 2.15, and openindiana 3.x)
3271              *
3272              * Once it is supported, os.chmod will automatically
3273              * support dir_fd and follow_symlinks=False.  (Hopefully.)
3274              * Until then, we need to be careful what exception we raise.
3275              */
3276             result = fchmodat(dir_fd, path->narrow, mode,
3277                               follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3278             /*
3279              * But wait!  We can't throw the exception without allowing threads,
3280              * and we can't do that in this nested scope.  (Macro trickery, sigh.)
3281              */
3282             fchmodat_nofollow_unsupported =
3283                              result &&
3284                              ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3285                              !follow_symlinks;
3286         } else {
3287             fchmodat_unsupported = 1;
3288             fchmodat_nofollow_unsupported = 1;
3289 
3290             result = -1;
3291         }
3292     }
3293     else
3294 #endif /* HAVE_FHCMODAT */
3295         result = chmod(path->narrow, mode);
3296     Py_END_ALLOW_THREADS
3297 
3298     if (result) {
3299 #ifdef HAVE_FCHMODAT
3300         if (fchmodat_unsupported) {
3301             if (dir_fd != DEFAULT_DIR_FD) {
3302                 argument_unavailable_error("chmod", "dir_fd");
3303                 return NULL;
3304             }
3305         }
3306 
3307         if (fchmodat_nofollow_unsupported) {
3308             if (dir_fd != DEFAULT_DIR_FD)
3309                 dir_fd_and_follow_symlinks_invalid("chmod",
3310                                                    dir_fd, follow_symlinks);
3311             else
3312                 follow_symlinks_specified("chmod", follow_symlinks);
3313             return NULL;
3314         }
3315         else
3316 #endif /* HAVE_FCHMODAT */
3317         return path_error(path);
3318     }
3319 #endif /* MS_WINDOWS */
3320 
3321     Py_RETURN_NONE;
3322 }
3323 
3324 
3325 #ifdef HAVE_FCHMOD
3326 /*[clinic input]
3327 os.fchmod
3328 
3329     fd: int
3330     mode: int
3331 
3332 Change the access permissions of the file given by file descriptor fd.
3333 
3334 Equivalent to os.chmod(fd, mode).
3335 [clinic start generated code]*/
3336 
3337 static PyObject *
os_fchmod_impl(PyObject * module,int fd,int mode)3338 os_fchmod_impl(PyObject *module, int fd, int mode)
3339 /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
3340 {
3341     int res;
3342     int async_err = 0;
3343 
3344     if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3345         return NULL;
3346     }
3347 
3348     do {
3349         Py_BEGIN_ALLOW_THREADS
3350         res = fchmod(fd, mode);
3351         Py_END_ALLOW_THREADS
3352     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3353     if (res != 0)
3354         return (!async_err) ? posix_error() : NULL;
3355 
3356     Py_RETURN_NONE;
3357 }
3358 #endif /* HAVE_FCHMOD */
3359 
3360 
3361 #ifdef HAVE_LCHMOD
3362 /*[clinic input]
3363 os.lchmod
3364 
3365     path: path_t
3366     mode: int
3367 
3368 Change the access permissions of a file, without following symbolic links.
3369 
3370 If path is a symlink, this affects the link itself rather than the target.
3371 Equivalent to chmod(path, mode, follow_symlinks=False)."
3372 [clinic start generated code]*/
3373 
3374 static PyObject *
os_lchmod_impl(PyObject * module,path_t * path,int mode)3375 os_lchmod_impl(PyObject *module, path_t *path, int mode)
3376 /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3377 {
3378     int res;
3379     if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3380         return NULL;
3381     }
3382     Py_BEGIN_ALLOW_THREADS
3383     res = lchmod(path->narrow, mode);
3384     Py_END_ALLOW_THREADS
3385     if (res < 0) {
3386         path_error(path);
3387         return NULL;
3388     }
3389     Py_RETURN_NONE;
3390 }
3391 #endif /* HAVE_LCHMOD */
3392 
3393 
3394 #ifdef HAVE_CHFLAGS
3395 /*[clinic input]
3396 os.chflags
3397 
3398     path: path_t
3399     flags: unsigned_long(bitwise=True)
3400     follow_symlinks: bool=True
3401 
3402 Set file flags.
3403 
3404 If follow_symlinks is False, and the last element of the path is a symbolic
3405   link, chflags will change flags on the symbolic link itself instead of the
3406   file the link points to.
3407 follow_symlinks may not be implemented on your platform.  If it is
3408 unavailable, using it will raise a NotImplementedError.
3409 
3410 [clinic start generated code]*/
3411 
3412 static PyObject *
os_chflags_impl(PyObject * module,path_t * path,unsigned long flags,int follow_symlinks)3413 os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3414                 int follow_symlinks)
3415 /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3416 {
3417     int result;
3418 
3419 #ifndef HAVE_LCHFLAGS
3420     if (follow_symlinks_specified("chflags", follow_symlinks))
3421         return NULL;
3422 #endif
3423 
3424     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3425         return NULL;
3426     }
3427 
3428     Py_BEGIN_ALLOW_THREADS
3429 #ifdef HAVE_LCHFLAGS
3430     if (!follow_symlinks)
3431         result = lchflags(path->narrow, flags);
3432     else
3433 #endif
3434         result = chflags(path->narrow, flags);
3435     Py_END_ALLOW_THREADS
3436 
3437     if (result)
3438         return path_error(path);
3439 
3440     Py_RETURN_NONE;
3441 }
3442 #endif /* HAVE_CHFLAGS */
3443 
3444 
3445 #ifdef HAVE_LCHFLAGS
3446 /*[clinic input]
3447 os.lchflags
3448 
3449     path: path_t
3450     flags: unsigned_long(bitwise=True)
3451 
3452 Set file flags.
3453 
3454 This function will not follow symbolic links.
3455 Equivalent to chflags(path, flags, follow_symlinks=False).
3456 [clinic start generated code]*/
3457 
3458 static PyObject *
os_lchflags_impl(PyObject * module,path_t * path,unsigned long flags)3459 os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3460 /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3461 {
3462     int res;
3463     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3464         return NULL;
3465     }
3466     Py_BEGIN_ALLOW_THREADS
3467     res = lchflags(path->narrow, flags);
3468     Py_END_ALLOW_THREADS
3469     if (res < 0) {
3470         return path_error(path);
3471     }
3472     Py_RETURN_NONE;
3473 }
3474 #endif /* HAVE_LCHFLAGS */
3475 
3476 
3477 #ifdef HAVE_CHROOT
3478 /*[clinic input]
3479 os.chroot
3480     path: path_t
3481 
3482 Change root directory to path.
3483 
3484 [clinic start generated code]*/
3485 
3486 static PyObject *
os_chroot_impl(PyObject * module,path_t * path)3487 os_chroot_impl(PyObject *module, path_t *path)
3488 /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3489 {
3490     int res;
3491     Py_BEGIN_ALLOW_THREADS
3492     res = chroot(path->narrow);
3493     Py_END_ALLOW_THREADS
3494     if (res < 0)
3495         return path_error(path);
3496     Py_RETURN_NONE;
3497 }
3498 #endif /* HAVE_CHROOT */
3499 
3500 
3501 #ifdef HAVE_FSYNC
3502 /*[clinic input]
3503 os.fsync
3504 
3505     fd: fildes
3506 
3507 Force write of fd to disk.
3508 [clinic start generated code]*/
3509 
3510 static PyObject *
os_fsync_impl(PyObject * module,int fd)3511 os_fsync_impl(PyObject *module, int fd)
3512 /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3513 {
3514     return posix_fildes_fd(fd, fsync);
3515 }
3516 #endif /* HAVE_FSYNC */
3517 
3518 
3519 #ifdef HAVE_SYNC
3520 /*[clinic input]
3521 os.sync
3522 
3523 Force write of everything to disk.
3524 [clinic start generated code]*/
3525 
3526 static PyObject *
os_sync_impl(PyObject * module)3527 os_sync_impl(PyObject *module)
3528 /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3529 {
3530     Py_BEGIN_ALLOW_THREADS
3531     sync();
3532     Py_END_ALLOW_THREADS
3533     Py_RETURN_NONE;
3534 }
3535 #endif /* HAVE_SYNC */
3536 
3537 
3538 #ifdef HAVE_FDATASYNC
3539 #ifdef __hpux
3540 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3541 #endif
3542 
3543 /*[clinic input]
3544 os.fdatasync
3545 
3546     fd: fildes
3547 
3548 Force write of fd to disk without forcing update of metadata.
3549 [clinic start generated code]*/
3550 
3551 static PyObject *
os_fdatasync_impl(PyObject * module,int fd)3552 os_fdatasync_impl(PyObject *module, int fd)
3553 /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3554 {
3555     return posix_fildes_fd(fd, fdatasync);
3556 }
3557 #endif /* HAVE_FDATASYNC */
3558 
3559 
3560 #ifdef HAVE_CHOWN
3561 /*[clinic input]
3562 os.chown
3563 
3564     path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3565         Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3566 
3567     uid: uid_t
3568 
3569     gid: gid_t
3570 
3571     *
3572 
3573     dir_fd : dir_fd(requires='fchownat') = None
3574         If not None, it should be a file descriptor open to a directory,
3575         and path should be relative; path will then be relative to that
3576         directory.
3577 
3578     follow_symlinks: bool = True
3579         If False, and the last element of the path is a symbolic link,
3580         stat will examine the symbolic link itself instead of the file
3581         the link points to.
3582 
3583 Change the owner and group id of path to the numeric uid and gid.\
3584 
3585 path may always be specified as a string.
3586 On some platforms, path may also be specified as an open file descriptor.
3587   If this functionality is unavailable, using it raises an exception.
3588 If dir_fd is not None, it should be a file descriptor open to a directory,
3589   and path should be relative; path will then be relative to that directory.
3590 If follow_symlinks is False, and the last element of the path is a symbolic
3591   link, chown will modify the symbolic link itself instead of the file the
3592   link points to.
3593 It is an error to use dir_fd or follow_symlinks when specifying path as
3594   an open file descriptor.
3595 dir_fd and follow_symlinks may not be implemented on your platform.
3596   If they are unavailable, using them will raise a NotImplementedError.
3597 
3598 [clinic start generated code]*/
3599 
3600 static PyObject *
os_chown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid,int dir_fd,int follow_symlinks)3601 os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3602               int dir_fd, int follow_symlinks)
3603 /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3604 {
3605     int result;
3606 
3607 #if defined(HAVE_FCHOWNAT)
3608     int fchownat_unsupported = 0;
3609 #endif
3610 
3611 #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3612     if (follow_symlinks_specified("chown", follow_symlinks))
3613         return NULL;
3614 #endif
3615     if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3616         fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3617         return NULL;
3618 
3619     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3620                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3621         return NULL;
3622     }
3623 
3624     Py_BEGIN_ALLOW_THREADS
3625 #ifdef HAVE_FCHOWN
3626     if (path->fd != -1)
3627         result = fchown(path->fd, uid, gid);
3628     else
3629 #endif
3630 #ifdef HAVE_LCHOWN
3631     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3632         result = lchown(path->narrow, uid, gid);
3633     else
3634 #endif
3635 #ifdef HAVE_FCHOWNAT
3636     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
3637       if (HAVE_FCHOWNAT_RUNTIME) {
3638         result = fchownat(dir_fd, path->narrow, uid, gid,
3639                           follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3640       } else {
3641          fchownat_unsupported = 1;
3642       }
3643     } else
3644 #endif
3645         result = chown(path->narrow, uid, gid);
3646     Py_END_ALLOW_THREADS
3647 
3648 #ifdef HAVE_FCHOWNAT
3649     if (fchownat_unsupported) {
3650         /* This would be incorrect if the current platform
3651          * doesn't support lchown.
3652          */
3653         argument_unavailable_error(NULL, "dir_fd");
3654         return NULL;
3655     }
3656 #endif
3657 
3658     if (result)
3659         return path_error(path);
3660 
3661     Py_RETURN_NONE;
3662 }
3663 #endif /* HAVE_CHOWN */
3664 
3665 
3666 #ifdef HAVE_FCHOWN
3667 /*[clinic input]
3668 os.fchown
3669 
3670     fd: int
3671     uid: uid_t
3672     gid: gid_t
3673 
3674 Change the owner and group id of the file specified by file descriptor.
3675 
3676 Equivalent to os.chown(fd, uid, gid).
3677 
3678 [clinic start generated code]*/
3679 
3680 static PyObject *
os_fchown_impl(PyObject * module,int fd,uid_t uid,gid_t gid)3681 os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3682 /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3683 {
3684     int res;
3685     int async_err = 0;
3686 
3687     if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
3688         return NULL;
3689     }
3690 
3691     do {
3692         Py_BEGIN_ALLOW_THREADS
3693         res = fchown(fd, uid, gid);
3694         Py_END_ALLOW_THREADS
3695     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3696     if (res != 0)
3697         return (!async_err) ? posix_error() : NULL;
3698 
3699     Py_RETURN_NONE;
3700 }
3701 #endif /* HAVE_FCHOWN */
3702 
3703 
3704 #ifdef HAVE_LCHOWN
3705 /*[clinic input]
3706 os.lchown
3707 
3708     path : path_t
3709     uid: uid_t
3710     gid: gid_t
3711 
3712 Change the owner and group id of path to the numeric uid and gid.
3713 
3714 This function will not follow symbolic links.
3715 Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3716 [clinic start generated code]*/
3717 
3718 static PyObject *
os_lchown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid)3719 os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3720 /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3721 {
3722     int res;
3723     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
3724         return NULL;
3725     }
3726     Py_BEGIN_ALLOW_THREADS
3727     res = lchown(path->narrow, uid, gid);
3728     Py_END_ALLOW_THREADS
3729     if (res < 0) {
3730         return path_error(path);
3731     }
3732     Py_RETURN_NONE;
3733 }
3734 #endif /* HAVE_LCHOWN */
3735 
3736 
3737 static PyObject *
posix_getcwd(int use_bytes)3738 posix_getcwd(int use_bytes)
3739 {
3740 #ifdef MS_WINDOWS
3741     wchar_t wbuf[MAXPATHLEN];
3742     wchar_t *wbuf2 = wbuf;
3743     DWORD len;
3744 
3745     Py_BEGIN_ALLOW_THREADS
3746     len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3747     /* If the buffer is large enough, len does not include the
3748        terminating \0. If the buffer is too small, len includes
3749        the space needed for the terminator. */
3750     if (len >= Py_ARRAY_LENGTH(wbuf)) {
3751         if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3752             wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3753         }
3754         else {
3755             wbuf2 = NULL;
3756         }
3757         if (wbuf2) {
3758             len = GetCurrentDirectoryW(len, wbuf2);
3759         }
3760     }
3761     Py_END_ALLOW_THREADS
3762 
3763     if (!wbuf2) {
3764         PyErr_NoMemory();
3765         return NULL;
3766     }
3767     if (!len) {
3768         if (wbuf2 != wbuf)
3769             PyMem_RawFree(wbuf2);
3770         return PyErr_SetFromWindowsErr(0);
3771     }
3772 
3773     PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3774     if (wbuf2 != wbuf) {
3775         PyMem_RawFree(wbuf2);
3776     }
3777 
3778     if (use_bytes) {
3779         if (resobj == NULL) {
3780             return NULL;
3781         }
3782         Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3783     }
3784 
3785     return resobj;
3786 #else
3787     const size_t chunk = 1024;
3788 
3789     char *buf = NULL;
3790     char *cwd = NULL;
3791     size_t buflen = 0;
3792 
3793     Py_BEGIN_ALLOW_THREADS
3794     do {
3795         char *newbuf;
3796         if (buflen <= PY_SSIZE_T_MAX - chunk) {
3797             buflen += chunk;
3798             newbuf = PyMem_RawRealloc(buf, buflen);
3799         }
3800         else {
3801             newbuf = NULL;
3802         }
3803         if (newbuf == NULL) {
3804             PyMem_RawFree(buf);
3805             buf = NULL;
3806             break;
3807         }
3808         buf = newbuf;
3809 
3810         cwd = getcwd(buf, buflen);
3811     } while (cwd == NULL && errno == ERANGE);
3812     Py_END_ALLOW_THREADS
3813 
3814     if (buf == NULL) {
3815         return PyErr_NoMemory();
3816     }
3817     if (cwd == NULL) {
3818         PyMem_RawFree(buf);
3819         return posix_error();
3820     }
3821 
3822     PyObject *obj;
3823     if (use_bytes) {
3824         obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3825     }
3826     else {
3827         obj = PyUnicode_DecodeFSDefault(buf);
3828     }
3829     PyMem_RawFree(buf);
3830 
3831     return obj;
3832 #endif   /* !MS_WINDOWS */
3833 }
3834 
3835 
3836 /*[clinic input]
3837 os.getcwd
3838 
3839 Return a unicode string representing the current working directory.
3840 [clinic start generated code]*/
3841 
3842 static PyObject *
os_getcwd_impl(PyObject * module)3843 os_getcwd_impl(PyObject *module)
3844 /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3845 {
3846     return posix_getcwd(0);
3847 }
3848 
3849 
3850 /*[clinic input]
3851 os.getcwdb
3852 
3853 Return a bytes string representing the current working directory.
3854 [clinic start generated code]*/
3855 
3856 static PyObject *
os_getcwdb_impl(PyObject * module)3857 os_getcwdb_impl(PyObject *module)
3858 /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3859 {
3860     return posix_getcwd(1);
3861 }
3862 
3863 
3864 #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3865 #define HAVE_LINK 1
3866 #endif
3867 
3868 #ifdef HAVE_LINK
3869 /*[clinic input]
3870 
3871 os.link
3872 
3873     src : path_t
3874     dst : path_t
3875     *
3876     src_dir_fd : dir_fd = None
3877     dst_dir_fd : dir_fd = None
3878     follow_symlinks: bool = True
3879 
3880 Create a hard link to a file.
3881 
3882 If either src_dir_fd or dst_dir_fd is not None, it should be a file
3883   descriptor open to a directory, and the respective path string (src or dst)
3884   should be relative; the path will then be relative to that directory.
3885 If follow_symlinks is False, and the last element of src is a symbolic
3886   link, link will create a link to the symbolic link itself instead of the
3887   file the link points to.
3888 src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3889   platform.  If they are unavailable, using them will raise a
3890   NotImplementedError.
3891 [clinic start generated code]*/
3892 
3893 static PyObject *
os_link_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int follow_symlinks)3894 os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3895              int dst_dir_fd, int follow_symlinks)
3896 /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3897 {
3898 #ifdef MS_WINDOWS
3899     BOOL result = FALSE;
3900 #else
3901     int result;
3902 #endif
3903 #if defined(HAVE_LINKAT)
3904     int linkat_unavailable = 0;
3905 #endif
3906 
3907 #ifndef HAVE_LINKAT
3908     if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3909         argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3910         return NULL;
3911     }
3912 #endif
3913 
3914 #ifndef MS_WINDOWS
3915     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3916         PyErr_SetString(PyExc_NotImplementedError,
3917                         "link: src and dst must be the same type");
3918         return NULL;
3919     }
3920 #endif
3921 
3922     if (PySys_Audit("os.link", "OOii", src->object, dst->object,
3923                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
3924                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
3925         return NULL;
3926     }
3927 
3928 #ifdef MS_WINDOWS
3929     Py_BEGIN_ALLOW_THREADS
3930     result = CreateHardLinkW(dst->wide, src->wide, NULL);
3931     Py_END_ALLOW_THREADS
3932 
3933     if (!result)
3934         return path_error2(src, dst);
3935 #else
3936     Py_BEGIN_ALLOW_THREADS
3937 #ifdef HAVE_LINKAT
3938     if ((src_dir_fd != DEFAULT_DIR_FD) ||
3939         (dst_dir_fd != DEFAULT_DIR_FD) ||
3940         (!follow_symlinks)) {
3941 
3942         if (HAVE_LINKAT_RUNTIME) {
3943 
3944             result = linkat(src_dir_fd, src->narrow,
3945                 dst_dir_fd, dst->narrow,
3946                 follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3947 
3948         }
3949 #ifdef __APPLE__
3950         else {
3951             if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
3952                 /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
3953                 result = link(src->narrow, dst->narrow);
3954             } else {
3955                 linkat_unavailable = 1;
3956             }
3957         }
3958 #endif
3959     }
3960     else
3961 #endif /* HAVE_LINKAT */
3962         result = link(src->narrow, dst->narrow);
3963     Py_END_ALLOW_THREADS
3964 
3965 #ifdef HAVE_LINKAT
3966     if (linkat_unavailable) {
3967         /* Either or both dir_fd arguments were specified */
3968         if (src_dir_fd  != DEFAULT_DIR_FD) {
3969             argument_unavailable_error("link", "src_dir_fd");
3970         } else {
3971             argument_unavailable_error("link", "dst_dir_fd");
3972         }
3973         return NULL;
3974     }
3975 #endif
3976 
3977     if (result)
3978         return path_error2(src, dst);
3979 #endif /* MS_WINDOWS */
3980 
3981     Py_RETURN_NONE;
3982 }
3983 #endif
3984 
3985 
3986 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3987 static PyObject *
_listdir_windows_no_opendir(path_t * path,PyObject * list)3988 _listdir_windows_no_opendir(path_t *path, PyObject *list)
3989 {
3990     PyObject *v;
3991     HANDLE hFindFile = INVALID_HANDLE_VALUE;
3992     BOOL result;
3993     wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
3994     /* only claim to have space for MAX_PATH */
3995     Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
3996     wchar_t *wnamebuf = NULL;
3997 
3998     WIN32_FIND_DATAW wFileData;
3999     const wchar_t *po_wchars;
4000 
4001     if (!path->wide) { /* Default arg: "." */
4002         po_wchars = L".";
4003         len = 1;
4004     } else {
4005         po_wchars = path->wide;
4006         len = wcslen(path->wide);
4007     }
4008     /* The +5 is so we can append "\\*.*\0" */
4009     wnamebuf = PyMem_New(wchar_t, len + 5);
4010     if (!wnamebuf) {
4011         PyErr_NoMemory();
4012         goto exit;
4013     }
4014     wcscpy(wnamebuf, po_wchars);
4015     if (len > 0) {
4016         wchar_t wch = wnamebuf[len-1];
4017         if (wch != SEP && wch != ALTSEP && wch != L':')
4018             wnamebuf[len++] = SEP;
4019         wcscpy(wnamebuf + len, L"*.*");
4020     }
4021     if ((list = PyList_New(0)) == NULL) {
4022         goto exit;
4023     }
4024     Py_BEGIN_ALLOW_THREADS
4025     hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4026     Py_END_ALLOW_THREADS
4027     if (hFindFile == INVALID_HANDLE_VALUE) {
4028         int error = GetLastError();
4029         if (error == ERROR_FILE_NOT_FOUND)
4030             goto exit;
4031         Py_DECREF(list);
4032         list = path_error(path);
4033         goto exit;
4034     }
4035     do {
4036         /* Skip over . and .. */
4037         if (wcscmp(wFileData.cFileName, L".") != 0 &&
4038             wcscmp(wFileData.cFileName, L"..") != 0) {
4039             v = PyUnicode_FromWideChar(wFileData.cFileName,
4040                                        wcslen(wFileData.cFileName));
4041             if (path->narrow && v) {
4042                 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4043             }
4044             if (v == NULL) {
4045                 Py_DECREF(list);
4046                 list = NULL;
4047                 break;
4048             }
4049             if (PyList_Append(list, v) != 0) {
4050                 Py_DECREF(v);
4051                 Py_DECREF(list);
4052                 list = NULL;
4053                 break;
4054             }
4055             Py_DECREF(v);
4056         }
4057         Py_BEGIN_ALLOW_THREADS
4058         result = FindNextFileW(hFindFile, &wFileData);
4059         Py_END_ALLOW_THREADS
4060         /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4061            it got to the end of the directory. */
4062         if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4063             Py_DECREF(list);
4064             list = path_error(path);
4065             goto exit;
4066         }
4067     } while (result == TRUE);
4068 
4069 exit:
4070     if (hFindFile != INVALID_HANDLE_VALUE) {
4071         if (FindClose(hFindFile) == FALSE) {
4072             if (list != NULL) {
4073                 Py_DECREF(list);
4074                 list = path_error(path);
4075             }
4076         }
4077     }
4078     PyMem_Free(wnamebuf);
4079 
4080     return list;
4081 }  /* end of _listdir_windows_no_opendir */
4082 
4083 #else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4084 
4085 static PyObject *
_posix_listdir(path_t * path,PyObject * list)4086 _posix_listdir(path_t *path, PyObject *list)
4087 {
4088     PyObject *v;
4089     DIR *dirp = NULL;
4090     struct dirent *ep;
4091     int return_str; /* if false, return bytes */
4092 #ifdef HAVE_FDOPENDIR
4093     int fd = -1;
4094 #endif
4095 
4096     errno = 0;
4097 #ifdef HAVE_FDOPENDIR
4098     if (path->fd != -1) {
4099       if (HAVE_FDOPENDIR_RUNTIME) {
4100         /* closedir() closes the FD, so we duplicate it */
4101         fd = _Py_dup(path->fd);
4102         if (fd == -1)
4103             return NULL;
4104 
4105         return_str = 1;
4106 
4107         Py_BEGIN_ALLOW_THREADS
4108         dirp = fdopendir(fd);
4109         Py_END_ALLOW_THREADS
4110       } else {
4111         PyErr_SetString(PyExc_TypeError,
4112             "listdir: path should be string, bytes, os.PathLike or None, not int");
4113         return NULL;
4114       }
4115     }
4116     else
4117 #endif
4118     {
4119         const char *name;
4120         if (path->narrow) {
4121             name = path->narrow;
4122             /* only return bytes if they specified a bytes-like object */
4123             return_str = !PyObject_CheckBuffer(path->object);
4124         }
4125         else {
4126             name = ".";
4127             return_str = 1;
4128         }
4129 
4130         Py_BEGIN_ALLOW_THREADS
4131         dirp = opendir(name);
4132         Py_END_ALLOW_THREADS
4133     }
4134 
4135     if (dirp == NULL) {
4136         list = path_error(path);
4137 #ifdef HAVE_FDOPENDIR
4138         if (fd != -1) {
4139             Py_BEGIN_ALLOW_THREADS
4140             close(fd);
4141             Py_END_ALLOW_THREADS
4142         }
4143 #endif
4144         goto exit;
4145     }
4146     if ((list = PyList_New(0)) == NULL) {
4147         goto exit;
4148     }
4149     for (;;) {
4150         errno = 0;
4151         Py_BEGIN_ALLOW_THREADS
4152         ep = readdir(dirp);
4153         Py_END_ALLOW_THREADS
4154         if (ep == NULL) {
4155             if (errno == 0) {
4156                 break;
4157             } else {
4158                 Py_DECREF(list);
4159                 list = path_error(path);
4160                 goto exit;
4161             }
4162         }
4163         if (ep->d_name[0] == '.' &&
4164             (NAMLEN(ep) == 1 ||
4165              (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4166             continue;
4167         if (return_str)
4168             v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4169         else
4170             v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4171         if (v == NULL) {
4172             Py_CLEAR(list);
4173             break;
4174         }
4175         if (PyList_Append(list, v) != 0) {
4176             Py_DECREF(v);
4177             Py_CLEAR(list);
4178             break;
4179         }
4180         Py_DECREF(v);
4181     }
4182 
4183 exit:
4184     if (dirp != NULL) {
4185         Py_BEGIN_ALLOW_THREADS
4186 #ifdef HAVE_FDOPENDIR
4187         if (fd > -1)
4188             rewinddir(dirp);
4189 #endif
4190         closedir(dirp);
4191         Py_END_ALLOW_THREADS
4192     }
4193 
4194     return list;
4195 }  /* end of _posix_listdir */
4196 #endif  /* which OS */
4197 
4198 
4199 /*[clinic input]
4200 os.listdir
4201 
4202     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4203 
4204 Return a list containing the names of the files in the directory.
4205 
4206 path can be specified as either str, bytes, or a path-like object.  If path is bytes,
4207   the filenames returned will also be bytes; in all other circumstances
4208   the filenames returned will be str.
4209 If path is None, uses the path='.'.
4210 On some platforms, path may also be specified as an open file descriptor;\
4211   the file descriptor must refer to a directory.
4212   If this functionality is unavailable, using it raises NotImplementedError.
4213 
4214 The list is in arbitrary order.  It does not include the special
4215 entries '.' and '..' even if they are present in the directory.
4216 
4217 
4218 [clinic start generated code]*/
4219 
4220 static PyObject *
os_listdir_impl(PyObject * module,path_t * path)4221 os_listdir_impl(PyObject *module, path_t *path)
4222 /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4223 {
4224     if (PySys_Audit("os.listdir", "O",
4225                     path->object ? path->object : Py_None) < 0) {
4226         return NULL;
4227     }
4228 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4229     return _listdir_windows_no_opendir(path, NULL);
4230 #else
4231     return _posix_listdir(path, NULL);
4232 #endif
4233 }
4234 
4235 #ifdef MS_WINDOWS
4236 /* A helper function for abspath on win32 */
4237 /*[clinic input]
4238 os._getfullpathname
4239 
4240     path: path_t
4241     /
4242 
4243 [clinic start generated code]*/
4244 
4245 static PyObject *
os__getfullpathname_impl(PyObject * module,path_t * path)4246 os__getfullpathname_impl(PyObject *module, path_t *path)
4247 /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
4248 {
4249     wchar_t *abspath;
4250 
4251     /* _Py_abspath() is implemented with GetFullPathNameW() on Windows */
4252     if (_Py_abspath(path->wide, &abspath) < 0) {
4253         return win32_error_object("GetFullPathNameW", path->object);
4254     }
4255     if (abspath == NULL) {
4256         return PyErr_NoMemory();
4257     }
4258 
4259     PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
4260     PyMem_RawFree(abspath);
4261     if (str == NULL) {
4262         return NULL;
4263     }
4264     if (path->narrow) {
4265         Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
4266     }
4267     return str;
4268 }
4269 
4270 
4271 /*[clinic input]
4272 os._getfinalpathname
4273 
4274     path: path_t
4275     /
4276 
4277 A helper function for samepath on windows.
4278 [clinic start generated code]*/
4279 
4280 static PyObject *
os__getfinalpathname_impl(PyObject * module,path_t * path)4281 os__getfinalpathname_impl(PyObject *module, path_t *path)
4282 /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
4283 {
4284     HANDLE hFile;
4285     wchar_t buf[MAXPATHLEN], *target_path = buf;
4286     int buf_size = Py_ARRAY_LENGTH(buf);
4287     int result_length;
4288     PyObject *result;
4289 
4290     Py_BEGIN_ALLOW_THREADS
4291     hFile = CreateFileW(
4292         path->wide,
4293         0, /* desired access */
4294         0, /* share mode */
4295         NULL, /* security attributes */
4296         OPEN_EXISTING,
4297         /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
4298         FILE_FLAG_BACKUP_SEMANTICS,
4299         NULL);
4300     Py_END_ALLOW_THREADS
4301 
4302     if (hFile == INVALID_HANDLE_VALUE) {
4303         return win32_error_object("CreateFileW", path->object);
4304     }
4305 
4306     /* We have a good handle to the target, use it to determine the
4307        target path name. */
4308     while (1) {
4309         Py_BEGIN_ALLOW_THREADS
4310         result_length = GetFinalPathNameByHandleW(hFile, target_path,
4311                                                   buf_size, VOLUME_NAME_DOS);
4312         Py_END_ALLOW_THREADS
4313 
4314         if (!result_length) {
4315             result = win32_error_object("GetFinalPathNameByHandleW",
4316                                          path->object);
4317             goto cleanup;
4318         }
4319 
4320         if (result_length < buf_size) {
4321             break;
4322         }
4323 
4324         wchar_t *tmp;
4325         tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
4326                             result_length * sizeof(*tmp));
4327         if (!tmp) {
4328             result = PyErr_NoMemory();
4329             goto cleanup;
4330         }
4331 
4332         buf_size = result_length;
4333         target_path = tmp;
4334     }
4335 
4336     result = PyUnicode_FromWideChar(target_path, result_length);
4337     if (result && path->narrow) {
4338         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4339     }
4340 
4341 cleanup:
4342     if (target_path != buf) {
4343         PyMem_Free(target_path);
4344     }
4345     CloseHandle(hFile);
4346     return result;
4347 }
4348 
4349 
4350 /*[clinic input]
4351 os._getvolumepathname
4352 
4353     path: path_t
4354 
4355 A helper function for ismount on Win32.
4356 [clinic start generated code]*/
4357 
4358 static PyObject *
os__getvolumepathname_impl(PyObject * module,path_t * path)4359 os__getvolumepathname_impl(PyObject *module, path_t *path)
4360 /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
4361 {
4362     PyObject *result;
4363     wchar_t *mountpath=NULL;
4364     size_t buflen;
4365     BOOL ret;
4366 
4367     /* Volume path should be shorter than entire path */
4368     buflen = Py_MAX(path->length, MAX_PATH);
4369 
4370     if (buflen > PY_DWORD_MAX) {
4371         PyErr_SetString(PyExc_OverflowError, "path too long");
4372         return NULL;
4373     }
4374 
4375     mountpath = PyMem_New(wchar_t, buflen);
4376     if (mountpath == NULL)
4377         return PyErr_NoMemory();
4378 
4379     Py_BEGIN_ALLOW_THREADS
4380     ret = GetVolumePathNameW(path->wide, mountpath,
4381                              Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
4382     Py_END_ALLOW_THREADS
4383 
4384     if (!ret) {
4385         result = win32_error_object("_getvolumepathname", path->object);
4386         goto exit;
4387     }
4388     result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
4389     if (path->narrow)
4390         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4391 
4392 exit:
4393     PyMem_Free(mountpath);
4394     return result;
4395 }
4396 
4397 
4398 /*[clinic input]
4399 os._path_splitroot
4400 
4401     path: path_t
4402 
4403 Removes everything after the root on Win32.
4404 [clinic start generated code]*/
4405 
4406 static PyObject *
os__path_splitroot_impl(PyObject * module,path_t * path)4407 os__path_splitroot_impl(PyObject *module, path_t *path)
4408 /*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/
4409 {
4410     wchar_t *buffer;
4411     wchar_t *end;
4412     PyObject *result = NULL;
4413     HRESULT ret;
4414 
4415     buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
4416     if (!buffer) {
4417         return NULL;
4418     }
4419     wcscpy(buffer, path->wide);
4420     for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
4421         *p = L'\\';
4422     }
4423 
4424     Py_BEGIN_ALLOW_THREADS
4425     ret = PathCchSkipRoot(buffer, &end);
4426     Py_END_ALLOW_THREADS
4427     if (FAILED(ret)) {
4428         result = Py_BuildValue("sO", "", path->object);
4429     } else if (end != buffer) {
4430         size_t rootLen = (size_t)(end - buffer);
4431         result = Py_BuildValue("NN",
4432             PyUnicode_FromWideChar(path->wide, rootLen),
4433             PyUnicode_FromWideChar(path->wide + rootLen, -1)
4434         );
4435     } else {
4436         result = Py_BuildValue("Os", path->object, "");
4437     }
4438     PyMem_Free(buffer);
4439 
4440     return result;
4441 }
4442 
4443 
4444 #endif /* MS_WINDOWS */
4445 
4446 
4447 /*[clinic input]
4448 os._path_normpath
4449 
4450     path: object
4451 
4452 Basic path normalization.
4453 [clinic start generated code]*/
4454 
4455 static PyObject *
os__path_normpath_impl(PyObject * module,PyObject * path)4456 os__path_normpath_impl(PyObject *module, PyObject *path)
4457 /*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/
4458 {
4459     if (!PyUnicode_Check(path)) {
4460         PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'",
4461             Py_TYPE(path)->tp_name);
4462         return NULL;
4463     }
4464     Py_ssize_t len;
4465     wchar_t *buffer = PyUnicode_AsWideCharString(path, &len);
4466     if (!buffer) {
4467         return NULL;
4468     }
4469     PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1);
4470     PyMem_Free(buffer);
4471     return result;
4472 }
4473 
4474 /*[clinic input]
4475 os.mkdir
4476 
4477     path : path_t
4478 
4479     mode: int = 0o777
4480 
4481     *
4482 
4483     dir_fd : dir_fd(requires='mkdirat') = None
4484 
4485 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4486 
4487 Create a directory.
4488 
4489 If dir_fd is not None, it should be a file descriptor open to a directory,
4490   and path should be relative; path will then be relative to that directory.
4491 dir_fd may not be implemented on your platform.
4492   If it is unavailable, using it will raise a NotImplementedError.
4493 
4494 The mode argument is ignored on Windows.
4495 [clinic start generated code]*/
4496 
4497 static PyObject *
os_mkdir_impl(PyObject * module,path_t * path,int mode,int dir_fd)4498 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4499 /*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/
4500 {
4501     int result;
4502 #ifdef HAVE_MKDIRAT
4503     int mkdirat_unavailable = 0;
4504 #endif
4505 
4506     if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4507                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4508         return NULL;
4509     }
4510 
4511 #ifdef MS_WINDOWS
4512     Py_BEGIN_ALLOW_THREADS
4513     result = CreateDirectoryW(path->wide, NULL);
4514     Py_END_ALLOW_THREADS
4515 
4516     if (!result)
4517         return path_error(path);
4518 #else
4519     Py_BEGIN_ALLOW_THREADS
4520 #if HAVE_MKDIRAT
4521     if (dir_fd != DEFAULT_DIR_FD) {
4522       if (HAVE_MKDIRAT_RUNTIME) {
4523         result = mkdirat(dir_fd, path->narrow, mode);
4524 
4525       } else {
4526         mkdirat_unavailable = 1;
4527       }
4528     } else
4529 #endif
4530 #if defined(__WATCOMC__) && !defined(__QNX__)
4531         result = mkdir(path->narrow);
4532 #else
4533         result = mkdir(path->narrow, mode);
4534 #endif
4535     Py_END_ALLOW_THREADS
4536 
4537 #if HAVE_MKDIRAT
4538     if (mkdirat_unavailable) {
4539         argument_unavailable_error(NULL, "dir_fd");
4540         return NULL;
4541     }
4542 #endif
4543 
4544     if (result < 0)
4545         return path_error(path);
4546 #endif /* MS_WINDOWS */
4547     Py_RETURN_NONE;
4548 }
4549 
4550 
4551 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4552 #if defined(HAVE_SYS_RESOURCE_H)
4553 #include <sys/resource.h>
4554 #endif
4555 
4556 
4557 #ifdef HAVE_NICE
4558 /*[clinic input]
4559 os.nice
4560 
4561     increment: int
4562     /
4563 
4564 Add increment to the priority of process and return the new priority.
4565 [clinic start generated code]*/
4566 
4567 static PyObject *
os_nice_impl(PyObject * module,int increment)4568 os_nice_impl(PyObject *module, int increment)
4569 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4570 {
4571     int value;
4572 
4573     /* There are two flavours of 'nice': one that returns the new
4574        priority (as required by almost all standards out there) and the
4575        Linux/FreeBSD one, which returns '0' on success and advices
4576        the use of getpriority() to get the new priority.
4577 
4578        If we are of the nice family that returns the new priority, we
4579        need to clear errno before the call, and check if errno is filled
4580        before calling posix_error() on a returnvalue of -1, because the
4581        -1 may be the actual new priority! */
4582 
4583     errno = 0;
4584     value = nice(increment);
4585 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4586     if (value == 0)
4587         value = getpriority(PRIO_PROCESS, 0);
4588 #endif
4589     if (value == -1 && errno != 0)
4590         /* either nice() or getpriority() returned an error */
4591         return posix_error();
4592     return PyLong_FromLong((long) value);
4593 }
4594 #endif /* HAVE_NICE */
4595 
4596 
4597 #ifdef HAVE_GETPRIORITY
4598 /*[clinic input]
4599 os.getpriority
4600 
4601     which: int
4602     who: int
4603 
4604 Return program scheduling priority.
4605 [clinic start generated code]*/
4606 
4607 static PyObject *
os_getpriority_impl(PyObject * module,int which,int who)4608 os_getpriority_impl(PyObject *module, int which, int who)
4609 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4610 {
4611     int retval;
4612 
4613     errno = 0;
4614     retval = getpriority(which, who);
4615     if (errno != 0)
4616         return posix_error();
4617     return PyLong_FromLong((long)retval);
4618 }
4619 #endif /* HAVE_GETPRIORITY */
4620 
4621 
4622 #ifdef HAVE_SETPRIORITY
4623 /*[clinic input]
4624 os.setpriority
4625 
4626     which: int
4627     who: int
4628     priority: int
4629 
4630 Set program scheduling priority.
4631 [clinic start generated code]*/
4632 
4633 static PyObject *
os_setpriority_impl(PyObject * module,int which,int who,int priority)4634 os_setpriority_impl(PyObject *module, int which, int who, int priority)
4635 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4636 {
4637     int retval;
4638 
4639     retval = setpriority(which, who, priority);
4640     if (retval == -1)
4641         return posix_error();
4642     Py_RETURN_NONE;
4643 }
4644 #endif /* HAVE_SETPRIORITY */
4645 
4646 
4647 static PyObject *
internal_rename(path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int is_replace)4648 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4649 {
4650     const char *function_name = is_replace ? "replace" : "rename";
4651     int dir_fd_specified;
4652 
4653 #ifdef HAVE_RENAMEAT
4654     int renameat_unavailable = 0;
4655 #endif
4656 
4657 #ifdef MS_WINDOWS
4658     BOOL result;
4659     int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4660 #else
4661     int result;
4662 #endif
4663 
4664     dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4665                        (dst_dir_fd != DEFAULT_DIR_FD);
4666 #ifndef HAVE_RENAMEAT
4667     if (dir_fd_specified) {
4668         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4669         return NULL;
4670     }
4671 #endif
4672 
4673     if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
4674                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4675                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4676         return NULL;
4677     }
4678 
4679 #ifdef MS_WINDOWS
4680     Py_BEGIN_ALLOW_THREADS
4681     result = MoveFileExW(src->wide, dst->wide, flags);
4682     Py_END_ALLOW_THREADS
4683 
4684     if (!result)
4685         return path_error2(src, dst);
4686 
4687 #else
4688     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4689         PyErr_Format(PyExc_ValueError,
4690                      "%s: src and dst must be the same type", function_name);
4691         return NULL;
4692     }
4693 
4694     Py_BEGIN_ALLOW_THREADS
4695 #ifdef HAVE_RENAMEAT
4696     if (dir_fd_specified) {
4697         if (HAVE_RENAMEAT_RUNTIME) {
4698             result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4699         } else {
4700             renameat_unavailable = 1;
4701         }
4702     } else
4703 #endif
4704     result = rename(src->narrow, dst->narrow);
4705     Py_END_ALLOW_THREADS
4706 
4707 
4708 #ifdef HAVE_RENAMEAT
4709     if (renameat_unavailable) {
4710         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4711         return NULL;
4712     }
4713 #endif
4714 
4715     if (result)
4716         return path_error2(src, dst);
4717 #endif
4718     Py_RETURN_NONE;
4719 }
4720 
4721 
4722 /*[clinic input]
4723 os.rename
4724 
4725     src : path_t
4726     dst : path_t
4727     *
4728     src_dir_fd : dir_fd = None
4729     dst_dir_fd : dir_fd = None
4730 
4731 Rename a file or directory.
4732 
4733 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4734   descriptor open to a directory, and the respective path string (src or dst)
4735   should be relative; the path will then be relative to that directory.
4736 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4737   If they are unavailable, using them will raise a NotImplementedError.
4738 [clinic start generated code]*/
4739 
4740 static PyObject *
os_rename_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4741 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4742                int dst_dir_fd)
4743 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4744 {
4745     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4746 }
4747 
4748 
4749 /*[clinic input]
4750 os.replace = os.rename
4751 
4752 Rename a file or directory, overwriting the destination.
4753 
4754 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4755   descriptor open to a directory, and the respective path string (src or dst)
4756   should be relative; the path will then be relative to that directory.
4757 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4758   If they are unavailable, using them will raise a NotImplementedError.
4759 [clinic start generated code]*/
4760 
4761 static PyObject *
os_replace_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4762 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4763                 int dst_dir_fd)
4764 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4765 {
4766     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4767 }
4768 
4769 
4770 /*[clinic input]
4771 os.rmdir
4772 
4773     path: path_t
4774     *
4775     dir_fd: dir_fd(requires='unlinkat') = None
4776 
4777 Remove a directory.
4778 
4779 If dir_fd is not None, it should be a file descriptor open to a directory,
4780   and path should be relative; path will then be relative to that directory.
4781 dir_fd may not be implemented on your platform.
4782   If it is unavailable, using it will raise a NotImplementedError.
4783 [clinic start generated code]*/
4784 
4785 static PyObject *
os_rmdir_impl(PyObject * module,path_t * path,int dir_fd)4786 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4787 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4788 {
4789     int result;
4790 #ifdef HAVE_UNLINKAT
4791     int unlinkat_unavailable = 0;
4792 #endif
4793 
4794     if (PySys_Audit("os.rmdir", "Oi", path->object,
4795                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4796         return NULL;
4797     }
4798 
4799     Py_BEGIN_ALLOW_THREADS
4800 #ifdef MS_WINDOWS
4801     /* Windows, success=1, UNIX, success=0 */
4802     result = !RemoveDirectoryW(path->wide);
4803 #else
4804 #ifdef HAVE_UNLINKAT
4805     if (dir_fd != DEFAULT_DIR_FD) {
4806       if (HAVE_UNLINKAT_RUNTIME) {
4807         result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4808       } else {
4809         unlinkat_unavailable = 1;
4810         result = -1;
4811       }
4812     } else
4813 #endif
4814         result = rmdir(path->narrow);
4815 #endif
4816     Py_END_ALLOW_THREADS
4817 
4818 #ifdef HAVE_UNLINKAT
4819     if (unlinkat_unavailable) {
4820         argument_unavailable_error("rmdir", "dir_fd");
4821         return NULL;
4822     }
4823 #endif
4824 
4825     if (result)
4826         return path_error(path);
4827 
4828     Py_RETURN_NONE;
4829 }
4830 
4831 
4832 #ifdef HAVE_SYSTEM
4833 #ifdef MS_WINDOWS
4834 /*[clinic input]
4835 os.system -> long
4836 
4837     command: Py_UNICODE
4838 
4839 Execute the command in a subshell.
4840 [clinic start generated code]*/
4841 
4842 static long
os_system_impl(PyObject * module,const Py_UNICODE * command)4843 os_system_impl(PyObject *module, const Py_UNICODE *command)
4844 /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4845 {
4846     long result;
4847 
4848     if (PySys_Audit("os.system", "(u)", command) < 0) {
4849         return -1;
4850     }
4851 
4852     Py_BEGIN_ALLOW_THREADS
4853     _Py_BEGIN_SUPPRESS_IPH
4854     result = _wsystem(command);
4855     _Py_END_SUPPRESS_IPH
4856     Py_END_ALLOW_THREADS
4857     return result;
4858 }
4859 #else /* MS_WINDOWS */
4860 /*[clinic input]
4861 os.system -> long
4862 
4863     command: FSConverter
4864 
4865 Execute the command in a subshell.
4866 [clinic start generated code]*/
4867 
4868 static long
os_system_impl(PyObject * module,PyObject * command)4869 os_system_impl(PyObject *module, PyObject *command)
4870 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4871 {
4872     long result;
4873     const char *bytes = PyBytes_AsString(command);
4874 
4875     if (PySys_Audit("os.system", "(O)", command) < 0) {
4876         return -1;
4877     }
4878 
4879     Py_BEGIN_ALLOW_THREADS
4880     result = system(bytes);
4881     Py_END_ALLOW_THREADS
4882     return result;
4883 }
4884 #endif
4885 #endif /* HAVE_SYSTEM */
4886 
4887 
4888 /*[clinic input]
4889 os.umask
4890 
4891     mask: int
4892     /
4893 
4894 Set the current numeric umask and return the previous umask.
4895 [clinic start generated code]*/
4896 
4897 static PyObject *
os_umask_impl(PyObject * module,int mask)4898 os_umask_impl(PyObject *module, int mask)
4899 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4900 {
4901     int i = (int)umask(mask);
4902     if (i < 0)
4903         return posix_error();
4904     return PyLong_FromLong((long)i);
4905 }
4906 
4907 #ifdef MS_WINDOWS
4908 
4909 /* override the default DeleteFileW behavior so that directory
4910 symlinks can be removed with this function, the same as with
4911 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)4912 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
4913 {
4914     WIN32_FILE_ATTRIBUTE_DATA info;
4915     WIN32_FIND_DATAW find_data;
4916     HANDLE find_data_handle;
4917     int is_directory = 0;
4918     int is_link = 0;
4919 
4920     if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
4921         is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4922 
4923         /* Get WIN32_FIND_DATA structure for the path to determine if
4924            it is a symlink */
4925         if(is_directory &&
4926            info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
4927             find_data_handle = FindFirstFileW(lpFileName, &find_data);
4928 
4929             if(find_data_handle != INVALID_HANDLE_VALUE) {
4930                 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
4931                    IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
4932                 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
4933                           find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
4934                 FindClose(find_data_handle);
4935             }
4936         }
4937     }
4938 
4939     if (is_directory && is_link)
4940         return RemoveDirectoryW(lpFileName);
4941 
4942     return DeleteFileW(lpFileName);
4943 }
4944 #endif /* MS_WINDOWS */
4945 
4946 
4947 /*[clinic input]
4948 os.unlink
4949 
4950     path: path_t
4951     *
4952     dir_fd: dir_fd(requires='unlinkat')=None
4953 
4954 Remove a file (same as remove()).
4955 
4956 If dir_fd is not None, it should be a file descriptor open to a directory,
4957   and path should be relative; path will then be relative to that directory.
4958 dir_fd may not be implemented on your platform.
4959   If it is unavailable, using it will raise a NotImplementedError.
4960 
4961 [clinic start generated code]*/
4962 
4963 static PyObject *
os_unlink_impl(PyObject * module,path_t * path,int dir_fd)4964 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
4965 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
4966 {
4967     int result;
4968 #ifdef HAVE_UNLINKAT
4969     int unlinkat_unavailable = 0;
4970 #endif
4971 
4972     if (PySys_Audit("os.remove", "Oi", path->object,
4973                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4974         return NULL;
4975     }
4976 
4977     Py_BEGIN_ALLOW_THREADS
4978     _Py_BEGIN_SUPPRESS_IPH
4979 #ifdef MS_WINDOWS
4980     /* Windows, success=1, UNIX, success=0 */
4981     result = !Py_DeleteFileW(path->wide);
4982 #else
4983 #ifdef HAVE_UNLINKAT
4984     if (dir_fd != DEFAULT_DIR_FD) {
4985       if (HAVE_UNLINKAT_RUNTIME) {
4986 
4987         result = unlinkat(dir_fd, path->narrow, 0);
4988       } else {
4989         unlinkat_unavailable = 1;
4990       }
4991     } else
4992 #endif /* HAVE_UNLINKAT */
4993         result = unlink(path->narrow);
4994 #endif
4995     _Py_END_SUPPRESS_IPH
4996     Py_END_ALLOW_THREADS
4997 
4998 #ifdef HAVE_UNLINKAT
4999     if (unlinkat_unavailable) {
5000         argument_unavailable_error(NULL, "dir_fd");
5001         return NULL;
5002     }
5003 #endif
5004 
5005     if (result)
5006         return path_error(path);
5007 
5008     Py_RETURN_NONE;
5009 }
5010 
5011 
5012 /*[clinic input]
5013 os.remove = os.unlink
5014 
5015 Remove a file (same as unlink()).
5016 
5017 If dir_fd is not None, it should be a file descriptor open to a directory,
5018   and path should be relative; path will then be relative to that directory.
5019 dir_fd may not be implemented on your platform.
5020   If it is unavailable, using it will raise a NotImplementedError.
5021 [clinic start generated code]*/
5022 
5023 static PyObject *
os_remove_impl(PyObject * module,path_t * path,int dir_fd)5024 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
5025 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
5026 {
5027     return os_unlink_impl(module, path, dir_fd);
5028 }
5029 
5030 
5031 static PyStructSequence_Field uname_result_fields[] = {
5032     {"sysname",    "operating system name"},
5033     {"nodename",   "name of machine on network (implementation-defined)"},
5034     {"release",    "operating system release"},
5035     {"version",    "operating system version"},
5036     {"machine",    "hardware identifier"},
5037     {NULL}
5038 };
5039 
5040 PyDoc_STRVAR(uname_result__doc__,
5041 "uname_result: Result from os.uname().\n\n\
5042 This object may be accessed either as a tuple of\n\
5043   (sysname, nodename, release, version, machine),\n\
5044 or via the attributes sysname, nodename, release, version, and machine.\n\
5045 \n\
5046 See os.uname for more information.");
5047 
5048 static PyStructSequence_Desc uname_result_desc = {
5049     MODNAME ".uname_result", /* name */
5050     uname_result__doc__, /* doc */
5051     uname_result_fields,
5052     5
5053 };
5054 
5055 #ifdef HAVE_UNAME
5056 /*[clinic input]
5057 os.uname
5058 
5059 Return an object identifying the current operating system.
5060 
5061 The object behaves like a named tuple with the following fields:
5062   (sysname, nodename, release, version, machine)
5063 
5064 [clinic start generated code]*/
5065 
5066 static PyObject *
os_uname_impl(PyObject * module)5067 os_uname_impl(PyObject *module)
5068 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
5069 {
5070     struct utsname u;
5071     int res;
5072     PyObject *value;
5073 
5074     Py_BEGIN_ALLOW_THREADS
5075     res = uname(&u);
5076     Py_END_ALLOW_THREADS
5077     if (res < 0)
5078         return posix_error();
5079 
5080     PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
5081     value = PyStructSequence_New((PyTypeObject *)UnameResultType);
5082     if (value == NULL)
5083         return NULL;
5084 
5085 #define SET(i, field) \
5086     { \
5087     PyObject *o = PyUnicode_DecodeFSDefault(field); \
5088     if (!o) { \
5089         Py_DECREF(value); \
5090         return NULL; \
5091     } \
5092     PyStructSequence_SET_ITEM(value, i, o); \
5093     } \
5094 
5095     SET(0, u.sysname);
5096     SET(1, u.nodename);
5097     SET(2, u.release);
5098     SET(3, u.version);
5099     SET(4, u.machine);
5100 
5101 #undef SET
5102 
5103     return value;
5104 }
5105 #endif /* HAVE_UNAME */
5106 
5107 
5108 
5109 typedef struct {
5110     int    now;
5111     time_t atime_s;
5112     long   atime_ns;
5113     time_t mtime_s;
5114     long   mtime_ns;
5115 } utime_t;
5116 
5117 /*
5118  * these macros assume that "ut" is a pointer to a utime_t
5119  * they also intentionally leak the declaration of a pointer named "time"
5120  */
5121 #define UTIME_TO_TIMESPEC \
5122     struct timespec ts[2]; \
5123     struct timespec *time; \
5124     if (ut->now) \
5125         time = NULL; \
5126     else { \
5127         ts[0].tv_sec = ut->atime_s; \
5128         ts[0].tv_nsec = ut->atime_ns; \
5129         ts[1].tv_sec = ut->mtime_s; \
5130         ts[1].tv_nsec = ut->mtime_ns; \
5131         time = ts; \
5132     } \
5133 
5134 #define UTIME_TO_TIMEVAL \
5135     struct timeval tv[2]; \
5136     struct timeval *time; \
5137     if (ut->now) \
5138         time = NULL; \
5139     else { \
5140         tv[0].tv_sec = ut->atime_s; \
5141         tv[0].tv_usec = ut->atime_ns / 1000; \
5142         tv[1].tv_sec = ut->mtime_s; \
5143         tv[1].tv_usec = ut->mtime_ns / 1000; \
5144         time = tv; \
5145     } \
5146 
5147 #define UTIME_TO_UTIMBUF \
5148     struct utimbuf u; \
5149     struct utimbuf *time; \
5150     if (ut->now) \
5151         time = NULL; \
5152     else { \
5153         u.actime = ut->atime_s; \
5154         u.modtime = ut->mtime_s; \
5155         time = &u; \
5156     }
5157 
5158 #define UTIME_TO_TIME_T \
5159     time_t timet[2]; \
5160     time_t *time; \
5161     if (ut->now) \
5162         time = NULL; \
5163     else { \
5164         timet[0] = ut->atime_s; \
5165         timet[1] = ut->mtime_s; \
5166         time = timet; \
5167     } \
5168 
5169 
5170 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5171 
5172 static int
utime_dir_fd(utime_t * ut,int dir_fd,const char * path,int follow_symlinks)5173 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
5174 {
5175 #if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
5176     if (HAVE_UTIMENSAT_RUNTIME) {
5177         int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5178         UTIME_TO_TIMESPEC;
5179         return utimensat(dir_fd, path, time, flags);
5180     }  else {
5181         errno = ENOSYS;
5182         return -1;
5183     }
5184 #elif defined(HAVE_UTIMENSAT)
5185     int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5186     UTIME_TO_TIMESPEC;
5187     return utimensat(dir_fd, path, time, flags);
5188 #elif defined(HAVE_FUTIMESAT)
5189     UTIME_TO_TIMEVAL;
5190     /*
5191      * follow_symlinks will never be false here;
5192      * we only allow !follow_symlinks and dir_fd together
5193      * if we have utimensat()
5194      */
5195     assert(follow_symlinks);
5196     return futimesat(dir_fd, path, time);
5197 #endif
5198 }
5199 
5200     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
5201 #else
5202     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
5203 #endif
5204 
5205 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5206 
5207 static int
utime_fd(utime_t * ut,int fd)5208 utime_fd(utime_t *ut, int fd)
5209 {
5210 #ifdef HAVE_FUTIMENS
5211 
5212     if (HAVE_FUTIMENS_RUNTIME) {
5213 
5214     UTIME_TO_TIMESPEC;
5215     return futimens(fd, time);
5216 
5217     } else
5218 #ifndef HAVE_FUTIMES
5219     {
5220         /* Not sure if this can happen */
5221         PyErr_SetString(
5222             PyExc_RuntimeError,
5223             "neither futimens nor futimes are supported"
5224             " on this system");
5225         return -1;
5226     }
5227 #endif
5228 
5229 #endif
5230 #ifdef HAVE_FUTIMES
5231     {
5232     UTIME_TO_TIMEVAL;
5233     return futimes(fd, time);
5234     }
5235 #endif
5236 }
5237 
5238     #define PATH_UTIME_HAVE_FD 1
5239 #else
5240     #define PATH_UTIME_HAVE_FD 0
5241 #endif
5242 
5243 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
5244 #  define UTIME_HAVE_NOFOLLOW_SYMLINKS
5245 #endif
5246 
5247 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5248 
5249 static int
utime_nofollow_symlinks(utime_t * ut,const char * path)5250 utime_nofollow_symlinks(utime_t *ut, const char *path)
5251 {
5252 #ifdef HAVE_UTIMENSAT
5253     if (HAVE_UTIMENSAT_RUNTIME) {
5254         UTIME_TO_TIMESPEC;
5255         return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
5256     } else
5257 #ifndef HAVE_LUTIMES
5258     {
5259         /* Not sure if this can happen */
5260         PyErr_SetString(
5261             PyExc_RuntimeError,
5262             "neither utimensat nor lutimes are supported"
5263             " on this system");
5264         return -1;
5265     }
5266 #endif
5267 #endif
5268 
5269 #ifdef HAVE_LUTIMES
5270     {
5271     UTIME_TO_TIMEVAL;
5272     return lutimes(path, time);
5273     }
5274 #endif
5275 }
5276 
5277 #endif
5278 
5279 #ifndef MS_WINDOWS
5280 
5281 static int
utime_default(utime_t * ut,const char * path)5282 utime_default(utime_t *ut, const char *path)
5283 {
5284 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5285     if (HAVE_UTIMENSAT_RUNTIME) {
5286         UTIME_TO_TIMESPEC;
5287         return utimensat(DEFAULT_DIR_FD, path, time, 0);
5288     } else {
5289         UTIME_TO_TIMEVAL;
5290         return utimes(path, time);
5291     }
5292 #elif defined(HAVE_UTIMENSAT)
5293     UTIME_TO_TIMESPEC;
5294     return utimensat(DEFAULT_DIR_FD, path, time, 0);
5295 #elif defined(HAVE_UTIMES)
5296     UTIME_TO_TIMEVAL;
5297     return utimes(path, time);
5298 #elif defined(HAVE_UTIME_H)
5299     UTIME_TO_UTIMBUF;
5300     return utime(path, time);
5301 #else
5302     UTIME_TO_TIME_T;
5303     return utime(path, time);
5304 #endif
5305 }
5306 
5307 #endif
5308 
5309 static int
split_py_long_to_s_and_ns(PyObject * module,PyObject * py_long,time_t * s,long * ns)5310 split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5311 {
5312     int result = 0;
5313     PyObject *divmod;
5314     divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5315     if (!divmod)
5316         goto exit;
5317     if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
5318         PyErr_Format(PyExc_TypeError,
5319                      "%.200s.__divmod__() must return a 2-tuple, not %.200s",
5320                      _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
5321         goto exit;
5322     }
5323     *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5324     if ((*s == -1) && PyErr_Occurred())
5325         goto exit;
5326     *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5327     if ((*ns == -1) && PyErr_Occurred())
5328         goto exit;
5329 
5330     result = 1;
5331 exit:
5332     Py_XDECREF(divmod);
5333     return result;
5334 }
5335 
5336 
5337 /*[clinic input]
5338 os.utime
5339 
5340     path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
5341     times: object = None
5342     *
5343     ns: object = NULL
5344     dir_fd: dir_fd(requires='futimensat') = None
5345     follow_symlinks: bool=True
5346 
5347 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
5348 
5349 Set the access and modified time of path.
5350 
5351 path may always be specified as a string.
5352 On some platforms, path may also be specified as an open file descriptor.
5353   If this functionality is unavailable, using it raises an exception.
5354 
5355 If times is not None, it must be a tuple (atime, mtime);
5356     atime and mtime should be expressed as float seconds since the epoch.
5357 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
5358     atime_ns and mtime_ns should be expressed as integer nanoseconds
5359     since the epoch.
5360 If times is None and ns is unspecified, utime uses the current time.
5361 Specifying tuples for both times and ns is an error.
5362 
5363 If dir_fd is not None, it should be a file descriptor open to a directory,
5364   and path should be relative; path will then be relative to that directory.
5365 If follow_symlinks is False, and the last element of the path is a symbolic
5366   link, utime will modify the symbolic link itself instead of the file the
5367   link points to.
5368 It is an error to use dir_fd or follow_symlinks when specifying path
5369   as an open file descriptor.
5370 dir_fd and follow_symlinks may not be available on your platform.
5371   If they are unavailable, using them will raise a NotImplementedError.
5372 
5373 [clinic start generated code]*/
5374 
5375 static PyObject *
os_utime_impl(PyObject * module,path_t * path,PyObject * times,PyObject * ns,int dir_fd,int follow_symlinks)5376 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
5377               int dir_fd, int follow_symlinks)
5378 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
5379 {
5380 #ifdef MS_WINDOWS
5381     HANDLE hFile;
5382     FILETIME atime, mtime;
5383 #else
5384     int result;
5385 #endif
5386 
5387     utime_t utime;
5388 
5389     memset(&utime, 0, sizeof(utime_t));
5390 
5391     if (times != Py_None && ns) {
5392         PyErr_SetString(PyExc_ValueError,
5393                      "utime: you may specify either 'times'"
5394                      " or 'ns' but not both");
5395         return NULL;
5396     }
5397 
5398     if (times != Py_None) {
5399         time_t a_sec, m_sec;
5400         long a_nsec, m_nsec;
5401         if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
5402             PyErr_SetString(PyExc_TypeError,
5403                          "utime: 'times' must be either"
5404                          " a tuple of two ints or None");
5405             return NULL;
5406         }
5407         utime.now = 0;
5408         if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
5409                                      &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
5410             _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
5411                                      &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
5412             return NULL;
5413         }
5414         utime.atime_s = a_sec;
5415         utime.atime_ns = a_nsec;
5416         utime.mtime_s = m_sec;
5417         utime.mtime_ns = m_nsec;
5418     }
5419     else if (ns) {
5420         if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
5421             PyErr_SetString(PyExc_TypeError,
5422                          "utime: 'ns' must be a tuple of two ints");
5423             return NULL;
5424         }
5425         utime.now = 0;
5426         if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
5427                                       &utime.atime_s, &utime.atime_ns) ||
5428             !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
5429                                        &utime.mtime_s, &utime.mtime_ns)) {
5430             return NULL;
5431         }
5432     }
5433     else {
5434         /* times and ns are both None/unspecified. use "now". */
5435         utime.now = 1;
5436     }
5437 
5438 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
5439     if (follow_symlinks_specified("utime", follow_symlinks))
5440         return NULL;
5441 #endif
5442 
5443     if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
5444         dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
5445         fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
5446         return NULL;
5447 
5448 #if !defined(HAVE_UTIMENSAT)
5449     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
5450         PyErr_SetString(PyExc_ValueError,
5451                      "utime: cannot use dir_fd and follow_symlinks "
5452                      "together on this platform");
5453         return NULL;
5454     }
5455 #endif
5456 
5457     if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
5458                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5459         return NULL;
5460     }
5461 
5462 #ifdef MS_WINDOWS
5463     Py_BEGIN_ALLOW_THREADS
5464     hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
5465                         NULL, OPEN_EXISTING,
5466                         FILE_FLAG_BACKUP_SEMANTICS, NULL);
5467     Py_END_ALLOW_THREADS
5468     if (hFile == INVALID_HANDLE_VALUE) {
5469         path_error(path);
5470         return NULL;
5471     }
5472 
5473     if (utime.now) {
5474         GetSystemTimeAsFileTime(&mtime);
5475         atime = mtime;
5476     }
5477     else {
5478         _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
5479         _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
5480     }
5481     if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
5482         /* Avoid putting the file name into the error here,
5483            as that may confuse the user into believing that
5484            something is wrong with the file, when it also
5485            could be the time stamp that gives a problem. */
5486         PyErr_SetFromWindowsErr(0);
5487         CloseHandle(hFile);
5488         return NULL;
5489     }
5490     CloseHandle(hFile);
5491 #else /* MS_WINDOWS */
5492     Py_BEGIN_ALLOW_THREADS
5493 
5494 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5495     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
5496         result = utime_nofollow_symlinks(&utime, path->narrow);
5497     else
5498 #endif
5499 
5500 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5501     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
5502         result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
5503 
5504     } else
5505 #endif
5506 
5507 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5508     if (path->fd != -1)
5509         result = utime_fd(&utime, path->fd);
5510     else
5511 #endif
5512 
5513     result = utime_default(&utime, path->narrow);
5514 
5515     Py_END_ALLOW_THREADS
5516 
5517 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5518     /* See utime_dir_fd implementation */
5519     if (result == -1 && errno == ENOSYS) {
5520         argument_unavailable_error(NULL, "dir_fd");
5521         return NULL;
5522     }
5523 #endif
5524 
5525     if (result < 0) {
5526         /* see previous comment about not putting filename in error here */
5527         posix_error();
5528         return NULL;
5529     }
5530 
5531 #endif /* MS_WINDOWS */
5532 
5533     Py_RETURN_NONE;
5534 }
5535 
5536 /* Process operations */
5537 
5538 
5539 /*[clinic input]
5540 os._exit
5541 
5542     status: int
5543 
5544 Exit to the system with specified status, without normal exit processing.
5545 [clinic start generated code]*/
5546 
5547 static PyObject *
os__exit_impl(PyObject * module,int status)5548 os__exit_impl(PyObject *module, int status)
5549 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5550 {
5551     _exit(status);
5552     return NULL; /* Make gcc -Wall happy */
5553 }
5554 
5555 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5556 #define EXECV_CHAR wchar_t
5557 #else
5558 #define EXECV_CHAR char
5559 #endif
5560 
5561 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5562 static void
free_string_array(EXECV_CHAR ** array,Py_ssize_t count)5563 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5564 {
5565     Py_ssize_t i;
5566     for (i = 0; i < count; i++)
5567         PyMem_Free(array[i]);
5568     PyMem_Free(array);
5569 }
5570 
5571 static int
fsconvert_strdup(PyObject * o,EXECV_CHAR ** out)5572 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5573 {
5574     Py_ssize_t size;
5575     PyObject *ub;
5576     int result = 0;
5577 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5578     if (!PyUnicode_FSDecoder(o, &ub))
5579         return 0;
5580     *out = PyUnicode_AsWideCharString(ub, &size);
5581     if (*out)
5582         result = 1;
5583 #else
5584     if (!PyUnicode_FSConverter(o, &ub))
5585         return 0;
5586     size = PyBytes_GET_SIZE(ub);
5587     *out = PyMem_Malloc(size + 1);
5588     if (*out) {
5589         memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5590         result = 1;
5591     } else
5592         PyErr_NoMemory();
5593 #endif
5594     Py_DECREF(ub);
5595     return result;
5596 }
5597 #endif
5598 
5599 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5600 static EXECV_CHAR**
parse_envlist(PyObject * env,Py_ssize_t * envc_ptr)5601 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5602 {
5603     Py_ssize_t i, pos, envc;
5604     PyObject *keys=NULL, *vals=NULL;
5605     PyObject *key, *val, *key2, *val2, *keyval;
5606     EXECV_CHAR **envlist;
5607 
5608     i = PyMapping_Size(env);
5609     if (i < 0)
5610         return NULL;
5611     envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5612     if (envlist == NULL) {
5613         PyErr_NoMemory();
5614         return NULL;
5615     }
5616     envc = 0;
5617     keys = PyMapping_Keys(env);
5618     if (!keys)
5619         goto error;
5620     vals = PyMapping_Values(env);
5621     if (!vals)
5622         goto error;
5623     if (!PyList_Check(keys) || !PyList_Check(vals)) {
5624         PyErr_Format(PyExc_TypeError,
5625                      "env.keys() or env.values() is not a list");
5626         goto error;
5627     }
5628 
5629     for (pos = 0; pos < i; pos++) {
5630         key = PyList_GetItem(keys, pos);
5631         val = PyList_GetItem(vals, pos);
5632         if (!key || !val)
5633             goto error;
5634 
5635 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5636         if (!PyUnicode_FSDecoder(key, &key2))
5637             goto error;
5638         if (!PyUnicode_FSDecoder(val, &val2)) {
5639             Py_DECREF(key2);
5640             goto error;
5641         }
5642         /* Search from index 1 because on Windows starting '=' is allowed for
5643            defining hidden environment variables. */
5644         if (PyUnicode_GET_LENGTH(key2) == 0 ||
5645             PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5646         {
5647             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5648             Py_DECREF(key2);
5649             Py_DECREF(val2);
5650             goto error;
5651         }
5652         keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5653 #else
5654         if (!PyUnicode_FSConverter(key, &key2))
5655             goto error;
5656         if (!PyUnicode_FSConverter(val, &val2)) {
5657             Py_DECREF(key2);
5658             goto error;
5659         }
5660         if (PyBytes_GET_SIZE(key2) == 0 ||
5661             strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5662         {
5663             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5664             Py_DECREF(key2);
5665             Py_DECREF(val2);
5666             goto error;
5667         }
5668         keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5669                                              PyBytes_AS_STRING(val2));
5670 #endif
5671         Py_DECREF(key2);
5672         Py_DECREF(val2);
5673         if (!keyval)
5674             goto error;
5675 
5676         if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5677             Py_DECREF(keyval);
5678             goto error;
5679         }
5680 
5681         Py_DECREF(keyval);
5682     }
5683     Py_DECREF(vals);
5684     Py_DECREF(keys);
5685 
5686     envlist[envc] = 0;
5687     *envc_ptr = envc;
5688     return envlist;
5689 
5690 error:
5691     Py_XDECREF(keys);
5692     Py_XDECREF(vals);
5693     free_string_array(envlist, envc);
5694     return NULL;
5695 }
5696 
5697 static EXECV_CHAR**
parse_arglist(PyObject * argv,Py_ssize_t * argc)5698 parse_arglist(PyObject* argv, Py_ssize_t *argc)
5699 {
5700     int i;
5701     EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5702     if (argvlist == NULL) {
5703         PyErr_NoMemory();
5704         return NULL;
5705     }
5706     for (i = 0; i < *argc; i++) {
5707         PyObject* item = PySequence_ITEM(argv, i);
5708         if (item == NULL)
5709             goto fail;
5710         if (!fsconvert_strdup(item, &argvlist[i])) {
5711             Py_DECREF(item);
5712             goto fail;
5713         }
5714         Py_DECREF(item);
5715     }
5716     argvlist[*argc] = NULL;
5717     return argvlist;
5718 fail:
5719     *argc = i;
5720     free_string_array(argvlist, *argc);
5721     return NULL;
5722 }
5723 
5724 #endif
5725 
5726 
5727 #ifdef HAVE_EXECV
5728 /*[clinic input]
5729 os.execv
5730 
5731     path: path_t
5732         Path of executable file.
5733     argv: object
5734         Tuple or list of strings.
5735     /
5736 
5737 Execute an executable path with arguments, replacing current process.
5738 [clinic start generated code]*/
5739 
5740 static PyObject *
os_execv_impl(PyObject * module,path_t * path,PyObject * argv)5741 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5742 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5743 {
5744     EXECV_CHAR **argvlist;
5745     Py_ssize_t argc;
5746 
5747     /* execv has two arguments: (path, argv), where
5748        argv is a list or tuple of strings. */
5749 
5750     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5751         PyErr_SetString(PyExc_TypeError,
5752                         "execv() arg 2 must be a tuple or list");
5753         return NULL;
5754     }
5755     argc = PySequence_Size(argv);
5756     if (argc < 1) {
5757         PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5758         return NULL;
5759     }
5760 
5761     argvlist = parse_arglist(argv, &argc);
5762     if (argvlist == NULL) {
5763         return NULL;
5764     }
5765     if (!argvlist[0][0]) {
5766         PyErr_SetString(PyExc_ValueError,
5767             "execv() arg 2 first element cannot be empty");
5768         free_string_array(argvlist, argc);
5769         return NULL;
5770     }
5771 
5772     if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5773         free_string_array(argvlist, argc);
5774         return NULL;
5775     }
5776 
5777     _Py_BEGIN_SUPPRESS_IPH
5778 #ifdef HAVE_WEXECV
5779     _wexecv(path->wide, argvlist);
5780 #else
5781     execv(path->narrow, argvlist);
5782 #endif
5783     _Py_END_SUPPRESS_IPH
5784 
5785     /* If we get here it's definitely an error */
5786 
5787     free_string_array(argvlist, argc);
5788     return posix_error();
5789 }
5790 
5791 
5792 /*[clinic input]
5793 os.execve
5794 
5795     path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5796         Path of executable file.
5797     argv: object
5798         Tuple or list of strings.
5799     env: object
5800         Dictionary of strings mapping to strings.
5801 
5802 Execute an executable path with arguments, replacing current process.
5803 [clinic start generated code]*/
5804 
5805 static PyObject *
os_execve_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env)5806 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5807 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5808 {
5809     EXECV_CHAR **argvlist = NULL;
5810     EXECV_CHAR **envlist;
5811     Py_ssize_t argc, envc;
5812 
5813     /* execve has three arguments: (path, argv, env), where
5814        argv is a list or tuple of strings and env is a dictionary
5815        like posix.environ. */
5816 
5817     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5818         PyErr_SetString(PyExc_TypeError,
5819                         "execve: argv must be a tuple or list");
5820         goto fail_0;
5821     }
5822     argc = PySequence_Size(argv);
5823     if (argc < 1) {
5824         PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5825         return NULL;
5826     }
5827 
5828     if (!PyMapping_Check(env)) {
5829         PyErr_SetString(PyExc_TypeError,
5830                         "execve: environment must be a mapping object");
5831         goto fail_0;
5832     }
5833 
5834     argvlist = parse_arglist(argv, &argc);
5835     if (argvlist == NULL) {
5836         goto fail_0;
5837     }
5838     if (!argvlist[0][0]) {
5839         PyErr_SetString(PyExc_ValueError,
5840             "execve: argv first element cannot be empty");
5841         goto fail_0;
5842     }
5843 
5844     envlist = parse_envlist(env, &envc);
5845     if (envlist == NULL)
5846         goto fail_0;
5847 
5848     if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5849         goto fail_1;
5850     }
5851 
5852     _Py_BEGIN_SUPPRESS_IPH
5853 #ifdef HAVE_FEXECVE
5854     if (path->fd > -1)
5855         fexecve(path->fd, argvlist, envlist);
5856     else
5857 #endif
5858 #ifdef HAVE_WEXECV
5859         _wexecve(path->wide, argvlist, envlist);
5860 #else
5861         execve(path->narrow, argvlist, envlist);
5862 #endif
5863     _Py_END_SUPPRESS_IPH
5864 
5865     /* If we get here it's definitely an error */
5866 
5867     posix_path_error(path);
5868   fail_1:
5869     free_string_array(envlist, envc);
5870   fail_0:
5871     if (argvlist)
5872         free_string_array(argvlist, argc);
5873     return NULL;
5874 }
5875 
5876 #endif /* HAVE_EXECV */
5877 
5878 #ifdef HAVE_POSIX_SPAWN
5879 
5880 enum posix_spawn_file_actions_identifier {
5881     POSIX_SPAWN_OPEN,
5882     POSIX_SPAWN_CLOSE,
5883     POSIX_SPAWN_DUP2
5884 };
5885 
5886 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
5887 static int
5888 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
5889 #endif
5890 
5891 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)5892 parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
5893                         int resetids, int setsid, PyObject *setsigmask,
5894                         PyObject *setsigdef, PyObject *scheduler,
5895                         posix_spawnattr_t *attrp)
5896 {
5897     long all_flags = 0;
5898 
5899     errno = posix_spawnattr_init(attrp);
5900     if (errno) {
5901         posix_error();
5902         return -1;
5903     }
5904 
5905     if (setpgroup) {
5906         pid_t pgid = PyLong_AsPid(setpgroup);
5907         if (pgid == (pid_t)-1 && PyErr_Occurred()) {
5908             goto fail;
5909         }
5910         errno = posix_spawnattr_setpgroup(attrp, pgid);
5911         if (errno) {
5912             posix_error();
5913             goto fail;
5914         }
5915         all_flags |= POSIX_SPAWN_SETPGROUP;
5916     }
5917 
5918     if (resetids) {
5919         all_flags |= POSIX_SPAWN_RESETIDS;
5920     }
5921 
5922     if (setsid) {
5923 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5924         if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
5925 #endif
5926 #ifdef POSIX_SPAWN_SETSID
5927         all_flags |= POSIX_SPAWN_SETSID;
5928 #elif defined(POSIX_SPAWN_SETSID_NP)
5929         all_flags |= POSIX_SPAWN_SETSID_NP;
5930 #else
5931         argument_unavailable_error(func_name, "setsid");
5932         return -1;
5933 #endif
5934 
5935 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5936         } else {
5937             argument_unavailable_error(func_name, "setsid");
5938             return -1;
5939         }
5940 #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
5941 
5942     }
5943 
5944 #ifdef HAVE_SIGSET_T
5945    if (setsigmask) {
5946         sigset_t set;
5947         if (!_Py_Sigset_Converter(setsigmask, &set)) {
5948             goto fail;
5949         }
5950         errno = posix_spawnattr_setsigmask(attrp, &set);
5951         if (errno) {
5952             posix_error();
5953             goto fail;
5954         }
5955         all_flags |= POSIX_SPAWN_SETSIGMASK;
5956     }
5957 
5958     if (setsigdef) {
5959         sigset_t set;
5960         if (!_Py_Sigset_Converter(setsigdef, &set)) {
5961             goto fail;
5962         }
5963         errno = posix_spawnattr_setsigdefault(attrp, &set);
5964         if (errno) {
5965             posix_error();
5966             goto fail;
5967         }
5968         all_flags |= POSIX_SPAWN_SETSIGDEF;
5969     }
5970 #else
5971     if (setsigmask || setsigdef) {
5972         PyErr_SetString(PyExc_NotImplementedError,
5973                         "sigset is not supported on this platform");
5974         goto fail;
5975     }
5976 #endif
5977 
5978     if (scheduler) {
5979 #ifdef POSIX_SPAWN_SETSCHEDULER
5980         PyObject *py_schedpolicy;
5981         PyObject *schedparam_obj;
5982         struct sched_param schedparam;
5983 
5984         if (!PyArg_ParseTuple(scheduler, "OO"
5985                         ";A scheduler tuple must have two elements",
5986                         &py_schedpolicy, &schedparam_obj)) {
5987             goto fail;
5988         }
5989         if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
5990             goto fail;
5991         }
5992         if (py_schedpolicy != Py_None) {
5993             int schedpolicy = _PyLong_AsInt(py_schedpolicy);
5994 
5995             if (schedpolicy == -1 && PyErr_Occurred()) {
5996                 goto fail;
5997             }
5998             errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
5999             if (errno) {
6000                 posix_error();
6001                 goto fail;
6002             }
6003             all_flags |= POSIX_SPAWN_SETSCHEDULER;
6004         }
6005         errno = posix_spawnattr_setschedparam(attrp, &schedparam);
6006         if (errno) {
6007             posix_error();
6008             goto fail;
6009         }
6010         all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
6011 #else
6012         PyErr_SetString(PyExc_NotImplementedError,
6013                 "The scheduler option is not supported in this system.");
6014         goto fail;
6015 #endif
6016     }
6017 
6018     errno = posix_spawnattr_setflags(attrp, all_flags);
6019     if (errno) {
6020         posix_error();
6021         goto fail;
6022     }
6023 
6024     return 0;
6025 
6026 fail:
6027     (void)posix_spawnattr_destroy(attrp);
6028     return -1;
6029 }
6030 
6031 static int
parse_file_actions(PyObject * file_actions,posix_spawn_file_actions_t * file_actionsp,PyObject * temp_buffer)6032 parse_file_actions(PyObject *file_actions,
6033                    posix_spawn_file_actions_t *file_actionsp,
6034                    PyObject *temp_buffer)
6035 {
6036     PyObject *seq;
6037     PyObject *file_action = NULL;
6038     PyObject *tag_obj;
6039 
6040     seq = PySequence_Fast(file_actions,
6041                           "file_actions must be a sequence or None");
6042     if (seq == NULL) {
6043         return -1;
6044     }
6045 
6046     errno = posix_spawn_file_actions_init(file_actionsp);
6047     if (errno) {
6048         posix_error();
6049         Py_DECREF(seq);
6050         return -1;
6051     }
6052 
6053     for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
6054         file_action = PySequence_Fast_GET_ITEM(seq, i);
6055         Py_INCREF(file_action);
6056         if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
6057             PyErr_SetString(PyExc_TypeError,
6058                 "Each file_actions element must be a non-empty tuple");
6059             goto fail;
6060         }
6061         long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
6062         if (tag == -1 && PyErr_Occurred()) {
6063             goto fail;
6064         }
6065 
6066         /* Populate the file_actions object */
6067         switch (tag) {
6068             case POSIX_SPAWN_OPEN: {
6069                 int fd, oflag;
6070                 PyObject *path;
6071                 unsigned long mode;
6072                 if (!PyArg_ParseTuple(file_action, "OiO&ik"
6073                         ";A open file_action tuple must have 5 elements",
6074                         &tag_obj, &fd, PyUnicode_FSConverter, &path,
6075                         &oflag, &mode))
6076                 {
6077                     goto fail;
6078                 }
6079                 if (PyList_Append(temp_buffer, path)) {
6080                     Py_DECREF(path);
6081                     goto fail;
6082                 }
6083                 errno = posix_spawn_file_actions_addopen(file_actionsp,
6084                         fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
6085                 Py_DECREF(path);
6086                 if (errno) {
6087                     posix_error();
6088                     goto fail;
6089                 }
6090                 break;
6091             }
6092             case POSIX_SPAWN_CLOSE: {
6093                 int fd;
6094                 if (!PyArg_ParseTuple(file_action, "Oi"
6095                         ";A close file_action tuple must have 2 elements",
6096                         &tag_obj, &fd))
6097                 {
6098                     goto fail;
6099                 }
6100                 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
6101                 if (errno) {
6102                     posix_error();
6103                     goto fail;
6104                 }
6105                 break;
6106             }
6107             case POSIX_SPAWN_DUP2: {
6108                 int fd1, fd2;
6109                 if (!PyArg_ParseTuple(file_action, "Oii"
6110                         ";A dup2 file_action tuple must have 3 elements",
6111                         &tag_obj, &fd1, &fd2))
6112                 {
6113                     goto fail;
6114                 }
6115                 errno = posix_spawn_file_actions_adddup2(file_actionsp,
6116                                                          fd1, fd2);
6117                 if (errno) {
6118                     posix_error();
6119                     goto fail;
6120                 }
6121                 break;
6122             }
6123             default: {
6124                 PyErr_SetString(PyExc_TypeError,
6125                                 "Unknown file_actions identifier");
6126                 goto fail;
6127             }
6128         }
6129         Py_DECREF(file_action);
6130     }
6131 
6132     Py_DECREF(seq);
6133     return 0;
6134 
6135 fail:
6136     Py_DECREF(seq);
6137     Py_DECREF(file_action);
6138     (void)posix_spawn_file_actions_destroy(file_actionsp);
6139     return -1;
6140 }
6141 
6142 
6143 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)6144 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
6145                PyObject *env, PyObject *file_actions,
6146                PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
6147                PyObject *setsigdef, PyObject *scheduler)
6148 {
6149     const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
6150     EXECV_CHAR **argvlist = NULL;
6151     EXECV_CHAR **envlist = NULL;
6152     posix_spawn_file_actions_t file_actions_buf;
6153     posix_spawn_file_actions_t *file_actionsp = NULL;
6154     posix_spawnattr_t attr;
6155     posix_spawnattr_t *attrp = NULL;
6156     Py_ssize_t argc, envc;
6157     PyObject *result = NULL;
6158     PyObject *temp_buffer = NULL;
6159     pid_t pid;
6160     int err_code;
6161 
6162     /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
6163        argv is a list or tuple of strings and env is a dictionary
6164        like posix.environ. */
6165 
6166     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6167         PyErr_Format(PyExc_TypeError,
6168                      "%s: argv must be a tuple or list", func_name);
6169         goto exit;
6170     }
6171     argc = PySequence_Size(argv);
6172     if (argc < 1) {
6173         PyErr_Format(PyExc_ValueError,
6174                      "%s: argv must not be empty", func_name);
6175         return NULL;
6176     }
6177 
6178     if (!PyMapping_Check(env)) {
6179         PyErr_Format(PyExc_TypeError,
6180                      "%s: environment must be a mapping object", func_name);
6181         goto exit;
6182     }
6183 
6184     argvlist = parse_arglist(argv, &argc);
6185     if (argvlist == NULL) {
6186         goto exit;
6187     }
6188     if (!argvlist[0][0]) {
6189         PyErr_Format(PyExc_ValueError,
6190                      "%s: argv first element cannot be empty", func_name);
6191         goto exit;
6192     }
6193 
6194     envlist = parse_envlist(env, &envc);
6195     if (envlist == NULL) {
6196         goto exit;
6197     }
6198 
6199     if (file_actions != NULL && file_actions != Py_None) {
6200         /* There is a bug in old versions of glibc that makes some of the
6201          * helper functions for manipulating file actions not copy the provided
6202          * buffers. The problem is that posix_spawn_file_actions_addopen does not
6203          * copy the value of path for some old versions of glibc (<2.20).
6204          * The use of temp_buffer here is a workaround that keeps the
6205          * python objects that own the buffers alive until posix_spawn gets called.
6206          * Check https://bugs.python.org/issue33630 and
6207          * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
6208         temp_buffer = PyList_New(0);
6209         if (!temp_buffer) {
6210             goto exit;
6211         }
6212         if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
6213             goto exit;
6214         }
6215         file_actionsp = &file_actions_buf;
6216     }
6217 
6218     if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
6219                                 setsigmask, setsigdef, scheduler, &attr)) {
6220         goto exit;
6221     }
6222     attrp = &attr;
6223 
6224     if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
6225         goto exit;
6226     }
6227 
6228     _Py_BEGIN_SUPPRESS_IPH
6229 #ifdef HAVE_POSIX_SPAWNP
6230     if (use_posix_spawnp) {
6231         err_code = posix_spawnp(&pid, path->narrow,
6232                                 file_actionsp, attrp, argvlist, envlist);
6233     }
6234     else
6235 #endif /* HAVE_POSIX_SPAWNP */
6236     {
6237         err_code = posix_spawn(&pid, path->narrow,
6238                                file_actionsp, attrp, argvlist, envlist);
6239     }
6240     _Py_END_SUPPRESS_IPH
6241 
6242     if (err_code) {
6243         errno = err_code;
6244         PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
6245         goto exit;
6246     }
6247 #ifdef _Py_MEMORY_SANITIZER
6248     __msan_unpoison(&pid, sizeof(pid));
6249 #endif
6250     result = PyLong_FromPid(pid);
6251 
6252 exit:
6253     if (file_actionsp) {
6254         (void)posix_spawn_file_actions_destroy(file_actionsp);
6255     }
6256     if (attrp) {
6257         (void)posix_spawnattr_destroy(attrp);
6258     }
6259     if (envlist) {
6260         free_string_array(envlist, envc);
6261     }
6262     if (argvlist) {
6263         free_string_array(argvlist, argc);
6264     }
6265     Py_XDECREF(temp_buffer);
6266     return result;
6267 }
6268 
6269 
6270 /*[clinic input]
6271 
6272 os.posix_spawn
6273     path: path_t
6274         Path of executable file.
6275     argv: object
6276         Tuple or list of strings.
6277     env: object
6278         Dictionary of strings mapping to strings.
6279     /
6280     *
6281     file_actions: object(c_default='NULL') = ()
6282         A sequence of file action tuples.
6283     setpgroup: object = NULL
6284         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6285     resetids: bool(accept={int}) = False
6286         If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
6287     setsid: bool(accept={int}) = False
6288         If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6289     setsigmask: object(c_default='NULL') = ()
6290         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6291     setsigdef: object(c_default='NULL') = ()
6292         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6293     scheduler: object = NULL
6294         A tuple with the scheduler policy (optional) and parameters.
6295 
6296 Execute the program specified by path in a new process.
6297 [clinic start generated code]*/
6298 
6299 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)6300 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
6301                     PyObject *env, PyObject *file_actions,
6302                     PyObject *setpgroup, int resetids, int setsid,
6303                     PyObject *setsigmask, PyObject *setsigdef,
6304                     PyObject *scheduler)
6305 /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
6306 {
6307     return py_posix_spawn(0, module, path, argv, env, file_actions,
6308                           setpgroup, resetids, setsid, setsigmask, setsigdef,
6309                           scheduler);
6310 }
6311  #endif /* HAVE_POSIX_SPAWN */
6312 
6313 
6314 
6315 #ifdef HAVE_POSIX_SPAWNP
6316 /*[clinic input]
6317 
6318 os.posix_spawnp
6319     path: path_t
6320         Path of executable file.
6321     argv: object
6322         Tuple or list of strings.
6323     env: object
6324         Dictionary of strings mapping to strings.
6325     /
6326     *
6327     file_actions: object(c_default='NULL') = ()
6328         A sequence of file action tuples.
6329     setpgroup: object = NULL
6330         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6331     resetids: bool(accept={int}) = False
6332         If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
6333     setsid: bool(accept={int}) = False
6334         If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6335     setsigmask: object(c_default='NULL') = ()
6336         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6337     setsigdef: object(c_default='NULL') = ()
6338         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6339     scheduler: object = NULL
6340         A tuple with the scheduler policy (optional) and parameters.
6341 
6342 Execute the program specified by path in a new process.
6343 [clinic start generated code]*/
6344 
6345 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)6346 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
6347                      PyObject *env, PyObject *file_actions,
6348                      PyObject *setpgroup, int resetids, int setsid,
6349                      PyObject *setsigmask, PyObject *setsigdef,
6350                      PyObject *scheduler)
6351 /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
6352 {
6353     return py_posix_spawn(1, module, path, argv, env, file_actions,
6354                           setpgroup, resetids, setsid, setsigmask, setsigdef,
6355                           scheduler);
6356 }
6357 #endif /* HAVE_POSIX_SPAWNP */
6358 
6359 #ifdef HAVE_RTPSPAWN
6360 static intptr_t
_rtp_spawn(int mode,const char * rtpFileName,const char * argv[],const char * envp[])6361 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
6362                const char  *envp[])
6363 {
6364      RTP_ID rtpid;
6365      int status;
6366      pid_t res;
6367      int async_err = 0;
6368 
6369      /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
6370         uStackSize=0 cannot be used, the default stack size is too small for
6371         Python. */
6372      if (envp) {
6373          rtpid = rtpSpawn(rtpFileName, argv, envp,
6374                           100, 0x1000000, 0, VX_FP_TASK);
6375      }
6376      else {
6377          rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
6378                           100, 0x1000000, 0, VX_FP_TASK);
6379      }
6380      if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
6381          do {
6382              res = waitpid((pid_t)rtpid, &status, 0);
6383          } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6384 
6385          if (res < 0)
6386              return RTP_ID_ERROR;
6387          return ((intptr_t)status);
6388      }
6389      return ((intptr_t)rtpid);
6390 }
6391 #endif
6392 
6393 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
6394 /*[clinic input]
6395 os.spawnv
6396 
6397     mode: int
6398         Mode of process creation.
6399     path: path_t
6400         Path of executable file.
6401     argv: object
6402         Tuple or list of strings.
6403     /
6404 
6405 Execute the program specified by path in a new process.
6406 [clinic start generated code]*/
6407 
6408 static PyObject *
os_spawnv_impl(PyObject * module,int mode,path_t * path,PyObject * argv)6409 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
6410 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
6411 {
6412     EXECV_CHAR **argvlist;
6413     int i;
6414     Py_ssize_t argc;
6415     intptr_t spawnval;
6416     PyObject *(*getitem)(PyObject *, Py_ssize_t);
6417 
6418     /* spawnv has three arguments: (mode, path, argv), where
6419        argv is a list or tuple of strings. */
6420 
6421     if (PyList_Check(argv)) {
6422         argc = PyList_Size(argv);
6423         getitem = PyList_GetItem;
6424     }
6425     else if (PyTuple_Check(argv)) {
6426         argc = PyTuple_Size(argv);
6427         getitem = PyTuple_GetItem;
6428     }
6429     else {
6430         PyErr_SetString(PyExc_TypeError,
6431                         "spawnv() arg 2 must be a tuple or list");
6432         return NULL;
6433     }
6434     if (argc == 0) {
6435         PyErr_SetString(PyExc_ValueError,
6436             "spawnv() arg 2 cannot be empty");
6437         return NULL;
6438     }
6439 
6440     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6441     if (argvlist == NULL) {
6442         return PyErr_NoMemory();
6443     }
6444     for (i = 0; i < argc; i++) {
6445         if (!fsconvert_strdup((*getitem)(argv, i),
6446                               &argvlist[i])) {
6447             free_string_array(argvlist, i);
6448             PyErr_SetString(
6449                 PyExc_TypeError,
6450                 "spawnv() arg 2 must contain only strings");
6451             return NULL;
6452         }
6453         if (i == 0 && !argvlist[0][0]) {
6454             free_string_array(argvlist, i + 1);
6455             PyErr_SetString(
6456                 PyExc_ValueError,
6457                 "spawnv() arg 2 first element cannot be empty");
6458             return NULL;
6459         }
6460     }
6461     argvlist[argc] = NULL;
6462 
6463 #if !defined(HAVE_RTPSPAWN)
6464     if (mode == _OLD_P_OVERLAY)
6465         mode = _P_OVERLAY;
6466 #endif
6467 
6468     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
6469                     Py_None) < 0) {
6470         free_string_array(argvlist, argc);
6471         return NULL;
6472     }
6473 
6474     Py_BEGIN_ALLOW_THREADS
6475     _Py_BEGIN_SUPPRESS_IPH
6476 #ifdef HAVE_WSPAWNV
6477     spawnval = _wspawnv(mode, path->wide, argvlist);
6478 #elif defined(HAVE_RTPSPAWN)
6479     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
6480 #else
6481     spawnval = _spawnv(mode, path->narrow, argvlist);
6482 #endif
6483     _Py_END_SUPPRESS_IPH
6484     Py_END_ALLOW_THREADS
6485 
6486     free_string_array(argvlist, argc);
6487 
6488     if (spawnval == -1)
6489         return posix_error();
6490     else
6491         return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6492 }
6493 
6494 /*[clinic input]
6495 os.spawnve
6496 
6497     mode: int
6498         Mode of process creation.
6499     path: path_t
6500         Path of executable file.
6501     argv: object
6502         Tuple or list of strings.
6503     env: object
6504         Dictionary of strings mapping to strings.
6505     /
6506 
6507 Execute the program specified by path in a new process.
6508 [clinic start generated code]*/
6509 
6510 static PyObject *
os_spawnve_impl(PyObject * module,int mode,path_t * path,PyObject * argv,PyObject * env)6511 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
6512                 PyObject *env)
6513 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
6514 {
6515     EXECV_CHAR **argvlist;
6516     EXECV_CHAR **envlist;
6517     PyObject *res = NULL;
6518     Py_ssize_t argc, i, envc;
6519     intptr_t spawnval;
6520     PyObject *(*getitem)(PyObject *, Py_ssize_t);
6521     Py_ssize_t lastarg = 0;
6522 
6523     /* spawnve has four arguments: (mode, path, argv, env), where
6524        argv is a list or tuple of strings and env is a dictionary
6525        like posix.environ. */
6526 
6527     if (PyList_Check(argv)) {
6528         argc = PyList_Size(argv);
6529         getitem = PyList_GetItem;
6530     }
6531     else if (PyTuple_Check(argv)) {
6532         argc = PyTuple_Size(argv);
6533         getitem = PyTuple_GetItem;
6534     }
6535     else {
6536         PyErr_SetString(PyExc_TypeError,
6537                         "spawnve() arg 2 must be a tuple or list");
6538         goto fail_0;
6539     }
6540     if (argc == 0) {
6541         PyErr_SetString(PyExc_ValueError,
6542             "spawnve() arg 2 cannot be empty");
6543         goto fail_0;
6544     }
6545     if (!PyMapping_Check(env)) {
6546         PyErr_SetString(PyExc_TypeError,
6547                         "spawnve() arg 3 must be a mapping object");
6548         goto fail_0;
6549     }
6550 
6551     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6552     if (argvlist == NULL) {
6553         PyErr_NoMemory();
6554         goto fail_0;
6555     }
6556     for (i = 0; i < argc; i++) {
6557         if (!fsconvert_strdup((*getitem)(argv, i),
6558                               &argvlist[i]))
6559         {
6560             lastarg = i;
6561             goto fail_1;
6562         }
6563         if (i == 0 && !argvlist[0][0]) {
6564             lastarg = i + 1;
6565             PyErr_SetString(
6566                 PyExc_ValueError,
6567                 "spawnv() arg 2 first element cannot be empty");
6568             goto fail_1;
6569         }
6570     }
6571     lastarg = argc;
6572     argvlist[argc] = NULL;
6573 
6574     envlist = parse_envlist(env, &envc);
6575     if (envlist == NULL)
6576         goto fail_1;
6577 
6578 #if !defined(HAVE_RTPSPAWN)
6579     if (mode == _OLD_P_OVERLAY)
6580         mode = _P_OVERLAY;
6581 #endif
6582 
6583     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6584         goto fail_2;
6585     }
6586 
6587     Py_BEGIN_ALLOW_THREADS
6588     _Py_BEGIN_SUPPRESS_IPH
6589 #ifdef HAVE_WSPAWNV
6590     spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6591 #elif defined(HAVE_RTPSPAWN)
6592     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6593                            (const char **)envlist);
6594 #else
6595     spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6596 #endif
6597     _Py_END_SUPPRESS_IPH
6598     Py_END_ALLOW_THREADS
6599 
6600     if (spawnval == -1)
6601         (void) posix_error();
6602     else
6603         res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6604 
6605   fail_2:
6606     while (--envc >= 0) {
6607         PyMem_Free(envlist[envc]);
6608     }
6609     PyMem_Free(envlist);
6610   fail_1:
6611     free_string_array(argvlist, lastarg);
6612   fail_0:
6613     return res;
6614 }
6615 
6616 #endif /* HAVE_SPAWNV */
6617 
6618 #ifdef HAVE_FORK
6619 
6620 /* Helper function to validate arguments.
6621    Returns 0 on success.  non-zero on failure with a TypeError raised.
6622    If obj is non-NULL it must be callable.  */
6623 static int
check_null_or_callable(PyObject * obj,const char * obj_name)6624 check_null_or_callable(PyObject *obj, const char* obj_name)
6625 {
6626     if (obj && !PyCallable_Check(obj)) {
6627         PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6628                      obj_name, _PyType_Name(Py_TYPE(obj)));
6629         return -1;
6630     }
6631     return 0;
6632 }
6633 
6634 /*[clinic input]
6635 os.register_at_fork
6636 
6637     *
6638     before: object=NULL
6639         A callable to be called in the parent before the fork() syscall.
6640     after_in_child: object=NULL
6641         A callable to be called in the child after fork().
6642     after_in_parent: object=NULL
6643         A callable to be called in the parent after fork().
6644 
6645 Register callables to be called when forking a new process.
6646 
6647 'before' callbacks are called in reverse order.
6648 'after_in_child' and 'after_in_parent' callbacks are called in order.
6649 
6650 [clinic start generated code]*/
6651 
6652 static PyObject *
os_register_at_fork_impl(PyObject * module,PyObject * before,PyObject * after_in_child,PyObject * after_in_parent)6653 os_register_at_fork_impl(PyObject *module, PyObject *before,
6654                          PyObject *after_in_child, PyObject *after_in_parent)
6655 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6656 {
6657     PyInterpreterState *interp;
6658 
6659     if (!before && !after_in_child && !after_in_parent) {
6660         PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6661         return NULL;
6662     }
6663     if (check_null_or_callable(before, "before") ||
6664         check_null_or_callable(after_in_child, "after_in_child") ||
6665         check_null_or_callable(after_in_parent, "after_in_parent")) {
6666         return NULL;
6667     }
6668     interp = _PyInterpreterState_GET();
6669 
6670     if (register_at_forker(&interp->before_forkers, before)) {
6671         return NULL;
6672     }
6673     if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6674         return NULL;
6675     }
6676     if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6677         return NULL;
6678     }
6679     Py_RETURN_NONE;
6680 }
6681 #endif /* HAVE_FORK */
6682 
6683 
6684 #ifdef HAVE_FORK1
6685 /*[clinic input]
6686 os.fork1
6687 
6688 Fork a child process with a single multiplexed (i.e., not bound) thread.
6689 
6690 Return 0 to child process and PID of child to parent process.
6691 [clinic start generated code]*/
6692 
6693 static PyObject *
os_fork1_impl(PyObject * module)6694 os_fork1_impl(PyObject *module)
6695 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6696 {
6697     pid_t pid;
6698 
6699     if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
6700         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6701         return NULL;
6702     }
6703     PyOS_BeforeFork();
6704     pid = fork1();
6705     if (pid == 0) {
6706         /* child: this clobbers and resets the import lock. */
6707         PyOS_AfterFork_Child();
6708     } else {
6709         /* parent: release the import lock. */
6710         PyOS_AfterFork_Parent();
6711     }
6712     if (pid == -1)
6713         return posix_error();
6714     return PyLong_FromPid(pid);
6715 }
6716 #endif /* HAVE_FORK1 */
6717 
6718 
6719 #ifdef HAVE_FORK
6720 /*[clinic input]
6721 os.fork
6722 
6723 Fork a child process.
6724 
6725 Return 0 to child process and PID of child to parent process.
6726 [clinic start generated code]*/
6727 
6728 static PyObject *
os_fork_impl(PyObject * module)6729 os_fork_impl(PyObject *module)
6730 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6731 {
6732     pid_t pid;
6733     PyInterpreterState *interp = _PyInterpreterState_GET();
6734     if (interp->config._isolated_interpreter) {
6735         PyErr_SetString(PyExc_RuntimeError,
6736                         "fork not supported for isolated subinterpreters");
6737         return NULL;
6738     }
6739     if (PySys_Audit("os.fork", NULL) < 0) {
6740         return NULL;
6741     }
6742     PyOS_BeforeFork();
6743     pid = fork();
6744     if (pid == 0) {
6745         /* child: this clobbers and resets the import lock. */
6746         PyOS_AfterFork_Child();
6747     } else {
6748         /* parent: release the import lock. */
6749         PyOS_AfterFork_Parent();
6750     }
6751     if (pid == -1)
6752         return posix_error();
6753     return PyLong_FromPid(pid);
6754 }
6755 #endif /* HAVE_FORK */
6756 
6757 
6758 #ifdef HAVE_SCHED_H
6759 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6760 /*[clinic input]
6761 os.sched_get_priority_max
6762 
6763     policy: int
6764 
6765 Get the maximum scheduling priority for policy.
6766 [clinic start generated code]*/
6767 
6768 static PyObject *
os_sched_get_priority_max_impl(PyObject * module,int policy)6769 os_sched_get_priority_max_impl(PyObject *module, int policy)
6770 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6771 {
6772     int max;
6773 
6774     max = sched_get_priority_max(policy);
6775     if (max < 0)
6776         return posix_error();
6777     return PyLong_FromLong(max);
6778 }
6779 
6780 
6781 /*[clinic input]
6782 os.sched_get_priority_min
6783 
6784     policy: int
6785 
6786 Get the minimum scheduling priority for policy.
6787 [clinic start generated code]*/
6788 
6789 static PyObject *
os_sched_get_priority_min_impl(PyObject * module,int policy)6790 os_sched_get_priority_min_impl(PyObject *module, int policy)
6791 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6792 {
6793     int min = sched_get_priority_min(policy);
6794     if (min < 0)
6795         return posix_error();
6796     return PyLong_FromLong(min);
6797 }
6798 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6799 
6800 
6801 #ifdef HAVE_SCHED_SETSCHEDULER
6802 /*[clinic input]
6803 os.sched_getscheduler
6804     pid: pid_t
6805     /
6806 
6807 Get the scheduling policy for the process identified by pid.
6808 
6809 Passing 0 for pid returns the scheduling policy for the calling process.
6810 [clinic start generated code]*/
6811 
6812 static PyObject *
os_sched_getscheduler_impl(PyObject * module,pid_t pid)6813 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6814 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
6815 {
6816     int policy;
6817 
6818     policy = sched_getscheduler(pid);
6819     if (policy < 0)
6820         return posix_error();
6821     return PyLong_FromLong(policy);
6822 }
6823 #endif /* HAVE_SCHED_SETSCHEDULER */
6824 
6825 
6826 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6827 /*[clinic input]
6828 class os.sched_param "PyObject *" "SchedParamType"
6829 
6830 @classmethod
6831 os.sched_param.__new__
6832 
6833     sched_priority: object
6834         A scheduling parameter.
6835 
6836 Currently has only one field: sched_priority
6837 [clinic start generated code]*/
6838 
6839 static PyObject *
os_sched_param_impl(PyTypeObject * type,PyObject * sched_priority)6840 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6841 /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
6842 {
6843     PyObject *res;
6844 
6845     res = PyStructSequence_New(type);
6846     if (!res)
6847         return NULL;
6848     Py_INCREF(sched_priority);
6849     PyStructSequence_SET_ITEM(res, 0, sched_priority);
6850     return res;
6851 }
6852 
6853 PyDoc_VAR(os_sched_param__doc__);
6854 
6855 static PyStructSequence_Field sched_param_fields[] = {
6856     {"sched_priority", "the scheduling priority"},
6857     {0}
6858 };
6859 
6860 static PyStructSequence_Desc sched_param_desc = {
6861     "sched_param", /* name */
6862     os_sched_param__doc__, /* doc */
6863     sched_param_fields,
6864     1
6865 };
6866 
6867 static int
convert_sched_param(PyObject * module,PyObject * param,struct sched_param * res)6868 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
6869 {
6870     long priority;
6871 
6872     if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
6873         PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
6874         return 0;
6875     }
6876     priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
6877     if (priority == -1 && PyErr_Occurred())
6878         return 0;
6879     if (priority > INT_MAX || priority < INT_MIN) {
6880         PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
6881         return 0;
6882     }
6883     res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
6884     return 1;
6885 }
6886 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
6887 
6888 
6889 #ifdef HAVE_SCHED_SETSCHEDULER
6890 /*[clinic input]
6891 os.sched_setscheduler
6892 
6893     pid: pid_t
6894     policy: int
6895     param as param_obj: object
6896     /
6897 
6898 Set the scheduling policy for the process identified by pid.
6899 
6900 If pid is 0, the calling process is changed.
6901 param is an instance of sched_param.
6902 [clinic start generated code]*/
6903 
6904 static PyObject *
os_sched_setscheduler_impl(PyObject * module,pid_t pid,int policy,PyObject * param_obj)6905 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
6906                            PyObject *param_obj)
6907 /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
6908 {
6909     struct sched_param param;
6910     if (!convert_sched_param(module, param_obj, &param)) {
6911         return NULL;
6912     }
6913 
6914     /*
6915     ** sched_setscheduler() returns 0 in Linux, but the previous
6916     ** scheduling policy under Solaris/Illumos, and others.
6917     ** On error, -1 is returned in all Operating Systems.
6918     */
6919     if (sched_setscheduler(pid, policy, &param) == -1)
6920         return posix_error();
6921     Py_RETURN_NONE;
6922 }
6923 #endif  /* HAVE_SCHED_SETSCHEDULER*/
6924 
6925 
6926 #ifdef HAVE_SCHED_SETPARAM
6927 /*[clinic input]
6928 os.sched_getparam
6929     pid: pid_t
6930     /
6931 
6932 Returns scheduling parameters for the process identified by pid.
6933 
6934 If pid is 0, returns parameters for the calling process.
6935 Return value is an instance of sched_param.
6936 [clinic start generated code]*/
6937 
6938 static PyObject *
os_sched_getparam_impl(PyObject * module,pid_t pid)6939 os_sched_getparam_impl(PyObject *module, pid_t pid)
6940 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
6941 {
6942     struct sched_param param;
6943     PyObject *result;
6944     PyObject *priority;
6945 
6946     if (sched_getparam(pid, &param))
6947         return posix_error();
6948     PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
6949     result = PyStructSequence_New((PyTypeObject *)SchedParamType);
6950     if (!result)
6951         return NULL;
6952     priority = PyLong_FromLong(param.sched_priority);
6953     if (!priority) {
6954         Py_DECREF(result);
6955         return NULL;
6956     }
6957     PyStructSequence_SET_ITEM(result, 0, priority);
6958     return result;
6959 }
6960 
6961 
6962 /*[clinic input]
6963 os.sched_setparam
6964     pid: pid_t
6965     param as param_obj: object
6966     /
6967 
6968 Set scheduling parameters for the process identified by pid.
6969 
6970 If pid is 0, sets parameters for the calling process.
6971 param should be an instance of sched_param.
6972 [clinic start generated code]*/
6973 
6974 static PyObject *
os_sched_setparam_impl(PyObject * module,pid_t pid,PyObject * param_obj)6975 os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
6976 /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
6977 {
6978     struct sched_param param;
6979     if (!convert_sched_param(module, param_obj, &param)) {
6980         return NULL;
6981     }
6982 
6983     if (sched_setparam(pid, &param))
6984         return posix_error();
6985     Py_RETURN_NONE;
6986 }
6987 #endif /* HAVE_SCHED_SETPARAM */
6988 
6989 
6990 #ifdef HAVE_SCHED_RR_GET_INTERVAL
6991 /*[clinic input]
6992 os.sched_rr_get_interval -> double
6993     pid: pid_t
6994     /
6995 
6996 Return the round-robin quantum for the process identified by pid, in seconds.
6997 
6998 Value returned is a float.
6999 [clinic start generated code]*/
7000 
7001 static double
os_sched_rr_get_interval_impl(PyObject * module,pid_t pid)7002 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
7003 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
7004 {
7005     struct timespec interval;
7006     if (sched_rr_get_interval(pid, &interval)) {
7007         posix_error();
7008         return -1.0;
7009     }
7010 #ifdef _Py_MEMORY_SANITIZER
7011     __msan_unpoison(&interval, sizeof(interval));
7012 #endif
7013     return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
7014 }
7015 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
7016 
7017 
7018 /*[clinic input]
7019 os.sched_yield
7020 
7021 Voluntarily relinquish the CPU.
7022 [clinic start generated code]*/
7023 
7024 static PyObject *
os_sched_yield_impl(PyObject * module)7025 os_sched_yield_impl(PyObject *module)
7026 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
7027 {
7028     if (sched_yield())
7029         return posix_error();
7030     Py_RETURN_NONE;
7031 }
7032 
7033 #ifdef HAVE_SCHED_SETAFFINITY
7034 /* The minimum number of CPUs allocated in a cpu_set_t */
7035 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
7036 
7037 /*[clinic input]
7038 os.sched_setaffinity
7039     pid: pid_t
7040     mask : object
7041     /
7042 
7043 Set the CPU affinity of the process identified by pid to mask.
7044 
7045 mask should be an iterable of integers identifying CPUs.
7046 [clinic start generated code]*/
7047 
7048 static PyObject *
os_sched_setaffinity_impl(PyObject * module,pid_t pid,PyObject * mask)7049 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
7050 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
7051 {
7052     int ncpus;
7053     size_t setsize;
7054     cpu_set_t *cpu_set = NULL;
7055     PyObject *iterator = NULL, *item;
7056 
7057     iterator = PyObject_GetIter(mask);
7058     if (iterator == NULL)
7059         return NULL;
7060 
7061     ncpus = NCPUS_START;
7062     setsize = CPU_ALLOC_SIZE(ncpus);
7063     cpu_set = CPU_ALLOC(ncpus);
7064     if (cpu_set == NULL) {
7065         PyErr_NoMemory();
7066         goto error;
7067     }
7068     CPU_ZERO_S(setsize, cpu_set);
7069 
7070     while ((item = PyIter_Next(iterator))) {
7071         long cpu;
7072         if (!PyLong_Check(item)) {
7073             PyErr_Format(PyExc_TypeError,
7074                         "expected an iterator of ints, "
7075                         "but iterator yielded %R",
7076                         Py_TYPE(item));
7077             Py_DECREF(item);
7078             goto error;
7079         }
7080         cpu = PyLong_AsLong(item);
7081         Py_DECREF(item);
7082         if (cpu < 0) {
7083             if (!PyErr_Occurred())
7084                 PyErr_SetString(PyExc_ValueError, "negative CPU number");
7085             goto error;
7086         }
7087         if (cpu > INT_MAX - 1) {
7088             PyErr_SetString(PyExc_OverflowError, "CPU number too large");
7089             goto error;
7090         }
7091         if (cpu >= ncpus) {
7092             /* Grow CPU mask to fit the CPU number */
7093             int newncpus = ncpus;
7094             cpu_set_t *newmask;
7095             size_t newsetsize;
7096             while (newncpus <= cpu) {
7097                 if (newncpus > INT_MAX / 2)
7098                     newncpus = cpu + 1;
7099                 else
7100                     newncpus = newncpus * 2;
7101             }
7102             newmask = CPU_ALLOC(newncpus);
7103             if (newmask == NULL) {
7104                 PyErr_NoMemory();
7105                 goto error;
7106             }
7107             newsetsize = CPU_ALLOC_SIZE(newncpus);
7108             CPU_ZERO_S(newsetsize, newmask);
7109             memcpy(newmask, cpu_set, setsize);
7110             CPU_FREE(cpu_set);
7111             setsize = newsetsize;
7112             cpu_set = newmask;
7113             ncpus = newncpus;
7114         }
7115         CPU_SET_S(cpu, setsize, cpu_set);
7116     }
7117     if (PyErr_Occurred()) {
7118         goto error;
7119     }
7120     Py_CLEAR(iterator);
7121 
7122     if (sched_setaffinity(pid, setsize, cpu_set)) {
7123         posix_error();
7124         goto error;
7125     }
7126     CPU_FREE(cpu_set);
7127     Py_RETURN_NONE;
7128 
7129 error:
7130     if (cpu_set)
7131         CPU_FREE(cpu_set);
7132     Py_XDECREF(iterator);
7133     return NULL;
7134 }
7135 
7136 
7137 /*[clinic input]
7138 os.sched_getaffinity
7139     pid: pid_t
7140     /
7141 
7142 Return the affinity of the process identified by pid (or the current process if zero).
7143 
7144 The affinity is returned as a set of CPU identifiers.
7145 [clinic start generated code]*/
7146 
7147 static PyObject *
os_sched_getaffinity_impl(PyObject * module,pid_t pid)7148 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
7149 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
7150 {
7151     int cpu, ncpus, count;
7152     size_t setsize;
7153     cpu_set_t *mask = NULL;
7154     PyObject *res = NULL;
7155 
7156     ncpus = NCPUS_START;
7157     while (1) {
7158         setsize = CPU_ALLOC_SIZE(ncpus);
7159         mask = CPU_ALLOC(ncpus);
7160         if (mask == NULL)
7161             return PyErr_NoMemory();
7162         if (sched_getaffinity(pid, setsize, mask) == 0)
7163             break;
7164         CPU_FREE(mask);
7165         if (errno != EINVAL)
7166             return posix_error();
7167         if (ncpus > INT_MAX / 2) {
7168             PyErr_SetString(PyExc_OverflowError, "could not allocate "
7169                             "a large enough CPU set");
7170             return NULL;
7171         }
7172         ncpus = ncpus * 2;
7173     }
7174 
7175     res = PySet_New(NULL);
7176     if (res == NULL)
7177         goto error;
7178     for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7179         if (CPU_ISSET_S(cpu, setsize, mask)) {
7180             PyObject *cpu_num = PyLong_FromLong(cpu);
7181             --count;
7182             if (cpu_num == NULL)
7183                 goto error;
7184             if (PySet_Add(res, cpu_num)) {
7185                 Py_DECREF(cpu_num);
7186                 goto error;
7187             }
7188             Py_DECREF(cpu_num);
7189         }
7190     }
7191     CPU_FREE(mask);
7192     return res;
7193 
7194 error:
7195     if (mask)
7196         CPU_FREE(mask);
7197     Py_XDECREF(res);
7198     return NULL;
7199 }
7200 
7201 #endif /* HAVE_SCHED_SETAFFINITY */
7202 
7203 #endif /* HAVE_SCHED_H */
7204 
7205 
7206 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
7207 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
7208 #  define DEV_PTY_FILE "/dev/ptc"
7209 #  define HAVE_DEV_PTMX
7210 #else
7211 #  define DEV_PTY_FILE "/dev/ptmx"
7212 #endif
7213 
7214 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
7215 #ifdef HAVE_PTY_H
7216 #include <pty.h>
7217 #else
7218 #ifdef HAVE_LIBUTIL_H
7219 #include <libutil.h>
7220 #else
7221 #ifdef HAVE_UTIL_H
7222 #include <util.h>
7223 #endif /* HAVE_UTIL_H */
7224 #endif /* HAVE_LIBUTIL_H */
7225 #endif /* HAVE_PTY_H */
7226 #ifdef HAVE_STROPTS_H
7227 #include <stropts.h>
7228 #endif
7229 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */
7230 
7231 
7232 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7233 /*[clinic input]
7234 os.openpty
7235 
7236 Open a pseudo-terminal.
7237 
7238 Return a tuple of (master_fd, slave_fd) containing open file descriptors
7239 for both the master and slave ends.
7240 [clinic start generated code]*/
7241 
7242 static PyObject *
os_openpty_impl(PyObject * module)7243 os_openpty_impl(PyObject *module)
7244 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
7245 {
7246     int master_fd = -1, slave_fd = -1;
7247 #ifndef HAVE_OPENPTY
7248     char * slave_name;
7249 #endif
7250 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
7251     PyOS_sighandler_t sig_saved;
7252 #if defined(__sun) && defined(__SVR4)
7253     extern char *ptsname(int fildes);
7254 #endif
7255 #endif
7256 
7257 #ifdef HAVE_OPENPTY
7258     if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
7259         goto posix_error;
7260 
7261     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7262         goto error;
7263     if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
7264         goto error;
7265 
7266 #elif defined(HAVE__GETPTY)
7267     slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
7268     if (slave_name == NULL)
7269         goto posix_error;
7270     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7271         goto error;
7272 
7273     slave_fd = _Py_open(slave_name, O_RDWR);
7274     if (slave_fd < 0)
7275         goto error;
7276 
7277 #else
7278     master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
7279     if (master_fd < 0)
7280         goto posix_error;
7281 
7282     sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
7283 
7284     /* change permission of slave */
7285     if (grantpt(master_fd) < 0) {
7286         PyOS_setsig(SIGCHLD, sig_saved);
7287         goto posix_error;
7288     }
7289 
7290     /* unlock slave */
7291     if (unlockpt(master_fd) < 0) {
7292         PyOS_setsig(SIGCHLD, sig_saved);
7293         goto posix_error;
7294     }
7295 
7296     PyOS_setsig(SIGCHLD, sig_saved);
7297 
7298     slave_name = ptsname(master_fd); /* get name of slave */
7299     if (slave_name == NULL)
7300         goto posix_error;
7301 
7302     slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
7303     if (slave_fd == -1)
7304         goto error;
7305 
7306     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7307         goto posix_error;
7308 
7309 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
7310     ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
7311     ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
7312 #ifndef __hpux
7313     ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
7314 #endif /* __hpux */
7315 #endif /* HAVE_CYGWIN */
7316 #endif /* HAVE_OPENPTY */
7317 
7318     return Py_BuildValue("(ii)", master_fd, slave_fd);
7319 
7320 posix_error:
7321     posix_error();
7322 error:
7323     if (master_fd != -1)
7324         close(master_fd);
7325     if (slave_fd != -1)
7326         close(slave_fd);
7327     return NULL;
7328 }
7329 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
7330 
7331 
7332 #ifdef HAVE_FORKPTY
7333 /*[clinic input]
7334 os.forkpty
7335 
7336 Fork a new process with a new pseudo-terminal as controlling tty.
7337 
7338 Returns a tuple of (pid, master_fd).
7339 Like fork(), return pid of 0 to the child process,
7340 and pid of child to the parent process.
7341 To both, return fd of newly opened pseudo-terminal.
7342 [clinic start generated code]*/
7343 
7344 static PyObject *
os_forkpty_impl(PyObject * module)7345 os_forkpty_impl(PyObject *module)
7346 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
7347 {
7348     int master_fd = -1;
7349     pid_t pid;
7350 
7351     if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
7352         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
7353         return NULL;
7354     }
7355     if (PySys_Audit("os.forkpty", NULL) < 0) {
7356         return NULL;
7357     }
7358     PyOS_BeforeFork();
7359     pid = forkpty(&master_fd, NULL, NULL, NULL);
7360     if (pid == 0) {
7361         /* child: this clobbers and resets the import lock. */
7362         PyOS_AfterFork_Child();
7363     } else {
7364         /* parent: release the import lock. */
7365         PyOS_AfterFork_Parent();
7366     }
7367     if (pid == -1)
7368         return posix_error();
7369     return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
7370 }
7371 #endif /* HAVE_FORKPTY */
7372 
7373 
7374 #ifdef HAVE_GETEGID
7375 /*[clinic input]
7376 os.getegid
7377 
7378 Return the current process's effective group id.
7379 [clinic start generated code]*/
7380 
7381 static PyObject *
os_getegid_impl(PyObject * module)7382 os_getegid_impl(PyObject *module)
7383 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
7384 {
7385     return _PyLong_FromGid(getegid());
7386 }
7387 #endif /* HAVE_GETEGID */
7388 
7389 
7390 #ifdef HAVE_GETEUID
7391 /*[clinic input]
7392 os.geteuid
7393 
7394 Return the current process's effective user id.
7395 [clinic start generated code]*/
7396 
7397 static PyObject *
os_geteuid_impl(PyObject * module)7398 os_geteuid_impl(PyObject *module)
7399 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
7400 {
7401     return _PyLong_FromUid(geteuid());
7402 }
7403 #endif /* HAVE_GETEUID */
7404 
7405 
7406 #ifdef HAVE_GETGID
7407 /*[clinic input]
7408 os.getgid
7409 
7410 Return the current process's group id.
7411 [clinic start generated code]*/
7412 
7413 static PyObject *
os_getgid_impl(PyObject * module)7414 os_getgid_impl(PyObject *module)
7415 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
7416 {
7417     return _PyLong_FromGid(getgid());
7418 }
7419 #endif /* HAVE_GETGID */
7420 
7421 
7422 #ifdef HAVE_GETPID
7423 /*[clinic input]
7424 os.getpid
7425 
7426 Return the current process id.
7427 [clinic start generated code]*/
7428 
7429 static PyObject *
os_getpid_impl(PyObject * module)7430 os_getpid_impl(PyObject *module)
7431 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
7432 {
7433     return PyLong_FromPid(getpid());
7434 }
7435 #endif /* HAVE_GETPID */
7436 
7437 #ifdef NGROUPS_MAX
7438 #define MAX_GROUPS NGROUPS_MAX
7439 #else
7440     /* defined to be 16 on Solaris7, so this should be a small number */
7441 #define MAX_GROUPS 64
7442 #endif
7443 
7444 #ifdef HAVE_GETGROUPLIST
7445 
7446 #ifdef __APPLE__
7447 /*[clinic input]
7448 os.getgrouplist
7449 
7450     user: str
7451         username to lookup
7452     group as basegid: int
7453         base group id of the user
7454     /
7455 
7456 Returns a list of groups to which a user belongs.
7457 [clinic start generated code]*/
7458 
7459 static PyObject *
os_getgrouplist_impl(PyObject * module,const char * user,int basegid)7460 os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
7461 /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
7462 #else
7463 /*[clinic input]
7464 os.getgrouplist
7465 
7466     user: str
7467         username to lookup
7468     group as basegid: gid_t
7469         base group id of the user
7470     /
7471 
7472 Returns a list of groups to which a user belongs.
7473 [clinic start generated code]*/
7474 
7475 static PyObject *
7476 os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
7477 /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
7478 #endif
7479 {
7480     int i, ngroups;
7481     PyObject *list;
7482 #ifdef __APPLE__
7483     int *groups;
7484 #else
7485     gid_t *groups;
7486 #endif
7487 
7488     /*
7489      * NGROUPS_MAX is defined by POSIX.1 as the maximum
7490      * number of supplimental groups a users can belong to.
7491      * We have to increment it by one because
7492      * getgrouplist() returns both the supplemental groups
7493      * and the primary group, i.e. all of the groups the
7494      * user belongs to.
7495      */
7496     ngroups = 1 + MAX_GROUPS;
7497 
7498     while (1) {
7499 #ifdef __APPLE__
7500         groups = PyMem_New(int, ngroups);
7501 #else
7502         groups = PyMem_New(gid_t, ngroups);
7503 #endif
7504         if (groups == NULL) {
7505             return PyErr_NoMemory();
7506         }
7507 
7508         int old_ngroups = ngroups;
7509         if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
7510             /* Success */
7511             break;
7512         }
7513 
7514         /* getgrouplist() fails if the group list is too small */
7515         PyMem_Free(groups);
7516 
7517         if (ngroups > old_ngroups) {
7518             /* If the group list is too small, the glibc implementation of
7519                getgrouplist() sets ngroups to the total number of groups and
7520                returns -1. */
7521         }
7522         else {
7523             /* Double the group list size */
7524             if (ngroups > INT_MAX / 2) {
7525                 return PyErr_NoMemory();
7526             }
7527             ngroups *= 2;
7528         }
7529 
7530         /* Retry getgrouplist() with a larger group list */
7531     }
7532 
7533 #ifdef _Py_MEMORY_SANITIZER
7534     /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
7535     __msan_unpoison(&ngroups, sizeof(ngroups));
7536     __msan_unpoison(groups, ngroups*sizeof(*groups));
7537 #endif
7538 
7539     list = PyList_New(ngroups);
7540     if (list == NULL) {
7541         PyMem_Free(groups);
7542         return NULL;
7543     }
7544 
7545     for (i = 0; i < ngroups; i++) {
7546 #ifdef __APPLE__
7547         PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7548 #else
7549         PyObject *o = _PyLong_FromGid(groups[i]);
7550 #endif
7551         if (o == NULL) {
7552             Py_DECREF(list);
7553             PyMem_Free(groups);
7554             return NULL;
7555         }
7556         PyList_SET_ITEM(list, i, o);
7557     }
7558 
7559     PyMem_Free(groups);
7560 
7561     return list;
7562 }
7563 #endif /* HAVE_GETGROUPLIST */
7564 
7565 
7566 #ifdef HAVE_GETGROUPS
7567 /*[clinic input]
7568 os.getgroups
7569 
7570 Return list of supplemental group IDs for the process.
7571 [clinic start generated code]*/
7572 
7573 static PyObject *
os_getgroups_impl(PyObject * module)7574 os_getgroups_impl(PyObject *module)
7575 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
7576 {
7577     PyObject *result = NULL;
7578     gid_t grouplist[MAX_GROUPS];
7579 
7580     /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
7581      * This is a helper variable to store the intermediate result when
7582      * that happens.
7583      *
7584      * To keep the code readable the OSX behaviour is unconditional,
7585      * according to the POSIX spec this should be safe on all unix-y
7586      * systems.
7587      */
7588     gid_t* alt_grouplist = grouplist;
7589     int n;
7590 
7591 #ifdef __APPLE__
7592     /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if
7593      * there are more groups than can fit in grouplist.  Therefore, on OS X
7594      * always first call getgroups with length 0 to get the actual number
7595      * of groups.
7596      */
7597     n = getgroups(0, NULL);
7598     if (n < 0) {
7599         return posix_error();
7600     } else if (n <= MAX_GROUPS) {
7601         /* groups will fit in existing array */
7602         alt_grouplist = grouplist;
7603     } else {
7604         alt_grouplist = PyMem_New(gid_t, n);
7605         if (alt_grouplist == NULL) {
7606             return PyErr_NoMemory();
7607         }
7608     }
7609 
7610     n = getgroups(n, alt_grouplist);
7611     if (n == -1) {
7612         if (alt_grouplist != grouplist) {
7613             PyMem_Free(alt_grouplist);
7614         }
7615         return posix_error();
7616     }
7617 #else
7618     n = getgroups(MAX_GROUPS, grouplist);
7619     if (n < 0) {
7620         if (errno == EINVAL) {
7621             n = getgroups(0, NULL);
7622             if (n == -1) {
7623                 return posix_error();
7624             }
7625             if (n == 0) {
7626                 /* Avoid malloc(0) */
7627                 alt_grouplist = grouplist;
7628             } else {
7629                 alt_grouplist = PyMem_New(gid_t, n);
7630                 if (alt_grouplist == NULL) {
7631                     return PyErr_NoMemory();
7632                 }
7633                 n = getgroups(n, alt_grouplist);
7634                 if (n == -1) {
7635                     PyMem_Free(alt_grouplist);
7636                     return posix_error();
7637                 }
7638             }
7639         } else {
7640             return posix_error();
7641         }
7642     }
7643 #endif
7644 
7645     result = PyList_New(n);
7646     if (result != NULL) {
7647         int i;
7648         for (i = 0; i < n; ++i) {
7649             PyObject *o = _PyLong_FromGid(alt_grouplist[i]);
7650             if (o == NULL) {
7651                 Py_DECREF(result);
7652                 result = NULL;
7653                 break;
7654             }
7655             PyList_SET_ITEM(result, i, o);
7656         }
7657     }
7658 
7659     if (alt_grouplist != grouplist) {
7660         PyMem_Free(alt_grouplist);
7661     }
7662 
7663     return result;
7664 }
7665 #endif /* HAVE_GETGROUPS */
7666 
7667 #ifdef HAVE_INITGROUPS
7668 #ifdef __APPLE__
7669 /*[clinic input]
7670 os.initgroups
7671 
7672     username as oname: FSConverter
7673     gid: int
7674     /
7675 
7676 Initialize the group access list.
7677 
7678 Call the system initgroups() to initialize the group access list with all of
7679 the groups of which the specified username is a member, plus the specified
7680 group id.
7681 [clinic start generated code]*/
7682 
7683 static PyObject *
os_initgroups_impl(PyObject * module,PyObject * oname,int gid)7684 os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
7685 /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
7686 #else
7687 /*[clinic input]
7688 os.initgroups
7689 
7690     username as oname: FSConverter
7691     gid: gid_t
7692     /
7693 
7694 Initialize the group access list.
7695 
7696 Call the system initgroups() to initialize the group access list with all of
7697 the groups of which the specified username is a member, plus the specified
7698 group id.
7699 [clinic start generated code]*/
7700 
7701 static PyObject *
7702 os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
7703 /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
7704 #endif
7705 {
7706     const char *username = PyBytes_AS_STRING(oname);
7707 
7708     if (initgroups(username, gid) == -1)
7709         return PyErr_SetFromErrno(PyExc_OSError);
7710 
7711     Py_RETURN_NONE;
7712 }
7713 #endif /* HAVE_INITGROUPS */
7714 
7715 
7716 #ifdef HAVE_GETPGID
7717 /*[clinic input]
7718 os.getpgid
7719 
7720     pid: pid_t
7721 
7722 Call the system call getpgid(), and return the result.
7723 [clinic start generated code]*/
7724 
7725 static PyObject *
os_getpgid_impl(PyObject * module,pid_t pid)7726 os_getpgid_impl(PyObject *module, pid_t pid)
7727 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7728 {
7729     pid_t pgid = getpgid(pid);
7730     if (pgid < 0)
7731         return posix_error();
7732     return PyLong_FromPid(pgid);
7733 }
7734 #endif /* HAVE_GETPGID */
7735 
7736 
7737 #ifdef HAVE_GETPGRP
7738 /*[clinic input]
7739 os.getpgrp
7740 
7741 Return the current process group id.
7742 [clinic start generated code]*/
7743 
7744 static PyObject *
os_getpgrp_impl(PyObject * module)7745 os_getpgrp_impl(PyObject *module)
7746 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7747 {
7748 #ifdef GETPGRP_HAVE_ARG
7749     return PyLong_FromPid(getpgrp(0));
7750 #else /* GETPGRP_HAVE_ARG */
7751     return PyLong_FromPid(getpgrp());
7752 #endif /* GETPGRP_HAVE_ARG */
7753 }
7754 #endif /* HAVE_GETPGRP */
7755 
7756 
7757 #ifdef HAVE_SETPGRP
7758 /*[clinic input]
7759 os.setpgrp
7760 
7761 Make the current process the leader of its process group.
7762 [clinic start generated code]*/
7763 
7764 static PyObject *
os_setpgrp_impl(PyObject * module)7765 os_setpgrp_impl(PyObject *module)
7766 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7767 {
7768 #ifdef SETPGRP_HAVE_ARG
7769     if (setpgrp(0, 0) < 0)
7770 #else /* SETPGRP_HAVE_ARG */
7771     if (setpgrp() < 0)
7772 #endif /* SETPGRP_HAVE_ARG */
7773         return posix_error();
7774     Py_RETURN_NONE;
7775 }
7776 #endif /* HAVE_SETPGRP */
7777 
7778 #ifdef HAVE_GETPPID
7779 
7780 #ifdef MS_WINDOWS
7781 #include <tlhelp32.h>
7782 
7783 static PyObject*
win32_getppid()7784 win32_getppid()
7785 {
7786     HANDLE snapshot;
7787     pid_t mypid;
7788     PyObject* result = NULL;
7789     BOOL have_record;
7790     PROCESSENTRY32 pe;
7791 
7792     mypid = getpid(); /* This function never fails */
7793 
7794     snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7795     if (snapshot == INVALID_HANDLE_VALUE)
7796         return PyErr_SetFromWindowsErr(GetLastError());
7797 
7798     pe.dwSize = sizeof(pe);
7799     have_record = Process32First(snapshot, &pe);
7800     while (have_record) {
7801         if (mypid == (pid_t)pe.th32ProcessID) {
7802             /* We could cache the ulong value in a static variable. */
7803             result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7804             break;
7805         }
7806 
7807         have_record = Process32Next(snapshot, &pe);
7808     }
7809 
7810     /* If our loop exits and our pid was not found (result will be NULL)
7811      * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7812      * error anyway, so let's raise it. */
7813     if (!result)
7814         result = PyErr_SetFromWindowsErr(GetLastError());
7815 
7816     CloseHandle(snapshot);
7817 
7818     return result;
7819 }
7820 #endif /*MS_WINDOWS*/
7821 
7822 
7823 /*[clinic input]
7824 os.getppid
7825 
7826 Return the parent's process id.
7827 
7828 If the parent process has already exited, Windows machines will still
7829 return its id; others systems will return the id of the 'init' process (1).
7830 [clinic start generated code]*/
7831 
7832 static PyObject *
os_getppid_impl(PyObject * module)7833 os_getppid_impl(PyObject *module)
7834 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7835 {
7836 #ifdef MS_WINDOWS
7837     return win32_getppid();
7838 #else
7839     return PyLong_FromPid(getppid());
7840 #endif
7841 }
7842 #endif /* HAVE_GETPPID */
7843 
7844 
7845 #ifdef HAVE_GETLOGIN
7846 /*[clinic input]
7847 os.getlogin
7848 
7849 Return the actual login name.
7850 [clinic start generated code]*/
7851 
7852 static PyObject *
os_getlogin_impl(PyObject * module)7853 os_getlogin_impl(PyObject *module)
7854 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7855 {
7856     PyObject *result = NULL;
7857 #ifdef MS_WINDOWS
7858     wchar_t user_name[UNLEN + 1];
7859     DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7860 
7861     if (GetUserNameW(user_name, &num_chars)) {
7862         /* num_chars is the number of unicode chars plus null terminator */
7863         result = PyUnicode_FromWideChar(user_name, num_chars - 1);
7864     }
7865     else
7866         result = PyErr_SetFromWindowsErr(GetLastError());
7867 #else
7868     char *name;
7869     int old_errno = errno;
7870 
7871     errno = 0;
7872     name = getlogin();
7873     if (name == NULL) {
7874         if (errno)
7875             posix_error();
7876         else
7877             PyErr_SetString(PyExc_OSError, "unable to determine login name");
7878     }
7879     else
7880         result = PyUnicode_DecodeFSDefault(name);
7881     errno = old_errno;
7882 #endif
7883     return result;
7884 }
7885 #endif /* HAVE_GETLOGIN */
7886 
7887 
7888 #ifdef HAVE_GETUID
7889 /*[clinic input]
7890 os.getuid
7891 
7892 Return the current process's user id.
7893 [clinic start generated code]*/
7894 
7895 static PyObject *
os_getuid_impl(PyObject * module)7896 os_getuid_impl(PyObject *module)
7897 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7898 {
7899     return _PyLong_FromUid(getuid());
7900 }
7901 #endif /* HAVE_GETUID */
7902 
7903 
7904 #ifdef MS_WINDOWS
7905 #define HAVE_KILL
7906 #endif /* MS_WINDOWS */
7907 
7908 #ifdef HAVE_KILL
7909 /*[clinic input]
7910 os.kill
7911 
7912     pid: pid_t
7913     signal: Py_ssize_t
7914     /
7915 
7916 Kill a process with a signal.
7917 [clinic start generated code]*/
7918 
7919 static PyObject *
os_kill_impl(PyObject * module,pid_t pid,Py_ssize_t signal)7920 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
7921 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
7922 {
7923     if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
7924         return NULL;
7925     }
7926 #ifndef MS_WINDOWS
7927     if (kill(pid, (int)signal) == -1)
7928         return posix_error();
7929     Py_RETURN_NONE;
7930 #else /* !MS_WINDOWS */
7931     PyObject *result;
7932     DWORD sig = (DWORD)signal;
7933     DWORD err;
7934     HANDLE handle;
7935 
7936     /* Console processes which share a common console can be sent CTRL+C or
7937        CTRL+BREAK events, provided they handle said events. */
7938     if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
7939         if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
7940             err = GetLastError();
7941             PyErr_SetFromWindowsErr(err);
7942         }
7943         else
7944             Py_RETURN_NONE;
7945     }
7946 
7947     /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
7948        attempt to open and terminate the process. */
7949     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
7950     if (handle == NULL) {
7951         err = GetLastError();
7952         return PyErr_SetFromWindowsErr(err);
7953     }
7954 
7955     if (TerminateProcess(handle, sig) == 0) {
7956         err = GetLastError();
7957         result = PyErr_SetFromWindowsErr(err);
7958     } else {
7959         Py_INCREF(Py_None);
7960         result = Py_None;
7961     }
7962 
7963     CloseHandle(handle);
7964     return result;
7965 #endif /* !MS_WINDOWS */
7966 }
7967 #endif /* HAVE_KILL */
7968 
7969 
7970 #ifdef HAVE_KILLPG
7971 /*[clinic input]
7972 os.killpg
7973 
7974     pgid: pid_t
7975     signal: int
7976     /
7977 
7978 Kill a process group with a signal.
7979 [clinic start generated code]*/
7980 
7981 static PyObject *
os_killpg_impl(PyObject * module,pid_t pgid,int signal)7982 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
7983 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
7984 {
7985     if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
7986         return NULL;
7987     }
7988     /* XXX some man pages make the `pgid` parameter an int, others
7989        a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
7990        take the same type. Moreover, pid_t is always at least as wide as
7991        int (else compilation of this module fails), which is safe. */
7992     if (killpg(pgid, signal) == -1)
7993         return posix_error();
7994     Py_RETURN_NONE;
7995 }
7996 #endif /* HAVE_KILLPG */
7997 
7998 
7999 #ifdef HAVE_PLOCK
8000 #ifdef HAVE_SYS_LOCK_H
8001 #include <sys/lock.h>
8002 #endif
8003 
8004 /*[clinic input]
8005 os.plock
8006     op: int
8007     /
8008 
8009 Lock program segments into memory.");
8010 [clinic start generated code]*/
8011 
8012 static PyObject *
os_plock_impl(PyObject * module,int op)8013 os_plock_impl(PyObject *module, int op)
8014 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
8015 {
8016     if (plock(op) == -1)
8017         return posix_error();
8018     Py_RETURN_NONE;
8019 }
8020 #endif /* HAVE_PLOCK */
8021 
8022 
8023 #ifdef HAVE_SETUID
8024 /*[clinic input]
8025 os.setuid
8026 
8027     uid: uid_t
8028     /
8029 
8030 Set the current process's user id.
8031 [clinic start generated code]*/
8032 
8033 static PyObject *
os_setuid_impl(PyObject * module,uid_t uid)8034 os_setuid_impl(PyObject *module, uid_t uid)
8035 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
8036 {
8037     if (setuid(uid) < 0)
8038         return posix_error();
8039     Py_RETURN_NONE;
8040 }
8041 #endif /* HAVE_SETUID */
8042 
8043 
8044 #ifdef HAVE_SETEUID
8045 /*[clinic input]
8046 os.seteuid
8047 
8048     euid: uid_t
8049     /
8050 
8051 Set the current process's effective user id.
8052 [clinic start generated code]*/
8053 
8054 static PyObject *
os_seteuid_impl(PyObject * module,uid_t euid)8055 os_seteuid_impl(PyObject *module, uid_t euid)
8056 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
8057 {
8058     if (seteuid(euid) < 0)
8059         return posix_error();
8060     Py_RETURN_NONE;
8061 }
8062 #endif /* HAVE_SETEUID */
8063 
8064 
8065 #ifdef HAVE_SETEGID
8066 /*[clinic input]
8067 os.setegid
8068 
8069     egid: gid_t
8070     /
8071 
8072 Set the current process's effective group id.
8073 [clinic start generated code]*/
8074 
8075 static PyObject *
os_setegid_impl(PyObject * module,gid_t egid)8076 os_setegid_impl(PyObject *module, gid_t egid)
8077 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
8078 {
8079     if (setegid(egid) < 0)
8080         return posix_error();
8081     Py_RETURN_NONE;
8082 }
8083 #endif /* HAVE_SETEGID */
8084 
8085 
8086 #ifdef HAVE_SETREUID
8087 /*[clinic input]
8088 os.setreuid
8089 
8090     ruid: uid_t
8091     euid: uid_t
8092     /
8093 
8094 Set the current process's real and effective user ids.
8095 [clinic start generated code]*/
8096 
8097 static PyObject *
os_setreuid_impl(PyObject * module,uid_t ruid,uid_t euid)8098 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
8099 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
8100 {
8101     if (setreuid(ruid, euid) < 0) {
8102         return posix_error();
8103     } else {
8104         Py_RETURN_NONE;
8105     }
8106 }
8107 #endif /* HAVE_SETREUID */
8108 
8109 
8110 #ifdef HAVE_SETREGID
8111 /*[clinic input]
8112 os.setregid
8113 
8114     rgid: gid_t
8115     egid: gid_t
8116     /
8117 
8118 Set the current process's real and effective group ids.
8119 [clinic start generated code]*/
8120 
8121 static PyObject *
os_setregid_impl(PyObject * module,gid_t rgid,gid_t egid)8122 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
8123 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
8124 {
8125     if (setregid(rgid, egid) < 0)
8126         return posix_error();
8127     Py_RETURN_NONE;
8128 }
8129 #endif /* HAVE_SETREGID */
8130 
8131 
8132 #ifdef HAVE_SETGID
8133 /*[clinic input]
8134 os.setgid
8135     gid: gid_t
8136     /
8137 
8138 Set the current process's group id.
8139 [clinic start generated code]*/
8140 
8141 static PyObject *
os_setgid_impl(PyObject * module,gid_t gid)8142 os_setgid_impl(PyObject *module, gid_t gid)
8143 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
8144 {
8145     if (setgid(gid) < 0)
8146         return posix_error();
8147     Py_RETURN_NONE;
8148 }
8149 #endif /* HAVE_SETGID */
8150 
8151 
8152 #ifdef HAVE_SETGROUPS
8153 /*[clinic input]
8154 os.setgroups
8155 
8156     groups: object
8157     /
8158 
8159 Set the groups of the current process to list.
8160 [clinic start generated code]*/
8161 
8162 static PyObject *
os_setgroups(PyObject * module,PyObject * groups)8163 os_setgroups(PyObject *module, PyObject *groups)
8164 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
8165 {
8166     Py_ssize_t i, len;
8167     gid_t grouplist[MAX_GROUPS];
8168 
8169     if (!PySequence_Check(groups)) {
8170         PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
8171         return NULL;
8172     }
8173     len = PySequence_Size(groups);
8174     if (len < 0) {
8175         return NULL;
8176     }
8177     if (len > MAX_GROUPS) {
8178         PyErr_SetString(PyExc_ValueError, "too many groups");
8179         return NULL;
8180     }
8181     for(i = 0; i < len; i++) {
8182         PyObject *elem;
8183         elem = PySequence_GetItem(groups, i);
8184         if (!elem)
8185             return NULL;
8186         if (!PyLong_Check(elem)) {
8187             PyErr_SetString(PyExc_TypeError,
8188                             "groups must be integers");
8189             Py_DECREF(elem);
8190             return NULL;
8191         } else {
8192             if (!_Py_Gid_Converter(elem, &grouplist[i])) {
8193                 Py_DECREF(elem);
8194                 return NULL;
8195             }
8196         }
8197         Py_DECREF(elem);
8198     }
8199 
8200     if (setgroups(len, grouplist) < 0)
8201         return posix_error();
8202     Py_RETURN_NONE;
8203 }
8204 #endif /* HAVE_SETGROUPS */
8205 
8206 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
8207 static PyObject *
wait_helper(PyObject * module,pid_t pid,int status,struct rusage * ru)8208 wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
8209 {
8210     PyObject *result;
8211     PyObject *struct_rusage;
8212 
8213     if (pid == -1)
8214         return posix_error();
8215 
8216     // If wait succeeded but no child was ready to report status, ru will not
8217     // have been populated.
8218     if (pid == 0) {
8219         memset(ru, 0, sizeof(*ru));
8220     }
8221 
8222     PyObject *m = PyImport_ImportModuleNoBlock("resource");
8223     if (m == NULL)
8224         return NULL;
8225     struct_rusage = PyObject_GetAttr(m, get_posix_state(module)->struct_rusage);
8226     Py_DECREF(m);
8227     if (struct_rusage == NULL)
8228         return NULL;
8229 
8230     /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
8231     result = PyStructSequence_New((PyTypeObject*) struct_rusage);
8232     Py_DECREF(struct_rusage);
8233     if (!result)
8234         return NULL;
8235 
8236 #ifndef doubletime
8237 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
8238 #endif
8239 
8240     PyStructSequence_SET_ITEM(result, 0,
8241                               PyFloat_FromDouble(doubletime(ru->ru_utime)));
8242     PyStructSequence_SET_ITEM(result, 1,
8243                               PyFloat_FromDouble(doubletime(ru->ru_stime)));
8244 #define SET_INT(result, index, value)\
8245         PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
8246     SET_INT(result, 2, ru->ru_maxrss);
8247     SET_INT(result, 3, ru->ru_ixrss);
8248     SET_INT(result, 4, ru->ru_idrss);
8249     SET_INT(result, 5, ru->ru_isrss);
8250     SET_INT(result, 6, ru->ru_minflt);
8251     SET_INT(result, 7, ru->ru_majflt);
8252     SET_INT(result, 8, ru->ru_nswap);
8253     SET_INT(result, 9, ru->ru_inblock);
8254     SET_INT(result, 10, ru->ru_oublock);
8255     SET_INT(result, 11, ru->ru_msgsnd);
8256     SET_INT(result, 12, ru->ru_msgrcv);
8257     SET_INT(result, 13, ru->ru_nsignals);
8258     SET_INT(result, 14, ru->ru_nvcsw);
8259     SET_INT(result, 15, ru->ru_nivcsw);
8260 #undef SET_INT
8261 
8262     if (PyErr_Occurred()) {
8263         Py_DECREF(result);
8264         return NULL;
8265     }
8266 
8267     return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
8268 }
8269 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
8270 
8271 
8272 #ifdef HAVE_WAIT3
8273 /*[clinic input]
8274 os.wait3
8275 
8276     options: int
8277 Wait for completion of a child process.
8278 
8279 Returns a tuple of information about the child process:
8280   (pid, status, rusage)
8281 [clinic start generated code]*/
8282 
8283 static PyObject *
os_wait3_impl(PyObject * module,int options)8284 os_wait3_impl(PyObject *module, int options)
8285 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
8286 {
8287     pid_t pid;
8288     struct rusage ru;
8289     int async_err = 0;
8290     WAIT_TYPE status;
8291     WAIT_STATUS_INT(status) = 0;
8292 
8293     do {
8294         Py_BEGIN_ALLOW_THREADS
8295         pid = wait3(&status, options, &ru);
8296         Py_END_ALLOW_THREADS
8297     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8298     if (pid < 0)
8299         return (!async_err) ? posix_error() : NULL;
8300 
8301     return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
8302 }
8303 #endif /* HAVE_WAIT3 */
8304 
8305 
8306 #ifdef HAVE_WAIT4
8307 /*[clinic input]
8308 
8309 os.wait4
8310 
8311     pid: pid_t
8312     options: int
8313 
8314 Wait for completion of a specific child process.
8315 
8316 Returns a tuple of information about the child process:
8317   (pid, status, rusage)
8318 [clinic start generated code]*/
8319 
8320 static PyObject *
os_wait4_impl(PyObject * module,pid_t pid,int options)8321 os_wait4_impl(PyObject *module, pid_t pid, int options)
8322 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
8323 {
8324     pid_t res;
8325     struct rusage ru;
8326     int async_err = 0;
8327     WAIT_TYPE status;
8328     WAIT_STATUS_INT(status) = 0;
8329 
8330     do {
8331         Py_BEGIN_ALLOW_THREADS
8332         res = wait4(pid, &status, options, &ru);
8333         Py_END_ALLOW_THREADS
8334     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8335     if (res < 0)
8336         return (!async_err) ? posix_error() : NULL;
8337 
8338     return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
8339 }
8340 #endif /* HAVE_WAIT4 */
8341 
8342 
8343 #if defined(HAVE_WAITID) && !defined(__APPLE__)
8344 /*[clinic input]
8345 os.waitid
8346 
8347     idtype: idtype_t
8348         Must be one of be P_PID, P_PGID or P_ALL.
8349     id: id_t
8350         The id to wait on.
8351     options: int
8352         Constructed from the ORing of one or more of WEXITED, WSTOPPED
8353         or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
8354     /
8355 
8356 Returns the result of waiting for a process or processes.
8357 
8358 Returns either waitid_result or None if WNOHANG is specified and there are
8359 no children in a waitable state.
8360 [clinic start generated code]*/
8361 
8362 static PyObject *
os_waitid_impl(PyObject * module,idtype_t idtype,id_t id,int options)8363 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
8364 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
8365 {
8366     PyObject *result;
8367     int res;
8368     int async_err = 0;
8369     siginfo_t si;
8370     si.si_pid = 0;
8371 
8372     do {
8373         Py_BEGIN_ALLOW_THREADS
8374         res = waitid(idtype, id, &si, options);
8375         Py_END_ALLOW_THREADS
8376     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8377     if (res < 0)
8378         return (!async_err) ? posix_error() : NULL;
8379 
8380     if (si.si_pid == 0)
8381         Py_RETURN_NONE;
8382 
8383     PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
8384     result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
8385     if (!result)
8386         return NULL;
8387 
8388     PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
8389     PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
8390     PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
8391     PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
8392     PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
8393     if (PyErr_Occurred()) {
8394         Py_DECREF(result);
8395         return NULL;
8396     }
8397 
8398     return result;
8399 }
8400 #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
8401 
8402 
8403 #if defined(HAVE_WAITPID)
8404 /*[clinic input]
8405 os.waitpid
8406     pid: pid_t
8407     options: int
8408     /
8409 
8410 Wait for completion of a given child process.
8411 
8412 Returns a tuple of information regarding the child process:
8413     (pid, status)
8414 
8415 The options argument is ignored on Windows.
8416 [clinic start generated code]*/
8417 
8418 static PyObject *
os_waitpid_impl(PyObject * module,pid_t pid,int options)8419 os_waitpid_impl(PyObject *module, pid_t pid, int options)
8420 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
8421 {
8422     pid_t res;
8423     int async_err = 0;
8424     WAIT_TYPE status;
8425     WAIT_STATUS_INT(status) = 0;
8426 
8427     do {
8428         Py_BEGIN_ALLOW_THREADS
8429         res = waitpid(pid, &status, options);
8430         Py_END_ALLOW_THREADS
8431     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8432     if (res < 0)
8433         return (!async_err) ? posix_error() : NULL;
8434 
8435     return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
8436 }
8437 #elif defined(HAVE_CWAIT)
8438 /* MS C has a variant of waitpid() that's usable for most purposes. */
8439 /*[clinic input]
8440 os.waitpid
8441     pid: intptr_t
8442     options: int
8443     /
8444 
8445 Wait for completion of a given process.
8446 
8447 Returns a tuple of information regarding the process:
8448     (pid, status << 8)
8449 
8450 The options argument is ignored on Windows.
8451 [clinic start generated code]*/
8452 
8453 static PyObject *
os_waitpid_impl(PyObject * module,intptr_t pid,int options)8454 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
8455 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
8456 {
8457     int status;
8458     intptr_t res;
8459     int async_err = 0;
8460 
8461     do {
8462         Py_BEGIN_ALLOW_THREADS
8463         _Py_BEGIN_SUPPRESS_IPH
8464         res = _cwait(&status, pid, options);
8465         _Py_END_SUPPRESS_IPH
8466         Py_END_ALLOW_THREADS
8467     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8468     if (res < 0)
8469         return (!async_err) ? posix_error() : NULL;
8470 
8471     unsigned long long ustatus = (unsigned int)status;
8472 
8473     /* shift the status left a byte so this is more like the POSIX waitpid */
8474     return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
8475 }
8476 #endif
8477 
8478 
8479 #ifdef HAVE_WAIT
8480 /*[clinic input]
8481 os.wait
8482 
8483 Wait for completion of a child process.
8484 
8485 Returns a tuple of information about the child process:
8486     (pid, status)
8487 [clinic start generated code]*/
8488 
8489 static PyObject *
os_wait_impl(PyObject * module)8490 os_wait_impl(PyObject *module)
8491 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
8492 {
8493     pid_t pid;
8494     int async_err = 0;
8495     WAIT_TYPE status;
8496     WAIT_STATUS_INT(status) = 0;
8497 
8498     do {
8499         Py_BEGIN_ALLOW_THREADS
8500         pid = wait(&status);
8501         Py_END_ALLOW_THREADS
8502     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8503     if (pid < 0)
8504         return (!async_err) ? posix_error() : NULL;
8505 
8506     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
8507 }
8508 #endif /* HAVE_WAIT */
8509 
8510 #if defined(__linux__) && defined(__NR_pidfd_open)
8511 /*[clinic input]
8512 os.pidfd_open
8513   pid: pid_t
8514   flags: unsigned_int = 0
8515 
8516 Return a file descriptor referring to the process *pid*.
8517 
8518 The descriptor can be used to perform process management without races and
8519 signals.
8520 [clinic start generated code]*/
8521 
8522 static PyObject *
os_pidfd_open_impl(PyObject * module,pid_t pid,unsigned int flags)8523 os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
8524 /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
8525 {
8526     int fd = syscall(__NR_pidfd_open, pid, flags);
8527     if (fd < 0) {
8528         return posix_error();
8529     }
8530     return PyLong_FromLong(fd);
8531 }
8532 #endif
8533 
8534 
8535 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
8536 /*[clinic input]
8537 os.readlink
8538 
8539     path: path_t
8540     *
8541     dir_fd: dir_fd(requires='readlinkat') = None
8542 
8543 Return a string representing the path to which the symbolic link points.
8544 
8545 If dir_fd is not None, it should be a file descriptor open to a directory,
8546 and path should be relative; path will then be relative to that directory.
8547 
8548 dir_fd may not be implemented on your platform.  If it is unavailable,
8549 using it will raise a NotImplementedError.
8550 [clinic start generated code]*/
8551 
8552 static PyObject *
os_readlink_impl(PyObject * module,path_t * path,int dir_fd)8553 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
8554 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
8555 {
8556 #if defined(HAVE_READLINK)
8557     char buffer[MAXPATHLEN+1];
8558     ssize_t length;
8559 #ifdef HAVE_READLINKAT
8560     int readlinkat_unavailable = 0;
8561 #endif
8562 
8563     Py_BEGIN_ALLOW_THREADS
8564 #ifdef HAVE_READLINKAT
8565     if (dir_fd != DEFAULT_DIR_FD) {
8566         if (HAVE_READLINKAT_RUNTIME) {
8567             length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
8568         } else {
8569             readlinkat_unavailable = 1;
8570         }
8571     } else
8572 #endif
8573         length = readlink(path->narrow, buffer, MAXPATHLEN);
8574     Py_END_ALLOW_THREADS
8575 
8576 #ifdef HAVE_READLINKAT
8577     if (readlinkat_unavailable) {
8578         argument_unavailable_error(NULL, "dir_fd");
8579         return NULL;
8580     }
8581 #endif
8582 
8583     if (length < 0) {
8584         return path_error(path);
8585     }
8586     buffer[length] = '\0';
8587 
8588     if (PyUnicode_Check(path->object))
8589         return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
8590     else
8591         return PyBytes_FromStringAndSize(buffer, length);
8592 #elif defined(MS_WINDOWS)
8593     DWORD n_bytes_returned;
8594     DWORD io_result = 0;
8595     HANDLE reparse_point_handle;
8596     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
8597     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
8598     PyObject *result = NULL;
8599 
8600     /* First get a handle to the reparse point */
8601     Py_BEGIN_ALLOW_THREADS
8602     reparse_point_handle = CreateFileW(
8603         path->wide,
8604         0,
8605         0,
8606         0,
8607         OPEN_EXISTING,
8608         FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
8609         0);
8610     if (reparse_point_handle != INVALID_HANDLE_VALUE) {
8611         /* New call DeviceIoControl to read the reparse point */
8612         io_result = DeviceIoControl(
8613             reparse_point_handle,
8614             FSCTL_GET_REPARSE_POINT,
8615             0, 0, /* in buffer */
8616             target_buffer, sizeof(target_buffer),
8617             &n_bytes_returned,
8618             0 /* we're not using OVERLAPPED_IO */
8619             );
8620         CloseHandle(reparse_point_handle);
8621     }
8622     Py_END_ALLOW_THREADS
8623 
8624     if (io_result == 0) {
8625         return path_error(path);
8626     }
8627 
8628     wchar_t *name = NULL;
8629     Py_ssize_t nameLen = 0;
8630     if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
8631     {
8632         name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
8633                            rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
8634         nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8635     }
8636     else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
8637     {
8638         name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8639                            rdb->MountPointReparseBuffer.SubstituteNameOffset);
8640         nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8641     }
8642     else
8643     {
8644         PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8645     }
8646     if (name) {
8647         if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8648             /* Our buffer is mutable, so this is okay */
8649             name[1] = L'\\';
8650         }
8651         result = PyUnicode_FromWideChar(name, nameLen);
8652         if (result && path->narrow) {
8653             Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8654         }
8655     }
8656     return result;
8657 #endif
8658 }
8659 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8660 
8661 #if defined(MS_WINDOWS)
8662 
8663 /* Remove the last portion of the path - return 0 on success */
8664 static int
_dirnameW(WCHAR * path)8665 _dirnameW(WCHAR *path)
8666 {
8667     WCHAR *ptr;
8668     size_t length = wcsnlen_s(path, MAX_PATH);
8669     if (length == MAX_PATH) {
8670         return -1;
8671     }
8672 
8673     /* walk the path from the end until a backslash is encountered */
8674     for(ptr = path + length; ptr != path; ptr--) {
8675         if (*ptr == L'\\' || *ptr == L'/') {
8676             break;
8677         }
8678     }
8679     *ptr = 0;
8680     return 0;
8681 }
8682 
8683 #endif
8684 
8685 #ifdef HAVE_SYMLINK
8686 
8687 #if defined(MS_WINDOWS)
8688 
8689 /* Is this path absolute? */
8690 static int
_is_absW(const WCHAR * path)8691 _is_absW(const WCHAR *path)
8692 {
8693     return path[0] == L'\\' || path[0] == L'/' ||
8694         (path[0] && path[1] == L':');
8695 }
8696 
8697 /* join root and rest with a backslash - return 0 on success */
8698 static int
_joinW(WCHAR * dest_path,const WCHAR * root,const WCHAR * rest)8699 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8700 {
8701     if (_is_absW(rest)) {
8702         return wcscpy_s(dest_path, MAX_PATH, rest);
8703     }
8704 
8705     if (wcscpy_s(dest_path, MAX_PATH, root)) {
8706         return -1;
8707     }
8708 
8709     if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8710         return -1;
8711     }
8712 
8713     return wcscat_s(dest_path, MAX_PATH, rest);
8714 }
8715 
8716 /* Return True if the path at src relative to dest is a directory */
8717 static int
_check_dirW(LPCWSTR src,LPCWSTR dest)8718 _check_dirW(LPCWSTR src, LPCWSTR dest)
8719 {
8720     WIN32_FILE_ATTRIBUTE_DATA src_info;
8721     WCHAR dest_parent[MAX_PATH];
8722     WCHAR src_resolved[MAX_PATH] = L"";
8723 
8724     /* dest_parent = os.path.dirname(dest) */
8725     if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8726         _dirnameW(dest_parent)) {
8727         return 0;
8728     }
8729     /* src_resolved = os.path.join(dest_parent, src) */
8730     if (_joinW(src_resolved, dest_parent, src)) {
8731         return 0;
8732     }
8733     return (
8734         GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8735         && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8736     );
8737 }
8738 #endif
8739 
8740 
8741 /*[clinic input]
8742 os.symlink
8743     src: path_t
8744     dst: path_t
8745     target_is_directory: bool = False
8746     *
8747     dir_fd: dir_fd(requires='symlinkat')=None
8748 
8749 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8750 
8751 Create a symbolic link pointing to src named dst.
8752 
8753 target_is_directory is required on Windows if the target is to be
8754   interpreted as a directory.  (On Windows, symlink requires
8755   Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8756   target_is_directory is ignored on non-Windows platforms.
8757 
8758 If dir_fd is not None, it should be a file descriptor open to a directory,
8759   and path should be relative; path will then be relative to that directory.
8760 dir_fd may not be implemented on your platform.
8761   If it is unavailable, using it will raise a NotImplementedError.
8762 
8763 [clinic start generated code]*/
8764 
8765 static PyObject *
os_symlink_impl(PyObject * module,path_t * src,path_t * dst,int target_is_directory,int dir_fd)8766 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8767                 int target_is_directory, int dir_fd)
8768 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8769 {
8770 #ifdef MS_WINDOWS
8771     DWORD result;
8772     DWORD flags = 0;
8773 
8774     /* Assumed true, set to false if detected to not be available. */
8775     static int windows_has_symlink_unprivileged_flag = TRUE;
8776 #else
8777     int result;
8778 #ifdef HAVE_SYMLINKAT
8779     int symlinkat_unavailable = 0;
8780 #endif
8781 #endif
8782 
8783     if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8784                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8785         return NULL;
8786     }
8787 
8788 #ifdef MS_WINDOWS
8789 
8790     if (windows_has_symlink_unprivileged_flag) {
8791         /* Allow non-admin symlinks if system allows it. */
8792         flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8793     }
8794 
8795     Py_BEGIN_ALLOW_THREADS
8796     _Py_BEGIN_SUPPRESS_IPH
8797     /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8798     if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8799         flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8800     }
8801 
8802     result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8803     _Py_END_SUPPRESS_IPH
8804     Py_END_ALLOW_THREADS
8805 
8806     if (windows_has_symlink_unprivileged_flag && !result &&
8807         ERROR_INVALID_PARAMETER == GetLastError()) {
8808 
8809         Py_BEGIN_ALLOW_THREADS
8810         _Py_BEGIN_SUPPRESS_IPH
8811         /* This error might be caused by
8812         SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8813         Try again, and update windows_has_symlink_unprivileged_flag if we
8814         are successful this time.
8815 
8816         NOTE: There is a risk of a race condition here if there are other
8817         conditions than the flag causing ERROR_INVALID_PARAMETER, and
8818         another process (or thread) changes that condition in between our
8819         calls to CreateSymbolicLink.
8820         */
8821         flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8822         result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8823         _Py_END_SUPPRESS_IPH
8824         Py_END_ALLOW_THREADS
8825 
8826         if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8827             windows_has_symlink_unprivileged_flag = FALSE;
8828         }
8829     }
8830 
8831     if (!result)
8832         return path_error2(src, dst);
8833 
8834 #else
8835 
8836     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8837         PyErr_SetString(PyExc_ValueError,
8838             "symlink: src and dst must be the same type");
8839         return NULL;
8840     }
8841 
8842     Py_BEGIN_ALLOW_THREADS
8843 #ifdef HAVE_SYMLINKAT
8844     if (dir_fd != DEFAULT_DIR_FD) {
8845         if (HAVE_SYMLINKAT_RUNTIME) {
8846             result = symlinkat(src->narrow, dir_fd, dst->narrow);
8847         } else {
8848             symlinkat_unavailable = 1;
8849         }
8850     } else
8851 #endif
8852         result = symlink(src->narrow, dst->narrow);
8853     Py_END_ALLOW_THREADS
8854 
8855 #ifdef HAVE_SYMLINKAT
8856     if (symlinkat_unavailable) {
8857           argument_unavailable_error(NULL, "dir_fd");
8858           return NULL;
8859     }
8860 #endif
8861 
8862     if (result)
8863         return path_error2(src, dst);
8864 #endif
8865 
8866     Py_RETURN_NONE;
8867 }
8868 #endif /* HAVE_SYMLINK */
8869 
8870 
8871 
8872 
8873 static PyStructSequence_Field times_result_fields[] = {
8874     {"user",    "user time"},
8875     {"system",   "system time"},
8876     {"children_user",    "user time of children"},
8877     {"children_system",    "system time of children"},
8878     {"elapsed",    "elapsed time since an arbitrary point in the past"},
8879     {NULL}
8880 };
8881 
8882 PyDoc_STRVAR(times_result__doc__,
8883 "times_result: Result from os.times().\n\n\
8884 This object may be accessed either as a tuple of\n\
8885   (user, system, children_user, children_system, elapsed),\n\
8886 or via the attributes user, system, children_user, children_system,\n\
8887 and elapsed.\n\
8888 \n\
8889 See os.times for more information.");
8890 
8891 static PyStructSequence_Desc times_result_desc = {
8892     "times_result", /* name */
8893     times_result__doc__, /* doc */
8894     times_result_fields,
8895     5
8896 };
8897 
8898 #ifdef MS_WINDOWS
8899 #define HAVE_TIMES  /* mandatory, for the method table */
8900 #endif
8901 
8902 #ifdef HAVE_TIMES
8903 
8904 static PyObject *
build_times_result(PyObject * module,double user,double system,double children_user,double children_system,double elapsed)8905 build_times_result(PyObject *module, double user, double system,
8906     double children_user, double children_system,
8907     double elapsed)
8908 {
8909     PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
8910     PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
8911     if (value == NULL)
8912         return NULL;
8913 
8914 #define SET(i, field) \
8915     { \
8916     PyObject *o = PyFloat_FromDouble(field); \
8917     if (!o) { \
8918         Py_DECREF(value); \
8919         return NULL; \
8920     } \
8921     PyStructSequence_SET_ITEM(value, i, o); \
8922     } \
8923 
8924     SET(0, user);
8925     SET(1, system);
8926     SET(2, children_user);
8927     SET(3, children_system);
8928     SET(4, elapsed);
8929 
8930 #undef SET
8931 
8932     return value;
8933 }
8934 
8935 
8936 #ifndef MS_WINDOWS
8937 #define NEED_TICKS_PER_SECOND
8938 static long ticks_per_second = -1;
8939 #endif /* MS_WINDOWS */
8940 
8941 /*[clinic input]
8942 os.times
8943 
8944 Return a collection containing process timing information.
8945 
8946 The object returned behaves like a named tuple with these fields:
8947   (utime, stime, cutime, cstime, elapsed_time)
8948 All fields are floating point numbers.
8949 [clinic start generated code]*/
8950 
8951 static PyObject *
os_times_impl(PyObject * module)8952 os_times_impl(PyObject *module)
8953 /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
8954 #ifdef MS_WINDOWS
8955 {
8956     FILETIME create, exit, kernel, user;
8957     HANDLE hProc;
8958     hProc = GetCurrentProcess();
8959     GetProcessTimes(hProc, &create, &exit, &kernel, &user);
8960     /* The fields of a FILETIME structure are the hi and lo part
8961        of a 64-bit value expressed in 100 nanosecond units.
8962        1e7 is one second in such units; 1e-7 the inverse.
8963        429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
8964     */
8965     return build_times_result(module,
8966         (double)(user.dwHighDateTime*429.4967296 +
8967                  user.dwLowDateTime*1e-7),
8968         (double)(kernel.dwHighDateTime*429.4967296 +
8969                  kernel.dwLowDateTime*1e-7),
8970         (double)0,
8971         (double)0,
8972         (double)0);
8973 }
8974 #else /* MS_WINDOWS */
8975 {
8976 
8977 
8978     struct tms t;
8979     clock_t c;
8980     errno = 0;
8981     c = times(&t);
8982     if (c == (clock_t) -1)
8983         return posix_error();
8984     return build_times_result(module,
8985                          (double)t.tms_utime / ticks_per_second,
8986                          (double)t.tms_stime / ticks_per_second,
8987                          (double)t.tms_cutime / ticks_per_second,
8988                          (double)t.tms_cstime / ticks_per_second,
8989                          (double)c / ticks_per_second);
8990 }
8991 #endif /* MS_WINDOWS */
8992 #endif /* HAVE_TIMES */
8993 
8994 
8995 #ifdef HAVE_GETSID
8996 /*[clinic input]
8997 os.getsid
8998 
8999     pid: pid_t
9000     /
9001 
9002 Call the system call getsid(pid) and return the result.
9003 [clinic start generated code]*/
9004 
9005 static PyObject *
os_getsid_impl(PyObject * module,pid_t pid)9006 os_getsid_impl(PyObject *module, pid_t pid)
9007 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
9008 {
9009     int sid;
9010     sid = getsid(pid);
9011     if (sid < 0)
9012         return posix_error();
9013     return PyLong_FromLong((long)sid);
9014 }
9015 #endif /* HAVE_GETSID */
9016 
9017 
9018 #ifdef HAVE_SETSID
9019 /*[clinic input]
9020 os.setsid
9021 
9022 Call the system call setsid().
9023 [clinic start generated code]*/
9024 
9025 static PyObject *
os_setsid_impl(PyObject * module)9026 os_setsid_impl(PyObject *module)
9027 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
9028 {
9029     if (setsid() < 0)
9030         return posix_error();
9031     Py_RETURN_NONE;
9032 }
9033 #endif /* HAVE_SETSID */
9034 
9035 
9036 #ifdef HAVE_SETPGID
9037 /*[clinic input]
9038 os.setpgid
9039 
9040     pid: pid_t
9041     pgrp: pid_t
9042     /
9043 
9044 Call the system call setpgid(pid, pgrp).
9045 [clinic start generated code]*/
9046 
9047 static PyObject *
os_setpgid_impl(PyObject * module,pid_t pid,pid_t pgrp)9048 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
9049 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
9050 {
9051     if (setpgid(pid, pgrp) < 0)
9052         return posix_error();
9053     Py_RETURN_NONE;
9054 }
9055 #endif /* HAVE_SETPGID */
9056 
9057 
9058 #ifdef HAVE_TCGETPGRP
9059 /*[clinic input]
9060 os.tcgetpgrp
9061 
9062     fd: int
9063     /
9064 
9065 Return the process group associated with the terminal specified by fd.
9066 [clinic start generated code]*/
9067 
9068 static PyObject *
os_tcgetpgrp_impl(PyObject * module,int fd)9069 os_tcgetpgrp_impl(PyObject *module, int fd)
9070 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
9071 {
9072     pid_t pgid = tcgetpgrp(fd);
9073     if (pgid < 0)
9074         return posix_error();
9075     return PyLong_FromPid(pgid);
9076 }
9077 #endif /* HAVE_TCGETPGRP */
9078 
9079 
9080 #ifdef HAVE_TCSETPGRP
9081 /*[clinic input]
9082 os.tcsetpgrp
9083 
9084     fd: int
9085     pgid: pid_t
9086     /
9087 
9088 Set the process group associated with the terminal specified by fd.
9089 [clinic start generated code]*/
9090 
9091 static PyObject *
os_tcsetpgrp_impl(PyObject * module,int fd,pid_t pgid)9092 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
9093 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
9094 {
9095     if (tcsetpgrp(fd, pgid) < 0)
9096         return posix_error();
9097     Py_RETURN_NONE;
9098 }
9099 #endif /* HAVE_TCSETPGRP */
9100 
9101 /* Functions acting on file descriptors */
9102 
9103 #ifdef O_CLOEXEC
9104 extern int _Py_open_cloexec_works;
9105 #endif
9106 
9107 
9108 /*[clinic input]
9109 os.open -> int
9110     path: path_t
9111     flags: int
9112     mode: int = 0o777
9113     *
9114     dir_fd: dir_fd(requires='openat') = None
9115 
9116 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
9117 
9118 Open a file for low level IO.  Returns a file descriptor (integer).
9119 
9120 If dir_fd is not None, it should be a file descriptor open to a directory,
9121   and path should be relative; path will then be relative to that directory.
9122 dir_fd may not be implemented on your platform.
9123   If it is unavailable, using it will raise a NotImplementedError.
9124 [clinic start generated code]*/
9125 
9126 static int
os_open_impl(PyObject * module,path_t * path,int flags,int mode,int dir_fd)9127 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
9128 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
9129 {
9130     int fd;
9131     int async_err = 0;
9132 #ifdef HAVE_OPENAT
9133     int openat_unavailable = 0;
9134 #endif
9135 
9136 #ifdef O_CLOEXEC
9137     int *atomic_flag_works = &_Py_open_cloexec_works;
9138 #elif !defined(MS_WINDOWS)
9139     int *atomic_flag_works = NULL;
9140 #endif
9141 
9142 #ifdef MS_WINDOWS
9143     flags |= O_NOINHERIT;
9144 #elif defined(O_CLOEXEC)
9145     flags |= O_CLOEXEC;
9146 #endif
9147 
9148     if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
9149         return -1;
9150     }
9151 
9152     _Py_BEGIN_SUPPRESS_IPH
9153     do {
9154         Py_BEGIN_ALLOW_THREADS
9155 #ifdef MS_WINDOWS
9156         fd = _wopen(path->wide, flags, mode);
9157 #else
9158 #ifdef HAVE_OPENAT
9159         if (dir_fd != DEFAULT_DIR_FD) {
9160             if (HAVE_OPENAT_RUNTIME) {
9161                 fd = openat(dir_fd, path->narrow, flags, mode);
9162 
9163             } else {
9164                 openat_unavailable = 1;
9165                 fd = -1;
9166             }
9167         } else
9168 #endif /* HAVE_OPENAT */
9169             fd = open(path->narrow, flags, mode);
9170 #endif /* !MS_WINDOWS */
9171         Py_END_ALLOW_THREADS
9172     } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9173     _Py_END_SUPPRESS_IPH
9174 
9175 #ifdef HAVE_OPENAT
9176     if (openat_unavailable) {
9177         argument_unavailable_error(NULL, "dir_fd");
9178         return -1;
9179     }
9180 #endif
9181 
9182     if (fd < 0) {
9183         if (!async_err)
9184             PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
9185         return -1;
9186     }
9187 
9188 #ifndef MS_WINDOWS
9189     if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
9190         close(fd);
9191         return -1;
9192     }
9193 #endif
9194 
9195     return fd;
9196 }
9197 
9198 
9199 /*[clinic input]
9200 os.close
9201 
9202     fd: int
9203 
9204 Close a file descriptor.
9205 [clinic start generated code]*/
9206 
9207 static PyObject *
os_close_impl(PyObject * module,int fd)9208 os_close_impl(PyObject *module, int fd)
9209 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
9210 {
9211     int res;
9212     /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
9213      * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
9214      * for more details.
9215      */
9216     Py_BEGIN_ALLOW_THREADS
9217     _Py_BEGIN_SUPPRESS_IPH
9218     res = close(fd);
9219     _Py_END_SUPPRESS_IPH
9220     Py_END_ALLOW_THREADS
9221     if (res < 0)
9222         return posix_error();
9223     Py_RETURN_NONE;
9224 }
9225 
9226 /*[clinic input]
9227 os.closerange
9228 
9229     fd_low: int
9230     fd_high: int
9231     /
9232 
9233 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
9234 [clinic start generated code]*/
9235 
9236 static PyObject *
os_closerange_impl(PyObject * module,int fd_low,int fd_high)9237 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
9238 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
9239 {
9240     Py_BEGIN_ALLOW_THREADS
9241     _Py_closerange(fd_low, fd_high - 1);
9242     Py_END_ALLOW_THREADS
9243     Py_RETURN_NONE;
9244 }
9245 
9246 
9247 /*[clinic input]
9248 os.dup -> int
9249 
9250     fd: int
9251     /
9252 
9253 Return a duplicate of a file descriptor.
9254 [clinic start generated code]*/
9255 
9256 static int
os_dup_impl(PyObject * module,int fd)9257 os_dup_impl(PyObject *module, int fd)
9258 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
9259 {
9260     return _Py_dup(fd);
9261 }
9262 
9263 
9264 /*[clinic input]
9265 os.dup2 -> int
9266     fd: int
9267     fd2: int
9268     inheritable: bool=True
9269 
9270 Duplicate file descriptor.
9271 [clinic start generated code]*/
9272 
9273 static int
os_dup2_impl(PyObject * module,int fd,int fd2,int inheritable)9274 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
9275 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
9276 {
9277     int res = 0;
9278 #if defined(HAVE_DUP3) && \
9279     !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
9280     /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
9281     static int dup3_works = -1;
9282 #endif
9283 
9284     if (fd < 0 || fd2 < 0) {
9285         posix_error();
9286         return -1;
9287     }
9288 
9289     /* dup2() can fail with EINTR if the target FD is already open, because it
9290      * then has to be closed. See os_close_impl() for why we don't handle EINTR
9291      * upon close(), and therefore below.
9292      */
9293 #ifdef MS_WINDOWS
9294     Py_BEGIN_ALLOW_THREADS
9295     _Py_BEGIN_SUPPRESS_IPH
9296     res = dup2(fd, fd2);
9297     _Py_END_SUPPRESS_IPH
9298     Py_END_ALLOW_THREADS
9299     if (res < 0) {
9300         posix_error();
9301         return -1;
9302     }
9303     res = fd2; // msvcrt dup2 returns 0 on success.
9304 
9305     /* Character files like console cannot be make non-inheritable */
9306     if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9307         close(fd2);
9308         return -1;
9309     }
9310 
9311 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
9312     Py_BEGIN_ALLOW_THREADS
9313     if (!inheritable)
9314         res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
9315     else
9316         res = dup2(fd, fd2);
9317     Py_END_ALLOW_THREADS
9318     if (res < 0) {
9319         posix_error();
9320         return -1;
9321     }
9322 
9323 #else
9324 
9325 #ifdef HAVE_DUP3
9326     if (!inheritable && dup3_works != 0) {
9327         Py_BEGIN_ALLOW_THREADS
9328         res = dup3(fd, fd2, O_CLOEXEC);
9329         Py_END_ALLOW_THREADS
9330         if (res < 0) {
9331             if (dup3_works == -1)
9332                 dup3_works = (errno != ENOSYS);
9333             if (dup3_works) {
9334                 posix_error();
9335                 return -1;
9336             }
9337         }
9338     }
9339 
9340     if (inheritable || dup3_works == 0)
9341     {
9342 #endif
9343         Py_BEGIN_ALLOW_THREADS
9344         res = dup2(fd, fd2);
9345         Py_END_ALLOW_THREADS
9346         if (res < 0) {
9347             posix_error();
9348             return -1;
9349         }
9350 
9351         if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9352             close(fd2);
9353             return -1;
9354         }
9355 #ifdef HAVE_DUP3
9356     }
9357 #endif
9358 
9359 #endif
9360 
9361     return res;
9362 }
9363 
9364 
9365 #ifdef HAVE_LOCKF
9366 /*[clinic input]
9367 os.lockf
9368 
9369     fd: int
9370         An open file descriptor.
9371     command: int
9372         One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
9373     length: Py_off_t
9374         The number of bytes to lock, starting at the current position.
9375     /
9376 
9377 Apply, test or remove a POSIX lock on an open file descriptor.
9378 
9379 [clinic start generated code]*/
9380 
9381 static PyObject *
os_lockf_impl(PyObject * module,int fd,int command,Py_off_t length)9382 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
9383 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
9384 {
9385     int res;
9386 
9387     if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
9388         return NULL;
9389     }
9390 
9391     Py_BEGIN_ALLOW_THREADS
9392     res = lockf(fd, command, length);
9393     Py_END_ALLOW_THREADS
9394 
9395     if (res < 0)
9396         return posix_error();
9397 
9398     Py_RETURN_NONE;
9399 }
9400 #endif /* HAVE_LOCKF */
9401 
9402 
9403 /*[clinic input]
9404 os.lseek -> Py_off_t
9405 
9406     fd: int
9407     position: Py_off_t
9408     how: int
9409     /
9410 
9411 Set the position of a file descriptor.  Return the new position.
9412 
9413 Return the new cursor position in number of bytes
9414 relative to the beginning of the file.
9415 [clinic start generated code]*/
9416 
9417 static Py_off_t
os_lseek_impl(PyObject * module,int fd,Py_off_t position,int how)9418 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
9419 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
9420 {
9421     Py_off_t result;
9422 
9423 #ifdef SEEK_SET
9424     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
9425     switch (how) {
9426         case 0: how = SEEK_SET; break;
9427         case 1: how = SEEK_CUR; break;
9428         case 2: how = SEEK_END; break;
9429     }
9430 #endif /* SEEK_END */
9431 
9432     Py_BEGIN_ALLOW_THREADS
9433     _Py_BEGIN_SUPPRESS_IPH
9434 #ifdef MS_WINDOWS
9435     result = _lseeki64(fd, position, how);
9436 #else
9437     result = lseek(fd, position, how);
9438 #endif
9439     _Py_END_SUPPRESS_IPH
9440     Py_END_ALLOW_THREADS
9441     if (result < 0)
9442         posix_error();
9443 
9444     return result;
9445 }
9446 
9447 
9448 /*[clinic input]
9449 os.read
9450     fd: int
9451     length: Py_ssize_t
9452     /
9453 
9454 Read from a file descriptor.  Returns a bytes object.
9455 [clinic start generated code]*/
9456 
9457 static PyObject *
os_read_impl(PyObject * module,int fd,Py_ssize_t length)9458 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
9459 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
9460 {
9461     Py_ssize_t n;
9462     PyObject *buffer;
9463 
9464     if (length < 0) {
9465         errno = EINVAL;
9466         return posix_error();
9467     }
9468 
9469     length = Py_MIN(length, _PY_READ_MAX);
9470 
9471     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9472     if (buffer == NULL)
9473         return NULL;
9474 
9475     n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
9476     if (n == -1) {
9477         Py_DECREF(buffer);
9478         return NULL;
9479     }
9480 
9481     if (n != length)
9482         _PyBytes_Resize(&buffer, n);
9483 
9484     return buffer;
9485 }
9486 
9487 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
9488                                 || defined(__APPLE__))) \
9489     || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
9490     || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9491 static int
iov_setup(struct iovec ** iov,Py_buffer ** buf,PyObject * seq,Py_ssize_t cnt,int type)9492 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
9493 {
9494     Py_ssize_t i, j;
9495 
9496     *iov = PyMem_New(struct iovec, cnt);
9497     if (*iov == NULL) {
9498         PyErr_NoMemory();
9499         return -1;
9500     }
9501 
9502     *buf = PyMem_New(Py_buffer, cnt);
9503     if (*buf == NULL) {
9504         PyMem_Free(*iov);
9505         PyErr_NoMemory();
9506         return -1;
9507     }
9508 
9509     for (i = 0; i < cnt; i++) {
9510         PyObject *item = PySequence_GetItem(seq, i);
9511         if (item == NULL)
9512             goto fail;
9513         if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
9514             Py_DECREF(item);
9515             goto fail;
9516         }
9517         Py_DECREF(item);
9518         (*iov)[i].iov_base = (*buf)[i].buf;
9519         (*iov)[i].iov_len = (*buf)[i].len;
9520     }
9521     return 0;
9522 
9523 fail:
9524     PyMem_Free(*iov);
9525     for (j = 0; j < i; j++) {
9526         PyBuffer_Release(&(*buf)[j]);
9527     }
9528     PyMem_Free(*buf);
9529     return -1;
9530 }
9531 
9532 static void
iov_cleanup(struct iovec * iov,Py_buffer * buf,int cnt)9533 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9534 {
9535     int i;
9536     PyMem_Free(iov);
9537     for (i = 0; i < cnt; i++) {
9538         PyBuffer_Release(&buf[i]);
9539     }
9540     PyMem_Free(buf);
9541 }
9542 #endif
9543 
9544 
9545 #ifdef HAVE_READV
9546 /*[clinic input]
9547 os.readv -> Py_ssize_t
9548 
9549     fd: int
9550     buffers: object
9551     /
9552 
9553 Read from a file descriptor fd into an iterable of buffers.
9554 
9555 The buffers should be mutable buffers accepting bytes.
9556 readv will transfer data into each buffer until it is full
9557 and then move on to the next buffer in the sequence to hold
9558 the rest of the data.
9559 
9560 readv returns the total number of bytes read,
9561 which may be less than the total capacity of all the buffers.
9562 [clinic start generated code]*/
9563 
9564 static Py_ssize_t
os_readv_impl(PyObject * module,int fd,PyObject * buffers)9565 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9566 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9567 {
9568     Py_ssize_t cnt, n;
9569     int async_err = 0;
9570     struct iovec *iov;
9571     Py_buffer *buf;
9572 
9573     if (!PySequence_Check(buffers)) {
9574         PyErr_SetString(PyExc_TypeError,
9575             "readv() arg 2 must be a sequence");
9576         return -1;
9577     }
9578 
9579     cnt = PySequence_Size(buffers);
9580     if (cnt < 0)
9581         return -1;
9582 
9583     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9584         return -1;
9585 
9586     do {
9587         Py_BEGIN_ALLOW_THREADS
9588         n = readv(fd, iov, cnt);
9589         Py_END_ALLOW_THREADS
9590     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9591 
9592     iov_cleanup(iov, buf, cnt);
9593     if (n < 0) {
9594         if (!async_err)
9595             posix_error();
9596         return -1;
9597     }
9598 
9599     return n;
9600 }
9601 #endif /* HAVE_READV */
9602 
9603 
9604 #ifdef HAVE_PREAD
9605 /*[clinic input]
9606 os.pread
9607 
9608     fd: int
9609     length: Py_ssize_t
9610     offset: Py_off_t
9611     /
9612 
9613 Read a number of bytes from a file descriptor starting at a particular offset.
9614 
9615 Read length bytes from file descriptor fd, starting at offset bytes from
9616 the beginning of the file.  The file offset remains unchanged.
9617 [clinic start generated code]*/
9618 
9619 static PyObject *
os_pread_impl(PyObject * module,int fd,Py_ssize_t length,Py_off_t offset)9620 os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
9621 /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
9622 {
9623     Py_ssize_t n;
9624     int async_err = 0;
9625     PyObject *buffer;
9626 
9627     if (length < 0) {
9628         errno = EINVAL;
9629         return posix_error();
9630     }
9631     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9632     if (buffer == NULL)
9633         return NULL;
9634 
9635     do {
9636         Py_BEGIN_ALLOW_THREADS
9637         _Py_BEGIN_SUPPRESS_IPH
9638         n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9639         _Py_END_SUPPRESS_IPH
9640         Py_END_ALLOW_THREADS
9641     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9642 
9643     if (n < 0) {
9644         Py_DECREF(buffer);
9645         return (!async_err) ? posix_error() : NULL;
9646     }
9647     if (n != length)
9648         _PyBytes_Resize(&buffer, n);
9649     return buffer;
9650 }
9651 #endif /* HAVE_PREAD */
9652 
9653 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9654 /*[clinic input]
9655 os.preadv -> Py_ssize_t
9656 
9657     fd: int
9658     buffers: object
9659     offset: Py_off_t
9660     flags: int = 0
9661     /
9662 
9663 Reads from a file descriptor into a number of mutable bytes-like objects.
9664 
9665 Combines the functionality of readv() and pread(). As readv(), it will
9666 transfer data into each buffer until it is full and then move on to the next
9667 buffer in the sequence to hold the rest of the data. Its fourth argument,
9668 specifies the file offset at which the input operation is to be performed. It
9669 will return the total number of bytes read (which can be less than the total
9670 capacity of all the objects).
9671 
9672 The flags argument contains a bitwise OR of zero or more of the following flags:
9673 
9674 - RWF_HIPRI
9675 - RWF_NOWAIT
9676 
9677 Using non-zero flags requires Linux 4.6 or newer.
9678 [clinic start generated code]*/
9679 
9680 static Py_ssize_t
os_preadv_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9681 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9682                int flags)
9683 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9684 {
9685     Py_ssize_t cnt, n;
9686     int async_err = 0;
9687     struct iovec *iov;
9688     Py_buffer *buf;
9689 
9690     if (!PySequence_Check(buffers)) {
9691         PyErr_SetString(PyExc_TypeError,
9692             "preadv2() arg 2 must be a sequence");
9693         return -1;
9694     }
9695 
9696     cnt = PySequence_Size(buffers);
9697     if (cnt < 0) {
9698         return -1;
9699     }
9700 
9701 #ifndef HAVE_PREADV2
9702     if(flags != 0) {
9703         argument_unavailable_error("preadv2", "flags");
9704         return -1;
9705     }
9706 #endif
9707 
9708     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9709         return -1;
9710     }
9711 #ifdef HAVE_PREADV2
9712     do {
9713         Py_BEGIN_ALLOW_THREADS
9714         _Py_BEGIN_SUPPRESS_IPH
9715         n = preadv2(fd, iov, cnt, offset, flags);
9716         _Py_END_SUPPRESS_IPH
9717         Py_END_ALLOW_THREADS
9718     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9719 #else
9720     do {
9721 #ifdef __APPLE__
9722 /* This entire function will be removed from the module dict when the API
9723  * is not available.
9724  */
9725 #pragma clang diagnostic push
9726 #pragma clang diagnostic ignored "-Wunguarded-availability"
9727 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
9728 #endif
9729         Py_BEGIN_ALLOW_THREADS
9730         _Py_BEGIN_SUPPRESS_IPH
9731         n = preadv(fd, iov, cnt, offset);
9732         _Py_END_SUPPRESS_IPH
9733         Py_END_ALLOW_THREADS
9734     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9735 
9736 #ifdef __APPLE__
9737 #pragma clang diagnostic pop
9738 #endif
9739 
9740 #endif
9741 
9742     iov_cleanup(iov, buf, cnt);
9743     if (n < 0) {
9744         if (!async_err) {
9745             posix_error();
9746         }
9747         return -1;
9748     }
9749 
9750     return n;
9751 }
9752 #endif /* HAVE_PREADV */
9753 
9754 
9755 /*[clinic input]
9756 os.write -> Py_ssize_t
9757 
9758     fd: int
9759     data: Py_buffer
9760     /
9761 
9762 Write a bytes object to a file descriptor.
9763 [clinic start generated code]*/
9764 
9765 static Py_ssize_t
os_write_impl(PyObject * module,int fd,Py_buffer * data)9766 os_write_impl(PyObject *module, int fd, Py_buffer *data)
9767 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9768 {
9769     return _Py_write(fd, data->buf, data->len);
9770 }
9771 
9772 #ifdef HAVE_SENDFILE
9773 #ifdef __APPLE__
9774 /*[clinic input]
9775 os.sendfile
9776 
9777     out_fd: int
9778     in_fd: int
9779     offset: Py_off_t
9780     count as sbytes: Py_off_t
9781     headers: object(c_default="NULL") = ()
9782     trailers: object(c_default="NULL") = ()
9783     flags: int = 0
9784 
9785 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9786 [clinic start generated code]*/
9787 
9788 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)9789 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9790                  Py_off_t sbytes, PyObject *headers, PyObject *trailers,
9791                  int flags)
9792 /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
9793 #elif defined(__FreeBSD__) || defined(__DragonFly__)
9794 /*[clinic input]
9795 os.sendfile
9796 
9797     out_fd: int
9798     in_fd: int
9799     offset: Py_off_t
9800     count: Py_ssize_t
9801     headers: object(c_default="NULL") = ()
9802     trailers: object(c_default="NULL") = ()
9803     flags: int = 0
9804 
9805 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9806 [clinic start generated code]*/
9807 
9808 static PyObject *
9809 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9810                  Py_ssize_t count, PyObject *headers, PyObject *trailers,
9811                  int flags)
9812 /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
9813 #else
9814 /*[clinic input]
9815 os.sendfile
9816 
9817     out_fd: int
9818     in_fd: int
9819     offset as offobj: object
9820     count: Py_ssize_t
9821 
9822 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9823 [clinic start generated code]*/
9824 
9825 static PyObject *
9826 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
9827                  Py_ssize_t count)
9828 /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
9829 #endif
9830 {
9831     Py_ssize_t ret;
9832     int async_err = 0;
9833 
9834 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9835 #ifndef __APPLE__
9836     off_t sbytes;
9837 #endif
9838     Py_buffer *hbuf, *tbuf;
9839     struct sf_hdtr sf;
9840 
9841     sf.headers = NULL;
9842     sf.trailers = NULL;
9843 
9844     if (headers != NULL) {
9845         if (!PySequence_Check(headers)) {
9846             PyErr_SetString(PyExc_TypeError,
9847                 "sendfile() headers must be a sequence");
9848             return NULL;
9849         } else {
9850             Py_ssize_t i = PySequence_Size(headers);
9851             if (i < 0)
9852                 return NULL;
9853             if (i > INT_MAX) {
9854                 PyErr_SetString(PyExc_OverflowError,
9855                     "sendfile() header is too large");
9856                 return NULL;
9857             }
9858             if (i > 0) {
9859                 sf.hdr_cnt = (int)i;
9860                 if (iov_setup(&(sf.headers), &hbuf,
9861                               headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9862                     return NULL;
9863 #ifdef __APPLE__
9864                 for (i = 0; i < sf.hdr_cnt; i++) {
9865                     Py_ssize_t blen = sf.headers[i].iov_len;
9866 # define OFF_T_MAX 0x7fffffffffffffff
9867                     if (sbytes >= OFF_T_MAX - blen) {
9868                         PyErr_SetString(PyExc_OverflowError,
9869                             "sendfile() header is too large");
9870                         return NULL;
9871                     }
9872                     sbytes += blen;
9873                 }
9874 #endif
9875             }
9876         }
9877     }
9878     if (trailers != NULL) {
9879         if (!PySequence_Check(trailers)) {
9880             PyErr_SetString(PyExc_TypeError,
9881                 "sendfile() trailers must be a sequence");
9882             return NULL;
9883         } else {
9884             Py_ssize_t i = PySequence_Size(trailers);
9885             if (i < 0)
9886                 return NULL;
9887             if (i > INT_MAX) {
9888                 PyErr_SetString(PyExc_OverflowError,
9889                     "sendfile() trailer is too large");
9890                 return NULL;
9891             }
9892             if (i > 0) {
9893                 sf.trl_cnt = (int)i;
9894                 if (iov_setup(&(sf.trailers), &tbuf,
9895                               trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
9896                     return NULL;
9897             }
9898         }
9899     }
9900 
9901     _Py_BEGIN_SUPPRESS_IPH
9902     do {
9903         Py_BEGIN_ALLOW_THREADS
9904 #ifdef __APPLE__
9905         ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
9906 #else
9907         ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
9908 #endif
9909         Py_END_ALLOW_THREADS
9910     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9911     _Py_END_SUPPRESS_IPH
9912 
9913     if (sf.headers != NULL)
9914         iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
9915     if (sf.trailers != NULL)
9916         iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
9917 
9918     if (ret < 0) {
9919         if ((errno == EAGAIN) || (errno == EBUSY)) {
9920             if (sbytes != 0) {
9921                 // some data has been sent
9922                 goto done;
9923             }
9924             else {
9925                 // no data has been sent; upper application is supposed
9926                 // to retry on EAGAIN or EBUSY
9927                 return posix_error();
9928             }
9929         }
9930         return (!async_err) ? posix_error() : NULL;
9931     }
9932     goto done;
9933 
9934 done:
9935     #if !defined(HAVE_LARGEFILE_SUPPORT)
9936         return Py_BuildValue("l", sbytes);
9937     #else
9938         return Py_BuildValue("L", sbytes);
9939     #endif
9940 
9941 #else
9942 #ifdef __linux__
9943     if (offobj == Py_None) {
9944         do {
9945             Py_BEGIN_ALLOW_THREADS
9946             ret = sendfile(out_fd, in_fd, NULL, count);
9947             Py_END_ALLOW_THREADS
9948         } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9949         if (ret < 0)
9950             return (!async_err) ? posix_error() : NULL;
9951         return Py_BuildValue("n", ret);
9952     }
9953 #endif
9954     off_t offset;
9955     if (!Py_off_t_converter(offobj, &offset))
9956         return NULL;
9957 
9958 #if defined(__sun) && defined(__SVR4)
9959     // On Solaris, sendfile raises EINVAL rather than returning 0
9960     // when the offset is equal or bigger than the in_fd size.
9961     struct stat st;
9962 
9963     do {
9964         Py_BEGIN_ALLOW_THREADS
9965         ret = fstat(in_fd, &st);
9966         Py_END_ALLOW_THREADS
9967     } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9968     if (ret < 0)
9969         return (!async_err) ? posix_error() : NULL;
9970 
9971     if (offset >= st.st_size) {
9972         return Py_BuildValue("i", 0);
9973     }
9974 
9975     // On illumos specifically sendfile() may perform a partial write but
9976     // return -1/an error (in one confirmed case the destination socket
9977     // had a 5 second timeout set and errno was EAGAIN) and it's on the client
9978     // code to check if the offset parameter was modified by sendfile().
9979     //
9980     // We need this variable to track said change.
9981     off_t original_offset = offset;
9982 #endif
9983 
9984     do {
9985         Py_BEGIN_ALLOW_THREADS
9986         ret = sendfile(out_fd, in_fd, &offset, count);
9987 #if defined(__sun) && defined(__SVR4)
9988         // This handles illumos-specific sendfile() partial write behavior,
9989         // see a comment above for more details.
9990         if (ret < 0 && offset != original_offset) {
9991             ret = offset - original_offset;
9992         }
9993 #endif
9994         Py_END_ALLOW_THREADS
9995     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9996     if (ret < 0)
9997         return (!async_err) ? posix_error() : NULL;
9998     return Py_BuildValue("n", ret);
9999 #endif
10000 }
10001 #endif /* HAVE_SENDFILE */
10002 
10003 
10004 #if defined(__APPLE__)
10005 /*[clinic input]
10006 os._fcopyfile
10007 
10008     in_fd: int
10009     out_fd: int
10010     flags: int
10011     /
10012 
10013 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
10014 [clinic start generated code]*/
10015 
10016 static PyObject *
os__fcopyfile_impl(PyObject * module,int in_fd,int out_fd,int flags)10017 os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
10018 /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
10019 {
10020     int ret;
10021 
10022     Py_BEGIN_ALLOW_THREADS
10023     ret = fcopyfile(in_fd, out_fd, NULL, flags);
10024     Py_END_ALLOW_THREADS
10025     if (ret < 0)
10026         return posix_error();
10027     Py_RETURN_NONE;
10028 }
10029 #endif
10030 
10031 
10032 /*[clinic input]
10033 os.fstat
10034 
10035     fd : int
10036 
10037 Perform a stat system call on the given file descriptor.
10038 
10039 Like stat(), but for an open file descriptor.
10040 Equivalent to os.stat(fd).
10041 [clinic start generated code]*/
10042 
10043 static PyObject *
os_fstat_impl(PyObject * module,int fd)10044 os_fstat_impl(PyObject *module, int fd)
10045 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
10046 {
10047     STRUCT_STAT st;
10048     int res;
10049     int async_err = 0;
10050 
10051     do {
10052         Py_BEGIN_ALLOW_THREADS
10053         res = FSTAT(fd, &st);
10054         Py_END_ALLOW_THREADS
10055     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10056     if (res != 0) {
10057 #ifdef MS_WINDOWS
10058         return PyErr_SetFromWindowsErr(0);
10059 #else
10060         return (!async_err) ? posix_error() : NULL;
10061 #endif
10062     }
10063 
10064     return _pystat_fromstructstat(module, &st);
10065 }
10066 
10067 
10068 /*[clinic input]
10069 os.isatty -> bool
10070     fd: int
10071     /
10072 
10073 Return True if the fd is connected to a terminal.
10074 
10075 Return True if the file descriptor is an open file descriptor
10076 connected to the slave end of a terminal.
10077 [clinic start generated code]*/
10078 
10079 static int
os_isatty_impl(PyObject * module,int fd)10080 os_isatty_impl(PyObject *module, int fd)
10081 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
10082 {
10083     int return_value;
10084     Py_BEGIN_ALLOW_THREADS
10085     _Py_BEGIN_SUPPRESS_IPH
10086     return_value = isatty(fd);
10087     _Py_END_SUPPRESS_IPH
10088     Py_END_ALLOW_THREADS
10089     return return_value;
10090 }
10091 
10092 
10093 #ifdef HAVE_PIPE
10094 /*[clinic input]
10095 os.pipe
10096 
10097 Create a pipe.
10098 
10099 Returns a tuple of two file descriptors:
10100   (read_fd, write_fd)
10101 [clinic start generated code]*/
10102 
10103 static PyObject *
os_pipe_impl(PyObject * module)10104 os_pipe_impl(PyObject *module)
10105 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
10106 {
10107     int fds[2];
10108 #ifdef MS_WINDOWS
10109     HANDLE read, write;
10110     SECURITY_ATTRIBUTES attr;
10111     BOOL ok;
10112 #else
10113     int res;
10114 #endif
10115 
10116 #ifdef MS_WINDOWS
10117     attr.nLength = sizeof(attr);
10118     attr.lpSecurityDescriptor = NULL;
10119     attr.bInheritHandle = FALSE;
10120 
10121     Py_BEGIN_ALLOW_THREADS
10122     ok = CreatePipe(&read, &write, &attr, 0);
10123     if (ok) {
10124         fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY);
10125         fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY);
10126         if (fds[0] == -1 || fds[1] == -1) {
10127             CloseHandle(read);
10128             CloseHandle(write);
10129             ok = 0;
10130         }
10131     }
10132     Py_END_ALLOW_THREADS
10133 
10134     if (!ok)
10135         return PyErr_SetFromWindowsErr(0);
10136 #else
10137 
10138 #ifdef HAVE_PIPE2
10139     Py_BEGIN_ALLOW_THREADS
10140     res = pipe2(fds, O_CLOEXEC);
10141     Py_END_ALLOW_THREADS
10142 
10143     if (res != 0 && errno == ENOSYS)
10144     {
10145 #endif
10146         Py_BEGIN_ALLOW_THREADS
10147         res = pipe(fds);
10148         Py_END_ALLOW_THREADS
10149 
10150         if (res == 0) {
10151             if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
10152                 close(fds[0]);
10153                 close(fds[1]);
10154                 return NULL;
10155             }
10156             if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
10157                 close(fds[0]);
10158                 close(fds[1]);
10159                 return NULL;
10160             }
10161         }
10162 #ifdef HAVE_PIPE2
10163     }
10164 #endif
10165 
10166     if (res != 0)
10167         return PyErr_SetFromErrno(PyExc_OSError);
10168 #endif /* !MS_WINDOWS */
10169     return Py_BuildValue("(ii)", fds[0], fds[1]);
10170 }
10171 #endif  /* HAVE_PIPE */
10172 
10173 
10174 #ifdef HAVE_PIPE2
10175 /*[clinic input]
10176 os.pipe2
10177 
10178     flags: int
10179     /
10180 
10181 Create a pipe with flags set atomically.
10182 
10183 Returns a tuple of two file descriptors:
10184   (read_fd, write_fd)
10185 
10186 flags can be constructed by ORing together one or more of these values:
10187 O_NONBLOCK, O_CLOEXEC.
10188 [clinic start generated code]*/
10189 
10190 static PyObject *
os_pipe2_impl(PyObject * module,int flags)10191 os_pipe2_impl(PyObject *module, int flags)
10192 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
10193 {
10194     int fds[2];
10195     int res;
10196 
10197     res = pipe2(fds, flags);
10198     if (res != 0)
10199         return posix_error();
10200     return Py_BuildValue("(ii)", fds[0], fds[1]);
10201 }
10202 #endif /* HAVE_PIPE2 */
10203 
10204 
10205 #ifdef HAVE_WRITEV
10206 /*[clinic input]
10207 os.writev -> Py_ssize_t
10208     fd: int
10209     buffers: object
10210     /
10211 
10212 Iterate over buffers, and write the contents of each to a file descriptor.
10213 
10214 Returns the total number of bytes written.
10215 buffers must be a sequence of bytes-like objects.
10216 [clinic start generated code]*/
10217 
10218 static Py_ssize_t
os_writev_impl(PyObject * module,int fd,PyObject * buffers)10219 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
10220 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
10221 {
10222     Py_ssize_t cnt;
10223     Py_ssize_t result;
10224     int async_err = 0;
10225     struct iovec *iov;
10226     Py_buffer *buf;
10227 
10228     if (!PySequence_Check(buffers)) {
10229         PyErr_SetString(PyExc_TypeError,
10230             "writev() arg 2 must be a sequence");
10231         return -1;
10232     }
10233     cnt = PySequence_Size(buffers);
10234     if (cnt < 0)
10235         return -1;
10236 
10237     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10238         return -1;
10239     }
10240 
10241     do {
10242         Py_BEGIN_ALLOW_THREADS
10243         result = writev(fd, iov, cnt);
10244         Py_END_ALLOW_THREADS
10245     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10246 
10247     iov_cleanup(iov, buf, cnt);
10248     if (result < 0 && !async_err)
10249         posix_error();
10250 
10251     return result;
10252 }
10253 #endif /* HAVE_WRITEV */
10254 
10255 
10256 #ifdef HAVE_PWRITE
10257 /*[clinic input]
10258 os.pwrite -> Py_ssize_t
10259 
10260     fd: int
10261     buffer: Py_buffer
10262     offset: Py_off_t
10263     /
10264 
10265 Write bytes to a file descriptor starting at a particular offset.
10266 
10267 Write buffer to fd, starting at offset bytes from the beginning of
10268 the file.  Returns the number of bytes writte.  Does not change the
10269 current file offset.
10270 [clinic start generated code]*/
10271 
10272 static Py_ssize_t
os_pwrite_impl(PyObject * module,int fd,Py_buffer * buffer,Py_off_t offset)10273 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
10274 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
10275 {
10276     Py_ssize_t size;
10277     int async_err = 0;
10278 
10279     do {
10280         Py_BEGIN_ALLOW_THREADS
10281         _Py_BEGIN_SUPPRESS_IPH
10282         size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
10283         _Py_END_SUPPRESS_IPH
10284         Py_END_ALLOW_THREADS
10285     } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10286 
10287     if (size < 0 && !async_err)
10288         posix_error();
10289     return size;
10290 }
10291 #endif /* HAVE_PWRITE */
10292 
10293 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
10294 /*[clinic input]
10295 os.pwritev -> Py_ssize_t
10296 
10297     fd: int
10298     buffers: object
10299     offset: Py_off_t
10300     flags: int = 0
10301     /
10302 
10303 Writes the contents of bytes-like objects to a file descriptor at a given offset.
10304 
10305 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
10306 of bytes-like objects. Buffers are processed in array order. Entire contents of first
10307 buffer is written before proceeding to second, and so on. The operating system may
10308 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
10309 This function writes the contents of each object to the file descriptor and returns
10310 the total number of bytes written.
10311 
10312 The flags argument contains a bitwise OR of zero or more of the following flags:
10313 
10314 - RWF_DSYNC
10315 - RWF_SYNC
10316 - RWF_APPEND
10317 
10318 Using non-zero flags requires Linux 4.7 or newer.
10319 [clinic start generated code]*/
10320 
10321 static Py_ssize_t
os_pwritev_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)10322 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
10323                 int flags)
10324 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
10325 {
10326     Py_ssize_t cnt;
10327     Py_ssize_t result;
10328     int async_err = 0;
10329     struct iovec *iov;
10330     Py_buffer *buf;
10331 
10332     if (!PySequence_Check(buffers)) {
10333         PyErr_SetString(PyExc_TypeError,
10334             "pwritev() arg 2 must be a sequence");
10335         return -1;
10336     }
10337 
10338     cnt = PySequence_Size(buffers);
10339     if (cnt < 0) {
10340         return -1;
10341     }
10342 
10343 #ifndef HAVE_PWRITEV2
10344     if(flags != 0) {
10345         argument_unavailable_error("pwritev2", "flags");
10346         return -1;
10347     }
10348 #endif
10349 
10350     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10351         return -1;
10352     }
10353 #ifdef HAVE_PWRITEV2
10354     do {
10355         Py_BEGIN_ALLOW_THREADS
10356         _Py_BEGIN_SUPPRESS_IPH
10357         result = pwritev2(fd, iov, cnt, offset, flags);
10358         _Py_END_SUPPRESS_IPH
10359         Py_END_ALLOW_THREADS
10360     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10361 #else
10362 
10363 #ifdef __APPLE__
10364 /* This entire function will be removed from the module dict when the API
10365  * is not available.
10366  */
10367 #pragma clang diagnostic push
10368 #pragma clang diagnostic ignored "-Wunguarded-availability"
10369 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
10370 #endif
10371     do {
10372         Py_BEGIN_ALLOW_THREADS
10373         _Py_BEGIN_SUPPRESS_IPH
10374         result = pwritev(fd, iov, cnt, offset);
10375         _Py_END_SUPPRESS_IPH
10376         Py_END_ALLOW_THREADS
10377     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10378 
10379 #ifdef __APPLE__
10380 #pragma clang diagnostic pop
10381 #endif
10382 
10383 #endif
10384 
10385     iov_cleanup(iov, buf, cnt);
10386     if (result < 0) {
10387         if (!async_err) {
10388             posix_error();
10389         }
10390         return -1;
10391     }
10392 
10393     return result;
10394 }
10395 #endif /* HAVE_PWRITEV */
10396 
10397 #ifdef HAVE_COPY_FILE_RANGE
10398 /*[clinic input]
10399 
10400 os.copy_file_range
10401     src: int
10402         Source file descriptor.
10403     dst: int
10404         Destination file descriptor.
10405     count: Py_ssize_t
10406         Number of bytes to copy.
10407     offset_src: object = None
10408         Starting offset in src.
10409     offset_dst: object = None
10410         Starting offset in dst.
10411 
10412 Copy count bytes from one file descriptor to another.
10413 
10414 If offset_src is None, then src is read from the current position;
10415 respectively for offset_dst.
10416 [clinic start generated code]*/
10417 
10418 static PyObject *
os_copy_file_range_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst)10419 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10420                         PyObject *offset_src, PyObject *offset_dst)
10421 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
10422 {
10423     off_t offset_src_val, offset_dst_val;
10424     off_t *p_offset_src = NULL;
10425     off_t *p_offset_dst = NULL;
10426     Py_ssize_t ret;
10427     int async_err = 0;
10428     /* The flags argument is provided to allow
10429      * for future extensions and currently must be to 0. */
10430     int flags = 0;
10431 
10432 
10433     if (count < 0) {
10434         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10435         return NULL;
10436     }
10437 
10438     if (offset_src != Py_None) {
10439         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10440             return NULL;
10441         }
10442         p_offset_src = &offset_src_val;
10443     }
10444 
10445     if (offset_dst != Py_None) {
10446         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10447             return NULL;
10448         }
10449         p_offset_dst = &offset_dst_val;
10450     }
10451 
10452     do {
10453         Py_BEGIN_ALLOW_THREADS
10454         ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
10455         Py_END_ALLOW_THREADS
10456     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10457 
10458     if (ret < 0) {
10459         return (!async_err) ? posix_error() : NULL;
10460     }
10461 
10462     return PyLong_FromSsize_t(ret);
10463 }
10464 #endif /* HAVE_COPY_FILE_RANGE*/
10465 
10466 #if (defined(HAVE_SPLICE) && !defined(_AIX))
10467 /*[clinic input]
10468 
10469 os.splice
10470     src: int
10471         Source file descriptor.
10472     dst: int
10473         Destination file descriptor.
10474     count: Py_ssize_t
10475         Number of bytes to copy.
10476     offset_src: object = None
10477         Starting offset in src.
10478     offset_dst: object = None
10479         Starting offset in dst.
10480     flags: unsigned_int = 0
10481         Flags to modify the semantics of the call.
10482 
10483 Transfer count bytes from one pipe to a descriptor or vice versa.
10484 
10485 If offset_src is None, then src is read from the current position;
10486 respectively for offset_dst. The offset associated to the file
10487 descriptor that refers to a pipe must be None.
10488 [clinic start generated code]*/
10489 
10490 static PyObject *
os_splice_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst,unsigned int flags)10491 os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10492                PyObject *offset_src, PyObject *offset_dst,
10493                unsigned int flags)
10494 /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
10495 {
10496     off_t offset_src_val, offset_dst_val;
10497     off_t *p_offset_src = NULL;
10498     off_t *p_offset_dst = NULL;
10499     Py_ssize_t ret;
10500     int async_err = 0;
10501 
10502     if (count < 0) {
10503         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10504         return NULL;
10505     }
10506 
10507     if (offset_src != Py_None) {
10508         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10509             return NULL;
10510         }
10511         p_offset_src = &offset_src_val;
10512     }
10513 
10514     if (offset_dst != Py_None) {
10515         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10516             return NULL;
10517         }
10518         p_offset_dst = &offset_dst_val;
10519     }
10520 
10521     do {
10522         Py_BEGIN_ALLOW_THREADS
10523         ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
10524         Py_END_ALLOW_THREADS
10525     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10526 
10527     if (ret < 0) {
10528         return (!async_err) ? posix_error() : NULL;
10529     }
10530 
10531     return PyLong_FromSsize_t(ret);
10532 }
10533 #endif /* HAVE_SPLICE*/
10534 
10535 #ifdef HAVE_MKFIFO
10536 /*[clinic input]
10537 os.mkfifo
10538 
10539     path: path_t
10540     mode: int=0o666
10541     *
10542     dir_fd: dir_fd(requires='mkfifoat')=None
10543 
10544 Create a "fifo" (a POSIX named pipe).
10545 
10546 If dir_fd is not None, it should be a file descriptor open to a directory,
10547   and path should be relative; path will then be relative to that directory.
10548 dir_fd may not be implemented on your platform.
10549   If it is unavailable, using it will raise a NotImplementedError.
10550 [clinic start generated code]*/
10551 
10552 static PyObject *
os_mkfifo_impl(PyObject * module,path_t * path,int mode,int dir_fd)10553 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
10554 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
10555 {
10556     int result;
10557     int async_err = 0;
10558 
10559     do {
10560         Py_BEGIN_ALLOW_THREADS
10561 #ifdef HAVE_MKFIFOAT
10562         if (dir_fd != DEFAULT_DIR_FD)
10563             result = mkfifoat(dir_fd, path->narrow, mode);
10564         else
10565 #endif
10566             result = mkfifo(path->narrow, mode);
10567         Py_END_ALLOW_THREADS
10568     } while (result != 0 && errno == EINTR &&
10569              !(async_err = PyErr_CheckSignals()));
10570     if (result != 0)
10571         return (!async_err) ? posix_error() : NULL;
10572 
10573     Py_RETURN_NONE;
10574 }
10575 #endif /* HAVE_MKFIFO */
10576 
10577 
10578 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
10579 /*[clinic input]
10580 os.mknod
10581 
10582     path: path_t
10583     mode: int=0o600
10584     device: dev_t=0
10585     *
10586     dir_fd: dir_fd(requires='mknodat')=None
10587 
10588 Create a node in the file system.
10589 
10590 Create a node in the file system (file, device special file or named pipe)
10591 at path.  mode specifies both the permissions to use and the
10592 type of node to be created, being combined (bitwise OR) with one of
10593 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
10594 device defines the newly created device special file (probably using
10595 os.makedev()).  Otherwise device is ignored.
10596 
10597 If dir_fd is not None, it should be a file descriptor open to a directory,
10598   and path should be relative; path will then be relative to that directory.
10599 dir_fd may not be implemented on your platform.
10600   If it is unavailable, using it will raise a NotImplementedError.
10601 [clinic start generated code]*/
10602 
10603 static PyObject *
os_mknod_impl(PyObject * module,path_t * path,int mode,dev_t device,int dir_fd)10604 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
10605               int dir_fd)
10606 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
10607 {
10608     int result;
10609     int async_err = 0;
10610 
10611     do {
10612         Py_BEGIN_ALLOW_THREADS
10613 #ifdef HAVE_MKNODAT
10614         if (dir_fd != DEFAULT_DIR_FD)
10615             result = mknodat(dir_fd, path->narrow, mode, device);
10616         else
10617 #endif
10618             result = mknod(path->narrow, mode, device);
10619         Py_END_ALLOW_THREADS
10620     } while (result != 0 && errno == EINTR &&
10621              !(async_err = PyErr_CheckSignals()));
10622     if (result != 0)
10623         return (!async_err) ? posix_error() : NULL;
10624 
10625     Py_RETURN_NONE;
10626 }
10627 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
10628 
10629 
10630 #ifdef HAVE_DEVICE_MACROS
10631 /*[clinic input]
10632 os.major -> unsigned_int
10633 
10634     device: dev_t
10635     /
10636 
10637 Extracts a device major number from a raw device number.
10638 [clinic start generated code]*/
10639 
10640 static unsigned int
os_major_impl(PyObject * module,dev_t device)10641 os_major_impl(PyObject *module, dev_t device)
10642 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
10643 {
10644     return major(device);
10645 }
10646 
10647 
10648 /*[clinic input]
10649 os.minor -> unsigned_int
10650 
10651     device: dev_t
10652     /
10653 
10654 Extracts a device minor number from a raw device number.
10655 [clinic start generated code]*/
10656 
10657 static unsigned int
os_minor_impl(PyObject * module,dev_t device)10658 os_minor_impl(PyObject *module, dev_t device)
10659 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10660 {
10661     return minor(device);
10662 }
10663 
10664 
10665 /*[clinic input]
10666 os.makedev -> dev_t
10667 
10668     major: int
10669     minor: int
10670     /
10671 
10672 Composes a raw device number from the major and minor device numbers.
10673 [clinic start generated code]*/
10674 
10675 static dev_t
os_makedev_impl(PyObject * module,int major,int minor)10676 os_makedev_impl(PyObject *module, int major, int minor)
10677 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10678 {
10679     return makedev(major, minor);
10680 }
10681 #endif /* HAVE_DEVICE_MACROS */
10682 
10683 
10684 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10685 /*[clinic input]
10686 os.ftruncate
10687 
10688     fd: int
10689     length: Py_off_t
10690     /
10691 
10692 Truncate a file, specified by file descriptor, to a specific length.
10693 [clinic start generated code]*/
10694 
10695 static PyObject *
os_ftruncate_impl(PyObject * module,int fd,Py_off_t length)10696 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10697 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10698 {
10699     int result;
10700     int async_err = 0;
10701 
10702     if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10703         return NULL;
10704     }
10705 
10706     do {
10707         Py_BEGIN_ALLOW_THREADS
10708         _Py_BEGIN_SUPPRESS_IPH
10709 #ifdef MS_WINDOWS
10710         result = _chsize_s(fd, length);
10711 #else
10712         result = ftruncate(fd, length);
10713 #endif
10714         _Py_END_SUPPRESS_IPH
10715         Py_END_ALLOW_THREADS
10716     } while (result != 0 && errno == EINTR &&
10717              !(async_err = PyErr_CheckSignals()));
10718     if (result != 0)
10719         return (!async_err) ? posix_error() : NULL;
10720     Py_RETURN_NONE;
10721 }
10722 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10723 
10724 
10725 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10726 /*[clinic input]
10727 os.truncate
10728     path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10729     length: Py_off_t
10730 
10731 Truncate a file, specified by path, to a specific length.
10732 
10733 On some platforms, path may also be specified as an open file descriptor.
10734   If this functionality is unavailable, using it raises an exception.
10735 [clinic start generated code]*/
10736 
10737 static PyObject *
os_truncate_impl(PyObject * module,path_t * path,Py_off_t length)10738 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10739 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10740 {
10741     int result;
10742 #ifdef MS_WINDOWS
10743     int fd;
10744 #endif
10745 
10746     if (path->fd != -1)
10747         return os_ftruncate_impl(module, path->fd, length);
10748 
10749     if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10750         return NULL;
10751     }
10752 
10753     Py_BEGIN_ALLOW_THREADS
10754     _Py_BEGIN_SUPPRESS_IPH
10755 #ifdef MS_WINDOWS
10756     fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10757     if (fd < 0)
10758         result = -1;
10759     else {
10760         result = _chsize_s(fd, length);
10761         close(fd);
10762         if (result < 0)
10763             errno = result;
10764     }
10765 #else
10766     result = truncate(path->narrow, length);
10767 #endif
10768     _Py_END_SUPPRESS_IPH
10769     Py_END_ALLOW_THREADS
10770     if (result < 0)
10771         return posix_path_error(path);
10772 
10773     Py_RETURN_NONE;
10774 }
10775 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10776 
10777 
10778 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10779    and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10780    defined, which is the case in Python on AIX. AIX bug report:
10781    http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10782 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10783 #  define POSIX_FADVISE_AIX_BUG
10784 #endif
10785 
10786 
10787 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10788 /*[clinic input]
10789 os.posix_fallocate
10790 
10791     fd: int
10792     offset: Py_off_t
10793     length: Py_off_t
10794     /
10795 
10796 Ensure a file has allocated at least a particular number of bytes on disk.
10797 
10798 Ensure that the file specified by fd encompasses a range of bytes
10799 starting at offset bytes from the beginning and continuing for length bytes.
10800 [clinic start generated code]*/
10801 
10802 static PyObject *
os_posix_fallocate_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length)10803 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10804                         Py_off_t length)
10805 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10806 {
10807     int result;
10808     int async_err = 0;
10809 
10810     do {
10811         Py_BEGIN_ALLOW_THREADS
10812         result = posix_fallocate(fd, offset, length);
10813         Py_END_ALLOW_THREADS
10814     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10815 
10816     if (result == 0)
10817         Py_RETURN_NONE;
10818 
10819     if (async_err)
10820         return NULL;
10821 
10822     errno = result;
10823     return posix_error();
10824 }
10825 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
10826 
10827 
10828 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
10829 /*[clinic input]
10830 os.posix_fadvise
10831 
10832     fd: int
10833     offset: Py_off_t
10834     length: Py_off_t
10835     advice: int
10836     /
10837 
10838 Announce an intention to access data in a specific pattern.
10839 
10840 Announce an intention to access data in a specific pattern, thus allowing
10841 the kernel to make optimizations.
10842 The advice applies to the region of the file specified by fd starting at
10843 offset and continuing for length bytes.
10844 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
10845 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
10846 POSIX_FADV_DONTNEED.
10847 [clinic start generated code]*/
10848 
10849 static PyObject *
os_posix_fadvise_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length,int advice)10850 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
10851                       Py_off_t length, int advice)
10852 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
10853 {
10854     int result;
10855     int async_err = 0;
10856 
10857     do {
10858         Py_BEGIN_ALLOW_THREADS
10859         result = posix_fadvise(fd, offset, length, advice);
10860         Py_END_ALLOW_THREADS
10861     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10862 
10863     if (result == 0)
10864         Py_RETURN_NONE;
10865 
10866     if (async_err)
10867         return NULL;
10868 
10869     errno = result;
10870     return posix_error();
10871 }
10872 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
10873 
10874 
10875 #ifdef MS_WINDOWS
10876 static PyObject*
win32_putenv(PyObject * name,PyObject * value)10877 win32_putenv(PyObject *name, PyObject *value)
10878 {
10879     /* Search from index 1 because on Windows starting '=' is allowed for
10880        defining hidden environment variables. */
10881     if (PyUnicode_GET_LENGTH(name) == 0 ||
10882         PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
10883     {
10884         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10885         return NULL;
10886     }
10887     PyObject *unicode;
10888     if (value != NULL) {
10889         unicode = PyUnicode_FromFormat("%U=%U", name, value);
10890     }
10891     else {
10892         unicode = PyUnicode_FromFormat("%U=", name);
10893     }
10894     if (unicode == NULL) {
10895         return NULL;
10896     }
10897 
10898     Py_ssize_t size;
10899     /* PyUnicode_AsWideCharString() rejects embedded null characters */
10900     wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
10901     Py_DECREF(unicode);
10902 
10903     if (env == NULL) {
10904         return NULL;
10905     }
10906     if (size > _MAX_ENV) {
10907         PyErr_Format(PyExc_ValueError,
10908                      "the environment variable is longer than %u characters",
10909                      _MAX_ENV);
10910         PyMem_Free(env);
10911         return NULL;
10912     }
10913 
10914     /* _wputenv() and SetEnvironmentVariableW() update the environment in the
10915        Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
10916        and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
10917 
10918        Prefer _wputenv() to be compatible with C libraries using CRT
10919        variables and CRT functions using these variables (ex: getenv()). */
10920     int err = _wputenv(env);
10921     PyMem_Free(env);
10922 
10923     if (err) {
10924         posix_error();
10925         return NULL;
10926     }
10927 
10928     Py_RETURN_NONE;
10929 }
10930 #endif
10931 
10932 
10933 #ifdef MS_WINDOWS
10934 /*[clinic input]
10935 os.putenv
10936 
10937     name: unicode
10938     value: unicode
10939     /
10940 
10941 Change or add an environment variable.
10942 [clinic start generated code]*/
10943 
10944 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10945 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10946 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
10947 {
10948     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10949         return NULL;
10950     }
10951     return win32_putenv(name, value);
10952 }
10953 #else
10954 /*[clinic input]
10955 os.putenv
10956 
10957     name: FSConverter
10958     value: FSConverter
10959     /
10960 
10961 Change or add an environment variable.
10962 [clinic start generated code]*/
10963 
10964 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10965 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10966 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
10967 {
10968     const char *name_string = PyBytes_AS_STRING(name);
10969     const char *value_string = PyBytes_AS_STRING(value);
10970 
10971     if (strchr(name_string, '=') != NULL) {
10972         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10973         return NULL;
10974     }
10975 
10976     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10977         return NULL;
10978     }
10979 
10980     if (setenv(name_string, value_string, 1)) {
10981         return posix_error();
10982     }
10983     Py_RETURN_NONE;
10984 }
10985 #endif  /* !defined(MS_WINDOWS) */
10986 
10987 
10988 #ifdef MS_WINDOWS
10989 /*[clinic input]
10990 os.unsetenv
10991     name: unicode
10992     /
10993 
10994 Delete an environment variable.
10995 [clinic start generated code]*/
10996 
10997 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)10998 os_unsetenv_impl(PyObject *module, PyObject *name)
10999 /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
11000 {
11001     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11002         return NULL;
11003     }
11004     return win32_putenv(name, NULL);
11005 }
11006 #else
11007 /*[clinic input]
11008 os.unsetenv
11009     name: FSConverter
11010     /
11011 
11012 Delete an environment variable.
11013 [clinic start generated code]*/
11014 
11015 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)11016 os_unsetenv_impl(PyObject *module, PyObject *name)
11017 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
11018 {
11019     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11020         return NULL;
11021     }
11022 #ifdef HAVE_BROKEN_UNSETENV
11023     unsetenv(PyBytes_AS_STRING(name));
11024 #else
11025     int err = unsetenv(PyBytes_AS_STRING(name));
11026     if (err) {
11027         return posix_error();
11028     }
11029 #endif
11030 
11031     Py_RETURN_NONE;
11032 }
11033 #endif /* !MS_WINDOWS */
11034 
11035 
11036 /*[clinic input]
11037 os.strerror
11038 
11039     code: int
11040     /
11041 
11042 Translate an error code to a message string.
11043 [clinic start generated code]*/
11044 
11045 static PyObject *
os_strerror_impl(PyObject * module,int code)11046 os_strerror_impl(PyObject *module, int code)
11047 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
11048 {
11049     char *message = strerror(code);
11050     if (message == NULL) {
11051         PyErr_SetString(PyExc_ValueError,
11052                         "strerror() argument out of range");
11053         return NULL;
11054     }
11055     return PyUnicode_DecodeLocale(message, "surrogateescape");
11056 }
11057 
11058 
11059 #ifdef HAVE_SYS_WAIT_H
11060 #ifdef WCOREDUMP
11061 /*[clinic input]
11062 os.WCOREDUMP -> bool
11063 
11064     status: int
11065     /
11066 
11067 Return True if the process returning status was dumped to a core file.
11068 [clinic start generated code]*/
11069 
11070 static int
os_WCOREDUMP_impl(PyObject * module,int status)11071 os_WCOREDUMP_impl(PyObject *module, int status)
11072 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
11073 {
11074     WAIT_TYPE wait_status;
11075     WAIT_STATUS_INT(wait_status) = status;
11076     return WCOREDUMP(wait_status);
11077 }
11078 #endif /* WCOREDUMP */
11079 
11080 
11081 #ifdef WIFCONTINUED
11082 /*[clinic input]
11083 os.WIFCONTINUED -> bool
11084 
11085     status: int
11086 
11087 Return True if a particular process was continued from a job control stop.
11088 
11089 Return True if the process returning status was continued from a
11090 job control stop.
11091 [clinic start generated code]*/
11092 
11093 static int
os_WIFCONTINUED_impl(PyObject * module,int status)11094 os_WIFCONTINUED_impl(PyObject *module, int status)
11095 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
11096 {
11097     WAIT_TYPE wait_status;
11098     WAIT_STATUS_INT(wait_status) = status;
11099     return WIFCONTINUED(wait_status);
11100 }
11101 #endif /* WIFCONTINUED */
11102 
11103 
11104 #ifdef WIFSTOPPED
11105 /*[clinic input]
11106 os.WIFSTOPPED -> bool
11107 
11108     status: int
11109 
11110 Return True if the process returning status was stopped.
11111 [clinic start generated code]*/
11112 
11113 static int
os_WIFSTOPPED_impl(PyObject * module,int status)11114 os_WIFSTOPPED_impl(PyObject *module, int status)
11115 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
11116 {
11117     WAIT_TYPE wait_status;
11118     WAIT_STATUS_INT(wait_status) = status;
11119     return WIFSTOPPED(wait_status);
11120 }
11121 #endif /* WIFSTOPPED */
11122 
11123 
11124 #ifdef WIFSIGNALED
11125 /*[clinic input]
11126 os.WIFSIGNALED -> bool
11127 
11128     status: int
11129 
11130 Return True if the process returning status was terminated by a signal.
11131 [clinic start generated code]*/
11132 
11133 static int
os_WIFSIGNALED_impl(PyObject * module,int status)11134 os_WIFSIGNALED_impl(PyObject *module, int status)
11135 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
11136 {
11137     WAIT_TYPE wait_status;
11138     WAIT_STATUS_INT(wait_status) = status;
11139     return WIFSIGNALED(wait_status);
11140 }
11141 #endif /* WIFSIGNALED */
11142 
11143 
11144 #ifdef WIFEXITED
11145 /*[clinic input]
11146 os.WIFEXITED -> bool
11147 
11148     status: int
11149 
11150 Return True if the process returning status exited via the exit() system call.
11151 [clinic start generated code]*/
11152 
11153 static int
os_WIFEXITED_impl(PyObject * module,int status)11154 os_WIFEXITED_impl(PyObject *module, int status)
11155 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
11156 {
11157     WAIT_TYPE wait_status;
11158     WAIT_STATUS_INT(wait_status) = status;
11159     return WIFEXITED(wait_status);
11160 }
11161 #endif /* WIFEXITED */
11162 
11163 
11164 #ifdef WEXITSTATUS
11165 /*[clinic input]
11166 os.WEXITSTATUS -> int
11167 
11168     status: int
11169 
11170 Return the process return code from status.
11171 [clinic start generated code]*/
11172 
11173 static int
os_WEXITSTATUS_impl(PyObject * module,int status)11174 os_WEXITSTATUS_impl(PyObject *module, int status)
11175 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
11176 {
11177     WAIT_TYPE wait_status;
11178     WAIT_STATUS_INT(wait_status) = status;
11179     return WEXITSTATUS(wait_status);
11180 }
11181 #endif /* WEXITSTATUS */
11182 
11183 
11184 #ifdef WTERMSIG
11185 /*[clinic input]
11186 os.WTERMSIG -> int
11187 
11188     status: int
11189 
11190 Return the signal that terminated the process that provided the status value.
11191 [clinic start generated code]*/
11192 
11193 static int
os_WTERMSIG_impl(PyObject * module,int status)11194 os_WTERMSIG_impl(PyObject *module, int status)
11195 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
11196 {
11197     WAIT_TYPE wait_status;
11198     WAIT_STATUS_INT(wait_status) = status;
11199     return WTERMSIG(wait_status);
11200 }
11201 #endif /* WTERMSIG */
11202 
11203 
11204 #ifdef WSTOPSIG
11205 /*[clinic input]
11206 os.WSTOPSIG -> int
11207 
11208     status: int
11209 
11210 Return the signal that stopped the process that provided the status value.
11211 [clinic start generated code]*/
11212 
11213 static int
os_WSTOPSIG_impl(PyObject * module,int status)11214 os_WSTOPSIG_impl(PyObject *module, int status)
11215 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
11216 {
11217     WAIT_TYPE wait_status;
11218     WAIT_STATUS_INT(wait_status) = status;
11219     return WSTOPSIG(wait_status);
11220 }
11221 #endif /* WSTOPSIG */
11222 #endif /* HAVE_SYS_WAIT_H */
11223 
11224 
11225 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
11226 #ifdef _SCO_DS
11227 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
11228    needed definitions in sys/statvfs.h */
11229 #define _SVID3
11230 #endif
11231 #include <sys/statvfs.h>
11232 
11233 static PyObject*
_pystatvfs_fromstructstatvfs(PyObject * module,struct statvfs st)11234 _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
11235     PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
11236     PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
11237     if (v == NULL)
11238         return NULL;
11239 
11240 #if !defined(HAVE_LARGEFILE_SUPPORT)
11241     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11242     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11243     PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
11244     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
11245     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
11246     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
11247     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
11248     PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
11249     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11250     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11251 #else
11252     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11253     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11254     PyStructSequence_SET_ITEM(v, 2,
11255                               PyLong_FromLongLong((long long) st.f_blocks));
11256     PyStructSequence_SET_ITEM(v, 3,
11257                               PyLong_FromLongLong((long long) st.f_bfree));
11258     PyStructSequence_SET_ITEM(v, 4,
11259                               PyLong_FromLongLong((long long) st.f_bavail));
11260     PyStructSequence_SET_ITEM(v, 5,
11261                               PyLong_FromLongLong((long long) st.f_files));
11262     PyStructSequence_SET_ITEM(v, 6,
11263                               PyLong_FromLongLong((long long) st.f_ffree));
11264     PyStructSequence_SET_ITEM(v, 7,
11265                               PyLong_FromLongLong((long long) st.f_favail));
11266     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11267     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11268 #endif
11269 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
11270  * (issue #32390). */
11271 #if defined(_AIX) && defined(_ALL_SOURCE)
11272     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
11273 #else
11274     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
11275 #endif
11276     if (PyErr_Occurred()) {
11277         Py_DECREF(v);
11278         return NULL;
11279     }
11280 
11281     return v;
11282 }
11283 
11284 
11285 /*[clinic input]
11286 os.fstatvfs
11287     fd: int
11288     /
11289 
11290 Perform an fstatvfs system call on the given fd.
11291 
11292 Equivalent to statvfs(fd).
11293 [clinic start generated code]*/
11294 
11295 static PyObject *
os_fstatvfs_impl(PyObject * module,int fd)11296 os_fstatvfs_impl(PyObject *module, int fd)
11297 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
11298 {
11299     int result;
11300     int async_err = 0;
11301     struct statvfs st;
11302 
11303     do {
11304         Py_BEGIN_ALLOW_THREADS
11305         result = fstatvfs(fd, &st);
11306         Py_END_ALLOW_THREADS
11307     } while (result != 0 && errno == EINTR &&
11308              !(async_err = PyErr_CheckSignals()));
11309     if (result != 0)
11310         return (!async_err) ? posix_error() : NULL;
11311 
11312     return _pystatvfs_fromstructstatvfs(module, st);
11313 }
11314 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
11315 
11316 
11317 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
11318 #include <sys/statvfs.h>
11319 /*[clinic input]
11320 os.statvfs
11321 
11322     path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
11323 
11324 Perform a statvfs system call on the given path.
11325 
11326 path may always be specified as a string.
11327 On some platforms, path may also be specified as an open file descriptor.
11328   If this functionality is unavailable, using it raises an exception.
11329 [clinic start generated code]*/
11330 
11331 static PyObject *
os_statvfs_impl(PyObject * module,path_t * path)11332 os_statvfs_impl(PyObject *module, path_t *path)
11333 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
11334 {
11335     int result;
11336     struct statvfs st;
11337 
11338     Py_BEGIN_ALLOW_THREADS
11339 #ifdef HAVE_FSTATVFS
11340     if (path->fd != -1) {
11341         result = fstatvfs(path->fd, &st);
11342     }
11343     else
11344 #endif
11345         result = statvfs(path->narrow, &st);
11346     Py_END_ALLOW_THREADS
11347 
11348     if (result) {
11349         return path_error(path);
11350     }
11351 
11352     return _pystatvfs_fromstructstatvfs(module, st);
11353 }
11354 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
11355 
11356 
11357 #ifdef MS_WINDOWS
11358 /*[clinic input]
11359 os._getdiskusage
11360 
11361     path: path_t
11362 
11363 Return disk usage statistics about the given path as a (total, free) tuple.
11364 [clinic start generated code]*/
11365 
11366 static PyObject *
os__getdiskusage_impl(PyObject * module,path_t * path)11367 os__getdiskusage_impl(PyObject *module, path_t *path)
11368 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
11369 {
11370     BOOL retval;
11371     ULARGE_INTEGER _, total, free;
11372     DWORD err = 0;
11373 
11374     Py_BEGIN_ALLOW_THREADS
11375     retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
11376     Py_END_ALLOW_THREADS
11377     if (retval == 0) {
11378         if (GetLastError() == ERROR_DIRECTORY) {
11379             wchar_t *dir_path = NULL;
11380 
11381             dir_path = PyMem_New(wchar_t, path->length + 1);
11382             if (dir_path == NULL) {
11383                 return PyErr_NoMemory();
11384             }
11385 
11386             wcscpy_s(dir_path, path->length + 1, path->wide);
11387 
11388             if (_dirnameW(dir_path) != -1) {
11389                 Py_BEGIN_ALLOW_THREADS
11390                 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
11391                 Py_END_ALLOW_THREADS
11392             }
11393             /* Record the last error in case it's modified by PyMem_Free. */
11394             err = GetLastError();
11395             PyMem_Free(dir_path);
11396             if (retval) {
11397                 goto success;
11398             }
11399         }
11400         return PyErr_SetFromWindowsErr(err);
11401     }
11402 
11403 success:
11404     return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
11405 }
11406 #endif /* MS_WINDOWS */
11407 
11408 
11409 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
11410  * It maps strings representing configuration variable names to
11411  * integer values, allowing those functions to be called with the
11412  * magic names instead of polluting the module's namespace with tons of
11413  * rarely-used constants.  There are three separate tables that use
11414  * these definitions.
11415  *
11416  * This code is always included, even if none of the interfaces that
11417  * need it are included.  The #if hackery needed to avoid it would be
11418  * sufficiently pervasive that it's not worth the loss of readability.
11419  */
11420 struct constdef {
11421     const char *name;
11422     int value;
11423 };
11424 
11425 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)11426 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
11427               size_t tablesize)
11428 {
11429     if (PyLong_Check(arg)) {
11430         int value = _PyLong_AsInt(arg);
11431         if (value == -1 && PyErr_Occurred())
11432             return 0;
11433         *valuep = value;
11434         return 1;
11435     }
11436     else {
11437         /* look up the value in the table using a binary search */
11438         size_t lo = 0;
11439         size_t mid;
11440         size_t hi = tablesize;
11441         int cmp;
11442         const char *confname;
11443         if (!PyUnicode_Check(arg)) {
11444             PyErr_SetString(PyExc_TypeError,
11445                 "configuration names must be strings or integers");
11446             return 0;
11447         }
11448         confname = PyUnicode_AsUTF8(arg);
11449         if (confname == NULL)
11450             return 0;
11451         while (lo < hi) {
11452             mid = (lo + hi) / 2;
11453             cmp = strcmp(confname, table[mid].name);
11454             if (cmp < 0)
11455                 hi = mid;
11456             else if (cmp > 0)
11457                 lo = mid + 1;
11458             else {
11459                 *valuep = table[mid].value;
11460                 return 1;
11461             }
11462         }
11463         PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
11464         return 0;
11465     }
11466 }
11467 
11468 
11469 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11470 static struct constdef  posix_constants_pathconf[] = {
11471 #ifdef _PC_ABI_AIO_XFER_MAX
11472     {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
11473 #endif
11474 #ifdef _PC_ABI_ASYNC_IO
11475     {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
11476 #endif
11477 #ifdef _PC_ASYNC_IO
11478     {"PC_ASYNC_IO",     _PC_ASYNC_IO},
11479 #endif
11480 #ifdef _PC_CHOWN_RESTRICTED
11481     {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
11482 #endif
11483 #ifdef _PC_FILESIZEBITS
11484     {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
11485 #endif
11486 #ifdef _PC_LAST
11487     {"PC_LAST", _PC_LAST},
11488 #endif
11489 #ifdef _PC_LINK_MAX
11490     {"PC_LINK_MAX",     _PC_LINK_MAX},
11491 #endif
11492 #ifdef _PC_MAX_CANON
11493     {"PC_MAX_CANON",    _PC_MAX_CANON},
11494 #endif
11495 #ifdef _PC_MAX_INPUT
11496     {"PC_MAX_INPUT",    _PC_MAX_INPUT},
11497 #endif
11498 #ifdef _PC_NAME_MAX
11499     {"PC_NAME_MAX",     _PC_NAME_MAX},
11500 #endif
11501 #ifdef _PC_NO_TRUNC
11502     {"PC_NO_TRUNC",     _PC_NO_TRUNC},
11503 #endif
11504 #ifdef _PC_PATH_MAX
11505     {"PC_PATH_MAX",     _PC_PATH_MAX},
11506 #endif
11507 #ifdef _PC_PIPE_BUF
11508     {"PC_PIPE_BUF",     _PC_PIPE_BUF},
11509 #endif
11510 #ifdef _PC_PRIO_IO
11511     {"PC_PRIO_IO",      _PC_PRIO_IO},
11512 #endif
11513 #ifdef _PC_SOCK_MAXBUF
11514     {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
11515 #endif
11516 #ifdef _PC_SYNC_IO
11517     {"PC_SYNC_IO",      _PC_SYNC_IO},
11518 #endif
11519 #ifdef _PC_VDISABLE
11520     {"PC_VDISABLE",     _PC_VDISABLE},
11521 #endif
11522 #ifdef _PC_ACL_ENABLED
11523     {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
11524 #endif
11525 #ifdef _PC_MIN_HOLE_SIZE
11526     {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
11527 #endif
11528 #ifdef _PC_ALLOC_SIZE_MIN
11529     {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
11530 #endif
11531 #ifdef _PC_REC_INCR_XFER_SIZE
11532     {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
11533 #endif
11534 #ifdef _PC_REC_MAX_XFER_SIZE
11535     {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
11536 #endif
11537 #ifdef _PC_REC_MIN_XFER_SIZE
11538     {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
11539 #endif
11540 #ifdef _PC_REC_XFER_ALIGN
11541     {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
11542 #endif
11543 #ifdef _PC_SYMLINK_MAX
11544     {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
11545 #endif
11546 #ifdef _PC_XATTR_ENABLED
11547     {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
11548 #endif
11549 #ifdef _PC_XATTR_EXISTS
11550     {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
11551 #endif
11552 #ifdef _PC_TIMESTAMP_RESOLUTION
11553     {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
11554 #endif
11555 };
11556 
11557 static int
conv_path_confname(PyObject * arg,int * valuep)11558 conv_path_confname(PyObject *arg, int *valuep)
11559 {
11560     return conv_confname(arg, valuep, posix_constants_pathconf,
11561                          sizeof(posix_constants_pathconf)
11562                            / sizeof(struct constdef));
11563 }
11564 #endif
11565 
11566 
11567 #ifdef HAVE_FPATHCONF
11568 /*[clinic input]
11569 os.fpathconf -> long
11570 
11571     fd: fildes
11572     name: path_confname
11573     /
11574 
11575 Return the configuration limit name for the file descriptor fd.
11576 
11577 If there is no limit, return -1.
11578 [clinic start generated code]*/
11579 
11580 static long
os_fpathconf_impl(PyObject * module,int fd,int name)11581 os_fpathconf_impl(PyObject *module, int fd, int name)
11582 /*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
11583 {
11584     long limit;
11585 
11586     errno = 0;
11587     limit = fpathconf(fd, name);
11588     if (limit == -1 && errno != 0)
11589         posix_error();
11590 
11591     return limit;
11592 }
11593 #endif /* HAVE_FPATHCONF */
11594 
11595 
11596 #ifdef HAVE_PATHCONF
11597 /*[clinic input]
11598 os.pathconf -> long
11599     path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
11600     name: path_confname
11601 
11602 Return the configuration limit name for the file or directory path.
11603 
11604 If there is no limit, return -1.
11605 On some platforms, path may also be specified as an open file descriptor.
11606   If this functionality is unavailable, using it raises an exception.
11607 [clinic start generated code]*/
11608 
11609 static long
os_pathconf_impl(PyObject * module,path_t * path,int name)11610 os_pathconf_impl(PyObject *module, path_t *path, int name)
11611 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
11612 {
11613     long limit;
11614 
11615     errno = 0;
11616 #ifdef HAVE_FPATHCONF
11617     if (path->fd != -1)
11618         limit = fpathconf(path->fd, name);
11619     else
11620 #endif
11621         limit = pathconf(path->narrow, name);
11622     if (limit == -1 && errno != 0) {
11623         if (errno == EINVAL)
11624             /* could be a path or name problem */
11625             posix_error();
11626         else
11627             path_error(path);
11628     }
11629 
11630     return limit;
11631 }
11632 #endif /* HAVE_PATHCONF */
11633 
11634 #ifdef HAVE_CONFSTR
11635 static struct constdef posix_constants_confstr[] = {
11636 #ifdef _CS_ARCHITECTURE
11637     {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
11638 #endif
11639 #ifdef _CS_GNU_LIBC_VERSION
11640     {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
11641 #endif
11642 #ifdef _CS_GNU_LIBPTHREAD_VERSION
11643     {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
11644 #endif
11645 #ifdef _CS_HOSTNAME
11646     {"CS_HOSTNAME",     _CS_HOSTNAME},
11647 #endif
11648 #ifdef _CS_HW_PROVIDER
11649     {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
11650 #endif
11651 #ifdef _CS_HW_SERIAL
11652     {"CS_HW_SERIAL",    _CS_HW_SERIAL},
11653 #endif
11654 #ifdef _CS_INITTAB_NAME
11655     {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11656 #endif
11657 #ifdef _CS_LFS64_CFLAGS
11658     {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11659 #endif
11660 #ifdef _CS_LFS64_LDFLAGS
11661     {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
11662 #endif
11663 #ifdef _CS_LFS64_LIBS
11664     {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
11665 #endif
11666 #ifdef _CS_LFS64_LINTFLAGS
11667     {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
11668 #endif
11669 #ifdef _CS_LFS_CFLAGS
11670     {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
11671 #endif
11672 #ifdef _CS_LFS_LDFLAGS
11673     {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
11674 #endif
11675 #ifdef _CS_LFS_LIBS
11676     {"CS_LFS_LIBS",     _CS_LFS_LIBS},
11677 #endif
11678 #ifdef _CS_LFS_LINTFLAGS
11679     {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
11680 #endif
11681 #ifdef _CS_MACHINE
11682     {"CS_MACHINE",      _CS_MACHINE},
11683 #endif
11684 #ifdef _CS_PATH
11685     {"CS_PATH", _CS_PATH},
11686 #endif
11687 #ifdef _CS_RELEASE
11688     {"CS_RELEASE",      _CS_RELEASE},
11689 #endif
11690 #ifdef _CS_SRPC_DOMAIN
11691     {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
11692 #endif
11693 #ifdef _CS_SYSNAME
11694     {"CS_SYSNAME",      _CS_SYSNAME},
11695 #endif
11696 #ifdef _CS_VERSION
11697     {"CS_VERSION",      _CS_VERSION},
11698 #endif
11699 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11700     {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
11701 #endif
11702 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11703     {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
11704 #endif
11705 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11706     {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
11707 #endif
11708 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11709     {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11710 #endif
11711 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11712     {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11713 #endif
11714 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11715     {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11716 #endif
11717 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11718     {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
11719 #endif
11720 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11721     {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11722 #endif
11723 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11724     {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
11725 #endif
11726 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11727     {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
11728 #endif
11729 #ifdef _CS_XBS5_LP64_OFF64_LIBS
11730     {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11731 #endif
11732 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11733     {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
11734 #endif
11735 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11736     {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11737 #endif
11738 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11739     {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11740 #endif
11741 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11742     {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
11743 #endif
11744 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11745     {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11746 #endif
11747 #ifdef _MIPS_CS_AVAIL_PROCESSORS
11748     {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
11749 #endif
11750 #ifdef _MIPS_CS_BASE
11751     {"MIPS_CS_BASE",    _MIPS_CS_BASE},
11752 #endif
11753 #ifdef _MIPS_CS_HOSTID
11754     {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
11755 #endif
11756 #ifdef _MIPS_CS_HW_NAME
11757     {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11758 #endif
11759 #ifdef _MIPS_CS_NUM_PROCESSORS
11760     {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
11761 #endif
11762 #ifdef _MIPS_CS_OSREL_MAJ
11763     {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
11764 #endif
11765 #ifdef _MIPS_CS_OSREL_MIN
11766     {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
11767 #endif
11768 #ifdef _MIPS_CS_OSREL_PATCH
11769     {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
11770 #endif
11771 #ifdef _MIPS_CS_OS_NAME
11772     {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11773 #endif
11774 #ifdef _MIPS_CS_OS_PROVIDER
11775     {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
11776 #endif
11777 #ifdef _MIPS_CS_PROCESSORS
11778     {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
11779 #endif
11780 #ifdef _MIPS_CS_SERIAL
11781     {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
11782 #endif
11783 #ifdef _MIPS_CS_VENDOR
11784     {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
11785 #endif
11786 };
11787 
11788 static int
conv_confstr_confname(PyObject * arg,int * valuep)11789 conv_confstr_confname(PyObject *arg, int *valuep)
11790 {
11791     return conv_confname(arg, valuep, posix_constants_confstr,
11792                          sizeof(posix_constants_confstr)
11793                            / sizeof(struct constdef));
11794 }
11795 
11796 
11797 /*[clinic input]
11798 os.confstr
11799 
11800     name: confstr_confname
11801     /
11802 
11803 Return a string-valued system configuration variable.
11804 [clinic start generated code]*/
11805 
11806 static PyObject *
os_confstr_impl(PyObject * module,int name)11807 os_confstr_impl(PyObject *module, int name)
11808 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11809 {
11810     PyObject *result = NULL;
11811     char buffer[255];
11812     size_t len;
11813 
11814     errno = 0;
11815     len = confstr(name, buffer, sizeof(buffer));
11816     if (len == 0) {
11817         if (errno) {
11818             posix_error();
11819             return NULL;
11820         }
11821         else {
11822             Py_RETURN_NONE;
11823         }
11824     }
11825 
11826     if (len >= sizeof(buffer)) {
11827         size_t len2;
11828         char *buf = PyMem_Malloc(len);
11829         if (buf == NULL)
11830             return PyErr_NoMemory();
11831         len2 = confstr(name, buf, len);
11832         assert(len == len2);
11833         result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11834         PyMem_Free(buf);
11835     }
11836     else
11837         result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11838     return result;
11839 }
11840 #endif /* HAVE_CONFSTR */
11841 
11842 
11843 #ifdef HAVE_SYSCONF
11844 static struct constdef posix_constants_sysconf[] = {
11845 #ifdef _SC_2_CHAR_TERM
11846     {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
11847 #endif
11848 #ifdef _SC_2_C_BIND
11849     {"SC_2_C_BIND",     _SC_2_C_BIND},
11850 #endif
11851 #ifdef _SC_2_C_DEV
11852     {"SC_2_C_DEV",      _SC_2_C_DEV},
11853 #endif
11854 #ifdef _SC_2_C_VERSION
11855     {"SC_2_C_VERSION",  _SC_2_C_VERSION},
11856 #endif
11857 #ifdef _SC_2_FORT_DEV
11858     {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
11859 #endif
11860 #ifdef _SC_2_FORT_RUN
11861     {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
11862 #endif
11863 #ifdef _SC_2_LOCALEDEF
11864     {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
11865 #endif
11866 #ifdef _SC_2_SW_DEV
11867     {"SC_2_SW_DEV",     _SC_2_SW_DEV},
11868 #endif
11869 #ifdef _SC_2_UPE
11870     {"SC_2_UPE",        _SC_2_UPE},
11871 #endif
11872 #ifdef _SC_2_VERSION
11873     {"SC_2_VERSION",    _SC_2_VERSION},
11874 #endif
11875 #ifdef _SC_ABI_ASYNCHRONOUS_IO
11876     {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
11877 #endif
11878 #ifdef _SC_ACL
11879     {"SC_ACL",  _SC_ACL},
11880 #endif
11881 #ifdef _SC_AIO_LISTIO_MAX
11882     {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
11883 #endif
11884 #ifdef _SC_AIO_MAX
11885     {"SC_AIO_MAX",      _SC_AIO_MAX},
11886 #endif
11887 #ifdef _SC_AIO_PRIO_DELTA_MAX
11888     {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
11889 #endif
11890 #ifdef _SC_ARG_MAX
11891     {"SC_ARG_MAX",      _SC_ARG_MAX},
11892 #endif
11893 #ifdef _SC_ASYNCHRONOUS_IO
11894     {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
11895 #endif
11896 #ifdef _SC_ATEXIT_MAX
11897     {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
11898 #endif
11899 #ifdef _SC_AUDIT
11900     {"SC_AUDIT",        _SC_AUDIT},
11901 #endif
11902 #ifdef _SC_AVPHYS_PAGES
11903     {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
11904 #endif
11905 #ifdef _SC_BC_BASE_MAX
11906     {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
11907 #endif
11908 #ifdef _SC_BC_DIM_MAX
11909     {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
11910 #endif
11911 #ifdef _SC_BC_SCALE_MAX
11912     {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
11913 #endif
11914 #ifdef _SC_BC_STRING_MAX
11915     {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
11916 #endif
11917 #ifdef _SC_CAP
11918     {"SC_CAP",  _SC_CAP},
11919 #endif
11920 #ifdef _SC_CHARCLASS_NAME_MAX
11921     {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
11922 #endif
11923 #ifdef _SC_CHAR_BIT
11924     {"SC_CHAR_BIT",     _SC_CHAR_BIT},
11925 #endif
11926 #ifdef _SC_CHAR_MAX
11927     {"SC_CHAR_MAX",     _SC_CHAR_MAX},
11928 #endif
11929 #ifdef _SC_CHAR_MIN
11930     {"SC_CHAR_MIN",     _SC_CHAR_MIN},
11931 #endif
11932 #ifdef _SC_CHILD_MAX
11933     {"SC_CHILD_MAX",    _SC_CHILD_MAX},
11934 #endif
11935 #ifdef _SC_CLK_TCK
11936     {"SC_CLK_TCK",      _SC_CLK_TCK},
11937 #endif
11938 #ifdef _SC_COHER_BLKSZ
11939     {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
11940 #endif
11941 #ifdef _SC_COLL_WEIGHTS_MAX
11942     {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
11943 #endif
11944 #ifdef _SC_DCACHE_ASSOC
11945     {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
11946 #endif
11947 #ifdef _SC_DCACHE_BLKSZ
11948     {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
11949 #endif
11950 #ifdef _SC_DCACHE_LINESZ
11951     {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
11952 #endif
11953 #ifdef _SC_DCACHE_SZ
11954     {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
11955 #endif
11956 #ifdef _SC_DCACHE_TBLKSZ
11957     {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
11958 #endif
11959 #ifdef _SC_DELAYTIMER_MAX
11960     {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
11961 #endif
11962 #ifdef _SC_EQUIV_CLASS_MAX
11963     {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
11964 #endif
11965 #ifdef _SC_EXPR_NEST_MAX
11966     {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
11967 #endif
11968 #ifdef _SC_FSYNC
11969     {"SC_FSYNC",        _SC_FSYNC},
11970 #endif
11971 #ifdef _SC_GETGR_R_SIZE_MAX
11972     {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
11973 #endif
11974 #ifdef _SC_GETPW_R_SIZE_MAX
11975     {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
11976 #endif
11977 #ifdef _SC_ICACHE_ASSOC
11978     {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
11979 #endif
11980 #ifdef _SC_ICACHE_BLKSZ
11981     {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
11982 #endif
11983 #ifdef _SC_ICACHE_LINESZ
11984     {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
11985 #endif
11986 #ifdef _SC_ICACHE_SZ
11987     {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
11988 #endif
11989 #ifdef _SC_INF
11990     {"SC_INF",  _SC_INF},
11991 #endif
11992 #ifdef _SC_INT_MAX
11993     {"SC_INT_MAX",      _SC_INT_MAX},
11994 #endif
11995 #ifdef _SC_INT_MIN
11996     {"SC_INT_MIN",      _SC_INT_MIN},
11997 #endif
11998 #ifdef _SC_IOV_MAX
11999     {"SC_IOV_MAX",      _SC_IOV_MAX},
12000 #endif
12001 #ifdef _SC_IP_SECOPTS
12002     {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
12003 #endif
12004 #ifdef _SC_JOB_CONTROL
12005     {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
12006 #endif
12007 #ifdef _SC_KERN_POINTERS
12008     {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
12009 #endif
12010 #ifdef _SC_KERN_SIM
12011     {"SC_KERN_SIM",     _SC_KERN_SIM},
12012 #endif
12013 #ifdef _SC_LINE_MAX
12014     {"SC_LINE_MAX",     _SC_LINE_MAX},
12015 #endif
12016 #ifdef _SC_LOGIN_NAME_MAX
12017     {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
12018 #endif
12019 #ifdef _SC_LOGNAME_MAX
12020     {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
12021 #endif
12022 #ifdef _SC_LONG_BIT
12023     {"SC_LONG_BIT",     _SC_LONG_BIT},
12024 #endif
12025 #ifdef _SC_MAC
12026     {"SC_MAC",  _SC_MAC},
12027 #endif
12028 #ifdef _SC_MAPPED_FILES
12029     {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
12030 #endif
12031 #ifdef _SC_MAXPID
12032     {"SC_MAXPID",       _SC_MAXPID},
12033 #endif
12034 #ifdef _SC_MB_LEN_MAX
12035     {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
12036 #endif
12037 #ifdef _SC_MEMLOCK
12038     {"SC_MEMLOCK",      _SC_MEMLOCK},
12039 #endif
12040 #ifdef _SC_MEMLOCK_RANGE
12041     {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
12042 #endif
12043 #ifdef _SC_MEMORY_PROTECTION
12044     {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
12045 #endif
12046 #ifdef _SC_MESSAGE_PASSING
12047     {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
12048 #endif
12049 #ifdef _SC_MMAP_FIXED_ALIGNMENT
12050     {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
12051 #endif
12052 #ifdef _SC_MQ_OPEN_MAX
12053     {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
12054 #endif
12055 #ifdef _SC_MQ_PRIO_MAX
12056     {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
12057 #endif
12058 #ifdef _SC_NACLS_MAX
12059     {"SC_NACLS_MAX",    _SC_NACLS_MAX},
12060 #endif
12061 #ifdef _SC_NGROUPS_MAX
12062     {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
12063 #endif
12064 #ifdef _SC_NL_ARGMAX
12065     {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
12066 #endif
12067 #ifdef _SC_NL_LANGMAX
12068     {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
12069 #endif
12070 #ifdef _SC_NL_MSGMAX
12071     {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
12072 #endif
12073 #ifdef _SC_NL_NMAX
12074     {"SC_NL_NMAX",      _SC_NL_NMAX},
12075 #endif
12076 #ifdef _SC_NL_SETMAX
12077     {"SC_NL_SETMAX",    _SC_NL_SETMAX},
12078 #endif
12079 #ifdef _SC_NL_TEXTMAX
12080     {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
12081 #endif
12082 #ifdef _SC_NPROCESSORS_CONF
12083     {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
12084 #endif
12085 #ifdef _SC_NPROCESSORS_ONLN
12086     {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
12087 #endif
12088 #ifdef _SC_NPROC_CONF
12089     {"SC_NPROC_CONF",   _SC_NPROC_CONF},
12090 #endif
12091 #ifdef _SC_NPROC_ONLN
12092     {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
12093 #endif
12094 #ifdef _SC_NZERO
12095     {"SC_NZERO",        _SC_NZERO},
12096 #endif
12097 #ifdef _SC_OPEN_MAX
12098     {"SC_OPEN_MAX",     _SC_OPEN_MAX},
12099 #endif
12100 #ifdef _SC_PAGESIZE
12101     {"SC_PAGESIZE",     _SC_PAGESIZE},
12102 #endif
12103 #ifdef _SC_PAGE_SIZE
12104     {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
12105 #endif
12106 #ifdef _SC_AIX_REALMEM
12107     {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
12108 #endif
12109 #ifdef _SC_PASS_MAX
12110     {"SC_PASS_MAX",     _SC_PASS_MAX},
12111 #endif
12112 #ifdef _SC_PHYS_PAGES
12113     {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
12114 #endif
12115 #ifdef _SC_PII
12116     {"SC_PII",  _SC_PII},
12117 #endif
12118 #ifdef _SC_PII_INTERNET
12119     {"SC_PII_INTERNET", _SC_PII_INTERNET},
12120 #endif
12121 #ifdef _SC_PII_INTERNET_DGRAM
12122     {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
12123 #endif
12124 #ifdef _SC_PII_INTERNET_STREAM
12125     {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
12126 #endif
12127 #ifdef _SC_PII_OSI
12128     {"SC_PII_OSI",      _SC_PII_OSI},
12129 #endif
12130 #ifdef _SC_PII_OSI_CLTS
12131     {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
12132 #endif
12133 #ifdef _SC_PII_OSI_COTS
12134     {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
12135 #endif
12136 #ifdef _SC_PII_OSI_M
12137     {"SC_PII_OSI_M",    _SC_PII_OSI_M},
12138 #endif
12139 #ifdef _SC_PII_SOCKET
12140     {"SC_PII_SOCKET",   _SC_PII_SOCKET},
12141 #endif
12142 #ifdef _SC_PII_XTI
12143     {"SC_PII_XTI",      _SC_PII_XTI},
12144 #endif
12145 #ifdef _SC_POLL
12146     {"SC_POLL", _SC_POLL},
12147 #endif
12148 #ifdef _SC_PRIORITIZED_IO
12149     {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
12150 #endif
12151 #ifdef _SC_PRIORITY_SCHEDULING
12152     {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
12153 #endif
12154 #ifdef _SC_REALTIME_SIGNALS
12155     {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
12156 #endif
12157 #ifdef _SC_RE_DUP_MAX
12158     {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
12159 #endif
12160 #ifdef _SC_RTSIG_MAX
12161     {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
12162 #endif
12163 #ifdef _SC_SAVED_IDS
12164     {"SC_SAVED_IDS",    _SC_SAVED_IDS},
12165 #endif
12166 #ifdef _SC_SCHAR_MAX
12167     {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
12168 #endif
12169 #ifdef _SC_SCHAR_MIN
12170     {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
12171 #endif
12172 #ifdef _SC_SELECT
12173     {"SC_SELECT",       _SC_SELECT},
12174 #endif
12175 #ifdef _SC_SEMAPHORES
12176     {"SC_SEMAPHORES",   _SC_SEMAPHORES},
12177 #endif
12178 #ifdef _SC_SEM_NSEMS_MAX
12179     {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
12180 #endif
12181 #ifdef _SC_SEM_VALUE_MAX
12182     {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
12183 #endif
12184 #ifdef _SC_SHARED_MEMORY_OBJECTS
12185     {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
12186 #endif
12187 #ifdef _SC_SHRT_MAX
12188     {"SC_SHRT_MAX",     _SC_SHRT_MAX},
12189 #endif
12190 #ifdef _SC_SHRT_MIN
12191     {"SC_SHRT_MIN",     _SC_SHRT_MIN},
12192 #endif
12193 #ifdef _SC_SIGQUEUE_MAX
12194     {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
12195 #endif
12196 #ifdef _SC_SIGRT_MAX
12197     {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
12198 #endif
12199 #ifdef _SC_SIGRT_MIN
12200     {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
12201 #endif
12202 #ifdef _SC_SOFTPOWER
12203     {"SC_SOFTPOWER",    _SC_SOFTPOWER},
12204 #endif
12205 #ifdef _SC_SPLIT_CACHE
12206     {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
12207 #endif
12208 #ifdef _SC_SSIZE_MAX
12209     {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
12210 #endif
12211 #ifdef _SC_STACK_PROT
12212     {"SC_STACK_PROT",   _SC_STACK_PROT},
12213 #endif
12214 #ifdef _SC_STREAM_MAX
12215     {"SC_STREAM_MAX",   _SC_STREAM_MAX},
12216 #endif
12217 #ifdef _SC_SYNCHRONIZED_IO
12218     {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
12219 #endif
12220 #ifdef _SC_THREADS
12221     {"SC_THREADS",      _SC_THREADS},
12222 #endif
12223 #ifdef _SC_THREAD_ATTR_STACKADDR
12224     {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
12225 #endif
12226 #ifdef _SC_THREAD_ATTR_STACKSIZE
12227     {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
12228 #endif
12229 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
12230     {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
12231 #endif
12232 #ifdef _SC_THREAD_KEYS_MAX
12233     {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
12234 #endif
12235 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
12236     {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
12237 #endif
12238 #ifdef _SC_THREAD_PRIO_INHERIT
12239     {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
12240 #endif
12241 #ifdef _SC_THREAD_PRIO_PROTECT
12242     {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
12243 #endif
12244 #ifdef _SC_THREAD_PROCESS_SHARED
12245     {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
12246 #endif
12247 #ifdef _SC_THREAD_SAFE_FUNCTIONS
12248     {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
12249 #endif
12250 #ifdef _SC_THREAD_STACK_MIN
12251     {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
12252 #endif
12253 #ifdef _SC_THREAD_THREADS_MAX
12254     {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
12255 #endif
12256 #ifdef _SC_TIMERS
12257     {"SC_TIMERS",       _SC_TIMERS},
12258 #endif
12259 #ifdef _SC_TIMER_MAX
12260     {"SC_TIMER_MAX",    _SC_TIMER_MAX},
12261 #endif
12262 #ifdef _SC_TTY_NAME_MAX
12263     {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
12264 #endif
12265 #ifdef _SC_TZNAME_MAX
12266     {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
12267 #endif
12268 #ifdef _SC_T_IOV_MAX
12269     {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
12270 #endif
12271 #ifdef _SC_UCHAR_MAX
12272     {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
12273 #endif
12274 #ifdef _SC_UINT_MAX
12275     {"SC_UINT_MAX",     _SC_UINT_MAX},
12276 #endif
12277 #ifdef _SC_UIO_MAXIOV
12278     {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
12279 #endif
12280 #ifdef _SC_ULONG_MAX
12281     {"SC_ULONG_MAX",    _SC_ULONG_MAX},
12282 #endif
12283 #ifdef _SC_USHRT_MAX
12284     {"SC_USHRT_MAX",    _SC_USHRT_MAX},
12285 #endif
12286 #ifdef _SC_VERSION
12287     {"SC_VERSION",      _SC_VERSION},
12288 #endif
12289 #ifdef _SC_WORD_BIT
12290     {"SC_WORD_BIT",     _SC_WORD_BIT},
12291 #endif
12292 #ifdef _SC_XBS5_ILP32_OFF32
12293     {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
12294 #endif
12295 #ifdef _SC_XBS5_ILP32_OFFBIG
12296     {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
12297 #endif
12298 #ifdef _SC_XBS5_LP64_OFF64
12299     {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
12300 #endif
12301 #ifdef _SC_XBS5_LPBIG_OFFBIG
12302     {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
12303 #endif
12304 #ifdef _SC_XOPEN_CRYPT
12305     {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
12306 #endif
12307 #ifdef _SC_XOPEN_ENH_I18N
12308     {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
12309 #endif
12310 #ifdef _SC_XOPEN_LEGACY
12311     {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
12312 #endif
12313 #ifdef _SC_XOPEN_REALTIME
12314     {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
12315 #endif
12316 #ifdef _SC_XOPEN_REALTIME_THREADS
12317     {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
12318 #endif
12319 #ifdef _SC_XOPEN_SHM
12320     {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
12321 #endif
12322 #ifdef _SC_XOPEN_UNIX
12323     {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
12324 #endif
12325 #ifdef _SC_XOPEN_VERSION
12326     {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
12327 #endif
12328 #ifdef _SC_XOPEN_XCU_VERSION
12329     {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
12330 #endif
12331 #ifdef _SC_XOPEN_XPG2
12332     {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
12333 #endif
12334 #ifdef _SC_XOPEN_XPG3
12335     {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
12336 #endif
12337 #ifdef _SC_XOPEN_XPG4
12338     {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
12339 #endif
12340 };
12341 
12342 static int
conv_sysconf_confname(PyObject * arg,int * valuep)12343 conv_sysconf_confname(PyObject *arg, int *valuep)
12344 {
12345     return conv_confname(arg, valuep, posix_constants_sysconf,
12346                          sizeof(posix_constants_sysconf)
12347                            / sizeof(struct constdef));
12348 }
12349 
12350 
12351 /*[clinic input]
12352 os.sysconf -> long
12353     name: sysconf_confname
12354     /
12355 
12356 Return an integer-valued system configuration variable.
12357 [clinic start generated code]*/
12358 
12359 static long
os_sysconf_impl(PyObject * module,int name)12360 os_sysconf_impl(PyObject *module, int name)
12361 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
12362 {
12363     long value;
12364 
12365     errno = 0;
12366     value = sysconf(name);
12367     if (value == -1 && errno != 0)
12368         posix_error();
12369     return value;
12370 }
12371 #endif /* HAVE_SYSCONF */
12372 
12373 
12374 /* This code is used to ensure that the tables of configuration value names
12375  * are in sorted order as required by conv_confname(), and also to build
12376  * the exported dictionaries that are used to publish information about the
12377  * names available on the host platform.
12378  *
12379  * Sorting the table at runtime ensures that the table is properly ordered
12380  * when used, even for platforms we're not able to test on.  It also makes
12381  * it easier to add additional entries to the tables.
12382  */
12383 
12384 static int
cmp_constdefs(const void * v1,const void * v2)12385 cmp_constdefs(const void *v1,  const void *v2)
12386 {
12387     const struct constdef *c1 =
12388     (const struct constdef *) v1;
12389     const struct constdef *c2 =
12390     (const struct constdef *) v2;
12391 
12392     return strcmp(c1->name, c2->name);
12393 }
12394 
12395 static int
setup_confname_table(struct constdef * table,size_t tablesize,const char * tablename,PyObject * module)12396 setup_confname_table(struct constdef *table, size_t tablesize,
12397                      const char *tablename, PyObject *module)
12398 {
12399     PyObject *d = NULL;
12400     size_t i;
12401 
12402     qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
12403     d = PyDict_New();
12404     if (d == NULL)
12405         return -1;
12406 
12407     for (i=0; i < tablesize; ++i) {
12408         PyObject *o = PyLong_FromLong(table[i].value);
12409         if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
12410             Py_XDECREF(o);
12411             Py_DECREF(d);
12412             return -1;
12413         }
12414         Py_DECREF(o);
12415     }
12416     return PyModule_AddObject(module, tablename, d);
12417 }
12418 
12419 /* Return -1 on failure, 0 on success. */
12420 static int
setup_confname_tables(PyObject * module)12421 setup_confname_tables(PyObject *module)
12422 {
12423 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12424     if (setup_confname_table(posix_constants_pathconf,
12425                              sizeof(posix_constants_pathconf)
12426                                / sizeof(struct constdef),
12427                              "pathconf_names", module))
12428         return -1;
12429 #endif
12430 #ifdef HAVE_CONFSTR
12431     if (setup_confname_table(posix_constants_confstr,
12432                              sizeof(posix_constants_confstr)
12433                                / sizeof(struct constdef),
12434                              "confstr_names", module))
12435         return -1;
12436 #endif
12437 #ifdef HAVE_SYSCONF
12438     if (setup_confname_table(posix_constants_sysconf,
12439                              sizeof(posix_constants_sysconf)
12440                                / sizeof(struct constdef),
12441                              "sysconf_names", module))
12442         return -1;
12443 #endif
12444     return 0;
12445 }
12446 
12447 
12448 /*[clinic input]
12449 os.abort
12450 
12451 Abort the interpreter immediately.
12452 
12453 This function 'dumps core' or otherwise fails in the hardest way possible
12454 on the hosting operating system.  This function never returns.
12455 [clinic start generated code]*/
12456 
12457 static PyObject *
os_abort_impl(PyObject * module)12458 os_abort_impl(PyObject *module)
12459 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
12460 {
12461     abort();
12462     /*NOTREACHED*/
12463 #ifndef __clang__
12464     /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
12465        GCC emits a warning without "return NULL;" (compiler bug?), but Clang
12466        is smarter and emits a warning on the return. */
12467     Py_FatalError("abort() called from Python code didn't abort!");
12468     return NULL;
12469 #endif
12470 }
12471 
12472 #ifdef MS_WINDOWS
12473 /* Grab ShellExecute dynamically from shell32 */
12474 static int has_ShellExecute = -1;
12475 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
12476                                               LPCWSTR, INT);
12477 static int
check_ShellExecute()12478 check_ShellExecute()
12479 {
12480     HINSTANCE hShell32;
12481 
12482     /* only recheck */
12483     if (-1 == has_ShellExecute) {
12484         Py_BEGIN_ALLOW_THREADS
12485         /* Security note: this call is not vulnerable to "DLL hijacking".
12486            SHELL32 is part of "KnownDLLs" and so Windows always load
12487            the system SHELL32.DLL, even if there is another SHELL32.DLL
12488            in the DLL search path. */
12489         hShell32 = LoadLibraryW(L"SHELL32");
12490         if (hShell32) {
12491             *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
12492                                             "ShellExecuteW");
12493             has_ShellExecute = Py_ShellExecuteW != NULL;
12494         } else {
12495             has_ShellExecute = 0;
12496         }
12497         Py_END_ALLOW_THREADS
12498     }
12499     return has_ShellExecute;
12500 }
12501 
12502 
12503 /*[clinic input]
12504 os.startfile
12505     filepath: path_t
12506     operation: Py_UNICODE = NULL
12507     arguments: Py_UNICODE = NULL
12508     cwd: path_t(nullable=True) = None
12509     show_cmd: int = 1
12510 
12511 Start a file with its associated application.
12512 
12513 When "operation" is not specified or "open", this acts like
12514 double-clicking the file in Explorer, or giving the file name as an
12515 argument to the DOS "start" command: the file is opened with whatever
12516 application (if any) its extension is associated.
12517 When another "operation" is given, it specifies what should be done with
12518 the file.  A typical operation is "print".
12519 
12520 "arguments" is passed to the application, but should be omitted if the
12521 file is a document.
12522 
12523 "cwd" is the working directory for the operation. If "filepath" is
12524 relative, it will be resolved against this directory. This argument
12525 should usually be an absolute path.
12526 
12527 "show_cmd" can be used to override the recommended visibility option.
12528 See the Windows ShellExecute documentation for values.
12529 
12530 startfile returns as soon as the associated application is launched.
12531 There is no option to wait for the application to close, and no way
12532 to retrieve the application's exit status.
12533 
12534 The filepath is relative to the current directory.  If you want to use
12535 an absolute path, make sure the first character is not a slash ("/");
12536 the underlying Win32 ShellExecute function doesn't work if it is.
12537 [clinic start generated code]*/
12538 
12539 static PyObject *
os_startfile_impl(PyObject * module,path_t * filepath,const Py_UNICODE * operation,const Py_UNICODE * arguments,path_t * cwd,int show_cmd)12540 os_startfile_impl(PyObject *module, path_t *filepath,
12541                   const Py_UNICODE *operation, const Py_UNICODE *arguments,
12542                   path_t *cwd, int show_cmd)
12543 /*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/
12544 {
12545     HINSTANCE rc;
12546 
12547     if(!check_ShellExecute()) {
12548         /* If the OS doesn't have ShellExecute, return a
12549            NotImplementedError. */
12550         return PyErr_Format(PyExc_NotImplementedError,
12551             "startfile not available on this platform");
12552     }
12553 
12554     if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
12555         return NULL;
12556     }
12557     if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
12558                     arguments, cwd->object ? cwd->object : Py_None,
12559                     show_cmd) < 0) {
12560         return NULL;
12561     }
12562 
12563     Py_BEGIN_ALLOW_THREADS
12564     rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
12565                           arguments, cwd->wide, show_cmd);
12566     Py_END_ALLOW_THREADS
12567 
12568     if (rc <= (HINSTANCE)32) {
12569         win32_error_object("startfile", filepath->object);
12570         return NULL;
12571     }
12572     Py_RETURN_NONE;
12573 }
12574 #endif /* MS_WINDOWS */
12575 
12576 
12577 #ifdef HAVE_GETLOADAVG
12578 /*[clinic input]
12579 os.getloadavg
12580 
12581 Return average recent system load information.
12582 
12583 Return the number of processes in the system run queue averaged over
12584 the last 1, 5, and 15 minutes as a tuple of three floats.
12585 Raises OSError if the load average was unobtainable.
12586 [clinic start generated code]*/
12587 
12588 static PyObject *
os_getloadavg_impl(PyObject * module)12589 os_getloadavg_impl(PyObject *module)
12590 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
12591 {
12592     double loadavg[3];
12593     if (getloadavg(loadavg, 3)!=3) {
12594         PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
12595         return NULL;
12596     } else
12597         return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
12598 }
12599 #endif /* HAVE_GETLOADAVG */
12600 
12601 
12602 /*[clinic input]
12603 os.device_encoding
12604     fd: int
12605 
12606 Return a string describing the encoding of a terminal's file descriptor.
12607 
12608 The file descriptor must be attached to a terminal.
12609 If the device is not a terminal, return None.
12610 [clinic start generated code]*/
12611 
12612 static PyObject *
os_device_encoding_impl(PyObject * module,int fd)12613 os_device_encoding_impl(PyObject *module, int fd)
12614 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
12615 {
12616     return _Py_device_encoding(fd);
12617 }
12618 
12619 
12620 #ifdef HAVE_SETRESUID
12621 /*[clinic input]
12622 os.setresuid
12623 
12624     ruid: uid_t
12625     euid: uid_t
12626     suid: uid_t
12627     /
12628 
12629 Set the current process's real, effective, and saved user ids.
12630 [clinic start generated code]*/
12631 
12632 static PyObject *
os_setresuid_impl(PyObject * module,uid_t ruid,uid_t euid,uid_t suid)12633 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
12634 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
12635 {
12636     if (setresuid(ruid, euid, suid) < 0)
12637         return posix_error();
12638     Py_RETURN_NONE;
12639 }
12640 #endif /* HAVE_SETRESUID */
12641 
12642 
12643 #ifdef HAVE_SETRESGID
12644 /*[clinic input]
12645 os.setresgid
12646 
12647     rgid: gid_t
12648     egid: gid_t
12649     sgid: gid_t
12650     /
12651 
12652 Set the current process's real, effective, and saved group ids.
12653 [clinic start generated code]*/
12654 
12655 static PyObject *
os_setresgid_impl(PyObject * module,gid_t rgid,gid_t egid,gid_t sgid)12656 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
12657 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
12658 {
12659     if (setresgid(rgid, egid, sgid) < 0)
12660         return posix_error();
12661     Py_RETURN_NONE;
12662 }
12663 #endif /* HAVE_SETRESGID */
12664 
12665 
12666 #ifdef HAVE_GETRESUID
12667 /*[clinic input]
12668 os.getresuid
12669 
12670 Return a tuple of the current process's real, effective, and saved user ids.
12671 [clinic start generated code]*/
12672 
12673 static PyObject *
os_getresuid_impl(PyObject * module)12674 os_getresuid_impl(PyObject *module)
12675 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12676 {
12677     uid_t ruid, euid, suid;
12678     if (getresuid(&ruid, &euid, &suid) < 0)
12679         return posix_error();
12680     return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12681                                   _PyLong_FromUid(euid),
12682                                   _PyLong_FromUid(suid));
12683 }
12684 #endif /* HAVE_GETRESUID */
12685 
12686 
12687 #ifdef HAVE_GETRESGID
12688 /*[clinic input]
12689 os.getresgid
12690 
12691 Return a tuple of the current process's real, effective, and saved group ids.
12692 [clinic start generated code]*/
12693 
12694 static PyObject *
os_getresgid_impl(PyObject * module)12695 os_getresgid_impl(PyObject *module)
12696 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12697 {
12698     gid_t rgid, egid, sgid;
12699     if (getresgid(&rgid, &egid, &sgid) < 0)
12700         return posix_error();
12701     return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12702                                   _PyLong_FromGid(egid),
12703                                   _PyLong_FromGid(sgid));
12704 }
12705 #endif /* HAVE_GETRESGID */
12706 
12707 
12708 #ifdef USE_XATTRS
12709 /*[clinic input]
12710 os.getxattr
12711 
12712     path: path_t(allow_fd=True)
12713     attribute: path_t
12714     *
12715     follow_symlinks: bool = True
12716 
12717 Return the value of extended attribute attribute on path.
12718 
12719 path may be either a string, a path-like object, or an open file descriptor.
12720 If follow_symlinks is False, and the last element of the path is a symbolic
12721   link, getxattr will examine the symbolic link itself instead of the file
12722   the link points to.
12723 
12724 [clinic start generated code]*/
12725 
12726 static PyObject *
os_getxattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12727 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12728                  int follow_symlinks)
12729 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12730 {
12731     Py_ssize_t i;
12732     PyObject *buffer = NULL;
12733 
12734     if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12735         return NULL;
12736 
12737     if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12738         return NULL;
12739     }
12740 
12741     for (i = 0; ; i++) {
12742         void *ptr;
12743         ssize_t result;
12744         static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12745         Py_ssize_t buffer_size = buffer_sizes[i];
12746         if (!buffer_size) {
12747             path_error(path);
12748             return NULL;
12749         }
12750         buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12751         if (!buffer)
12752             return NULL;
12753         ptr = PyBytes_AS_STRING(buffer);
12754 
12755         Py_BEGIN_ALLOW_THREADS;
12756         if (path->fd >= 0)
12757             result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12758         else if (follow_symlinks)
12759             result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12760         else
12761             result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12762         Py_END_ALLOW_THREADS;
12763 
12764         if (result < 0) {
12765             Py_DECREF(buffer);
12766             if (errno == ERANGE)
12767                 continue;
12768             path_error(path);
12769             return NULL;
12770         }
12771 
12772         if (result != buffer_size) {
12773             /* Can only shrink. */
12774             _PyBytes_Resize(&buffer, result);
12775         }
12776         break;
12777     }
12778 
12779     return buffer;
12780 }
12781 
12782 
12783 /*[clinic input]
12784 os.setxattr
12785 
12786     path: path_t(allow_fd=True)
12787     attribute: path_t
12788     value: Py_buffer
12789     flags: int = 0
12790     *
12791     follow_symlinks: bool = True
12792 
12793 Set extended attribute attribute on path to value.
12794 
12795 path may be either a string, a path-like object,  or an open file descriptor.
12796 If follow_symlinks is False, and the last element of the path is a symbolic
12797   link, setxattr will modify the symbolic link itself instead of the file
12798   the link points to.
12799 
12800 [clinic start generated code]*/
12801 
12802 static PyObject *
os_setxattr_impl(PyObject * module,path_t * path,path_t * attribute,Py_buffer * value,int flags,int follow_symlinks)12803 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12804                  Py_buffer *value, int flags, int follow_symlinks)
12805 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12806 {
12807     ssize_t result;
12808 
12809     if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12810         return NULL;
12811 
12812     if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12813                     value->buf, value->len, flags) < 0) {
12814         return NULL;
12815     }
12816 
12817     Py_BEGIN_ALLOW_THREADS;
12818     if (path->fd > -1)
12819         result = fsetxattr(path->fd, attribute->narrow,
12820                            value->buf, value->len, flags);
12821     else if (follow_symlinks)
12822         result = setxattr(path->narrow, attribute->narrow,
12823                            value->buf, value->len, flags);
12824     else
12825         result = lsetxattr(path->narrow, attribute->narrow,
12826                            value->buf, value->len, flags);
12827     Py_END_ALLOW_THREADS;
12828 
12829     if (result) {
12830         path_error(path);
12831         return NULL;
12832     }
12833 
12834     Py_RETURN_NONE;
12835 }
12836 
12837 
12838 /*[clinic input]
12839 os.removexattr
12840 
12841     path: path_t(allow_fd=True)
12842     attribute: path_t
12843     *
12844     follow_symlinks: bool = True
12845 
12846 Remove extended attribute attribute on path.
12847 
12848 path may be either a string, a path-like object, or an open file descriptor.
12849 If follow_symlinks is False, and the last element of the path is a symbolic
12850   link, removexattr will modify the symbolic link itself instead of the file
12851   the link points to.
12852 
12853 [clinic start generated code]*/
12854 
12855 static PyObject *
os_removexattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12856 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
12857                     int follow_symlinks)
12858 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
12859 {
12860     ssize_t result;
12861 
12862     if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
12863         return NULL;
12864 
12865     if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
12866         return NULL;
12867     }
12868 
12869     Py_BEGIN_ALLOW_THREADS;
12870     if (path->fd > -1)
12871         result = fremovexattr(path->fd, attribute->narrow);
12872     else if (follow_symlinks)
12873         result = removexattr(path->narrow, attribute->narrow);
12874     else
12875         result = lremovexattr(path->narrow, attribute->narrow);
12876     Py_END_ALLOW_THREADS;
12877 
12878     if (result) {
12879         return path_error(path);
12880     }
12881 
12882     Py_RETURN_NONE;
12883 }
12884 
12885 
12886 /*[clinic input]
12887 os.listxattr
12888 
12889     path: path_t(allow_fd=True, nullable=True) = None
12890     *
12891     follow_symlinks: bool = True
12892 
12893 Return a list of extended attributes on path.
12894 
12895 path may be either None, a string, a path-like object, or an open file descriptor.
12896 if path is None, listxattr will examine the current directory.
12897 If follow_symlinks is False, and the last element of the path is a symbolic
12898   link, listxattr will examine the symbolic link itself instead of the file
12899   the link points to.
12900 [clinic start generated code]*/
12901 
12902 static PyObject *
os_listxattr_impl(PyObject * module,path_t * path,int follow_symlinks)12903 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
12904 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
12905 {
12906     Py_ssize_t i;
12907     PyObject *result = NULL;
12908     const char *name;
12909     char *buffer = NULL;
12910 
12911     if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
12912         goto exit;
12913 
12914     if (PySys_Audit("os.listxattr", "(O)",
12915                     path->object ? path->object : Py_None) < 0) {
12916         return NULL;
12917     }
12918 
12919     name = path->narrow ? path->narrow : ".";
12920 
12921     for (i = 0; ; i++) {
12922         const char *start, *trace, *end;
12923         ssize_t length;
12924         static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
12925         Py_ssize_t buffer_size = buffer_sizes[i];
12926         if (!buffer_size) {
12927             /* ERANGE */
12928             path_error(path);
12929             break;
12930         }
12931         buffer = PyMem_Malloc(buffer_size);
12932         if (!buffer) {
12933             PyErr_NoMemory();
12934             break;
12935         }
12936 
12937         Py_BEGIN_ALLOW_THREADS;
12938         if (path->fd > -1)
12939             length = flistxattr(path->fd, buffer, buffer_size);
12940         else if (follow_symlinks)
12941             length = listxattr(name, buffer, buffer_size);
12942         else
12943             length = llistxattr(name, buffer, buffer_size);
12944         Py_END_ALLOW_THREADS;
12945 
12946         if (length < 0) {
12947             if (errno == ERANGE) {
12948                 PyMem_Free(buffer);
12949                 buffer = NULL;
12950                 continue;
12951             }
12952             path_error(path);
12953             break;
12954         }
12955 
12956         result = PyList_New(0);
12957         if (!result) {
12958             goto exit;
12959         }
12960 
12961         end = buffer + length;
12962         for (trace = start = buffer; trace != end; trace++) {
12963             if (!*trace) {
12964                 int error;
12965                 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
12966                                                                  trace - start);
12967                 if (!attribute) {
12968                     Py_DECREF(result);
12969                     result = NULL;
12970                     goto exit;
12971                 }
12972                 error = PyList_Append(result, attribute);
12973                 Py_DECREF(attribute);
12974                 if (error) {
12975                     Py_DECREF(result);
12976                     result = NULL;
12977                     goto exit;
12978                 }
12979                 start = trace + 1;
12980             }
12981         }
12982     break;
12983     }
12984 exit:
12985     if (buffer)
12986         PyMem_Free(buffer);
12987     return result;
12988 }
12989 #endif /* USE_XATTRS */
12990 
12991 
12992 /*[clinic input]
12993 os.urandom
12994 
12995     size: Py_ssize_t
12996     /
12997 
12998 Return a bytes object containing random bytes suitable for cryptographic use.
12999 [clinic start generated code]*/
13000 
13001 static PyObject *
os_urandom_impl(PyObject * module,Py_ssize_t size)13002 os_urandom_impl(PyObject *module, Py_ssize_t size)
13003 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
13004 {
13005     PyObject *bytes;
13006     int result;
13007 
13008     if (size < 0)
13009         return PyErr_Format(PyExc_ValueError,
13010                             "negative argument not allowed");
13011     bytes = PyBytes_FromStringAndSize(NULL, size);
13012     if (bytes == NULL)
13013         return NULL;
13014 
13015     result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
13016     if (result == -1) {
13017         Py_DECREF(bytes);
13018         return NULL;
13019     }
13020     return bytes;
13021 }
13022 
13023 #ifdef HAVE_MEMFD_CREATE
13024 /*[clinic input]
13025 os.memfd_create
13026 
13027     name: FSConverter
13028     flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
13029 
13030 [clinic start generated code]*/
13031 
13032 static PyObject *
os_memfd_create_impl(PyObject * module,PyObject * name,unsigned int flags)13033 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
13034 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
13035 {
13036     int fd;
13037     const char *bytes = PyBytes_AS_STRING(name);
13038     Py_BEGIN_ALLOW_THREADS
13039     fd = memfd_create(bytes, flags);
13040     Py_END_ALLOW_THREADS
13041     if (fd == -1) {
13042         return PyErr_SetFromErrno(PyExc_OSError);
13043     }
13044     return PyLong_FromLong(fd);
13045 }
13046 #endif
13047 
13048 #ifdef HAVE_EVENTFD
13049 /*[clinic input]
13050 os.eventfd
13051 
13052     initval: unsigned_int
13053     flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
13054 
13055 Creates and returns an event notification file descriptor.
13056 [clinic start generated code]*/
13057 
13058 static PyObject *
os_eventfd_impl(PyObject * module,unsigned int initval,int flags)13059 os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
13060 /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
13061 
13062 {
13063     /* initval is limited to uint32_t, internal counter is uint64_t */
13064     int fd;
13065     Py_BEGIN_ALLOW_THREADS
13066     fd = eventfd(initval, flags);
13067     Py_END_ALLOW_THREADS
13068     if (fd == -1) {
13069         return PyErr_SetFromErrno(PyExc_OSError);
13070     }
13071     return PyLong_FromLong(fd);
13072 }
13073 
13074 /*[clinic input]
13075 os.eventfd_read
13076 
13077     fd: fildes
13078 
13079 Read eventfd value
13080 [clinic start generated code]*/
13081 
13082 static PyObject *
os_eventfd_read_impl(PyObject * module,int fd)13083 os_eventfd_read_impl(PyObject *module, int fd)
13084 /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
13085 {
13086     eventfd_t value;
13087     int result;
13088     Py_BEGIN_ALLOW_THREADS
13089     result = eventfd_read(fd, &value);
13090     Py_END_ALLOW_THREADS
13091     if (result == -1) {
13092         return PyErr_SetFromErrno(PyExc_OSError);
13093     }
13094     return PyLong_FromUnsignedLongLong(value);
13095 }
13096 
13097 /*[clinic input]
13098 os.eventfd_write
13099 
13100     fd: fildes
13101     value: unsigned_long_long
13102 
13103 Write eventfd value.
13104 [clinic start generated code]*/
13105 
13106 static PyObject *
os_eventfd_write_impl(PyObject * module,int fd,unsigned long long value)13107 os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
13108 /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
13109 {
13110     int result;
13111     Py_BEGIN_ALLOW_THREADS
13112     result = eventfd_write(fd, value);
13113     Py_END_ALLOW_THREADS
13114     if (result == -1) {
13115         return PyErr_SetFromErrno(PyExc_OSError);
13116     }
13117     Py_RETURN_NONE;
13118 }
13119 #endif  /* HAVE_EVENTFD */
13120 
13121 /* Terminal size querying */
13122 
13123 PyDoc_STRVAR(TerminalSize_docstring,
13124     "A tuple of (columns, lines) for holding terminal window size");
13125 
13126 static PyStructSequence_Field TerminalSize_fields[] = {
13127     {"columns", "width of the terminal window in characters"},
13128     {"lines", "height of the terminal window in characters"},
13129     {NULL, NULL}
13130 };
13131 
13132 static PyStructSequence_Desc TerminalSize_desc = {
13133     "os.terminal_size",
13134     TerminalSize_docstring,
13135     TerminalSize_fields,
13136     2,
13137 };
13138 
13139 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
13140 /*[clinic input]
13141 os.get_terminal_size
13142 
13143     fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
13144     /
13145 
13146 Return the size of the terminal window as (columns, lines).
13147 
13148 The optional argument fd (default standard output) specifies
13149 which file descriptor should be queried.
13150 
13151 If the file descriptor is not connected to a terminal, an OSError
13152 is thrown.
13153 
13154 This function will only be defined if an implementation is
13155 available for this system.
13156 
13157 shutil.get_terminal_size is the high-level function which should
13158 normally be used, os.get_terminal_size is the low-level implementation.
13159 [clinic start generated code]*/
13160 
13161 static PyObject *
os_get_terminal_size_impl(PyObject * module,int fd)13162 os_get_terminal_size_impl(PyObject *module, int fd)
13163 /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
13164 {
13165     int columns, lines;
13166     PyObject *termsize;
13167 
13168     /* Under some conditions stdout may not be connected and
13169      * fileno(stdout) may point to an invalid file descriptor. For example
13170      * GUI apps don't have valid standard streams by default.
13171      *
13172      * If this happens, and the optional fd argument is not present,
13173      * the ioctl below will fail returning EBADF. This is what we want.
13174      */
13175 
13176 #ifdef TERMSIZE_USE_IOCTL
13177     {
13178         struct winsize w;
13179         if (ioctl(fd, TIOCGWINSZ, &w))
13180             return PyErr_SetFromErrno(PyExc_OSError);
13181         columns = w.ws_col;
13182         lines = w.ws_row;
13183     }
13184 #endif /* TERMSIZE_USE_IOCTL */
13185 
13186 #ifdef TERMSIZE_USE_CONIO
13187     {
13188         DWORD nhandle;
13189         HANDLE handle;
13190         CONSOLE_SCREEN_BUFFER_INFO csbi;
13191         switch (fd) {
13192         case 0: nhandle = STD_INPUT_HANDLE;
13193             break;
13194         case 1: nhandle = STD_OUTPUT_HANDLE;
13195             break;
13196         case 2: nhandle = STD_ERROR_HANDLE;
13197             break;
13198         default:
13199             return PyErr_Format(PyExc_ValueError, "bad file descriptor");
13200         }
13201         handle = GetStdHandle(nhandle);
13202         if (handle == NULL)
13203             return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
13204         if (handle == INVALID_HANDLE_VALUE)
13205             return PyErr_SetFromWindowsErr(0);
13206 
13207         if (!GetConsoleScreenBufferInfo(handle, &csbi))
13208             return PyErr_SetFromWindowsErr(0);
13209 
13210         columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
13211         lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
13212     }
13213 #endif /* TERMSIZE_USE_CONIO */
13214 
13215     PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
13216     termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
13217     if (termsize == NULL)
13218         return NULL;
13219     PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
13220     PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
13221     if (PyErr_Occurred()) {
13222         Py_DECREF(termsize);
13223         return NULL;
13224     }
13225     return termsize;
13226 }
13227 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
13228 
13229 
13230 /*[clinic input]
13231 os.cpu_count
13232 
13233 Return the number of CPUs in the system; return None if indeterminable.
13234 
13235 This number is not equivalent to the number of CPUs the current process can
13236 use.  The number of usable CPUs can be obtained with
13237 ``len(os.sched_getaffinity(0))``
13238 [clinic start generated code]*/
13239 
13240 static PyObject *
os_cpu_count_impl(PyObject * module)13241 os_cpu_count_impl(PyObject *module)
13242 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
13243 {
13244     int ncpu = 0;
13245 #ifdef MS_WINDOWS
13246     ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
13247 #elif defined(__hpux)
13248     ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
13249 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
13250     ncpu = sysconf(_SC_NPROCESSORS_ONLN);
13251 #elif defined(__VXWORKS__)
13252     ncpu = _Py_popcount32(vxCpuEnabledGet());
13253 #elif defined(__DragonFly__) || \
13254       defined(__OpenBSD__)   || \
13255       defined(__FreeBSD__)   || \
13256       defined(__NetBSD__)    || \
13257       defined(__APPLE__)
13258     int mib[2];
13259     size_t len = sizeof(ncpu);
13260     mib[0] = CTL_HW;
13261     mib[1] = HW_NCPU;
13262     if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
13263         ncpu = 0;
13264 #endif
13265     if (ncpu >= 1)
13266         return PyLong_FromLong(ncpu);
13267     else
13268         Py_RETURN_NONE;
13269 }
13270 
13271 
13272 /*[clinic input]
13273 os.get_inheritable -> bool
13274 
13275     fd: int
13276     /
13277 
13278 Get the close-on-exe flag of the specified file descriptor.
13279 [clinic start generated code]*/
13280 
13281 static int
os_get_inheritable_impl(PyObject * module,int fd)13282 os_get_inheritable_impl(PyObject *module, int fd)
13283 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
13284 {
13285     int return_value;
13286     _Py_BEGIN_SUPPRESS_IPH
13287     return_value = _Py_get_inheritable(fd);
13288     _Py_END_SUPPRESS_IPH
13289     return return_value;
13290 }
13291 
13292 
13293 /*[clinic input]
13294 os.set_inheritable
13295     fd: int
13296     inheritable: int
13297     /
13298 
13299 Set the inheritable flag of the specified file descriptor.
13300 [clinic start generated code]*/
13301 
13302 static PyObject *
os_set_inheritable_impl(PyObject * module,int fd,int inheritable)13303 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
13304 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
13305 {
13306     int result;
13307 
13308     _Py_BEGIN_SUPPRESS_IPH
13309     result = _Py_set_inheritable(fd, inheritable, NULL);
13310     _Py_END_SUPPRESS_IPH
13311     if (result < 0)
13312         return NULL;
13313     Py_RETURN_NONE;
13314 }
13315 
13316 
13317 #ifdef MS_WINDOWS
13318 /*[clinic input]
13319 os.get_handle_inheritable -> bool
13320     handle: intptr_t
13321     /
13322 
13323 Get the close-on-exe flag of the specified file descriptor.
13324 [clinic start generated code]*/
13325 
13326 static int
os_get_handle_inheritable_impl(PyObject * module,intptr_t handle)13327 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
13328 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
13329 {
13330     DWORD flags;
13331 
13332     if (!GetHandleInformation((HANDLE)handle, &flags)) {
13333         PyErr_SetFromWindowsErr(0);
13334         return -1;
13335     }
13336 
13337     return flags & HANDLE_FLAG_INHERIT;
13338 }
13339 
13340 
13341 /*[clinic input]
13342 os.set_handle_inheritable
13343     handle: intptr_t
13344     inheritable: bool
13345     /
13346 
13347 Set the inheritable flag of the specified handle.
13348 [clinic start generated code]*/
13349 
13350 static PyObject *
os_set_handle_inheritable_impl(PyObject * module,intptr_t handle,int inheritable)13351 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
13352                                int inheritable)
13353 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
13354 {
13355     DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
13356     if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
13357         PyErr_SetFromWindowsErr(0);
13358         return NULL;
13359     }
13360     Py_RETURN_NONE;
13361 }
13362 #endif /* MS_WINDOWS */
13363 
13364 #ifndef MS_WINDOWS
13365 /*[clinic input]
13366 os.get_blocking -> bool
13367     fd: int
13368     /
13369 
13370 Get the blocking mode of the file descriptor.
13371 
13372 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
13373 [clinic start generated code]*/
13374 
13375 static int
os_get_blocking_impl(PyObject * module,int fd)13376 os_get_blocking_impl(PyObject *module, int fd)
13377 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
13378 {
13379     int blocking;
13380 
13381     _Py_BEGIN_SUPPRESS_IPH
13382     blocking = _Py_get_blocking(fd);
13383     _Py_END_SUPPRESS_IPH
13384     return blocking;
13385 }
13386 
13387 /*[clinic input]
13388 os.set_blocking
13389     fd: int
13390     blocking: bool(accept={int})
13391     /
13392 
13393 Set the blocking mode of the specified file descriptor.
13394 
13395 Set the O_NONBLOCK flag if blocking is False,
13396 clear the O_NONBLOCK flag otherwise.
13397 [clinic start generated code]*/
13398 
13399 static PyObject *
os_set_blocking_impl(PyObject * module,int fd,int blocking)13400 os_set_blocking_impl(PyObject *module, int fd, int blocking)
13401 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
13402 {
13403     int result;
13404 
13405     _Py_BEGIN_SUPPRESS_IPH
13406     result = _Py_set_blocking(fd, blocking);
13407     _Py_END_SUPPRESS_IPH
13408     if (result < 0)
13409         return NULL;
13410     Py_RETURN_NONE;
13411 }
13412 #endif   /* !MS_WINDOWS */
13413 
13414 
13415 /*[clinic input]
13416 class os.DirEntry "DirEntry *" "DirEntryType"
13417 [clinic start generated code]*/
13418 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
13419 
13420 typedef struct {
13421     PyObject_HEAD
13422     PyObject *name;
13423     PyObject *path;
13424     PyObject *stat;
13425     PyObject *lstat;
13426 #ifdef MS_WINDOWS
13427     struct _Py_stat_struct win32_lstat;
13428     uint64_t win32_file_index;
13429     int got_file_index;
13430 #else /* POSIX */
13431 #ifdef HAVE_DIRENT_D_TYPE
13432     unsigned char d_type;
13433 #endif
13434     ino_t d_ino;
13435     int dir_fd;
13436 #endif
13437 } DirEntry;
13438 
13439 static void
DirEntry_dealloc(DirEntry * entry)13440 DirEntry_dealloc(DirEntry *entry)
13441 {
13442     PyTypeObject *tp = Py_TYPE(entry);
13443     Py_XDECREF(entry->name);
13444     Py_XDECREF(entry->path);
13445     Py_XDECREF(entry->stat);
13446     Py_XDECREF(entry->lstat);
13447     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13448     free_func(entry);
13449     Py_DECREF(tp);
13450 }
13451 
13452 /* Forward reference */
13453 static int
13454 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13455                    int follow_symlinks, unsigned short mode_bits);
13456 
13457 /*[clinic input]
13458 os.DirEntry.is_symlink -> bool
13459     defining_class: defining_class
13460     /
13461 
13462 Return True if the entry is a symbolic link; cached per entry.
13463 [clinic start generated code]*/
13464 
13465 static int
os_DirEntry_is_symlink_impl(DirEntry * self,PyTypeObject * defining_class)13466 os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
13467 /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
13468 {
13469 #ifdef MS_WINDOWS
13470     return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13471 #elif defined(HAVE_DIRENT_D_TYPE)
13472     /* POSIX */
13473     if (self->d_type != DT_UNKNOWN)
13474         return self->d_type == DT_LNK;
13475     else
13476         return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13477 #else
13478     /* POSIX without d_type */
13479     return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13480 #endif
13481 }
13482 
13483 static PyObject *
DirEntry_fetch_stat(PyObject * module,DirEntry * self,int follow_symlinks)13484 DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
13485 {
13486     int result;
13487     STRUCT_STAT st;
13488     PyObject *ub;
13489 
13490 #ifdef MS_WINDOWS
13491     if (!PyUnicode_FSDecoder(self->path, &ub))
13492         return NULL;
13493 #if USE_UNICODE_WCHAR_CACHE
13494 _Py_COMP_DIAG_PUSH
13495 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13496     const wchar_t *path = PyUnicode_AsUnicode(ub);
13497 _Py_COMP_DIAG_POP
13498 #else /* USE_UNICODE_WCHAR_CACHE */
13499     wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
13500     Py_DECREF(ub);
13501 #endif /* USE_UNICODE_WCHAR_CACHE */
13502 #else /* POSIX */
13503     if (!PyUnicode_FSConverter(self->path, &ub))
13504         return NULL;
13505     const char *path = PyBytes_AS_STRING(ub);
13506     if (self->dir_fd != DEFAULT_DIR_FD) {
13507 #ifdef HAVE_FSTATAT
13508       if (HAVE_FSTATAT_RUNTIME) {
13509         Py_BEGIN_ALLOW_THREADS
13510         result = fstatat(self->dir_fd, path, &st,
13511                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
13512         Py_END_ALLOW_THREADS
13513       } else
13514 
13515 #endif /* HAVE_FSTATAT */
13516       {
13517         Py_DECREF(ub);
13518         PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
13519         return NULL;
13520       }
13521     }
13522     else
13523 #endif
13524     {
13525         Py_BEGIN_ALLOW_THREADS
13526         if (follow_symlinks) {
13527             result = STAT(path, &st);
13528         }
13529         else {
13530             result = LSTAT(path, &st);
13531         }
13532         Py_END_ALLOW_THREADS
13533     }
13534 #if defined(MS_WINDOWS) && !USE_UNICODE_WCHAR_CACHE
13535     PyMem_Free(path);
13536 #else /* USE_UNICODE_WCHAR_CACHE */
13537     Py_DECREF(ub);
13538 #endif /* USE_UNICODE_WCHAR_CACHE */
13539 
13540     if (result != 0)
13541         return path_object_error(self->path);
13542 
13543     return _pystat_fromstructstat(module, &st);
13544 }
13545 
13546 static PyObject *
DirEntry_get_lstat(PyTypeObject * defining_class,DirEntry * self)13547 DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
13548 {
13549     if (!self->lstat) {
13550         PyObject *module = PyType_GetModule(defining_class);
13551 #ifdef MS_WINDOWS
13552         self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
13553 #else /* POSIX */
13554         self->lstat = DirEntry_fetch_stat(module, self, 0);
13555 #endif
13556     }
13557     Py_XINCREF(self->lstat);
13558     return self->lstat;
13559 }
13560 
13561 /*[clinic input]
13562 os.DirEntry.stat
13563     defining_class: defining_class
13564     /
13565     *
13566     follow_symlinks: bool = True
13567 
13568 Return stat_result object for the entry; cached per entry.
13569 [clinic start generated code]*/
13570 
13571 static PyObject *
os_DirEntry_stat_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13572 os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
13573                       int follow_symlinks)
13574 /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
13575 {
13576     if (!follow_symlinks) {
13577         return DirEntry_get_lstat(defining_class, self);
13578     }
13579 
13580     if (!self->stat) {
13581         int result = os_DirEntry_is_symlink_impl(self, defining_class);
13582         if (result == -1) {
13583             return NULL;
13584         }
13585         if (result) {
13586             PyObject *module = PyType_GetModule(defining_class);
13587             self->stat = DirEntry_fetch_stat(module, self, 1);
13588         }
13589         else {
13590             self->stat = DirEntry_get_lstat(defining_class, self);
13591         }
13592     }
13593 
13594     Py_XINCREF(self->stat);
13595     return self->stat;
13596 }
13597 
13598 /* Set exception and return -1 on error, 0 for False, 1 for True */
13599 static int
DirEntry_test_mode(PyTypeObject * defining_class,DirEntry * self,int follow_symlinks,unsigned short mode_bits)13600 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13601                    int follow_symlinks, unsigned short mode_bits)
13602 {
13603     PyObject *stat = NULL;
13604     PyObject *st_mode = NULL;
13605     long mode;
13606     int result;
13607 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13608     int is_symlink;
13609     int need_stat;
13610 #endif
13611 #ifdef MS_WINDOWS
13612     unsigned long dir_bits;
13613 #endif
13614 
13615 #ifdef MS_WINDOWS
13616     is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13617     need_stat = follow_symlinks && is_symlink;
13618 #elif defined(HAVE_DIRENT_D_TYPE)
13619     is_symlink = self->d_type == DT_LNK;
13620     need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
13621 #endif
13622 
13623 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13624     if (need_stat) {
13625 #endif
13626         stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
13627         if (!stat) {
13628             if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
13629                 /* If file doesn't exist (anymore), then return False
13630                    (i.e., say it's not a file/directory) */
13631                 PyErr_Clear();
13632                 return 0;
13633             }
13634             goto error;
13635         }
13636         _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
13637         st_mode = PyObject_GetAttr(stat, state->st_mode);
13638         if (!st_mode)
13639             goto error;
13640 
13641         mode = PyLong_AsLong(st_mode);
13642         if (mode == -1 && PyErr_Occurred())
13643             goto error;
13644         Py_CLEAR(st_mode);
13645         Py_CLEAR(stat);
13646         result = (mode & S_IFMT) == mode_bits;
13647 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13648     }
13649     else if (is_symlink) {
13650         assert(mode_bits != S_IFLNK);
13651         result = 0;
13652     }
13653     else {
13654         assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
13655 #ifdef MS_WINDOWS
13656         dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
13657         if (mode_bits == S_IFDIR)
13658             result = dir_bits != 0;
13659         else
13660             result = dir_bits == 0;
13661 #else /* POSIX */
13662         if (mode_bits == S_IFDIR)
13663             result = self->d_type == DT_DIR;
13664         else
13665             result = self->d_type == DT_REG;
13666 #endif
13667     }
13668 #endif
13669 
13670     return result;
13671 
13672 error:
13673     Py_XDECREF(st_mode);
13674     Py_XDECREF(stat);
13675     return -1;
13676 }
13677 
13678 /*[clinic input]
13679 os.DirEntry.is_dir -> bool
13680     defining_class: defining_class
13681     /
13682     *
13683     follow_symlinks: bool = True
13684 
13685 Return True if the entry is a directory; cached per entry.
13686 [clinic start generated code]*/
13687 
13688 static int
os_DirEntry_is_dir_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13689 os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
13690                         int follow_symlinks)
13691 /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
13692 {
13693     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
13694 }
13695 
13696 /*[clinic input]
13697 os.DirEntry.is_file -> bool
13698     defining_class: defining_class
13699     /
13700     *
13701     follow_symlinks: bool = True
13702 
13703 Return True if the entry is a file; cached per entry.
13704 [clinic start generated code]*/
13705 
13706 static int
os_DirEntry_is_file_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13707 os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
13708                          int follow_symlinks)
13709 /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
13710 {
13711     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
13712 }
13713 
13714 /*[clinic input]
13715 os.DirEntry.inode
13716 
13717 Return inode of the entry; cached per entry.
13718 [clinic start generated code]*/
13719 
13720 static PyObject *
os_DirEntry_inode_impl(DirEntry * self)13721 os_DirEntry_inode_impl(DirEntry *self)
13722 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
13723 {
13724 #ifdef MS_WINDOWS
13725     if (!self->got_file_index) {
13726         PyObject *unicode;
13727         STRUCT_STAT stat;
13728         int result;
13729 
13730         if (!PyUnicode_FSDecoder(self->path, &unicode))
13731             return NULL;
13732 #if USE_UNICODE_WCHAR_CACHE
13733 _Py_COMP_DIAG_PUSH
13734 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13735         const wchar_t *path = PyUnicode_AsUnicode(unicode);
13736         result = LSTAT(path, &stat);
13737         Py_DECREF(unicode);
13738 _Py_COMP_DIAG_POP
13739 #else /* USE_UNICODE_WCHAR_CACHE */
13740         wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
13741         Py_DECREF(unicode);
13742         result = LSTAT(path, &stat);
13743         PyMem_Free(path);
13744 #endif /* USE_UNICODE_WCHAR_CACHE */
13745 
13746         if (result != 0)
13747             return path_object_error(self->path);
13748 
13749         self->win32_file_index = stat.st_ino;
13750         self->got_file_index = 1;
13751     }
13752     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->win32_file_index));
13753     return PyLong_FromUnsignedLongLong(self->win32_file_index);
13754 #else /* POSIX */
13755     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->d_ino));
13756     return PyLong_FromUnsignedLongLong(self->d_ino);
13757 #endif
13758 }
13759 
13760 static PyObject *
DirEntry_repr(DirEntry * self)13761 DirEntry_repr(DirEntry *self)
13762 {
13763     return PyUnicode_FromFormat("<DirEntry %R>", self->name);
13764 }
13765 
13766 /*[clinic input]
13767 os.DirEntry.__fspath__
13768 
13769 Returns the path for the entry.
13770 [clinic start generated code]*/
13771 
13772 static PyObject *
os_DirEntry___fspath___impl(DirEntry * self)13773 os_DirEntry___fspath___impl(DirEntry *self)
13774 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
13775 {
13776     Py_INCREF(self->path);
13777     return self->path;
13778 }
13779 
13780 static PyMemberDef DirEntry_members[] = {
13781     {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
13782      "the entry's base filename, relative to scandir() \"path\" argument"},
13783     {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
13784      "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
13785     {NULL}
13786 };
13787 
13788 #include "clinic/posixmodule.c.h"
13789 
13790 static PyMethodDef DirEntry_methods[] = {
13791     OS_DIRENTRY_IS_DIR_METHODDEF
13792     OS_DIRENTRY_IS_FILE_METHODDEF
13793     OS_DIRENTRY_IS_SYMLINK_METHODDEF
13794     OS_DIRENTRY_STAT_METHODDEF
13795     OS_DIRENTRY_INODE_METHODDEF
13796     OS_DIRENTRY___FSPATH___METHODDEF
13797     {"__class_getitem__",       Py_GenericAlias,
13798     METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
13799     {NULL}
13800 };
13801 
13802 static PyType_Slot DirEntryType_slots[] = {
13803     {Py_tp_dealloc, DirEntry_dealloc},
13804     {Py_tp_repr, DirEntry_repr},
13805     {Py_tp_methods, DirEntry_methods},
13806     {Py_tp_members, DirEntry_members},
13807     {0, 0},
13808 };
13809 
13810 static PyType_Spec DirEntryType_spec = {
13811     MODNAME ".DirEntry",
13812     sizeof(DirEntry),
13813     0,
13814     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
13815     DirEntryType_slots
13816 };
13817 
13818 
13819 #ifdef MS_WINDOWS
13820 
13821 static wchar_t *
join_path_filenameW(const wchar_t * path_wide,const wchar_t * filename)13822 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
13823 {
13824     Py_ssize_t path_len;
13825     Py_ssize_t size;
13826     wchar_t *result;
13827     wchar_t ch;
13828 
13829     if (!path_wide) { /* Default arg: "." */
13830         path_wide = L".";
13831         path_len = 1;
13832     }
13833     else {
13834         path_len = wcslen(path_wide);
13835     }
13836 
13837     /* The +1's are for the path separator and the NUL */
13838     size = path_len + 1 + wcslen(filename) + 1;
13839     result = PyMem_New(wchar_t, size);
13840     if (!result) {
13841         PyErr_NoMemory();
13842         return NULL;
13843     }
13844     wcscpy(result, path_wide);
13845     if (path_len > 0) {
13846         ch = result[path_len - 1];
13847         if (ch != SEP && ch != ALTSEP && ch != L':')
13848             result[path_len++] = SEP;
13849         wcscpy(result + path_len, filename);
13850     }
13851     return result;
13852 }
13853 
13854 static PyObject *
DirEntry_from_find_data(PyObject * module,path_t * path,WIN32_FIND_DATAW * dataW)13855 DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
13856 {
13857     DirEntry *entry;
13858     BY_HANDLE_FILE_INFORMATION file_info;
13859     ULONG reparse_tag;
13860     wchar_t *joined_path;
13861 
13862     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13863     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13864     if (!entry)
13865         return NULL;
13866     entry->name = NULL;
13867     entry->path = NULL;
13868     entry->stat = NULL;
13869     entry->lstat = NULL;
13870     entry->got_file_index = 0;
13871 
13872     entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
13873     if (!entry->name)
13874         goto error;
13875     if (path->narrow) {
13876         Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
13877         if (!entry->name)
13878             goto error;
13879     }
13880 
13881     joined_path = join_path_filenameW(path->wide, dataW->cFileName);
13882     if (!joined_path)
13883         goto error;
13884 
13885     entry->path = PyUnicode_FromWideChar(joined_path, -1);
13886     PyMem_Free(joined_path);
13887     if (!entry->path)
13888         goto error;
13889     if (path->narrow) {
13890         Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
13891         if (!entry->path)
13892             goto error;
13893     }
13894 
13895     find_data_to_file_info(dataW, &file_info, &reparse_tag);
13896     _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
13897 
13898     return (PyObject *)entry;
13899 
13900 error:
13901     Py_DECREF(entry);
13902     return NULL;
13903 }
13904 
13905 #else /* POSIX */
13906 
13907 static char *
join_path_filename(const char * path_narrow,const char * filename,Py_ssize_t filename_len)13908 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
13909 {
13910     Py_ssize_t path_len;
13911     Py_ssize_t size;
13912     char *result;
13913 
13914     if (!path_narrow) { /* Default arg: "." */
13915         path_narrow = ".";
13916         path_len = 1;
13917     }
13918     else {
13919         path_len = strlen(path_narrow);
13920     }
13921 
13922     if (filename_len == -1)
13923         filename_len = strlen(filename);
13924 
13925     /* The +1's are for the path separator and the NUL */
13926     size = path_len + 1 + filename_len + 1;
13927     result = PyMem_New(char, size);
13928     if (!result) {
13929         PyErr_NoMemory();
13930         return NULL;
13931     }
13932     strcpy(result, path_narrow);
13933     if (path_len > 0 && result[path_len - 1] != '/')
13934         result[path_len++] = '/';
13935     strcpy(result + path_len, filename);
13936     return result;
13937 }
13938 
13939 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)13940 DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
13941                          Py_ssize_t name_len, ino_t d_ino
13942 #ifdef HAVE_DIRENT_D_TYPE
13943                          , unsigned char d_type
13944 #endif
13945                          )
13946 {
13947     DirEntry *entry;
13948     char *joined_path;
13949 
13950     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13951     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13952     if (!entry)
13953         return NULL;
13954     entry->name = NULL;
13955     entry->path = NULL;
13956     entry->stat = NULL;
13957     entry->lstat = NULL;
13958 
13959     if (path->fd != -1) {
13960         entry->dir_fd = path->fd;
13961         joined_path = NULL;
13962     }
13963     else {
13964         entry->dir_fd = DEFAULT_DIR_FD;
13965         joined_path = join_path_filename(path->narrow, name, name_len);
13966         if (!joined_path)
13967             goto error;
13968     }
13969 
13970     if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
13971         entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
13972         if (joined_path)
13973             entry->path = PyUnicode_DecodeFSDefault(joined_path);
13974     }
13975     else {
13976         entry->name = PyBytes_FromStringAndSize(name, name_len);
13977         if (joined_path)
13978             entry->path = PyBytes_FromString(joined_path);
13979     }
13980     PyMem_Free(joined_path);
13981     if (!entry->name)
13982         goto error;
13983 
13984     if (path->fd != -1) {
13985         entry->path = entry->name;
13986         Py_INCREF(entry->path);
13987     }
13988     else if (!entry->path)
13989         goto error;
13990 
13991 #ifdef HAVE_DIRENT_D_TYPE
13992     entry->d_type = d_type;
13993 #endif
13994     entry->d_ino = d_ino;
13995 
13996     return (PyObject *)entry;
13997 
13998 error:
13999     Py_XDECREF(entry);
14000     return NULL;
14001 }
14002 
14003 #endif
14004 
14005 
14006 typedef struct {
14007     PyObject_HEAD
14008     path_t path;
14009 #ifdef MS_WINDOWS
14010     HANDLE handle;
14011     WIN32_FIND_DATAW file_data;
14012     int first_time;
14013 #else /* POSIX */
14014     DIR *dirp;
14015 #endif
14016 #ifdef HAVE_FDOPENDIR
14017     int fd;
14018 #endif
14019 } ScandirIterator;
14020 
14021 #ifdef MS_WINDOWS
14022 
14023 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14024 ScandirIterator_is_closed(ScandirIterator *iterator)
14025 {
14026     return iterator->handle == INVALID_HANDLE_VALUE;
14027 }
14028 
14029 static void
ScandirIterator_closedir(ScandirIterator * iterator)14030 ScandirIterator_closedir(ScandirIterator *iterator)
14031 {
14032     HANDLE handle = iterator->handle;
14033 
14034     if (handle == INVALID_HANDLE_VALUE)
14035         return;
14036 
14037     iterator->handle = INVALID_HANDLE_VALUE;
14038     Py_BEGIN_ALLOW_THREADS
14039     FindClose(handle);
14040     Py_END_ALLOW_THREADS
14041 }
14042 
14043 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14044 ScandirIterator_iternext(ScandirIterator *iterator)
14045 {
14046     WIN32_FIND_DATAW *file_data = &iterator->file_data;
14047     BOOL success;
14048     PyObject *entry;
14049 
14050     /* Happens if the iterator is iterated twice, or closed explicitly */
14051     if (iterator->handle == INVALID_HANDLE_VALUE)
14052         return NULL;
14053 
14054     while (1) {
14055         if (!iterator->first_time) {
14056             Py_BEGIN_ALLOW_THREADS
14057             success = FindNextFileW(iterator->handle, file_data);
14058             Py_END_ALLOW_THREADS
14059             if (!success) {
14060                 /* Error or no more files */
14061                 if (GetLastError() != ERROR_NO_MORE_FILES)
14062                     path_error(&iterator->path);
14063                 break;
14064             }
14065         }
14066         iterator->first_time = 0;
14067 
14068         /* Skip over . and .. */
14069         if (wcscmp(file_data->cFileName, L".") != 0 &&
14070             wcscmp(file_data->cFileName, L"..") != 0)
14071         {
14072             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14073             entry = DirEntry_from_find_data(module, &iterator->path, file_data);
14074             if (!entry)
14075                 break;
14076             return entry;
14077         }
14078 
14079         /* Loop till we get a non-dot directory or finish iterating */
14080     }
14081 
14082     /* Error or no more files */
14083     ScandirIterator_closedir(iterator);
14084     return NULL;
14085 }
14086 
14087 #else /* POSIX */
14088 
14089 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14090 ScandirIterator_is_closed(ScandirIterator *iterator)
14091 {
14092     return !iterator->dirp;
14093 }
14094 
14095 static void
ScandirIterator_closedir(ScandirIterator * iterator)14096 ScandirIterator_closedir(ScandirIterator *iterator)
14097 {
14098     DIR *dirp = iterator->dirp;
14099 
14100     if (!dirp)
14101         return;
14102 
14103     iterator->dirp = NULL;
14104     Py_BEGIN_ALLOW_THREADS
14105 #ifdef HAVE_FDOPENDIR
14106     if (iterator->path.fd != -1)
14107         rewinddir(dirp);
14108 #endif
14109     closedir(dirp);
14110     Py_END_ALLOW_THREADS
14111     return;
14112 }
14113 
14114 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14115 ScandirIterator_iternext(ScandirIterator *iterator)
14116 {
14117     struct dirent *direntp;
14118     Py_ssize_t name_len;
14119     int is_dot;
14120     PyObject *entry;
14121 
14122     /* Happens if the iterator is iterated twice, or closed explicitly */
14123     if (!iterator->dirp)
14124         return NULL;
14125 
14126     while (1) {
14127         errno = 0;
14128         Py_BEGIN_ALLOW_THREADS
14129         direntp = readdir(iterator->dirp);
14130         Py_END_ALLOW_THREADS
14131 
14132         if (!direntp) {
14133             /* Error or no more files */
14134             if (errno != 0)
14135                 path_error(&iterator->path);
14136             break;
14137         }
14138 
14139         /* Skip over . and .. */
14140         name_len = NAMLEN(direntp);
14141         is_dot = direntp->d_name[0] == '.' &&
14142                  (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
14143         if (!is_dot) {
14144             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14145             entry = DirEntry_from_posix_info(module,
14146                                              &iterator->path, direntp->d_name,
14147                                              name_len, direntp->d_ino
14148 #ifdef HAVE_DIRENT_D_TYPE
14149                                              , direntp->d_type
14150 #endif
14151                                             );
14152             if (!entry)
14153                 break;
14154             return entry;
14155         }
14156 
14157         /* Loop till we get a non-dot directory or finish iterating */
14158     }
14159 
14160     /* Error or no more files */
14161     ScandirIterator_closedir(iterator);
14162     return NULL;
14163 }
14164 
14165 #endif
14166 
14167 static PyObject *
ScandirIterator_close(ScandirIterator * self,PyObject * args)14168 ScandirIterator_close(ScandirIterator *self, PyObject *args)
14169 {
14170     ScandirIterator_closedir(self);
14171     Py_RETURN_NONE;
14172 }
14173 
14174 static PyObject *
ScandirIterator_enter(PyObject * self,PyObject * args)14175 ScandirIterator_enter(PyObject *self, PyObject *args)
14176 {
14177     Py_INCREF(self);
14178     return self;
14179 }
14180 
14181 static PyObject *
ScandirIterator_exit(ScandirIterator * self,PyObject * args)14182 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
14183 {
14184     ScandirIterator_closedir(self);
14185     Py_RETURN_NONE;
14186 }
14187 
14188 static void
ScandirIterator_finalize(ScandirIterator * iterator)14189 ScandirIterator_finalize(ScandirIterator *iterator)
14190 {
14191     PyObject *error_type, *error_value, *error_traceback;
14192 
14193     /* Save the current exception, if any. */
14194     PyErr_Fetch(&error_type, &error_value, &error_traceback);
14195 
14196     if (!ScandirIterator_is_closed(iterator)) {
14197         ScandirIterator_closedir(iterator);
14198 
14199         if (PyErr_ResourceWarning((PyObject *)iterator, 1,
14200                                   "unclosed scandir iterator %R", iterator)) {
14201             /* Spurious errors can appear at shutdown */
14202             if (PyErr_ExceptionMatches(PyExc_Warning)) {
14203                 PyErr_WriteUnraisable((PyObject *) iterator);
14204             }
14205         }
14206     }
14207 
14208     path_cleanup(&iterator->path);
14209 
14210     /* Restore the saved exception. */
14211     PyErr_Restore(error_type, error_value, error_traceback);
14212 }
14213 
14214 static void
ScandirIterator_dealloc(ScandirIterator * iterator)14215 ScandirIterator_dealloc(ScandirIterator *iterator)
14216 {
14217     PyTypeObject *tp = Py_TYPE(iterator);
14218     if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
14219         return;
14220 
14221     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
14222     free_func(iterator);
14223     Py_DECREF(tp);
14224 }
14225 
14226 static PyMethodDef ScandirIterator_methods[] = {
14227     {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
14228     {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
14229     {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
14230     {NULL}
14231 };
14232 
14233 static PyType_Slot ScandirIteratorType_slots[] = {
14234     {Py_tp_dealloc, ScandirIterator_dealloc},
14235     {Py_tp_finalize, ScandirIterator_finalize},
14236     {Py_tp_iter, PyObject_SelfIter},
14237     {Py_tp_iternext, ScandirIterator_iternext},
14238     {Py_tp_methods, ScandirIterator_methods},
14239     {0, 0},
14240 };
14241 
14242 static PyType_Spec ScandirIteratorType_spec = {
14243     MODNAME ".ScandirIterator",
14244     sizeof(ScandirIterator),
14245     0,
14246     // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
14247     // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
14248     (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
14249         | Py_TPFLAGS_DISALLOW_INSTANTIATION),
14250     ScandirIteratorType_slots
14251 };
14252 
14253 /*[clinic input]
14254 os.scandir
14255 
14256     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
14257 
14258 Return an iterator of DirEntry objects for given path.
14259 
14260 path can be specified as either str, bytes, or a path-like object.  If path
14261 is bytes, the names of yielded DirEntry objects will also be bytes; in
14262 all other circumstances they will be str.
14263 
14264 If path is None, uses the path='.'.
14265 [clinic start generated code]*/
14266 
14267 static PyObject *
os_scandir_impl(PyObject * module,path_t * path)14268 os_scandir_impl(PyObject *module, path_t *path)
14269 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
14270 {
14271     ScandirIterator *iterator;
14272 #ifdef MS_WINDOWS
14273     wchar_t *path_strW;
14274 #else
14275     const char *path_str;
14276 #ifdef HAVE_FDOPENDIR
14277     int fd = -1;
14278 #endif
14279 #endif
14280 
14281     if (PySys_Audit("os.scandir", "O",
14282                     path->object ? path->object : Py_None) < 0) {
14283         return NULL;
14284     }
14285 
14286     PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
14287     iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
14288     if (!iterator)
14289         return NULL;
14290 
14291 #ifdef MS_WINDOWS
14292     iterator->handle = INVALID_HANDLE_VALUE;
14293 #else
14294     iterator->dirp = NULL;
14295 #endif
14296 
14297     /* Move the ownership to iterator->path */
14298     memcpy(&iterator->path, path, sizeof(path_t));
14299     memset(path, 0, sizeof(path_t));
14300 
14301 #ifdef MS_WINDOWS
14302     iterator->first_time = 1;
14303 
14304     path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
14305     if (!path_strW)
14306         goto error;
14307 
14308     Py_BEGIN_ALLOW_THREADS
14309     iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
14310     Py_END_ALLOW_THREADS
14311 
14312     PyMem_Free(path_strW);
14313 
14314     if (iterator->handle == INVALID_HANDLE_VALUE) {
14315         path_error(&iterator->path);
14316         goto error;
14317     }
14318 #else /* POSIX */
14319     errno = 0;
14320 #ifdef HAVE_FDOPENDIR
14321     if (iterator->path.fd != -1) {
14322       if (HAVE_FDOPENDIR_RUNTIME) {
14323         /* closedir() closes the FD, so we duplicate it */
14324         fd = _Py_dup(iterator->path.fd);
14325         if (fd == -1)
14326             goto error;
14327 
14328         Py_BEGIN_ALLOW_THREADS
14329         iterator->dirp = fdopendir(fd);
14330         Py_END_ALLOW_THREADS
14331       } else {
14332         PyErr_SetString(PyExc_TypeError,
14333             "scandir: path should be string, bytes, os.PathLike or None, not int");
14334         return NULL;
14335       }
14336     }
14337     else
14338 #endif
14339     {
14340         if (iterator->path.narrow)
14341             path_str = iterator->path.narrow;
14342         else
14343             path_str = ".";
14344 
14345         Py_BEGIN_ALLOW_THREADS
14346         iterator->dirp = opendir(path_str);
14347         Py_END_ALLOW_THREADS
14348     }
14349 
14350     if (!iterator->dirp) {
14351         path_error(&iterator->path);
14352 #ifdef HAVE_FDOPENDIR
14353         if (fd != -1) {
14354             Py_BEGIN_ALLOW_THREADS
14355             close(fd);
14356             Py_END_ALLOW_THREADS
14357         }
14358 #endif
14359         goto error;
14360     }
14361 #endif
14362 
14363     return (PyObject *)iterator;
14364 
14365 error:
14366     Py_DECREF(iterator);
14367     return NULL;
14368 }
14369 
14370 /*
14371     Return the file system path representation of the object.
14372 
14373     If the object is str or bytes, then allow it to pass through with
14374     an incremented refcount. If the object defines __fspath__(), then
14375     return the result of that method. All other types raise a TypeError.
14376 */
14377 PyObject *
PyOS_FSPath(PyObject * path)14378 PyOS_FSPath(PyObject *path)
14379 {
14380     /* For error message reasons, this function is manually inlined in
14381        path_converter(). */
14382     PyObject *func = NULL;
14383     PyObject *path_repr = NULL;
14384 
14385     if (PyUnicode_Check(path) || PyBytes_Check(path)) {
14386         Py_INCREF(path);
14387         return path;
14388     }
14389 
14390     func = _PyObject_LookupSpecial(path, &PyId___fspath__);
14391     if (NULL == func) {
14392         return PyErr_Format(PyExc_TypeError,
14393                             "expected str, bytes or os.PathLike object, "
14394                             "not %.200s",
14395                             _PyType_Name(Py_TYPE(path)));
14396     }
14397 
14398     path_repr = _PyObject_CallNoArgs(func);
14399     Py_DECREF(func);
14400     if (NULL == path_repr) {
14401         return NULL;
14402     }
14403 
14404     if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
14405         PyErr_Format(PyExc_TypeError,
14406                      "expected %.200s.__fspath__() to return str or bytes, "
14407                      "not %.200s", _PyType_Name(Py_TYPE(path)),
14408                      _PyType_Name(Py_TYPE(path_repr)));
14409         Py_DECREF(path_repr);
14410         return NULL;
14411     }
14412 
14413     return path_repr;
14414 }
14415 
14416 /*[clinic input]
14417 os.fspath
14418 
14419     path: object
14420 
14421 Return the file system path representation of the object.
14422 
14423 If the object is str or bytes, then allow it to pass through as-is. If the
14424 object defines __fspath__(), then return the result of that method. All other
14425 types raise a TypeError.
14426 [clinic start generated code]*/
14427 
14428 static PyObject *
os_fspath_impl(PyObject * module,PyObject * path)14429 os_fspath_impl(PyObject *module, PyObject *path)
14430 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
14431 {
14432     return PyOS_FSPath(path);
14433 }
14434 
14435 #ifdef HAVE_GETRANDOM_SYSCALL
14436 /*[clinic input]
14437 os.getrandom
14438 
14439     size: Py_ssize_t
14440     flags: int=0
14441 
14442 Obtain a series of random bytes.
14443 [clinic start generated code]*/
14444 
14445 static PyObject *
os_getrandom_impl(PyObject * module,Py_ssize_t size,int flags)14446 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
14447 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
14448 {
14449     PyObject *bytes;
14450     Py_ssize_t n;
14451 
14452     if (size < 0) {
14453         errno = EINVAL;
14454         return posix_error();
14455     }
14456 
14457     bytes = PyBytes_FromStringAndSize(NULL, size);
14458     if (bytes == NULL) {
14459         PyErr_NoMemory();
14460         return NULL;
14461     }
14462 
14463     while (1) {
14464         n = syscall(SYS_getrandom,
14465                     PyBytes_AS_STRING(bytes),
14466                     PyBytes_GET_SIZE(bytes),
14467                     flags);
14468         if (n < 0 && errno == EINTR) {
14469             if (PyErr_CheckSignals() < 0) {
14470                 goto error;
14471             }
14472 
14473             /* getrandom() was interrupted by a signal: retry */
14474             continue;
14475         }
14476         break;
14477     }
14478 
14479     if (n < 0) {
14480         PyErr_SetFromErrno(PyExc_OSError);
14481         goto error;
14482     }
14483 
14484     if (n != size) {
14485         _PyBytes_Resize(&bytes, n);
14486     }
14487 
14488     return bytes;
14489 
14490 error:
14491     Py_DECREF(bytes);
14492     return NULL;
14493 }
14494 #endif   /* HAVE_GETRANDOM_SYSCALL */
14495 
14496 #ifdef MS_WINDOWS
14497 /* bpo-36085: Helper functions for managing DLL search directories
14498  * on win32
14499  */
14500 
14501 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
14502 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
14503 
14504 /*[clinic input]
14505 os._add_dll_directory
14506 
14507     path: path_t
14508 
14509 Add a path to the DLL search path.
14510 
14511 This search path is used when resolving dependencies for imported
14512 extension modules (the module itself is resolved through sys.path),
14513 and also by ctypes.
14514 
14515 Returns an opaque value that may be passed to os.remove_dll_directory
14516 to remove this directory from the search path.
14517 [clinic start generated code]*/
14518 
14519 static PyObject *
os__add_dll_directory_impl(PyObject * module,path_t * path)14520 os__add_dll_directory_impl(PyObject *module, path_t *path)
14521 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
14522 {
14523     HMODULE hKernel32;
14524     PAddDllDirectory AddDllDirectory;
14525     DLL_DIRECTORY_COOKIE cookie = 0;
14526     DWORD err = 0;
14527 
14528     if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
14529         return NULL;
14530     }
14531 
14532     /* For Windows 7, we have to load this. As this will be a fairly
14533        infrequent operation, just do it each time. Kernel32 is always
14534        loaded. */
14535     Py_BEGIN_ALLOW_THREADS
14536     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14537         !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
14538             hKernel32, "AddDllDirectory")) ||
14539         !(cookie = (*AddDllDirectory)(path->wide))) {
14540         err = GetLastError();
14541     }
14542     Py_END_ALLOW_THREADS
14543 
14544     if (err) {
14545         return win32_error_object_err("add_dll_directory",
14546                                       path->object, err);
14547     }
14548 
14549     return PyCapsule_New(cookie, "DLL directory cookie", NULL);
14550 }
14551 
14552 /*[clinic input]
14553 os._remove_dll_directory
14554 
14555     cookie: object
14556 
14557 Removes a path from the DLL search path.
14558 
14559 The parameter is an opaque value that was returned from
14560 os.add_dll_directory. You can only remove directories that you added
14561 yourself.
14562 [clinic start generated code]*/
14563 
14564 static PyObject *
os__remove_dll_directory_impl(PyObject * module,PyObject * cookie)14565 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
14566 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
14567 {
14568     HMODULE hKernel32;
14569     PRemoveDllDirectory RemoveDllDirectory;
14570     DLL_DIRECTORY_COOKIE cookieValue;
14571     DWORD err = 0;
14572 
14573     if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
14574         PyErr_SetString(PyExc_TypeError,
14575             "Provided cookie was not returned from os.add_dll_directory");
14576         return NULL;
14577     }
14578 
14579     cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
14580         cookie, "DLL directory cookie");
14581 
14582     /* For Windows 7, we have to load this. As this will be a fairly
14583        infrequent operation, just do it each time. Kernel32 is always
14584        loaded. */
14585     Py_BEGIN_ALLOW_THREADS
14586     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14587         !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
14588             hKernel32, "RemoveDllDirectory")) ||
14589         !(*RemoveDllDirectory)(cookieValue)) {
14590         err = GetLastError();
14591     }
14592     Py_END_ALLOW_THREADS
14593 
14594     if (err) {
14595         return win32_error_object_err("remove_dll_directory",
14596                                       NULL, err);
14597     }
14598 
14599     if (PyCapsule_SetName(cookie, NULL)) {
14600         return NULL;
14601     }
14602 
14603     Py_RETURN_NONE;
14604 }
14605 
14606 #endif
14607 
14608 
14609 /* Only check if WIFEXITED is available: expect that it comes
14610    with WEXITSTATUS, WIFSIGNALED, etc.
14611 
14612    os.waitstatus_to_exitcode() is implemented in C and not in Python, so
14613    subprocess can safely call it during late Python finalization without
14614    risking that used os attributes were set to None by finalize_modules(). */
14615 #if defined(WIFEXITED) || defined(MS_WINDOWS)
14616 /*[clinic input]
14617 os.waitstatus_to_exitcode
14618 
14619     status as status_obj: object
14620 
14621 Convert a wait status to an exit code.
14622 
14623 On Unix:
14624 
14625 * If WIFEXITED(status) is true, return WEXITSTATUS(status).
14626 * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
14627 * Otherwise, raise a ValueError.
14628 
14629 On Windows, return status shifted right by 8 bits.
14630 
14631 On Unix, if the process is being traced or if waitpid() was called with
14632 WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
14633 This function must not be called if WIFSTOPPED(status) is true.
14634 [clinic start generated code]*/
14635 
14636 static PyObject *
os_waitstatus_to_exitcode_impl(PyObject * module,PyObject * status_obj)14637 os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
14638 /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
14639 {
14640 #ifndef MS_WINDOWS
14641     int status = _PyLong_AsInt(status_obj);
14642     if (status == -1 && PyErr_Occurred()) {
14643         return NULL;
14644     }
14645 
14646     WAIT_TYPE wait_status;
14647     WAIT_STATUS_INT(wait_status) = status;
14648     int exitcode;
14649     if (WIFEXITED(wait_status)) {
14650         exitcode = WEXITSTATUS(wait_status);
14651         /* Sanity check to provide warranty on the function behavior.
14652            It should not occur in practice */
14653         if (exitcode < 0) {
14654             PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
14655             return NULL;
14656         }
14657     }
14658     else if (WIFSIGNALED(wait_status)) {
14659         int signum = WTERMSIG(wait_status);
14660         /* Sanity check to provide warranty on the function behavior.
14661            It should not occurs in practice */
14662         if (signum <= 0) {
14663             PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
14664             return NULL;
14665         }
14666         exitcode = -signum;
14667     } else if (WIFSTOPPED(wait_status)) {
14668         /* Status only received if the process is being traced
14669            or if waitpid() was called with WUNTRACED option. */
14670         int signum = WSTOPSIG(wait_status);
14671         PyErr_Format(PyExc_ValueError,
14672                      "process stopped by delivery of signal %i",
14673                      signum);
14674         return NULL;
14675     }
14676     else {
14677         PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
14678         return NULL;
14679     }
14680     return PyLong_FromLong(exitcode);
14681 #else
14682     /* Windows implementation: see os.waitpid() implementation
14683        which uses _cwait(). */
14684     unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
14685     if (status == (unsigned long long)-1 && PyErr_Occurred()) {
14686         return NULL;
14687     }
14688 
14689     unsigned long long exitcode = (status >> 8);
14690     /* ExitProcess() accepts an UINT type:
14691        reject exit code which doesn't fit in an UINT */
14692     if (exitcode > UINT_MAX) {
14693         PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
14694         return NULL;
14695     }
14696     return PyLong_FromUnsignedLong((unsigned long)exitcode);
14697 #endif
14698 }
14699 #endif
14700 
14701 
14702 static PyMethodDef posix_methods[] = {
14703 
14704     OS_STAT_METHODDEF
14705     OS_ACCESS_METHODDEF
14706     OS_TTYNAME_METHODDEF
14707     OS_CHDIR_METHODDEF
14708     OS_CHFLAGS_METHODDEF
14709     OS_CHMOD_METHODDEF
14710     OS_FCHMOD_METHODDEF
14711     OS_LCHMOD_METHODDEF
14712     OS_CHOWN_METHODDEF
14713     OS_FCHOWN_METHODDEF
14714     OS_LCHOWN_METHODDEF
14715     OS_LCHFLAGS_METHODDEF
14716     OS_CHROOT_METHODDEF
14717     OS_CTERMID_METHODDEF
14718     OS_GETCWD_METHODDEF
14719     OS_GETCWDB_METHODDEF
14720     OS_LINK_METHODDEF
14721     OS_LISTDIR_METHODDEF
14722     OS_LSTAT_METHODDEF
14723     OS_MKDIR_METHODDEF
14724     OS_NICE_METHODDEF
14725     OS_GETPRIORITY_METHODDEF
14726     OS_SETPRIORITY_METHODDEF
14727     OS_POSIX_SPAWN_METHODDEF
14728     OS_POSIX_SPAWNP_METHODDEF
14729     OS_READLINK_METHODDEF
14730     OS_COPY_FILE_RANGE_METHODDEF
14731     OS_SPLICE_METHODDEF
14732     OS_RENAME_METHODDEF
14733     OS_REPLACE_METHODDEF
14734     OS_RMDIR_METHODDEF
14735     OS_SYMLINK_METHODDEF
14736     OS_SYSTEM_METHODDEF
14737     OS_UMASK_METHODDEF
14738     OS_UNAME_METHODDEF
14739     OS_UNLINK_METHODDEF
14740     OS_REMOVE_METHODDEF
14741     OS_UTIME_METHODDEF
14742     OS_TIMES_METHODDEF
14743     OS__EXIT_METHODDEF
14744     OS__FCOPYFILE_METHODDEF
14745     OS_EXECV_METHODDEF
14746     OS_EXECVE_METHODDEF
14747     OS_SPAWNV_METHODDEF
14748     OS_SPAWNVE_METHODDEF
14749     OS_FORK1_METHODDEF
14750     OS_FORK_METHODDEF
14751     OS_REGISTER_AT_FORK_METHODDEF
14752     OS_SCHED_GET_PRIORITY_MAX_METHODDEF
14753     OS_SCHED_GET_PRIORITY_MIN_METHODDEF
14754     OS_SCHED_GETPARAM_METHODDEF
14755     OS_SCHED_GETSCHEDULER_METHODDEF
14756     OS_SCHED_RR_GET_INTERVAL_METHODDEF
14757     OS_SCHED_SETPARAM_METHODDEF
14758     OS_SCHED_SETSCHEDULER_METHODDEF
14759     OS_SCHED_YIELD_METHODDEF
14760     OS_SCHED_SETAFFINITY_METHODDEF
14761     OS_SCHED_GETAFFINITY_METHODDEF
14762     OS_OPENPTY_METHODDEF
14763     OS_FORKPTY_METHODDEF
14764     OS_GETEGID_METHODDEF
14765     OS_GETEUID_METHODDEF
14766     OS_GETGID_METHODDEF
14767     OS_GETGROUPLIST_METHODDEF
14768     OS_GETGROUPS_METHODDEF
14769     OS_GETPID_METHODDEF
14770     OS_GETPGRP_METHODDEF
14771     OS_GETPPID_METHODDEF
14772     OS_GETUID_METHODDEF
14773     OS_GETLOGIN_METHODDEF
14774     OS_KILL_METHODDEF
14775     OS_KILLPG_METHODDEF
14776     OS_PLOCK_METHODDEF
14777     OS_STARTFILE_METHODDEF
14778     OS_SETUID_METHODDEF
14779     OS_SETEUID_METHODDEF
14780     OS_SETREUID_METHODDEF
14781     OS_SETGID_METHODDEF
14782     OS_SETEGID_METHODDEF
14783     OS_SETREGID_METHODDEF
14784     OS_SETGROUPS_METHODDEF
14785     OS_INITGROUPS_METHODDEF
14786     OS_GETPGID_METHODDEF
14787     OS_SETPGRP_METHODDEF
14788     OS_WAIT_METHODDEF
14789     OS_WAIT3_METHODDEF
14790     OS_WAIT4_METHODDEF
14791     OS_WAITID_METHODDEF
14792     OS_WAITPID_METHODDEF
14793     OS_PIDFD_OPEN_METHODDEF
14794     OS_GETSID_METHODDEF
14795     OS_SETSID_METHODDEF
14796     OS_SETPGID_METHODDEF
14797     OS_TCGETPGRP_METHODDEF
14798     OS_TCSETPGRP_METHODDEF
14799     OS_OPEN_METHODDEF
14800     OS_CLOSE_METHODDEF
14801     OS_CLOSERANGE_METHODDEF
14802     OS_DEVICE_ENCODING_METHODDEF
14803     OS_DUP_METHODDEF
14804     OS_DUP2_METHODDEF
14805     OS_LOCKF_METHODDEF
14806     OS_LSEEK_METHODDEF
14807     OS_READ_METHODDEF
14808     OS_READV_METHODDEF
14809     OS_PREAD_METHODDEF
14810     OS_PREADV_METHODDEF
14811     OS_WRITE_METHODDEF
14812     OS_WRITEV_METHODDEF
14813     OS_PWRITE_METHODDEF
14814     OS_PWRITEV_METHODDEF
14815     OS_SENDFILE_METHODDEF
14816     OS_FSTAT_METHODDEF
14817     OS_ISATTY_METHODDEF
14818     OS_PIPE_METHODDEF
14819     OS_PIPE2_METHODDEF
14820     OS_MKFIFO_METHODDEF
14821     OS_MKNOD_METHODDEF
14822     OS_MAJOR_METHODDEF
14823     OS_MINOR_METHODDEF
14824     OS_MAKEDEV_METHODDEF
14825     OS_FTRUNCATE_METHODDEF
14826     OS_TRUNCATE_METHODDEF
14827     OS_POSIX_FALLOCATE_METHODDEF
14828     OS_POSIX_FADVISE_METHODDEF
14829     OS_PUTENV_METHODDEF
14830     OS_UNSETENV_METHODDEF
14831     OS_STRERROR_METHODDEF
14832     OS_FCHDIR_METHODDEF
14833     OS_FSYNC_METHODDEF
14834     OS_SYNC_METHODDEF
14835     OS_FDATASYNC_METHODDEF
14836     OS_WCOREDUMP_METHODDEF
14837     OS_WIFCONTINUED_METHODDEF
14838     OS_WIFSTOPPED_METHODDEF
14839     OS_WIFSIGNALED_METHODDEF
14840     OS_WIFEXITED_METHODDEF
14841     OS_WEXITSTATUS_METHODDEF
14842     OS_WTERMSIG_METHODDEF
14843     OS_WSTOPSIG_METHODDEF
14844     OS_FSTATVFS_METHODDEF
14845     OS_STATVFS_METHODDEF
14846     OS_CONFSTR_METHODDEF
14847     OS_SYSCONF_METHODDEF
14848     OS_FPATHCONF_METHODDEF
14849     OS_PATHCONF_METHODDEF
14850     OS_ABORT_METHODDEF
14851     OS__GETFULLPATHNAME_METHODDEF
14852     OS__GETDISKUSAGE_METHODDEF
14853     OS__GETFINALPATHNAME_METHODDEF
14854     OS__GETVOLUMEPATHNAME_METHODDEF
14855     OS__PATH_SPLITROOT_METHODDEF
14856     OS__PATH_NORMPATH_METHODDEF
14857     OS_GETLOADAVG_METHODDEF
14858     OS_URANDOM_METHODDEF
14859     OS_SETRESUID_METHODDEF
14860     OS_SETRESGID_METHODDEF
14861     OS_GETRESUID_METHODDEF
14862     OS_GETRESGID_METHODDEF
14863 
14864     OS_GETXATTR_METHODDEF
14865     OS_SETXATTR_METHODDEF
14866     OS_REMOVEXATTR_METHODDEF
14867     OS_LISTXATTR_METHODDEF
14868 
14869     OS_GET_TERMINAL_SIZE_METHODDEF
14870     OS_CPU_COUNT_METHODDEF
14871     OS_GET_INHERITABLE_METHODDEF
14872     OS_SET_INHERITABLE_METHODDEF
14873     OS_GET_HANDLE_INHERITABLE_METHODDEF
14874     OS_SET_HANDLE_INHERITABLE_METHODDEF
14875     OS_GET_BLOCKING_METHODDEF
14876     OS_SET_BLOCKING_METHODDEF
14877     OS_SCANDIR_METHODDEF
14878     OS_FSPATH_METHODDEF
14879     OS_GETRANDOM_METHODDEF
14880     OS_MEMFD_CREATE_METHODDEF
14881     OS_EVENTFD_METHODDEF
14882     OS_EVENTFD_READ_METHODDEF
14883     OS_EVENTFD_WRITE_METHODDEF
14884     OS__ADD_DLL_DIRECTORY_METHODDEF
14885     OS__REMOVE_DLL_DIRECTORY_METHODDEF
14886     OS_WAITSTATUS_TO_EXITCODE_METHODDEF
14887     {NULL,              NULL}            /* Sentinel */
14888 };
14889 
14890 static int
all_ins(PyObject * m)14891 all_ins(PyObject *m)
14892 {
14893 #ifdef F_OK
14894     if (PyModule_AddIntMacro(m, F_OK)) return -1;
14895 #endif
14896 #ifdef R_OK
14897     if (PyModule_AddIntMacro(m, R_OK)) return -1;
14898 #endif
14899 #ifdef W_OK
14900     if (PyModule_AddIntMacro(m, W_OK)) return -1;
14901 #endif
14902 #ifdef X_OK
14903     if (PyModule_AddIntMacro(m, X_OK)) return -1;
14904 #endif
14905 #ifdef NGROUPS_MAX
14906     if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
14907 #endif
14908 #ifdef TMP_MAX
14909     if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
14910 #endif
14911 #ifdef WCONTINUED
14912     if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
14913 #endif
14914 #ifdef WNOHANG
14915     if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
14916 #endif
14917 #ifdef WUNTRACED
14918     if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
14919 #endif
14920 #ifdef O_RDONLY
14921     if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
14922 #endif
14923 #ifdef O_WRONLY
14924     if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
14925 #endif
14926 #ifdef O_RDWR
14927     if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
14928 #endif
14929 #ifdef O_NDELAY
14930     if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
14931 #endif
14932 #ifdef O_NONBLOCK
14933     if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
14934 #endif
14935 #ifdef O_APPEND
14936     if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
14937 #endif
14938 #ifdef O_DSYNC
14939     if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
14940 #endif
14941 #ifdef O_RSYNC
14942     if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
14943 #endif
14944 #ifdef O_SYNC
14945     if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
14946 #endif
14947 #ifdef O_NOCTTY
14948     if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
14949 #endif
14950 #ifdef O_CREAT
14951     if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
14952 #endif
14953 #ifdef O_EXCL
14954     if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
14955 #endif
14956 #ifdef O_TRUNC
14957     if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
14958 #endif
14959 #ifdef O_BINARY
14960     if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
14961 #endif
14962 #ifdef O_TEXT
14963     if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
14964 #endif
14965 #ifdef O_XATTR
14966     if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
14967 #endif
14968 #ifdef O_LARGEFILE
14969     if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
14970 #endif
14971 #ifndef __GNU__
14972 #ifdef O_SHLOCK
14973     if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
14974 #endif
14975 #ifdef O_EXLOCK
14976     if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
14977 #endif
14978 #endif
14979 #ifdef O_EXEC
14980     if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
14981 #endif
14982 #ifdef O_SEARCH
14983     if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
14984 #endif
14985 #ifdef O_PATH
14986     if (PyModule_AddIntMacro(m, O_PATH)) return -1;
14987 #endif
14988 #ifdef O_TTY_INIT
14989     if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
14990 #endif
14991 #ifdef O_TMPFILE
14992     if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
14993 #endif
14994 #ifdef PRIO_PROCESS
14995     if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
14996 #endif
14997 #ifdef PRIO_PGRP
14998     if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
14999 #endif
15000 #ifdef PRIO_USER
15001     if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
15002 #endif
15003 #ifdef O_CLOEXEC
15004     if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
15005 #endif
15006 #ifdef O_ACCMODE
15007     if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
15008 #endif
15009 #ifdef O_EVTONLY
15010     if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
15011 #endif
15012 #ifdef O_FSYNC
15013     if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
15014 #endif
15015 #ifdef O_SYMLINK
15016     if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
15017 #endif
15018 
15019 #ifdef SEEK_HOLE
15020     if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
15021 #endif
15022 #ifdef SEEK_DATA
15023     if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
15024 #endif
15025 
15026 /* MS Windows */
15027 #ifdef O_NOINHERIT
15028     /* Don't inherit in child processes. */
15029     if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
15030 #endif
15031 #ifdef _O_SHORT_LIVED
15032     /* Optimize for short life (keep in memory). */
15033     /* MS forgot to define this one with a non-underscore form too. */
15034     if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
15035 #endif
15036 #ifdef O_TEMPORARY
15037     /* Automatically delete when last handle is closed. */
15038     if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
15039 #endif
15040 #ifdef O_RANDOM
15041     /* Optimize for random access. */
15042     if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
15043 #endif
15044 #ifdef O_SEQUENTIAL
15045     /* Optimize for sequential access. */
15046     if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
15047 #endif
15048 
15049 /* GNU extensions. */
15050 #ifdef O_ASYNC
15051     /* Send a SIGIO signal whenever input or output
15052        becomes available on file descriptor */
15053     if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
15054 #endif
15055 #ifdef O_DIRECT
15056     /* Direct disk access. */
15057     if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
15058 #endif
15059 #ifdef O_DIRECTORY
15060     /* Must be a directory.      */
15061     if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
15062 #endif
15063 #ifdef O_NOFOLLOW
15064     /* Do not follow links.      */
15065     if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
15066 #endif
15067 #ifdef O_NOFOLLOW_ANY
15068     if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
15069 #endif
15070 #ifdef O_NOLINKS
15071     /* Fails if link count of the named file is greater than 1 */
15072     if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
15073 #endif
15074 #ifdef O_NOATIME
15075     /* Do not update the access time. */
15076     if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
15077 #endif
15078 
15079     /* These come from sysexits.h */
15080 #ifdef EX_OK
15081     if (PyModule_AddIntMacro(m, EX_OK)) return -1;
15082 #endif /* EX_OK */
15083 #ifdef EX_USAGE
15084     if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
15085 #endif /* EX_USAGE */
15086 #ifdef EX_DATAERR
15087     if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
15088 #endif /* EX_DATAERR */
15089 #ifdef EX_NOINPUT
15090     if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
15091 #endif /* EX_NOINPUT */
15092 #ifdef EX_NOUSER
15093     if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
15094 #endif /* EX_NOUSER */
15095 #ifdef EX_NOHOST
15096     if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
15097 #endif /* EX_NOHOST */
15098 #ifdef EX_UNAVAILABLE
15099     if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
15100 #endif /* EX_UNAVAILABLE */
15101 #ifdef EX_SOFTWARE
15102     if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
15103 #endif /* EX_SOFTWARE */
15104 #ifdef EX_OSERR
15105     if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
15106 #endif /* EX_OSERR */
15107 #ifdef EX_OSFILE
15108     if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
15109 #endif /* EX_OSFILE */
15110 #ifdef EX_CANTCREAT
15111     if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
15112 #endif /* EX_CANTCREAT */
15113 #ifdef EX_IOERR
15114     if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
15115 #endif /* EX_IOERR */
15116 #ifdef EX_TEMPFAIL
15117     if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
15118 #endif /* EX_TEMPFAIL */
15119 #ifdef EX_PROTOCOL
15120     if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
15121 #endif /* EX_PROTOCOL */
15122 #ifdef EX_NOPERM
15123     if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
15124 #endif /* EX_NOPERM */
15125 #ifdef EX_CONFIG
15126     if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
15127 #endif /* EX_CONFIG */
15128 #ifdef EX_NOTFOUND
15129     if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
15130 #endif /* EX_NOTFOUND */
15131 
15132     /* statvfs */
15133 #ifdef ST_RDONLY
15134     if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
15135 #endif /* ST_RDONLY */
15136 #ifdef ST_NOSUID
15137     if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
15138 #endif /* ST_NOSUID */
15139 
15140        /* GNU extensions */
15141 #ifdef ST_NODEV
15142     if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
15143 #endif /* ST_NODEV */
15144 #ifdef ST_NOEXEC
15145     if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
15146 #endif /* ST_NOEXEC */
15147 #ifdef ST_SYNCHRONOUS
15148     if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
15149 #endif /* ST_SYNCHRONOUS */
15150 #ifdef ST_MANDLOCK
15151     if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
15152 #endif /* ST_MANDLOCK */
15153 #ifdef ST_WRITE
15154     if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
15155 #endif /* ST_WRITE */
15156 #ifdef ST_APPEND
15157     if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
15158 #endif /* ST_APPEND */
15159 #ifdef ST_NOATIME
15160     if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
15161 #endif /* ST_NOATIME */
15162 #ifdef ST_NODIRATIME
15163     if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
15164 #endif /* ST_NODIRATIME */
15165 #ifdef ST_RELATIME
15166     if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
15167 #endif /* ST_RELATIME */
15168 
15169     /* FreeBSD sendfile() constants */
15170 #ifdef SF_NODISKIO
15171     if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
15172 #endif
15173 #ifdef SF_MNOWAIT
15174     if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
15175 #endif
15176 #ifdef SF_SYNC
15177     if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
15178 #endif
15179 
15180     /* constants for posix_fadvise */
15181 #ifdef POSIX_FADV_NORMAL
15182     if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
15183 #endif
15184 #ifdef POSIX_FADV_SEQUENTIAL
15185     if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
15186 #endif
15187 #ifdef POSIX_FADV_RANDOM
15188     if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
15189 #endif
15190 #ifdef POSIX_FADV_NOREUSE
15191     if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
15192 #endif
15193 #ifdef POSIX_FADV_WILLNEED
15194     if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
15195 #endif
15196 #ifdef POSIX_FADV_DONTNEED
15197     if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
15198 #endif
15199 
15200     /* constants for waitid */
15201 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
15202     if (PyModule_AddIntMacro(m, P_PID)) return -1;
15203     if (PyModule_AddIntMacro(m, P_PGID)) return -1;
15204     if (PyModule_AddIntMacro(m, P_ALL)) return -1;
15205 #ifdef P_PIDFD
15206     if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
15207 #endif
15208 #endif
15209 #ifdef WEXITED
15210     if (PyModule_AddIntMacro(m, WEXITED)) return -1;
15211 #endif
15212 #ifdef WNOWAIT
15213     if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
15214 #endif
15215 #ifdef WSTOPPED
15216     if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
15217 #endif
15218 #ifdef CLD_EXITED
15219     if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
15220 #endif
15221 #ifdef CLD_KILLED
15222     if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
15223 #endif
15224 #ifdef CLD_DUMPED
15225     if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
15226 #endif
15227 #ifdef CLD_TRAPPED
15228     if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
15229 #endif
15230 #ifdef CLD_STOPPED
15231     if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
15232 #endif
15233 #ifdef CLD_CONTINUED
15234     if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
15235 #endif
15236 
15237     /* constants for lockf */
15238 #ifdef F_LOCK
15239     if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
15240 #endif
15241 #ifdef F_TLOCK
15242     if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
15243 #endif
15244 #ifdef F_ULOCK
15245     if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
15246 #endif
15247 #ifdef F_TEST
15248     if (PyModule_AddIntMacro(m, F_TEST)) return -1;
15249 #endif
15250 
15251 #ifdef RWF_DSYNC
15252     if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
15253 #endif
15254 #ifdef RWF_HIPRI
15255     if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
15256 #endif
15257 #ifdef RWF_SYNC
15258     if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
15259 #endif
15260 #ifdef RWF_NOWAIT
15261     if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
15262 #endif
15263 #ifdef RWF_APPEND
15264     if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
15265 #endif
15266 
15267 /* constants for splice */
15268 #if defined(HAVE_SPLICE) && defined(__linux__)
15269     if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
15270     if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
15271     if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
15272 #endif
15273 
15274 /* constants for posix_spawn */
15275 #ifdef HAVE_POSIX_SPAWN
15276     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
15277     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
15278     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
15279 #endif
15280 
15281 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
15282     if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
15283     if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
15284     if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
15285 #endif
15286 #ifdef HAVE_SPAWNV
15287     if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
15288     if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
15289 #endif
15290 
15291 #ifdef HAVE_SCHED_H
15292 #ifdef SCHED_OTHER
15293     if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
15294 #endif
15295 #ifdef SCHED_FIFO
15296     if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
15297 #endif
15298 #ifdef SCHED_RR
15299     if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
15300 #endif
15301 #ifdef SCHED_SPORADIC
15302     if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
15303 #endif
15304 #ifdef SCHED_BATCH
15305     if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
15306 #endif
15307 #ifdef SCHED_IDLE
15308     if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
15309 #endif
15310 #ifdef SCHED_RESET_ON_FORK
15311     if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
15312 #endif
15313 #ifdef SCHED_SYS
15314     if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
15315 #endif
15316 #ifdef SCHED_IA
15317     if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
15318 #endif
15319 #ifdef SCHED_FSS
15320     if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
15321 #endif
15322 #ifdef SCHED_FX
15323     if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
15324 #endif
15325 #endif
15326 
15327 #ifdef USE_XATTRS
15328     if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
15329     if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
15330     if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
15331 #endif
15332 
15333 #if HAVE_DECL_RTLD_LAZY
15334     if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
15335 #endif
15336 #if HAVE_DECL_RTLD_NOW
15337     if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
15338 #endif
15339 #if HAVE_DECL_RTLD_GLOBAL
15340     if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
15341 #endif
15342 #if HAVE_DECL_RTLD_LOCAL
15343     if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
15344 #endif
15345 #if HAVE_DECL_RTLD_NODELETE
15346     if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
15347 #endif
15348 #if HAVE_DECL_RTLD_NOLOAD
15349     if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
15350 #endif
15351 #if HAVE_DECL_RTLD_DEEPBIND
15352     if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
15353 #endif
15354 #if HAVE_DECL_RTLD_MEMBER
15355     if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
15356 #endif
15357 
15358 #ifdef HAVE_GETRANDOM_SYSCALL
15359     if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
15360     if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
15361 #endif
15362 #ifdef HAVE_MEMFD_CREATE
15363     if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
15364     if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
15365 #ifdef MFD_HUGETLB
15366     if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
15367 #endif
15368 #ifdef MFD_HUGE_SHIFT
15369     if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
15370 #endif
15371 #ifdef MFD_HUGE_MASK
15372     if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
15373 #endif
15374 #ifdef MFD_HUGE_64KB
15375     if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
15376 #endif
15377 #ifdef MFD_HUGE_512KB
15378     if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
15379 #endif
15380 #ifdef MFD_HUGE_1MB
15381     if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
15382 #endif
15383 #ifdef MFD_HUGE_2MB
15384     if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
15385 #endif
15386 #ifdef MFD_HUGE_8MB
15387     if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
15388 #endif
15389 #ifdef MFD_HUGE_16MB
15390     if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
15391 #endif
15392 #ifdef MFD_HUGE_32MB
15393     if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
15394 #endif
15395 #ifdef MFD_HUGE_256MB
15396     if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
15397 #endif
15398 #ifdef MFD_HUGE_512MB
15399     if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
15400 #endif
15401 #ifdef MFD_HUGE_1GB
15402     if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
15403 #endif
15404 #ifdef MFD_HUGE_2GB
15405     if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
15406 #endif
15407 #ifdef MFD_HUGE_16GB
15408     if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
15409 #endif
15410 #endif /* HAVE_MEMFD_CREATE */
15411 
15412 #ifdef HAVE_EVENTFD
15413     if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
15414     if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
15415     if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
15416 #endif
15417 
15418 #if defined(__APPLE__)
15419     if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
15420 #endif
15421 
15422 #ifdef MS_WINDOWS
15423     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
15424     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
15425     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
15426     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
15427     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
15428 #endif
15429 
15430     return 0;
15431 }
15432 
15433 
15434 
15435 #define PROBE(name, test) \
15436    static int name(void)  \
15437    {                      \
15438       if (test) {        \
15439           return 1;       \
15440       } else {            \
15441           return 0;       \
15442       }                   \
15443    }
15444 
15445 #ifdef HAVE_FSTATAT
15446 PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
15447 #endif
15448 
15449 #ifdef HAVE_FACCESSAT
15450 PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
15451 #endif
15452 
15453 #ifdef HAVE_FCHMODAT
15454 PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
15455 #endif
15456 
15457 #ifdef HAVE_FCHOWNAT
15458 PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
15459 #endif
15460 
15461 #ifdef HAVE_LINKAT
15462 PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
15463 #endif
15464 
15465 #ifdef HAVE_FDOPENDIR
15466 PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
15467 #endif
15468 
15469 #ifdef HAVE_MKDIRAT
15470 PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
15471 #endif
15472 
15473 #ifdef HAVE_RENAMEAT
15474 PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
15475 #endif
15476 
15477 #ifdef HAVE_UNLINKAT
15478 PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
15479 #endif
15480 
15481 #ifdef HAVE_OPENAT
15482 PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
15483 #endif
15484 
15485 #ifdef HAVE_READLINKAT
15486 PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
15487 #endif
15488 
15489 #ifdef HAVE_SYMLINKAT
15490 PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
15491 #endif
15492 
15493 #ifdef HAVE_FUTIMENS
15494 PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
15495 #endif
15496 
15497 #ifdef HAVE_UTIMENSAT
15498 PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
15499 #endif
15500 
15501 
15502 
15503 
15504 static const struct have_function {
15505     const char * const label;
15506     int (*probe)(void);
15507 } have_functions[] = {
15508 
15509 #ifdef HAVE_EVENTFD
15510     {"HAVE_EVENTFD", NULL},
15511 #endif
15512 
15513 #ifdef HAVE_FACCESSAT
15514     { "HAVE_FACCESSAT", probe_faccessat },
15515 #endif
15516 
15517 #ifdef HAVE_FCHDIR
15518     { "HAVE_FCHDIR", NULL },
15519 #endif
15520 
15521 #ifdef HAVE_FCHMOD
15522     { "HAVE_FCHMOD", NULL },
15523 #endif
15524 
15525 #ifdef HAVE_FCHMODAT
15526     { "HAVE_FCHMODAT", probe_fchmodat },
15527 #endif
15528 
15529 #ifdef HAVE_FCHOWN
15530     { "HAVE_FCHOWN", NULL },
15531 #endif
15532 
15533 #ifdef HAVE_FCHOWNAT
15534     { "HAVE_FCHOWNAT", probe_fchownat },
15535 #endif
15536 
15537 #ifdef HAVE_FEXECVE
15538     { "HAVE_FEXECVE", NULL },
15539 #endif
15540 
15541 #ifdef HAVE_FDOPENDIR
15542     { "HAVE_FDOPENDIR", probe_fdopendir },
15543 #endif
15544 
15545 #ifdef HAVE_FPATHCONF
15546     { "HAVE_FPATHCONF", NULL },
15547 #endif
15548 
15549 #ifdef HAVE_FSTATAT
15550     { "HAVE_FSTATAT", probe_fstatat },
15551 #endif
15552 
15553 #ifdef HAVE_FSTATVFS
15554     { "HAVE_FSTATVFS", NULL },
15555 #endif
15556 
15557 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
15558     { "HAVE_FTRUNCATE", NULL },
15559 #endif
15560 
15561 #ifdef HAVE_FUTIMENS
15562     { "HAVE_FUTIMENS", probe_futimens },
15563 #endif
15564 
15565 #ifdef HAVE_FUTIMES
15566     { "HAVE_FUTIMES", NULL },
15567 #endif
15568 
15569 #ifdef HAVE_FUTIMESAT
15570     { "HAVE_FUTIMESAT", NULL },
15571 #endif
15572 
15573 #ifdef HAVE_LINKAT
15574     { "HAVE_LINKAT", probe_linkat },
15575 #endif
15576 
15577 #ifdef HAVE_LCHFLAGS
15578     { "HAVE_LCHFLAGS", NULL },
15579 #endif
15580 
15581 #ifdef HAVE_LCHMOD
15582     { "HAVE_LCHMOD", NULL },
15583 #endif
15584 
15585 #ifdef HAVE_LCHOWN
15586     { "HAVE_LCHOWN", NULL },
15587 #endif
15588 
15589 #ifdef HAVE_LSTAT
15590     { "HAVE_LSTAT", NULL },
15591 #endif
15592 
15593 #ifdef HAVE_LUTIMES
15594     { "HAVE_LUTIMES", NULL },
15595 #endif
15596 
15597 #ifdef HAVE_MEMFD_CREATE
15598     { "HAVE_MEMFD_CREATE", NULL },
15599 #endif
15600 
15601 #ifdef HAVE_MKDIRAT
15602     { "HAVE_MKDIRAT", probe_mkdirat },
15603 #endif
15604 
15605 #ifdef HAVE_MKFIFOAT
15606     { "HAVE_MKFIFOAT", NULL },
15607 #endif
15608 
15609 #ifdef HAVE_MKNODAT
15610     { "HAVE_MKNODAT", NULL },
15611 #endif
15612 
15613 #ifdef HAVE_OPENAT
15614     { "HAVE_OPENAT", probe_openat },
15615 #endif
15616 
15617 #ifdef HAVE_READLINKAT
15618     { "HAVE_READLINKAT", probe_readlinkat },
15619 #endif
15620 
15621 #ifdef HAVE_RENAMEAT
15622     { "HAVE_RENAMEAT", probe_renameat },
15623 #endif
15624 
15625 #ifdef HAVE_SYMLINKAT
15626     { "HAVE_SYMLINKAT", probe_symlinkat },
15627 #endif
15628 
15629 #ifdef HAVE_UNLINKAT
15630     { "HAVE_UNLINKAT", probe_unlinkat },
15631 #endif
15632 
15633 #ifdef HAVE_UTIMENSAT
15634     { "HAVE_UTIMENSAT", probe_utimensat },
15635 #endif
15636 
15637 #ifdef MS_WINDOWS
15638     { "MS_WINDOWS", NULL },
15639 #endif
15640 
15641     { NULL, NULL }
15642 };
15643 
15644 
15645 static int
posixmodule_exec(PyObject * m)15646 posixmodule_exec(PyObject *m)
15647 {
15648     _posixstate *state = get_posix_state(m);
15649 
15650 #if defined(HAVE_PWRITEV)
15651     if (HAVE_PWRITEV_RUNTIME) {} else {
15652         PyObject* dct = PyModule_GetDict(m);
15653 
15654         if (dct == NULL) {
15655             return -1;
15656         }
15657 
15658         if (PyDict_DelItemString(dct, "pwritev") == -1) {
15659             PyErr_Clear();
15660         }
15661         if (PyDict_DelItemString(dct, "preadv") == -1) {
15662             PyErr_Clear();
15663         }
15664     }
15665 #endif
15666 
15667     /* Initialize environ dictionary */
15668     PyObject *v = convertenviron();
15669     Py_XINCREF(v);
15670     if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
15671         return -1;
15672     Py_DECREF(v);
15673 
15674     if (all_ins(m))
15675         return -1;
15676 
15677     if (setup_confname_tables(m))
15678         return -1;
15679 
15680     Py_INCREF(PyExc_OSError);
15681     PyModule_AddObject(m, "error", PyExc_OSError);
15682 
15683 #if defined(HAVE_WAITID) && !defined(__APPLE__)
15684     waitid_result_desc.name = MODNAME ".waitid_result";
15685     PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
15686     if (WaitidResultType == NULL) {
15687         return -1;
15688     }
15689     Py_INCREF(WaitidResultType);
15690     PyModule_AddObject(m, "waitid_result", WaitidResultType);
15691     state->WaitidResultType = WaitidResultType;
15692 #endif
15693 
15694     stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
15695     stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
15696     stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
15697     stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
15698     PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
15699     if (StatResultType == NULL) {
15700         return -1;
15701     }
15702     Py_INCREF(StatResultType);
15703     PyModule_AddObject(m, "stat_result", StatResultType);
15704     state->StatResultType = StatResultType;
15705     structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15706     ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
15707 
15708     statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
15709     PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
15710     if (StatVFSResultType == NULL) {
15711         return -1;
15712     }
15713     Py_INCREF(StatVFSResultType);
15714     PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
15715     state->StatVFSResultType = StatVFSResultType;
15716 #ifdef NEED_TICKS_PER_SECOND
15717 #  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15718     ticks_per_second = sysconf(_SC_CLK_TCK);
15719 #  elif defined(HZ)
15720     ticks_per_second = HZ;
15721 #  else
15722     ticks_per_second = 60; /* magic fallback value; may be bogus */
15723 #  endif
15724 #endif
15725 
15726 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
15727     sched_param_desc.name = MODNAME ".sched_param";
15728     PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
15729     if (SchedParamType == NULL) {
15730         return -1;
15731     }
15732     Py_INCREF(SchedParamType);
15733     PyModule_AddObject(m, "sched_param", SchedParamType);
15734     state->SchedParamType = SchedParamType;
15735     ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
15736 #endif
15737 
15738     /* initialize TerminalSize_info */
15739     PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
15740     if (TerminalSizeType == NULL) {
15741         return -1;
15742     }
15743     Py_INCREF(TerminalSizeType);
15744     PyModule_AddObject(m, "terminal_size", TerminalSizeType);
15745     state->TerminalSizeType = TerminalSizeType;
15746 
15747     /* initialize scandir types */
15748     PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
15749     if (ScandirIteratorType == NULL) {
15750         return -1;
15751     }
15752     state->ScandirIteratorType = ScandirIteratorType;
15753 
15754     PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
15755     if (DirEntryType == NULL) {
15756         return -1;
15757     }
15758     Py_INCREF(DirEntryType);
15759     PyModule_AddObject(m, "DirEntry", DirEntryType);
15760     state->DirEntryType = DirEntryType;
15761 
15762     times_result_desc.name = MODNAME ".times_result";
15763     PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
15764     if (TimesResultType == NULL) {
15765         return -1;
15766     }
15767     Py_INCREF(TimesResultType);
15768     PyModule_AddObject(m, "times_result", TimesResultType);
15769     state->TimesResultType = TimesResultType;
15770 
15771     PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
15772     if (UnameResultType == NULL) {
15773         return -1;
15774     }
15775     Py_INCREF(UnameResultType);
15776     PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
15777     state->UnameResultType = (PyObject *)UnameResultType;
15778 
15779     if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
15780         return -1;
15781 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
15782     state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
15783     if (state->struct_rusage == NULL)
15784         return -1;
15785 #endif
15786     state->st_mode = PyUnicode_InternFromString("st_mode");
15787     if (state->st_mode == NULL)
15788         return -1;
15789 
15790     /* suppress "function not used" warnings */
15791     {
15792     int ignored;
15793     fd_specified("", -1);
15794     follow_symlinks_specified("", 1);
15795     dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
15796     dir_fd_converter(Py_None, &ignored);
15797     dir_fd_unavailable(Py_None, &ignored);
15798     }
15799 
15800     /*
15801      * provide list of locally available functions
15802      * so os.py can populate support_* lists
15803      */
15804     PyObject *list = PyList_New(0);
15805     if (!list) {
15806         return -1;
15807     }
15808     for (const struct have_function *trace = have_functions; trace->label; trace++) {
15809         PyObject *unicode;
15810         if (trace->probe && !trace->probe()) continue;
15811         unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
15812         if (!unicode)
15813             return -1;
15814         if (PyList_Append(list, unicode))
15815             return -1;
15816         Py_DECREF(unicode);
15817     }
15818 
15819     PyModule_AddObject(m, "_have_functions", list);
15820 
15821     return 0;
15822 }
15823 
15824 
15825 static PyModuleDef_Slot posixmodile_slots[] = {
15826     {Py_mod_exec, posixmodule_exec},
15827     {0, NULL}
15828 };
15829 
15830 static struct PyModuleDef posixmodule = {
15831     PyModuleDef_HEAD_INIT,
15832     .m_name = MODNAME,
15833     .m_doc = posix__doc__,
15834     .m_size = sizeof(_posixstate),
15835     .m_methods = posix_methods,
15836     .m_slots = posixmodile_slots,
15837     .m_traverse = _posix_traverse,
15838     .m_clear = _posix_clear,
15839     .m_free = _posix_free,
15840 };
15841 
15842 PyMODINIT_FUNC
INITFUNC(void)15843 INITFUNC(void)
15844 {
15845     return PyModuleDef_Init(&posixmodule);
15846 }
15847 
15848 #ifdef __cplusplus
15849 }
15850 #endif
15851