• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* POSIX module implementation */
2 
3 /* This file is also used for Windows NT/MS-Win.  In that case the
4    module actually calls itself 'nt', not 'posix', and a few
5    functions are either unimplemented or implemented differently.  The source
6    assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
7    of the compiler used.  Different compilers define their own feature
8    test macro, e.g. '_MSC_VER'. */
9 
10 #define PY_SSIZE_T_CLEAN
11 
12 #include "Python.h"
13 #ifdef MS_WINDOWS
14    /* include <windows.h> early to avoid conflict with pycore_condvar.h:
15 
16         #define WIN32_LEAN_AND_MEAN
17         #include <windows.h>
18 
19       FSCTL_GET_REPARSE_POINT is not exported with WIN32_LEAN_AND_MEAN. */
20 #  include <windows.h>
21 #endif
22 
23 #include "pycore_ceval.h"         // _PyEval_ReInitThreads()
24 #include "pycore_import.h"        // _PyImport_ReInitLock()
25 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
26 #include "structmember.h"         // PyMemberDef
27 #ifndef MS_WINDOWS
28 #  include "posixmodule.h"
29 #else
30 #  include "winreparse.h"
31 #endif
32 
33 /* On android API level 21, 'AT_EACCESS' is not declared although
34  * HAVE_FACCESSAT is defined. */
35 #ifdef __ANDROID__
36 #  undef HAVE_FACCESSAT
37 #endif
38 
39 #include <stdio.h>  /* needed for ctermid() */
40 
41 /*
42  * A number of APIs are available on macOS from a certain macOS version.
43  * To support building with a new SDK while deploying to older versions
44  * the availability test is split into two:
45  *   - HAVE_<FUNCTION>:  The configure check for compile time availability
46  *   - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
47  *
48  * The latter is always true when not on macOS, or when using a compiler
49  * that does not support __has_builtin (older versions of Xcode).
50  *
51  * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
52  *    if (HAVE_<FUNCTION>_RUNTIME) { ... }
53  *
54  * In mixing the test with other tests or using negations will result in compile
55  * errors.
56  */
57 #if defined(__APPLE__)
58 
59 #if defined(__has_builtin)
60 #if __has_builtin(__builtin_available)
61 #define HAVE_BUILTIN_AVAILABLE 1
62 #endif
63 #endif
64 
65 #ifdef HAVE_BUILTIN_AVAILABLE
66 #  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
67 #  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
68 #  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
69 #  define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
70 #  define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
71 #  define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
72 #  define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
73 #  define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
74 #  define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
75 #  define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
76 #  define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
77 #  define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
78 #  define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
79 #  define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
80 #  define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
81 
82 #  define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
83 
84 #else /* Xcode 8 or earlier */
85 
86    /* __builtin_available is not present in these compilers, but
87     * some of the symbols might be weak linked (10.10 SDK or later
88     * deploying on 10.9.
89     *
90     * Fall back to the older style of availability checking for
91     * symbols introduced in macOS 10.10.
92     */
93 
94 #  ifdef HAVE_FSTATAT
95 #    define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
96 #  endif
97 
98 #  ifdef HAVE_FACCESSAT
99 #    define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
100 #  endif
101 
102 #  ifdef HAVE_FCHMODAT
103 #    define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
104 #  endif
105 
106 #  ifdef HAVE_FCHOWNAT
107 #    define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
108 #  endif
109 
110 #  ifdef HAVE_LINKAT
111 #    define HAVE_LINKAT_RUNTIME (linkat != NULL)
112 #  endif
113 
114 #  ifdef HAVE_FDOPENDIR
115 #    define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
116 #  endif
117 
118 #  ifdef HAVE_MKDIRAT
119 #    define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
120 #  endif
121 
122 #  ifdef HAVE_RENAMEAT
123 #    define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
124 #  endif
125 
126 #  ifdef HAVE_UNLINKAT
127 #    define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
128 #  endif
129 
130 #  ifdef HAVE_OPENAT
131 #    define HAVE_OPENAT_RUNTIME (openat != NULL)
132 #  endif
133 
134 #  ifdef HAVE_READLINKAT
135 #    define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
136 #  endif
137 
138 #  ifdef HAVE_SYMLINKAT
139 #    define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
140 #  endif
141 
142 #endif
143 
144 #ifdef HAVE_FUTIMESAT
145 /* Some of the logic for weak linking depends on this assertion */
146 # error "HAVE_FUTIMESAT unexpectedly defined"
147 #endif
148 
149 #else
150 #  define HAVE_FSTATAT_RUNTIME 1
151 #  define HAVE_FACCESSAT_RUNTIME 1
152 #  define HAVE_FCHMODAT_RUNTIME 1
153 #  define HAVE_FCHOWNAT_RUNTIME 1
154 #  define HAVE_LINKAT_RUNTIME 1
155 #  define HAVE_FDOPENDIR_RUNTIME 1
156 #  define HAVE_MKDIRAT_RUNTIME 1
157 #  define HAVE_RENAMEAT_RUNTIME 1
158 #  define HAVE_UNLINKAT_RUNTIME 1
159 #  define HAVE_OPENAT_RUNTIME 1
160 #  define HAVE_READLINKAT_RUNTIME 1
161 #  define HAVE_SYMLINKAT_RUNTIME 1
162 #  define HAVE_FUTIMENS_RUNTIME 1
163 #  define HAVE_UTIMENSAT_RUNTIME 1
164 #  define HAVE_PWRITEV_RUNTIME 1
165 #endif
166 
167 
168 #ifdef __cplusplus
169 extern "C" {
170 #endif
171 
172 PyDoc_STRVAR(posix__doc__,
173 "This module provides access to operating system functionality that is\n\
174 standardized by the C Standard and the POSIX standard (a thinly\n\
175 disguised Unix interface).  Refer to the library manual and\n\
176 corresponding Unix manual entries for more information on calls.");
177 
178 
179 #ifdef HAVE_SYS_UIO_H
180 #  include <sys/uio.h>
181 #endif
182 
183 #ifdef HAVE_SYS_SYSMACROS_H
184 /* GNU C Library: major(), minor(), makedev() */
185 #  include <sys/sysmacros.h>
186 #endif
187 
188 #ifdef HAVE_SYS_TYPES_H
189 #  include <sys/types.h>
190 #endif /* HAVE_SYS_TYPES_H */
191 
192 #ifdef HAVE_SYS_STAT_H
193 #  include <sys/stat.h>
194 #endif /* HAVE_SYS_STAT_H */
195 
196 #ifdef HAVE_SYS_WAIT_H
197 #  include <sys/wait.h>           // WNOHANG
198 #endif
199 #ifdef HAVE_LINUX_WAIT_H
200 #  include <linux/wait.h>         // P_PIDFD
201 #endif
202 
203 #ifdef HAVE_SIGNAL_H
204 #  include <signal.h>
205 #endif
206 
207 #ifdef HAVE_FCNTL_H
208 #  include <fcntl.h>
209 #endif
210 
211 #ifdef HAVE_GRP_H
212 #  include <grp.h>
213 #endif
214 
215 #ifdef HAVE_SYSEXITS_H
216 #  include <sysexits.h>
217 #endif
218 
219 #ifdef HAVE_SYS_LOADAVG_H
220 #  include <sys/loadavg.h>
221 #endif
222 
223 #ifdef HAVE_SYS_SENDFILE_H
224 #  include <sys/sendfile.h>
225 #endif
226 
227 #if defined(__APPLE__)
228 #  include <copyfile.h>
229 #endif
230 
231 #ifdef HAVE_SCHED_H
232 #  include <sched.h>
233 #endif
234 
235 #ifdef HAVE_COPY_FILE_RANGE
236 #  include <unistd.h>
237 #endif
238 
239 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
240 #  undef HAVE_SCHED_SETAFFINITY
241 #endif
242 
243 #if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
244 #  define USE_XATTRS
245 #endif
246 
247 #ifdef USE_XATTRS
248 #  include <sys/xattr.h>
249 #endif
250 
251 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
252 #  ifdef HAVE_SYS_SOCKET_H
253 #    include <sys/socket.h>
254 #  endif
255 #endif
256 
257 #ifdef HAVE_DLFCN_H
258 #  include <dlfcn.h>
259 #endif
260 
261 #ifdef __hpux
262 #  include <sys/mpctl.h>
263 #endif
264 
265 #if defined(__DragonFly__) || \
266     defined(__OpenBSD__)   || \
267     defined(__FreeBSD__)   || \
268     defined(__NetBSD__)    || \
269     defined(__APPLE__)
270 #  include <sys/sysctl.h>
271 #endif
272 
273 #ifdef HAVE_LINUX_RANDOM_H
274 #  include <linux/random.h>
275 #endif
276 #ifdef HAVE_GETRANDOM_SYSCALL
277 #  include <sys/syscall.h>
278 #endif
279 
280 #if defined(MS_WINDOWS)
281 #  define TERMSIZE_USE_CONIO
282 #elif defined(HAVE_SYS_IOCTL_H)
283 #  include <sys/ioctl.h>
284 #  if defined(HAVE_TERMIOS_H)
285 #    include <termios.h>
286 #  endif
287 #  if defined(TIOCGWINSZ)
288 #    define TERMSIZE_USE_IOCTL
289 #  endif
290 #endif /* MS_WINDOWS */
291 
292 /* Various compilers have only certain posix functions */
293 /* XXX Gosh I wish these were all moved into pyconfig.h */
294 #if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
295 #  define HAVE_OPENDIR    1
296 #  define HAVE_SYSTEM     1
297 #  include <process.h>
298 #else
299 #  ifdef _MSC_VER
300      /* Microsoft compiler */
301 #    define HAVE_GETPPID    1
302 #    define HAVE_GETLOGIN   1
303 #    define HAVE_SPAWNV     1
304 #    define HAVE_EXECV      1
305 #    define HAVE_WSPAWNV    1
306 #    define HAVE_WEXECV     1
307 #    define HAVE_PIPE       1
308 #    define HAVE_SYSTEM     1
309 #    define HAVE_CWAIT      1
310 #    define HAVE_FSYNC      1
311 #    define fsync _commit
312 #  else
313      /* Unix functions that the configure script doesn't check for */
314 #    ifndef __VXWORKS__
315 #      define HAVE_EXECV      1
316 #      define HAVE_FORK       1
317 #      if defined(__USLC__) && defined(__SCO_VERSION__)       /* SCO UDK Compiler */
318 #        define HAVE_FORK1      1
319 #      endif
320 #    endif
321 #    define HAVE_GETEGID    1
322 #    define HAVE_GETEUID    1
323 #    define HAVE_GETGID     1
324 #    define HAVE_GETPPID    1
325 #    define HAVE_GETUID     1
326 #    define HAVE_KILL       1
327 #    define HAVE_OPENDIR    1
328 #    define HAVE_PIPE       1
329 #    define HAVE_SYSTEM     1
330 #    define HAVE_WAIT       1
331 #    define HAVE_TTYNAME    1
332 #  endif  /* _MSC_VER */
333 #endif  /* ! __WATCOMC__ || __QNX__ */
334 
335 _Py_IDENTIFIER(__fspath__);
336 
337 /*[clinic input]
338 # one of the few times we lie about this name!
339 module os
340 [clinic start generated code]*/
341 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
342 
343 #ifndef _MSC_VER
344 
345 #if defined(__sgi)&&_COMPILER_VERSION>=700
346 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
347    (default) */
348 extern char        *ctermid_r(char *);
349 #endif
350 
351 #endif /* !_MSC_VER */
352 
353 #if defined(__VXWORKS__)
354 #  include <vxCpuLib.h>
355 #  include <rtpLib.h>
356 #  include <wait.h>
357 #  include <taskLib.h>
358 #  ifndef _P_WAIT
359 #    define _P_WAIT          0
360 #    define _P_NOWAIT        1
361 #    define _P_NOWAITO       1
362 #  endif
363 #endif /* __VXWORKS__ */
364 
365 #ifdef HAVE_POSIX_SPAWN
366 #  include <spawn.h>
367 #endif
368 
369 #ifdef HAVE_UTIME_H
370 #  include <utime.h>
371 #endif /* HAVE_UTIME_H */
372 
373 #ifdef HAVE_SYS_UTIME_H
374 #  include <sys/utime.h>
375 #  define HAVE_UTIME_H /* pretend we do for the rest of this file */
376 #endif /* HAVE_SYS_UTIME_H */
377 
378 #ifdef HAVE_SYS_TIMES_H
379 #  include <sys/times.h>
380 #endif /* HAVE_SYS_TIMES_H */
381 
382 #ifdef HAVE_SYS_PARAM_H
383 #  include <sys/param.h>
384 #endif /* HAVE_SYS_PARAM_H */
385 
386 #ifdef HAVE_SYS_UTSNAME_H
387 #  include <sys/utsname.h>
388 #endif /* HAVE_SYS_UTSNAME_H */
389 
390 #ifdef HAVE_DIRENT_H
391 #  include <dirent.h>
392 #  define NAMLEN(dirent) strlen((dirent)->d_name)
393 #else
394 #  if defined(__WATCOMC__) && !defined(__QNX__)
395 #    include <direct.h>
396 #    define NAMLEN(dirent) strlen((dirent)->d_name)
397 #  else
398 #    define dirent direct
399 #    define NAMLEN(dirent) (dirent)->d_namlen
400 #  endif
401 #  ifdef HAVE_SYS_NDIR_H
402 #    include <sys/ndir.h>
403 #  endif
404 #  ifdef HAVE_SYS_DIR_H
405 #    include <sys/dir.h>
406 #  endif
407 #  ifdef HAVE_NDIR_H
408 #    include <ndir.h>
409 #  endif
410 #endif
411 
412 #ifdef _MSC_VER
413 #  ifdef HAVE_DIRECT_H
414 #    include <direct.h>
415 #  endif
416 #  ifdef HAVE_IO_H
417 #    include <io.h>
418 #  endif
419 #  ifdef HAVE_PROCESS_H
420 #    include <process.h>
421 #  endif
422 #  ifndef IO_REPARSE_TAG_SYMLINK
423 #    define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
424 #  endif
425 #  ifndef IO_REPARSE_TAG_MOUNT_POINT
426 #    define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
427 #  endif
428 #  include "osdefs.h"             // SEP
429 #  include <malloc.h>
430 #  include <windows.h>
431 #  include <shellapi.h>           // ShellExecute()
432 #  include <lmcons.h>             // UNLEN
433 #  define HAVE_SYMLINK
434 #endif /* _MSC_VER */
435 
436 #ifndef MAXPATHLEN
437 #  if defined(PATH_MAX) && PATH_MAX > 1024
438 #    define MAXPATHLEN PATH_MAX
439 #  else
440 #    define MAXPATHLEN 1024
441 #  endif
442 #endif /* MAXPATHLEN */
443 
444 #ifdef UNION_WAIT
445    /* Emulate some macros on systems that have a union instead of macros */
446 #  ifndef WIFEXITED
447 #    define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
448 #  endif
449 #  ifndef WEXITSTATUS
450 #    define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
451 #  endif
452 #  ifndef WTERMSIG
453 #    define WTERMSIG(u_wait) ((u_wait).w_termsig)
454 #  endif
455 #  define WAIT_TYPE union wait
456 #  define WAIT_STATUS_INT(s) (s.w_status)
457 #else
458    /* !UNION_WAIT */
459 #  define WAIT_TYPE int
460 #  define WAIT_STATUS_INT(s) (s)
461 #endif /* UNION_WAIT */
462 
463 /* Don't use the "_r" form if we don't need it (also, won't have a
464    prototype for it, at least on Solaris -- maybe others as well?). */
465 #if defined(HAVE_CTERMID_R)
466 #  define USE_CTERMID_R
467 #endif
468 
469 /* choose the appropriate stat and fstat functions and return structs */
470 #undef STAT
471 #undef FSTAT
472 #undef STRUCT_STAT
473 #ifdef MS_WINDOWS
474 #  define STAT win32_stat
475 #  define LSTAT win32_lstat
476 #  define FSTAT _Py_fstat_noraise
477 #  define STRUCT_STAT struct _Py_stat_struct
478 #else
479 #  define STAT stat
480 #  define LSTAT lstat
481 #  define FSTAT fstat
482 #  define STRUCT_STAT struct stat
483 #endif
484 
485 #if defined(MAJOR_IN_MKDEV)
486 #  include <sys/mkdev.h>
487 #else
488 #  if defined(MAJOR_IN_SYSMACROS)
489 #    include <sys/sysmacros.h>
490 #  endif
491 #  if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
492 #    include <sys/mkdev.h>
493 #  endif
494 #endif
495 
496 #ifdef MS_WINDOWS
497 #  define INITFUNC PyInit_nt
498 #  define MODNAME "nt"
499 #else
500 #  define INITFUNC PyInit_posix
501 #  define MODNAME "posix"
502 #endif
503 
504 #if defined(__sun)
505 /* Something to implement in autoconf, not present in autoconf 2.69 */
506 #  define HAVE_STRUCT_STAT_ST_FSTYPE 1
507 #endif
508 
509 /* memfd_create is either defined in sys/mman.h or sys/memfd.h
510  * linux/memfd.h defines additional flags
511  */
512 #ifdef HAVE_SYS_MMAN_H
513 #  include <sys/mman.h>
514 #endif
515 #ifdef HAVE_SYS_MEMFD_H
516 #  include <sys/memfd.h>
517 #endif
518 #ifdef HAVE_LINUX_MEMFD_H
519 #  include <linux/memfd.h>
520 #endif
521 
522 #ifdef _Py_MEMORY_SANITIZER
523 #  include <sanitizer/msan_interface.h>
524 #endif
525 
526 #ifdef HAVE_FORK
527 static void
run_at_forkers(PyObject * lst,int reverse)528 run_at_forkers(PyObject *lst, int reverse)
529 {
530     Py_ssize_t i;
531     PyObject *cpy;
532 
533     if (lst != NULL) {
534         assert(PyList_CheckExact(lst));
535 
536         /* Use a list copy in case register_at_fork() is called from
537          * one of the callbacks.
538          */
539         cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
540         if (cpy == NULL)
541             PyErr_WriteUnraisable(lst);
542         else {
543             if (reverse)
544                 PyList_Reverse(cpy);
545             for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
546                 PyObject *func, *res;
547                 func = PyList_GET_ITEM(cpy, i);
548                 res = _PyObject_CallNoArg(func);
549                 if (res == NULL)
550                     PyErr_WriteUnraisable(func);
551                 else
552                     Py_DECREF(res);
553             }
554             Py_DECREF(cpy);
555         }
556     }
557 }
558 
559 void
PyOS_BeforeFork(void)560 PyOS_BeforeFork(void)
561 {
562     run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1);
563 
564     _PyImport_AcquireLock();
565 }
566 
567 void
PyOS_AfterFork_Parent(void)568 PyOS_AfterFork_Parent(void)
569 {
570     if (_PyImport_ReleaseLock() <= 0)
571         Py_FatalError("failed releasing import lock after fork");
572 
573     run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0);
574 }
575 
576 void
PyOS_AfterFork_Child(void)577 PyOS_AfterFork_Child(void)
578 {
579     _PyRuntimeState *runtime = &_PyRuntime;
580     _PyGILState_Reinit(runtime);
581     _PyEval_ReInitThreads(runtime);
582     _PyImport_ReInitLock();
583     _PySignal_AfterFork();
584     _PyRuntimeState_ReInitThreads(runtime);
585     _PyInterpreterState_DeleteExceptMain(runtime);
586 
587     run_at_forkers(_PyInterpreterState_GET()->after_forkers_child, 0);
588 }
589 
590 static int
register_at_forker(PyObject ** lst,PyObject * func)591 register_at_forker(PyObject **lst, PyObject *func)
592 {
593     if (func == NULL)  /* nothing to register? do nothing. */
594         return 0;
595     if (*lst == NULL) {
596         *lst = PyList_New(0);
597         if (*lst == NULL)
598             return -1;
599     }
600     return PyList_Append(*lst, func);
601 }
602 #endif  /* HAVE_FORK */
603 
604 
605 /* Legacy wrapper */
606 void
PyOS_AfterFork(void)607 PyOS_AfterFork(void)
608 {
609 #ifdef HAVE_FORK
610     PyOS_AfterFork_Child();
611 #endif
612 }
613 
614 
615 #ifdef MS_WINDOWS
616 /* defined in fileutils.c */
617 void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
618 void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
619                                             ULONG, struct _Py_stat_struct *);
620 #endif
621 
622 
623 #ifndef MS_WINDOWS
624 PyObject *
_PyLong_FromUid(uid_t uid)625 _PyLong_FromUid(uid_t uid)
626 {
627     if (uid == (uid_t)-1)
628         return PyLong_FromLong(-1);
629     return PyLong_FromUnsignedLong(uid);
630 }
631 
632 PyObject *
_PyLong_FromGid(gid_t gid)633 _PyLong_FromGid(gid_t gid)
634 {
635     if (gid == (gid_t)-1)
636         return PyLong_FromLong(-1);
637     return PyLong_FromUnsignedLong(gid);
638 }
639 
640 int
_Py_Uid_Converter(PyObject * obj,uid_t * p)641 _Py_Uid_Converter(PyObject *obj, uid_t *p)
642 {
643     uid_t uid;
644     PyObject *index;
645     int overflow;
646     long result;
647     unsigned long uresult;
648 
649     index = PyNumber_Index(obj);
650     if (index == NULL) {
651         PyErr_Format(PyExc_TypeError,
652                      "uid should be integer, not %.200s",
653                      _PyType_Name(Py_TYPE(obj)));
654         return 0;
655     }
656 
657     /*
658      * Handling uid_t is complicated for two reasons:
659      *  * Although uid_t is (always?) unsigned, it still
660      *    accepts -1.
661      *  * We don't know its size in advance--it may be
662      *    bigger than an int, or it may be smaller than
663      *    a long.
664      *
665      * So a bit of defensive programming is in order.
666      * Start with interpreting the value passed
667      * in as a signed long and see if it works.
668      */
669 
670     result = PyLong_AsLongAndOverflow(index, &overflow);
671 
672     if (!overflow) {
673         uid = (uid_t)result;
674 
675         if (result == -1) {
676             if (PyErr_Occurred())
677                 goto fail;
678             /* It's a legitimate -1, we're done. */
679             goto success;
680         }
681 
682         /* Any other negative number is disallowed. */
683         if (result < 0)
684             goto underflow;
685 
686         /* Ensure the value wasn't truncated. */
687         if (sizeof(uid_t) < sizeof(long) &&
688             (long)uid != result)
689             goto underflow;
690         goto success;
691     }
692 
693     if (overflow < 0)
694         goto underflow;
695 
696     /*
697      * Okay, the value overflowed a signed long.  If it
698      * fits in an *unsigned* long, it may still be okay,
699      * as uid_t may be unsigned long on this platform.
700      */
701     uresult = PyLong_AsUnsignedLong(index);
702     if (PyErr_Occurred()) {
703         if (PyErr_ExceptionMatches(PyExc_OverflowError))
704             goto overflow;
705         goto fail;
706     }
707 
708     uid = (uid_t)uresult;
709 
710     /*
711      * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
712      * but this value would get interpreted as (uid_t)-1  by chown
713      * and its siblings.   That's not what the user meant!  So we
714      * throw an overflow exception instead.   (We already
715      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
716      */
717     if (uid == (uid_t)-1)
718         goto overflow;
719 
720     /* Ensure the value wasn't truncated. */
721     if (sizeof(uid_t) < sizeof(long) &&
722         (unsigned long)uid != uresult)
723         goto overflow;
724     /* fallthrough */
725 
726 success:
727     Py_DECREF(index);
728     *p = uid;
729     return 1;
730 
731 underflow:
732     PyErr_SetString(PyExc_OverflowError,
733                     "uid is less than minimum");
734     goto fail;
735 
736 overflow:
737     PyErr_SetString(PyExc_OverflowError,
738                     "uid is greater than maximum");
739     /* fallthrough */
740 
741 fail:
742     Py_DECREF(index);
743     return 0;
744 }
745 
746 int
_Py_Gid_Converter(PyObject * obj,gid_t * p)747 _Py_Gid_Converter(PyObject *obj, gid_t *p)
748 {
749     gid_t gid;
750     PyObject *index;
751     int overflow;
752     long result;
753     unsigned long uresult;
754 
755     index = PyNumber_Index(obj);
756     if (index == NULL) {
757         PyErr_Format(PyExc_TypeError,
758                      "gid should be integer, not %.200s",
759                      _PyType_Name(Py_TYPE(obj)));
760         return 0;
761     }
762 
763     /*
764      * Handling gid_t is complicated for two reasons:
765      *  * Although gid_t is (always?) unsigned, it still
766      *    accepts -1.
767      *  * We don't know its size in advance--it may be
768      *    bigger than an int, or it may be smaller than
769      *    a long.
770      *
771      * So a bit of defensive programming is in order.
772      * Start with interpreting the value passed
773      * in as a signed long and see if it works.
774      */
775 
776     result = PyLong_AsLongAndOverflow(index, &overflow);
777 
778     if (!overflow) {
779         gid = (gid_t)result;
780 
781         if (result == -1) {
782             if (PyErr_Occurred())
783                 goto fail;
784             /* It's a legitimate -1, we're done. */
785             goto success;
786         }
787 
788         /* Any other negative number is disallowed. */
789         if (result < 0) {
790             goto underflow;
791         }
792 
793         /* Ensure the value wasn't truncated. */
794         if (sizeof(gid_t) < sizeof(long) &&
795             (long)gid != result)
796             goto underflow;
797         goto success;
798     }
799 
800     if (overflow < 0)
801         goto underflow;
802 
803     /*
804      * Okay, the value overflowed a signed long.  If it
805      * fits in an *unsigned* long, it may still be okay,
806      * as gid_t may be unsigned long on this platform.
807      */
808     uresult = PyLong_AsUnsignedLong(index);
809     if (PyErr_Occurred()) {
810         if (PyErr_ExceptionMatches(PyExc_OverflowError))
811             goto overflow;
812         goto fail;
813     }
814 
815     gid = (gid_t)uresult;
816 
817     /*
818      * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
819      * but this value would get interpreted as (gid_t)-1  by chown
820      * and its siblings.   That's not what the user meant!  So we
821      * throw an overflow exception instead.   (We already
822      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
823      */
824     if (gid == (gid_t)-1)
825         goto overflow;
826 
827     /* Ensure the value wasn't truncated. */
828     if (sizeof(gid_t) < sizeof(long) &&
829         (unsigned long)gid != uresult)
830         goto overflow;
831     /* fallthrough */
832 
833 success:
834     Py_DECREF(index);
835     *p = gid;
836     return 1;
837 
838 underflow:
839     PyErr_SetString(PyExc_OverflowError,
840                     "gid is less than minimum");
841     goto fail;
842 
843 overflow:
844     PyErr_SetString(PyExc_OverflowError,
845                     "gid is greater than maximum");
846     /* fallthrough */
847 
848 fail:
849     Py_DECREF(index);
850     return 0;
851 }
852 #endif /* MS_WINDOWS */
853 
854 
855 #define _PyLong_FromDev PyLong_FromLongLong
856 
857 
858 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
859 static int
_Py_Dev_Converter(PyObject * obj,void * p)860 _Py_Dev_Converter(PyObject *obj, void *p)
861 {
862     *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
863     if (PyErr_Occurred())
864         return 0;
865     return 1;
866 }
867 #endif /* HAVE_MKNOD && HAVE_MAKEDEV */
868 
869 
870 #ifdef AT_FDCWD
871 /*
872  * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
873  * without the int cast, the value gets interpreted as uint (4291925331),
874  * which doesn't play nicely with all the initializer lines in this file that
875  * look like this:
876  *      int dir_fd = DEFAULT_DIR_FD;
877  */
878 #define DEFAULT_DIR_FD (int)AT_FDCWD
879 #else
880 #define DEFAULT_DIR_FD (-100)
881 #endif
882 
883 static int
_fd_converter(PyObject * o,int * p)884 _fd_converter(PyObject *o, int *p)
885 {
886     int overflow;
887     long long_value;
888 
889     PyObject *index = PyNumber_Index(o);
890     if (index == NULL) {
891         return 0;
892     }
893 
894     assert(PyLong_Check(index));
895     long_value = PyLong_AsLongAndOverflow(index, &overflow);
896     Py_DECREF(index);
897     assert(!PyErr_Occurred());
898     if (overflow > 0 || long_value > INT_MAX) {
899         PyErr_SetString(PyExc_OverflowError,
900                         "fd is greater than maximum");
901         return 0;
902     }
903     if (overflow < 0 || long_value < INT_MIN) {
904         PyErr_SetString(PyExc_OverflowError,
905                         "fd is less than minimum");
906         return 0;
907     }
908 
909     *p = (int)long_value;
910     return 1;
911 }
912 
913 static int
dir_fd_converter(PyObject * o,void * p)914 dir_fd_converter(PyObject *o, void *p)
915 {
916     if (o == Py_None) {
917         *(int *)p = DEFAULT_DIR_FD;
918         return 1;
919     }
920     else if (PyIndex_Check(o)) {
921         return _fd_converter(o, (int *)p);
922     }
923     else {
924         PyErr_Format(PyExc_TypeError,
925                      "argument should be integer or None, not %.200s",
926                      _PyType_Name(Py_TYPE(o)));
927         return 0;
928     }
929 }
930 
931 typedef struct {
932     PyObject *billion;
933     PyObject *DirEntryType;
934     PyObject *ScandirIteratorType;
935 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
936     PyObject *SchedParamType;
937 #endif
938     PyObject *StatResultType;
939     PyObject *StatVFSResultType;
940     PyObject *TerminalSizeType;
941     PyObject *TimesResultType;
942     PyObject *UnameResultType;
943 #if defined(HAVE_WAITID) && !defined(__APPLE__)
944     PyObject *WaitidResultType;
945 #endif
946 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
947     PyObject *struct_rusage;
948 #endif
949     PyObject *st_mode;
950 } _posixstate;
951 
952 
953 static inline _posixstate*
get_posix_state(PyObject * module)954 get_posix_state(PyObject *module)
955 {
956     void *state = PyModule_GetState(module);
957     assert(state != NULL);
958     return (_posixstate *)state;
959 }
960 
961 /*
962  * A PyArg_ParseTuple "converter" function
963  * that handles filesystem paths in the manner
964  * preferred by the os module.
965  *
966  * path_converter accepts (Unicode) strings and their
967  * subclasses, and bytes and their subclasses.  What
968  * it does with the argument depends on the platform:
969  *
970  *   * On Windows, if we get a (Unicode) string we
971  *     extract the wchar_t * and return it; if we get
972  *     bytes we decode to wchar_t * and return that.
973  *
974  *   * On all other platforms, strings are encoded
975  *     to bytes using PyUnicode_FSConverter, then we
976  *     extract the char * from the bytes object and
977  *     return that.
978  *
979  * path_converter also optionally accepts signed
980  * integers (representing open file descriptors) instead
981  * of path strings.
982  *
983  * Input fields:
984  *   path.nullable
985  *     If nonzero, the path is permitted to be None.
986  *   path.allow_fd
987  *     If nonzero, the path is permitted to be a file handle
988  *     (a signed int) instead of a string.
989  *   path.function_name
990  *     If non-NULL, path_converter will use that as the name
991  *     of the function in error messages.
992  *     (If path.function_name is NULL it omits the function name.)
993  *   path.argument_name
994  *     If non-NULL, path_converter will use that as the name
995  *     of the parameter in error messages.
996  *     (If path.argument_name is NULL it uses "path".)
997  *
998  * Output fields:
999  *   path.wide
1000  *     Points to the path if it was expressed as Unicode
1001  *     and was not encoded.  (Only used on Windows.)
1002  *   path.narrow
1003  *     Points to the path if it was expressed as bytes,
1004  *     or it was Unicode and was encoded to bytes. (On Windows,
1005  *     is a non-zero integer if the path was expressed as bytes.
1006  *     The type is deliberately incompatible to prevent misuse.)
1007  *   path.fd
1008  *     Contains a file descriptor if path.accept_fd was true
1009  *     and the caller provided a signed integer instead of any
1010  *     sort of string.
1011  *
1012  *     WARNING: if your "path" parameter is optional, and is
1013  *     unspecified, path_converter will never get called.
1014  *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1015  *     yourself!
1016  *   path.length
1017  *     The length of the path in characters, if specified as
1018  *     a string.
1019  *   path.object
1020  *     The original object passed in (if get a PathLike object,
1021  *     the result of PyOS_FSPath() is treated as the original object).
1022  *     Own a reference to the object.
1023  *   path.cleanup
1024  *     For internal use only.  May point to a temporary object.
1025  *     (Pay no attention to the man behind the curtain.)
1026  *
1027  *   At most one of path.wide or path.narrow will be non-NULL.
1028  *   If path was None and path.nullable was set,
1029  *     or if path was an integer and path.allow_fd was set,
1030  *     both path.wide and path.narrow will be NULL
1031  *     and path.length will be 0.
1032  *
1033  *   path_converter takes care to not write to the path_t
1034  *   unless it's successful.  However it must reset the
1035  *   "cleanup" field each time it's called.
1036  *
1037  * Use as follows:
1038  *      path_t path;
1039  *      memset(&path, 0, sizeof(path));
1040  *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1041  *      // ... use values from path ...
1042  *      path_cleanup(&path);
1043  *
1044  * (Note that if PyArg_Parse fails you don't need to call
1045  * path_cleanup().  However it is safe to do so.)
1046  */
1047 typedef struct {
1048     const char *function_name;
1049     const char *argument_name;
1050     int nullable;
1051     int allow_fd;
1052     const wchar_t *wide;
1053 #ifdef MS_WINDOWS
1054     BOOL narrow;
1055 #else
1056     const char *narrow;
1057 #endif
1058     int fd;
1059     Py_ssize_t length;
1060     PyObject *object;
1061     PyObject *cleanup;
1062 } path_t;
1063 
1064 #ifdef MS_WINDOWS
1065 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1066     {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
1067 #else
1068 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1069     {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
1070 #endif
1071 
1072 static void
path_cleanup(path_t * path)1073 path_cleanup(path_t *path)
1074 {
1075     Py_CLEAR(path->object);
1076     Py_CLEAR(path->cleanup);
1077 }
1078 
1079 static int
path_converter(PyObject * o,void * p)1080 path_converter(PyObject *o, void *p)
1081 {
1082     path_t *path = (path_t *)p;
1083     PyObject *bytes = NULL;
1084     Py_ssize_t length = 0;
1085     int is_index, is_buffer, is_bytes, is_unicode;
1086     const char *narrow;
1087 #ifdef MS_WINDOWS
1088     PyObject *wo = NULL;
1089     const wchar_t *wide;
1090 #endif
1091 
1092 #define FORMAT_EXCEPTION(exc, fmt) \
1093     PyErr_Format(exc, "%s%s" fmt, \
1094         path->function_name ? path->function_name : "", \
1095         path->function_name ? ": "                : "", \
1096         path->argument_name ? path->argument_name : "path")
1097 
1098     /* Py_CLEANUP_SUPPORTED support */
1099     if (o == NULL) {
1100         path_cleanup(path);
1101         return 1;
1102     }
1103 
1104     /* Ensure it's always safe to call path_cleanup(). */
1105     path->object = path->cleanup = NULL;
1106     /* path->object owns a reference to the original object */
1107     Py_INCREF(o);
1108 
1109     if ((o == Py_None) && path->nullable) {
1110         path->wide = NULL;
1111 #ifdef MS_WINDOWS
1112         path->narrow = FALSE;
1113 #else
1114         path->narrow = NULL;
1115 #endif
1116         path->fd = -1;
1117         goto success_exit;
1118     }
1119 
1120     /* Only call this here so that we don't treat the return value of
1121        os.fspath() as an fd or buffer. */
1122     is_index = path->allow_fd && PyIndex_Check(o);
1123     is_buffer = PyObject_CheckBuffer(o);
1124     is_bytes = PyBytes_Check(o);
1125     is_unicode = PyUnicode_Check(o);
1126 
1127     if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
1128         /* Inline PyOS_FSPath() for better error messages. */
1129         PyObject *func, *res;
1130 
1131         func = _PyObject_LookupSpecial(o, &PyId___fspath__);
1132         if (NULL == func) {
1133             goto error_format;
1134         }
1135         res = _PyObject_CallNoArg(func);
1136         Py_DECREF(func);
1137         if (NULL == res) {
1138             goto error_exit;
1139         }
1140         else if (PyUnicode_Check(res)) {
1141             is_unicode = 1;
1142         }
1143         else if (PyBytes_Check(res)) {
1144             is_bytes = 1;
1145         }
1146         else {
1147             PyErr_Format(PyExc_TypeError,
1148                  "expected %.200s.__fspath__() to return str or bytes, "
1149                  "not %.200s", _PyType_Name(Py_TYPE(o)),
1150                  _PyType_Name(Py_TYPE(res)));
1151             Py_DECREF(res);
1152             goto error_exit;
1153         }
1154 
1155         /* still owns a reference to the original object */
1156         Py_DECREF(o);
1157         o = res;
1158     }
1159 
1160     if (is_unicode) {
1161 #ifdef MS_WINDOWS
1162         wide = PyUnicode_AsUnicodeAndSize(o, &length);
1163         if (!wide) {
1164             goto error_exit;
1165         }
1166         if (length > 32767) {
1167             FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1168             goto error_exit;
1169         }
1170         if (wcslen(wide) != length) {
1171             FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1172             goto error_exit;
1173         }
1174 
1175         path->wide = wide;
1176         path->narrow = FALSE;
1177         path->fd = -1;
1178         goto success_exit;
1179 #else
1180         if (!PyUnicode_FSConverter(o, &bytes)) {
1181             goto error_exit;
1182         }
1183 #endif
1184     }
1185     else if (is_bytes) {
1186         bytes = o;
1187         Py_INCREF(bytes);
1188     }
1189     else if (is_buffer) {
1190         /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1191            after removing support of non-bytes buffer objects. */
1192         if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
1193             "%s%s%s should be %s, not %.200s",
1194             path->function_name ? path->function_name : "",
1195             path->function_name ? ": "                : "",
1196             path->argument_name ? path->argument_name : "path",
1197             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1198                                                "integer or None" :
1199             path->allow_fd ? "string, bytes, os.PathLike or integer" :
1200             path->nullable ? "string, bytes, os.PathLike or None" :
1201                              "string, bytes or os.PathLike",
1202             _PyType_Name(Py_TYPE(o)))) {
1203             goto error_exit;
1204         }
1205         bytes = PyBytes_FromObject(o);
1206         if (!bytes) {
1207             goto error_exit;
1208         }
1209     }
1210     else if (is_index) {
1211         if (!_fd_converter(o, &path->fd)) {
1212             goto error_exit;
1213         }
1214         path->wide = NULL;
1215 #ifdef MS_WINDOWS
1216         path->narrow = FALSE;
1217 #else
1218         path->narrow = NULL;
1219 #endif
1220         goto success_exit;
1221     }
1222     else {
1223  error_format:
1224         PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1225             path->function_name ? path->function_name : "",
1226             path->function_name ? ": "                : "",
1227             path->argument_name ? path->argument_name : "path",
1228             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1229                                                "integer or None" :
1230             path->allow_fd ? "string, bytes, os.PathLike or integer" :
1231             path->nullable ? "string, bytes, os.PathLike or None" :
1232                              "string, bytes or os.PathLike",
1233             _PyType_Name(Py_TYPE(o)));
1234         goto error_exit;
1235     }
1236 
1237     length = PyBytes_GET_SIZE(bytes);
1238     narrow = PyBytes_AS_STRING(bytes);
1239     if ((size_t)length != strlen(narrow)) {
1240         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1241         goto error_exit;
1242     }
1243 
1244 #ifdef MS_WINDOWS
1245     wo = PyUnicode_DecodeFSDefaultAndSize(
1246         narrow,
1247         length
1248     );
1249     if (!wo) {
1250         goto error_exit;
1251     }
1252 
1253     wide = PyUnicode_AsUnicodeAndSize(wo, &length);
1254     if (!wide) {
1255         goto error_exit;
1256     }
1257     if (length > 32767) {
1258         FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1259         goto error_exit;
1260     }
1261     if (wcslen(wide) != length) {
1262         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1263         goto error_exit;
1264     }
1265     path->wide = wide;
1266     path->narrow = TRUE;
1267     path->cleanup = wo;
1268     Py_DECREF(bytes);
1269 #else
1270     path->wide = NULL;
1271     path->narrow = narrow;
1272     if (bytes == o) {
1273         /* Still a reference owned by path->object, don't have to
1274            worry about path->narrow is used after free. */
1275         Py_DECREF(bytes);
1276     }
1277     else {
1278         path->cleanup = bytes;
1279     }
1280 #endif
1281     path->fd = -1;
1282 
1283  success_exit:
1284     path->length = length;
1285     path->object = o;
1286     return Py_CLEANUP_SUPPORTED;
1287 
1288  error_exit:
1289     Py_XDECREF(o);
1290     Py_XDECREF(bytes);
1291 #ifdef MS_WINDOWS
1292     Py_XDECREF(wo);
1293 #endif
1294     return 0;
1295 }
1296 
1297 static void
argument_unavailable_error(const char * function_name,const char * argument_name)1298 argument_unavailable_error(const char *function_name, const char *argument_name)
1299 {
1300     PyErr_Format(PyExc_NotImplementedError,
1301         "%s%s%s unavailable on this platform",
1302         (function_name != NULL) ? function_name : "",
1303         (function_name != NULL) ? ": ": "",
1304         argument_name);
1305 }
1306 
1307 static int
dir_fd_unavailable(PyObject * o,void * p)1308 dir_fd_unavailable(PyObject *o, void *p)
1309 {
1310     int dir_fd;
1311     if (!dir_fd_converter(o, &dir_fd))
1312         return 0;
1313     if (dir_fd != DEFAULT_DIR_FD) {
1314         argument_unavailable_error(NULL, "dir_fd");
1315         return 0;
1316     }
1317     *(int *)p = dir_fd;
1318     return 1;
1319 }
1320 
1321 static int
fd_specified(const char * function_name,int fd)1322 fd_specified(const char *function_name, int fd)
1323 {
1324     if (fd == -1)
1325         return 0;
1326 
1327     argument_unavailable_error(function_name, "fd");
1328     return 1;
1329 }
1330 
1331 static int
follow_symlinks_specified(const char * function_name,int follow_symlinks)1332 follow_symlinks_specified(const char *function_name, int follow_symlinks)
1333 {
1334     if (follow_symlinks)
1335         return 0;
1336 
1337     argument_unavailable_error(function_name, "follow_symlinks");
1338     return 1;
1339 }
1340 
1341 static int
path_and_dir_fd_invalid(const char * function_name,path_t * path,int dir_fd)1342 path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1343 {
1344     if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1345 #ifndef MS_WINDOWS
1346         && !path->narrow
1347 #endif
1348     ) {
1349         PyErr_Format(PyExc_ValueError,
1350                      "%s: can't specify dir_fd without matching path",
1351                      function_name);
1352         return 1;
1353     }
1354     return 0;
1355 }
1356 
1357 static int
dir_fd_and_fd_invalid(const char * function_name,int dir_fd,int fd)1358 dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1359 {
1360     if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1361         PyErr_Format(PyExc_ValueError,
1362                      "%s: can't specify both dir_fd and fd",
1363                      function_name);
1364         return 1;
1365     }
1366     return 0;
1367 }
1368 
1369 static int
fd_and_follow_symlinks_invalid(const char * function_name,int fd,int follow_symlinks)1370 fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1371                                int follow_symlinks)
1372 {
1373     if ((fd > 0) && (!follow_symlinks)) {
1374         PyErr_Format(PyExc_ValueError,
1375                      "%s: cannot use fd and follow_symlinks together",
1376                      function_name);
1377         return 1;
1378     }
1379     return 0;
1380 }
1381 
1382 static int
dir_fd_and_follow_symlinks_invalid(const char * function_name,int dir_fd,int follow_symlinks)1383 dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1384                                    int follow_symlinks)
1385 {
1386     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1387         PyErr_Format(PyExc_ValueError,
1388                      "%s: cannot use dir_fd and follow_symlinks together",
1389                      function_name);
1390         return 1;
1391     }
1392     return 0;
1393 }
1394 
1395 #ifdef MS_WINDOWS
1396     typedef long long Py_off_t;
1397 #else
1398     typedef off_t Py_off_t;
1399 #endif
1400 
1401 static int
Py_off_t_converter(PyObject * arg,void * addr)1402 Py_off_t_converter(PyObject *arg, void *addr)
1403 {
1404 #ifdef HAVE_LARGEFILE_SUPPORT
1405     *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1406 #else
1407     *((Py_off_t *)addr) = PyLong_AsLong(arg);
1408 #endif
1409     if (PyErr_Occurred())
1410         return 0;
1411     return 1;
1412 }
1413 
1414 static PyObject *
PyLong_FromPy_off_t(Py_off_t offset)1415 PyLong_FromPy_off_t(Py_off_t offset)
1416 {
1417 #ifdef HAVE_LARGEFILE_SUPPORT
1418     return PyLong_FromLongLong(offset);
1419 #else
1420     return PyLong_FromLong(offset);
1421 #endif
1422 }
1423 
1424 #ifdef HAVE_SIGSET_T
1425 /* Convert an iterable of integers to a sigset.
1426    Return 1 on success, return 0 and raise an exception on error. */
1427 int
_Py_Sigset_Converter(PyObject * obj,void * addr)1428 _Py_Sigset_Converter(PyObject *obj, void *addr)
1429 {
1430     sigset_t *mask = (sigset_t *)addr;
1431     PyObject *iterator, *item;
1432     long signum;
1433     int overflow;
1434 
1435     // The extra parens suppress the unreachable-code warning with clang on MacOS
1436     if (sigemptyset(mask) < (0)) {
1437         /* Probably only if mask == NULL. */
1438         PyErr_SetFromErrno(PyExc_OSError);
1439         return 0;
1440     }
1441 
1442     iterator = PyObject_GetIter(obj);
1443     if (iterator == NULL) {
1444         return 0;
1445     }
1446 
1447     while ((item = PyIter_Next(iterator)) != NULL) {
1448         signum = PyLong_AsLongAndOverflow(item, &overflow);
1449         Py_DECREF(item);
1450         if (signum <= 0 || signum >= NSIG) {
1451             if (overflow || signum != -1 || !PyErr_Occurred()) {
1452                 PyErr_Format(PyExc_ValueError,
1453                              "signal number %ld out of range", signum);
1454             }
1455             goto error;
1456         }
1457         if (sigaddset(mask, (int)signum)) {
1458             if (errno != EINVAL) {
1459                 /* Probably impossible */
1460                 PyErr_SetFromErrno(PyExc_OSError);
1461                 goto error;
1462             }
1463             /* For backwards compatibility, allow idioms such as
1464              * `range(1, NSIG)` but warn about invalid signal numbers
1465              */
1466             const char msg[] =
1467                 "invalid signal number %ld, please use valid_signals()";
1468             if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1469                 goto error;
1470             }
1471         }
1472     }
1473     if (!PyErr_Occurred()) {
1474         Py_DECREF(iterator);
1475         return 1;
1476     }
1477 
1478 error:
1479     Py_DECREF(iterator);
1480     return 0;
1481 }
1482 #endif /* HAVE_SIGSET_T */
1483 
1484 #ifdef MS_WINDOWS
1485 
1486 static int
win32_get_reparse_tag(HANDLE reparse_point_handle,ULONG * reparse_tag)1487 win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1488 {
1489     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1490     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1491     DWORD n_bytes_returned;
1492 
1493     if (0 == DeviceIoControl(
1494         reparse_point_handle,
1495         FSCTL_GET_REPARSE_POINT,
1496         NULL, 0, /* in buffer */
1497         target_buffer, sizeof(target_buffer),
1498         &n_bytes_returned,
1499         NULL)) /* we're not using OVERLAPPED_IO */
1500         return FALSE;
1501 
1502     if (reparse_tag)
1503         *reparse_tag = rdb->ReparseTag;
1504 
1505     return TRUE;
1506 }
1507 
1508 #endif /* MS_WINDOWS */
1509 
1510 /* Return a dictionary corresponding to the POSIX environment table */
1511 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1512 /* On Darwin/MacOSX a shared library or framework has no access to
1513 ** environ directly, we must obtain it with _NSGetEnviron(). See also
1514 ** man environ(7).
1515 */
1516 #include <crt_externs.h>
1517 #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1518 extern char **environ;
1519 #endif /* !_MSC_VER */
1520 
1521 static PyObject *
convertenviron(void)1522 convertenviron(void)
1523 {
1524     PyObject *d;
1525 #ifdef MS_WINDOWS
1526     wchar_t **e;
1527 #else
1528     char **e;
1529 #endif
1530 
1531     d = PyDict_New();
1532     if (d == NULL)
1533         return NULL;
1534 #ifdef MS_WINDOWS
1535     /* _wenviron must be initialized in this way if the program is started
1536        through main() instead of wmain(). */
1537     _wgetenv(L"");
1538     e = _wenviron;
1539 #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1540     /* environ is not accessible as an extern in a shared object on OSX; use
1541        _NSGetEnviron to resolve it. The value changes if you add environment
1542        variables between calls to Py_Initialize, so don't cache the value. */
1543     e = *_NSGetEnviron();
1544 #else
1545     e = environ;
1546 #endif
1547     if (e == NULL)
1548         return d;
1549     for (; *e != NULL; e++) {
1550         PyObject *k;
1551         PyObject *v;
1552 #ifdef MS_WINDOWS
1553         const wchar_t *p = wcschr(*e, L'=');
1554 #else
1555         const char *p = strchr(*e, '=');
1556 #endif
1557         if (p == NULL)
1558             continue;
1559 #ifdef MS_WINDOWS
1560         k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1561 #else
1562         k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1563 #endif
1564         if (k == NULL) {
1565             Py_DECREF(d);
1566             return NULL;
1567         }
1568 #ifdef MS_WINDOWS
1569         v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1570 #else
1571         v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1572 #endif
1573         if (v == NULL) {
1574             Py_DECREF(k);
1575             Py_DECREF(d);
1576             return NULL;
1577         }
1578         if (PyDict_GetItemWithError(d, k) == NULL) {
1579             if (PyErr_Occurred() || PyDict_SetItem(d, k, v) != 0) {
1580                 Py_DECREF(v);
1581                 Py_DECREF(k);
1582                 Py_DECREF(d);
1583                 return NULL;
1584             }
1585         }
1586         Py_DECREF(k);
1587         Py_DECREF(v);
1588     }
1589     return d;
1590 }
1591 
1592 /* Set a POSIX-specific error from errno, and return NULL */
1593 
1594 static PyObject *
posix_error(void)1595 posix_error(void)
1596 {
1597     return PyErr_SetFromErrno(PyExc_OSError);
1598 }
1599 
1600 #ifdef MS_WINDOWS
1601 static PyObject *
win32_error(const char * function,const char * filename)1602 win32_error(const char* function, const char* filename)
1603 {
1604     /* XXX We should pass the function name along in the future.
1605        (winreg.c also wants to pass the function name.)
1606        This would however require an additional param to the
1607        Windows error object, which is non-trivial.
1608     */
1609     errno = GetLastError();
1610     if (filename)
1611         return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1612     else
1613         return PyErr_SetFromWindowsErr(errno);
1614 }
1615 
1616 static PyObject *
win32_error_object_err(const char * function,PyObject * filename,DWORD err)1617 win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1618 {
1619     /* XXX - see win32_error for comments on 'function' */
1620     if (filename)
1621         return PyErr_SetExcFromWindowsErrWithFilenameObject(
1622                     PyExc_OSError,
1623                     err,
1624                     filename);
1625     else
1626         return PyErr_SetFromWindowsErr(err);
1627 }
1628 
1629 static PyObject *
win32_error_object(const char * function,PyObject * filename)1630 win32_error_object(const char* function, PyObject* filename)
1631 {
1632     errno = GetLastError();
1633     return win32_error_object_err(function, filename, errno);
1634 }
1635 
1636 #endif /* MS_WINDOWS */
1637 
1638 static PyObject *
posix_path_object_error(PyObject * path)1639 posix_path_object_error(PyObject *path)
1640 {
1641     return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1642 }
1643 
1644 static PyObject *
path_object_error(PyObject * path)1645 path_object_error(PyObject *path)
1646 {
1647 #ifdef MS_WINDOWS
1648     return PyErr_SetExcFromWindowsErrWithFilenameObject(
1649                 PyExc_OSError, 0, path);
1650 #else
1651     return posix_path_object_error(path);
1652 #endif
1653 }
1654 
1655 static PyObject *
path_object_error2(PyObject * path,PyObject * path2)1656 path_object_error2(PyObject *path, PyObject *path2)
1657 {
1658 #ifdef MS_WINDOWS
1659     return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1660                 PyExc_OSError, 0, path, path2);
1661 #else
1662     return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1663 #endif
1664 }
1665 
1666 static PyObject *
path_error(path_t * path)1667 path_error(path_t *path)
1668 {
1669     return path_object_error(path->object);
1670 }
1671 
1672 static PyObject *
posix_path_error(path_t * path)1673 posix_path_error(path_t *path)
1674 {
1675     return posix_path_object_error(path->object);
1676 }
1677 
1678 static PyObject *
path_error2(path_t * path,path_t * path2)1679 path_error2(path_t *path, path_t *path2)
1680 {
1681     return path_object_error2(path->object, path2->object);
1682 }
1683 
1684 
1685 /* POSIX generic methods */
1686 
1687 static int
fildes_converter(PyObject * o,void * p)1688 fildes_converter(PyObject *o, void *p)
1689 {
1690     int fd;
1691     int *pointer = (int *)p;
1692     fd = PyObject_AsFileDescriptor(o);
1693     if (fd < 0)
1694         return 0;
1695     *pointer = fd;
1696     return 1;
1697 }
1698 
1699 static PyObject *
posix_fildes_fd(int fd,int (* func)(int))1700 posix_fildes_fd(int fd, int (*func)(int))
1701 {
1702     int res;
1703     int async_err = 0;
1704 
1705     do {
1706         Py_BEGIN_ALLOW_THREADS
1707         _Py_BEGIN_SUPPRESS_IPH
1708         res = (*func)(fd);
1709         _Py_END_SUPPRESS_IPH
1710         Py_END_ALLOW_THREADS
1711     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1712     if (res != 0)
1713         return (!async_err) ? posix_error() : NULL;
1714     Py_RETURN_NONE;
1715 }
1716 
1717 
1718 #ifdef MS_WINDOWS
1719 /* This is a reimplementation of the C library's chdir function,
1720    but one that produces Win32 errors instead of DOS error codes.
1721    chdir is essentially a wrapper around SetCurrentDirectory; however,
1722    it also needs to set "magic" environment variables indicating
1723    the per-drive current directory, which are of the form =<drive>: */
1724 static BOOL __stdcall
win32_wchdir(LPCWSTR path)1725 win32_wchdir(LPCWSTR path)
1726 {
1727     wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1728     int result;
1729     wchar_t env[4] = L"=x:";
1730 
1731     if(!SetCurrentDirectoryW(path))
1732         return FALSE;
1733     result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1734     if (!result)
1735         return FALSE;
1736     if (result > Py_ARRAY_LENGTH(path_buf)) {
1737         new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1738         if (!new_path) {
1739             SetLastError(ERROR_OUTOFMEMORY);
1740             return FALSE;
1741         }
1742         result = GetCurrentDirectoryW(result, new_path);
1743         if (!result) {
1744             PyMem_RawFree(new_path);
1745             return FALSE;
1746         }
1747     }
1748     int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1749                             wcsncmp(new_path, L"//", 2) == 0);
1750     if (!is_unc_like_path) {
1751         env[1] = new_path[0];
1752         result = SetEnvironmentVariableW(env, new_path);
1753     }
1754     if (new_path != path_buf)
1755         PyMem_RawFree(new_path);
1756     return result ? TRUE : FALSE;
1757 }
1758 #endif
1759 
1760 #ifdef MS_WINDOWS
1761 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1762    - time stamps are restricted to second resolution
1763    - file modification times suffer from forth-and-back conversions between
1764      UTC and local time
1765    Therefore, we implement our own stat, based on the Win32 API directly.
1766 */
1767 #define HAVE_STAT_NSEC 1
1768 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1769 #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1770 
1771 static void
find_data_to_file_info(WIN32_FIND_DATAW * pFileData,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1772 find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1773                        BY_HANDLE_FILE_INFORMATION *info,
1774                        ULONG *reparse_tag)
1775 {
1776     memset(info, 0, sizeof(*info));
1777     info->dwFileAttributes = pFileData->dwFileAttributes;
1778     info->ftCreationTime   = pFileData->ftCreationTime;
1779     info->ftLastAccessTime = pFileData->ftLastAccessTime;
1780     info->ftLastWriteTime  = pFileData->ftLastWriteTime;
1781     info->nFileSizeHigh    = pFileData->nFileSizeHigh;
1782     info->nFileSizeLow     = pFileData->nFileSizeLow;
1783 /*  info->nNumberOfLinks   = 1; */
1784     if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1785         *reparse_tag = pFileData->dwReserved0;
1786     else
1787         *reparse_tag = 0;
1788 }
1789 
1790 static BOOL
attributes_from_dir(LPCWSTR pszFile,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1791 attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1792 {
1793     HANDLE hFindFile;
1794     WIN32_FIND_DATAW FileData;
1795     hFindFile = FindFirstFileW(pszFile, &FileData);
1796     if (hFindFile == INVALID_HANDLE_VALUE)
1797         return FALSE;
1798     FindClose(hFindFile);
1799     find_data_to_file_info(&FileData, info, reparse_tag);
1800     return TRUE;
1801 }
1802 
1803 static int
win32_xstat_impl(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1804 win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1805                  BOOL traverse)
1806 {
1807     HANDLE hFile;
1808     BY_HANDLE_FILE_INFORMATION fileInfo;
1809     FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1810     DWORD fileType, error;
1811     BOOL isUnhandledTag = FALSE;
1812     int retval = 0;
1813 
1814     DWORD access = FILE_READ_ATTRIBUTES;
1815     DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1816     if (!traverse) {
1817         flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1818     }
1819 
1820     hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1821     if (hFile == INVALID_HANDLE_VALUE) {
1822         /* Either the path doesn't exist, or the caller lacks access. */
1823         error = GetLastError();
1824         switch (error) {
1825         case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
1826         case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1827             /* Try reading the parent directory. */
1828             if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1829                 /* Cannot read the parent directory. */
1830                 SetLastError(error);
1831                 return -1;
1832             }
1833             if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1834                 if (traverse ||
1835                     !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1836                     /* The stat call has to traverse but cannot, so fail. */
1837                     SetLastError(error);
1838                     return -1;
1839                 }
1840             }
1841             break;
1842 
1843         case ERROR_INVALID_PARAMETER:
1844             /* \\.\con requires read or write access. */
1845             hFile = CreateFileW(path, access | GENERIC_READ,
1846                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1847                         OPEN_EXISTING, flags, NULL);
1848             if (hFile == INVALID_HANDLE_VALUE) {
1849                 SetLastError(error);
1850                 return -1;
1851             }
1852             break;
1853 
1854         case ERROR_CANT_ACCESS_FILE:
1855             /* bpo37834: open unhandled reparse points if traverse fails. */
1856             if (traverse) {
1857                 traverse = FALSE;
1858                 isUnhandledTag = TRUE;
1859                 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1860                             flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1861             }
1862             if (hFile == INVALID_HANDLE_VALUE) {
1863                 SetLastError(error);
1864                 return -1;
1865             }
1866             break;
1867 
1868         default:
1869             return -1;
1870         }
1871     }
1872 
1873     if (hFile != INVALID_HANDLE_VALUE) {
1874         /* Handle types other than files on disk. */
1875         fileType = GetFileType(hFile);
1876         if (fileType != FILE_TYPE_DISK) {
1877             if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1878                 retval = -1;
1879                 goto cleanup;
1880             }
1881             DWORD fileAttributes = GetFileAttributesW(path);
1882             memset(result, 0, sizeof(*result));
1883             if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1884                 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1885                 /* \\.\pipe\ or \\.\mailslot\ */
1886                 result->st_mode = _S_IFDIR;
1887             } else if (fileType == FILE_TYPE_CHAR) {
1888                 /* \\.\nul */
1889                 result->st_mode = _S_IFCHR;
1890             } else if (fileType == FILE_TYPE_PIPE) {
1891                 /* \\.\pipe\spam */
1892                 result->st_mode = _S_IFIFO;
1893             }
1894             /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1895             goto cleanup;
1896         }
1897 
1898         /* Query the reparse tag, and traverse a non-link. */
1899         if (!traverse) {
1900             if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
1901                     &tagInfo, sizeof(tagInfo))) {
1902                 /* Allow devices that do not support FileAttributeTagInfo. */
1903                 switch (GetLastError()) {
1904                 case ERROR_INVALID_PARAMETER:
1905                 case ERROR_INVALID_FUNCTION:
1906                 case ERROR_NOT_SUPPORTED:
1907                     tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1908                     tagInfo.ReparseTag = 0;
1909                     break;
1910                 default:
1911                     retval = -1;
1912                     goto cleanup;
1913                 }
1914             } else if (tagInfo.FileAttributes &
1915                          FILE_ATTRIBUTE_REPARSE_POINT) {
1916                 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1917                     if (isUnhandledTag) {
1918                         /* Traversing previously failed for either this link
1919                            or its target. */
1920                         SetLastError(ERROR_CANT_ACCESS_FILE);
1921                         retval = -1;
1922                         goto cleanup;
1923                     }
1924                 /* Traverse a non-link, but not if traversing already failed
1925                    for an unhandled tag. */
1926                 } else if (!isUnhandledTag) {
1927                     CloseHandle(hFile);
1928                     return win32_xstat_impl(path, result, TRUE);
1929                 }
1930             }
1931         }
1932 
1933         if (!GetFileInformationByHandle(hFile, &fileInfo)) {
1934             switch (GetLastError()) {
1935             case ERROR_INVALID_PARAMETER:
1936             case ERROR_INVALID_FUNCTION:
1937             case ERROR_NOT_SUPPORTED:
1938                 /* Volumes and physical disks are block devices, e.g.
1939                    \\.\C: and \\.\PhysicalDrive0. */
1940                 memset(result, 0, sizeof(*result));
1941                 result->st_mode = 0x6000; /* S_IFBLK */
1942                 goto cleanup;
1943             }
1944             retval = -1;
1945             goto cleanup;
1946         }
1947     }
1948 
1949     _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
1950 
1951     if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
1952         /* Fix the file execute permissions. This hack sets S_IEXEC if
1953            the filename has an extension that is commonly used by files
1954            that CreateProcessW can execute. A real implementation calls
1955            GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
1956            AccessCheck to check for generic read, write, and execute
1957            access. */
1958         const wchar_t *fileExtension = wcsrchr(path, '.');
1959         if (fileExtension) {
1960             if (_wcsicmp(fileExtension, L".exe") == 0 ||
1961                 _wcsicmp(fileExtension, L".bat") == 0 ||
1962                 _wcsicmp(fileExtension, L".cmd") == 0 ||
1963                 _wcsicmp(fileExtension, L".com") == 0) {
1964                 result->st_mode |= 0111;
1965             }
1966         }
1967     }
1968 
1969 cleanup:
1970     if (hFile != INVALID_HANDLE_VALUE) {
1971         /* Preserve last error if we are failing */
1972         error = retval ? GetLastError() : 0;
1973         if (!CloseHandle(hFile)) {
1974             retval = -1;
1975         } else if (retval) {
1976             /* Restore last error */
1977             SetLastError(error);
1978         }
1979     }
1980 
1981     return retval;
1982 }
1983 
1984 static int
win32_xstat(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1985 win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
1986 {
1987     /* Protocol violation: we explicitly clear errno, instead of
1988        setting it to a POSIX error. Callers should use GetLastError. */
1989     int code = win32_xstat_impl(path, result, traverse);
1990     errno = 0;
1991     return code;
1992 }
1993 /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
1994 
1995    In Posix, stat automatically traverses symlinks and returns the stat
1996    structure for the target.  In Windows, the equivalent GetFileAttributes by
1997    default does not traverse symlinks and instead returns attributes for
1998    the symlink.
1999 
2000    Instead, we will open the file (which *does* traverse symlinks by default)
2001    and GetFileInformationByHandle(). */
2002 
2003 static int
win32_lstat(const wchar_t * path,struct _Py_stat_struct * result)2004 win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2005 {
2006     return win32_xstat(path, result, FALSE);
2007 }
2008 
2009 static int
win32_stat(const wchar_t * path,struct _Py_stat_struct * result)2010 win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2011 {
2012     return win32_xstat(path, result, TRUE);
2013 }
2014 
2015 #endif /* MS_WINDOWS */
2016 
2017 PyDoc_STRVAR(stat_result__doc__,
2018 "stat_result: Result from stat, fstat, or lstat.\n\n\
2019 This object may be accessed either as a tuple of\n\
2020   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2021 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2022 \n\
2023 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2024 or st_flags, they are available as attributes only.\n\
2025 \n\
2026 See os.stat for more information.");
2027 
2028 static PyStructSequence_Field stat_result_fields[] = {
2029     {"st_mode",    "protection bits"},
2030     {"st_ino",     "inode"},
2031     {"st_dev",     "device"},
2032     {"st_nlink",   "number of hard links"},
2033     {"st_uid",     "user ID of owner"},
2034     {"st_gid",     "group ID of owner"},
2035     {"st_size",    "total size, in bytes"},
2036     /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2037     {NULL,   "integer time of last access"},
2038     {NULL,   "integer time of last modification"},
2039     {NULL,   "integer time of last change"},
2040     {"st_atime",   "time of last access"},
2041     {"st_mtime",   "time of last modification"},
2042     {"st_ctime",   "time of last change"},
2043     {"st_atime_ns",   "time of last access in nanoseconds"},
2044     {"st_mtime_ns",   "time of last modification in nanoseconds"},
2045     {"st_ctime_ns",   "time of last change in nanoseconds"},
2046 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2047     {"st_blksize", "blocksize for filesystem I/O"},
2048 #endif
2049 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2050     {"st_blocks",  "number of blocks allocated"},
2051 #endif
2052 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2053     {"st_rdev",    "device type (if inode device)"},
2054 #endif
2055 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2056     {"st_flags",   "user defined flags for file"},
2057 #endif
2058 #ifdef HAVE_STRUCT_STAT_ST_GEN
2059     {"st_gen",    "generation number"},
2060 #endif
2061 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2062     {"st_birthtime",   "time of creation"},
2063 #endif
2064 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2065     {"st_file_attributes", "Windows file attribute bits"},
2066 #endif
2067 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2068     {"st_fstype",  "Type of filesystem"},
2069 #endif
2070 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2071     {"st_reparse_tag", "Windows reparse tag"},
2072 #endif
2073     {0}
2074 };
2075 
2076 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2077 #define ST_BLKSIZE_IDX 16
2078 #else
2079 #define ST_BLKSIZE_IDX 15
2080 #endif
2081 
2082 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2083 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2084 #else
2085 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2086 #endif
2087 
2088 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2089 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2090 #else
2091 #define ST_RDEV_IDX ST_BLOCKS_IDX
2092 #endif
2093 
2094 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2095 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2096 #else
2097 #define ST_FLAGS_IDX ST_RDEV_IDX
2098 #endif
2099 
2100 #ifdef HAVE_STRUCT_STAT_ST_GEN
2101 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
2102 #else
2103 #define ST_GEN_IDX ST_FLAGS_IDX
2104 #endif
2105 
2106 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2107 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2108 #else
2109 #define ST_BIRTHTIME_IDX ST_GEN_IDX
2110 #endif
2111 
2112 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2113 #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
2114 #else
2115 #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
2116 #endif
2117 
2118 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2119 #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2120 #else
2121 #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2122 #endif
2123 
2124 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2125 #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2126 #else
2127 #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2128 #endif
2129 
2130 static PyStructSequence_Desc stat_result_desc = {
2131     "stat_result", /* name */
2132     stat_result__doc__, /* doc */
2133     stat_result_fields,
2134     10
2135 };
2136 
2137 PyDoc_STRVAR(statvfs_result__doc__,
2138 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
2139 This object may be accessed either as a tuple of\n\
2140   (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2141 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2142 \n\
2143 See os.statvfs for more information.");
2144 
2145 static PyStructSequence_Field statvfs_result_fields[] = {
2146     {"f_bsize",  },
2147     {"f_frsize", },
2148     {"f_blocks", },
2149     {"f_bfree",  },
2150     {"f_bavail", },
2151     {"f_files",  },
2152     {"f_ffree",  },
2153     {"f_favail", },
2154     {"f_flag",   },
2155     {"f_namemax",},
2156     {"f_fsid",   },
2157     {0}
2158 };
2159 
2160 static PyStructSequence_Desc statvfs_result_desc = {
2161     "statvfs_result", /* name */
2162     statvfs_result__doc__, /* doc */
2163     statvfs_result_fields,
2164     10
2165 };
2166 
2167 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2168 PyDoc_STRVAR(waitid_result__doc__,
2169 "waitid_result: Result from waitid.\n\n\
2170 This object may be accessed either as a tuple of\n\
2171   (si_pid, si_uid, si_signo, si_status, si_code),\n\
2172 or via the attributes si_pid, si_uid, and so on.\n\
2173 \n\
2174 See os.waitid for more information.");
2175 
2176 static PyStructSequence_Field waitid_result_fields[] = {
2177     {"si_pid",  },
2178     {"si_uid", },
2179     {"si_signo", },
2180     {"si_status",  },
2181     {"si_code", },
2182     {0}
2183 };
2184 
2185 static PyStructSequence_Desc waitid_result_desc = {
2186     "waitid_result", /* name */
2187     waitid_result__doc__, /* doc */
2188     waitid_result_fields,
2189     5
2190 };
2191 #endif
2192 static newfunc structseq_new;
2193 
2194 static PyObject *
statresult_new(PyTypeObject * type,PyObject * args,PyObject * kwds)2195 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2196 {
2197     PyStructSequence *result;
2198     int i;
2199 
2200     result = (PyStructSequence*)structseq_new(type, args, kwds);
2201     if (!result)
2202         return NULL;
2203     /* If we have been initialized from a tuple,
2204        st_?time might be set to None. Initialize it
2205        from the int slots.  */
2206     for (i = 7; i <= 9; i++) {
2207         if (result->ob_item[i+3] == Py_None) {
2208             Py_DECREF(Py_None);
2209             Py_INCREF(result->ob_item[i]);
2210             result->ob_item[i+3] = result->ob_item[i];
2211         }
2212     }
2213     return (PyObject*)result;
2214 }
2215 
2216 static int
_posix_clear(PyObject * module)2217 _posix_clear(PyObject *module)
2218 {
2219     _posixstate *state = get_posix_state(module);
2220     Py_CLEAR(state->billion);
2221     Py_CLEAR(state->DirEntryType);
2222     Py_CLEAR(state->ScandirIteratorType);
2223 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2224     Py_CLEAR(state->SchedParamType);
2225 #endif
2226     Py_CLEAR(state->StatResultType);
2227     Py_CLEAR(state->StatVFSResultType);
2228     Py_CLEAR(state->TerminalSizeType);
2229     Py_CLEAR(state->TimesResultType);
2230     Py_CLEAR(state->UnameResultType);
2231 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2232     Py_CLEAR(state->WaitidResultType);
2233 #endif
2234 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2235     Py_CLEAR(state->struct_rusage);
2236 #endif
2237     Py_CLEAR(state->st_mode);
2238     return 0;
2239 }
2240 
2241 static int
_posix_traverse(PyObject * module,visitproc visit,void * arg)2242 _posix_traverse(PyObject *module, visitproc visit, void *arg)
2243 {
2244     _posixstate *state = get_posix_state(module);
2245     Py_VISIT(state->billion);
2246     Py_VISIT(state->DirEntryType);
2247     Py_VISIT(state->ScandirIteratorType);
2248 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2249     Py_VISIT(state->SchedParamType);
2250 #endif
2251     Py_VISIT(state->StatResultType);
2252     Py_VISIT(state->StatVFSResultType);
2253     Py_VISIT(state->TerminalSizeType);
2254     Py_VISIT(state->TimesResultType);
2255     Py_VISIT(state->UnameResultType);
2256 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2257     Py_VISIT(state->WaitidResultType);
2258 #endif
2259 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2260     Py_VISIT(state->struct_rusage);
2261 #endif
2262     Py_VISIT(state->st_mode);
2263     return 0;
2264 }
2265 
2266 static void
_posix_free(void * module)2267 _posix_free(void *module)
2268 {
2269    _posix_clear((PyObject *)module);
2270 }
2271 
2272 static void
fill_time(PyObject * module,PyObject * v,int index,time_t sec,unsigned long nsec)2273 fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)
2274 {
2275     PyObject *s = _PyLong_FromTime_t(sec);
2276     PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2277     PyObject *s_in_ns = NULL;
2278     PyObject *ns_total = NULL;
2279     PyObject *float_s = NULL;
2280 
2281     if (!(s && ns_fractional))
2282         goto exit;
2283 
2284     s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2285     if (!s_in_ns)
2286         goto exit;
2287 
2288     ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2289     if (!ns_total)
2290         goto exit;
2291 
2292     float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2293     if (!float_s) {
2294         goto exit;
2295     }
2296 
2297     PyStructSequence_SET_ITEM(v, index, s);
2298     PyStructSequence_SET_ITEM(v, index+3, float_s);
2299     PyStructSequence_SET_ITEM(v, index+6, ns_total);
2300     s = NULL;
2301     float_s = NULL;
2302     ns_total = NULL;
2303 exit:
2304     Py_XDECREF(s);
2305     Py_XDECREF(ns_fractional);
2306     Py_XDECREF(s_in_ns);
2307     Py_XDECREF(ns_total);
2308     Py_XDECREF(float_s);
2309 }
2310 
2311 /* pack a system stat C structure into the Python stat tuple
2312    (used by posix_stat() and posix_fstat()) */
2313 static PyObject*
_pystat_fromstructstat(PyObject * module,STRUCT_STAT * st)2314 _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2315 {
2316     unsigned long ansec, mnsec, cnsec;
2317     PyObject *StatResultType = get_posix_state(module)->StatResultType;
2318     PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2319     if (v == NULL)
2320         return NULL;
2321 
2322     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2323     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(st->st_ino));
2324     PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2325 #ifdef MS_WINDOWS
2326     PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
2327 #else
2328     PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2329 #endif
2330     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2331 #if defined(MS_WINDOWS)
2332     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2333     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2334 #else
2335     PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2336     PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2337 #endif
2338     Py_BUILD_ASSERT(sizeof(long long) >= sizeof(st->st_size));
2339     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2340 
2341 #if defined(HAVE_STAT_TV_NSEC)
2342     ansec = st->st_atim.tv_nsec;
2343     mnsec = st->st_mtim.tv_nsec;
2344     cnsec = st->st_ctim.tv_nsec;
2345 #elif defined(HAVE_STAT_TV_NSEC2)
2346     ansec = st->st_atimespec.tv_nsec;
2347     mnsec = st->st_mtimespec.tv_nsec;
2348     cnsec = st->st_ctimespec.tv_nsec;
2349 #elif defined(HAVE_STAT_NSEC)
2350     ansec = st->st_atime_nsec;
2351     mnsec = st->st_mtime_nsec;
2352     cnsec = st->st_ctime_nsec;
2353 #else
2354     ansec = mnsec = cnsec = 0;
2355 #endif
2356     fill_time(module, v, 7, st->st_atime, ansec);
2357     fill_time(module, v, 8, st->st_mtime, mnsec);
2358     fill_time(module, v, 9, st->st_ctime, cnsec);
2359 
2360 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2361     PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2362                               PyLong_FromLong((long)st->st_blksize));
2363 #endif
2364 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2365     PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2366                               PyLong_FromLong((long)st->st_blocks));
2367 #endif
2368 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2369     PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2370                               PyLong_FromLong((long)st->st_rdev));
2371 #endif
2372 #ifdef HAVE_STRUCT_STAT_ST_GEN
2373     PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2374                               PyLong_FromLong((long)st->st_gen));
2375 #endif
2376 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2377     {
2378       PyObject *val;
2379       unsigned long bsec,bnsec;
2380       bsec = (long)st->st_birthtime;
2381 #ifdef HAVE_STAT_TV_NSEC2
2382       bnsec = st->st_birthtimespec.tv_nsec;
2383 #else
2384       bnsec = 0;
2385 #endif
2386       val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2387       PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2388                                 val);
2389     }
2390 #endif
2391 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2392     PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2393                               PyLong_FromLong((long)st->st_flags));
2394 #endif
2395 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2396     PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2397                               PyLong_FromUnsignedLong(st->st_file_attributes));
2398 #endif
2399 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2400    PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2401                               PyUnicode_FromString(st->st_fstype));
2402 #endif
2403 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2404     PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2405                               PyLong_FromUnsignedLong(st->st_reparse_tag));
2406 #endif
2407 
2408     if (PyErr_Occurred()) {
2409         Py_DECREF(v);
2410         return NULL;
2411     }
2412 
2413     return v;
2414 }
2415 
2416 /* POSIX methods */
2417 
2418 
2419 static PyObject *
posix_do_stat(PyObject * module,const char * function_name,path_t * path,int dir_fd,int follow_symlinks)2420 posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2421               int dir_fd, int follow_symlinks)
2422 {
2423     STRUCT_STAT st;
2424     int result;
2425 
2426 #ifdef HAVE_FSTATAT
2427     int fstatat_unavailable = 0;
2428 #endif
2429 
2430 #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2431     if (follow_symlinks_specified(function_name, follow_symlinks))
2432         return NULL;
2433 #endif
2434 
2435     if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2436         dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2437         fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2438         return NULL;
2439 
2440     Py_BEGIN_ALLOW_THREADS
2441     if (path->fd != -1)
2442         result = FSTAT(path->fd, &st);
2443 #ifdef MS_WINDOWS
2444     else if (follow_symlinks)
2445         result = win32_stat(path->wide, &st);
2446     else
2447         result = win32_lstat(path->wide, &st);
2448 #else
2449     else
2450 #if defined(HAVE_LSTAT)
2451     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2452         result = LSTAT(path->narrow, &st);
2453     else
2454 #endif /* HAVE_LSTAT */
2455 #ifdef HAVE_FSTATAT
2456     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2457         if (HAVE_FSTATAT_RUNTIME) {
2458             result = fstatat(dir_fd, path->narrow, &st,
2459                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2460 
2461         } else {
2462             fstatat_unavailable = 1;
2463         }
2464     } else
2465 #endif /* HAVE_FSTATAT */
2466         result = STAT(path->narrow, &st);
2467 #endif /* MS_WINDOWS */
2468     Py_END_ALLOW_THREADS
2469 
2470 #ifdef HAVE_FSTATAT
2471     if (fstatat_unavailable) {
2472         argument_unavailable_error("stat", "dir_fd");
2473         return NULL;
2474     }
2475 #endif
2476 
2477     if (result != 0) {
2478         return path_error(path);
2479     }
2480 
2481     return _pystat_fromstructstat(module, &st);
2482 }
2483 
2484 /*[python input]
2485 
2486 for s in """
2487 
2488 FACCESSAT
2489 FCHMODAT
2490 FCHOWNAT
2491 FSTATAT
2492 LINKAT
2493 MKDIRAT
2494 MKFIFOAT
2495 MKNODAT
2496 OPENAT
2497 READLINKAT
2498 SYMLINKAT
2499 UNLINKAT
2500 
2501 """.strip().split():
2502     s = s.strip()
2503     print("""
2504 #ifdef HAVE_{s}
2505     #define {s}_DIR_FD_CONVERTER dir_fd_converter
2506 #else
2507     #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2508 #endif
2509 """.rstrip().format(s=s))
2510 
2511 for s in """
2512 
2513 FCHDIR
2514 FCHMOD
2515 FCHOWN
2516 FDOPENDIR
2517 FEXECVE
2518 FPATHCONF
2519 FSTATVFS
2520 FTRUNCATE
2521 
2522 """.strip().split():
2523     s = s.strip()
2524     print("""
2525 #ifdef HAVE_{s}
2526     #define PATH_HAVE_{s} 1
2527 #else
2528     #define PATH_HAVE_{s} 0
2529 #endif
2530 
2531 """.rstrip().format(s=s))
2532 [python start generated code]*/
2533 
2534 #ifdef HAVE_FACCESSAT
2535     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2536 #else
2537     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2538 #endif
2539 
2540 #ifdef HAVE_FCHMODAT
2541     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2542 #else
2543     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2544 #endif
2545 
2546 #ifdef HAVE_FCHOWNAT
2547     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2548 #else
2549     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2550 #endif
2551 
2552 #ifdef HAVE_FSTATAT
2553     #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2554 #else
2555     #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2556 #endif
2557 
2558 #ifdef HAVE_LINKAT
2559     #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2560 #else
2561     #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2562 #endif
2563 
2564 #ifdef HAVE_MKDIRAT
2565     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2566 #else
2567     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2568 #endif
2569 
2570 #ifdef HAVE_MKFIFOAT
2571     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2572 #else
2573     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2574 #endif
2575 
2576 #ifdef HAVE_MKNODAT
2577     #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2578 #else
2579     #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2580 #endif
2581 
2582 #ifdef HAVE_OPENAT
2583     #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2584 #else
2585     #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2586 #endif
2587 
2588 #ifdef HAVE_READLINKAT
2589     #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2590 #else
2591     #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2592 #endif
2593 
2594 #ifdef HAVE_SYMLINKAT
2595     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2596 #else
2597     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2598 #endif
2599 
2600 #ifdef HAVE_UNLINKAT
2601     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2602 #else
2603     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2604 #endif
2605 
2606 #ifdef HAVE_FCHDIR
2607     #define PATH_HAVE_FCHDIR 1
2608 #else
2609     #define PATH_HAVE_FCHDIR 0
2610 #endif
2611 
2612 #ifdef HAVE_FCHMOD
2613     #define PATH_HAVE_FCHMOD 1
2614 #else
2615     #define PATH_HAVE_FCHMOD 0
2616 #endif
2617 
2618 #ifdef HAVE_FCHOWN
2619     #define PATH_HAVE_FCHOWN 1
2620 #else
2621     #define PATH_HAVE_FCHOWN 0
2622 #endif
2623 
2624 #ifdef HAVE_FDOPENDIR
2625     #define PATH_HAVE_FDOPENDIR 1
2626 #else
2627     #define PATH_HAVE_FDOPENDIR 0
2628 #endif
2629 
2630 #ifdef HAVE_FEXECVE
2631     #define PATH_HAVE_FEXECVE 1
2632 #else
2633     #define PATH_HAVE_FEXECVE 0
2634 #endif
2635 
2636 #ifdef HAVE_FPATHCONF
2637     #define PATH_HAVE_FPATHCONF 1
2638 #else
2639     #define PATH_HAVE_FPATHCONF 0
2640 #endif
2641 
2642 #ifdef HAVE_FSTATVFS
2643     #define PATH_HAVE_FSTATVFS 1
2644 #else
2645     #define PATH_HAVE_FSTATVFS 0
2646 #endif
2647 
2648 #ifdef HAVE_FTRUNCATE
2649     #define PATH_HAVE_FTRUNCATE 1
2650 #else
2651     #define PATH_HAVE_FTRUNCATE 0
2652 #endif
2653 /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2654 
2655 #ifdef MS_WINDOWS
2656     #undef PATH_HAVE_FTRUNCATE
2657     #define PATH_HAVE_FTRUNCATE 1
2658 #endif
2659 
2660 /*[python input]
2661 
2662 class path_t_converter(CConverter):
2663 
2664     type = "path_t"
2665     impl_by_reference = True
2666     parse_by_reference = True
2667 
2668     converter = 'path_converter'
2669 
2670     def converter_init(self, *, allow_fd=False, nullable=False):
2671         # right now path_t doesn't support default values.
2672         # to support a default value, you'll need to override initialize().
2673         if self.default not in (unspecified, None):
2674             fail("Can't specify a default to the path_t converter!")
2675 
2676         if self.c_default not in (None, 'Py_None'):
2677             raise RuntimeError("Can't specify a c_default to the path_t converter!")
2678 
2679         self.nullable = nullable
2680         self.allow_fd = allow_fd
2681 
2682     def pre_render(self):
2683         def strify(value):
2684             if isinstance(value, str):
2685                 return value
2686             return str(int(bool(value)))
2687 
2688         # add self.py_name here when merging with posixmodule conversion
2689         self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2690             self.function.name,
2691             self.name,
2692             strify(self.nullable),
2693             strify(self.allow_fd),
2694             )
2695 
2696     def cleanup(self):
2697         return "path_cleanup(&" + self.name + ");\n"
2698 
2699 
2700 class dir_fd_converter(CConverter):
2701     type = 'int'
2702 
2703     def converter_init(self, requires=None):
2704         if self.default in (unspecified, None):
2705             self.c_default = 'DEFAULT_DIR_FD'
2706         if isinstance(requires, str):
2707             self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2708         else:
2709             self.converter = 'dir_fd_converter'
2710 
2711 class fildes_converter(CConverter):
2712     type = 'int'
2713     converter = 'fildes_converter'
2714 
2715 class uid_t_converter(CConverter):
2716     type = "uid_t"
2717     converter = '_Py_Uid_Converter'
2718 
2719 class gid_t_converter(CConverter):
2720     type = "gid_t"
2721     converter = '_Py_Gid_Converter'
2722 
2723 class dev_t_converter(CConverter):
2724     type = 'dev_t'
2725     converter = '_Py_Dev_Converter'
2726 
2727 class dev_t_return_converter(unsigned_long_return_converter):
2728     type = 'dev_t'
2729     conversion_fn = '_PyLong_FromDev'
2730     unsigned_cast = '(dev_t)'
2731 
2732 class FSConverter_converter(CConverter):
2733     type = 'PyObject *'
2734     converter = 'PyUnicode_FSConverter'
2735     def converter_init(self):
2736         if self.default is not unspecified:
2737             fail("FSConverter_converter does not support default values")
2738         self.c_default = 'NULL'
2739 
2740     def cleanup(self):
2741         return "Py_XDECREF(" + self.name + ");\n"
2742 
2743 class pid_t_converter(CConverter):
2744     type = 'pid_t'
2745     format_unit = '" _Py_PARSE_PID "'
2746 
2747 class idtype_t_converter(int_converter):
2748     type = 'idtype_t'
2749 
2750 class id_t_converter(CConverter):
2751     type = 'id_t'
2752     format_unit = '" _Py_PARSE_PID "'
2753 
2754 class intptr_t_converter(CConverter):
2755     type = 'intptr_t'
2756     format_unit = '" _Py_PARSE_INTPTR "'
2757 
2758 class Py_off_t_converter(CConverter):
2759     type = 'Py_off_t'
2760     converter = 'Py_off_t_converter'
2761 
2762 class Py_off_t_return_converter(long_return_converter):
2763     type = 'Py_off_t'
2764     conversion_fn = 'PyLong_FromPy_off_t'
2765 
2766 class path_confname_converter(CConverter):
2767     type="int"
2768     converter="conv_path_confname"
2769 
2770 class confstr_confname_converter(path_confname_converter):
2771     converter='conv_confstr_confname'
2772 
2773 class sysconf_confname_converter(path_confname_converter):
2774     converter="conv_sysconf_confname"
2775 
2776 [python start generated code]*/
2777 /*[python end generated code: output=da39a3ee5e6b4b0d input=f1c8ae8d744f6c8b]*/
2778 
2779 /*[clinic input]
2780 
2781 os.stat
2782 
2783     path : path_t(allow_fd=True)
2784         Path to be examined; can be string, bytes, a path-like object or
2785         open-file-descriptor int.
2786 
2787     *
2788 
2789     dir_fd : dir_fd(requires='fstatat') = None
2790         If not None, it should be a file descriptor open to a directory,
2791         and path should be a relative string; path will then be relative to
2792         that directory.
2793 
2794     follow_symlinks: bool = True
2795         If False, and the last element of the path is a symbolic link,
2796         stat will examine the symbolic link itself instead of the file
2797         the link points to.
2798 
2799 Perform a stat system call on the given path.
2800 
2801 dir_fd and follow_symlinks may not be implemented
2802   on your platform.  If they are unavailable, using them will raise a
2803   NotImplementedError.
2804 
2805 It's an error to use dir_fd or follow_symlinks when specifying path as
2806   an open file descriptor.
2807 
2808 [clinic start generated code]*/
2809 
2810 static PyObject *
os_stat_impl(PyObject * module,path_t * path,int dir_fd,int follow_symlinks)2811 os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2812 /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2813 {
2814     return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
2815 }
2816 
2817 
2818 /*[clinic input]
2819 os.lstat
2820 
2821     path : path_t
2822 
2823     *
2824 
2825     dir_fd : dir_fd(requires='fstatat') = None
2826 
2827 Perform a stat system call on the given path, without following symbolic links.
2828 
2829 Like stat(), but do not follow symbolic links.
2830 Equivalent to stat(path, follow_symlinks=False).
2831 [clinic start generated code]*/
2832 
2833 static PyObject *
os_lstat_impl(PyObject * module,path_t * path,int dir_fd)2834 os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2835 /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2836 {
2837     int follow_symlinks = 0;
2838     return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
2839 }
2840 
2841 
2842 /*[clinic input]
2843 os.access -> bool
2844 
2845     path: path_t
2846         Path to be tested; can be string, bytes, or a path-like object.
2847 
2848     mode: int
2849         Operating-system mode bitfield.  Can be F_OK to test existence,
2850         or the inclusive-OR of R_OK, W_OK, and X_OK.
2851 
2852     *
2853 
2854     dir_fd : dir_fd(requires='faccessat') = None
2855         If not None, it should be a file descriptor open to a directory,
2856         and path should be relative; path will then be relative to that
2857         directory.
2858 
2859     effective_ids: bool = False
2860         If True, access will use the effective uid/gid instead of
2861         the real uid/gid.
2862 
2863     follow_symlinks: bool = True
2864         If False, and the last element of the path is a symbolic link,
2865         access will examine the symbolic link itself instead of the file
2866         the link points to.
2867 
2868 Use the real uid/gid to test for access to a path.
2869 
2870 {parameters}
2871 dir_fd, effective_ids, and follow_symlinks may not be implemented
2872   on your platform.  If they are unavailable, using them will raise a
2873   NotImplementedError.
2874 
2875 Note that most operations will use the effective uid/gid, therefore this
2876   routine can be used in a suid/sgid environment to test if the invoking user
2877   has the specified access to the path.
2878 
2879 [clinic start generated code]*/
2880 
2881 static int
os_access_impl(PyObject * module,path_t * path,int mode,int dir_fd,int effective_ids,int follow_symlinks)2882 os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2883                int effective_ids, int follow_symlinks)
2884 /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
2885 {
2886     int return_value;
2887 
2888 #ifdef MS_WINDOWS
2889     DWORD attr;
2890 #else
2891     int result;
2892 #endif
2893 
2894 #ifdef HAVE_FACCESSAT
2895     int faccessat_unavailable = 0;
2896 #endif
2897 
2898 #ifndef HAVE_FACCESSAT
2899     if (follow_symlinks_specified("access", follow_symlinks))
2900         return -1;
2901 
2902     if (effective_ids) {
2903         argument_unavailable_error("access", "effective_ids");
2904         return -1;
2905     }
2906 #endif
2907 
2908 #ifdef MS_WINDOWS
2909     Py_BEGIN_ALLOW_THREADS
2910     attr = GetFileAttributesW(path->wide);
2911     Py_END_ALLOW_THREADS
2912 
2913     /*
2914      * Access is possible if
2915      *   * we didn't get a -1, and
2916      *     * write access wasn't requested,
2917      *     * or the file isn't read-only,
2918      *     * or it's a directory.
2919      * (Directories cannot be read-only on Windows.)
2920     */
2921     return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
2922             (!(mode & 2) ||
2923             !(attr & FILE_ATTRIBUTE_READONLY) ||
2924             (attr & FILE_ATTRIBUTE_DIRECTORY));
2925 #else
2926 
2927     Py_BEGIN_ALLOW_THREADS
2928 #ifdef HAVE_FACCESSAT
2929     if ((dir_fd != DEFAULT_DIR_FD) ||
2930         effective_ids ||
2931         !follow_symlinks) {
2932 
2933         if (HAVE_FACCESSAT_RUNTIME) {
2934             int flags = 0;
2935             if (!follow_symlinks)
2936                 flags |= AT_SYMLINK_NOFOLLOW;
2937             if (effective_ids)
2938                 flags |= AT_EACCESS;
2939             result = faccessat(dir_fd, path->narrow, mode, flags);
2940         } else {
2941             faccessat_unavailable = 1;
2942         }
2943     }
2944     else
2945 #endif
2946         result = access(path->narrow, mode);
2947     Py_END_ALLOW_THREADS
2948 
2949 #ifdef HAVE_FACCESSAT
2950     if (faccessat_unavailable) {
2951         if (dir_fd != DEFAULT_DIR_FD) {
2952             argument_unavailable_error("access", "dir_fd");
2953             return -1;
2954         }
2955         if (follow_symlinks_specified("access", follow_symlinks))
2956             return -1;
2957 
2958         if (effective_ids) {
2959             argument_unavailable_error("access", "effective_ids");
2960             return -1;
2961         }
2962         /* should be unreachable */
2963         return -1;
2964     }
2965 #endif
2966     return_value = !result;
2967 #endif
2968 
2969     return return_value;
2970 }
2971 
2972 #ifndef F_OK
2973 #define F_OK 0
2974 #endif
2975 #ifndef R_OK
2976 #define R_OK 4
2977 #endif
2978 #ifndef W_OK
2979 #define W_OK 2
2980 #endif
2981 #ifndef X_OK
2982 #define X_OK 1
2983 #endif
2984 
2985 
2986 #ifdef HAVE_TTYNAME
2987 /*[clinic input]
2988 os.ttyname
2989 
2990     fd: int
2991         Integer file descriptor handle.
2992 
2993     /
2994 
2995 Return the name of the terminal device connected to 'fd'.
2996 [clinic start generated code]*/
2997 
2998 static PyObject *
os_ttyname_impl(PyObject * module,int fd)2999 os_ttyname_impl(PyObject *module, int fd)
3000 /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3001 {
3002 
3003     long size = sysconf(_SC_TTY_NAME_MAX);
3004     if (size == -1) {
3005         return posix_error();
3006     }
3007     char *buffer = (char *)PyMem_RawMalloc(size);
3008     if (buffer == NULL) {
3009         return PyErr_NoMemory();
3010     }
3011     int ret = ttyname_r(fd, buffer, size);
3012     if (ret != 0) {
3013         PyMem_RawFree(buffer);
3014         errno = ret;
3015         return posix_error();
3016     }
3017     PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3018     PyMem_RawFree(buffer);
3019     return res;
3020 }
3021 #endif
3022 
3023 #ifdef HAVE_CTERMID
3024 /*[clinic input]
3025 os.ctermid
3026 
3027 Return the name of the controlling terminal for this process.
3028 [clinic start generated code]*/
3029 
3030 static PyObject *
os_ctermid_impl(PyObject * module)3031 os_ctermid_impl(PyObject *module)
3032 /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3033 {
3034     char *ret;
3035     char buffer[L_ctermid];
3036 
3037 #ifdef USE_CTERMID_R
3038     ret = ctermid_r(buffer);
3039 #else
3040     ret = ctermid(buffer);
3041 #endif
3042     if (ret == NULL)
3043         return posix_error();
3044     return PyUnicode_DecodeFSDefault(buffer);
3045 }
3046 #endif /* HAVE_CTERMID */
3047 
3048 
3049 /*[clinic input]
3050 os.chdir
3051 
3052     path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3053 
3054 Change the current working directory to the specified path.
3055 
3056 path may always be specified as a string.
3057 On some platforms, path may also be specified as an open file descriptor.
3058   If this functionality is unavailable, using it raises an exception.
3059 [clinic start generated code]*/
3060 
3061 static PyObject *
os_chdir_impl(PyObject * module,path_t * path)3062 os_chdir_impl(PyObject *module, path_t *path)
3063 /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3064 {
3065     int result;
3066 
3067     if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3068         return NULL;
3069     }
3070 
3071     Py_BEGIN_ALLOW_THREADS
3072 #ifdef MS_WINDOWS
3073     /* on unix, success = 0, on windows, success = !0 */
3074     result = !win32_wchdir(path->wide);
3075 #else
3076 #ifdef HAVE_FCHDIR
3077     if (path->fd != -1)
3078         result = fchdir(path->fd);
3079     else
3080 #endif
3081         result = chdir(path->narrow);
3082 #endif
3083     Py_END_ALLOW_THREADS
3084 
3085     if (result) {
3086         return path_error(path);
3087     }
3088 
3089     Py_RETURN_NONE;
3090 }
3091 
3092 
3093 #ifdef HAVE_FCHDIR
3094 /*[clinic input]
3095 os.fchdir
3096 
3097     fd: fildes
3098 
3099 Change to the directory of the given file descriptor.
3100 
3101 fd must be opened on a directory, not a file.
3102 Equivalent to os.chdir(fd).
3103 
3104 [clinic start generated code]*/
3105 
3106 static PyObject *
os_fchdir_impl(PyObject * module,int fd)3107 os_fchdir_impl(PyObject *module, int fd)
3108 /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3109 {
3110     if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3111         return NULL;
3112     }
3113     return posix_fildes_fd(fd, fchdir);
3114 }
3115 #endif /* HAVE_FCHDIR */
3116 
3117 
3118 /*[clinic input]
3119 os.chmod
3120 
3121     path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3122         Path to be modified.  May always be specified as a str, bytes, or a path-like object.
3123         On some platforms, path may also be specified as an open file descriptor.
3124         If this functionality is unavailable, using it raises an exception.
3125 
3126     mode: int
3127         Operating-system mode bitfield.
3128 
3129     *
3130 
3131     dir_fd : dir_fd(requires='fchmodat') = None
3132         If not None, it should be a file descriptor open to a directory,
3133         and path should be relative; path will then be relative to that
3134         directory.
3135 
3136     follow_symlinks: bool = True
3137         If False, and the last element of the path is a symbolic link,
3138         chmod will modify the symbolic link itself instead of the file
3139         the link points to.
3140 
3141 Change the access permissions of a file.
3142 
3143 It is an error to use dir_fd or follow_symlinks when specifying path as
3144   an open file descriptor.
3145 dir_fd and follow_symlinks may not be implemented on your platform.
3146   If they are unavailable, using them will raise a NotImplementedError.
3147 
3148 [clinic start generated code]*/
3149 
3150 static PyObject *
os_chmod_impl(PyObject * module,path_t * path,int mode,int dir_fd,int follow_symlinks)3151 os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3152               int follow_symlinks)
3153 /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
3154 {
3155     int result;
3156 
3157 #ifdef MS_WINDOWS
3158     DWORD attr;
3159 #endif
3160 
3161 #ifdef HAVE_FCHMODAT
3162     int fchmodat_nofollow_unsupported = 0;
3163     int fchmodat_unsupported = 0;
3164 #endif
3165 
3166 #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
3167     if (follow_symlinks_specified("chmod", follow_symlinks))
3168         return NULL;
3169 #endif
3170 
3171     if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3172                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3173         return NULL;
3174     }
3175 
3176 #ifdef MS_WINDOWS
3177     Py_BEGIN_ALLOW_THREADS
3178     attr = GetFileAttributesW(path->wide);
3179     if (attr == INVALID_FILE_ATTRIBUTES)
3180         result = 0;
3181     else {
3182         if (mode & _S_IWRITE)
3183             attr &= ~FILE_ATTRIBUTE_READONLY;
3184         else
3185             attr |= FILE_ATTRIBUTE_READONLY;
3186         result = SetFileAttributesW(path->wide, attr);
3187     }
3188     Py_END_ALLOW_THREADS
3189 
3190     if (!result) {
3191         return path_error(path);
3192     }
3193 #else /* MS_WINDOWS */
3194     Py_BEGIN_ALLOW_THREADS
3195 #ifdef HAVE_FCHMOD
3196     if (path->fd != -1)
3197         result = fchmod(path->fd, mode);
3198     else
3199 #endif /* HAVE_CHMOD */
3200 #ifdef HAVE_LCHMOD
3201     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3202         result = lchmod(path->narrow, mode);
3203     else
3204 #endif /* HAVE_LCHMOD */
3205 #ifdef HAVE_FCHMODAT
3206     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3207         if (HAVE_FCHMODAT_RUNTIME) {
3208             /*
3209              * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3210              * The documentation specifically shows how to use it,
3211              * and then says it isn't implemented yet.
3212              * (true on linux with glibc 2.15, and openindiana 3.x)
3213              *
3214              * Once it is supported, os.chmod will automatically
3215              * support dir_fd and follow_symlinks=False.  (Hopefully.)
3216              * Until then, we need to be careful what exception we raise.
3217              */
3218             result = fchmodat(dir_fd, path->narrow, mode,
3219                               follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3220             /*
3221              * But wait!  We can't throw the exception without allowing threads,
3222              * and we can't do that in this nested scope.  (Macro trickery, sigh.)
3223              */
3224             fchmodat_nofollow_unsupported =
3225                              result &&
3226                              ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3227                              !follow_symlinks;
3228         } else {
3229             fchmodat_unsupported = 1;
3230             fchmodat_nofollow_unsupported = 1;
3231 
3232             result = -1;
3233         }
3234     }
3235     else
3236 #endif /* HAVE_FHCMODAT */
3237         result = chmod(path->narrow, mode);
3238     Py_END_ALLOW_THREADS
3239 
3240     if (result) {
3241 #ifdef HAVE_FCHMODAT
3242         if (fchmodat_unsupported) {
3243             if (dir_fd != DEFAULT_DIR_FD) {
3244                 argument_unavailable_error("chmod", "dir_fd");
3245                 return NULL;
3246             }
3247         }
3248 
3249         if (fchmodat_nofollow_unsupported) {
3250             if (dir_fd != DEFAULT_DIR_FD)
3251                 dir_fd_and_follow_symlinks_invalid("chmod",
3252                                                    dir_fd, follow_symlinks);
3253             else
3254                 follow_symlinks_specified("chmod", follow_symlinks);
3255             return NULL;
3256         }
3257         else
3258 #endif /* HAVE_FCHMODAT */
3259         return path_error(path);
3260     }
3261 #endif /* MS_WINDOWS */
3262 
3263     Py_RETURN_NONE;
3264 }
3265 
3266 
3267 #ifdef HAVE_FCHMOD
3268 /*[clinic input]
3269 os.fchmod
3270 
3271     fd: int
3272     mode: int
3273 
3274 Change the access permissions of the file given by file descriptor fd.
3275 
3276 Equivalent to os.chmod(fd, mode).
3277 [clinic start generated code]*/
3278 
3279 static PyObject *
os_fchmod_impl(PyObject * module,int fd,int mode)3280 os_fchmod_impl(PyObject *module, int fd, int mode)
3281 /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
3282 {
3283     int res;
3284     int async_err = 0;
3285 
3286     if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3287         return NULL;
3288     }
3289 
3290     do {
3291         Py_BEGIN_ALLOW_THREADS
3292         res = fchmod(fd, mode);
3293         Py_END_ALLOW_THREADS
3294     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3295     if (res != 0)
3296         return (!async_err) ? posix_error() : NULL;
3297 
3298     Py_RETURN_NONE;
3299 }
3300 #endif /* HAVE_FCHMOD */
3301 
3302 
3303 #ifdef HAVE_LCHMOD
3304 /*[clinic input]
3305 os.lchmod
3306 
3307     path: path_t
3308     mode: int
3309 
3310 Change the access permissions of a file, without following symbolic links.
3311 
3312 If path is a symlink, this affects the link itself rather than the target.
3313 Equivalent to chmod(path, mode, follow_symlinks=False)."
3314 [clinic start generated code]*/
3315 
3316 static PyObject *
os_lchmod_impl(PyObject * module,path_t * path,int mode)3317 os_lchmod_impl(PyObject *module, path_t *path, int mode)
3318 /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3319 {
3320     int res;
3321     if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3322         return NULL;
3323     }
3324     Py_BEGIN_ALLOW_THREADS
3325     res = lchmod(path->narrow, mode);
3326     Py_END_ALLOW_THREADS
3327     if (res < 0) {
3328         path_error(path);
3329         return NULL;
3330     }
3331     Py_RETURN_NONE;
3332 }
3333 #endif /* HAVE_LCHMOD */
3334 
3335 
3336 #ifdef HAVE_CHFLAGS
3337 /*[clinic input]
3338 os.chflags
3339 
3340     path: path_t
3341     flags: unsigned_long(bitwise=True)
3342     follow_symlinks: bool=True
3343 
3344 Set file flags.
3345 
3346 If follow_symlinks is False, and the last element of the path is a symbolic
3347   link, chflags will change flags on the symbolic link itself instead of the
3348   file the link points to.
3349 follow_symlinks may not be implemented on your platform.  If it is
3350 unavailable, using it will raise a NotImplementedError.
3351 
3352 [clinic start generated code]*/
3353 
3354 static PyObject *
os_chflags_impl(PyObject * module,path_t * path,unsigned long flags,int follow_symlinks)3355 os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3356                 int follow_symlinks)
3357 /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3358 {
3359     int result;
3360 
3361 #ifndef HAVE_LCHFLAGS
3362     if (follow_symlinks_specified("chflags", follow_symlinks))
3363         return NULL;
3364 #endif
3365 
3366     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3367         return NULL;
3368     }
3369 
3370     Py_BEGIN_ALLOW_THREADS
3371 #ifdef HAVE_LCHFLAGS
3372     if (!follow_symlinks)
3373         result = lchflags(path->narrow, flags);
3374     else
3375 #endif
3376         result = chflags(path->narrow, flags);
3377     Py_END_ALLOW_THREADS
3378 
3379     if (result)
3380         return path_error(path);
3381 
3382     Py_RETURN_NONE;
3383 }
3384 #endif /* HAVE_CHFLAGS */
3385 
3386 
3387 #ifdef HAVE_LCHFLAGS
3388 /*[clinic input]
3389 os.lchflags
3390 
3391     path: path_t
3392     flags: unsigned_long(bitwise=True)
3393 
3394 Set file flags.
3395 
3396 This function will not follow symbolic links.
3397 Equivalent to chflags(path, flags, follow_symlinks=False).
3398 [clinic start generated code]*/
3399 
3400 static PyObject *
os_lchflags_impl(PyObject * module,path_t * path,unsigned long flags)3401 os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3402 /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3403 {
3404     int res;
3405     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3406         return NULL;
3407     }
3408     Py_BEGIN_ALLOW_THREADS
3409     res = lchflags(path->narrow, flags);
3410     Py_END_ALLOW_THREADS
3411     if (res < 0) {
3412         return path_error(path);
3413     }
3414     Py_RETURN_NONE;
3415 }
3416 #endif /* HAVE_LCHFLAGS */
3417 
3418 
3419 #ifdef HAVE_CHROOT
3420 /*[clinic input]
3421 os.chroot
3422     path: path_t
3423 
3424 Change root directory to path.
3425 
3426 [clinic start generated code]*/
3427 
3428 static PyObject *
os_chroot_impl(PyObject * module,path_t * path)3429 os_chroot_impl(PyObject *module, path_t *path)
3430 /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3431 {
3432     int res;
3433     Py_BEGIN_ALLOW_THREADS
3434     res = chroot(path->narrow);
3435     Py_END_ALLOW_THREADS
3436     if (res < 0)
3437         return path_error(path);
3438     Py_RETURN_NONE;
3439 }
3440 #endif /* HAVE_CHROOT */
3441 
3442 
3443 #ifdef HAVE_FSYNC
3444 /*[clinic input]
3445 os.fsync
3446 
3447     fd: fildes
3448 
3449 Force write of fd to disk.
3450 [clinic start generated code]*/
3451 
3452 static PyObject *
os_fsync_impl(PyObject * module,int fd)3453 os_fsync_impl(PyObject *module, int fd)
3454 /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3455 {
3456     return posix_fildes_fd(fd, fsync);
3457 }
3458 #endif /* HAVE_FSYNC */
3459 
3460 
3461 #ifdef HAVE_SYNC
3462 /*[clinic input]
3463 os.sync
3464 
3465 Force write of everything to disk.
3466 [clinic start generated code]*/
3467 
3468 static PyObject *
os_sync_impl(PyObject * module)3469 os_sync_impl(PyObject *module)
3470 /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3471 {
3472     Py_BEGIN_ALLOW_THREADS
3473     sync();
3474     Py_END_ALLOW_THREADS
3475     Py_RETURN_NONE;
3476 }
3477 #endif /* HAVE_SYNC */
3478 
3479 
3480 #ifdef HAVE_FDATASYNC
3481 #ifdef __hpux
3482 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3483 #endif
3484 
3485 /*[clinic input]
3486 os.fdatasync
3487 
3488     fd: fildes
3489 
3490 Force write of fd to disk without forcing update of metadata.
3491 [clinic start generated code]*/
3492 
3493 static PyObject *
os_fdatasync_impl(PyObject * module,int fd)3494 os_fdatasync_impl(PyObject *module, int fd)
3495 /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3496 {
3497     return posix_fildes_fd(fd, fdatasync);
3498 }
3499 #endif /* HAVE_FDATASYNC */
3500 
3501 
3502 #ifdef HAVE_CHOWN
3503 /*[clinic input]
3504 os.chown
3505 
3506     path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3507         Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3508 
3509     uid: uid_t
3510 
3511     gid: gid_t
3512 
3513     *
3514 
3515     dir_fd : dir_fd(requires='fchownat') = None
3516         If not None, it should be a file descriptor open to a directory,
3517         and path should be relative; path will then be relative to that
3518         directory.
3519 
3520     follow_symlinks: bool = True
3521         If False, and the last element of the path is a symbolic link,
3522         stat will examine the symbolic link itself instead of the file
3523         the link points to.
3524 
3525 Change the owner and group id of path to the numeric uid and gid.\
3526 
3527 path may always be specified as a string.
3528 On some platforms, path may also be specified as an open file descriptor.
3529   If this functionality is unavailable, using it raises an exception.
3530 If dir_fd is not None, it should be a file descriptor open to a directory,
3531   and path should be relative; path will then be relative to that directory.
3532 If follow_symlinks is False, and the last element of the path is a symbolic
3533   link, chown will modify the symbolic link itself instead of the file the
3534   link points to.
3535 It is an error to use dir_fd or follow_symlinks when specifying path as
3536   an open file descriptor.
3537 dir_fd and follow_symlinks may not be implemented on your platform.
3538   If they are unavailable, using them will raise a NotImplementedError.
3539 
3540 [clinic start generated code]*/
3541 
3542 static PyObject *
os_chown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid,int dir_fd,int follow_symlinks)3543 os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3544               int dir_fd, int follow_symlinks)
3545 /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3546 {
3547     int result;
3548 
3549 #if defined(HAVE_FCHOWNAT)
3550     int fchownat_unsupported = 0;
3551 #endif
3552 
3553 #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3554     if (follow_symlinks_specified("chown", follow_symlinks))
3555         return NULL;
3556 #endif
3557     if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3558         fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3559         return NULL;
3560 
3561     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3562                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3563         return NULL;
3564     }
3565 
3566     Py_BEGIN_ALLOW_THREADS
3567 #ifdef HAVE_FCHOWN
3568     if (path->fd != -1)
3569         result = fchown(path->fd, uid, gid);
3570     else
3571 #endif
3572 #ifdef HAVE_LCHOWN
3573     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3574         result = lchown(path->narrow, uid, gid);
3575     else
3576 #endif
3577 #ifdef HAVE_FCHOWNAT
3578     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
3579       if (HAVE_FCHOWNAT_RUNTIME) {
3580         result = fchownat(dir_fd, path->narrow, uid, gid,
3581                           follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3582       } else {
3583          fchownat_unsupported = 1;
3584       }
3585     } else
3586 #endif
3587         result = chown(path->narrow, uid, gid);
3588     Py_END_ALLOW_THREADS
3589 
3590 #ifdef HAVE_FCHOWNAT
3591     if (fchownat_unsupported) {
3592         /* This would be incorrect if the current platform
3593          * doesn't support lchown.
3594          */
3595         argument_unavailable_error(NULL, "dir_fd");
3596         return NULL;
3597     }
3598 #endif
3599 
3600     if (result)
3601         return path_error(path);
3602 
3603     Py_RETURN_NONE;
3604 }
3605 #endif /* HAVE_CHOWN */
3606 
3607 
3608 #ifdef HAVE_FCHOWN
3609 /*[clinic input]
3610 os.fchown
3611 
3612     fd: int
3613     uid: uid_t
3614     gid: gid_t
3615 
3616 Change the owner and group id of the file specified by file descriptor.
3617 
3618 Equivalent to os.chown(fd, uid, gid).
3619 
3620 [clinic start generated code]*/
3621 
3622 static PyObject *
os_fchown_impl(PyObject * module,int fd,uid_t uid,gid_t gid)3623 os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3624 /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3625 {
3626     int res;
3627     int async_err = 0;
3628 
3629     if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
3630         return NULL;
3631     }
3632 
3633     do {
3634         Py_BEGIN_ALLOW_THREADS
3635         res = fchown(fd, uid, gid);
3636         Py_END_ALLOW_THREADS
3637     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3638     if (res != 0)
3639         return (!async_err) ? posix_error() : NULL;
3640 
3641     Py_RETURN_NONE;
3642 }
3643 #endif /* HAVE_FCHOWN */
3644 
3645 
3646 #ifdef HAVE_LCHOWN
3647 /*[clinic input]
3648 os.lchown
3649 
3650     path : path_t
3651     uid: uid_t
3652     gid: gid_t
3653 
3654 Change the owner and group id of path to the numeric uid and gid.
3655 
3656 This function will not follow symbolic links.
3657 Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3658 [clinic start generated code]*/
3659 
3660 static PyObject *
os_lchown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid)3661 os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3662 /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3663 {
3664     int res;
3665     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
3666         return NULL;
3667     }
3668     Py_BEGIN_ALLOW_THREADS
3669     res = lchown(path->narrow, uid, gid);
3670     Py_END_ALLOW_THREADS
3671     if (res < 0) {
3672         return path_error(path);
3673     }
3674     Py_RETURN_NONE;
3675 }
3676 #endif /* HAVE_LCHOWN */
3677 
3678 
3679 static PyObject *
posix_getcwd(int use_bytes)3680 posix_getcwd(int use_bytes)
3681 {
3682 #ifdef MS_WINDOWS
3683     wchar_t wbuf[MAXPATHLEN];
3684     wchar_t *wbuf2 = wbuf;
3685     DWORD len;
3686 
3687     Py_BEGIN_ALLOW_THREADS
3688     len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3689     /* If the buffer is large enough, len does not include the
3690        terminating \0. If the buffer is too small, len includes
3691        the space needed for the terminator. */
3692     if (len >= Py_ARRAY_LENGTH(wbuf)) {
3693         if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3694             wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3695         }
3696         else {
3697             wbuf2 = NULL;
3698         }
3699         if (wbuf2) {
3700             len = GetCurrentDirectoryW(len, wbuf2);
3701         }
3702     }
3703     Py_END_ALLOW_THREADS
3704 
3705     if (!wbuf2) {
3706         PyErr_NoMemory();
3707         return NULL;
3708     }
3709     if (!len) {
3710         if (wbuf2 != wbuf)
3711             PyMem_RawFree(wbuf2);
3712         return PyErr_SetFromWindowsErr(0);
3713     }
3714 
3715     PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3716     if (wbuf2 != wbuf) {
3717         PyMem_RawFree(wbuf2);
3718     }
3719 
3720     if (use_bytes) {
3721         if (resobj == NULL) {
3722             return NULL;
3723         }
3724         Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3725     }
3726 
3727     return resobj;
3728 #else
3729     const size_t chunk = 1024;
3730 
3731     char *buf = NULL;
3732     char *cwd = NULL;
3733     size_t buflen = 0;
3734 
3735     Py_BEGIN_ALLOW_THREADS
3736     do {
3737         char *newbuf;
3738         if (buflen <= PY_SSIZE_T_MAX - chunk) {
3739             buflen += chunk;
3740             newbuf = PyMem_RawRealloc(buf, buflen);
3741         }
3742         else {
3743             newbuf = NULL;
3744         }
3745         if (newbuf == NULL) {
3746             PyMem_RawFree(buf);
3747             buf = NULL;
3748             break;
3749         }
3750         buf = newbuf;
3751 
3752         cwd = getcwd(buf, buflen);
3753     } while (cwd == NULL && errno == ERANGE);
3754     Py_END_ALLOW_THREADS
3755 
3756     if (buf == NULL) {
3757         return PyErr_NoMemory();
3758     }
3759     if (cwd == NULL) {
3760         PyMem_RawFree(buf);
3761         return posix_error();
3762     }
3763 
3764     PyObject *obj;
3765     if (use_bytes) {
3766         obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3767     }
3768     else {
3769         obj = PyUnicode_DecodeFSDefault(buf);
3770     }
3771     PyMem_RawFree(buf);
3772 
3773     return obj;
3774 #endif   /* !MS_WINDOWS */
3775 }
3776 
3777 
3778 /*[clinic input]
3779 os.getcwd
3780 
3781 Return a unicode string representing the current working directory.
3782 [clinic start generated code]*/
3783 
3784 static PyObject *
os_getcwd_impl(PyObject * module)3785 os_getcwd_impl(PyObject *module)
3786 /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3787 {
3788     return posix_getcwd(0);
3789 }
3790 
3791 
3792 /*[clinic input]
3793 os.getcwdb
3794 
3795 Return a bytes string representing the current working directory.
3796 [clinic start generated code]*/
3797 
3798 static PyObject *
os_getcwdb_impl(PyObject * module)3799 os_getcwdb_impl(PyObject *module)
3800 /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3801 {
3802     return posix_getcwd(1);
3803 }
3804 
3805 
3806 #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3807 #define HAVE_LINK 1
3808 #endif
3809 
3810 #ifdef HAVE_LINK
3811 /*[clinic input]
3812 
3813 os.link
3814 
3815     src : path_t
3816     dst : path_t
3817     *
3818     src_dir_fd : dir_fd = None
3819     dst_dir_fd : dir_fd = None
3820     follow_symlinks: bool = True
3821 
3822 Create a hard link to a file.
3823 
3824 If either src_dir_fd or dst_dir_fd is not None, it should be a file
3825   descriptor open to a directory, and the respective path string (src or dst)
3826   should be relative; the path will then be relative to that directory.
3827 If follow_symlinks is False, and the last element of src is a symbolic
3828   link, link will create a link to the symbolic link itself instead of the
3829   file the link points to.
3830 src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3831   platform.  If they are unavailable, using them will raise a
3832   NotImplementedError.
3833 [clinic start generated code]*/
3834 
3835 static PyObject *
os_link_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int follow_symlinks)3836 os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3837              int dst_dir_fd, int follow_symlinks)
3838 /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3839 {
3840 #ifdef MS_WINDOWS
3841     BOOL result = FALSE;
3842 #else
3843     int result;
3844 #endif
3845 #if defined(HAVE_LINKAT)
3846     int linkat_unavailable = 0;
3847 #endif
3848 
3849 #ifndef HAVE_LINKAT
3850     if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3851         argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3852         return NULL;
3853     }
3854 #endif
3855 
3856 #ifndef MS_WINDOWS
3857     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3858         PyErr_SetString(PyExc_NotImplementedError,
3859                         "link: src and dst must be the same type");
3860         return NULL;
3861     }
3862 #endif
3863 
3864     if (PySys_Audit("os.link", "OOii", src->object, dst->object,
3865                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
3866                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
3867         return NULL;
3868     }
3869 
3870 #ifdef MS_WINDOWS
3871     Py_BEGIN_ALLOW_THREADS
3872     result = CreateHardLinkW(dst->wide, src->wide, NULL);
3873     Py_END_ALLOW_THREADS
3874 
3875     if (!result)
3876         return path_error2(src, dst);
3877 #else
3878     Py_BEGIN_ALLOW_THREADS
3879 #ifdef HAVE_LINKAT
3880     if ((src_dir_fd != DEFAULT_DIR_FD) ||
3881         (dst_dir_fd != DEFAULT_DIR_FD) ||
3882         (!follow_symlinks)) {
3883 
3884         if (HAVE_LINKAT_RUNTIME) {
3885 
3886             result = linkat(src_dir_fd, src->narrow,
3887                 dst_dir_fd, dst->narrow,
3888                 follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3889 
3890         }
3891 #ifdef __APPLE__
3892         else {
3893             if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
3894                 /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
3895                 result = link(src->narrow, dst->narrow);
3896             } else {
3897                 linkat_unavailable = 1;
3898             }
3899         }
3900 #endif
3901     }
3902     else
3903 #endif /* HAVE_LINKAT */
3904         result = link(src->narrow, dst->narrow);
3905     Py_END_ALLOW_THREADS
3906 
3907 #ifdef HAVE_LINKAT
3908     if (linkat_unavailable) {
3909         /* Either or both dir_fd arguments were specified */
3910         if (src_dir_fd  != DEFAULT_DIR_FD) {
3911             argument_unavailable_error("link", "src_dir_fd");
3912         } else {
3913             argument_unavailable_error("link", "dst_dir_fd");
3914         }
3915         return NULL;
3916     }
3917 #endif
3918 
3919     if (result)
3920         return path_error2(src, dst);
3921 #endif /* MS_WINDOWS */
3922 
3923     Py_RETURN_NONE;
3924 }
3925 #endif
3926 
3927 
3928 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3929 static PyObject *
_listdir_windows_no_opendir(path_t * path,PyObject * list)3930 _listdir_windows_no_opendir(path_t *path, PyObject *list)
3931 {
3932     PyObject *v;
3933     HANDLE hFindFile = INVALID_HANDLE_VALUE;
3934     BOOL result;
3935     wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
3936     /* only claim to have space for MAX_PATH */
3937     Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
3938     wchar_t *wnamebuf = NULL;
3939 
3940     WIN32_FIND_DATAW wFileData;
3941     const wchar_t *po_wchars;
3942 
3943     if (!path->wide) { /* Default arg: "." */
3944         po_wchars = L".";
3945         len = 1;
3946     } else {
3947         po_wchars = path->wide;
3948         len = wcslen(path->wide);
3949     }
3950     /* The +5 is so we can append "\\*.*\0" */
3951     wnamebuf = PyMem_New(wchar_t, len + 5);
3952     if (!wnamebuf) {
3953         PyErr_NoMemory();
3954         goto exit;
3955     }
3956     wcscpy(wnamebuf, po_wchars);
3957     if (len > 0) {
3958         wchar_t wch = wnamebuf[len-1];
3959         if (wch != SEP && wch != ALTSEP && wch != L':')
3960             wnamebuf[len++] = SEP;
3961         wcscpy(wnamebuf + len, L"*.*");
3962     }
3963     if ((list = PyList_New(0)) == NULL) {
3964         goto exit;
3965     }
3966     Py_BEGIN_ALLOW_THREADS
3967     hFindFile = FindFirstFileW(wnamebuf, &wFileData);
3968     Py_END_ALLOW_THREADS
3969     if (hFindFile == INVALID_HANDLE_VALUE) {
3970         int error = GetLastError();
3971         if (error == ERROR_FILE_NOT_FOUND)
3972             goto exit;
3973         Py_DECREF(list);
3974         list = path_error(path);
3975         goto exit;
3976     }
3977     do {
3978         /* Skip over . and .. */
3979         if (wcscmp(wFileData.cFileName, L".") != 0 &&
3980             wcscmp(wFileData.cFileName, L"..") != 0) {
3981             v = PyUnicode_FromWideChar(wFileData.cFileName,
3982                                        wcslen(wFileData.cFileName));
3983             if (path->narrow && v) {
3984                 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
3985             }
3986             if (v == NULL) {
3987                 Py_DECREF(list);
3988                 list = NULL;
3989                 break;
3990             }
3991             if (PyList_Append(list, v) != 0) {
3992                 Py_DECREF(v);
3993                 Py_DECREF(list);
3994                 list = NULL;
3995                 break;
3996             }
3997             Py_DECREF(v);
3998         }
3999         Py_BEGIN_ALLOW_THREADS
4000         result = FindNextFileW(hFindFile, &wFileData);
4001         Py_END_ALLOW_THREADS
4002         /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4003            it got to the end of the directory. */
4004         if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4005             Py_DECREF(list);
4006             list = path_error(path);
4007             goto exit;
4008         }
4009     } while (result == TRUE);
4010 
4011 exit:
4012     if (hFindFile != INVALID_HANDLE_VALUE) {
4013         if (FindClose(hFindFile) == FALSE) {
4014             if (list != NULL) {
4015                 Py_DECREF(list);
4016                 list = path_error(path);
4017             }
4018         }
4019     }
4020     PyMem_Free(wnamebuf);
4021 
4022     return list;
4023 }  /* end of _listdir_windows_no_opendir */
4024 
4025 #else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4026 
4027 static PyObject *
_posix_listdir(path_t * path,PyObject * list)4028 _posix_listdir(path_t *path, PyObject *list)
4029 {
4030     PyObject *v;
4031     DIR *dirp = NULL;
4032     struct dirent *ep;
4033     int return_str; /* if false, return bytes */
4034 #ifdef HAVE_FDOPENDIR
4035     int fd = -1;
4036 #endif
4037 
4038     errno = 0;
4039 #ifdef HAVE_FDOPENDIR
4040     if (path->fd != -1) {
4041       if (HAVE_FDOPENDIR_RUNTIME) {
4042         /* closedir() closes the FD, so we duplicate it */
4043         fd = _Py_dup(path->fd);
4044         if (fd == -1)
4045             return NULL;
4046 
4047         return_str = 1;
4048 
4049         Py_BEGIN_ALLOW_THREADS
4050         dirp = fdopendir(fd);
4051         Py_END_ALLOW_THREADS
4052       } else {
4053         PyErr_SetString(PyExc_TypeError,
4054             "listdir: path should be string, bytes, os.PathLike or None, not int");
4055         return NULL;
4056       }
4057     }
4058     else
4059 #endif
4060     {
4061         const char *name;
4062         if (path->narrow) {
4063             name = path->narrow;
4064             /* only return bytes if they specified a bytes-like object */
4065             return_str = !PyObject_CheckBuffer(path->object);
4066         }
4067         else {
4068             name = ".";
4069             return_str = 1;
4070         }
4071 
4072         Py_BEGIN_ALLOW_THREADS
4073         dirp = opendir(name);
4074         Py_END_ALLOW_THREADS
4075     }
4076 
4077     if (dirp == NULL) {
4078         list = path_error(path);
4079 #ifdef HAVE_FDOPENDIR
4080         if (fd != -1) {
4081             Py_BEGIN_ALLOW_THREADS
4082             close(fd);
4083             Py_END_ALLOW_THREADS
4084         }
4085 #endif
4086         goto exit;
4087     }
4088     if ((list = PyList_New(0)) == NULL) {
4089         goto exit;
4090     }
4091     for (;;) {
4092         errno = 0;
4093         Py_BEGIN_ALLOW_THREADS
4094         ep = readdir(dirp);
4095         Py_END_ALLOW_THREADS
4096         if (ep == NULL) {
4097             if (errno == 0) {
4098                 break;
4099             } else {
4100                 Py_DECREF(list);
4101                 list = path_error(path);
4102                 goto exit;
4103             }
4104         }
4105         if (ep->d_name[0] == '.' &&
4106             (NAMLEN(ep) == 1 ||
4107              (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4108             continue;
4109         if (return_str)
4110             v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4111         else
4112             v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4113         if (v == NULL) {
4114             Py_CLEAR(list);
4115             break;
4116         }
4117         if (PyList_Append(list, v) != 0) {
4118             Py_DECREF(v);
4119             Py_CLEAR(list);
4120             break;
4121         }
4122         Py_DECREF(v);
4123     }
4124 
4125 exit:
4126     if (dirp != NULL) {
4127         Py_BEGIN_ALLOW_THREADS
4128 #ifdef HAVE_FDOPENDIR
4129         if (fd > -1)
4130             rewinddir(dirp);
4131 #endif
4132         closedir(dirp);
4133         Py_END_ALLOW_THREADS
4134     }
4135 
4136     return list;
4137 }  /* end of _posix_listdir */
4138 #endif  /* which OS */
4139 
4140 
4141 /*[clinic input]
4142 os.listdir
4143 
4144     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4145 
4146 Return a list containing the names of the files in the directory.
4147 
4148 path can be specified as either str, bytes, or a path-like object.  If path is bytes,
4149   the filenames returned will also be bytes; in all other circumstances
4150   the filenames returned will be str.
4151 If path is None, uses the path='.'.
4152 On some platforms, path may also be specified as an open file descriptor;\
4153   the file descriptor must refer to a directory.
4154   If this functionality is unavailable, using it raises NotImplementedError.
4155 
4156 The list is in arbitrary order.  It does not include the special
4157 entries '.' and '..' even if they are present in the directory.
4158 
4159 
4160 [clinic start generated code]*/
4161 
4162 static PyObject *
os_listdir_impl(PyObject * module,path_t * path)4163 os_listdir_impl(PyObject *module, path_t *path)
4164 /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4165 {
4166     if (PySys_Audit("os.listdir", "O",
4167                     path->object ? path->object : Py_None) < 0) {
4168         return NULL;
4169     }
4170 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4171     return _listdir_windows_no_opendir(path, NULL);
4172 #else
4173     return _posix_listdir(path, NULL);
4174 #endif
4175 }
4176 
4177 #ifdef MS_WINDOWS
4178 /* A helper function for abspath on win32 */
4179 /*[clinic input]
4180 os._getfullpathname
4181 
4182     path: path_t
4183     /
4184 
4185 [clinic start generated code]*/
4186 
4187 static PyObject *
os__getfullpathname_impl(PyObject * module,path_t * path)4188 os__getfullpathname_impl(PyObject *module, path_t *path)
4189 /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
4190 {
4191     wchar_t *abspath;
4192 
4193     /* _Py_abspath() is implemented with GetFullPathNameW() on Windows */
4194     if (_Py_abspath(path->wide, &abspath) < 0) {
4195         return win32_error_object("GetFullPathNameW", path->object);
4196     }
4197     if (abspath == NULL) {
4198         return PyErr_NoMemory();
4199     }
4200 
4201     PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
4202     PyMem_RawFree(abspath);
4203     if (str == NULL) {
4204         return NULL;
4205     }
4206     if (path->narrow) {
4207         Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
4208     }
4209     return str;
4210 }
4211 
4212 
4213 /*[clinic input]
4214 os._getfinalpathname
4215 
4216     path: path_t
4217     /
4218 
4219 A helper function for samepath on windows.
4220 [clinic start generated code]*/
4221 
4222 static PyObject *
os__getfinalpathname_impl(PyObject * module,path_t * path)4223 os__getfinalpathname_impl(PyObject *module, path_t *path)
4224 /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
4225 {
4226     HANDLE hFile;
4227     wchar_t buf[MAXPATHLEN], *target_path = buf;
4228     int buf_size = Py_ARRAY_LENGTH(buf);
4229     int result_length;
4230     PyObject *result;
4231 
4232     Py_BEGIN_ALLOW_THREADS
4233     hFile = CreateFileW(
4234         path->wide,
4235         0, /* desired access */
4236         0, /* share mode */
4237         NULL, /* security attributes */
4238         OPEN_EXISTING,
4239         /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
4240         FILE_FLAG_BACKUP_SEMANTICS,
4241         NULL);
4242     Py_END_ALLOW_THREADS
4243 
4244     if (hFile == INVALID_HANDLE_VALUE) {
4245         return win32_error_object("CreateFileW", path->object);
4246     }
4247 
4248     /* We have a good handle to the target, use it to determine the
4249        target path name. */
4250     while (1) {
4251         Py_BEGIN_ALLOW_THREADS
4252         result_length = GetFinalPathNameByHandleW(hFile, target_path,
4253                                                   buf_size, VOLUME_NAME_DOS);
4254         Py_END_ALLOW_THREADS
4255 
4256         if (!result_length) {
4257             result = win32_error_object("GetFinalPathNameByHandleW",
4258                                          path->object);
4259             goto cleanup;
4260         }
4261 
4262         if (result_length < buf_size) {
4263             break;
4264         }
4265 
4266         wchar_t *tmp;
4267         tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
4268                             result_length * sizeof(*tmp));
4269         if (!tmp) {
4270             result = PyErr_NoMemory();
4271             goto cleanup;
4272         }
4273 
4274         buf_size = result_length;
4275         target_path = tmp;
4276     }
4277 
4278     result = PyUnicode_FromWideChar(target_path, result_length);
4279     if (result && path->narrow) {
4280         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4281     }
4282 
4283 cleanup:
4284     if (target_path != buf) {
4285         PyMem_Free(target_path);
4286     }
4287     CloseHandle(hFile);
4288     return result;
4289 }
4290 
4291 
4292 /*[clinic input]
4293 os._getvolumepathname
4294 
4295     path: path_t
4296 
4297 A helper function for ismount on Win32.
4298 [clinic start generated code]*/
4299 
4300 static PyObject *
os__getvolumepathname_impl(PyObject * module,path_t * path)4301 os__getvolumepathname_impl(PyObject *module, path_t *path)
4302 /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
4303 {
4304     PyObject *result;
4305     wchar_t *mountpath=NULL;
4306     size_t buflen;
4307     BOOL ret;
4308 
4309     /* Volume path should be shorter than entire path */
4310     buflen = Py_MAX(path->length, MAX_PATH);
4311 
4312     if (buflen > PY_DWORD_MAX) {
4313         PyErr_SetString(PyExc_OverflowError, "path too long");
4314         return NULL;
4315     }
4316 
4317     mountpath = PyMem_New(wchar_t, buflen);
4318     if (mountpath == NULL)
4319         return PyErr_NoMemory();
4320 
4321     Py_BEGIN_ALLOW_THREADS
4322     ret = GetVolumePathNameW(path->wide, mountpath,
4323                              Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
4324     Py_END_ALLOW_THREADS
4325 
4326     if (!ret) {
4327         result = win32_error_object("_getvolumepathname", path->object);
4328         goto exit;
4329     }
4330     result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
4331     if (path->narrow)
4332         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4333 
4334 exit:
4335     PyMem_Free(mountpath);
4336     return result;
4337 }
4338 
4339 #endif /* MS_WINDOWS */
4340 
4341 
4342 /*[clinic input]
4343 os.mkdir
4344 
4345     path : path_t
4346 
4347     mode: int = 0o777
4348 
4349     *
4350 
4351     dir_fd : dir_fd(requires='mkdirat') = None
4352 
4353 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4354 
4355 Create a directory.
4356 
4357 If dir_fd is not None, it should be a file descriptor open to a directory,
4358   and path should be relative; path will then be relative to that directory.
4359 dir_fd may not be implemented on your platform.
4360   If it is unavailable, using it will raise a NotImplementedError.
4361 
4362 The mode argument is ignored on Windows.
4363 [clinic start generated code]*/
4364 
4365 static PyObject *
os_mkdir_impl(PyObject * module,path_t * path,int mode,int dir_fd)4366 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4367 /*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/
4368 {
4369     int result;
4370 #ifdef HAVE_MKDIRAT
4371     int mkdirat_unavailable = 0;
4372 #endif
4373 
4374     if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4375                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4376         return NULL;
4377     }
4378 
4379 #ifdef MS_WINDOWS
4380     Py_BEGIN_ALLOW_THREADS
4381     result = CreateDirectoryW(path->wide, NULL);
4382     Py_END_ALLOW_THREADS
4383 
4384     if (!result)
4385         return path_error(path);
4386 #else
4387     Py_BEGIN_ALLOW_THREADS
4388 #if HAVE_MKDIRAT
4389     if (dir_fd != DEFAULT_DIR_FD) {
4390       if (HAVE_MKDIRAT_RUNTIME) {
4391         result = mkdirat(dir_fd, path->narrow, mode);
4392 
4393       } else {
4394         mkdirat_unavailable = 1;
4395       }
4396     } else
4397 #endif
4398 #if defined(__WATCOMC__) && !defined(__QNX__)
4399         result = mkdir(path->narrow);
4400 #else
4401         result = mkdir(path->narrow, mode);
4402 #endif
4403     Py_END_ALLOW_THREADS
4404 
4405 #if HAVE_MKDIRAT
4406     if (mkdirat_unavailable) {
4407         argument_unavailable_error(NULL, "dir_fd");
4408         return NULL;
4409     }
4410 #endif
4411 
4412     if (result < 0)
4413         return path_error(path);
4414 #endif /* MS_WINDOWS */
4415     Py_RETURN_NONE;
4416 }
4417 
4418 
4419 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4420 #if defined(HAVE_SYS_RESOURCE_H)
4421 #include <sys/resource.h>
4422 #endif
4423 
4424 
4425 #ifdef HAVE_NICE
4426 /*[clinic input]
4427 os.nice
4428 
4429     increment: int
4430     /
4431 
4432 Add increment to the priority of process and return the new priority.
4433 [clinic start generated code]*/
4434 
4435 static PyObject *
os_nice_impl(PyObject * module,int increment)4436 os_nice_impl(PyObject *module, int increment)
4437 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4438 {
4439     int value;
4440 
4441     /* There are two flavours of 'nice': one that returns the new
4442        priority (as required by almost all standards out there) and the
4443        Linux/FreeBSD one, which returns '0' on success and advices
4444        the use of getpriority() to get the new priority.
4445 
4446        If we are of the nice family that returns the new priority, we
4447        need to clear errno before the call, and check if errno is filled
4448        before calling posix_error() on a returnvalue of -1, because the
4449        -1 may be the actual new priority! */
4450 
4451     errno = 0;
4452     value = nice(increment);
4453 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4454     if (value == 0)
4455         value = getpriority(PRIO_PROCESS, 0);
4456 #endif
4457     if (value == -1 && errno != 0)
4458         /* either nice() or getpriority() returned an error */
4459         return posix_error();
4460     return PyLong_FromLong((long) value);
4461 }
4462 #endif /* HAVE_NICE */
4463 
4464 
4465 #ifdef HAVE_GETPRIORITY
4466 /*[clinic input]
4467 os.getpriority
4468 
4469     which: int
4470     who: int
4471 
4472 Return program scheduling priority.
4473 [clinic start generated code]*/
4474 
4475 static PyObject *
os_getpriority_impl(PyObject * module,int which,int who)4476 os_getpriority_impl(PyObject *module, int which, int who)
4477 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4478 {
4479     int retval;
4480 
4481     errno = 0;
4482     retval = getpriority(which, who);
4483     if (errno != 0)
4484         return posix_error();
4485     return PyLong_FromLong((long)retval);
4486 }
4487 #endif /* HAVE_GETPRIORITY */
4488 
4489 
4490 #ifdef HAVE_SETPRIORITY
4491 /*[clinic input]
4492 os.setpriority
4493 
4494     which: int
4495     who: int
4496     priority: int
4497 
4498 Set program scheduling priority.
4499 [clinic start generated code]*/
4500 
4501 static PyObject *
os_setpriority_impl(PyObject * module,int which,int who,int priority)4502 os_setpriority_impl(PyObject *module, int which, int who, int priority)
4503 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4504 {
4505     int retval;
4506 
4507     retval = setpriority(which, who, priority);
4508     if (retval == -1)
4509         return posix_error();
4510     Py_RETURN_NONE;
4511 }
4512 #endif /* HAVE_SETPRIORITY */
4513 
4514 
4515 static PyObject *
internal_rename(path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int is_replace)4516 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4517 {
4518     const char *function_name = is_replace ? "replace" : "rename";
4519     int dir_fd_specified;
4520 
4521 #ifdef HAVE_RENAMEAT
4522     int renameat_unavailable = 0;
4523 #endif
4524 
4525 #ifdef MS_WINDOWS
4526     BOOL result;
4527     int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4528 #else
4529     int result;
4530 #endif
4531 
4532     dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4533                        (dst_dir_fd != DEFAULT_DIR_FD);
4534 #ifndef HAVE_RENAMEAT
4535     if (dir_fd_specified) {
4536         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4537         return NULL;
4538     }
4539 #endif
4540 
4541     if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
4542                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4543                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4544         return NULL;
4545     }
4546 
4547 #ifdef MS_WINDOWS
4548     Py_BEGIN_ALLOW_THREADS
4549     result = MoveFileExW(src->wide, dst->wide, flags);
4550     Py_END_ALLOW_THREADS
4551 
4552     if (!result)
4553         return path_error2(src, dst);
4554 
4555 #else
4556     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4557         PyErr_Format(PyExc_ValueError,
4558                      "%s: src and dst must be the same type", function_name);
4559         return NULL;
4560     }
4561 
4562     Py_BEGIN_ALLOW_THREADS
4563 #ifdef HAVE_RENAMEAT
4564     if (dir_fd_specified) {
4565         if (HAVE_RENAMEAT_RUNTIME) {
4566             result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4567         } else {
4568             renameat_unavailable = 1;
4569         }
4570     } else
4571 #endif
4572     result = rename(src->narrow, dst->narrow);
4573     Py_END_ALLOW_THREADS
4574 
4575 
4576 #ifdef HAVE_RENAMEAT
4577     if (renameat_unavailable) {
4578         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4579         return NULL;
4580     }
4581 #endif
4582 
4583     if (result)
4584         return path_error2(src, dst);
4585 #endif
4586     Py_RETURN_NONE;
4587 }
4588 
4589 
4590 /*[clinic input]
4591 os.rename
4592 
4593     src : path_t
4594     dst : path_t
4595     *
4596     src_dir_fd : dir_fd = None
4597     dst_dir_fd : dir_fd = None
4598 
4599 Rename a file or directory.
4600 
4601 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4602   descriptor open to a directory, and the respective path string (src or dst)
4603   should be relative; the path will then be relative to that directory.
4604 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4605   If they are unavailable, using them will raise a NotImplementedError.
4606 [clinic start generated code]*/
4607 
4608 static PyObject *
os_rename_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4609 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4610                int dst_dir_fd)
4611 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4612 {
4613     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4614 }
4615 
4616 
4617 /*[clinic input]
4618 os.replace = os.rename
4619 
4620 Rename a file or directory, overwriting the destination.
4621 
4622 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4623   descriptor open to a directory, and the respective path string (src or dst)
4624   should be relative; the path will then be relative to that directory.
4625 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4626   If they are unavailable, using them will raise a NotImplementedError.
4627 [clinic start generated code]*/
4628 
4629 static PyObject *
os_replace_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4630 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4631                 int dst_dir_fd)
4632 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4633 {
4634     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4635 }
4636 
4637 
4638 /*[clinic input]
4639 os.rmdir
4640 
4641     path: path_t
4642     *
4643     dir_fd: dir_fd(requires='unlinkat') = None
4644 
4645 Remove a directory.
4646 
4647 If dir_fd is not None, it should be a file descriptor open to a directory,
4648   and path should be relative; path will then be relative to that directory.
4649 dir_fd may not be implemented on your platform.
4650   If it is unavailable, using it will raise a NotImplementedError.
4651 [clinic start generated code]*/
4652 
4653 static PyObject *
os_rmdir_impl(PyObject * module,path_t * path,int dir_fd)4654 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4655 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4656 {
4657     int result;
4658 #ifdef HAVE_UNLINKAT
4659     int unlinkat_unavailable = 0;
4660 #endif
4661 
4662     if (PySys_Audit("os.rmdir", "Oi", path->object,
4663                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4664         return NULL;
4665     }
4666 
4667     Py_BEGIN_ALLOW_THREADS
4668 #ifdef MS_WINDOWS
4669     /* Windows, success=1, UNIX, success=0 */
4670     result = !RemoveDirectoryW(path->wide);
4671 #else
4672 #ifdef HAVE_UNLINKAT
4673     if (dir_fd != DEFAULT_DIR_FD) {
4674       if (HAVE_UNLINKAT_RUNTIME) {
4675         result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4676       } else {
4677         unlinkat_unavailable = 1;
4678         result = -1;
4679       }
4680     } else
4681 #endif
4682         result = rmdir(path->narrow);
4683 #endif
4684     Py_END_ALLOW_THREADS
4685 
4686 #ifdef HAVE_UNLINKAT
4687     if (unlinkat_unavailable) {
4688         argument_unavailable_error("rmdir", "dir_fd");
4689         return NULL;
4690     }
4691 #endif
4692 
4693     if (result)
4694         return path_error(path);
4695 
4696     Py_RETURN_NONE;
4697 }
4698 
4699 
4700 #ifdef HAVE_SYSTEM
4701 #ifdef MS_WINDOWS
4702 /*[clinic input]
4703 os.system -> long
4704 
4705     command: Py_UNICODE
4706 
4707 Execute the command in a subshell.
4708 [clinic start generated code]*/
4709 
4710 static long
os_system_impl(PyObject * module,const Py_UNICODE * command)4711 os_system_impl(PyObject *module, const Py_UNICODE *command)
4712 /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4713 {
4714     long result;
4715 
4716     if (PySys_Audit("os.system", "(u)", command) < 0) {
4717         return -1;
4718     }
4719 
4720     Py_BEGIN_ALLOW_THREADS
4721     _Py_BEGIN_SUPPRESS_IPH
4722     result = _wsystem(command);
4723     _Py_END_SUPPRESS_IPH
4724     Py_END_ALLOW_THREADS
4725     return result;
4726 }
4727 #else /* MS_WINDOWS */
4728 /*[clinic input]
4729 os.system -> long
4730 
4731     command: FSConverter
4732 
4733 Execute the command in a subshell.
4734 [clinic start generated code]*/
4735 
4736 static long
os_system_impl(PyObject * module,PyObject * command)4737 os_system_impl(PyObject *module, PyObject *command)
4738 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4739 {
4740     long result;
4741     const char *bytes = PyBytes_AsString(command);
4742 
4743     if (PySys_Audit("os.system", "(O)", command) < 0) {
4744         return -1;
4745     }
4746 
4747     Py_BEGIN_ALLOW_THREADS
4748     result = system(bytes);
4749     Py_END_ALLOW_THREADS
4750     return result;
4751 }
4752 #endif
4753 #endif /* HAVE_SYSTEM */
4754 
4755 
4756 /*[clinic input]
4757 os.umask
4758 
4759     mask: int
4760     /
4761 
4762 Set the current numeric umask and return the previous umask.
4763 [clinic start generated code]*/
4764 
4765 static PyObject *
os_umask_impl(PyObject * module,int mask)4766 os_umask_impl(PyObject *module, int mask)
4767 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4768 {
4769     int i = (int)umask(mask);
4770     if (i < 0)
4771         return posix_error();
4772     return PyLong_FromLong((long)i);
4773 }
4774 
4775 #ifdef MS_WINDOWS
4776 
4777 /* override the default DeleteFileW behavior so that directory
4778 symlinks can be removed with this function, the same as with
4779 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)4780 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
4781 {
4782     WIN32_FILE_ATTRIBUTE_DATA info;
4783     WIN32_FIND_DATAW find_data;
4784     HANDLE find_data_handle;
4785     int is_directory = 0;
4786     int is_link = 0;
4787 
4788     if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
4789         is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4790 
4791         /* Get WIN32_FIND_DATA structure for the path to determine if
4792            it is a symlink */
4793         if(is_directory &&
4794            info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
4795             find_data_handle = FindFirstFileW(lpFileName, &find_data);
4796 
4797             if(find_data_handle != INVALID_HANDLE_VALUE) {
4798                 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
4799                    IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
4800                 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
4801                           find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
4802                 FindClose(find_data_handle);
4803             }
4804         }
4805     }
4806 
4807     if (is_directory && is_link)
4808         return RemoveDirectoryW(lpFileName);
4809 
4810     return DeleteFileW(lpFileName);
4811 }
4812 #endif /* MS_WINDOWS */
4813 
4814 
4815 /*[clinic input]
4816 os.unlink
4817 
4818     path: path_t
4819     *
4820     dir_fd: dir_fd(requires='unlinkat')=None
4821 
4822 Remove a file (same as remove()).
4823 
4824 If dir_fd is not None, it should be a file descriptor open to a directory,
4825   and path should be relative; path will then be relative to that directory.
4826 dir_fd may not be implemented on your platform.
4827   If it is unavailable, using it will raise a NotImplementedError.
4828 
4829 [clinic start generated code]*/
4830 
4831 static PyObject *
os_unlink_impl(PyObject * module,path_t * path,int dir_fd)4832 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
4833 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
4834 {
4835     int result;
4836 #ifdef HAVE_UNLINKAT
4837     int unlinkat_unavailable = 0;
4838 #endif
4839 
4840     if (PySys_Audit("os.remove", "Oi", path->object,
4841                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4842         return NULL;
4843     }
4844 
4845     Py_BEGIN_ALLOW_THREADS
4846     _Py_BEGIN_SUPPRESS_IPH
4847 #ifdef MS_WINDOWS
4848     /* Windows, success=1, UNIX, success=0 */
4849     result = !Py_DeleteFileW(path->wide);
4850 #else
4851 #ifdef HAVE_UNLINKAT
4852     if (dir_fd != DEFAULT_DIR_FD) {
4853       if (HAVE_UNLINKAT_RUNTIME) {
4854 
4855         result = unlinkat(dir_fd, path->narrow, 0);
4856       } else {
4857         unlinkat_unavailable = 1;
4858       }
4859     } else
4860 #endif /* HAVE_UNLINKAT */
4861         result = unlink(path->narrow);
4862 #endif
4863     _Py_END_SUPPRESS_IPH
4864     Py_END_ALLOW_THREADS
4865 
4866 #ifdef HAVE_UNLINKAT
4867     if (unlinkat_unavailable) {
4868         argument_unavailable_error(NULL, "dir_fd");
4869         return NULL;
4870     }
4871 #endif
4872 
4873     if (result)
4874         return path_error(path);
4875 
4876     Py_RETURN_NONE;
4877 }
4878 
4879 
4880 /*[clinic input]
4881 os.remove = os.unlink
4882 
4883 Remove a file (same as unlink()).
4884 
4885 If dir_fd is not None, it should be a file descriptor open to a directory,
4886   and path should be relative; path will then be relative to that directory.
4887 dir_fd may not be implemented on your platform.
4888   If it is unavailable, using it will raise a NotImplementedError.
4889 [clinic start generated code]*/
4890 
4891 static PyObject *
os_remove_impl(PyObject * module,path_t * path,int dir_fd)4892 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
4893 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
4894 {
4895     return os_unlink_impl(module, path, dir_fd);
4896 }
4897 
4898 
4899 static PyStructSequence_Field uname_result_fields[] = {
4900     {"sysname",    "operating system name"},
4901     {"nodename",   "name of machine on network (implementation-defined)"},
4902     {"release",    "operating system release"},
4903     {"version",    "operating system version"},
4904     {"machine",    "hardware identifier"},
4905     {NULL}
4906 };
4907 
4908 PyDoc_STRVAR(uname_result__doc__,
4909 "uname_result: Result from os.uname().\n\n\
4910 This object may be accessed either as a tuple of\n\
4911   (sysname, nodename, release, version, machine),\n\
4912 or via the attributes sysname, nodename, release, version, and machine.\n\
4913 \n\
4914 See os.uname for more information.");
4915 
4916 static PyStructSequence_Desc uname_result_desc = {
4917     MODNAME ".uname_result", /* name */
4918     uname_result__doc__, /* doc */
4919     uname_result_fields,
4920     5
4921 };
4922 
4923 #ifdef HAVE_UNAME
4924 /*[clinic input]
4925 os.uname
4926 
4927 Return an object identifying the current operating system.
4928 
4929 The object behaves like a named tuple with the following fields:
4930   (sysname, nodename, release, version, machine)
4931 
4932 [clinic start generated code]*/
4933 
4934 static PyObject *
os_uname_impl(PyObject * module)4935 os_uname_impl(PyObject *module)
4936 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
4937 {
4938     struct utsname u;
4939     int res;
4940     PyObject *value;
4941 
4942     Py_BEGIN_ALLOW_THREADS
4943     res = uname(&u);
4944     Py_END_ALLOW_THREADS
4945     if (res < 0)
4946         return posix_error();
4947 
4948     PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
4949     value = PyStructSequence_New((PyTypeObject *)UnameResultType);
4950     if (value == NULL)
4951         return NULL;
4952 
4953 #define SET(i, field) \
4954     { \
4955     PyObject *o = PyUnicode_DecodeFSDefault(field); \
4956     if (!o) { \
4957         Py_DECREF(value); \
4958         return NULL; \
4959     } \
4960     PyStructSequence_SET_ITEM(value, i, o); \
4961     } \
4962 
4963     SET(0, u.sysname);
4964     SET(1, u.nodename);
4965     SET(2, u.release);
4966     SET(3, u.version);
4967     SET(4, u.machine);
4968 
4969 #undef SET
4970 
4971     return value;
4972 }
4973 #endif /* HAVE_UNAME */
4974 
4975 
4976 
4977 typedef struct {
4978     int    now;
4979     time_t atime_s;
4980     long   atime_ns;
4981     time_t mtime_s;
4982     long   mtime_ns;
4983 } utime_t;
4984 
4985 /*
4986  * these macros assume that "ut" is a pointer to a utime_t
4987  * they also intentionally leak the declaration of a pointer named "time"
4988  */
4989 #define UTIME_TO_TIMESPEC \
4990     struct timespec ts[2]; \
4991     struct timespec *time; \
4992     if (ut->now) \
4993         time = NULL; \
4994     else { \
4995         ts[0].tv_sec = ut->atime_s; \
4996         ts[0].tv_nsec = ut->atime_ns; \
4997         ts[1].tv_sec = ut->mtime_s; \
4998         ts[1].tv_nsec = ut->mtime_ns; \
4999         time = ts; \
5000     } \
5001 
5002 #define UTIME_TO_TIMEVAL \
5003     struct timeval tv[2]; \
5004     struct timeval *time; \
5005     if (ut->now) \
5006         time = NULL; \
5007     else { \
5008         tv[0].tv_sec = ut->atime_s; \
5009         tv[0].tv_usec = ut->atime_ns / 1000; \
5010         tv[1].tv_sec = ut->mtime_s; \
5011         tv[1].tv_usec = ut->mtime_ns / 1000; \
5012         time = tv; \
5013     } \
5014 
5015 #define UTIME_TO_UTIMBUF \
5016     struct utimbuf u; \
5017     struct utimbuf *time; \
5018     if (ut->now) \
5019         time = NULL; \
5020     else { \
5021         u.actime = ut->atime_s; \
5022         u.modtime = ut->mtime_s; \
5023         time = &u; \
5024     }
5025 
5026 #define UTIME_TO_TIME_T \
5027     time_t timet[2]; \
5028     time_t *time; \
5029     if (ut->now) \
5030         time = NULL; \
5031     else { \
5032         timet[0] = ut->atime_s; \
5033         timet[1] = ut->mtime_s; \
5034         time = timet; \
5035     } \
5036 
5037 
5038 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5039 
5040 static int
utime_dir_fd(utime_t * ut,int dir_fd,const char * path,int follow_symlinks)5041 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
5042 {
5043 #if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
5044     if (HAVE_UTIMENSAT_RUNTIME) {
5045         int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5046         UTIME_TO_TIMESPEC;
5047         return utimensat(dir_fd, path, time, flags);
5048     }  else {
5049         errno = ENOSYS;
5050         return -1;
5051     }
5052 #elif defined(HAVE_UTIMENSAT)
5053     int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5054     UTIME_TO_TIMESPEC;
5055     return utimensat(dir_fd, path, time, flags);
5056 #elif defined(HAVE_FUTIMESAT)
5057     UTIME_TO_TIMEVAL;
5058     /*
5059      * follow_symlinks will never be false here;
5060      * we only allow !follow_symlinks and dir_fd together
5061      * if we have utimensat()
5062      */
5063     assert(follow_symlinks);
5064     return futimesat(dir_fd, path, time);
5065 #endif
5066 }
5067 
5068     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
5069 #else
5070     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
5071 #endif
5072 
5073 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5074 
5075 static int
utime_fd(utime_t * ut,int fd)5076 utime_fd(utime_t *ut, int fd)
5077 {
5078 #ifdef HAVE_FUTIMENS
5079 
5080     if (HAVE_FUTIMENS_RUNTIME) {
5081 
5082     UTIME_TO_TIMESPEC;
5083     return futimens(fd, time);
5084 
5085     } else
5086 #ifndef HAVE_FUTIMES
5087     {
5088         /* Not sure if this can happen */
5089         PyErr_SetString(
5090             PyExc_RuntimeError,
5091             "neither futimens nor futimes are supported"
5092             " on this system");
5093         return -1;
5094     }
5095 #endif
5096 
5097 #endif
5098 #ifdef HAVE_FUTIMES
5099     {
5100     UTIME_TO_TIMEVAL;
5101     return futimes(fd, time);
5102     }
5103 #endif
5104 }
5105 
5106     #define PATH_UTIME_HAVE_FD 1
5107 #else
5108     #define PATH_UTIME_HAVE_FD 0
5109 #endif
5110 
5111 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
5112 #  define UTIME_HAVE_NOFOLLOW_SYMLINKS
5113 #endif
5114 
5115 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5116 
5117 static int
utime_nofollow_symlinks(utime_t * ut,const char * path)5118 utime_nofollow_symlinks(utime_t *ut, const char *path)
5119 {
5120 #ifdef HAVE_UTIMENSAT
5121     if (HAVE_UTIMENSAT_RUNTIME) {
5122         UTIME_TO_TIMESPEC;
5123         return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
5124     } else
5125 #ifndef HAVE_LUTIMES
5126     {
5127         /* Not sure if this can happen */
5128         PyErr_SetString(
5129             PyExc_RuntimeError,
5130             "neither utimensat nor lutimes are supported"
5131             " on this system");
5132         return -1;
5133     }
5134 #endif
5135 #endif
5136 
5137 #ifdef HAVE_LUTIMES
5138     {
5139     UTIME_TO_TIMEVAL;
5140     return lutimes(path, time);
5141     }
5142 #endif
5143 }
5144 
5145 #endif
5146 
5147 #ifndef MS_WINDOWS
5148 
5149 static int
utime_default(utime_t * ut,const char * path)5150 utime_default(utime_t *ut, const char *path)
5151 {
5152 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5153     if (HAVE_UTIMENSAT_RUNTIME) {
5154         UTIME_TO_TIMESPEC;
5155         return utimensat(DEFAULT_DIR_FD, path, time, 0);
5156     } else {
5157         UTIME_TO_TIMEVAL;
5158         return utimes(path, time);
5159     }
5160 #elif defined(HAVE_UTIMENSAT)
5161     UTIME_TO_TIMESPEC;
5162     return utimensat(DEFAULT_DIR_FD, path, time, 0);
5163 #elif defined(HAVE_UTIMES)
5164     UTIME_TO_TIMEVAL;
5165     return utimes(path, time);
5166 #elif defined(HAVE_UTIME_H)
5167     UTIME_TO_UTIMBUF;
5168     return utime(path, time);
5169 #else
5170     UTIME_TO_TIME_T;
5171     return utime(path, time);
5172 #endif
5173 }
5174 
5175 #endif
5176 
5177 static int
split_py_long_to_s_and_ns(PyObject * module,PyObject * py_long,time_t * s,long * ns)5178 split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5179 {
5180     int result = 0;
5181     PyObject *divmod;
5182     divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5183     if (!divmod)
5184         goto exit;
5185     if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
5186         PyErr_Format(PyExc_TypeError,
5187                      "%.200s.__divmod__() must return a 2-tuple, not %.200s",
5188                      _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
5189         goto exit;
5190     }
5191     *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5192     if ((*s == -1) && PyErr_Occurred())
5193         goto exit;
5194     *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5195     if ((*ns == -1) && PyErr_Occurred())
5196         goto exit;
5197 
5198     result = 1;
5199 exit:
5200     Py_XDECREF(divmod);
5201     return result;
5202 }
5203 
5204 
5205 /*[clinic input]
5206 os.utime
5207 
5208     path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
5209     times: object = None
5210     *
5211     ns: object = NULL
5212     dir_fd: dir_fd(requires='futimensat') = None
5213     follow_symlinks: bool=True
5214 
5215 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
5216 
5217 Set the access and modified time of path.
5218 
5219 path may always be specified as a string.
5220 On some platforms, path may also be specified as an open file descriptor.
5221   If this functionality is unavailable, using it raises an exception.
5222 
5223 If times is not None, it must be a tuple (atime, mtime);
5224     atime and mtime should be expressed as float seconds since the epoch.
5225 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
5226     atime_ns and mtime_ns should be expressed as integer nanoseconds
5227     since the epoch.
5228 If times is None and ns is unspecified, utime uses the current time.
5229 Specifying tuples for both times and ns is an error.
5230 
5231 If dir_fd is not None, it should be a file descriptor open to a directory,
5232   and path should be relative; path will then be relative to that directory.
5233 If follow_symlinks is False, and the last element of the path is a symbolic
5234   link, utime will modify the symbolic link itself instead of the file the
5235   link points to.
5236 It is an error to use dir_fd or follow_symlinks when specifying path
5237   as an open file descriptor.
5238 dir_fd and follow_symlinks may not be available on your platform.
5239   If they are unavailable, using them will raise a NotImplementedError.
5240 
5241 [clinic start generated code]*/
5242 
5243 static PyObject *
os_utime_impl(PyObject * module,path_t * path,PyObject * times,PyObject * ns,int dir_fd,int follow_symlinks)5244 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
5245               int dir_fd, int follow_symlinks)
5246 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
5247 {
5248 #ifdef MS_WINDOWS
5249     HANDLE hFile;
5250     FILETIME atime, mtime;
5251 #else
5252     int result;
5253 #endif
5254 
5255     utime_t utime;
5256 
5257     memset(&utime, 0, sizeof(utime_t));
5258 
5259     if (times != Py_None && ns) {
5260         PyErr_SetString(PyExc_ValueError,
5261                      "utime: you may specify either 'times'"
5262                      " or 'ns' but not both");
5263         return NULL;
5264     }
5265 
5266     if (times != Py_None) {
5267         time_t a_sec, m_sec;
5268         long a_nsec, m_nsec;
5269         if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
5270             PyErr_SetString(PyExc_TypeError,
5271                          "utime: 'times' must be either"
5272                          " a tuple of two ints or None");
5273             return NULL;
5274         }
5275         utime.now = 0;
5276         if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
5277                                      &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
5278             _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
5279                                      &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
5280             return NULL;
5281         }
5282         utime.atime_s = a_sec;
5283         utime.atime_ns = a_nsec;
5284         utime.mtime_s = m_sec;
5285         utime.mtime_ns = m_nsec;
5286     }
5287     else if (ns) {
5288         if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
5289             PyErr_SetString(PyExc_TypeError,
5290                          "utime: 'ns' must be a tuple of two ints");
5291             return NULL;
5292         }
5293         utime.now = 0;
5294         if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
5295                                       &utime.atime_s, &utime.atime_ns) ||
5296             !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
5297                                        &utime.mtime_s, &utime.mtime_ns)) {
5298             return NULL;
5299         }
5300     }
5301     else {
5302         /* times and ns are both None/unspecified. use "now". */
5303         utime.now = 1;
5304     }
5305 
5306 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
5307     if (follow_symlinks_specified("utime", follow_symlinks))
5308         return NULL;
5309 #endif
5310 
5311     if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
5312         dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
5313         fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
5314         return NULL;
5315 
5316 #if !defined(HAVE_UTIMENSAT)
5317     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
5318         PyErr_SetString(PyExc_ValueError,
5319                      "utime: cannot use dir_fd and follow_symlinks "
5320                      "together on this platform");
5321         return NULL;
5322     }
5323 #endif
5324 
5325     if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
5326                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5327         return NULL;
5328     }
5329 
5330 #ifdef MS_WINDOWS
5331     Py_BEGIN_ALLOW_THREADS
5332     hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
5333                         NULL, OPEN_EXISTING,
5334                         FILE_FLAG_BACKUP_SEMANTICS, NULL);
5335     Py_END_ALLOW_THREADS
5336     if (hFile == INVALID_HANDLE_VALUE) {
5337         path_error(path);
5338         return NULL;
5339     }
5340 
5341     if (utime.now) {
5342         GetSystemTimeAsFileTime(&mtime);
5343         atime = mtime;
5344     }
5345     else {
5346         _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
5347         _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
5348     }
5349     if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
5350         /* Avoid putting the file name into the error here,
5351            as that may confuse the user into believing that
5352            something is wrong with the file, when it also
5353            could be the time stamp that gives a problem. */
5354         PyErr_SetFromWindowsErr(0);
5355         CloseHandle(hFile);
5356         return NULL;
5357     }
5358     CloseHandle(hFile);
5359 #else /* MS_WINDOWS */
5360     Py_BEGIN_ALLOW_THREADS
5361 
5362 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5363     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
5364         result = utime_nofollow_symlinks(&utime, path->narrow);
5365     else
5366 #endif
5367 
5368 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5369     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
5370         result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
5371 
5372     } else
5373 #endif
5374 
5375 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5376     if (path->fd != -1)
5377         result = utime_fd(&utime, path->fd);
5378     else
5379 #endif
5380 
5381     result = utime_default(&utime, path->narrow);
5382 
5383     Py_END_ALLOW_THREADS
5384 
5385 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5386     /* See utime_dir_fd implementation */
5387     if (result == -1 && errno == ENOSYS) {
5388         argument_unavailable_error(NULL, "dir_fd");
5389         return NULL;
5390     }
5391 #endif
5392 
5393     if (result < 0) {
5394         /* see previous comment about not putting filename in error here */
5395         posix_error();
5396         return NULL;
5397     }
5398 
5399 #endif /* MS_WINDOWS */
5400 
5401     Py_RETURN_NONE;
5402 }
5403 
5404 /* Process operations */
5405 
5406 
5407 /*[clinic input]
5408 os._exit
5409 
5410     status: int
5411 
5412 Exit to the system with specified status, without normal exit processing.
5413 [clinic start generated code]*/
5414 
5415 static PyObject *
os__exit_impl(PyObject * module,int status)5416 os__exit_impl(PyObject *module, int status)
5417 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5418 {
5419     _exit(status);
5420     return NULL; /* Make gcc -Wall happy */
5421 }
5422 
5423 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5424 #define EXECV_CHAR wchar_t
5425 #else
5426 #define EXECV_CHAR char
5427 #endif
5428 
5429 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5430 static void
free_string_array(EXECV_CHAR ** array,Py_ssize_t count)5431 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5432 {
5433     Py_ssize_t i;
5434     for (i = 0; i < count; i++)
5435         PyMem_Free(array[i]);
5436     PyMem_DEL(array);
5437 }
5438 
5439 static int
fsconvert_strdup(PyObject * o,EXECV_CHAR ** out)5440 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5441 {
5442     Py_ssize_t size;
5443     PyObject *ub;
5444     int result = 0;
5445 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5446     if (!PyUnicode_FSDecoder(o, &ub))
5447         return 0;
5448     *out = PyUnicode_AsWideCharString(ub, &size);
5449     if (*out)
5450         result = 1;
5451 #else
5452     if (!PyUnicode_FSConverter(o, &ub))
5453         return 0;
5454     size = PyBytes_GET_SIZE(ub);
5455     *out = PyMem_Malloc(size + 1);
5456     if (*out) {
5457         memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5458         result = 1;
5459     } else
5460         PyErr_NoMemory();
5461 #endif
5462     Py_DECREF(ub);
5463     return result;
5464 }
5465 #endif
5466 
5467 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5468 static EXECV_CHAR**
parse_envlist(PyObject * env,Py_ssize_t * envc_ptr)5469 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5470 {
5471     Py_ssize_t i, pos, envc;
5472     PyObject *keys=NULL, *vals=NULL;
5473     PyObject *key, *val, *key2, *val2, *keyval;
5474     EXECV_CHAR **envlist;
5475 
5476     i = PyMapping_Size(env);
5477     if (i < 0)
5478         return NULL;
5479     envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5480     if (envlist == NULL) {
5481         PyErr_NoMemory();
5482         return NULL;
5483     }
5484     envc = 0;
5485     keys = PyMapping_Keys(env);
5486     if (!keys)
5487         goto error;
5488     vals = PyMapping_Values(env);
5489     if (!vals)
5490         goto error;
5491     if (!PyList_Check(keys) || !PyList_Check(vals)) {
5492         PyErr_Format(PyExc_TypeError,
5493                      "env.keys() or env.values() is not a list");
5494         goto error;
5495     }
5496 
5497     for (pos = 0; pos < i; pos++) {
5498         key = PyList_GetItem(keys, pos);
5499         val = PyList_GetItem(vals, pos);
5500         if (!key || !val)
5501             goto error;
5502 
5503 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5504         if (!PyUnicode_FSDecoder(key, &key2))
5505             goto error;
5506         if (!PyUnicode_FSDecoder(val, &val2)) {
5507             Py_DECREF(key2);
5508             goto error;
5509         }
5510         /* Search from index 1 because on Windows starting '=' is allowed for
5511            defining hidden environment variables. */
5512         if (PyUnicode_GET_LENGTH(key2) == 0 ||
5513             PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5514         {
5515             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5516             Py_DECREF(key2);
5517             Py_DECREF(val2);
5518             goto error;
5519         }
5520         keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5521 #else
5522         if (!PyUnicode_FSConverter(key, &key2))
5523             goto error;
5524         if (!PyUnicode_FSConverter(val, &val2)) {
5525             Py_DECREF(key2);
5526             goto error;
5527         }
5528         if (PyBytes_GET_SIZE(key2) == 0 ||
5529             strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5530         {
5531             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5532             Py_DECREF(key2);
5533             Py_DECREF(val2);
5534             goto error;
5535         }
5536         keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5537                                              PyBytes_AS_STRING(val2));
5538 #endif
5539         Py_DECREF(key2);
5540         Py_DECREF(val2);
5541         if (!keyval)
5542             goto error;
5543 
5544         if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5545             Py_DECREF(keyval);
5546             goto error;
5547         }
5548 
5549         Py_DECREF(keyval);
5550     }
5551     Py_DECREF(vals);
5552     Py_DECREF(keys);
5553 
5554     envlist[envc] = 0;
5555     *envc_ptr = envc;
5556     return envlist;
5557 
5558 error:
5559     Py_XDECREF(keys);
5560     Py_XDECREF(vals);
5561     free_string_array(envlist, envc);
5562     return NULL;
5563 }
5564 
5565 static EXECV_CHAR**
parse_arglist(PyObject * argv,Py_ssize_t * argc)5566 parse_arglist(PyObject* argv, Py_ssize_t *argc)
5567 {
5568     int i;
5569     EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5570     if (argvlist == NULL) {
5571         PyErr_NoMemory();
5572         return NULL;
5573     }
5574     for (i = 0; i < *argc; i++) {
5575         PyObject* item = PySequence_ITEM(argv, i);
5576         if (item == NULL)
5577             goto fail;
5578         if (!fsconvert_strdup(item, &argvlist[i])) {
5579             Py_DECREF(item);
5580             goto fail;
5581         }
5582         Py_DECREF(item);
5583     }
5584     argvlist[*argc] = NULL;
5585     return argvlist;
5586 fail:
5587     *argc = i;
5588     free_string_array(argvlist, *argc);
5589     return NULL;
5590 }
5591 
5592 #endif
5593 
5594 
5595 #ifdef HAVE_EXECV
5596 /*[clinic input]
5597 os.execv
5598 
5599     path: path_t
5600         Path of executable file.
5601     argv: object
5602         Tuple or list of strings.
5603     /
5604 
5605 Execute an executable path with arguments, replacing current process.
5606 [clinic start generated code]*/
5607 
5608 static PyObject *
os_execv_impl(PyObject * module,path_t * path,PyObject * argv)5609 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5610 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5611 {
5612     EXECV_CHAR **argvlist;
5613     Py_ssize_t argc;
5614 
5615     /* execv has two arguments: (path, argv), where
5616        argv is a list or tuple of strings. */
5617 
5618     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5619         PyErr_SetString(PyExc_TypeError,
5620                         "execv() arg 2 must be a tuple or list");
5621         return NULL;
5622     }
5623     argc = PySequence_Size(argv);
5624     if (argc < 1) {
5625         PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5626         return NULL;
5627     }
5628 
5629     argvlist = parse_arglist(argv, &argc);
5630     if (argvlist == NULL) {
5631         return NULL;
5632     }
5633     if (!argvlist[0][0]) {
5634         PyErr_SetString(PyExc_ValueError,
5635             "execv() arg 2 first element cannot be empty");
5636         free_string_array(argvlist, argc);
5637         return NULL;
5638     }
5639 
5640     if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5641         free_string_array(argvlist, argc);
5642         return NULL;
5643     }
5644 
5645     _Py_BEGIN_SUPPRESS_IPH
5646 #ifdef HAVE_WEXECV
5647     _wexecv(path->wide, argvlist);
5648 #else
5649     execv(path->narrow, argvlist);
5650 #endif
5651     _Py_END_SUPPRESS_IPH
5652 
5653     /* If we get here it's definitely an error */
5654 
5655     free_string_array(argvlist, argc);
5656     return posix_error();
5657 }
5658 
5659 
5660 /*[clinic input]
5661 os.execve
5662 
5663     path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5664         Path of executable file.
5665     argv: object
5666         Tuple or list of strings.
5667     env: object
5668         Dictionary of strings mapping to strings.
5669 
5670 Execute an executable path with arguments, replacing current process.
5671 [clinic start generated code]*/
5672 
5673 static PyObject *
os_execve_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env)5674 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5675 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5676 {
5677     EXECV_CHAR **argvlist = NULL;
5678     EXECV_CHAR **envlist;
5679     Py_ssize_t argc, envc;
5680 
5681     /* execve has three arguments: (path, argv, env), where
5682        argv is a list or tuple of strings and env is a dictionary
5683        like posix.environ. */
5684 
5685     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5686         PyErr_SetString(PyExc_TypeError,
5687                         "execve: argv must be a tuple or list");
5688         goto fail_0;
5689     }
5690     argc = PySequence_Size(argv);
5691     if (argc < 1) {
5692         PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5693         return NULL;
5694     }
5695 
5696     if (!PyMapping_Check(env)) {
5697         PyErr_SetString(PyExc_TypeError,
5698                         "execve: environment must be a mapping object");
5699         goto fail_0;
5700     }
5701 
5702     argvlist = parse_arglist(argv, &argc);
5703     if (argvlist == NULL) {
5704         goto fail_0;
5705     }
5706     if (!argvlist[0][0]) {
5707         PyErr_SetString(PyExc_ValueError,
5708             "execve: argv first element cannot be empty");
5709         goto fail_0;
5710     }
5711 
5712     envlist = parse_envlist(env, &envc);
5713     if (envlist == NULL)
5714         goto fail_0;
5715 
5716     if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5717         goto fail_1;
5718     }
5719 
5720     _Py_BEGIN_SUPPRESS_IPH
5721 #ifdef HAVE_FEXECVE
5722     if (path->fd > -1)
5723         fexecve(path->fd, argvlist, envlist);
5724     else
5725 #endif
5726 #ifdef HAVE_WEXECV
5727         _wexecve(path->wide, argvlist, envlist);
5728 #else
5729         execve(path->narrow, argvlist, envlist);
5730 #endif
5731     _Py_END_SUPPRESS_IPH
5732 
5733     /* If we get here it's definitely an error */
5734 
5735     posix_path_error(path);
5736   fail_1:
5737     free_string_array(envlist, envc);
5738   fail_0:
5739     if (argvlist)
5740         free_string_array(argvlist, argc);
5741     return NULL;
5742 }
5743 
5744 #endif /* HAVE_EXECV */
5745 
5746 #ifdef HAVE_POSIX_SPAWN
5747 
5748 enum posix_spawn_file_actions_identifier {
5749     POSIX_SPAWN_OPEN,
5750     POSIX_SPAWN_CLOSE,
5751     POSIX_SPAWN_DUP2
5752 };
5753 
5754 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
5755 static int
5756 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
5757 #endif
5758 
5759 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)5760 parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
5761                         int resetids, int setsid, PyObject *setsigmask,
5762                         PyObject *setsigdef, PyObject *scheduler,
5763                         posix_spawnattr_t *attrp)
5764 {
5765     long all_flags = 0;
5766 
5767     errno = posix_spawnattr_init(attrp);
5768     if (errno) {
5769         posix_error();
5770         return -1;
5771     }
5772 
5773     if (setpgroup) {
5774         pid_t pgid = PyLong_AsPid(setpgroup);
5775         if (pgid == (pid_t)-1 && PyErr_Occurred()) {
5776             goto fail;
5777         }
5778         errno = posix_spawnattr_setpgroup(attrp, pgid);
5779         if (errno) {
5780             posix_error();
5781             goto fail;
5782         }
5783         all_flags |= POSIX_SPAWN_SETPGROUP;
5784     }
5785 
5786     if (resetids) {
5787         all_flags |= POSIX_SPAWN_RESETIDS;
5788     }
5789 
5790     if (setsid) {
5791 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5792         if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
5793 #endif
5794 #ifdef POSIX_SPAWN_SETSID
5795         all_flags |= POSIX_SPAWN_SETSID;
5796 #elif defined(POSIX_SPAWN_SETSID_NP)
5797         all_flags |= POSIX_SPAWN_SETSID_NP;
5798 #else
5799         argument_unavailable_error(func_name, "setsid");
5800         return -1;
5801 #endif
5802 
5803 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5804         } else {
5805             argument_unavailable_error(func_name, "setsid");
5806             return -1;
5807         }
5808 #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
5809 
5810     }
5811 
5812    if (setsigmask) {
5813         sigset_t set;
5814         if (!_Py_Sigset_Converter(setsigmask, &set)) {
5815             goto fail;
5816         }
5817         errno = posix_spawnattr_setsigmask(attrp, &set);
5818         if (errno) {
5819             posix_error();
5820             goto fail;
5821         }
5822         all_flags |= POSIX_SPAWN_SETSIGMASK;
5823     }
5824 
5825     if (setsigdef) {
5826         sigset_t set;
5827         if (!_Py_Sigset_Converter(setsigdef, &set)) {
5828             goto fail;
5829         }
5830         errno = posix_spawnattr_setsigdefault(attrp, &set);
5831         if (errno) {
5832             posix_error();
5833             goto fail;
5834         }
5835         all_flags |= POSIX_SPAWN_SETSIGDEF;
5836     }
5837 
5838     if (scheduler) {
5839 #ifdef POSIX_SPAWN_SETSCHEDULER
5840         PyObject *py_schedpolicy;
5841         PyObject *schedparam_obj;
5842         struct sched_param schedparam;
5843 
5844         if (!PyArg_ParseTuple(scheduler, "OO"
5845                         ";A scheduler tuple must have two elements",
5846                         &py_schedpolicy, &schedparam_obj)) {
5847             goto fail;
5848         }
5849         if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
5850             goto fail;
5851         }
5852         if (py_schedpolicy != Py_None) {
5853             int schedpolicy = _PyLong_AsInt(py_schedpolicy);
5854 
5855             if (schedpolicy == -1 && PyErr_Occurred()) {
5856                 goto fail;
5857             }
5858             errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
5859             if (errno) {
5860                 posix_error();
5861                 goto fail;
5862             }
5863             all_flags |= POSIX_SPAWN_SETSCHEDULER;
5864         }
5865         errno = posix_spawnattr_setschedparam(attrp, &schedparam);
5866         if (errno) {
5867             posix_error();
5868             goto fail;
5869         }
5870         all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
5871 #else
5872         PyErr_SetString(PyExc_NotImplementedError,
5873                 "The scheduler option is not supported in this system.");
5874         goto fail;
5875 #endif
5876     }
5877 
5878     errno = posix_spawnattr_setflags(attrp, all_flags);
5879     if (errno) {
5880         posix_error();
5881         goto fail;
5882     }
5883 
5884     return 0;
5885 
5886 fail:
5887     (void)posix_spawnattr_destroy(attrp);
5888     return -1;
5889 }
5890 
5891 static int
parse_file_actions(PyObject * file_actions,posix_spawn_file_actions_t * file_actionsp,PyObject * temp_buffer)5892 parse_file_actions(PyObject *file_actions,
5893                    posix_spawn_file_actions_t *file_actionsp,
5894                    PyObject *temp_buffer)
5895 {
5896     PyObject *seq;
5897     PyObject *file_action = NULL;
5898     PyObject *tag_obj;
5899 
5900     seq = PySequence_Fast(file_actions,
5901                           "file_actions must be a sequence or None");
5902     if (seq == NULL) {
5903         return -1;
5904     }
5905 
5906     errno = posix_spawn_file_actions_init(file_actionsp);
5907     if (errno) {
5908         posix_error();
5909         Py_DECREF(seq);
5910         return -1;
5911     }
5912 
5913     for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
5914         file_action = PySequence_Fast_GET_ITEM(seq, i);
5915         Py_INCREF(file_action);
5916         if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
5917             PyErr_SetString(PyExc_TypeError,
5918                 "Each file_actions element must be a non-empty tuple");
5919             goto fail;
5920         }
5921         long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
5922         if (tag == -1 && PyErr_Occurred()) {
5923             goto fail;
5924         }
5925 
5926         /* Populate the file_actions object */
5927         switch (tag) {
5928             case POSIX_SPAWN_OPEN: {
5929                 int fd, oflag;
5930                 PyObject *path;
5931                 unsigned long mode;
5932                 if (!PyArg_ParseTuple(file_action, "OiO&ik"
5933                         ";A open file_action tuple must have 5 elements",
5934                         &tag_obj, &fd, PyUnicode_FSConverter, &path,
5935                         &oflag, &mode))
5936                 {
5937                     goto fail;
5938                 }
5939                 if (PyList_Append(temp_buffer, path)) {
5940                     Py_DECREF(path);
5941                     goto fail;
5942                 }
5943                 errno = posix_spawn_file_actions_addopen(file_actionsp,
5944                         fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
5945                 Py_DECREF(path);
5946                 if (errno) {
5947                     posix_error();
5948                     goto fail;
5949                 }
5950                 break;
5951             }
5952             case POSIX_SPAWN_CLOSE: {
5953                 int fd;
5954                 if (!PyArg_ParseTuple(file_action, "Oi"
5955                         ";A close file_action tuple must have 2 elements",
5956                         &tag_obj, &fd))
5957                 {
5958                     goto fail;
5959                 }
5960                 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
5961                 if (errno) {
5962                     posix_error();
5963                     goto fail;
5964                 }
5965                 break;
5966             }
5967             case POSIX_SPAWN_DUP2: {
5968                 int fd1, fd2;
5969                 if (!PyArg_ParseTuple(file_action, "Oii"
5970                         ";A dup2 file_action tuple must have 3 elements",
5971                         &tag_obj, &fd1, &fd2))
5972                 {
5973                     goto fail;
5974                 }
5975                 errno = posix_spawn_file_actions_adddup2(file_actionsp,
5976                                                          fd1, fd2);
5977                 if (errno) {
5978                     posix_error();
5979                     goto fail;
5980                 }
5981                 break;
5982             }
5983             default: {
5984                 PyErr_SetString(PyExc_TypeError,
5985                                 "Unknown file_actions identifier");
5986                 goto fail;
5987             }
5988         }
5989         Py_DECREF(file_action);
5990     }
5991 
5992     Py_DECREF(seq);
5993     return 0;
5994 
5995 fail:
5996     Py_DECREF(seq);
5997     Py_DECREF(file_action);
5998     (void)posix_spawn_file_actions_destroy(file_actionsp);
5999     return -1;
6000 }
6001 
6002 
6003 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)6004 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
6005                PyObject *env, PyObject *file_actions,
6006                PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
6007                PyObject *setsigdef, PyObject *scheduler)
6008 {
6009     const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
6010     EXECV_CHAR **argvlist = NULL;
6011     EXECV_CHAR **envlist = NULL;
6012     posix_spawn_file_actions_t file_actions_buf;
6013     posix_spawn_file_actions_t *file_actionsp = NULL;
6014     posix_spawnattr_t attr;
6015     posix_spawnattr_t *attrp = NULL;
6016     Py_ssize_t argc, envc;
6017     PyObject *result = NULL;
6018     PyObject *temp_buffer = NULL;
6019     pid_t pid;
6020     int err_code;
6021 
6022     /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
6023        argv is a list or tuple of strings and env is a dictionary
6024        like posix.environ. */
6025 
6026     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6027         PyErr_Format(PyExc_TypeError,
6028                      "%s: argv must be a tuple or list", func_name);
6029         goto exit;
6030     }
6031     argc = PySequence_Size(argv);
6032     if (argc < 1) {
6033         PyErr_Format(PyExc_ValueError,
6034                      "%s: argv must not be empty", func_name);
6035         return NULL;
6036     }
6037 
6038     if (!PyMapping_Check(env)) {
6039         PyErr_Format(PyExc_TypeError,
6040                      "%s: environment must be a mapping object", func_name);
6041         goto exit;
6042     }
6043 
6044     argvlist = parse_arglist(argv, &argc);
6045     if (argvlist == NULL) {
6046         goto exit;
6047     }
6048     if (!argvlist[0][0]) {
6049         PyErr_Format(PyExc_ValueError,
6050                      "%s: argv first element cannot be empty", func_name);
6051         goto exit;
6052     }
6053 
6054     envlist = parse_envlist(env, &envc);
6055     if (envlist == NULL) {
6056         goto exit;
6057     }
6058 
6059     if (file_actions != NULL && file_actions != Py_None) {
6060         /* There is a bug in old versions of glibc that makes some of the
6061          * helper functions for manipulating file actions not copy the provided
6062          * buffers. The problem is that posix_spawn_file_actions_addopen does not
6063          * copy the value of path for some old versions of glibc (<2.20).
6064          * The use of temp_buffer here is a workaround that keeps the
6065          * python objects that own the buffers alive until posix_spawn gets called.
6066          * Check https://bugs.python.org/issue33630 and
6067          * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
6068         temp_buffer = PyList_New(0);
6069         if (!temp_buffer) {
6070             goto exit;
6071         }
6072         if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
6073             goto exit;
6074         }
6075         file_actionsp = &file_actions_buf;
6076     }
6077 
6078     if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
6079                                 setsigmask, setsigdef, scheduler, &attr)) {
6080         goto exit;
6081     }
6082     attrp = &attr;
6083 
6084     if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
6085         goto exit;
6086     }
6087 
6088     _Py_BEGIN_SUPPRESS_IPH
6089 #ifdef HAVE_POSIX_SPAWNP
6090     if (use_posix_spawnp) {
6091         err_code = posix_spawnp(&pid, path->narrow,
6092                                 file_actionsp, attrp, argvlist, envlist);
6093     }
6094     else
6095 #endif /* HAVE_POSIX_SPAWNP */
6096     {
6097         err_code = posix_spawn(&pid, path->narrow,
6098                                file_actionsp, attrp, argvlist, envlist);
6099     }
6100     _Py_END_SUPPRESS_IPH
6101 
6102     if (err_code) {
6103         errno = err_code;
6104         PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
6105         goto exit;
6106     }
6107 #ifdef _Py_MEMORY_SANITIZER
6108     __msan_unpoison(&pid, sizeof(pid));
6109 #endif
6110     result = PyLong_FromPid(pid);
6111 
6112 exit:
6113     if (file_actionsp) {
6114         (void)posix_spawn_file_actions_destroy(file_actionsp);
6115     }
6116     if (attrp) {
6117         (void)posix_spawnattr_destroy(attrp);
6118     }
6119     if (envlist) {
6120         free_string_array(envlist, envc);
6121     }
6122     if (argvlist) {
6123         free_string_array(argvlist, argc);
6124     }
6125     Py_XDECREF(temp_buffer);
6126     return result;
6127 }
6128 
6129 
6130 /*[clinic input]
6131 
6132 os.posix_spawn
6133     path: path_t
6134         Path of executable file.
6135     argv: object
6136         Tuple or list of strings.
6137     env: object
6138         Dictionary of strings mapping to strings.
6139     /
6140     *
6141     file_actions: object(c_default='NULL') = ()
6142         A sequence of file action tuples.
6143     setpgroup: object = NULL
6144         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6145     resetids: bool(accept={int}) = False
6146         If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
6147     setsid: bool(accept={int}) = False
6148         If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6149     setsigmask: object(c_default='NULL') = ()
6150         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6151     setsigdef: object(c_default='NULL') = ()
6152         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6153     scheduler: object = NULL
6154         A tuple with the scheduler policy (optional) and parameters.
6155 
6156 Execute the program specified by path in a new process.
6157 [clinic start generated code]*/
6158 
6159 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)6160 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
6161                     PyObject *env, PyObject *file_actions,
6162                     PyObject *setpgroup, int resetids, int setsid,
6163                     PyObject *setsigmask, PyObject *setsigdef,
6164                     PyObject *scheduler)
6165 /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
6166 {
6167     return py_posix_spawn(0, module, path, argv, env, file_actions,
6168                           setpgroup, resetids, setsid, setsigmask, setsigdef,
6169                           scheduler);
6170 }
6171  #endif /* HAVE_POSIX_SPAWN */
6172 
6173 
6174 
6175 #ifdef HAVE_POSIX_SPAWNP
6176 /*[clinic input]
6177 
6178 os.posix_spawnp
6179     path: path_t
6180         Path of executable file.
6181     argv: object
6182         Tuple or list of strings.
6183     env: object
6184         Dictionary of strings mapping to strings.
6185     /
6186     *
6187     file_actions: object(c_default='NULL') = ()
6188         A sequence of file action tuples.
6189     setpgroup: object = NULL
6190         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6191     resetids: bool(accept={int}) = False
6192         If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
6193     setsid: bool(accept={int}) = False
6194         If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6195     setsigmask: object(c_default='NULL') = ()
6196         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6197     setsigdef: object(c_default='NULL') = ()
6198         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6199     scheduler: object = NULL
6200         A tuple with the scheduler policy (optional) and parameters.
6201 
6202 Execute the program specified by path in a new process.
6203 [clinic start generated code]*/
6204 
6205 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)6206 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
6207                      PyObject *env, PyObject *file_actions,
6208                      PyObject *setpgroup, int resetids, int setsid,
6209                      PyObject *setsigmask, PyObject *setsigdef,
6210                      PyObject *scheduler)
6211 /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
6212 {
6213     return py_posix_spawn(1, module, path, argv, env, file_actions,
6214                           setpgroup, resetids, setsid, setsigmask, setsigdef,
6215                           scheduler);
6216 }
6217 #endif /* HAVE_POSIX_SPAWNP */
6218 
6219 #ifdef HAVE_RTPSPAWN
6220 static intptr_t
_rtp_spawn(int mode,const char * rtpFileName,const char * argv[],const char * envp[])6221 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
6222                const char  *envp[])
6223 {
6224      RTP_ID rtpid;
6225      int status;
6226      pid_t res;
6227      int async_err = 0;
6228 
6229      /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
6230         uStackSize=0 cannot be used, the default stack size is too small for
6231         Python. */
6232      if (envp) {
6233          rtpid = rtpSpawn(rtpFileName, argv, envp,
6234                           100, 0x1000000, 0, VX_FP_TASK);
6235      }
6236      else {
6237          rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
6238                           100, 0x1000000, 0, VX_FP_TASK);
6239      }
6240      if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
6241          do {
6242              res = waitpid((pid_t)rtpid, &status, 0);
6243          } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6244 
6245          if (res < 0)
6246              return RTP_ID_ERROR;
6247          return ((intptr_t)status);
6248      }
6249      return ((intptr_t)rtpid);
6250 }
6251 #endif
6252 
6253 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
6254 /*[clinic input]
6255 os.spawnv
6256 
6257     mode: int
6258         Mode of process creation.
6259     path: path_t
6260         Path of executable file.
6261     argv: object
6262         Tuple or list of strings.
6263     /
6264 
6265 Execute the program specified by path in a new process.
6266 [clinic start generated code]*/
6267 
6268 static PyObject *
os_spawnv_impl(PyObject * module,int mode,path_t * path,PyObject * argv)6269 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
6270 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
6271 {
6272     EXECV_CHAR **argvlist;
6273     int i;
6274     Py_ssize_t argc;
6275     intptr_t spawnval;
6276     PyObject *(*getitem)(PyObject *, Py_ssize_t);
6277 
6278     /* spawnv has three arguments: (mode, path, argv), where
6279        argv is a list or tuple of strings. */
6280 
6281     if (PyList_Check(argv)) {
6282         argc = PyList_Size(argv);
6283         getitem = PyList_GetItem;
6284     }
6285     else if (PyTuple_Check(argv)) {
6286         argc = PyTuple_Size(argv);
6287         getitem = PyTuple_GetItem;
6288     }
6289     else {
6290         PyErr_SetString(PyExc_TypeError,
6291                         "spawnv() arg 2 must be a tuple or list");
6292         return NULL;
6293     }
6294     if (argc == 0) {
6295         PyErr_SetString(PyExc_ValueError,
6296             "spawnv() arg 2 cannot be empty");
6297         return NULL;
6298     }
6299 
6300     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6301     if (argvlist == NULL) {
6302         return PyErr_NoMemory();
6303     }
6304     for (i = 0; i < argc; i++) {
6305         if (!fsconvert_strdup((*getitem)(argv, i),
6306                               &argvlist[i])) {
6307             free_string_array(argvlist, i);
6308             PyErr_SetString(
6309                 PyExc_TypeError,
6310                 "spawnv() arg 2 must contain only strings");
6311             return NULL;
6312         }
6313         if (i == 0 && !argvlist[0][0]) {
6314             free_string_array(argvlist, i + 1);
6315             PyErr_SetString(
6316                 PyExc_ValueError,
6317                 "spawnv() arg 2 first element cannot be empty");
6318             return NULL;
6319         }
6320     }
6321     argvlist[argc] = NULL;
6322 
6323 #if !defined(HAVE_RTPSPAWN)
6324     if (mode == _OLD_P_OVERLAY)
6325         mode = _P_OVERLAY;
6326 #endif
6327 
6328     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
6329                     Py_None) < 0) {
6330         free_string_array(argvlist, argc);
6331         return NULL;
6332     }
6333 
6334     Py_BEGIN_ALLOW_THREADS
6335     _Py_BEGIN_SUPPRESS_IPH
6336 #ifdef HAVE_WSPAWNV
6337     spawnval = _wspawnv(mode, path->wide, argvlist);
6338 #elif defined(HAVE_RTPSPAWN)
6339     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
6340 #else
6341     spawnval = _spawnv(mode, path->narrow, argvlist);
6342 #endif
6343     _Py_END_SUPPRESS_IPH
6344     Py_END_ALLOW_THREADS
6345 
6346     free_string_array(argvlist, argc);
6347 
6348     if (spawnval == -1)
6349         return posix_error();
6350     else
6351         return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6352 }
6353 
6354 /*[clinic input]
6355 os.spawnve
6356 
6357     mode: int
6358         Mode of process creation.
6359     path: path_t
6360         Path of executable file.
6361     argv: object
6362         Tuple or list of strings.
6363     env: object
6364         Dictionary of strings mapping to strings.
6365     /
6366 
6367 Execute the program specified by path in a new process.
6368 [clinic start generated code]*/
6369 
6370 static PyObject *
os_spawnve_impl(PyObject * module,int mode,path_t * path,PyObject * argv,PyObject * env)6371 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
6372                 PyObject *env)
6373 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
6374 {
6375     EXECV_CHAR **argvlist;
6376     EXECV_CHAR **envlist;
6377     PyObject *res = NULL;
6378     Py_ssize_t argc, i, envc;
6379     intptr_t spawnval;
6380     PyObject *(*getitem)(PyObject *, Py_ssize_t);
6381     Py_ssize_t lastarg = 0;
6382 
6383     /* spawnve has four arguments: (mode, path, argv, env), where
6384        argv is a list or tuple of strings and env is a dictionary
6385        like posix.environ. */
6386 
6387     if (PyList_Check(argv)) {
6388         argc = PyList_Size(argv);
6389         getitem = PyList_GetItem;
6390     }
6391     else if (PyTuple_Check(argv)) {
6392         argc = PyTuple_Size(argv);
6393         getitem = PyTuple_GetItem;
6394     }
6395     else {
6396         PyErr_SetString(PyExc_TypeError,
6397                         "spawnve() arg 2 must be a tuple or list");
6398         goto fail_0;
6399     }
6400     if (argc == 0) {
6401         PyErr_SetString(PyExc_ValueError,
6402             "spawnve() arg 2 cannot be empty");
6403         goto fail_0;
6404     }
6405     if (!PyMapping_Check(env)) {
6406         PyErr_SetString(PyExc_TypeError,
6407                         "spawnve() arg 3 must be a mapping object");
6408         goto fail_0;
6409     }
6410 
6411     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6412     if (argvlist == NULL) {
6413         PyErr_NoMemory();
6414         goto fail_0;
6415     }
6416     for (i = 0; i < argc; i++) {
6417         if (!fsconvert_strdup((*getitem)(argv, i),
6418                               &argvlist[i]))
6419         {
6420             lastarg = i;
6421             goto fail_1;
6422         }
6423         if (i == 0 && !argvlist[0][0]) {
6424             lastarg = i + 1;
6425             PyErr_SetString(
6426                 PyExc_ValueError,
6427                 "spawnv() arg 2 first element cannot be empty");
6428             goto fail_1;
6429         }
6430     }
6431     lastarg = argc;
6432     argvlist[argc] = NULL;
6433 
6434     envlist = parse_envlist(env, &envc);
6435     if (envlist == NULL)
6436         goto fail_1;
6437 
6438 #if !defined(HAVE_RTPSPAWN)
6439     if (mode == _OLD_P_OVERLAY)
6440         mode = _P_OVERLAY;
6441 #endif
6442 
6443     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6444         goto fail_2;
6445     }
6446 
6447     Py_BEGIN_ALLOW_THREADS
6448     _Py_BEGIN_SUPPRESS_IPH
6449 #ifdef HAVE_WSPAWNV
6450     spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6451 #elif defined(HAVE_RTPSPAWN)
6452     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6453                            (const char **)envlist);
6454 #else
6455     spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6456 #endif
6457     _Py_END_SUPPRESS_IPH
6458     Py_END_ALLOW_THREADS
6459 
6460     if (spawnval == -1)
6461         (void) posix_error();
6462     else
6463         res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6464 
6465   fail_2:
6466     while (--envc >= 0)
6467         PyMem_DEL(envlist[envc]);
6468     PyMem_DEL(envlist);
6469   fail_1:
6470     free_string_array(argvlist, lastarg);
6471   fail_0:
6472     return res;
6473 }
6474 
6475 #endif /* HAVE_SPAWNV */
6476 
6477 
6478 #ifdef HAVE_FORK
6479 
6480 /* Helper function to validate arguments.
6481    Returns 0 on success.  non-zero on failure with a TypeError raised.
6482    If obj is non-NULL it must be callable.  */
6483 static int
check_null_or_callable(PyObject * obj,const char * obj_name)6484 check_null_or_callable(PyObject *obj, const char* obj_name)
6485 {
6486     if (obj && !PyCallable_Check(obj)) {
6487         PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6488                      obj_name, _PyType_Name(Py_TYPE(obj)));
6489         return -1;
6490     }
6491     return 0;
6492 }
6493 
6494 /*[clinic input]
6495 os.register_at_fork
6496 
6497     *
6498     before: object=NULL
6499         A callable to be called in the parent before the fork() syscall.
6500     after_in_child: object=NULL
6501         A callable to be called in the child after fork().
6502     after_in_parent: object=NULL
6503         A callable to be called in the parent after fork().
6504 
6505 Register callables to be called when forking a new process.
6506 
6507 'before' callbacks are called in reverse order.
6508 'after_in_child' and 'after_in_parent' callbacks are called in order.
6509 
6510 [clinic start generated code]*/
6511 
6512 static PyObject *
os_register_at_fork_impl(PyObject * module,PyObject * before,PyObject * after_in_child,PyObject * after_in_parent)6513 os_register_at_fork_impl(PyObject *module, PyObject *before,
6514                          PyObject *after_in_child, PyObject *after_in_parent)
6515 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6516 {
6517     PyInterpreterState *interp;
6518 
6519     if (!before && !after_in_child && !after_in_parent) {
6520         PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6521         return NULL;
6522     }
6523     if (check_null_or_callable(before, "before") ||
6524         check_null_or_callable(after_in_child, "after_in_child") ||
6525         check_null_or_callable(after_in_parent, "after_in_parent")) {
6526         return NULL;
6527     }
6528     interp = _PyInterpreterState_GET();
6529 
6530     if (register_at_forker(&interp->before_forkers, before)) {
6531         return NULL;
6532     }
6533     if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6534         return NULL;
6535     }
6536     if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6537         return NULL;
6538     }
6539     Py_RETURN_NONE;
6540 }
6541 #endif /* HAVE_FORK */
6542 
6543 
6544 #ifdef HAVE_FORK1
6545 /*[clinic input]
6546 os.fork1
6547 
6548 Fork a child process with a single multiplexed (i.e., not bound) thread.
6549 
6550 Return 0 to child process and PID of child to parent process.
6551 [clinic start generated code]*/
6552 
6553 static PyObject *
os_fork1_impl(PyObject * module)6554 os_fork1_impl(PyObject *module)
6555 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6556 {
6557     pid_t pid;
6558 
6559     if (_PyInterpreterState_GET() != PyInterpreterState_Main()) {
6560         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6561         return NULL;
6562     }
6563     PyOS_BeforeFork();
6564     pid = fork1();
6565     if (pid == 0) {
6566         /* child: this clobbers and resets the import lock. */
6567         PyOS_AfterFork_Child();
6568     } else {
6569         /* parent: release the import lock. */
6570         PyOS_AfterFork_Parent();
6571     }
6572     if (pid == -1)
6573         return posix_error();
6574     return PyLong_FromPid(pid);
6575 }
6576 #endif /* HAVE_FORK1 */
6577 
6578 
6579 #ifdef HAVE_FORK
6580 /*[clinic input]
6581 os.fork
6582 
6583 Fork a child process.
6584 
6585 Return 0 to child process and PID of child to parent process.
6586 [clinic start generated code]*/
6587 
6588 static PyObject *
os_fork_impl(PyObject * module)6589 os_fork_impl(PyObject *module)
6590 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6591 {
6592     pid_t pid;
6593     PyInterpreterState *interp = _PyInterpreterState_GET();
6594     if (interp->config._isolated_interpreter) {
6595         PyErr_SetString(PyExc_RuntimeError,
6596                         "fork not supported for isolated subinterpreters");
6597         return NULL;
6598     }
6599     if (PySys_Audit("os.fork", NULL) < 0) {
6600         return NULL;
6601     }
6602     PyOS_BeforeFork();
6603     pid = fork();
6604     if (pid == 0) {
6605         /* child: this clobbers and resets the import lock. */
6606         PyOS_AfterFork_Child();
6607     } else {
6608         /* parent: release the import lock. */
6609         PyOS_AfterFork_Parent();
6610     }
6611     if (pid == -1)
6612         return posix_error();
6613     return PyLong_FromPid(pid);
6614 }
6615 #endif /* HAVE_FORK */
6616 
6617 
6618 #ifdef HAVE_SCHED_H
6619 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6620 /*[clinic input]
6621 os.sched_get_priority_max
6622 
6623     policy: int
6624 
6625 Get the maximum scheduling priority for policy.
6626 [clinic start generated code]*/
6627 
6628 static PyObject *
os_sched_get_priority_max_impl(PyObject * module,int policy)6629 os_sched_get_priority_max_impl(PyObject *module, int policy)
6630 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6631 {
6632     int max;
6633 
6634     max = sched_get_priority_max(policy);
6635     if (max < 0)
6636         return posix_error();
6637     return PyLong_FromLong(max);
6638 }
6639 
6640 
6641 /*[clinic input]
6642 os.sched_get_priority_min
6643 
6644     policy: int
6645 
6646 Get the minimum scheduling priority for policy.
6647 [clinic start generated code]*/
6648 
6649 static PyObject *
os_sched_get_priority_min_impl(PyObject * module,int policy)6650 os_sched_get_priority_min_impl(PyObject *module, int policy)
6651 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6652 {
6653     int min = sched_get_priority_min(policy);
6654     if (min < 0)
6655         return posix_error();
6656     return PyLong_FromLong(min);
6657 }
6658 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6659 
6660 
6661 #ifdef HAVE_SCHED_SETSCHEDULER
6662 /*[clinic input]
6663 os.sched_getscheduler
6664     pid: pid_t
6665     /
6666 
6667 Get the scheduling policy for the process identified by pid.
6668 
6669 Passing 0 for pid returns the scheduling policy for the calling process.
6670 [clinic start generated code]*/
6671 
6672 static PyObject *
os_sched_getscheduler_impl(PyObject * module,pid_t pid)6673 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6674 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
6675 {
6676     int policy;
6677 
6678     policy = sched_getscheduler(pid);
6679     if (policy < 0)
6680         return posix_error();
6681     return PyLong_FromLong(policy);
6682 }
6683 #endif /* HAVE_SCHED_SETSCHEDULER */
6684 
6685 
6686 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6687 /*[clinic input]
6688 class os.sched_param "PyObject *" "SchedParamType"
6689 
6690 @classmethod
6691 os.sched_param.__new__
6692 
6693     sched_priority: object
6694         A scheduling parameter.
6695 
6696 Currently has only one field: sched_priority
6697 [clinic start generated code]*/
6698 
6699 static PyObject *
os_sched_param_impl(PyTypeObject * type,PyObject * sched_priority)6700 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6701 /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
6702 {
6703     PyObject *res;
6704 
6705     res = PyStructSequence_New(type);
6706     if (!res)
6707         return NULL;
6708     Py_INCREF(sched_priority);
6709     PyStructSequence_SET_ITEM(res, 0, sched_priority);
6710     return res;
6711 }
6712 
6713 PyDoc_VAR(os_sched_param__doc__);
6714 
6715 static PyStructSequence_Field sched_param_fields[] = {
6716     {"sched_priority", "the scheduling priority"},
6717     {0}
6718 };
6719 
6720 static PyStructSequence_Desc sched_param_desc = {
6721     "sched_param", /* name */
6722     os_sched_param__doc__, /* doc */
6723     sched_param_fields,
6724     1
6725 };
6726 
6727 static int
convert_sched_param(PyObject * module,PyObject * param,struct sched_param * res)6728 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
6729 {
6730     long priority;
6731 
6732     if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
6733         PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
6734         return 0;
6735     }
6736     priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
6737     if (priority == -1 && PyErr_Occurred())
6738         return 0;
6739     if (priority > INT_MAX || priority < INT_MIN) {
6740         PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
6741         return 0;
6742     }
6743     res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
6744     return 1;
6745 }
6746 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
6747 
6748 
6749 #ifdef HAVE_SCHED_SETSCHEDULER
6750 /*[clinic input]
6751 os.sched_setscheduler
6752 
6753     pid: pid_t
6754     policy: int
6755     param as param_obj: object
6756     /
6757 
6758 Set the scheduling policy for the process identified by pid.
6759 
6760 If pid is 0, the calling process is changed.
6761 param is an instance of sched_param.
6762 [clinic start generated code]*/
6763 
6764 static PyObject *
os_sched_setscheduler_impl(PyObject * module,pid_t pid,int policy,PyObject * param_obj)6765 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
6766                            PyObject *param_obj)
6767 /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
6768 {
6769     struct sched_param param;
6770     if (!convert_sched_param(module, param_obj, &param)) {
6771         return NULL;
6772     }
6773 
6774     /*
6775     ** sched_setscheduler() returns 0 in Linux, but the previous
6776     ** scheduling policy under Solaris/Illumos, and others.
6777     ** On error, -1 is returned in all Operating Systems.
6778     */
6779     if (sched_setscheduler(pid, policy, &param) == -1)
6780         return posix_error();
6781     Py_RETURN_NONE;
6782 }
6783 #endif  /* HAVE_SCHED_SETSCHEDULER*/
6784 
6785 
6786 #ifdef HAVE_SCHED_SETPARAM
6787 /*[clinic input]
6788 os.sched_getparam
6789     pid: pid_t
6790     /
6791 
6792 Returns scheduling parameters for the process identified by pid.
6793 
6794 If pid is 0, returns parameters for the calling process.
6795 Return value is an instance of sched_param.
6796 [clinic start generated code]*/
6797 
6798 static PyObject *
os_sched_getparam_impl(PyObject * module,pid_t pid)6799 os_sched_getparam_impl(PyObject *module, pid_t pid)
6800 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
6801 {
6802     struct sched_param param;
6803     PyObject *result;
6804     PyObject *priority;
6805 
6806     if (sched_getparam(pid, &param))
6807         return posix_error();
6808     PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
6809     result = PyStructSequence_New((PyTypeObject *)SchedParamType);
6810     if (!result)
6811         return NULL;
6812     priority = PyLong_FromLong(param.sched_priority);
6813     if (!priority) {
6814         Py_DECREF(result);
6815         return NULL;
6816     }
6817     PyStructSequence_SET_ITEM(result, 0, priority);
6818     return result;
6819 }
6820 
6821 
6822 /*[clinic input]
6823 os.sched_setparam
6824     pid: pid_t
6825     param as param_obj: object
6826     /
6827 
6828 Set scheduling parameters for the process identified by pid.
6829 
6830 If pid is 0, sets parameters for the calling process.
6831 param should be an instance of sched_param.
6832 [clinic start generated code]*/
6833 
6834 static PyObject *
os_sched_setparam_impl(PyObject * module,pid_t pid,PyObject * param_obj)6835 os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
6836 /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
6837 {
6838     struct sched_param param;
6839     if (!convert_sched_param(module, param_obj, &param)) {
6840         return NULL;
6841     }
6842 
6843     if (sched_setparam(pid, &param))
6844         return posix_error();
6845     Py_RETURN_NONE;
6846 }
6847 #endif /* HAVE_SCHED_SETPARAM */
6848 
6849 
6850 #ifdef HAVE_SCHED_RR_GET_INTERVAL
6851 /*[clinic input]
6852 os.sched_rr_get_interval -> double
6853     pid: pid_t
6854     /
6855 
6856 Return the round-robin quantum for the process identified by pid, in seconds.
6857 
6858 Value returned is a float.
6859 [clinic start generated code]*/
6860 
6861 static double
os_sched_rr_get_interval_impl(PyObject * module,pid_t pid)6862 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
6863 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
6864 {
6865     struct timespec interval;
6866     if (sched_rr_get_interval(pid, &interval)) {
6867         posix_error();
6868         return -1.0;
6869     }
6870 #ifdef _Py_MEMORY_SANITIZER
6871     __msan_unpoison(&interval, sizeof(interval));
6872 #endif
6873     return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
6874 }
6875 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
6876 
6877 
6878 /*[clinic input]
6879 os.sched_yield
6880 
6881 Voluntarily relinquish the CPU.
6882 [clinic start generated code]*/
6883 
6884 static PyObject *
os_sched_yield_impl(PyObject * module)6885 os_sched_yield_impl(PyObject *module)
6886 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
6887 {
6888     if (sched_yield())
6889         return posix_error();
6890     Py_RETURN_NONE;
6891 }
6892 
6893 #ifdef HAVE_SCHED_SETAFFINITY
6894 /* The minimum number of CPUs allocated in a cpu_set_t */
6895 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
6896 
6897 /*[clinic input]
6898 os.sched_setaffinity
6899     pid: pid_t
6900     mask : object
6901     /
6902 
6903 Set the CPU affinity of the process identified by pid to mask.
6904 
6905 mask should be an iterable of integers identifying CPUs.
6906 [clinic start generated code]*/
6907 
6908 static PyObject *
os_sched_setaffinity_impl(PyObject * module,pid_t pid,PyObject * mask)6909 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
6910 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
6911 {
6912     int ncpus;
6913     size_t setsize;
6914     cpu_set_t *cpu_set = NULL;
6915     PyObject *iterator = NULL, *item;
6916 
6917     iterator = PyObject_GetIter(mask);
6918     if (iterator == NULL)
6919         return NULL;
6920 
6921     ncpus = NCPUS_START;
6922     setsize = CPU_ALLOC_SIZE(ncpus);
6923     cpu_set = CPU_ALLOC(ncpus);
6924     if (cpu_set == NULL) {
6925         PyErr_NoMemory();
6926         goto error;
6927     }
6928     CPU_ZERO_S(setsize, cpu_set);
6929 
6930     while ((item = PyIter_Next(iterator))) {
6931         long cpu;
6932         if (!PyLong_Check(item)) {
6933             PyErr_Format(PyExc_TypeError,
6934                         "expected an iterator of ints, "
6935                         "but iterator yielded %R",
6936                         Py_TYPE(item));
6937             Py_DECREF(item);
6938             goto error;
6939         }
6940         cpu = PyLong_AsLong(item);
6941         Py_DECREF(item);
6942         if (cpu < 0) {
6943             if (!PyErr_Occurred())
6944                 PyErr_SetString(PyExc_ValueError, "negative CPU number");
6945             goto error;
6946         }
6947         if (cpu > INT_MAX - 1) {
6948             PyErr_SetString(PyExc_OverflowError, "CPU number too large");
6949             goto error;
6950         }
6951         if (cpu >= ncpus) {
6952             /* Grow CPU mask to fit the CPU number */
6953             int newncpus = ncpus;
6954             cpu_set_t *newmask;
6955             size_t newsetsize;
6956             while (newncpus <= cpu) {
6957                 if (newncpus > INT_MAX / 2)
6958                     newncpus = cpu + 1;
6959                 else
6960                     newncpus = newncpus * 2;
6961             }
6962             newmask = CPU_ALLOC(newncpus);
6963             if (newmask == NULL) {
6964                 PyErr_NoMemory();
6965                 goto error;
6966             }
6967             newsetsize = CPU_ALLOC_SIZE(newncpus);
6968             CPU_ZERO_S(newsetsize, newmask);
6969             memcpy(newmask, cpu_set, setsize);
6970             CPU_FREE(cpu_set);
6971             setsize = newsetsize;
6972             cpu_set = newmask;
6973             ncpus = newncpus;
6974         }
6975         CPU_SET_S(cpu, setsize, cpu_set);
6976     }
6977     if (PyErr_Occurred()) {
6978         goto error;
6979     }
6980     Py_CLEAR(iterator);
6981 
6982     if (sched_setaffinity(pid, setsize, cpu_set)) {
6983         posix_error();
6984         goto error;
6985     }
6986     CPU_FREE(cpu_set);
6987     Py_RETURN_NONE;
6988 
6989 error:
6990     if (cpu_set)
6991         CPU_FREE(cpu_set);
6992     Py_XDECREF(iterator);
6993     return NULL;
6994 }
6995 
6996 
6997 /*[clinic input]
6998 os.sched_getaffinity
6999     pid: pid_t
7000     /
7001 
7002 Return the affinity of the process identified by pid (or the current process if zero).
7003 
7004 The affinity is returned as a set of CPU identifiers.
7005 [clinic start generated code]*/
7006 
7007 static PyObject *
os_sched_getaffinity_impl(PyObject * module,pid_t pid)7008 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
7009 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
7010 {
7011     int cpu, ncpus, count;
7012     size_t setsize;
7013     cpu_set_t *mask = NULL;
7014     PyObject *res = NULL;
7015 
7016     ncpus = NCPUS_START;
7017     while (1) {
7018         setsize = CPU_ALLOC_SIZE(ncpus);
7019         mask = CPU_ALLOC(ncpus);
7020         if (mask == NULL)
7021             return PyErr_NoMemory();
7022         if (sched_getaffinity(pid, setsize, mask) == 0)
7023             break;
7024         CPU_FREE(mask);
7025         if (errno != EINVAL)
7026             return posix_error();
7027         if (ncpus > INT_MAX / 2) {
7028             PyErr_SetString(PyExc_OverflowError, "could not allocate "
7029                             "a large enough CPU set");
7030             return NULL;
7031         }
7032         ncpus = ncpus * 2;
7033     }
7034 
7035     res = PySet_New(NULL);
7036     if (res == NULL)
7037         goto error;
7038     for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7039         if (CPU_ISSET_S(cpu, setsize, mask)) {
7040             PyObject *cpu_num = PyLong_FromLong(cpu);
7041             --count;
7042             if (cpu_num == NULL)
7043                 goto error;
7044             if (PySet_Add(res, cpu_num)) {
7045                 Py_DECREF(cpu_num);
7046                 goto error;
7047             }
7048             Py_DECREF(cpu_num);
7049         }
7050     }
7051     CPU_FREE(mask);
7052     return res;
7053 
7054 error:
7055     if (mask)
7056         CPU_FREE(mask);
7057     Py_XDECREF(res);
7058     return NULL;
7059 }
7060 
7061 #endif /* HAVE_SCHED_SETAFFINITY */
7062 
7063 #endif /* HAVE_SCHED_H */
7064 
7065 
7066 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
7067 /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
7068 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
7069 #define DEV_PTY_FILE "/dev/ptc"
7070 #define HAVE_DEV_PTMX
7071 #else
7072 #define DEV_PTY_FILE "/dev/ptmx"
7073 #endif
7074 
7075 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
7076 #ifdef HAVE_PTY_H
7077 #include <pty.h>
7078 #else
7079 #ifdef HAVE_LIBUTIL_H
7080 #include <libutil.h>
7081 #else
7082 #ifdef HAVE_UTIL_H
7083 #include <util.h>
7084 #endif /* HAVE_UTIL_H */
7085 #endif /* HAVE_LIBUTIL_H */
7086 #endif /* HAVE_PTY_H */
7087 #ifdef HAVE_STROPTS_H
7088 #include <stropts.h>
7089 #endif
7090 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */
7091 
7092 
7093 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7094 /*[clinic input]
7095 os.openpty
7096 
7097 Open a pseudo-terminal.
7098 
7099 Return a tuple of (master_fd, slave_fd) containing open file descriptors
7100 for both the master and slave ends.
7101 [clinic start generated code]*/
7102 
7103 static PyObject *
os_openpty_impl(PyObject * module)7104 os_openpty_impl(PyObject *module)
7105 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
7106 {
7107     int master_fd = -1, slave_fd = -1;
7108 #ifndef HAVE_OPENPTY
7109     char * slave_name;
7110 #endif
7111 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
7112     PyOS_sighandler_t sig_saved;
7113 #if defined(__sun) && defined(__SVR4)
7114     extern char *ptsname(int fildes);
7115 #endif
7116 #endif
7117 
7118 #ifdef HAVE_OPENPTY
7119     if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
7120         goto posix_error;
7121 
7122     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7123         goto error;
7124     if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
7125         goto error;
7126 
7127 #elif defined(HAVE__GETPTY)
7128     slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
7129     if (slave_name == NULL)
7130         goto posix_error;
7131     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7132         goto error;
7133 
7134     slave_fd = _Py_open(slave_name, O_RDWR);
7135     if (slave_fd < 0)
7136         goto error;
7137 
7138 #else
7139     master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
7140     if (master_fd < 0)
7141         goto posix_error;
7142 
7143     sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
7144 
7145     /* change permission of slave */
7146     if (grantpt(master_fd) < 0) {
7147         PyOS_setsig(SIGCHLD, sig_saved);
7148         goto posix_error;
7149     }
7150 
7151     /* unlock slave */
7152     if (unlockpt(master_fd) < 0) {
7153         PyOS_setsig(SIGCHLD, sig_saved);
7154         goto posix_error;
7155     }
7156 
7157     PyOS_setsig(SIGCHLD, sig_saved);
7158 
7159     slave_name = ptsname(master_fd); /* get name of slave */
7160     if (slave_name == NULL)
7161         goto posix_error;
7162 
7163     slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
7164     if (slave_fd == -1)
7165         goto error;
7166 
7167     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7168         goto posix_error;
7169 
7170 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
7171     ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
7172     ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
7173 #ifndef __hpux
7174     ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
7175 #endif /* __hpux */
7176 #endif /* HAVE_CYGWIN */
7177 #endif /* HAVE_OPENPTY */
7178 
7179     return Py_BuildValue("(ii)", master_fd, slave_fd);
7180 
7181 posix_error:
7182     posix_error();
7183 error:
7184     if (master_fd != -1)
7185         close(master_fd);
7186     if (slave_fd != -1)
7187         close(slave_fd);
7188     return NULL;
7189 }
7190 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
7191 
7192 
7193 #ifdef HAVE_FORKPTY
7194 /*[clinic input]
7195 os.forkpty
7196 
7197 Fork a new process with a new pseudo-terminal as controlling tty.
7198 
7199 Returns a tuple of (pid, master_fd).
7200 Like fork(), return pid of 0 to the child process,
7201 and pid of child to the parent process.
7202 To both, return fd of newly opened pseudo-terminal.
7203 [clinic start generated code]*/
7204 
7205 static PyObject *
os_forkpty_impl(PyObject * module)7206 os_forkpty_impl(PyObject *module)
7207 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
7208 {
7209     int master_fd = -1;
7210     pid_t pid;
7211 
7212     if (_PyInterpreterState_GET() != PyInterpreterState_Main()) {
7213         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
7214         return NULL;
7215     }
7216     if (PySys_Audit("os.forkpty", NULL) < 0) {
7217         return NULL;
7218     }
7219     PyOS_BeforeFork();
7220     pid = forkpty(&master_fd, NULL, NULL, NULL);
7221     if (pid == 0) {
7222         /* child: this clobbers and resets the import lock. */
7223         PyOS_AfterFork_Child();
7224     } else {
7225         /* parent: release the import lock. */
7226         PyOS_AfterFork_Parent();
7227     }
7228     if (pid == -1)
7229         return posix_error();
7230     return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
7231 }
7232 #endif /* HAVE_FORKPTY */
7233 
7234 
7235 #ifdef HAVE_GETEGID
7236 /*[clinic input]
7237 os.getegid
7238 
7239 Return the current process's effective group id.
7240 [clinic start generated code]*/
7241 
7242 static PyObject *
os_getegid_impl(PyObject * module)7243 os_getegid_impl(PyObject *module)
7244 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
7245 {
7246     return _PyLong_FromGid(getegid());
7247 }
7248 #endif /* HAVE_GETEGID */
7249 
7250 
7251 #ifdef HAVE_GETEUID
7252 /*[clinic input]
7253 os.geteuid
7254 
7255 Return the current process's effective user id.
7256 [clinic start generated code]*/
7257 
7258 static PyObject *
os_geteuid_impl(PyObject * module)7259 os_geteuid_impl(PyObject *module)
7260 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
7261 {
7262     return _PyLong_FromUid(geteuid());
7263 }
7264 #endif /* HAVE_GETEUID */
7265 
7266 
7267 #ifdef HAVE_GETGID
7268 /*[clinic input]
7269 os.getgid
7270 
7271 Return the current process's group id.
7272 [clinic start generated code]*/
7273 
7274 static PyObject *
os_getgid_impl(PyObject * module)7275 os_getgid_impl(PyObject *module)
7276 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
7277 {
7278     return _PyLong_FromGid(getgid());
7279 }
7280 #endif /* HAVE_GETGID */
7281 
7282 
7283 #ifdef HAVE_GETPID
7284 /*[clinic input]
7285 os.getpid
7286 
7287 Return the current process id.
7288 [clinic start generated code]*/
7289 
7290 static PyObject *
os_getpid_impl(PyObject * module)7291 os_getpid_impl(PyObject *module)
7292 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
7293 {
7294     return PyLong_FromPid(getpid());
7295 }
7296 #endif /* HAVE_GETPID */
7297 
7298 #ifdef NGROUPS_MAX
7299 #define MAX_GROUPS NGROUPS_MAX
7300 #else
7301     /* defined to be 16 on Solaris7, so this should be a small number */
7302 #define MAX_GROUPS 64
7303 #endif
7304 
7305 #ifdef HAVE_GETGROUPLIST
7306 
7307 #ifdef __APPLE__
7308 /*[clinic input]
7309 os.getgrouplist
7310 
7311     user: str
7312         username to lookup
7313     group as basegid: int
7314         base group id of the user
7315     /
7316 
7317 Returns a list of groups to which a user belongs.
7318 [clinic start generated code]*/
7319 
7320 static PyObject *
os_getgrouplist_impl(PyObject * module,const char * user,int basegid)7321 os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
7322 /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
7323 #else
7324 /*[clinic input]
7325 os.getgrouplist
7326 
7327     user: str
7328         username to lookup
7329     group as basegid: gid_t
7330         base group id of the user
7331     /
7332 
7333 Returns a list of groups to which a user belongs.
7334 [clinic start generated code]*/
7335 
7336 static PyObject *
7337 os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
7338 /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
7339 #endif
7340 {
7341     int i, ngroups;
7342     PyObject *list;
7343 #ifdef __APPLE__
7344     int *groups;
7345 #else
7346     gid_t *groups;
7347 #endif
7348 
7349     /*
7350      * NGROUPS_MAX is defined by POSIX.1 as the maximum
7351      * number of supplimental groups a users can belong to.
7352      * We have to increment it by one because
7353      * getgrouplist() returns both the supplemental groups
7354      * and the primary group, i.e. all of the groups the
7355      * user belongs to.
7356      */
7357     ngroups = 1 + MAX_GROUPS;
7358 
7359     while (1) {
7360 #ifdef __APPLE__
7361         groups = PyMem_New(int, ngroups);
7362 #else
7363         groups = PyMem_New(gid_t, ngroups);
7364 #endif
7365         if (groups == NULL) {
7366             return PyErr_NoMemory();
7367         }
7368 
7369         int old_ngroups = ngroups;
7370         if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
7371             /* Success */
7372             break;
7373         }
7374 
7375         /* getgrouplist() fails if the group list is too small */
7376         PyMem_Free(groups);
7377 
7378         if (ngroups > old_ngroups) {
7379             /* If the group list is too small, the glibc implementation of
7380                getgrouplist() sets ngroups to the total number of groups and
7381                returns -1. */
7382         }
7383         else {
7384             /* Double the group list size */
7385             if (ngroups > INT_MAX / 2) {
7386                 return PyErr_NoMemory();
7387             }
7388             ngroups *= 2;
7389         }
7390 
7391         /* Retry getgrouplist() with a larger group list */
7392     }
7393 
7394 #ifdef _Py_MEMORY_SANITIZER
7395     /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
7396     __msan_unpoison(&ngroups, sizeof(ngroups));
7397     __msan_unpoison(groups, ngroups*sizeof(*groups));
7398 #endif
7399 
7400     list = PyList_New(ngroups);
7401     if (list == NULL) {
7402         PyMem_Del(groups);
7403         return NULL;
7404     }
7405 
7406     for (i = 0; i < ngroups; i++) {
7407 #ifdef __APPLE__
7408         PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7409 #else
7410         PyObject *o = _PyLong_FromGid(groups[i]);
7411 #endif
7412         if (o == NULL) {
7413             Py_DECREF(list);
7414             PyMem_Del(groups);
7415             return NULL;
7416         }
7417         PyList_SET_ITEM(list, i, o);
7418     }
7419 
7420     PyMem_Del(groups);
7421 
7422     return list;
7423 }
7424 #endif /* HAVE_GETGROUPLIST */
7425 
7426 
7427 #ifdef HAVE_GETGROUPS
7428 /*[clinic input]
7429 os.getgroups
7430 
7431 Return list of supplemental group IDs for the process.
7432 [clinic start generated code]*/
7433 
7434 static PyObject *
os_getgroups_impl(PyObject * module)7435 os_getgroups_impl(PyObject *module)
7436 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
7437 {
7438     PyObject *result = NULL;
7439     gid_t grouplist[MAX_GROUPS];
7440 
7441     /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
7442      * This is a helper variable to store the intermediate result when
7443      * that happens.
7444      *
7445      * To keep the code readable the OSX behaviour is unconditional,
7446      * according to the POSIX spec this should be safe on all unix-y
7447      * systems.
7448      */
7449     gid_t* alt_grouplist = grouplist;
7450     int n;
7451 
7452 #ifdef __APPLE__
7453     /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if
7454      * there are more groups than can fit in grouplist.  Therefore, on OS X
7455      * always first call getgroups with length 0 to get the actual number
7456      * of groups.
7457      */
7458     n = getgroups(0, NULL);
7459     if (n < 0) {
7460         return posix_error();
7461     } else if (n <= MAX_GROUPS) {
7462         /* groups will fit in existing array */
7463         alt_grouplist = grouplist;
7464     } else {
7465         alt_grouplist = PyMem_New(gid_t, n);
7466         if (alt_grouplist == NULL) {
7467             return PyErr_NoMemory();
7468         }
7469     }
7470 
7471     n = getgroups(n, alt_grouplist);
7472     if (n == -1) {
7473         if (alt_grouplist != grouplist) {
7474             PyMem_Free(alt_grouplist);
7475         }
7476         return posix_error();
7477     }
7478 #else
7479     n = getgroups(MAX_GROUPS, grouplist);
7480     if (n < 0) {
7481         if (errno == EINVAL) {
7482             n = getgroups(0, NULL);
7483             if (n == -1) {
7484                 return posix_error();
7485             }
7486             if (n == 0) {
7487                 /* Avoid malloc(0) */
7488                 alt_grouplist = grouplist;
7489             } else {
7490                 alt_grouplist = PyMem_New(gid_t, n);
7491                 if (alt_grouplist == NULL) {
7492                     return PyErr_NoMemory();
7493                 }
7494                 n = getgroups(n, alt_grouplist);
7495                 if (n == -1) {
7496                     PyMem_Free(alt_grouplist);
7497                     return posix_error();
7498                 }
7499             }
7500         } else {
7501             return posix_error();
7502         }
7503     }
7504 #endif
7505 
7506     result = PyList_New(n);
7507     if (result != NULL) {
7508         int i;
7509         for (i = 0; i < n; ++i) {
7510             PyObject *o = _PyLong_FromGid(alt_grouplist[i]);
7511             if (o == NULL) {
7512                 Py_DECREF(result);
7513                 result = NULL;
7514                 break;
7515             }
7516             PyList_SET_ITEM(result, i, o);
7517         }
7518     }
7519 
7520     if (alt_grouplist != grouplist) {
7521         PyMem_Free(alt_grouplist);
7522     }
7523 
7524     return result;
7525 }
7526 #endif /* HAVE_GETGROUPS */
7527 
7528 #ifdef HAVE_INITGROUPS
7529 #ifdef __APPLE__
7530 /*[clinic input]
7531 os.initgroups
7532 
7533     username as oname: FSConverter
7534     gid: int
7535     /
7536 
7537 Initialize the group access list.
7538 
7539 Call the system initgroups() to initialize the group access list with all of
7540 the groups of which the specified username is a member, plus the specified
7541 group id.
7542 [clinic start generated code]*/
7543 
7544 static PyObject *
os_initgroups_impl(PyObject * module,PyObject * oname,int gid)7545 os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
7546 /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
7547 #else
7548 /*[clinic input]
7549 os.initgroups
7550 
7551     username as oname: FSConverter
7552     gid: gid_t
7553     /
7554 
7555 Initialize the group access list.
7556 
7557 Call the system initgroups() to initialize the group access list with all of
7558 the groups of which the specified username is a member, plus the specified
7559 group id.
7560 [clinic start generated code]*/
7561 
7562 static PyObject *
7563 os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
7564 /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
7565 #endif
7566 {
7567     const char *username = PyBytes_AS_STRING(oname);
7568 
7569     if (initgroups(username, gid) == -1)
7570         return PyErr_SetFromErrno(PyExc_OSError);
7571 
7572     Py_RETURN_NONE;
7573 }
7574 #endif /* HAVE_INITGROUPS */
7575 
7576 
7577 #ifdef HAVE_GETPGID
7578 /*[clinic input]
7579 os.getpgid
7580 
7581     pid: pid_t
7582 
7583 Call the system call getpgid(), and return the result.
7584 [clinic start generated code]*/
7585 
7586 static PyObject *
os_getpgid_impl(PyObject * module,pid_t pid)7587 os_getpgid_impl(PyObject *module, pid_t pid)
7588 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7589 {
7590     pid_t pgid = getpgid(pid);
7591     if (pgid < 0)
7592         return posix_error();
7593     return PyLong_FromPid(pgid);
7594 }
7595 #endif /* HAVE_GETPGID */
7596 
7597 
7598 #ifdef HAVE_GETPGRP
7599 /*[clinic input]
7600 os.getpgrp
7601 
7602 Return the current process group id.
7603 [clinic start generated code]*/
7604 
7605 static PyObject *
os_getpgrp_impl(PyObject * module)7606 os_getpgrp_impl(PyObject *module)
7607 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7608 {
7609 #ifdef GETPGRP_HAVE_ARG
7610     return PyLong_FromPid(getpgrp(0));
7611 #else /* GETPGRP_HAVE_ARG */
7612     return PyLong_FromPid(getpgrp());
7613 #endif /* GETPGRP_HAVE_ARG */
7614 }
7615 #endif /* HAVE_GETPGRP */
7616 
7617 
7618 #ifdef HAVE_SETPGRP
7619 /*[clinic input]
7620 os.setpgrp
7621 
7622 Make the current process the leader of its process group.
7623 [clinic start generated code]*/
7624 
7625 static PyObject *
os_setpgrp_impl(PyObject * module)7626 os_setpgrp_impl(PyObject *module)
7627 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7628 {
7629 #ifdef SETPGRP_HAVE_ARG
7630     if (setpgrp(0, 0) < 0)
7631 #else /* SETPGRP_HAVE_ARG */
7632     if (setpgrp() < 0)
7633 #endif /* SETPGRP_HAVE_ARG */
7634         return posix_error();
7635     Py_RETURN_NONE;
7636 }
7637 #endif /* HAVE_SETPGRP */
7638 
7639 #ifdef HAVE_GETPPID
7640 
7641 #ifdef MS_WINDOWS
7642 #include <tlhelp32.h>
7643 
7644 static PyObject*
win32_getppid()7645 win32_getppid()
7646 {
7647     HANDLE snapshot;
7648     pid_t mypid;
7649     PyObject* result = NULL;
7650     BOOL have_record;
7651     PROCESSENTRY32 pe;
7652 
7653     mypid = getpid(); /* This function never fails */
7654 
7655     snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7656     if (snapshot == INVALID_HANDLE_VALUE)
7657         return PyErr_SetFromWindowsErr(GetLastError());
7658 
7659     pe.dwSize = sizeof(pe);
7660     have_record = Process32First(snapshot, &pe);
7661     while (have_record) {
7662         if (mypid == (pid_t)pe.th32ProcessID) {
7663             /* We could cache the ulong value in a static variable. */
7664             result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7665             break;
7666         }
7667 
7668         have_record = Process32Next(snapshot, &pe);
7669     }
7670 
7671     /* If our loop exits and our pid was not found (result will be NULL)
7672      * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7673      * error anyway, so let's raise it. */
7674     if (!result)
7675         result = PyErr_SetFromWindowsErr(GetLastError());
7676 
7677     CloseHandle(snapshot);
7678 
7679     return result;
7680 }
7681 #endif /*MS_WINDOWS*/
7682 
7683 
7684 /*[clinic input]
7685 os.getppid
7686 
7687 Return the parent's process id.
7688 
7689 If the parent process has already exited, Windows machines will still
7690 return its id; others systems will return the id of the 'init' process (1).
7691 [clinic start generated code]*/
7692 
7693 static PyObject *
os_getppid_impl(PyObject * module)7694 os_getppid_impl(PyObject *module)
7695 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7696 {
7697 #ifdef MS_WINDOWS
7698     return win32_getppid();
7699 #else
7700     return PyLong_FromPid(getppid());
7701 #endif
7702 }
7703 #endif /* HAVE_GETPPID */
7704 
7705 
7706 #ifdef HAVE_GETLOGIN
7707 /*[clinic input]
7708 os.getlogin
7709 
7710 Return the actual login name.
7711 [clinic start generated code]*/
7712 
7713 static PyObject *
os_getlogin_impl(PyObject * module)7714 os_getlogin_impl(PyObject *module)
7715 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7716 {
7717     PyObject *result = NULL;
7718 #ifdef MS_WINDOWS
7719     wchar_t user_name[UNLEN + 1];
7720     DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7721 
7722     if (GetUserNameW(user_name, &num_chars)) {
7723         /* num_chars is the number of unicode chars plus null terminator */
7724         result = PyUnicode_FromWideChar(user_name, num_chars - 1);
7725     }
7726     else
7727         result = PyErr_SetFromWindowsErr(GetLastError());
7728 #else
7729     char *name;
7730     int old_errno = errno;
7731 
7732     errno = 0;
7733     name = getlogin();
7734     if (name == NULL) {
7735         if (errno)
7736             posix_error();
7737         else
7738             PyErr_SetString(PyExc_OSError, "unable to determine login name");
7739     }
7740     else
7741         result = PyUnicode_DecodeFSDefault(name);
7742     errno = old_errno;
7743 #endif
7744     return result;
7745 }
7746 #endif /* HAVE_GETLOGIN */
7747 
7748 
7749 #ifdef HAVE_GETUID
7750 /*[clinic input]
7751 os.getuid
7752 
7753 Return the current process's user id.
7754 [clinic start generated code]*/
7755 
7756 static PyObject *
os_getuid_impl(PyObject * module)7757 os_getuid_impl(PyObject *module)
7758 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7759 {
7760     return _PyLong_FromUid(getuid());
7761 }
7762 #endif /* HAVE_GETUID */
7763 
7764 
7765 #ifdef MS_WINDOWS
7766 #define HAVE_KILL
7767 #endif /* MS_WINDOWS */
7768 
7769 #ifdef HAVE_KILL
7770 /*[clinic input]
7771 os.kill
7772 
7773     pid: pid_t
7774     signal: Py_ssize_t
7775     /
7776 
7777 Kill a process with a signal.
7778 [clinic start generated code]*/
7779 
7780 static PyObject *
os_kill_impl(PyObject * module,pid_t pid,Py_ssize_t signal)7781 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
7782 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
7783 {
7784     if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
7785         return NULL;
7786     }
7787 #ifndef MS_WINDOWS
7788     if (kill(pid, (int)signal) == -1)
7789         return posix_error();
7790     Py_RETURN_NONE;
7791 #else /* !MS_WINDOWS */
7792     PyObject *result;
7793     DWORD sig = (DWORD)signal;
7794     DWORD err;
7795     HANDLE handle;
7796 
7797     /* Console processes which share a common console can be sent CTRL+C or
7798        CTRL+BREAK events, provided they handle said events. */
7799     if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
7800         if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
7801             err = GetLastError();
7802             PyErr_SetFromWindowsErr(err);
7803         }
7804         else
7805             Py_RETURN_NONE;
7806     }
7807 
7808     /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
7809        attempt to open and terminate the process. */
7810     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
7811     if (handle == NULL) {
7812         err = GetLastError();
7813         return PyErr_SetFromWindowsErr(err);
7814     }
7815 
7816     if (TerminateProcess(handle, sig) == 0) {
7817         err = GetLastError();
7818         result = PyErr_SetFromWindowsErr(err);
7819     } else {
7820         Py_INCREF(Py_None);
7821         result = Py_None;
7822     }
7823 
7824     CloseHandle(handle);
7825     return result;
7826 #endif /* !MS_WINDOWS */
7827 }
7828 #endif /* HAVE_KILL */
7829 
7830 
7831 #ifdef HAVE_KILLPG
7832 /*[clinic input]
7833 os.killpg
7834 
7835     pgid: pid_t
7836     signal: int
7837     /
7838 
7839 Kill a process group with a signal.
7840 [clinic start generated code]*/
7841 
7842 static PyObject *
os_killpg_impl(PyObject * module,pid_t pgid,int signal)7843 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
7844 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
7845 {
7846     if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
7847         return NULL;
7848     }
7849     /* XXX some man pages make the `pgid` parameter an int, others
7850        a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
7851        take the same type. Moreover, pid_t is always at least as wide as
7852        int (else compilation of this module fails), which is safe. */
7853     if (killpg(pgid, signal) == -1)
7854         return posix_error();
7855     Py_RETURN_NONE;
7856 }
7857 #endif /* HAVE_KILLPG */
7858 
7859 
7860 #ifdef HAVE_PLOCK
7861 #ifdef HAVE_SYS_LOCK_H
7862 #include <sys/lock.h>
7863 #endif
7864 
7865 /*[clinic input]
7866 os.plock
7867     op: int
7868     /
7869 
7870 Lock program segments into memory.");
7871 [clinic start generated code]*/
7872 
7873 static PyObject *
os_plock_impl(PyObject * module,int op)7874 os_plock_impl(PyObject *module, int op)
7875 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
7876 {
7877     if (plock(op) == -1)
7878         return posix_error();
7879     Py_RETURN_NONE;
7880 }
7881 #endif /* HAVE_PLOCK */
7882 
7883 
7884 #ifdef HAVE_SETUID
7885 /*[clinic input]
7886 os.setuid
7887 
7888     uid: uid_t
7889     /
7890 
7891 Set the current process's user id.
7892 [clinic start generated code]*/
7893 
7894 static PyObject *
os_setuid_impl(PyObject * module,uid_t uid)7895 os_setuid_impl(PyObject *module, uid_t uid)
7896 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
7897 {
7898     if (setuid(uid) < 0)
7899         return posix_error();
7900     Py_RETURN_NONE;
7901 }
7902 #endif /* HAVE_SETUID */
7903 
7904 
7905 #ifdef HAVE_SETEUID
7906 /*[clinic input]
7907 os.seteuid
7908 
7909     euid: uid_t
7910     /
7911 
7912 Set the current process's effective user id.
7913 [clinic start generated code]*/
7914 
7915 static PyObject *
os_seteuid_impl(PyObject * module,uid_t euid)7916 os_seteuid_impl(PyObject *module, uid_t euid)
7917 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
7918 {
7919     if (seteuid(euid) < 0)
7920         return posix_error();
7921     Py_RETURN_NONE;
7922 }
7923 #endif /* HAVE_SETEUID */
7924 
7925 
7926 #ifdef HAVE_SETEGID
7927 /*[clinic input]
7928 os.setegid
7929 
7930     egid: gid_t
7931     /
7932 
7933 Set the current process's effective group id.
7934 [clinic start generated code]*/
7935 
7936 static PyObject *
os_setegid_impl(PyObject * module,gid_t egid)7937 os_setegid_impl(PyObject *module, gid_t egid)
7938 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
7939 {
7940     if (setegid(egid) < 0)
7941         return posix_error();
7942     Py_RETURN_NONE;
7943 }
7944 #endif /* HAVE_SETEGID */
7945 
7946 
7947 #ifdef HAVE_SETREUID
7948 /*[clinic input]
7949 os.setreuid
7950 
7951     ruid: uid_t
7952     euid: uid_t
7953     /
7954 
7955 Set the current process's real and effective user ids.
7956 [clinic start generated code]*/
7957 
7958 static PyObject *
os_setreuid_impl(PyObject * module,uid_t ruid,uid_t euid)7959 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
7960 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
7961 {
7962     if (setreuid(ruid, euid) < 0) {
7963         return posix_error();
7964     } else {
7965         Py_RETURN_NONE;
7966     }
7967 }
7968 #endif /* HAVE_SETREUID */
7969 
7970 
7971 #ifdef HAVE_SETREGID
7972 /*[clinic input]
7973 os.setregid
7974 
7975     rgid: gid_t
7976     egid: gid_t
7977     /
7978 
7979 Set the current process's real and effective group ids.
7980 [clinic start generated code]*/
7981 
7982 static PyObject *
os_setregid_impl(PyObject * module,gid_t rgid,gid_t egid)7983 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
7984 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
7985 {
7986     if (setregid(rgid, egid) < 0)
7987         return posix_error();
7988     Py_RETURN_NONE;
7989 }
7990 #endif /* HAVE_SETREGID */
7991 
7992 
7993 #ifdef HAVE_SETGID
7994 /*[clinic input]
7995 os.setgid
7996     gid: gid_t
7997     /
7998 
7999 Set the current process's group id.
8000 [clinic start generated code]*/
8001 
8002 static PyObject *
os_setgid_impl(PyObject * module,gid_t gid)8003 os_setgid_impl(PyObject *module, gid_t gid)
8004 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
8005 {
8006     if (setgid(gid) < 0)
8007         return posix_error();
8008     Py_RETURN_NONE;
8009 }
8010 #endif /* HAVE_SETGID */
8011 
8012 
8013 #ifdef HAVE_SETGROUPS
8014 /*[clinic input]
8015 os.setgroups
8016 
8017     groups: object
8018     /
8019 
8020 Set the groups of the current process to list.
8021 [clinic start generated code]*/
8022 
8023 static PyObject *
os_setgroups(PyObject * module,PyObject * groups)8024 os_setgroups(PyObject *module, PyObject *groups)
8025 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
8026 {
8027     Py_ssize_t i, len;
8028     gid_t grouplist[MAX_GROUPS];
8029 
8030     if (!PySequence_Check(groups)) {
8031         PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
8032         return NULL;
8033     }
8034     len = PySequence_Size(groups);
8035     if (len < 0) {
8036         return NULL;
8037     }
8038     if (len > MAX_GROUPS) {
8039         PyErr_SetString(PyExc_ValueError, "too many groups");
8040         return NULL;
8041     }
8042     for(i = 0; i < len; i++) {
8043         PyObject *elem;
8044         elem = PySequence_GetItem(groups, i);
8045         if (!elem)
8046             return NULL;
8047         if (!PyLong_Check(elem)) {
8048             PyErr_SetString(PyExc_TypeError,
8049                             "groups must be integers");
8050             Py_DECREF(elem);
8051             return NULL;
8052         } else {
8053             if (!_Py_Gid_Converter(elem, &grouplist[i])) {
8054                 Py_DECREF(elem);
8055                 return NULL;
8056             }
8057         }
8058         Py_DECREF(elem);
8059     }
8060 
8061     if (setgroups(len, grouplist) < 0)
8062         return posix_error();
8063     Py_RETURN_NONE;
8064 }
8065 #endif /* HAVE_SETGROUPS */
8066 
8067 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
8068 static PyObject *
wait_helper(PyObject * module,pid_t pid,int status,struct rusage * ru)8069 wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
8070 {
8071     PyObject *result;
8072     PyObject *struct_rusage;
8073 
8074     if (pid == -1)
8075         return posix_error();
8076 
8077     // If wait succeeded but no child was ready to report status, ru will not
8078     // have been populated.
8079     if (pid == 0) {
8080         memset(ru, 0, sizeof(*ru));
8081     }
8082 
8083     PyObject *m = PyImport_ImportModuleNoBlock("resource");
8084     if (m == NULL)
8085         return NULL;
8086     struct_rusage = PyObject_GetAttr(m, get_posix_state(module)->struct_rusage);
8087     Py_DECREF(m);
8088     if (struct_rusage == NULL)
8089         return NULL;
8090 
8091     /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
8092     result = PyStructSequence_New((PyTypeObject*) struct_rusage);
8093     Py_DECREF(struct_rusage);
8094     if (!result)
8095         return NULL;
8096 
8097 #ifndef doubletime
8098 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
8099 #endif
8100 
8101     PyStructSequence_SET_ITEM(result, 0,
8102                               PyFloat_FromDouble(doubletime(ru->ru_utime)));
8103     PyStructSequence_SET_ITEM(result, 1,
8104                               PyFloat_FromDouble(doubletime(ru->ru_stime)));
8105 #define SET_INT(result, index, value)\
8106         PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
8107     SET_INT(result, 2, ru->ru_maxrss);
8108     SET_INT(result, 3, ru->ru_ixrss);
8109     SET_INT(result, 4, ru->ru_idrss);
8110     SET_INT(result, 5, ru->ru_isrss);
8111     SET_INT(result, 6, ru->ru_minflt);
8112     SET_INT(result, 7, ru->ru_majflt);
8113     SET_INT(result, 8, ru->ru_nswap);
8114     SET_INT(result, 9, ru->ru_inblock);
8115     SET_INT(result, 10, ru->ru_oublock);
8116     SET_INT(result, 11, ru->ru_msgsnd);
8117     SET_INT(result, 12, ru->ru_msgrcv);
8118     SET_INT(result, 13, ru->ru_nsignals);
8119     SET_INT(result, 14, ru->ru_nvcsw);
8120     SET_INT(result, 15, ru->ru_nivcsw);
8121 #undef SET_INT
8122 
8123     if (PyErr_Occurred()) {
8124         Py_DECREF(result);
8125         return NULL;
8126     }
8127 
8128     return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
8129 }
8130 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
8131 
8132 
8133 #ifdef HAVE_WAIT3
8134 /*[clinic input]
8135 os.wait3
8136 
8137     options: int
8138 Wait for completion of a child process.
8139 
8140 Returns a tuple of information about the child process:
8141   (pid, status, rusage)
8142 [clinic start generated code]*/
8143 
8144 static PyObject *
os_wait3_impl(PyObject * module,int options)8145 os_wait3_impl(PyObject *module, int options)
8146 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
8147 {
8148     pid_t pid;
8149     struct rusage ru;
8150     int async_err = 0;
8151     WAIT_TYPE status;
8152     WAIT_STATUS_INT(status) = 0;
8153 
8154     do {
8155         Py_BEGIN_ALLOW_THREADS
8156         pid = wait3(&status, options, &ru);
8157         Py_END_ALLOW_THREADS
8158     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8159     if (pid < 0)
8160         return (!async_err) ? posix_error() : NULL;
8161 
8162     return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
8163 }
8164 #endif /* HAVE_WAIT3 */
8165 
8166 
8167 #ifdef HAVE_WAIT4
8168 /*[clinic input]
8169 
8170 os.wait4
8171 
8172     pid: pid_t
8173     options: int
8174 
8175 Wait for completion of a specific child process.
8176 
8177 Returns a tuple of information about the child process:
8178   (pid, status, rusage)
8179 [clinic start generated code]*/
8180 
8181 static PyObject *
os_wait4_impl(PyObject * module,pid_t pid,int options)8182 os_wait4_impl(PyObject *module, pid_t pid, int options)
8183 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
8184 {
8185     pid_t res;
8186     struct rusage ru;
8187     int async_err = 0;
8188     WAIT_TYPE status;
8189     WAIT_STATUS_INT(status) = 0;
8190 
8191     do {
8192         Py_BEGIN_ALLOW_THREADS
8193         res = wait4(pid, &status, options, &ru);
8194         Py_END_ALLOW_THREADS
8195     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8196     if (res < 0)
8197         return (!async_err) ? posix_error() : NULL;
8198 
8199     return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
8200 }
8201 #endif /* HAVE_WAIT4 */
8202 
8203 
8204 #if defined(HAVE_WAITID) && !defined(__APPLE__)
8205 /*[clinic input]
8206 os.waitid
8207 
8208     idtype: idtype_t
8209         Must be one of be P_PID, P_PGID or P_ALL.
8210     id: id_t
8211         The id to wait on.
8212     options: int
8213         Constructed from the ORing of one or more of WEXITED, WSTOPPED
8214         or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
8215     /
8216 
8217 Returns the result of waiting for a process or processes.
8218 
8219 Returns either waitid_result or None if WNOHANG is specified and there are
8220 no children in a waitable state.
8221 [clinic start generated code]*/
8222 
8223 static PyObject *
os_waitid_impl(PyObject * module,idtype_t idtype,id_t id,int options)8224 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
8225 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
8226 {
8227     PyObject *result;
8228     int res;
8229     int async_err = 0;
8230     siginfo_t si;
8231     si.si_pid = 0;
8232 
8233     do {
8234         Py_BEGIN_ALLOW_THREADS
8235         res = waitid(idtype, id, &si, options);
8236         Py_END_ALLOW_THREADS
8237     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8238     if (res < 0)
8239         return (!async_err) ? posix_error() : NULL;
8240 
8241     if (si.si_pid == 0)
8242         Py_RETURN_NONE;
8243 
8244     PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
8245     result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
8246     if (!result)
8247         return NULL;
8248 
8249     PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
8250     PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
8251     PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
8252     PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
8253     PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
8254     if (PyErr_Occurred()) {
8255         Py_DECREF(result);
8256         return NULL;
8257     }
8258 
8259     return result;
8260 }
8261 #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
8262 
8263 
8264 #if defined(HAVE_WAITPID)
8265 /*[clinic input]
8266 os.waitpid
8267     pid: pid_t
8268     options: int
8269     /
8270 
8271 Wait for completion of a given child process.
8272 
8273 Returns a tuple of information regarding the child process:
8274     (pid, status)
8275 
8276 The options argument is ignored on Windows.
8277 [clinic start generated code]*/
8278 
8279 static PyObject *
os_waitpid_impl(PyObject * module,pid_t pid,int options)8280 os_waitpid_impl(PyObject *module, pid_t pid, int options)
8281 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
8282 {
8283     pid_t res;
8284     int async_err = 0;
8285     WAIT_TYPE status;
8286     WAIT_STATUS_INT(status) = 0;
8287 
8288     do {
8289         Py_BEGIN_ALLOW_THREADS
8290         res = waitpid(pid, &status, options);
8291         Py_END_ALLOW_THREADS
8292     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8293     if (res < 0)
8294         return (!async_err) ? posix_error() : NULL;
8295 
8296     return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
8297 }
8298 #elif defined(HAVE_CWAIT)
8299 /* MS C has a variant of waitpid() that's usable for most purposes. */
8300 /*[clinic input]
8301 os.waitpid
8302     pid: intptr_t
8303     options: int
8304     /
8305 
8306 Wait for completion of a given process.
8307 
8308 Returns a tuple of information regarding the process:
8309     (pid, status << 8)
8310 
8311 The options argument is ignored on Windows.
8312 [clinic start generated code]*/
8313 
8314 static PyObject *
os_waitpid_impl(PyObject * module,intptr_t pid,int options)8315 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
8316 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
8317 {
8318     int status;
8319     intptr_t res;
8320     int async_err = 0;
8321 
8322     do {
8323         Py_BEGIN_ALLOW_THREADS
8324         _Py_BEGIN_SUPPRESS_IPH
8325         res = _cwait(&status, pid, options);
8326         _Py_END_SUPPRESS_IPH
8327         Py_END_ALLOW_THREADS
8328     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8329     if (res < 0)
8330         return (!async_err) ? posix_error() : NULL;
8331 
8332     unsigned long long ustatus = (unsigned int)status;
8333 
8334     /* shift the status left a byte so this is more like the POSIX waitpid */
8335     return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
8336 }
8337 #endif
8338 
8339 
8340 #ifdef HAVE_WAIT
8341 /*[clinic input]
8342 os.wait
8343 
8344 Wait for completion of a child process.
8345 
8346 Returns a tuple of information about the child process:
8347     (pid, status)
8348 [clinic start generated code]*/
8349 
8350 static PyObject *
os_wait_impl(PyObject * module)8351 os_wait_impl(PyObject *module)
8352 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
8353 {
8354     pid_t pid;
8355     int async_err = 0;
8356     WAIT_TYPE status;
8357     WAIT_STATUS_INT(status) = 0;
8358 
8359     do {
8360         Py_BEGIN_ALLOW_THREADS
8361         pid = wait(&status);
8362         Py_END_ALLOW_THREADS
8363     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8364     if (pid < 0)
8365         return (!async_err) ? posix_error() : NULL;
8366 
8367     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
8368 }
8369 #endif /* HAVE_WAIT */
8370 
8371 #if defined(__linux__) && defined(__NR_pidfd_open)
8372 /*[clinic input]
8373 os.pidfd_open
8374   pid: pid_t
8375   flags: unsigned_int = 0
8376 
8377 Return a file descriptor referring to the process *pid*.
8378 
8379 The descriptor can be used to perform process management without races and
8380 signals.
8381 [clinic start generated code]*/
8382 
8383 static PyObject *
os_pidfd_open_impl(PyObject * module,pid_t pid,unsigned int flags)8384 os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
8385 /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
8386 {
8387     int fd = syscall(__NR_pidfd_open, pid, flags);
8388     if (fd < 0) {
8389         return posix_error();
8390     }
8391     return PyLong_FromLong(fd);
8392 }
8393 #endif
8394 
8395 
8396 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
8397 /*[clinic input]
8398 os.readlink
8399 
8400     path: path_t
8401     *
8402     dir_fd: dir_fd(requires='readlinkat') = None
8403 
8404 Return a string representing the path to which the symbolic link points.
8405 
8406 If dir_fd is not None, it should be a file descriptor open to a directory,
8407 and path should be relative; path will then be relative to that directory.
8408 
8409 dir_fd may not be implemented on your platform.  If it is unavailable,
8410 using it will raise a NotImplementedError.
8411 [clinic start generated code]*/
8412 
8413 static PyObject *
os_readlink_impl(PyObject * module,path_t * path,int dir_fd)8414 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
8415 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
8416 {
8417 #if defined(HAVE_READLINK)
8418     char buffer[MAXPATHLEN+1];
8419     ssize_t length;
8420 #ifdef HAVE_READLINKAT
8421     int readlinkat_unavailable = 0;
8422 #endif
8423 
8424     Py_BEGIN_ALLOW_THREADS
8425 #ifdef HAVE_READLINKAT
8426     if (dir_fd != DEFAULT_DIR_FD) {
8427         if (HAVE_READLINKAT_RUNTIME) {
8428             length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
8429         } else {
8430             readlinkat_unavailable = 1;
8431         }
8432     } else
8433 #endif
8434         length = readlink(path->narrow, buffer, MAXPATHLEN);
8435     Py_END_ALLOW_THREADS
8436 
8437 #ifdef HAVE_READLINKAT
8438     if (readlinkat_unavailable) {
8439         argument_unavailable_error(NULL, "dir_fd");
8440         return NULL;
8441     }
8442 #endif
8443 
8444     if (length < 0) {
8445         return path_error(path);
8446     }
8447     buffer[length] = '\0';
8448 
8449     if (PyUnicode_Check(path->object))
8450         return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
8451     else
8452         return PyBytes_FromStringAndSize(buffer, length);
8453 #elif defined(MS_WINDOWS)
8454     DWORD n_bytes_returned;
8455     DWORD io_result = 0;
8456     HANDLE reparse_point_handle;
8457     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
8458     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
8459     PyObject *result = NULL;
8460 
8461     /* First get a handle to the reparse point */
8462     Py_BEGIN_ALLOW_THREADS
8463     reparse_point_handle = CreateFileW(
8464         path->wide,
8465         0,
8466         0,
8467         0,
8468         OPEN_EXISTING,
8469         FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
8470         0);
8471     if (reparse_point_handle != INVALID_HANDLE_VALUE) {
8472         /* New call DeviceIoControl to read the reparse point */
8473         io_result = DeviceIoControl(
8474             reparse_point_handle,
8475             FSCTL_GET_REPARSE_POINT,
8476             0, 0, /* in buffer */
8477             target_buffer, sizeof(target_buffer),
8478             &n_bytes_returned,
8479             0 /* we're not using OVERLAPPED_IO */
8480             );
8481         CloseHandle(reparse_point_handle);
8482     }
8483     Py_END_ALLOW_THREADS
8484 
8485     if (io_result == 0) {
8486         return path_error(path);
8487     }
8488 
8489     wchar_t *name = NULL;
8490     Py_ssize_t nameLen = 0;
8491     if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
8492     {
8493         name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
8494                            rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
8495         nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8496     }
8497     else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
8498     {
8499         name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8500                            rdb->MountPointReparseBuffer.SubstituteNameOffset);
8501         nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8502     }
8503     else
8504     {
8505         PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8506     }
8507     if (name) {
8508         if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8509             /* Our buffer is mutable, so this is okay */
8510             name[1] = L'\\';
8511         }
8512         result = PyUnicode_FromWideChar(name, nameLen);
8513         if (result && path->narrow) {
8514             Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8515         }
8516     }
8517     return result;
8518 #endif
8519 }
8520 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8521 
8522 #if defined(MS_WINDOWS)
8523 
8524 /* Remove the last portion of the path - return 0 on success */
8525 static int
_dirnameW(WCHAR * path)8526 _dirnameW(WCHAR *path)
8527 {
8528     WCHAR *ptr;
8529     size_t length = wcsnlen_s(path, MAX_PATH);
8530     if (length == MAX_PATH) {
8531         return -1;
8532     }
8533 
8534     /* walk the path from the end until a backslash is encountered */
8535     for(ptr = path + length; ptr != path; ptr--) {
8536         if (*ptr == L'\\' || *ptr == L'/') {
8537             break;
8538         }
8539     }
8540     *ptr = 0;
8541     return 0;
8542 }
8543 
8544 #endif
8545 
8546 #ifdef HAVE_SYMLINK
8547 
8548 #if defined(MS_WINDOWS)
8549 
8550 /* Is this path absolute? */
8551 static int
_is_absW(const WCHAR * path)8552 _is_absW(const WCHAR *path)
8553 {
8554     return path[0] == L'\\' || path[0] == L'/' ||
8555         (path[0] && path[1] == L':');
8556 }
8557 
8558 /* join root and rest with a backslash - return 0 on success */
8559 static int
_joinW(WCHAR * dest_path,const WCHAR * root,const WCHAR * rest)8560 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8561 {
8562     if (_is_absW(rest)) {
8563         return wcscpy_s(dest_path, MAX_PATH, rest);
8564     }
8565 
8566     if (wcscpy_s(dest_path, MAX_PATH, root)) {
8567         return -1;
8568     }
8569 
8570     if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8571         return -1;
8572     }
8573 
8574     return wcscat_s(dest_path, MAX_PATH, rest);
8575 }
8576 
8577 /* Return True if the path at src relative to dest is a directory */
8578 static int
_check_dirW(LPCWSTR src,LPCWSTR dest)8579 _check_dirW(LPCWSTR src, LPCWSTR dest)
8580 {
8581     WIN32_FILE_ATTRIBUTE_DATA src_info;
8582     WCHAR dest_parent[MAX_PATH];
8583     WCHAR src_resolved[MAX_PATH] = L"";
8584 
8585     /* dest_parent = os.path.dirname(dest) */
8586     if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8587         _dirnameW(dest_parent)) {
8588         return 0;
8589     }
8590     /* src_resolved = os.path.join(dest_parent, src) */
8591     if (_joinW(src_resolved, dest_parent, src)) {
8592         return 0;
8593     }
8594     return (
8595         GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8596         && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8597     );
8598 }
8599 #endif
8600 
8601 
8602 /*[clinic input]
8603 os.symlink
8604     src: path_t
8605     dst: path_t
8606     target_is_directory: bool = False
8607     *
8608     dir_fd: dir_fd(requires='symlinkat')=None
8609 
8610 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8611 
8612 Create a symbolic link pointing to src named dst.
8613 
8614 target_is_directory is required on Windows if the target is to be
8615   interpreted as a directory.  (On Windows, symlink requires
8616   Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8617   target_is_directory is ignored on non-Windows platforms.
8618 
8619 If dir_fd is not None, it should be a file descriptor open to a directory,
8620   and path should be relative; path will then be relative to that directory.
8621 dir_fd may not be implemented on your platform.
8622   If it is unavailable, using it will raise a NotImplementedError.
8623 
8624 [clinic start generated code]*/
8625 
8626 static PyObject *
os_symlink_impl(PyObject * module,path_t * src,path_t * dst,int target_is_directory,int dir_fd)8627 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8628                 int target_is_directory, int dir_fd)
8629 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8630 {
8631 #ifdef MS_WINDOWS
8632     DWORD result;
8633     DWORD flags = 0;
8634 
8635     /* Assumed true, set to false if detected to not be available. */
8636     static int windows_has_symlink_unprivileged_flag = TRUE;
8637 #else
8638     int result;
8639 #ifdef HAVE_SYMLINKAT
8640     int symlinkat_unavailable = 0;
8641 #endif
8642 #endif
8643 
8644     if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8645                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8646         return NULL;
8647     }
8648 
8649 #ifdef MS_WINDOWS
8650 
8651     if (windows_has_symlink_unprivileged_flag) {
8652         /* Allow non-admin symlinks if system allows it. */
8653         flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8654     }
8655 
8656     Py_BEGIN_ALLOW_THREADS
8657     _Py_BEGIN_SUPPRESS_IPH
8658     /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8659     if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8660         flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8661     }
8662 
8663     result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8664     _Py_END_SUPPRESS_IPH
8665     Py_END_ALLOW_THREADS
8666 
8667     if (windows_has_symlink_unprivileged_flag && !result &&
8668         ERROR_INVALID_PARAMETER == GetLastError()) {
8669 
8670         Py_BEGIN_ALLOW_THREADS
8671         _Py_BEGIN_SUPPRESS_IPH
8672         /* This error might be caused by
8673         SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8674         Try again, and update windows_has_symlink_unprivileged_flag if we
8675         are successful this time.
8676 
8677         NOTE: There is a risk of a race condition here if there are other
8678         conditions than the flag causing ERROR_INVALID_PARAMETER, and
8679         another process (or thread) changes that condition in between our
8680         calls to CreateSymbolicLink.
8681         */
8682         flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8683         result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8684         _Py_END_SUPPRESS_IPH
8685         Py_END_ALLOW_THREADS
8686 
8687         if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8688             windows_has_symlink_unprivileged_flag = FALSE;
8689         }
8690     }
8691 
8692     if (!result)
8693         return path_error2(src, dst);
8694 
8695 #else
8696 
8697     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8698         PyErr_SetString(PyExc_ValueError,
8699             "symlink: src and dst must be the same type");
8700         return NULL;
8701     }
8702 
8703     Py_BEGIN_ALLOW_THREADS
8704 #ifdef HAVE_SYMLINKAT
8705     if (dir_fd != DEFAULT_DIR_FD) {
8706         if (HAVE_SYMLINKAT_RUNTIME) {
8707             result = symlinkat(src->narrow, dir_fd, dst->narrow);
8708         } else {
8709             symlinkat_unavailable = 1;
8710         }
8711     } else
8712 #endif
8713         result = symlink(src->narrow, dst->narrow);
8714     Py_END_ALLOW_THREADS
8715 
8716 #ifdef HAVE_SYMLINKAT
8717     if (symlinkat_unavailable) {
8718           argument_unavailable_error(NULL, "dir_fd");
8719           return NULL;
8720     }
8721 #endif
8722 
8723     if (result)
8724         return path_error2(src, dst);
8725 #endif
8726 
8727     Py_RETURN_NONE;
8728 }
8729 #endif /* HAVE_SYMLINK */
8730 
8731 
8732 
8733 
8734 static PyStructSequence_Field times_result_fields[] = {
8735     {"user",    "user time"},
8736     {"system",   "system time"},
8737     {"children_user",    "user time of children"},
8738     {"children_system",    "system time of children"},
8739     {"elapsed",    "elapsed time since an arbitrary point in the past"},
8740     {NULL}
8741 };
8742 
8743 PyDoc_STRVAR(times_result__doc__,
8744 "times_result: Result from os.times().\n\n\
8745 This object may be accessed either as a tuple of\n\
8746   (user, system, children_user, children_system, elapsed),\n\
8747 or via the attributes user, system, children_user, children_system,\n\
8748 and elapsed.\n\
8749 \n\
8750 See os.times for more information.");
8751 
8752 static PyStructSequence_Desc times_result_desc = {
8753     "times_result", /* name */
8754     times_result__doc__, /* doc */
8755     times_result_fields,
8756     5
8757 };
8758 
8759 #ifdef MS_WINDOWS
8760 #define HAVE_TIMES  /* mandatory, for the method table */
8761 #endif
8762 
8763 #ifdef HAVE_TIMES
8764 
8765 static PyObject *
build_times_result(PyObject * module,double user,double system,double children_user,double children_system,double elapsed)8766 build_times_result(PyObject *module, double user, double system,
8767     double children_user, double children_system,
8768     double elapsed)
8769 {
8770     PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
8771     PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
8772     if (value == NULL)
8773         return NULL;
8774 
8775 #define SET(i, field) \
8776     { \
8777     PyObject *o = PyFloat_FromDouble(field); \
8778     if (!o) { \
8779         Py_DECREF(value); \
8780         return NULL; \
8781     } \
8782     PyStructSequence_SET_ITEM(value, i, o); \
8783     } \
8784 
8785     SET(0, user);
8786     SET(1, system);
8787     SET(2, children_user);
8788     SET(3, children_system);
8789     SET(4, elapsed);
8790 
8791 #undef SET
8792 
8793     return value;
8794 }
8795 
8796 
8797 #ifndef MS_WINDOWS
8798 #define NEED_TICKS_PER_SECOND
8799 static long ticks_per_second = -1;
8800 #endif /* MS_WINDOWS */
8801 
8802 /*[clinic input]
8803 os.times
8804 
8805 Return a collection containing process timing information.
8806 
8807 The object returned behaves like a named tuple with these fields:
8808   (utime, stime, cutime, cstime, elapsed_time)
8809 All fields are floating point numbers.
8810 [clinic start generated code]*/
8811 
8812 static PyObject *
os_times_impl(PyObject * module)8813 os_times_impl(PyObject *module)
8814 /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
8815 #ifdef MS_WINDOWS
8816 {
8817     FILETIME create, exit, kernel, user;
8818     HANDLE hProc;
8819     hProc = GetCurrentProcess();
8820     GetProcessTimes(hProc, &create, &exit, &kernel, &user);
8821     /* The fields of a FILETIME structure are the hi and lo part
8822        of a 64-bit value expressed in 100 nanosecond units.
8823        1e7 is one second in such units; 1e-7 the inverse.
8824        429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
8825     */
8826     return build_times_result(module,
8827         (double)(user.dwHighDateTime*429.4967296 +
8828                  user.dwLowDateTime*1e-7),
8829         (double)(kernel.dwHighDateTime*429.4967296 +
8830                  kernel.dwLowDateTime*1e-7),
8831         (double)0,
8832         (double)0,
8833         (double)0);
8834 }
8835 #else /* MS_WINDOWS */
8836 {
8837 
8838 
8839     struct tms t;
8840     clock_t c;
8841     errno = 0;
8842     c = times(&t);
8843     if (c == (clock_t) -1)
8844         return posix_error();
8845     return build_times_result(module,
8846                          (double)t.tms_utime / ticks_per_second,
8847                          (double)t.tms_stime / ticks_per_second,
8848                          (double)t.tms_cutime / ticks_per_second,
8849                          (double)t.tms_cstime / ticks_per_second,
8850                          (double)c / ticks_per_second);
8851 }
8852 #endif /* MS_WINDOWS */
8853 #endif /* HAVE_TIMES */
8854 
8855 
8856 #ifdef HAVE_GETSID
8857 /*[clinic input]
8858 os.getsid
8859 
8860     pid: pid_t
8861     /
8862 
8863 Call the system call getsid(pid) and return the result.
8864 [clinic start generated code]*/
8865 
8866 static PyObject *
os_getsid_impl(PyObject * module,pid_t pid)8867 os_getsid_impl(PyObject *module, pid_t pid)
8868 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
8869 {
8870     int sid;
8871     sid = getsid(pid);
8872     if (sid < 0)
8873         return posix_error();
8874     return PyLong_FromLong((long)sid);
8875 }
8876 #endif /* HAVE_GETSID */
8877 
8878 
8879 #ifdef HAVE_SETSID
8880 /*[clinic input]
8881 os.setsid
8882 
8883 Call the system call setsid().
8884 [clinic start generated code]*/
8885 
8886 static PyObject *
os_setsid_impl(PyObject * module)8887 os_setsid_impl(PyObject *module)
8888 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
8889 {
8890     if (setsid() < 0)
8891         return posix_error();
8892     Py_RETURN_NONE;
8893 }
8894 #endif /* HAVE_SETSID */
8895 
8896 
8897 #ifdef HAVE_SETPGID
8898 /*[clinic input]
8899 os.setpgid
8900 
8901     pid: pid_t
8902     pgrp: pid_t
8903     /
8904 
8905 Call the system call setpgid(pid, pgrp).
8906 [clinic start generated code]*/
8907 
8908 static PyObject *
os_setpgid_impl(PyObject * module,pid_t pid,pid_t pgrp)8909 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
8910 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
8911 {
8912     if (setpgid(pid, pgrp) < 0)
8913         return posix_error();
8914     Py_RETURN_NONE;
8915 }
8916 #endif /* HAVE_SETPGID */
8917 
8918 
8919 #ifdef HAVE_TCGETPGRP
8920 /*[clinic input]
8921 os.tcgetpgrp
8922 
8923     fd: int
8924     /
8925 
8926 Return the process group associated with the terminal specified by fd.
8927 [clinic start generated code]*/
8928 
8929 static PyObject *
os_tcgetpgrp_impl(PyObject * module,int fd)8930 os_tcgetpgrp_impl(PyObject *module, int fd)
8931 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
8932 {
8933     pid_t pgid = tcgetpgrp(fd);
8934     if (pgid < 0)
8935         return posix_error();
8936     return PyLong_FromPid(pgid);
8937 }
8938 #endif /* HAVE_TCGETPGRP */
8939 
8940 
8941 #ifdef HAVE_TCSETPGRP
8942 /*[clinic input]
8943 os.tcsetpgrp
8944 
8945     fd: int
8946     pgid: pid_t
8947     /
8948 
8949 Set the process group associated with the terminal specified by fd.
8950 [clinic start generated code]*/
8951 
8952 static PyObject *
os_tcsetpgrp_impl(PyObject * module,int fd,pid_t pgid)8953 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
8954 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
8955 {
8956     if (tcsetpgrp(fd, pgid) < 0)
8957         return posix_error();
8958     Py_RETURN_NONE;
8959 }
8960 #endif /* HAVE_TCSETPGRP */
8961 
8962 /* Functions acting on file descriptors */
8963 
8964 #ifdef O_CLOEXEC
8965 extern int _Py_open_cloexec_works;
8966 #endif
8967 
8968 
8969 /*[clinic input]
8970 os.open -> int
8971     path: path_t
8972     flags: int
8973     mode: int = 0o777
8974     *
8975     dir_fd: dir_fd(requires='openat') = None
8976 
8977 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
8978 
8979 Open a file for low level IO.  Returns a file descriptor (integer).
8980 
8981 If dir_fd is not None, it should be a file descriptor open to a directory,
8982   and path should be relative; path will then be relative to that directory.
8983 dir_fd may not be implemented on your platform.
8984   If it is unavailable, using it will raise a NotImplementedError.
8985 [clinic start generated code]*/
8986 
8987 static int
os_open_impl(PyObject * module,path_t * path,int flags,int mode,int dir_fd)8988 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
8989 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
8990 {
8991     int fd;
8992     int async_err = 0;
8993 #ifdef HAVE_OPENAT
8994     int openat_unavailable = 0;
8995 #endif
8996 
8997 #ifdef O_CLOEXEC
8998     int *atomic_flag_works = &_Py_open_cloexec_works;
8999 #elif !defined(MS_WINDOWS)
9000     int *atomic_flag_works = NULL;
9001 #endif
9002 
9003 #ifdef MS_WINDOWS
9004     flags |= O_NOINHERIT;
9005 #elif defined(O_CLOEXEC)
9006     flags |= O_CLOEXEC;
9007 #endif
9008 
9009     if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
9010         return -1;
9011     }
9012 
9013     _Py_BEGIN_SUPPRESS_IPH
9014     do {
9015         Py_BEGIN_ALLOW_THREADS
9016 #ifdef MS_WINDOWS
9017         fd = _wopen(path->wide, flags, mode);
9018 #else
9019 #ifdef HAVE_OPENAT
9020         if (dir_fd != DEFAULT_DIR_FD) {
9021             if (HAVE_OPENAT_RUNTIME) {
9022                 fd = openat(dir_fd, path->narrow, flags, mode);
9023 
9024             } else {
9025                 openat_unavailable = 1;
9026                 fd = -1;
9027             }
9028         } else
9029 #endif /* HAVE_OPENAT */
9030             fd = open(path->narrow, flags, mode);
9031 #endif /* !MS_WINDOWS */
9032         Py_END_ALLOW_THREADS
9033     } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9034     _Py_END_SUPPRESS_IPH
9035 
9036 #ifdef HAVE_OPENAT
9037     if (openat_unavailable) {
9038         argument_unavailable_error(NULL, "dir_fd");
9039         return -1;
9040     }
9041 #endif
9042 
9043     if (fd < 0) {
9044         if (!async_err)
9045             PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
9046         return -1;
9047     }
9048 
9049 #ifndef MS_WINDOWS
9050     if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
9051         close(fd);
9052         return -1;
9053     }
9054 #endif
9055 
9056     return fd;
9057 }
9058 
9059 
9060 /*[clinic input]
9061 os.close
9062 
9063     fd: int
9064 
9065 Close a file descriptor.
9066 [clinic start generated code]*/
9067 
9068 static PyObject *
os_close_impl(PyObject * module,int fd)9069 os_close_impl(PyObject *module, int fd)
9070 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
9071 {
9072     int res;
9073     /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
9074      * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
9075      * for more details.
9076      */
9077     Py_BEGIN_ALLOW_THREADS
9078     _Py_BEGIN_SUPPRESS_IPH
9079     res = close(fd);
9080     _Py_END_SUPPRESS_IPH
9081     Py_END_ALLOW_THREADS
9082     if (res < 0)
9083         return posix_error();
9084     Py_RETURN_NONE;
9085 }
9086 
9087 
9088 #ifdef HAVE_FDWALK
9089 static int
_fdwalk_close_func(void * lohi,int fd)9090 _fdwalk_close_func(void *lohi, int fd)
9091 {
9092     int lo = ((int *)lohi)[0];
9093     int hi = ((int *)lohi)[1];
9094 
9095     if (fd >= hi) {
9096         return 1;
9097     }
9098     else if (fd >= lo) {
9099         /* Ignore errors */
9100         (void)close(fd);
9101     }
9102     return 0;
9103 }
9104 #endif /* HAVE_FDWALK */
9105 
9106 /*[clinic input]
9107 os.closerange
9108 
9109     fd_low: int
9110     fd_high: int
9111     /
9112 
9113 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
9114 [clinic start generated code]*/
9115 
9116 static PyObject *
os_closerange_impl(PyObject * module,int fd_low,int fd_high)9117 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
9118 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
9119 {
9120 #ifdef HAVE_FDWALK
9121     int lohi[2];
9122 #endif
9123     Py_BEGIN_ALLOW_THREADS
9124     _Py_BEGIN_SUPPRESS_IPH
9125 #ifdef HAVE_FDWALK
9126     lohi[0] = Py_MAX(fd_low, 0);
9127     lohi[1] = fd_high;
9128     fdwalk(_fdwalk_close_func, lohi);
9129 #else
9130     fd_low = Py_MAX(fd_low, 0);
9131 #ifdef __FreeBSD__
9132     if (fd_high >= sysconf(_SC_OPEN_MAX)) {
9133         /* Any errors encountered while closing file descriptors are ignored */
9134         closefrom(fd_low);
9135     }
9136     else
9137 #endif
9138     {
9139         for (int i = fd_low; i < fd_high; i++) {
9140             /* Ignore errors */
9141             (void)close(i);
9142         }
9143     }
9144 #endif
9145     _Py_END_SUPPRESS_IPH
9146     Py_END_ALLOW_THREADS
9147     Py_RETURN_NONE;
9148 }
9149 
9150 
9151 /*[clinic input]
9152 os.dup -> int
9153 
9154     fd: int
9155     /
9156 
9157 Return a duplicate of a file descriptor.
9158 [clinic start generated code]*/
9159 
9160 static int
os_dup_impl(PyObject * module,int fd)9161 os_dup_impl(PyObject *module, int fd)
9162 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
9163 {
9164     return _Py_dup(fd);
9165 }
9166 
9167 
9168 /*[clinic input]
9169 os.dup2 -> int
9170     fd: int
9171     fd2: int
9172     inheritable: bool=True
9173 
9174 Duplicate file descriptor.
9175 [clinic start generated code]*/
9176 
9177 static int
os_dup2_impl(PyObject * module,int fd,int fd2,int inheritable)9178 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
9179 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
9180 {
9181     int res = 0;
9182 #if defined(HAVE_DUP3) && \
9183     !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
9184     /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
9185     static int dup3_works = -1;
9186 #endif
9187 
9188     if (fd < 0 || fd2 < 0) {
9189         posix_error();
9190         return -1;
9191     }
9192 
9193     /* dup2() can fail with EINTR if the target FD is already open, because it
9194      * then has to be closed. See os_close_impl() for why we don't handle EINTR
9195      * upon close(), and therefore below.
9196      */
9197 #ifdef MS_WINDOWS
9198     Py_BEGIN_ALLOW_THREADS
9199     _Py_BEGIN_SUPPRESS_IPH
9200     res = dup2(fd, fd2);
9201     _Py_END_SUPPRESS_IPH
9202     Py_END_ALLOW_THREADS
9203     if (res < 0) {
9204         posix_error();
9205         return -1;
9206     }
9207     res = fd2; // msvcrt dup2 returns 0 on success.
9208 
9209     /* Character files like console cannot be make non-inheritable */
9210     if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9211         close(fd2);
9212         return -1;
9213     }
9214 
9215 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
9216     Py_BEGIN_ALLOW_THREADS
9217     if (!inheritable)
9218         res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
9219     else
9220         res = dup2(fd, fd2);
9221     Py_END_ALLOW_THREADS
9222     if (res < 0) {
9223         posix_error();
9224         return -1;
9225     }
9226 
9227 #else
9228 
9229 #ifdef HAVE_DUP3
9230     if (!inheritable && dup3_works != 0) {
9231         Py_BEGIN_ALLOW_THREADS
9232         res = dup3(fd, fd2, O_CLOEXEC);
9233         Py_END_ALLOW_THREADS
9234         if (res < 0) {
9235             if (dup3_works == -1)
9236                 dup3_works = (errno != ENOSYS);
9237             if (dup3_works) {
9238                 posix_error();
9239                 return -1;
9240             }
9241         }
9242     }
9243 
9244     if (inheritable || dup3_works == 0)
9245     {
9246 #endif
9247         Py_BEGIN_ALLOW_THREADS
9248         res = dup2(fd, fd2);
9249         Py_END_ALLOW_THREADS
9250         if (res < 0) {
9251             posix_error();
9252             return -1;
9253         }
9254 
9255         if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9256             close(fd2);
9257             return -1;
9258         }
9259 #ifdef HAVE_DUP3
9260     }
9261 #endif
9262 
9263 #endif
9264 
9265     return res;
9266 }
9267 
9268 
9269 #ifdef HAVE_LOCKF
9270 /*[clinic input]
9271 os.lockf
9272 
9273     fd: int
9274         An open file descriptor.
9275     command: int
9276         One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
9277     length: Py_off_t
9278         The number of bytes to lock, starting at the current position.
9279     /
9280 
9281 Apply, test or remove a POSIX lock on an open file descriptor.
9282 
9283 [clinic start generated code]*/
9284 
9285 static PyObject *
os_lockf_impl(PyObject * module,int fd,int command,Py_off_t length)9286 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
9287 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
9288 {
9289     int res;
9290 
9291     if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
9292         return NULL;
9293     }
9294 
9295     Py_BEGIN_ALLOW_THREADS
9296     res = lockf(fd, command, length);
9297     Py_END_ALLOW_THREADS
9298 
9299     if (res < 0)
9300         return posix_error();
9301 
9302     Py_RETURN_NONE;
9303 }
9304 #endif /* HAVE_LOCKF */
9305 
9306 
9307 /*[clinic input]
9308 os.lseek -> Py_off_t
9309 
9310     fd: int
9311     position: Py_off_t
9312     how: int
9313     /
9314 
9315 Set the position of a file descriptor.  Return the new position.
9316 
9317 Return the new cursor position in number of bytes
9318 relative to the beginning of the file.
9319 [clinic start generated code]*/
9320 
9321 static Py_off_t
os_lseek_impl(PyObject * module,int fd,Py_off_t position,int how)9322 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
9323 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
9324 {
9325     Py_off_t result;
9326 
9327 #ifdef SEEK_SET
9328     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
9329     switch (how) {
9330         case 0: how = SEEK_SET; break;
9331         case 1: how = SEEK_CUR; break;
9332         case 2: how = SEEK_END; break;
9333     }
9334 #endif /* SEEK_END */
9335 
9336     Py_BEGIN_ALLOW_THREADS
9337     _Py_BEGIN_SUPPRESS_IPH
9338 #ifdef MS_WINDOWS
9339     result = _lseeki64(fd, position, how);
9340 #else
9341     result = lseek(fd, position, how);
9342 #endif
9343     _Py_END_SUPPRESS_IPH
9344     Py_END_ALLOW_THREADS
9345     if (result < 0)
9346         posix_error();
9347 
9348     return result;
9349 }
9350 
9351 
9352 /*[clinic input]
9353 os.read
9354     fd: int
9355     length: Py_ssize_t
9356     /
9357 
9358 Read from a file descriptor.  Returns a bytes object.
9359 [clinic start generated code]*/
9360 
9361 static PyObject *
os_read_impl(PyObject * module,int fd,Py_ssize_t length)9362 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
9363 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
9364 {
9365     Py_ssize_t n;
9366     PyObject *buffer;
9367 
9368     if (length < 0) {
9369         errno = EINVAL;
9370         return posix_error();
9371     }
9372 
9373     length = Py_MIN(length, _PY_READ_MAX);
9374 
9375     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9376     if (buffer == NULL)
9377         return NULL;
9378 
9379     n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
9380     if (n == -1) {
9381         Py_DECREF(buffer);
9382         return NULL;
9383     }
9384 
9385     if (n != length)
9386         _PyBytes_Resize(&buffer, n);
9387 
9388     return buffer;
9389 }
9390 
9391 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
9392                                 || defined(__APPLE__))) \
9393     || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
9394     || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9395 static int
iov_setup(struct iovec ** iov,Py_buffer ** buf,PyObject * seq,Py_ssize_t cnt,int type)9396 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
9397 {
9398     Py_ssize_t i, j;
9399 
9400     *iov = PyMem_New(struct iovec, cnt);
9401     if (*iov == NULL) {
9402         PyErr_NoMemory();
9403         return -1;
9404     }
9405 
9406     *buf = PyMem_New(Py_buffer, cnt);
9407     if (*buf == NULL) {
9408         PyMem_Del(*iov);
9409         PyErr_NoMemory();
9410         return -1;
9411     }
9412 
9413     for (i = 0; i < cnt; i++) {
9414         PyObject *item = PySequence_GetItem(seq, i);
9415         if (item == NULL)
9416             goto fail;
9417         if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
9418             Py_DECREF(item);
9419             goto fail;
9420         }
9421         Py_DECREF(item);
9422         (*iov)[i].iov_base = (*buf)[i].buf;
9423         (*iov)[i].iov_len = (*buf)[i].len;
9424     }
9425     return 0;
9426 
9427 fail:
9428     PyMem_Del(*iov);
9429     for (j = 0; j < i; j++) {
9430         PyBuffer_Release(&(*buf)[j]);
9431     }
9432     PyMem_Del(*buf);
9433     return -1;
9434 }
9435 
9436 static void
iov_cleanup(struct iovec * iov,Py_buffer * buf,int cnt)9437 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9438 {
9439     int i;
9440     PyMem_Del(iov);
9441     for (i = 0; i < cnt; i++) {
9442         PyBuffer_Release(&buf[i]);
9443     }
9444     PyMem_Del(buf);
9445 }
9446 #endif
9447 
9448 
9449 #ifdef HAVE_READV
9450 /*[clinic input]
9451 os.readv -> Py_ssize_t
9452 
9453     fd: int
9454     buffers: object
9455     /
9456 
9457 Read from a file descriptor fd into an iterable of buffers.
9458 
9459 The buffers should be mutable buffers accepting bytes.
9460 readv will transfer data into each buffer until it is full
9461 and then move on to the next buffer in the sequence to hold
9462 the rest of the data.
9463 
9464 readv returns the total number of bytes read,
9465 which may be less than the total capacity of all the buffers.
9466 [clinic start generated code]*/
9467 
9468 static Py_ssize_t
os_readv_impl(PyObject * module,int fd,PyObject * buffers)9469 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9470 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9471 {
9472     Py_ssize_t cnt, n;
9473     int async_err = 0;
9474     struct iovec *iov;
9475     Py_buffer *buf;
9476 
9477     if (!PySequence_Check(buffers)) {
9478         PyErr_SetString(PyExc_TypeError,
9479             "readv() arg 2 must be a sequence");
9480         return -1;
9481     }
9482 
9483     cnt = PySequence_Size(buffers);
9484     if (cnt < 0)
9485         return -1;
9486 
9487     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9488         return -1;
9489 
9490     do {
9491         Py_BEGIN_ALLOW_THREADS
9492         n = readv(fd, iov, cnt);
9493         Py_END_ALLOW_THREADS
9494     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9495 
9496     iov_cleanup(iov, buf, cnt);
9497     if (n < 0) {
9498         if (!async_err)
9499             posix_error();
9500         return -1;
9501     }
9502 
9503     return n;
9504 }
9505 #endif /* HAVE_READV */
9506 
9507 
9508 #ifdef HAVE_PREAD
9509 /*[clinic input]
9510 os.pread
9511 
9512     fd: int
9513     length: Py_ssize_t
9514     offset: Py_off_t
9515     /
9516 
9517 Read a number of bytes from a file descriptor starting at a particular offset.
9518 
9519 Read length bytes from file descriptor fd, starting at offset bytes from
9520 the beginning of the file.  The file offset remains unchanged.
9521 [clinic start generated code]*/
9522 
9523 static PyObject *
os_pread_impl(PyObject * module,int fd,Py_ssize_t length,Py_off_t offset)9524 os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
9525 /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
9526 {
9527     Py_ssize_t n;
9528     int async_err = 0;
9529     PyObject *buffer;
9530 
9531     if (length < 0) {
9532         errno = EINVAL;
9533         return posix_error();
9534     }
9535     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9536     if (buffer == NULL)
9537         return NULL;
9538 
9539     do {
9540         Py_BEGIN_ALLOW_THREADS
9541         _Py_BEGIN_SUPPRESS_IPH
9542         n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9543         _Py_END_SUPPRESS_IPH
9544         Py_END_ALLOW_THREADS
9545     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9546 
9547     if (n < 0) {
9548         Py_DECREF(buffer);
9549         return (!async_err) ? posix_error() : NULL;
9550     }
9551     if (n != length)
9552         _PyBytes_Resize(&buffer, n);
9553     return buffer;
9554 }
9555 #endif /* HAVE_PREAD */
9556 
9557 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9558 /*[clinic input]
9559 os.preadv -> Py_ssize_t
9560 
9561     fd: int
9562     buffers: object
9563     offset: Py_off_t
9564     flags: int = 0
9565     /
9566 
9567 Reads from a file descriptor into a number of mutable bytes-like objects.
9568 
9569 Combines the functionality of readv() and pread(). As readv(), it will
9570 transfer data into each buffer until it is full and then move on to the next
9571 buffer in the sequence to hold the rest of the data. Its fourth argument,
9572 specifies the file offset at which the input operation is to be performed. It
9573 will return the total number of bytes read (which can be less than the total
9574 capacity of all the objects).
9575 
9576 The flags argument contains a bitwise OR of zero or more of the following flags:
9577 
9578 - RWF_HIPRI
9579 - RWF_NOWAIT
9580 
9581 Using non-zero flags requires Linux 4.6 or newer.
9582 [clinic start generated code]*/
9583 
9584 static Py_ssize_t
os_preadv_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9585 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9586                int flags)
9587 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9588 {
9589     Py_ssize_t cnt, n;
9590     int async_err = 0;
9591     struct iovec *iov;
9592     Py_buffer *buf;
9593 
9594     if (!PySequence_Check(buffers)) {
9595         PyErr_SetString(PyExc_TypeError,
9596             "preadv2() arg 2 must be a sequence");
9597         return -1;
9598     }
9599 
9600     cnt = PySequence_Size(buffers);
9601     if (cnt < 0) {
9602         return -1;
9603     }
9604 
9605 #ifndef HAVE_PREADV2
9606     if(flags != 0) {
9607         argument_unavailable_error("preadv2", "flags");
9608         return -1;
9609     }
9610 #endif
9611 
9612     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9613         return -1;
9614     }
9615 #ifdef HAVE_PREADV2
9616     do {
9617         Py_BEGIN_ALLOW_THREADS
9618         _Py_BEGIN_SUPPRESS_IPH
9619         n = preadv2(fd, iov, cnt, offset, flags);
9620         _Py_END_SUPPRESS_IPH
9621         Py_END_ALLOW_THREADS
9622     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9623 #else
9624     do {
9625 #ifdef __APPLE__
9626 /* This entire function will be removed from the module dict when the API
9627  * is not available.
9628  */
9629 #pragma clang diagnostic push
9630 #pragma clang diagnostic ignored "-Wunguarded-availability"
9631 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
9632 #endif
9633         Py_BEGIN_ALLOW_THREADS
9634         _Py_BEGIN_SUPPRESS_IPH
9635         n = preadv(fd, iov, cnt, offset);
9636         _Py_END_SUPPRESS_IPH
9637         Py_END_ALLOW_THREADS
9638     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9639 
9640 #ifdef __APPLE__
9641 #pragma clang diagnostic pop
9642 #endif
9643 
9644 #endif
9645 
9646     iov_cleanup(iov, buf, cnt);
9647     if (n < 0) {
9648         if (!async_err) {
9649             posix_error();
9650         }
9651         return -1;
9652     }
9653 
9654     return n;
9655 }
9656 #endif /* HAVE_PREADV */
9657 
9658 
9659 /*[clinic input]
9660 os.write -> Py_ssize_t
9661 
9662     fd: int
9663     data: Py_buffer
9664     /
9665 
9666 Write a bytes object to a file descriptor.
9667 [clinic start generated code]*/
9668 
9669 static Py_ssize_t
os_write_impl(PyObject * module,int fd,Py_buffer * data)9670 os_write_impl(PyObject *module, int fd, Py_buffer *data)
9671 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9672 {
9673     return _Py_write(fd, data->buf, data->len);
9674 }
9675 
9676 #ifdef HAVE_SENDFILE
9677 #ifdef __APPLE__
9678 /*[clinic input]
9679 os.sendfile
9680 
9681     out_fd: int
9682     in_fd: int
9683     offset: Py_off_t
9684     count as sbytes: Py_off_t
9685     headers: object(c_default="NULL") = ()
9686     trailers: object(c_default="NULL") = ()
9687     flags: int = 0
9688 
9689 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9690 [clinic start generated code]*/
9691 
9692 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)9693 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9694                  Py_off_t sbytes, PyObject *headers, PyObject *trailers,
9695                  int flags)
9696 /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
9697 #elif defined(__FreeBSD__) || defined(__DragonFly__)
9698 /*[clinic input]
9699 os.sendfile
9700 
9701     out_fd: int
9702     in_fd: int
9703     offset: Py_off_t
9704     count: Py_ssize_t
9705     headers: object(c_default="NULL") = ()
9706     trailers: object(c_default="NULL") = ()
9707     flags: int = 0
9708 
9709 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9710 [clinic start generated code]*/
9711 
9712 static PyObject *
9713 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9714                  Py_ssize_t count, PyObject *headers, PyObject *trailers,
9715                  int flags)
9716 /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
9717 #else
9718 /*[clinic input]
9719 os.sendfile
9720 
9721     out_fd: int
9722     in_fd: int
9723     offset as offobj: object
9724     count: Py_ssize_t
9725 
9726 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9727 [clinic start generated code]*/
9728 
9729 static PyObject *
9730 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
9731                  Py_ssize_t count)
9732 /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
9733 #endif
9734 {
9735     Py_ssize_t ret;
9736     int async_err = 0;
9737 
9738 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9739 #ifndef __APPLE__
9740     off_t sbytes;
9741 #endif
9742     Py_buffer *hbuf, *tbuf;
9743     struct sf_hdtr sf;
9744 
9745     sf.headers = NULL;
9746     sf.trailers = NULL;
9747 
9748     if (headers != NULL) {
9749         if (!PySequence_Check(headers)) {
9750             PyErr_SetString(PyExc_TypeError,
9751                 "sendfile() headers must be a sequence");
9752             return NULL;
9753         } else {
9754             Py_ssize_t i = PySequence_Size(headers);
9755             if (i < 0)
9756                 return NULL;
9757             if (i > INT_MAX) {
9758                 PyErr_SetString(PyExc_OverflowError,
9759                     "sendfile() header is too large");
9760                 return NULL;
9761             }
9762             if (i > 0) {
9763                 sf.hdr_cnt = (int)i;
9764                 if (iov_setup(&(sf.headers), &hbuf,
9765                               headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9766                     return NULL;
9767 #ifdef __APPLE__
9768                 for (i = 0; i < sf.hdr_cnt; i++) {
9769                     Py_ssize_t blen = sf.headers[i].iov_len;
9770 # define OFF_T_MAX 0x7fffffffffffffff
9771                     if (sbytes >= OFF_T_MAX - blen) {
9772                         PyErr_SetString(PyExc_OverflowError,
9773                             "sendfile() header is too large");
9774                         return NULL;
9775                     }
9776                     sbytes += blen;
9777                 }
9778 #endif
9779             }
9780         }
9781     }
9782     if (trailers != NULL) {
9783         if (!PySequence_Check(trailers)) {
9784             PyErr_SetString(PyExc_TypeError,
9785                 "sendfile() trailers must be a sequence");
9786             return NULL;
9787         } else {
9788             Py_ssize_t i = PySequence_Size(trailers);
9789             if (i < 0)
9790                 return NULL;
9791             if (i > INT_MAX) {
9792                 PyErr_SetString(PyExc_OverflowError,
9793                     "sendfile() trailer is too large");
9794                 return NULL;
9795             }
9796             if (i > 0) {
9797                 sf.trl_cnt = (int)i;
9798                 if (iov_setup(&(sf.trailers), &tbuf,
9799                               trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
9800                     return NULL;
9801             }
9802         }
9803     }
9804 
9805     _Py_BEGIN_SUPPRESS_IPH
9806     do {
9807         Py_BEGIN_ALLOW_THREADS
9808 #ifdef __APPLE__
9809         ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
9810 #else
9811         ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
9812 #endif
9813         Py_END_ALLOW_THREADS
9814     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9815     _Py_END_SUPPRESS_IPH
9816 
9817     if (sf.headers != NULL)
9818         iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
9819     if (sf.trailers != NULL)
9820         iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
9821 
9822     if (ret < 0) {
9823         if ((errno == EAGAIN) || (errno == EBUSY)) {
9824             if (sbytes != 0) {
9825                 // some data has been sent
9826                 goto done;
9827             }
9828             else {
9829                 // no data has been sent; upper application is supposed
9830                 // to retry on EAGAIN or EBUSY
9831                 return posix_error();
9832             }
9833         }
9834         return (!async_err) ? posix_error() : NULL;
9835     }
9836     goto done;
9837 
9838 done:
9839     #if !defined(HAVE_LARGEFILE_SUPPORT)
9840         return Py_BuildValue("l", sbytes);
9841     #else
9842         return Py_BuildValue("L", sbytes);
9843     #endif
9844 
9845 #else
9846 #ifdef __linux__
9847     if (offobj == Py_None) {
9848         do {
9849             Py_BEGIN_ALLOW_THREADS
9850             ret = sendfile(out_fd, in_fd, NULL, count);
9851             Py_END_ALLOW_THREADS
9852         } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9853         if (ret < 0)
9854             return (!async_err) ? posix_error() : NULL;
9855         return Py_BuildValue("n", ret);
9856     }
9857 #endif
9858     off_t offset;
9859     if (!Py_off_t_converter(offobj, &offset))
9860         return NULL;
9861 
9862 #if defined(__sun) && defined(__SVR4)
9863     // On Solaris, sendfile raises EINVAL rather than returning 0
9864     // when the offset is equal or bigger than the in_fd size.
9865     struct stat st;
9866 
9867     do {
9868         Py_BEGIN_ALLOW_THREADS
9869         ret = fstat(in_fd, &st);
9870         Py_END_ALLOW_THREADS
9871     } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9872     if (ret < 0)
9873         return (!async_err) ? posix_error() : NULL;
9874 
9875     if (offset >= st.st_size) {
9876         return Py_BuildValue("i", 0);
9877     }
9878 
9879     // On illumos specifically sendfile() may perform a partial write but
9880     // return -1/an error (in one confirmed case the destination socket
9881     // had a 5 second timeout set and errno was EAGAIN) and it's on the client
9882     // code to check if the offset parameter was modified by sendfile().
9883     //
9884     // We need this variable to track said change.
9885     off_t original_offset = offset;
9886 #endif
9887 
9888     do {
9889         Py_BEGIN_ALLOW_THREADS
9890         ret = sendfile(out_fd, in_fd, &offset, count);
9891 #if defined(__sun) && defined(__SVR4)
9892         // This handles illumos-specific sendfile() partial write behavior,
9893         // see a comment above for more details.
9894         if (ret < 0 && offset != original_offset) {
9895             ret = offset - original_offset;
9896         }
9897 #endif
9898         Py_END_ALLOW_THREADS
9899     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9900     if (ret < 0)
9901         return (!async_err) ? posix_error() : NULL;
9902     return Py_BuildValue("n", ret);
9903 #endif
9904 }
9905 #endif /* HAVE_SENDFILE */
9906 
9907 
9908 #if defined(__APPLE__)
9909 /*[clinic input]
9910 os._fcopyfile
9911 
9912     in_fd: int
9913     out_fd: int
9914     flags: int
9915     /
9916 
9917 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
9918 [clinic start generated code]*/
9919 
9920 static PyObject *
os__fcopyfile_impl(PyObject * module,int in_fd,int out_fd,int flags)9921 os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
9922 /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
9923 {
9924     int ret;
9925 
9926     Py_BEGIN_ALLOW_THREADS
9927     ret = fcopyfile(in_fd, out_fd, NULL, flags);
9928     Py_END_ALLOW_THREADS
9929     if (ret < 0)
9930         return posix_error();
9931     Py_RETURN_NONE;
9932 }
9933 #endif
9934 
9935 
9936 /*[clinic input]
9937 os.fstat
9938 
9939     fd : int
9940 
9941 Perform a stat system call on the given file descriptor.
9942 
9943 Like stat(), but for an open file descriptor.
9944 Equivalent to os.stat(fd).
9945 [clinic start generated code]*/
9946 
9947 static PyObject *
os_fstat_impl(PyObject * module,int fd)9948 os_fstat_impl(PyObject *module, int fd)
9949 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
9950 {
9951     STRUCT_STAT st;
9952     int res;
9953     int async_err = 0;
9954 
9955     do {
9956         Py_BEGIN_ALLOW_THREADS
9957         res = FSTAT(fd, &st);
9958         Py_END_ALLOW_THREADS
9959     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9960     if (res != 0) {
9961 #ifdef MS_WINDOWS
9962         return PyErr_SetFromWindowsErr(0);
9963 #else
9964         return (!async_err) ? posix_error() : NULL;
9965 #endif
9966     }
9967 
9968     return _pystat_fromstructstat(module, &st);
9969 }
9970 
9971 
9972 /*[clinic input]
9973 os.isatty -> bool
9974     fd: int
9975     /
9976 
9977 Return True if the fd is connected to a terminal.
9978 
9979 Return True if the file descriptor is an open file descriptor
9980 connected to the slave end of a terminal.
9981 [clinic start generated code]*/
9982 
9983 static int
os_isatty_impl(PyObject * module,int fd)9984 os_isatty_impl(PyObject *module, int fd)
9985 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
9986 {
9987     int return_value;
9988     _Py_BEGIN_SUPPRESS_IPH
9989     return_value = isatty(fd);
9990     _Py_END_SUPPRESS_IPH
9991     return return_value;
9992 }
9993 
9994 
9995 #ifdef HAVE_PIPE
9996 /*[clinic input]
9997 os.pipe
9998 
9999 Create a pipe.
10000 
10001 Returns a tuple of two file descriptors:
10002   (read_fd, write_fd)
10003 [clinic start generated code]*/
10004 
10005 static PyObject *
os_pipe_impl(PyObject * module)10006 os_pipe_impl(PyObject *module)
10007 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
10008 {
10009     int fds[2];
10010 #ifdef MS_WINDOWS
10011     HANDLE read, write;
10012     SECURITY_ATTRIBUTES attr;
10013     BOOL ok;
10014 #else
10015     int res;
10016 #endif
10017 
10018 #ifdef MS_WINDOWS
10019     attr.nLength = sizeof(attr);
10020     attr.lpSecurityDescriptor = NULL;
10021     attr.bInheritHandle = FALSE;
10022 
10023     Py_BEGIN_ALLOW_THREADS
10024     _Py_BEGIN_SUPPRESS_IPH
10025     ok = CreatePipe(&read, &write, &attr, 0);
10026     if (ok) {
10027         fds[0] = _open_osfhandle((intptr_t)read, _O_RDONLY);
10028         fds[1] = _open_osfhandle((intptr_t)write, _O_WRONLY);
10029         if (fds[0] == -1 || fds[1] == -1) {
10030             CloseHandle(read);
10031             CloseHandle(write);
10032             ok = 0;
10033         }
10034     }
10035     _Py_END_SUPPRESS_IPH
10036     Py_END_ALLOW_THREADS
10037 
10038     if (!ok)
10039         return PyErr_SetFromWindowsErr(0);
10040 #else
10041 
10042 #ifdef HAVE_PIPE2
10043     Py_BEGIN_ALLOW_THREADS
10044     res = pipe2(fds, O_CLOEXEC);
10045     Py_END_ALLOW_THREADS
10046 
10047     if (res != 0 && errno == ENOSYS)
10048     {
10049 #endif
10050         Py_BEGIN_ALLOW_THREADS
10051         res = pipe(fds);
10052         Py_END_ALLOW_THREADS
10053 
10054         if (res == 0) {
10055             if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
10056                 close(fds[0]);
10057                 close(fds[1]);
10058                 return NULL;
10059             }
10060             if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
10061                 close(fds[0]);
10062                 close(fds[1]);
10063                 return NULL;
10064             }
10065         }
10066 #ifdef HAVE_PIPE2
10067     }
10068 #endif
10069 
10070     if (res != 0)
10071         return PyErr_SetFromErrno(PyExc_OSError);
10072 #endif /* !MS_WINDOWS */
10073     return Py_BuildValue("(ii)", fds[0], fds[1]);
10074 }
10075 #endif  /* HAVE_PIPE */
10076 
10077 
10078 #ifdef HAVE_PIPE2
10079 /*[clinic input]
10080 os.pipe2
10081 
10082     flags: int
10083     /
10084 
10085 Create a pipe with flags set atomically.
10086 
10087 Returns a tuple of two file descriptors:
10088   (read_fd, write_fd)
10089 
10090 flags can be constructed by ORing together one or more of these values:
10091 O_NONBLOCK, O_CLOEXEC.
10092 [clinic start generated code]*/
10093 
10094 static PyObject *
os_pipe2_impl(PyObject * module,int flags)10095 os_pipe2_impl(PyObject *module, int flags)
10096 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
10097 {
10098     int fds[2];
10099     int res;
10100 
10101     res = pipe2(fds, flags);
10102     if (res != 0)
10103         return posix_error();
10104     return Py_BuildValue("(ii)", fds[0], fds[1]);
10105 }
10106 #endif /* HAVE_PIPE2 */
10107 
10108 
10109 #ifdef HAVE_WRITEV
10110 /*[clinic input]
10111 os.writev -> Py_ssize_t
10112     fd: int
10113     buffers: object
10114     /
10115 
10116 Iterate over buffers, and write the contents of each to a file descriptor.
10117 
10118 Returns the total number of bytes written.
10119 buffers must be a sequence of bytes-like objects.
10120 [clinic start generated code]*/
10121 
10122 static Py_ssize_t
os_writev_impl(PyObject * module,int fd,PyObject * buffers)10123 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
10124 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
10125 {
10126     Py_ssize_t cnt;
10127     Py_ssize_t result;
10128     int async_err = 0;
10129     struct iovec *iov;
10130     Py_buffer *buf;
10131 
10132     if (!PySequence_Check(buffers)) {
10133         PyErr_SetString(PyExc_TypeError,
10134             "writev() arg 2 must be a sequence");
10135         return -1;
10136     }
10137     cnt = PySequence_Size(buffers);
10138     if (cnt < 0)
10139         return -1;
10140 
10141     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10142         return -1;
10143     }
10144 
10145     do {
10146         Py_BEGIN_ALLOW_THREADS
10147         result = writev(fd, iov, cnt);
10148         Py_END_ALLOW_THREADS
10149     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10150 
10151     iov_cleanup(iov, buf, cnt);
10152     if (result < 0 && !async_err)
10153         posix_error();
10154 
10155     return result;
10156 }
10157 #endif /* HAVE_WRITEV */
10158 
10159 
10160 #ifdef HAVE_PWRITE
10161 /*[clinic input]
10162 os.pwrite -> Py_ssize_t
10163 
10164     fd: int
10165     buffer: Py_buffer
10166     offset: Py_off_t
10167     /
10168 
10169 Write bytes to a file descriptor starting at a particular offset.
10170 
10171 Write buffer to fd, starting at offset bytes from the beginning of
10172 the file.  Returns the number of bytes writte.  Does not change the
10173 current file offset.
10174 [clinic start generated code]*/
10175 
10176 static Py_ssize_t
os_pwrite_impl(PyObject * module,int fd,Py_buffer * buffer,Py_off_t offset)10177 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
10178 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
10179 {
10180     Py_ssize_t size;
10181     int async_err = 0;
10182 
10183     do {
10184         Py_BEGIN_ALLOW_THREADS
10185         _Py_BEGIN_SUPPRESS_IPH
10186         size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
10187         _Py_END_SUPPRESS_IPH
10188         Py_END_ALLOW_THREADS
10189     } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10190 
10191     if (size < 0 && !async_err)
10192         posix_error();
10193     return size;
10194 }
10195 #endif /* HAVE_PWRITE */
10196 
10197 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
10198 /*[clinic input]
10199 os.pwritev -> Py_ssize_t
10200 
10201     fd: int
10202     buffers: object
10203     offset: Py_off_t
10204     flags: int = 0
10205     /
10206 
10207 Writes the contents of bytes-like objects to a file descriptor at a given offset.
10208 
10209 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
10210 of bytes-like objects. Buffers are processed in array order. Entire contents of first
10211 buffer is written before proceeding to second, and so on. The operating system may
10212 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
10213 This function writes the contents of each object to the file descriptor and returns
10214 the total number of bytes written.
10215 
10216 The flags argument contains a bitwise OR of zero or more of the following flags:
10217 
10218 - RWF_DSYNC
10219 - RWF_SYNC
10220 
10221 Using non-zero flags requires Linux 4.7 or newer.
10222 [clinic start generated code]*/
10223 
10224 static Py_ssize_t
os_pwritev_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)10225 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
10226                 int flags)
10227 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=803dc5ddbf0cfd3b]*/
10228 {
10229     Py_ssize_t cnt;
10230     Py_ssize_t result;
10231     int async_err = 0;
10232     struct iovec *iov;
10233     Py_buffer *buf;
10234 
10235     if (!PySequence_Check(buffers)) {
10236         PyErr_SetString(PyExc_TypeError,
10237             "pwritev() arg 2 must be a sequence");
10238         return -1;
10239     }
10240 
10241     cnt = PySequence_Size(buffers);
10242     if (cnt < 0) {
10243         return -1;
10244     }
10245 
10246 #ifndef HAVE_PWRITEV2
10247     if(flags != 0) {
10248         argument_unavailable_error("pwritev2", "flags");
10249         return -1;
10250     }
10251 #endif
10252 
10253     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10254         return -1;
10255     }
10256 #ifdef HAVE_PWRITEV2
10257     do {
10258         Py_BEGIN_ALLOW_THREADS
10259         _Py_BEGIN_SUPPRESS_IPH
10260         result = pwritev2(fd, iov, cnt, offset, flags);
10261         _Py_END_SUPPRESS_IPH
10262         Py_END_ALLOW_THREADS
10263     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10264 #else
10265 
10266 #ifdef __APPLE__
10267 /* This entire function will be removed from the module dict when the API
10268  * is not available.
10269  */
10270 #pragma clang diagnostic push
10271 #pragma clang diagnostic ignored "-Wunguarded-availability"
10272 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
10273 #endif
10274     do {
10275         Py_BEGIN_ALLOW_THREADS
10276         _Py_BEGIN_SUPPRESS_IPH
10277         result = pwritev(fd, iov, cnt, offset);
10278         _Py_END_SUPPRESS_IPH
10279         Py_END_ALLOW_THREADS
10280     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10281 
10282 #ifdef __APPLE__
10283 #pragma clang diagnostic pop
10284 #endif
10285 
10286 #endif
10287 
10288     iov_cleanup(iov, buf, cnt);
10289     if (result < 0) {
10290         if (!async_err) {
10291             posix_error();
10292         }
10293         return -1;
10294     }
10295 
10296     return result;
10297 }
10298 #endif /* HAVE_PWRITEV */
10299 
10300 #ifdef HAVE_COPY_FILE_RANGE
10301 /*[clinic input]
10302 
10303 os.copy_file_range
10304     src: int
10305         Source file descriptor.
10306     dst: int
10307         Destination file descriptor.
10308     count: Py_ssize_t
10309         Number of bytes to copy.
10310     offset_src: object = None
10311         Starting offset in src.
10312     offset_dst: object = None
10313         Starting offset in dst.
10314 
10315 Copy count bytes from one file descriptor to another.
10316 
10317 If offset_src is None, then src is read from the current position;
10318 respectively for offset_dst.
10319 [clinic start generated code]*/
10320 
10321 static PyObject *
os_copy_file_range_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst)10322 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10323                         PyObject *offset_src, PyObject *offset_dst)
10324 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
10325 {
10326     off_t offset_src_val, offset_dst_val;
10327     off_t *p_offset_src = NULL;
10328     off_t *p_offset_dst = NULL;
10329     Py_ssize_t ret;
10330     int async_err = 0;
10331     /* The flags argument is provided to allow
10332      * for future extensions and currently must be to 0. */
10333     int flags = 0;
10334 
10335 
10336     if (count < 0) {
10337         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10338         return NULL;
10339     }
10340 
10341     if (offset_src != Py_None) {
10342         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10343             return NULL;
10344         }
10345         p_offset_src = &offset_src_val;
10346     }
10347 
10348     if (offset_dst != Py_None) {
10349         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10350             return NULL;
10351         }
10352         p_offset_dst = &offset_dst_val;
10353     }
10354 
10355     do {
10356         Py_BEGIN_ALLOW_THREADS
10357         ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
10358         Py_END_ALLOW_THREADS
10359     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10360 
10361     if (ret < 0) {
10362         return (!async_err) ? posix_error() : NULL;
10363     }
10364 
10365     return PyLong_FromSsize_t(ret);
10366 }
10367 #endif /* HAVE_COPY_FILE_RANGE*/
10368 
10369 #ifdef HAVE_MKFIFO
10370 /*[clinic input]
10371 os.mkfifo
10372 
10373     path: path_t
10374     mode: int=0o666
10375     *
10376     dir_fd: dir_fd(requires='mkfifoat')=None
10377 
10378 Create a "fifo" (a POSIX named pipe).
10379 
10380 If dir_fd is not None, it should be a file descriptor open to a directory,
10381   and path should be relative; path will then be relative to that directory.
10382 dir_fd may not be implemented on your platform.
10383   If it is unavailable, using it will raise a NotImplementedError.
10384 [clinic start generated code]*/
10385 
10386 static PyObject *
os_mkfifo_impl(PyObject * module,path_t * path,int mode,int dir_fd)10387 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
10388 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
10389 {
10390     int result;
10391     int async_err = 0;
10392 
10393     do {
10394         Py_BEGIN_ALLOW_THREADS
10395 #ifdef HAVE_MKFIFOAT
10396         if (dir_fd != DEFAULT_DIR_FD)
10397             result = mkfifoat(dir_fd, path->narrow, mode);
10398         else
10399 #endif
10400             result = mkfifo(path->narrow, mode);
10401         Py_END_ALLOW_THREADS
10402     } while (result != 0 && errno == EINTR &&
10403              !(async_err = PyErr_CheckSignals()));
10404     if (result != 0)
10405         return (!async_err) ? posix_error() : NULL;
10406 
10407     Py_RETURN_NONE;
10408 }
10409 #endif /* HAVE_MKFIFO */
10410 
10411 
10412 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
10413 /*[clinic input]
10414 os.mknod
10415 
10416     path: path_t
10417     mode: int=0o600
10418     device: dev_t=0
10419     *
10420     dir_fd: dir_fd(requires='mknodat')=None
10421 
10422 Create a node in the file system.
10423 
10424 Create a node in the file system (file, device special file or named pipe)
10425 at path.  mode specifies both the permissions to use and the
10426 type of node to be created, being combined (bitwise OR) with one of
10427 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
10428 device defines the newly created device special file (probably using
10429 os.makedev()).  Otherwise device is ignored.
10430 
10431 If dir_fd is not None, it should be a file descriptor open to a directory,
10432   and path should be relative; path will then be relative to that directory.
10433 dir_fd may not be implemented on your platform.
10434   If it is unavailable, using it will raise a NotImplementedError.
10435 [clinic start generated code]*/
10436 
10437 static PyObject *
os_mknod_impl(PyObject * module,path_t * path,int mode,dev_t device,int dir_fd)10438 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
10439               int dir_fd)
10440 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
10441 {
10442     int result;
10443     int async_err = 0;
10444 
10445     do {
10446         Py_BEGIN_ALLOW_THREADS
10447 #ifdef HAVE_MKNODAT
10448         if (dir_fd != DEFAULT_DIR_FD)
10449             result = mknodat(dir_fd, path->narrow, mode, device);
10450         else
10451 #endif
10452             result = mknod(path->narrow, mode, device);
10453         Py_END_ALLOW_THREADS
10454     } while (result != 0 && errno == EINTR &&
10455              !(async_err = PyErr_CheckSignals()));
10456     if (result != 0)
10457         return (!async_err) ? posix_error() : NULL;
10458 
10459     Py_RETURN_NONE;
10460 }
10461 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
10462 
10463 
10464 #ifdef HAVE_DEVICE_MACROS
10465 /*[clinic input]
10466 os.major -> unsigned_int
10467 
10468     device: dev_t
10469     /
10470 
10471 Extracts a device major number from a raw device number.
10472 [clinic start generated code]*/
10473 
10474 static unsigned int
os_major_impl(PyObject * module,dev_t device)10475 os_major_impl(PyObject *module, dev_t device)
10476 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
10477 {
10478     return major(device);
10479 }
10480 
10481 
10482 /*[clinic input]
10483 os.minor -> unsigned_int
10484 
10485     device: dev_t
10486     /
10487 
10488 Extracts a device minor number from a raw device number.
10489 [clinic start generated code]*/
10490 
10491 static unsigned int
os_minor_impl(PyObject * module,dev_t device)10492 os_minor_impl(PyObject *module, dev_t device)
10493 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10494 {
10495     return minor(device);
10496 }
10497 
10498 
10499 /*[clinic input]
10500 os.makedev -> dev_t
10501 
10502     major: int
10503     minor: int
10504     /
10505 
10506 Composes a raw device number from the major and minor device numbers.
10507 [clinic start generated code]*/
10508 
10509 static dev_t
os_makedev_impl(PyObject * module,int major,int minor)10510 os_makedev_impl(PyObject *module, int major, int minor)
10511 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10512 {
10513     return makedev(major, minor);
10514 }
10515 #endif /* HAVE_DEVICE_MACROS */
10516 
10517 
10518 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10519 /*[clinic input]
10520 os.ftruncate
10521 
10522     fd: int
10523     length: Py_off_t
10524     /
10525 
10526 Truncate a file, specified by file descriptor, to a specific length.
10527 [clinic start generated code]*/
10528 
10529 static PyObject *
os_ftruncate_impl(PyObject * module,int fd,Py_off_t length)10530 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10531 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10532 {
10533     int result;
10534     int async_err = 0;
10535 
10536     if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10537         return NULL;
10538     }
10539 
10540     do {
10541         Py_BEGIN_ALLOW_THREADS
10542         _Py_BEGIN_SUPPRESS_IPH
10543 #ifdef MS_WINDOWS
10544         result = _chsize_s(fd, length);
10545 #else
10546         result = ftruncate(fd, length);
10547 #endif
10548         _Py_END_SUPPRESS_IPH
10549         Py_END_ALLOW_THREADS
10550     } while (result != 0 && errno == EINTR &&
10551              !(async_err = PyErr_CheckSignals()));
10552     if (result != 0)
10553         return (!async_err) ? posix_error() : NULL;
10554     Py_RETURN_NONE;
10555 }
10556 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10557 
10558 
10559 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10560 /*[clinic input]
10561 os.truncate
10562     path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10563     length: Py_off_t
10564 
10565 Truncate a file, specified by path, to a specific length.
10566 
10567 On some platforms, path may also be specified as an open file descriptor.
10568   If this functionality is unavailable, using it raises an exception.
10569 [clinic start generated code]*/
10570 
10571 static PyObject *
os_truncate_impl(PyObject * module,path_t * path,Py_off_t length)10572 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10573 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10574 {
10575     int result;
10576 #ifdef MS_WINDOWS
10577     int fd;
10578 #endif
10579 
10580     if (path->fd != -1)
10581         return os_ftruncate_impl(module, path->fd, length);
10582 
10583     if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10584         return NULL;
10585     }
10586 
10587     Py_BEGIN_ALLOW_THREADS
10588     _Py_BEGIN_SUPPRESS_IPH
10589 #ifdef MS_WINDOWS
10590     fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10591     if (fd < 0)
10592         result = -1;
10593     else {
10594         result = _chsize_s(fd, length);
10595         close(fd);
10596         if (result < 0)
10597             errno = result;
10598     }
10599 #else
10600     result = truncate(path->narrow, length);
10601 #endif
10602     _Py_END_SUPPRESS_IPH
10603     Py_END_ALLOW_THREADS
10604     if (result < 0)
10605         return posix_path_error(path);
10606 
10607     Py_RETURN_NONE;
10608 }
10609 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10610 
10611 
10612 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10613    and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10614    defined, which is the case in Python on AIX. AIX bug report:
10615    http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10616 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10617 #  define POSIX_FADVISE_AIX_BUG
10618 #endif
10619 
10620 
10621 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10622 /*[clinic input]
10623 os.posix_fallocate
10624 
10625     fd: int
10626     offset: Py_off_t
10627     length: Py_off_t
10628     /
10629 
10630 Ensure a file has allocated at least a particular number of bytes on disk.
10631 
10632 Ensure that the file specified by fd encompasses a range of bytes
10633 starting at offset bytes from the beginning and continuing for length bytes.
10634 [clinic start generated code]*/
10635 
10636 static PyObject *
os_posix_fallocate_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length)10637 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10638                         Py_off_t length)
10639 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10640 {
10641     int result;
10642     int async_err = 0;
10643 
10644     do {
10645         Py_BEGIN_ALLOW_THREADS
10646         result = posix_fallocate(fd, offset, length);
10647         Py_END_ALLOW_THREADS
10648     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10649 
10650     if (result == 0)
10651         Py_RETURN_NONE;
10652 
10653     if (async_err)
10654         return NULL;
10655 
10656     errno = result;
10657     return posix_error();
10658 }
10659 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
10660 
10661 
10662 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
10663 /*[clinic input]
10664 os.posix_fadvise
10665 
10666     fd: int
10667     offset: Py_off_t
10668     length: Py_off_t
10669     advice: int
10670     /
10671 
10672 Announce an intention to access data in a specific pattern.
10673 
10674 Announce an intention to access data in a specific pattern, thus allowing
10675 the kernel to make optimizations.
10676 The advice applies to the region of the file specified by fd starting at
10677 offset and continuing for length bytes.
10678 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
10679 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
10680 POSIX_FADV_DONTNEED.
10681 [clinic start generated code]*/
10682 
10683 static PyObject *
os_posix_fadvise_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length,int advice)10684 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
10685                       Py_off_t length, int advice)
10686 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
10687 {
10688     int result;
10689     int async_err = 0;
10690 
10691     do {
10692         Py_BEGIN_ALLOW_THREADS
10693         result = posix_fadvise(fd, offset, length, advice);
10694         Py_END_ALLOW_THREADS
10695     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10696 
10697     if (result == 0)
10698         Py_RETURN_NONE;
10699 
10700     if (async_err)
10701         return NULL;
10702 
10703     errno = result;
10704     return posix_error();
10705 }
10706 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
10707 
10708 
10709 #ifdef MS_WINDOWS
10710 static PyObject*
win32_putenv(PyObject * name,PyObject * value)10711 win32_putenv(PyObject *name, PyObject *value)
10712 {
10713     /* Search from index 1 because on Windows starting '=' is allowed for
10714        defining hidden environment variables. */
10715     if (PyUnicode_GET_LENGTH(name) == 0 ||
10716         PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
10717     {
10718         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10719         return NULL;
10720     }
10721     PyObject *unicode;
10722     if (value != NULL) {
10723         unicode = PyUnicode_FromFormat("%U=%U", name, value);
10724     }
10725     else {
10726         unicode = PyUnicode_FromFormat("%U=", name);
10727     }
10728     if (unicode == NULL) {
10729         return NULL;
10730     }
10731 
10732     Py_ssize_t size;
10733     /* PyUnicode_AsWideCharString() rejects embedded null characters */
10734     wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
10735     Py_DECREF(unicode);
10736 
10737     if (env == NULL) {
10738         return NULL;
10739     }
10740     if (size > _MAX_ENV) {
10741         PyErr_Format(PyExc_ValueError,
10742                      "the environment variable is longer than %u characters",
10743                      _MAX_ENV);
10744         PyMem_Free(env);
10745         return NULL;
10746     }
10747 
10748     /* _wputenv() and SetEnvironmentVariableW() update the environment in the
10749        Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
10750        and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
10751 
10752        Prefer _wputenv() to be compatible with C libraries using CRT
10753        variables and CRT functions using these variables (ex: getenv()). */
10754     int err = _wputenv(env);
10755     PyMem_Free(env);
10756 
10757     if (err) {
10758         posix_error();
10759         return NULL;
10760     }
10761 
10762     Py_RETURN_NONE;
10763 }
10764 #endif
10765 
10766 
10767 #ifdef MS_WINDOWS
10768 /*[clinic input]
10769 os.putenv
10770 
10771     name: unicode
10772     value: unicode
10773     /
10774 
10775 Change or add an environment variable.
10776 [clinic start generated code]*/
10777 
10778 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10779 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10780 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
10781 {
10782     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10783         return NULL;
10784     }
10785     return win32_putenv(name, value);
10786 }
10787 #else
10788 /*[clinic input]
10789 os.putenv
10790 
10791     name: FSConverter
10792     value: FSConverter
10793     /
10794 
10795 Change or add an environment variable.
10796 [clinic start generated code]*/
10797 
10798 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10799 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10800 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
10801 {
10802     const char *name_string = PyBytes_AS_STRING(name);
10803     const char *value_string = PyBytes_AS_STRING(value);
10804 
10805     if (strchr(name_string, '=') != NULL) {
10806         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10807         return NULL;
10808     }
10809 
10810     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10811         return NULL;
10812     }
10813 
10814     if (setenv(name_string, value_string, 1)) {
10815         return posix_error();
10816     }
10817     Py_RETURN_NONE;
10818 }
10819 #endif  /* !defined(MS_WINDOWS) */
10820 
10821 
10822 #ifdef MS_WINDOWS
10823 /*[clinic input]
10824 os.unsetenv
10825     name: unicode
10826     /
10827 
10828 Delete an environment variable.
10829 [clinic start generated code]*/
10830 
10831 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)10832 os_unsetenv_impl(PyObject *module, PyObject *name)
10833 /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
10834 {
10835     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
10836         return NULL;
10837     }
10838     return win32_putenv(name, NULL);
10839 }
10840 #else
10841 /*[clinic input]
10842 os.unsetenv
10843     name: FSConverter
10844     /
10845 
10846 Delete an environment variable.
10847 [clinic start generated code]*/
10848 
10849 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)10850 os_unsetenv_impl(PyObject *module, PyObject *name)
10851 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
10852 {
10853     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
10854         return NULL;
10855     }
10856 #ifdef HAVE_BROKEN_UNSETENV
10857     unsetenv(PyBytes_AS_STRING(name));
10858 #else
10859     int err = unsetenv(PyBytes_AS_STRING(name));
10860     if (err) {
10861         return posix_error();
10862     }
10863 #endif
10864 
10865     Py_RETURN_NONE;
10866 }
10867 #endif /* !MS_WINDOWS */
10868 
10869 
10870 /*[clinic input]
10871 os.strerror
10872 
10873     code: int
10874     /
10875 
10876 Translate an error code to a message string.
10877 [clinic start generated code]*/
10878 
10879 static PyObject *
os_strerror_impl(PyObject * module,int code)10880 os_strerror_impl(PyObject *module, int code)
10881 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
10882 {
10883     char *message = strerror(code);
10884     if (message == NULL) {
10885         PyErr_SetString(PyExc_ValueError,
10886                         "strerror() argument out of range");
10887         return NULL;
10888     }
10889     return PyUnicode_DecodeLocale(message, "surrogateescape");
10890 }
10891 
10892 
10893 #ifdef HAVE_SYS_WAIT_H
10894 #ifdef WCOREDUMP
10895 /*[clinic input]
10896 os.WCOREDUMP -> bool
10897 
10898     status: int
10899     /
10900 
10901 Return True if the process returning status was dumped to a core file.
10902 [clinic start generated code]*/
10903 
10904 static int
os_WCOREDUMP_impl(PyObject * module,int status)10905 os_WCOREDUMP_impl(PyObject *module, int status)
10906 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
10907 {
10908     WAIT_TYPE wait_status;
10909     WAIT_STATUS_INT(wait_status) = status;
10910     return WCOREDUMP(wait_status);
10911 }
10912 #endif /* WCOREDUMP */
10913 
10914 
10915 #ifdef WIFCONTINUED
10916 /*[clinic input]
10917 os.WIFCONTINUED -> bool
10918 
10919     status: int
10920 
10921 Return True if a particular process was continued from a job control stop.
10922 
10923 Return True if the process returning status was continued from a
10924 job control stop.
10925 [clinic start generated code]*/
10926 
10927 static int
os_WIFCONTINUED_impl(PyObject * module,int status)10928 os_WIFCONTINUED_impl(PyObject *module, int status)
10929 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
10930 {
10931     WAIT_TYPE wait_status;
10932     WAIT_STATUS_INT(wait_status) = status;
10933     return WIFCONTINUED(wait_status);
10934 }
10935 #endif /* WIFCONTINUED */
10936 
10937 
10938 #ifdef WIFSTOPPED
10939 /*[clinic input]
10940 os.WIFSTOPPED -> bool
10941 
10942     status: int
10943 
10944 Return True if the process returning status was stopped.
10945 [clinic start generated code]*/
10946 
10947 static int
os_WIFSTOPPED_impl(PyObject * module,int status)10948 os_WIFSTOPPED_impl(PyObject *module, int status)
10949 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
10950 {
10951     WAIT_TYPE wait_status;
10952     WAIT_STATUS_INT(wait_status) = status;
10953     return WIFSTOPPED(wait_status);
10954 }
10955 #endif /* WIFSTOPPED */
10956 
10957 
10958 #ifdef WIFSIGNALED
10959 /*[clinic input]
10960 os.WIFSIGNALED -> bool
10961 
10962     status: int
10963 
10964 Return True if the process returning status was terminated by a signal.
10965 [clinic start generated code]*/
10966 
10967 static int
os_WIFSIGNALED_impl(PyObject * module,int status)10968 os_WIFSIGNALED_impl(PyObject *module, int status)
10969 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
10970 {
10971     WAIT_TYPE wait_status;
10972     WAIT_STATUS_INT(wait_status) = status;
10973     return WIFSIGNALED(wait_status);
10974 }
10975 #endif /* WIFSIGNALED */
10976 
10977 
10978 #ifdef WIFEXITED
10979 /*[clinic input]
10980 os.WIFEXITED -> bool
10981 
10982     status: int
10983 
10984 Return True if the process returning status exited via the exit() system call.
10985 [clinic start generated code]*/
10986 
10987 static int
os_WIFEXITED_impl(PyObject * module,int status)10988 os_WIFEXITED_impl(PyObject *module, int status)
10989 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
10990 {
10991     WAIT_TYPE wait_status;
10992     WAIT_STATUS_INT(wait_status) = status;
10993     return WIFEXITED(wait_status);
10994 }
10995 #endif /* WIFEXITED */
10996 
10997 
10998 #ifdef WEXITSTATUS
10999 /*[clinic input]
11000 os.WEXITSTATUS -> int
11001 
11002     status: int
11003 
11004 Return the process return code from status.
11005 [clinic start generated code]*/
11006 
11007 static int
os_WEXITSTATUS_impl(PyObject * module,int status)11008 os_WEXITSTATUS_impl(PyObject *module, int status)
11009 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
11010 {
11011     WAIT_TYPE wait_status;
11012     WAIT_STATUS_INT(wait_status) = status;
11013     return WEXITSTATUS(wait_status);
11014 }
11015 #endif /* WEXITSTATUS */
11016 
11017 
11018 #ifdef WTERMSIG
11019 /*[clinic input]
11020 os.WTERMSIG -> int
11021 
11022     status: int
11023 
11024 Return the signal that terminated the process that provided the status value.
11025 [clinic start generated code]*/
11026 
11027 static int
os_WTERMSIG_impl(PyObject * module,int status)11028 os_WTERMSIG_impl(PyObject *module, int status)
11029 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
11030 {
11031     WAIT_TYPE wait_status;
11032     WAIT_STATUS_INT(wait_status) = status;
11033     return WTERMSIG(wait_status);
11034 }
11035 #endif /* WTERMSIG */
11036 
11037 
11038 #ifdef WSTOPSIG
11039 /*[clinic input]
11040 os.WSTOPSIG -> int
11041 
11042     status: int
11043 
11044 Return the signal that stopped the process that provided the status value.
11045 [clinic start generated code]*/
11046 
11047 static int
os_WSTOPSIG_impl(PyObject * module,int status)11048 os_WSTOPSIG_impl(PyObject *module, int status)
11049 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
11050 {
11051     WAIT_TYPE wait_status;
11052     WAIT_STATUS_INT(wait_status) = status;
11053     return WSTOPSIG(wait_status);
11054 }
11055 #endif /* WSTOPSIG */
11056 #endif /* HAVE_SYS_WAIT_H */
11057 
11058 
11059 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
11060 #ifdef _SCO_DS
11061 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
11062    needed definitions in sys/statvfs.h */
11063 #define _SVID3
11064 #endif
11065 #include <sys/statvfs.h>
11066 
11067 static PyObject*
_pystatvfs_fromstructstatvfs(PyObject * module,struct statvfs st)11068 _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
11069     PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
11070     PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
11071     if (v == NULL)
11072         return NULL;
11073 
11074 #if !defined(HAVE_LARGEFILE_SUPPORT)
11075     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11076     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11077     PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
11078     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
11079     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
11080     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
11081     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
11082     PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
11083     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11084     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11085 #else
11086     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11087     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11088     PyStructSequence_SET_ITEM(v, 2,
11089                               PyLong_FromLongLong((long long) st.f_blocks));
11090     PyStructSequence_SET_ITEM(v, 3,
11091                               PyLong_FromLongLong((long long) st.f_bfree));
11092     PyStructSequence_SET_ITEM(v, 4,
11093                               PyLong_FromLongLong((long long) st.f_bavail));
11094     PyStructSequence_SET_ITEM(v, 5,
11095                               PyLong_FromLongLong((long long) st.f_files));
11096     PyStructSequence_SET_ITEM(v, 6,
11097                               PyLong_FromLongLong((long long) st.f_ffree));
11098     PyStructSequence_SET_ITEM(v, 7,
11099                               PyLong_FromLongLong((long long) st.f_favail));
11100     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11101     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11102 #endif
11103 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
11104  * (issue #32390). */
11105 #if defined(_AIX) && defined(_ALL_SOURCE)
11106     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
11107 #else
11108     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
11109 #endif
11110     if (PyErr_Occurred()) {
11111         Py_DECREF(v);
11112         return NULL;
11113     }
11114 
11115     return v;
11116 }
11117 
11118 
11119 /*[clinic input]
11120 os.fstatvfs
11121     fd: int
11122     /
11123 
11124 Perform an fstatvfs system call on the given fd.
11125 
11126 Equivalent to statvfs(fd).
11127 [clinic start generated code]*/
11128 
11129 static PyObject *
os_fstatvfs_impl(PyObject * module,int fd)11130 os_fstatvfs_impl(PyObject *module, int fd)
11131 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
11132 {
11133     int result;
11134     int async_err = 0;
11135     struct statvfs st;
11136 
11137     do {
11138         Py_BEGIN_ALLOW_THREADS
11139         result = fstatvfs(fd, &st);
11140         Py_END_ALLOW_THREADS
11141     } while (result != 0 && errno == EINTR &&
11142              !(async_err = PyErr_CheckSignals()));
11143     if (result != 0)
11144         return (!async_err) ? posix_error() : NULL;
11145 
11146     return _pystatvfs_fromstructstatvfs(module, st);
11147 }
11148 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
11149 
11150 
11151 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
11152 #include <sys/statvfs.h>
11153 /*[clinic input]
11154 os.statvfs
11155 
11156     path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
11157 
11158 Perform a statvfs system call on the given path.
11159 
11160 path may always be specified as a string.
11161 On some platforms, path may also be specified as an open file descriptor.
11162   If this functionality is unavailable, using it raises an exception.
11163 [clinic start generated code]*/
11164 
11165 static PyObject *
os_statvfs_impl(PyObject * module,path_t * path)11166 os_statvfs_impl(PyObject *module, path_t *path)
11167 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
11168 {
11169     int result;
11170     struct statvfs st;
11171 
11172     Py_BEGIN_ALLOW_THREADS
11173 #ifdef HAVE_FSTATVFS
11174     if (path->fd != -1) {
11175         result = fstatvfs(path->fd, &st);
11176     }
11177     else
11178 #endif
11179         result = statvfs(path->narrow, &st);
11180     Py_END_ALLOW_THREADS
11181 
11182     if (result) {
11183         return path_error(path);
11184     }
11185 
11186     return _pystatvfs_fromstructstatvfs(module, st);
11187 }
11188 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
11189 
11190 
11191 #ifdef MS_WINDOWS
11192 /*[clinic input]
11193 os._getdiskusage
11194 
11195     path: path_t
11196 
11197 Return disk usage statistics about the given path as a (total, free) tuple.
11198 [clinic start generated code]*/
11199 
11200 static PyObject *
os__getdiskusage_impl(PyObject * module,path_t * path)11201 os__getdiskusage_impl(PyObject *module, path_t *path)
11202 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
11203 {
11204     BOOL retval;
11205     ULARGE_INTEGER _, total, free;
11206     DWORD err = 0;
11207 
11208     Py_BEGIN_ALLOW_THREADS
11209     retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
11210     Py_END_ALLOW_THREADS
11211     if (retval == 0) {
11212         if (GetLastError() == ERROR_DIRECTORY) {
11213             wchar_t *dir_path = NULL;
11214 
11215             dir_path = PyMem_New(wchar_t, path->length + 1);
11216             if (dir_path == NULL) {
11217                 return PyErr_NoMemory();
11218             }
11219 
11220             wcscpy_s(dir_path, path->length + 1, path->wide);
11221 
11222             if (_dirnameW(dir_path) != -1) {
11223                 Py_BEGIN_ALLOW_THREADS
11224                 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
11225                 Py_END_ALLOW_THREADS
11226             }
11227             /* Record the last error in case it's modified by PyMem_Free. */
11228             err = GetLastError();
11229             PyMem_Free(dir_path);
11230             if (retval) {
11231                 goto success;
11232             }
11233         }
11234         return PyErr_SetFromWindowsErr(err);
11235     }
11236 
11237 success:
11238     return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
11239 }
11240 #endif /* MS_WINDOWS */
11241 
11242 
11243 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
11244  * It maps strings representing configuration variable names to
11245  * integer values, allowing those functions to be called with the
11246  * magic names instead of polluting the module's namespace with tons of
11247  * rarely-used constants.  There are three separate tables that use
11248  * these definitions.
11249  *
11250  * This code is always included, even if none of the interfaces that
11251  * need it are included.  The #if hackery needed to avoid it would be
11252  * sufficiently pervasive that it's not worth the loss of readability.
11253  */
11254 struct constdef {
11255     const char *name;
11256     int value;
11257 };
11258 
11259 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)11260 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
11261               size_t tablesize)
11262 {
11263     if (PyLong_Check(arg)) {
11264         int value = _PyLong_AsInt(arg);
11265         if (value == -1 && PyErr_Occurred())
11266             return 0;
11267         *valuep = value;
11268         return 1;
11269     }
11270     else {
11271         /* look up the value in the table using a binary search */
11272         size_t lo = 0;
11273         size_t mid;
11274         size_t hi = tablesize;
11275         int cmp;
11276         const char *confname;
11277         if (!PyUnicode_Check(arg)) {
11278             PyErr_SetString(PyExc_TypeError,
11279                 "configuration names must be strings or integers");
11280             return 0;
11281         }
11282         confname = PyUnicode_AsUTF8(arg);
11283         if (confname == NULL)
11284             return 0;
11285         while (lo < hi) {
11286             mid = (lo + hi) / 2;
11287             cmp = strcmp(confname, table[mid].name);
11288             if (cmp < 0)
11289                 hi = mid;
11290             else if (cmp > 0)
11291                 lo = mid + 1;
11292             else {
11293                 *valuep = table[mid].value;
11294                 return 1;
11295             }
11296         }
11297         PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
11298         return 0;
11299     }
11300 }
11301 
11302 
11303 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11304 static struct constdef  posix_constants_pathconf[] = {
11305 #ifdef _PC_ABI_AIO_XFER_MAX
11306     {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
11307 #endif
11308 #ifdef _PC_ABI_ASYNC_IO
11309     {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
11310 #endif
11311 #ifdef _PC_ASYNC_IO
11312     {"PC_ASYNC_IO",     _PC_ASYNC_IO},
11313 #endif
11314 #ifdef _PC_CHOWN_RESTRICTED
11315     {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
11316 #endif
11317 #ifdef _PC_FILESIZEBITS
11318     {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
11319 #endif
11320 #ifdef _PC_LAST
11321     {"PC_LAST", _PC_LAST},
11322 #endif
11323 #ifdef _PC_LINK_MAX
11324     {"PC_LINK_MAX",     _PC_LINK_MAX},
11325 #endif
11326 #ifdef _PC_MAX_CANON
11327     {"PC_MAX_CANON",    _PC_MAX_CANON},
11328 #endif
11329 #ifdef _PC_MAX_INPUT
11330     {"PC_MAX_INPUT",    _PC_MAX_INPUT},
11331 #endif
11332 #ifdef _PC_NAME_MAX
11333     {"PC_NAME_MAX",     _PC_NAME_MAX},
11334 #endif
11335 #ifdef _PC_NO_TRUNC
11336     {"PC_NO_TRUNC",     _PC_NO_TRUNC},
11337 #endif
11338 #ifdef _PC_PATH_MAX
11339     {"PC_PATH_MAX",     _PC_PATH_MAX},
11340 #endif
11341 #ifdef _PC_PIPE_BUF
11342     {"PC_PIPE_BUF",     _PC_PIPE_BUF},
11343 #endif
11344 #ifdef _PC_PRIO_IO
11345     {"PC_PRIO_IO",      _PC_PRIO_IO},
11346 #endif
11347 #ifdef _PC_SOCK_MAXBUF
11348     {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
11349 #endif
11350 #ifdef _PC_SYNC_IO
11351     {"PC_SYNC_IO",      _PC_SYNC_IO},
11352 #endif
11353 #ifdef _PC_VDISABLE
11354     {"PC_VDISABLE",     _PC_VDISABLE},
11355 #endif
11356 #ifdef _PC_ACL_ENABLED
11357     {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
11358 #endif
11359 #ifdef _PC_MIN_HOLE_SIZE
11360     {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
11361 #endif
11362 #ifdef _PC_ALLOC_SIZE_MIN
11363     {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
11364 #endif
11365 #ifdef _PC_REC_INCR_XFER_SIZE
11366     {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
11367 #endif
11368 #ifdef _PC_REC_MAX_XFER_SIZE
11369     {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
11370 #endif
11371 #ifdef _PC_REC_MIN_XFER_SIZE
11372     {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
11373 #endif
11374 #ifdef _PC_REC_XFER_ALIGN
11375     {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
11376 #endif
11377 #ifdef _PC_SYMLINK_MAX
11378     {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
11379 #endif
11380 #ifdef _PC_XATTR_ENABLED
11381     {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
11382 #endif
11383 #ifdef _PC_XATTR_EXISTS
11384     {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
11385 #endif
11386 #ifdef _PC_TIMESTAMP_RESOLUTION
11387     {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
11388 #endif
11389 };
11390 
11391 static int
conv_path_confname(PyObject * arg,int * valuep)11392 conv_path_confname(PyObject *arg, int *valuep)
11393 {
11394     return conv_confname(arg, valuep, posix_constants_pathconf,
11395                          sizeof(posix_constants_pathconf)
11396                            / sizeof(struct constdef));
11397 }
11398 #endif
11399 
11400 
11401 #ifdef HAVE_FPATHCONF
11402 /*[clinic input]
11403 os.fpathconf -> long
11404 
11405     fd: int
11406     name: path_confname
11407     /
11408 
11409 Return the configuration limit name for the file descriptor fd.
11410 
11411 If there is no limit, return -1.
11412 [clinic start generated code]*/
11413 
11414 static long
os_fpathconf_impl(PyObject * module,int fd,int name)11415 os_fpathconf_impl(PyObject *module, int fd, int name)
11416 /*[clinic end generated code: output=d5b7042425fc3e21 input=5942a024d3777810]*/
11417 {
11418     long limit;
11419 
11420     errno = 0;
11421     limit = fpathconf(fd, name);
11422     if (limit == -1 && errno != 0)
11423         posix_error();
11424 
11425     return limit;
11426 }
11427 #endif /* HAVE_FPATHCONF */
11428 
11429 
11430 #ifdef HAVE_PATHCONF
11431 /*[clinic input]
11432 os.pathconf -> long
11433     path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
11434     name: path_confname
11435 
11436 Return the configuration limit name for the file or directory path.
11437 
11438 If there is no limit, return -1.
11439 On some platforms, path may also be specified as an open file descriptor.
11440   If this functionality is unavailable, using it raises an exception.
11441 [clinic start generated code]*/
11442 
11443 static long
os_pathconf_impl(PyObject * module,path_t * path,int name)11444 os_pathconf_impl(PyObject *module, path_t *path, int name)
11445 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
11446 {
11447     long limit;
11448 
11449     errno = 0;
11450 #ifdef HAVE_FPATHCONF
11451     if (path->fd != -1)
11452         limit = fpathconf(path->fd, name);
11453     else
11454 #endif
11455         limit = pathconf(path->narrow, name);
11456     if (limit == -1 && errno != 0) {
11457         if (errno == EINVAL)
11458             /* could be a path or name problem */
11459             posix_error();
11460         else
11461             path_error(path);
11462     }
11463 
11464     return limit;
11465 }
11466 #endif /* HAVE_PATHCONF */
11467 
11468 #ifdef HAVE_CONFSTR
11469 static struct constdef posix_constants_confstr[] = {
11470 #ifdef _CS_ARCHITECTURE
11471     {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
11472 #endif
11473 #ifdef _CS_GNU_LIBC_VERSION
11474     {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
11475 #endif
11476 #ifdef _CS_GNU_LIBPTHREAD_VERSION
11477     {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
11478 #endif
11479 #ifdef _CS_HOSTNAME
11480     {"CS_HOSTNAME",     _CS_HOSTNAME},
11481 #endif
11482 #ifdef _CS_HW_PROVIDER
11483     {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
11484 #endif
11485 #ifdef _CS_HW_SERIAL
11486     {"CS_HW_SERIAL",    _CS_HW_SERIAL},
11487 #endif
11488 #ifdef _CS_INITTAB_NAME
11489     {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11490 #endif
11491 #ifdef _CS_LFS64_CFLAGS
11492     {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11493 #endif
11494 #ifdef _CS_LFS64_LDFLAGS
11495     {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
11496 #endif
11497 #ifdef _CS_LFS64_LIBS
11498     {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
11499 #endif
11500 #ifdef _CS_LFS64_LINTFLAGS
11501     {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
11502 #endif
11503 #ifdef _CS_LFS_CFLAGS
11504     {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
11505 #endif
11506 #ifdef _CS_LFS_LDFLAGS
11507     {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
11508 #endif
11509 #ifdef _CS_LFS_LIBS
11510     {"CS_LFS_LIBS",     _CS_LFS_LIBS},
11511 #endif
11512 #ifdef _CS_LFS_LINTFLAGS
11513     {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
11514 #endif
11515 #ifdef _CS_MACHINE
11516     {"CS_MACHINE",      _CS_MACHINE},
11517 #endif
11518 #ifdef _CS_PATH
11519     {"CS_PATH", _CS_PATH},
11520 #endif
11521 #ifdef _CS_RELEASE
11522     {"CS_RELEASE",      _CS_RELEASE},
11523 #endif
11524 #ifdef _CS_SRPC_DOMAIN
11525     {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
11526 #endif
11527 #ifdef _CS_SYSNAME
11528     {"CS_SYSNAME",      _CS_SYSNAME},
11529 #endif
11530 #ifdef _CS_VERSION
11531     {"CS_VERSION",      _CS_VERSION},
11532 #endif
11533 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11534     {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
11535 #endif
11536 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11537     {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
11538 #endif
11539 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11540     {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
11541 #endif
11542 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11543     {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11544 #endif
11545 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11546     {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11547 #endif
11548 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11549     {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11550 #endif
11551 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11552     {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
11553 #endif
11554 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11555     {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11556 #endif
11557 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11558     {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
11559 #endif
11560 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11561     {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
11562 #endif
11563 #ifdef _CS_XBS5_LP64_OFF64_LIBS
11564     {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11565 #endif
11566 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11567     {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
11568 #endif
11569 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11570     {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11571 #endif
11572 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11573     {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11574 #endif
11575 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11576     {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
11577 #endif
11578 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11579     {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11580 #endif
11581 #ifdef _MIPS_CS_AVAIL_PROCESSORS
11582     {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
11583 #endif
11584 #ifdef _MIPS_CS_BASE
11585     {"MIPS_CS_BASE",    _MIPS_CS_BASE},
11586 #endif
11587 #ifdef _MIPS_CS_HOSTID
11588     {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
11589 #endif
11590 #ifdef _MIPS_CS_HW_NAME
11591     {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11592 #endif
11593 #ifdef _MIPS_CS_NUM_PROCESSORS
11594     {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
11595 #endif
11596 #ifdef _MIPS_CS_OSREL_MAJ
11597     {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
11598 #endif
11599 #ifdef _MIPS_CS_OSREL_MIN
11600     {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
11601 #endif
11602 #ifdef _MIPS_CS_OSREL_PATCH
11603     {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
11604 #endif
11605 #ifdef _MIPS_CS_OS_NAME
11606     {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11607 #endif
11608 #ifdef _MIPS_CS_OS_PROVIDER
11609     {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
11610 #endif
11611 #ifdef _MIPS_CS_PROCESSORS
11612     {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
11613 #endif
11614 #ifdef _MIPS_CS_SERIAL
11615     {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
11616 #endif
11617 #ifdef _MIPS_CS_VENDOR
11618     {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
11619 #endif
11620 };
11621 
11622 static int
conv_confstr_confname(PyObject * arg,int * valuep)11623 conv_confstr_confname(PyObject *arg, int *valuep)
11624 {
11625     return conv_confname(arg, valuep, posix_constants_confstr,
11626                          sizeof(posix_constants_confstr)
11627                            / sizeof(struct constdef));
11628 }
11629 
11630 
11631 /*[clinic input]
11632 os.confstr
11633 
11634     name: confstr_confname
11635     /
11636 
11637 Return a string-valued system configuration variable.
11638 [clinic start generated code]*/
11639 
11640 static PyObject *
os_confstr_impl(PyObject * module,int name)11641 os_confstr_impl(PyObject *module, int name)
11642 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11643 {
11644     PyObject *result = NULL;
11645     char buffer[255];
11646     size_t len;
11647 
11648     errno = 0;
11649     len = confstr(name, buffer, sizeof(buffer));
11650     if (len == 0) {
11651         if (errno) {
11652             posix_error();
11653             return NULL;
11654         }
11655         else {
11656             Py_RETURN_NONE;
11657         }
11658     }
11659 
11660     if (len >= sizeof(buffer)) {
11661         size_t len2;
11662         char *buf = PyMem_Malloc(len);
11663         if (buf == NULL)
11664             return PyErr_NoMemory();
11665         len2 = confstr(name, buf, len);
11666         assert(len == len2);
11667         result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11668         PyMem_Free(buf);
11669     }
11670     else
11671         result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11672     return result;
11673 }
11674 #endif /* HAVE_CONFSTR */
11675 
11676 
11677 #ifdef HAVE_SYSCONF
11678 static struct constdef posix_constants_sysconf[] = {
11679 #ifdef _SC_2_CHAR_TERM
11680     {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
11681 #endif
11682 #ifdef _SC_2_C_BIND
11683     {"SC_2_C_BIND",     _SC_2_C_BIND},
11684 #endif
11685 #ifdef _SC_2_C_DEV
11686     {"SC_2_C_DEV",      _SC_2_C_DEV},
11687 #endif
11688 #ifdef _SC_2_C_VERSION
11689     {"SC_2_C_VERSION",  _SC_2_C_VERSION},
11690 #endif
11691 #ifdef _SC_2_FORT_DEV
11692     {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
11693 #endif
11694 #ifdef _SC_2_FORT_RUN
11695     {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
11696 #endif
11697 #ifdef _SC_2_LOCALEDEF
11698     {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
11699 #endif
11700 #ifdef _SC_2_SW_DEV
11701     {"SC_2_SW_DEV",     _SC_2_SW_DEV},
11702 #endif
11703 #ifdef _SC_2_UPE
11704     {"SC_2_UPE",        _SC_2_UPE},
11705 #endif
11706 #ifdef _SC_2_VERSION
11707     {"SC_2_VERSION",    _SC_2_VERSION},
11708 #endif
11709 #ifdef _SC_ABI_ASYNCHRONOUS_IO
11710     {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
11711 #endif
11712 #ifdef _SC_ACL
11713     {"SC_ACL",  _SC_ACL},
11714 #endif
11715 #ifdef _SC_AIO_LISTIO_MAX
11716     {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
11717 #endif
11718 #ifdef _SC_AIO_MAX
11719     {"SC_AIO_MAX",      _SC_AIO_MAX},
11720 #endif
11721 #ifdef _SC_AIO_PRIO_DELTA_MAX
11722     {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
11723 #endif
11724 #ifdef _SC_ARG_MAX
11725     {"SC_ARG_MAX",      _SC_ARG_MAX},
11726 #endif
11727 #ifdef _SC_ASYNCHRONOUS_IO
11728     {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
11729 #endif
11730 #ifdef _SC_ATEXIT_MAX
11731     {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
11732 #endif
11733 #ifdef _SC_AUDIT
11734     {"SC_AUDIT",        _SC_AUDIT},
11735 #endif
11736 #ifdef _SC_AVPHYS_PAGES
11737     {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
11738 #endif
11739 #ifdef _SC_BC_BASE_MAX
11740     {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
11741 #endif
11742 #ifdef _SC_BC_DIM_MAX
11743     {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
11744 #endif
11745 #ifdef _SC_BC_SCALE_MAX
11746     {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
11747 #endif
11748 #ifdef _SC_BC_STRING_MAX
11749     {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
11750 #endif
11751 #ifdef _SC_CAP
11752     {"SC_CAP",  _SC_CAP},
11753 #endif
11754 #ifdef _SC_CHARCLASS_NAME_MAX
11755     {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
11756 #endif
11757 #ifdef _SC_CHAR_BIT
11758     {"SC_CHAR_BIT",     _SC_CHAR_BIT},
11759 #endif
11760 #ifdef _SC_CHAR_MAX
11761     {"SC_CHAR_MAX",     _SC_CHAR_MAX},
11762 #endif
11763 #ifdef _SC_CHAR_MIN
11764     {"SC_CHAR_MIN",     _SC_CHAR_MIN},
11765 #endif
11766 #ifdef _SC_CHILD_MAX
11767     {"SC_CHILD_MAX",    _SC_CHILD_MAX},
11768 #endif
11769 #ifdef _SC_CLK_TCK
11770     {"SC_CLK_TCK",      _SC_CLK_TCK},
11771 #endif
11772 #ifdef _SC_COHER_BLKSZ
11773     {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
11774 #endif
11775 #ifdef _SC_COLL_WEIGHTS_MAX
11776     {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
11777 #endif
11778 #ifdef _SC_DCACHE_ASSOC
11779     {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
11780 #endif
11781 #ifdef _SC_DCACHE_BLKSZ
11782     {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
11783 #endif
11784 #ifdef _SC_DCACHE_LINESZ
11785     {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
11786 #endif
11787 #ifdef _SC_DCACHE_SZ
11788     {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
11789 #endif
11790 #ifdef _SC_DCACHE_TBLKSZ
11791     {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
11792 #endif
11793 #ifdef _SC_DELAYTIMER_MAX
11794     {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
11795 #endif
11796 #ifdef _SC_EQUIV_CLASS_MAX
11797     {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
11798 #endif
11799 #ifdef _SC_EXPR_NEST_MAX
11800     {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
11801 #endif
11802 #ifdef _SC_FSYNC
11803     {"SC_FSYNC",        _SC_FSYNC},
11804 #endif
11805 #ifdef _SC_GETGR_R_SIZE_MAX
11806     {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
11807 #endif
11808 #ifdef _SC_GETPW_R_SIZE_MAX
11809     {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
11810 #endif
11811 #ifdef _SC_ICACHE_ASSOC
11812     {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
11813 #endif
11814 #ifdef _SC_ICACHE_BLKSZ
11815     {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
11816 #endif
11817 #ifdef _SC_ICACHE_LINESZ
11818     {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
11819 #endif
11820 #ifdef _SC_ICACHE_SZ
11821     {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
11822 #endif
11823 #ifdef _SC_INF
11824     {"SC_INF",  _SC_INF},
11825 #endif
11826 #ifdef _SC_INT_MAX
11827     {"SC_INT_MAX",      _SC_INT_MAX},
11828 #endif
11829 #ifdef _SC_INT_MIN
11830     {"SC_INT_MIN",      _SC_INT_MIN},
11831 #endif
11832 #ifdef _SC_IOV_MAX
11833     {"SC_IOV_MAX",      _SC_IOV_MAX},
11834 #endif
11835 #ifdef _SC_IP_SECOPTS
11836     {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
11837 #endif
11838 #ifdef _SC_JOB_CONTROL
11839     {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
11840 #endif
11841 #ifdef _SC_KERN_POINTERS
11842     {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
11843 #endif
11844 #ifdef _SC_KERN_SIM
11845     {"SC_KERN_SIM",     _SC_KERN_SIM},
11846 #endif
11847 #ifdef _SC_LINE_MAX
11848     {"SC_LINE_MAX",     _SC_LINE_MAX},
11849 #endif
11850 #ifdef _SC_LOGIN_NAME_MAX
11851     {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
11852 #endif
11853 #ifdef _SC_LOGNAME_MAX
11854     {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
11855 #endif
11856 #ifdef _SC_LONG_BIT
11857     {"SC_LONG_BIT",     _SC_LONG_BIT},
11858 #endif
11859 #ifdef _SC_MAC
11860     {"SC_MAC",  _SC_MAC},
11861 #endif
11862 #ifdef _SC_MAPPED_FILES
11863     {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
11864 #endif
11865 #ifdef _SC_MAXPID
11866     {"SC_MAXPID",       _SC_MAXPID},
11867 #endif
11868 #ifdef _SC_MB_LEN_MAX
11869     {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
11870 #endif
11871 #ifdef _SC_MEMLOCK
11872     {"SC_MEMLOCK",      _SC_MEMLOCK},
11873 #endif
11874 #ifdef _SC_MEMLOCK_RANGE
11875     {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
11876 #endif
11877 #ifdef _SC_MEMORY_PROTECTION
11878     {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
11879 #endif
11880 #ifdef _SC_MESSAGE_PASSING
11881     {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
11882 #endif
11883 #ifdef _SC_MMAP_FIXED_ALIGNMENT
11884     {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
11885 #endif
11886 #ifdef _SC_MQ_OPEN_MAX
11887     {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
11888 #endif
11889 #ifdef _SC_MQ_PRIO_MAX
11890     {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
11891 #endif
11892 #ifdef _SC_NACLS_MAX
11893     {"SC_NACLS_MAX",    _SC_NACLS_MAX},
11894 #endif
11895 #ifdef _SC_NGROUPS_MAX
11896     {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
11897 #endif
11898 #ifdef _SC_NL_ARGMAX
11899     {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
11900 #endif
11901 #ifdef _SC_NL_LANGMAX
11902     {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
11903 #endif
11904 #ifdef _SC_NL_MSGMAX
11905     {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
11906 #endif
11907 #ifdef _SC_NL_NMAX
11908     {"SC_NL_NMAX",      _SC_NL_NMAX},
11909 #endif
11910 #ifdef _SC_NL_SETMAX
11911     {"SC_NL_SETMAX",    _SC_NL_SETMAX},
11912 #endif
11913 #ifdef _SC_NL_TEXTMAX
11914     {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
11915 #endif
11916 #ifdef _SC_NPROCESSORS_CONF
11917     {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
11918 #endif
11919 #ifdef _SC_NPROCESSORS_ONLN
11920     {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
11921 #endif
11922 #ifdef _SC_NPROC_CONF
11923     {"SC_NPROC_CONF",   _SC_NPROC_CONF},
11924 #endif
11925 #ifdef _SC_NPROC_ONLN
11926     {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
11927 #endif
11928 #ifdef _SC_NZERO
11929     {"SC_NZERO",        _SC_NZERO},
11930 #endif
11931 #ifdef _SC_OPEN_MAX
11932     {"SC_OPEN_MAX",     _SC_OPEN_MAX},
11933 #endif
11934 #ifdef _SC_PAGESIZE
11935     {"SC_PAGESIZE",     _SC_PAGESIZE},
11936 #endif
11937 #ifdef _SC_PAGE_SIZE
11938     {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
11939 #endif
11940 #ifdef _SC_AIX_REALMEM
11941     {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
11942 #endif
11943 #ifdef _SC_PASS_MAX
11944     {"SC_PASS_MAX",     _SC_PASS_MAX},
11945 #endif
11946 #ifdef _SC_PHYS_PAGES
11947     {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
11948 #endif
11949 #ifdef _SC_PII
11950     {"SC_PII",  _SC_PII},
11951 #endif
11952 #ifdef _SC_PII_INTERNET
11953     {"SC_PII_INTERNET", _SC_PII_INTERNET},
11954 #endif
11955 #ifdef _SC_PII_INTERNET_DGRAM
11956     {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
11957 #endif
11958 #ifdef _SC_PII_INTERNET_STREAM
11959     {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
11960 #endif
11961 #ifdef _SC_PII_OSI
11962     {"SC_PII_OSI",      _SC_PII_OSI},
11963 #endif
11964 #ifdef _SC_PII_OSI_CLTS
11965     {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
11966 #endif
11967 #ifdef _SC_PII_OSI_COTS
11968     {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
11969 #endif
11970 #ifdef _SC_PII_OSI_M
11971     {"SC_PII_OSI_M",    _SC_PII_OSI_M},
11972 #endif
11973 #ifdef _SC_PII_SOCKET
11974     {"SC_PII_SOCKET",   _SC_PII_SOCKET},
11975 #endif
11976 #ifdef _SC_PII_XTI
11977     {"SC_PII_XTI",      _SC_PII_XTI},
11978 #endif
11979 #ifdef _SC_POLL
11980     {"SC_POLL", _SC_POLL},
11981 #endif
11982 #ifdef _SC_PRIORITIZED_IO
11983     {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
11984 #endif
11985 #ifdef _SC_PRIORITY_SCHEDULING
11986     {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
11987 #endif
11988 #ifdef _SC_REALTIME_SIGNALS
11989     {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
11990 #endif
11991 #ifdef _SC_RE_DUP_MAX
11992     {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
11993 #endif
11994 #ifdef _SC_RTSIG_MAX
11995     {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
11996 #endif
11997 #ifdef _SC_SAVED_IDS
11998     {"SC_SAVED_IDS",    _SC_SAVED_IDS},
11999 #endif
12000 #ifdef _SC_SCHAR_MAX
12001     {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
12002 #endif
12003 #ifdef _SC_SCHAR_MIN
12004     {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
12005 #endif
12006 #ifdef _SC_SELECT
12007     {"SC_SELECT",       _SC_SELECT},
12008 #endif
12009 #ifdef _SC_SEMAPHORES
12010     {"SC_SEMAPHORES",   _SC_SEMAPHORES},
12011 #endif
12012 #ifdef _SC_SEM_NSEMS_MAX
12013     {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
12014 #endif
12015 #ifdef _SC_SEM_VALUE_MAX
12016     {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
12017 #endif
12018 #ifdef _SC_SHARED_MEMORY_OBJECTS
12019     {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
12020 #endif
12021 #ifdef _SC_SHRT_MAX
12022     {"SC_SHRT_MAX",     _SC_SHRT_MAX},
12023 #endif
12024 #ifdef _SC_SHRT_MIN
12025     {"SC_SHRT_MIN",     _SC_SHRT_MIN},
12026 #endif
12027 #ifdef _SC_SIGQUEUE_MAX
12028     {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
12029 #endif
12030 #ifdef _SC_SIGRT_MAX
12031     {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
12032 #endif
12033 #ifdef _SC_SIGRT_MIN
12034     {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
12035 #endif
12036 #ifdef _SC_SOFTPOWER
12037     {"SC_SOFTPOWER",    _SC_SOFTPOWER},
12038 #endif
12039 #ifdef _SC_SPLIT_CACHE
12040     {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
12041 #endif
12042 #ifdef _SC_SSIZE_MAX
12043     {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
12044 #endif
12045 #ifdef _SC_STACK_PROT
12046     {"SC_STACK_PROT",   _SC_STACK_PROT},
12047 #endif
12048 #ifdef _SC_STREAM_MAX
12049     {"SC_STREAM_MAX",   _SC_STREAM_MAX},
12050 #endif
12051 #ifdef _SC_SYNCHRONIZED_IO
12052     {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
12053 #endif
12054 #ifdef _SC_THREADS
12055     {"SC_THREADS",      _SC_THREADS},
12056 #endif
12057 #ifdef _SC_THREAD_ATTR_STACKADDR
12058     {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
12059 #endif
12060 #ifdef _SC_THREAD_ATTR_STACKSIZE
12061     {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
12062 #endif
12063 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
12064     {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
12065 #endif
12066 #ifdef _SC_THREAD_KEYS_MAX
12067     {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
12068 #endif
12069 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
12070     {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
12071 #endif
12072 #ifdef _SC_THREAD_PRIO_INHERIT
12073     {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
12074 #endif
12075 #ifdef _SC_THREAD_PRIO_PROTECT
12076     {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
12077 #endif
12078 #ifdef _SC_THREAD_PROCESS_SHARED
12079     {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
12080 #endif
12081 #ifdef _SC_THREAD_SAFE_FUNCTIONS
12082     {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
12083 #endif
12084 #ifdef _SC_THREAD_STACK_MIN
12085     {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
12086 #endif
12087 #ifdef _SC_THREAD_THREADS_MAX
12088     {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
12089 #endif
12090 #ifdef _SC_TIMERS
12091     {"SC_TIMERS",       _SC_TIMERS},
12092 #endif
12093 #ifdef _SC_TIMER_MAX
12094     {"SC_TIMER_MAX",    _SC_TIMER_MAX},
12095 #endif
12096 #ifdef _SC_TTY_NAME_MAX
12097     {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
12098 #endif
12099 #ifdef _SC_TZNAME_MAX
12100     {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
12101 #endif
12102 #ifdef _SC_T_IOV_MAX
12103     {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
12104 #endif
12105 #ifdef _SC_UCHAR_MAX
12106     {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
12107 #endif
12108 #ifdef _SC_UINT_MAX
12109     {"SC_UINT_MAX",     _SC_UINT_MAX},
12110 #endif
12111 #ifdef _SC_UIO_MAXIOV
12112     {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
12113 #endif
12114 #ifdef _SC_ULONG_MAX
12115     {"SC_ULONG_MAX",    _SC_ULONG_MAX},
12116 #endif
12117 #ifdef _SC_USHRT_MAX
12118     {"SC_USHRT_MAX",    _SC_USHRT_MAX},
12119 #endif
12120 #ifdef _SC_VERSION
12121     {"SC_VERSION",      _SC_VERSION},
12122 #endif
12123 #ifdef _SC_WORD_BIT
12124     {"SC_WORD_BIT",     _SC_WORD_BIT},
12125 #endif
12126 #ifdef _SC_XBS5_ILP32_OFF32
12127     {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
12128 #endif
12129 #ifdef _SC_XBS5_ILP32_OFFBIG
12130     {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
12131 #endif
12132 #ifdef _SC_XBS5_LP64_OFF64
12133     {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
12134 #endif
12135 #ifdef _SC_XBS5_LPBIG_OFFBIG
12136     {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
12137 #endif
12138 #ifdef _SC_XOPEN_CRYPT
12139     {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
12140 #endif
12141 #ifdef _SC_XOPEN_ENH_I18N
12142     {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
12143 #endif
12144 #ifdef _SC_XOPEN_LEGACY
12145     {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
12146 #endif
12147 #ifdef _SC_XOPEN_REALTIME
12148     {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
12149 #endif
12150 #ifdef _SC_XOPEN_REALTIME_THREADS
12151     {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
12152 #endif
12153 #ifdef _SC_XOPEN_SHM
12154     {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
12155 #endif
12156 #ifdef _SC_XOPEN_UNIX
12157     {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
12158 #endif
12159 #ifdef _SC_XOPEN_VERSION
12160     {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
12161 #endif
12162 #ifdef _SC_XOPEN_XCU_VERSION
12163     {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
12164 #endif
12165 #ifdef _SC_XOPEN_XPG2
12166     {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
12167 #endif
12168 #ifdef _SC_XOPEN_XPG3
12169     {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
12170 #endif
12171 #ifdef _SC_XOPEN_XPG4
12172     {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
12173 #endif
12174 };
12175 
12176 static int
conv_sysconf_confname(PyObject * arg,int * valuep)12177 conv_sysconf_confname(PyObject *arg, int *valuep)
12178 {
12179     return conv_confname(arg, valuep, posix_constants_sysconf,
12180                          sizeof(posix_constants_sysconf)
12181                            / sizeof(struct constdef));
12182 }
12183 
12184 
12185 /*[clinic input]
12186 os.sysconf -> long
12187     name: sysconf_confname
12188     /
12189 
12190 Return an integer-valued system configuration variable.
12191 [clinic start generated code]*/
12192 
12193 static long
os_sysconf_impl(PyObject * module,int name)12194 os_sysconf_impl(PyObject *module, int name)
12195 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
12196 {
12197     long value;
12198 
12199     errno = 0;
12200     value = sysconf(name);
12201     if (value == -1 && errno != 0)
12202         posix_error();
12203     return value;
12204 }
12205 #endif /* HAVE_SYSCONF */
12206 
12207 
12208 /* This code is used to ensure that the tables of configuration value names
12209  * are in sorted order as required by conv_confname(), and also to build
12210  * the exported dictionaries that are used to publish information about the
12211  * names available on the host platform.
12212  *
12213  * Sorting the table at runtime ensures that the table is properly ordered
12214  * when used, even for platforms we're not able to test on.  It also makes
12215  * it easier to add additional entries to the tables.
12216  */
12217 
12218 static int
cmp_constdefs(const void * v1,const void * v2)12219 cmp_constdefs(const void *v1,  const void *v2)
12220 {
12221     const struct constdef *c1 =
12222     (const struct constdef *) v1;
12223     const struct constdef *c2 =
12224     (const struct constdef *) v2;
12225 
12226     return strcmp(c1->name, c2->name);
12227 }
12228 
12229 static int
setup_confname_table(struct constdef * table,size_t tablesize,const char * tablename,PyObject * module)12230 setup_confname_table(struct constdef *table, size_t tablesize,
12231                      const char *tablename, PyObject *module)
12232 {
12233     PyObject *d = NULL;
12234     size_t i;
12235 
12236     qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
12237     d = PyDict_New();
12238     if (d == NULL)
12239         return -1;
12240 
12241     for (i=0; i < tablesize; ++i) {
12242         PyObject *o = PyLong_FromLong(table[i].value);
12243         if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
12244             Py_XDECREF(o);
12245             Py_DECREF(d);
12246             return -1;
12247         }
12248         Py_DECREF(o);
12249     }
12250     return PyModule_AddObject(module, tablename, d);
12251 }
12252 
12253 /* Return -1 on failure, 0 on success. */
12254 static int
setup_confname_tables(PyObject * module)12255 setup_confname_tables(PyObject *module)
12256 {
12257 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12258     if (setup_confname_table(posix_constants_pathconf,
12259                              sizeof(posix_constants_pathconf)
12260                                / sizeof(struct constdef),
12261                              "pathconf_names", module))
12262         return -1;
12263 #endif
12264 #ifdef HAVE_CONFSTR
12265     if (setup_confname_table(posix_constants_confstr,
12266                              sizeof(posix_constants_confstr)
12267                                / sizeof(struct constdef),
12268                              "confstr_names", module))
12269         return -1;
12270 #endif
12271 #ifdef HAVE_SYSCONF
12272     if (setup_confname_table(posix_constants_sysconf,
12273                              sizeof(posix_constants_sysconf)
12274                                / sizeof(struct constdef),
12275                              "sysconf_names", module))
12276         return -1;
12277 #endif
12278     return 0;
12279 }
12280 
12281 
12282 /*[clinic input]
12283 os.abort
12284 
12285 Abort the interpreter immediately.
12286 
12287 This function 'dumps core' or otherwise fails in the hardest way possible
12288 on the hosting operating system.  This function never returns.
12289 [clinic start generated code]*/
12290 
12291 static PyObject *
os_abort_impl(PyObject * module)12292 os_abort_impl(PyObject *module)
12293 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
12294 {
12295     abort();
12296     /*NOTREACHED*/
12297 #ifndef __clang__
12298     /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
12299        GCC emits a warning without "return NULL;" (compiler bug?), but Clang
12300        is smarter and emits a warning on the return. */
12301     Py_FatalError("abort() called from Python code didn't abort!");
12302     return NULL;
12303 #endif
12304 }
12305 
12306 #ifdef MS_WINDOWS
12307 /* Grab ShellExecute dynamically from shell32 */
12308 static int has_ShellExecute = -1;
12309 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
12310                                               LPCWSTR, INT);
12311 static int
check_ShellExecute()12312 check_ShellExecute()
12313 {
12314     HINSTANCE hShell32;
12315 
12316     /* only recheck */
12317     if (-1 == has_ShellExecute) {
12318         Py_BEGIN_ALLOW_THREADS
12319         /* Security note: this call is not vulnerable to "DLL hijacking".
12320            SHELL32 is part of "KnownDLLs" and so Windows always load
12321            the system SHELL32.DLL, even if there is another SHELL32.DLL
12322            in the DLL search path. */
12323         hShell32 = LoadLibraryW(L"SHELL32");
12324         if (hShell32) {
12325             *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
12326                                             "ShellExecuteW");
12327             has_ShellExecute = Py_ShellExecuteW != NULL;
12328         } else {
12329             has_ShellExecute = 0;
12330         }
12331         Py_END_ALLOW_THREADS
12332     }
12333     return has_ShellExecute;
12334 }
12335 
12336 
12337 /*[clinic input]
12338 os.startfile
12339     filepath: path_t
12340     operation: Py_UNICODE = NULL
12341 
12342 Start a file with its associated application.
12343 
12344 When "operation" is not specified or "open", this acts like
12345 double-clicking the file in Explorer, or giving the file name as an
12346 argument to the DOS "start" command: the file is opened with whatever
12347 application (if any) its extension is associated.
12348 When another "operation" is given, it specifies what should be done with
12349 the file.  A typical operation is "print".
12350 
12351 startfile returns as soon as the associated application is launched.
12352 There is no option to wait for the application to close, and no way
12353 to retrieve the application's exit status.
12354 
12355 The filepath is relative to the current directory.  If you want to use
12356 an absolute path, make sure the first character is not a slash ("/");
12357 the underlying Win32 ShellExecute function doesn't work if it is.
12358 [clinic start generated code]*/
12359 
12360 static PyObject *
os_startfile_impl(PyObject * module,path_t * filepath,const Py_UNICODE * operation)12361 os_startfile_impl(PyObject *module, path_t *filepath,
12362                   const Py_UNICODE *operation)
12363 /*[clinic end generated code: output=66dc311c94d50797 input=c940888a5390f039]*/
12364 {
12365     HINSTANCE rc;
12366 
12367     if(!check_ShellExecute()) {
12368         /* If the OS doesn't have ShellExecute, return a
12369            NotImplementedError. */
12370         return PyErr_Format(PyExc_NotImplementedError,
12371             "startfile not available on this platform");
12372     }
12373 
12374     if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
12375         return NULL;
12376     }
12377 
12378     Py_BEGIN_ALLOW_THREADS
12379     rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
12380                           NULL, NULL, SW_SHOWNORMAL);
12381     Py_END_ALLOW_THREADS
12382 
12383     if (rc <= (HINSTANCE)32) {
12384         win32_error_object("startfile", filepath->object);
12385         return NULL;
12386     }
12387     Py_RETURN_NONE;
12388 }
12389 #endif /* MS_WINDOWS */
12390 
12391 
12392 #ifdef HAVE_GETLOADAVG
12393 /*[clinic input]
12394 os.getloadavg
12395 
12396 Return average recent system load information.
12397 
12398 Return the number of processes in the system run queue averaged over
12399 the last 1, 5, and 15 minutes as a tuple of three floats.
12400 Raises OSError if the load average was unobtainable.
12401 [clinic start generated code]*/
12402 
12403 static PyObject *
os_getloadavg_impl(PyObject * module)12404 os_getloadavg_impl(PyObject *module)
12405 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
12406 {
12407     double loadavg[3];
12408     if (getloadavg(loadavg, 3)!=3) {
12409         PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
12410         return NULL;
12411     } else
12412         return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
12413 }
12414 #endif /* HAVE_GETLOADAVG */
12415 
12416 
12417 /*[clinic input]
12418 os.device_encoding
12419     fd: int
12420 
12421 Return a string describing the encoding of a terminal's file descriptor.
12422 
12423 The file descriptor must be attached to a terminal.
12424 If the device is not a terminal, return None.
12425 [clinic start generated code]*/
12426 
12427 static PyObject *
os_device_encoding_impl(PyObject * module,int fd)12428 os_device_encoding_impl(PyObject *module, int fd)
12429 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
12430 {
12431     return _Py_device_encoding(fd);
12432 }
12433 
12434 
12435 #ifdef HAVE_SETRESUID
12436 /*[clinic input]
12437 os.setresuid
12438 
12439     ruid: uid_t
12440     euid: uid_t
12441     suid: uid_t
12442     /
12443 
12444 Set the current process's real, effective, and saved user ids.
12445 [clinic start generated code]*/
12446 
12447 static PyObject *
os_setresuid_impl(PyObject * module,uid_t ruid,uid_t euid,uid_t suid)12448 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
12449 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
12450 {
12451     if (setresuid(ruid, euid, suid) < 0)
12452         return posix_error();
12453     Py_RETURN_NONE;
12454 }
12455 #endif /* HAVE_SETRESUID */
12456 
12457 
12458 #ifdef HAVE_SETRESGID
12459 /*[clinic input]
12460 os.setresgid
12461 
12462     rgid: gid_t
12463     egid: gid_t
12464     sgid: gid_t
12465     /
12466 
12467 Set the current process's real, effective, and saved group ids.
12468 [clinic start generated code]*/
12469 
12470 static PyObject *
os_setresgid_impl(PyObject * module,gid_t rgid,gid_t egid,gid_t sgid)12471 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
12472 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
12473 {
12474     if (setresgid(rgid, egid, sgid) < 0)
12475         return posix_error();
12476     Py_RETURN_NONE;
12477 }
12478 #endif /* HAVE_SETRESGID */
12479 
12480 
12481 #ifdef HAVE_GETRESUID
12482 /*[clinic input]
12483 os.getresuid
12484 
12485 Return a tuple of the current process's real, effective, and saved user ids.
12486 [clinic start generated code]*/
12487 
12488 static PyObject *
os_getresuid_impl(PyObject * module)12489 os_getresuid_impl(PyObject *module)
12490 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12491 {
12492     uid_t ruid, euid, suid;
12493     if (getresuid(&ruid, &euid, &suid) < 0)
12494         return posix_error();
12495     return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12496                                   _PyLong_FromUid(euid),
12497                                   _PyLong_FromUid(suid));
12498 }
12499 #endif /* HAVE_GETRESUID */
12500 
12501 
12502 #ifdef HAVE_GETRESGID
12503 /*[clinic input]
12504 os.getresgid
12505 
12506 Return a tuple of the current process's real, effective, and saved group ids.
12507 [clinic start generated code]*/
12508 
12509 static PyObject *
os_getresgid_impl(PyObject * module)12510 os_getresgid_impl(PyObject *module)
12511 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12512 {
12513     gid_t rgid, egid, sgid;
12514     if (getresgid(&rgid, &egid, &sgid) < 0)
12515         return posix_error();
12516     return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12517                                   _PyLong_FromGid(egid),
12518                                   _PyLong_FromGid(sgid));
12519 }
12520 #endif /* HAVE_GETRESGID */
12521 
12522 
12523 #ifdef USE_XATTRS
12524 /*[clinic input]
12525 os.getxattr
12526 
12527     path: path_t(allow_fd=True)
12528     attribute: path_t
12529     *
12530     follow_symlinks: bool = True
12531 
12532 Return the value of extended attribute attribute on path.
12533 
12534 path may be either a string, a path-like object, or an open file descriptor.
12535 If follow_symlinks is False, and the last element of the path is a symbolic
12536   link, getxattr will examine the symbolic link itself instead of the file
12537   the link points to.
12538 
12539 [clinic start generated code]*/
12540 
12541 static PyObject *
os_getxattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12542 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12543                  int follow_symlinks)
12544 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12545 {
12546     Py_ssize_t i;
12547     PyObject *buffer = NULL;
12548 
12549     if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12550         return NULL;
12551 
12552     if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12553         return NULL;
12554     }
12555 
12556     for (i = 0; ; i++) {
12557         void *ptr;
12558         ssize_t result;
12559         static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12560         Py_ssize_t buffer_size = buffer_sizes[i];
12561         if (!buffer_size) {
12562             path_error(path);
12563             return NULL;
12564         }
12565         buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12566         if (!buffer)
12567             return NULL;
12568         ptr = PyBytes_AS_STRING(buffer);
12569 
12570         Py_BEGIN_ALLOW_THREADS;
12571         if (path->fd >= 0)
12572             result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12573         else if (follow_symlinks)
12574             result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12575         else
12576             result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12577         Py_END_ALLOW_THREADS;
12578 
12579         if (result < 0) {
12580             Py_DECREF(buffer);
12581             if (errno == ERANGE)
12582                 continue;
12583             path_error(path);
12584             return NULL;
12585         }
12586 
12587         if (result != buffer_size) {
12588             /* Can only shrink. */
12589             _PyBytes_Resize(&buffer, result);
12590         }
12591         break;
12592     }
12593 
12594     return buffer;
12595 }
12596 
12597 
12598 /*[clinic input]
12599 os.setxattr
12600 
12601     path: path_t(allow_fd=True)
12602     attribute: path_t
12603     value: Py_buffer
12604     flags: int = 0
12605     *
12606     follow_symlinks: bool = True
12607 
12608 Set extended attribute attribute on path to value.
12609 
12610 path may be either a string, a path-like object,  or an open file descriptor.
12611 If follow_symlinks is False, and the last element of the path is a symbolic
12612   link, setxattr will modify the symbolic link itself instead of the file
12613   the link points to.
12614 
12615 [clinic start generated code]*/
12616 
12617 static PyObject *
os_setxattr_impl(PyObject * module,path_t * path,path_t * attribute,Py_buffer * value,int flags,int follow_symlinks)12618 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12619                  Py_buffer *value, int flags, int follow_symlinks)
12620 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12621 {
12622     ssize_t result;
12623 
12624     if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12625         return NULL;
12626 
12627     if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12628                     value->buf, value->len, flags) < 0) {
12629         return NULL;
12630     }
12631 
12632     Py_BEGIN_ALLOW_THREADS;
12633     if (path->fd > -1)
12634         result = fsetxattr(path->fd, attribute->narrow,
12635                            value->buf, value->len, flags);
12636     else if (follow_symlinks)
12637         result = setxattr(path->narrow, attribute->narrow,
12638                            value->buf, value->len, flags);
12639     else
12640         result = lsetxattr(path->narrow, attribute->narrow,
12641                            value->buf, value->len, flags);
12642     Py_END_ALLOW_THREADS;
12643 
12644     if (result) {
12645         path_error(path);
12646         return NULL;
12647     }
12648 
12649     Py_RETURN_NONE;
12650 }
12651 
12652 
12653 /*[clinic input]
12654 os.removexattr
12655 
12656     path: path_t(allow_fd=True)
12657     attribute: path_t
12658     *
12659     follow_symlinks: bool = True
12660 
12661 Remove extended attribute attribute on path.
12662 
12663 path may be either a string, a path-like object, or an open file descriptor.
12664 If follow_symlinks is False, and the last element of the path is a symbolic
12665   link, removexattr will modify the symbolic link itself instead of the file
12666   the link points to.
12667 
12668 [clinic start generated code]*/
12669 
12670 static PyObject *
os_removexattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12671 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
12672                     int follow_symlinks)
12673 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
12674 {
12675     ssize_t result;
12676 
12677     if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
12678         return NULL;
12679 
12680     if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
12681         return NULL;
12682     }
12683 
12684     Py_BEGIN_ALLOW_THREADS;
12685     if (path->fd > -1)
12686         result = fremovexattr(path->fd, attribute->narrow);
12687     else if (follow_symlinks)
12688         result = removexattr(path->narrow, attribute->narrow);
12689     else
12690         result = lremovexattr(path->narrow, attribute->narrow);
12691     Py_END_ALLOW_THREADS;
12692 
12693     if (result) {
12694         return path_error(path);
12695     }
12696 
12697     Py_RETURN_NONE;
12698 }
12699 
12700 
12701 /*[clinic input]
12702 os.listxattr
12703 
12704     path: path_t(allow_fd=True, nullable=True) = None
12705     *
12706     follow_symlinks: bool = True
12707 
12708 Return a list of extended attributes on path.
12709 
12710 path may be either None, a string, a path-like object, or an open file descriptor.
12711 if path is None, listxattr will examine the current directory.
12712 If follow_symlinks is False, and the last element of the path is a symbolic
12713   link, listxattr will examine the symbolic link itself instead of the file
12714   the link points to.
12715 [clinic start generated code]*/
12716 
12717 static PyObject *
os_listxattr_impl(PyObject * module,path_t * path,int follow_symlinks)12718 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
12719 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
12720 {
12721     Py_ssize_t i;
12722     PyObject *result = NULL;
12723     const char *name;
12724     char *buffer = NULL;
12725 
12726     if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
12727         goto exit;
12728 
12729     if (PySys_Audit("os.listxattr", "(O)",
12730                     path->object ? path->object : Py_None) < 0) {
12731         return NULL;
12732     }
12733 
12734     name = path->narrow ? path->narrow : ".";
12735 
12736     for (i = 0; ; i++) {
12737         const char *start, *trace, *end;
12738         ssize_t length;
12739         static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
12740         Py_ssize_t buffer_size = buffer_sizes[i];
12741         if (!buffer_size) {
12742             /* ERANGE */
12743             path_error(path);
12744             break;
12745         }
12746         buffer = PyMem_MALLOC(buffer_size);
12747         if (!buffer) {
12748             PyErr_NoMemory();
12749             break;
12750         }
12751 
12752         Py_BEGIN_ALLOW_THREADS;
12753         if (path->fd > -1)
12754             length = flistxattr(path->fd, buffer, buffer_size);
12755         else if (follow_symlinks)
12756             length = listxattr(name, buffer, buffer_size);
12757         else
12758             length = llistxattr(name, buffer, buffer_size);
12759         Py_END_ALLOW_THREADS;
12760 
12761         if (length < 0) {
12762             if (errno == ERANGE) {
12763                 PyMem_FREE(buffer);
12764                 buffer = NULL;
12765                 continue;
12766             }
12767             path_error(path);
12768             break;
12769         }
12770 
12771         result = PyList_New(0);
12772         if (!result) {
12773             goto exit;
12774         }
12775 
12776         end = buffer + length;
12777         for (trace = start = buffer; trace != end; trace++) {
12778             if (!*trace) {
12779                 int error;
12780                 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
12781                                                                  trace - start);
12782                 if (!attribute) {
12783                     Py_DECREF(result);
12784                     result = NULL;
12785                     goto exit;
12786                 }
12787                 error = PyList_Append(result, attribute);
12788                 Py_DECREF(attribute);
12789                 if (error) {
12790                     Py_DECREF(result);
12791                     result = NULL;
12792                     goto exit;
12793                 }
12794                 start = trace + 1;
12795             }
12796         }
12797     break;
12798     }
12799 exit:
12800     if (buffer)
12801         PyMem_FREE(buffer);
12802     return result;
12803 }
12804 #endif /* USE_XATTRS */
12805 
12806 
12807 /*[clinic input]
12808 os.urandom
12809 
12810     size: Py_ssize_t
12811     /
12812 
12813 Return a bytes object containing random bytes suitable for cryptographic use.
12814 [clinic start generated code]*/
12815 
12816 static PyObject *
os_urandom_impl(PyObject * module,Py_ssize_t size)12817 os_urandom_impl(PyObject *module, Py_ssize_t size)
12818 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
12819 {
12820     PyObject *bytes;
12821     int result;
12822 
12823     if (size < 0)
12824         return PyErr_Format(PyExc_ValueError,
12825                             "negative argument not allowed");
12826     bytes = PyBytes_FromStringAndSize(NULL, size);
12827     if (bytes == NULL)
12828         return NULL;
12829 
12830     result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
12831     if (result == -1) {
12832         Py_DECREF(bytes);
12833         return NULL;
12834     }
12835     return bytes;
12836 }
12837 
12838 #ifdef HAVE_MEMFD_CREATE
12839 /*[clinic input]
12840 os.memfd_create
12841 
12842     name: FSConverter
12843     flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
12844 
12845 [clinic start generated code]*/
12846 
12847 static PyObject *
os_memfd_create_impl(PyObject * module,PyObject * name,unsigned int flags)12848 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
12849 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
12850 {
12851     int fd;
12852     const char *bytes = PyBytes_AS_STRING(name);
12853     Py_BEGIN_ALLOW_THREADS
12854     fd = memfd_create(bytes, flags);
12855     Py_END_ALLOW_THREADS
12856     if (fd == -1) {
12857         return PyErr_SetFromErrno(PyExc_OSError);
12858     }
12859     return PyLong_FromLong(fd);
12860 }
12861 #endif
12862 
12863 /* Terminal size querying */
12864 
12865 PyDoc_STRVAR(TerminalSize_docstring,
12866     "A tuple of (columns, lines) for holding terminal window size");
12867 
12868 static PyStructSequence_Field TerminalSize_fields[] = {
12869     {"columns", "width of the terminal window in characters"},
12870     {"lines", "height of the terminal window in characters"},
12871     {NULL, NULL}
12872 };
12873 
12874 static PyStructSequence_Desc TerminalSize_desc = {
12875     "os.terminal_size",
12876     TerminalSize_docstring,
12877     TerminalSize_fields,
12878     2,
12879 };
12880 
12881 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
12882 /*[clinic input]
12883 os.get_terminal_size
12884 
12885     fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
12886     /
12887 
12888 Return the size of the terminal window as (columns, lines).
12889 
12890 The optional argument fd (default standard output) specifies
12891 which file descriptor should be queried.
12892 
12893 If the file descriptor is not connected to a terminal, an OSError
12894 is thrown.
12895 
12896 This function will only be defined if an implementation is
12897 available for this system.
12898 
12899 shutil.get_terminal_size is the high-level function which should
12900 normally be used, os.get_terminal_size is the low-level implementation.
12901 [clinic start generated code]*/
12902 
12903 static PyObject *
os_get_terminal_size_impl(PyObject * module,int fd)12904 os_get_terminal_size_impl(PyObject *module, int fd)
12905 /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
12906 {
12907     int columns, lines;
12908     PyObject *termsize;
12909 
12910     /* Under some conditions stdout may not be connected and
12911      * fileno(stdout) may point to an invalid file descriptor. For example
12912      * GUI apps don't have valid standard streams by default.
12913      *
12914      * If this happens, and the optional fd argument is not present,
12915      * the ioctl below will fail returning EBADF. This is what we want.
12916      */
12917 
12918 #ifdef TERMSIZE_USE_IOCTL
12919     {
12920         struct winsize w;
12921         if (ioctl(fd, TIOCGWINSZ, &w))
12922             return PyErr_SetFromErrno(PyExc_OSError);
12923         columns = w.ws_col;
12924         lines = w.ws_row;
12925     }
12926 #endif /* TERMSIZE_USE_IOCTL */
12927 
12928 #ifdef TERMSIZE_USE_CONIO
12929     {
12930         DWORD nhandle;
12931         HANDLE handle;
12932         CONSOLE_SCREEN_BUFFER_INFO csbi;
12933         switch (fd) {
12934         case 0: nhandle = STD_INPUT_HANDLE;
12935             break;
12936         case 1: nhandle = STD_OUTPUT_HANDLE;
12937             break;
12938         case 2: nhandle = STD_ERROR_HANDLE;
12939             break;
12940         default:
12941             return PyErr_Format(PyExc_ValueError, "bad file descriptor");
12942         }
12943         handle = GetStdHandle(nhandle);
12944         if (handle == NULL)
12945             return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
12946         if (handle == INVALID_HANDLE_VALUE)
12947             return PyErr_SetFromWindowsErr(0);
12948 
12949         if (!GetConsoleScreenBufferInfo(handle, &csbi))
12950             return PyErr_SetFromWindowsErr(0);
12951 
12952         columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
12953         lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
12954     }
12955 #endif /* TERMSIZE_USE_CONIO */
12956 
12957     PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
12958     termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
12959     if (termsize == NULL)
12960         return NULL;
12961     PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
12962     PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
12963     if (PyErr_Occurred()) {
12964         Py_DECREF(termsize);
12965         return NULL;
12966     }
12967     return termsize;
12968 }
12969 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
12970 
12971 
12972 /*[clinic input]
12973 os.cpu_count
12974 
12975 Return the number of CPUs in the system; return None if indeterminable.
12976 
12977 This number is not equivalent to the number of CPUs the current process can
12978 use.  The number of usable CPUs can be obtained with
12979 ``len(os.sched_getaffinity(0))``
12980 [clinic start generated code]*/
12981 
12982 static PyObject *
os_cpu_count_impl(PyObject * module)12983 os_cpu_count_impl(PyObject *module)
12984 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
12985 {
12986     int ncpu = 0;
12987 #ifdef MS_WINDOWS
12988     ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
12989 #elif defined(__hpux)
12990     ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
12991 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
12992     ncpu = sysconf(_SC_NPROCESSORS_ONLN);
12993 #elif defined(__DragonFly__) || \
12994       defined(__OpenBSD__)   || \
12995       defined(__FreeBSD__)   || \
12996       defined(__NetBSD__)    || \
12997       defined(__APPLE__)
12998     int mib[2];
12999     size_t len = sizeof(ncpu);
13000     mib[0] = CTL_HW;
13001     mib[1] = HW_NCPU;
13002     if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
13003         ncpu = 0;
13004 #endif
13005     if (ncpu >= 1)
13006         return PyLong_FromLong(ncpu);
13007     else
13008         Py_RETURN_NONE;
13009 }
13010 
13011 
13012 /*[clinic input]
13013 os.get_inheritable -> bool
13014 
13015     fd: int
13016     /
13017 
13018 Get the close-on-exe flag of the specified file descriptor.
13019 [clinic start generated code]*/
13020 
13021 static int
os_get_inheritable_impl(PyObject * module,int fd)13022 os_get_inheritable_impl(PyObject *module, int fd)
13023 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
13024 {
13025     int return_value;
13026     _Py_BEGIN_SUPPRESS_IPH
13027     return_value = _Py_get_inheritable(fd);
13028     _Py_END_SUPPRESS_IPH
13029     return return_value;
13030 }
13031 
13032 
13033 /*[clinic input]
13034 os.set_inheritable
13035     fd: int
13036     inheritable: int
13037     /
13038 
13039 Set the inheritable flag of the specified file descriptor.
13040 [clinic start generated code]*/
13041 
13042 static PyObject *
os_set_inheritable_impl(PyObject * module,int fd,int inheritable)13043 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
13044 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
13045 {
13046     int result;
13047 
13048     _Py_BEGIN_SUPPRESS_IPH
13049     result = _Py_set_inheritable(fd, inheritable, NULL);
13050     _Py_END_SUPPRESS_IPH
13051     if (result < 0)
13052         return NULL;
13053     Py_RETURN_NONE;
13054 }
13055 
13056 
13057 #ifdef MS_WINDOWS
13058 /*[clinic input]
13059 os.get_handle_inheritable -> bool
13060     handle: intptr_t
13061     /
13062 
13063 Get the close-on-exe flag of the specified file descriptor.
13064 [clinic start generated code]*/
13065 
13066 static int
os_get_handle_inheritable_impl(PyObject * module,intptr_t handle)13067 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
13068 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
13069 {
13070     DWORD flags;
13071 
13072     if (!GetHandleInformation((HANDLE)handle, &flags)) {
13073         PyErr_SetFromWindowsErr(0);
13074         return -1;
13075     }
13076 
13077     return flags & HANDLE_FLAG_INHERIT;
13078 }
13079 
13080 
13081 /*[clinic input]
13082 os.set_handle_inheritable
13083     handle: intptr_t
13084     inheritable: bool
13085     /
13086 
13087 Set the inheritable flag of the specified handle.
13088 [clinic start generated code]*/
13089 
13090 static PyObject *
os_set_handle_inheritable_impl(PyObject * module,intptr_t handle,int inheritable)13091 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
13092                                int inheritable)
13093 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
13094 {
13095     DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
13096     if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
13097         PyErr_SetFromWindowsErr(0);
13098         return NULL;
13099     }
13100     Py_RETURN_NONE;
13101 }
13102 #endif /* MS_WINDOWS */
13103 
13104 #ifndef MS_WINDOWS
13105 /*[clinic input]
13106 os.get_blocking -> bool
13107     fd: int
13108     /
13109 
13110 Get the blocking mode of the file descriptor.
13111 
13112 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
13113 [clinic start generated code]*/
13114 
13115 static int
os_get_blocking_impl(PyObject * module,int fd)13116 os_get_blocking_impl(PyObject *module, int fd)
13117 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
13118 {
13119     int blocking;
13120 
13121     _Py_BEGIN_SUPPRESS_IPH
13122     blocking = _Py_get_blocking(fd);
13123     _Py_END_SUPPRESS_IPH
13124     return blocking;
13125 }
13126 
13127 /*[clinic input]
13128 os.set_blocking
13129     fd: int
13130     blocking: bool(accept={int})
13131     /
13132 
13133 Set the blocking mode of the specified file descriptor.
13134 
13135 Set the O_NONBLOCK flag if blocking is False,
13136 clear the O_NONBLOCK flag otherwise.
13137 [clinic start generated code]*/
13138 
13139 static PyObject *
os_set_blocking_impl(PyObject * module,int fd,int blocking)13140 os_set_blocking_impl(PyObject *module, int fd, int blocking)
13141 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
13142 {
13143     int result;
13144 
13145     _Py_BEGIN_SUPPRESS_IPH
13146     result = _Py_set_blocking(fd, blocking);
13147     _Py_END_SUPPRESS_IPH
13148     if (result < 0)
13149         return NULL;
13150     Py_RETURN_NONE;
13151 }
13152 #endif   /* !MS_WINDOWS */
13153 
13154 
13155 /*[clinic input]
13156 class os.DirEntry "DirEntry *" "DirEntryType"
13157 [clinic start generated code]*/
13158 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
13159 
13160 typedef struct {
13161     PyObject_HEAD
13162     PyObject *name;
13163     PyObject *path;
13164     PyObject *stat;
13165     PyObject *lstat;
13166 #ifdef MS_WINDOWS
13167     struct _Py_stat_struct win32_lstat;
13168     uint64_t win32_file_index;
13169     int got_file_index;
13170 #else /* POSIX */
13171 #ifdef HAVE_DIRENT_D_TYPE
13172     unsigned char d_type;
13173 #endif
13174     ino_t d_ino;
13175     int dir_fd;
13176 #endif
13177 } DirEntry;
13178 
13179 static PyObject *
_disabled_new(PyTypeObject * type,PyObject * args,PyObject * kwargs)13180 _disabled_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
13181 {
13182     PyErr_Format(PyExc_TypeError,
13183         "cannot create '%.100s' instances", _PyType_Name(type));
13184     return NULL;
13185 }
13186 
13187 static void
DirEntry_dealloc(DirEntry * entry)13188 DirEntry_dealloc(DirEntry *entry)
13189 {
13190     PyTypeObject *tp = Py_TYPE(entry);
13191     Py_XDECREF(entry->name);
13192     Py_XDECREF(entry->path);
13193     Py_XDECREF(entry->stat);
13194     Py_XDECREF(entry->lstat);
13195     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13196     free_func(entry);
13197     Py_DECREF(tp);
13198 }
13199 
13200 /* Forward reference */
13201 static int
13202 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13203                    int follow_symlinks, unsigned short mode_bits);
13204 
13205 /*[clinic input]
13206 os.DirEntry.is_symlink -> bool
13207     defining_class: defining_class
13208     /
13209 
13210 Return True if the entry is a symbolic link; cached per entry.
13211 [clinic start generated code]*/
13212 
13213 static int
os_DirEntry_is_symlink_impl(DirEntry * self,PyTypeObject * defining_class)13214 os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
13215 /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
13216 {
13217 #ifdef MS_WINDOWS
13218     return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13219 #elif defined(HAVE_DIRENT_D_TYPE)
13220     /* POSIX */
13221     if (self->d_type != DT_UNKNOWN)
13222         return self->d_type == DT_LNK;
13223     else
13224         return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13225 #else
13226     /* POSIX without d_type */
13227     return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13228 #endif
13229 }
13230 
13231 static PyObject *
DirEntry_fetch_stat(PyObject * module,DirEntry * self,int follow_symlinks)13232 DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
13233 {
13234     int result;
13235     STRUCT_STAT st;
13236     PyObject *ub;
13237 
13238 #ifdef MS_WINDOWS
13239     if (!PyUnicode_FSDecoder(self->path, &ub))
13240         return NULL;
13241     const wchar_t *path = PyUnicode_AsUnicode(ub);
13242 #else /* POSIX */
13243     if (!PyUnicode_FSConverter(self->path, &ub))
13244         return NULL;
13245     const char *path = PyBytes_AS_STRING(ub);
13246     if (self->dir_fd != DEFAULT_DIR_FD) {
13247 #ifdef HAVE_FSTATAT
13248       if (HAVE_FSTATAT_RUNTIME) {
13249         result = fstatat(self->dir_fd, path, &st,
13250                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
13251       } else
13252 
13253 #endif /* HAVE_FSTATAT */
13254       {
13255         Py_DECREF(ub);
13256         PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
13257         return NULL;
13258       }
13259     }
13260     else
13261 #endif
13262     {
13263         if (follow_symlinks)
13264             result = STAT(path, &st);
13265         else
13266             result = LSTAT(path, &st);
13267     }
13268     Py_DECREF(ub);
13269 
13270     if (result != 0)
13271         return path_object_error(self->path);
13272 
13273     return _pystat_fromstructstat(module, &st);
13274 }
13275 
13276 static PyObject *
DirEntry_get_lstat(PyTypeObject * defining_class,DirEntry * self)13277 DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
13278 {
13279     if (!self->lstat) {
13280         PyObject *module = PyType_GetModule(defining_class);
13281 #ifdef MS_WINDOWS
13282         self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
13283 #else /* POSIX */
13284         self->lstat = DirEntry_fetch_stat(module, self, 0);
13285 #endif
13286     }
13287     Py_XINCREF(self->lstat);
13288     return self->lstat;
13289 }
13290 
13291 /*[clinic input]
13292 os.DirEntry.stat
13293     defining_class: defining_class
13294     /
13295     *
13296     follow_symlinks: bool = True
13297 
13298 Return stat_result object for the entry; cached per entry.
13299 [clinic start generated code]*/
13300 
13301 static PyObject *
os_DirEntry_stat_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13302 os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
13303                       int follow_symlinks)
13304 /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
13305 {
13306     if (!follow_symlinks) {
13307         return DirEntry_get_lstat(defining_class, self);
13308     }
13309 
13310     if (!self->stat) {
13311         int result = os_DirEntry_is_symlink_impl(self, defining_class);
13312         if (result == -1) {
13313             return NULL;
13314         }
13315         if (result) {
13316             PyObject *module = PyType_GetModule(defining_class);
13317             self->stat = DirEntry_fetch_stat(module, self, 1);
13318         }
13319         else {
13320             self->stat = DirEntry_get_lstat(defining_class, self);
13321         }
13322     }
13323 
13324     Py_XINCREF(self->stat);
13325     return self->stat;
13326 }
13327 
13328 /* Set exception and return -1 on error, 0 for False, 1 for True */
13329 static int
DirEntry_test_mode(PyTypeObject * defining_class,DirEntry * self,int follow_symlinks,unsigned short mode_bits)13330 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13331                    int follow_symlinks, unsigned short mode_bits)
13332 {
13333     PyObject *stat = NULL;
13334     PyObject *st_mode = NULL;
13335     long mode;
13336     int result;
13337 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13338     int is_symlink;
13339     int need_stat;
13340 #endif
13341 #ifdef MS_WINDOWS
13342     unsigned long dir_bits;
13343 #endif
13344 
13345 #ifdef MS_WINDOWS
13346     is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13347     need_stat = follow_symlinks && is_symlink;
13348 #elif defined(HAVE_DIRENT_D_TYPE)
13349     is_symlink = self->d_type == DT_LNK;
13350     need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
13351 #endif
13352 
13353 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13354     if (need_stat) {
13355 #endif
13356         stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
13357         if (!stat) {
13358             if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
13359                 /* If file doesn't exist (anymore), then return False
13360                    (i.e., say it's not a file/directory) */
13361                 PyErr_Clear();
13362                 return 0;
13363             }
13364             goto error;
13365         }
13366         _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
13367         st_mode = PyObject_GetAttr(stat, state->st_mode);
13368         if (!st_mode)
13369             goto error;
13370 
13371         mode = PyLong_AsLong(st_mode);
13372         if (mode == -1 && PyErr_Occurred())
13373             goto error;
13374         Py_CLEAR(st_mode);
13375         Py_CLEAR(stat);
13376         result = (mode & S_IFMT) == mode_bits;
13377 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13378     }
13379     else if (is_symlink) {
13380         assert(mode_bits != S_IFLNK);
13381         result = 0;
13382     }
13383     else {
13384         assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
13385 #ifdef MS_WINDOWS
13386         dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
13387         if (mode_bits == S_IFDIR)
13388             result = dir_bits != 0;
13389         else
13390             result = dir_bits == 0;
13391 #else /* POSIX */
13392         if (mode_bits == S_IFDIR)
13393             result = self->d_type == DT_DIR;
13394         else
13395             result = self->d_type == DT_REG;
13396 #endif
13397     }
13398 #endif
13399 
13400     return result;
13401 
13402 error:
13403     Py_XDECREF(st_mode);
13404     Py_XDECREF(stat);
13405     return -1;
13406 }
13407 
13408 /*[clinic input]
13409 os.DirEntry.is_dir -> bool
13410     defining_class: defining_class
13411     /
13412     *
13413     follow_symlinks: bool = True
13414 
13415 Return True if the entry is a directory; cached per entry.
13416 [clinic start generated code]*/
13417 
13418 static int
os_DirEntry_is_dir_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13419 os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
13420                         int follow_symlinks)
13421 /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
13422 {
13423     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
13424 }
13425 
13426 /*[clinic input]
13427 os.DirEntry.is_file -> bool
13428     defining_class: defining_class
13429     /
13430     *
13431     follow_symlinks: bool = True
13432 
13433 Return True if the entry is a file; cached per entry.
13434 [clinic start generated code]*/
13435 
13436 static int
os_DirEntry_is_file_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13437 os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
13438                          int follow_symlinks)
13439 /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
13440 {
13441     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
13442 }
13443 
13444 /*[clinic input]
13445 os.DirEntry.inode
13446 
13447 Return inode of the entry; cached per entry.
13448 [clinic start generated code]*/
13449 
13450 static PyObject *
os_DirEntry_inode_impl(DirEntry * self)13451 os_DirEntry_inode_impl(DirEntry *self)
13452 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
13453 {
13454 #ifdef MS_WINDOWS
13455     if (!self->got_file_index) {
13456         PyObject *unicode;
13457         const wchar_t *path;
13458         STRUCT_STAT stat;
13459         int result;
13460 
13461         if (!PyUnicode_FSDecoder(self->path, &unicode))
13462             return NULL;
13463         path = PyUnicode_AsUnicode(unicode);
13464         result = LSTAT(path, &stat);
13465         Py_DECREF(unicode);
13466 
13467         if (result != 0)
13468             return path_object_error(self->path);
13469 
13470         self->win32_file_index = stat.st_ino;
13471         self->got_file_index = 1;
13472     }
13473     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->win32_file_index));
13474     return PyLong_FromUnsignedLongLong(self->win32_file_index);
13475 #else /* POSIX */
13476     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->d_ino));
13477     return PyLong_FromUnsignedLongLong(self->d_ino);
13478 #endif
13479 }
13480 
13481 static PyObject *
DirEntry_repr(DirEntry * self)13482 DirEntry_repr(DirEntry *self)
13483 {
13484     return PyUnicode_FromFormat("<DirEntry %R>", self->name);
13485 }
13486 
13487 /*[clinic input]
13488 os.DirEntry.__fspath__
13489 
13490 Returns the path for the entry.
13491 [clinic start generated code]*/
13492 
13493 static PyObject *
os_DirEntry___fspath___impl(DirEntry * self)13494 os_DirEntry___fspath___impl(DirEntry *self)
13495 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
13496 {
13497     Py_INCREF(self->path);
13498     return self->path;
13499 }
13500 
13501 static PyMemberDef DirEntry_members[] = {
13502     {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
13503      "the entry's base filename, relative to scandir() \"path\" argument"},
13504     {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
13505      "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
13506     {NULL}
13507 };
13508 
13509 #include "clinic/posixmodule.c.h"
13510 
13511 static PyMethodDef DirEntry_methods[] = {
13512     OS_DIRENTRY_IS_DIR_METHODDEF
13513     OS_DIRENTRY_IS_FILE_METHODDEF
13514     OS_DIRENTRY_IS_SYMLINK_METHODDEF
13515     OS_DIRENTRY_STAT_METHODDEF
13516     OS_DIRENTRY_INODE_METHODDEF
13517     OS_DIRENTRY___FSPATH___METHODDEF
13518     {"__class_getitem__",       (PyCFunction)Py_GenericAlias,
13519     METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
13520     {NULL}
13521 };
13522 
13523 static PyType_Slot DirEntryType_slots[] = {
13524     {Py_tp_new, _disabled_new},
13525     {Py_tp_dealloc, DirEntry_dealloc},
13526     {Py_tp_repr, DirEntry_repr},
13527     {Py_tp_methods, DirEntry_methods},
13528     {Py_tp_members, DirEntry_members},
13529     {0, 0},
13530 };
13531 
13532 static PyType_Spec DirEntryType_spec = {
13533     MODNAME ".DirEntry",
13534     sizeof(DirEntry),
13535     0,
13536     Py_TPFLAGS_DEFAULT,
13537     DirEntryType_slots
13538 };
13539 
13540 
13541 #ifdef MS_WINDOWS
13542 
13543 static wchar_t *
join_path_filenameW(const wchar_t * path_wide,const wchar_t * filename)13544 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
13545 {
13546     Py_ssize_t path_len;
13547     Py_ssize_t size;
13548     wchar_t *result;
13549     wchar_t ch;
13550 
13551     if (!path_wide) { /* Default arg: "." */
13552         path_wide = L".";
13553         path_len = 1;
13554     }
13555     else {
13556         path_len = wcslen(path_wide);
13557     }
13558 
13559     /* The +1's are for the path separator and the NUL */
13560     size = path_len + 1 + wcslen(filename) + 1;
13561     result = PyMem_New(wchar_t, size);
13562     if (!result) {
13563         PyErr_NoMemory();
13564         return NULL;
13565     }
13566     wcscpy(result, path_wide);
13567     if (path_len > 0) {
13568         ch = result[path_len - 1];
13569         if (ch != SEP && ch != ALTSEP && ch != L':')
13570             result[path_len++] = SEP;
13571         wcscpy(result + path_len, filename);
13572     }
13573     return result;
13574 }
13575 
13576 static PyObject *
DirEntry_from_find_data(PyObject * module,path_t * path,WIN32_FIND_DATAW * dataW)13577 DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
13578 {
13579     DirEntry *entry;
13580     BY_HANDLE_FILE_INFORMATION file_info;
13581     ULONG reparse_tag;
13582     wchar_t *joined_path;
13583 
13584     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13585     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13586     if (!entry)
13587         return NULL;
13588     entry->name = NULL;
13589     entry->path = NULL;
13590     entry->stat = NULL;
13591     entry->lstat = NULL;
13592     entry->got_file_index = 0;
13593 
13594     entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
13595     if (!entry->name)
13596         goto error;
13597     if (path->narrow) {
13598         Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
13599         if (!entry->name)
13600             goto error;
13601     }
13602 
13603     joined_path = join_path_filenameW(path->wide, dataW->cFileName);
13604     if (!joined_path)
13605         goto error;
13606 
13607     entry->path = PyUnicode_FromWideChar(joined_path, -1);
13608     PyMem_Free(joined_path);
13609     if (!entry->path)
13610         goto error;
13611     if (path->narrow) {
13612         Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
13613         if (!entry->path)
13614             goto error;
13615     }
13616 
13617     find_data_to_file_info(dataW, &file_info, &reparse_tag);
13618     _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
13619 
13620     return (PyObject *)entry;
13621 
13622 error:
13623     Py_DECREF(entry);
13624     return NULL;
13625 }
13626 
13627 #else /* POSIX */
13628 
13629 static char *
join_path_filename(const char * path_narrow,const char * filename,Py_ssize_t filename_len)13630 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
13631 {
13632     Py_ssize_t path_len;
13633     Py_ssize_t size;
13634     char *result;
13635 
13636     if (!path_narrow) { /* Default arg: "." */
13637         path_narrow = ".";
13638         path_len = 1;
13639     }
13640     else {
13641         path_len = strlen(path_narrow);
13642     }
13643 
13644     if (filename_len == -1)
13645         filename_len = strlen(filename);
13646 
13647     /* The +1's are for the path separator and the NUL */
13648     size = path_len + 1 + filename_len + 1;
13649     result = PyMem_New(char, size);
13650     if (!result) {
13651         PyErr_NoMemory();
13652         return NULL;
13653     }
13654     strcpy(result, path_narrow);
13655     if (path_len > 0 && result[path_len - 1] != '/')
13656         result[path_len++] = '/';
13657     strcpy(result + path_len, filename);
13658     return result;
13659 }
13660 
13661 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)13662 DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
13663                          Py_ssize_t name_len, ino_t d_ino
13664 #ifdef HAVE_DIRENT_D_TYPE
13665                          , unsigned char d_type
13666 #endif
13667                          )
13668 {
13669     DirEntry *entry;
13670     char *joined_path;
13671 
13672     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13673     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13674     if (!entry)
13675         return NULL;
13676     entry->name = NULL;
13677     entry->path = NULL;
13678     entry->stat = NULL;
13679     entry->lstat = NULL;
13680 
13681     if (path->fd != -1) {
13682         entry->dir_fd = path->fd;
13683         joined_path = NULL;
13684     }
13685     else {
13686         entry->dir_fd = DEFAULT_DIR_FD;
13687         joined_path = join_path_filename(path->narrow, name, name_len);
13688         if (!joined_path)
13689             goto error;
13690     }
13691 
13692     if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
13693         entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
13694         if (joined_path)
13695             entry->path = PyUnicode_DecodeFSDefault(joined_path);
13696     }
13697     else {
13698         entry->name = PyBytes_FromStringAndSize(name, name_len);
13699         if (joined_path)
13700             entry->path = PyBytes_FromString(joined_path);
13701     }
13702     PyMem_Free(joined_path);
13703     if (!entry->name)
13704         goto error;
13705 
13706     if (path->fd != -1) {
13707         entry->path = entry->name;
13708         Py_INCREF(entry->path);
13709     }
13710     else if (!entry->path)
13711         goto error;
13712 
13713 #ifdef HAVE_DIRENT_D_TYPE
13714     entry->d_type = d_type;
13715 #endif
13716     entry->d_ino = d_ino;
13717 
13718     return (PyObject *)entry;
13719 
13720 error:
13721     Py_XDECREF(entry);
13722     return NULL;
13723 }
13724 
13725 #endif
13726 
13727 
13728 typedef struct {
13729     PyObject_HEAD
13730     path_t path;
13731 #ifdef MS_WINDOWS
13732     HANDLE handle;
13733     WIN32_FIND_DATAW file_data;
13734     int first_time;
13735 #else /* POSIX */
13736     DIR *dirp;
13737 #endif
13738 #ifdef HAVE_FDOPENDIR
13739     int fd;
13740 #endif
13741 } ScandirIterator;
13742 
13743 #ifdef MS_WINDOWS
13744 
13745 static int
ScandirIterator_is_closed(ScandirIterator * iterator)13746 ScandirIterator_is_closed(ScandirIterator *iterator)
13747 {
13748     return iterator->handle == INVALID_HANDLE_VALUE;
13749 }
13750 
13751 static void
ScandirIterator_closedir(ScandirIterator * iterator)13752 ScandirIterator_closedir(ScandirIterator *iterator)
13753 {
13754     HANDLE handle = iterator->handle;
13755 
13756     if (handle == INVALID_HANDLE_VALUE)
13757         return;
13758 
13759     iterator->handle = INVALID_HANDLE_VALUE;
13760     Py_BEGIN_ALLOW_THREADS
13761     FindClose(handle);
13762     Py_END_ALLOW_THREADS
13763 }
13764 
13765 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)13766 ScandirIterator_iternext(ScandirIterator *iterator)
13767 {
13768     WIN32_FIND_DATAW *file_data = &iterator->file_data;
13769     BOOL success;
13770     PyObject *entry;
13771 
13772     /* Happens if the iterator is iterated twice, or closed explicitly */
13773     if (iterator->handle == INVALID_HANDLE_VALUE)
13774         return NULL;
13775 
13776     while (1) {
13777         if (!iterator->first_time) {
13778             Py_BEGIN_ALLOW_THREADS
13779             success = FindNextFileW(iterator->handle, file_data);
13780             Py_END_ALLOW_THREADS
13781             if (!success) {
13782                 /* Error or no more files */
13783                 if (GetLastError() != ERROR_NO_MORE_FILES)
13784                     path_error(&iterator->path);
13785                 break;
13786             }
13787         }
13788         iterator->first_time = 0;
13789 
13790         /* Skip over . and .. */
13791         if (wcscmp(file_data->cFileName, L".") != 0 &&
13792             wcscmp(file_data->cFileName, L"..") != 0)
13793         {
13794             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
13795             entry = DirEntry_from_find_data(module, &iterator->path, file_data);
13796             if (!entry)
13797                 break;
13798             return entry;
13799         }
13800 
13801         /* Loop till we get a non-dot directory or finish iterating */
13802     }
13803 
13804     /* Error or no more files */
13805     ScandirIterator_closedir(iterator);
13806     return NULL;
13807 }
13808 
13809 #else /* POSIX */
13810 
13811 static int
ScandirIterator_is_closed(ScandirIterator * iterator)13812 ScandirIterator_is_closed(ScandirIterator *iterator)
13813 {
13814     return !iterator->dirp;
13815 }
13816 
13817 static void
ScandirIterator_closedir(ScandirIterator * iterator)13818 ScandirIterator_closedir(ScandirIterator *iterator)
13819 {
13820     DIR *dirp = iterator->dirp;
13821 
13822     if (!dirp)
13823         return;
13824 
13825     iterator->dirp = NULL;
13826     Py_BEGIN_ALLOW_THREADS
13827 #ifdef HAVE_FDOPENDIR
13828     if (iterator->path.fd != -1)
13829         rewinddir(dirp);
13830 #endif
13831     closedir(dirp);
13832     Py_END_ALLOW_THREADS
13833     return;
13834 }
13835 
13836 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)13837 ScandirIterator_iternext(ScandirIterator *iterator)
13838 {
13839     struct dirent *direntp;
13840     Py_ssize_t name_len;
13841     int is_dot;
13842     PyObject *entry;
13843 
13844     /* Happens if the iterator is iterated twice, or closed explicitly */
13845     if (!iterator->dirp)
13846         return NULL;
13847 
13848     while (1) {
13849         errno = 0;
13850         Py_BEGIN_ALLOW_THREADS
13851         direntp = readdir(iterator->dirp);
13852         Py_END_ALLOW_THREADS
13853 
13854         if (!direntp) {
13855             /* Error or no more files */
13856             if (errno != 0)
13857                 path_error(&iterator->path);
13858             break;
13859         }
13860 
13861         /* Skip over . and .. */
13862         name_len = NAMLEN(direntp);
13863         is_dot = direntp->d_name[0] == '.' &&
13864                  (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
13865         if (!is_dot) {
13866             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
13867             entry = DirEntry_from_posix_info(module,
13868                                              &iterator->path, direntp->d_name,
13869                                              name_len, direntp->d_ino
13870 #ifdef HAVE_DIRENT_D_TYPE
13871                                              , direntp->d_type
13872 #endif
13873                                             );
13874             if (!entry)
13875                 break;
13876             return entry;
13877         }
13878 
13879         /* Loop till we get a non-dot directory or finish iterating */
13880     }
13881 
13882     /* Error or no more files */
13883     ScandirIterator_closedir(iterator);
13884     return NULL;
13885 }
13886 
13887 #endif
13888 
13889 static PyObject *
ScandirIterator_close(ScandirIterator * self,PyObject * args)13890 ScandirIterator_close(ScandirIterator *self, PyObject *args)
13891 {
13892     ScandirIterator_closedir(self);
13893     Py_RETURN_NONE;
13894 }
13895 
13896 static PyObject *
ScandirIterator_enter(PyObject * self,PyObject * args)13897 ScandirIterator_enter(PyObject *self, PyObject *args)
13898 {
13899     Py_INCREF(self);
13900     return self;
13901 }
13902 
13903 static PyObject *
ScandirIterator_exit(ScandirIterator * self,PyObject * args)13904 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
13905 {
13906     ScandirIterator_closedir(self);
13907     Py_RETURN_NONE;
13908 }
13909 
13910 static void
ScandirIterator_finalize(ScandirIterator * iterator)13911 ScandirIterator_finalize(ScandirIterator *iterator)
13912 {
13913     PyObject *error_type, *error_value, *error_traceback;
13914 
13915     /* Save the current exception, if any. */
13916     PyErr_Fetch(&error_type, &error_value, &error_traceback);
13917 
13918     if (!ScandirIterator_is_closed(iterator)) {
13919         ScandirIterator_closedir(iterator);
13920 
13921         if (PyErr_ResourceWarning((PyObject *)iterator, 1,
13922                                   "unclosed scandir iterator %R", iterator)) {
13923             /* Spurious errors can appear at shutdown */
13924             if (PyErr_ExceptionMatches(PyExc_Warning)) {
13925                 PyErr_WriteUnraisable((PyObject *) iterator);
13926             }
13927         }
13928     }
13929 
13930     path_cleanup(&iterator->path);
13931 
13932     /* Restore the saved exception. */
13933     PyErr_Restore(error_type, error_value, error_traceback);
13934 }
13935 
13936 static void
ScandirIterator_dealloc(ScandirIterator * iterator)13937 ScandirIterator_dealloc(ScandirIterator *iterator)
13938 {
13939     PyTypeObject *tp = Py_TYPE(iterator);
13940     if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
13941         return;
13942 
13943     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13944     free_func(iterator);
13945     Py_DECREF(tp);
13946 }
13947 
13948 static PyMethodDef ScandirIterator_methods[] = {
13949     {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
13950     {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
13951     {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
13952     {NULL}
13953 };
13954 
13955 static PyType_Slot ScandirIteratorType_slots[] = {
13956     {Py_tp_new, _disabled_new},
13957     {Py_tp_dealloc, ScandirIterator_dealloc},
13958     {Py_tp_finalize, ScandirIterator_finalize},
13959     {Py_tp_iter, PyObject_SelfIter},
13960     {Py_tp_iternext, ScandirIterator_iternext},
13961     {Py_tp_methods, ScandirIterator_methods},
13962     {0, 0},
13963 };
13964 
13965 static PyType_Spec ScandirIteratorType_spec = {
13966     MODNAME ".ScandirIterator",
13967     sizeof(ScandirIterator),
13968     0,
13969     // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
13970     // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
13971     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE,
13972     ScandirIteratorType_slots
13973 };
13974 
13975 /*[clinic input]
13976 os.scandir
13977 
13978     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
13979 
13980 Return an iterator of DirEntry objects for given path.
13981 
13982 path can be specified as either str, bytes, or a path-like object.  If path
13983 is bytes, the names of yielded DirEntry objects will also be bytes; in
13984 all other circumstances they will be str.
13985 
13986 If path is None, uses the path='.'.
13987 [clinic start generated code]*/
13988 
13989 static PyObject *
os_scandir_impl(PyObject * module,path_t * path)13990 os_scandir_impl(PyObject *module, path_t *path)
13991 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
13992 {
13993     ScandirIterator *iterator;
13994 #ifdef MS_WINDOWS
13995     wchar_t *path_strW;
13996 #else
13997     const char *path_str;
13998 #ifdef HAVE_FDOPENDIR
13999     int fd = -1;
14000 #endif
14001 #endif
14002 
14003     if (PySys_Audit("os.scandir", "O",
14004                     path->object ? path->object : Py_None) < 0) {
14005         return NULL;
14006     }
14007 
14008     PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
14009     iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
14010     if (!iterator)
14011         return NULL;
14012 
14013 #ifdef MS_WINDOWS
14014     iterator->handle = INVALID_HANDLE_VALUE;
14015 #else
14016     iterator->dirp = NULL;
14017 #endif
14018 
14019     memcpy(&iterator->path, path, sizeof(path_t));
14020     /* Move the ownership to iterator->path */
14021     path->object = NULL;
14022     path->cleanup = NULL;
14023 
14024 #ifdef MS_WINDOWS
14025     iterator->first_time = 1;
14026 
14027     path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
14028     if (!path_strW)
14029         goto error;
14030 
14031     Py_BEGIN_ALLOW_THREADS
14032     iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
14033     Py_END_ALLOW_THREADS
14034 
14035     PyMem_Free(path_strW);
14036 
14037     if (iterator->handle == INVALID_HANDLE_VALUE) {
14038         path_error(&iterator->path);
14039         goto error;
14040     }
14041 #else /* POSIX */
14042     errno = 0;
14043 #ifdef HAVE_FDOPENDIR
14044     if (iterator->path.fd != -1) {
14045       if (HAVE_FDOPENDIR_RUNTIME) {
14046         /* closedir() closes the FD, so we duplicate it */
14047         fd = _Py_dup(path->fd);
14048         if (fd == -1)
14049             goto error;
14050 
14051         Py_BEGIN_ALLOW_THREADS
14052         iterator->dirp = fdopendir(fd);
14053         Py_END_ALLOW_THREADS
14054       } else {
14055         PyErr_SetString(PyExc_TypeError,
14056             "scandir: path should be string, bytes, os.PathLike or None, not int");
14057         return NULL;
14058       }
14059     }
14060     else
14061 #endif
14062     {
14063         if (iterator->path.narrow)
14064             path_str = iterator->path.narrow;
14065         else
14066             path_str = ".";
14067 
14068         Py_BEGIN_ALLOW_THREADS
14069         iterator->dirp = opendir(path_str);
14070         Py_END_ALLOW_THREADS
14071     }
14072 
14073     if (!iterator->dirp) {
14074         path_error(&iterator->path);
14075 #ifdef HAVE_FDOPENDIR
14076         if (fd != -1) {
14077             Py_BEGIN_ALLOW_THREADS
14078             close(fd);
14079             Py_END_ALLOW_THREADS
14080         }
14081 #endif
14082         goto error;
14083     }
14084 #endif
14085 
14086     return (PyObject *)iterator;
14087 
14088 error:
14089     Py_DECREF(iterator);
14090     return NULL;
14091 }
14092 
14093 /*
14094     Return the file system path representation of the object.
14095 
14096     If the object is str or bytes, then allow it to pass through with
14097     an incremented refcount. If the object defines __fspath__(), then
14098     return the result of that method. All other types raise a TypeError.
14099 */
14100 PyObject *
PyOS_FSPath(PyObject * path)14101 PyOS_FSPath(PyObject *path)
14102 {
14103     /* For error message reasons, this function is manually inlined in
14104        path_converter(). */
14105     PyObject *func = NULL;
14106     PyObject *path_repr = NULL;
14107 
14108     if (PyUnicode_Check(path) || PyBytes_Check(path)) {
14109         Py_INCREF(path);
14110         return path;
14111     }
14112 
14113     func = _PyObject_LookupSpecial(path, &PyId___fspath__);
14114     if (NULL == func) {
14115         return PyErr_Format(PyExc_TypeError,
14116                             "expected str, bytes or os.PathLike object, "
14117                             "not %.200s",
14118                             _PyType_Name(Py_TYPE(path)));
14119     }
14120 
14121     path_repr = _PyObject_CallNoArg(func);
14122     Py_DECREF(func);
14123     if (NULL == path_repr) {
14124         return NULL;
14125     }
14126 
14127     if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
14128         PyErr_Format(PyExc_TypeError,
14129                      "expected %.200s.__fspath__() to return str or bytes, "
14130                      "not %.200s", _PyType_Name(Py_TYPE(path)),
14131                      _PyType_Name(Py_TYPE(path_repr)));
14132         Py_DECREF(path_repr);
14133         return NULL;
14134     }
14135 
14136     return path_repr;
14137 }
14138 
14139 /*[clinic input]
14140 os.fspath
14141 
14142     path: object
14143 
14144 Return the file system path representation of the object.
14145 
14146 If the object is str or bytes, then allow it to pass through as-is. If the
14147 object defines __fspath__(), then return the result of that method. All other
14148 types raise a TypeError.
14149 [clinic start generated code]*/
14150 
14151 static PyObject *
os_fspath_impl(PyObject * module,PyObject * path)14152 os_fspath_impl(PyObject *module, PyObject *path)
14153 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
14154 {
14155     return PyOS_FSPath(path);
14156 }
14157 
14158 #ifdef HAVE_GETRANDOM_SYSCALL
14159 /*[clinic input]
14160 os.getrandom
14161 
14162     size: Py_ssize_t
14163     flags: int=0
14164 
14165 Obtain a series of random bytes.
14166 [clinic start generated code]*/
14167 
14168 static PyObject *
os_getrandom_impl(PyObject * module,Py_ssize_t size,int flags)14169 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
14170 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
14171 {
14172     PyObject *bytes;
14173     Py_ssize_t n;
14174 
14175     if (size < 0) {
14176         errno = EINVAL;
14177         return posix_error();
14178     }
14179 
14180     bytes = PyBytes_FromStringAndSize(NULL, size);
14181     if (bytes == NULL) {
14182         PyErr_NoMemory();
14183         return NULL;
14184     }
14185 
14186     while (1) {
14187         n = syscall(SYS_getrandom,
14188                     PyBytes_AS_STRING(bytes),
14189                     PyBytes_GET_SIZE(bytes),
14190                     flags);
14191         if (n < 0 && errno == EINTR) {
14192             if (PyErr_CheckSignals() < 0) {
14193                 goto error;
14194             }
14195 
14196             /* getrandom() was interrupted by a signal: retry */
14197             continue;
14198         }
14199         break;
14200     }
14201 
14202     if (n < 0) {
14203         PyErr_SetFromErrno(PyExc_OSError);
14204         goto error;
14205     }
14206 
14207     if (n != size) {
14208         _PyBytes_Resize(&bytes, n);
14209     }
14210 
14211     return bytes;
14212 
14213 error:
14214     Py_DECREF(bytes);
14215     return NULL;
14216 }
14217 #endif   /* HAVE_GETRANDOM_SYSCALL */
14218 
14219 #ifdef MS_WINDOWS
14220 /* bpo-36085: Helper functions for managing DLL search directories
14221  * on win32
14222  */
14223 
14224 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
14225 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
14226 
14227 /*[clinic input]
14228 os._add_dll_directory
14229 
14230     path: path_t
14231 
14232 Add a path to the DLL search path.
14233 
14234 This search path is used when resolving dependencies for imported
14235 extension modules (the module itself is resolved through sys.path),
14236 and also by ctypes.
14237 
14238 Returns an opaque value that may be passed to os.remove_dll_directory
14239 to remove this directory from the search path.
14240 [clinic start generated code]*/
14241 
14242 static PyObject *
os__add_dll_directory_impl(PyObject * module,path_t * path)14243 os__add_dll_directory_impl(PyObject *module, path_t *path)
14244 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
14245 {
14246     HMODULE hKernel32;
14247     PAddDllDirectory AddDllDirectory;
14248     DLL_DIRECTORY_COOKIE cookie = 0;
14249     DWORD err = 0;
14250 
14251     if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
14252         return NULL;
14253     }
14254 
14255     /* For Windows 7, we have to load this. As this will be a fairly
14256        infrequent operation, just do it each time. Kernel32 is always
14257        loaded. */
14258     Py_BEGIN_ALLOW_THREADS
14259     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14260         !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
14261             hKernel32, "AddDllDirectory")) ||
14262         !(cookie = (*AddDllDirectory)(path->wide))) {
14263         err = GetLastError();
14264     }
14265     Py_END_ALLOW_THREADS
14266 
14267     if (err) {
14268         return win32_error_object_err("add_dll_directory",
14269                                       path->object, err);
14270     }
14271 
14272     return PyCapsule_New(cookie, "DLL directory cookie", NULL);
14273 }
14274 
14275 /*[clinic input]
14276 os._remove_dll_directory
14277 
14278     cookie: object
14279 
14280 Removes a path from the DLL search path.
14281 
14282 The parameter is an opaque value that was returned from
14283 os.add_dll_directory. You can only remove directories that you added
14284 yourself.
14285 [clinic start generated code]*/
14286 
14287 static PyObject *
os__remove_dll_directory_impl(PyObject * module,PyObject * cookie)14288 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
14289 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
14290 {
14291     HMODULE hKernel32;
14292     PRemoveDllDirectory RemoveDllDirectory;
14293     DLL_DIRECTORY_COOKIE cookieValue;
14294     DWORD err = 0;
14295 
14296     if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
14297         PyErr_SetString(PyExc_TypeError,
14298             "Provided cookie was not returned from os.add_dll_directory");
14299         return NULL;
14300     }
14301 
14302     cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
14303         cookie, "DLL directory cookie");
14304 
14305     /* For Windows 7, we have to load this. As this will be a fairly
14306        infrequent operation, just do it each time. Kernel32 is always
14307        loaded. */
14308     Py_BEGIN_ALLOW_THREADS
14309     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14310         !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
14311             hKernel32, "RemoveDllDirectory")) ||
14312         !(*RemoveDllDirectory)(cookieValue)) {
14313         err = GetLastError();
14314     }
14315     Py_END_ALLOW_THREADS
14316 
14317     if (err) {
14318         return win32_error_object_err("remove_dll_directory",
14319                                       NULL, err);
14320     }
14321 
14322     if (PyCapsule_SetName(cookie, NULL)) {
14323         return NULL;
14324     }
14325 
14326     Py_RETURN_NONE;
14327 }
14328 
14329 #endif
14330 
14331 
14332 /* Only check if WIFEXITED is available: expect that it comes
14333    with WEXITSTATUS, WIFSIGNALED, etc.
14334 
14335    os.waitstatus_to_exitcode() is implemented in C and not in Python, so
14336    subprocess can safely call it during late Python finalization without
14337    risking that used os attributes were set to None by _PyImport_Cleanup(). */
14338 #if defined(WIFEXITED) || defined(MS_WINDOWS)
14339 /*[clinic input]
14340 os.waitstatus_to_exitcode
14341 
14342     status as status_obj: object
14343 
14344 Convert a wait status to an exit code.
14345 
14346 On Unix:
14347 
14348 * If WIFEXITED(status) is true, return WEXITSTATUS(status).
14349 * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
14350 * Otherwise, raise a ValueError.
14351 
14352 On Windows, return status shifted right by 8 bits.
14353 
14354 On Unix, if the process is being traced or if waitpid() was called with
14355 WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
14356 This function must not be called if WIFSTOPPED(status) is true.
14357 [clinic start generated code]*/
14358 
14359 static PyObject *
os_waitstatus_to_exitcode_impl(PyObject * module,PyObject * status_obj)14360 os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
14361 /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
14362 {
14363     if (PyFloat_Check(status_obj)) {
14364         PyErr_SetString(PyExc_TypeError,
14365                         "integer argument expected, got float" );
14366         return NULL;
14367     }
14368 #ifndef MS_WINDOWS
14369     int status = _PyLong_AsInt(status_obj);
14370     if (status == -1 && PyErr_Occurred()) {
14371         return NULL;
14372     }
14373 
14374     WAIT_TYPE wait_status;
14375     WAIT_STATUS_INT(wait_status) = status;
14376     int exitcode;
14377     if (WIFEXITED(wait_status)) {
14378         exitcode = WEXITSTATUS(wait_status);
14379         /* Sanity check to provide warranty on the function behavior.
14380            It should not occur in practice */
14381         if (exitcode < 0) {
14382             PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
14383             return NULL;
14384         }
14385     }
14386     else if (WIFSIGNALED(wait_status)) {
14387         int signum = WTERMSIG(wait_status);
14388         /* Sanity check to provide warranty on the function behavior.
14389            It should not occurs in practice */
14390         if (signum <= 0) {
14391             PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
14392             return NULL;
14393         }
14394         exitcode = -signum;
14395     } else if (WIFSTOPPED(wait_status)) {
14396         /* Status only received if the process is being traced
14397            or if waitpid() was called with WUNTRACED option. */
14398         int signum = WSTOPSIG(wait_status);
14399         PyErr_Format(PyExc_ValueError,
14400                      "process stopped by delivery of signal %i",
14401                      signum);
14402         return NULL;
14403     }
14404     else {
14405         PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
14406         return NULL;
14407     }
14408     return PyLong_FromLong(exitcode);
14409 #else
14410     /* Windows implementation: see os.waitpid() implementation
14411        which uses _cwait(). */
14412     unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
14413     if (status == (unsigned long long)-1 && PyErr_Occurred()) {
14414         return NULL;
14415     }
14416 
14417     unsigned long long exitcode = (status >> 8);
14418     /* ExitProcess() accepts an UINT type:
14419        reject exit code which doesn't fit in an UINT */
14420     if (exitcode > UINT_MAX) {
14421         PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
14422         return NULL;
14423     }
14424     return PyLong_FromUnsignedLong((unsigned long)exitcode);
14425 #endif
14426 }
14427 #endif
14428 
14429 
14430 static PyMethodDef posix_methods[] = {
14431 
14432     OS_STAT_METHODDEF
14433     OS_ACCESS_METHODDEF
14434     OS_TTYNAME_METHODDEF
14435     OS_CHDIR_METHODDEF
14436     OS_CHFLAGS_METHODDEF
14437     OS_CHMOD_METHODDEF
14438     OS_FCHMOD_METHODDEF
14439     OS_LCHMOD_METHODDEF
14440     OS_CHOWN_METHODDEF
14441     OS_FCHOWN_METHODDEF
14442     OS_LCHOWN_METHODDEF
14443     OS_LCHFLAGS_METHODDEF
14444     OS_CHROOT_METHODDEF
14445     OS_CTERMID_METHODDEF
14446     OS_GETCWD_METHODDEF
14447     OS_GETCWDB_METHODDEF
14448     OS_LINK_METHODDEF
14449     OS_LISTDIR_METHODDEF
14450     OS_LSTAT_METHODDEF
14451     OS_MKDIR_METHODDEF
14452     OS_NICE_METHODDEF
14453     OS_GETPRIORITY_METHODDEF
14454     OS_SETPRIORITY_METHODDEF
14455     OS_POSIX_SPAWN_METHODDEF
14456     OS_POSIX_SPAWNP_METHODDEF
14457     OS_READLINK_METHODDEF
14458     OS_COPY_FILE_RANGE_METHODDEF
14459     OS_RENAME_METHODDEF
14460     OS_REPLACE_METHODDEF
14461     OS_RMDIR_METHODDEF
14462     OS_SYMLINK_METHODDEF
14463     OS_SYSTEM_METHODDEF
14464     OS_UMASK_METHODDEF
14465     OS_UNAME_METHODDEF
14466     OS_UNLINK_METHODDEF
14467     OS_REMOVE_METHODDEF
14468     OS_UTIME_METHODDEF
14469     OS_TIMES_METHODDEF
14470     OS__EXIT_METHODDEF
14471     OS__FCOPYFILE_METHODDEF
14472     OS_EXECV_METHODDEF
14473     OS_EXECVE_METHODDEF
14474     OS_SPAWNV_METHODDEF
14475     OS_SPAWNVE_METHODDEF
14476     OS_FORK1_METHODDEF
14477     OS_FORK_METHODDEF
14478     OS_REGISTER_AT_FORK_METHODDEF
14479     OS_SCHED_GET_PRIORITY_MAX_METHODDEF
14480     OS_SCHED_GET_PRIORITY_MIN_METHODDEF
14481     OS_SCHED_GETPARAM_METHODDEF
14482     OS_SCHED_GETSCHEDULER_METHODDEF
14483     OS_SCHED_RR_GET_INTERVAL_METHODDEF
14484     OS_SCHED_SETPARAM_METHODDEF
14485     OS_SCHED_SETSCHEDULER_METHODDEF
14486     OS_SCHED_YIELD_METHODDEF
14487     OS_SCHED_SETAFFINITY_METHODDEF
14488     OS_SCHED_GETAFFINITY_METHODDEF
14489     OS_OPENPTY_METHODDEF
14490     OS_FORKPTY_METHODDEF
14491     OS_GETEGID_METHODDEF
14492     OS_GETEUID_METHODDEF
14493     OS_GETGID_METHODDEF
14494     OS_GETGROUPLIST_METHODDEF
14495     OS_GETGROUPS_METHODDEF
14496     OS_GETPID_METHODDEF
14497     OS_GETPGRP_METHODDEF
14498     OS_GETPPID_METHODDEF
14499     OS_GETUID_METHODDEF
14500     OS_GETLOGIN_METHODDEF
14501     OS_KILL_METHODDEF
14502     OS_KILLPG_METHODDEF
14503     OS_PLOCK_METHODDEF
14504     OS_STARTFILE_METHODDEF
14505     OS_SETUID_METHODDEF
14506     OS_SETEUID_METHODDEF
14507     OS_SETREUID_METHODDEF
14508     OS_SETGID_METHODDEF
14509     OS_SETEGID_METHODDEF
14510     OS_SETREGID_METHODDEF
14511     OS_SETGROUPS_METHODDEF
14512     OS_INITGROUPS_METHODDEF
14513     OS_GETPGID_METHODDEF
14514     OS_SETPGRP_METHODDEF
14515     OS_WAIT_METHODDEF
14516     OS_WAIT3_METHODDEF
14517     OS_WAIT4_METHODDEF
14518     OS_WAITID_METHODDEF
14519     OS_WAITPID_METHODDEF
14520     OS_PIDFD_OPEN_METHODDEF
14521     OS_GETSID_METHODDEF
14522     OS_SETSID_METHODDEF
14523     OS_SETPGID_METHODDEF
14524     OS_TCGETPGRP_METHODDEF
14525     OS_TCSETPGRP_METHODDEF
14526     OS_OPEN_METHODDEF
14527     OS_CLOSE_METHODDEF
14528     OS_CLOSERANGE_METHODDEF
14529     OS_DEVICE_ENCODING_METHODDEF
14530     OS_DUP_METHODDEF
14531     OS_DUP2_METHODDEF
14532     OS_LOCKF_METHODDEF
14533     OS_LSEEK_METHODDEF
14534     OS_READ_METHODDEF
14535     OS_READV_METHODDEF
14536     OS_PREAD_METHODDEF
14537     OS_PREADV_METHODDEF
14538     OS_WRITE_METHODDEF
14539     OS_WRITEV_METHODDEF
14540     OS_PWRITE_METHODDEF
14541     OS_PWRITEV_METHODDEF
14542     OS_SENDFILE_METHODDEF
14543     OS_FSTAT_METHODDEF
14544     OS_ISATTY_METHODDEF
14545     OS_PIPE_METHODDEF
14546     OS_PIPE2_METHODDEF
14547     OS_MKFIFO_METHODDEF
14548     OS_MKNOD_METHODDEF
14549     OS_MAJOR_METHODDEF
14550     OS_MINOR_METHODDEF
14551     OS_MAKEDEV_METHODDEF
14552     OS_FTRUNCATE_METHODDEF
14553     OS_TRUNCATE_METHODDEF
14554     OS_POSIX_FALLOCATE_METHODDEF
14555     OS_POSIX_FADVISE_METHODDEF
14556     OS_PUTENV_METHODDEF
14557     OS_UNSETENV_METHODDEF
14558     OS_STRERROR_METHODDEF
14559     OS_FCHDIR_METHODDEF
14560     OS_FSYNC_METHODDEF
14561     OS_SYNC_METHODDEF
14562     OS_FDATASYNC_METHODDEF
14563     OS_WCOREDUMP_METHODDEF
14564     OS_WIFCONTINUED_METHODDEF
14565     OS_WIFSTOPPED_METHODDEF
14566     OS_WIFSIGNALED_METHODDEF
14567     OS_WIFEXITED_METHODDEF
14568     OS_WEXITSTATUS_METHODDEF
14569     OS_WTERMSIG_METHODDEF
14570     OS_WSTOPSIG_METHODDEF
14571     OS_FSTATVFS_METHODDEF
14572     OS_STATVFS_METHODDEF
14573     OS_CONFSTR_METHODDEF
14574     OS_SYSCONF_METHODDEF
14575     OS_FPATHCONF_METHODDEF
14576     OS_PATHCONF_METHODDEF
14577     OS_ABORT_METHODDEF
14578     OS__GETFULLPATHNAME_METHODDEF
14579     OS__GETDISKUSAGE_METHODDEF
14580     OS__GETFINALPATHNAME_METHODDEF
14581     OS__GETVOLUMEPATHNAME_METHODDEF
14582     OS_GETLOADAVG_METHODDEF
14583     OS_URANDOM_METHODDEF
14584     OS_SETRESUID_METHODDEF
14585     OS_SETRESGID_METHODDEF
14586     OS_GETRESUID_METHODDEF
14587     OS_GETRESGID_METHODDEF
14588 
14589     OS_GETXATTR_METHODDEF
14590     OS_SETXATTR_METHODDEF
14591     OS_REMOVEXATTR_METHODDEF
14592     OS_LISTXATTR_METHODDEF
14593 
14594     OS_GET_TERMINAL_SIZE_METHODDEF
14595     OS_CPU_COUNT_METHODDEF
14596     OS_GET_INHERITABLE_METHODDEF
14597     OS_SET_INHERITABLE_METHODDEF
14598     OS_GET_HANDLE_INHERITABLE_METHODDEF
14599     OS_SET_HANDLE_INHERITABLE_METHODDEF
14600     OS_GET_BLOCKING_METHODDEF
14601     OS_SET_BLOCKING_METHODDEF
14602     OS_SCANDIR_METHODDEF
14603     OS_FSPATH_METHODDEF
14604     OS_GETRANDOM_METHODDEF
14605     OS_MEMFD_CREATE_METHODDEF
14606     OS__ADD_DLL_DIRECTORY_METHODDEF
14607     OS__REMOVE_DLL_DIRECTORY_METHODDEF
14608     OS_WAITSTATUS_TO_EXITCODE_METHODDEF
14609     {NULL,              NULL}            /* Sentinel */
14610 };
14611 
14612 static int
all_ins(PyObject * m)14613 all_ins(PyObject *m)
14614 {
14615 #ifdef F_OK
14616     if (PyModule_AddIntMacro(m, F_OK)) return -1;
14617 #endif
14618 #ifdef R_OK
14619     if (PyModule_AddIntMacro(m, R_OK)) return -1;
14620 #endif
14621 #ifdef W_OK
14622     if (PyModule_AddIntMacro(m, W_OK)) return -1;
14623 #endif
14624 #ifdef X_OK
14625     if (PyModule_AddIntMacro(m, X_OK)) return -1;
14626 #endif
14627 #ifdef NGROUPS_MAX
14628     if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
14629 #endif
14630 #ifdef TMP_MAX
14631     if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
14632 #endif
14633 #ifdef WCONTINUED
14634     if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
14635 #endif
14636 #ifdef WNOHANG
14637     if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
14638 #endif
14639 #ifdef WUNTRACED
14640     if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
14641 #endif
14642 #ifdef O_RDONLY
14643     if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
14644 #endif
14645 #ifdef O_WRONLY
14646     if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
14647 #endif
14648 #ifdef O_RDWR
14649     if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
14650 #endif
14651 #ifdef O_NDELAY
14652     if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
14653 #endif
14654 #ifdef O_NONBLOCK
14655     if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
14656 #endif
14657 #ifdef O_APPEND
14658     if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
14659 #endif
14660 #ifdef O_DSYNC
14661     if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
14662 #endif
14663 #ifdef O_RSYNC
14664     if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
14665 #endif
14666 #ifdef O_SYNC
14667     if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
14668 #endif
14669 #ifdef O_NOCTTY
14670     if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
14671 #endif
14672 #ifdef O_CREAT
14673     if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
14674 #endif
14675 #ifdef O_EXCL
14676     if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
14677 #endif
14678 #ifdef O_TRUNC
14679     if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
14680 #endif
14681 #ifdef O_BINARY
14682     if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
14683 #endif
14684 #ifdef O_TEXT
14685     if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
14686 #endif
14687 #ifdef O_XATTR
14688     if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
14689 #endif
14690 #ifdef O_LARGEFILE
14691     if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
14692 #endif
14693 #ifndef __GNU__
14694 #ifdef O_SHLOCK
14695     if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
14696 #endif
14697 #ifdef O_EXLOCK
14698     if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
14699 #endif
14700 #endif
14701 #ifdef O_EXEC
14702     if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
14703 #endif
14704 #ifdef O_SEARCH
14705     if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
14706 #endif
14707 #ifdef O_PATH
14708     if (PyModule_AddIntMacro(m, O_PATH)) return -1;
14709 #endif
14710 #ifdef O_TTY_INIT
14711     if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
14712 #endif
14713 #ifdef O_TMPFILE
14714     if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
14715 #endif
14716 #ifdef PRIO_PROCESS
14717     if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
14718 #endif
14719 #ifdef PRIO_PGRP
14720     if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
14721 #endif
14722 #ifdef PRIO_USER
14723     if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
14724 #endif
14725 #ifdef O_CLOEXEC
14726     if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
14727 #endif
14728 #ifdef O_ACCMODE
14729     if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
14730 #endif
14731 
14732 
14733 #ifdef SEEK_HOLE
14734     if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
14735 #endif
14736 #ifdef SEEK_DATA
14737     if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
14738 #endif
14739 
14740 /* MS Windows */
14741 #ifdef O_NOINHERIT
14742     /* Don't inherit in child processes. */
14743     if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
14744 #endif
14745 #ifdef _O_SHORT_LIVED
14746     /* Optimize for short life (keep in memory). */
14747     /* MS forgot to define this one with a non-underscore form too. */
14748     if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
14749 #endif
14750 #ifdef O_TEMPORARY
14751     /* Automatically delete when last handle is closed. */
14752     if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
14753 #endif
14754 #ifdef O_RANDOM
14755     /* Optimize for random access. */
14756     if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
14757 #endif
14758 #ifdef O_SEQUENTIAL
14759     /* Optimize for sequential access. */
14760     if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
14761 #endif
14762 
14763 /* GNU extensions. */
14764 #ifdef O_ASYNC
14765     /* Send a SIGIO signal whenever input or output
14766        becomes available on file descriptor */
14767     if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
14768 #endif
14769 #ifdef O_DIRECT
14770     /* Direct disk access. */
14771     if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
14772 #endif
14773 #ifdef O_DIRECTORY
14774     /* Must be a directory.      */
14775     if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
14776 #endif
14777 #ifdef O_NOFOLLOW
14778     /* Do not follow links.      */
14779     if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
14780 #endif
14781 #ifdef O_NOLINKS
14782     /* Fails if link count of the named file is greater than 1 */
14783     if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
14784 #endif
14785 #ifdef O_NOATIME
14786     /* Do not update the access time. */
14787     if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
14788 #endif
14789 
14790     /* These come from sysexits.h */
14791 #ifdef EX_OK
14792     if (PyModule_AddIntMacro(m, EX_OK)) return -1;
14793 #endif /* EX_OK */
14794 #ifdef EX_USAGE
14795     if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
14796 #endif /* EX_USAGE */
14797 #ifdef EX_DATAERR
14798     if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
14799 #endif /* EX_DATAERR */
14800 #ifdef EX_NOINPUT
14801     if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
14802 #endif /* EX_NOINPUT */
14803 #ifdef EX_NOUSER
14804     if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
14805 #endif /* EX_NOUSER */
14806 #ifdef EX_NOHOST
14807     if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
14808 #endif /* EX_NOHOST */
14809 #ifdef EX_UNAVAILABLE
14810     if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
14811 #endif /* EX_UNAVAILABLE */
14812 #ifdef EX_SOFTWARE
14813     if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
14814 #endif /* EX_SOFTWARE */
14815 #ifdef EX_OSERR
14816     if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
14817 #endif /* EX_OSERR */
14818 #ifdef EX_OSFILE
14819     if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
14820 #endif /* EX_OSFILE */
14821 #ifdef EX_CANTCREAT
14822     if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
14823 #endif /* EX_CANTCREAT */
14824 #ifdef EX_IOERR
14825     if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
14826 #endif /* EX_IOERR */
14827 #ifdef EX_TEMPFAIL
14828     if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
14829 #endif /* EX_TEMPFAIL */
14830 #ifdef EX_PROTOCOL
14831     if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
14832 #endif /* EX_PROTOCOL */
14833 #ifdef EX_NOPERM
14834     if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
14835 #endif /* EX_NOPERM */
14836 #ifdef EX_CONFIG
14837     if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
14838 #endif /* EX_CONFIG */
14839 #ifdef EX_NOTFOUND
14840     if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
14841 #endif /* EX_NOTFOUND */
14842 
14843     /* statvfs */
14844 #ifdef ST_RDONLY
14845     if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
14846 #endif /* ST_RDONLY */
14847 #ifdef ST_NOSUID
14848     if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
14849 #endif /* ST_NOSUID */
14850 
14851        /* GNU extensions */
14852 #ifdef ST_NODEV
14853     if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
14854 #endif /* ST_NODEV */
14855 #ifdef ST_NOEXEC
14856     if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
14857 #endif /* ST_NOEXEC */
14858 #ifdef ST_SYNCHRONOUS
14859     if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
14860 #endif /* ST_SYNCHRONOUS */
14861 #ifdef ST_MANDLOCK
14862     if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
14863 #endif /* ST_MANDLOCK */
14864 #ifdef ST_WRITE
14865     if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
14866 #endif /* ST_WRITE */
14867 #ifdef ST_APPEND
14868     if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
14869 #endif /* ST_APPEND */
14870 #ifdef ST_NOATIME
14871     if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
14872 #endif /* ST_NOATIME */
14873 #ifdef ST_NODIRATIME
14874     if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
14875 #endif /* ST_NODIRATIME */
14876 #ifdef ST_RELATIME
14877     if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
14878 #endif /* ST_RELATIME */
14879 
14880     /* FreeBSD sendfile() constants */
14881 #ifdef SF_NODISKIO
14882     if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
14883 #endif
14884 #ifdef SF_MNOWAIT
14885     if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
14886 #endif
14887 #ifdef SF_SYNC
14888     if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
14889 #endif
14890 
14891     /* constants for posix_fadvise */
14892 #ifdef POSIX_FADV_NORMAL
14893     if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
14894 #endif
14895 #ifdef POSIX_FADV_SEQUENTIAL
14896     if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
14897 #endif
14898 #ifdef POSIX_FADV_RANDOM
14899     if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
14900 #endif
14901 #ifdef POSIX_FADV_NOREUSE
14902     if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
14903 #endif
14904 #ifdef POSIX_FADV_WILLNEED
14905     if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
14906 #endif
14907 #ifdef POSIX_FADV_DONTNEED
14908     if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
14909 #endif
14910 
14911     /* constants for waitid */
14912 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
14913     if (PyModule_AddIntMacro(m, P_PID)) return -1;
14914     if (PyModule_AddIntMacro(m, P_PGID)) return -1;
14915     if (PyModule_AddIntMacro(m, P_ALL)) return -1;
14916 #ifdef P_PIDFD
14917     if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
14918 #endif
14919 #endif
14920 #ifdef WEXITED
14921     if (PyModule_AddIntMacro(m, WEXITED)) return -1;
14922 #endif
14923 #ifdef WNOWAIT
14924     if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
14925 #endif
14926 #ifdef WSTOPPED
14927     if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
14928 #endif
14929 #ifdef CLD_EXITED
14930     if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
14931 #endif
14932 #ifdef CLD_KILLED
14933     if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
14934 #endif
14935 #ifdef CLD_DUMPED
14936     if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
14937 #endif
14938 #ifdef CLD_TRAPPED
14939     if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
14940 #endif
14941 #ifdef CLD_STOPPED
14942     if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
14943 #endif
14944 #ifdef CLD_CONTINUED
14945     if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
14946 #endif
14947 
14948     /* constants for lockf */
14949 #ifdef F_LOCK
14950     if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
14951 #endif
14952 #ifdef F_TLOCK
14953     if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
14954 #endif
14955 #ifdef F_ULOCK
14956     if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
14957 #endif
14958 #ifdef F_TEST
14959     if (PyModule_AddIntMacro(m, F_TEST)) return -1;
14960 #endif
14961 
14962 #ifdef RWF_DSYNC
14963     if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
14964 #endif
14965 #ifdef RWF_HIPRI
14966     if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
14967 #endif
14968 #ifdef RWF_SYNC
14969     if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
14970 #endif
14971 #ifdef RWF_NOWAIT
14972     if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
14973 #endif
14974 
14975 /* constants for posix_spawn */
14976 #ifdef HAVE_POSIX_SPAWN
14977     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
14978     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
14979     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
14980 #endif
14981 
14982 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
14983     if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
14984     if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
14985     if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
14986 #endif
14987 #ifdef HAVE_SPAWNV
14988     if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
14989     if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
14990 #endif
14991 
14992 #ifdef HAVE_SCHED_H
14993 #ifdef SCHED_OTHER
14994     if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
14995 #endif
14996 #ifdef SCHED_FIFO
14997     if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
14998 #endif
14999 #ifdef SCHED_RR
15000     if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
15001 #endif
15002 #ifdef SCHED_SPORADIC
15003     if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
15004 #endif
15005 #ifdef SCHED_BATCH
15006     if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
15007 #endif
15008 #ifdef SCHED_IDLE
15009     if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
15010 #endif
15011 #ifdef SCHED_RESET_ON_FORK
15012     if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
15013 #endif
15014 #ifdef SCHED_SYS
15015     if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
15016 #endif
15017 #ifdef SCHED_IA
15018     if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
15019 #endif
15020 #ifdef SCHED_FSS
15021     if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
15022 #endif
15023 #ifdef SCHED_FX
15024     if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
15025 #endif
15026 #endif
15027 
15028 #ifdef USE_XATTRS
15029     if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
15030     if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
15031     if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
15032 #endif
15033 
15034 #if HAVE_DECL_RTLD_LAZY
15035     if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
15036 #endif
15037 #if HAVE_DECL_RTLD_NOW
15038     if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
15039 #endif
15040 #if HAVE_DECL_RTLD_GLOBAL
15041     if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
15042 #endif
15043 #if HAVE_DECL_RTLD_LOCAL
15044     if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
15045 #endif
15046 #if HAVE_DECL_RTLD_NODELETE
15047     if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
15048 #endif
15049 #if HAVE_DECL_RTLD_NOLOAD
15050     if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
15051 #endif
15052 #if HAVE_DECL_RTLD_DEEPBIND
15053     if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
15054 #endif
15055 #if HAVE_DECL_RTLD_MEMBER
15056     if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
15057 #endif
15058 
15059 #ifdef HAVE_GETRANDOM_SYSCALL
15060     if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
15061     if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
15062 #endif
15063 #ifdef HAVE_MEMFD_CREATE
15064     if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
15065     if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
15066 #ifdef MFD_HUGETLB
15067     if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
15068 #endif
15069 #ifdef MFD_HUGE_SHIFT
15070     if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
15071 #endif
15072 #ifdef MFD_HUGE_MASK
15073     if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
15074 #endif
15075 #ifdef MFD_HUGE_64KB
15076     if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
15077 #endif
15078 #ifdef MFD_HUGE_512KB
15079     if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
15080 #endif
15081 #ifdef MFD_HUGE_1MB
15082     if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
15083 #endif
15084 #ifdef MFD_HUGE_2MB
15085     if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
15086 #endif
15087 #ifdef MFD_HUGE_8MB
15088     if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
15089 #endif
15090 #ifdef MFD_HUGE_16MB
15091     if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
15092 #endif
15093 #ifdef MFD_HUGE_32MB
15094     if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
15095 #endif
15096 #ifdef MFD_HUGE_256MB
15097     if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
15098 #endif
15099 #ifdef MFD_HUGE_512MB
15100     if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
15101 #endif
15102 #ifdef MFD_HUGE_1GB
15103     if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
15104 #endif
15105 #ifdef MFD_HUGE_2GB
15106     if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
15107 #endif
15108 #ifdef MFD_HUGE_16GB
15109     if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
15110 #endif
15111 #endif
15112 
15113 #if defined(__APPLE__)
15114     if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
15115 #endif
15116 
15117 #ifdef MS_WINDOWS
15118     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
15119     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
15120     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
15121     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
15122     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
15123 #endif
15124 
15125     return 0;
15126 }
15127 
15128 
15129 
15130 #define PROBE(name, test) \
15131    static int name(void)  \
15132    {                      \
15133       if (test) {        \
15134           return 1;       \
15135       } else {            \
15136           return 0;       \
15137       }                   \
15138    }
15139 
15140 #ifdef HAVE_FSTATAT
15141 PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
15142 #endif
15143 
15144 #ifdef HAVE_FACCESSAT
15145 PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
15146 #endif
15147 
15148 #ifdef HAVE_FCHMODAT
15149 PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
15150 #endif
15151 
15152 #ifdef HAVE_FCHOWNAT
15153 PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
15154 #endif
15155 
15156 #ifdef HAVE_LINKAT
15157 PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
15158 #endif
15159 
15160 #ifdef HAVE_FDOPENDIR
15161 PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
15162 #endif
15163 
15164 #ifdef HAVE_MKDIRAT
15165 PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
15166 #endif
15167 
15168 #ifdef HAVE_RENAMEAT
15169 PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
15170 #endif
15171 
15172 #ifdef HAVE_UNLINKAT
15173 PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
15174 #endif
15175 
15176 #ifdef HAVE_OPENAT
15177 PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
15178 #endif
15179 
15180 #ifdef HAVE_READLINKAT
15181 PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
15182 #endif
15183 
15184 #ifdef HAVE_SYMLINKAT
15185 PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
15186 #endif
15187 
15188 #ifdef HAVE_FUTIMENS
15189 PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
15190 #endif
15191 
15192 #ifdef HAVE_UTIMENSAT
15193 PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
15194 #endif
15195 
15196 
15197 
15198 
15199 static const struct have_function {
15200     const char * const label;
15201     int (*probe)(void);
15202 } have_functions[] = {
15203 
15204 #ifdef HAVE_FACCESSAT
15205     { "HAVE_FACCESSAT", probe_faccessat },
15206 #endif
15207 
15208 #ifdef HAVE_FCHDIR
15209     { "HAVE_FCHDIR", NULL },
15210 #endif
15211 
15212 #ifdef HAVE_FCHMOD
15213     { "HAVE_FCHMOD", NULL },
15214 #endif
15215 
15216 #ifdef HAVE_FCHMODAT
15217     { "HAVE_FCHMODAT", probe_fchmodat },
15218 #endif
15219 
15220 #ifdef HAVE_FCHOWN
15221     { "HAVE_FCHOWN", NULL },
15222 #endif
15223 
15224 #ifdef HAVE_FCHOWNAT
15225     { "HAVE_FCHOWNAT", probe_fchownat },
15226 #endif
15227 
15228 #ifdef HAVE_FEXECVE
15229     { "HAVE_FEXECVE", NULL },
15230 #endif
15231 
15232 #ifdef HAVE_FDOPENDIR
15233     { "HAVE_FDOPENDIR", probe_fdopendir },
15234 #endif
15235 
15236 #ifdef HAVE_FPATHCONF
15237     { "HAVE_FPATHCONF", NULL },
15238 #endif
15239 
15240 #ifdef HAVE_FSTATAT
15241     { "HAVE_FSTATAT", probe_fstatat },
15242 #endif
15243 
15244 #ifdef HAVE_FSTATVFS
15245     { "HAVE_FSTATVFS", NULL },
15246 #endif
15247 
15248 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
15249     { "HAVE_FTRUNCATE", NULL },
15250 #endif
15251 
15252 #ifdef HAVE_FUTIMENS
15253     { "HAVE_FUTIMENS", probe_futimens },
15254 #endif
15255 
15256 #ifdef HAVE_FUTIMES
15257     { "HAVE_FUTIMES", NULL },
15258 #endif
15259 
15260 #ifdef HAVE_FUTIMESAT
15261     { "HAVE_FUTIMESAT", NULL },
15262 #endif
15263 
15264 #ifdef HAVE_LINKAT
15265     { "HAVE_LINKAT", probe_linkat },
15266 #endif
15267 
15268 #ifdef HAVE_LCHFLAGS
15269     { "HAVE_LCHFLAGS", NULL },
15270 #endif
15271 
15272 #ifdef HAVE_LCHMOD
15273     { "HAVE_LCHMOD", NULL },
15274 #endif
15275 
15276 #ifdef HAVE_LCHOWN
15277     { "HAVE_LCHOWN", NULL },
15278 #endif
15279 
15280 #ifdef HAVE_LSTAT
15281     { "HAVE_LSTAT", NULL },
15282 #endif
15283 
15284 #ifdef HAVE_LUTIMES
15285     { "HAVE_LUTIMES", NULL },
15286 #endif
15287 
15288 #ifdef HAVE_MEMFD_CREATE
15289     { "HAVE_MEMFD_CREATE", NULL },
15290 #endif
15291 
15292 #ifdef HAVE_MKDIRAT
15293     { "HAVE_MKDIRAT", probe_mkdirat },
15294 #endif
15295 
15296 #ifdef HAVE_MKFIFOAT
15297     { "HAVE_MKFIFOAT", NULL },
15298 #endif
15299 
15300 #ifdef HAVE_MKNODAT
15301     { "HAVE_MKNODAT", NULL },
15302 #endif
15303 
15304 #ifdef HAVE_OPENAT
15305     { "HAVE_OPENAT", probe_openat },
15306 #endif
15307 
15308 #ifdef HAVE_READLINKAT
15309     { "HAVE_READLINKAT", probe_readlinkat },
15310 #endif
15311 
15312 #ifdef HAVE_RENAMEAT
15313     { "HAVE_RENAMEAT", probe_renameat },
15314 #endif
15315 
15316 #ifdef HAVE_SYMLINKAT
15317     { "HAVE_SYMLINKAT", probe_symlinkat },
15318 #endif
15319 
15320 #ifdef HAVE_UNLINKAT
15321     { "HAVE_UNLINKAT", probe_unlinkat },
15322 #endif
15323 
15324 #ifdef HAVE_UTIMENSAT
15325     { "HAVE_UTIMENSAT", probe_utimensat },
15326 #endif
15327 
15328 #ifdef MS_WINDOWS
15329     { "MS_WINDOWS", NULL },
15330 #endif
15331 
15332     { NULL, NULL }
15333 };
15334 
15335 
15336 static int
posixmodule_exec(PyObject * m)15337 posixmodule_exec(PyObject *m)
15338 {
15339     _posixstate *state = get_posix_state(m);
15340 
15341 #if defined(HAVE_PWRITEV)
15342     if (HAVE_PWRITEV_RUNTIME) {} else {
15343         PyObject* dct = PyModule_GetDict(m);
15344 
15345         if (dct == NULL) {
15346             return -1;
15347         }
15348 
15349         if (PyDict_DelItemString(dct, "pwritev") == -1) {
15350             PyErr_Clear();
15351         }
15352         if (PyDict_DelItemString(dct, "preadv") == -1) {
15353             PyErr_Clear();
15354         }
15355     }
15356 #endif
15357 
15358     /* Initialize environ dictionary */
15359     PyObject *v = convertenviron();
15360     Py_XINCREF(v);
15361     if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
15362         return -1;
15363     Py_DECREF(v);
15364 
15365     if (all_ins(m))
15366         return -1;
15367 
15368     if (setup_confname_tables(m))
15369         return -1;
15370 
15371     Py_INCREF(PyExc_OSError);
15372     PyModule_AddObject(m, "error", PyExc_OSError);
15373 
15374 #if defined(HAVE_WAITID) && !defined(__APPLE__)
15375     waitid_result_desc.name = MODNAME ".waitid_result";
15376     PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
15377     if (WaitidResultType == NULL) {
15378         return -1;
15379     }
15380     Py_INCREF(WaitidResultType);
15381     PyModule_AddObject(m, "waitid_result", WaitidResultType);
15382     state->WaitidResultType = WaitidResultType;
15383 #endif
15384 
15385     stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
15386     stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
15387     stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
15388     stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
15389     PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
15390     if (StatResultType == NULL) {
15391         return -1;
15392     }
15393     Py_INCREF(StatResultType);
15394     PyModule_AddObject(m, "stat_result", StatResultType);
15395     state->StatResultType = StatResultType;
15396     structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15397     ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
15398 
15399     statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
15400     PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
15401     if (StatVFSResultType == NULL) {
15402         return -1;
15403     }
15404     Py_INCREF(StatVFSResultType);
15405     PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
15406     state->StatVFSResultType = StatVFSResultType;
15407 #ifdef NEED_TICKS_PER_SECOND
15408 #  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15409     ticks_per_second = sysconf(_SC_CLK_TCK);
15410 #  elif defined(HZ)
15411     ticks_per_second = HZ;
15412 #  else
15413     ticks_per_second = 60; /* magic fallback value; may be bogus */
15414 #  endif
15415 #endif
15416 
15417 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
15418     sched_param_desc.name = MODNAME ".sched_param";
15419     PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
15420     if (SchedParamType == NULL) {
15421         return -1;
15422     }
15423     Py_INCREF(SchedParamType);
15424     PyModule_AddObject(m, "sched_param", SchedParamType);
15425     state->SchedParamType = SchedParamType;
15426     ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
15427 #endif
15428 
15429     /* initialize TerminalSize_info */
15430     PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
15431     if (TerminalSizeType == NULL) {
15432         return -1;
15433     }
15434     Py_INCREF(TerminalSizeType);
15435     PyModule_AddObject(m, "terminal_size", TerminalSizeType);
15436     state->TerminalSizeType = TerminalSizeType;
15437 
15438     /* initialize scandir types */
15439     PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
15440     if (ScandirIteratorType == NULL) {
15441         return -1;
15442     }
15443     state->ScandirIteratorType = ScandirIteratorType;
15444 
15445     PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
15446     if (DirEntryType == NULL) {
15447         return -1;
15448     }
15449     Py_INCREF(DirEntryType);
15450     PyModule_AddObject(m, "DirEntry", DirEntryType);
15451     state->DirEntryType = DirEntryType;
15452 
15453     times_result_desc.name = MODNAME ".times_result";
15454     PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
15455     if (TimesResultType == NULL) {
15456         return -1;
15457     }
15458     Py_INCREF(TimesResultType);
15459     PyModule_AddObject(m, "times_result", TimesResultType);
15460     state->TimesResultType = TimesResultType;
15461 
15462     PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
15463     if (UnameResultType == NULL) {
15464         return -1;
15465     }
15466     Py_INCREF(UnameResultType);
15467     PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
15468     state->UnameResultType = (PyObject *)UnameResultType;
15469 
15470     if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
15471         return -1;
15472 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
15473     state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
15474     if (state->struct_rusage == NULL)
15475         return -1;
15476 #endif
15477     state->st_mode = PyUnicode_InternFromString("st_mode");
15478     if (state->st_mode == NULL)
15479         return -1;
15480 
15481     /* suppress "function not used" warnings */
15482     {
15483     int ignored;
15484     fd_specified("", -1);
15485     follow_symlinks_specified("", 1);
15486     dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
15487     dir_fd_converter(Py_None, &ignored);
15488     dir_fd_unavailable(Py_None, &ignored);
15489     }
15490 
15491     /*
15492      * provide list of locally available functions
15493      * so os.py can populate support_* lists
15494      */
15495     PyObject *list = PyList_New(0);
15496     if (!list) {
15497         return -1;
15498     }
15499     for (const struct have_function *trace = have_functions; trace->label; trace++) {
15500         PyObject *unicode;
15501         if (trace->probe && !trace->probe()) continue;
15502         unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
15503         if (!unicode)
15504             return -1;
15505         if (PyList_Append(list, unicode))
15506             return -1;
15507         Py_DECREF(unicode);
15508     }
15509 
15510     PyModule_AddObject(m, "_have_functions", list);
15511 
15512     return 0;
15513 }
15514 
15515 
15516 static PyModuleDef_Slot posixmodile_slots[] = {
15517     {Py_mod_exec, posixmodule_exec},
15518     {0, NULL}
15519 };
15520 
15521 static struct PyModuleDef posixmodule = {
15522     PyModuleDef_HEAD_INIT,
15523     .m_name = MODNAME,
15524     .m_doc = posix__doc__,
15525     .m_size = sizeof(_posixstate),
15526     .m_methods = posix_methods,
15527     .m_slots = posixmodile_slots,
15528     .m_traverse = _posix_traverse,
15529     .m_clear = _posix_clear,
15530     .m_free = _posix_free,
15531 };
15532 
15533 PyMODINIT_FUNC
INITFUNC(void)15534 INITFUNC(void)
15535 {
15536     return PyModuleDef_Init(&posixmodule);
15537 }
15538 
15539 #ifdef __cplusplus
15540 }
15541 #endif
15542