• 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 __BIONIC__
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) && __has_builtin(__builtin_available)
60 #  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
61 #  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
62 #  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
63 #  define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
64 #  define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
65 #  define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
66 #  define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
67 #  define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
68 #  define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
69 #  define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
70 #  define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
71 #  define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
72 #  define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
73 #  define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
74 #  define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
75 
76 #  define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
77 
78 #else /* Xcode 8 or earlier */
79 
80    /* __builtin_available is not present in these compilers, but
81     * some of the symbols might be weak linked (10.10 SDK or later
82     * deploying on 10.9.
83     *
84     * Fall back to the older style of availability checking for
85     * symbols introduced in macOS 10.10.
86     */
87 
88 #  ifdef HAVE_FSTATAT
89 #    define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
90 #  endif
91 
92 #  ifdef HAVE_FACCESSAT
93 #    define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
94 #  endif
95 
96 #  ifdef HAVE_FCHMODAT
97 #    define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
98 #  endif
99 
100 #  ifdef HAVE_FCHOWNAT
101 #    define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
102 #  endif
103 
104 #  ifdef HAVE_LINKAT
105 #    define HAVE_LINKAT_RUNTIME (linkat != NULL)
106 #  endif
107 
108 #  ifdef HAVE_FDOPENDIR
109 #    define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
110 #  endif
111 
112 #  ifdef HAVE_MKDIRAT
113 #    define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
114 #  endif
115 
116 #  ifdef HAVE_RENAMEAT
117 #    define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
118 #  endif
119 
120 #  ifdef HAVE_UNLINKAT
121 #    define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
122 #  endif
123 
124 #  ifdef HAVE_OPENAT
125 #    define HAVE_OPENAT_RUNTIME (openat != NULL)
126 #  endif
127 
128 #  ifdef HAVE_READLINKAT
129 #    define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
130 #  endif
131 
132 #  ifdef HAVE_SYMLINKAT
133 #    define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
134 #  endif
135 
136 #endif
137 
138 #ifdef HAVE_FUTIMESAT
139 /* Some of the logic for weak linking depends on this assertion */
140 # error "HAVE_FUTIMESAT unexpectedly defined"
141 #endif
142 
143 #else
144 #  define HAVE_FSTATAT_RUNTIME 1
145 #  define HAVE_FACCESSAT_RUNTIME 1
146 #  define HAVE_FCHMODAT_RUNTIME 1
147 #  define HAVE_FCHOWNAT_RUNTIME 1
148 #  define HAVE_LINKAT_RUNTIME 1
149 #  define HAVE_FDOPENDIR_RUNTIME 1
150 #  define HAVE_MKDIRAT_RUNTIME 1
151 #  define HAVE_RENAMEAT_RUNTIME 1
152 #  define HAVE_UNLINKAT_RUNTIME 1
153 #  define HAVE_OPENAT_RUNTIME 1
154 #  define HAVE_READLINKAT_RUNTIME 1
155 #  define HAVE_SYMLINKAT_RUNTIME 1
156 #  define HAVE_FUTIMENS_RUNTIME 1
157 #  define HAVE_UTIMENSAT_RUNTIME 1
158 #  define HAVE_PWRITEV_RUNTIME 1
159 #endif
160 
161 
162 #ifdef __cplusplus
163 extern "C" {
164 #endif
165 
166 PyDoc_STRVAR(posix__doc__,
167 "This module provides access to operating system functionality that is\n\
168 standardized by the C Standard and the POSIX standard (a thinly\n\
169 disguised Unix interface).  Refer to the library manual and\n\
170 corresponding Unix manual entries for more information on calls.");
171 
172 
173 #ifdef HAVE_SYS_UIO_H
174 #  include <sys/uio.h>
175 #endif
176 
177 #ifdef HAVE_SYS_SYSMACROS_H
178 /* GNU C Library: major(), minor(), makedev() */
179 #  include <sys/sysmacros.h>
180 #endif
181 
182 #ifdef HAVE_SYS_TYPES_H
183 #  include <sys/types.h>
184 #endif /* HAVE_SYS_TYPES_H */
185 
186 #ifdef HAVE_SYS_STAT_H
187 #  include <sys/stat.h>
188 #endif /* HAVE_SYS_STAT_H */
189 
190 #ifdef HAVE_SYS_WAIT_H
191 #  include <sys/wait.h>           // WNOHANG
192 #endif
193 #ifdef HAVE_LINUX_WAIT_H
194 #  include <linux/wait.h>         // P_PIDFD
195 #endif
196 
197 #ifdef HAVE_SIGNAL_H
198 #  include <signal.h>
199 #endif
200 
201 #ifdef HAVE_FCNTL_H
202 #  include <fcntl.h>
203 #endif
204 
205 #ifdef HAVE_GRP_H
206 #  include <grp.h>
207 #endif
208 
209 #ifdef HAVE_SYSEXITS_H
210 #  include <sysexits.h>
211 #endif
212 
213 #ifdef HAVE_SYS_LOADAVG_H
214 #  include <sys/loadavg.h>
215 #endif
216 
217 #ifdef HAVE_SYS_SENDFILE_H
218 #  include <sys/sendfile.h>
219 #endif
220 
221 #if defined(__APPLE__)
222 #  include <copyfile.h>
223 #endif
224 
225 #ifdef HAVE_SCHED_H
226 #  include <sched.h>
227 #endif
228 
229 #ifdef HAVE_COPY_FILE_RANGE
230 #  include <unistd.h>
231 #endif
232 
233 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
234 #  undef HAVE_SCHED_SETAFFINITY
235 #endif
236 
237 #if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
238 #  define USE_XATTRS
239 #endif
240 
241 #ifdef USE_XATTRS
242 #  include <sys/xattr.h>
243 #endif
244 
245 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
246 #  ifdef HAVE_SYS_SOCKET_H
247 #    include <sys/socket.h>
248 #  endif
249 #endif
250 
251 #ifdef HAVE_DLFCN_H
252 #  include <dlfcn.h>
253 #endif
254 
255 #ifdef __hpux
256 #  include <sys/mpctl.h>
257 #endif
258 
259 #if defined(__DragonFly__) || \
260     defined(__OpenBSD__)   || \
261     defined(__FreeBSD__)   || \
262     defined(__NetBSD__)    || \
263     defined(__APPLE__)
264 #  include <sys/sysctl.h>
265 #endif
266 
267 #ifdef HAVE_LINUX_RANDOM_H
268 #  include <linux/random.h>
269 #endif
270 #ifdef HAVE_GETRANDOM_SYSCALL
271 #  include <sys/syscall.h>
272 #endif
273 
274 #if defined(MS_WINDOWS)
275 #  define TERMSIZE_USE_CONIO
276 #elif defined(HAVE_SYS_IOCTL_H)
277 #  include <sys/ioctl.h>
278 #  if defined(HAVE_TERMIOS_H)
279 #    include <termios.h>
280 #  endif
281 #  if defined(TIOCGWINSZ)
282 #    define TERMSIZE_USE_IOCTL
283 #  endif
284 #endif /* MS_WINDOWS */
285 
286 /* Various compilers have only certain posix functions */
287 /* XXX Gosh I wish these were all moved into pyconfig.h */
288 #if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
289 #  define HAVE_OPENDIR    1
290 #  define HAVE_SYSTEM     1
291 #  include <process.h>
292 #else
293 #  ifdef _MSC_VER
294      /* Microsoft compiler */
295 #    define HAVE_GETPPID    1
296 #    define HAVE_GETLOGIN   1
297 #    define HAVE_SPAWNV     1
298 #    define HAVE_EXECV      1
299 #    define HAVE_WSPAWNV    1
300 #    define HAVE_WEXECV     1
301 #    define HAVE_PIPE       1
302 #    define HAVE_SYSTEM     1
303 #    define HAVE_CWAIT      1
304 #    define HAVE_FSYNC      1
305 #    define fsync _commit
306 #  else
307      /* Unix functions that the configure script doesn't check for */
308 #    ifndef __VXWORKS__
309 #      define HAVE_EXECV      1
310 #      define HAVE_FORK       1
311 #      if defined(__USLC__) && defined(__SCO_VERSION__)       /* SCO UDK Compiler */
312 #        define HAVE_FORK1      1
313 #      endif
314 #    endif
315 #    define HAVE_GETEGID    1
316 #    define HAVE_GETEUID    1
317 #    define HAVE_GETGID     1
318 #    define HAVE_GETPPID    1
319 #    define HAVE_GETUID     1
320 #    define HAVE_KILL       1
321 #    define HAVE_OPENDIR    1
322 #    define HAVE_PIPE       1
323 #    define HAVE_SYSTEM     1
324 #    define HAVE_WAIT       1
325 #    define HAVE_TTYNAME    1
326 #  endif  /* _MSC_VER */
327 #endif  /* ! __WATCOMC__ || __QNX__ */
328 
329 _Py_IDENTIFIER(__fspath__);
330 
331 /*[clinic input]
332 # one of the few times we lie about this name!
333 module os
334 [clinic start generated code]*/
335 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
336 
337 #ifndef _MSC_VER
338 
339 #if defined(__sgi)&&_COMPILER_VERSION>=700
340 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
341    (default) */
342 extern char        *ctermid_r(char *);
343 #endif
344 
345 #endif /* !_MSC_VER */
346 
347 #if defined(__VXWORKS__)
348 #  include <vxCpuLib.h>
349 #  include <rtpLib.h>
350 #  include <wait.h>
351 #  include <taskLib.h>
352 #  ifndef _P_WAIT
353 #    define _P_WAIT          0
354 #    define _P_NOWAIT        1
355 #    define _P_NOWAITO       1
356 #  endif
357 #endif /* __VXWORKS__ */
358 
359 #ifdef HAVE_POSIX_SPAWN
360 #  include <spawn.h>
361 #endif
362 
363 #ifdef HAVE_UTIME_H
364 #  include <utime.h>
365 #endif /* HAVE_UTIME_H */
366 
367 #ifdef HAVE_SYS_UTIME_H
368 #  include <sys/utime.h>
369 #  define HAVE_UTIME_H /* pretend we do for the rest of this file */
370 #endif /* HAVE_SYS_UTIME_H */
371 
372 #ifdef HAVE_SYS_TIMES_H
373 #  include <sys/times.h>
374 #endif /* HAVE_SYS_TIMES_H */
375 
376 #ifdef HAVE_SYS_PARAM_H
377 #  include <sys/param.h>
378 #endif /* HAVE_SYS_PARAM_H */
379 
380 #ifdef HAVE_SYS_UTSNAME_H
381 #  include <sys/utsname.h>
382 #endif /* HAVE_SYS_UTSNAME_H */
383 
384 #ifdef HAVE_DIRENT_H
385 #  include <dirent.h>
386 #  define NAMLEN(dirent) strlen((dirent)->d_name)
387 #else
388 #  if defined(__WATCOMC__) && !defined(__QNX__)
389 #    include <direct.h>
390 #    define NAMLEN(dirent) strlen((dirent)->d_name)
391 #  else
392 #    define dirent direct
393 #    define NAMLEN(dirent) (dirent)->d_namlen
394 #  endif
395 #  ifdef HAVE_SYS_NDIR_H
396 #    include <sys/ndir.h>
397 #  endif
398 #  ifdef HAVE_SYS_DIR_H
399 #    include <sys/dir.h>
400 #  endif
401 #  ifdef HAVE_NDIR_H
402 #    include <ndir.h>
403 #  endif
404 #endif
405 
406 #ifdef _MSC_VER
407 #  ifdef HAVE_DIRECT_H
408 #    include <direct.h>
409 #  endif
410 #  ifdef HAVE_IO_H
411 #    include <io.h>
412 #  endif
413 #  ifdef HAVE_PROCESS_H
414 #    include <process.h>
415 #  endif
416 #  ifndef IO_REPARSE_TAG_SYMLINK
417 #    define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
418 #  endif
419 #  ifndef IO_REPARSE_TAG_MOUNT_POINT
420 #    define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
421 #  endif
422 #  include "osdefs.h"             // SEP
423 #  include <malloc.h>
424 #  include <windows.h>
425 #  include <shellapi.h>           // ShellExecute()
426 #  include <lmcons.h>             // UNLEN
427 #  define HAVE_SYMLINK
428 #endif /* _MSC_VER */
429 
430 #ifndef MAXPATHLEN
431 #  if defined(PATH_MAX) && PATH_MAX > 1024
432 #    define MAXPATHLEN PATH_MAX
433 #  else
434 #    define MAXPATHLEN 1024
435 #  endif
436 #endif /* MAXPATHLEN */
437 
438 #ifdef UNION_WAIT
439    /* Emulate some macros on systems that have a union instead of macros */
440 #  ifndef WIFEXITED
441 #    define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
442 #  endif
443 #  ifndef WEXITSTATUS
444 #    define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
445 #  endif
446 #  ifndef WTERMSIG
447 #    define WTERMSIG(u_wait) ((u_wait).w_termsig)
448 #  endif
449 #  define WAIT_TYPE union wait
450 #  define WAIT_STATUS_INT(s) (s.w_status)
451 #else
452    /* !UNION_WAIT */
453 #  define WAIT_TYPE int
454 #  define WAIT_STATUS_INT(s) (s)
455 #endif /* UNION_WAIT */
456 
457 /* Don't use the "_r" form if we don't need it (also, won't have a
458    prototype for it, at least on Solaris -- maybe others as well?). */
459 #if defined(HAVE_CTERMID_R)
460 #  define USE_CTERMID_R
461 #endif
462 
463 /* choose the appropriate stat and fstat functions and return structs */
464 #undef STAT
465 #undef FSTAT
466 #undef STRUCT_STAT
467 #ifdef MS_WINDOWS
468 #  define STAT win32_stat
469 #  define LSTAT win32_lstat
470 #  define FSTAT _Py_fstat_noraise
471 #  define STRUCT_STAT struct _Py_stat_struct
472 #else
473 #  define STAT stat
474 #  define LSTAT lstat
475 #  define FSTAT fstat
476 #  define STRUCT_STAT struct stat
477 #endif
478 
479 #if defined(MAJOR_IN_MKDEV)
480 #  include <sys/mkdev.h>
481 #else
482 #  if defined(MAJOR_IN_SYSMACROS)
483 #    include <sys/sysmacros.h>
484 #  endif
485 #  if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
486 #    include <sys/mkdev.h>
487 #  endif
488 #endif
489 
490 #ifdef MS_WINDOWS
491 #  define INITFUNC PyInit_nt
492 #  define MODNAME "nt"
493 #else
494 #  define INITFUNC PyInit_posix
495 #  define MODNAME "posix"
496 #endif
497 
498 #if defined(__sun)
499 /* Something to implement in autoconf, not present in autoconf 2.69 */
500 #  define HAVE_STRUCT_STAT_ST_FSTYPE 1
501 #endif
502 
503 /* memfd_create is either defined in sys/mman.h or sys/memfd.h
504  * linux/memfd.h defines additional flags
505  */
506 #ifdef HAVE_SYS_MMAN_H
507 #  include <sys/mman.h>
508 #endif
509 #ifdef HAVE_SYS_MEMFD_H
510 #  include <sys/memfd.h>
511 #endif
512 #ifdef HAVE_LINUX_MEMFD_H
513 #  include <linux/memfd.h>
514 #endif
515 
516 #ifdef _Py_MEMORY_SANITIZER
517 #  include <sanitizer/msan_interface.h>
518 #endif
519 
520 #ifdef HAVE_FORK
521 static void
run_at_forkers(PyObject * lst,int reverse)522 run_at_forkers(PyObject *lst, int reverse)
523 {
524     Py_ssize_t i;
525     PyObject *cpy;
526 
527     if (lst != NULL) {
528         assert(PyList_CheckExact(lst));
529 
530         /* Use a list copy in case register_at_fork() is called from
531          * one of the callbacks.
532          */
533         cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
534         if (cpy == NULL)
535             PyErr_WriteUnraisable(lst);
536         else {
537             if (reverse)
538                 PyList_Reverse(cpy);
539             for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
540                 PyObject *func, *res;
541                 func = PyList_GET_ITEM(cpy, i);
542                 res = _PyObject_CallNoArg(func);
543                 if (res == NULL)
544                     PyErr_WriteUnraisable(func);
545                 else
546                     Py_DECREF(res);
547             }
548             Py_DECREF(cpy);
549         }
550     }
551 }
552 
553 void
PyOS_BeforeFork(void)554 PyOS_BeforeFork(void)
555 {
556     run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1);
557 
558     _PyImport_AcquireLock();
559 }
560 
561 void
PyOS_AfterFork_Parent(void)562 PyOS_AfterFork_Parent(void)
563 {
564     if (_PyImport_ReleaseLock() <= 0)
565         Py_FatalError("failed releasing import lock after fork");
566 
567     run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0);
568 }
569 
570 void
PyOS_AfterFork_Child(void)571 PyOS_AfterFork_Child(void)
572 {
573     _PyRuntimeState *runtime = &_PyRuntime;
574     _PyGILState_Reinit(runtime);
575     _PyEval_ReInitThreads(runtime);
576     _PyImport_ReInitLock();
577     _PySignal_AfterFork();
578     _PyRuntimeState_ReInitThreads(runtime);
579     _PyInterpreterState_DeleteExceptMain(runtime);
580 
581     run_at_forkers(_PyInterpreterState_GET()->after_forkers_child, 0);
582 }
583 
584 static int
register_at_forker(PyObject ** lst,PyObject * func)585 register_at_forker(PyObject **lst, PyObject *func)
586 {
587     if (func == NULL)  /* nothing to register? do nothing. */
588         return 0;
589     if (*lst == NULL) {
590         *lst = PyList_New(0);
591         if (*lst == NULL)
592             return -1;
593     }
594     return PyList_Append(*lst, func);
595 }
596 #endif  /* HAVE_FORK */
597 
598 
599 /* Legacy wrapper */
600 void
PyOS_AfterFork(void)601 PyOS_AfterFork(void)
602 {
603 #ifdef HAVE_FORK
604     PyOS_AfterFork_Child();
605 #endif
606 }
607 
608 
609 #ifdef MS_WINDOWS
610 /* defined in fileutils.c */
611 void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
612 void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
613                                             ULONG, struct _Py_stat_struct *);
614 #endif
615 
616 
617 #ifndef MS_WINDOWS
618 PyObject *
_PyLong_FromUid(uid_t uid)619 _PyLong_FromUid(uid_t uid)
620 {
621     if (uid == (uid_t)-1)
622         return PyLong_FromLong(-1);
623     return PyLong_FromUnsignedLong(uid);
624 }
625 
626 PyObject *
_PyLong_FromGid(gid_t gid)627 _PyLong_FromGid(gid_t gid)
628 {
629     if (gid == (gid_t)-1)
630         return PyLong_FromLong(-1);
631     return PyLong_FromUnsignedLong(gid);
632 }
633 
634 int
_Py_Uid_Converter(PyObject * obj,void * p)635 _Py_Uid_Converter(PyObject *obj, void *p)
636 {
637     uid_t uid;
638     PyObject *index;
639     int overflow;
640     long result;
641     unsigned long uresult;
642 
643     index = PyNumber_Index(obj);
644     if (index == NULL) {
645         PyErr_Format(PyExc_TypeError,
646                      "uid should be integer, not %.200s",
647                      _PyType_Name(Py_TYPE(obj)));
648         return 0;
649     }
650 
651     /*
652      * Handling uid_t is complicated for two reasons:
653      *  * Although uid_t is (always?) unsigned, it still
654      *    accepts -1.
655      *  * We don't know its size in advance--it may be
656      *    bigger than an int, or it may be smaller than
657      *    a long.
658      *
659      * So a bit of defensive programming is in order.
660      * Start with interpreting the value passed
661      * in as a signed long and see if it works.
662      */
663 
664     result = PyLong_AsLongAndOverflow(index, &overflow);
665 
666     if (!overflow) {
667         uid = (uid_t)result;
668 
669         if (result == -1) {
670             if (PyErr_Occurred())
671                 goto fail;
672             /* It's a legitimate -1, we're done. */
673             goto success;
674         }
675 
676         /* Any other negative number is disallowed. */
677         if (result < 0)
678             goto underflow;
679 
680         /* Ensure the value wasn't truncated. */
681         if (sizeof(uid_t) < sizeof(long) &&
682             (long)uid != result)
683             goto underflow;
684         goto success;
685     }
686 
687     if (overflow < 0)
688         goto underflow;
689 
690     /*
691      * Okay, the value overflowed a signed long.  If it
692      * fits in an *unsigned* long, it may still be okay,
693      * as uid_t may be unsigned long on this platform.
694      */
695     uresult = PyLong_AsUnsignedLong(index);
696     if (PyErr_Occurred()) {
697         if (PyErr_ExceptionMatches(PyExc_OverflowError))
698             goto overflow;
699         goto fail;
700     }
701 
702     uid = (uid_t)uresult;
703 
704     /*
705      * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
706      * but this value would get interpreted as (uid_t)-1  by chown
707      * and its siblings.   That's not what the user meant!  So we
708      * throw an overflow exception instead.   (We already
709      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
710      */
711     if (uid == (uid_t)-1)
712         goto overflow;
713 
714     /* Ensure the value wasn't truncated. */
715     if (sizeof(uid_t) < sizeof(long) &&
716         (unsigned long)uid != uresult)
717         goto overflow;
718     /* fallthrough */
719 
720 success:
721     Py_DECREF(index);
722     *(uid_t *)p = uid;
723     return 1;
724 
725 underflow:
726     PyErr_SetString(PyExc_OverflowError,
727                     "uid is less than minimum");
728     goto fail;
729 
730 overflow:
731     PyErr_SetString(PyExc_OverflowError,
732                     "uid is greater than maximum");
733     /* fallthrough */
734 
735 fail:
736     Py_DECREF(index);
737     return 0;
738 }
739 
740 int
_Py_Gid_Converter(PyObject * obj,void * p)741 _Py_Gid_Converter(PyObject *obj, void *p)
742 {
743     gid_t gid;
744     PyObject *index;
745     int overflow;
746     long result;
747     unsigned long uresult;
748 
749     index = PyNumber_Index(obj);
750     if (index == NULL) {
751         PyErr_Format(PyExc_TypeError,
752                      "gid should be integer, not %.200s",
753                      _PyType_Name(Py_TYPE(obj)));
754         return 0;
755     }
756 
757     /*
758      * Handling gid_t is complicated for two reasons:
759      *  * Although gid_t is (always?) unsigned, it still
760      *    accepts -1.
761      *  * We don't know its size in advance--it may be
762      *    bigger than an int, or it may be smaller than
763      *    a long.
764      *
765      * So a bit of defensive programming is in order.
766      * Start with interpreting the value passed
767      * in as a signed long and see if it works.
768      */
769 
770     result = PyLong_AsLongAndOverflow(index, &overflow);
771 
772     if (!overflow) {
773         gid = (gid_t)result;
774 
775         if (result == -1) {
776             if (PyErr_Occurred())
777                 goto fail;
778             /* It's a legitimate -1, we're done. */
779             goto success;
780         }
781 
782         /* Any other negative number is disallowed. */
783         if (result < 0) {
784             goto underflow;
785         }
786 
787         /* Ensure the value wasn't truncated. */
788         if (sizeof(gid_t) < sizeof(long) &&
789             (long)gid != result)
790             goto underflow;
791         goto success;
792     }
793 
794     if (overflow < 0)
795         goto underflow;
796 
797     /*
798      * Okay, the value overflowed a signed long.  If it
799      * fits in an *unsigned* long, it may still be okay,
800      * as gid_t may be unsigned long on this platform.
801      */
802     uresult = PyLong_AsUnsignedLong(index);
803     if (PyErr_Occurred()) {
804         if (PyErr_ExceptionMatches(PyExc_OverflowError))
805             goto overflow;
806         goto fail;
807     }
808 
809     gid = (gid_t)uresult;
810 
811     /*
812      * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
813      * but this value would get interpreted as (gid_t)-1  by chown
814      * and its siblings.   That's not what the user meant!  So we
815      * throw an overflow exception instead.   (We already
816      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
817      */
818     if (gid == (gid_t)-1)
819         goto overflow;
820 
821     /* Ensure the value wasn't truncated. */
822     if (sizeof(gid_t) < sizeof(long) &&
823         (unsigned long)gid != uresult)
824         goto overflow;
825     /* fallthrough */
826 
827 success:
828     Py_DECREF(index);
829     *(gid_t *)p = gid;
830     return 1;
831 
832 underflow:
833     PyErr_SetString(PyExc_OverflowError,
834                     "gid is less than minimum");
835     goto fail;
836 
837 overflow:
838     PyErr_SetString(PyExc_OverflowError,
839                     "gid is greater than maximum");
840     /* fallthrough */
841 
842 fail:
843     Py_DECREF(index);
844     return 0;
845 }
846 #endif /* MS_WINDOWS */
847 
848 
849 #define _PyLong_FromDev PyLong_FromLongLong
850 
851 
852 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
853 static int
_Py_Dev_Converter(PyObject * obj,void * p)854 _Py_Dev_Converter(PyObject *obj, void *p)
855 {
856     *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
857     if (PyErr_Occurred())
858         return 0;
859     return 1;
860 }
861 #endif /* HAVE_MKNOD && HAVE_MAKEDEV */
862 
863 
864 #ifdef AT_FDCWD
865 /*
866  * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
867  * without the int cast, the value gets interpreted as uint (4291925331),
868  * which doesn't play nicely with all the initializer lines in this file that
869  * look like this:
870  *      int dir_fd = DEFAULT_DIR_FD;
871  */
872 #define DEFAULT_DIR_FD (int)AT_FDCWD
873 #else
874 #define DEFAULT_DIR_FD (-100)
875 #endif
876 
877 static int
_fd_converter(PyObject * o,int * p)878 _fd_converter(PyObject *o, int *p)
879 {
880     int overflow;
881     long long_value;
882 
883     PyObject *index = PyNumber_Index(o);
884     if (index == NULL) {
885         return 0;
886     }
887 
888     assert(PyLong_Check(index));
889     long_value = PyLong_AsLongAndOverflow(index, &overflow);
890     Py_DECREF(index);
891     assert(!PyErr_Occurred());
892     if (overflow > 0 || long_value > INT_MAX) {
893         PyErr_SetString(PyExc_OverflowError,
894                         "fd is greater than maximum");
895         return 0;
896     }
897     if (overflow < 0 || long_value < INT_MIN) {
898         PyErr_SetString(PyExc_OverflowError,
899                         "fd is less than minimum");
900         return 0;
901     }
902 
903     *p = (int)long_value;
904     return 1;
905 }
906 
907 static int
dir_fd_converter(PyObject * o,void * p)908 dir_fd_converter(PyObject *o, void *p)
909 {
910     if (o == Py_None) {
911         *(int *)p = DEFAULT_DIR_FD;
912         return 1;
913     }
914     else if (PyIndex_Check(o)) {
915         return _fd_converter(o, (int *)p);
916     }
917     else {
918         PyErr_Format(PyExc_TypeError,
919                      "argument should be integer or None, not %.200s",
920                      _PyType_Name(Py_TYPE(o)));
921         return 0;
922     }
923 }
924 
925 typedef struct {
926     PyObject *billion;
927     PyObject *DirEntryType;
928     PyObject *ScandirIteratorType;
929 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
930     PyObject *SchedParamType;
931 #endif
932     PyObject *StatResultType;
933     PyObject *StatVFSResultType;
934     PyObject *TerminalSizeType;
935     PyObject *TimesResultType;
936     PyObject *UnameResultType;
937 #if defined(HAVE_WAITID) && !defined(__APPLE__)
938     PyObject *WaitidResultType;
939 #endif
940 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
941     PyObject *struct_rusage;
942 #endif
943     PyObject *st_mode;
944 } _posixstate;
945 
946 
947 static inline _posixstate*
get_posix_state(PyObject * module)948 get_posix_state(PyObject *module)
949 {
950     void *state = PyModule_GetState(module);
951     assert(state != NULL);
952     return (_posixstate *)state;
953 }
954 
955 /*
956  * A PyArg_ParseTuple "converter" function
957  * that handles filesystem paths in the manner
958  * preferred by the os module.
959  *
960  * path_converter accepts (Unicode) strings and their
961  * subclasses, and bytes and their subclasses.  What
962  * it does with the argument depends on the platform:
963  *
964  *   * On Windows, if we get a (Unicode) string we
965  *     extract the wchar_t * and return it; if we get
966  *     bytes we decode to wchar_t * and return that.
967  *
968  *   * On all other platforms, strings are encoded
969  *     to bytes using PyUnicode_FSConverter, then we
970  *     extract the char * from the bytes object and
971  *     return that.
972  *
973  * path_converter also optionally accepts signed
974  * integers (representing open file descriptors) instead
975  * of path strings.
976  *
977  * Input fields:
978  *   path.nullable
979  *     If nonzero, the path is permitted to be None.
980  *   path.allow_fd
981  *     If nonzero, the path is permitted to be a file handle
982  *     (a signed int) instead of a string.
983  *   path.function_name
984  *     If non-NULL, path_converter will use that as the name
985  *     of the function in error messages.
986  *     (If path.function_name is NULL it omits the function name.)
987  *   path.argument_name
988  *     If non-NULL, path_converter will use that as the name
989  *     of the parameter in error messages.
990  *     (If path.argument_name is NULL it uses "path".)
991  *
992  * Output fields:
993  *   path.wide
994  *     Points to the path if it was expressed as Unicode
995  *     and was not encoded.  (Only used on Windows.)
996  *   path.narrow
997  *     Points to the path if it was expressed as bytes,
998  *     or it was Unicode and was encoded to bytes. (On Windows,
999  *     is a non-zero integer if the path was expressed as bytes.
1000  *     The type is deliberately incompatible to prevent misuse.)
1001  *   path.fd
1002  *     Contains a file descriptor if path.accept_fd was true
1003  *     and the caller provided a signed integer instead of any
1004  *     sort of string.
1005  *
1006  *     WARNING: if your "path" parameter is optional, and is
1007  *     unspecified, path_converter will never get called.
1008  *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1009  *     yourself!
1010  *   path.length
1011  *     The length of the path in characters, if specified as
1012  *     a string.
1013  *   path.object
1014  *     The original object passed in (if get a PathLike object,
1015  *     the result of PyOS_FSPath() is treated as the original object).
1016  *     Own a reference to the object.
1017  *   path.cleanup
1018  *     For internal use only.  May point to a temporary object.
1019  *     (Pay no attention to the man behind the curtain.)
1020  *
1021  *   At most one of path.wide or path.narrow will be non-NULL.
1022  *   If path was None and path.nullable was set,
1023  *     or if path was an integer and path.allow_fd was set,
1024  *     both path.wide and path.narrow will be NULL
1025  *     and path.length will be 0.
1026  *
1027  *   path_converter takes care to not write to the path_t
1028  *   unless it's successful.  However it must reset the
1029  *   "cleanup" field each time it's called.
1030  *
1031  * Use as follows:
1032  *      path_t path;
1033  *      memset(&path, 0, sizeof(path));
1034  *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1035  *      // ... use values from path ...
1036  *      path_cleanup(&path);
1037  *
1038  * (Note that if PyArg_Parse fails you don't need to call
1039  * path_cleanup().  However it is safe to do so.)
1040  */
1041 typedef struct {
1042     const char *function_name;
1043     const char *argument_name;
1044     int nullable;
1045     int allow_fd;
1046     const wchar_t *wide;
1047 #ifdef MS_WINDOWS
1048     BOOL narrow;
1049 #else
1050     const char *narrow;
1051 #endif
1052     int fd;
1053     Py_ssize_t length;
1054     PyObject *object;
1055     PyObject *cleanup;
1056 } path_t;
1057 
1058 #ifdef MS_WINDOWS
1059 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1060     {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
1061 #else
1062 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1063     {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
1064 #endif
1065 
1066 static void
path_cleanup(path_t * path)1067 path_cleanup(path_t *path)
1068 {
1069     Py_CLEAR(path->object);
1070     Py_CLEAR(path->cleanup);
1071 }
1072 
1073 static int
path_converter(PyObject * o,void * p)1074 path_converter(PyObject *o, void *p)
1075 {
1076     path_t *path = (path_t *)p;
1077     PyObject *bytes = NULL;
1078     Py_ssize_t length = 0;
1079     int is_index, is_buffer, is_bytes, is_unicode;
1080     const char *narrow;
1081 #ifdef MS_WINDOWS
1082     PyObject *wo = NULL;
1083     const wchar_t *wide;
1084 #endif
1085 
1086 #define FORMAT_EXCEPTION(exc, fmt) \
1087     PyErr_Format(exc, "%s%s" fmt, \
1088         path->function_name ? path->function_name : "", \
1089         path->function_name ? ": "                : "", \
1090         path->argument_name ? path->argument_name : "path")
1091 
1092     /* Py_CLEANUP_SUPPORTED support */
1093     if (o == NULL) {
1094         path_cleanup(path);
1095         return 1;
1096     }
1097 
1098     /* Ensure it's always safe to call path_cleanup(). */
1099     path->object = path->cleanup = NULL;
1100     /* path->object owns a reference to the original object */
1101     Py_INCREF(o);
1102 
1103     if ((o == Py_None) && path->nullable) {
1104         path->wide = NULL;
1105 #ifdef MS_WINDOWS
1106         path->narrow = FALSE;
1107 #else
1108         path->narrow = NULL;
1109 #endif
1110         path->fd = -1;
1111         goto success_exit;
1112     }
1113 
1114     /* Only call this here so that we don't treat the return value of
1115        os.fspath() as an fd or buffer. */
1116     is_index = path->allow_fd && PyIndex_Check(o);
1117     is_buffer = PyObject_CheckBuffer(o);
1118     is_bytes = PyBytes_Check(o);
1119     is_unicode = PyUnicode_Check(o);
1120 
1121     if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
1122         /* Inline PyOS_FSPath() for better error messages. */
1123         PyObject *func, *res;
1124 
1125         func = _PyObject_LookupSpecial(o, &PyId___fspath__);
1126         if (NULL == func) {
1127             goto error_format;
1128         }
1129         res = _PyObject_CallNoArg(func);
1130         Py_DECREF(func);
1131         if (NULL == res) {
1132             goto error_exit;
1133         }
1134         else if (PyUnicode_Check(res)) {
1135             is_unicode = 1;
1136         }
1137         else if (PyBytes_Check(res)) {
1138             is_bytes = 1;
1139         }
1140         else {
1141             PyErr_Format(PyExc_TypeError,
1142                  "expected %.200s.__fspath__() to return str or bytes, "
1143                  "not %.200s", _PyType_Name(Py_TYPE(o)),
1144                  _PyType_Name(Py_TYPE(res)));
1145             Py_DECREF(res);
1146             goto error_exit;
1147         }
1148 
1149         /* still owns a reference to the original object */
1150         Py_DECREF(o);
1151         o = res;
1152     }
1153 
1154     if (is_unicode) {
1155 #ifdef MS_WINDOWS
1156         wide = PyUnicode_AsUnicodeAndSize(o, &length);
1157         if (!wide) {
1158             goto error_exit;
1159         }
1160         if (length > 32767) {
1161             FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1162             goto error_exit;
1163         }
1164         if (wcslen(wide) != length) {
1165             FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1166             goto error_exit;
1167         }
1168 
1169         path->wide = wide;
1170         path->narrow = FALSE;
1171         path->fd = -1;
1172         goto success_exit;
1173 #else
1174         if (!PyUnicode_FSConverter(o, &bytes)) {
1175             goto error_exit;
1176         }
1177 #endif
1178     }
1179     else if (is_bytes) {
1180         bytes = o;
1181         Py_INCREF(bytes);
1182     }
1183     else if (is_buffer) {
1184         /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1185            after removing support of non-bytes buffer objects. */
1186         if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
1187             "%s%s%s should be %s, not %.200s",
1188             path->function_name ? path->function_name : "",
1189             path->function_name ? ": "                : "",
1190             path->argument_name ? path->argument_name : "path",
1191             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1192                                                "integer or None" :
1193             path->allow_fd ? "string, bytes, os.PathLike or integer" :
1194             path->nullable ? "string, bytes, os.PathLike or None" :
1195                              "string, bytes or os.PathLike",
1196             _PyType_Name(Py_TYPE(o)))) {
1197             goto error_exit;
1198         }
1199         bytes = PyBytes_FromObject(o);
1200         if (!bytes) {
1201             goto error_exit;
1202         }
1203     }
1204     else if (is_index) {
1205         if (!_fd_converter(o, &path->fd)) {
1206             goto error_exit;
1207         }
1208         path->wide = NULL;
1209 #ifdef MS_WINDOWS
1210         path->narrow = FALSE;
1211 #else
1212         path->narrow = NULL;
1213 #endif
1214         goto success_exit;
1215     }
1216     else {
1217  error_format:
1218         PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1219             path->function_name ? path->function_name : "",
1220             path->function_name ? ": "                : "",
1221             path->argument_name ? path->argument_name : "path",
1222             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1223                                                "integer or None" :
1224             path->allow_fd ? "string, bytes, os.PathLike or integer" :
1225             path->nullable ? "string, bytes, os.PathLike or None" :
1226                              "string, bytes or os.PathLike",
1227             _PyType_Name(Py_TYPE(o)));
1228         goto error_exit;
1229     }
1230 
1231     length = PyBytes_GET_SIZE(bytes);
1232     narrow = PyBytes_AS_STRING(bytes);
1233     if ((size_t)length != strlen(narrow)) {
1234         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1235         goto error_exit;
1236     }
1237 
1238 #ifdef MS_WINDOWS
1239     wo = PyUnicode_DecodeFSDefaultAndSize(
1240         narrow,
1241         length
1242     );
1243     if (!wo) {
1244         goto error_exit;
1245     }
1246 
1247     wide = PyUnicode_AsUnicodeAndSize(wo, &length);
1248     if (!wide) {
1249         goto error_exit;
1250     }
1251     if (length > 32767) {
1252         FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1253         goto error_exit;
1254     }
1255     if (wcslen(wide) != length) {
1256         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1257         goto error_exit;
1258     }
1259     path->wide = wide;
1260     path->narrow = TRUE;
1261     path->cleanup = wo;
1262     Py_DECREF(bytes);
1263 #else
1264     path->wide = NULL;
1265     path->narrow = narrow;
1266     if (bytes == o) {
1267         /* Still a reference owned by path->object, don't have to
1268            worry about path->narrow is used after free. */
1269         Py_DECREF(bytes);
1270     }
1271     else {
1272         path->cleanup = bytes;
1273     }
1274 #endif
1275     path->fd = -1;
1276 
1277  success_exit:
1278     path->length = length;
1279     path->object = o;
1280     return Py_CLEANUP_SUPPORTED;
1281 
1282  error_exit:
1283     Py_XDECREF(o);
1284     Py_XDECREF(bytes);
1285 #ifdef MS_WINDOWS
1286     Py_XDECREF(wo);
1287 #endif
1288     return 0;
1289 }
1290 
1291 static void
argument_unavailable_error(const char * function_name,const char * argument_name)1292 argument_unavailable_error(const char *function_name, const char *argument_name)
1293 {
1294     PyErr_Format(PyExc_NotImplementedError,
1295         "%s%s%s unavailable on this platform",
1296         (function_name != NULL) ? function_name : "",
1297         (function_name != NULL) ? ": ": "",
1298         argument_name);
1299 }
1300 
1301 static int
dir_fd_unavailable(PyObject * o,void * p)1302 dir_fd_unavailable(PyObject *o, void *p)
1303 {
1304     int dir_fd;
1305     if (!dir_fd_converter(o, &dir_fd))
1306         return 0;
1307     if (dir_fd != DEFAULT_DIR_FD) {
1308         argument_unavailable_error(NULL, "dir_fd");
1309         return 0;
1310     }
1311     *(int *)p = dir_fd;
1312     return 1;
1313 }
1314 
1315 static int
fd_specified(const char * function_name,int fd)1316 fd_specified(const char *function_name, int fd)
1317 {
1318     if (fd == -1)
1319         return 0;
1320 
1321     argument_unavailable_error(function_name, "fd");
1322     return 1;
1323 }
1324 
1325 static int
follow_symlinks_specified(const char * function_name,int follow_symlinks)1326 follow_symlinks_specified(const char *function_name, int follow_symlinks)
1327 {
1328     if (follow_symlinks)
1329         return 0;
1330 
1331     argument_unavailable_error(function_name, "follow_symlinks");
1332     return 1;
1333 }
1334 
1335 static int
path_and_dir_fd_invalid(const char * function_name,path_t * path,int dir_fd)1336 path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1337 {
1338     if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1339 #ifndef MS_WINDOWS
1340         && !path->narrow
1341 #endif
1342     ) {
1343         PyErr_Format(PyExc_ValueError,
1344                      "%s: can't specify dir_fd without matching path",
1345                      function_name);
1346         return 1;
1347     }
1348     return 0;
1349 }
1350 
1351 static int
dir_fd_and_fd_invalid(const char * function_name,int dir_fd,int fd)1352 dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1353 {
1354     if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1355         PyErr_Format(PyExc_ValueError,
1356                      "%s: can't specify both dir_fd and fd",
1357                      function_name);
1358         return 1;
1359     }
1360     return 0;
1361 }
1362 
1363 static int
fd_and_follow_symlinks_invalid(const char * function_name,int fd,int follow_symlinks)1364 fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1365                                int follow_symlinks)
1366 {
1367     if ((fd > 0) && (!follow_symlinks)) {
1368         PyErr_Format(PyExc_ValueError,
1369                      "%s: cannot use fd and follow_symlinks together",
1370                      function_name);
1371         return 1;
1372     }
1373     return 0;
1374 }
1375 
1376 static int
dir_fd_and_follow_symlinks_invalid(const char * function_name,int dir_fd,int follow_symlinks)1377 dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1378                                    int follow_symlinks)
1379 {
1380     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1381         PyErr_Format(PyExc_ValueError,
1382                      "%s: cannot use dir_fd and follow_symlinks together",
1383                      function_name);
1384         return 1;
1385     }
1386     return 0;
1387 }
1388 
1389 #ifdef MS_WINDOWS
1390     typedef long long Py_off_t;
1391 #else
1392     typedef off_t Py_off_t;
1393 #endif
1394 
1395 static int
Py_off_t_converter(PyObject * arg,void * addr)1396 Py_off_t_converter(PyObject *arg, void *addr)
1397 {
1398 #ifdef HAVE_LARGEFILE_SUPPORT
1399     *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1400 #else
1401     *((Py_off_t *)addr) = PyLong_AsLong(arg);
1402 #endif
1403     if (PyErr_Occurred())
1404         return 0;
1405     return 1;
1406 }
1407 
1408 static PyObject *
PyLong_FromPy_off_t(Py_off_t offset)1409 PyLong_FromPy_off_t(Py_off_t offset)
1410 {
1411 #ifdef HAVE_LARGEFILE_SUPPORT
1412     return PyLong_FromLongLong(offset);
1413 #else
1414     return PyLong_FromLong(offset);
1415 #endif
1416 }
1417 
1418 #ifdef HAVE_SIGSET_T
1419 /* Convert an iterable of integers to a sigset.
1420    Return 1 on success, return 0 and raise an exception on error. */
1421 int
_Py_Sigset_Converter(PyObject * obj,void * addr)1422 _Py_Sigset_Converter(PyObject *obj, void *addr)
1423 {
1424     sigset_t *mask = (sigset_t *)addr;
1425     PyObject *iterator, *item;
1426     long signum;
1427     int overflow;
1428 
1429     // The extra parens suppress the unreachable-code warning with clang on MacOS
1430     if (sigemptyset(mask) < (0)) {
1431         /* Probably only if mask == NULL. */
1432         PyErr_SetFromErrno(PyExc_OSError);
1433         return 0;
1434     }
1435 
1436     iterator = PyObject_GetIter(obj);
1437     if (iterator == NULL) {
1438         return 0;
1439     }
1440 
1441     while ((item = PyIter_Next(iterator)) != NULL) {
1442         signum = PyLong_AsLongAndOverflow(item, &overflow);
1443         Py_DECREF(item);
1444         if (signum <= 0 || signum >= NSIG) {
1445             if (overflow || signum != -1 || !PyErr_Occurred()) {
1446                 PyErr_Format(PyExc_ValueError,
1447                              "signal number %ld out of range", signum);
1448             }
1449             goto error;
1450         }
1451         if (sigaddset(mask, (int)signum)) {
1452             if (errno != EINVAL) {
1453                 /* Probably impossible */
1454                 PyErr_SetFromErrno(PyExc_OSError);
1455                 goto error;
1456             }
1457             /* For backwards compatibility, allow idioms such as
1458              * `range(1, NSIG)` but warn about invalid signal numbers
1459              */
1460             const char msg[] =
1461                 "invalid signal number %ld, please use valid_signals()";
1462             if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1463                 goto error;
1464             }
1465         }
1466     }
1467     if (!PyErr_Occurred()) {
1468         Py_DECREF(iterator);
1469         return 1;
1470     }
1471 
1472 error:
1473     Py_DECREF(iterator);
1474     return 0;
1475 }
1476 #endif /* HAVE_SIGSET_T */
1477 
1478 #ifdef MS_WINDOWS
1479 
1480 static int
win32_get_reparse_tag(HANDLE reparse_point_handle,ULONG * reparse_tag)1481 win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1482 {
1483     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1484     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1485     DWORD n_bytes_returned;
1486 
1487     if (0 == DeviceIoControl(
1488         reparse_point_handle,
1489         FSCTL_GET_REPARSE_POINT,
1490         NULL, 0, /* in buffer */
1491         target_buffer, sizeof(target_buffer),
1492         &n_bytes_returned,
1493         NULL)) /* we're not using OVERLAPPED_IO */
1494         return FALSE;
1495 
1496     if (reparse_tag)
1497         *reparse_tag = rdb->ReparseTag;
1498 
1499     return TRUE;
1500 }
1501 
1502 #endif /* MS_WINDOWS */
1503 
1504 /* Return a dictionary corresponding to the POSIX environment table */
1505 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1506 /* On Darwin/MacOSX a shared library or framework has no access to
1507 ** environ directly, we must obtain it with _NSGetEnviron(). See also
1508 ** man environ(7).
1509 */
1510 #include <crt_externs.h>
1511 #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1512 extern char **environ;
1513 #endif /* !_MSC_VER */
1514 
1515 static PyObject *
convertenviron(void)1516 convertenviron(void)
1517 {
1518     PyObject *d;
1519 #ifdef MS_WINDOWS
1520     wchar_t **e;
1521 #else
1522     char **e;
1523 #endif
1524 
1525     d = PyDict_New();
1526     if (d == NULL)
1527         return NULL;
1528 #ifdef MS_WINDOWS
1529     /* _wenviron must be initialized in this way if the program is started
1530        through main() instead of wmain(). */
1531     _wgetenv(L"");
1532     e = _wenviron;
1533 #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1534     /* environ is not accessible as an extern in a shared object on OSX; use
1535        _NSGetEnviron to resolve it. The value changes if you add environment
1536        variables between calls to Py_Initialize, so don't cache the value. */
1537     e = *_NSGetEnviron();
1538 #else
1539     e = environ;
1540 #endif
1541     if (e == NULL)
1542         return d;
1543     for (; *e != NULL; e++) {
1544         PyObject *k;
1545         PyObject *v;
1546 #ifdef MS_WINDOWS
1547         const wchar_t *p = wcschr(*e, L'=');
1548 #else
1549         const char *p = strchr(*e, '=');
1550 #endif
1551         if (p == NULL)
1552             continue;
1553 #ifdef MS_WINDOWS
1554         k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1555 #else
1556         k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1557 #endif
1558         if (k == NULL) {
1559             Py_DECREF(d);
1560             return NULL;
1561         }
1562 #ifdef MS_WINDOWS
1563         v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1564 #else
1565         v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1566 #endif
1567         if (v == NULL) {
1568             Py_DECREF(k);
1569             Py_DECREF(d);
1570             return NULL;
1571         }
1572         if (PyDict_GetItemWithError(d, k) == NULL) {
1573             if (PyErr_Occurred() || PyDict_SetItem(d, k, v) != 0) {
1574                 Py_DECREF(v);
1575                 Py_DECREF(k);
1576                 Py_DECREF(d);
1577                 return NULL;
1578             }
1579         }
1580         Py_DECREF(k);
1581         Py_DECREF(v);
1582     }
1583     return d;
1584 }
1585 
1586 /* Set a POSIX-specific error from errno, and return NULL */
1587 
1588 static PyObject *
posix_error(void)1589 posix_error(void)
1590 {
1591     return PyErr_SetFromErrno(PyExc_OSError);
1592 }
1593 
1594 #ifdef MS_WINDOWS
1595 static PyObject *
win32_error(const char * function,const char * filename)1596 win32_error(const char* function, const char* filename)
1597 {
1598     /* XXX We should pass the function name along in the future.
1599        (winreg.c also wants to pass the function name.)
1600        This would however require an additional param to the
1601        Windows error object, which is non-trivial.
1602     */
1603     errno = GetLastError();
1604     if (filename)
1605         return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1606     else
1607         return PyErr_SetFromWindowsErr(errno);
1608 }
1609 
1610 static PyObject *
win32_error_object_err(const char * function,PyObject * filename,DWORD err)1611 win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1612 {
1613     /* XXX - see win32_error for comments on 'function' */
1614     if (filename)
1615         return PyErr_SetExcFromWindowsErrWithFilenameObject(
1616                     PyExc_OSError,
1617                     err,
1618                     filename);
1619     else
1620         return PyErr_SetFromWindowsErr(err);
1621 }
1622 
1623 static PyObject *
win32_error_object(const char * function,PyObject * filename)1624 win32_error_object(const char* function, PyObject* filename)
1625 {
1626     errno = GetLastError();
1627     return win32_error_object_err(function, filename, errno);
1628 }
1629 
1630 #endif /* MS_WINDOWS */
1631 
1632 static PyObject *
posix_path_object_error(PyObject * path)1633 posix_path_object_error(PyObject *path)
1634 {
1635     return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1636 }
1637 
1638 static PyObject *
path_object_error(PyObject * path)1639 path_object_error(PyObject *path)
1640 {
1641 #ifdef MS_WINDOWS
1642     return PyErr_SetExcFromWindowsErrWithFilenameObject(
1643                 PyExc_OSError, 0, path);
1644 #else
1645     return posix_path_object_error(path);
1646 #endif
1647 }
1648 
1649 static PyObject *
path_object_error2(PyObject * path,PyObject * path2)1650 path_object_error2(PyObject *path, PyObject *path2)
1651 {
1652 #ifdef MS_WINDOWS
1653     return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1654                 PyExc_OSError, 0, path, path2);
1655 #else
1656     return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1657 #endif
1658 }
1659 
1660 static PyObject *
path_error(path_t * path)1661 path_error(path_t *path)
1662 {
1663     return path_object_error(path->object);
1664 }
1665 
1666 static PyObject *
posix_path_error(path_t * path)1667 posix_path_error(path_t *path)
1668 {
1669     return posix_path_object_error(path->object);
1670 }
1671 
1672 static PyObject *
path_error2(path_t * path,path_t * path2)1673 path_error2(path_t *path, path_t *path2)
1674 {
1675     return path_object_error2(path->object, path2->object);
1676 }
1677 
1678 
1679 /* POSIX generic methods */
1680 
1681 static int
fildes_converter(PyObject * o,void * p)1682 fildes_converter(PyObject *o, void *p)
1683 {
1684     int fd;
1685     int *pointer = (int *)p;
1686     fd = PyObject_AsFileDescriptor(o);
1687     if (fd < 0)
1688         return 0;
1689     *pointer = fd;
1690     return 1;
1691 }
1692 
1693 static PyObject *
posix_fildes_fd(int fd,int (* func)(int))1694 posix_fildes_fd(int fd, int (*func)(int))
1695 {
1696     int res;
1697     int async_err = 0;
1698 
1699     do {
1700         Py_BEGIN_ALLOW_THREADS
1701         _Py_BEGIN_SUPPRESS_IPH
1702         res = (*func)(fd);
1703         _Py_END_SUPPRESS_IPH
1704         Py_END_ALLOW_THREADS
1705     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1706     if (res != 0)
1707         return (!async_err) ? posix_error() : NULL;
1708     Py_RETURN_NONE;
1709 }
1710 
1711 
1712 #ifdef MS_WINDOWS
1713 /* This is a reimplementation of the C library's chdir function,
1714    but one that produces Win32 errors instead of DOS error codes.
1715    chdir is essentially a wrapper around SetCurrentDirectory; however,
1716    it also needs to set "magic" environment variables indicating
1717    the per-drive current directory, which are of the form =<drive>: */
1718 static BOOL __stdcall
win32_wchdir(LPCWSTR path)1719 win32_wchdir(LPCWSTR path)
1720 {
1721     wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1722     int result;
1723     wchar_t env[4] = L"=x:";
1724 
1725     if(!SetCurrentDirectoryW(path))
1726         return FALSE;
1727     result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1728     if (!result)
1729         return FALSE;
1730     if (result > Py_ARRAY_LENGTH(path_buf)) {
1731         new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1732         if (!new_path) {
1733             SetLastError(ERROR_OUTOFMEMORY);
1734             return FALSE;
1735         }
1736         result = GetCurrentDirectoryW(result, new_path);
1737         if (!result) {
1738             PyMem_RawFree(new_path);
1739             return FALSE;
1740         }
1741     }
1742     int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1743                             wcsncmp(new_path, L"//", 2) == 0);
1744     if (!is_unc_like_path) {
1745         env[1] = new_path[0];
1746         result = SetEnvironmentVariableW(env, new_path);
1747     }
1748     if (new_path != path_buf)
1749         PyMem_RawFree(new_path);
1750     return result ? TRUE : FALSE;
1751 }
1752 #endif
1753 
1754 #ifdef MS_WINDOWS
1755 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1756    - time stamps are restricted to second resolution
1757    - file modification times suffer from forth-and-back conversions between
1758      UTC and local time
1759    Therefore, we implement our own stat, based on the Win32 API directly.
1760 */
1761 #define HAVE_STAT_NSEC 1
1762 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1763 #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1764 
1765 static void
find_data_to_file_info(WIN32_FIND_DATAW * pFileData,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1766 find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1767                        BY_HANDLE_FILE_INFORMATION *info,
1768                        ULONG *reparse_tag)
1769 {
1770     memset(info, 0, sizeof(*info));
1771     info->dwFileAttributes = pFileData->dwFileAttributes;
1772     info->ftCreationTime   = pFileData->ftCreationTime;
1773     info->ftLastAccessTime = pFileData->ftLastAccessTime;
1774     info->ftLastWriteTime  = pFileData->ftLastWriteTime;
1775     info->nFileSizeHigh    = pFileData->nFileSizeHigh;
1776     info->nFileSizeLow     = pFileData->nFileSizeLow;
1777 /*  info->nNumberOfLinks   = 1; */
1778     if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1779         *reparse_tag = pFileData->dwReserved0;
1780     else
1781         *reparse_tag = 0;
1782 }
1783 
1784 static BOOL
attributes_from_dir(LPCWSTR pszFile,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1785 attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1786 {
1787     HANDLE hFindFile;
1788     WIN32_FIND_DATAW FileData;
1789     hFindFile = FindFirstFileW(pszFile, &FileData);
1790     if (hFindFile == INVALID_HANDLE_VALUE)
1791         return FALSE;
1792     FindClose(hFindFile);
1793     find_data_to_file_info(&FileData, info, reparse_tag);
1794     return TRUE;
1795 }
1796 
1797 static int
win32_xstat_impl(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1798 win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1799                  BOOL traverse)
1800 {
1801     HANDLE hFile;
1802     BY_HANDLE_FILE_INFORMATION fileInfo;
1803     FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1804     DWORD fileType, error;
1805     BOOL isUnhandledTag = FALSE;
1806     int retval = 0;
1807 
1808     DWORD access = FILE_READ_ATTRIBUTES;
1809     DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1810     if (!traverse) {
1811         flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1812     }
1813 
1814     hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1815     if (hFile == INVALID_HANDLE_VALUE) {
1816         /* Either the path doesn't exist, or the caller lacks access. */
1817         error = GetLastError();
1818         switch (error) {
1819         case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
1820         case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1821             /* Try reading the parent directory. */
1822             if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1823                 /* Cannot read the parent directory. */
1824                 SetLastError(error);
1825                 return -1;
1826             }
1827             if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1828                 if (traverse ||
1829                     !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1830                     /* The stat call has to traverse but cannot, so fail. */
1831                     SetLastError(error);
1832                     return -1;
1833                 }
1834             }
1835             break;
1836 
1837         case ERROR_INVALID_PARAMETER:
1838             /* \\.\con requires read or write access. */
1839             hFile = CreateFileW(path, access | GENERIC_READ,
1840                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1841                         OPEN_EXISTING, flags, NULL);
1842             if (hFile == INVALID_HANDLE_VALUE) {
1843                 SetLastError(error);
1844                 return -1;
1845             }
1846             break;
1847 
1848         case ERROR_CANT_ACCESS_FILE:
1849             /* bpo37834: open unhandled reparse points if traverse fails. */
1850             if (traverse) {
1851                 traverse = FALSE;
1852                 isUnhandledTag = TRUE;
1853                 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1854                             flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1855             }
1856             if (hFile == INVALID_HANDLE_VALUE) {
1857                 SetLastError(error);
1858                 return -1;
1859             }
1860             break;
1861 
1862         default:
1863             return -1;
1864         }
1865     }
1866 
1867     if (hFile != INVALID_HANDLE_VALUE) {
1868         /* Handle types other than files on disk. */
1869         fileType = GetFileType(hFile);
1870         if (fileType != FILE_TYPE_DISK) {
1871             if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1872                 retval = -1;
1873                 goto cleanup;
1874             }
1875             DWORD fileAttributes = GetFileAttributesW(path);
1876             memset(result, 0, sizeof(*result));
1877             if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1878                 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1879                 /* \\.\pipe\ or \\.\mailslot\ */
1880                 result->st_mode = _S_IFDIR;
1881             } else if (fileType == FILE_TYPE_CHAR) {
1882                 /* \\.\nul */
1883                 result->st_mode = _S_IFCHR;
1884             } else if (fileType == FILE_TYPE_PIPE) {
1885                 /* \\.\pipe\spam */
1886                 result->st_mode = _S_IFIFO;
1887             }
1888             /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1889             goto cleanup;
1890         }
1891 
1892         /* Query the reparse tag, and traverse a non-link. */
1893         if (!traverse) {
1894             if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
1895                     &tagInfo, sizeof(tagInfo))) {
1896                 /* Allow devices that do not support FileAttributeTagInfo. */
1897                 switch (GetLastError()) {
1898                 case ERROR_INVALID_PARAMETER:
1899                 case ERROR_INVALID_FUNCTION:
1900                 case ERROR_NOT_SUPPORTED:
1901                     tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1902                     tagInfo.ReparseTag = 0;
1903                     break;
1904                 default:
1905                     retval = -1;
1906                     goto cleanup;
1907                 }
1908             } else if (tagInfo.FileAttributes &
1909                          FILE_ATTRIBUTE_REPARSE_POINT) {
1910                 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1911                     if (isUnhandledTag) {
1912                         /* Traversing previously failed for either this link
1913                            or its target. */
1914                         SetLastError(ERROR_CANT_ACCESS_FILE);
1915                         retval = -1;
1916                         goto cleanup;
1917                     }
1918                 /* Traverse a non-link, but not if traversing already failed
1919                    for an unhandled tag. */
1920                 } else if (!isUnhandledTag) {
1921                     CloseHandle(hFile);
1922                     return win32_xstat_impl(path, result, TRUE);
1923                 }
1924             }
1925         }
1926 
1927         if (!GetFileInformationByHandle(hFile, &fileInfo)) {
1928             switch (GetLastError()) {
1929             case ERROR_INVALID_PARAMETER:
1930             case ERROR_INVALID_FUNCTION:
1931             case ERROR_NOT_SUPPORTED:
1932                 /* Volumes and physical disks are block devices, e.g.
1933                    \\.\C: and \\.\PhysicalDrive0. */
1934                 memset(result, 0, sizeof(*result));
1935                 result->st_mode = 0x6000; /* S_IFBLK */
1936                 goto cleanup;
1937             }
1938             retval = -1;
1939             goto cleanup;
1940         }
1941     }
1942 
1943     _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
1944 
1945     if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
1946         /* Fix the file execute permissions. This hack sets S_IEXEC if
1947            the filename has an extension that is commonly used by files
1948            that CreateProcessW can execute. A real implementation calls
1949            GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
1950            AccessCheck to check for generic read, write, and execute
1951            access. */
1952         const wchar_t *fileExtension = wcsrchr(path, '.');
1953         if (fileExtension) {
1954             if (_wcsicmp(fileExtension, L".exe") == 0 ||
1955                 _wcsicmp(fileExtension, L".bat") == 0 ||
1956                 _wcsicmp(fileExtension, L".cmd") == 0 ||
1957                 _wcsicmp(fileExtension, L".com") == 0) {
1958                 result->st_mode |= 0111;
1959             }
1960         }
1961     }
1962 
1963 cleanup:
1964     if (hFile != INVALID_HANDLE_VALUE) {
1965         /* Preserve last error if we are failing */
1966         error = retval ? GetLastError() : 0;
1967         if (!CloseHandle(hFile)) {
1968             retval = -1;
1969         } else if (retval) {
1970             /* Restore last error */
1971             SetLastError(error);
1972         }
1973     }
1974 
1975     return retval;
1976 }
1977 
1978 static int
win32_xstat(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1979 win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
1980 {
1981     /* Protocol violation: we explicitly clear errno, instead of
1982        setting it to a POSIX error. Callers should use GetLastError. */
1983     int code = win32_xstat_impl(path, result, traverse);
1984     errno = 0;
1985     return code;
1986 }
1987 /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
1988 
1989    In Posix, stat automatically traverses symlinks and returns the stat
1990    structure for the target.  In Windows, the equivalent GetFileAttributes by
1991    default does not traverse symlinks and instead returns attributes for
1992    the symlink.
1993 
1994    Instead, we will open the file (which *does* traverse symlinks by default)
1995    and GetFileInformationByHandle(). */
1996 
1997 static int
win32_lstat(const wchar_t * path,struct _Py_stat_struct * result)1998 win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
1999 {
2000     return win32_xstat(path, result, FALSE);
2001 }
2002 
2003 static int
win32_stat(const wchar_t * path,struct _Py_stat_struct * result)2004 win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2005 {
2006     return win32_xstat(path, result, TRUE);
2007 }
2008 
2009 #endif /* MS_WINDOWS */
2010 
2011 PyDoc_STRVAR(stat_result__doc__,
2012 "stat_result: Result from stat, fstat, or lstat.\n\n\
2013 This object may be accessed either as a tuple of\n\
2014   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2015 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2016 \n\
2017 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2018 or st_flags, they are available as attributes only.\n\
2019 \n\
2020 See os.stat for more information.");
2021 
2022 static PyStructSequence_Field stat_result_fields[] = {
2023     {"st_mode",    "protection bits"},
2024     {"st_ino",     "inode"},
2025     {"st_dev",     "device"},
2026     {"st_nlink",   "number of hard links"},
2027     {"st_uid",     "user ID of owner"},
2028     {"st_gid",     "group ID of owner"},
2029     {"st_size",    "total size, in bytes"},
2030     /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2031     {NULL,   "integer time of last access"},
2032     {NULL,   "integer time of last modification"},
2033     {NULL,   "integer time of last change"},
2034     {"st_atime",   "time of last access"},
2035     {"st_mtime",   "time of last modification"},
2036     {"st_ctime",   "time of last change"},
2037     {"st_atime_ns",   "time of last access in nanoseconds"},
2038     {"st_mtime_ns",   "time of last modification in nanoseconds"},
2039     {"st_ctime_ns",   "time of last change in nanoseconds"},
2040 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2041     {"st_blksize", "blocksize for filesystem I/O"},
2042 #endif
2043 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2044     {"st_blocks",  "number of blocks allocated"},
2045 #endif
2046 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2047     {"st_rdev",    "device type (if inode device)"},
2048 #endif
2049 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2050     {"st_flags",   "user defined flags for file"},
2051 #endif
2052 #ifdef HAVE_STRUCT_STAT_ST_GEN
2053     {"st_gen",    "generation number"},
2054 #endif
2055 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2056     {"st_birthtime",   "time of creation"},
2057 #endif
2058 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2059     {"st_file_attributes", "Windows file attribute bits"},
2060 #endif
2061 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2062     {"st_fstype",  "Type of filesystem"},
2063 #endif
2064 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2065     {"st_reparse_tag", "Windows reparse tag"},
2066 #endif
2067     {0}
2068 };
2069 
2070 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2071 #define ST_BLKSIZE_IDX 16
2072 #else
2073 #define ST_BLKSIZE_IDX 15
2074 #endif
2075 
2076 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2077 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2078 #else
2079 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2080 #endif
2081 
2082 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2083 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2084 #else
2085 #define ST_RDEV_IDX ST_BLOCKS_IDX
2086 #endif
2087 
2088 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2089 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2090 #else
2091 #define ST_FLAGS_IDX ST_RDEV_IDX
2092 #endif
2093 
2094 #ifdef HAVE_STRUCT_STAT_ST_GEN
2095 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
2096 #else
2097 #define ST_GEN_IDX ST_FLAGS_IDX
2098 #endif
2099 
2100 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2101 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2102 #else
2103 #define ST_BIRTHTIME_IDX ST_GEN_IDX
2104 #endif
2105 
2106 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2107 #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
2108 #else
2109 #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
2110 #endif
2111 
2112 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2113 #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2114 #else
2115 #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2116 #endif
2117 
2118 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2119 #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2120 #else
2121 #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2122 #endif
2123 
2124 static PyStructSequence_Desc stat_result_desc = {
2125     "stat_result", /* name */
2126     stat_result__doc__, /* doc */
2127     stat_result_fields,
2128     10
2129 };
2130 
2131 PyDoc_STRVAR(statvfs_result__doc__,
2132 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
2133 This object may be accessed either as a tuple of\n\
2134   (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2135 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2136 \n\
2137 See os.statvfs for more information.");
2138 
2139 static PyStructSequence_Field statvfs_result_fields[] = {
2140     {"f_bsize",  },
2141     {"f_frsize", },
2142     {"f_blocks", },
2143     {"f_bfree",  },
2144     {"f_bavail", },
2145     {"f_files",  },
2146     {"f_ffree",  },
2147     {"f_favail", },
2148     {"f_flag",   },
2149     {"f_namemax",},
2150     {"f_fsid",   },
2151     {0}
2152 };
2153 
2154 static PyStructSequence_Desc statvfs_result_desc = {
2155     "statvfs_result", /* name */
2156     statvfs_result__doc__, /* doc */
2157     statvfs_result_fields,
2158     10
2159 };
2160 
2161 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2162 PyDoc_STRVAR(waitid_result__doc__,
2163 "waitid_result: Result from waitid.\n\n\
2164 This object may be accessed either as a tuple of\n\
2165   (si_pid, si_uid, si_signo, si_status, si_code),\n\
2166 or via the attributes si_pid, si_uid, and so on.\n\
2167 \n\
2168 See os.waitid for more information.");
2169 
2170 static PyStructSequence_Field waitid_result_fields[] = {
2171     {"si_pid",  },
2172     {"si_uid", },
2173     {"si_signo", },
2174     {"si_status",  },
2175     {"si_code", },
2176     {0}
2177 };
2178 
2179 static PyStructSequence_Desc waitid_result_desc = {
2180     "waitid_result", /* name */
2181     waitid_result__doc__, /* doc */
2182     waitid_result_fields,
2183     5
2184 };
2185 #endif
2186 static newfunc structseq_new;
2187 
2188 static PyObject *
statresult_new(PyTypeObject * type,PyObject * args,PyObject * kwds)2189 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2190 {
2191     PyStructSequence *result;
2192     int i;
2193 
2194     result = (PyStructSequence*)structseq_new(type, args, kwds);
2195     if (!result)
2196         return NULL;
2197     /* If we have been initialized from a tuple,
2198        st_?time might be set to None. Initialize it
2199        from the int slots.  */
2200     for (i = 7; i <= 9; i++) {
2201         if (result->ob_item[i+3] == Py_None) {
2202             Py_DECREF(Py_None);
2203             Py_INCREF(result->ob_item[i]);
2204             result->ob_item[i+3] = result->ob_item[i];
2205         }
2206     }
2207     return (PyObject*)result;
2208 }
2209 
2210 static int
_posix_clear(PyObject * module)2211 _posix_clear(PyObject *module)
2212 {
2213     _posixstate *state = get_posix_state(module);
2214     Py_CLEAR(state->billion);
2215     Py_CLEAR(state->DirEntryType);
2216     Py_CLEAR(state->ScandirIteratorType);
2217 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2218     Py_CLEAR(state->SchedParamType);
2219 #endif
2220     Py_CLEAR(state->StatResultType);
2221     Py_CLEAR(state->StatVFSResultType);
2222     Py_CLEAR(state->TerminalSizeType);
2223     Py_CLEAR(state->TimesResultType);
2224     Py_CLEAR(state->UnameResultType);
2225 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2226     Py_CLEAR(state->WaitidResultType);
2227 #endif
2228 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2229     Py_CLEAR(state->struct_rusage);
2230 #endif
2231     Py_CLEAR(state->st_mode);
2232     return 0;
2233 }
2234 
2235 static int
_posix_traverse(PyObject * module,visitproc visit,void * arg)2236 _posix_traverse(PyObject *module, visitproc visit, void *arg)
2237 {
2238     _posixstate *state = get_posix_state(module);
2239     Py_VISIT(state->billion);
2240     Py_VISIT(state->DirEntryType);
2241     Py_VISIT(state->ScandirIteratorType);
2242 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2243     Py_VISIT(state->SchedParamType);
2244 #endif
2245     Py_VISIT(state->StatResultType);
2246     Py_VISIT(state->StatVFSResultType);
2247     Py_VISIT(state->TerminalSizeType);
2248     Py_VISIT(state->TimesResultType);
2249     Py_VISIT(state->UnameResultType);
2250 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2251     Py_VISIT(state->WaitidResultType);
2252 #endif
2253 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2254     Py_VISIT(state->struct_rusage);
2255 #endif
2256     Py_VISIT(state->st_mode);
2257     return 0;
2258 }
2259 
2260 static void
_posix_free(void * module)2261 _posix_free(void *module)
2262 {
2263    _posix_clear((PyObject *)module);
2264 }
2265 
2266 static void
fill_time(PyObject * module,PyObject * v,int index,time_t sec,unsigned long nsec)2267 fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)
2268 {
2269     PyObject *s = _PyLong_FromTime_t(sec);
2270     PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2271     PyObject *s_in_ns = NULL;
2272     PyObject *ns_total = NULL;
2273     PyObject *float_s = NULL;
2274 
2275     if (!(s && ns_fractional))
2276         goto exit;
2277 
2278     s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2279     if (!s_in_ns)
2280         goto exit;
2281 
2282     ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2283     if (!ns_total)
2284         goto exit;
2285 
2286     float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2287     if (!float_s) {
2288         goto exit;
2289     }
2290 
2291     PyStructSequence_SET_ITEM(v, index, s);
2292     PyStructSequence_SET_ITEM(v, index+3, float_s);
2293     PyStructSequence_SET_ITEM(v, index+6, ns_total);
2294     s = NULL;
2295     float_s = NULL;
2296     ns_total = NULL;
2297 exit:
2298     Py_XDECREF(s);
2299     Py_XDECREF(ns_fractional);
2300     Py_XDECREF(s_in_ns);
2301     Py_XDECREF(ns_total);
2302     Py_XDECREF(float_s);
2303 }
2304 
2305 /* pack a system stat C structure into the Python stat tuple
2306    (used by posix_stat() and posix_fstat()) */
2307 static PyObject*
_pystat_fromstructstat(PyObject * module,STRUCT_STAT * st)2308 _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2309 {
2310     unsigned long ansec, mnsec, cnsec;
2311     PyObject *StatResultType = get_posix_state(module)->StatResultType;
2312     PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2313     if (v == NULL)
2314         return NULL;
2315 
2316     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2317     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(st->st_ino));
2318     PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2319 #ifdef MS_WINDOWS
2320     PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
2321 #else
2322     PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2323 #endif
2324     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2325 #if defined(MS_WINDOWS)
2326     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2327     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2328 #else
2329     PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2330     PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2331 #endif
2332     Py_BUILD_ASSERT(sizeof(long long) >= sizeof(st->st_size));
2333     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2334 
2335 #if defined(HAVE_STAT_TV_NSEC)
2336     ansec = st->st_atim.tv_nsec;
2337     mnsec = st->st_mtim.tv_nsec;
2338     cnsec = st->st_ctim.tv_nsec;
2339 #elif defined(HAVE_STAT_TV_NSEC2)
2340     ansec = st->st_atimespec.tv_nsec;
2341     mnsec = st->st_mtimespec.tv_nsec;
2342     cnsec = st->st_ctimespec.tv_nsec;
2343 #elif defined(HAVE_STAT_NSEC)
2344     ansec = st->st_atime_nsec;
2345     mnsec = st->st_mtime_nsec;
2346     cnsec = st->st_ctime_nsec;
2347 #else
2348     ansec = mnsec = cnsec = 0;
2349 #endif
2350     fill_time(module, v, 7, st->st_atime, ansec);
2351     fill_time(module, v, 8, st->st_mtime, mnsec);
2352     fill_time(module, v, 9, st->st_ctime, cnsec);
2353 
2354 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2355     PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2356                               PyLong_FromLong((long)st->st_blksize));
2357 #endif
2358 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2359     PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2360                               PyLong_FromLong((long)st->st_blocks));
2361 #endif
2362 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2363     PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2364                               PyLong_FromLong((long)st->st_rdev));
2365 #endif
2366 #ifdef HAVE_STRUCT_STAT_ST_GEN
2367     PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2368                               PyLong_FromLong((long)st->st_gen));
2369 #endif
2370 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2371     {
2372       PyObject *val;
2373       unsigned long bsec,bnsec;
2374       bsec = (long)st->st_birthtime;
2375 #ifdef HAVE_STAT_TV_NSEC2
2376       bnsec = st->st_birthtimespec.tv_nsec;
2377 #else
2378       bnsec = 0;
2379 #endif
2380       val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2381       PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2382                                 val);
2383     }
2384 #endif
2385 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2386     PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2387                               PyLong_FromLong((long)st->st_flags));
2388 #endif
2389 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2390     PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2391                               PyLong_FromUnsignedLong(st->st_file_attributes));
2392 #endif
2393 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2394    PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2395                               PyUnicode_FromString(st->st_fstype));
2396 #endif
2397 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2398     PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2399                               PyLong_FromUnsignedLong(st->st_reparse_tag));
2400 #endif
2401 
2402     if (PyErr_Occurred()) {
2403         Py_DECREF(v);
2404         return NULL;
2405     }
2406 
2407     return v;
2408 }
2409 
2410 /* POSIX methods */
2411 
2412 
2413 static PyObject *
posix_do_stat(PyObject * module,const char * function_name,path_t * path,int dir_fd,int follow_symlinks)2414 posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2415               int dir_fd, int follow_symlinks)
2416 {
2417     STRUCT_STAT st;
2418     int result;
2419 
2420 #ifdef HAVE_FSTATAT
2421     int fstatat_unavailable = 0;
2422 #endif
2423 
2424 #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2425     if (follow_symlinks_specified(function_name, follow_symlinks))
2426         return NULL;
2427 #endif
2428 
2429     if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2430         dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2431         fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2432         return NULL;
2433 
2434     Py_BEGIN_ALLOW_THREADS
2435     if (path->fd != -1)
2436         result = FSTAT(path->fd, &st);
2437 #ifdef MS_WINDOWS
2438     else if (follow_symlinks)
2439         result = win32_stat(path->wide, &st);
2440     else
2441         result = win32_lstat(path->wide, &st);
2442 #else
2443     else
2444 #if defined(HAVE_LSTAT)
2445     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2446         result = LSTAT(path->narrow, &st);
2447     else
2448 #endif /* HAVE_LSTAT */
2449 #ifdef HAVE_FSTATAT
2450     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2451         if (HAVE_FSTATAT_RUNTIME) {
2452             result = fstatat(dir_fd, path->narrow, &st,
2453                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2454 
2455         } else {
2456             fstatat_unavailable = 1;
2457         }
2458     } else
2459 #endif /* HAVE_FSTATAT */
2460         result = STAT(path->narrow, &st);
2461 #endif /* MS_WINDOWS */
2462     Py_END_ALLOW_THREADS
2463 
2464 #ifdef HAVE_FSTATAT
2465     if (fstatat_unavailable) {
2466         argument_unavailable_error("stat", "dir_fd");
2467         return NULL;
2468     }
2469 #endif
2470 
2471     if (result != 0) {
2472         return path_error(path);
2473     }
2474 
2475     return _pystat_fromstructstat(module, &st);
2476 }
2477 
2478 /*[python input]
2479 
2480 for s in """
2481 
2482 FACCESSAT
2483 FCHMODAT
2484 FCHOWNAT
2485 FSTATAT
2486 LINKAT
2487 MKDIRAT
2488 MKFIFOAT
2489 MKNODAT
2490 OPENAT
2491 READLINKAT
2492 SYMLINKAT
2493 UNLINKAT
2494 
2495 """.strip().split():
2496     s = s.strip()
2497     print("""
2498 #ifdef HAVE_{s}
2499     #define {s}_DIR_FD_CONVERTER dir_fd_converter
2500 #else
2501     #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2502 #endif
2503 """.rstrip().format(s=s))
2504 
2505 for s in """
2506 
2507 FCHDIR
2508 FCHMOD
2509 FCHOWN
2510 FDOPENDIR
2511 FEXECVE
2512 FPATHCONF
2513 FSTATVFS
2514 FTRUNCATE
2515 
2516 """.strip().split():
2517     s = s.strip()
2518     print("""
2519 #ifdef HAVE_{s}
2520     #define PATH_HAVE_{s} 1
2521 #else
2522     #define PATH_HAVE_{s} 0
2523 #endif
2524 
2525 """.rstrip().format(s=s))
2526 [python start generated code]*/
2527 
2528 #ifdef HAVE_FACCESSAT
2529     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2530 #else
2531     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2532 #endif
2533 
2534 #ifdef HAVE_FCHMODAT
2535     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2536 #else
2537     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2538 #endif
2539 
2540 #ifdef HAVE_FCHOWNAT
2541     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2542 #else
2543     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2544 #endif
2545 
2546 #ifdef HAVE_FSTATAT
2547     #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2548 #else
2549     #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2550 #endif
2551 
2552 #ifdef HAVE_LINKAT
2553     #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2554 #else
2555     #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2556 #endif
2557 
2558 #ifdef HAVE_MKDIRAT
2559     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2560 #else
2561     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2562 #endif
2563 
2564 #ifdef HAVE_MKFIFOAT
2565     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2566 #else
2567     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2568 #endif
2569 
2570 #ifdef HAVE_MKNODAT
2571     #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2572 #else
2573     #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2574 #endif
2575 
2576 #ifdef HAVE_OPENAT
2577     #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2578 #else
2579     #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2580 #endif
2581 
2582 #ifdef HAVE_READLINKAT
2583     #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2584 #else
2585     #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2586 #endif
2587 
2588 #ifdef HAVE_SYMLINKAT
2589     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2590 #else
2591     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2592 #endif
2593 
2594 #ifdef HAVE_UNLINKAT
2595     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2596 #else
2597     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2598 #endif
2599 
2600 #ifdef HAVE_FCHDIR
2601     #define PATH_HAVE_FCHDIR 1
2602 #else
2603     #define PATH_HAVE_FCHDIR 0
2604 #endif
2605 
2606 #ifdef HAVE_FCHMOD
2607     #define PATH_HAVE_FCHMOD 1
2608 #else
2609     #define PATH_HAVE_FCHMOD 0
2610 #endif
2611 
2612 #ifdef HAVE_FCHOWN
2613     #define PATH_HAVE_FCHOWN 1
2614 #else
2615     #define PATH_HAVE_FCHOWN 0
2616 #endif
2617 
2618 #ifdef HAVE_FDOPENDIR
2619     #define PATH_HAVE_FDOPENDIR 1
2620 #else
2621     #define PATH_HAVE_FDOPENDIR 0
2622 #endif
2623 
2624 #ifdef HAVE_FEXECVE
2625     #define PATH_HAVE_FEXECVE 1
2626 #else
2627     #define PATH_HAVE_FEXECVE 0
2628 #endif
2629 
2630 #ifdef HAVE_FPATHCONF
2631     #define PATH_HAVE_FPATHCONF 1
2632 #else
2633     #define PATH_HAVE_FPATHCONF 0
2634 #endif
2635 
2636 #ifdef HAVE_FSTATVFS
2637     #define PATH_HAVE_FSTATVFS 1
2638 #else
2639     #define PATH_HAVE_FSTATVFS 0
2640 #endif
2641 
2642 #ifdef HAVE_FTRUNCATE
2643     #define PATH_HAVE_FTRUNCATE 1
2644 #else
2645     #define PATH_HAVE_FTRUNCATE 0
2646 #endif
2647 /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2648 
2649 #ifdef MS_WINDOWS
2650     #undef PATH_HAVE_FTRUNCATE
2651     #define PATH_HAVE_FTRUNCATE 1
2652 #endif
2653 
2654 /*[python input]
2655 
2656 class path_t_converter(CConverter):
2657 
2658     type = "path_t"
2659     impl_by_reference = True
2660     parse_by_reference = True
2661 
2662     converter = 'path_converter'
2663 
2664     def converter_init(self, *, allow_fd=False, nullable=False):
2665         # right now path_t doesn't support default values.
2666         # to support a default value, you'll need to override initialize().
2667         if self.default not in (unspecified, None):
2668             fail("Can't specify a default to the path_t converter!")
2669 
2670         if self.c_default not in (None, 'Py_None'):
2671             raise RuntimeError("Can't specify a c_default to the path_t converter!")
2672 
2673         self.nullable = nullable
2674         self.allow_fd = allow_fd
2675 
2676     def pre_render(self):
2677         def strify(value):
2678             if isinstance(value, str):
2679                 return value
2680             return str(int(bool(value)))
2681 
2682         # add self.py_name here when merging with posixmodule conversion
2683         self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2684             self.function.name,
2685             self.name,
2686             strify(self.nullable),
2687             strify(self.allow_fd),
2688             )
2689 
2690     def cleanup(self):
2691         return "path_cleanup(&" + self.name + ");\n"
2692 
2693 
2694 class dir_fd_converter(CConverter):
2695     type = 'int'
2696 
2697     def converter_init(self, requires=None):
2698         if self.default in (unspecified, None):
2699             self.c_default = 'DEFAULT_DIR_FD'
2700         if isinstance(requires, str):
2701             self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2702         else:
2703             self.converter = 'dir_fd_converter'
2704 
2705 class fildes_converter(CConverter):
2706     type = 'int'
2707     converter = 'fildes_converter'
2708 
2709 class uid_t_converter(CConverter):
2710     type = "uid_t"
2711     converter = '_Py_Uid_Converter'
2712 
2713 class gid_t_converter(CConverter):
2714     type = "gid_t"
2715     converter = '_Py_Gid_Converter'
2716 
2717 class dev_t_converter(CConverter):
2718     type = 'dev_t'
2719     converter = '_Py_Dev_Converter'
2720 
2721 class dev_t_return_converter(unsigned_long_return_converter):
2722     type = 'dev_t'
2723     conversion_fn = '_PyLong_FromDev'
2724     unsigned_cast = '(dev_t)'
2725 
2726 class FSConverter_converter(CConverter):
2727     type = 'PyObject *'
2728     converter = 'PyUnicode_FSConverter'
2729     def converter_init(self):
2730         if self.default is not unspecified:
2731             fail("FSConverter_converter does not support default values")
2732         self.c_default = 'NULL'
2733 
2734     def cleanup(self):
2735         return "Py_XDECREF(" + self.name + ");\n"
2736 
2737 class pid_t_converter(CConverter):
2738     type = 'pid_t'
2739     format_unit = '" _Py_PARSE_PID "'
2740 
2741 class idtype_t_converter(int_converter):
2742     type = 'idtype_t'
2743 
2744 class id_t_converter(CConverter):
2745     type = 'id_t'
2746     format_unit = '" _Py_PARSE_PID "'
2747 
2748 class intptr_t_converter(CConverter):
2749     type = 'intptr_t'
2750     format_unit = '" _Py_PARSE_INTPTR "'
2751 
2752 class Py_off_t_converter(CConverter):
2753     type = 'Py_off_t'
2754     converter = 'Py_off_t_converter'
2755 
2756 class Py_off_t_return_converter(long_return_converter):
2757     type = 'Py_off_t'
2758     conversion_fn = 'PyLong_FromPy_off_t'
2759 
2760 class path_confname_converter(CConverter):
2761     type="int"
2762     converter="conv_path_confname"
2763 
2764 class confstr_confname_converter(path_confname_converter):
2765     converter='conv_confstr_confname'
2766 
2767 class sysconf_confname_converter(path_confname_converter):
2768     converter="conv_sysconf_confname"
2769 
2770 [python start generated code]*/
2771 /*[python end generated code: output=da39a3ee5e6b4b0d input=f1c8ae8d744f6c8b]*/
2772 
2773 /*[clinic input]
2774 
2775 os.stat
2776 
2777     path : path_t(allow_fd=True)
2778         Path to be examined; can be string, bytes, a path-like object or
2779         open-file-descriptor int.
2780 
2781     *
2782 
2783     dir_fd : dir_fd(requires='fstatat') = None
2784         If not None, it should be a file descriptor open to a directory,
2785         and path should be a relative string; path will then be relative to
2786         that directory.
2787 
2788     follow_symlinks: bool = True
2789         If False, and the last element of the path is a symbolic link,
2790         stat will examine the symbolic link itself instead of the file
2791         the link points to.
2792 
2793 Perform a stat system call on the given path.
2794 
2795 dir_fd and follow_symlinks may not be implemented
2796   on your platform.  If they are unavailable, using them will raise a
2797   NotImplementedError.
2798 
2799 It's an error to use dir_fd or follow_symlinks when specifying path as
2800   an open file descriptor.
2801 
2802 [clinic start generated code]*/
2803 
2804 static PyObject *
os_stat_impl(PyObject * module,path_t * path,int dir_fd,int follow_symlinks)2805 os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2806 /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2807 {
2808     return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
2809 }
2810 
2811 
2812 /*[clinic input]
2813 os.lstat
2814 
2815     path : path_t
2816 
2817     *
2818 
2819     dir_fd : dir_fd(requires='fstatat') = None
2820 
2821 Perform a stat system call on the given path, without following symbolic links.
2822 
2823 Like stat(), but do not follow symbolic links.
2824 Equivalent to stat(path, follow_symlinks=False).
2825 [clinic start generated code]*/
2826 
2827 static PyObject *
os_lstat_impl(PyObject * module,path_t * path,int dir_fd)2828 os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2829 /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2830 {
2831     int follow_symlinks = 0;
2832     return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
2833 }
2834 
2835 
2836 /*[clinic input]
2837 os.access -> bool
2838 
2839     path: path_t
2840         Path to be tested; can be string, bytes, or a path-like object.
2841 
2842     mode: int
2843         Operating-system mode bitfield.  Can be F_OK to test existence,
2844         or the inclusive-OR of R_OK, W_OK, and X_OK.
2845 
2846     *
2847 
2848     dir_fd : dir_fd(requires='faccessat') = None
2849         If not None, it should be a file descriptor open to a directory,
2850         and path should be relative; path will then be relative to that
2851         directory.
2852 
2853     effective_ids: bool = False
2854         If True, access will use the effective uid/gid instead of
2855         the real uid/gid.
2856 
2857     follow_symlinks: bool = True
2858         If False, and the last element of the path is a symbolic link,
2859         access will examine the symbolic link itself instead of the file
2860         the link points to.
2861 
2862 Use the real uid/gid to test for access to a path.
2863 
2864 {parameters}
2865 dir_fd, effective_ids, and follow_symlinks may not be implemented
2866   on your platform.  If they are unavailable, using them will raise a
2867   NotImplementedError.
2868 
2869 Note that most operations will use the effective uid/gid, therefore this
2870   routine can be used in a suid/sgid environment to test if the invoking user
2871   has the specified access to the path.
2872 
2873 [clinic start generated code]*/
2874 
2875 static int
os_access_impl(PyObject * module,path_t * path,int mode,int dir_fd,int effective_ids,int follow_symlinks)2876 os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2877                int effective_ids, int follow_symlinks)
2878 /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
2879 {
2880     int return_value;
2881 
2882 #ifdef MS_WINDOWS
2883     DWORD attr;
2884 #else
2885     int result;
2886 #endif
2887 
2888 #ifdef HAVE_FACCESSAT
2889     int faccessat_unavailable = 0;
2890 #endif
2891 
2892 #ifndef HAVE_FACCESSAT
2893     if (follow_symlinks_specified("access", follow_symlinks))
2894         return -1;
2895 
2896     if (effective_ids) {
2897         argument_unavailable_error("access", "effective_ids");
2898         return -1;
2899     }
2900 #endif
2901 
2902 #ifdef MS_WINDOWS
2903     Py_BEGIN_ALLOW_THREADS
2904     attr = GetFileAttributesW(path->wide);
2905     Py_END_ALLOW_THREADS
2906 
2907     /*
2908      * Access is possible if
2909      *   * we didn't get a -1, and
2910      *     * write access wasn't requested,
2911      *     * or the file isn't read-only,
2912      *     * or it's a directory.
2913      * (Directories cannot be read-only on Windows.)
2914     */
2915     return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
2916             (!(mode & 2) ||
2917             !(attr & FILE_ATTRIBUTE_READONLY) ||
2918             (attr & FILE_ATTRIBUTE_DIRECTORY));
2919 #else
2920 
2921     Py_BEGIN_ALLOW_THREADS
2922 #ifdef HAVE_FACCESSAT
2923     if ((dir_fd != DEFAULT_DIR_FD) ||
2924         effective_ids ||
2925         !follow_symlinks) {
2926 
2927         if (HAVE_FACCESSAT_RUNTIME) {
2928             int flags = 0;
2929             if (!follow_symlinks)
2930                 flags |= AT_SYMLINK_NOFOLLOW;
2931             if (effective_ids)
2932                 flags |= AT_EACCESS;
2933             result = faccessat(dir_fd, path->narrow, mode, flags);
2934         } else {
2935             faccessat_unavailable = 1;
2936         }
2937     }
2938     else
2939 #endif
2940         result = access(path->narrow, mode);
2941     Py_END_ALLOW_THREADS
2942 
2943 #ifdef HAVE_FACCESSAT
2944     if (faccessat_unavailable) {
2945         if (dir_fd != DEFAULT_DIR_FD) {
2946             argument_unavailable_error("access", "dir_fd");
2947             return -1;
2948         }
2949         if (follow_symlinks_specified("access", follow_symlinks))
2950             return -1;
2951 
2952         if (effective_ids) {
2953             argument_unavailable_error("access", "effective_ids");
2954             return -1;
2955         }
2956         /* should be unreachable */
2957         return -1;
2958     }
2959 #endif
2960     return_value = !result;
2961 #endif
2962 
2963     return return_value;
2964 }
2965 
2966 #ifndef F_OK
2967 #define F_OK 0
2968 #endif
2969 #ifndef R_OK
2970 #define R_OK 4
2971 #endif
2972 #ifndef W_OK
2973 #define W_OK 2
2974 #endif
2975 #ifndef X_OK
2976 #define X_OK 1
2977 #endif
2978 
2979 
2980 #ifdef HAVE_TTYNAME
2981 /*[clinic input]
2982 os.ttyname
2983 
2984     fd: int
2985         Integer file descriptor handle.
2986 
2987     /
2988 
2989 Return the name of the terminal device connected to 'fd'.
2990 [clinic start generated code]*/
2991 
2992 static PyObject *
os_ttyname_impl(PyObject * module,int fd)2993 os_ttyname_impl(PyObject *module, int fd)
2994 /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
2995 {
2996 
2997     long size = sysconf(_SC_TTY_NAME_MAX);
2998     if (size == -1) {
2999         return posix_error();
3000     }
3001     char *buffer = (char *)PyMem_RawMalloc(size);
3002     if (buffer == NULL) {
3003         return PyErr_NoMemory();
3004     }
3005     int ret = ttyname_r(fd, buffer, size);
3006     if (ret != 0) {
3007         PyMem_RawFree(buffer);
3008         errno = ret;
3009         return posix_error();
3010     }
3011     PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3012     PyMem_RawFree(buffer);
3013     return res;
3014 }
3015 #endif
3016 
3017 #ifdef HAVE_CTERMID
3018 /*[clinic input]
3019 os.ctermid
3020 
3021 Return the name of the controlling terminal for this process.
3022 [clinic start generated code]*/
3023 
3024 static PyObject *
os_ctermid_impl(PyObject * module)3025 os_ctermid_impl(PyObject *module)
3026 /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3027 {
3028     char *ret;
3029     char buffer[L_ctermid];
3030 
3031 #ifdef USE_CTERMID_R
3032     ret = ctermid_r(buffer);
3033 #else
3034     ret = ctermid(buffer);
3035 #endif
3036     if (ret == NULL)
3037         return posix_error();
3038     return PyUnicode_DecodeFSDefault(buffer);
3039 }
3040 #endif /* HAVE_CTERMID */
3041 
3042 
3043 /*[clinic input]
3044 os.chdir
3045 
3046     path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3047 
3048 Change the current working directory to the specified path.
3049 
3050 path may always be specified as a string.
3051 On some platforms, path may also be specified as an open file descriptor.
3052   If this functionality is unavailable, using it raises an exception.
3053 [clinic start generated code]*/
3054 
3055 static PyObject *
os_chdir_impl(PyObject * module,path_t * path)3056 os_chdir_impl(PyObject *module, path_t *path)
3057 /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3058 {
3059     int result;
3060 
3061     if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3062         return NULL;
3063     }
3064 
3065     Py_BEGIN_ALLOW_THREADS
3066 #ifdef MS_WINDOWS
3067     /* on unix, success = 0, on windows, success = !0 */
3068     result = !win32_wchdir(path->wide);
3069 #else
3070 #ifdef HAVE_FCHDIR
3071     if (path->fd != -1)
3072         result = fchdir(path->fd);
3073     else
3074 #endif
3075         result = chdir(path->narrow);
3076 #endif
3077     Py_END_ALLOW_THREADS
3078 
3079     if (result) {
3080         return path_error(path);
3081     }
3082 
3083     Py_RETURN_NONE;
3084 }
3085 
3086 
3087 #ifdef HAVE_FCHDIR
3088 /*[clinic input]
3089 os.fchdir
3090 
3091     fd: fildes
3092 
3093 Change to the directory of the given file descriptor.
3094 
3095 fd must be opened on a directory, not a file.
3096 Equivalent to os.chdir(fd).
3097 
3098 [clinic start generated code]*/
3099 
3100 static PyObject *
os_fchdir_impl(PyObject * module,int fd)3101 os_fchdir_impl(PyObject *module, int fd)
3102 /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3103 {
3104     if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3105         return NULL;
3106     }
3107     return posix_fildes_fd(fd, fchdir);
3108 }
3109 #endif /* HAVE_FCHDIR */
3110 
3111 
3112 /*[clinic input]
3113 os.chmod
3114 
3115     path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3116         Path to be modified.  May always be specified as a str, bytes, or a path-like object.
3117         On some platforms, path may also be specified as an open file descriptor.
3118         If this functionality is unavailable, using it raises an exception.
3119 
3120     mode: int
3121         Operating-system mode bitfield.
3122 
3123     *
3124 
3125     dir_fd : dir_fd(requires='fchmodat') = None
3126         If not None, it should be a file descriptor open to a directory,
3127         and path should be relative; path will then be relative to that
3128         directory.
3129 
3130     follow_symlinks: bool = True
3131         If False, and the last element of the path is a symbolic link,
3132         chmod will modify the symbolic link itself instead of the file
3133         the link points to.
3134 
3135 Change the access permissions of a file.
3136 
3137 It is an error to use dir_fd or follow_symlinks when specifying path as
3138   an open file descriptor.
3139 dir_fd and follow_symlinks may not be implemented on your platform.
3140   If they are unavailable, using them will raise a NotImplementedError.
3141 
3142 [clinic start generated code]*/
3143 
3144 static PyObject *
os_chmod_impl(PyObject * module,path_t * path,int mode,int dir_fd,int follow_symlinks)3145 os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3146               int follow_symlinks)
3147 /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
3148 {
3149     int result;
3150 
3151 #ifdef MS_WINDOWS
3152     DWORD attr;
3153 #endif
3154 
3155 #ifdef HAVE_FCHMODAT
3156     int fchmodat_nofollow_unsupported = 0;
3157     int fchmodat_unsupported = 0;
3158 #endif
3159 
3160 #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
3161     if (follow_symlinks_specified("chmod", follow_symlinks))
3162         return NULL;
3163 #endif
3164 
3165     if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3166                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3167         return NULL;
3168     }
3169 
3170 #ifdef MS_WINDOWS
3171     Py_BEGIN_ALLOW_THREADS
3172     attr = GetFileAttributesW(path->wide);
3173     if (attr == INVALID_FILE_ATTRIBUTES)
3174         result = 0;
3175     else {
3176         if (mode & _S_IWRITE)
3177             attr &= ~FILE_ATTRIBUTE_READONLY;
3178         else
3179             attr |= FILE_ATTRIBUTE_READONLY;
3180         result = SetFileAttributesW(path->wide, attr);
3181     }
3182     Py_END_ALLOW_THREADS
3183 
3184     if (!result) {
3185         return path_error(path);
3186     }
3187 #else /* MS_WINDOWS */
3188     Py_BEGIN_ALLOW_THREADS
3189 #ifdef HAVE_FCHMOD
3190     if (path->fd != -1)
3191         result = fchmod(path->fd, mode);
3192     else
3193 #endif /* HAVE_CHMOD */
3194 #ifdef HAVE_LCHMOD
3195     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3196         result = lchmod(path->narrow, mode);
3197     else
3198 #endif /* HAVE_LCHMOD */
3199 #ifdef HAVE_FCHMODAT
3200     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3201         if (HAVE_FCHMODAT_RUNTIME) {
3202             /*
3203              * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3204              * The documentation specifically shows how to use it,
3205              * and then says it isn't implemented yet.
3206              * (true on linux with glibc 2.15, and openindiana 3.x)
3207              *
3208              * Once it is supported, os.chmod will automatically
3209              * support dir_fd and follow_symlinks=False.  (Hopefully.)
3210              * Until then, we need to be careful what exception we raise.
3211              */
3212             result = fchmodat(dir_fd, path->narrow, mode,
3213                               follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3214             /*
3215              * But wait!  We can't throw the exception without allowing threads,
3216              * and we can't do that in this nested scope.  (Macro trickery, sigh.)
3217              */
3218             fchmodat_nofollow_unsupported =
3219                              result &&
3220                              ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3221                              !follow_symlinks;
3222         } else {
3223             fchmodat_unsupported = 1;
3224             fchmodat_nofollow_unsupported = 1;
3225 
3226             result = -1;
3227         }
3228     }
3229     else
3230 #endif /* HAVE_FHCMODAT */
3231         result = chmod(path->narrow, mode);
3232     Py_END_ALLOW_THREADS
3233 
3234     if (result) {
3235 #ifdef HAVE_FCHMODAT
3236         if (fchmodat_unsupported) {
3237             if (dir_fd != DEFAULT_DIR_FD) {
3238                 argument_unavailable_error("chmod", "dir_fd");
3239                 return NULL;
3240             }
3241         }
3242 
3243         if (fchmodat_nofollow_unsupported) {
3244             if (dir_fd != DEFAULT_DIR_FD)
3245                 dir_fd_and_follow_symlinks_invalid("chmod",
3246                                                    dir_fd, follow_symlinks);
3247             else
3248                 follow_symlinks_specified("chmod", follow_symlinks);
3249             return NULL;
3250         }
3251         else
3252 #endif /* HAVE_FCHMODAT */
3253         return path_error(path);
3254     }
3255 #endif /* MS_WINDOWS */
3256 
3257     Py_RETURN_NONE;
3258 }
3259 
3260 
3261 #ifdef HAVE_FCHMOD
3262 /*[clinic input]
3263 os.fchmod
3264 
3265     fd: int
3266     mode: int
3267 
3268 Change the access permissions of the file given by file descriptor fd.
3269 
3270 Equivalent to os.chmod(fd, mode).
3271 [clinic start generated code]*/
3272 
3273 static PyObject *
os_fchmod_impl(PyObject * module,int fd,int mode)3274 os_fchmod_impl(PyObject *module, int fd, int mode)
3275 /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
3276 {
3277     int res;
3278     int async_err = 0;
3279 
3280     if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3281         return NULL;
3282     }
3283 
3284     do {
3285         Py_BEGIN_ALLOW_THREADS
3286         res = fchmod(fd, mode);
3287         Py_END_ALLOW_THREADS
3288     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3289     if (res != 0)
3290         return (!async_err) ? posix_error() : NULL;
3291 
3292     Py_RETURN_NONE;
3293 }
3294 #endif /* HAVE_FCHMOD */
3295 
3296 
3297 #ifdef HAVE_LCHMOD
3298 /*[clinic input]
3299 os.lchmod
3300 
3301     path: path_t
3302     mode: int
3303 
3304 Change the access permissions of a file, without following symbolic links.
3305 
3306 If path is a symlink, this affects the link itself rather than the target.
3307 Equivalent to chmod(path, mode, follow_symlinks=False)."
3308 [clinic start generated code]*/
3309 
3310 static PyObject *
os_lchmod_impl(PyObject * module,path_t * path,int mode)3311 os_lchmod_impl(PyObject *module, path_t *path, int mode)
3312 /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3313 {
3314     int res;
3315     if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3316         return NULL;
3317     }
3318     Py_BEGIN_ALLOW_THREADS
3319     res = lchmod(path->narrow, mode);
3320     Py_END_ALLOW_THREADS
3321     if (res < 0) {
3322         path_error(path);
3323         return NULL;
3324     }
3325     Py_RETURN_NONE;
3326 }
3327 #endif /* HAVE_LCHMOD */
3328 
3329 
3330 #ifdef HAVE_CHFLAGS
3331 /*[clinic input]
3332 os.chflags
3333 
3334     path: path_t
3335     flags: unsigned_long(bitwise=True)
3336     follow_symlinks: bool=True
3337 
3338 Set file flags.
3339 
3340 If follow_symlinks is False, and the last element of the path is a symbolic
3341   link, chflags will change flags on the symbolic link itself instead of the
3342   file the link points to.
3343 follow_symlinks may not be implemented on your platform.  If it is
3344 unavailable, using it will raise a NotImplementedError.
3345 
3346 [clinic start generated code]*/
3347 
3348 static PyObject *
os_chflags_impl(PyObject * module,path_t * path,unsigned long flags,int follow_symlinks)3349 os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3350                 int follow_symlinks)
3351 /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3352 {
3353     int result;
3354 
3355 #ifndef HAVE_LCHFLAGS
3356     if (follow_symlinks_specified("chflags", follow_symlinks))
3357         return NULL;
3358 #endif
3359 
3360     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3361         return NULL;
3362     }
3363 
3364     Py_BEGIN_ALLOW_THREADS
3365 #ifdef HAVE_LCHFLAGS
3366     if (!follow_symlinks)
3367         result = lchflags(path->narrow, flags);
3368     else
3369 #endif
3370         result = chflags(path->narrow, flags);
3371     Py_END_ALLOW_THREADS
3372 
3373     if (result)
3374         return path_error(path);
3375 
3376     Py_RETURN_NONE;
3377 }
3378 #endif /* HAVE_CHFLAGS */
3379 
3380 
3381 #ifdef HAVE_LCHFLAGS
3382 /*[clinic input]
3383 os.lchflags
3384 
3385     path: path_t
3386     flags: unsigned_long(bitwise=True)
3387 
3388 Set file flags.
3389 
3390 This function will not follow symbolic links.
3391 Equivalent to chflags(path, flags, follow_symlinks=False).
3392 [clinic start generated code]*/
3393 
3394 static PyObject *
os_lchflags_impl(PyObject * module,path_t * path,unsigned long flags)3395 os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3396 /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3397 {
3398     int res;
3399     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3400         return NULL;
3401     }
3402     Py_BEGIN_ALLOW_THREADS
3403     res = lchflags(path->narrow, flags);
3404     Py_END_ALLOW_THREADS
3405     if (res < 0) {
3406         return path_error(path);
3407     }
3408     Py_RETURN_NONE;
3409 }
3410 #endif /* HAVE_LCHFLAGS */
3411 
3412 
3413 #ifdef HAVE_CHROOT
3414 /*[clinic input]
3415 os.chroot
3416     path: path_t
3417 
3418 Change root directory to path.
3419 
3420 [clinic start generated code]*/
3421 
3422 static PyObject *
os_chroot_impl(PyObject * module,path_t * path)3423 os_chroot_impl(PyObject *module, path_t *path)
3424 /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3425 {
3426     int res;
3427     Py_BEGIN_ALLOW_THREADS
3428     res = chroot(path->narrow);
3429     Py_END_ALLOW_THREADS
3430     if (res < 0)
3431         return path_error(path);
3432     Py_RETURN_NONE;
3433 }
3434 #endif /* HAVE_CHROOT */
3435 
3436 
3437 #ifdef HAVE_FSYNC
3438 /*[clinic input]
3439 os.fsync
3440 
3441     fd: fildes
3442 
3443 Force write of fd to disk.
3444 [clinic start generated code]*/
3445 
3446 static PyObject *
os_fsync_impl(PyObject * module,int fd)3447 os_fsync_impl(PyObject *module, int fd)
3448 /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3449 {
3450     return posix_fildes_fd(fd, fsync);
3451 }
3452 #endif /* HAVE_FSYNC */
3453 
3454 
3455 #ifdef HAVE_SYNC
3456 /*[clinic input]
3457 os.sync
3458 
3459 Force write of everything to disk.
3460 [clinic start generated code]*/
3461 
3462 static PyObject *
os_sync_impl(PyObject * module)3463 os_sync_impl(PyObject *module)
3464 /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3465 {
3466     Py_BEGIN_ALLOW_THREADS
3467     sync();
3468     Py_END_ALLOW_THREADS
3469     Py_RETURN_NONE;
3470 }
3471 #endif /* HAVE_SYNC */
3472 
3473 
3474 #ifdef HAVE_FDATASYNC
3475 #ifdef __hpux
3476 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3477 #endif
3478 
3479 /*[clinic input]
3480 os.fdatasync
3481 
3482     fd: fildes
3483 
3484 Force write of fd to disk without forcing update of metadata.
3485 [clinic start generated code]*/
3486 
3487 static PyObject *
os_fdatasync_impl(PyObject * module,int fd)3488 os_fdatasync_impl(PyObject *module, int fd)
3489 /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3490 {
3491     return posix_fildes_fd(fd, fdatasync);
3492 }
3493 #endif /* HAVE_FDATASYNC */
3494 
3495 
3496 #ifdef HAVE_CHOWN
3497 /*[clinic input]
3498 os.chown
3499 
3500     path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3501         Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3502 
3503     uid: uid_t
3504 
3505     gid: gid_t
3506 
3507     *
3508 
3509     dir_fd : dir_fd(requires='fchownat') = None
3510         If not None, it should be a file descriptor open to a directory,
3511         and path should be relative; path will then be relative to that
3512         directory.
3513 
3514     follow_symlinks: bool = True
3515         If False, and the last element of the path is a symbolic link,
3516         stat will examine the symbolic link itself instead of the file
3517         the link points to.
3518 
3519 Change the owner and group id of path to the numeric uid and gid.\
3520 
3521 path may always be specified as a string.
3522 On some platforms, path may also be specified as an open file descriptor.
3523   If this functionality is unavailable, using it raises an exception.
3524 If dir_fd is not None, it should be a file descriptor open to a directory,
3525   and path should be relative; path will then be relative to that directory.
3526 If follow_symlinks is False, and the last element of the path is a symbolic
3527   link, chown will modify the symbolic link itself instead of the file the
3528   link points to.
3529 It is an error to use dir_fd or follow_symlinks when specifying path as
3530   an open file descriptor.
3531 dir_fd and follow_symlinks may not be implemented on your platform.
3532   If they are unavailable, using them will raise a NotImplementedError.
3533 
3534 [clinic start generated code]*/
3535 
3536 static PyObject *
os_chown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid,int dir_fd,int follow_symlinks)3537 os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3538               int dir_fd, int follow_symlinks)
3539 /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3540 {
3541     int result;
3542 
3543 #if defined(HAVE_FCHOWNAT)
3544     int fchownat_unsupported = 0;
3545 #endif
3546 
3547 #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3548     if (follow_symlinks_specified("chown", follow_symlinks))
3549         return NULL;
3550 #endif
3551     if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3552         fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3553         return NULL;
3554 
3555     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3556                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3557         return NULL;
3558     }
3559 
3560     Py_BEGIN_ALLOW_THREADS
3561 #ifdef HAVE_FCHOWN
3562     if (path->fd != -1)
3563         result = fchown(path->fd, uid, gid);
3564     else
3565 #endif
3566 #ifdef HAVE_LCHOWN
3567     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3568         result = lchown(path->narrow, uid, gid);
3569     else
3570 #endif
3571 #ifdef HAVE_FCHOWNAT
3572     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
3573       if (HAVE_FCHOWNAT_RUNTIME) {
3574         result = fchownat(dir_fd, path->narrow, uid, gid,
3575                           follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3576       } else {
3577          fchownat_unsupported = 1;
3578       }
3579     } else
3580 #endif
3581         result = chown(path->narrow, uid, gid);
3582     Py_END_ALLOW_THREADS
3583 
3584 #ifdef HAVE_FCHOWNAT
3585     if (fchownat_unsupported) {
3586         /* This would be incorrect if the current platform
3587          * doesn't support lchown.
3588          */
3589         argument_unavailable_error(NULL, "dir_fd");
3590         return NULL;
3591     }
3592 #endif
3593 
3594     if (result)
3595         return path_error(path);
3596 
3597     Py_RETURN_NONE;
3598 }
3599 #endif /* HAVE_CHOWN */
3600 
3601 
3602 #ifdef HAVE_FCHOWN
3603 /*[clinic input]
3604 os.fchown
3605 
3606     fd: int
3607     uid: uid_t
3608     gid: gid_t
3609 
3610 Change the owner and group id of the file specified by file descriptor.
3611 
3612 Equivalent to os.chown(fd, uid, gid).
3613 
3614 [clinic start generated code]*/
3615 
3616 static PyObject *
os_fchown_impl(PyObject * module,int fd,uid_t uid,gid_t gid)3617 os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3618 /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3619 {
3620     int res;
3621     int async_err = 0;
3622 
3623     if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
3624         return NULL;
3625     }
3626 
3627     do {
3628         Py_BEGIN_ALLOW_THREADS
3629         res = fchown(fd, uid, gid);
3630         Py_END_ALLOW_THREADS
3631     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3632     if (res != 0)
3633         return (!async_err) ? posix_error() : NULL;
3634 
3635     Py_RETURN_NONE;
3636 }
3637 #endif /* HAVE_FCHOWN */
3638 
3639 
3640 #ifdef HAVE_LCHOWN
3641 /*[clinic input]
3642 os.lchown
3643 
3644     path : path_t
3645     uid: uid_t
3646     gid: gid_t
3647 
3648 Change the owner and group id of path to the numeric uid and gid.
3649 
3650 This function will not follow symbolic links.
3651 Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3652 [clinic start generated code]*/
3653 
3654 static PyObject *
os_lchown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid)3655 os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3656 /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3657 {
3658     int res;
3659     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
3660         return NULL;
3661     }
3662     Py_BEGIN_ALLOW_THREADS
3663     res = lchown(path->narrow, uid, gid);
3664     Py_END_ALLOW_THREADS
3665     if (res < 0) {
3666         return path_error(path);
3667     }
3668     Py_RETURN_NONE;
3669 }
3670 #endif /* HAVE_LCHOWN */
3671 
3672 
3673 static PyObject *
posix_getcwd(int use_bytes)3674 posix_getcwd(int use_bytes)
3675 {
3676 #ifdef MS_WINDOWS
3677     wchar_t wbuf[MAXPATHLEN];
3678     wchar_t *wbuf2 = wbuf;
3679     DWORD len;
3680 
3681     Py_BEGIN_ALLOW_THREADS
3682     len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3683     /* If the buffer is large enough, len does not include the
3684        terminating \0. If the buffer is too small, len includes
3685        the space needed for the terminator. */
3686     if (len >= Py_ARRAY_LENGTH(wbuf)) {
3687         if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3688             wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3689         }
3690         else {
3691             wbuf2 = NULL;
3692         }
3693         if (wbuf2) {
3694             len = GetCurrentDirectoryW(len, wbuf2);
3695         }
3696     }
3697     Py_END_ALLOW_THREADS
3698 
3699     if (!wbuf2) {
3700         PyErr_NoMemory();
3701         return NULL;
3702     }
3703     if (!len) {
3704         if (wbuf2 != wbuf)
3705             PyMem_RawFree(wbuf2);
3706         return PyErr_SetFromWindowsErr(0);
3707     }
3708 
3709     PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3710     if (wbuf2 != wbuf) {
3711         PyMem_RawFree(wbuf2);
3712     }
3713 
3714     if (use_bytes) {
3715         if (resobj == NULL) {
3716             return NULL;
3717         }
3718         Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3719     }
3720 
3721     return resobj;
3722 #else
3723     const size_t chunk = 1024;
3724 
3725     char *buf = NULL;
3726     char *cwd = NULL;
3727     size_t buflen = 0;
3728 
3729     Py_BEGIN_ALLOW_THREADS
3730     do {
3731         char *newbuf;
3732         if (buflen <= PY_SSIZE_T_MAX - chunk) {
3733             buflen += chunk;
3734             newbuf = PyMem_RawRealloc(buf, buflen);
3735         }
3736         else {
3737             newbuf = NULL;
3738         }
3739         if (newbuf == NULL) {
3740             PyMem_RawFree(buf);
3741             buf = NULL;
3742             break;
3743         }
3744         buf = newbuf;
3745 
3746         cwd = getcwd(buf, buflen);
3747     } while (cwd == NULL && errno == ERANGE);
3748     Py_END_ALLOW_THREADS
3749 
3750     if (buf == NULL) {
3751         return PyErr_NoMemory();
3752     }
3753     if (cwd == NULL) {
3754         PyMem_RawFree(buf);
3755         return posix_error();
3756     }
3757 
3758     PyObject *obj;
3759     if (use_bytes) {
3760         obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3761     }
3762     else {
3763         obj = PyUnicode_DecodeFSDefault(buf);
3764     }
3765     PyMem_RawFree(buf);
3766 
3767     return obj;
3768 #endif   /* !MS_WINDOWS */
3769 }
3770 
3771 
3772 /*[clinic input]
3773 os.getcwd
3774 
3775 Return a unicode string representing the current working directory.
3776 [clinic start generated code]*/
3777 
3778 static PyObject *
os_getcwd_impl(PyObject * module)3779 os_getcwd_impl(PyObject *module)
3780 /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3781 {
3782     return posix_getcwd(0);
3783 }
3784 
3785 
3786 /*[clinic input]
3787 os.getcwdb
3788 
3789 Return a bytes string representing the current working directory.
3790 [clinic start generated code]*/
3791 
3792 static PyObject *
os_getcwdb_impl(PyObject * module)3793 os_getcwdb_impl(PyObject *module)
3794 /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3795 {
3796     return posix_getcwd(1);
3797 }
3798 
3799 
3800 #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3801 #define HAVE_LINK 1
3802 #endif
3803 
3804 #ifdef HAVE_LINK
3805 /*[clinic input]
3806 
3807 os.link
3808 
3809     src : path_t
3810     dst : path_t
3811     *
3812     src_dir_fd : dir_fd = None
3813     dst_dir_fd : dir_fd = None
3814     follow_symlinks: bool = True
3815 
3816 Create a hard link to a file.
3817 
3818 If either src_dir_fd or dst_dir_fd is not None, it should be a file
3819   descriptor open to a directory, and the respective path string (src or dst)
3820   should be relative; the path will then be relative to that directory.
3821 If follow_symlinks is False, and the last element of src is a symbolic
3822   link, link will create a link to the symbolic link itself instead of the
3823   file the link points to.
3824 src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3825   platform.  If they are unavailable, using them will raise a
3826   NotImplementedError.
3827 [clinic start generated code]*/
3828 
3829 static PyObject *
os_link_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int follow_symlinks)3830 os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3831              int dst_dir_fd, int follow_symlinks)
3832 /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3833 {
3834 #ifdef MS_WINDOWS
3835     BOOL result = FALSE;
3836 #else
3837     int result;
3838 #endif
3839 #if defined(HAVE_LINKAT)
3840     int linkat_unavailable = 0;
3841 #endif
3842 
3843 #ifndef HAVE_LINKAT
3844     if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3845         argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3846         return NULL;
3847     }
3848 #endif
3849 
3850 #ifndef MS_WINDOWS
3851     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3852         PyErr_SetString(PyExc_NotImplementedError,
3853                         "link: src and dst must be the same type");
3854         return NULL;
3855     }
3856 #endif
3857 
3858     if (PySys_Audit("os.link", "OOii", src->object, dst->object,
3859                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
3860                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
3861         return NULL;
3862     }
3863 
3864 #ifdef MS_WINDOWS
3865     Py_BEGIN_ALLOW_THREADS
3866     result = CreateHardLinkW(dst->wide, src->wide, NULL);
3867     Py_END_ALLOW_THREADS
3868 
3869     if (!result)
3870         return path_error2(src, dst);
3871 #else
3872     Py_BEGIN_ALLOW_THREADS
3873 #ifdef HAVE_LINKAT
3874     if ((src_dir_fd != DEFAULT_DIR_FD) ||
3875         (dst_dir_fd != DEFAULT_DIR_FD) ||
3876         (!follow_symlinks)) {
3877 
3878         if (HAVE_LINKAT_RUNTIME) {
3879 
3880             result = linkat(src_dir_fd, src->narrow,
3881                 dst_dir_fd, dst->narrow,
3882                 follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3883 
3884         }
3885 #ifdef __APPLE__
3886         else {
3887             if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
3888                 /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
3889                 result = link(src->narrow, dst->narrow);
3890             } else {
3891                 linkat_unavailable = 1;
3892             }
3893         }
3894 #endif
3895     }
3896     else
3897 #endif /* HAVE_LINKAT */
3898         result = link(src->narrow, dst->narrow);
3899     Py_END_ALLOW_THREADS
3900 
3901 #ifdef HAVE_LINKAT
3902     if (linkat_unavailable) {
3903         /* Either or both dir_fd arguments were specified */
3904         if (src_dir_fd  != DEFAULT_DIR_FD) {
3905             argument_unavailable_error("link", "src_dir_fd");
3906         } else {
3907             argument_unavailable_error("link", "dst_dir_fd");
3908         }
3909         return NULL;
3910     }
3911 #endif
3912 
3913     if (result)
3914         return path_error2(src, dst);
3915 #endif /* MS_WINDOWS */
3916 
3917     Py_RETURN_NONE;
3918 }
3919 #endif
3920 
3921 
3922 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3923 static PyObject *
_listdir_windows_no_opendir(path_t * path,PyObject * list)3924 _listdir_windows_no_opendir(path_t *path, PyObject *list)
3925 {
3926     PyObject *v;
3927     HANDLE hFindFile = INVALID_HANDLE_VALUE;
3928     BOOL result;
3929     wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
3930     /* only claim to have space for MAX_PATH */
3931     Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
3932     wchar_t *wnamebuf = NULL;
3933 
3934     WIN32_FIND_DATAW wFileData;
3935     const wchar_t *po_wchars;
3936 
3937     if (!path->wide) { /* Default arg: "." */
3938         po_wchars = L".";
3939         len = 1;
3940     } else {
3941         po_wchars = path->wide;
3942         len = wcslen(path->wide);
3943     }
3944     /* The +5 is so we can append "\\*.*\0" */
3945     wnamebuf = PyMem_New(wchar_t, len + 5);
3946     if (!wnamebuf) {
3947         PyErr_NoMemory();
3948         goto exit;
3949     }
3950     wcscpy(wnamebuf, po_wchars);
3951     if (len > 0) {
3952         wchar_t wch = wnamebuf[len-1];
3953         if (wch != SEP && wch != ALTSEP && wch != L':')
3954             wnamebuf[len++] = SEP;
3955         wcscpy(wnamebuf + len, L"*.*");
3956     }
3957     if ((list = PyList_New(0)) == NULL) {
3958         goto exit;
3959     }
3960     Py_BEGIN_ALLOW_THREADS
3961     hFindFile = FindFirstFileW(wnamebuf, &wFileData);
3962     Py_END_ALLOW_THREADS
3963     if (hFindFile == INVALID_HANDLE_VALUE) {
3964         int error = GetLastError();
3965         if (error == ERROR_FILE_NOT_FOUND)
3966             goto exit;
3967         Py_DECREF(list);
3968         list = path_error(path);
3969         goto exit;
3970     }
3971     do {
3972         /* Skip over . and .. */
3973         if (wcscmp(wFileData.cFileName, L".") != 0 &&
3974             wcscmp(wFileData.cFileName, L"..") != 0) {
3975             v = PyUnicode_FromWideChar(wFileData.cFileName,
3976                                        wcslen(wFileData.cFileName));
3977             if (path->narrow && v) {
3978                 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
3979             }
3980             if (v == NULL) {
3981                 Py_DECREF(list);
3982                 list = NULL;
3983                 break;
3984             }
3985             if (PyList_Append(list, v) != 0) {
3986                 Py_DECREF(v);
3987                 Py_DECREF(list);
3988                 list = NULL;
3989                 break;
3990             }
3991             Py_DECREF(v);
3992         }
3993         Py_BEGIN_ALLOW_THREADS
3994         result = FindNextFileW(hFindFile, &wFileData);
3995         Py_END_ALLOW_THREADS
3996         /* FindNextFile sets error to ERROR_NO_MORE_FILES if
3997            it got to the end of the directory. */
3998         if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
3999             Py_DECREF(list);
4000             list = path_error(path);
4001             goto exit;
4002         }
4003     } while (result == TRUE);
4004 
4005 exit:
4006     if (hFindFile != INVALID_HANDLE_VALUE) {
4007         if (FindClose(hFindFile) == FALSE) {
4008             if (list != NULL) {
4009                 Py_DECREF(list);
4010                 list = path_error(path);
4011             }
4012         }
4013     }
4014     PyMem_Free(wnamebuf);
4015 
4016     return list;
4017 }  /* end of _listdir_windows_no_opendir */
4018 
4019 #else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4020 
4021 static PyObject *
_posix_listdir(path_t * path,PyObject * list)4022 _posix_listdir(path_t *path, PyObject *list)
4023 {
4024     PyObject *v;
4025     DIR *dirp = NULL;
4026     struct dirent *ep;
4027     int return_str; /* if false, return bytes */
4028 #ifdef HAVE_FDOPENDIR
4029     int fd = -1;
4030 #endif
4031 
4032     errno = 0;
4033 #ifdef HAVE_FDOPENDIR
4034     if (path->fd != -1) {
4035       if (HAVE_FDOPENDIR_RUNTIME) {
4036         /* closedir() closes the FD, so we duplicate it */
4037         fd = _Py_dup(path->fd);
4038         if (fd == -1)
4039             return NULL;
4040 
4041         return_str = 1;
4042 
4043         Py_BEGIN_ALLOW_THREADS
4044         dirp = fdopendir(fd);
4045         Py_END_ALLOW_THREADS
4046       } else {
4047         PyErr_SetString(PyExc_TypeError,
4048             "listdir: path should be string, bytes, os.PathLike or None, not int");
4049         return NULL;
4050       }
4051     }
4052     else
4053 #endif
4054     {
4055         const char *name;
4056         if (path->narrow) {
4057             name = path->narrow;
4058             /* only return bytes if they specified a bytes-like object */
4059             return_str = !PyObject_CheckBuffer(path->object);
4060         }
4061         else {
4062             name = ".";
4063             return_str = 1;
4064         }
4065 
4066         Py_BEGIN_ALLOW_THREADS
4067         dirp = opendir(name);
4068         Py_END_ALLOW_THREADS
4069     }
4070 
4071     if (dirp == NULL) {
4072         list = path_error(path);
4073 #ifdef HAVE_FDOPENDIR
4074         if (fd != -1) {
4075             Py_BEGIN_ALLOW_THREADS
4076             close(fd);
4077             Py_END_ALLOW_THREADS
4078         }
4079 #endif
4080         goto exit;
4081     }
4082     if ((list = PyList_New(0)) == NULL) {
4083         goto exit;
4084     }
4085     for (;;) {
4086         errno = 0;
4087         Py_BEGIN_ALLOW_THREADS
4088         ep = readdir(dirp);
4089         Py_END_ALLOW_THREADS
4090         if (ep == NULL) {
4091             if (errno == 0) {
4092                 break;
4093             } else {
4094                 Py_DECREF(list);
4095                 list = path_error(path);
4096                 goto exit;
4097             }
4098         }
4099         if (ep->d_name[0] == '.' &&
4100             (NAMLEN(ep) == 1 ||
4101              (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4102             continue;
4103         if (return_str)
4104             v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4105         else
4106             v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4107         if (v == NULL) {
4108             Py_CLEAR(list);
4109             break;
4110         }
4111         if (PyList_Append(list, v) != 0) {
4112             Py_DECREF(v);
4113             Py_CLEAR(list);
4114             break;
4115         }
4116         Py_DECREF(v);
4117     }
4118 
4119 exit:
4120     if (dirp != NULL) {
4121         Py_BEGIN_ALLOW_THREADS
4122 #ifdef HAVE_FDOPENDIR
4123         if (fd > -1)
4124             rewinddir(dirp);
4125 #endif
4126         closedir(dirp);
4127         Py_END_ALLOW_THREADS
4128     }
4129 
4130     return list;
4131 }  /* end of _posix_listdir */
4132 #endif  /* which OS */
4133 
4134 
4135 /*[clinic input]
4136 os.listdir
4137 
4138     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4139 
4140 Return a list containing the names of the files in the directory.
4141 
4142 path can be specified as either str, bytes, or a path-like object.  If path is bytes,
4143   the filenames returned will also be bytes; in all other circumstances
4144   the filenames returned will be str.
4145 If path is None, uses the path='.'.
4146 On some platforms, path may also be specified as an open file descriptor;\
4147   the file descriptor must refer to a directory.
4148   If this functionality is unavailable, using it raises NotImplementedError.
4149 
4150 The list is in arbitrary order.  It does not include the special
4151 entries '.' and '..' even if they are present in the directory.
4152 
4153 
4154 [clinic start generated code]*/
4155 
4156 static PyObject *
os_listdir_impl(PyObject * module,path_t * path)4157 os_listdir_impl(PyObject *module, path_t *path)
4158 /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4159 {
4160     if (PySys_Audit("os.listdir", "O",
4161                     path->object ? path->object : Py_None) < 0) {
4162         return NULL;
4163     }
4164 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4165     return _listdir_windows_no_opendir(path, NULL);
4166 #else
4167     return _posix_listdir(path, NULL);
4168 #endif
4169 }
4170 
4171 #ifdef MS_WINDOWS
4172 /* A helper function for abspath on win32 */
4173 /*[clinic input]
4174 os._getfullpathname
4175 
4176     path: path_t
4177     /
4178 
4179 [clinic start generated code]*/
4180 
4181 static PyObject *
os__getfullpathname_impl(PyObject * module,path_t * path)4182 os__getfullpathname_impl(PyObject *module, path_t *path)
4183 /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
4184 {
4185     wchar_t *abspath;
4186 
4187     /* _Py_abspath() is implemented with GetFullPathNameW() on Windows */
4188     if (_Py_abspath(path->wide, &abspath) < 0) {
4189         return win32_error_object("GetFullPathNameW", path->object);
4190     }
4191     if (abspath == NULL) {
4192         return PyErr_NoMemory();
4193     }
4194 
4195     PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
4196     PyMem_RawFree(abspath);
4197     if (str == NULL) {
4198         return NULL;
4199     }
4200     if (path->narrow) {
4201         Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
4202     }
4203     return str;
4204 }
4205 
4206 
4207 /*[clinic input]
4208 os._getfinalpathname
4209 
4210     path: path_t
4211     /
4212 
4213 A helper function for samepath on windows.
4214 [clinic start generated code]*/
4215 
4216 static PyObject *
os__getfinalpathname_impl(PyObject * module,path_t * path)4217 os__getfinalpathname_impl(PyObject *module, path_t *path)
4218 /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
4219 {
4220     HANDLE hFile;
4221     wchar_t buf[MAXPATHLEN], *target_path = buf;
4222     int buf_size = Py_ARRAY_LENGTH(buf);
4223     int result_length;
4224     PyObject *result;
4225 
4226     Py_BEGIN_ALLOW_THREADS
4227     hFile = CreateFileW(
4228         path->wide,
4229         0, /* desired access */
4230         0, /* share mode */
4231         NULL, /* security attributes */
4232         OPEN_EXISTING,
4233         /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
4234         FILE_FLAG_BACKUP_SEMANTICS,
4235         NULL);
4236     Py_END_ALLOW_THREADS
4237 
4238     if (hFile == INVALID_HANDLE_VALUE) {
4239         return win32_error_object("CreateFileW", path->object);
4240     }
4241 
4242     /* We have a good handle to the target, use it to determine the
4243        target path name. */
4244     while (1) {
4245         Py_BEGIN_ALLOW_THREADS
4246         result_length = GetFinalPathNameByHandleW(hFile, target_path,
4247                                                   buf_size, VOLUME_NAME_DOS);
4248         Py_END_ALLOW_THREADS
4249 
4250         if (!result_length) {
4251             result = win32_error_object("GetFinalPathNameByHandleW",
4252                                          path->object);
4253             goto cleanup;
4254         }
4255 
4256         if (result_length < buf_size) {
4257             break;
4258         }
4259 
4260         wchar_t *tmp;
4261         tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
4262                             result_length * sizeof(*tmp));
4263         if (!tmp) {
4264             result = PyErr_NoMemory();
4265             goto cleanup;
4266         }
4267 
4268         buf_size = result_length;
4269         target_path = tmp;
4270     }
4271 
4272     result = PyUnicode_FromWideChar(target_path, result_length);
4273     if (result && path->narrow) {
4274         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4275     }
4276 
4277 cleanup:
4278     if (target_path != buf) {
4279         PyMem_Free(target_path);
4280     }
4281     CloseHandle(hFile);
4282     return result;
4283 }
4284 
4285 
4286 /*[clinic input]
4287 os._getvolumepathname
4288 
4289     path: path_t
4290 
4291 A helper function for ismount on Win32.
4292 [clinic start generated code]*/
4293 
4294 static PyObject *
os__getvolumepathname_impl(PyObject * module,path_t * path)4295 os__getvolumepathname_impl(PyObject *module, path_t *path)
4296 /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
4297 {
4298     PyObject *result;
4299     wchar_t *mountpath=NULL;
4300     size_t buflen;
4301     BOOL ret;
4302 
4303     /* Volume path should be shorter than entire path */
4304     buflen = Py_MAX(path->length, MAX_PATH);
4305 
4306     if (buflen > PY_DWORD_MAX) {
4307         PyErr_SetString(PyExc_OverflowError, "path too long");
4308         return NULL;
4309     }
4310 
4311     mountpath = PyMem_New(wchar_t, buflen);
4312     if (mountpath == NULL)
4313         return PyErr_NoMemory();
4314 
4315     Py_BEGIN_ALLOW_THREADS
4316     ret = GetVolumePathNameW(path->wide, mountpath,
4317                              Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
4318     Py_END_ALLOW_THREADS
4319 
4320     if (!ret) {
4321         result = win32_error_object("_getvolumepathname", path->object);
4322         goto exit;
4323     }
4324     result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
4325     if (path->narrow)
4326         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4327 
4328 exit:
4329     PyMem_Free(mountpath);
4330     return result;
4331 }
4332 
4333 #endif /* MS_WINDOWS */
4334 
4335 
4336 /*[clinic input]
4337 os.mkdir
4338 
4339     path : path_t
4340 
4341     mode: int = 0o777
4342 
4343     *
4344 
4345     dir_fd : dir_fd(requires='mkdirat') = None
4346 
4347 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4348 
4349 Create a directory.
4350 
4351 If dir_fd is not None, it should be a file descriptor open to a directory,
4352   and path should be relative; path will then be relative to that directory.
4353 dir_fd may not be implemented on your platform.
4354   If it is unavailable, using it will raise a NotImplementedError.
4355 
4356 The mode argument is ignored on Windows.
4357 [clinic start generated code]*/
4358 
4359 static PyObject *
os_mkdir_impl(PyObject * module,path_t * path,int mode,int dir_fd)4360 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4361 /*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/
4362 {
4363     int result;
4364 #ifdef HAVE_MKDIRAT
4365     int mkdirat_unavailable = 0;
4366 #endif
4367 
4368     if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4369                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4370         return NULL;
4371     }
4372 
4373 #ifdef MS_WINDOWS
4374     Py_BEGIN_ALLOW_THREADS
4375     result = CreateDirectoryW(path->wide, NULL);
4376     Py_END_ALLOW_THREADS
4377 
4378     if (!result)
4379         return path_error(path);
4380 #else
4381     Py_BEGIN_ALLOW_THREADS
4382 #if HAVE_MKDIRAT
4383     if (dir_fd != DEFAULT_DIR_FD) {
4384       if (HAVE_MKDIRAT_RUNTIME) {
4385         result = mkdirat(dir_fd, path->narrow, mode);
4386 
4387       } else {
4388         mkdirat_unavailable = 1;
4389       }
4390     } else
4391 #endif
4392 #if defined(__WATCOMC__) && !defined(__QNX__)
4393         result = mkdir(path->narrow);
4394 #else
4395         result = mkdir(path->narrow, mode);
4396 #endif
4397     Py_END_ALLOW_THREADS
4398 
4399 #if HAVE_MKDIRAT
4400     if (mkdirat_unavailable) {
4401         argument_unavailable_error(NULL, "dir_fd");
4402         return NULL;
4403     }
4404 #endif
4405 
4406     if (result < 0)
4407         return path_error(path);
4408 #endif /* MS_WINDOWS */
4409     Py_RETURN_NONE;
4410 }
4411 
4412 
4413 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4414 #if defined(HAVE_SYS_RESOURCE_H)
4415 #include <sys/resource.h>
4416 #endif
4417 
4418 
4419 #ifdef HAVE_NICE
4420 /*[clinic input]
4421 os.nice
4422 
4423     increment: int
4424     /
4425 
4426 Add increment to the priority of process and return the new priority.
4427 [clinic start generated code]*/
4428 
4429 static PyObject *
os_nice_impl(PyObject * module,int increment)4430 os_nice_impl(PyObject *module, int increment)
4431 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4432 {
4433     int value;
4434 
4435     /* There are two flavours of 'nice': one that returns the new
4436        priority (as required by almost all standards out there) and the
4437        Linux/FreeBSD one, which returns '0' on success and advices
4438        the use of getpriority() to get the new priority.
4439 
4440        If we are of the nice family that returns the new priority, we
4441        need to clear errno before the call, and check if errno is filled
4442        before calling posix_error() on a returnvalue of -1, because the
4443        -1 may be the actual new priority! */
4444 
4445     errno = 0;
4446     value = nice(increment);
4447 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4448     if (value == 0)
4449         value = getpriority(PRIO_PROCESS, 0);
4450 #endif
4451     if (value == -1 && errno != 0)
4452         /* either nice() or getpriority() returned an error */
4453         return posix_error();
4454     return PyLong_FromLong((long) value);
4455 }
4456 #endif /* HAVE_NICE */
4457 
4458 
4459 #ifdef HAVE_GETPRIORITY
4460 /*[clinic input]
4461 os.getpriority
4462 
4463     which: int
4464     who: int
4465 
4466 Return program scheduling priority.
4467 [clinic start generated code]*/
4468 
4469 static PyObject *
os_getpriority_impl(PyObject * module,int which,int who)4470 os_getpriority_impl(PyObject *module, int which, int who)
4471 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4472 {
4473     int retval;
4474 
4475     errno = 0;
4476     retval = getpriority(which, who);
4477     if (errno != 0)
4478         return posix_error();
4479     return PyLong_FromLong((long)retval);
4480 }
4481 #endif /* HAVE_GETPRIORITY */
4482 
4483 
4484 #ifdef HAVE_SETPRIORITY
4485 /*[clinic input]
4486 os.setpriority
4487 
4488     which: int
4489     who: int
4490     priority: int
4491 
4492 Set program scheduling priority.
4493 [clinic start generated code]*/
4494 
4495 static PyObject *
os_setpriority_impl(PyObject * module,int which,int who,int priority)4496 os_setpriority_impl(PyObject *module, int which, int who, int priority)
4497 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4498 {
4499     int retval;
4500 
4501     retval = setpriority(which, who, priority);
4502     if (retval == -1)
4503         return posix_error();
4504     Py_RETURN_NONE;
4505 }
4506 #endif /* HAVE_SETPRIORITY */
4507 
4508 
4509 static PyObject *
internal_rename(path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int is_replace)4510 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4511 {
4512     const char *function_name = is_replace ? "replace" : "rename";
4513     int dir_fd_specified;
4514 
4515 #ifdef HAVE_RENAMEAT
4516     int renameat_unavailable = 0;
4517 #endif
4518 
4519 #ifdef MS_WINDOWS
4520     BOOL result;
4521     int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4522 #else
4523     int result;
4524 #endif
4525 
4526     dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4527                        (dst_dir_fd != DEFAULT_DIR_FD);
4528 #ifndef HAVE_RENAMEAT
4529     if (dir_fd_specified) {
4530         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4531         return NULL;
4532     }
4533 #endif
4534 
4535     if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
4536                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4537                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4538         return NULL;
4539     }
4540 
4541 #ifdef MS_WINDOWS
4542     Py_BEGIN_ALLOW_THREADS
4543     result = MoveFileExW(src->wide, dst->wide, flags);
4544     Py_END_ALLOW_THREADS
4545 
4546     if (!result)
4547         return path_error2(src, dst);
4548 
4549 #else
4550     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4551         PyErr_Format(PyExc_ValueError,
4552                      "%s: src and dst must be the same type", function_name);
4553         return NULL;
4554     }
4555 
4556     Py_BEGIN_ALLOW_THREADS
4557 #ifdef HAVE_RENAMEAT
4558     if (dir_fd_specified) {
4559         if (HAVE_RENAMEAT_RUNTIME) {
4560             result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4561         } else {
4562             renameat_unavailable = 1;
4563         }
4564     } else
4565 #endif
4566     result = rename(src->narrow, dst->narrow);
4567     Py_END_ALLOW_THREADS
4568 
4569 
4570 #ifdef HAVE_RENAMEAT
4571     if (renameat_unavailable) {
4572         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4573         return NULL;
4574     }
4575 #endif
4576 
4577     if (result)
4578         return path_error2(src, dst);
4579 #endif
4580     Py_RETURN_NONE;
4581 }
4582 
4583 
4584 /*[clinic input]
4585 os.rename
4586 
4587     src : path_t
4588     dst : path_t
4589     *
4590     src_dir_fd : dir_fd = None
4591     dst_dir_fd : dir_fd = None
4592 
4593 Rename a file or directory.
4594 
4595 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4596   descriptor open to a directory, and the respective path string (src or dst)
4597   should be relative; the path will then be relative to that directory.
4598 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4599   If they are unavailable, using them will raise a NotImplementedError.
4600 [clinic start generated code]*/
4601 
4602 static PyObject *
os_rename_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4603 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4604                int dst_dir_fd)
4605 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4606 {
4607     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4608 }
4609 
4610 
4611 /*[clinic input]
4612 os.replace = os.rename
4613 
4614 Rename a file or directory, overwriting the destination.
4615 
4616 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4617   descriptor open to a directory, and the respective path string (src or dst)
4618   should be relative; the path will then be relative to that directory.
4619 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4620   If they are unavailable, using them will raise a NotImplementedError.
4621 [clinic start generated code]*/
4622 
4623 static PyObject *
os_replace_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4624 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4625                 int dst_dir_fd)
4626 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4627 {
4628     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4629 }
4630 
4631 
4632 /*[clinic input]
4633 os.rmdir
4634 
4635     path: path_t
4636     *
4637     dir_fd: dir_fd(requires='unlinkat') = None
4638 
4639 Remove a directory.
4640 
4641 If dir_fd is not None, it should be a file descriptor open to a directory,
4642   and path should be relative; path will then be relative to that directory.
4643 dir_fd may not be implemented on your platform.
4644   If it is unavailable, using it will raise a NotImplementedError.
4645 [clinic start generated code]*/
4646 
4647 static PyObject *
os_rmdir_impl(PyObject * module,path_t * path,int dir_fd)4648 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4649 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4650 {
4651     int result;
4652 #ifdef HAVE_UNLINKAT
4653     int unlinkat_unavailable = 0;
4654 #endif
4655 
4656     if (PySys_Audit("os.rmdir", "Oi", path->object,
4657                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4658         return NULL;
4659     }
4660 
4661     Py_BEGIN_ALLOW_THREADS
4662 #ifdef MS_WINDOWS
4663     /* Windows, success=1, UNIX, success=0 */
4664     result = !RemoveDirectoryW(path->wide);
4665 #else
4666 #ifdef HAVE_UNLINKAT
4667     if (dir_fd != DEFAULT_DIR_FD) {
4668       if (HAVE_UNLINKAT_RUNTIME) {
4669         result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4670       } else {
4671         unlinkat_unavailable = 1;
4672         result = -1;
4673       }
4674     } else
4675 #endif
4676         result = rmdir(path->narrow);
4677 #endif
4678     Py_END_ALLOW_THREADS
4679 
4680 #ifdef HAVE_UNLINKAT
4681     if (unlinkat_unavailable) {
4682         argument_unavailable_error("rmdir", "dir_fd");
4683         return NULL;
4684     }
4685 #endif
4686 
4687     if (result)
4688         return path_error(path);
4689 
4690     Py_RETURN_NONE;
4691 }
4692 
4693 
4694 #ifdef HAVE_SYSTEM
4695 #ifdef MS_WINDOWS
4696 /*[clinic input]
4697 os.system -> long
4698 
4699     command: Py_UNICODE
4700 
4701 Execute the command in a subshell.
4702 [clinic start generated code]*/
4703 
4704 static long
os_system_impl(PyObject * module,const Py_UNICODE * command)4705 os_system_impl(PyObject *module, const Py_UNICODE *command)
4706 /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4707 {
4708     long result;
4709 
4710     if (PySys_Audit("os.system", "(u)", command) < 0) {
4711         return -1;
4712     }
4713 
4714     Py_BEGIN_ALLOW_THREADS
4715     _Py_BEGIN_SUPPRESS_IPH
4716     result = _wsystem(command);
4717     _Py_END_SUPPRESS_IPH
4718     Py_END_ALLOW_THREADS
4719     return result;
4720 }
4721 #else /* MS_WINDOWS */
4722 /*[clinic input]
4723 os.system -> long
4724 
4725     command: FSConverter
4726 
4727 Execute the command in a subshell.
4728 [clinic start generated code]*/
4729 
4730 static long
os_system_impl(PyObject * module,PyObject * command)4731 os_system_impl(PyObject *module, PyObject *command)
4732 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4733 {
4734     long result;
4735     const char *bytes = PyBytes_AsString(command);
4736 
4737     if (PySys_Audit("os.system", "(O)", command) < 0) {
4738         return -1;
4739     }
4740 
4741     Py_BEGIN_ALLOW_THREADS
4742     result = system(bytes);
4743     Py_END_ALLOW_THREADS
4744     return result;
4745 }
4746 #endif
4747 #endif /* HAVE_SYSTEM */
4748 
4749 
4750 /*[clinic input]
4751 os.umask
4752 
4753     mask: int
4754     /
4755 
4756 Set the current numeric umask and return the previous umask.
4757 [clinic start generated code]*/
4758 
4759 static PyObject *
os_umask_impl(PyObject * module,int mask)4760 os_umask_impl(PyObject *module, int mask)
4761 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4762 {
4763     int i = (int)umask(mask);
4764     if (i < 0)
4765         return posix_error();
4766     return PyLong_FromLong((long)i);
4767 }
4768 
4769 #ifdef MS_WINDOWS
4770 
4771 /* override the default DeleteFileW behavior so that directory
4772 symlinks can be removed with this function, the same as with
4773 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)4774 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
4775 {
4776     WIN32_FILE_ATTRIBUTE_DATA info;
4777     WIN32_FIND_DATAW find_data;
4778     HANDLE find_data_handle;
4779     int is_directory = 0;
4780     int is_link = 0;
4781 
4782     if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
4783         is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4784 
4785         /* Get WIN32_FIND_DATA structure for the path to determine if
4786            it is a symlink */
4787         if(is_directory &&
4788            info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
4789             find_data_handle = FindFirstFileW(lpFileName, &find_data);
4790 
4791             if(find_data_handle != INVALID_HANDLE_VALUE) {
4792                 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
4793                    IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
4794                 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
4795                           find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
4796                 FindClose(find_data_handle);
4797             }
4798         }
4799     }
4800 
4801     if (is_directory && is_link)
4802         return RemoveDirectoryW(lpFileName);
4803 
4804     return DeleteFileW(lpFileName);
4805 }
4806 #endif /* MS_WINDOWS */
4807 
4808 
4809 /*[clinic input]
4810 os.unlink
4811 
4812     path: path_t
4813     *
4814     dir_fd: dir_fd(requires='unlinkat')=None
4815 
4816 Remove a file (same as remove()).
4817 
4818 If dir_fd is not None, it should be a file descriptor open to a directory,
4819   and path should be relative; path will then be relative to that directory.
4820 dir_fd may not be implemented on your platform.
4821   If it is unavailable, using it will raise a NotImplementedError.
4822 
4823 [clinic start generated code]*/
4824 
4825 static PyObject *
os_unlink_impl(PyObject * module,path_t * path,int dir_fd)4826 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
4827 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
4828 {
4829     int result;
4830 #ifdef HAVE_UNLINKAT
4831     int unlinkat_unavailable = 0;
4832 #endif
4833 
4834     if (PySys_Audit("os.remove", "Oi", path->object,
4835                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4836         return NULL;
4837     }
4838 
4839     Py_BEGIN_ALLOW_THREADS
4840     _Py_BEGIN_SUPPRESS_IPH
4841 #ifdef MS_WINDOWS
4842     /* Windows, success=1, UNIX, success=0 */
4843     result = !Py_DeleteFileW(path->wide);
4844 #else
4845 #ifdef HAVE_UNLINKAT
4846     if (dir_fd != DEFAULT_DIR_FD) {
4847       if (HAVE_UNLINKAT_RUNTIME) {
4848 
4849         result = unlinkat(dir_fd, path->narrow, 0);
4850       } else {
4851         unlinkat_unavailable = 1;
4852       }
4853     } else
4854 #endif /* HAVE_UNLINKAT */
4855         result = unlink(path->narrow);
4856 #endif
4857     _Py_END_SUPPRESS_IPH
4858     Py_END_ALLOW_THREADS
4859 
4860 #ifdef HAVE_UNLINKAT
4861     if (unlinkat_unavailable) {
4862         argument_unavailable_error(NULL, "dir_fd");
4863         return NULL;
4864     }
4865 #endif
4866 
4867     if (result)
4868         return path_error(path);
4869 
4870     Py_RETURN_NONE;
4871 }
4872 
4873 
4874 /*[clinic input]
4875 os.remove = os.unlink
4876 
4877 Remove a file (same as unlink()).
4878 
4879 If dir_fd is not None, it should be a file descriptor open to a directory,
4880   and path should be relative; path will then be relative to that directory.
4881 dir_fd may not be implemented on your platform.
4882   If it is unavailable, using it will raise a NotImplementedError.
4883 [clinic start generated code]*/
4884 
4885 static PyObject *
os_remove_impl(PyObject * module,path_t * path,int dir_fd)4886 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
4887 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
4888 {
4889     return os_unlink_impl(module, path, dir_fd);
4890 }
4891 
4892 
4893 static PyStructSequence_Field uname_result_fields[] = {
4894     {"sysname",    "operating system name"},
4895     {"nodename",   "name of machine on network (implementation-defined)"},
4896     {"release",    "operating system release"},
4897     {"version",    "operating system version"},
4898     {"machine",    "hardware identifier"},
4899     {NULL}
4900 };
4901 
4902 PyDoc_STRVAR(uname_result__doc__,
4903 "uname_result: Result from os.uname().\n\n\
4904 This object may be accessed either as a tuple of\n\
4905   (sysname, nodename, release, version, machine),\n\
4906 or via the attributes sysname, nodename, release, version, and machine.\n\
4907 \n\
4908 See os.uname for more information.");
4909 
4910 static PyStructSequence_Desc uname_result_desc = {
4911     MODNAME ".uname_result", /* name */
4912     uname_result__doc__, /* doc */
4913     uname_result_fields,
4914     5
4915 };
4916 
4917 #ifdef HAVE_UNAME
4918 /*[clinic input]
4919 os.uname
4920 
4921 Return an object identifying the current operating system.
4922 
4923 The object behaves like a named tuple with the following fields:
4924   (sysname, nodename, release, version, machine)
4925 
4926 [clinic start generated code]*/
4927 
4928 static PyObject *
os_uname_impl(PyObject * module)4929 os_uname_impl(PyObject *module)
4930 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
4931 {
4932     struct utsname u;
4933     int res;
4934     PyObject *value;
4935 
4936     Py_BEGIN_ALLOW_THREADS
4937     res = uname(&u);
4938     Py_END_ALLOW_THREADS
4939     if (res < 0)
4940         return posix_error();
4941 
4942     PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
4943     value = PyStructSequence_New((PyTypeObject *)UnameResultType);
4944     if (value == NULL)
4945         return NULL;
4946 
4947 #define SET(i, field) \
4948     { \
4949     PyObject *o = PyUnicode_DecodeFSDefault(field); \
4950     if (!o) { \
4951         Py_DECREF(value); \
4952         return NULL; \
4953     } \
4954     PyStructSequence_SET_ITEM(value, i, o); \
4955     } \
4956 
4957     SET(0, u.sysname);
4958     SET(1, u.nodename);
4959     SET(2, u.release);
4960     SET(3, u.version);
4961     SET(4, u.machine);
4962 
4963 #undef SET
4964 
4965     return value;
4966 }
4967 #endif /* HAVE_UNAME */
4968 
4969 
4970 
4971 typedef struct {
4972     int    now;
4973     time_t atime_s;
4974     long   atime_ns;
4975     time_t mtime_s;
4976     long   mtime_ns;
4977 } utime_t;
4978 
4979 /*
4980  * these macros assume that "ut" is a pointer to a utime_t
4981  * they also intentionally leak the declaration of a pointer named "time"
4982  */
4983 #define UTIME_TO_TIMESPEC \
4984     struct timespec ts[2]; \
4985     struct timespec *time; \
4986     if (ut->now) \
4987         time = NULL; \
4988     else { \
4989         ts[0].tv_sec = ut->atime_s; \
4990         ts[0].tv_nsec = ut->atime_ns; \
4991         ts[1].tv_sec = ut->mtime_s; \
4992         ts[1].tv_nsec = ut->mtime_ns; \
4993         time = ts; \
4994     } \
4995 
4996 #define UTIME_TO_TIMEVAL \
4997     struct timeval tv[2]; \
4998     struct timeval *time; \
4999     if (ut->now) \
5000         time = NULL; \
5001     else { \
5002         tv[0].tv_sec = ut->atime_s; \
5003         tv[0].tv_usec = ut->atime_ns / 1000; \
5004         tv[1].tv_sec = ut->mtime_s; \
5005         tv[1].tv_usec = ut->mtime_ns / 1000; \
5006         time = tv; \
5007     } \
5008 
5009 #define UTIME_TO_UTIMBUF \
5010     struct utimbuf u; \
5011     struct utimbuf *time; \
5012     if (ut->now) \
5013         time = NULL; \
5014     else { \
5015         u.actime = ut->atime_s; \
5016         u.modtime = ut->mtime_s; \
5017         time = &u; \
5018     }
5019 
5020 #define UTIME_TO_TIME_T \
5021     time_t timet[2]; \
5022     time_t *time; \
5023     if (ut->now) \
5024         time = NULL; \
5025     else { \
5026         timet[0] = ut->atime_s; \
5027         timet[1] = ut->mtime_s; \
5028         time = timet; \
5029     } \
5030 
5031 
5032 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5033 
5034 static int
utime_dir_fd(utime_t * ut,int dir_fd,const char * path,int follow_symlinks)5035 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
5036 {
5037 #if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
5038     if (HAVE_UTIMENSAT_RUNTIME) {
5039         int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5040         UTIME_TO_TIMESPEC;
5041         return utimensat(dir_fd, path, time, flags);
5042     }  else {
5043         errno = ENOSYS;
5044         return -1;
5045     }
5046 #elif defined(HAVE_UTIMENSAT)
5047     int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5048     UTIME_TO_TIMESPEC;
5049     return utimensat(dir_fd, path, time, flags);
5050 #elif defined(HAVE_FUTIMESAT)
5051     UTIME_TO_TIMEVAL;
5052     /*
5053      * follow_symlinks will never be false here;
5054      * we only allow !follow_symlinks and dir_fd together
5055      * if we have utimensat()
5056      */
5057     assert(follow_symlinks);
5058     return futimesat(dir_fd, path, time);
5059 #endif
5060 }
5061 
5062     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
5063 #else
5064     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
5065 #endif
5066 
5067 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5068 
5069 static int
utime_fd(utime_t * ut,int fd)5070 utime_fd(utime_t *ut, int fd)
5071 {
5072 #ifdef HAVE_FUTIMENS
5073 
5074     if (HAVE_FUTIMENS_RUNTIME) {
5075 
5076     UTIME_TO_TIMESPEC;
5077     return futimens(fd, time);
5078 
5079     } else
5080 #ifndef HAVE_FUTIMES
5081     {
5082         /* Not sure if this can happen */
5083         PyErr_SetString(
5084             PyExc_RuntimeError,
5085             "neither futimens nor futimes are supported"
5086             " on this system");
5087         return -1;
5088     }
5089 #endif
5090 
5091 #endif
5092 #ifdef HAVE_FUTIMES
5093     {
5094     UTIME_TO_TIMEVAL;
5095     return futimes(fd, time);
5096     }
5097 #endif
5098 }
5099 
5100     #define PATH_UTIME_HAVE_FD 1
5101 #else
5102     #define PATH_UTIME_HAVE_FD 0
5103 #endif
5104 
5105 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
5106 #  define UTIME_HAVE_NOFOLLOW_SYMLINKS
5107 #endif
5108 
5109 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5110 
5111 static int
utime_nofollow_symlinks(utime_t * ut,const char * path)5112 utime_nofollow_symlinks(utime_t *ut, const char *path)
5113 {
5114 #ifdef HAVE_UTIMENSAT
5115     if (HAVE_UTIMENSAT_RUNTIME) {
5116         UTIME_TO_TIMESPEC;
5117         return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
5118     } else
5119 #ifndef HAVE_LUTIMES
5120     {
5121         /* Not sure if this can happen */
5122         PyErr_SetString(
5123             PyExc_RuntimeError,
5124             "neither utimensat nor lutimes are supported"
5125             " on this system");
5126         return -1;
5127     }
5128 #endif
5129 #endif
5130 
5131 #ifdef HAVE_LUTIMES
5132     {
5133     UTIME_TO_TIMEVAL;
5134     return lutimes(path, time);
5135     }
5136 #endif
5137 }
5138 
5139 #endif
5140 
5141 #ifndef MS_WINDOWS
5142 
5143 static int
utime_default(utime_t * ut,const char * path)5144 utime_default(utime_t *ut, const char *path)
5145 {
5146 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5147     if (HAVE_UTIMENSAT_RUNTIME) {
5148         UTIME_TO_TIMESPEC;
5149         return utimensat(DEFAULT_DIR_FD, path, time, 0);
5150     } else {
5151         UTIME_TO_TIMEVAL;
5152         return utimes(path, time);
5153     }
5154 #elif defined(HAVE_UTIMENSAT)
5155     UTIME_TO_TIMESPEC;
5156     return utimensat(DEFAULT_DIR_FD, path, time, 0);
5157 #elif defined(HAVE_UTIMES)
5158     UTIME_TO_TIMEVAL;
5159     return utimes(path, time);
5160 #elif defined(HAVE_UTIME_H)
5161     UTIME_TO_UTIMBUF;
5162     return utime(path, time);
5163 #else
5164     UTIME_TO_TIME_T;
5165     return utime(path, time);
5166 #endif
5167 }
5168 
5169 #endif
5170 
5171 static int
split_py_long_to_s_and_ns(PyObject * module,PyObject * py_long,time_t * s,long * ns)5172 split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5173 {
5174     int result = 0;
5175     PyObject *divmod;
5176     divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5177     if (!divmod)
5178         goto exit;
5179     if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
5180         PyErr_Format(PyExc_TypeError,
5181                      "%.200s.__divmod__() must return a 2-tuple, not %.200s",
5182                      _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
5183         goto exit;
5184     }
5185     *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5186     if ((*s == -1) && PyErr_Occurred())
5187         goto exit;
5188     *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5189     if ((*ns == -1) && PyErr_Occurred())
5190         goto exit;
5191 
5192     result = 1;
5193 exit:
5194     Py_XDECREF(divmod);
5195     return result;
5196 }
5197 
5198 
5199 /*[clinic input]
5200 os.utime
5201 
5202     path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
5203     times: object = None
5204     *
5205     ns: object = NULL
5206     dir_fd: dir_fd(requires='futimensat') = None
5207     follow_symlinks: bool=True
5208 
5209 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
5210 
5211 Set the access and modified time of path.
5212 
5213 path may always be specified as a string.
5214 On some platforms, path may also be specified as an open file descriptor.
5215   If this functionality is unavailable, using it raises an exception.
5216 
5217 If times is not None, it must be a tuple (atime, mtime);
5218     atime and mtime should be expressed as float seconds since the epoch.
5219 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
5220     atime_ns and mtime_ns should be expressed as integer nanoseconds
5221     since the epoch.
5222 If times is None and ns is unspecified, utime uses the current time.
5223 Specifying tuples for both times and ns is an error.
5224 
5225 If dir_fd is not None, it should be a file descriptor open to a directory,
5226   and path should be relative; path will then be relative to that directory.
5227 If follow_symlinks is False, and the last element of the path is a symbolic
5228   link, utime will modify the symbolic link itself instead of the file the
5229   link points to.
5230 It is an error to use dir_fd or follow_symlinks when specifying path
5231   as an open file descriptor.
5232 dir_fd and follow_symlinks may not be available on your platform.
5233   If they are unavailable, using them will raise a NotImplementedError.
5234 
5235 [clinic start generated code]*/
5236 
5237 static PyObject *
os_utime_impl(PyObject * module,path_t * path,PyObject * times,PyObject * ns,int dir_fd,int follow_symlinks)5238 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
5239               int dir_fd, int follow_symlinks)
5240 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
5241 {
5242 #ifdef MS_WINDOWS
5243     HANDLE hFile;
5244     FILETIME atime, mtime;
5245 #else
5246     int result;
5247 #endif
5248 
5249     utime_t utime;
5250 
5251     memset(&utime, 0, sizeof(utime_t));
5252 
5253     if (times != Py_None && ns) {
5254         PyErr_SetString(PyExc_ValueError,
5255                      "utime: you may specify either 'times'"
5256                      " or 'ns' but not both");
5257         return NULL;
5258     }
5259 
5260     if (times != Py_None) {
5261         time_t a_sec, m_sec;
5262         long a_nsec, m_nsec;
5263         if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
5264             PyErr_SetString(PyExc_TypeError,
5265                          "utime: 'times' must be either"
5266                          " a tuple of two ints or None");
5267             return NULL;
5268         }
5269         utime.now = 0;
5270         if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
5271                                      &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
5272             _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
5273                                      &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
5274             return NULL;
5275         }
5276         utime.atime_s = a_sec;
5277         utime.atime_ns = a_nsec;
5278         utime.mtime_s = m_sec;
5279         utime.mtime_ns = m_nsec;
5280     }
5281     else if (ns) {
5282         if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
5283             PyErr_SetString(PyExc_TypeError,
5284                          "utime: 'ns' must be a tuple of two ints");
5285             return NULL;
5286         }
5287         utime.now = 0;
5288         if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
5289                                       &utime.atime_s, &utime.atime_ns) ||
5290             !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
5291                                        &utime.mtime_s, &utime.mtime_ns)) {
5292             return NULL;
5293         }
5294     }
5295     else {
5296         /* times and ns are both None/unspecified. use "now". */
5297         utime.now = 1;
5298     }
5299 
5300 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
5301     if (follow_symlinks_specified("utime", follow_symlinks))
5302         return NULL;
5303 #endif
5304 
5305     if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
5306         dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
5307         fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
5308         return NULL;
5309 
5310 #if !defined(HAVE_UTIMENSAT)
5311     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
5312         PyErr_SetString(PyExc_ValueError,
5313                      "utime: cannot use dir_fd and follow_symlinks "
5314                      "together on this platform");
5315         return NULL;
5316     }
5317 #endif
5318 
5319     if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
5320                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5321         return NULL;
5322     }
5323 
5324 #ifdef MS_WINDOWS
5325     Py_BEGIN_ALLOW_THREADS
5326     hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
5327                         NULL, OPEN_EXISTING,
5328                         FILE_FLAG_BACKUP_SEMANTICS, NULL);
5329     Py_END_ALLOW_THREADS
5330     if (hFile == INVALID_HANDLE_VALUE) {
5331         path_error(path);
5332         return NULL;
5333     }
5334 
5335     if (utime.now) {
5336         GetSystemTimeAsFileTime(&mtime);
5337         atime = mtime;
5338     }
5339     else {
5340         _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
5341         _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
5342     }
5343     if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
5344         /* Avoid putting the file name into the error here,
5345            as that may confuse the user into believing that
5346            something is wrong with the file, when it also
5347            could be the time stamp that gives a problem. */
5348         PyErr_SetFromWindowsErr(0);
5349         CloseHandle(hFile);
5350         return NULL;
5351     }
5352     CloseHandle(hFile);
5353 #else /* MS_WINDOWS */
5354     Py_BEGIN_ALLOW_THREADS
5355 
5356 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5357     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
5358         result = utime_nofollow_symlinks(&utime, path->narrow);
5359     else
5360 #endif
5361 
5362 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5363     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
5364         result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
5365 
5366     } else
5367 #endif
5368 
5369 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5370     if (path->fd != -1)
5371         result = utime_fd(&utime, path->fd);
5372     else
5373 #endif
5374 
5375     result = utime_default(&utime, path->narrow);
5376 
5377     Py_END_ALLOW_THREADS
5378 
5379 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5380     /* See utime_dir_fd implementation */
5381     if (result == -1 && errno == ENOSYS) {
5382         argument_unavailable_error(NULL, "dir_fd");
5383         return NULL;
5384     }
5385 #endif
5386 
5387     if (result < 0) {
5388         /* see previous comment about not putting filename in error here */
5389         posix_error();
5390         return NULL;
5391     }
5392 
5393 #endif /* MS_WINDOWS */
5394 
5395     Py_RETURN_NONE;
5396 }
5397 
5398 /* Process operations */
5399 
5400 
5401 /*[clinic input]
5402 os._exit
5403 
5404     status: int
5405 
5406 Exit to the system with specified status, without normal exit processing.
5407 [clinic start generated code]*/
5408 
5409 static PyObject *
os__exit_impl(PyObject * module,int status)5410 os__exit_impl(PyObject *module, int status)
5411 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5412 {
5413     _exit(status);
5414     return NULL; /* Make gcc -Wall happy */
5415 }
5416 
5417 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5418 #define EXECV_CHAR wchar_t
5419 #else
5420 #define EXECV_CHAR char
5421 #endif
5422 
5423 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5424 static void
free_string_array(EXECV_CHAR ** array,Py_ssize_t count)5425 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5426 {
5427     Py_ssize_t i;
5428     for (i = 0; i < count; i++)
5429         PyMem_Free(array[i]);
5430     PyMem_DEL(array);
5431 }
5432 
5433 static int
fsconvert_strdup(PyObject * o,EXECV_CHAR ** out)5434 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5435 {
5436     Py_ssize_t size;
5437     PyObject *ub;
5438     int result = 0;
5439 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5440     if (!PyUnicode_FSDecoder(o, &ub))
5441         return 0;
5442     *out = PyUnicode_AsWideCharString(ub, &size);
5443     if (*out)
5444         result = 1;
5445 #else
5446     if (!PyUnicode_FSConverter(o, &ub))
5447         return 0;
5448     size = PyBytes_GET_SIZE(ub);
5449     *out = PyMem_Malloc(size + 1);
5450     if (*out) {
5451         memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5452         result = 1;
5453     } else
5454         PyErr_NoMemory();
5455 #endif
5456     Py_DECREF(ub);
5457     return result;
5458 }
5459 #endif
5460 
5461 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5462 static EXECV_CHAR**
parse_envlist(PyObject * env,Py_ssize_t * envc_ptr)5463 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5464 {
5465     Py_ssize_t i, pos, envc;
5466     PyObject *keys=NULL, *vals=NULL;
5467     PyObject *key, *val, *key2, *val2, *keyval;
5468     EXECV_CHAR **envlist;
5469 
5470     i = PyMapping_Size(env);
5471     if (i < 0)
5472         return NULL;
5473     envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5474     if (envlist == NULL) {
5475         PyErr_NoMemory();
5476         return NULL;
5477     }
5478     envc = 0;
5479     keys = PyMapping_Keys(env);
5480     if (!keys)
5481         goto error;
5482     vals = PyMapping_Values(env);
5483     if (!vals)
5484         goto error;
5485     if (!PyList_Check(keys) || !PyList_Check(vals)) {
5486         PyErr_Format(PyExc_TypeError,
5487                      "env.keys() or env.values() is not a list");
5488         goto error;
5489     }
5490 
5491     for (pos = 0; pos < i; pos++) {
5492         key = PyList_GetItem(keys, pos);
5493         val = PyList_GetItem(vals, pos);
5494         if (!key || !val)
5495             goto error;
5496 
5497 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5498         if (!PyUnicode_FSDecoder(key, &key2))
5499             goto error;
5500         if (!PyUnicode_FSDecoder(val, &val2)) {
5501             Py_DECREF(key2);
5502             goto error;
5503         }
5504         /* Search from index 1 because on Windows starting '=' is allowed for
5505            defining hidden environment variables. */
5506         if (PyUnicode_GET_LENGTH(key2) == 0 ||
5507             PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5508         {
5509             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5510             Py_DECREF(key2);
5511             Py_DECREF(val2);
5512             goto error;
5513         }
5514         keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5515 #else
5516         if (!PyUnicode_FSConverter(key, &key2))
5517             goto error;
5518         if (!PyUnicode_FSConverter(val, &val2)) {
5519             Py_DECREF(key2);
5520             goto error;
5521         }
5522         if (PyBytes_GET_SIZE(key2) == 0 ||
5523             strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5524         {
5525             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5526             Py_DECREF(key2);
5527             Py_DECREF(val2);
5528             goto error;
5529         }
5530         keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5531                                              PyBytes_AS_STRING(val2));
5532 #endif
5533         Py_DECREF(key2);
5534         Py_DECREF(val2);
5535         if (!keyval)
5536             goto error;
5537 
5538         if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5539             Py_DECREF(keyval);
5540             goto error;
5541         }
5542 
5543         Py_DECREF(keyval);
5544     }
5545     Py_DECREF(vals);
5546     Py_DECREF(keys);
5547 
5548     envlist[envc] = 0;
5549     *envc_ptr = envc;
5550     return envlist;
5551 
5552 error:
5553     Py_XDECREF(keys);
5554     Py_XDECREF(vals);
5555     free_string_array(envlist, envc);
5556     return NULL;
5557 }
5558 
5559 static EXECV_CHAR**
parse_arglist(PyObject * argv,Py_ssize_t * argc)5560 parse_arglist(PyObject* argv, Py_ssize_t *argc)
5561 {
5562     int i;
5563     EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5564     if (argvlist == NULL) {
5565         PyErr_NoMemory();
5566         return NULL;
5567     }
5568     for (i = 0; i < *argc; i++) {
5569         PyObject* item = PySequence_ITEM(argv, i);
5570         if (item == NULL)
5571             goto fail;
5572         if (!fsconvert_strdup(item, &argvlist[i])) {
5573             Py_DECREF(item);
5574             goto fail;
5575         }
5576         Py_DECREF(item);
5577     }
5578     argvlist[*argc] = NULL;
5579     return argvlist;
5580 fail:
5581     *argc = i;
5582     free_string_array(argvlist, *argc);
5583     return NULL;
5584 }
5585 
5586 #endif
5587 
5588 
5589 #ifdef HAVE_EXECV
5590 /*[clinic input]
5591 os.execv
5592 
5593     path: path_t
5594         Path of executable file.
5595     argv: object
5596         Tuple or list of strings.
5597     /
5598 
5599 Execute an executable path with arguments, replacing current process.
5600 [clinic start generated code]*/
5601 
5602 static PyObject *
os_execv_impl(PyObject * module,path_t * path,PyObject * argv)5603 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5604 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5605 {
5606     EXECV_CHAR **argvlist;
5607     Py_ssize_t argc;
5608 
5609     /* execv has two arguments: (path, argv), where
5610        argv is a list or tuple of strings. */
5611 
5612     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5613         PyErr_SetString(PyExc_TypeError,
5614                         "execv() arg 2 must be a tuple or list");
5615         return NULL;
5616     }
5617     argc = PySequence_Size(argv);
5618     if (argc < 1) {
5619         PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5620         return NULL;
5621     }
5622 
5623     argvlist = parse_arglist(argv, &argc);
5624     if (argvlist == NULL) {
5625         return NULL;
5626     }
5627     if (!argvlist[0][0]) {
5628         PyErr_SetString(PyExc_ValueError,
5629             "execv() arg 2 first element cannot be empty");
5630         free_string_array(argvlist, argc);
5631         return NULL;
5632     }
5633 
5634     if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5635         free_string_array(argvlist, argc);
5636         return NULL;
5637     }
5638 
5639     _Py_BEGIN_SUPPRESS_IPH
5640 #ifdef HAVE_WEXECV
5641     _wexecv(path->wide, argvlist);
5642 #else
5643     execv(path->narrow, argvlist);
5644 #endif
5645     _Py_END_SUPPRESS_IPH
5646 
5647     /* If we get here it's definitely an error */
5648 
5649     free_string_array(argvlist, argc);
5650     return posix_error();
5651 }
5652 
5653 
5654 /*[clinic input]
5655 os.execve
5656 
5657     path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5658         Path of executable file.
5659     argv: object
5660         Tuple or list of strings.
5661     env: object
5662         Dictionary of strings mapping to strings.
5663 
5664 Execute an executable path with arguments, replacing current process.
5665 [clinic start generated code]*/
5666 
5667 static PyObject *
os_execve_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env)5668 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5669 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5670 {
5671     EXECV_CHAR **argvlist = NULL;
5672     EXECV_CHAR **envlist;
5673     Py_ssize_t argc, envc;
5674 
5675     /* execve has three arguments: (path, argv, env), where
5676        argv is a list or tuple of strings and env is a dictionary
5677        like posix.environ. */
5678 
5679     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5680         PyErr_SetString(PyExc_TypeError,
5681                         "execve: argv must be a tuple or list");
5682         goto fail_0;
5683     }
5684     argc = PySequence_Size(argv);
5685     if (argc < 1) {
5686         PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5687         return NULL;
5688     }
5689 
5690     if (!PyMapping_Check(env)) {
5691         PyErr_SetString(PyExc_TypeError,
5692                         "execve: environment must be a mapping object");
5693         goto fail_0;
5694     }
5695 
5696     argvlist = parse_arglist(argv, &argc);
5697     if (argvlist == NULL) {
5698         goto fail_0;
5699     }
5700     if (!argvlist[0][0]) {
5701         PyErr_SetString(PyExc_ValueError,
5702             "execve: argv first element cannot be empty");
5703         goto fail_0;
5704     }
5705 
5706     envlist = parse_envlist(env, &envc);
5707     if (envlist == NULL)
5708         goto fail_0;
5709 
5710     if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5711         goto fail_1;
5712     }
5713 
5714     _Py_BEGIN_SUPPRESS_IPH
5715 #ifdef HAVE_FEXECVE
5716     if (path->fd > -1)
5717         fexecve(path->fd, argvlist, envlist);
5718     else
5719 #endif
5720 #ifdef HAVE_WEXECV
5721         _wexecve(path->wide, argvlist, envlist);
5722 #else
5723         execve(path->narrow, argvlist, envlist);
5724 #endif
5725     _Py_END_SUPPRESS_IPH
5726 
5727     /* If we get here it's definitely an error */
5728 
5729     posix_path_error(path);
5730   fail_1:
5731     free_string_array(envlist, envc);
5732   fail_0:
5733     if (argvlist)
5734         free_string_array(argvlist, argc);
5735     return NULL;
5736 }
5737 
5738 #endif /* HAVE_EXECV */
5739 
5740 #ifdef HAVE_POSIX_SPAWN
5741 
5742 enum posix_spawn_file_actions_identifier {
5743     POSIX_SPAWN_OPEN,
5744     POSIX_SPAWN_CLOSE,
5745     POSIX_SPAWN_DUP2
5746 };
5747 
5748 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
5749 static int
5750 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
5751 #endif
5752 
5753 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)5754 parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
5755                         int resetids, int setsid, PyObject *setsigmask,
5756                         PyObject *setsigdef, PyObject *scheduler,
5757                         posix_spawnattr_t *attrp)
5758 {
5759     long all_flags = 0;
5760 
5761     errno = posix_spawnattr_init(attrp);
5762     if (errno) {
5763         posix_error();
5764         return -1;
5765     }
5766 
5767     if (setpgroup) {
5768         pid_t pgid = PyLong_AsPid(setpgroup);
5769         if (pgid == (pid_t)-1 && PyErr_Occurred()) {
5770             goto fail;
5771         }
5772         errno = posix_spawnattr_setpgroup(attrp, pgid);
5773         if (errno) {
5774             posix_error();
5775             goto fail;
5776         }
5777         all_flags |= POSIX_SPAWN_SETPGROUP;
5778     }
5779 
5780     if (resetids) {
5781         all_flags |= POSIX_SPAWN_RESETIDS;
5782     }
5783 
5784     if (setsid) {
5785 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5786         if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
5787 #endif
5788 #ifdef POSIX_SPAWN_SETSID
5789         all_flags |= POSIX_SPAWN_SETSID;
5790 #elif defined(POSIX_SPAWN_SETSID_NP)
5791         all_flags |= POSIX_SPAWN_SETSID_NP;
5792 #else
5793         argument_unavailable_error(func_name, "setsid");
5794         return -1;
5795 #endif
5796 
5797 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5798         } else {
5799             argument_unavailable_error(func_name, "setsid");
5800             return -1;
5801         }
5802 #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
5803 
5804     }
5805 
5806    if (setsigmask) {
5807         sigset_t set;
5808         if (!_Py_Sigset_Converter(setsigmask, &set)) {
5809             goto fail;
5810         }
5811         errno = posix_spawnattr_setsigmask(attrp, &set);
5812         if (errno) {
5813             posix_error();
5814             goto fail;
5815         }
5816         all_flags |= POSIX_SPAWN_SETSIGMASK;
5817     }
5818 
5819     if (setsigdef) {
5820         sigset_t set;
5821         if (!_Py_Sigset_Converter(setsigdef, &set)) {
5822             goto fail;
5823         }
5824         errno = posix_spawnattr_setsigdefault(attrp, &set);
5825         if (errno) {
5826             posix_error();
5827             goto fail;
5828         }
5829         all_flags |= POSIX_SPAWN_SETSIGDEF;
5830     }
5831 
5832     if (scheduler) {
5833 #ifdef POSIX_SPAWN_SETSCHEDULER
5834         PyObject *py_schedpolicy;
5835         PyObject *schedparam_obj;
5836         struct sched_param schedparam;
5837 
5838         if (!PyArg_ParseTuple(scheduler, "OO"
5839                         ";A scheduler tuple must have two elements",
5840                         &py_schedpolicy, &schedparam_obj)) {
5841             goto fail;
5842         }
5843         if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
5844             goto fail;
5845         }
5846         if (py_schedpolicy != Py_None) {
5847             int schedpolicy = _PyLong_AsInt(py_schedpolicy);
5848 
5849             if (schedpolicy == -1 && PyErr_Occurred()) {
5850                 goto fail;
5851             }
5852             errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
5853             if (errno) {
5854                 posix_error();
5855                 goto fail;
5856             }
5857             all_flags |= POSIX_SPAWN_SETSCHEDULER;
5858         }
5859         errno = posix_spawnattr_setschedparam(attrp, &schedparam);
5860         if (errno) {
5861             posix_error();
5862             goto fail;
5863         }
5864         all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
5865 #else
5866         PyErr_SetString(PyExc_NotImplementedError,
5867                 "The scheduler option is not supported in this system.");
5868         goto fail;
5869 #endif
5870     }
5871 
5872     errno = posix_spawnattr_setflags(attrp, all_flags);
5873     if (errno) {
5874         posix_error();
5875         goto fail;
5876     }
5877 
5878     return 0;
5879 
5880 fail:
5881     (void)posix_spawnattr_destroy(attrp);
5882     return -1;
5883 }
5884 
5885 static int
parse_file_actions(PyObject * file_actions,posix_spawn_file_actions_t * file_actionsp,PyObject * temp_buffer)5886 parse_file_actions(PyObject *file_actions,
5887                    posix_spawn_file_actions_t *file_actionsp,
5888                    PyObject *temp_buffer)
5889 {
5890     PyObject *seq;
5891     PyObject *file_action = NULL;
5892     PyObject *tag_obj;
5893 
5894     seq = PySequence_Fast(file_actions,
5895                           "file_actions must be a sequence or None");
5896     if (seq == NULL) {
5897         return -1;
5898     }
5899 
5900     errno = posix_spawn_file_actions_init(file_actionsp);
5901     if (errno) {
5902         posix_error();
5903         Py_DECREF(seq);
5904         return -1;
5905     }
5906 
5907     for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
5908         file_action = PySequence_Fast_GET_ITEM(seq, i);
5909         Py_INCREF(file_action);
5910         if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
5911             PyErr_SetString(PyExc_TypeError,
5912                 "Each file_actions element must be a non-empty tuple");
5913             goto fail;
5914         }
5915         long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
5916         if (tag == -1 && PyErr_Occurred()) {
5917             goto fail;
5918         }
5919 
5920         /* Populate the file_actions object */
5921         switch (tag) {
5922             case POSIX_SPAWN_OPEN: {
5923                 int fd, oflag;
5924                 PyObject *path;
5925                 unsigned long mode;
5926                 if (!PyArg_ParseTuple(file_action, "OiO&ik"
5927                         ";A open file_action tuple must have 5 elements",
5928                         &tag_obj, &fd, PyUnicode_FSConverter, &path,
5929                         &oflag, &mode))
5930                 {
5931                     goto fail;
5932                 }
5933                 if (PyList_Append(temp_buffer, path)) {
5934                     Py_DECREF(path);
5935                     goto fail;
5936                 }
5937                 errno = posix_spawn_file_actions_addopen(file_actionsp,
5938                         fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
5939                 Py_DECREF(path);
5940                 if (errno) {
5941                     posix_error();
5942                     goto fail;
5943                 }
5944                 break;
5945             }
5946             case POSIX_SPAWN_CLOSE: {
5947                 int fd;
5948                 if (!PyArg_ParseTuple(file_action, "Oi"
5949                         ";A close file_action tuple must have 2 elements",
5950                         &tag_obj, &fd))
5951                 {
5952                     goto fail;
5953                 }
5954                 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
5955                 if (errno) {
5956                     posix_error();
5957                     goto fail;
5958                 }
5959                 break;
5960             }
5961             case POSIX_SPAWN_DUP2: {
5962                 int fd1, fd2;
5963                 if (!PyArg_ParseTuple(file_action, "Oii"
5964                         ";A dup2 file_action tuple must have 3 elements",
5965                         &tag_obj, &fd1, &fd2))
5966                 {
5967                     goto fail;
5968                 }
5969                 errno = posix_spawn_file_actions_adddup2(file_actionsp,
5970                                                          fd1, fd2);
5971                 if (errno) {
5972                     posix_error();
5973                     goto fail;
5974                 }
5975                 break;
5976             }
5977             default: {
5978                 PyErr_SetString(PyExc_TypeError,
5979                                 "Unknown file_actions identifier");
5980                 goto fail;
5981             }
5982         }
5983         Py_DECREF(file_action);
5984     }
5985 
5986     Py_DECREF(seq);
5987     return 0;
5988 
5989 fail:
5990     Py_DECREF(seq);
5991     Py_DECREF(file_action);
5992     (void)posix_spawn_file_actions_destroy(file_actionsp);
5993     return -1;
5994 }
5995 
5996 
5997 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)5998 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
5999                PyObject *env, PyObject *file_actions,
6000                PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
6001                PyObject *setsigdef, PyObject *scheduler)
6002 {
6003     const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
6004     EXECV_CHAR **argvlist = NULL;
6005     EXECV_CHAR **envlist = NULL;
6006     posix_spawn_file_actions_t file_actions_buf;
6007     posix_spawn_file_actions_t *file_actionsp = NULL;
6008     posix_spawnattr_t attr;
6009     posix_spawnattr_t *attrp = NULL;
6010     Py_ssize_t argc, envc;
6011     PyObject *result = NULL;
6012     PyObject *temp_buffer = NULL;
6013     pid_t pid;
6014     int err_code;
6015 
6016     /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
6017        argv is a list or tuple of strings and env is a dictionary
6018        like posix.environ. */
6019 
6020     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6021         PyErr_Format(PyExc_TypeError,
6022                      "%s: argv must be a tuple or list", func_name);
6023         goto exit;
6024     }
6025     argc = PySequence_Size(argv);
6026     if (argc < 1) {
6027         PyErr_Format(PyExc_ValueError,
6028                      "%s: argv must not be empty", func_name);
6029         return NULL;
6030     }
6031 
6032     if (!PyMapping_Check(env)) {
6033         PyErr_Format(PyExc_TypeError,
6034                      "%s: environment must be a mapping object", func_name);
6035         goto exit;
6036     }
6037 
6038     argvlist = parse_arglist(argv, &argc);
6039     if (argvlist == NULL) {
6040         goto exit;
6041     }
6042     if (!argvlist[0][0]) {
6043         PyErr_Format(PyExc_ValueError,
6044                      "%s: argv first element cannot be empty", func_name);
6045         goto exit;
6046     }
6047 
6048     envlist = parse_envlist(env, &envc);
6049     if (envlist == NULL) {
6050         goto exit;
6051     }
6052 
6053     if (file_actions != NULL && file_actions != Py_None) {
6054         /* There is a bug in old versions of glibc that makes some of the
6055          * helper functions for manipulating file actions not copy the provided
6056          * buffers. The problem is that posix_spawn_file_actions_addopen does not
6057          * copy the value of path for some old versions of glibc (<2.20).
6058          * The use of temp_buffer here is a workaround that keeps the
6059          * python objects that own the buffers alive until posix_spawn gets called.
6060          * Check https://bugs.python.org/issue33630 and
6061          * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
6062         temp_buffer = PyList_New(0);
6063         if (!temp_buffer) {
6064             goto exit;
6065         }
6066         if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
6067             goto exit;
6068         }
6069         file_actionsp = &file_actions_buf;
6070     }
6071 
6072     if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
6073                                 setsigmask, setsigdef, scheduler, &attr)) {
6074         goto exit;
6075     }
6076     attrp = &attr;
6077 
6078     if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
6079         goto exit;
6080     }
6081 
6082     _Py_BEGIN_SUPPRESS_IPH
6083 #ifdef HAVE_POSIX_SPAWNP
6084     if (use_posix_spawnp) {
6085         err_code = posix_spawnp(&pid, path->narrow,
6086                                 file_actionsp, attrp, argvlist, envlist);
6087     }
6088     else
6089 #endif /* HAVE_POSIX_SPAWNP */
6090     {
6091         err_code = posix_spawn(&pid, path->narrow,
6092                                file_actionsp, attrp, argvlist, envlist);
6093     }
6094     _Py_END_SUPPRESS_IPH
6095 
6096     if (err_code) {
6097         errno = err_code;
6098         PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
6099         goto exit;
6100     }
6101 #ifdef _Py_MEMORY_SANITIZER
6102     __msan_unpoison(&pid, sizeof(pid));
6103 #endif
6104     result = PyLong_FromPid(pid);
6105 
6106 exit:
6107     if (file_actionsp) {
6108         (void)posix_spawn_file_actions_destroy(file_actionsp);
6109     }
6110     if (attrp) {
6111         (void)posix_spawnattr_destroy(attrp);
6112     }
6113     if (envlist) {
6114         free_string_array(envlist, envc);
6115     }
6116     if (argvlist) {
6117         free_string_array(argvlist, argc);
6118     }
6119     Py_XDECREF(temp_buffer);
6120     return result;
6121 }
6122 
6123 
6124 /*[clinic input]
6125 
6126 os.posix_spawn
6127     path: path_t
6128         Path of executable file.
6129     argv: object
6130         Tuple or list of strings.
6131     env: object
6132         Dictionary of strings mapping to strings.
6133     /
6134     *
6135     file_actions: object(c_default='NULL') = ()
6136         A sequence of file action tuples.
6137     setpgroup: object = NULL
6138         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6139     resetids: bool(accept={int}) = False
6140         If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
6141     setsid: bool(accept={int}) = False
6142         If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6143     setsigmask: object(c_default='NULL') = ()
6144         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6145     setsigdef: object(c_default='NULL') = ()
6146         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6147     scheduler: object = NULL
6148         A tuple with the scheduler policy (optional) and parameters.
6149 
6150 Execute the program specified by path in a new process.
6151 [clinic start generated code]*/
6152 
6153 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)6154 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
6155                     PyObject *env, PyObject *file_actions,
6156                     PyObject *setpgroup, int resetids, int setsid,
6157                     PyObject *setsigmask, PyObject *setsigdef,
6158                     PyObject *scheduler)
6159 /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
6160 {
6161     return py_posix_spawn(0, module, path, argv, env, file_actions,
6162                           setpgroup, resetids, setsid, setsigmask, setsigdef,
6163                           scheduler);
6164 }
6165  #endif /* HAVE_POSIX_SPAWN */
6166 
6167 
6168 
6169 #ifdef HAVE_POSIX_SPAWNP
6170 /*[clinic input]
6171 
6172 os.posix_spawnp
6173     path: path_t
6174         Path of executable file.
6175     argv: object
6176         Tuple or list of strings.
6177     env: object
6178         Dictionary of strings mapping to strings.
6179     /
6180     *
6181     file_actions: object(c_default='NULL') = ()
6182         A sequence of file action tuples.
6183     setpgroup: object = NULL
6184         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6185     resetids: bool(accept={int}) = False
6186         If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
6187     setsid: bool(accept={int}) = False
6188         If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6189     setsigmask: object(c_default='NULL') = ()
6190         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6191     setsigdef: object(c_default='NULL') = ()
6192         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6193     scheduler: object = NULL
6194         A tuple with the scheduler policy (optional) and parameters.
6195 
6196 Execute the program specified by path in a new process.
6197 [clinic start generated code]*/
6198 
6199 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)6200 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
6201                      PyObject *env, PyObject *file_actions,
6202                      PyObject *setpgroup, int resetids, int setsid,
6203                      PyObject *setsigmask, PyObject *setsigdef,
6204                      PyObject *scheduler)
6205 /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
6206 {
6207     return py_posix_spawn(1, module, path, argv, env, file_actions,
6208                           setpgroup, resetids, setsid, setsigmask, setsigdef,
6209                           scheduler);
6210 }
6211 #endif /* HAVE_POSIX_SPAWNP */
6212 
6213 #ifdef HAVE_RTPSPAWN
6214 static intptr_t
_rtp_spawn(int mode,const char * rtpFileName,const char * argv[],const char * envp[])6215 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
6216                const char  *envp[])
6217 {
6218      RTP_ID rtpid;
6219      int status;
6220      pid_t res;
6221      int async_err = 0;
6222 
6223      /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
6224         uStackSize=0 cannot be used, the default stack size is too small for
6225         Python. */
6226      if (envp) {
6227          rtpid = rtpSpawn(rtpFileName, argv, envp,
6228                           100, 0x1000000, 0, VX_FP_TASK);
6229      }
6230      else {
6231          rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
6232                           100, 0x1000000, 0, VX_FP_TASK);
6233      }
6234      if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
6235          do {
6236              res = waitpid((pid_t)rtpid, &status, 0);
6237          } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6238 
6239          if (res < 0)
6240              return RTP_ID_ERROR;
6241          return ((intptr_t)status);
6242      }
6243      return ((intptr_t)rtpid);
6244 }
6245 #endif
6246 
6247 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
6248 /*[clinic input]
6249 os.spawnv
6250 
6251     mode: int
6252         Mode of process creation.
6253     path: path_t
6254         Path of executable file.
6255     argv: object
6256         Tuple or list of strings.
6257     /
6258 
6259 Execute the program specified by path in a new process.
6260 [clinic start generated code]*/
6261 
6262 static PyObject *
os_spawnv_impl(PyObject * module,int mode,path_t * path,PyObject * argv)6263 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
6264 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
6265 {
6266     EXECV_CHAR **argvlist;
6267     int i;
6268     Py_ssize_t argc;
6269     intptr_t spawnval;
6270     PyObject *(*getitem)(PyObject *, Py_ssize_t);
6271 
6272     /* spawnv has three arguments: (mode, path, argv), where
6273        argv is a list or tuple of strings. */
6274 
6275     if (PyList_Check(argv)) {
6276         argc = PyList_Size(argv);
6277         getitem = PyList_GetItem;
6278     }
6279     else if (PyTuple_Check(argv)) {
6280         argc = PyTuple_Size(argv);
6281         getitem = PyTuple_GetItem;
6282     }
6283     else {
6284         PyErr_SetString(PyExc_TypeError,
6285                         "spawnv() arg 2 must be a tuple or list");
6286         return NULL;
6287     }
6288     if (argc == 0) {
6289         PyErr_SetString(PyExc_ValueError,
6290             "spawnv() arg 2 cannot be empty");
6291         return NULL;
6292     }
6293 
6294     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6295     if (argvlist == NULL) {
6296         return PyErr_NoMemory();
6297     }
6298     for (i = 0; i < argc; i++) {
6299         if (!fsconvert_strdup((*getitem)(argv, i),
6300                               &argvlist[i])) {
6301             free_string_array(argvlist, i);
6302             PyErr_SetString(
6303                 PyExc_TypeError,
6304                 "spawnv() arg 2 must contain only strings");
6305             return NULL;
6306         }
6307         if (i == 0 && !argvlist[0][0]) {
6308             free_string_array(argvlist, i + 1);
6309             PyErr_SetString(
6310                 PyExc_ValueError,
6311                 "spawnv() arg 2 first element cannot be empty");
6312             return NULL;
6313         }
6314     }
6315     argvlist[argc] = NULL;
6316 
6317 #if !defined(HAVE_RTPSPAWN)
6318     if (mode == _OLD_P_OVERLAY)
6319         mode = _P_OVERLAY;
6320 #endif
6321 
6322     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
6323                     Py_None) < 0) {
6324         free_string_array(argvlist, argc);
6325         return NULL;
6326     }
6327 
6328     Py_BEGIN_ALLOW_THREADS
6329     _Py_BEGIN_SUPPRESS_IPH
6330 #ifdef HAVE_WSPAWNV
6331     spawnval = _wspawnv(mode, path->wide, argvlist);
6332 #elif defined(HAVE_RTPSPAWN)
6333     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
6334 #else
6335     spawnval = _spawnv(mode, path->narrow, argvlist);
6336 #endif
6337     _Py_END_SUPPRESS_IPH
6338     Py_END_ALLOW_THREADS
6339 
6340     free_string_array(argvlist, argc);
6341 
6342     if (spawnval == -1)
6343         return posix_error();
6344     else
6345         return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6346 }
6347 
6348 /*[clinic input]
6349 os.spawnve
6350 
6351     mode: int
6352         Mode of process creation.
6353     path: path_t
6354         Path of executable file.
6355     argv: object
6356         Tuple or list of strings.
6357     env: object
6358         Dictionary of strings mapping to strings.
6359     /
6360 
6361 Execute the program specified by path in a new process.
6362 [clinic start generated code]*/
6363 
6364 static PyObject *
os_spawnve_impl(PyObject * module,int mode,path_t * path,PyObject * argv,PyObject * env)6365 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
6366                 PyObject *env)
6367 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
6368 {
6369     EXECV_CHAR **argvlist;
6370     EXECV_CHAR **envlist;
6371     PyObject *res = NULL;
6372     Py_ssize_t argc, i, envc;
6373     intptr_t spawnval;
6374     PyObject *(*getitem)(PyObject *, Py_ssize_t);
6375     Py_ssize_t lastarg = 0;
6376 
6377     /* spawnve has four arguments: (mode, path, argv, env), where
6378        argv is a list or tuple of strings and env is a dictionary
6379        like posix.environ. */
6380 
6381     if (PyList_Check(argv)) {
6382         argc = PyList_Size(argv);
6383         getitem = PyList_GetItem;
6384     }
6385     else if (PyTuple_Check(argv)) {
6386         argc = PyTuple_Size(argv);
6387         getitem = PyTuple_GetItem;
6388     }
6389     else {
6390         PyErr_SetString(PyExc_TypeError,
6391                         "spawnve() arg 2 must be a tuple or list");
6392         goto fail_0;
6393     }
6394     if (argc == 0) {
6395         PyErr_SetString(PyExc_ValueError,
6396             "spawnve() arg 2 cannot be empty");
6397         goto fail_0;
6398     }
6399     if (!PyMapping_Check(env)) {
6400         PyErr_SetString(PyExc_TypeError,
6401                         "spawnve() arg 3 must be a mapping object");
6402         goto fail_0;
6403     }
6404 
6405     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6406     if (argvlist == NULL) {
6407         PyErr_NoMemory();
6408         goto fail_0;
6409     }
6410     for (i = 0; i < argc; i++) {
6411         if (!fsconvert_strdup((*getitem)(argv, i),
6412                               &argvlist[i]))
6413         {
6414             lastarg = i;
6415             goto fail_1;
6416         }
6417         if (i == 0 && !argvlist[0][0]) {
6418             lastarg = i + 1;
6419             PyErr_SetString(
6420                 PyExc_ValueError,
6421                 "spawnv() arg 2 first element cannot be empty");
6422             goto fail_1;
6423         }
6424     }
6425     lastarg = argc;
6426     argvlist[argc] = NULL;
6427 
6428     envlist = parse_envlist(env, &envc);
6429     if (envlist == NULL)
6430         goto fail_1;
6431 
6432 #if !defined(HAVE_RTPSPAWN)
6433     if (mode == _OLD_P_OVERLAY)
6434         mode = _P_OVERLAY;
6435 #endif
6436 
6437     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6438         goto fail_2;
6439     }
6440 
6441     Py_BEGIN_ALLOW_THREADS
6442     _Py_BEGIN_SUPPRESS_IPH
6443 #ifdef HAVE_WSPAWNV
6444     spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6445 #elif defined(HAVE_RTPSPAWN)
6446     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6447                            (const char **)envlist);
6448 #else
6449     spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6450 #endif
6451     _Py_END_SUPPRESS_IPH
6452     Py_END_ALLOW_THREADS
6453 
6454     if (spawnval == -1)
6455         (void) posix_error();
6456     else
6457         res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6458 
6459   fail_2:
6460     while (--envc >= 0)
6461         PyMem_DEL(envlist[envc]);
6462     PyMem_DEL(envlist);
6463   fail_1:
6464     free_string_array(argvlist, lastarg);
6465   fail_0:
6466     return res;
6467 }
6468 
6469 #endif /* HAVE_SPAWNV */
6470 
6471 
6472 #ifdef HAVE_FORK
6473 
6474 /* Helper function to validate arguments.
6475    Returns 0 on success.  non-zero on failure with a TypeError raised.
6476    If obj is non-NULL it must be callable.  */
6477 static int
check_null_or_callable(PyObject * obj,const char * obj_name)6478 check_null_or_callable(PyObject *obj, const char* obj_name)
6479 {
6480     if (obj && !PyCallable_Check(obj)) {
6481         PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6482                      obj_name, _PyType_Name(Py_TYPE(obj)));
6483         return -1;
6484     }
6485     return 0;
6486 }
6487 
6488 /*[clinic input]
6489 os.register_at_fork
6490 
6491     *
6492     before: object=NULL
6493         A callable to be called in the parent before the fork() syscall.
6494     after_in_child: object=NULL
6495         A callable to be called in the child after fork().
6496     after_in_parent: object=NULL
6497         A callable to be called in the parent after fork().
6498 
6499 Register callables to be called when forking a new process.
6500 
6501 'before' callbacks are called in reverse order.
6502 'after_in_child' and 'after_in_parent' callbacks are called in order.
6503 
6504 [clinic start generated code]*/
6505 
6506 static PyObject *
os_register_at_fork_impl(PyObject * module,PyObject * before,PyObject * after_in_child,PyObject * after_in_parent)6507 os_register_at_fork_impl(PyObject *module, PyObject *before,
6508                          PyObject *after_in_child, PyObject *after_in_parent)
6509 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6510 {
6511     PyInterpreterState *interp;
6512 
6513     if (!before && !after_in_child && !after_in_parent) {
6514         PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6515         return NULL;
6516     }
6517     if (check_null_or_callable(before, "before") ||
6518         check_null_or_callable(after_in_child, "after_in_child") ||
6519         check_null_or_callable(after_in_parent, "after_in_parent")) {
6520         return NULL;
6521     }
6522     interp = _PyInterpreterState_GET();
6523 
6524     if (register_at_forker(&interp->before_forkers, before)) {
6525         return NULL;
6526     }
6527     if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6528         return NULL;
6529     }
6530     if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6531         return NULL;
6532     }
6533     Py_RETURN_NONE;
6534 }
6535 #endif /* HAVE_FORK */
6536 
6537 
6538 #ifdef HAVE_FORK1
6539 /*[clinic input]
6540 os.fork1
6541 
6542 Fork a child process with a single multiplexed (i.e., not bound) thread.
6543 
6544 Return 0 to child process and PID of child to parent process.
6545 [clinic start generated code]*/
6546 
6547 static PyObject *
os_fork1_impl(PyObject * module)6548 os_fork1_impl(PyObject *module)
6549 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6550 {
6551     pid_t pid;
6552 
6553     if (_PyInterpreterState_GET() != PyInterpreterState_Main()) {
6554         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6555         return NULL;
6556     }
6557     PyOS_BeforeFork();
6558     pid = fork1();
6559     if (pid == 0) {
6560         /* child: this clobbers and resets the import lock. */
6561         PyOS_AfterFork_Child();
6562     } else {
6563         /* parent: release the import lock. */
6564         PyOS_AfterFork_Parent();
6565     }
6566     if (pid == -1)
6567         return posix_error();
6568     return PyLong_FromPid(pid);
6569 }
6570 #endif /* HAVE_FORK1 */
6571 
6572 
6573 #ifdef HAVE_FORK
6574 /*[clinic input]
6575 os.fork
6576 
6577 Fork a child process.
6578 
6579 Return 0 to child process and PID of child to parent process.
6580 [clinic start generated code]*/
6581 
6582 static PyObject *
os_fork_impl(PyObject * module)6583 os_fork_impl(PyObject *module)
6584 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6585 {
6586     pid_t pid;
6587     PyInterpreterState *interp = _PyInterpreterState_GET();
6588     if (interp->config._isolated_interpreter) {
6589         PyErr_SetString(PyExc_RuntimeError,
6590                         "fork not supported for isolated subinterpreters");
6591         return NULL;
6592     }
6593     if (PySys_Audit("os.fork", NULL) < 0) {
6594         return NULL;
6595     }
6596     PyOS_BeforeFork();
6597     pid = fork();
6598     if (pid == 0) {
6599         /* child: this clobbers and resets the import lock. */
6600         PyOS_AfterFork_Child();
6601     } else {
6602         /* parent: release the import lock. */
6603         PyOS_AfterFork_Parent();
6604     }
6605     if (pid == -1)
6606         return posix_error();
6607     return PyLong_FromPid(pid);
6608 }
6609 #endif /* HAVE_FORK */
6610 
6611 
6612 #ifdef HAVE_SCHED_H
6613 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6614 /*[clinic input]
6615 os.sched_get_priority_max
6616 
6617     policy: int
6618 
6619 Get the maximum scheduling priority for policy.
6620 [clinic start generated code]*/
6621 
6622 static PyObject *
os_sched_get_priority_max_impl(PyObject * module,int policy)6623 os_sched_get_priority_max_impl(PyObject *module, int policy)
6624 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6625 {
6626     int max;
6627 
6628     max = sched_get_priority_max(policy);
6629     if (max < 0)
6630         return posix_error();
6631     return PyLong_FromLong(max);
6632 }
6633 
6634 
6635 /*[clinic input]
6636 os.sched_get_priority_min
6637 
6638     policy: int
6639 
6640 Get the minimum scheduling priority for policy.
6641 [clinic start generated code]*/
6642 
6643 static PyObject *
os_sched_get_priority_min_impl(PyObject * module,int policy)6644 os_sched_get_priority_min_impl(PyObject *module, int policy)
6645 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6646 {
6647     int min = sched_get_priority_min(policy);
6648     if (min < 0)
6649         return posix_error();
6650     return PyLong_FromLong(min);
6651 }
6652 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6653 
6654 
6655 #ifdef HAVE_SCHED_SETSCHEDULER
6656 /*[clinic input]
6657 os.sched_getscheduler
6658     pid: pid_t
6659     /
6660 
6661 Get the scheduling policy for the process identified by pid.
6662 
6663 Passing 0 for pid returns the scheduling policy for the calling process.
6664 [clinic start generated code]*/
6665 
6666 static PyObject *
os_sched_getscheduler_impl(PyObject * module,pid_t pid)6667 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6668 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
6669 {
6670     int policy;
6671 
6672     policy = sched_getscheduler(pid);
6673     if (policy < 0)
6674         return posix_error();
6675     return PyLong_FromLong(policy);
6676 }
6677 #endif /* HAVE_SCHED_SETSCHEDULER */
6678 
6679 
6680 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6681 /*[clinic input]
6682 class os.sched_param "PyObject *" "SchedParamType"
6683 
6684 @classmethod
6685 os.sched_param.__new__
6686 
6687     sched_priority: object
6688         A scheduling parameter.
6689 
6690 Currently has only one field: sched_priority
6691 [clinic start generated code]*/
6692 
6693 static PyObject *
os_sched_param_impl(PyTypeObject * type,PyObject * sched_priority)6694 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6695 /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
6696 {
6697     PyObject *res;
6698 
6699     res = PyStructSequence_New(type);
6700     if (!res)
6701         return NULL;
6702     Py_INCREF(sched_priority);
6703     PyStructSequence_SET_ITEM(res, 0, sched_priority);
6704     return res;
6705 }
6706 
6707 PyDoc_VAR(os_sched_param__doc__);
6708 
6709 static PyStructSequence_Field sched_param_fields[] = {
6710     {"sched_priority", "the scheduling priority"},
6711     {0}
6712 };
6713 
6714 static PyStructSequence_Desc sched_param_desc = {
6715     "sched_param", /* name */
6716     os_sched_param__doc__, /* doc */
6717     sched_param_fields,
6718     1
6719 };
6720 
6721 static int
convert_sched_param(PyObject * module,PyObject * param,struct sched_param * res)6722 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
6723 {
6724     long priority;
6725 
6726     if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
6727         PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
6728         return 0;
6729     }
6730     priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
6731     if (priority == -1 && PyErr_Occurred())
6732         return 0;
6733     if (priority > INT_MAX || priority < INT_MIN) {
6734         PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
6735         return 0;
6736     }
6737     res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
6738     return 1;
6739 }
6740 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
6741 
6742 
6743 #ifdef HAVE_SCHED_SETSCHEDULER
6744 /*[clinic input]
6745 os.sched_setscheduler
6746 
6747     pid: pid_t
6748     policy: int
6749     param as param_obj: object
6750     /
6751 
6752 Set the scheduling policy for the process identified by pid.
6753 
6754 If pid is 0, the calling process is changed.
6755 param is an instance of sched_param.
6756 [clinic start generated code]*/
6757 
6758 static PyObject *
os_sched_setscheduler_impl(PyObject * module,pid_t pid,int policy,PyObject * param_obj)6759 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
6760                            PyObject *param_obj)
6761 /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
6762 {
6763     struct sched_param param;
6764     if (!convert_sched_param(module, param_obj, &param)) {
6765         return NULL;
6766     }
6767 
6768     /*
6769     ** sched_setscheduler() returns 0 in Linux, but the previous
6770     ** scheduling policy under Solaris/Illumos, and others.
6771     ** On error, -1 is returned in all Operating Systems.
6772     */
6773     if (sched_setscheduler(pid, policy, &param) == -1)
6774         return posix_error();
6775     Py_RETURN_NONE;
6776 }
6777 #endif  /* HAVE_SCHED_SETSCHEDULER*/
6778 
6779 
6780 #ifdef HAVE_SCHED_SETPARAM
6781 /*[clinic input]
6782 os.sched_getparam
6783     pid: pid_t
6784     /
6785 
6786 Returns scheduling parameters for the process identified by pid.
6787 
6788 If pid is 0, returns parameters for the calling process.
6789 Return value is an instance of sched_param.
6790 [clinic start generated code]*/
6791 
6792 static PyObject *
os_sched_getparam_impl(PyObject * module,pid_t pid)6793 os_sched_getparam_impl(PyObject *module, pid_t pid)
6794 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
6795 {
6796     struct sched_param param;
6797     PyObject *result;
6798     PyObject *priority;
6799 
6800     if (sched_getparam(pid, &param))
6801         return posix_error();
6802     PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
6803     result = PyStructSequence_New((PyTypeObject *)SchedParamType);
6804     if (!result)
6805         return NULL;
6806     priority = PyLong_FromLong(param.sched_priority);
6807     if (!priority) {
6808         Py_DECREF(result);
6809         return NULL;
6810     }
6811     PyStructSequence_SET_ITEM(result, 0, priority);
6812     return result;
6813 }
6814 
6815 
6816 /*[clinic input]
6817 os.sched_setparam
6818     pid: pid_t
6819     param as param_obj: object
6820     /
6821 
6822 Set scheduling parameters for the process identified by pid.
6823 
6824 If pid is 0, sets parameters for the calling process.
6825 param should be an instance of sched_param.
6826 [clinic start generated code]*/
6827 
6828 static PyObject *
os_sched_setparam_impl(PyObject * module,pid_t pid,PyObject * param_obj)6829 os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
6830 /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
6831 {
6832     struct sched_param param;
6833     if (!convert_sched_param(module, param_obj, &param)) {
6834         return NULL;
6835     }
6836 
6837     if (sched_setparam(pid, &param))
6838         return posix_error();
6839     Py_RETURN_NONE;
6840 }
6841 #endif /* HAVE_SCHED_SETPARAM */
6842 
6843 
6844 #ifdef HAVE_SCHED_RR_GET_INTERVAL
6845 /*[clinic input]
6846 os.sched_rr_get_interval -> double
6847     pid: pid_t
6848     /
6849 
6850 Return the round-robin quantum for the process identified by pid, in seconds.
6851 
6852 Value returned is a float.
6853 [clinic start generated code]*/
6854 
6855 static double
os_sched_rr_get_interval_impl(PyObject * module,pid_t pid)6856 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
6857 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
6858 {
6859     struct timespec interval;
6860     if (sched_rr_get_interval(pid, &interval)) {
6861         posix_error();
6862         return -1.0;
6863     }
6864 #ifdef _Py_MEMORY_SANITIZER
6865     __msan_unpoison(&interval, sizeof(interval));
6866 #endif
6867     return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
6868 }
6869 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
6870 
6871 
6872 /*[clinic input]
6873 os.sched_yield
6874 
6875 Voluntarily relinquish the CPU.
6876 [clinic start generated code]*/
6877 
6878 static PyObject *
os_sched_yield_impl(PyObject * module)6879 os_sched_yield_impl(PyObject *module)
6880 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
6881 {
6882     if (sched_yield())
6883         return posix_error();
6884     Py_RETURN_NONE;
6885 }
6886 
6887 #ifdef HAVE_SCHED_SETAFFINITY
6888 /* The minimum number of CPUs allocated in a cpu_set_t */
6889 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
6890 
6891 /*[clinic input]
6892 os.sched_setaffinity
6893     pid: pid_t
6894     mask : object
6895     /
6896 
6897 Set the CPU affinity of the process identified by pid to mask.
6898 
6899 mask should be an iterable of integers identifying CPUs.
6900 [clinic start generated code]*/
6901 
6902 static PyObject *
os_sched_setaffinity_impl(PyObject * module,pid_t pid,PyObject * mask)6903 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
6904 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
6905 {
6906     int ncpus;
6907     size_t setsize;
6908     cpu_set_t *cpu_set = NULL;
6909     PyObject *iterator = NULL, *item;
6910 
6911     iterator = PyObject_GetIter(mask);
6912     if (iterator == NULL)
6913         return NULL;
6914 
6915     ncpus = NCPUS_START;
6916     setsize = CPU_ALLOC_SIZE(ncpus);
6917     cpu_set = CPU_ALLOC(ncpus);
6918     if (cpu_set == NULL) {
6919         PyErr_NoMemory();
6920         goto error;
6921     }
6922     CPU_ZERO_S(setsize, cpu_set);
6923 
6924     while ((item = PyIter_Next(iterator))) {
6925         long cpu;
6926         if (!PyLong_Check(item)) {
6927             PyErr_Format(PyExc_TypeError,
6928                         "expected an iterator of ints, "
6929                         "but iterator yielded %R",
6930                         Py_TYPE(item));
6931             Py_DECREF(item);
6932             goto error;
6933         }
6934         cpu = PyLong_AsLong(item);
6935         Py_DECREF(item);
6936         if (cpu < 0) {
6937             if (!PyErr_Occurred())
6938                 PyErr_SetString(PyExc_ValueError, "negative CPU number");
6939             goto error;
6940         }
6941         if (cpu > INT_MAX - 1) {
6942             PyErr_SetString(PyExc_OverflowError, "CPU number too large");
6943             goto error;
6944         }
6945         if (cpu >= ncpus) {
6946             /* Grow CPU mask to fit the CPU number */
6947             int newncpus = ncpus;
6948             cpu_set_t *newmask;
6949             size_t newsetsize;
6950             while (newncpus <= cpu) {
6951                 if (newncpus > INT_MAX / 2)
6952                     newncpus = cpu + 1;
6953                 else
6954                     newncpus = newncpus * 2;
6955             }
6956             newmask = CPU_ALLOC(newncpus);
6957             if (newmask == NULL) {
6958                 PyErr_NoMemory();
6959                 goto error;
6960             }
6961             newsetsize = CPU_ALLOC_SIZE(newncpus);
6962             CPU_ZERO_S(newsetsize, newmask);
6963             memcpy(newmask, cpu_set, setsize);
6964             CPU_FREE(cpu_set);
6965             setsize = newsetsize;
6966             cpu_set = newmask;
6967             ncpus = newncpus;
6968         }
6969         CPU_SET_S(cpu, setsize, cpu_set);
6970     }
6971     if (PyErr_Occurred()) {
6972         goto error;
6973     }
6974     Py_CLEAR(iterator);
6975 
6976     if (sched_setaffinity(pid, setsize, cpu_set)) {
6977         posix_error();
6978         goto error;
6979     }
6980     CPU_FREE(cpu_set);
6981     Py_RETURN_NONE;
6982 
6983 error:
6984     if (cpu_set)
6985         CPU_FREE(cpu_set);
6986     Py_XDECREF(iterator);
6987     return NULL;
6988 }
6989 
6990 
6991 /*[clinic input]
6992 os.sched_getaffinity
6993     pid: pid_t
6994     /
6995 
6996 Return the affinity of the process identified by pid (or the current process if zero).
6997 
6998 The affinity is returned as a set of CPU identifiers.
6999 [clinic start generated code]*/
7000 
7001 static PyObject *
os_sched_getaffinity_impl(PyObject * module,pid_t pid)7002 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
7003 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
7004 {
7005     int cpu, ncpus, count;
7006     size_t setsize;
7007     cpu_set_t *mask = NULL;
7008     PyObject *res = NULL;
7009 
7010     ncpus = NCPUS_START;
7011     while (1) {
7012         setsize = CPU_ALLOC_SIZE(ncpus);
7013         mask = CPU_ALLOC(ncpus);
7014         if (mask == NULL)
7015             return PyErr_NoMemory();
7016         if (sched_getaffinity(pid, setsize, mask) == 0)
7017             break;
7018         CPU_FREE(mask);
7019         if (errno != EINVAL)
7020             return posix_error();
7021         if (ncpus > INT_MAX / 2) {
7022             PyErr_SetString(PyExc_OverflowError, "could not allocate "
7023                             "a large enough CPU set");
7024             return NULL;
7025         }
7026         ncpus = ncpus * 2;
7027     }
7028 
7029     res = PySet_New(NULL);
7030     if (res == NULL)
7031         goto error;
7032     for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7033         if (CPU_ISSET_S(cpu, setsize, mask)) {
7034             PyObject *cpu_num = PyLong_FromLong(cpu);
7035             --count;
7036             if (cpu_num == NULL)
7037                 goto error;
7038             if (PySet_Add(res, cpu_num)) {
7039                 Py_DECREF(cpu_num);
7040                 goto error;
7041             }
7042             Py_DECREF(cpu_num);
7043         }
7044     }
7045     CPU_FREE(mask);
7046     return res;
7047 
7048 error:
7049     if (mask)
7050         CPU_FREE(mask);
7051     Py_XDECREF(res);
7052     return NULL;
7053 }
7054 
7055 #endif /* HAVE_SCHED_SETAFFINITY */
7056 
7057 #endif /* HAVE_SCHED_H */
7058 
7059 
7060 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
7061 /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
7062 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
7063 #define DEV_PTY_FILE "/dev/ptc"
7064 #define HAVE_DEV_PTMX
7065 #else
7066 #define DEV_PTY_FILE "/dev/ptmx"
7067 #endif
7068 
7069 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
7070 #ifdef HAVE_PTY_H
7071 #include <pty.h>
7072 #else
7073 #ifdef HAVE_LIBUTIL_H
7074 #include <libutil.h>
7075 #else
7076 #ifdef HAVE_UTIL_H
7077 #include <util.h>
7078 #endif /* HAVE_UTIL_H */
7079 #endif /* HAVE_LIBUTIL_H */
7080 #endif /* HAVE_PTY_H */
7081 #ifdef HAVE_STROPTS_H
7082 #include <stropts.h>
7083 #endif
7084 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */
7085 
7086 
7087 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7088 /*[clinic input]
7089 os.openpty
7090 
7091 Open a pseudo-terminal.
7092 
7093 Return a tuple of (master_fd, slave_fd) containing open file descriptors
7094 for both the master and slave ends.
7095 [clinic start generated code]*/
7096 
7097 static PyObject *
os_openpty_impl(PyObject * module)7098 os_openpty_impl(PyObject *module)
7099 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
7100 {
7101     int master_fd = -1, slave_fd = -1;
7102 #ifndef HAVE_OPENPTY
7103     char * slave_name;
7104 #endif
7105 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
7106     PyOS_sighandler_t sig_saved;
7107 #if defined(__sun) && defined(__SVR4)
7108     extern char *ptsname(int fildes);
7109 #endif
7110 #endif
7111 
7112 #ifdef HAVE_OPENPTY
7113     if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
7114         goto posix_error;
7115 
7116     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7117         goto error;
7118     if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
7119         goto error;
7120 
7121 #elif defined(HAVE__GETPTY)
7122     slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
7123     if (slave_name == NULL)
7124         goto posix_error;
7125     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7126         goto error;
7127 
7128     slave_fd = _Py_open(slave_name, O_RDWR);
7129     if (slave_fd < 0)
7130         goto error;
7131 
7132 #else
7133     master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
7134     if (master_fd < 0)
7135         goto posix_error;
7136 
7137     sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
7138 
7139     /* change permission of slave */
7140     if (grantpt(master_fd) < 0) {
7141         PyOS_setsig(SIGCHLD, sig_saved);
7142         goto posix_error;
7143     }
7144 
7145     /* unlock slave */
7146     if (unlockpt(master_fd) < 0) {
7147         PyOS_setsig(SIGCHLD, sig_saved);
7148         goto posix_error;
7149     }
7150 
7151     PyOS_setsig(SIGCHLD, sig_saved);
7152 
7153     slave_name = ptsname(master_fd); /* get name of slave */
7154     if (slave_name == NULL)
7155         goto posix_error;
7156 
7157     slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
7158     if (slave_fd == -1)
7159         goto error;
7160 
7161     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7162         goto posix_error;
7163 
7164 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
7165     ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
7166     ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
7167 #ifndef __hpux
7168     ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
7169 #endif /* __hpux */
7170 #endif /* HAVE_CYGWIN */
7171 #endif /* HAVE_OPENPTY */
7172 
7173     return Py_BuildValue("(ii)", master_fd, slave_fd);
7174 
7175 posix_error:
7176     posix_error();
7177 error:
7178     if (master_fd != -1)
7179         close(master_fd);
7180     if (slave_fd != -1)
7181         close(slave_fd);
7182     return NULL;
7183 }
7184 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
7185 
7186 
7187 #ifdef HAVE_FORKPTY
7188 /*[clinic input]
7189 os.forkpty
7190 
7191 Fork a new process with a new pseudo-terminal as controlling tty.
7192 
7193 Returns a tuple of (pid, master_fd).
7194 Like fork(), return pid of 0 to the child process,
7195 and pid of child to the parent process.
7196 To both, return fd of newly opened pseudo-terminal.
7197 [clinic start generated code]*/
7198 
7199 static PyObject *
os_forkpty_impl(PyObject * module)7200 os_forkpty_impl(PyObject *module)
7201 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
7202 {
7203     int master_fd = -1;
7204     pid_t pid;
7205 
7206     if (_PyInterpreterState_GET() != PyInterpreterState_Main()) {
7207         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
7208         return NULL;
7209     }
7210     if (PySys_Audit("os.forkpty", NULL) < 0) {
7211         return NULL;
7212     }
7213     PyOS_BeforeFork();
7214     pid = forkpty(&master_fd, NULL, NULL, NULL);
7215     if (pid == 0) {
7216         /* child: this clobbers and resets the import lock. */
7217         PyOS_AfterFork_Child();
7218     } else {
7219         /* parent: release the import lock. */
7220         PyOS_AfterFork_Parent();
7221     }
7222     if (pid == -1)
7223         return posix_error();
7224     return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
7225 }
7226 #endif /* HAVE_FORKPTY */
7227 
7228 
7229 #ifdef HAVE_GETEGID
7230 /*[clinic input]
7231 os.getegid
7232 
7233 Return the current process's effective group id.
7234 [clinic start generated code]*/
7235 
7236 static PyObject *
os_getegid_impl(PyObject * module)7237 os_getegid_impl(PyObject *module)
7238 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
7239 {
7240     return _PyLong_FromGid(getegid());
7241 }
7242 #endif /* HAVE_GETEGID */
7243 
7244 
7245 #ifdef HAVE_GETEUID
7246 /*[clinic input]
7247 os.geteuid
7248 
7249 Return the current process's effective user id.
7250 [clinic start generated code]*/
7251 
7252 static PyObject *
os_geteuid_impl(PyObject * module)7253 os_geteuid_impl(PyObject *module)
7254 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
7255 {
7256     return _PyLong_FromUid(geteuid());
7257 }
7258 #endif /* HAVE_GETEUID */
7259 
7260 
7261 #ifdef HAVE_GETGID
7262 /*[clinic input]
7263 os.getgid
7264 
7265 Return the current process's group id.
7266 [clinic start generated code]*/
7267 
7268 static PyObject *
os_getgid_impl(PyObject * module)7269 os_getgid_impl(PyObject *module)
7270 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
7271 {
7272     return _PyLong_FromGid(getgid());
7273 }
7274 #endif /* HAVE_GETGID */
7275 
7276 
7277 #ifdef HAVE_GETPID
7278 /*[clinic input]
7279 os.getpid
7280 
7281 Return the current process id.
7282 [clinic start generated code]*/
7283 
7284 static PyObject *
os_getpid_impl(PyObject * module)7285 os_getpid_impl(PyObject *module)
7286 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
7287 {
7288     return PyLong_FromPid(getpid());
7289 }
7290 #endif /* HAVE_GETPID */
7291 
7292 #ifdef NGROUPS_MAX
7293 #define MAX_GROUPS NGROUPS_MAX
7294 #else
7295     /* defined to be 16 on Solaris7, so this should be a small number */
7296 #define MAX_GROUPS 64
7297 #endif
7298 
7299 #ifdef HAVE_GETGROUPLIST
7300 
7301 #ifdef __APPLE__
7302 /*[clinic input]
7303 os.getgrouplist
7304 
7305     user: str
7306         username to lookup
7307     group as basegid: int
7308         base group id of the user
7309     /
7310 
7311 Returns a list of groups to which a user belongs.
7312 [clinic start generated code]*/
7313 
7314 static PyObject *
os_getgrouplist_impl(PyObject * module,const char * user,int basegid)7315 os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
7316 /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
7317 #else
7318 /*[clinic input]
7319 os.getgrouplist
7320 
7321     user: str
7322         username to lookup
7323     group as basegid: gid_t
7324         base group id of the user
7325     /
7326 
7327 Returns a list of groups to which a user belongs.
7328 [clinic start generated code]*/
7329 
7330 static PyObject *
7331 os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
7332 /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
7333 #endif
7334 {
7335     int i, ngroups;
7336     PyObject *list;
7337 #ifdef __APPLE__
7338     int *groups;
7339 #else
7340     gid_t *groups;
7341 #endif
7342 
7343     /*
7344      * NGROUPS_MAX is defined by POSIX.1 as the maximum
7345      * number of supplimental groups a users can belong to.
7346      * We have to increment it by one because
7347      * getgrouplist() returns both the supplemental groups
7348      * and the primary group, i.e. all of the groups the
7349      * user belongs to.
7350      */
7351     ngroups = 1 + MAX_GROUPS;
7352 
7353     while (1) {
7354 #ifdef __APPLE__
7355         groups = PyMem_New(int, ngroups);
7356 #else
7357         groups = PyMem_New(gid_t, ngroups);
7358 #endif
7359         if (groups == NULL) {
7360             return PyErr_NoMemory();
7361         }
7362 
7363         int old_ngroups = ngroups;
7364         if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
7365             /* Success */
7366             break;
7367         }
7368 
7369         /* getgrouplist() fails if the group list is too small */
7370         PyMem_Free(groups);
7371 
7372         if (ngroups > old_ngroups) {
7373             /* If the group list is too small, the glibc implementation of
7374                getgrouplist() sets ngroups to the total number of groups and
7375                returns -1. */
7376         }
7377         else {
7378             /* Double the group list size */
7379             if (ngroups > INT_MAX / 2) {
7380                 return PyErr_NoMemory();
7381             }
7382             ngroups *= 2;
7383         }
7384 
7385         /* Retry getgrouplist() with a larger group list */
7386     }
7387 
7388 #ifdef _Py_MEMORY_SANITIZER
7389     /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
7390     __msan_unpoison(&ngroups, sizeof(ngroups));
7391     __msan_unpoison(groups, ngroups*sizeof(*groups));
7392 #endif
7393 
7394     list = PyList_New(ngroups);
7395     if (list == NULL) {
7396         PyMem_Del(groups);
7397         return NULL;
7398     }
7399 
7400     for (i = 0; i < ngroups; i++) {
7401 #ifdef __APPLE__
7402         PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7403 #else
7404         PyObject *o = _PyLong_FromGid(groups[i]);
7405 #endif
7406         if (o == NULL) {
7407             Py_DECREF(list);
7408             PyMem_Del(groups);
7409             return NULL;
7410         }
7411         PyList_SET_ITEM(list, i, o);
7412     }
7413 
7414     PyMem_Del(groups);
7415 
7416     return list;
7417 }
7418 #endif /* HAVE_GETGROUPLIST */
7419 
7420 
7421 #ifdef HAVE_GETGROUPS
7422 /*[clinic input]
7423 os.getgroups
7424 
7425 Return list of supplemental group IDs for the process.
7426 [clinic start generated code]*/
7427 
7428 static PyObject *
os_getgroups_impl(PyObject * module)7429 os_getgroups_impl(PyObject *module)
7430 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
7431 {
7432     PyObject *result = NULL;
7433     gid_t grouplist[MAX_GROUPS];
7434 
7435     /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
7436      * This is a helper variable to store the intermediate result when
7437      * that happens.
7438      *
7439      * To keep the code readable the OSX behaviour is unconditional,
7440      * according to the POSIX spec this should be safe on all unix-y
7441      * systems.
7442      */
7443     gid_t* alt_grouplist = grouplist;
7444     int n;
7445 
7446 #ifdef __APPLE__
7447     /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if
7448      * there are more groups than can fit in grouplist.  Therefore, on OS X
7449      * always first call getgroups with length 0 to get the actual number
7450      * of groups.
7451      */
7452     n = getgroups(0, NULL);
7453     if (n < 0) {
7454         return posix_error();
7455     } else if (n <= MAX_GROUPS) {
7456         /* groups will fit in existing array */
7457         alt_grouplist = grouplist;
7458     } else {
7459         alt_grouplist = PyMem_New(gid_t, n);
7460         if (alt_grouplist == NULL) {
7461             return PyErr_NoMemory();
7462         }
7463     }
7464 
7465     n = getgroups(n, alt_grouplist);
7466     if (n == -1) {
7467         if (alt_grouplist != grouplist) {
7468             PyMem_Free(alt_grouplist);
7469         }
7470         return posix_error();
7471     }
7472 #else
7473     n = getgroups(MAX_GROUPS, grouplist);
7474     if (n < 0) {
7475         if (errno == EINVAL) {
7476             n = getgroups(0, NULL);
7477             if (n == -1) {
7478                 return posix_error();
7479             }
7480             if (n == 0) {
7481                 /* Avoid malloc(0) */
7482                 alt_grouplist = grouplist;
7483             } else {
7484                 alt_grouplist = PyMem_New(gid_t, n);
7485                 if (alt_grouplist == NULL) {
7486                     return PyErr_NoMemory();
7487                 }
7488                 n = getgroups(n, alt_grouplist);
7489                 if (n == -1) {
7490                     PyMem_Free(alt_grouplist);
7491                     return posix_error();
7492                 }
7493             }
7494         } else {
7495             return posix_error();
7496         }
7497     }
7498 #endif
7499 
7500     result = PyList_New(n);
7501     if (result != NULL) {
7502         int i;
7503         for (i = 0; i < n; ++i) {
7504             PyObject *o = _PyLong_FromGid(alt_grouplist[i]);
7505             if (o == NULL) {
7506                 Py_DECREF(result);
7507                 result = NULL;
7508                 break;
7509             }
7510             PyList_SET_ITEM(result, i, o);
7511         }
7512     }
7513 
7514     if (alt_grouplist != grouplist) {
7515         PyMem_Free(alt_grouplist);
7516     }
7517 
7518     return result;
7519 }
7520 #endif /* HAVE_GETGROUPS */
7521 
7522 #ifdef HAVE_INITGROUPS
7523 #ifdef __APPLE__
7524 /*[clinic input]
7525 os.initgroups
7526 
7527     username as oname: FSConverter
7528     gid: int
7529     /
7530 
7531 Initialize the group access list.
7532 
7533 Call the system initgroups() to initialize the group access list with all of
7534 the groups of which the specified username is a member, plus the specified
7535 group id.
7536 [clinic start generated code]*/
7537 
7538 static PyObject *
os_initgroups_impl(PyObject * module,PyObject * oname,int gid)7539 os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
7540 /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
7541 #else
7542 /*[clinic input]
7543 os.initgroups
7544 
7545     username as oname: FSConverter
7546     gid: gid_t
7547     /
7548 
7549 Initialize the group access list.
7550 
7551 Call the system initgroups() to initialize the group access list with all of
7552 the groups of which the specified username is a member, plus the specified
7553 group id.
7554 [clinic start generated code]*/
7555 
7556 static PyObject *
7557 os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
7558 /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
7559 #endif
7560 {
7561     const char *username = PyBytes_AS_STRING(oname);
7562 
7563     if (initgroups(username, gid) == -1)
7564         return PyErr_SetFromErrno(PyExc_OSError);
7565 
7566     Py_RETURN_NONE;
7567 }
7568 #endif /* HAVE_INITGROUPS */
7569 
7570 
7571 #ifdef HAVE_GETPGID
7572 /*[clinic input]
7573 os.getpgid
7574 
7575     pid: pid_t
7576 
7577 Call the system call getpgid(), and return the result.
7578 [clinic start generated code]*/
7579 
7580 static PyObject *
os_getpgid_impl(PyObject * module,pid_t pid)7581 os_getpgid_impl(PyObject *module, pid_t pid)
7582 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7583 {
7584     pid_t pgid = getpgid(pid);
7585     if (pgid < 0)
7586         return posix_error();
7587     return PyLong_FromPid(pgid);
7588 }
7589 #endif /* HAVE_GETPGID */
7590 
7591 
7592 #ifdef HAVE_GETPGRP
7593 /*[clinic input]
7594 os.getpgrp
7595 
7596 Return the current process group id.
7597 [clinic start generated code]*/
7598 
7599 static PyObject *
os_getpgrp_impl(PyObject * module)7600 os_getpgrp_impl(PyObject *module)
7601 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7602 {
7603 #ifdef GETPGRP_HAVE_ARG
7604     return PyLong_FromPid(getpgrp(0));
7605 #else /* GETPGRP_HAVE_ARG */
7606     return PyLong_FromPid(getpgrp());
7607 #endif /* GETPGRP_HAVE_ARG */
7608 }
7609 #endif /* HAVE_GETPGRP */
7610 
7611 
7612 #ifdef HAVE_SETPGRP
7613 /*[clinic input]
7614 os.setpgrp
7615 
7616 Make the current process the leader of its process group.
7617 [clinic start generated code]*/
7618 
7619 static PyObject *
os_setpgrp_impl(PyObject * module)7620 os_setpgrp_impl(PyObject *module)
7621 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7622 {
7623 #ifdef SETPGRP_HAVE_ARG
7624     if (setpgrp(0, 0) < 0)
7625 #else /* SETPGRP_HAVE_ARG */
7626     if (setpgrp() < 0)
7627 #endif /* SETPGRP_HAVE_ARG */
7628         return posix_error();
7629     Py_RETURN_NONE;
7630 }
7631 #endif /* HAVE_SETPGRP */
7632 
7633 #ifdef HAVE_GETPPID
7634 
7635 #ifdef MS_WINDOWS
7636 #include <tlhelp32.h>
7637 
7638 static PyObject*
win32_getppid()7639 win32_getppid()
7640 {
7641     HANDLE snapshot;
7642     pid_t mypid;
7643     PyObject* result = NULL;
7644     BOOL have_record;
7645     PROCESSENTRY32 pe;
7646 
7647     mypid = getpid(); /* This function never fails */
7648 
7649     snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7650     if (snapshot == INVALID_HANDLE_VALUE)
7651         return PyErr_SetFromWindowsErr(GetLastError());
7652 
7653     pe.dwSize = sizeof(pe);
7654     have_record = Process32First(snapshot, &pe);
7655     while (have_record) {
7656         if (mypid == (pid_t)pe.th32ProcessID) {
7657             /* We could cache the ulong value in a static variable. */
7658             result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7659             break;
7660         }
7661 
7662         have_record = Process32Next(snapshot, &pe);
7663     }
7664 
7665     /* If our loop exits and our pid was not found (result will be NULL)
7666      * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7667      * error anyway, so let's raise it. */
7668     if (!result)
7669         result = PyErr_SetFromWindowsErr(GetLastError());
7670 
7671     CloseHandle(snapshot);
7672 
7673     return result;
7674 }
7675 #endif /*MS_WINDOWS*/
7676 
7677 
7678 /*[clinic input]
7679 os.getppid
7680 
7681 Return the parent's process id.
7682 
7683 If the parent process has already exited, Windows machines will still
7684 return its id; others systems will return the id of the 'init' process (1).
7685 [clinic start generated code]*/
7686 
7687 static PyObject *
os_getppid_impl(PyObject * module)7688 os_getppid_impl(PyObject *module)
7689 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7690 {
7691 #ifdef MS_WINDOWS
7692     return win32_getppid();
7693 #else
7694     return PyLong_FromPid(getppid());
7695 #endif
7696 }
7697 #endif /* HAVE_GETPPID */
7698 
7699 
7700 #ifdef HAVE_GETLOGIN
7701 /*[clinic input]
7702 os.getlogin
7703 
7704 Return the actual login name.
7705 [clinic start generated code]*/
7706 
7707 static PyObject *
os_getlogin_impl(PyObject * module)7708 os_getlogin_impl(PyObject *module)
7709 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7710 {
7711     PyObject *result = NULL;
7712 #ifdef MS_WINDOWS
7713     wchar_t user_name[UNLEN + 1];
7714     DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7715 
7716     if (GetUserNameW(user_name, &num_chars)) {
7717         /* num_chars is the number of unicode chars plus null terminator */
7718         result = PyUnicode_FromWideChar(user_name, num_chars - 1);
7719     }
7720     else
7721         result = PyErr_SetFromWindowsErr(GetLastError());
7722 #else
7723     char *name;
7724     int old_errno = errno;
7725 
7726     errno = 0;
7727     name = getlogin();
7728     if (name == NULL) {
7729         if (errno)
7730             posix_error();
7731         else
7732             PyErr_SetString(PyExc_OSError, "unable to determine login name");
7733     }
7734     else
7735         result = PyUnicode_DecodeFSDefault(name);
7736     errno = old_errno;
7737 #endif
7738     return result;
7739 }
7740 #endif /* HAVE_GETLOGIN */
7741 
7742 
7743 #ifdef HAVE_GETUID
7744 /*[clinic input]
7745 os.getuid
7746 
7747 Return the current process's user id.
7748 [clinic start generated code]*/
7749 
7750 static PyObject *
os_getuid_impl(PyObject * module)7751 os_getuid_impl(PyObject *module)
7752 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7753 {
7754     return _PyLong_FromUid(getuid());
7755 }
7756 #endif /* HAVE_GETUID */
7757 
7758 
7759 #ifdef MS_WINDOWS
7760 #define HAVE_KILL
7761 #endif /* MS_WINDOWS */
7762 
7763 #ifdef HAVE_KILL
7764 /*[clinic input]
7765 os.kill
7766 
7767     pid: pid_t
7768     signal: Py_ssize_t
7769     /
7770 
7771 Kill a process with a signal.
7772 [clinic start generated code]*/
7773 
7774 static PyObject *
os_kill_impl(PyObject * module,pid_t pid,Py_ssize_t signal)7775 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
7776 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
7777 {
7778     if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
7779         return NULL;
7780     }
7781 #ifndef MS_WINDOWS
7782     if (kill(pid, (int)signal) == -1)
7783         return posix_error();
7784     Py_RETURN_NONE;
7785 #else /* !MS_WINDOWS */
7786     PyObject *result;
7787     DWORD sig = (DWORD)signal;
7788     DWORD err;
7789     HANDLE handle;
7790 
7791     /* Console processes which share a common console can be sent CTRL+C or
7792        CTRL+BREAK events, provided they handle said events. */
7793     if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
7794         if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
7795             err = GetLastError();
7796             PyErr_SetFromWindowsErr(err);
7797         }
7798         else
7799             Py_RETURN_NONE;
7800     }
7801 
7802     /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
7803        attempt to open and terminate the process. */
7804     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
7805     if (handle == NULL) {
7806         err = GetLastError();
7807         return PyErr_SetFromWindowsErr(err);
7808     }
7809 
7810     if (TerminateProcess(handle, sig) == 0) {
7811         err = GetLastError();
7812         result = PyErr_SetFromWindowsErr(err);
7813     } else {
7814         Py_INCREF(Py_None);
7815         result = Py_None;
7816     }
7817 
7818     CloseHandle(handle);
7819     return result;
7820 #endif /* !MS_WINDOWS */
7821 }
7822 #endif /* HAVE_KILL */
7823 
7824 
7825 #ifdef HAVE_KILLPG
7826 /*[clinic input]
7827 os.killpg
7828 
7829     pgid: pid_t
7830     signal: int
7831     /
7832 
7833 Kill a process group with a signal.
7834 [clinic start generated code]*/
7835 
7836 static PyObject *
os_killpg_impl(PyObject * module,pid_t pgid,int signal)7837 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
7838 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
7839 {
7840     if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
7841         return NULL;
7842     }
7843     /* XXX some man pages make the `pgid` parameter an int, others
7844        a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
7845        take the same type. Moreover, pid_t is always at least as wide as
7846        int (else compilation of this module fails), which is safe. */
7847     if (killpg(pgid, signal) == -1)
7848         return posix_error();
7849     Py_RETURN_NONE;
7850 }
7851 #endif /* HAVE_KILLPG */
7852 
7853 
7854 #ifdef HAVE_PLOCK
7855 #ifdef HAVE_SYS_LOCK_H
7856 #include <sys/lock.h>
7857 #endif
7858 
7859 /*[clinic input]
7860 os.plock
7861     op: int
7862     /
7863 
7864 Lock program segments into memory.");
7865 [clinic start generated code]*/
7866 
7867 static PyObject *
os_plock_impl(PyObject * module,int op)7868 os_plock_impl(PyObject *module, int op)
7869 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
7870 {
7871     if (plock(op) == -1)
7872         return posix_error();
7873     Py_RETURN_NONE;
7874 }
7875 #endif /* HAVE_PLOCK */
7876 
7877 
7878 #ifdef HAVE_SETUID
7879 /*[clinic input]
7880 os.setuid
7881 
7882     uid: uid_t
7883     /
7884 
7885 Set the current process's user id.
7886 [clinic start generated code]*/
7887 
7888 static PyObject *
os_setuid_impl(PyObject * module,uid_t uid)7889 os_setuid_impl(PyObject *module, uid_t uid)
7890 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
7891 {
7892     if (setuid(uid) < 0)
7893         return posix_error();
7894     Py_RETURN_NONE;
7895 }
7896 #endif /* HAVE_SETUID */
7897 
7898 
7899 #ifdef HAVE_SETEUID
7900 /*[clinic input]
7901 os.seteuid
7902 
7903     euid: uid_t
7904     /
7905 
7906 Set the current process's effective user id.
7907 [clinic start generated code]*/
7908 
7909 static PyObject *
os_seteuid_impl(PyObject * module,uid_t euid)7910 os_seteuid_impl(PyObject *module, uid_t euid)
7911 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
7912 {
7913     if (seteuid(euid) < 0)
7914         return posix_error();
7915     Py_RETURN_NONE;
7916 }
7917 #endif /* HAVE_SETEUID */
7918 
7919 
7920 #ifdef HAVE_SETEGID
7921 /*[clinic input]
7922 os.setegid
7923 
7924     egid: gid_t
7925     /
7926 
7927 Set the current process's effective group id.
7928 [clinic start generated code]*/
7929 
7930 static PyObject *
os_setegid_impl(PyObject * module,gid_t egid)7931 os_setegid_impl(PyObject *module, gid_t egid)
7932 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
7933 {
7934     if (setegid(egid) < 0)
7935         return posix_error();
7936     Py_RETURN_NONE;
7937 }
7938 #endif /* HAVE_SETEGID */
7939 
7940 
7941 #ifdef HAVE_SETREUID
7942 /*[clinic input]
7943 os.setreuid
7944 
7945     ruid: uid_t
7946     euid: uid_t
7947     /
7948 
7949 Set the current process's real and effective user ids.
7950 [clinic start generated code]*/
7951 
7952 static PyObject *
os_setreuid_impl(PyObject * module,uid_t ruid,uid_t euid)7953 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
7954 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
7955 {
7956     if (setreuid(ruid, euid) < 0) {
7957         return posix_error();
7958     } else {
7959         Py_RETURN_NONE;
7960     }
7961 }
7962 #endif /* HAVE_SETREUID */
7963 
7964 
7965 #ifdef HAVE_SETREGID
7966 /*[clinic input]
7967 os.setregid
7968 
7969     rgid: gid_t
7970     egid: gid_t
7971     /
7972 
7973 Set the current process's real and effective group ids.
7974 [clinic start generated code]*/
7975 
7976 static PyObject *
os_setregid_impl(PyObject * module,gid_t rgid,gid_t egid)7977 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
7978 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
7979 {
7980     if (setregid(rgid, egid) < 0)
7981         return posix_error();
7982     Py_RETURN_NONE;
7983 }
7984 #endif /* HAVE_SETREGID */
7985 
7986 
7987 #ifdef HAVE_SETGID
7988 /*[clinic input]
7989 os.setgid
7990     gid: gid_t
7991     /
7992 
7993 Set the current process's group id.
7994 [clinic start generated code]*/
7995 
7996 static PyObject *
os_setgid_impl(PyObject * module,gid_t gid)7997 os_setgid_impl(PyObject *module, gid_t gid)
7998 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
7999 {
8000     if (setgid(gid) < 0)
8001         return posix_error();
8002     Py_RETURN_NONE;
8003 }
8004 #endif /* HAVE_SETGID */
8005 
8006 
8007 #ifdef HAVE_SETGROUPS
8008 /*[clinic input]
8009 os.setgroups
8010 
8011     groups: object
8012     /
8013 
8014 Set the groups of the current process to list.
8015 [clinic start generated code]*/
8016 
8017 static PyObject *
os_setgroups(PyObject * module,PyObject * groups)8018 os_setgroups(PyObject *module, PyObject *groups)
8019 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
8020 {
8021     Py_ssize_t i, len;
8022     gid_t grouplist[MAX_GROUPS];
8023 
8024     if (!PySequence_Check(groups)) {
8025         PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
8026         return NULL;
8027     }
8028     len = PySequence_Size(groups);
8029     if (len < 0) {
8030         return NULL;
8031     }
8032     if (len > MAX_GROUPS) {
8033         PyErr_SetString(PyExc_ValueError, "too many groups");
8034         return NULL;
8035     }
8036     for(i = 0; i < len; i++) {
8037         PyObject *elem;
8038         elem = PySequence_GetItem(groups, i);
8039         if (!elem)
8040             return NULL;
8041         if (!PyLong_Check(elem)) {
8042             PyErr_SetString(PyExc_TypeError,
8043                             "groups must be integers");
8044             Py_DECREF(elem);
8045             return NULL;
8046         } else {
8047             if (!_Py_Gid_Converter(elem, &grouplist[i])) {
8048                 Py_DECREF(elem);
8049                 return NULL;
8050             }
8051         }
8052         Py_DECREF(elem);
8053     }
8054 
8055     if (setgroups(len, grouplist) < 0)
8056         return posix_error();
8057     Py_RETURN_NONE;
8058 }
8059 #endif /* HAVE_SETGROUPS */
8060 
8061 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
8062 static PyObject *
wait_helper(PyObject * module,pid_t pid,int status,struct rusage * ru)8063 wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
8064 {
8065     PyObject *result;
8066     PyObject *struct_rusage;
8067 
8068     if (pid == -1)
8069         return posix_error();
8070 
8071     // If wait succeeded but no child was ready to report status, ru will not
8072     // have been populated.
8073     if (pid == 0) {
8074         memset(ru, 0, sizeof(*ru));
8075     }
8076 
8077     PyObject *m = PyImport_ImportModuleNoBlock("resource");
8078     if (m == NULL)
8079         return NULL;
8080     struct_rusage = PyObject_GetAttr(m, get_posix_state(module)->struct_rusage);
8081     Py_DECREF(m);
8082     if (struct_rusage == NULL)
8083         return NULL;
8084 
8085     /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
8086     result = PyStructSequence_New((PyTypeObject*) struct_rusage);
8087     Py_DECREF(struct_rusage);
8088     if (!result)
8089         return NULL;
8090 
8091 #ifndef doubletime
8092 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
8093 #endif
8094 
8095     PyStructSequence_SET_ITEM(result, 0,
8096                               PyFloat_FromDouble(doubletime(ru->ru_utime)));
8097     PyStructSequence_SET_ITEM(result, 1,
8098                               PyFloat_FromDouble(doubletime(ru->ru_stime)));
8099 #define SET_INT(result, index, value)\
8100         PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
8101     SET_INT(result, 2, ru->ru_maxrss);
8102     SET_INT(result, 3, ru->ru_ixrss);
8103     SET_INT(result, 4, ru->ru_idrss);
8104     SET_INT(result, 5, ru->ru_isrss);
8105     SET_INT(result, 6, ru->ru_minflt);
8106     SET_INT(result, 7, ru->ru_majflt);
8107     SET_INT(result, 8, ru->ru_nswap);
8108     SET_INT(result, 9, ru->ru_inblock);
8109     SET_INT(result, 10, ru->ru_oublock);
8110     SET_INT(result, 11, ru->ru_msgsnd);
8111     SET_INT(result, 12, ru->ru_msgrcv);
8112     SET_INT(result, 13, ru->ru_nsignals);
8113     SET_INT(result, 14, ru->ru_nvcsw);
8114     SET_INT(result, 15, ru->ru_nivcsw);
8115 #undef SET_INT
8116 
8117     if (PyErr_Occurred()) {
8118         Py_DECREF(result);
8119         return NULL;
8120     }
8121 
8122     return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
8123 }
8124 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
8125 
8126 
8127 #ifdef HAVE_WAIT3
8128 /*[clinic input]
8129 os.wait3
8130 
8131     options: int
8132 Wait for completion of a child process.
8133 
8134 Returns a tuple of information about the child process:
8135   (pid, status, rusage)
8136 [clinic start generated code]*/
8137 
8138 static PyObject *
os_wait3_impl(PyObject * module,int options)8139 os_wait3_impl(PyObject *module, int options)
8140 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
8141 {
8142     pid_t pid;
8143     struct rusage ru;
8144     int async_err = 0;
8145     WAIT_TYPE status;
8146     WAIT_STATUS_INT(status) = 0;
8147 
8148     do {
8149         Py_BEGIN_ALLOW_THREADS
8150         pid = wait3(&status, options, &ru);
8151         Py_END_ALLOW_THREADS
8152     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8153     if (pid < 0)
8154         return (!async_err) ? posix_error() : NULL;
8155 
8156     return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
8157 }
8158 #endif /* HAVE_WAIT3 */
8159 
8160 
8161 #ifdef HAVE_WAIT4
8162 /*[clinic input]
8163 
8164 os.wait4
8165 
8166     pid: pid_t
8167     options: int
8168 
8169 Wait for completion of a specific child process.
8170 
8171 Returns a tuple of information about the child process:
8172   (pid, status, rusage)
8173 [clinic start generated code]*/
8174 
8175 static PyObject *
os_wait4_impl(PyObject * module,pid_t pid,int options)8176 os_wait4_impl(PyObject *module, pid_t pid, int options)
8177 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
8178 {
8179     pid_t res;
8180     struct rusage ru;
8181     int async_err = 0;
8182     WAIT_TYPE status;
8183     WAIT_STATUS_INT(status) = 0;
8184 
8185     do {
8186         Py_BEGIN_ALLOW_THREADS
8187         res = wait4(pid, &status, options, &ru);
8188         Py_END_ALLOW_THREADS
8189     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8190     if (res < 0)
8191         return (!async_err) ? posix_error() : NULL;
8192 
8193     return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
8194 }
8195 #endif /* HAVE_WAIT4 */
8196 
8197 
8198 #if defined(HAVE_WAITID) && !defined(__APPLE__)
8199 /*[clinic input]
8200 os.waitid
8201 
8202     idtype: idtype_t
8203         Must be one of be P_PID, P_PGID or P_ALL.
8204     id: id_t
8205         The id to wait on.
8206     options: int
8207         Constructed from the ORing of one or more of WEXITED, WSTOPPED
8208         or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
8209     /
8210 
8211 Returns the result of waiting for a process or processes.
8212 
8213 Returns either waitid_result or None if WNOHANG is specified and there are
8214 no children in a waitable state.
8215 [clinic start generated code]*/
8216 
8217 static PyObject *
os_waitid_impl(PyObject * module,idtype_t idtype,id_t id,int options)8218 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
8219 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
8220 {
8221     PyObject *result;
8222     int res;
8223     int async_err = 0;
8224     siginfo_t si;
8225     si.si_pid = 0;
8226 
8227     do {
8228         Py_BEGIN_ALLOW_THREADS
8229         res = waitid(idtype, id, &si, options);
8230         Py_END_ALLOW_THREADS
8231     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8232     if (res < 0)
8233         return (!async_err) ? posix_error() : NULL;
8234 
8235     if (si.si_pid == 0)
8236         Py_RETURN_NONE;
8237 
8238     PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
8239     result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
8240     if (!result)
8241         return NULL;
8242 
8243     PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
8244     PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
8245     PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
8246     PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
8247     PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
8248     if (PyErr_Occurred()) {
8249         Py_DECREF(result);
8250         return NULL;
8251     }
8252 
8253     return result;
8254 }
8255 #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
8256 
8257 
8258 #if defined(HAVE_WAITPID)
8259 /*[clinic input]
8260 os.waitpid
8261     pid: pid_t
8262     options: int
8263     /
8264 
8265 Wait for completion of a given child process.
8266 
8267 Returns a tuple of information regarding the child process:
8268     (pid, status)
8269 
8270 The options argument is ignored on Windows.
8271 [clinic start generated code]*/
8272 
8273 static PyObject *
os_waitpid_impl(PyObject * module,pid_t pid,int options)8274 os_waitpid_impl(PyObject *module, pid_t pid, int options)
8275 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
8276 {
8277     pid_t res;
8278     int async_err = 0;
8279     WAIT_TYPE status;
8280     WAIT_STATUS_INT(status) = 0;
8281 
8282     do {
8283         Py_BEGIN_ALLOW_THREADS
8284         res = waitpid(pid, &status, options);
8285         Py_END_ALLOW_THREADS
8286     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8287     if (res < 0)
8288         return (!async_err) ? posix_error() : NULL;
8289 
8290     return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
8291 }
8292 #elif defined(HAVE_CWAIT)
8293 /* MS C has a variant of waitpid() that's usable for most purposes. */
8294 /*[clinic input]
8295 os.waitpid
8296     pid: intptr_t
8297     options: int
8298     /
8299 
8300 Wait for completion of a given process.
8301 
8302 Returns a tuple of information regarding the process:
8303     (pid, status << 8)
8304 
8305 The options argument is ignored on Windows.
8306 [clinic start generated code]*/
8307 
8308 static PyObject *
os_waitpid_impl(PyObject * module,intptr_t pid,int options)8309 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
8310 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
8311 {
8312     int status;
8313     intptr_t res;
8314     int async_err = 0;
8315 
8316     do {
8317         Py_BEGIN_ALLOW_THREADS
8318         _Py_BEGIN_SUPPRESS_IPH
8319         res = _cwait(&status, pid, options);
8320         _Py_END_SUPPRESS_IPH
8321         Py_END_ALLOW_THREADS
8322     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8323     if (res < 0)
8324         return (!async_err) ? posix_error() : NULL;
8325 
8326     unsigned long long ustatus = (unsigned int)status;
8327 
8328     /* shift the status left a byte so this is more like the POSIX waitpid */
8329     return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
8330 }
8331 #endif
8332 
8333 
8334 #ifdef HAVE_WAIT
8335 /*[clinic input]
8336 os.wait
8337 
8338 Wait for completion of a child process.
8339 
8340 Returns a tuple of information about the child process:
8341     (pid, status)
8342 [clinic start generated code]*/
8343 
8344 static PyObject *
os_wait_impl(PyObject * module)8345 os_wait_impl(PyObject *module)
8346 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
8347 {
8348     pid_t pid;
8349     int async_err = 0;
8350     WAIT_TYPE status;
8351     WAIT_STATUS_INT(status) = 0;
8352 
8353     do {
8354         Py_BEGIN_ALLOW_THREADS
8355         pid = wait(&status);
8356         Py_END_ALLOW_THREADS
8357     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8358     if (pid < 0)
8359         return (!async_err) ? posix_error() : NULL;
8360 
8361     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
8362 }
8363 #endif /* HAVE_WAIT */
8364 
8365 #if defined(__linux__) && defined(__NR_pidfd_open)
8366 /*[clinic input]
8367 os.pidfd_open
8368   pid: pid_t
8369   flags: unsigned_int = 0
8370 
8371 Return a file descriptor referring to the process *pid*.
8372 
8373 The descriptor can be used to perform process management without races and
8374 signals.
8375 [clinic start generated code]*/
8376 
8377 static PyObject *
os_pidfd_open_impl(PyObject * module,pid_t pid,unsigned int flags)8378 os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
8379 /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
8380 {
8381     int fd = syscall(__NR_pidfd_open, pid, flags);
8382     if (fd < 0) {
8383         return posix_error();
8384     }
8385     return PyLong_FromLong(fd);
8386 }
8387 #endif
8388 
8389 
8390 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
8391 /*[clinic input]
8392 os.readlink
8393 
8394     path: path_t
8395     *
8396     dir_fd: dir_fd(requires='readlinkat') = None
8397 
8398 Return a string representing the path to which the symbolic link points.
8399 
8400 If dir_fd is not None, it should be a file descriptor open to a directory,
8401 and path should be relative; path will then be relative to that directory.
8402 
8403 dir_fd may not be implemented on your platform.  If it is unavailable,
8404 using it will raise a NotImplementedError.
8405 [clinic start generated code]*/
8406 
8407 static PyObject *
os_readlink_impl(PyObject * module,path_t * path,int dir_fd)8408 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
8409 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
8410 {
8411 #if defined(HAVE_READLINK)
8412     char buffer[MAXPATHLEN+1];
8413     ssize_t length;
8414 #ifdef HAVE_READLINKAT
8415     int readlinkat_unavailable = 0;
8416 #endif
8417 
8418     Py_BEGIN_ALLOW_THREADS
8419 #ifdef HAVE_READLINKAT
8420     if (dir_fd != DEFAULT_DIR_FD) {
8421         if (HAVE_READLINKAT_RUNTIME) {
8422             length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
8423         } else {
8424             readlinkat_unavailable = 1;
8425         }
8426     } else
8427 #endif
8428         length = readlink(path->narrow, buffer, MAXPATHLEN);
8429     Py_END_ALLOW_THREADS
8430 
8431 #ifdef HAVE_READLINKAT
8432     if (readlinkat_unavailable) {
8433         argument_unavailable_error(NULL, "dir_fd");
8434         return NULL;
8435     }
8436 #endif
8437 
8438     if (length < 0) {
8439         return path_error(path);
8440     }
8441     buffer[length] = '\0';
8442 
8443     if (PyUnicode_Check(path->object))
8444         return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
8445     else
8446         return PyBytes_FromStringAndSize(buffer, length);
8447 #elif defined(MS_WINDOWS)
8448     DWORD n_bytes_returned;
8449     DWORD io_result = 0;
8450     HANDLE reparse_point_handle;
8451     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
8452     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
8453     PyObject *result = NULL;
8454 
8455     /* First get a handle to the reparse point */
8456     Py_BEGIN_ALLOW_THREADS
8457     reparse_point_handle = CreateFileW(
8458         path->wide,
8459         0,
8460         0,
8461         0,
8462         OPEN_EXISTING,
8463         FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
8464         0);
8465     if (reparse_point_handle != INVALID_HANDLE_VALUE) {
8466         /* New call DeviceIoControl to read the reparse point */
8467         io_result = DeviceIoControl(
8468             reparse_point_handle,
8469             FSCTL_GET_REPARSE_POINT,
8470             0, 0, /* in buffer */
8471             target_buffer, sizeof(target_buffer),
8472             &n_bytes_returned,
8473             0 /* we're not using OVERLAPPED_IO */
8474             );
8475         CloseHandle(reparse_point_handle);
8476     }
8477     Py_END_ALLOW_THREADS
8478 
8479     if (io_result == 0) {
8480         return path_error(path);
8481     }
8482 
8483     wchar_t *name = NULL;
8484     Py_ssize_t nameLen = 0;
8485     if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
8486     {
8487         name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
8488                            rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
8489         nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8490     }
8491     else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
8492     {
8493         name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8494                            rdb->MountPointReparseBuffer.SubstituteNameOffset);
8495         nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8496     }
8497     else
8498     {
8499         PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8500     }
8501     if (name) {
8502         if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8503             /* Our buffer is mutable, so this is okay */
8504             name[1] = L'\\';
8505         }
8506         result = PyUnicode_FromWideChar(name, nameLen);
8507         if (result && path->narrow) {
8508             Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8509         }
8510     }
8511     return result;
8512 #endif
8513 }
8514 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8515 
8516 #if defined(MS_WINDOWS)
8517 
8518 /* Remove the last portion of the path - return 0 on success */
8519 static int
_dirnameW(WCHAR * path)8520 _dirnameW(WCHAR *path)
8521 {
8522     WCHAR *ptr;
8523     size_t length = wcsnlen_s(path, MAX_PATH);
8524     if (length == MAX_PATH) {
8525         return -1;
8526     }
8527 
8528     /* walk the path from the end until a backslash is encountered */
8529     for(ptr = path + length; ptr != path; ptr--) {
8530         if (*ptr == L'\\' || *ptr == L'/') {
8531             break;
8532         }
8533     }
8534     *ptr = 0;
8535     return 0;
8536 }
8537 
8538 #endif
8539 
8540 #ifdef HAVE_SYMLINK
8541 
8542 #if defined(MS_WINDOWS)
8543 
8544 /* Is this path absolute? */
8545 static int
_is_absW(const WCHAR * path)8546 _is_absW(const WCHAR *path)
8547 {
8548     return path[0] == L'\\' || path[0] == L'/' ||
8549         (path[0] && path[1] == L':');
8550 }
8551 
8552 /* join root and rest with a backslash - return 0 on success */
8553 static int
_joinW(WCHAR * dest_path,const WCHAR * root,const WCHAR * rest)8554 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8555 {
8556     if (_is_absW(rest)) {
8557         return wcscpy_s(dest_path, MAX_PATH, rest);
8558     }
8559 
8560     if (wcscpy_s(dest_path, MAX_PATH, root)) {
8561         return -1;
8562     }
8563 
8564     if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8565         return -1;
8566     }
8567 
8568     return wcscat_s(dest_path, MAX_PATH, rest);
8569 }
8570 
8571 /* Return True if the path at src relative to dest is a directory */
8572 static int
_check_dirW(LPCWSTR src,LPCWSTR dest)8573 _check_dirW(LPCWSTR src, LPCWSTR dest)
8574 {
8575     WIN32_FILE_ATTRIBUTE_DATA src_info;
8576     WCHAR dest_parent[MAX_PATH];
8577     WCHAR src_resolved[MAX_PATH] = L"";
8578 
8579     /* dest_parent = os.path.dirname(dest) */
8580     if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8581         _dirnameW(dest_parent)) {
8582         return 0;
8583     }
8584     /* src_resolved = os.path.join(dest_parent, src) */
8585     if (_joinW(src_resolved, dest_parent, src)) {
8586         return 0;
8587     }
8588     return (
8589         GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8590         && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8591     );
8592 }
8593 #endif
8594 
8595 
8596 /*[clinic input]
8597 os.symlink
8598     src: path_t
8599     dst: path_t
8600     target_is_directory: bool = False
8601     *
8602     dir_fd: dir_fd(requires='symlinkat')=None
8603 
8604 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8605 
8606 Create a symbolic link pointing to src named dst.
8607 
8608 target_is_directory is required on Windows if the target is to be
8609   interpreted as a directory.  (On Windows, symlink requires
8610   Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8611   target_is_directory is ignored on non-Windows platforms.
8612 
8613 If dir_fd is not None, it should be a file descriptor open to a directory,
8614   and path should be relative; path will then be relative to that directory.
8615 dir_fd may not be implemented on your platform.
8616   If it is unavailable, using it will raise a NotImplementedError.
8617 
8618 [clinic start generated code]*/
8619 
8620 static PyObject *
os_symlink_impl(PyObject * module,path_t * src,path_t * dst,int target_is_directory,int dir_fd)8621 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8622                 int target_is_directory, int dir_fd)
8623 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8624 {
8625 #ifdef MS_WINDOWS
8626     DWORD result;
8627     DWORD flags = 0;
8628 
8629     /* Assumed true, set to false if detected to not be available. */
8630     static int windows_has_symlink_unprivileged_flag = TRUE;
8631 #else
8632     int result;
8633 #ifdef HAVE_SYMLINKAT
8634     int symlinkat_unavailable = 0;
8635 #endif
8636 #endif
8637 
8638     if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8639                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8640         return NULL;
8641     }
8642 
8643 #ifdef MS_WINDOWS
8644 
8645     if (windows_has_symlink_unprivileged_flag) {
8646         /* Allow non-admin symlinks if system allows it. */
8647         flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8648     }
8649 
8650     Py_BEGIN_ALLOW_THREADS
8651     _Py_BEGIN_SUPPRESS_IPH
8652     /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8653     if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8654         flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8655     }
8656 
8657     result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8658     _Py_END_SUPPRESS_IPH
8659     Py_END_ALLOW_THREADS
8660 
8661     if (windows_has_symlink_unprivileged_flag && !result &&
8662         ERROR_INVALID_PARAMETER == GetLastError()) {
8663 
8664         Py_BEGIN_ALLOW_THREADS
8665         _Py_BEGIN_SUPPRESS_IPH
8666         /* This error might be caused by
8667         SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8668         Try again, and update windows_has_symlink_unprivileged_flag if we
8669         are successful this time.
8670 
8671         NOTE: There is a risk of a race condition here if there are other
8672         conditions than the flag causing ERROR_INVALID_PARAMETER, and
8673         another process (or thread) changes that condition in between our
8674         calls to CreateSymbolicLink.
8675         */
8676         flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8677         result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8678         _Py_END_SUPPRESS_IPH
8679         Py_END_ALLOW_THREADS
8680 
8681         if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8682             windows_has_symlink_unprivileged_flag = FALSE;
8683         }
8684     }
8685 
8686     if (!result)
8687         return path_error2(src, dst);
8688 
8689 #else
8690 
8691     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8692         PyErr_SetString(PyExc_ValueError,
8693             "symlink: src and dst must be the same type");
8694         return NULL;
8695     }
8696 
8697     Py_BEGIN_ALLOW_THREADS
8698 #ifdef HAVE_SYMLINKAT
8699     if (dir_fd != DEFAULT_DIR_FD) {
8700         if (HAVE_SYMLINKAT_RUNTIME) {
8701             result = symlinkat(src->narrow, dir_fd, dst->narrow);
8702         } else {
8703             symlinkat_unavailable = 1;
8704         }
8705     } else
8706 #endif
8707         result = symlink(src->narrow, dst->narrow);
8708     Py_END_ALLOW_THREADS
8709 
8710 #ifdef HAVE_SYMLINKAT
8711     if (symlinkat_unavailable) {
8712           argument_unavailable_error(NULL, "dir_fd");
8713           return NULL;
8714     }
8715 #endif
8716 
8717     if (result)
8718         return path_error2(src, dst);
8719 #endif
8720 
8721     Py_RETURN_NONE;
8722 }
8723 #endif /* HAVE_SYMLINK */
8724 
8725 
8726 
8727 
8728 static PyStructSequence_Field times_result_fields[] = {
8729     {"user",    "user time"},
8730     {"system",   "system time"},
8731     {"children_user",    "user time of children"},
8732     {"children_system",    "system time of children"},
8733     {"elapsed",    "elapsed time since an arbitrary point in the past"},
8734     {NULL}
8735 };
8736 
8737 PyDoc_STRVAR(times_result__doc__,
8738 "times_result: Result from os.times().\n\n\
8739 This object may be accessed either as a tuple of\n\
8740   (user, system, children_user, children_system, elapsed),\n\
8741 or via the attributes user, system, children_user, children_system,\n\
8742 and elapsed.\n\
8743 \n\
8744 See os.times for more information.");
8745 
8746 static PyStructSequence_Desc times_result_desc = {
8747     "times_result", /* name */
8748     times_result__doc__, /* doc */
8749     times_result_fields,
8750     5
8751 };
8752 
8753 #ifdef MS_WINDOWS
8754 #define HAVE_TIMES  /* mandatory, for the method table */
8755 #endif
8756 
8757 #ifdef HAVE_TIMES
8758 
8759 static PyObject *
build_times_result(PyObject * module,double user,double system,double children_user,double children_system,double elapsed)8760 build_times_result(PyObject *module, double user, double system,
8761     double children_user, double children_system,
8762     double elapsed)
8763 {
8764     PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
8765     PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
8766     if (value == NULL)
8767         return NULL;
8768 
8769 #define SET(i, field) \
8770     { \
8771     PyObject *o = PyFloat_FromDouble(field); \
8772     if (!o) { \
8773         Py_DECREF(value); \
8774         return NULL; \
8775     } \
8776     PyStructSequence_SET_ITEM(value, i, o); \
8777     } \
8778 
8779     SET(0, user);
8780     SET(1, system);
8781     SET(2, children_user);
8782     SET(3, children_system);
8783     SET(4, elapsed);
8784 
8785 #undef SET
8786 
8787     return value;
8788 }
8789 
8790 
8791 #ifndef MS_WINDOWS
8792 #define NEED_TICKS_PER_SECOND
8793 static long ticks_per_second = -1;
8794 #endif /* MS_WINDOWS */
8795 
8796 /*[clinic input]
8797 os.times
8798 
8799 Return a collection containing process timing information.
8800 
8801 The object returned behaves like a named tuple with these fields:
8802   (utime, stime, cutime, cstime, elapsed_time)
8803 All fields are floating point numbers.
8804 [clinic start generated code]*/
8805 
8806 static PyObject *
os_times_impl(PyObject * module)8807 os_times_impl(PyObject *module)
8808 /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
8809 #ifdef MS_WINDOWS
8810 {
8811     FILETIME create, exit, kernel, user;
8812     HANDLE hProc;
8813     hProc = GetCurrentProcess();
8814     GetProcessTimes(hProc, &create, &exit, &kernel, &user);
8815     /* The fields of a FILETIME structure are the hi and lo part
8816        of a 64-bit value expressed in 100 nanosecond units.
8817        1e7 is one second in such units; 1e-7 the inverse.
8818        429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
8819     */
8820     return build_times_result(module,
8821         (double)(user.dwHighDateTime*429.4967296 +
8822                  user.dwLowDateTime*1e-7),
8823         (double)(kernel.dwHighDateTime*429.4967296 +
8824                  kernel.dwLowDateTime*1e-7),
8825         (double)0,
8826         (double)0,
8827         (double)0);
8828 }
8829 #else /* MS_WINDOWS */
8830 {
8831 
8832 
8833     struct tms t;
8834     clock_t c;
8835     errno = 0;
8836     c = times(&t);
8837     if (c == (clock_t) -1)
8838         return posix_error();
8839     return build_times_result(module,
8840                          (double)t.tms_utime / ticks_per_second,
8841                          (double)t.tms_stime / ticks_per_second,
8842                          (double)t.tms_cutime / ticks_per_second,
8843                          (double)t.tms_cstime / ticks_per_second,
8844                          (double)c / ticks_per_second);
8845 }
8846 #endif /* MS_WINDOWS */
8847 #endif /* HAVE_TIMES */
8848 
8849 
8850 #ifdef HAVE_GETSID
8851 /*[clinic input]
8852 os.getsid
8853 
8854     pid: pid_t
8855     /
8856 
8857 Call the system call getsid(pid) and return the result.
8858 [clinic start generated code]*/
8859 
8860 static PyObject *
os_getsid_impl(PyObject * module,pid_t pid)8861 os_getsid_impl(PyObject *module, pid_t pid)
8862 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
8863 {
8864     int sid;
8865     sid = getsid(pid);
8866     if (sid < 0)
8867         return posix_error();
8868     return PyLong_FromLong((long)sid);
8869 }
8870 #endif /* HAVE_GETSID */
8871 
8872 
8873 #ifdef HAVE_SETSID
8874 /*[clinic input]
8875 os.setsid
8876 
8877 Call the system call setsid().
8878 [clinic start generated code]*/
8879 
8880 static PyObject *
os_setsid_impl(PyObject * module)8881 os_setsid_impl(PyObject *module)
8882 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
8883 {
8884     if (setsid() < 0)
8885         return posix_error();
8886     Py_RETURN_NONE;
8887 }
8888 #endif /* HAVE_SETSID */
8889 
8890 
8891 #ifdef HAVE_SETPGID
8892 /*[clinic input]
8893 os.setpgid
8894 
8895     pid: pid_t
8896     pgrp: pid_t
8897     /
8898 
8899 Call the system call setpgid(pid, pgrp).
8900 [clinic start generated code]*/
8901 
8902 static PyObject *
os_setpgid_impl(PyObject * module,pid_t pid,pid_t pgrp)8903 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
8904 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
8905 {
8906     if (setpgid(pid, pgrp) < 0)
8907         return posix_error();
8908     Py_RETURN_NONE;
8909 }
8910 #endif /* HAVE_SETPGID */
8911 
8912 
8913 #ifdef HAVE_TCGETPGRP
8914 /*[clinic input]
8915 os.tcgetpgrp
8916 
8917     fd: int
8918     /
8919 
8920 Return the process group associated with the terminal specified by fd.
8921 [clinic start generated code]*/
8922 
8923 static PyObject *
os_tcgetpgrp_impl(PyObject * module,int fd)8924 os_tcgetpgrp_impl(PyObject *module, int fd)
8925 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
8926 {
8927     pid_t pgid = tcgetpgrp(fd);
8928     if (pgid < 0)
8929         return posix_error();
8930     return PyLong_FromPid(pgid);
8931 }
8932 #endif /* HAVE_TCGETPGRP */
8933 
8934 
8935 #ifdef HAVE_TCSETPGRP
8936 /*[clinic input]
8937 os.tcsetpgrp
8938 
8939     fd: int
8940     pgid: pid_t
8941     /
8942 
8943 Set the process group associated with the terminal specified by fd.
8944 [clinic start generated code]*/
8945 
8946 static PyObject *
os_tcsetpgrp_impl(PyObject * module,int fd,pid_t pgid)8947 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
8948 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
8949 {
8950     if (tcsetpgrp(fd, pgid) < 0)
8951         return posix_error();
8952     Py_RETURN_NONE;
8953 }
8954 #endif /* HAVE_TCSETPGRP */
8955 
8956 /* Functions acting on file descriptors */
8957 
8958 #ifdef O_CLOEXEC
8959 extern int _Py_open_cloexec_works;
8960 #endif
8961 
8962 
8963 /*[clinic input]
8964 os.open -> int
8965     path: path_t
8966     flags: int
8967     mode: int = 0o777
8968     *
8969     dir_fd: dir_fd(requires='openat') = None
8970 
8971 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
8972 
8973 Open a file for low level IO.  Returns a file descriptor (integer).
8974 
8975 If dir_fd is not None, it should be a file descriptor open to a directory,
8976   and path should be relative; path will then be relative to that directory.
8977 dir_fd may not be implemented on your platform.
8978   If it is unavailable, using it will raise a NotImplementedError.
8979 [clinic start generated code]*/
8980 
8981 static int
os_open_impl(PyObject * module,path_t * path,int flags,int mode,int dir_fd)8982 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
8983 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
8984 {
8985     int fd;
8986     int async_err = 0;
8987 #ifdef HAVE_OPENAT
8988     int openat_unavailable = 0;
8989 #endif
8990 
8991 #ifdef O_CLOEXEC
8992     int *atomic_flag_works = &_Py_open_cloexec_works;
8993 #elif !defined(MS_WINDOWS)
8994     int *atomic_flag_works = NULL;
8995 #endif
8996 
8997 #ifdef MS_WINDOWS
8998     flags |= O_NOINHERIT;
8999 #elif defined(O_CLOEXEC)
9000     flags |= O_CLOEXEC;
9001 #endif
9002 
9003     if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
9004         return -1;
9005     }
9006 
9007     _Py_BEGIN_SUPPRESS_IPH
9008     do {
9009         Py_BEGIN_ALLOW_THREADS
9010 #ifdef MS_WINDOWS
9011         fd = _wopen(path->wide, flags, mode);
9012 #else
9013 #ifdef HAVE_OPENAT
9014         if (dir_fd != DEFAULT_DIR_FD) {
9015             if (HAVE_OPENAT_RUNTIME) {
9016                 fd = openat(dir_fd, path->narrow, flags, mode);
9017 
9018             } else {
9019                 openat_unavailable = 1;
9020                 fd = -1;
9021             }
9022         } else
9023 #endif /* HAVE_OPENAT */
9024             fd = open(path->narrow, flags, mode);
9025 #endif /* !MS_WINDOWS */
9026         Py_END_ALLOW_THREADS
9027     } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9028     _Py_END_SUPPRESS_IPH
9029 
9030 #ifdef HAVE_OPENAT
9031     if (openat_unavailable) {
9032         argument_unavailable_error(NULL, "dir_fd");
9033         return -1;
9034     }
9035 #endif
9036 
9037     if (fd < 0) {
9038         if (!async_err)
9039             PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
9040         return -1;
9041     }
9042 
9043 #ifndef MS_WINDOWS
9044     if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
9045         close(fd);
9046         return -1;
9047     }
9048 #endif
9049 
9050     return fd;
9051 }
9052 
9053 
9054 /*[clinic input]
9055 os.close
9056 
9057     fd: int
9058 
9059 Close a file descriptor.
9060 [clinic start generated code]*/
9061 
9062 static PyObject *
os_close_impl(PyObject * module,int fd)9063 os_close_impl(PyObject *module, int fd)
9064 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
9065 {
9066     int res;
9067     /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
9068      * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
9069      * for more details.
9070      */
9071     Py_BEGIN_ALLOW_THREADS
9072     _Py_BEGIN_SUPPRESS_IPH
9073     res = close(fd);
9074     _Py_END_SUPPRESS_IPH
9075     Py_END_ALLOW_THREADS
9076     if (res < 0)
9077         return posix_error();
9078     Py_RETURN_NONE;
9079 }
9080 
9081 
9082 #ifdef HAVE_FDWALK
9083 static int
_fdwalk_close_func(void * lohi,int fd)9084 _fdwalk_close_func(void *lohi, int fd)
9085 {
9086     int lo = ((int *)lohi)[0];
9087     int hi = ((int *)lohi)[1];
9088 
9089     if (fd >= hi) {
9090         return 1;
9091     }
9092     else if (fd >= lo) {
9093         /* Ignore errors */
9094         (void)close(fd);
9095     }
9096     return 0;
9097 }
9098 #endif /* HAVE_FDWALK */
9099 
9100 /*[clinic input]
9101 os.closerange
9102 
9103     fd_low: int
9104     fd_high: int
9105     /
9106 
9107 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
9108 [clinic start generated code]*/
9109 
9110 static PyObject *
os_closerange_impl(PyObject * module,int fd_low,int fd_high)9111 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
9112 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
9113 {
9114 #ifdef HAVE_FDWALK
9115     int lohi[2];
9116 #endif
9117     Py_BEGIN_ALLOW_THREADS
9118     _Py_BEGIN_SUPPRESS_IPH
9119 #ifdef HAVE_FDWALK
9120     lohi[0] = Py_MAX(fd_low, 0);
9121     lohi[1] = fd_high;
9122     fdwalk(_fdwalk_close_func, lohi);
9123 #else
9124     fd_low = Py_MAX(fd_low, 0);
9125 #ifdef __FreeBSD__
9126     if (fd_high >= sysconf(_SC_OPEN_MAX)) {
9127         /* Any errors encountered while closing file descriptors are ignored */
9128         closefrom(fd_low);
9129     }
9130     else
9131 #endif
9132     {
9133         for (int i = fd_low; i < fd_high; i++) {
9134             /* Ignore errors */
9135             (void)close(i);
9136         }
9137     }
9138 #endif
9139     _Py_END_SUPPRESS_IPH
9140     Py_END_ALLOW_THREADS
9141     Py_RETURN_NONE;
9142 }
9143 
9144 
9145 /*[clinic input]
9146 os.dup -> int
9147 
9148     fd: int
9149     /
9150 
9151 Return a duplicate of a file descriptor.
9152 [clinic start generated code]*/
9153 
9154 static int
os_dup_impl(PyObject * module,int fd)9155 os_dup_impl(PyObject *module, int fd)
9156 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
9157 {
9158     return _Py_dup(fd);
9159 }
9160 
9161 
9162 /*[clinic input]
9163 os.dup2 -> int
9164     fd: int
9165     fd2: int
9166     inheritable: bool=True
9167 
9168 Duplicate file descriptor.
9169 [clinic start generated code]*/
9170 
9171 static int
os_dup2_impl(PyObject * module,int fd,int fd2,int inheritable)9172 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
9173 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
9174 {
9175     int res = 0;
9176 #if defined(HAVE_DUP3) && \
9177     !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
9178     /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
9179     static int dup3_works = -1;
9180 #endif
9181 
9182     if (fd < 0 || fd2 < 0) {
9183         posix_error();
9184         return -1;
9185     }
9186 
9187     /* dup2() can fail with EINTR if the target FD is already open, because it
9188      * then has to be closed. See os_close_impl() for why we don't handle EINTR
9189      * upon close(), and therefore below.
9190      */
9191 #ifdef MS_WINDOWS
9192     Py_BEGIN_ALLOW_THREADS
9193     _Py_BEGIN_SUPPRESS_IPH
9194     res = dup2(fd, fd2);
9195     _Py_END_SUPPRESS_IPH
9196     Py_END_ALLOW_THREADS
9197     if (res < 0) {
9198         posix_error();
9199         return -1;
9200     }
9201     res = fd2; // msvcrt dup2 returns 0 on success.
9202 
9203     /* Character files like console cannot be make non-inheritable */
9204     if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9205         close(fd2);
9206         return -1;
9207     }
9208 
9209 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
9210     Py_BEGIN_ALLOW_THREADS
9211     if (!inheritable)
9212         res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
9213     else
9214         res = dup2(fd, fd2);
9215     Py_END_ALLOW_THREADS
9216     if (res < 0) {
9217         posix_error();
9218         return -1;
9219     }
9220 
9221 #else
9222 
9223 #ifdef HAVE_DUP3
9224     if (!inheritable && dup3_works != 0) {
9225         Py_BEGIN_ALLOW_THREADS
9226         res = dup3(fd, fd2, O_CLOEXEC);
9227         Py_END_ALLOW_THREADS
9228         if (res < 0) {
9229             if (dup3_works == -1)
9230                 dup3_works = (errno != ENOSYS);
9231             if (dup3_works) {
9232                 posix_error();
9233                 return -1;
9234             }
9235         }
9236     }
9237 
9238     if (inheritable || dup3_works == 0)
9239     {
9240 #endif
9241         Py_BEGIN_ALLOW_THREADS
9242         res = dup2(fd, fd2);
9243         Py_END_ALLOW_THREADS
9244         if (res < 0) {
9245             posix_error();
9246             return -1;
9247         }
9248 
9249         if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9250             close(fd2);
9251             return -1;
9252         }
9253 #ifdef HAVE_DUP3
9254     }
9255 #endif
9256 
9257 #endif
9258 
9259     return res;
9260 }
9261 
9262 
9263 #ifdef HAVE_LOCKF
9264 /*[clinic input]
9265 os.lockf
9266 
9267     fd: int
9268         An open file descriptor.
9269     command: int
9270         One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
9271     length: Py_off_t
9272         The number of bytes to lock, starting at the current position.
9273     /
9274 
9275 Apply, test or remove a POSIX lock on an open file descriptor.
9276 
9277 [clinic start generated code]*/
9278 
9279 static PyObject *
os_lockf_impl(PyObject * module,int fd,int command,Py_off_t length)9280 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
9281 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
9282 {
9283     int res;
9284 
9285     if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
9286         return NULL;
9287     }
9288 
9289     Py_BEGIN_ALLOW_THREADS
9290     res = lockf(fd, command, length);
9291     Py_END_ALLOW_THREADS
9292 
9293     if (res < 0)
9294         return posix_error();
9295 
9296     Py_RETURN_NONE;
9297 }
9298 #endif /* HAVE_LOCKF */
9299 
9300 
9301 /*[clinic input]
9302 os.lseek -> Py_off_t
9303 
9304     fd: int
9305     position: Py_off_t
9306     how: int
9307     /
9308 
9309 Set the position of a file descriptor.  Return the new position.
9310 
9311 Return the new cursor position in number of bytes
9312 relative to the beginning of the file.
9313 [clinic start generated code]*/
9314 
9315 static Py_off_t
os_lseek_impl(PyObject * module,int fd,Py_off_t position,int how)9316 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
9317 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
9318 {
9319     Py_off_t result;
9320 
9321 #ifdef SEEK_SET
9322     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
9323     switch (how) {
9324         case 0: how = SEEK_SET; break;
9325         case 1: how = SEEK_CUR; break;
9326         case 2: how = SEEK_END; break;
9327     }
9328 #endif /* SEEK_END */
9329 
9330     Py_BEGIN_ALLOW_THREADS
9331     _Py_BEGIN_SUPPRESS_IPH
9332 #ifdef MS_WINDOWS
9333     result = _lseeki64(fd, position, how);
9334 #else
9335     result = lseek(fd, position, how);
9336 #endif
9337     _Py_END_SUPPRESS_IPH
9338     Py_END_ALLOW_THREADS
9339     if (result < 0)
9340         posix_error();
9341 
9342     return result;
9343 }
9344 
9345 
9346 /*[clinic input]
9347 os.read
9348     fd: int
9349     length: Py_ssize_t
9350     /
9351 
9352 Read from a file descriptor.  Returns a bytes object.
9353 [clinic start generated code]*/
9354 
9355 static PyObject *
os_read_impl(PyObject * module,int fd,Py_ssize_t length)9356 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
9357 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
9358 {
9359     Py_ssize_t n;
9360     PyObject *buffer;
9361 
9362     if (length < 0) {
9363         errno = EINVAL;
9364         return posix_error();
9365     }
9366 
9367     length = Py_MIN(length, _PY_READ_MAX);
9368 
9369     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9370     if (buffer == NULL)
9371         return NULL;
9372 
9373     n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
9374     if (n == -1) {
9375         Py_DECREF(buffer);
9376         return NULL;
9377     }
9378 
9379     if (n != length)
9380         _PyBytes_Resize(&buffer, n);
9381 
9382     return buffer;
9383 }
9384 
9385 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
9386                                 || defined(__APPLE__))) \
9387     || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
9388     || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9389 static int
iov_setup(struct iovec ** iov,Py_buffer ** buf,PyObject * seq,Py_ssize_t cnt,int type)9390 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
9391 {
9392     Py_ssize_t i, j;
9393 
9394     *iov = PyMem_New(struct iovec, cnt);
9395     if (*iov == NULL) {
9396         PyErr_NoMemory();
9397         return -1;
9398     }
9399 
9400     *buf = PyMem_New(Py_buffer, cnt);
9401     if (*buf == NULL) {
9402         PyMem_Del(*iov);
9403         PyErr_NoMemory();
9404         return -1;
9405     }
9406 
9407     for (i = 0; i < cnt; i++) {
9408         PyObject *item = PySequence_GetItem(seq, i);
9409         if (item == NULL)
9410             goto fail;
9411         if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
9412             Py_DECREF(item);
9413             goto fail;
9414         }
9415         Py_DECREF(item);
9416         (*iov)[i].iov_base = (*buf)[i].buf;
9417         (*iov)[i].iov_len = (*buf)[i].len;
9418     }
9419     return 0;
9420 
9421 fail:
9422     PyMem_Del(*iov);
9423     for (j = 0; j < i; j++) {
9424         PyBuffer_Release(&(*buf)[j]);
9425     }
9426     PyMem_Del(*buf);
9427     return -1;
9428 }
9429 
9430 static void
iov_cleanup(struct iovec * iov,Py_buffer * buf,int cnt)9431 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9432 {
9433     int i;
9434     PyMem_Del(iov);
9435     for (i = 0; i < cnt; i++) {
9436         PyBuffer_Release(&buf[i]);
9437     }
9438     PyMem_Del(buf);
9439 }
9440 #endif
9441 
9442 
9443 #ifdef HAVE_READV
9444 /*[clinic input]
9445 os.readv -> Py_ssize_t
9446 
9447     fd: int
9448     buffers: object
9449     /
9450 
9451 Read from a file descriptor fd into an iterable of buffers.
9452 
9453 The buffers should be mutable buffers accepting bytes.
9454 readv will transfer data into each buffer until it is full
9455 and then move on to the next buffer in the sequence to hold
9456 the rest of the data.
9457 
9458 readv returns the total number of bytes read,
9459 which may be less than the total capacity of all the buffers.
9460 [clinic start generated code]*/
9461 
9462 static Py_ssize_t
os_readv_impl(PyObject * module,int fd,PyObject * buffers)9463 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9464 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9465 {
9466     Py_ssize_t cnt, n;
9467     int async_err = 0;
9468     struct iovec *iov;
9469     Py_buffer *buf;
9470 
9471     if (!PySequence_Check(buffers)) {
9472         PyErr_SetString(PyExc_TypeError,
9473             "readv() arg 2 must be a sequence");
9474         return -1;
9475     }
9476 
9477     cnt = PySequence_Size(buffers);
9478     if (cnt < 0)
9479         return -1;
9480 
9481     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9482         return -1;
9483 
9484     do {
9485         Py_BEGIN_ALLOW_THREADS
9486         n = readv(fd, iov, cnt);
9487         Py_END_ALLOW_THREADS
9488     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9489 
9490     iov_cleanup(iov, buf, cnt);
9491     if (n < 0) {
9492         if (!async_err)
9493             posix_error();
9494         return -1;
9495     }
9496 
9497     return n;
9498 }
9499 #endif /* HAVE_READV */
9500 
9501 
9502 #ifdef HAVE_PREAD
9503 /*[clinic input]
9504 os.pread
9505 
9506     fd: int
9507     length: Py_ssize_t
9508     offset: Py_off_t
9509     /
9510 
9511 Read a number of bytes from a file descriptor starting at a particular offset.
9512 
9513 Read length bytes from file descriptor fd, starting at offset bytes from
9514 the beginning of the file.  The file offset remains unchanged.
9515 [clinic start generated code]*/
9516 
9517 static PyObject *
os_pread_impl(PyObject * module,int fd,Py_ssize_t length,Py_off_t offset)9518 os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
9519 /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
9520 {
9521     Py_ssize_t n;
9522     int async_err = 0;
9523     PyObject *buffer;
9524 
9525     if (length < 0) {
9526         errno = EINVAL;
9527         return posix_error();
9528     }
9529     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9530     if (buffer == NULL)
9531         return NULL;
9532 
9533     do {
9534         Py_BEGIN_ALLOW_THREADS
9535         _Py_BEGIN_SUPPRESS_IPH
9536         n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9537         _Py_END_SUPPRESS_IPH
9538         Py_END_ALLOW_THREADS
9539     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9540 
9541     if (n < 0) {
9542         Py_DECREF(buffer);
9543         return (!async_err) ? posix_error() : NULL;
9544     }
9545     if (n != length)
9546         _PyBytes_Resize(&buffer, n);
9547     return buffer;
9548 }
9549 #endif /* HAVE_PREAD */
9550 
9551 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9552 /*[clinic input]
9553 os.preadv -> Py_ssize_t
9554 
9555     fd: int
9556     buffers: object
9557     offset: Py_off_t
9558     flags: int = 0
9559     /
9560 
9561 Reads from a file descriptor into a number of mutable bytes-like objects.
9562 
9563 Combines the functionality of readv() and pread(). As readv(), it will
9564 transfer data into each buffer until it is full and then move on to the next
9565 buffer in the sequence to hold the rest of the data. Its fourth argument,
9566 specifies the file offset at which the input operation is to be performed. It
9567 will return the total number of bytes read (which can be less than the total
9568 capacity of all the objects).
9569 
9570 The flags argument contains a bitwise OR of zero or more of the following flags:
9571 
9572 - RWF_HIPRI
9573 - RWF_NOWAIT
9574 
9575 Using non-zero flags requires Linux 4.6 or newer.
9576 [clinic start generated code]*/
9577 
9578 static Py_ssize_t
os_preadv_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9579 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9580                int flags)
9581 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9582 {
9583     Py_ssize_t cnt, n;
9584     int async_err = 0;
9585     struct iovec *iov;
9586     Py_buffer *buf;
9587 
9588     if (!PySequence_Check(buffers)) {
9589         PyErr_SetString(PyExc_TypeError,
9590             "preadv2() arg 2 must be a sequence");
9591         return -1;
9592     }
9593 
9594     cnt = PySequence_Size(buffers);
9595     if (cnt < 0) {
9596         return -1;
9597     }
9598 
9599 #ifndef HAVE_PREADV2
9600     if(flags != 0) {
9601         argument_unavailable_error("preadv2", "flags");
9602         return -1;
9603     }
9604 #endif
9605 
9606     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9607         return -1;
9608     }
9609 #ifdef HAVE_PREADV2
9610     do {
9611         Py_BEGIN_ALLOW_THREADS
9612         _Py_BEGIN_SUPPRESS_IPH
9613         n = preadv2(fd, iov, cnt, offset, flags);
9614         _Py_END_SUPPRESS_IPH
9615         Py_END_ALLOW_THREADS
9616     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9617 #else
9618     do {
9619 #ifdef __APPLE__
9620 /* This entire function will be removed from the module dict when the API
9621  * is not available.
9622  */
9623 #pragma clang diagnostic push
9624 #pragma clang diagnostic ignored "-Wunguarded-availability"
9625 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
9626 #endif
9627         Py_BEGIN_ALLOW_THREADS
9628         _Py_BEGIN_SUPPRESS_IPH
9629         n = preadv(fd, iov, cnt, offset);
9630         _Py_END_SUPPRESS_IPH
9631         Py_END_ALLOW_THREADS
9632     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9633 
9634 #ifdef __APPLE__
9635 #pragma clang diagnostic pop
9636 #endif
9637 
9638 #endif
9639 
9640     iov_cleanup(iov, buf, cnt);
9641     if (n < 0) {
9642         if (!async_err) {
9643             posix_error();
9644         }
9645         return -1;
9646     }
9647 
9648     return n;
9649 }
9650 #endif /* HAVE_PREADV */
9651 
9652 
9653 /*[clinic input]
9654 os.write -> Py_ssize_t
9655 
9656     fd: int
9657     data: Py_buffer
9658     /
9659 
9660 Write a bytes object to a file descriptor.
9661 [clinic start generated code]*/
9662 
9663 static Py_ssize_t
os_write_impl(PyObject * module,int fd,Py_buffer * data)9664 os_write_impl(PyObject *module, int fd, Py_buffer *data)
9665 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9666 {
9667     return _Py_write(fd, data->buf, data->len);
9668 }
9669 
9670 #ifdef HAVE_SENDFILE
9671 #ifdef __APPLE__
9672 /*[clinic input]
9673 os.sendfile
9674 
9675     out_fd: int
9676     in_fd: int
9677     offset: Py_off_t
9678     count as sbytes: Py_off_t
9679     headers: object(c_default="NULL") = ()
9680     trailers: object(c_default="NULL") = ()
9681     flags: int = 0
9682 
9683 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9684 [clinic start generated code]*/
9685 
9686 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)9687 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9688                  Py_off_t sbytes, PyObject *headers, PyObject *trailers,
9689                  int flags)
9690 /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
9691 #elif defined(__FreeBSD__) || defined(__DragonFly__)
9692 /*[clinic input]
9693 os.sendfile
9694 
9695     out_fd: int
9696     in_fd: int
9697     offset: Py_off_t
9698     count: Py_ssize_t
9699     headers: object(c_default="NULL") = ()
9700     trailers: object(c_default="NULL") = ()
9701     flags: int = 0
9702 
9703 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9704 [clinic start generated code]*/
9705 
9706 static PyObject *
9707 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9708                  Py_ssize_t count, PyObject *headers, PyObject *trailers,
9709                  int flags)
9710 /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
9711 #else
9712 /*[clinic input]
9713 os.sendfile
9714 
9715     out_fd: int
9716     in_fd: int
9717     offset as offobj: object
9718     count: Py_ssize_t
9719 
9720 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9721 [clinic start generated code]*/
9722 
9723 static PyObject *
9724 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
9725                  Py_ssize_t count)
9726 /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
9727 #endif
9728 {
9729     Py_ssize_t ret;
9730     int async_err = 0;
9731 
9732 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9733 #ifndef __APPLE__
9734     off_t sbytes;
9735 #endif
9736     Py_buffer *hbuf, *tbuf;
9737     struct sf_hdtr sf;
9738 
9739     sf.headers = NULL;
9740     sf.trailers = NULL;
9741 
9742     if (headers != NULL) {
9743         if (!PySequence_Check(headers)) {
9744             PyErr_SetString(PyExc_TypeError,
9745                 "sendfile() headers must be a sequence");
9746             return NULL;
9747         } else {
9748             Py_ssize_t i = PySequence_Size(headers);
9749             if (i < 0)
9750                 return NULL;
9751             if (i > INT_MAX) {
9752                 PyErr_SetString(PyExc_OverflowError,
9753                     "sendfile() header is too large");
9754                 return NULL;
9755             }
9756             if (i > 0) {
9757                 sf.hdr_cnt = (int)i;
9758                 if (iov_setup(&(sf.headers), &hbuf,
9759                               headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9760                     return NULL;
9761 #ifdef __APPLE__
9762                 for (i = 0; i < sf.hdr_cnt; i++) {
9763                     Py_ssize_t blen = sf.headers[i].iov_len;
9764 # define OFF_T_MAX 0x7fffffffffffffff
9765                     if (sbytes >= OFF_T_MAX - blen) {
9766                         PyErr_SetString(PyExc_OverflowError,
9767                             "sendfile() header is too large");
9768                         return NULL;
9769                     }
9770                     sbytes += blen;
9771                 }
9772 #endif
9773             }
9774         }
9775     }
9776     if (trailers != NULL) {
9777         if (!PySequence_Check(trailers)) {
9778             PyErr_SetString(PyExc_TypeError,
9779                 "sendfile() trailers must be a sequence");
9780             return NULL;
9781         } else {
9782             Py_ssize_t i = PySequence_Size(trailers);
9783             if (i < 0)
9784                 return NULL;
9785             if (i > INT_MAX) {
9786                 PyErr_SetString(PyExc_OverflowError,
9787                     "sendfile() trailer is too large");
9788                 return NULL;
9789             }
9790             if (i > 0) {
9791                 sf.trl_cnt = (int)i;
9792                 if (iov_setup(&(sf.trailers), &tbuf,
9793                               trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
9794                     return NULL;
9795             }
9796         }
9797     }
9798 
9799     _Py_BEGIN_SUPPRESS_IPH
9800     do {
9801         Py_BEGIN_ALLOW_THREADS
9802 #ifdef __APPLE__
9803         ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
9804 #else
9805         ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
9806 #endif
9807         Py_END_ALLOW_THREADS
9808     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9809     _Py_END_SUPPRESS_IPH
9810 
9811     if (sf.headers != NULL)
9812         iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
9813     if (sf.trailers != NULL)
9814         iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
9815 
9816     if (ret < 0) {
9817         if ((errno == EAGAIN) || (errno == EBUSY)) {
9818             if (sbytes != 0) {
9819                 // some data has been sent
9820                 goto done;
9821             }
9822             else {
9823                 // no data has been sent; upper application is supposed
9824                 // to retry on EAGAIN or EBUSY
9825                 return posix_error();
9826             }
9827         }
9828         return (!async_err) ? posix_error() : NULL;
9829     }
9830     goto done;
9831 
9832 done:
9833     #if !defined(HAVE_LARGEFILE_SUPPORT)
9834         return Py_BuildValue("l", sbytes);
9835     #else
9836         return Py_BuildValue("L", sbytes);
9837     #endif
9838 
9839 #else
9840 #ifdef __linux__
9841     if (offobj == Py_None) {
9842         do {
9843             Py_BEGIN_ALLOW_THREADS
9844             ret = sendfile(out_fd, in_fd, NULL, count);
9845             Py_END_ALLOW_THREADS
9846         } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9847         if (ret < 0)
9848             return (!async_err) ? posix_error() : NULL;
9849         return Py_BuildValue("n", ret);
9850     }
9851 #endif
9852     off_t offset;
9853     if (!Py_off_t_converter(offobj, &offset))
9854         return NULL;
9855 
9856 #if defined(__sun) && defined(__SVR4)
9857     // On Solaris, sendfile raises EINVAL rather than returning 0
9858     // when the offset is equal or bigger than the in_fd size.
9859     struct stat st;
9860 
9861     do {
9862         Py_BEGIN_ALLOW_THREADS
9863         ret = fstat(in_fd, &st);
9864         Py_END_ALLOW_THREADS
9865     } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9866     if (ret < 0)
9867         return (!async_err) ? posix_error() : NULL;
9868 
9869     if (offset >= st.st_size) {
9870         return Py_BuildValue("i", 0);
9871     }
9872 
9873     // On illumos specifically sendfile() may perform a partial write but
9874     // return -1/an error (in one confirmed case the destination socket
9875     // had a 5 second timeout set and errno was EAGAIN) and it's on the client
9876     // code to check if the offset parameter was modified by sendfile().
9877     //
9878     // We need this variable to track said change.
9879     off_t original_offset = offset;
9880 #endif
9881 
9882     do {
9883         Py_BEGIN_ALLOW_THREADS
9884         ret = sendfile(out_fd, in_fd, &offset, count);
9885 #if defined(__sun) && defined(__SVR4)
9886         // This handles illumos-specific sendfile() partial write behavior,
9887         // see a comment above for more details.
9888         if (ret < 0 && offset != original_offset) {
9889             ret = offset - original_offset;
9890         }
9891 #endif
9892         Py_END_ALLOW_THREADS
9893     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9894     if (ret < 0)
9895         return (!async_err) ? posix_error() : NULL;
9896     return Py_BuildValue("n", ret);
9897 #endif
9898 }
9899 #endif /* HAVE_SENDFILE */
9900 
9901 
9902 #if defined(__APPLE__)
9903 /*[clinic input]
9904 os._fcopyfile
9905 
9906     in_fd: int
9907     out_fd: int
9908     flags: int
9909     /
9910 
9911 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
9912 [clinic start generated code]*/
9913 
9914 static PyObject *
os__fcopyfile_impl(PyObject * module,int in_fd,int out_fd,int flags)9915 os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
9916 /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
9917 {
9918     int ret;
9919 
9920     Py_BEGIN_ALLOW_THREADS
9921     ret = fcopyfile(in_fd, out_fd, NULL, flags);
9922     Py_END_ALLOW_THREADS
9923     if (ret < 0)
9924         return posix_error();
9925     Py_RETURN_NONE;
9926 }
9927 #endif
9928 
9929 
9930 /*[clinic input]
9931 os.fstat
9932 
9933     fd : int
9934 
9935 Perform a stat system call on the given file descriptor.
9936 
9937 Like stat(), but for an open file descriptor.
9938 Equivalent to os.stat(fd).
9939 [clinic start generated code]*/
9940 
9941 static PyObject *
os_fstat_impl(PyObject * module,int fd)9942 os_fstat_impl(PyObject *module, int fd)
9943 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
9944 {
9945     STRUCT_STAT st;
9946     int res;
9947     int async_err = 0;
9948 
9949     do {
9950         Py_BEGIN_ALLOW_THREADS
9951         res = FSTAT(fd, &st);
9952         Py_END_ALLOW_THREADS
9953     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9954     if (res != 0) {
9955 #ifdef MS_WINDOWS
9956         return PyErr_SetFromWindowsErr(0);
9957 #else
9958         return (!async_err) ? posix_error() : NULL;
9959 #endif
9960     }
9961 
9962     return _pystat_fromstructstat(module, &st);
9963 }
9964 
9965 
9966 /*[clinic input]
9967 os.isatty -> bool
9968     fd: int
9969     /
9970 
9971 Return True if the fd is connected to a terminal.
9972 
9973 Return True if the file descriptor is an open file descriptor
9974 connected to the slave end of a terminal.
9975 [clinic start generated code]*/
9976 
9977 static int
os_isatty_impl(PyObject * module,int fd)9978 os_isatty_impl(PyObject *module, int fd)
9979 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
9980 {
9981     int return_value;
9982     _Py_BEGIN_SUPPRESS_IPH
9983     return_value = isatty(fd);
9984     _Py_END_SUPPRESS_IPH
9985     return return_value;
9986 }
9987 
9988 
9989 #ifdef HAVE_PIPE
9990 /*[clinic input]
9991 os.pipe
9992 
9993 Create a pipe.
9994 
9995 Returns a tuple of two file descriptors:
9996   (read_fd, write_fd)
9997 [clinic start generated code]*/
9998 
9999 static PyObject *
os_pipe_impl(PyObject * module)10000 os_pipe_impl(PyObject *module)
10001 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
10002 {
10003     int fds[2];
10004 #ifdef MS_WINDOWS
10005     HANDLE read, write;
10006     SECURITY_ATTRIBUTES attr;
10007     BOOL ok;
10008 #else
10009     int res;
10010 #endif
10011 
10012 #ifdef MS_WINDOWS
10013     attr.nLength = sizeof(attr);
10014     attr.lpSecurityDescriptor = NULL;
10015     attr.bInheritHandle = FALSE;
10016 
10017     Py_BEGIN_ALLOW_THREADS
10018     _Py_BEGIN_SUPPRESS_IPH
10019     ok = CreatePipe(&read, &write, &attr, 0);
10020     if (ok) {
10021         fds[0] = _open_osfhandle((intptr_t)read, _O_RDONLY);
10022         fds[1] = _open_osfhandle((intptr_t)write, _O_WRONLY);
10023         if (fds[0] == -1 || fds[1] == -1) {
10024             CloseHandle(read);
10025             CloseHandle(write);
10026             ok = 0;
10027         }
10028     }
10029     _Py_END_SUPPRESS_IPH
10030     Py_END_ALLOW_THREADS
10031 
10032     if (!ok)
10033         return PyErr_SetFromWindowsErr(0);
10034 #else
10035 
10036 #ifdef HAVE_PIPE2
10037     Py_BEGIN_ALLOW_THREADS
10038     res = pipe2(fds, O_CLOEXEC);
10039     Py_END_ALLOW_THREADS
10040 
10041     if (res != 0 && errno == ENOSYS)
10042     {
10043 #endif
10044         Py_BEGIN_ALLOW_THREADS
10045         res = pipe(fds);
10046         Py_END_ALLOW_THREADS
10047 
10048         if (res == 0) {
10049             if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
10050                 close(fds[0]);
10051                 close(fds[1]);
10052                 return NULL;
10053             }
10054             if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
10055                 close(fds[0]);
10056                 close(fds[1]);
10057                 return NULL;
10058             }
10059         }
10060 #ifdef HAVE_PIPE2
10061     }
10062 #endif
10063 
10064     if (res != 0)
10065         return PyErr_SetFromErrno(PyExc_OSError);
10066 #endif /* !MS_WINDOWS */
10067     return Py_BuildValue("(ii)", fds[0], fds[1]);
10068 }
10069 #endif  /* HAVE_PIPE */
10070 
10071 
10072 #ifdef HAVE_PIPE2
10073 /*[clinic input]
10074 os.pipe2
10075 
10076     flags: int
10077     /
10078 
10079 Create a pipe with flags set atomically.
10080 
10081 Returns a tuple of two file descriptors:
10082   (read_fd, write_fd)
10083 
10084 flags can be constructed by ORing together one or more of these values:
10085 O_NONBLOCK, O_CLOEXEC.
10086 [clinic start generated code]*/
10087 
10088 static PyObject *
os_pipe2_impl(PyObject * module,int flags)10089 os_pipe2_impl(PyObject *module, int flags)
10090 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
10091 {
10092     int fds[2];
10093     int res;
10094 
10095     res = pipe2(fds, flags);
10096     if (res != 0)
10097         return posix_error();
10098     return Py_BuildValue("(ii)", fds[0], fds[1]);
10099 }
10100 #endif /* HAVE_PIPE2 */
10101 
10102 
10103 #ifdef HAVE_WRITEV
10104 /*[clinic input]
10105 os.writev -> Py_ssize_t
10106     fd: int
10107     buffers: object
10108     /
10109 
10110 Iterate over buffers, and write the contents of each to a file descriptor.
10111 
10112 Returns the total number of bytes written.
10113 buffers must be a sequence of bytes-like objects.
10114 [clinic start generated code]*/
10115 
10116 static Py_ssize_t
os_writev_impl(PyObject * module,int fd,PyObject * buffers)10117 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
10118 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
10119 {
10120     Py_ssize_t cnt;
10121     Py_ssize_t result;
10122     int async_err = 0;
10123     struct iovec *iov;
10124     Py_buffer *buf;
10125 
10126     if (!PySequence_Check(buffers)) {
10127         PyErr_SetString(PyExc_TypeError,
10128             "writev() arg 2 must be a sequence");
10129         return -1;
10130     }
10131     cnt = PySequence_Size(buffers);
10132     if (cnt < 0)
10133         return -1;
10134 
10135     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10136         return -1;
10137     }
10138 
10139     do {
10140         Py_BEGIN_ALLOW_THREADS
10141         result = writev(fd, iov, cnt);
10142         Py_END_ALLOW_THREADS
10143     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10144 
10145     iov_cleanup(iov, buf, cnt);
10146     if (result < 0 && !async_err)
10147         posix_error();
10148 
10149     return result;
10150 }
10151 #endif /* HAVE_WRITEV */
10152 
10153 
10154 #ifdef HAVE_PWRITE
10155 /*[clinic input]
10156 os.pwrite -> Py_ssize_t
10157 
10158     fd: int
10159     buffer: Py_buffer
10160     offset: Py_off_t
10161     /
10162 
10163 Write bytes to a file descriptor starting at a particular offset.
10164 
10165 Write buffer to fd, starting at offset bytes from the beginning of
10166 the file.  Returns the number of bytes writte.  Does not change the
10167 current file offset.
10168 [clinic start generated code]*/
10169 
10170 static Py_ssize_t
os_pwrite_impl(PyObject * module,int fd,Py_buffer * buffer,Py_off_t offset)10171 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
10172 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
10173 {
10174     Py_ssize_t size;
10175     int async_err = 0;
10176 
10177     do {
10178         Py_BEGIN_ALLOW_THREADS
10179         _Py_BEGIN_SUPPRESS_IPH
10180         size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
10181         _Py_END_SUPPRESS_IPH
10182         Py_END_ALLOW_THREADS
10183     } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10184 
10185     if (size < 0 && !async_err)
10186         posix_error();
10187     return size;
10188 }
10189 #endif /* HAVE_PWRITE */
10190 
10191 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
10192 /*[clinic input]
10193 os.pwritev -> Py_ssize_t
10194 
10195     fd: int
10196     buffers: object
10197     offset: Py_off_t
10198     flags: int = 0
10199     /
10200 
10201 Writes the contents of bytes-like objects to a file descriptor at a given offset.
10202 
10203 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
10204 of bytes-like objects. Buffers are processed in array order. Entire contents of first
10205 buffer is written before proceeding to second, and so on. The operating system may
10206 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
10207 This function writes the contents of each object to the file descriptor and returns
10208 the total number of bytes written.
10209 
10210 The flags argument contains a bitwise OR of zero or more of the following flags:
10211 
10212 - RWF_DSYNC
10213 - RWF_SYNC
10214 
10215 Using non-zero flags requires Linux 4.7 or newer.
10216 [clinic start generated code]*/
10217 
10218 static Py_ssize_t
os_pwritev_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)10219 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
10220                 int flags)
10221 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=803dc5ddbf0cfd3b]*/
10222 {
10223     Py_ssize_t cnt;
10224     Py_ssize_t result;
10225     int async_err = 0;
10226     struct iovec *iov;
10227     Py_buffer *buf;
10228 
10229     if (!PySequence_Check(buffers)) {
10230         PyErr_SetString(PyExc_TypeError,
10231             "pwritev() arg 2 must be a sequence");
10232         return -1;
10233     }
10234 
10235     cnt = PySequence_Size(buffers);
10236     if (cnt < 0) {
10237         return -1;
10238     }
10239 
10240 #ifndef HAVE_PWRITEV2
10241     if(flags != 0) {
10242         argument_unavailable_error("pwritev2", "flags");
10243         return -1;
10244     }
10245 #endif
10246 
10247     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10248         return -1;
10249     }
10250 #ifdef HAVE_PWRITEV2
10251     do {
10252         Py_BEGIN_ALLOW_THREADS
10253         _Py_BEGIN_SUPPRESS_IPH
10254         result = pwritev2(fd, iov, cnt, offset, flags);
10255         _Py_END_SUPPRESS_IPH
10256         Py_END_ALLOW_THREADS
10257     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10258 #else
10259 
10260 #ifdef __APPLE__
10261 /* This entire function will be removed from the module dict when the API
10262  * is not available.
10263  */
10264 #pragma clang diagnostic push
10265 #pragma clang diagnostic ignored "-Wunguarded-availability"
10266 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
10267 #endif
10268     do {
10269         Py_BEGIN_ALLOW_THREADS
10270         _Py_BEGIN_SUPPRESS_IPH
10271         result = pwritev(fd, iov, cnt, offset);
10272         _Py_END_SUPPRESS_IPH
10273         Py_END_ALLOW_THREADS
10274     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10275 
10276 #ifdef __APPLE__
10277 #pragma clang diagnostic pop
10278 #endif
10279 
10280 #endif
10281 
10282     iov_cleanup(iov, buf, cnt);
10283     if (result < 0) {
10284         if (!async_err) {
10285             posix_error();
10286         }
10287         return -1;
10288     }
10289 
10290     return result;
10291 }
10292 #endif /* HAVE_PWRITEV */
10293 
10294 #ifdef HAVE_COPY_FILE_RANGE
10295 /*[clinic input]
10296 
10297 os.copy_file_range
10298     src: int
10299         Source file descriptor.
10300     dst: int
10301         Destination file descriptor.
10302     count: Py_ssize_t
10303         Number of bytes to copy.
10304     offset_src: object = None
10305         Starting offset in src.
10306     offset_dst: object = None
10307         Starting offset in dst.
10308 
10309 Copy count bytes from one file descriptor to another.
10310 
10311 If offset_src is None, then src is read from the current position;
10312 respectively for offset_dst.
10313 [clinic start generated code]*/
10314 
10315 static PyObject *
os_copy_file_range_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst)10316 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10317                         PyObject *offset_src, PyObject *offset_dst)
10318 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
10319 {
10320     off_t offset_src_val, offset_dst_val;
10321     off_t *p_offset_src = NULL;
10322     off_t *p_offset_dst = NULL;
10323     Py_ssize_t ret;
10324     int async_err = 0;
10325     /* The flags argument is provided to allow
10326      * for future extensions and currently must be to 0. */
10327     int flags = 0;
10328 
10329 
10330     if (count < 0) {
10331         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10332         return NULL;
10333     }
10334 
10335     if (offset_src != Py_None) {
10336         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10337             return NULL;
10338         }
10339         p_offset_src = &offset_src_val;
10340     }
10341 
10342     if (offset_dst != Py_None) {
10343         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10344             return NULL;
10345         }
10346         p_offset_dst = &offset_dst_val;
10347     }
10348 
10349     do {
10350         Py_BEGIN_ALLOW_THREADS
10351         ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
10352         Py_END_ALLOW_THREADS
10353     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10354 
10355     if (ret < 0) {
10356         return (!async_err) ? posix_error() : NULL;
10357     }
10358 
10359     return PyLong_FromSsize_t(ret);
10360 }
10361 #endif /* HAVE_COPY_FILE_RANGE*/
10362 
10363 #ifdef HAVE_MKFIFO
10364 /*[clinic input]
10365 os.mkfifo
10366 
10367     path: path_t
10368     mode: int=0o666
10369     *
10370     dir_fd: dir_fd(requires='mkfifoat')=None
10371 
10372 Create a "fifo" (a POSIX named pipe).
10373 
10374 If dir_fd is not None, it should be a file descriptor open to a directory,
10375   and path should be relative; path will then be relative to that directory.
10376 dir_fd may not be implemented on your platform.
10377   If it is unavailable, using it will raise a NotImplementedError.
10378 [clinic start generated code]*/
10379 
10380 static PyObject *
os_mkfifo_impl(PyObject * module,path_t * path,int mode,int dir_fd)10381 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
10382 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
10383 {
10384     int result;
10385     int async_err = 0;
10386 
10387     do {
10388         Py_BEGIN_ALLOW_THREADS
10389 #ifdef HAVE_MKFIFOAT
10390         if (dir_fd != DEFAULT_DIR_FD)
10391             result = mkfifoat(dir_fd, path->narrow, mode);
10392         else
10393 #endif
10394             result = mkfifo(path->narrow, mode);
10395         Py_END_ALLOW_THREADS
10396     } while (result != 0 && errno == EINTR &&
10397              !(async_err = PyErr_CheckSignals()));
10398     if (result != 0)
10399         return (!async_err) ? posix_error() : NULL;
10400 
10401     Py_RETURN_NONE;
10402 }
10403 #endif /* HAVE_MKFIFO */
10404 
10405 
10406 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
10407 /*[clinic input]
10408 os.mknod
10409 
10410     path: path_t
10411     mode: int=0o600
10412     device: dev_t=0
10413     *
10414     dir_fd: dir_fd(requires='mknodat')=None
10415 
10416 Create a node in the file system.
10417 
10418 Create a node in the file system (file, device special file or named pipe)
10419 at path.  mode specifies both the permissions to use and the
10420 type of node to be created, being combined (bitwise OR) with one of
10421 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
10422 device defines the newly created device special file (probably using
10423 os.makedev()).  Otherwise device is ignored.
10424 
10425 If dir_fd is not None, it should be a file descriptor open to a directory,
10426   and path should be relative; path will then be relative to that directory.
10427 dir_fd may not be implemented on your platform.
10428   If it is unavailable, using it will raise a NotImplementedError.
10429 [clinic start generated code]*/
10430 
10431 static PyObject *
os_mknod_impl(PyObject * module,path_t * path,int mode,dev_t device,int dir_fd)10432 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
10433               int dir_fd)
10434 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
10435 {
10436     int result;
10437     int async_err = 0;
10438 
10439     do {
10440         Py_BEGIN_ALLOW_THREADS
10441 #ifdef HAVE_MKNODAT
10442         if (dir_fd != DEFAULT_DIR_FD)
10443             result = mknodat(dir_fd, path->narrow, mode, device);
10444         else
10445 #endif
10446             result = mknod(path->narrow, mode, device);
10447         Py_END_ALLOW_THREADS
10448     } while (result != 0 && errno == EINTR &&
10449              !(async_err = PyErr_CheckSignals()));
10450     if (result != 0)
10451         return (!async_err) ? posix_error() : NULL;
10452 
10453     Py_RETURN_NONE;
10454 }
10455 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
10456 
10457 
10458 #ifdef HAVE_DEVICE_MACROS
10459 /*[clinic input]
10460 os.major -> unsigned_int
10461 
10462     device: dev_t
10463     /
10464 
10465 Extracts a device major number from a raw device number.
10466 [clinic start generated code]*/
10467 
10468 static unsigned int
os_major_impl(PyObject * module,dev_t device)10469 os_major_impl(PyObject *module, dev_t device)
10470 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
10471 {
10472     return major(device);
10473 }
10474 
10475 
10476 /*[clinic input]
10477 os.minor -> unsigned_int
10478 
10479     device: dev_t
10480     /
10481 
10482 Extracts a device minor number from a raw device number.
10483 [clinic start generated code]*/
10484 
10485 static unsigned int
os_minor_impl(PyObject * module,dev_t device)10486 os_minor_impl(PyObject *module, dev_t device)
10487 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10488 {
10489     return minor(device);
10490 }
10491 
10492 
10493 /*[clinic input]
10494 os.makedev -> dev_t
10495 
10496     major: int
10497     minor: int
10498     /
10499 
10500 Composes a raw device number from the major and minor device numbers.
10501 [clinic start generated code]*/
10502 
10503 static dev_t
os_makedev_impl(PyObject * module,int major,int minor)10504 os_makedev_impl(PyObject *module, int major, int minor)
10505 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10506 {
10507     return makedev(major, minor);
10508 }
10509 #endif /* HAVE_DEVICE_MACROS */
10510 
10511 
10512 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10513 /*[clinic input]
10514 os.ftruncate
10515 
10516     fd: int
10517     length: Py_off_t
10518     /
10519 
10520 Truncate a file, specified by file descriptor, to a specific length.
10521 [clinic start generated code]*/
10522 
10523 static PyObject *
os_ftruncate_impl(PyObject * module,int fd,Py_off_t length)10524 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10525 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10526 {
10527     int result;
10528     int async_err = 0;
10529 
10530     if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10531         return NULL;
10532     }
10533 
10534     do {
10535         Py_BEGIN_ALLOW_THREADS
10536         _Py_BEGIN_SUPPRESS_IPH
10537 #ifdef MS_WINDOWS
10538         result = _chsize_s(fd, length);
10539 #else
10540         result = ftruncate(fd, length);
10541 #endif
10542         _Py_END_SUPPRESS_IPH
10543         Py_END_ALLOW_THREADS
10544     } while (result != 0 && errno == EINTR &&
10545              !(async_err = PyErr_CheckSignals()));
10546     if (result != 0)
10547         return (!async_err) ? posix_error() : NULL;
10548     Py_RETURN_NONE;
10549 }
10550 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10551 
10552 
10553 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10554 /*[clinic input]
10555 os.truncate
10556     path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10557     length: Py_off_t
10558 
10559 Truncate a file, specified by path, to a specific length.
10560 
10561 On some platforms, path may also be specified as an open file descriptor.
10562   If this functionality is unavailable, using it raises an exception.
10563 [clinic start generated code]*/
10564 
10565 static PyObject *
os_truncate_impl(PyObject * module,path_t * path,Py_off_t length)10566 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10567 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10568 {
10569     int result;
10570 #ifdef MS_WINDOWS
10571     int fd;
10572 #endif
10573 
10574     if (path->fd != -1)
10575         return os_ftruncate_impl(module, path->fd, length);
10576 
10577     if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10578         return NULL;
10579     }
10580 
10581     Py_BEGIN_ALLOW_THREADS
10582     _Py_BEGIN_SUPPRESS_IPH
10583 #ifdef MS_WINDOWS
10584     fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10585     if (fd < 0)
10586         result = -1;
10587     else {
10588         result = _chsize_s(fd, length);
10589         close(fd);
10590         if (result < 0)
10591             errno = result;
10592     }
10593 #else
10594     result = truncate(path->narrow, length);
10595 #endif
10596     _Py_END_SUPPRESS_IPH
10597     Py_END_ALLOW_THREADS
10598     if (result < 0)
10599         return posix_path_error(path);
10600 
10601     Py_RETURN_NONE;
10602 }
10603 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10604 
10605 
10606 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10607    and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10608    defined, which is the case in Python on AIX. AIX bug report:
10609    http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10610 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10611 #  define POSIX_FADVISE_AIX_BUG
10612 #endif
10613 
10614 
10615 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10616 /*[clinic input]
10617 os.posix_fallocate
10618 
10619     fd: int
10620     offset: Py_off_t
10621     length: Py_off_t
10622     /
10623 
10624 Ensure a file has allocated at least a particular number of bytes on disk.
10625 
10626 Ensure that the file specified by fd encompasses a range of bytes
10627 starting at offset bytes from the beginning and continuing for length bytes.
10628 [clinic start generated code]*/
10629 
10630 static PyObject *
os_posix_fallocate_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length)10631 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10632                         Py_off_t length)
10633 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10634 {
10635     int result;
10636     int async_err = 0;
10637 
10638     do {
10639         Py_BEGIN_ALLOW_THREADS
10640         result = posix_fallocate(fd, offset, length);
10641         Py_END_ALLOW_THREADS
10642     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10643 
10644     if (result == 0)
10645         Py_RETURN_NONE;
10646 
10647     if (async_err)
10648         return NULL;
10649 
10650     errno = result;
10651     return posix_error();
10652 }
10653 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
10654 
10655 
10656 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
10657 /*[clinic input]
10658 os.posix_fadvise
10659 
10660     fd: int
10661     offset: Py_off_t
10662     length: Py_off_t
10663     advice: int
10664     /
10665 
10666 Announce an intention to access data in a specific pattern.
10667 
10668 Announce an intention to access data in a specific pattern, thus allowing
10669 the kernel to make optimizations.
10670 The advice applies to the region of the file specified by fd starting at
10671 offset and continuing for length bytes.
10672 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
10673 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
10674 POSIX_FADV_DONTNEED.
10675 [clinic start generated code]*/
10676 
10677 static PyObject *
os_posix_fadvise_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length,int advice)10678 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
10679                       Py_off_t length, int advice)
10680 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
10681 {
10682     int result;
10683     int async_err = 0;
10684 
10685     do {
10686         Py_BEGIN_ALLOW_THREADS
10687         result = posix_fadvise(fd, offset, length, advice);
10688         Py_END_ALLOW_THREADS
10689     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10690 
10691     if (result == 0)
10692         Py_RETURN_NONE;
10693 
10694     if (async_err)
10695         return NULL;
10696 
10697     errno = result;
10698     return posix_error();
10699 }
10700 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
10701 
10702 
10703 #ifdef MS_WINDOWS
10704 static PyObject*
win32_putenv(PyObject * name,PyObject * value)10705 win32_putenv(PyObject *name, PyObject *value)
10706 {
10707     /* Search from index 1 because on Windows starting '=' is allowed for
10708        defining hidden environment variables. */
10709     if (PyUnicode_GET_LENGTH(name) == 0 ||
10710         PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
10711     {
10712         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10713         return NULL;
10714     }
10715     PyObject *unicode;
10716     if (value != NULL) {
10717         unicode = PyUnicode_FromFormat("%U=%U", name, value);
10718     }
10719     else {
10720         unicode = PyUnicode_FromFormat("%U=", name);
10721     }
10722     if (unicode == NULL) {
10723         return NULL;
10724     }
10725 
10726     Py_ssize_t size;
10727     /* PyUnicode_AsWideCharString() rejects embedded null characters */
10728     wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
10729     Py_DECREF(unicode);
10730 
10731     if (env == NULL) {
10732         return NULL;
10733     }
10734     if (size > _MAX_ENV) {
10735         PyErr_Format(PyExc_ValueError,
10736                      "the environment variable is longer than %u characters",
10737                      _MAX_ENV);
10738         PyMem_Free(env);
10739         return NULL;
10740     }
10741 
10742     /* _wputenv() and SetEnvironmentVariableW() update the environment in the
10743        Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
10744        and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
10745 
10746        Prefer _wputenv() to be compatible with C libraries using CRT
10747        variables and CRT functions using these variables (ex: getenv()). */
10748     int err = _wputenv(env);
10749     PyMem_Free(env);
10750 
10751     if (err) {
10752         posix_error();
10753         return NULL;
10754     }
10755 
10756     Py_RETURN_NONE;
10757 }
10758 #endif
10759 
10760 
10761 #ifdef MS_WINDOWS
10762 /*[clinic input]
10763 os.putenv
10764 
10765     name: unicode
10766     value: unicode
10767     /
10768 
10769 Change or add an environment variable.
10770 [clinic start generated code]*/
10771 
10772 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10773 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10774 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
10775 {
10776     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10777         return NULL;
10778     }
10779     return win32_putenv(name, value);
10780 }
10781 #else
10782 /*[clinic input]
10783 os.putenv
10784 
10785     name: FSConverter
10786     value: FSConverter
10787     /
10788 
10789 Change or add an environment variable.
10790 [clinic start generated code]*/
10791 
10792 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10793 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10794 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
10795 {
10796     const char *name_string = PyBytes_AS_STRING(name);
10797     const char *value_string = PyBytes_AS_STRING(value);
10798 
10799     if (strchr(name_string, '=') != NULL) {
10800         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10801         return NULL;
10802     }
10803 
10804     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10805         return NULL;
10806     }
10807 
10808     if (setenv(name_string, value_string, 1)) {
10809         return posix_error();
10810     }
10811     Py_RETURN_NONE;
10812 }
10813 #endif  /* !defined(MS_WINDOWS) */
10814 
10815 
10816 #ifdef MS_WINDOWS
10817 /*[clinic input]
10818 os.unsetenv
10819     name: unicode
10820     /
10821 
10822 Delete an environment variable.
10823 [clinic start generated code]*/
10824 
10825 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)10826 os_unsetenv_impl(PyObject *module, PyObject *name)
10827 /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
10828 {
10829     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
10830         return NULL;
10831     }
10832     return win32_putenv(name, NULL);
10833 }
10834 #else
10835 /*[clinic input]
10836 os.unsetenv
10837     name: FSConverter
10838     /
10839 
10840 Delete an environment variable.
10841 [clinic start generated code]*/
10842 
10843 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)10844 os_unsetenv_impl(PyObject *module, PyObject *name)
10845 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
10846 {
10847     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
10848         return NULL;
10849     }
10850 #ifdef HAVE_BROKEN_UNSETENV
10851     unsetenv(PyBytes_AS_STRING(name));
10852 #else
10853     int err = unsetenv(PyBytes_AS_STRING(name));
10854     if (err) {
10855         return posix_error();
10856     }
10857 #endif
10858 
10859     Py_RETURN_NONE;
10860 }
10861 #endif /* !MS_WINDOWS */
10862 
10863 
10864 /*[clinic input]
10865 os.strerror
10866 
10867     code: int
10868     /
10869 
10870 Translate an error code to a message string.
10871 [clinic start generated code]*/
10872 
10873 static PyObject *
os_strerror_impl(PyObject * module,int code)10874 os_strerror_impl(PyObject *module, int code)
10875 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
10876 {
10877     char *message = strerror(code);
10878     if (message == NULL) {
10879         PyErr_SetString(PyExc_ValueError,
10880                         "strerror() argument out of range");
10881         return NULL;
10882     }
10883     return PyUnicode_DecodeLocale(message, "surrogateescape");
10884 }
10885 
10886 
10887 #ifdef HAVE_SYS_WAIT_H
10888 #ifdef WCOREDUMP
10889 /*[clinic input]
10890 os.WCOREDUMP -> bool
10891 
10892     status: int
10893     /
10894 
10895 Return True if the process returning status was dumped to a core file.
10896 [clinic start generated code]*/
10897 
10898 static int
os_WCOREDUMP_impl(PyObject * module,int status)10899 os_WCOREDUMP_impl(PyObject *module, int status)
10900 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
10901 {
10902     WAIT_TYPE wait_status;
10903     WAIT_STATUS_INT(wait_status) = status;
10904     return WCOREDUMP(wait_status);
10905 }
10906 #endif /* WCOREDUMP */
10907 
10908 
10909 #ifdef WIFCONTINUED
10910 /*[clinic input]
10911 os.WIFCONTINUED -> bool
10912 
10913     status: int
10914 
10915 Return True if a particular process was continued from a job control stop.
10916 
10917 Return True if the process returning status was continued from a
10918 job control stop.
10919 [clinic start generated code]*/
10920 
10921 static int
os_WIFCONTINUED_impl(PyObject * module,int status)10922 os_WIFCONTINUED_impl(PyObject *module, int status)
10923 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
10924 {
10925     WAIT_TYPE wait_status;
10926     WAIT_STATUS_INT(wait_status) = status;
10927     return WIFCONTINUED(wait_status);
10928 }
10929 #endif /* WIFCONTINUED */
10930 
10931 
10932 #ifdef WIFSTOPPED
10933 /*[clinic input]
10934 os.WIFSTOPPED -> bool
10935 
10936     status: int
10937 
10938 Return True if the process returning status was stopped.
10939 [clinic start generated code]*/
10940 
10941 static int
os_WIFSTOPPED_impl(PyObject * module,int status)10942 os_WIFSTOPPED_impl(PyObject *module, int status)
10943 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
10944 {
10945     WAIT_TYPE wait_status;
10946     WAIT_STATUS_INT(wait_status) = status;
10947     return WIFSTOPPED(wait_status);
10948 }
10949 #endif /* WIFSTOPPED */
10950 
10951 
10952 #ifdef WIFSIGNALED
10953 /*[clinic input]
10954 os.WIFSIGNALED -> bool
10955 
10956     status: int
10957 
10958 Return True if the process returning status was terminated by a signal.
10959 [clinic start generated code]*/
10960 
10961 static int
os_WIFSIGNALED_impl(PyObject * module,int status)10962 os_WIFSIGNALED_impl(PyObject *module, int status)
10963 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
10964 {
10965     WAIT_TYPE wait_status;
10966     WAIT_STATUS_INT(wait_status) = status;
10967     return WIFSIGNALED(wait_status);
10968 }
10969 #endif /* WIFSIGNALED */
10970 
10971 
10972 #ifdef WIFEXITED
10973 /*[clinic input]
10974 os.WIFEXITED -> bool
10975 
10976     status: int
10977 
10978 Return True if the process returning status exited via the exit() system call.
10979 [clinic start generated code]*/
10980 
10981 static int
os_WIFEXITED_impl(PyObject * module,int status)10982 os_WIFEXITED_impl(PyObject *module, int status)
10983 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
10984 {
10985     WAIT_TYPE wait_status;
10986     WAIT_STATUS_INT(wait_status) = status;
10987     return WIFEXITED(wait_status);
10988 }
10989 #endif /* WIFEXITED */
10990 
10991 
10992 #ifdef WEXITSTATUS
10993 /*[clinic input]
10994 os.WEXITSTATUS -> int
10995 
10996     status: int
10997 
10998 Return the process return code from status.
10999 [clinic start generated code]*/
11000 
11001 static int
os_WEXITSTATUS_impl(PyObject * module,int status)11002 os_WEXITSTATUS_impl(PyObject *module, int status)
11003 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
11004 {
11005     WAIT_TYPE wait_status;
11006     WAIT_STATUS_INT(wait_status) = status;
11007     return WEXITSTATUS(wait_status);
11008 }
11009 #endif /* WEXITSTATUS */
11010 
11011 
11012 #ifdef WTERMSIG
11013 /*[clinic input]
11014 os.WTERMSIG -> int
11015 
11016     status: int
11017 
11018 Return the signal that terminated the process that provided the status value.
11019 [clinic start generated code]*/
11020 
11021 static int
os_WTERMSIG_impl(PyObject * module,int status)11022 os_WTERMSIG_impl(PyObject *module, int status)
11023 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
11024 {
11025     WAIT_TYPE wait_status;
11026     WAIT_STATUS_INT(wait_status) = status;
11027     return WTERMSIG(wait_status);
11028 }
11029 #endif /* WTERMSIG */
11030 
11031 
11032 #ifdef WSTOPSIG
11033 /*[clinic input]
11034 os.WSTOPSIG -> int
11035 
11036     status: int
11037 
11038 Return the signal that stopped the process that provided the status value.
11039 [clinic start generated code]*/
11040 
11041 static int
os_WSTOPSIG_impl(PyObject * module,int status)11042 os_WSTOPSIG_impl(PyObject *module, int status)
11043 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
11044 {
11045     WAIT_TYPE wait_status;
11046     WAIT_STATUS_INT(wait_status) = status;
11047     return WSTOPSIG(wait_status);
11048 }
11049 #endif /* WSTOPSIG */
11050 #endif /* HAVE_SYS_WAIT_H */
11051 
11052 
11053 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
11054 #ifdef _SCO_DS
11055 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
11056    needed definitions in sys/statvfs.h */
11057 #define _SVID3
11058 #endif
11059 #include <sys/statvfs.h>
11060 
11061 static PyObject*
_pystatvfs_fromstructstatvfs(PyObject * module,struct statvfs st)11062 _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
11063     PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
11064     PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
11065     if (v == NULL)
11066         return NULL;
11067 
11068 #if !defined(HAVE_LARGEFILE_SUPPORT)
11069     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11070     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11071     PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
11072     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
11073     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
11074     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
11075     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
11076     PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
11077     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11078     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11079 #else
11080     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11081     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11082     PyStructSequence_SET_ITEM(v, 2,
11083                               PyLong_FromLongLong((long long) st.f_blocks));
11084     PyStructSequence_SET_ITEM(v, 3,
11085                               PyLong_FromLongLong((long long) st.f_bfree));
11086     PyStructSequence_SET_ITEM(v, 4,
11087                               PyLong_FromLongLong((long long) st.f_bavail));
11088     PyStructSequence_SET_ITEM(v, 5,
11089                               PyLong_FromLongLong((long long) st.f_files));
11090     PyStructSequence_SET_ITEM(v, 6,
11091                               PyLong_FromLongLong((long long) st.f_ffree));
11092     PyStructSequence_SET_ITEM(v, 7,
11093                               PyLong_FromLongLong((long long) st.f_favail));
11094     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11095     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11096 #endif
11097 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
11098  * (issue #32390). */
11099 #if defined(_AIX) && defined(_ALL_SOURCE)
11100     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
11101 #else
11102     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
11103 #endif
11104     if (PyErr_Occurred()) {
11105         Py_DECREF(v);
11106         return NULL;
11107     }
11108 
11109     return v;
11110 }
11111 
11112 
11113 /*[clinic input]
11114 os.fstatvfs
11115     fd: int
11116     /
11117 
11118 Perform an fstatvfs system call on the given fd.
11119 
11120 Equivalent to statvfs(fd).
11121 [clinic start generated code]*/
11122 
11123 static PyObject *
os_fstatvfs_impl(PyObject * module,int fd)11124 os_fstatvfs_impl(PyObject *module, int fd)
11125 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
11126 {
11127     int result;
11128     int async_err = 0;
11129     struct statvfs st;
11130 
11131     do {
11132         Py_BEGIN_ALLOW_THREADS
11133         result = fstatvfs(fd, &st);
11134         Py_END_ALLOW_THREADS
11135     } while (result != 0 && errno == EINTR &&
11136              !(async_err = PyErr_CheckSignals()));
11137     if (result != 0)
11138         return (!async_err) ? posix_error() : NULL;
11139 
11140     return _pystatvfs_fromstructstatvfs(module, st);
11141 }
11142 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
11143 
11144 
11145 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
11146 #include <sys/statvfs.h>
11147 /*[clinic input]
11148 os.statvfs
11149 
11150     path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
11151 
11152 Perform a statvfs system call on the given path.
11153 
11154 path may always be specified as a string.
11155 On some platforms, path may also be specified as an open file descriptor.
11156   If this functionality is unavailable, using it raises an exception.
11157 [clinic start generated code]*/
11158 
11159 static PyObject *
os_statvfs_impl(PyObject * module,path_t * path)11160 os_statvfs_impl(PyObject *module, path_t *path)
11161 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
11162 {
11163     int result;
11164     struct statvfs st;
11165 
11166     Py_BEGIN_ALLOW_THREADS
11167 #ifdef HAVE_FSTATVFS
11168     if (path->fd != -1) {
11169         result = fstatvfs(path->fd, &st);
11170     }
11171     else
11172 #endif
11173         result = statvfs(path->narrow, &st);
11174     Py_END_ALLOW_THREADS
11175 
11176     if (result) {
11177         return path_error(path);
11178     }
11179 
11180     return _pystatvfs_fromstructstatvfs(module, st);
11181 }
11182 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
11183 
11184 
11185 #ifdef MS_WINDOWS
11186 /*[clinic input]
11187 os._getdiskusage
11188 
11189     path: path_t
11190 
11191 Return disk usage statistics about the given path as a (total, free) tuple.
11192 [clinic start generated code]*/
11193 
11194 static PyObject *
os__getdiskusage_impl(PyObject * module,path_t * path)11195 os__getdiskusage_impl(PyObject *module, path_t *path)
11196 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
11197 {
11198     BOOL retval;
11199     ULARGE_INTEGER _, total, free;
11200     DWORD err = 0;
11201 
11202     Py_BEGIN_ALLOW_THREADS
11203     retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
11204     Py_END_ALLOW_THREADS
11205     if (retval == 0) {
11206         if (GetLastError() == ERROR_DIRECTORY) {
11207             wchar_t *dir_path = NULL;
11208 
11209             dir_path = PyMem_New(wchar_t, path->length + 1);
11210             if (dir_path == NULL) {
11211                 return PyErr_NoMemory();
11212             }
11213 
11214             wcscpy_s(dir_path, path->length + 1, path->wide);
11215 
11216             if (_dirnameW(dir_path) != -1) {
11217                 Py_BEGIN_ALLOW_THREADS
11218                 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
11219                 Py_END_ALLOW_THREADS
11220             }
11221             /* Record the last error in case it's modified by PyMem_Free. */
11222             err = GetLastError();
11223             PyMem_Free(dir_path);
11224             if (retval) {
11225                 goto success;
11226             }
11227         }
11228         return PyErr_SetFromWindowsErr(err);
11229     }
11230 
11231 success:
11232     return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
11233 }
11234 #endif /* MS_WINDOWS */
11235 
11236 
11237 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
11238  * It maps strings representing configuration variable names to
11239  * integer values, allowing those functions to be called with the
11240  * magic names instead of polluting the module's namespace with tons of
11241  * rarely-used constants.  There are three separate tables that use
11242  * these definitions.
11243  *
11244  * This code is always included, even if none of the interfaces that
11245  * need it are included.  The #if hackery needed to avoid it would be
11246  * sufficiently pervasive that it's not worth the loss of readability.
11247  */
11248 struct constdef {
11249     const char *name;
11250     int value;
11251 };
11252 
11253 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)11254 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
11255               size_t tablesize)
11256 {
11257     if (PyLong_Check(arg)) {
11258         int value = _PyLong_AsInt(arg);
11259         if (value == -1 && PyErr_Occurred())
11260             return 0;
11261         *valuep = value;
11262         return 1;
11263     }
11264     else {
11265         /* look up the value in the table using a binary search */
11266         size_t lo = 0;
11267         size_t mid;
11268         size_t hi = tablesize;
11269         int cmp;
11270         const char *confname;
11271         if (!PyUnicode_Check(arg)) {
11272             PyErr_SetString(PyExc_TypeError,
11273                 "configuration names must be strings or integers");
11274             return 0;
11275         }
11276         confname = PyUnicode_AsUTF8(arg);
11277         if (confname == NULL)
11278             return 0;
11279         while (lo < hi) {
11280             mid = (lo + hi) / 2;
11281             cmp = strcmp(confname, table[mid].name);
11282             if (cmp < 0)
11283                 hi = mid;
11284             else if (cmp > 0)
11285                 lo = mid + 1;
11286             else {
11287                 *valuep = table[mid].value;
11288                 return 1;
11289             }
11290         }
11291         PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
11292         return 0;
11293     }
11294 }
11295 
11296 
11297 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11298 static struct constdef  posix_constants_pathconf[] = {
11299 #ifdef _PC_ABI_AIO_XFER_MAX
11300     {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
11301 #endif
11302 #ifdef _PC_ABI_ASYNC_IO
11303     {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
11304 #endif
11305 #ifdef _PC_ASYNC_IO
11306     {"PC_ASYNC_IO",     _PC_ASYNC_IO},
11307 #endif
11308 #ifdef _PC_CHOWN_RESTRICTED
11309     {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
11310 #endif
11311 #ifdef _PC_FILESIZEBITS
11312     {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
11313 #endif
11314 #ifdef _PC_LAST
11315     {"PC_LAST", _PC_LAST},
11316 #endif
11317 #ifdef _PC_LINK_MAX
11318     {"PC_LINK_MAX",     _PC_LINK_MAX},
11319 #endif
11320 #ifdef _PC_MAX_CANON
11321     {"PC_MAX_CANON",    _PC_MAX_CANON},
11322 #endif
11323 #ifdef _PC_MAX_INPUT
11324     {"PC_MAX_INPUT",    _PC_MAX_INPUT},
11325 #endif
11326 #ifdef _PC_NAME_MAX
11327     {"PC_NAME_MAX",     _PC_NAME_MAX},
11328 #endif
11329 #ifdef _PC_NO_TRUNC
11330     {"PC_NO_TRUNC",     _PC_NO_TRUNC},
11331 #endif
11332 #ifdef _PC_PATH_MAX
11333     {"PC_PATH_MAX",     _PC_PATH_MAX},
11334 #endif
11335 #ifdef _PC_PIPE_BUF
11336     {"PC_PIPE_BUF",     _PC_PIPE_BUF},
11337 #endif
11338 #ifdef _PC_PRIO_IO
11339     {"PC_PRIO_IO",      _PC_PRIO_IO},
11340 #endif
11341 #ifdef _PC_SOCK_MAXBUF
11342     {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
11343 #endif
11344 #ifdef _PC_SYNC_IO
11345     {"PC_SYNC_IO",      _PC_SYNC_IO},
11346 #endif
11347 #ifdef _PC_VDISABLE
11348     {"PC_VDISABLE",     _PC_VDISABLE},
11349 #endif
11350 #ifdef _PC_ACL_ENABLED
11351     {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
11352 #endif
11353 #ifdef _PC_MIN_HOLE_SIZE
11354     {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
11355 #endif
11356 #ifdef _PC_ALLOC_SIZE_MIN
11357     {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
11358 #endif
11359 #ifdef _PC_REC_INCR_XFER_SIZE
11360     {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
11361 #endif
11362 #ifdef _PC_REC_MAX_XFER_SIZE
11363     {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
11364 #endif
11365 #ifdef _PC_REC_MIN_XFER_SIZE
11366     {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
11367 #endif
11368 #ifdef _PC_REC_XFER_ALIGN
11369     {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
11370 #endif
11371 #ifdef _PC_SYMLINK_MAX
11372     {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
11373 #endif
11374 #ifdef _PC_XATTR_ENABLED
11375     {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
11376 #endif
11377 #ifdef _PC_XATTR_EXISTS
11378     {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
11379 #endif
11380 #ifdef _PC_TIMESTAMP_RESOLUTION
11381     {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
11382 #endif
11383 };
11384 
11385 static int
conv_path_confname(PyObject * arg,int * valuep)11386 conv_path_confname(PyObject *arg, int *valuep)
11387 {
11388     return conv_confname(arg, valuep, posix_constants_pathconf,
11389                          sizeof(posix_constants_pathconf)
11390                            / sizeof(struct constdef));
11391 }
11392 #endif
11393 
11394 
11395 #ifdef HAVE_FPATHCONF
11396 /*[clinic input]
11397 os.fpathconf -> long
11398 
11399     fd: int
11400     name: path_confname
11401     /
11402 
11403 Return the configuration limit name for the file descriptor fd.
11404 
11405 If there is no limit, return -1.
11406 [clinic start generated code]*/
11407 
11408 static long
os_fpathconf_impl(PyObject * module,int fd,int name)11409 os_fpathconf_impl(PyObject *module, int fd, int name)
11410 /*[clinic end generated code: output=d5b7042425fc3e21 input=5942a024d3777810]*/
11411 {
11412     long limit;
11413 
11414     errno = 0;
11415     limit = fpathconf(fd, name);
11416     if (limit == -1 && errno != 0)
11417         posix_error();
11418 
11419     return limit;
11420 }
11421 #endif /* HAVE_FPATHCONF */
11422 
11423 
11424 #ifdef HAVE_PATHCONF
11425 /*[clinic input]
11426 os.pathconf -> long
11427     path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
11428     name: path_confname
11429 
11430 Return the configuration limit name for the file or directory path.
11431 
11432 If there is no limit, return -1.
11433 On some platforms, path may also be specified as an open file descriptor.
11434   If this functionality is unavailable, using it raises an exception.
11435 [clinic start generated code]*/
11436 
11437 static long
os_pathconf_impl(PyObject * module,path_t * path,int name)11438 os_pathconf_impl(PyObject *module, path_t *path, int name)
11439 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
11440 {
11441     long limit;
11442 
11443     errno = 0;
11444 #ifdef HAVE_FPATHCONF
11445     if (path->fd != -1)
11446         limit = fpathconf(path->fd, name);
11447     else
11448 #endif
11449         limit = pathconf(path->narrow, name);
11450     if (limit == -1 && errno != 0) {
11451         if (errno == EINVAL)
11452             /* could be a path or name problem */
11453             posix_error();
11454         else
11455             path_error(path);
11456     }
11457 
11458     return limit;
11459 }
11460 #endif /* HAVE_PATHCONF */
11461 
11462 #ifdef HAVE_CONFSTR
11463 static struct constdef posix_constants_confstr[] = {
11464 #ifdef _CS_ARCHITECTURE
11465     {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
11466 #endif
11467 #ifdef _CS_GNU_LIBC_VERSION
11468     {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
11469 #endif
11470 #ifdef _CS_GNU_LIBPTHREAD_VERSION
11471     {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
11472 #endif
11473 #ifdef _CS_HOSTNAME
11474     {"CS_HOSTNAME",     _CS_HOSTNAME},
11475 #endif
11476 #ifdef _CS_HW_PROVIDER
11477     {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
11478 #endif
11479 #ifdef _CS_HW_SERIAL
11480     {"CS_HW_SERIAL",    _CS_HW_SERIAL},
11481 #endif
11482 #ifdef _CS_INITTAB_NAME
11483     {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11484 #endif
11485 #ifdef _CS_LFS64_CFLAGS
11486     {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11487 #endif
11488 #ifdef _CS_LFS64_LDFLAGS
11489     {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
11490 #endif
11491 #ifdef _CS_LFS64_LIBS
11492     {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
11493 #endif
11494 #ifdef _CS_LFS64_LINTFLAGS
11495     {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
11496 #endif
11497 #ifdef _CS_LFS_CFLAGS
11498     {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
11499 #endif
11500 #ifdef _CS_LFS_LDFLAGS
11501     {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
11502 #endif
11503 #ifdef _CS_LFS_LIBS
11504     {"CS_LFS_LIBS",     _CS_LFS_LIBS},
11505 #endif
11506 #ifdef _CS_LFS_LINTFLAGS
11507     {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
11508 #endif
11509 #ifdef _CS_MACHINE
11510     {"CS_MACHINE",      _CS_MACHINE},
11511 #endif
11512 #ifdef _CS_PATH
11513     {"CS_PATH", _CS_PATH},
11514 #endif
11515 #ifdef _CS_RELEASE
11516     {"CS_RELEASE",      _CS_RELEASE},
11517 #endif
11518 #ifdef _CS_SRPC_DOMAIN
11519     {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
11520 #endif
11521 #ifdef _CS_SYSNAME
11522     {"CS_SYSNAME",      _CS_SYSNAME},
11523 #endif
11524 #ifdef _CS_VERSION
11525     {"CS_VERSION",      _CS_VERSION},
11526 #endif
11527 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11528     {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
11529 #endif
11530 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11531     {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
11532 #endif
11533 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11534     {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
11535 #endif
11536 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11537     {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11538 #endif
11539 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11540     {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11541 #endif
11542 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11543     {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11544 #endif
11545 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11546     {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
11547 #endif
11548 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11549     {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11550 #endif
11551 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11552     {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
11553 #endif
11554 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11555     {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
11556 #endif
11557 #ifdef _CS_XBS5_LP64_OFF64_LIBS
11558     {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11559 #endif
11560 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11561     {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
11562 #endif
11563 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11564     {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11565 #endif
11566 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11567     {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11568 #endif
11569 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11570     {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
11571 #endif
11572 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11573     {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11574 #endif
11575 #ifdef _MIPS_CS_AVAIL_PROCESSORS
11576     {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
11577 #endif
11578 #ifdef _MIPS_CS_BASE
11579     {"MIPS_CS_BASE",    _MIPS_CS_BASE},
11580 #endif
11581 #ifdef _MIPS_CS_HOSTID
11582     {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
11583 #endif
11584 #ifdef _MIPS_CS_HW_NAME
11585     {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11586 #endif
11587 #ifdef _MIPS_CS_NUM_PROCESSORS
11588     {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
11589 #endif
11590 #ifdef _MIPS_CS_OSREL_MAJ
11591     {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
11592 #endif
11593 #ifdef _MIPS_CS_OSREL_MIN
11594     {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
11595 #endif
11596 #ifdef _MIPS_CS_OSREL_PATCH
11597     {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
11598 #endif
11599 #ifdef _MIPS_CS_OS_NAME
11600     {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11601 #endif
11602 #ifdef _MIPS_CS_OS_PROVIDER
11603     {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
11604 #endif
11605 #ifdef _MIPS_CS_PROCESSORS
11606     {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
11607 #endif
11608 #ifdef _MIPS_CS_SERIAL
11609     {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
11610 #endif
11611 #ifdef _MIPS_CS_VENDOR
11612     {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
11613 #endif
11614 };
11615 
11616 static int
conv_confstr_confname(PyObject * arg,int * valuep)11617 conv_confstr_confname(PyObject *arg, int *valuep)
11618 {
11619     return conv_confname(arg, valuep, posix_constants_confstr,
11620                          sizeof(posix_constants_confstr)
11621                            / sizeof(struct constdef));
11622 }
11623 
11624 
11625 /*[clinic input]
11626 os.confstr
11627 
11628     name: confstr_confname
11629     /
11630 
11631 Return a string-valued system configuration variable.
11632 [clinic start generated code]*/
11633 
11634 static PyObject *
os_confstr_impl(PyObject * module,int name)11635 os_confstr_impl(PyObject *module, int name)
11636 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11637 {
11638     PyObject *result = NULL;
11639     char buffer[255];
11640     size_t len;
11641 
11642     errno = 0;
11643     len = confstr(name, buffer, sizeof(buffer));
11644     if (len == 0) {
11645         if (errno) {
11646             posix_error();
11647             return NULL;
11648         }
11649         else {
11650             Py_RETURN_NONE;
11651         }
11652     }
11653 
11654     if (len >= sizeof(buffer)) {
11655         size_t len2;
11656         char *buf = PyMem_Malloc(len);
11657         if (buf == NULL)
11658             return PyErr_NoMemory();
11659         len2 = confstr(name, buf, len);
11660         assert(len == len2);
11661         result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11662         PyMem_Free(buf);
11663     }
11664     else
11665         result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11666     return result;
11667 }
11668 #endif /* HAVE_CONFSTR */
11669 
11670 
11671 #ifdef HAVE_SYSCONF
11672 static struct constdef posix_constants_sysconf[] = {
11673 #ifdef _SC_2_CHAR_TERM
11674     {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
11675 #endif
11676 #ifdef _SC_2_C_BIND
11677     {"SC_2_C_BIND",     _SC_2_C_BIND},
11678 #endif
11679 #ifdef _SC_2_C_DEV
11680     {"SC_2_C_DEV",      _SC_2_C_DEV},
11681 #endif
11682 #ifdef _SC_2_C_VERSION
11683     {"SC_2_C_VERSION",  _SC_2_C_VERSION},
11684 #endif
11685 #ifdef _SC_2_FORT_DEV
11686     {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
11687 #endif
11688 #ifdef _SC_2_FORT_RUN
11689     {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
11690 #endif
11691 #ifdef _SC_2_LOCALEDEF
11692     {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
11693 #endif
11694 #ifdef _SC_2_SW_DEV
11695     {"SC_2_SW_DEV",     _SC_2_SW_DEV},
11696 #endif
11697 #ifdef _SC_2_UPE
11698     {"SC_2_UPE",        _SC_2_UPE},
11699 #endif
11700 #ifdef _SC_2_VERSION
11701     {"SC_2_VERSION",    _SC_2_VERSION},
11702 #endif
11703 #ifdef _SC_ABI_ASYNCHRONOUS_IO
11704     {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
11705 #endif
11706 #ifdef _SC_ACL
11707     {"SC_ACL",  _SC_ACL},
11708 #endif
11709 #ifdef _SC_AIO_LISTIO_MAX
11710     {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
11711 #endif
11712 #ifdef _SC_AIO_MAX
11713     {"SC_AIO_MAX",      _SC_AIO_MAX},
11714 #endif
11715 #ifdef _SC_AIO_PRIO_DELTA_MAX
11716     {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
11717 #endif
11718 #ifdef _SC_ARG_MAX
11719     {"SC_ARG_MAX",      _SC_ARG_MAX},
11720 #endif
11721 #ifdef _SC_ASYNCHRONOUS_IO
11722     {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
11723 #endif
11724 #ifdef _SC_ATEXIT_MAX
11725     {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
11726 #endif
11727 #ifdef _SC_AUDIT
11728     {"SC_AUDIT",        _SC_AUDIT},
11729 #endif
11730 #ifdef _SC_AVPHYS_PAGES
11731     {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
11732 #endif
11733 #ifdef _SC_BC_BASE_MAX
11734     {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
11735 #endif
11736 #ifdef _SC_BC_DIM_MAX
11737     {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
11738 #endif
11739 #ifdef _SC_BC_SCALE_MAX
11740     {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
11741 #endif
11742 #ifdef _SC_BC_STRING_MAX
11743     {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
11744 #endif
11745 #ifdef _SC_CAP
11746     {"SC_CAP",  _SC_CAP},
11747 #endif
11748 #ifdef _SC_CHARCLASS_NAME_MAX
11749     {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
11750 #endif
11751 #ifdef _SC_CHAR_BIT
11752     {"SC_CHAR_BIT",     _SC_CHAR_BIT},
11753 #endif
11754 #ifdef _SC_CHAR_MAX
11755     {"SC_CHAR_MAX",     _SC_CHAR_MAX},
11756 #endif
11757 #ifdef _SC_CHAR_MIN
11758     {"SC_CHAR_MIN",     _SC_CHAR_MIN},
11759 #endif
11760 #ifdef _SC_CHILD_MAX
11761     {"SC_CHILD_MAX",    _SC_CHILD_MAX},
11762 #endif
11763 #ifdef _SC_CLK_TCK
11764     {"SC_CLK_TCK",      _SC_CLK_TCK},
11765 #endif
11766 #ifdef _SC_COHER_BLKSZ
11767     {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
11768 #endif
11769 #ifdef _SC_COLL_WEIGHTS_MAX
11770     {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
11771 #endif
11772 #ifdef _SC_DCACHE_ASSOC
11773     {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
11774 #endif
11775 #ifdef _SC_DCACHE_BLKSZ
11776     {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
11777 #endif
11778 #ifdef _SC_DCACHE_LINESZ
11779     {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
11780 #endif
11781 #ifdef _SC_DCACHE_SZ
11782     {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
11783 #endif
11784 #ifdef _SC_DCACHE_TBLKSZ
11785     {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
11786 #endif
11787 #ifdef _SC_DELAYTIMER_MAX
11788     {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
11789 #endif
11790 #ifdef _SC_EQUIV_CLASS_MAX
11791     {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
11792 #endif
11793 #ifdef _SC_EXPR_NEST_MAX
11794     {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
11795 #endif
11796 #ifdef _SC_FSYNC
11797     {"SC_FSYNC",        _SC_FSYNC},
11798 #endif
11799 #ifdef _SC_GETGR_R_SIZE_MAX
11800     {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
11801 #endif
11802 #ifdef _SC_GETPW_R_SIZE_MAX
11803     {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
11804 #endif
11805 #ifdef _SC_ICACHE_ASSOC
11806     {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
11807 #endif
11808 #ifdef _SC_ICACHE_BLKSZ
11809     {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
11810 #endif
11811 #ifdef _SC_ICACHE_LINESZ
11812     {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
11813 #endif
11814 #ifdef _SC_ICACHE_SZ
11815     {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
11816 #endif
11817 #ifdef _SC_INF
11818     {"SC_INF",  _SC_INF},
11819 #endif
11820 #ifdef _SC_INT_MAX
11821     {"SC_INT_MAX",      _SC_INT_MAX},
11822 #endif
11823 #ifdef _SC_INT_MIN
11824     {"SC_INT_MIN",      _SC_INT_MIN},
11825 #endif
11826 #ifdef _SC_IOV_MAX
11827     {"SC_IOV_MAX",      _SC_IOV_MAX},
11828 #endif
11829 #ifdef _SC_IP_SECOPTS
11830     {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
11831 #endif
11832 #ifdef _SC_JOB_CONTROL
11833     {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
11834 #endif
11835 #ifdef _SC_KERN_POINTERS
11836     {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
11837 #endif
11838 #ifdef _SC_KERN_SIM
11839     {"SC_KERN_SIM",     _SC_KERN_SIM},
11840 #endif
11841 #ifdef _SC_LINE_MAX
11842     {"SC_LINE_MAX",     _SC_LINE_MAX},
11843 #endif
11844 #ifdef _SC_LOGIN_NAME_MAX
11845     {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
11846 #endif
11847 #ifdef _SC_LOGNAME_MAX
11848     {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
11849 #endif
11850 #ifdef _SC_LONG_BIT
11851     {"SC_LONG_BIT",     _SC_LONG_BIT},
11852 #endif
11853 #ifdef _SC_MAC
11854     {"SC_MAC",  _SC_MAC},
11855 #endif
11856 #ifdef _SC_MAPPED_FILES
11857     {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
11858 #endif
11859 #ifdef _SC_MAXPID
11860     {"SC_MAXPID",       _SC_MAXPID},
11861 #endif
11862 #ifdef _SC_MB_LEN_MAX
11863     {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
11864 #endif
11865 #ifdef _SC_MEMLOCK
11866     {"SC_MEMLOCK",      _SC_MEMLOCK},
11867 #endif
11868 #ifdef _SC_MEMLOCK_RANGE
11869     {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
11870 #endif
11871 #ifdef _SC_MEMORY_PROTECTION
11872     {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
11873 #endif
11874 #ifdef _SC_MESSAGE_PASSING
11875     {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
11876 #endif
11877 #ifdef _SC_MMAP_FIXED_ALIGNMENT
11878     {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
11879 #endif
11880 #ifdef _SC_MQ_OPEN_MAX
11881     {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
11882 #endif
11883 #ifdef _SC_MQ_PRIO_MAX
11884     {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
11885 #endif
11886 #ifdef _SC_NACLS_MAX
11887     {"SC_NACLS_MAX",    _SC_NACLS_MAX},
11888 #endif
11889 #ifdef _SC_NGROUPS_MAX
11890     {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
11891 #endif
11892 #ifdef _SC_NL_ARGMAX
11893     {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
11894 #endif
11895 #ifdef _SC_NL_LANGMAX
11896     {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
11897 #endif
11898 #ifdef _SC_NL_MSGMAX
11899     {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
11900 #endif
11901 #ifdef _SC_NL_NMAX
11902     {"SC_NL_NMAX",      _SC_NL_NMAX},
11903 #endif
11904 #ifdef _SC_NL_SETMAX
11905     {"SC_NL_SETMAX",    _SC_NL_SETMAX},
11906 #endif
11907 #ifdef _SC_NL_TEXTMAX
11908     {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
11909 #endif
11910 #ifdef _SC_NPROCESSORS_CONF
11911     {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
11912 #endif
11913 #ifdef _SC_NPROCESSORS_ONLN
11914     {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
11915 #endif
11916 #ifdef _SC_NPROC_CONF
11917     {"SC_NPROC_CONF",   _SC_NPROC_CONF},
11918 #endif
11919 #ifdef _SC_NPROC_ONLN
11920     {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
11921 #endif
11922 #ifdef _SC_NZERO
11923     {"SC_NZERO",        _SC_NZERO},
11924 #endif
11925 #ifdef _SC_OPEN_MAX
11926     {"SC_OPEN_MAX",     _SC_OPEN_MAX},
11927 #endif
11928 #ifdef _SC_PAGESIZE
11929     {"SC_PAGESIZE",     _SC_PAGESIZE},
11930 #endif
11931 #ifdef _SC_PAGE_SIZE
11932     {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
11933 #endif
11934 #ifdef _SC_AIX_REALMEM
11935     {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
11936 #endif
11937 #ifdef _SC_PASS_MAX
11938     {"SC_PASS_MAX",     _SC_PASS_MAX},
11939 #endif
11940 #ifdef _SC_PHYS_PAGES
11941     {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
11942 #endif
11943 #ifdef _SC_PII
11944     {"SC_PII",  _SC_PII},
11945 #endif
11946 #ifdef _SC_PII_INTERNET
11947     {"SC_PII_INTERNET", _SC_PII_INTERNET},
11948 #endif
11949 #ifdef _SC_PII_INTERNET_DGRAM
11950     {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
11951 #endif
11952 #ifdef _SC_PII_INTERNET_STREAM
11953     {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
11954 #endif
11955 #ifdef _SC_PII_OSI
11956     {"SC_PII_OSI",      _SC_PII_OSI},
11957 #endif
11958 #ifdef _SC_PII_OSI_CLTS
11959     {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
11960 #endif
11961 #ifdef _SC_PII_OSI_COTS
11962     {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
11963 #endif
11964 #ifdef _SC_PII_OSI_M
11965     {"SC_PII_OSI_M",    _SC_PII_OSI_M},
11966 #endif
11967 #ifdef _SC_PII_SOCKET
11968     {"SC_PII_SOCKET",   _SC_PII_SOCKET},
11969 #endif
11970 #ifdef _SC_PII_XTI
11971     {"SC_PII_XTI",      _SC_PII_XTI},
11972 #endif
11973 #ifdef _SC_POLL
11974     {"SC_POLL", _SC_POLL},
11975 #endif
11976 #ifdef _SC_PRIORITIZED_IO
11977     {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
11978 #endif
11979 #ifdef _SC_PRIORITY_SCHEDULING
11980     {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
11981 #endif
11982 #ifdef _SC_REALTIME_SIGNALS
11983     {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
11984 #endif
11985 #ifdef _SC_RE_DUP_MAX
11986     {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
11987 #endif
11988 #ifdef _SC_RTSIG_MAX
11989     {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
11990 #endif
11991 #ifdef _SC_SAVED_IDS
11992     {"SC_SAVED_IDS",    _SC_SAVED_IDS},
11993 #endif
11994 #ifdef _SC_SCHAR_MAX
11995     {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
11996 #endif
11997 #ifdef _SC_SCHAR_MIN
11998     {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
11999 #endif
12000 #ifdef _SC_SELECT
12001     {"SC_SELECT",       _SC_SELECT},
12002 #endif
12003 #ifdef _SC_SEMAPHORES
12004     {"SC_SEMAPHORES",   _SC_SEMAPHORES},
12005 #endif
12006 #ifdef _SC_SEM_NSEMS_MAX
12007     {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
12008 #endif
12009 #ifdef _SC_SEM_VALUE_MAX
12010     {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
12011 #endif
12012 #ifdef _SC_SHARED_MEMORY_OBJECTS
12013     {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
12014 #endif
12015 #ifdef _SC_SHRT_MAX
12016     {"SC_SHRT_MAX",     _SC_SHRT_MAX},
12017 #endif
12018 #ifdef _SC_SHRT_MIN
12019     {"SC_SHRT_MIN",     _SC_SHRT_MIN},
12020 #endif
12021 #ifdef _SC_SIGQUEUE_MAX
12022     {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
12023 #endif
12024 #ifdef _SC_SIGRT_MAX
12025     {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
12026 #endif
12027 #ifdef _SC_SIGRT_MIN
12028     {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
12029 #endif
12030 #ifdef _SC_SOFTPOWER
12031     {"SC_SOFTPOWER",    _SC_SOFTPOWER},
12032 #endif
12033 #ifdef _SC_SPLIT_CACHE
12034     {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
12035 #endif
12036 #ifdef _SC_SSIZE_MAX
12037     {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
12038 #endif
12039 #ifdef _SC_STACK_PROT
12040     {"SC_STACK_PROT",   _SC_STACK_PROT},
12041 #endif
12042 #ifdef _SC_STREAM_MAX
12043     {"SC_STREAM_MAX",   _SC_STREAM_MAX},
12044 #endif
12045 #ifdef _SC_SYNCHRONIZED_IO
12046     {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
12047 #endif
12048 #ifdef _SC_THREADS
12049     {"SC_THREADS",      _SC_THREADS},
12050 #endif
12051 #ifdef _SC_THREAD_ATTR_STACKADDR
12052     {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
12053 #endif
12054 #ifdef _SC_THREAD_ATTR_STACKSIZE
12055     {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
12056 #endif
12057 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
12058     {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
12059 #endif
12060 #ifdef _SC_THREAD_KEYS_MAX
12061     {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
12062 #endif
12063 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
12064     {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
12065 #endif
12066 #ifdef _SC_THREAD_PRIO_INHERIT
12067     {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
12068 #endif
12069 #ifdef _SC_THREAD_PRIO_PROTECT
12070     {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
12071 #endif
12072 #ifdef _SC_THREAD_PROCESS_SHARED
12073     {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
12074 #endif
12075 #ifdef _SC_THREAD_SAFE_FUNCTIONS
12076     {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
12077 #endif
12078 #ifdef _SC_THREAD_STACK_MIN
12079     {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
12080 #endif
12081 #ifdef _SC_THREAD_THREADS_MAX
12082     {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
12083 #endif
12084 #ifdef _SC_TIMERS
12085     {"SC_TIMERS",       _SC_TIMERS},
12086 #endif
12087 #ifdef _SC_TIMER_MAX
12088     {"SC_TIMER_MAX",    _SC_TIMER_MAX},
12089 #endif
12090 #ifdef _SC_TTY_NAME_MAX
12091     {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
12092 #endif
12093 #ifdef _SC_TZNAME_MAX
12094     {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
12095 #endif
12096 #ifdef _SC_T_IOV_MAX
12097     {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
12098 #endif
12099 #ifdef _SC_UCHAR_MAX
12100     {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
12101 #endif
12102 #ifdef _SC_UINT_MAX
12103     {"SC_UINT_MAX",     _SC_UINT_MAX},
12104 #endif
12105 #ifdef _SC_UIO_MAXIOV
12106     {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
12107 #endif
12108 #ifdef _SC_ULONG_MAX
12109     {"SC_ULONG_MAX",    _SC_ULONG_MAX},
12110 #endif
12111 #ifdef _SC_USHRT_MAX
12112     {"SC_USHRT_MAX",    _SC_USHRT_MAX},
12113 #endif
12114 #ifdef _SC_VERSION
12115     {"SC_VERSION",      _SC_VERSION},
12116 #endif
12117 #ifdef _SC_WORD_BIT
12118     {"SC_WORD_BIT",     _SC_WORD_BIT},
12119 #endif
12120 #ifdef _SC_XBS5_ILP32_OFF32
12121     {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
12122 #endif
12123 #ifdef _SC_XBS5_ILP32_OFFBIG
12124     {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
12125 #endif
12126 #ifdef _SC_XBS5_LP64_OFF64
12127     {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
12128 #endif
12129 #ifdef _SC_XBS5_LPBIG_OFFBIG
12130     {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
12131 #endif
12132 #ifdef _SC_XOPEN_CRYPT
12133     {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
12134 #endif
12135 #ifdef _SC_XOPEN_ENH_I18N
12136     {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
12137 #endif
12138 #ifdef _SC_XOPEN_LEGACY
12139     {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
12140 #endif
12141 #ifdef _SC_XOPEN_REALTIME
12142     {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
12143 #endif
12144 #ifdef _SC_XOPEN_REALTIME_THREADS
12145     {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
12146 #endif
12147 #ifdef _SC_XOPEN_SHM
12148     {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
12149 #endif
12150 #ifdef _SC_XOPEN_UNIX
12151     {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
12152 #endif
12153 #ifdef _SC_XOPEN_VERSION
12154     {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
12155 #endif
12156 #ifdef _SC_XOPEN_XCU_VERSION
12157     {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
12158 #endif
12159 #ifdef _SC_XOPEN_XPG2
12160     {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
12161 #endif
12162 #ifdef _SC_XOPEN_XPG3
12163     {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
12164 #endif
12165 #ifdef _SC_XOPEN_XPG4
12166     {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
12167 #endif
12168 };
12169 
12170 static int
conv_sysconf_confname(PyObject * arg,int * valuep)12171 conv_sysconf_confname(PyObject *arg, int *valuep)
12172 {
12173     return conv_confname(arg, valuep, posix_constants_sysconf,
12174                          sizeof(posix_constants_sysconf)
12175                            / sizeof(struct constdef));
12176 }
12177 
12178 
12179 /*[clinic input]
12180 os.sysconf -> long
12181     name: sysconf_confname
12182     /
12183 
12184 Return an integer-valued system configuration variable.
12185 [clinic start generated code]*/
12186 
12187 static long
os_sysconf_impl(PyObject * module,int name)12188 os_sysconf_impl(PyObject *module, int name)
12189 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
12190 {
12191     long value;
12192 
12193     errno = 0;
12194     value = sysconf(name);
12195     if (value == -1 && errno != 0)
12196         posix_error();
12197     return value;
12198 }
12199 #endif /* HAVE_SYSCONF */
12200 
12201 
12202 /* This code is used to ensure that the tables of configuration value names
12203  * are in sorted order as required by conv_confname(), and also to build
12204  * the exported dictionaries that are used to publish information about the
12205  * names available on the host platform.
12206  *
12207  * Sorting the table at runtime ensures that the table is properly ordered
12208  * when used, even for platforms we're not able to test on.  It also makes
12209  * it easier to add additional entries to the tables.
12210  */
12211 
12212 static int
cmp_constdefs(const void * v1,const void * v2)12213 cmp_constdefs(const void *v1,  const void *v2)
12214 {
12215     const struct constdef *c1 =
12216     (const struct constdef *) v1;
12217     const struct constdef *c2 =
12218     (const struct constdef *) v2;
12219 
12220     return strcmp(c1->name, c2->name);
12221 }
12222 
12223 static int
setup_confname_table(struct constdef * table,size_t tablesize,const char * tablename,PyObject * module)12224 setup_confname_table(struct constdef *table, size_t tablesize,
12225                      const char *tablename, PyObject *module)
12226 {
12227     PyObject *d = NULL;
12228     size_t i;
12229 
12230     qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
12231     d = PyDict_New();
12232     if (d == NULL)
12233         return -1;
12234 
12235     for (i=0; i < tablesize; ++i) {
12236         PyObject *o = PyLong_FromLong(table[i].value);
12237         if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
12238             Py_XDECREF(o);
12239             Py_DECREF(d);
12240             return -1;
12241         }
12242         Py_DECREF(o);
12243     }
12244     return PyModule_AddObject(module, tablename, d);
12245 }
12246 
12247 /* Return -1 on failure, 0 on success. */
12248 static int
setup_confname_tables(PyObject * module)12249 setup_confname_tables(PyObject *module)
12250 {
12251 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12252     if (setup_confname_table(posix_constants_pathconf,
12253                              sizeof(posix_constants_pathconf)
12254                                / sizeof(struct constdef),
12255                              "pathconf_names", module))
12256         return -1;
12257 #endif
12258 #ifdef HAVE_CONFSTR
12259     if (setup_confname_table(posix_constants_confstr,
12260                              sizeof(posix_constants_confstr)
12261                                / sizeof(struct constdef),
12262                              "confstr_names", module))
12263         return -1;
12264 #endif
12265 #ifdef HAVE_SYSCONF
12266     if (setup_confname_table(posix_constants_sysconf,
12267                              sizeof(posix_constants_sysconf)
12268                                / sizeof(struct constdef),
12269                              "sysconf_names", module))
12270         return -1;
12271 #endif
12272     return 0;
12273 }
12274 
12275 
12276 /*[clinic input]
12277 os.abort
12278 
12279 Abort the interpreter immediately.
12280 
12281 This function 'dumps core' or otherwise fails in the hardest way possible
12282 on the hosting operating system.  This function never returns.
12283 [clinic start generated code]*/
12284 
12285 static PyObject *
os_abort_impl(PyObject * module)12286 os_abort_impl(PyObject *module)
12287 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
12288 {
12289     abort();
12290     /*NOTREACHED*/
12291 #ifndef __clang__
12292     /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
12293        GCC emits a warning without "return NULL;" (compiler bug?), but Clang
12294        is smarter and emits a warning on the return. */
12295     Py_FatalError("abort() called from Python code didn't abort!");
12296     return NULL;
12297 #endif
12298 }
12299 
12300 #ifdef MS_WINDOWS
12301 /* Grab ShellExecute dynamically from shell32 */
12302 static int has_ShellExecute = -1;
12303 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
12304                                               LPCWSTR, INT);
12305 static int
check_ShellExecute()12306 check_ShellExecute()
12307 {
12308     HINSTANCE hShell32;
12309 
12310     /* only recheck */
12311     if (-1 == has_ShellExecute) {
12312         Py_BEGIN_ALLOW_THREADS
12313         /* Security note: this call is not vulnerable to "DLL hijacking".
12314            SHELL32 is part of "KnownDLLs" and so Windows always load
12315            the system SHELL32.DLL, even if there is another SHELL32.DLL
12316            in the DLL search path. */
12317         hShell32 = LoadLibraryW(L"SHELL32");
12318         if (hShell32) {
12319             *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
12320                                             "ShellExecuteW");
12321             has_ShellExecute = Py_ShellExecuteW != NULL;
12322         } else {
12323             has_ShellExecute = 0;
12324         }
12325         Py_END_ALLOW_THREADS
12326     }
12327     return has_ShellExecute;
12328 }
12329 
12330 
12331 /*[clinic input]
12332 os.startfile
12333     filepath: path_t
12334     operation: Py_UNICODE = NULL
12335 
12336 Start a file with its associated application.
12337 
12338 When "operation" is not specified or "open", this acts like
12339 double-clicking the file in Explorer, or giving the file name as an
12340 argument to the DOS "start" command: the file is opened with whatever
12341 application (if any) its extension is associated.
12342 When another "operation" is given, it specifies what should be done with
12343 the file.  A typical operation is "print".
12344 
12345 startfile returns as soon as the associated application is launched.
12346 There is no option to wait for the application to close, and no way
12347 to retrieve the application's exit status.
12348 
12349 The filepath is relative to the current directory.  If you want to use
12350 an absolute path, make sure the first character is not a slash ("/");
12351 the underlying Win32 ShellExecute function doesn't work if it is.
12352 [clinic start generated code]*/
12353 
12354 static PyObject *
os_startfile_impl(PyObject * module,path_t * filepath,const Py_UNICODE * operation)12355 os_startfile_impl(PyObject *module, path_t *filepath,
12356                   const Py_UNICODE *operation)
12357 /*[clinic end generated code: output=66dc311c94d50797 input=c940888a5390f039]*/
12358 {
12359     HINSTANCE rc;
12360 
12361     if(!check_ShellExecute()) {
12362         /* If the OS doesn't have ShellExecute, return a
12363            NotImplementedError. */
12364         return PyErr_Format(PyExc_NotImplementedError,
12365             "startfile not available on this platform");
12366     }
12367 
12368     if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
12369         return NULL;
12370     }
12371 
12372     Py_BEGIN_ALLOW_THREADS
12373     rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
12374                           NULL, NULL, SW_SHOWNORMAL);
12375     Py_END_ALLOW_THREADS
12376 
12377     if (rc <= (HINSTANCE)32) {
12378         win32_error_object("startfile", filepath->object);
12379         return NULL;
12380     }
12381     Py_RETURN_NONE;
12382 }
12383 #endif /* MS_WINDOWS */
12384 
12385 
12386 #ifdef HAVE_GETLOADAVG
12387 /*[clinic input]
12388 os.getloadavg
12389 
12390 Return average recent system load information.
12391 
12392 Return the number of processes in the system run queue averaged over
12393 the last 1, 5, and 15 minutes as a tuple of three floats.
12394 Raises OSError if the load average was unobtainable.
12395 [clinic start generated code]*/
12396 
12397 static PyObject *
os_getloadavg_impl(PyObject * module)12398 os_getloadavg_impl(PyObject *module)
12399 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
12400 {
12401     double loadavg[3];
12402     if (getloadavg(loadavg, 3)!=3) {
12403         PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
12404         return NULL;
12405     } else
12406         return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
12407 }
12408 #endif /* HAVE_GETLOADAVG */
12409 
12410 
12411 /*[clinic input]
12412 os.device_encoding
12413     fd: int
12414 
12415 Return a string describing the encoding of a terminal's file descriptor.
12416 
12417 The file descriptor must be attached to a terminal.
12418 If the device is not a terminal, return None.
12419 [clinic start generated code]*/
12420 
12421 static PyObject *
os_device_encoding_impl(PyObject * module,int fd)12422 os_device_encoding_impl(PyObject *module, int fd)
12423 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
12424 {
12425     return _Py_device_encoding(fd);
12426 }
12427 
12428 
12429 #ifdef HAVE_SETRESUID
12430 /*[clinic input]
12431 os.setresuid
12432 
12433     ruid: uid_t
12434     euid: uid_t
12435     suid: uid_t
12436     /
12437 
12438 Set the current process's real, effective, and saved user ids.
12439 [clinic start generated code]*/
12440 
12441 static PyObject *
os_setresuid_impl(PyObject * module,uid_t ruid,uid_t euid,uid_t suid)12442 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
12443 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
12444 {
12445     if (setresuid(ruid, euid, suid) < 0)
12446         return posix_error();
12447     Py_RETURN_NONE;
12448 }
12449 #endif /* HAVE_SETRESUID */
12450 
12451 
12452 #ifdef HAVE_SETRESGID
12453 /*[clinic input]
12454 os.setresgid
12455 
12456     rgid: gid_t
12457     egid: gid_t
12458     sgid: gid_t
12459     /
12460 
12461 Set the current process's real, effective, and saved group ids.
12462 [clinic start generated code]*/
12463 
12464 static PyObject *
os_setresgid_impl(PyObject * module,gid_t rgid,gid_t egid,gid_t sgid)12465 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
12466 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
12467 {
12468     if (setresgid(rgid, egid, sgid) < 0)
12469         return posix_error();
12470     Py_RETURN_NONE;
12471 }
12472 #endif /* HAVE_SETRESGID */
12473 
12474 
12475 #ifdef HAVE_GETRESUID
12476 /*[clinic input]
12477 os.getresuid
12478 
12479 Return a tuple of the current process's real, effective, and saved user ids.
12480 [clinic start generated code]*/
12481 
12482 static PyObject *
os_getresuid_impl(PyObject * module)12483 os_getresuid_impl(PyObject *module)
12484 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12485 {
12486     uid_t ruid, euid, suid;
12487     if (getresuid(&ruid, &euid, &suid) < 0)
12488         return posix_error();
12489     return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12490                                   _PyLong_FromUid(euid),
12491                                   _PyLong_FromUid(suid));
12492 }
12493 #endif /* HAVE_GETRESUID */
12494 
12495 
12496 #ifdef HAVE_GETRESGID
12497 /*[clinic input]
12498 os.getresgid
12499 
12500 Return a tuple of the current process's real, effective, and saved group ids.
12501 [clinic start generated code]*/
12502 
12503 static PyObject *
os_getresgid_impl(PyObject * module)12504 os_getresgid_impl(PyObject *module)
12505 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12506 {
12507     gid_t rgid, egid, sgid;
12508     if (getresgid(&rgid, &egid, &sgid) < 0)
12509         return posix_error();
12510     return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12511                                   _PyLong_FromGid(egid),
12512                                   _PyLong_FromGid(sgid));
12513 }
12514 #endif /* HAVE_GETRESGID */
12515 
12516 
12517 #ifdef USE_XATTRS
12518 /*[clinic input]
12519 os.getxattr
12520 
12521     path: path_t(allow_fd=True)
12522     attribute: path_t
12523     *
12524     follow_symlinks: bool = True
12525 
12526 Return the value of extended attribute attribute on path.
12527 
12528 path may be either a string, a path-like object, or an open file descriptor.
12529 If follow_symlinks is False, and the last element of the path is a symbolic
12530   link, getxattr will examine the symbolic link itself instead of the file
12531   the link points to.
12532 
12533 [clinic start generated code]*/
12534 
12535 static PyObject *
os_getxattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12536 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12537                  int follow_symlinks)
12538 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12539 {
12540     Py_ssize_t i;
12541     PyObject *buffer = NULL;
12542 
12543     if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12544         return NULL;
12545 
12546     if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12547         return NULL;
12548     }
12549 
12550     for (i = 0; ; i++) {
12551         void *ptr;
12552         ssize_t result;
12553         static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12554         Py_ssize_t buffer_size = buffer_sizes[i];
12555         if (!buffer_size) {
12556             path_error(path);
12557             return NULL;
12558         }
12559         buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12560         if (!buffer)
12561             return NULL;
12562         ptr = PyBytes_AS_STRING(buffer);
12563 
12564         Py_BEGIN_ALLOW_THREADS;
12565         if (path->fd >= 0)
12566             result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12567         else if (follow_symlinks)
12568             result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12569         else
12570             result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12571         Py_END_ALLOW_THREADS;
12572 
12573         if (result < 0) {
12574             Py_DECREF(buffer);
12575             if (errno == ERANGE)
12576                 continue;
12577             path_error(path);
12578             return NULL;
12579         }
12580 
12581         if (result != buffer_size) {
12582             /* Can only shrink. */
12583             _PyBytes_Resize(&buffer, result);
12584         }
12585         break;
12586     }
12587 
12588     return buffer;
12589 }
12590 
12591 
12592 /*[clinic input]
12593 os.setxattr
12594 
12595     path: path_t(allow_fd=True)
12596     attribute: path_t
12597     value: Py_buffer
12598     flags: int = 0
12599     *
12600     follow_symlinks: bool = True
12601 
12602 Set extended attribute attribute on path to value.
12603 
12604 path may be either a string, a path-like object,  or an open file descriptor.
12605 If follow_symlinks is False, and the last element of the path is a symbolic
12606   link, setxattr will modify the symbolic link itself instead of the file
12607   the link points to.
12608 
12609 [clinic start generated code]*/
12610 
12611 static PyObject *
os_setxattr_impl(PyObject * module,path_t * path,path_t * attribute,Py_buffer * value,int flags,int follow_symlinks)12612 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12613                  Py_buffer *value, int flags, int follow_symlinks)
12614 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12615 {
12616     ssize_t result;
12617 
12618     if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12619         return NULL;
12620 
12621     if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12622                     value->buf, value->len, flags) < 0) {
12623         return NULL;
12624     }
12625 
12626     Py_BEGIN_ALLOW_THREADS;
12627     if (path->fd > -1)
12628         result = fsetxattr(path->fd, attribute->narrow,
12629                            value->buf, value->len, flags);
12630     else if (follow_symlinks)
12631         result = setxattr(path->narrow, attribute->narrow,
12632                            value->buf, value->len, flags);
12633     else
12634         result = lsetxattr(path->narrow, attribute->narrow,
12635                            value->buf, value->len, flags);
12636     Py_END_ALLOW_THREADS;
12637 
12638     if (result) {
12639         path_error(path);
12640         return NULL;
12641     }
12642 
12643     Py_RETURN_NONE;
12644 }
12645 
12646 
12647 /*[clinic input]
12648 os.removexattr
12649 
12650     path: path_t(allow_fd=True)
12651     attribute: path_t
12652     *
12653     follow_symlinks: bool = True
12654 
12655 Remove extended attribute attribute on path.
12656 
12657 path may be either a string, a path-like object, or an open file descriptor.
12658 If follow_symlinks is False, and the last element of the path is a symbolic
12659   link, removexattr will modify the symbolic link itself instead of the file
12660   the link points to.
12661 
12662 [clinic start generated code]*/
12663 
12664 static PyObject *
os_removexattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12665 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
12666                     int follow_symlinks)
12667 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
12668 {
12669     ssize_t result;
12670 
12671     if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
12672         return NULL;
12673 
12674     if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
12675         return NULL;
12676     }
12677 
12678     Py_BEGIN_ALLOW_THREADS;
12679     if (path->fd > -1)
12680         result = fremovexattr(path->fd, attribute->narrow);
12681     else if (follow_symlinks)
12682         result = removexattr(path->narrow, attribute->narrow);
12683     else
12684         result = lremovexattr(path->narrow, attribute->narrow);
12685     Py_END_ALLOW_THREADS;
12686 
12687     if (result) {
12688         return path_error(path);
12689     }
12690 
12691     Py_RETURN_NONE;
12692 }
12693 
12694 
12695 /*[clinic input]
12696 os.listxattr
12697 
12698     path: path_t(allow_fd=True, nullable=True) = None
12699     *
12700     follow_symlinks: bool = True
12701 
12702 Return a list of extended attributes on path.
12703 
12704 path may be either None, a string, a path-like object, or an open file descriptor.
12705 if path is None, listxattr will examine the current directory.
12706 If follow_symlinks is False, and the last element of the path is a symbolic
12707   link, listxattr will examine the symbolic link itself instead of the file
12708   the link points to.
12709 [clinic start generated code]*/
12710 
12711 static PyObject *
os_listxattr_impl(PyObject * module,path_t * path,int follow_symlinks)12712 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
12713 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
12714 {
12715     Py_ssize_t i;
12716     PyObject *result = NULL;
12717     const char *name;
12718     char *buffer = NULL;
12719 
12720     if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
12721         goto exit;
12722 
12723     if (PySys_Audit("os.listxattr", "(O)",
12724                     path->object ? path->object : Py_None) < 0) {
12725         return NULL;
12726     }
12727 
12728     name = path->narrow ? path->narrow : ".";
12729 
12730     for (i = 0; ; i++) {
12731         const char *start, *trace, *end;
12732         ssize_t length;
12733         static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
12734         Py_ssize_t buffer_size = buffer_sizes[i];
12735         if (!buffer_size) {
12736             /* ERANGE */
12737             path_error(path);
12738             break;
12739         }
12740         buffer = PyMem_MALLOC(buffer_size);
12741         if (!buffer) {
12742             PyErr_NoMemory();
12743             break;
12744         }
12745 
12746         Py_BEGIN_ALLOW_THREADS;
12747         if (path->fd > -1)
12748             length = flistxattr(path->fd, buffer, buffer_size);
12749         else if (follow_symlinks)
12750             length = listxattr(name, buffer, buffer_size);
12751         else
12752             length = llistxattr(name, buffer, buffer_size);
12753         Py_END_ALLOW_THREADS;
12754 
12755         if (length < 0) {
12756             if (errno == ERANGE) {
12757                 PyMem_FREE(buffer);
12758                 buffer = NULL;
12759                 continue;
12760             }
12761             path_error(path);
12762             break;
12763         }
12764 
12765         result = PyList_New(0);
12766         if (!result) {
12767             goto exit;
12768         }
12769 
12770         end = buffer + length;
12771         for (trace = start = buffer; trace != end; trace++) {
12772             if (!*trace) {
12773                 int error;
12774                 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
12775                                                                  trace - start);
12776                 if (!attribute) {
12777                     Py_DECREF(result);
12778                     result = NULL;
12779                     goto exit;
12780                 }
12781                 error = PyList_Append(result, attribute);
12782                 Py_DECREF(attribute);
12783                 if (error) {
12784                     Py_DECREF(result);
12785                     result = NULL;
12786                     goto exit;
12787                 }
12788                 start = trace + 1;
12789             }
12790         }
12791     break;
12792     }
12793 exit:
12794     if (buffer)
12795         PyMem_FREE(buffer);
12796     return result;
12797 }
12798 #endif /* USE_XATTRS */
12799 
12800 
12801 /*[clinic input]
12802 os.urandom
12803 
12804     size: Py_ssize_t
12805     /
12806 
12807 Return a bytes object containing random bytes suitable for cryptographic use.
12808 [clinic start generated code]*/
12809 
12810 static PyObject *
os_urandom_impl(PyObject * module,Py_ssize_t size)12811 os_urandom_impl(PyObject *module, Py_ssize_t size)
12812 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
12813 {
12814     PyObject *bytes;
12815     int result;
12816 
12817     if (size < 0)
12818         return PyErr_Format(PyExc_ValueError,
12819                             "negative argument not allowed");
12820     bytes = PyBytes_FromStringAndSize(NULL, size);
12821     if (bytes == NULL)
12822         return NULL;
12823 
12824     result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
12825     if (result == -1) {
12826         Py_DECREF(bytes);
12827         return NULL;
12828     }
12829     return bytes;
12830 }
12831 
12832 #ifdef HAVE_MEMFD_CREATE
12833 /*[clinic input]
12834 os.memfd_create
12835 
12836     name: FSConverter
12837     flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
12838 
12839 [clinic start generated code]*/
12840 
12841 static PyObject *
os_memfd_create_impl(PyObject * module,PyObject * name,unsigned int flags)12842 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
12843 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
12844 {
12845     int fd;
12846     const char *bytes = PyBytes_AS_STRING(name);
12847     Py_BEGIN_ALLOW_THREADS
12848     fd = memfd_create(bytes, flags);
12849     Py_END_ALLOW_THREADS
12850     if (fd == -1) {
12851         return PyErr_SetFromErrno(PyExc_OSError);
12852     }
12853     return PyLong_FromLong(fd);
12854 }
12855 #endif
12856 
12857 /* Terminal size querying */
12858 
12859 PyDoc_STRVAR(TerminalSize_docstring,
12860     "A tuple of (columns, lines) for holding terminal window size");
12861 
12862 static PyStructSequence_Field TerminalSize_fields[] = {
12863     {"columns", "width of the terminal window in characters"},
12864     {"lines", "height of the terminal window in characters"},
12865     {NULL, NULL}
12866 };
12867 
12868 static PyStructSequence_Desc TerminalSize_desc = {
12869     "os.terminal_size",
12870     TerminalSize_docstring,
12871     TerminalSize_fields,
12872     2,
12873 };
12874 
12875 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
12876 /*[clinic input]
12877 os.get_terminal_size
12878 
12879     fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
12880     /
12881 
12882 Return the size of the terminal window as (columns, lines).
12883 
12884 The optional argument fd (default standard output) specifies
12885 which file descriptor should be queried.
12886 
12887 If the file descriptor is not connected to a terminal, an OSError
12888 is thrown.
12889 
12890 This function will only be defined if an implementation is
12891 available for this system.
12892 
12893 shutil.get_terminal_size is the high-level function which should
12894 normally be used, os.get_terminal_size is the low-level implementation.
12895 [clinic start generated code]*/
12896 
12897 static PyObject *
os_get_terminal_size_impl(PyObject * module,int fd)12898 os_get_terminal_size_impl(PyObject *module, int fd)
12899 /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
12900 {
12901     int columns, lines;
12902     PyObject *termsize;
12903 
12904     /* Under some conditions stdout may not be connected and
12905      * fileno(stdout) may point to an invalid file descriptor. For example
12906      * GUI apps don't have valid standard streams by default.
12907      *
12908      * If this happens, and the optional fd argument is not present,
12909      * the ioctl below will fail returning EBADF. This is what we want.
12910      */
12911 
12912 #ifdef TERMSIZE_USE_IOCTL
12913     {
12914         struct winsize w;
12915         if (ioctl(fd, TIOCGWINSZ, &w))
12916             return PyErr_SetFromErrno(PyExc_OSError);
12917         columns = w.ws_col;
12918         lines = w.ws_row;
12919     }
12920 #endif /* TERMSIZE_USE_IOCTL */
12921 
12922 #ifdef TERMSIZE_USE_CONIO
12923     {
12924         DWORD nhandle;
12925         HANDLE handle;
12926         CONSOLE_SCREEN_BUFFER_INFO csbi;
12927         switch (fd) {
12928         case 0: nhandle = STD_INPUT_HANDLE;
12929             break;
12930         case 1: nhandle = STD_OUTPUT_HANDLE;
12931             break;
12932         case 2: nhandle = STD_ERROR_HANDLE;
12933             break;
12934         default:
12935             return PyErr_Format(PyExc_ValueError, "bad file descriptor");
12936         }
12937         handle = GetStdHandle(nhandle);
12938         if (handle == NULL)
12939             return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
12940         if (handle == INVALID_HANDLE_VALUE)
12941             return PyErr_SetFromWindowsErr(0);
12942 
12943         if (!GetConsoleScreenBufferInfo(handle, &csbi))
12944             return PyErr_SetFromWindowsErr(0);
12945 
12946         columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
12947         lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
12948     }
12949 #endif /* TERMSIZE_USE_CONIO */
12950 
12951     PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
12952     termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
12953     if (termsize == NULL)
12954         return NULL;
12955     PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
12956     PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
12957     if (PyErr_Occurred()) {
12958         Py_DECREF(termsize);
12959         return NULL;
12960     }
12961     return termsize;
12962 }
12963 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
12964 
12965 
12966 /*[clinic input]
12967 os.cpu_count
12968 
12969 Return the number of CPUs in the system; return None if indeterminable.
12970 
12971 This number is not equivalent to the number of CPUs the current process can
12972 use.  The number of usable CPUs can be obtained with
12973 ``len(os.sched_getaffinity(0))``
12974 [clinic start generated code]*/
12975 
12976 static PyObject *
os_cpu_count_impl(PyObject * module)12977 os_cpu_count_impl(PyObject *module)
12978 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
12979 {
12980     int ncpu = 0;
12981 #ifdef MS_WINDOWS
12982     ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
12983 #elif defined(__hpux)
12984     ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
12985 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
12986     ncpu = sysconf(_SC_NPROCESSORS_ONLN);
12987 #elif defined(__DragonFly__) || \
12988       defined(__OpenBSD__)   || \
12989       defined(__FreeBSD__)   || \
12990       defined(__NetBSD__)    || \
12991       defined(__APPLE__)
12992     int mib[2];
12993     size_t len = sizeof(ncpu);
12994     mib[0] = CTL_HW;
12995     mib[1] = HW_NCPU;
12996     if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
12997         ncpu = 0;
12998 #endif
12999     if (ncpu >= 1)
13000         return PyLong_FromLong(ncpu);
13001     else
13002         Py_RETURN_NONE;
13003 }
13004 
13005 
13006 /*[clinic input]
13007 os.get_inheritable -> bool
13008 
13009     fd: int
13010     /
13011 
13012 Get the close-on-exe flag of the specified file descriptor.
13013 [clinic start generated code]*/
13014 
13015 static int
os_get_inheritable_impl(PyObject * module,int fd)13016 os_get_inheritable_impl(PyObject *module, int fd)
13017 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
13018 {
13019     int return_value;
13020     _Py_BEGIN_SUPPRESS_IPH
13021     return_value = _Py_get_inheritable(fd);
13022     _Py_END_SUPPRESS_IPH
13023     return return_value;
13024 }
13025 
13026 
13027 /*[clinic input]
13028 os.set_inheritable
13029     fd: int
13030     inheritable: int
13031     /
13032 
13033 Set the inheritable flag of the specified file descriptor.
13034 [clinic start generated code]*/
13035 
13036 static PyObject *
os_set_inheritable_impl(PyObject * module,int fd,int inheritable)13037 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
13038 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
13039 {
13040     int result;
13041 
13042     _Py_BEGIN_SUPPRESS_IPH
13043     result = _Py_set_inheritable(fd, inheritable, NULL);
13044     _Py_END_SUPPRESS_IPH
13045     if (result < 0)
13046         return NULL;
13047     Py_RETURN_NONE;
13048 }
13049 
13050 
13051 #ifdef MS_WINDOWS
13052 /*[clinic input]
13053 os.get_handle_inheritable -> bool
13054     handle: intptr_t
13055     /
13056 
13057 Get the close-on-exe flag of the specified file descriptor.
13058 [clinic start generated code]*/
13059 
13060 static int
os_get_handle_inheritable_impl(PyObject * module,intptr_t handle)13061 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
13062 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
13063 {
13064     DWORD flags;
13065 
13066     if (!GetHandleInformation((HANDLE)handle, &flags)) {
13067         PyErr_SetFromWindowsErr(0);
13068         return -1;
13069     }
13070 
13071     return flags & HANDLE_FLAG_INHERIT;
13072 }
13073 
13074 
13075 /*[clinic input]
13076 os.set_handle_inheritable
13077     handle: intptr_t
13078     inheritable: bool
13079     /
13080 
13081 Set the inheritable flag of the specified handle.
13082 [clinic start generated code]*/
13083 
13084 static PyObject *
os_set_handle_inheritable_impl(PyObject * module,intptr_t handle,int inheritable)13085 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
13086                                int inheritable)
13087 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
13088 {
13089     DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
13090     if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
13091         PyErr_SetFromWindowsErr(0);
13092         return NULL;
13093     }
13094     Py_RETURN_NONE;
13095 }
13096 #endif /* MS_WINDOWS */
13097 
13098 #ifndef MS_WINDOWS
13099 /*[clinic input]
13100 os.get_blocking -> bool
13101     fd: int
13102     /
13103 
13104 Get the blocking mode of the file descriptor.
13105 
13106 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
13107 [clinic start generated code]*/
13108 
13109 static int
os_get_blocking_impl(PyObject * module,int fd)13110 os_get_blocking_impl(PyObject *module, int fd)
13111 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
13112 {
13113     int blocking;
13114 
13115     _Py_BEGIN_SUPPRESS_IPH
13116     blocking = _Py_get_blocking(fd);
13117     _Py_END_SUPPRESS_IPH
13118     return blocking;
13119 }
13120 
13121 /*[clinic input]
13122 os.set_blocking
13123     fd: int
13124     blocking: bool(accept={int})
13125     /
13126 
13127 Set the blocking mode of the specified file descriptor.
13128 
13129 Set the O_NONBLOCK flag if blocking is False,
13130 clear the O_NONBLOCK flag otherwise.
13131 [clinic start generated code]*/
13132 
13133 static PyObject *
os_set_blocking_impl(PyObject * module,int fd,int blocking)13134 os_set_blocking_impl(PyObject *module, int fd, int blocking)
13135 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
13136 {
13137     int result;
13138 
13139     _Py_BEGIN_SUPPRESS_IPH
13140     result = _Py_set_blocking(fd, blocking);
13141     _Py_END_SUPPRESS_IPH
13142     if (result < 0)
13143         return NULL;
13144     Py_RETURN_NONE;
13145 }
13146 #endif   /* !MS_WINDOWS */
13147 
13148 
13149 /*[clinic input]
13150 class os.DirEntry "DirEntry *" "DirEntryType"
13151 [clinic start generated code]*/
13152 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
13153 
13154 typedef struct {
13155     PyObject_HEAD
13156     PyObject *name;
13157     PyObject *path;
13158     PyObject *stat;
13159     PyObject *lstat;
13160 #ifdef MS_WINDOWS
13161     struct _Py_stat_struct win32_lstat;
13162     uint64_t win32_file_index;
13163     int got_file_index;
13164 #else /* POSIX */
13165 #ifdef HAVE_DIRENT_D_TYPE
13166     unsigned char d_type;
13167 #endif
13168     ino_t d_ino;
13169     int dir_fd;
13170 #endif
13171 } DirEntry;
13172 
13173 static PyObject *
_disabled_new(PyTypeObject * type,PyObject * args,PyObject * kwargs)13174 _disabled_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
13175 {
13176     PyErr_Format(PyExc_TypeError,
13177         "cannot create '%.100s' instances", _PyType_Name(type));
13178     return NULL;
13179 }
13180 
13181 static void
DirEntry_dealloc(DirEntry * entry)13182 DirEntry_dealloc(DirEntry *entry)
13183 {
13184     PyTypeObject *tp = Py_TYPE(entry);
13185     Py_XDECREF(entry->name);
13186     Py_XDECREF(entry->path);
13187     Py_XDECREF(entry->stat);
13188     Py_XDECREF(entry->lstat);
13189     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13190     free_func(entry);
13191     Py_DECREF(tp);
13192 }
13193 
13194 /* Forward reference */
13195 static int
13196 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13197                    int follow_symlinks, unsigned short mode_bits);
13198 
13199 /*[clinic input]
13200 os.DirEntry.is_symlink -> bool
13201     defining_class: defining_class
13202     /
13203 
13204 Return True if the entry is a symbolic link; cached per entry.
13205 [clinic start generated code]*/
13206 
13207 static int
os_DirEntry_is_symlink_impl(DirEntry * self,PyTypeObject * defining_class)13208 os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
13209 /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
13210 {
13211 #ifdef MS_WINDOWS
13212     return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13213 #elif defined(HAVE_DIRENT_D_TYPE)
13214     /* POSIX */
13215     if (self->d_type != DT_UNKNOWN)
13216         return self->d_type == DT_LNK;
13217     else
13218         return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13219 #else
13220     /* POSIX without d_type */
13221     return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13222 #endif
13223 }
13224 
13225 static PyObject *
DirEntry_fetch_stat(PyObject * module,DirEntry * self,int follow_symlinks)13226 DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
13227 {
13228     int result;
13229     STRUCT_STAT st;
13230     PyObject *ub;
13231 
13232 #ifdef MS_WINDOWS
13233     if (!PyUnicode_FSDecoder(self->path, &ub))
13234         return NULL;
13235     const wchar_t *path = PyUnicode_AsUnicode(ub);
13236 #else /* POSIX */
13237     if (!PyUnicode_FSConverter(self->path, &ub))
13238         return NULL;
13239     const char *path = PyBytes_AS_STRING(ub);
13240     if (self->dir_fd != DEFAULT_DIR_FD) {
13241 #ifdef HAVE_FSTATAT
13242       if (HAVE_FSTATAT_RUNTIME) {
13243         result = fstatat(self->dir_fd, path, &st,
13244                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
13245       } else
13246 
13247 #endif /* HAVE_FSTATAT */
13248       {
13249         Py_DECREF(ub);
13250         PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
13251         return NULL;
13252       }
13253     }
13254     else
13255 #endif
13256     {
13257         if (follow_symlinks)
13258             result = STAT(path, &st);
13259         else
13260             result = LSTAT(path, &st);
13261     }
13262     Py_DECREF(ub);
13263 
13264     if (result != 0)
13265         return path_object_error(self->path);
13266 
13267     return _pystat_fromstructstat(module, &st);
13268 }
13269 
13270 static PyObject *
DirEntry_get_lstat(PyTypeObject * defining_class,DirEntry * self)13271 DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
13272 {
13273     if (!self->lstat) {
13274         PyObject *module = PyType_GetModule(defining_class);
13275 #ifdef MS_WINDOWS
13276         self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
13277 #else /* POSIX */
13278         self->lstat = DirEntry_fetch_stat(module, self, 0);
13279 #endif
13280     }
13281     Py_XINCREF(self->lstat);
13282     return self->lstat;
13283 }
13284 
13285 /*[clinic input]
13286 os.DirEntry.stat
13287     defining_class: defining_class
13288     /
13289     *
13290     follow_symlinks: bool = True
13291 
13292 Return stat_result object for the entry; cached per entry.
13293 [clinic start generated code]*/
13294 
13295 static PyObject *
os_DirEntry_stat_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13296 os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
13297                       int follow_symlinks)
13298 /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
13299 {
13300     if (!follow_symlinks) {
13301         return DirEntry_get_lstat(defining_class, self);
13302     }
13303 
13304     if (!self->stat) {
13305         int result = os_DirEntry_is_symlink_impl(self, defining_class);
13306         if (result == -1) {
13307             return NULL;
13308         }
13309         if (result) {
13310             PyObject *module = PyType_GetModule(defining_class);
13311             self->stat = DirEntry_fetch_stat(module, self, 1);
13312         }
13313         else {
13314             self->stat = DirEntry_get_lstat(defining_class, self);
13315         }
13316     }
13317 
13318     Py_XINCREF(self->stat);
13319     return self->stat;
13320 }
13321 
13322 /* Set exception and return -1 on error, 0 for False, 1 for True */
13323 static int
DirEntry_test_mode(PyTypeObject * defining_class,DirEntry * self,int follow_symlinks,unsigned short mode_bits)13324 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13325                    int follow_symlinks, unsigned short mode_bits)
13326 {
13327     PyObject *stat = NULL;
13328     PyObject *st_mode = NULL;
13329     long mode;
13330     int result;
13331 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13332     int is_symlink;
13333     int need_stat;
13334 #endif
13335 #ifdef MS_WINDOWS
13336     unsigned long dir_bits;
13337 #endif
13338 
13339 #ifdef MS_WINDOWS
13340     is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13341     need_stat = follow_symlinks && is_symlink;
13342 #elif defined(HAVE_DIRENT_D_TYPE)
13343     is_symlink = self->d_type == DT_LNK;
13344     need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
13345 #endif
13346 
13347 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13348     if (need_stat) {
13349 #endif
13350         stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
13351         if (!stat) {
13352             if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
13353                 /* If file doesn't exist (anymore), then return False
13354                    (i.e., say it's not a file/directory) */
13355                 PyErr_Clear();
13356                 return 0;
13357             }
13358             goto error;
13359         }
13360         _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
13361         st_mode = PyObject_GetAttr(stat, state->st_mode);
13362         if (!st_mode)
13363             goto error;
13364 
13365         mode = PyLong_AsLong(st_mode);
13366         if (mode == -1 && PyErr_Occurred())
13367             goto error;
13368         Py_CLEAR(st_mode);
13369         Py_CLEAR(stat);
13370         result = (mode & S_IFMT) == mode_bits;
13371 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13372     }
13373     else if (is_symlink) {
13374         assert(mode_bits != S_IFLNK);
13375         result = 0;
13376     }
13377     else {
13378         assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
13379 #ifdef MS_WINDOWS
13380         dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
13381         if (mode_bits == S_IFDIR)
13382             result = dir_bits != 0;
13383         else
13384             result = dir_bits == 0;
13385 #else /* POSIX */
13386         if (mode_bits == S_IFDIR)
13387             result = self->d_type == DT_DIR;
13388         else
13389             result = self->d_type == DT_REG;
13390 #endif
13391     }
13392 #endif
13393 
13394     return result;
13395 
13396 error:
13397     Py_XDECREF(st_mode);
13398     Py_XDECREF(stat);
13399     return -1;
13400 }
13401 
13402 /*[clinic input]
13403 os.DirEntry.is_dir -> bool
13404     defining_class: defining_class
13405     /
13406     *
13407     follow_symlinks: bool = True
13408 
13409 Return True if the entry is a directory; cached per entry.
13410 [clinic start generated code]*/
13411 
13412 static int
os_DirEntry_is_dir_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13413 os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
13414                         int follow_symlinks)
13415 /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
13416 {
13417     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
13418 }
13419 
13420 /*[clinic input]
13421 os.DirEntry.is_file -> bool
13422     defining_class: defining_class
13423     /
13424     *
13425     follow_symlinks: bool = True
13426 
13427 Return True if the entry is a file; cached per entry.
13428 [clinic start generated code]*/
13429 
13430 static int
os_DirEntry_is_file_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13431 os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
13432                          int follow_symlinks)
13433 /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
13434 {
13435     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
13436 }
13437 
13438 /*[clinic input]
13439 os.DirEntry.inode
13440 
13441 Return inode of the entry; cached per entry.
13442 [clinic start generated code]*/
13443 
13444 static PyObject *
os_DirEntry_inode_impl(DirEntry * self)13445 os_DirEntry_inode_impl(DirEntry *self)
13446 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
13447 {
13448 #ifdef MS_WINDOWS
13449     if (!self->got_file_index) {
13450         PyObject *unicode;
13451         const wchar_t *path;
13452         STRUCT_STAT stat;
13453         int result;
13454 
13455         if (!PyUnicode_FSDecoder(self->path, &unicode))
13456             return NULL;
13457         path = PyUnicode_AsUnicode(unicode);
13458         result = LSTAT(path, &stat);
13459         Py_DECREF(unicode);
13460 
13461         if (result != 0)
13462             return path_object_error(self->path);
13463 
13464         self->win32_file_index = stat.st_ino;
13465         self->got_file_index = 1;
13466     }
13467     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->win32_file_index));
13468     return PyLong_FromUnsignedLongLong(self->win32_file_index);
13469 #else /* POSIX */
13470     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->d_ino));
13471     return PyLong_FromUnsignedLongLong(self->d_ino);
13472 #endif
13473 }
13474 
13475 static PyObject *
DirEntry_repr(DirEntry * self)13476 DirEntry_repr(DirEntry *self)
13477 {
13478     return PyUnicode_FromFormat("<DirEntry %R>", self->name);
13479 }
13480 
13481 /*[clinic input]
13482 os.DirEntry.__fspath__
13483 
13484 Returns the path for the entry.
13485 [clinic start generated code]*/
13486 
13487 static PyObject *
os_DirEntry___fspath___impl(DirEntry * self)13488 os_DirEntry___fspath___impl(DirEntry *self)
13489 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
13490 {
13491     Py_INCREF(self->path);
13492     return self->path;
13493 }
13494 
13495 static PyMemberDef DirEntry_members[] = {
13496     {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
13497      "the entry's base filename, relative to scandir() \"path\" argument"},
13498     {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
13499      "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
13500     {NULL}
13501 };
13502 
13503 #include "clinic/posixmodule.c.h"
13504 
13505 static PyMethodDef DirEntry_methods[] = {
13506     OS_DIRENTRY_IS_DIR_METHODDEF
13507     OS_DIRENTRY_IS_FILE_METHODDEF
13508     OS_DIRENTRY_IS_SYMLINK_METHODDEF
13509     OS_DIRENTRY_STAT_METHODDEF
13510     OS_DIRENTRY_INODE_METHODDEF
13511     OS_DIRENTRY___FSPATH___METHODDEF
13512     {"__class_getitem__",       (PyCFunction)Py_GenericAlias,
13513     METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
13514     {NULL}
13515 };
13516 
13517 static PyType_Slot DirEntryType_slots[] = {
13518     {Py_tp_new, _disabled_new},
13519     {Py_tp_dealloc, DirEntry_dealloc},
13520     {Py_tp_repr, DirEntry_repr},
13521     {Py_tp_methods, DirEntry_methods},
13522     {Py_tp_members, DirEntry_members},
13523     {0, 0},
13524 };
13525 
13526 static PyType_Spec DirEntryType_spec = {
13527     MODNAME ".DirEntry",
13528     sizeof(DirEntry),
13529     0,
13530     Py_TPFLAGS_DEFAULT,
13531     DirEntryType_slots
13532 };
13533 
13534 
13535 #ifdef MS_WINDOWS
13536 
13537 static wchar_t *
join_path_filenameW(const wchar_t * path_wide,const wchar_t * filename)13538 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
13539 {
13540     Py_ssize_t path_len;
13541     Py_ssize_t size;
13542     wchar_t *result;
13543     wchar_t ch;
13544 
13545     if (!path_wide) { /* Default arg: "." */
13546         path_wide = L".";
13547         path_len = 1;
13548     }
13549     else {
13550         path_len = wcslen(path_wide);
13551     }
13552 
13553     /* The +1's are for the path separator and the NUL */
13554     size = path_len + 1 + wcslen(filename) + 1;
13555     result = PyMem_New(wchar_t, size);
13556     if (!result) {
13557         PyErr_NoMemory();
13558         return NULL;
13559     }
13560     wcscpy(result, path_wide);
13561     if (path_len > 0) {
13562         ch = result[path_len - 1];
13563         if (ch != SEP && ch != ALTSEP && ch != L':')
13564             result[path_len++] = SEP;
13565         wcscpy(result + path_len, filename);
13566     }
13567     return result;
13568 }
13569 
13570 static PyObject *
DirEntry_from_find_data(PyObject * module,path_t * path,WIN32_FIND_DATAW * dataW)13571 DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
13572 {
13573     DirEntry *entry;
13574     BY_HANDLE_FILE_INFORMATION file_info;
13575     ULONG reparse_tag;
13576     wchar_t *joined_path;
13577 
13578     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13579     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13580     if (!entry)
13581         return NULL;
13582     entry->name = NULL;
13583     entry->path = NULL;
13584     entry->stat = NULL;
13585     entry->lstat = NULL;
13586     entry->got_file_index = 0;
13587 
13588     entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
13589     if (!entry->name)
13590         goto error;
13591     if (path->narrow) {
13592         Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
13593         if (!entry->name)
13594             goto error;
13595     }
13596 
13597     joined_path = join_path_filenameW(path->wide, dataW->cFileName);
13598     if (!joined_path)
13599         goto error;
13600 
13601     entry->path = PyUnicode_FromWideChar(joined_path, -1);
13602     PyMem_Free(joined_path);
13603     if (!entry->path)
13604         goto error;
13605     if (path->narrow) {
13606         Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
13607         if (!entry->path)
13608             goto error;
13609     }
13610 
13611     find_data_to_file_info(dataW, &file_info, &reparse_tag);
13612     _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
13613 
13614     return (PyObject *)entry;
13615 
13616 error:
13617     Py_DECREF(entry);
13618     return NULL;
13619 }
13620 
13621 #else /* POSIX */
13622 
13623 static char *
join_path_filename(const char * path_narrow,const char * filename,Py_ssize_t filename_len)13624 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
13625 {
13626     Py_ssize_t path_len;
13627     Py_ssize_t size;
13628     char *result;
13629 
13630     if (!path_narrow) { /* Default arg: "." */
13631         path_narrow = ".";
13632         path_len = 1;
13633     }
13634     else {
13635         path_len = strlen(path_narrow);
13636     }
13637 
13638     if (filename_len == -1)
13639         filename_len = strlen(filename);
13640 
13641     /* The +1's are for the path separator and the NUL */
13642     size = path_len + 1 + filename_len + 1;
13643     result = PyMem_New(char, size);
13644     if (!result) {
13645         PyErr_NoMemory();
13646         return NULL;
13647     }
13648     strcpy(result, path_narrow);
13649     if (path_len > 0 && result[path_len - 1] != '/')
13650         result[path_len++] = '/';
13651     strcpy(result + path_len, filename);
13652     return result;
13653 }
13654 
13655 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)13656 DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
13657                          Py_ssize_t name_len, ino_t d_ino
13658 #ifdef HAVE_DIRENT_D_TYPE
13659                          , unsigned char d_type
13660 #endif
13661                          )
13662 {
13663     DirEntry *entry;
13664     char *joined_path;
13665 
13666     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13667     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13668     if (!entry)
13669         return NULL;
13670     entry->name = NULL;
13671     entry->path = NULL;
13672     entry->stat = NULL;
13673     entry->lstat = NULL;
13674 
13675     if (path->fd != -1) {
13676         entry->dir_fd = path->fd;
13677         joined_path = NULL;
13678     }
13679     else {
13680         entry->dir_fd = DEFAULT_DIR_FD;
13681         joined_path = join_path_filename(path->narrow, name, name_len);
13682         if (!joined_path)
13683             goto error;
13684     }
13685 
13686     if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
13687         entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
13688         if (joined_path)
13689             entry->path = PyUnicode_DecodeFSDefault(joined_path);
13690     }
13691     else {
13692         entry->name = PyBytes_FromStringAndSize(name, name_len);
13693         if (joined_path)
13694             entry->path = PyBytes_FromString(joined_path);
13695     }
13696     PyMem_Free(joined_path);
13697     if (!entry->name)
13698         goto error;
13699 
13700     if (path->fd != -1) {
13701         entry->path = entry->name;
13702         Py_INCREF(entry->path);
13703     }
13704     else if (!entry->path)
13705         goto error;
13706 
13707 #ifdef HAVE_DIRENT_D_TYPE
13708     entry->d_type = d_type;
13709 #endif
13710     entry->d_ino = d_ino;
13711 
13712     return (PyObject *)entry;
13713 
13714 error:
13715     Py_XDECREF(entry);
13716     return NULL;
13717 }
13718 
13719 #endif
13720 
13721 
13722 typedef struct {
13723     PyObject_HEAD
13724     path_t path;
13725 #ifdef MS_WINDOWS
13726     HANDLE handle;
13727     WIN32_FIND_DATAW file_data;
13728     int first_time;
13729 #else /* POSIX */
13730     DIR *dirp;
13731 #endif
13732 #ifdef HAVE_FDOPENDIR
13733     int fd;
13734 #endif
13735 } ScandirIterator;
13736 
13737 #ifdef MS_WINDOWS
13738 
13739 static int
ScandirIterator_is_closed(ScandirIterator * iterator)13740 ScandirIterator_is_closed(ScandirIterator *iterator)
13741 {
13742     return iterator->handle == INVALID_HANDLE_VALUE;
13743 }
13744 
13745 static void
ScandirIterator_closedir(ScandirIterator * iterator)13746 ScandirIterator_closedir(ScandirIterator *iterator)
13747 {
13748     HANDLE handle = iterator->handle;
13749 
13750     if (handle == INVALID_HANDLE_VALUE)
13751         return;
13752 
13753     iterator->handle = INVALID_HANDLE_VALUE;
13754     Py_BEGIN_ALLOW_THREADS
13755     FindClose(handle);
13756     Py_END_ALLOW_THREADS
13757 }
13758 
13759 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)13760 ScandirIterator_iternext(ScandirIterator *iterator)
13761 {
13762     WIN32_FIND_DATAW *file_data = &iterator->file_data;
13763     BOOL success;
13764     PyObject *entry;
13765 
13766     /* Happens if the iterator is iterated twice, or closed explicitly */
13767     if (iterator->handle == INVALID_HANDLE_VALUE)
13768         return NULL;
13769 
13770     while (1) {
13771         if (!iterator->first_time) {
13772             Py_BEGIN_ALLOW_THREADS
13773             success = FindNextFileW(iterator->handle, file_data);
13774             Py_END_ALLOW_THREADS
13775             if (!success) {
13776                 /* Error or no more files */
13777                 if (GetLastError() != ERROR_NO_MORE_FILES)
13778                     path_error(&iterator->path);
13779                 break;
13780             }
13781         }
13782         iterator->first_time = 0;
13783 
13784         /* Skip over . and .. */
13785         if (wcscmp(file_data->cFileName, L".") != 0 &&
13786             wcscmp(file_data->cFileName, L"..") != 0)
13787         {
13788             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
13789             entry = DirEntry_from_find_data(module, &iterator->path, file_data);
13790             if (!entry)
13791                 break;
13792             return entry;
13793         }
13794 
13795         /* Loop till we get a non-dot directory or finish iterating */
13796     }
13797 
13798     /* Error or no more files */
13799     ScandirIterator_closedir(iterator);
13800     return NULL;
13801 }
13802 
13803 #else /* POSIX */
13804 
13805 static int
ScandirIterator_is_closed(ScandirIterator * iterator)13806 ScandirIterator_is_closed(ScandirIterator *iterator)
13807 {
13808     return !iterator->dirp;
13809 }
13810 
13811 static void
ScandirIterator_closedir(ScandirIterator * iterator)13812 ScandirIterator_closedir(ScandirIterator *iterator)
13813 {
13814     DIR *dirp = iterator->dirp;
13815 
13816     if (!dirp)
13817         return;
13818 
13819     iterator->dirp = NULL;
13820     Py_BEGIN_ALLOW_THREADS
13821 #ifdef HAVE_FDOPENDIR
13822     if (iterator->path.fd != -1)
13823         rewinddir(dirp);
13824 #endif
13825     closedir(dirp);
13826     Py_END_ALLOW_THREADS
13827     return;
13828 }
13829 
13830 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)13831 ScandirIterator_iternext(ScandirIterator *iterator)
13832 {
13833     struct dirent *direntp;
13834     Py_ssize_t name_len;
13835     int is_dot;
13836     PyObject *entry;
13837 
13838     /* Happens if the iterator is iterated twice, or closed explicitly */
13839     if (!iterator->dirp)
13840         return NULL;
13841 
13842     while (1) {
13843         errno = 0;
13844         Py_BEGIN_ALLOW_THREADS
13845         direntp = readdir(iterator->dirp);
13846         Py_END_ALLOW_THREADS
13847 
13848         if (!direntp) {
13849             /* Error or no more files */
13850             if (errno != 0)
13851                 path_error(&iterator->path);
13852             break;
13853         }
13854 
13855         /* Skip over . and .. */
13856         name_len = NAMLEN(direntp);
13857         is_dot = direntp->d_name[0] == '.' &&
13858                  (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
13859         if (!is_dot) {
13860             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
13861             entry = DirEntry_from_posix_info(module,
13862                                              &iterator->path, direntp->d_name,
13863                                              name_len, direntp->d_ino
13864 #ifdef HAVE_DIRENT_D_TYPE
13865                                              , direntp->d_type
13866 #endif
13867                                             );
13868             if (!entry)
13869                 break;
13870             return entry;
13871         }
13872 
13873         /* Loop till we get a non-dot directory or finish iterating */
13874     }
13875 
13876     /* Error or no more files */
13877     ScandirIterator_closedir(iterator);
13878     return NULL;
13879 }
13880 
13881 #endif
13882 
13883 static PyObject *
ScandirIterator_close(ScandirIterator * self,PyObject * args)13884 ScandirIterator_close(ScandirIterator *self, PyObject *args)
13885 {
13886     ScandirIterator_closedir(self);
13887     Py_RETURN_NONE;
13888 }
13889 
13890 static PyObject *
ScandirIterator_enter(PyObject * self,PyObject * args)13891 ScandirIterator_enter(PyObject *self, PyObject *args)
13892 {
13893     Py_INCREF(self);
13894     return self;
13895 }
13896 
13897 static PyObject *
ScandirIterator_exit(ScandirIterator * self,PyObject * args)13898 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
13899 {
13900     ScandirIterator_closedir(self);
13901     Py_RETURN_NONE;
13902 }
13903 
13904 static void
ScandirIterator_finalize(ScandirIterator * iterator)13905 ScandirIterator_finalize(ScandirIterator *iterator)
13906 {
13907     PyObject *error_type, *error_value, *error_traceback;
13908 
13909     /* Save the current exception, if any. */
13910     PyErr_Fetch(&error_type, &error_value, &error_traceback);
13911 
13912     if (!ScandirIterator_is_closed(iterator)) {
13913         ScandirIterator_closedir(iterator);
13914 
13915         if (PyErr_ResourceWarning((PyObject *)iterator, 1,
13916                                   "unclosed scandir iterator %R", iterator)) {
13917             /* Spurious errors can appear at shutdown */
13918             if (PyErr_ExceptionMatches(PyExc_Warning)) {
13919                 PyErr_WriteUnraisable((PyObject *) iterator);
13920             }
13921         }
13922     }
13923 
13924     path_cleanup(&iterator->path);
13925 
13926     /* Restore the saved exception. */
13927     PyErr_Restore(error_type, error_value, error_traceback);
13928 }
13929 
13930 static void
ScandirIterator_dealloc(ScandirIterator * iterator)13931 ScandirIterator_dealloc(ScandirIterator *iterator)
13932 {
13933     PyTypeObject *tp = Py_TYPE(iterator);
13934     if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
13935         return;
13936 
13937     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13938     free_func(iterator);
13939     Py_DECREF(tp);
13940 }
13941 
13942 static PyMethodDef ScandirIterator_methods[] = {
13943     {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
13944     {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
13945     {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
13946     {NULL}
13947 };
13948 
13949 static PyType_Slot ScandirIteratorType_slots[] = {
13950     {Py_tp_new, _disabled_new},
13951     {Py_tp_dealloc, ScandirIterator_dealloc},
13952     {Py_tp_finalize, ScandirIterator_finalize},
13953     {Py_tp_iter, PyObject_SelfIter},
13954     {Py_tp_iternext, ScandirIterator_iternext},
13955     {Py_tp_methods, ScandirIterator_methods},
13956     {0, 0},
13957 };
13958 
13959 static PyType_Spec ScandirIteratorType_spec = {
13960     MODNAME ".ScandirIterator",
13961     sizeof(ScandirIterator),
13962     0,
13963     // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
13964     // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
13965     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE,
13966     ScandirIteratorType_slots
13967 };
13968 
13969 /*[clinic input]
13970 os.scandir
13971 
13972     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
13973 
13974 Return an iterator of DirEntry objects for given path.
13975 
13976 path can be specified as either str, bytes, or a path-like object.  If path
13977 is bytes, the names of yielded DirEntry objects will also be bytes; in
13978 all other circumstances they will be str.
13979 
13980 If path is None, uses the path='.'.
13981 [clinic start generated code]*/
13982 
13983 static PyObject *
os_scandir_impl(PyObject * module,path_t * path)13984 os_scandir_impl(PyObject *module, path_t *path)
13985 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
13986 {
13987     ScandirIterator *iterator;
13988 #ifdef MS_WINDOWS
13989     wchar_t *path_strW;
13990 #else
13991     const char *path_str;
13992 #ifdef HAVE_FDOPENDIR
13993     int fd = -1;
13994 #endif
13995 #endif
13996 
13997     if (PySys_Audit("os.scandir", "O",
13998                     path->object ? path->object : Py_None) < 0) {
13999         return NULL;
14000     }
14001 
14002     PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
14003     iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
14004     if (!iterator)
14005         return NULL;
14006 
14007 #ifdef MS_WINDOWS
14008     iterator->handle = INVALID_HANDLE_VALUE;
14009 #else
14010     iterator->dirp = NULL;
14011 #endif
14012 
14013     memcpy(&iterator->path, path, sizeof(path_t));
14014     /* Move the ownership to iterator->path */
14015     path->object = NULL;
14016     path->cleanup = NULL;
14017 
14018 #ifdef MS_WINDOWS
14019     iterator->first_time = 1;
14020 
14021     path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
14022     if (!path_strW)
14023         goto error;
14024 
14025     Py_BEGIN_ALLOW_THREADS
14026     iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
14027     Py_END_ALLOW_THREADS
14028 
14029     PyMem_Free(path_strW);
14030 
14031     if (iterator->handle == INVALID_HANDLE_VALUE) {
14032         path_error(&iterator->path);
14033         goto error;
14034     }
14035 #else /* POSIX */
14036     errno = 0;
14037 #ifdef HAVE_FDOPENDIR
14038     if (iterator->path.fd != -1) {
14039       if (HAVE_FDOPENDIR_RUNTIME) {
14040         /* closedir() closes the FD, so we duplicate it */
14041         fd = _Py_dup(path->fd);
14042         if (fd == -1)
14043             goto error;
14044 
14045         Py_BEGIN_ALLOW_THREADS
14046         iterator->dirp = fdopendir(fd);
14047         Py_END_ALLOW_THREADS
14048       } else {
14049         PyErr_SetString(PyExc_TypeError,
14050             "scandir: path should be string, bytes, os.PathLike or None, not int");
14051         return NULL;
14052       }
14053     }
14054     else
14055 #endif
14056     {
14057         if (iterator->path.narrow)
14058             path_str = iterator->path.narrow;
14059         else
14060             path_str = ".";
14061 
14062         Py_BEGIN_ALLOW_THREADS
14063         iterator->dirp = opendir(path_str);
14064         Py_END_ALLOW_THREADS
14065     }
14066 
14067     if (!iterator->dirp) {
14068         path_error(&iterator->path);
14069 #ifdef HAVE_FDOPENDIR
14070         if (fd != -1) {
14071             Py_BEGIN_ALLOW_THREADS
14072             close(fd);
14073             Py_END_ALLOW_THREADS
14074         }
14075 #endif
14076         goto error;
14077     }
14078 #endif
14079 
14080     return (PyObject *)iterator;
14081 
14082 error:
14083     Py_DECREF(iterator);
14084     return NULL;
14085 }
14086 
14087 /*
14088     Return the file system path representation of the object.
14089 
14090     If the object is str or bytes, then allow it to pass through with
14091     an incremented refcount. If the object defines __fspath__(), then
14092     return the result of that method. All other types raise a TypeError.
14093 */
14094 PyObject *
PyOS_FSPath(PyObject * path)14095 PyOS_FSPath(PyObject *path)
14096 {
14097     /* For error message reasons, this function is manually inlined in
14098        path_converter(). */
14099     PyObject *func = NULL;
14100     PyObject *path_repr = NULL;
14101 
14102     if (PyUnicode_Check(path) || PyBytes_Check(path)) {
14103         Py_INCREF(path);
14104         return path;
14105     }
14106 
14107     func = _PyObject_LookupSpecial(path, &PyId___fspath__);
14108     if (NULL == func) {
14109         return PyErr_Format(PyExc_TypeError,
14110                             "expected str, bytes or os.PathLike object, "
14111                             "not %.200s",
14112                             _PyType_Name(Py_TYPE(path)));
14113     }
14114 
14115     path_repr = _PyObject_CallNoArg(func);
14116     Py_DECREF(func);
14117     if (NULL == path_repr) {
14118         return NULL;
14119     }
14120 
14121     if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
14122         PyErr_Format(PyExc_TypeError,
14123                      "expected %.200s.__fspath__() to return str or bytes, "
14124                      "not %.200s", _PyType_Name(Py_TYPE(path)),
14125                      _PyType_Name(Py_TYPE(path_repr)));
14126         Py_DECREF(path_repr);
14127         return NULL;
14128     }
14129 
14130     return path_repr;
14131 }
14132 
14133 /*[clinic input]
14134 os.fspath
14135 
14136     path: object
14137 
14138 Return the file system path representation of the object.
14139 
14140 If the object is str or bytes, then allow it to pass through as-is. If the
14141 object defines __fspath__(), then return the result of that method. All other
14142 types raise a TypeError.
14143 [clinic start generated code]*/
14144 
14145 static PyObject *
os_fspath_impl(PyObject * module,PyObject * path)14146 os_fspath_impl(PyObject *module, PyObject *path)
14147 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
14148 {
14149     return PyOS_FSPath(path);
14150 }
14151 
14152 #ifdef HAVE_GETRANDOM_SYSCALL
14153 /*[clinic input]
14154 os.getrandom
14155 
14156     size: Py_ssize_t
14157     flags: int=0
14158 
14159 Obtain a series of random bytes.
14160 [clinic start generated code]*/
14161 
14162 static PyObject *
os_getrandom_impl(PyObject * module,Py_ssize_t size,int flags)14163 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
14164 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
14165 {
14166     PyObject *bytes;
14167     Py_ssize_t n;
14168 
14169     if (size < 0) {
14170         errno = EINVAL;
14171         return posix_error();
14172     }
14173 
14174     bytes = PyBytes_FromStringAndSize(NULL, size);
14175     if (bytes == NULL) {
14176         PyErr_NoMemory();
14177         return NULL;
14178     }
14179 
14180     while (1) {
14181         n = syscall(SYS_getrandom,
14182                     PyBytes_AS_STRING(bytes),
14183                     PyBytes_GET_SIZE(bytes),
14184                     flags);
14185         if (n < 0 && errno == EINTR) {
14186             if (PyErr_CheckSignals() < 0) {
14187                 goto error;
14188             }
14189 
14190             /* getrandom() was interrupted by a signal: retry */
14191             continue;
14192         }
14193         break;
14194     }
14195 
14196     if (n < 0) {
14197         PyErr_SetFromErrno(PyExc_OSError);
14198         goto error;
14199     }
14200 
14201     if (n != size) {
14202         _PyBytes_Resize(&bytes, n);
14203     }
14204 
14205     return bytes;
14206 
14207 error:
14208     Py_DECREF(bytes);
14209     return NULL;
14210 }
14211 #endif   /* HAVE_GETRANDOM_SYSCALL */
14212 
14213 #ifdef MS_WINDOWS
14214 /* bpo-36085: Helper functions for managing DLL search directories
14215  * on win32
14216  */
14217 
14218 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
14219 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
14220 
14221 /*[clinic input]
14222 os._add_dll_directory
14223 
14224     path: path_t
14225 
14226 Add a path to the DLL search path.
14227 
14228 This search path is used when resolving dependencies for imported
14229 extension modules (the module itself is resolved through sys.path),
14230 and also by ctypes.
14231 
14232 Returns an opaque value that may be passed to os.remove_dll_directory
14233 to remove this directory from the search path.
14234 [clinic start generated code]*/
14235 
14236 static PyObject *
os__add_dll_directory_impl(PyObject * module,path_t * path)14237 os__add_dll_directory_impl(PyObject *module, path_t *path)
14238 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
14239 {
14240     HMODULE hKernel32;
14241     PAddDllDirectory AddDllDirectory;
14242     DLL_DIRECTORY_COOKIE cookie = 0;
14243     DWORD err = 0;
14244 
14245     if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
14246         return NULL;
14247     }
14248 
14249     /* For Windows 7, we have to load this. As this will be a fairly
14250        infrequent operation, just do it each time. Kernel32 is always
14251        loaded. */
14252     Py_BEGIN_ALLOW_THREADS
14253     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14254         !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
14255             hKernel32, "AddDllDirectory")) ||
14256         !(cookie = (*AddDllDirectory)(path->wide))) {
14257         err = GetLastError();
14258     }
14259     Py_END_ALLOW_THREADS
14260 
14261     if (err) {
14262         return win32_error_object_err("add_dll_directory",
14263                                       path->object, err);
14264     }
14265 
14266     return PyCapsule_New(cookie, "DLL directory cookie", NULL);
14267 }
14268 
14269 /*[clinic input]
14270 os._remove_dll_directory
14271 
14272     cookie: object
14273 
14274 Removes a path from the DLL search path.
14275 
14276 The parameter is an opaque value that was returned from
14277 os.add_dll_directory. You can only remove directories that you added
14278 yourself.
14279 [clinic start generated code]*/
14280 
14281 static PyObject *
os__remove_dll_directory_impl(PyObject * module,PyObject * cookie)14282 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
14283 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
14284 {
14285     HMODULE hKernel32;
14286     PRemoveDllDirectory RemoveDllDirectory;
14287     DLL_DIRECTORY_COOKIE cookieValue;
14288     DWORD err = 0;
14289 
14290     if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
14291         PyErr_SetString(PyExc_TypeError,
14292             "Provided cookie was not returned from os.add_dll_directory");
14293         return NULL;
14294     }
14295 
14296     cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
14297         cookie, "DLL directory cookie");
14298 
14299     /* For Windows 7, we have to load this. As this will be a fairly
14300        infrequent operation, just do it each time. Kernel32 is always
14301        loaded. */
14302     Py_BEGIN_ALLOW_THREADS
14303     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14304         !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
14305             hKernel32, "RemoveDllDirectory")) ||
14306         !(*RemoveDllDirectory)(cookieValue)) {
14307         err = GetLastError();
14308     }
14309     Py_END_ALLOW_THREADS
14310 
14311     if (err) {
14312         return win32_error_object_err("remove_dll_directory",
14313                                       NULL, err);
14314     }
14315 
14316     if (PyCapsule_SetName(cookie, NULL)) {
14317         return NULL;
14318     }
14319 
14320     Py_RETURN_NONE;
14321 }
14322 
14323 #endif
14324 
14325 
14326 /* Only check if WIFEXITED is available: expect that it comes
14327    with WEXITSTATUS, WIFSIGNALED, etc.
14328 
14329    os.waitstatus_to_exitcode() is implemented in C and not in Python, so
14330    subprocess can safely call it during late Python finalization without
14331    risking that used os attributes were set to None by _PyImport_Cleanup(). */
14332 #if defined(WIFEXITED) || defined(MS_WINDOWS)
14333 /*[clinic input]
14334 os.waitstatus_to_exitcode
14335 
14336     status as status_obj: object
14337 
14338 Convert a wait status to an exit code.
14339 
14340 On Unix:
14341 
14342 * If WIFEXITED(status) is true, return WEXITSTATUS(status).
14343 * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
14344 * Otherwise, raise a ValueError.
14345 
14346 On Windows, return status shifted right by 8 bits.
14347 
14348 On Unix, if the process is being traced or if waitpid() was called with
14349 WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
14350 This function must not be called if WIFSTOPPED(status) is true.
14351 [clinic start generated code]*/
14352 
14353 static PyObject *
os_waitstatus_to_exitcode_impl(PyObject * module,PyObject * status_obj)14354 os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
14355 /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
14356 {
14357     if (PyFloat_Check(status_obj)) {
14358         PyErr_SetString(PyExc_TypeError,
14359                         "integer argument expected, got float" );
14360         return NULL;
14361     }
14362 #ifndef MS_WINDOWS
14363     int status = _PyLong_AsInt(status_obj);
14364     if (status == -1 && PyErr_Occurred()) {
14365         return NULL;
14366     }
14367 
14368     WAIT_TYPE wait_status;
14369     WAIT_STATUS_INT(wait_status) = status;
14370     int exitcode;
14371     if (WIFEXITED(wait_status)) {
14372         exitcode = WEXITSTATUS(wait_status);
14373         /* Sanity check to provide warranty on the function behavior.
14374            It should not occur in practice */
14375         if (exitcode < 0) {
14376             PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
14377             return NULL;
14378         }
14379     }
14380     else if (WIFSIGNALED(wait_status)) {
14381         int signum = WTERMSIG(wait_status);
14382         /* Sanity check to provide warranty on the function behavior.
14383            It should not occurs in practice */
14384         if (signum <= 0) {
14385             PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
14386             return NULL;
14387         }
14388         exitcode = -signum;
14389     } else if (WIFSTOPPED(wait_status)) {
14390         /* Status only received if the process is being traced
14391            or if waitpid() was called with WUNTRACED option. */
14392         int signum = WSTOPSIG(wait_status);
14393         PyErr_Format(PyExc_ValueError,
14394                      "process stopped by delivery of signal %i",
14395                      signum);
14396         return NULL;
14397     }
14398     else {
14399         PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
14400         return NULL;
14401     }
14402     return PyLong_FromLong(exitcode);
14403 #else
14404     /* Windows implementation: see os.waitpid() implementation
14405        which uses _cwait(). */
14406     unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
14407     if (status == (unsigned long long)-1 && PyErr_Occurred()) {
14408         return NULL;
14409     }
14410 
14411     unsigned long long exitcode = (status >> 8);
14412     /* ExitProcess() accepts an UINT type:
14413        reject exit code which doesn't fit in an UINT */
14414     if (exitcode > UINT_MAX) {
14415         PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
14416         return NULL;
14417     }
14418     return PyLong_FromUnsignedLong((unsigned long)exitcode);
14419 #endif
14420 }
14421 #endif
14422 
14423 
14424 static PyMethodDef posix_methods[] = {
14425 
14426     OS_STAT_METHODDEF
14427     OS_ACCESS_METHODDEF
14428     OS_TTYNAME_METHODDEF
14429     OS_CHDIR_METHODDEF
14430     OS_CHFLAGS_METHODDEF
14431     OS_CHMOD_METHODDEF
14432     OS_FCHMOD_METHODDEF
14433     OS_LCHMOD_METHODDEF
14434     OS_CHOWN_METHODDEF
14435     OS_FCHOWN_METHODDEF
14436     OS_LCHOWN_METHODDEF
14437     OS_LCHFLAGS_METHODDEF
14438     OS_CHROOT_METHODDEF
14439     OS_CTERMID_METHODDEF
14440     OS_GETCWD_METHODDEF
14441     OS_GETCWDB_METHODDEF
14442     OS_LINK_METHODDEF
14443     OS_LISTDIR_METHODDEF
14444     OS_LSTAT_METHODDEF
14445     OS_MKDIR_METHODDEF
14446     OS_NICE_METHODDEF
14447     OS_GETPRIORITY_METHODDEF
14448     OS_SETPRIORITY_METHODDEF
14449     OS_POSIX_SPAWN_METHODDEF
14450     OS_POSIX_SPAWNP_METHODDEF
14451     OS_READLINK_METHODDEF
14452     OS_COPY_FILE_RANGE_METHODDEF
14453     OS_RENAME_METHODDEF
14454     OS_REPLACE_METHODDEF
14455     OS_RMDIR_METHODDEF
14456     OS_SYMLINK_METHODDEF
14457     OS_SYSTEM_METHODDEF
14458     OS_UMASK_METHODDEF
14459     OS_UNAME_METHODDEF
14460     OS_UNLINK_METHODDEF
14461     OS_REMOVE_METHODDEF
14462     OS_UTIME_METHODDEF
14463     OS_TIMES_METHODDEF
14464     OS__EXIT_METHODDEF
14465     OS__FCOPYFILE_METHODDEF
14466     OS_EXECV_METHODDEF
14467     OS_EXECVE_METHODDEF
14468     OS_SPAWNV_METHODDEF
14469     OS_SPAWNVE_METHODDEF
14470     OS_FORK1_METHODDEF
14471     OS_FORK_METHODDEF
14472     OS_REGISTER_AT_FORK_METHODDEF
14473     OS_SCHED_GET_PRIORITY_MAX_METHODDEF
14474     OS_SCHED_GET_PRIORITY_MIN_METHODDEF
14475     OS_SCHED_GETPARAM_METHODDEF
14476     OS_SCHED_GETSCHEDULER_METHODDEF
14477     OS_SCHED_RR_GET_INTERVAL_METHODDEF
14478     OS_SCHED_SETPARAM_METHODDEF
14479     OS_SCHED_SETSCHEDULER_METHODDEF
14480     OS_SCHED_YIELD_METHODDEF
14481     OS_SCHED_SETAFFINITY_METHODDEF
14482     OS_SCHED_GETAFFINITY_METHODDEF
14483     OS_OPENPTY_METHODDEF
14484     OS_FORKPTY_METHODDEF
14485     OS_GETEGID_METHODDEF
14486     OS_GETEUID_METHODDEF
14487     OS_GETGID_METHODDEF
14488     OS_GETGROUPLIST_METHODDEF
14489     OS_GETGROUPS_METHODDEF
14490     OS_GETPID_METHODDEF
14491     OS_GETPGRP_METHODDEF
14492     OS_GETPPID_METHODDEF
14493     OS_GETUID_METHODDEF
14494     OS_GETLOGIN_METHODDEF
14495     OS_KILL_METHODDEF
14496     OS_KILLPG_METHODDEF
14497     OS_PLOCK_METHODDEF
14498     OS_STARTFILE_METHODDEF
14499     OS_SETUID_METHODDEF
14500     OS_SETEUID_METHODDEF
14501     OS_SETREUID_METHODDEF
14502     OS_SETGID_METHODDEF
14503     OS_SETEGID_METHODDEF
14504     OS_SETREGID_METHODDEF
14505     OS_SETGROUPS_METHODDEF
14506     OS_INITGROUPS_METHODDEF
14507     OS_GETPGID_METHODDEF
14508     OS_SETPGRP_METHODDEF
14509     OS_WAIT_METHODDEF
14510     OS_WAIT3_METHODDEF
14511     OS_WAIT4_METHODDEF
14512     OS_WAITID_METHODDEF
14513     OS_WAITPID_METHODDEF
14514     OS_PIDFD_OPEN_METHODDEF
14515     OS_GETSID_METHODDEF
14516     OS_SETSID_METHODDEF
14517     OS_SETPGID_METHODDEF
14518     OS_TCGETPGRP_METHODDEF
14519     OS_TCSETPGRP_METHODDEF
14520     OS_OPEN_METHODDEF
14521     OS_CLOSE_METHODDEF
14522     OS_CLOSERANGE_METHODDEF
14523     OS_DEVICE_ENCODING_METHODDEF
14524     OS_DUP_METHODDEF
14525     OS_DUP2_METHODDEF
14526     OS_LOCKF_METHODDEF
14527     OS_LSEEK_METHODDEF
14528     OS_READ_METHODDEF
14529     OS_READV_METHODDEF
14530     OS_PREAD_METHODDEF
14531     OS_PREADV_METHODDEF
14532     OS_WRITE_METHODDEF
14533     OS_WRITEV_METHODDEF
14534     OS_PWRITE_METHODDEF
14535     OS_PWRITEV_METHODDEF
14536     OS_SENDFILE_METHODDEF
14537     OS_FSTAT_METHODDEF
14538     OS_ISATTY_METHODDEF
14539     OS_PIPE_METHODDEF
14540     OS_PIPE2_METHODDEF
14541     OS_MKFIFO_METHODDEF
14542     OS_MKNOD_METHODDEF
14543     OS_MAJOR_METHODDEF
14544     OS_MINOR_METHODDEF
14545     OS_MAKEDEV_METHODDEF
14546     OS_FTRUNCATE_METHODDEF
14547     OS_TRUNCATE_METHODDEF
14548     OS_POSIX_FALLOCATE_METHODDEF
14549     OS_POSIX_FADVISE_METHODDEF
14550     OS_PUTENV_METHODDEF
14551     OS_UNSETENV_METHODDEF
14552     OS_STRERROR_METHODDEF
14553     OS_FCHDIR_METHODDEF
14554     OS_FSYNC_METHODDEF
14555     OS_SYNC_METHODDEF
14556     OS_FDATASYNC_METHODDEF
14557     OS_WCOREDUMP_METHODDEF
14558     OS_WIFCONTINUED_METHODDEF
14559     OS_WIFSTOPPED_METHODDEF
14560     OS_WIFSIGNALED_METHODDEF
14561     OS_WIFEXITED_METHODDEF
14562     OS_WEXITSTATUS_METHODDEF
14563     OS_WTERMSIG_METHODDEF
14564     OS_WSTOPSIG_METHODDEF
14565     OS_FSTATVFS_METHODDEF
14566     OS_STATVFS_METHODDEF
14567     OS_CONFSTR_METHODDEF
14568     OS_SYSCONF_METHODDEF
14569     OS_FPATHCONF_METHODDEF
14570     OS_PATHCONF_METHODDEF
14571     OS_ABORT_METHODDEF
14572     OS__GETFULLPATHNAME_METHODDEF
14573     OS__GETDISKUSAGE_METHODDEF
14574     OS__GETFINALPATHNAME_METHODDEF
14575     OS__GETVOLUMEPATHNAME_METHODDEF
14576     OS_GETLOADAVG_METHODDEF
14577     OS_URANDOM_METHODDEF
14578     OS_SETRESUID_METHODDEF
14579     OS_SETRESGID_METHODDEF
14580     OS_GETRESUID_METHODDEF
14581     OS_GETRESGID_METHODDEF
14582 
14583     OS_GETXATTR_METHODDEF
14584     OS_SETXATTR_METHODDEF
14585     OS_REMOVEXATTR_METHODDEF
14586     OS_LISTXATTR_METHODDEF
14587 
14588     OS_GET_TERMINAL_SIZE_METHODDEF
14589     OS_CPU_COUNT_METHODDEF
14590     OS_GET_INHERITABLE_METHODDEF
14591     OS_SET_INHERITABLE_METHODDEF
14592     OS_GET_HANDLE_INHERITABLE_METHODDEF
14593     OS_SET_HANDLE_INHERITABLE_METHODDEF
14594     OS_GET_BLOCKING_METHODDEF
14595     OS_SET_BLOCKING_METHODDEF
14596     OS_SCANDIR_METHODDEF
14597     OS_FSPATH_METHODDEF
14598     OS_GETRANDOM_METHODDEF
14599     OS_MEMFD_CREATE_METHODDEF
14600     OS__ADD_DLL_DIRECTORY_METHODDEF
14601     OS__REMOVE_DLL_DIRECTORY_METHODDEF
14602     OS_WAITSTATUS_TO_EXITCODE_METHODDEF
14603     {NULL,              NULL}            /* Sentinel */
14604 };
14605 
14606 static int
all_ins(PyObject * m)14607 all_ins(PyObject *m)
14608 {
14609 #ifdef F_OK
14610     if (PyModule_AddIntMacro(m, F_OK)) return -1;
14611 #endif
14612 #ifdef R_OK
14613     if (PyModule_AddIntMacro(m, R_OK)) return -1;
14614 #endif
14615 #ifdef W_OK
14616     if (PyModule_AddIntMacro(m, W_OK)) return -1;
14617 #endif
14618 #ifdef X_OK
14619     if (PyModule_AddIntMacro(m, X_OK)) return -1;
14620 #endif
14621 #ifdef NGROUPS_MAX
14622     if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
14623 #endif
14624 #ifdef TMP_MAX
14625     if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
14626 #endif
14627 #ifdef WCONTINUED
14628     if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
14629 #endif
14630 #ifdef WNOHANG
14631     if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
14632 #endif
14633 #ifdef WUNTRACED
14634     if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
14635 #endif
14636 #ifdef O_RDONLY
14637     if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
14638 #endif
14639 #ifdef O_WRONLY
14640     if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
14641 #endif
14642 #ifdef O_RDWR
14643     if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
14644 #endif
14645 #ifdef O_NDELAY
14646     if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
14647 #endif
14648 #ifdef O_NONBLOCK
14649     if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
14650 #endif
14651 #ifdef O_APPEND
14652     if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
14653 #endif
14654 #ifdef O_DSYNC
14655     if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
14656 #endif
14657 #ifdef O_RSYNC
14658     if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
14659 #endif
14660 #ifdef O_SYNC
14661     if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
14662 #endif
14663 #ifdef O_NOCTTY
14664     if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
14665 #endif
14666 #ifdef O_CREAT
14667     if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
14668 #endif
14669 #ifdef O_EXCL
14670     if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
14671 #endif
14672 #ifdef O_TRUNC
14673     if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
14674 #endif
14675 #ifdef O_BINARY
14676     if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
14677 #endif
14678 #ifdef O_TEXT
14679     if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
14680 #endif
14681 #ifdef O_XATTR
14682     if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
14683 #endif
14684 #ifdef O_LARGEFILE
14685     if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
14686 #endif
14687 #ifndef __GNU__
14688 #ifdef O_SHLOCK
14689     if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
14690 #endif
14691 #ifdef O_EXLOCK
14692     if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
14693 #endif
14694 #endif
14695 #ifdef O_EXEC
14696     if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
14697 #endif
14698 #ifdef O_SEARCH
14699     if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
14700 #endif
14701 #ifdef O_PATH
14702     if (PyModule_AddIntMacro(m, O_PATH)) return -1;
14703 #endif
14704 #ifdef O_TTY_INIT
14705     if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
14706 #endif
14707 #ifdef O_TMPFILE
14708     if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
14709 #endif
14710 #ifdef PRIO_PROCESS
14711     if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
14712 #endif
14713 #ifdef PRIO_PGRP
14714     if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
14715 #endif
14716 #ifdef PRIO_USER
14717     if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
14718 #endif
14719 #ifdef O_CLOEXEC
14720     if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
14721 #endif
14722 #ifdef O_ACCMODE
14723     if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
14724 #endif
14725 
14726 
14727 #ifdef SEEK_HOLE
14728     if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
14729 #endif
14730 #ifdef SEEK_DATA
14731     if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
14732 #endif
14733 
14734 /* MS Windows */
14735 #ifdef O_NOINHERIT
14736     /* Don't inherit in child processes. */
14737     if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
14738 #endif
14739 #ifdef _O_SHORT_LIVED
14740     /* Optimize for short life (keep in memory). */
14741     /* MS forgot to define this one with a non-underscore form too. */
14742     if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
14743 #endif
14744 #ifdef O_TEMPORARY
14745     /* Automatically delete when last handle is closed. */
14746     if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
14747 #endif
14748 #ifdef O_RANDOM
14749     /* Optimize for random access. */
14750     if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
14751 #endif
14752 #ifdef O_SEQUENTIAL
14753     /* Optimize for sequential access. */
14754     if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
14755 #endif
14756 
14757 /* GNU extensions. */
14758 #ifdef O_ASYNC
14759     /* Send a SIGIO signal whenever input or output
14760        becomes available on file descriptor */
14761     if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
14762 #endif
14763 #ifdef O_DIRECT
14764     /* Direct disk access. */
14765     if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
14766 #endif
14767 #ifdef O_DIRECTORY
14768     /* Must be a directory.      */
14769     if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
14770 #endif
14771 #ifdef O_NOFOLLOW
14772     /* Do not follow links.      */
14773     if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
14774 #endif
14775 #ifdef O_NOLINKS
14776     /* Fails if link count of the named file is greater than 1 */
14777     if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
14778 #endif
14779 #ifdef O_NOATIME
14780     /* Do not update the access time. */
14781     if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
14782 #endif
14783 
14784     /* These come from sysexits.h */
14785 #ifdef EX_OK
14786     if (PyModule_AddIntMacro(m, EX_OK)) return -1;
14787 #endif /* EX_OK */
14788 #ifdef EX_USAGE
14789     if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
14790 #endif /* EX_USAGE */
14791 #ifdef EX_DATAERR
14792     if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
14793 #endif /* EX_DATAERR */
14794 #ifdef EX_NOINPUT
14795     if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
14796 #endif /* EX_NOINPUT */
14797 #ifdef EX_NOUSER
14798     if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
14799 #endif /* EX_NOUSER */
14800 #ifdef EX_NOHOST
14801     if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
14802 #endif /* EX_NOHOST */
14803 #ifdef EX_UNAVAILABLE
14804     if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
14805 #endif /* EX_UNAVAILABLE */
14806 #ifdef EX_SOFTWARE
14807     if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
14808 #endif /* EX_SOFTWARE */
14809 #ifdef EX_OSERR
14810     if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
14811 #endif /* EX_OSERR */
14812 #ifdef EX_OSFILE
14813     if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
14814 #endif /* EX_OSFILE */
14815 #ifdef EX_CANTCREAT
14816     if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
14817 #endif /* EX_CANTCREAT */
14818 #ifdef EX_IOERR
14819     if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
14820 #endif /* EX_IOERR */
14821 #ifdef EX_TEMPFAIL
14822     if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
14823 #endif /* EX_TEMPFAIL */
14824 #ifdef EX_PROTOCOL
14825     if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
14826 #endif /* EX_PROTOCOL */
14827 #ifdef EX_NOPERM
14828     if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
14829 #endif /* EX_NOPERM */
14830 #ifdef EX_CONFIG
14831     if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
14832 #endif /* EX_CONFIG */
14833 #ifdef EX_NOTFOUND
14834     if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
14835 #endif /* EX_NOTFOUND */
14836 
14837     /* statvfs */
14838 #ifdef ST_RDONLY
14839     if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
14840 #endif /* ST_RDONLY */
14841 #ifdef ST_NOSUID
14842     if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
14843 #endif /* ST_NOSUID */
14844 
14845        /* GNU extensions */
14846 #ifdef ST_NODEV
14847     if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
14848 #endif /* ST_NODEV */
14849 #ifdef ST_NOEXEC
14850     if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
14851 #endif /* ST_NOEXEC */
14852 #ifdef ST_SYNCHRONOUS
14853     if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
14854 #endif /* ST_SYNCHRONOUS */
14855 #ifdef ST_MANDLOCK
14856     if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
14857 #endif /* ST_MANDLOCK */
14858 #ifdef ST_WRITE
14859     if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
14860 #endif /* ST_WRITE */
14861 #ifdef ST_APPEND
14862     if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
14863 #endif /* ST_APPEND */
14864 #ifdef ST_NOATIME
14865     if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
14866 #endif /* ST_NOATIME */
14867 #ifdef ST_NODIRATIME
14868     if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
14869 #endif /* ST_NODIRATIME */
14870 #ifdef ST_RELATIME
14871     if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
14872 #endif /* ST_RELATIME */
14873 
14874     /* FreeBSD sendfile() constants */
14875 #ifdef SF_NODISKIO
14876     if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
14877 #endif
14878 #ifdef SF_MNOWAIT
14879     if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
14880 #endif
14881 #ifdef SF_SYNC
14882     if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
14883 #endif
14884 
14885     /* constants for posix_fadvise */
14886 #ifdef POSIX_FADV_NORMAL
14887     if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
14888 #endif
14889 #ifdef POSIX_FADV_SEQUENTIAL
14890     if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
14891 #endif
14892 #ifdef POSIX_FADV_RANDOM
14893     if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
14894 #endif
14895 #ifdef POSIX_FADV_NOREUSE
14896     if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
14897 #endif
14898 #ifdef POSIX_FADV_WILLNEED
14899     if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
14900 #endif
14901 #ifdef POSIX_FADV_DONTNEED
14902     if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
14903 #endif
14904 
14905     /* constants for waitid */
14906 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
14907     if (PyModule_AddIntMacro(m, P_PID)) return -1;
14908     if (PyModule_AddIntMacro(m, P_PGID)) return -1;
14909     if (PyModule_AddIntMacro(m, P_ALL)) return -1;
14910 #ifdef P_PIDFD
14911     if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
14912 #endif
14913 #endif
14914 #ifdef WEXITED
14915     if (PyModule_AddIntMacro(m, WEXITED)) return -1;
14916 #endif
14917 #ifdef WNOWAIT
14918     if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
14919 #endif
14920 #ifdef WSTOPPED
14921     if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
14922 #endif
14923 #ifdef CLD_EXITED
14924     if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
14925 #endif
14926 #ifdef CLD_KILLED
14927     if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
14928 #endif
14929 #ifdef CLD_DUMPED
14930     if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
14931 #endif
14932 #ifdef CLD_TRAPPED
14933     if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
14934 #endif
14935 #ifdef CLD_STOPPED
14936     if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
14937 #endif
14938 #ifdef CLD_CONTINUED
14939     if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
14940 #endif
14941 
14942     /* constants for lockf */
14943 #ifdef F_LOCK
14944     if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
14945 #endif
14946 #ifdef F_TLOCK
14947     if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
14948 #endif
14949 #ifdef F_ULOCK
14950     if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
14951 #endif
14952 #ifdef F_TEST
14953     if (PyModule_AddIntMacro(m, F_TEST)) return -1;
14954 #endif
14955 
14956 #ifdef RWF_DSYNC
14957     if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
14958 #endif
14959 #ifdef RWF_HIPRI
14960     if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
14961 #endif
14962 #ifdef RWF_SYNC
14963     if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
14964 #endif
14965 #ifdef RWF_NOWAIT
14966     if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
14967 #endif
14968 
14969 /* constants for posix_spawn */
14970 #ifdef HAVE_POSIX_SPAWN
14971     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
14972     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
14973     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
14974 #endif
14975 
14976 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
14977     if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
14978     if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
14979     if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
14980 #endif
14981 #ifdef HAVE_SPAWNV
14982     if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
14983     if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
14984 #endif
14985 
14986 #ifdef HAVE_SCHED_H
14987 #ifdef SCHED_OTHER
14988     if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
14989 #endif
14990 #ifdef SCHED_FIFO
14991     if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
14992 #endif
14993 #ifdef SCHED_RR
14994     if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
14995 #endif
14996 #ifdef SCHED_SPORADIC
14997     if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
14998 #endif
14999 #ifdef SCHED_BATCH
15000     if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
15001 #endif
15002 #ifdef SCHED_IDLE
15003     if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
15004 #endif
15005 #ifdef SCHED_RESET_ON_FORK
15006     if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
15007 #endif
15008 #ifdef SCHED_SYS
15009     if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
15010 #endif
15011 #ifdef SCHED_IA
15012     if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
15013 #endif
15014 #ifdef SCHED_FSS
15015     if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
15016 #endif
15017 #ifdef SCHED_FX
15018     if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
15019 #endif
15020 #endif
15021 
15022 #ifdef USE_XATTRS
15023     if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
15024     if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
15025     if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
15026 #endif
15027 
15028 #if HAVE_DECL_RTLD_LAZY
15029     if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
15030 #endif
15031 #if HAVE_DECL_RTLD_NOW
15032     if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
15033 #endif
15034 #if HAVE_DECL_RTLD_GLOBAL
15035     if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
15036 #endif
15037 #if HAVE_DECL_RTLD_LOCAL
15038     if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
15039 #endif
15040 #if HAVE_DECL_RTLD_NODELETE
15041     if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
15042 #endif
15043 #if HAVE_DECL_RTLD_NOLOAD
15044     if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
15045 #endif
15046 #if HAVE_DECL_RTLD_DEEPBIND
15047     if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
15048 #endif
15049 #if HAVE_DECL_RTLD_MEMBER
15050     if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
15051 #endif
15052 
15053 #ifdef HAVE_GETRANDOM_SYSCALL
15054     if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
15055     if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
15056 #endif
15057 #ifdef HAVE_MEMFD_CREATE
15058     if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
15059     if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
15060 #ifdef MFD_HUGETLB
15061     if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
15062 #endif
15063 #ifdef MFD_HUGE_SHIFT
15064     if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
15065 #endif
15066 #ifdef MFD_HUGE_MASK
15067     if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
15068 #endif
15069 #ifdef MFD_HUGE_64KB
15070     if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
15071 #endif
15072 #ifdef MFD_HUGE_512KB
15073     if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
15074 #endif
15075 #ifdef MFD_HUGE_1MB
15076     if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
15077 #endif
15078 #ifdef MFD_HUGE_2MB
15079     if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
15080 #endif
15081 #ifdef MFD_HUGE_8MB
15082     if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
15083 #endif
15084 #ifdef MFD_HUGE_16MB
15085     if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
15086 #endif
15087 #ifdef MFD_HUGE_32MB
15088     if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
15089 #endif
15090 #ifdef MFD_HUGE_256MB
15091     if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
15092 #endif
15093 #ifdef MFD_HUGE_512MB
15094     if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
15095 #endif
15096 #ifdef MFD_HUGE_1GB
15097     if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
15098 #endif
15099 #ifdef MFD_HUGE_2GB
15100     if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
15101 #endif
15102 #ifdef MFD_HUGE_16GB
15103     if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
15104 #endif
15105 #endif
15106 
15107 #if defined(__APPLE__)
15108     if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
15109 #endif
15110 
15111 #ifdef MS_WINDOWS
15112     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
15113     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
15114     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
15115     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
15116     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
15117 #endif
15118 
15119     return 0;
15120 }
15121 
15122 
15123 
15124 #define PROBE(name, test) \
15125    static int name(void)  \
15126    {                      \
15127       if (test) {        \
15128           return 1;       \
15129       } else {            \
15130           return 0;       \
15131       }                   \
15132    }
15133 
15134 #ifdef HAVE_FSTATAT
15135 PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
15136 #endif
15137 
15138 #ifdef HAVE_FACCESSAT
15139 PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
15140 #endif
15141 
15142 #ifdef HAVE_FCHMODAT
15143 PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
15144 #endif
15145 
15146 #ifdef HAVE_FCHOWNAT
15147 PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
15148 #endif
15149 
15150 #ifdef HAVE_LINKAT
15151 PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
15152 #endif
15153 
15154 #ifdef HAVE_FDOPENDIR
15155 PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
15156 #endif
15157 
15158 #ifdef HAVE_MKDIRAT
15159 PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
15160 #endif
15161 
15162 #ifdef HAVE_RENAMEAT
15163 PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
15164 #endif
15165 
15166 #ifdef HAVE_UNLINKAT
15167 PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
15168 #endif
15169 
15170 #ifdef HAVE_OPENAT
15171 PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
15172 #endif
15173 
15174 #ifdef HAVE_READLINKAT
15175 PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
15176 #endif
15177 
15178 #ifdef HAVE_SYMLINKAT
15179 PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
15180 #endif
15181 
15182 #ifdef HAVE_FUTIMENS
15183 PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
15184 #endif
15185 
15186 #ifdef HAVE_UTIMENSAT
15187 PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
15188 #endif
15189 
15190 
15191 
15192 
15193 static const struct have_function {
15194     const char * const label;
15195     int (*probe)(void);
15196 } have_functions[] = {
15197 
15198 #ifdef HAVE_FACCESSAT
15199     { "HAVE_FACCESSAT", probe_faccessat },
15200 #endif
15201 
15202 #ifdef HAVE_FCHDIR
15203     { "HAVE_FCHDIR", NULL },
15204 #endif
15205 
15206 #ifdef HAVE_FCHMOD
15207     { "HAVE_FCHMOD", NULL },
15208 #endif
15209 
15210 #ifdef HAVE_FCHMODAT
15211     { "HAVE_FCHMODAT", probe_fchmodat },
15212 #endif
15213 
15214 #ifdef HAVE_FCHOWN
15215     { "HAVE_FCHOWN", NULL },
15216 #endif
15217 
15218 #ifdef HAVE_FCHOWNAT
15219     { "HAVE_FCHOWNAT", probe_fchownat },
15220 #endif
15221 
15222 #ifdef HAVE_FEXECVE
15223     { "HAVE_FEXECVE", NULL },
15224 #endif
15225 
15226 #ifdef HAVE_FDOPENDIR
15227     { "HAVE_FDOPENDIR", probe_fdopendir },
15228 #endif
15229 
15230 #ifdef HAVE_FPATHCONF
15231     { "HAVE_FPATHCONF", NULL },
15232 #endif
15233 
15234 #ifdef HAVE_FSTATAT
15235     { "HAVE_FSTATAT", probe_fstatat },
15236 #endif
15237 
15238 #ifdef HAVE_FSTATVFS
15239     { "HAVE_FSTATVFS", NULL },
15240 #endif
15241 
15242 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
15243     { "HAVE_FTRUNCATE", NULL },
15244 #endif
15245 
15246 #ifdef HAVE_FUTIMENS
15247     { "HAVE_FUTIMENS", probe_futimens },
15248 #endif
15249 
15250 #ifdef HAVE_FUTIMES
15251     { "HAVE_FUTIMES", NULL },
15252 #endif
15253 
15254 #ifdef HAVE_FUTIMESAT
15255     { "HAVE_FUTIMESAT", NULL },
15256 #endif
15257 
15258 #ifdef HAVE_LINKAT
15259     { "HAVE_LINKAT", probe_linkat },
15260 #endif
15261 
15262 #ifdef HAVE_LCHFLAGS
15263     { "HAVE_LCHFLAGS", NULL },
15264 #endif
15265 
15266 #ifdef HAVE_LCHMOD
15267     { "HAVE_LCHMOD", NULL },
15268 #endif
15269 
15270 #ifdef HAVE_LCHOWN
15271     { "HAVE_LCHOWN", NULL },
15272 #endif
15273 
15274 #ifdef HAVE_LSTAT
15275     { "HAVE_LSTAT", NULL },
15276 #endif
15277 
15278 #ifdef HAVE_LUTIMES
15279     { "HAVE_LUTIMES", NULL },
15280 #endif
15281 
15282 #ifdef HAVE_MEMFD_CREATE
15283     { "HAVE_MEMFD_CREATE", NULL },
15284 #endif
15285 
15286 #ifdef HAVE_MKDIRAT
15287     { "HAVE_MKDIRAT", probe_mkdirat },
15288 #endif
15289 
15290 #ifdef HAVE_MKFIFOAT
15291     { "HAVE_MKFIFOAT", NULL },
15292 #endif
15293 
15294 #ifdef HAVE_MKNODAT
15295     { "HAVE_MKNODAT", NULL },
15296 #endif
15297 
15298 #ifdef HAVE_OPENAT
15299     { "HAVE_OPENAT", probe_openat },
15300 #endif
15301 
15302 #ifdef HAVE_READLINKAT
15303     { "HAVE_READLINKAT", probe_readlinkat },
15304 #endif
15305 
15306 #ifdef HAVE_RENAMEAT
15307     { "HAVE_RENAMEAT", probe_renameat },
15308 #endif
15309 
15310 #ifdef HAVE_SYMLINKAT
15311     { "HAVE_SYMLINKAT", probe_symlinkat },
15312 #endif
15313 
15314 #ifdef HAVE_UNLINKAT
15315     { "HAVE_UNLINKAT", probe_unlinkat },
15316 #endif
15317 
15318 #ifdef HAVE_UTIMENSAT
15319     { "HAVE_UTIMENSAT", probe_utimensat },
15320 #endif
15321 
15322 #ifdef MS_WINDOWS
15323     { "MS_WINDOWS", NULL },
15324 #endif
15325 
15326     { NULL, NULL }
15327 };
15328 
15329 
15330 static int
posixmodule_exec(PyObject * m)15331 posixmodule_exec(PyObject *m)
15332 {
15333     _posixstate *state = get_posix_state(m);
15334 
15335 #if defined(HAVE_PWRITEV)
15336     if (HAVE_PWRITEV_RUNTIME) {} else {
15337         PyObject* dct = PyModule_GetDict(m);
15338 
15339         if (dct == NULL) {
15340             return -1;
15341         }
15342 
15343         if (PyDict_DelItemString(dct, "pwritev") == -1) {
15344             PyErr_Clear();
15345         }
15346         if (PyDict_DelItemString(dct, "preadv") == -1) {
15347             PyErr_Clear();
15348         }
15349     }
15350 #endif
15351 
15352     /* Initialize environ dictionary */
15353     PyObject *v = convertenviron();
15354     Py_XINCREF(v);
15355     if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
15356         return -1;
15357     Py_DECREF(v);
15358 
15359     if (all_ins(m))
15360         return -1;
15361 
15362     if (setup_confname_tables(m))
15363         return -1;
15364 
15365     Py_INCREF(PyExc_OSError);
15366     PyModule_AddObject(m, "error", PyExc_OSError);
15367 
15368 #if defined(HAVE_WAITID) && !defined(__APPLE__)
15369     waitid_result_desc.name = MODNAME ".waitid_result";
15370     PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
15371     if (WaitidResultType == NULL) {
15372         return -1;
15373     }
15374     Py_INCREF(WaitidResultType);
15375     PyModule_AddObject(m, "waitid_result", WaitidResultType);
15376     state->WaitidResultType = WaitidResultType;
15377 #endif
15378 
15379     stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
15380     stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
15381     stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
15382     stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
15383     PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
15384     if (StatResultType == NULL) {
15385         return -1;
15386     }
15387     Py_INCREF(StatResultType);
15388     PyModule_AddObject(m, "stat_result", StatResultType);
15389     state->StatResultType = StatResultType;
15390     structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15391     ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
15392 
15393     statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
15394     PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
15395     if (StatVFSResultType == NULL) {
15396         return -1;
15397     }
15398     Py_INCREF(StatVFSResultType);
15399     PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
15400     state->StatVFSResultType = StatVFSResultType;
15401 #ifdef NEED_TICKS_PER_SECOND
15402 #  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15403     ticks_per_second = sysconf(_SC_CLK_TCK);
15404 #  elif defined(HZ)
15405     ticks_per_second = HZ;
15406 #  else
15407     ticks_per_second = 60; /* magic fallback value; may be bogus */
15408 #  endif
15409 #endif
15410 
15411 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
15412     sched_param_desc.name = MODNAME ".sched_param";
15413     PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
15414     if (SchedParamType == NULL) {
15415         return -1;
15416     }
15417     Py_INCREF(SchedParamType);
15418     PyModule_AddObject(m, "sched_param", SchedParamType);
15419     state->SchedParamType = SchedParamType;
15420     ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
15421 #endif
15422 
15423     /* initialize TerminalSize_info */
15424     PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
15425     if (TerminalSizeType == NULL) {
15426         return -1;
15427     }
15428     Py_INCREF(TerminalSizeType);
15429     PyModule_AddObject(m, "terminal_size", TerminalSizeType);
15430     state->TerminalSizeType = TerminalSizeType;
15431 
15432     /* initialize scandir types */
15433     PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
15434     if (ScandirIteratorType == NULL) {
15435         return -1;
15436     }
15437     state->ScandirIteratorType = ScandirIteratorType;
15438 
15439     PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
15440     if (DirEntryType == NULL) {
15441         return -1;
15442     }
15443     Py_INCREF(DirEntryType);
15444     PyModule_AddObject(m, "DirEntry", DirEntryType);
15445     state->DirEntryType = DirEntryType;
15446 
15447     times_result_desc.name = MODNAME ".times_result";
15448     PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
15449     if (TimesResultType == NULL) {
15450         return -1;
15451     }
15452     Py_INCREF(TimesResultType);
15453     PyModule_AddObject(m, "times_result", TimesResultType);
15454     state->TimesResultType = TimesResultType;
15455 
15456     PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
15457     if (UnameResultType == NULL) {
15458         return -1;
15459     }
15460     Py_INCREF(UnameResultType);
15461     PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
15462     state->UnameResultType = (PyObject *)UnameResultType;
15463 
15464     if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
15465         return -1;
15466 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
15467     state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
15468     if (state->struct_rusage == NULL)
15469         return -1;
15470 #endif
15471     state->st_mode = PyUnicode_InternFromString("st_mode");
15472     if (state->st_mode == NULL)
15473         return -1;
15474 
15475     /* suppress "function not used" warnings */
15476     {
15477     int ignored;
15478     fd_specified("", -1);
15479     follow_symlinks_specified("", 1);
15480     dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
15481     dir_fd_converter(Py_None, &ignored);
15482     dir_fd_unavailable(Py_None, &ignored);
15483     }
15484 
15485     /*
15486      * provide list of locally available functions
15487      * so os.py can populate support_* lists
15488      */
15489     PyObject *list = PyList_New(0);
15490     if (!list) {
15491         return -1;
15492     }
15493     for (const struct have_function *trace = have_functions; trace->label; trace++) {
15494         PyObject *unicode;
15495         if (trace->probe && !trace->probe()) continue;
15496         unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
15497         if (!unicode)
15498             return -1;
15499         if (PyList_Append(list, unicode))
15500             return -1;
15501         Py_DECREF(unicode);
15502     }
15503 
15504     PyModule_AddObject(m, "_have_functions", list);
15505 
15506     return 0;
15507 }
15508 
15509 
15510 static PyModuleDef_Slot posixmodile_slots[] = {
15511     {Py_mod_exec, posixmodule_exec},
15512     {0, NULL}
15513 };
15514 
15515 static struct PyModuleDef posixmodule = {
15516     PyModuleDef_HEAD_INIT,
15517     .m_name = MODNAME,
15518     .m_doc = posix__doc__,
15519     .m_size = sizeof(_posixstate),
15520     .m_methods = posix_methods,
15521     .m_slots = posixmodile_slots,
15522     .m_traverse = _posix_traverse,
15523     .m_clear = _posix_clear,
15524     .m_free = _posix_free,
15525 };
15526 
15527 PyMODINIT_FUNC
INITFUNC(void)15528 INITFUNC(void)
15529 {
15530     return PyModuleDef_Init(&posixmodule);
15531 }
15532 
15533 #ifdef __cplusplus
15534 }
15535 #endif
15536