1 
2 /* POSIX module implementation */
3 
4 /* This file is also used for Windows NT/MS-Win.  In that case the
5    module actually calls itself 'nt', not 'posix', and a few
6    functions are either unimplemented or implemented differently.  The source
7    assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
8    of the compiler used.  Different compilers define their own feature
9    test macro, e.g. '_MSC_VER'. */
10 
11 
12 
13 #ifdef __APPLE__
14    /*
15     * Step 1 of support for weak-linking a number of symbols existing on
16     * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block
17     * at the end of this file for more information.
18     */
19 #  pragma weak lchown
20 #  pragma weak statvfs
21 #  pragma weak fstatvfs
22 
23 #endif /* __APPLE__ */
24 
25 #define PY_SSIZE_T_CLEAN
26 
27 #include "Python.h"
28 #ifdef MS_WINDOWS
29    /* include <windows.h> early to avoid conflict with pycore_condvar.h:
30 
31         #define WIN32_LEAN_AND_MEAN
32         #include <windows.h>
33 
34       FSCTL_GET_REPARSE_POINT is not exported with WIN32_LEAN_AND_MEAN. */
35 #  include <windows.h>
36 #  include <shlwapi.h>
37 #endif
38 
39 #include "pycore_ceval.h"     /* _PyEval_ReInitThreads() */
40 #include "pycore_pystate.h"   /* _PyRuntime */
41 #include "pythread.h"
42 #include "structmember.h"
43 #ifndef MS_WINDOWS
44 #  include "posixmodule.h"
45 #else
46 #  include "winreparse.h"
47 #endif
48 
49 /* On android API level 21, 'AT_EACCESS' is not declared although
50  * HAVE_FACCESSAT is defined. */
51 #ifdef __ANDROID__
52 #undef HAVE_FACCESSAT
53 #endif
54 
55 #include <stdio.h>  /* needed for ctermid() */
56 
57 #ifdef __cplusplus
58 extern "C" {
59 #endif
60 
61 PyDoc_STRVAR(posix__doc__,
62 "This module provides access to operating system functionality that is\n\
63 standardized by the C Standard and the POSIX standard (a thinly\n\
64 disguised Unix interface).  Refer to the library manual and\n\
65 corresponding Unix manual entries for more information on calls.");
66 
67 
68 #ifdef HAVE_SYS_UIO_H
69 #include <sys/uio.h>
70 #endif
71 
72 #ifdef HAVE_SYS_SYSMACROS_H
73 /* GNU C Library: major(), minor(), makedev() */
74 #include <sys/sysmacros.h>
75 #endif
76 
77 #ifdef HAVE_SYS_TYPES_H
78 #include <sys/types.h>
79 #endif /* HAVE_SYS_TYPES_H */
80 
81 #ifdef HAVE_SYS_STAT_H
82 #include <sys/stat.h>
83 #endif /* HAVE_SYS_STAT_H */
84 
85 #ifdef HAVE_SYS_WAIT_H
86 #include <sys/wait.h>           /* For WNOHANG */
87 #endif
88 
89 #ifdef HAVE_SIGNAL_H
90 #include <signal.h>
91 #endif
92 
93 #ifdef HAVE_FCNTL_H
94 #include <fcntl.h>
95 #endif /* HAVE_FCNTL_H */
96 
97 #ifdef HAVE_GRP_H
98 #include <grp.h>
99 #endif
100 
101 #ifdef HAVE_SYSEXITS_H
102 #include <sysexits.h>
103 #endif /* HAVE_SYSEXITS_H */
104 
105 #ifdef HAVE_SYS_LOADAVG_H
106 #include <sys/loadavg.h>
107 #endif
108 
109 #ifdef HAVE_SYS_SENDFILE_H
110 #include <sys/sendfile.h>
111 #endif
112 
113 #if defined(__APPLE__)
114 #include <copyfile.h>
115 #endif
116 
117 #ifdef HAVE_SCHED_H
118 #include <sched.h>
119 #endif
120 
121 #ifdef HAVE_COPY_FILE_RANGE
122 #include <unistd.h>
123 #endif
124 
125 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
126 #undef HAVE_SCHED_SETAFFINITY
127 #endif
128 
129 #if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
130 #define USE_XATTRS
131 #endif
132 
133 #ifdef USE_XATTRS
134 #include <sys/xattr.h>
135 #endif
136 
137 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
138 #ifdef HAVE_SYS_SOCKET_H
139 #include <sys/socket.h>
140 #endif
141 #endif
142 
143 #ifdef HAVE_DLFCN_H
144 #include <dlfcn.h>
145 #endif
146 
147 #ifdef __hpux
148 #include <sys/mpctl.h>
149 #endif
150 
151 #if defined(__DragonFly__) || \
152     defined(__OpenBSD__)   || \
153     defined(__FreeBSD__)   || \
154     defined(__NetBSD__)    || \
155     defined(__APPLE__)
156 #include <sys/sysctl.h>
157 #endif
158 
159 #ifdef HAVE_LINUX_RANDOM_H
160 #  include <linux/random.h>
161 #endif
162 #ifdef HAVE_GETRANDOM_SYSCALL
163 #  include <sys/syscall.h>
164 #endif
165 
166 #if defined(MS_WINDOWS)
167 #  define TERMSIZE_USE_CONIO
168 #elif defined(HAVE_SYS_IOCTL_H)
169 #  include <sys/ioctl.h>
170 #  if defined(HAVE_TERMIOS_H)
171 #    include <termios.h>
172 #  endif
173 #  if defined(TIOCGWINSZ)
174 #    define TERMSIZE_USE_IOCTL
175 #  endif
176 #endif /* MS_WINDOWS */
177 
178 /* Various compilers have only certain posix functions */
179 /* XXX Gosh I wish these were all moved into pyconfig.h */
180 #if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
181 #define HAVE_OPENDIR    1
182 #define HAVE_SYSTEM     1
183 #include <process.h>
184 #else
185 #ifdef _MSC_VER         /* Microsoft compiler */
186 #define HAVE_GETPPID    1
187 #define HAVE_GETLOGIN   1
188 #define HAVE_SPAWNV     1
189 #define HAVE_EXECV      1
190 #define HAVE_WSPAWNV    1
191 #define HAVE_WEXECV     1
192 #define HAVE_PIPE       1
193 #define HAVE_SYSTEM     1
194 #define HAVE_CWAIT      1
195 #define HAVE_FSYNC      1
196 #define fsync _commit
197 #else
198 /* Unix functions that the configure script doesn't check for */
199 #ifndef __VXWORKS__
200 #define HAVE_EXECV      1
201 #define HAVE_FORK       1
202 #if defined(__USLC__) && defined(__SCO_VERSION__)       /* SCO UDK Compiler */
203 #define HAVE_FORK1      1
204 #endif
205 #endif
206 #define HAVE_GETEGID    1
207 #define HAVE_GETEUID    1
208 #define HAVE_GETGID     1
209 #define HAVE_GETPPID    1
210 #define HAVE_GETUID     1
211 #define HAVE_KILL       1
212 #define HAVE_OPENDIR    1
213 #define HAVE_PIPE       1
214 #define HAVE_SYSTEM     1
215 #define HAVE_WAIT       1
216 #define HAVE_TTYNAME    1
217 #endif  /* _MSC_VER */
218 #endif  /* ! __WATCOMC__ || __QNX__ */
219 
220 
221 /*[clinic input]
222 # one of the few times we lie about this name!
223 module os
224 [clinic start generated code]*/
225 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
226 
227 #ifndef _MSC_VER
228 
229 #if defined(__sgi)&&_COMPILER_VERSION>=700
230 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
231    (default) */
232 extern char        *ctermid_r(char *);
233 #endif
234 
235 #endif /* !_MSC_VER */
236 
237 #if defined(__VXWORKS__)
238 #include <vxCpuLib.h>
239 #include <rtpLib.h>
240 #include <wait.h>
241 #include <taskLib.h>
242 #ifndef _P_WAIT
243 #define _P_WAIT          0
244 #define _P_NOWAIT        1
245 #define _P_NOWAITO       1
246 #endif
247 #endif /* __VXWORKS__ */
248 
249 #ifdef HAVE_POSIX_SPAWN
250 #include <spawn.h>
251 #endif
252 
253 #ifdef HAVE_UTIME_H
254 #include <utime.h>
255 #endif /* HAVE_UTIME_H */
256 
257 #ifdef HAVE_SYS_UTIME_H
258 #include <sys/utime.h>
259 #define HAVE_UTIME_H /* pretend we do for the rest of this file */
260 #endif /* HAVE_SYS_UTIME_H */
261 
262 #ifdef HAVE_SYS_TIMES_H
263 #include <sys/times.h>
264 #endif /* HAVE_SYS_TIMES_H */
265 
266 #ifdef HAVE_SYS_PARAM_H
267 #include <sys/param.h>
268 #endif /* HAVE_SYS_PARAM_H */
269 
270 #ifdef HAVE_SYS_UTSNAME_H
271 #include <sys/utsname.h>
272 #endif /* HAVE_SYS_UTSNAME_H */
273 
274 #ifdef HAVE_DIRENT_H
275 #include <dirent.h>
276 #define NAMLEN(dirent) strlen((dirent)->d_name)
277 #else
278 #if defined(__WATCOMC__) && !defined(__QNX__)
279 #include <direct.h>
280 #define NAMLEN(dirent) strlen((dirent)->d_name)
281 #else
282 #define dirent direct
283 #define NAMLEN(dirent) (dirent)->d_namlen
284 #endif
285 #ifdef HAVE_SYS_NDIR_H
286 #include <sys/ndir.h>
287 #endif
288 #ifdef HAVE_SYS_DIR_H
289 #include <sys/dir.h>
290 #endif
291 #ifdef HAVE_NDIR_H
292 #include <ndir.h>
293 #endif
294 #endif
295 
296 #ifdef _MSC_VER
297 #ifdef HAVE_DIRECT_H
298 #include <direct.h>
299 #endif
300 #ifdef HAVE_IO_H
301 #include <io.h>
302 #endif
303 #ifdef HAVE_PROCESS_H
304 #include <process.h>
305 #endif
306 #ifndef IO_REPARSE_TAG_SYMLINK
307 #define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
308 #endif
309 #ifndef IO_REPARSE_TAG_MOUNT_POINT
310 #define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
311 #endif
312 #include "osdefs.h"
313 #include <malloc.h>
314 #include <windows.h>
315 #include <shellapi.h>   /* for ShellExecute() */
316 #include <lmcons.h>     /* for UNLEN */
317 #define HAVE_SYMLINK
318 #endif /* _MSC_VER */
319 
320 #ifndef MAXPATHLEN
321 #if defined(PATH_MAX) && PATH_MAX > 1024
322 #define MAXPATHLEN PATH_MAX
323 #else
324 #define MAXPATHLEN 1024
325 #endif
326 #endif /* MAXPATHLEN */
327 
328 #ifdef UNION_WAIT
329 /* Emulate some macros on systems that have a union instead of macros */
330 
331 #ifndef WIFEXITED
332 #define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
333 #endif
334 
335 #ifndef WEXITSTATUS
336 #define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
337 #endif
338 
339 #ifndef WTERMSIG
340 #define WTERMSIG(u_wait) ((u_wait).w_termsig)
341 #endif
342 
343 #define WAIT_TYPE union wait
344 #define WAIT_STATUS_INT(s) (s.w_status)
345 
346 #else /* !UNION_WAIT */
347 #define WAIT_TYPE int
348 #define WAIT_STATUS_INT(s) (s)
349 #endif /* UNION_WAIT */
350 
351 /* Don't use the "_r" form if we don't need it (also, won't have a
352    prototype for it, at least on Solaris -- maybe others as well?). */
353 #if defined(HAVE_CTERMID_R)
354 #define USE_CTERMID_R
355 #endif
356 
357 /* choose the appropriate stat and fstat functions and return structs */
358 #undef STAT
359 #undef FSTAT
360 #undef STRUCT_STAT
361 #ifdef MS_WINDOWS
362 #       define STAT win32_stat
363 #       define LSTAT win32_lstat
364 #       define FSTAT _Py_fstat_noraise
365 #       define STRUCT_STAT struct _Py_stat_struct
366 #else
367 #       define STAT stat
368 #       define LSTAT lstat
369 #       define FSTAT fstat
370 #       define STRUCT_STAT struct stat
371 #endif
372 
373 #if defined(MAJOR_IN_MKDEV)
374 #include <sys/mkdev.h>
375 #else
376 #if defined(MAJOR_IN_SYSMACROS)
377 #include <sys/sysmacros.h>
378 #endif
379 #if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
380 #include <sys/mkdev.h>
381 #endif
382 #endif
383 
384 #ifdef MS_WINDOWS
385 #define INITFUNC PyInit_nt
386 #define MODNAME "nt"
387 #else
388 #define INITFUNC PyInit_posix
389 #define MODNAME "posix"
390 #endif
391 
392 #if defined(__sun)
393 /* Something to implement in autoconf, not present in autoconf 2.69 */
394 #define HAVE_STRUCT_STAT_ST_FSTYPE 1
395 #endif
396 
397 /* memfd_create is either defined in sys/mman.h or sys/memfd.h
398  * linux/memfd.h defines additional flags
399  */
400 #ifdef HAVE_SYS_MMAN_H
401 #include <sys/mman.h>
402 #endif
403 #ifdef HAVE_SYS_MEMFD_H
404 #include <sys/memfd.h>
405 #endif
406 #ifdef HAVE_LINUX_MEMFD_H
407 #include <linux/memfd.h>
408 #endif
409 
410 #ifdef _Py_MEMORY_SANITIZER
411 # include <sanitizer/msan_interface.h>
412 #endif
413 
414 #ifdef HAVE_FORK
415 static void
run_at_forkers(PyObject * lst,int reverse)416 run_at_forkers(PyObject *lst, int reverse)
417 {
418     Py_ssize_t i;
419     PyObject *cpy;
420 
421     if (lst != NULL) {
422         assert(PyList_CheckExact(lst));
423 
424         /* Use a list copy in case register_at_fork() is called from
425          * one of the callbacks.
426          */
427         cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
428         if (cpy == NULL)
429             PyErr_WriteUnraisable(lst);
430         else {
431             if (reverse)
432                 PyList_Reverse(cpy);
433             for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
434                 PyObject *func, *res;
435                 func = PyList_GET_ITEM(cpy, i);
436                 res = PyObject_CallObject(func, NULL);
437                 if (res == NULL)
438                     PyErr_WriteUnraisable(func);
439                 else
440                     Py_DECREF(res);
441             }
442             Py_DECREF(cpy);
443         }
444     }
445 }
446 
447 void
PyOS_BeforeFork(void)448 PyOS_BeforeFork(void)
449 {
450     run_at_forkers(_PyInterpreterState_Get()->before_forkers, 1);
451 
452     _PyImport_AcquireLock();
453 }
454 
455 void
PyOS_AfterFork_Parent(void)456 PyOS_AfterFork_Parent(void)
457 {
458     if (_PyImport_ReleaseLock() <= 0)
459         Py_FatalError("failed releasing import lock after fork");
460 
461     run_at_forkers(_PyInterpreterState_Get()->after_forkers_parent, 0);
462 }
463 
464 void
PyOS_AfterFork_Child(void)465 PyOS_AfterFork_Child(void)
466 {
467     _PyRuntimeState *runtime = &_PyRuntime;
468     _PyGILState_Reinit(runtime);
469     _PyEval_ReInitThreads(runtime);
470     _PyImport_ReInitLock();
471     _PySignal_AfterFork();
472     _PyRuntimeState_ReInitThreads(runtime);
473     _PyInterpreterState_DeleteExceptMain(runtime);
474 
475     run_at_forkers(_PyInterpreterState_Get()->after_forkers_child, 0);
476 }
477 
478 static int
register_at_forker(PyObject ** lst,PyObject * func)479 register_at_forker(PyObject **lst, PyObject *func)
480 {
481     if (func == NULL)  /* nothing to register? do nothing. */
482         return 0;
483     if (*lst == NULL) {
484         *lst = PyList_New(0);
485         if (*lst == NULL)
486             return -1;
487     }
488     return PyList_Append(*lst, func);
489 }
490 #endif
491 
492 /* Legacy wrapper */
493 void
PyOS_AfterFork(void)494 PyOS_AfterFork(void)
495 {
496 #ifdef HAVE_FORK
497     PyOS_AfterFork_Child();
498 #endif
499 }
500 
501 
502 #ifdef MS_WINDOWS
503 /* defined in fileutils.c */
504 void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
505 void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
506                                             ULONG, struct _Py_stat_struct *);
507 #endif
508 
509 
510 #ifndef MS_WINDOWS
511 PyObject *
_PyLong_FromUid(uid_t uid)512 _PyLong_FromUid(uid_t uid)
513 {
514     if (uid == (uid_t)-1)
515         return PyLong_FromLong(-1);
516     return PyLong_FromUnsignedLong(uid);
517 }
518 
519 PyObject *
_PyLong_FromGid(gid_t gid)520 _PyLong_FromGid(gid_t gid)
521 {
522     if (gid == (gid_t)-1)
523         return PyLong_FromLong(-1);
524     return PyLong_FromUnsignedLong(gid);
525 }
526 
527 int
_Py_Uid_Converter(PyObject * obj,void * p)528 _Py_Uid_Converter(PyObject *obj, void *p)
529 {
530     uid_t uid;
531     PyObject *index;
532     int overflow;
533     long result;
534     unsigned long uresult;
535 
536     index = PyNumber_Index(obj);
537     if (index == NULL) {
538         PyErr_Format(PyExc_TypeError,
539                      "uid should be integer, not %.200s",
540                      Py_TYPE(obj)->tp_name);
541         return 0;
542     }
543 
544     /*
545      * Handling uid_t is complicated for two reasons:
546      *  * Although uid_t is (always?) unsigned, it still
547      *    accepts -1.
548      *  * We don't know its size in advance--it may be
549      *    bigger than an int, or it may be smaller than
550      *    a long.
551      *
552      * So a bit of defensive programming is in order.
553      * Start with interpreting the value passed
554      * in as a signed long and see if it works.
555      */
556 
557     result = PyLong_AsLongAndOverflow(index, &overflow);
558 
559     if (!overflow) {
560         uid = (uid_t)result;
561 
562         if (result == -1) {
563             if (PyErr_Occurred())
564                 goto fail;
565             /* It's a legitimate -1, we're done. */
566             goto success;
567         }
568 
569         /* Any other negative number is disallowed. */
570         if (result < 0)
571             goto underflow;
572 
573         /* Ensure the value wasn't truncated. */
574         if (sizeof(uid_t) < sizeof(long) &&
575             (long)uid != result)
576             goto underflow;
577         goto success;
578     }
579 
580     if (overflow < 0)
581         goto underflow;
582 
583     /*
584      * Okay, the value overflowed a signed long.  If it
585      * fits in an *unsigned* long, it may still be okay,
586      * as uid_t may be unsigned long on this platform.
587      */
588     uresult = PyLong_AsUnsignedLong(index);
589     if (PyErr_Occurred()) {
590         if (PyErr_ExceptionMatches(PyExc_OverflowError))
591             goto overflow;
592         goto fail;
593     }
594 
595     uid = (uid_t)uresult;
596 
597     /*
598      * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
599      * but this value would get interpreted as (uid_t)-1  by chown
600      * and its siblings.   That's not what the user meant!  So we
601      * throw an overflow exception instead.   (We already
602      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
603      */
604     if (uid == (uid_t)-1)
605         goto overflow;
606 
607     /* Ensure the value wasn't truncated. */
608     if (sizeof(uid_t) < sizeof(long) &&
609         (unsigned long)uid != uresult)
610         goto overflow;
611     /* fallthrough */
612 
613 success:
614     Py_DECREF(index);
615     *(uid_t *)p = uid;
616     return 1;
617 
618 underflow:
619     PyErr_SetString(PyExc_OverflowError,
620                     "uid is less than minimum");
621     goto fail;
622 
623 overflow:
624     PyErr_SetString(PyExc_OverflowError,
625                     "uid is greater than maximum");
626     /* fallthrough */
627 
628 fail:
629     Py_DECREF(index);
630     return 0;
631 }
632 
633 int
_Py_Gid_Converter(PyObject * obj,void * p)634 _Py_Gid_Converter(PyObject *obj, void *p)
635 {
636     gid_t gid;
637     PyObject *index;
638     int overflow;
639     long result;
640     unsigned long uresult;
641 
642     index = PyNumber_Index(obj);
643     if (index == NULL) {
644         PyErr_Format(PyExc_TypeError,
645                      "gid should be integer, not %.200s",
646                      Py_TYPE(obj)->tp_name);
647         return 0;
648     }
649 
650     /*
651      * Handling gid_t is complicated for two reasons:
652      *  * Although gid_t is (always?) unsigned, it still
653      *    accepts -1.
654      *  * We don't know its size in advance--it may be
655      *    bigger than an int, or it may be smaller than
656      *    a long.
657      *
658      * So a bit of defensive programming is in order.
659      * Start with interpreting the value passed
660      * in as a signed long and see if it works.
661      */
662 
663     result = PyLong_AsLongAndOverflow(index, &overflow);
664 
665     if (!overflow) {
666         gid = (gid_t)result;
667 
668         if (result == -1) {
669             if (PyErr_Occurred())
670                 goto fail;
671             /* It's a legitimate -1, we're done. */
672             goto success;
673         }
674 
675         /* Any other negative number is disallowed. */
676         if (result < 0) {
677             goto underflow;
678         }
679 
680         /* Ensure the value wasn't truncated. */
681         if (sizeof(gid_t) < sizeof(long) &&
682             (long)gid != 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 gid_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     gid = (gid_t)uresult;
703 
704     /*
705      * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
706      * but this value would get interpreted as (gid_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 (gid == (gid_t)-1)
712         goto overflow;
713 
714     /* Ensure the value wasn't truncated. */
715     if (sizeof(gid_t) < sizeof(long) &&
716         (unsigned long)gid != uresult)
717         goto overflow;
718     /* fallthrough */
719 
720 success:
721     Py_DECREF(index);
722     *(gid_t *)p = gid;
723     return 1;
724 
725 underflow:
726     PyErr_SetString(PyExc_OverflowError,
727                     "gid is less than minimum");
728     goto fail;
729 
730 overflow:
731     PyErr_SetString(PyExc_OverflowError,
732                     "gid is greater than maximum");
733     /* fallthrough */
734 
735 fail:
736     Py_DECREF(index);
737     return 0;
738 }
739 #endif /* MS_WINDOWS */
740 
741 
742 #define _PyLong_FromDev PyLong_FromLongLong
743 
744 
745 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
746 static int
_Py_Dev_Converter(PyObject * obj,void * p)747 _Py_Dev_Converter(PyObject *obj, void *p)
748 {
749     *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
750     if (PyErr_Occurred())
751         return 0;
752     return 1;
753 }
754 #endif /* HAVE_MKNOD && HAVE_MAKEDEV */
755 
756 
757 #ifdef AT_FDCWD
758 /*
759  * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
760  * without the int cast, the value gets interpreted as uint (4291925331),
761  * which doesn't play nicely with all the initializer lines in this file that
762  * look like this:
763  *      int dir_fd = DEFAULT_DIR_FD;
764  */
765 #define DEFAULT_DIR_FD (int)AT_FDCWD
766 #else
767 #define DEFAULT_DIR_FD (-100)
768 #endif
769 
770 static int
_fd_converter(PyObject * o,int * p)771 _fd_converter(PyObject *o, int *p)
772 {
773     int overflow;
774     long long_value;
775 
776     PyObject *index = PyNumber_Index(o);
777     if (index == NULL) {
778         return 0;
779     }
780 
781     assert(PyLong_Check(index));
782     long_value = PyLong_AsLongAndOverflow(index, &overflow);
783     Py_DECREF(index);
784     assert(!PyErr_Occurred());
785     if (overflow > 0 || long_value > INT_MAX) {
786         PyErr_SetString(PyExc_OverflowError,
787                         "fd is greater than maximum");
788         return 0;
789     }
790     if (overflow < 0 || long_value < INT_MIN) {
791         PyErr_SetString(PyExc_OverflowError,
792                         "fd is less than minimum");
793         return 0;
794     }
795 
796     *p = (int)long_value;
797     return 1;
798 }
799 
800 static int
dir_fd_converter(PyObject * o,void * p)801 dir_fd_converter(PyObject *o, void *p)
802 {
803     if (o == Py_None) {
804         *(int *)p = DEFAULT_DIR_FD;
805         return 1;
806     }
807     else if (PyIndex_Check(o)) {
808         return _fd_converter(o, (int *)p);
809     }
810     else {
811         PyErr_Format(PyExc_TypeError,
812                      "argument should be integer or None, not %.200s",
813                      Py_TYPE(o)->tp_name);
814         return 0;
815     }
816 }
817 
818 
819 /*
820  * A PyArg_ParseTuple "converter" function
821  * that handles filesystem paths in the manner
822  * preferred by the os module.
823  *
824  * path_converter accepts (Unicode) strings and their
825  * subclasses, and bytes and their subclasses.  What
826  * it does with the argument depends on the platform:
827  *
828  *   * On Windows, if we get a (Unicode) string we
829  *     extract the wchar_t * and return it; if we get
830  *     bytes we decode to wchar_t * and return that.
831  *
832  *   * On all other platforms, strings are encoded
833  *     to bytes using PyUnicode_FSConverter, then we
834  *     extract the char * from the bytes object and
835  *     return that.
836  *
837  * path_converter also optionally accepts signed
838  * integers (representing open file descriptors) instead
839  * of path strings.
840  *
841  * Input fields:
842  *   path.nullable
843  *     If nonzero, the path is permitted to be None.
844  *   path.allow_fd
845  *     If nonzero, the path is permitted to be a file handle
846  *     (a signed int) instead of a string.
847  *   path.function_name
848  *     If non-NULL, path_converter will use that as the name
849  *     of the function in error messages.
850  *     (If path.function_name is NULL it omits the function name.)
851  *   path.argument_name
852  *     If non-NULL, path_converter will use that as the name
853  *     of the parameter in error messages.
854  *     (If path.argument_name is NULL it uses "path".)
855  *
856  * Output fields:
857  *   path.wide
858  *     Points to the path if it was expressed as Unicode
859  *     and was not encoded.  (Only used on Windows.)
860  *   path.narrow
861  *     Points to the path if it was expressed as bytes,
862  *     or it was Unicode and was encoded to bytes. (On Windows,
863  *     is a non-zero integer if the path was expressed as bytes.
864  *     The type is deliberately incompatible to prevent misuse.)
865  *   path.fd
866  *     Contains a file descriptor if path.accept_fd was true
867  *     and the caller provided a signed integer instead of any
868  *     sort of string.
869  *
870  *     WARNING: if your "path" parameter is optional, and is
871  *     unspecified, path_converter will never get called.
872  *     So if you set allow_fd, you *MUST* initialize path.fd = -1
873  *     yourself!
874  *   path.length
875  *     The length of the path in characters, if specified as
876  *     a string.
877  *   path.object
878  *     The original object passed in (if get a PathLike object,
879  *     the result of PyOS_FSPath() is treated as the original object).
880  *     Own a reference to the object.
881  *   path.cleanup
882  *     For internal use only.  May point to a temporary object.
883  *     (Pay no attention to the man behind the curtain.)
884  *
885  *   At most one of path.wide or path.narrow will be non-NULL.
886  *   If path was None and path.nullable was set,
887  *     or if path was an integer and path.allow_fd was set,
888  *     both path.wide and path.narrow will be NULL
889  *     and path.length will be 0.
890  *
891  *   path_converter takes care to not write to the path_t
892  *   unless it's successful.  However it must reset the
893  *   "cleanup" field each time it's called.
894  *
895  * Use as follows:
896  *      path_t path;
897  *      memset(&path, 0, sizeof(path));
898  *      PyArg_ParseTuple(args, "O&", path_converter, &path);
899  *      // ... use values from path ...
900  *      path_cleanup(&path);
901  *
902  * (Note that if PyArg_Parse fails you don't need to call
903  * path_cleanup().  However it is safe to do so.)
904  */
905 typedef struct {
906     const char *function_name;
907     const char *argument_name;
908     int nullable;
909     int allow_fd;
910     const wchar_t *wide;
911 #ifdef MS_WINDOWS
912     BOOL narrow;
913 #else
914     const char *narrow;
915 #endif
916     int fd;
917     Py_ssize_t length;
918     PyObject *object;
919     PyObject *cleanup;
920 } path_t;
921 
922 #ifdef MS_WINDOWS
923 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
924     {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
925 #else
926 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
927     {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
928 #endif
929 
930 static void
path_cleanup(path_t * path)931 path_cleanup(path_t *path)
932 {
933     Py_CLEAR(path->object);
934     Py_CLEAR(path->cleanup);
935 }
936 
937 static int
path_converter(PyObject * o,void * p)938 path_converter(PyObject *o, void *p)
939 {
940     path_t *path = (path_t *)p;
941     PyObject *bytes = NULL;
942     Py_ssize_t length = 0;
943     int is_index, is_buffer, is_bytes, is_unicode;
944     const char *narrow;
945 #ifdef MS_WINDOWS
946     PyObject *wo = NULL;
947     const wchar_t *wide;
948 #endif
949 
950 #define FORMAT_EXCEPTION(exc, fmt) \
951     PyErr_Format(exc, "%s%s" fmt, \
952         path->function_name ? path->function_name : "", \
953         path->function_name ? ": "                : "", \
954         path->argument_name ? path->argument_name : "path")
955 
956     /* Py_CLEANUP_SUPPORTED support */
957     if (o == NULL) {
958         path_cleanup(path);
959         return 1;
960     }
961 
962     /* Ensure it's always safe to call path_cleanup(). */
963     path->object = path->cleanup = NULL;
964     /* path->object owns a reference to the original object */
965     Py_INCREF(o);
966 
967     if ((o == Py_None) && path->nullable) {
968         path->wide = NULL;
969 #ifdef MS_WINDOWS
970         path->narrow = FALSE;
971 #else
972         path->narrow = NULL;
973 #endif
974         path->fd = -1;
975         goto success_exit;
976     }
977 
978     /* Only call this here so that we don't treat the return value of
979        os.fspath() as an fd or buffer. */
980     is_index = path->allow_fd && PyIndex_Check(o);
981     is_buffer = PyObject_CheckBuffer(o);
982     is_bytes = PyBytes_Check(o);
983     is_unicode = PyUnicode_Check(o);
984 
985     if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
986         /* Inline PyOS_FSPath() for better error messages. */
987         _Py_IDENTIFIER(__fspath__);
988         PyObject *func, *res;
989 
990         func = _PyObject_LookupSpecial(o, &PyId___fspath__);
991         if (NULL == func) {
992             goto error_format;
993         }
994         res = _PyObject_CallNoArg(func);
995         Py_DECREF(func);
996         if (NULL == res) {
997             goto error_exit;
998         }
999         else if (PyUnicode_Check(res)) {
1000             is_unicode = 1;
1001         }
1002         else if (PyBytes_Check(res)) {
1003             is_bytes = 1;
1004         }
1005         else {
1006             PyErr_Format(PyExc_TypeError,
1007                  "expected %.200s.__fspath__() to return str or bytes, "
1008                  "not %.200s", Py_TYPE(o)->tp_name,
1009                  Py_TYPE(res)->tp_name);
1010             Py_DECREF(res);
1011             goto error_exit;
1012         }
1013 
1014         /* still owns a reference to the original object */
1015         Py_DECREF(o);
1016         o = res;
1017     }
1018 
1019     if (is_unicode) {
1020 #ifdef MS_WINDOWS
1021         wide = PyUnicode_AsUnicodeAndSize(o, &length);
1022         if (!wide) {
1023             goto error_exit;
1024         }
1025         if (length > 32767) {
1026             FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1027             goto error_exit;
1028         }
1029         if (wcslen(wide) != length) {
1030             FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1031             goto error_exit;
1032         }
1033 
1034         path->wide = wide;
1035         path->narrow = FALSE;
1036         path->fd = -1;
1037         goto success_exit;
1038 #else
1039         if (!PyUnicode_FSConverter(o, &bytes)) {
1040             goto error_exit;
1041         }
1042 #endif
1043     }
1044     else if (is_bytes) {
1045         bytes = o;
1046         Py_INCREF(bytes);
1047     }
1048     else if (is_buffer) {
1049         /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1050            after removing support of non-bytes buffer objects. */
1051         if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
1052             "%s%s%s should be %s, not %.200s",
1053             path->function_name ? path->function_name : "",
1054             path->function_name ? ": "                : "",
1055             path->argument_name ? path->argument_name : "path",
1056             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1057                                                "integer or None" :
1058             path->allow_fd ? "string, bytes, os.PathLike or integer" :
1059             path->nullable ? "string, bytes, os.PathLike or None" :
1060                              "string, bytes or os.PathLike",
1061             Py_TYPE(o)->tp_name)) {
1062             goto error_exit;
1063         }
1064         bytes = PyBytes_FromObject(o);
1065         if (!bytes) {
1066             goto error_exit;
1067         }
1068     }
1069     else if (is_index) {
1070         if (!_fd_converter(o, &path->fd)) {
1071             goto error_exit;
1072         }
1073         path->wide = NULL;
1074 #ifdef MS_WINDOWS
1075         path->narrow = FALSE;
1076 #else
1077         path->narrow = NULL;
1078 #endif
1079         goto success_exit;
1080     }
1081     else {
1082  error_format:
1083         PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1084             path->function_name ? path->function_name : "",
1085             path->function_name ? ": "                : "",
1086             path->argument_name ? path->argument_name : "path",
1087             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1088                                                "integer or None" :
1089             path->allow_fd ? "string, bytes, os.PathLike or integer" :
1090             path->nullable ? "string, bytes, os.PathLike or None" :
1091                              "string, bytes or os.PathLike",
1092             Py_TYPE(o)->tp_name);
1093         goto error_exit;
1094     }
1095 
1096     length = PyBytes_GET_SIZE(bytes);
1097     narrow = PyBytes_AS_STRING(bytes);
1098     if ((size_t)length != strlen(narrow)) {
1099         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1100         goto error_exit;
1101     }
1102 
1103 #ifdef MS_WINDOWS
1104     wo = PyUnicode_DecodeFSDefaultAndSize(
1105         narrow,
1106         length
1107     );
1108     if (!wo) {
1109         goto error_exit;
1110     }
1111 
1112     wide = PyUnicode_AsUnicodeAndSize(wo, &length);
1113     if (!wide) {
1114         goto error_exit;
1115     }
1116     if (length > 32767) {
1117         FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1118         goto error_exit;
1119     }
1120     if (wcslen(wide) != length) {
1121         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1122         goto error_exit;
1123     }
1124     path->wide = wide;
1125     path->narrow = TRUE;
1126     path->cleanup = wo;
1127     Py_DECREF(bytes);
1128 #else
1129     path->wide = NULL;
1130     path->narrow = narrow;
1131     if (bytes == o) {
1132         /* Still a reference owned by path->object, don't have to
1133            worry about path->narrow is used after free. */
1134         Py_DECREF(bytes);
1135     }
1136     else {
1137         path->cleanup = bytes;
1138     }
1139 #endif
1140     path->fd = -1;
1141 
1142  success_exit:
1143     path->length = length;
1144     path->object = o;
1145     return Py_CLEANUP_SUPPORTED;
1146 
1147  error_exit:
1148     Py_XDECREF(o);
1149     Py_XDECREF(bytes);
1150 #ifdef MS_WINDOWS
1151     Py_XDECREF(wo);
1152 #endif
1153     return 0;
1154 }
1155 
1156 static void
argument_unavailable_error(const char * function_name,const char * argument_name)1157 argument_unavailable_error(const char *function_name, const char *argument_name)
1158 {
1159     PyErr_Format(PyExc_NotImplementedError,
1160         "%s%s%s unavailable on this platform",
1161         (function_name != NULL) ? function_name : "",
1162         (function_name != NULL) ? ": ": "",
1163         argument_name);
1164 }
1165 
1166 static int
dir_fd_unavailable(PyObject * o,void * p)1167 dir_fd_unavailable(PyObject *o, void *p)
1168 {
1169     int dir_fd;
1170     if (!dir_fd_converter(o, &dir_fd))
1171         return 0;
1172     if (dir_fd != DEFAULT_DIR_FD) {
1173         argument_unavailable_error(NULL, "dir_fd");
1174         return 0;
1175     }
1176     *(int *)p = dir_fd;
1177     return 1;
1178 }
1179 
1180 static int
fd_specified(const char * function_name,int fd)1181 fd_specified(const char *function_name, int fd)
1182 {
1183     if (fd == -1)
1184         return 0;
1185 
1186     argument_unavailable_error(function_name, "fd");
1187     return 1;
1188 }
1189 
1190 static int
follow_symlinks_specified(const char * function_name,int follow_symlinks)1191 follow_symlinks_specified(const char *function_name, int follow_symlinks)
1192 {
1193     if (follow_symlinks)
1194         return 0;
1195 
1196     argument_unavailable_error(function_name, "follow_symlinks");
1197     return 1;
1198 }
1199 
1200 static int
path_and_dir_fd_invalid(const char * function_name,path_t * path,int dir_fd)1201 path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1202 {
1203     if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1204 #ifndef MS_WINDOWS
1205         && !path->narrow
1206 #endif
1207     ) {
1208         PyErr_Format(PyExc_ValueError,
1209                      "%s: can't specify dir_fd without matching path",
1210                      function_name);
1211         return 1;
1212     }
1213     return 0;
1214 }
1215 
1216 static int
dir_fd_and_fd_invalid(const char * function_name,int dir_fd,int fd)1217 dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1218 {
1219     if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1220         PyErr_Format(PyExc_ValueError,
1221                      "%s: can't specify both dir_fd and fd",
1222                      function_name);
1223         return 1;
1224     }
1225     return 0;
1226 }
1227 
1228 static int
fd_and_follow_symlinks_invalid(const char * function_name,int fd,int follow_symlinks)1229 fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1230                                int follow_symlinks)
1231 {
1232     if ((fd > 0) && (!follow_symlinks)) {
1233         PyErr_Format(PyExc_ValueError,
1234                      "%s: cannot use fd and follow_symlinks together",
1235                      function_name);
1236         return 1;
1237     }
1238     return 0;
1239 }
1240 
1241 static int
dir_fd_and_follow_symlinks_invalid(const char * function_name,int dir_fd,int follow_symlinks)1242 dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1243                                    int follow_symlinks)
1244 {
1245     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1246         PyErr_Format(PyExc_ValueError,
1247                      "%s: cannot use dir_fd and follow_symlinks together",
1248                      function_name);
1249         return 1;
1250     }
1251     return 0;
1252 }
1253 
1254 #ifdef MS_WINDOWS
1255     typedef long long Py_off_t;
1256 #else
1257     typedef off_t Py_off_t;
1258 #endif
1259 
1260 static int
Py_off_t_converter(PyObject * arg,void * addr)1261 Py_off_t_converter(PyObject *arg, void *addr)
1262 {
1263 #ifdef HAVE_LARGEFILE_SUPPORT
1264     *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1265 #else
1266     *((Py_off_t *)addr) = PyLong_AsLong(arg);
1267 #endif
1268     if (PyErr_Occurred())
1269         return 0;
1270     return 1;
1271 }
1272 
1273 static PyObject *
PyLong_FromPy_off_t(Py_off_t offset)1274 PyLong_FromPy_off_t(Py_off_t offset)
1275 {
1276 #ifdef HAVE_LARGEFILE_SUPPORT
1277     return PyLong_FromLongLong(offset);
1278 #else
1279     return PyLong_FromLong(offset);
1280 #endif
1281 }
1282 
1283 #ifdef HAVE_SIGSET_T
1284 /* Convert an iterable of integers to a sigset.
1285    Return 1 on success, return 0 and raise an exception on error. */
1286 int
_Py_Sigset_Converter(PyObject * obj,void * addr)1287 _Py_Sigset_Converter(PyObject *obj, void *addr)
1288 {
1289     sigset_t *mask = (sigset_t *)addr;
1290     PyObject *iterator, *item;
1291     long signum;
1292     int overflow;
1293 
1294     // The extra parens suppress the unreachable-code warning with clang on MacOS
1295     if (sigemptyset(mask) < (0)) {
1296         /* Probably only if mask == NULL. */
1297         PyErr_SetFromErrno(PyExc_OSError);
1298         return 0;
1299     }
1300 
1301     iterator = PyObject_GetIter(obj);
1302     if (iterator == NULL) {
1303         return 0;
1304     }
1305 
1306     while ((item = PyIter_Next(iterator)) != NULL) {
1307         signum = PyLong_AsLongAndOverflow(item, &overflow);
1308         Py_DECREF(item);
1309         if (signum <= 0 || signum >= NSIG) {
1310             if (overflow || signum != -1 || !PyErr_Occurred()) {
1311                 PyErr_Format(PyExc_ValueError,
1312                              "signal number %ld out of range", signum);
1313             }
1314             goto error;
1315         }
1316         if (sigaddset(mask, (int)signum)) {
1317             if (errno != EINVAL) {
1318                 /* Probably impossible */
1319                 PyErr_SetFromErrno(PyExc_OSError);
1320                 goto error;
1321             }
1322             /* For backwards compatibility, allow idioms such as
1323              * `range(1, NSIG)` but warn about invalid signal numbers
1324              */
1325             const char msg[] =
1326                 "invalid signal number %ld, please use valid_signals()";
1327             if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1328                 goto error;
1329             }
1330         }
1331     }
1332     if (!PyErr_Occurred()) {
1333         Py_DECREF(iterator);
1334         return 1;
1335     }
1336 
1337 error:
1338     Py_DECREF(iterator);
1339     return 0;
1340 }
1341 #endif /* HAVE_SIGSET_T */
1342 
1343 #ifdef MS_WINDOWS
1344 
1345 static int
win32_get_reparse_tag(HANDLE reparse_point_handle,ULONG * reparse_tag)1346 win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1347 {
1348     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1349     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1350     DWORD n_bytes_returned;
1351 
1352     if (0 == DeviceIoControl(
1353         reparse_point_handle,
1354         FSCTL_GET_REPARSE_POINT,
1355         NULL, 0, /* in buffer */
1356         target_buffer, sizeof(target_buffer),
1357         &n_bytes_returned,
1358         NULL)) /* we're not using OVERLAPPED_IO */
1359         return FALSE;
1360 
1361     if (reparse_tag)
1362         *reparse_tag = rdb->ReparseTag;
1363 
1364     return TRUE;
1365 }
1366 
1367 #endif /* MS_WINDOWS */
1368 
1369 /* Return a dictionary corresponding to the POSIX environment table */
1370 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1371 /* On Darwin/MacOSX a shared library or framework has no access to
1372 ** environ directly, we must obtain it with _NSGetEnviron(). See also
1373 ** man environ(7).
1374 */
1375 #include <crt_externs.h>
1376 #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1377 extern char **environ;
1378 #endif /* !_MSC_VER */
1379 
1380 static PyObject *
convertenviron(void)1381 convertenviron(void)
1382 {
1383     PyObject *d;
1384 #ifdef MS_WINDOWS
1385     wchar_t **e;
1386 #else
1387     char **e;
1388 #endif
1389 
1390     d = PyDict_New();
1391     if (d == NULL)
1392         return NULL;
1393 #ifdef MS_WINDOWS
1394     /* _wenviron must be initialized in this way if the program is started
1395        through main() instead of wmain(). */
1396     _wgetenv(L"");
1397     e = _wenviron;
1398 #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1399     /* environ is not accessible as an extern in a shared object on OSX; use
1400        _NSGetEnviron to resolve it. The value changes if you add environment
1401        variables between calls to Py_Initialize, so don't cache the value. */
1402     e = *_NSGetEnviron();
1403 #else
1404     e = environ;
1405 #endif
1406     if (e == NULL)
1407         return d;
1408     for (; *e != NULL; e++) {
1409         PyObject *k;
1410         PyObject *v;
1411 #ifdef MS_WINDOWS
1412         const wchar_t *p = wcschr(*e, L'=');
1413 #else
1414         const char *p = strchr(*e, '=');
1415 #endif
1416         if (p == NULL)
1417             continue;
1418 #ifdef MS_WINDOWS
1419         k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1420 #else
1421         k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1422 #endif
1423         if (k == NULL) {
1424             Py_DECREF(d);
1425             return NULL;
1426         }
1427 #ifdef MS_WINDOWS
1428         v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1429 #else
1430         v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1431 #endif
1432         if (v == NULL) {
1433             Py_DECREF(k);
1434             Py_DECREF(d);
1435             return NULL;
1436         }
1437         if (PyDict_GetItemWithError(d, k) == NULL) {
1438             if (PyErr_Occurred() || PyDict_SetItem(d, k, v) != 0) {
1439                 Py_DECREF(v);
1440                 Py_DECREF(k);
1441                 Py_DECREF(d);
1442                 return NULL;
1443             }
1444         }
1445         Py_DECREF(k);
1446         Py_DECREF(v);
1447     }
1448     return d;
1449 }
1450 
1451 /* Set a POSIX-specific error from errno, and return NULL */
1452 
1453 static PyObject *
posix_error(void)1454 posix_error(void)
1455 {
1456     return PyErr_SetFromErrno(PyExc_OSError);
1457 }
1458 
1459 #ifdef MS_WINDOWS
1460 static PyObject *
win32_error(const char * function,const char * filename)1461 win32_error(const char* function, const char* filename)
1462 {
1463     /* XXX We should pass the function name along in the future.
1464        (winreg.c also wants to pass the function name.)
1465        This would however require an additional param to the
1466        Windows error object, which is non-trivial.
1467     */
1468     errno = GetLastError();
1469     if (filename)
1470         return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1471     else
1472         return PyErr_SetFromWindowsErr(errno);
1473 }
1474 
1475 static PyObject *
win32_error_object_err(const char * function,PyObject * filename,DWORD err)1476 win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1477 {
1478     /* XXX - see win32_error for comments on 'function' */
1479     if (filename)
1480         return PyErr_SetExcFromWindowsErrWithFilenameObject(
1481                     PyExc_OSError,
1482                     err,
1483                     filename);
1484     else
1485         return PyErr_SetFromWindowsErr(err);
1486 }
1487 
1488 static PyObject *
win32_error_object(const char * function,PyObject * filename)1489 win32_error_object(const char* function, PyObject* filename)
1490 {
1491     errno = GetLastError();
1492     return win32_error_object_err(function, filename, errno);
1493 }
1494 
1495 #endif /* MS_WINDOWS */
1496 
1497 static PyObject *
posix_path_object_error(PyObject * path)1498 posix_path_object_error(PyObject *path)
1499 {
1500     return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1501 }
1502 
1503 static PyObject *
path_object_error(PyObject * path)1504 path_object_error(PyObject *path)
1505 {
1506 #ifdef MS_WINDOWS
1507     return PyErr_SetExcFromWindowsErrWithFilenameObject(
1508                 PyExc_OSError, 0, path);
1509 #else
1510     return posix_path_object_error(path);
1511 #endif
1512 }
1513 
1514 static PyObject *
path_object_error2(PyObject * path,PyObject * path2)1515 path_object_error2(PyObject *path, PyObject *path2)
1516 {
1517 #ifdef MS_WINDOWS
1518     return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1519                 PyExc_OSError, 0, path, path2);
1520 #else
1521     return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1522 #endif
1523 }
1524 
1525 static PyObject *
path_error(path_t * path)1526 path_error(path_t *path)
1527 {
1528     return path_object_error(path->object);
1529 }
1530 
1531 static PyObject *
posix_path_error(path_t * path)1532 posix_path_error(path_t *path)
1533 {
1534     return posix_path_object_error(path->object);
1535 }
1536 
1537 static PyObject *
path_error2(path_t * path,path_t * path2)1538 path_error2(path_t *path, path_t *path2)
1539 {
1540     return path_object_error2(path->object, path2->object);
1541 }
1542 
1543 
1544 /* POSIX generic methods */
1545 
1546 static int
fildes_converter(PyObject * o,void * p)1547 fildes_converter(PyObject *o, void *p)
1548 {
1549     int fd;
1550     int *pointer = (int *)p;
1551     fd = PyObject_AsFileDescriptor(o);
1552     if (fd < 0)
1553         return 0;
1554     *pointer = fd;
1555     return 1;
1556 }
1557 
1558 static PyObject *
posix_fildes_fd(int fd,int (* func)(int))1559 posix_fildes_fd(int fd, int (*func)(int))
1560 {
1561     int res;
1562     int async_err = 0;
1563 
1564     do {
1565         Py_BEGIN_ALLOW_THREADS
1566         _Py_BEGIN_SUPPRESS_IPH
1567         res = (*func)(fd);
1568         _Py_END_SUPPRESS_IPH
1569         Py_END_ALLOW_THREADS
1570     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1571     if (res != 0)
1572         return (!async_err) ? posix_error() : NULL;
1573     Py_RETURN_NONE;
1574 }
1575 
1576 
1577 #ifdef MS_WINDOWS
1578 /* This is a reimplementation of the C library's chdir function,
1579    but one that produces Win32 errors instead of DOS error codes.
1580    chdir is essentially a wrapper around SetCurrentDirectory; however,
1581    it also needs to set "magic" environment variables indicating
1582    the per-drive current directory, which are of the form =<drive>: */
1583 static BOOL __stdcall
win32_wchdir(LPCWSTR path)1584 win32_wchdir(LPCWSTR path)
1585 {
1586     wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1587     int result;
1588     wchar_t env[4] = L"=x:";
1589 
1590     if(!SetCurrentDirectoryW(path))
1591         return FALSE;
1592     result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1593     if (!result)
1594         return FALSE;
1595     if (result > Py_ARRAY_LENGTH(path_buf)) {
1596         new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1597         if (!new_path) {
1598             SetLastError(ERROR_OUTOFMEMORY);
1599             return FALSE;
1600         }
1601         result = GetCurrentDirectoryW(result, new_path);
1602         if (!result) {
1603             PyMem_RawFree(new_path);
1604             return FALSE;
1605         }
1606     }
1607     int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1608                             wcsncmp(new_path, L"//", 2) == 0);
1609     if (!is_unc_like_path) {
1610         env[1] = new_path[0];
1611         result = SetEnvironmentVariableW(env, new_path);
1612     }
1613     if (new_path != path_buf)
1614         PyMem_RawFree(new_path);
1615     return result ? TRUE : FALSE;
1616 }
1617 #endif
1618 
1619 #ifdef MS_WINDOWS
1620 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1621    - time stamps are restricted to second resolution
1622    - file modification times suffer from forth-and-back conversions between
1623      UTC and local time
1624    Therefore, we implement our own stat, based on the Win32 API directly.
1625 */
1626 #define HAVE_STAT_NSEC 1
1627 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1628 #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1629 
1630 static void
find_data_to_file_info(WIN32_FIND_DATAW * pFileData,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1631 find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1632                        BY_HANDLE_FILE_INFORMATION *info,
1633                        ULONG *reparse_tag)
1634 {
1635     memset(info, 0, sizeof(*info));
1636     info->dwFileAttributes = pFileData->dwFileAttributes;
1637     info->ftCreationTime   = pFileData->ftCreationTime;
1638     info->ftLastAccessTime = pFileData->ftLastAccessTime;
1639     info->ftLastWriteTime  = pFileData->ftLastWriteTime;
1640     info->nFileSizeHigh    = pFileData->nFileSizeHigh;
1641     info->nFileSizeLow     = pFileData->nFileSizeLow;
1642 /*  info->nNumberOfLinks   = 1; */
1643     if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1644         *reparse_tag = pFileData->dwReserved0;
1645     else
1646         *reparse_tag = 0;
1647 }
1648 
1649 static BOOL
attributes_from_dir(LPCWSTR pszFile,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1650 attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1651 {
1652     HANDLE hFindFile;
1653     WIN32_FIND_DATAW FileData;
1654     LPCWSTR filename = pszFile;
1655     size_t n = wcslen(pszFile);
1656     if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
1657         // cannot use PyMem_Malloc here because we do not hold the GIL
1658         filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
1659         wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
1660         while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
1661             ((LPWSTR)filename)[n] = L'\0';
1662         }
1663         if (!n || (n == 1 && filename[1] == L':')) {
1664             // Nothing left to query
1665             free((void *)filename);
1666             return FALSE;
1667         }
1668     }
1669     hFindFile = FindFirstFileW(filename, &FileData);
1670     if (pszFile != filename) {
1671         free((void *)filename);
1672     }
1673     if (hFindFile == INVALID_HANDLE_VALUE) {
1674         return FALSE;
1675     }
1676     FindClose(hFindFile);
1677     find_data_to_file_info(&FileData, info, reparse_tag);
1678     return TRUE;
1679 }
1680 
1681 static int
win32_xstat_impl(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1682 win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1683                  BOOL traverse)
1684 {
1685     HANDLE hFile;
1686     BY_HANDLE_FILE_INFORMATION fileInfo;
1687     FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1688     DWORD fileType, error;
1689     BOOL isUnhandledTag = FALSE;
1690     int retval = 0;
1691 
1692     DWORD access = FILE_READ_ATTRIBUTES;
1693     DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1694     if (!traverse) {
1695         flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1696     }
1697 
1698     hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1699     if (hFile == INVALID_HANDLE_VALUE) {
1700         /* Either the path doesn't exist, or the caller lacks access. */
1701         error = GetLastError();
1702         switch (error) {
1703         case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
1704         case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1705             /* Try reading the parent directory. */
1706             if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1707                 /* Cannot read the parent directory. */
1708                 SetLastError(error);
1709                 return -1;
1710             }
1711             if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1712                 if (traverse ||
1713                     !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1714                     /* The stat call has to traverse but cannot, so fail. */
1715                     SetLastError(error);
1716                     return -1;
1717                 }
1718             }
1719             break;
1720 
1721         case ERROR_INVALID_PARAMETER:
1722             /* \\.\con requires read or write access. */
1723             hFile = CreateFileW(path, access | GENERIC_READ,
1724                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1725                         OPEN_EXISTING, flags, NULL);
1726             if (hFile == INVALID_HANDLE_VALUE) {
1727                 SetLastError(error);
1728                 return -1;
1729             }
1730             break;
1731 
1732         case ERROR_CANT_ACCESS_FILE:
1733             /* bpo37834: open unhandled reparse points if traverse fails. */
1734             if (traverse) {
1735                 traverse = FALSE;
1736                 isUnhandledTag = TRUE;
1737                 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1738                             flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1739             }
1740             if (hFile == INVALID_HANDLE_VALUE) {
1741                 SetLastError(error);
1742                 return -1;
1743             }
1744             break;
1745 
1746         default:
1747             return -1;
1748         }
1749     }
1750 
1751     if (hFile != INVALID_HANDLE_VALUE) {
1752         /* Handle types other than files on disk. */
1753         fileType = GetFileType(hFile);
1754         if (fileType != FILE_TYPE_DISK) {
1755             if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1756                 retval = -1;
1757                 goto cleanup;
1758             }
1759             DWORD fileAttributes = GetFileAttributesW(path);
1760             memset(result, 0, sizeof(*result));
1761             if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1762                 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1763                 /* \\.\pipe\ or \\.\mailslot\ */
1764                 result->st_mode = _S_IFDIR;
1765             } else if (fileType == FILE_TYPE_CHAR) {
1766                 /* \\.\nul */
1767                 result->st_mode = _S_IFCHR;
1768             } else if (fileType == FILE_TYPE_PIPE) {
1769                 /* \\.\pipe\spam */
1770                 result->st_mode = _S_IFIFO;
1771             }
1772             /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1773             goto cleanup;
1774         }
1775 
1776         /* Query the reparse tag, and traverse a non-link. */
1777         if (!traverse) {
1778             if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
1779                     &tagInfo, sizeof(tagInfo))) {
1780                 /* Allow devices that do not support FileAttributeTagInfo. */
1781                 switch (GetLastError()) {
1782                 case ERROR_INVALID_PARAMETER:
1783                 case ERROR_INVALID_FUNCTION:
1784                 case ERROR_NOT_SUPPORTED:
1785                     tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1786                     tagInfo.ReparseTag = 0;
1787                     break;
1788                 default:
1789                     retval = -1;
1790                     goto cleanup;
1791                 }
1792             } else if (tagInfo.FileAttributes &
1793                          FILE_ATTRIBUTE_REPARSE_POINT) {
1794                 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1795                     if (isUnhandledTag) {
1796                         /* Traversing previously failed for either this link
1797                            or its target. */
1798                         SetLastError(ERROR_CANT_ACCESS_FILE);
1799                         retval = -1;
1800                         goto cleanup;
1801                     }
1802                 /* Traverse a non-link, but not if traversing already failed
1803                    for an unhandled tag. */
1804                 } else if (!isUnhandledTag) {
1805                     CloseHandle(hFile);
1806                     return win32_xstat_impl(path, result, TRUE);
1807                 }
1808             }
1809         }
1810 
1811         if (!GetFileInformationByHandle(hFile, &fileInfo)) {
1812             switch (GetLastError()) {
1813             case ERROR_INVALID_PARAMETER:
1814             case ERROR_INVALID_FUNCTION:
1815             case ERROR_NOT_SUPPORTED:
1816                 /* Volumes and physical disks are block devices, e.g.
1817                    \\.\C: and \\.\PhysicalDrive0. */
1818                 memset(result, 0, sizeof(*result));
1819                 result->st_mode = 0x6000; /* S_IFBLK */
1820                 goto cleanup;
1821             }
1822             retval = -1;
1823             goto cleanup;
1824         }
1825     }
1826 
1827     _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
1828 
1829     if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
1830         /* Fix the file execute permissions. This hack sets S_IEXEC if
1831            the filename has an extension that is commonly used by files
1832            that CreateProcessW can execute. A real implementation calls
1833            GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
1834            AccessCheck to check for generic read, write, and execute
1835            access. */
1836         const wchar_t *fileExtension = wcsrchr(path, '.');
1837         if (fileExtension) {
1838             if (_wcsicmp(fileExtension, L".exe") == 0 ||
1839                 _wcsicmp(fileExtension, L".bat") == 0 ||
1840                 _wcsicmp(fileExtension, L".cmd") == 0 ||
1841                 _wcsicmp(fileExtension, L".com") == 0) {
1842                 result->st_mode |= 0111;
1843             }
1844         }
1845     }
1846 
1847 cleanup:
1848     if (hFile != INVALID_HANDLE_VALUE) {
1849         /* Preserve last error if we are failing */
1850         error = retval ? GetLastError() : 0;
1851         if (!CloseHandle(hFile)) {
1852             retval = -1;
1853         } else if (retval) {
1854             /* Restore last error */
1855             SetLastError(error);
1856         }
1857     }
1858 
1859     return retval;
1860 }
1861 
1862 static int
win32_xstat(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1863 win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
1864 {
1865     /* Protocol violation: we explicitly clear errno, instead of
1866        setting it to a POSIX error. Callers should use GetLastError. */
1867     int code = win32_xstat_impl(path, result, traverse);
1868     errno = 0;
1869     return code;
1870 }
1871 /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
1872 
1873    In Posix, stat automatically traverses symlinks and returns the stat
1874    structure for the target.  In Windows, the equivalent GetFileAttributes by
1875    default does not traverse symlinks and instead returns attributes for
1876    the symlink.
1877 
1878    Instead, we will open the file (which *does* traverse symlinks by default)
1879    and GetFileInformationByHandle(). */
1880 
1881 static int
win32_lstat(const wchar_t * path,struct _Py_stat_struct * result)1882 win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
1883 {
1884     return win32_xstat(path, result, FALSE);
1885 }
1886 
1887 static int
win32_stat(const wchar_t * path,struct _Py_stat_struct * result)1888 win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
1889 {
1890     return win32_xstat(path, result, TRUE);
1891 }
1892 
1893 #endif /* MS_WINDOWS */
1894 
1895 PyDoc_STRVAR(stat_result__doc__,
1896 "stat_result: Result from stat, fstat, or lstat.\n\n\
1897 This object may be accessed either as a tuple of\n\
1898   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
1899 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
1900 \n\
1901 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
1902 or st_flags, they are available as attributes only.\n\
1903 \n\
1904 See os.stat for more information.");
1905 
1906 static PyStructSequence_Field stat_result_fields[] = {
1907     {"st_mode",    "protection bits"},
1908     {"st_ino",     "inode"},
1909     {"st_dev",     "device"},
1910     {"st_nlink",   "number of hard links"},
1911     {"st_uid",     "user ID of owner"},
1912     {"st_gid",     "group ID of owner"},
1913     {"st_size",    "total size, in bytes"},
1914     /* The NULL is replaced with PyStructSequence_UnnamedField later. */
1915     {NULL,   "integer time of last access"},
1916     {NULL,   "integer time of last modification"},
1917     {NULL,   "integer time of last change"},
1918     {"st_atime",   "time of last access"},
1919     {"st_mtime",   "time of last modification"},
1920     {"st_ctime",   "time of last change"},
1921     {"st_atime_ns",   "time of last access in nanoseconds"},
1922     {"st_mtime_ns",   "time of last modification in nanoseconds"},
1923     {"st_ctime_ns",   "time of last change in nanoseconds"},
1924 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1925     {"st_blksize", "blocksize for filesystem I/O"},
1926 #endif
1927 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1928     {"st_blocks",  "number of blocks allocated"},
1929 #endif
1930 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1931     {"st_rdev",    "device type (if inode device)"},
1932 #endif
1933 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
1934     {"st_flags",   "user defined flags for file"},
1935 #endif
1936 #ifdef HAVE_STRUCT_STAT_ST_GEN
1937     {"st_gen",    "generation number"},
1938 #endif
1939 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1940     {"st_birthtime",   "time of creation"},
1941 #endif
1942 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
1943     {"st_file_attributes", "Windows file attribute bits"},
1944 #endif
1945 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
1946     {"st_fstype",  "Type of filesystem"},
1947 #endif
1948 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
1949     {"st_reparse_tag", "Windows reparse tag"},
1950 #endif
1951     {0}
1952 };
1953 
1954 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1955 #define ST_BLKSIZE_IDX 16
1956 #else
1957 #define ST_BLKSIZE_IDX 15
1958 #endif
1959 
1960 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1961 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
1962 #else
1963 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
1964 #endif
1965 
1966 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1967 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
1968 #else
1969 #define ST_RDEV_IDX ST_BLOCKS_IDX
1970 #endif
1971 
1972 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
1973 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
1974 #else
1975 #define ST_FLAGS_IDX ST_RDEV_IDX
1976 #endif
1977 
1978 #ifdef HAVE_STRUCT_STAT_ST_GEN
1979 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
1980 #else
1981 #define ST_GEN_IDX ST_FLAGS_IDX
1982 #endif
1983 
1984 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1985 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
1986 #else
1987 #define ST_BIRTHTIME_IDX ST_GEN_IDX
1988 #endif
1989 
1990 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
1991 #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
1992 #else
1993 #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
1994 #endif
1995 
1996 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
1997 #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
1998 #else
1999 #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2000 #endif
2001 
2002 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2003 #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2004 #else
2005 #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2006 #endif
2007 
2008 static PyStructSequence_Desc stat_result_desc = {
2009     "stat_result", /* name */
2010     stat_result__doc__, /* doc */
2011     stat_result_fields,
2012     10
2013 };
2014 
2015 PyDoc_STRVAR(statvfs_result__doc__,
2016 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
2017 This object may be accessed either as a tuple of\n\
2018   (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2019 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2020 \n\
2021 See os.statvfs for more information.");
2022 
2023 static PyStructSequence_Field statvfs_result_fields[] = {
2024     {"f_bsize",  },
2025     {"f_frsize", },
2026     {"f_blocks", },
2027     {"f_bfree",  },
2028     {"f_bavail", },
2029     {"f_files",  },
2030     {"f_ffree",  },
2031     {"f_favail", },
2032     {"f_flag",   },
2033     {"f_namemax",},
2034     {"f_fsid",   },
2035     {0}
2036 };
2037 
2038 static PyStructSequence_Desc statvfs_result_desc = {
2039     "statvfs_result", /* name */
2040     statvfs_result__doc__, /* doc */
2041     statvfs_result_fields,
2042     10
2043 };
2044 
2045 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2046 PyDoc_STRVAR(waitid_result__doc__,
2047 "waitid_result: Result from waitid.\n\n\
2048 This object may be accessed either as a tuple of\n\
2049   (si_pid, si_uid, si_signo, si_status, si_code),\n\
2050 or via the attributes si_pid, si_uid, and so on.\n\
2051 \n\
2052 See os.waitid for more information.");
2053 
2054 static PyStructSequence_Field waitid_result_fields[] = {
2055     {"si_pid",  },
2056     {"si_uid", },
2057     {"si_signo", },
2058     {"si_status",  },
2059     {"si_code", },
2060     {0}
2061 };
2062 
2063 static PyStructSequence_Desc waitid_result_desc = {
2064     "waitid_result", /* name */
2065     waitid_result__doc__, /* doc */
2066     waitid_result_fields,
2067     5
2068 };
2069 static PyTypeObject* WaitidResultType;
2070 #endif
2071 
2072 static int initialized;
2073 static PyTypeObject* StatResultType;
2074 static PyTypeObject* StatVFSResultType;
2075 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2076 static PyTypeObject* SchedParamType;
2077 #endif
2078 static newfunc structseq_new;
2079 
2080 static PyObject *
statresult_new(PyTypeObject * type,PyObject * args,PyObject * kwds)2081 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2082 {
2083     PyStructSequence *result;
2084     int i;
2085 
2086     result = (PyStructSequence*)structseq_new(type, args, kwds);
2087     if (!result)
2088         return NULL;
2089     /* If we have been initialized from a tuple,
2090        st_?time might be set to None. Initialize it
2091        from the int slots.  */
2092     for (i = 7; i <= 9; i++) {
2093         if (result->ob_item[i+3] == Py_None) {
2094             Py_DECREF(Py_None);
2095             Py_INCREF(result->ob_item[i]);
2096             result->ob_item[i+3] = result->ob_item[i];
2097         }
2098     }
2099     return (PyObject*)result;
2100 }
2101 
2102 
2103 static PyObject *billion = NULL;
2104 
2105 static void
fill_time(PyObject * v,int index,time_t sec,unsigned long nsec)2106 fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
2107 {
2108     PyObject *s = _PyLong_FromTime_t(sec);
2109     PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2110     PyObject *s_in_ns = NULL;
2111     PyObject *ns_total = NULL;
2112     PyObject *float_s = NULL;
2113 
2114     if (!(s && ns_fractional))
2115         goto exit;
2116 
2117     s_in_ns = PyNumber_Multiply(s, billion);
2118     if (!s_in_ns)
2119         goto exit;
2120 
2121     ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2122     if (!ns_total)
2123         goto exit;
2124 
2125     float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2126     if (!float_s) {
2127         goto exit;
2128     }
2129 
2130     PyStructSequence_SET_ITEM(v, index, s);
2131     PyStructSequence_SET_ITEM(v, index+3, float_s);
2132     PyStructSequence_SET_ITEM(v, index+6, ns_total);
2133     s = NULL;
2134     float_s = NULL;
2135     ns_total = NULL;
2136 exit:
2137     Py_XDECREF(s);
2138     Py_XDECREF(ns_fractional);
2139     Py_XDECREF(s_in_ns);
2140     Py_XDECREF(ns_total);
2141     Py_XDECREF(float_s);
2142 }
2143 
2144 /* pack a system stat C structure into the Python stat tuple
2145    (used by posix_stat() and posix_fstat()) */
2146 static PyObject*
_pystat_fromstructstat(STRUCT_STAT * st)2147 _pystat_fromstructstat(STRUCT_STAT *st)
2148 {
2149     unsigned long ansec, mnsec, cnsec;
2150     PyObject *v = PyStructSequence_New(StatResultType);
2151     if (v == NULL)
2152         return NULL;
2153 
2154     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2155     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(st->st_ino));
2156     PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2157 #ifdef MS_WINDOWS
2158     PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
2159 #else
2160     PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2161 #endif
2162     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2163 #if defined(MS_WINDOWS)
2164     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2165     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2166 #else
2167     PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2168     PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2169 #endif
2170     Py_BUILD_ASSERT(sizeof(long long) >= sizeof(st->st_size));
2171     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2172 
2173 #if defined(HAVE_STAT_TV_NSEC)
2174     ansec = st->st_atim.tv_nsec;
2175     mnsec = st->st_mtim.tv_nsec;
2176     cnsec = st->st_ctim.tv_nsec;
2177 #elif defined(HAVE_STAT_TV_NSEC2)
2178     ansec = st->st_atimespec.tv_nsec;
2179     mnsec = st->st_mtimespec.tv_nsec;
2180     cnsec = st->st_ctimespec.tv_nsec;
2181 #elif defined(HAVE_STAT_NSEC)
2182     ansec = st->st_atime_nsec;
2183     mnsec = st->st_mtime_nsec;
2184     cnsec = st->st_ctime_nsec;
2185 #else
2186     ansec = mnsec = cnsec = 0;
2187 #endif
2188     fill_time(v, 7, st->st_atime, ansec);
2189     fill_time(v, 8, st->st_mtime, mnsec);
2190     fill_time(v, 9, st->st_ctime, cnsec);
2191 
2192 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2193     PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2194                               PyLong_FromLong((long)st->st_blksize));
2195 #endif
2196 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2197     PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2198                               PyLong_FromLong((long)st->st_blocks));
2199 #endif
2200 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2201     PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2202                               PyLong_FromLong((long)st->st_rdev));
2203 #endif
2204 #ifdef HAVE_STRUCT_STAT_ST_GEN
2205     PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2206                               PyLong_FromLong((long)st->st_gen));
2207 #endif
2208 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2209     {
2210       PyObject *val;
2211       unsigned long bsec,bnsec;
2212       bsec = (long)st->st_birthtime;
2213 #ifdef HAVE_STAT_TV_NSEC2
2214       bnsec = st->st_birthtimespec.tv_nsec;
2215 #else
2216       bnsec = 0;
2217 #endif
2218       val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2219       PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2220                                 val);
2221     }
2222 #endif
2223 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2224     PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2225                               PyLong_FromLong((long)st->st_flags));
2226 #endif
2227 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2228     PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2229                               PyLong_FromUnsignedLong(st->st_file_attributes));
2230 #endif
2231 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2232    PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2233                               PyUnicode_FromString(st->st_fstype));
2234 #endif
2235 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2236     PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2237                               PyLong_FromUnsignedLong(st->st_reparse_tag));
2238 #endif
2239 
2240     if (PyErr_Occurred()) {
2241         Py_DECREF(v);
2242         return NULL;
2243     }
2244 
2245     return v;
2246 }
2247 
2248 /* POSIX methods */
2249 
2250 
2251 static PyObject *
posix_do_stat(const char * function_name,path_t * path,int dir_fd,int follow_symlinks)2252 posix_do_stat(const char *function_name, path_t *path,
2253               int dir_fd, int follow_symlinks)
2254 {
2255     STRUCT_STAT st;
2256     int result;
2257 
2258 #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2259     if (follow_symlinks_specified(function_name, follow_symlinks))
2260         return NULL;
2261 #endif
2262 
2263     if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2264         dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2265         fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2266         return NULL;
2267 
2268     Py_BEGIN_ALLOW_THREADS
2269     if (path->fd != -1)
2270         result = FSTAT(path->fd, &st);
2271 #ifdef MS_WINDOWS
2272     else if (follow_symlinks)
2273         result = win32_stat(path->wide, &st);
2274     else
2275         result = win32_lstat(path->wide, &st);
2276 #else
2277     else
2278 #if defined(HAVE_LSTAT)
2279     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2280         result = LSTAT(path->narrow, &st);
2281     else
2282 #endif /* HAVE_LSTAT */
2283 #ifdef HAVE_FSTATAT
2284     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks)
2285         result = fstatat(dir_fd, path->narrow, &st,
2286                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2287     else
2288 #endif /* HAVE_FSTATAT */
2289         result = STAT(path->narrow, &st);
2290 #endif /* MS_WINDOWS */
2291     Py_END_ALLOW_THREADS
2292 
2293     if (result != 0) {
2294         return path_error(path);
2295     }
2296 
2297     return _pystat_fromstructstat(&st);
2298 }
2299 
2300 /*[python input]
2301 
2302 for s in """
2303 
2304 FACCESSAT
2305 FCHMODAT
2306 FCHOWNAT
2307 FSTATAT
2308 LINKAT
2309 MKDIRAT
2310 MKFIFOAT
2311 MKNODAT
2312 OPENAT
2313 READLINKAT
2314 SYMLINKAT
2315 UNLINKAT
2316 
2317 """.strip().split():
2318     s = s.strip()
2319     print("""
2320 #ifdef HAVE_{s}
2321     #define {s}_DIR_FD_CONVERTER dir_fd_converter
2322 #else
2323     #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2324 #endif
2325 """.rstrip().format(s=s))
2326 
2327 for s in """
2328 
2329 FCHDIR
2330 FCHMOD
2331 FCHOWN
2332 FDOPENDIR
2333 FEXECVE
2334 FPATHCONF
2335 FSTATVFS
2336 FTRUNCATE
2337 
2338 """.strip().split():
2339     s = s.strip()
2340     print("""
2341 #ifdef HAVE_{s}
2342     #define PATH_HAVE_{s} 1
2343 #else
2344     #define PATH_HAVE_{s} 0
2345 #endif
2346 
2347 """.rstrip().format(s=s))
2348 [python start generated code]*/
2349 
2350 #ifdef HAVE_FACCESSAT
2351     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2352 #else
2353     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2354 #endif
2355 
2356 #ifdef HAVE_FCHMODAT
2357     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2358 #else
2359     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2360 #endif
2361 
2362 #ifdef HAVE_FCHOWNAT
2363     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2364 #else
2365     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2366 #endif
2367 
2368 #ifdef HAVE_FSTATAT
2369     #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2370 #else
2371     #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2372 #endif
2373 
2374 #ifdef HAVE_LINKAT
2375     #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2376 #else
2377     #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2378 #endif
2379 
2380 #ifdef HAVE_MKDIRAT
2381     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2382 #else
2383     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2384 #endif
2385 
2386 #ifdef HAVE_MKFIFOAT
2387     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2388 #else
2389     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2390 #endif
2391 
2392 #ifdef HAVE_MKNODAT
2393     #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2394 #else
2395     #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2396 #endif
2397 
2398 #ifdef HAVE_OPENAT
2399     #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2400 #else
2401     #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2402 #endif
2403 
2404 #ifdef HAVE_READLINKAT
2405     #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2406 #else
2407     #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2408 #endif
2409 
2410 #ifdef HAVE_SYMLINKAT
2411     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2412 #else
2413     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2414 #endif
2415 
2416 #ifdef HAVE_UNLINKAT
2417     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2418 #else
2419     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2420 #endif
2421 
2422 #ifdef HAVE_FCHDIR
2423     #define PATH_HAVE_FCHDIR 1
2424 #else
2425     #define PATH_HAVE_FCHDIR 0
2426 #endif
2427 
2428 #ifdef HAVE_FCHMOD
2429     #define PATH_HAVE_FCHMOD 1
2430 #else
2431     #define PATH_HAVE_FCHMOD 0
2432 #endif
2433 
2434 #ifdef HAVE_FCHOWN
2435     #define PATH_HAVE_FCHOWN 1
2436 #else
2437     #define PATH_HAVE_FCHOWN 0
2438 #endif
2439 
2440 #ifdef HAVE_FDOPENDIR
2441     #define PATH_HAVE_FDOPENDIR 1
2442 #else
2443     #define PATH_HAVE_FDOPENDIR 0
2444 #endif
2445 
2446 #ifdef HAVE_FEXECVE
2447     #define PATH_HAVE_FEXECVE 1
2448 #else
2449     #define PATH_HAVE_FEXECVE 0
2450 #endif
2451 
2452 #ifdef HAVE_FPATHCONF
2453     #define PATH_HAVE_FPATHCONF 1
2454 #else
2455     #define PATH_HAVE_FPATHCONF 0
2456 #endif
2457 
2458 #ifdef HAVE_FSTATVFS
2459     #define PATH_HAVE_FSTATVFS 1
2460 #else
2461     #define PATH_HAVE_FSTATVFS 0
2462 #endif
2463 
2464 #ifdef HAVE_FTRUNCATE
2465     #define PATH_HAVE_FTRUNCATE 1
2466 #else
2467     #define PATH_HAVE_FTRUNCATE 0
2468 #endif
2469 /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2470 
2471 #ifdef MS_WINDOWS
2472     #undef PATH_HAVE_FTRUNCATE
2473     #define PATH_HAVE_FTRUNCATE 1
2474 #endif
2475 
2476 /*[python input]
2477 
2478 class path_t_converter(CConverter):
2479 
2480     type = "path_t"
2481     impl_by_reference = True
2482     parse_by_reference = True
2483 
2484     converter = 'path_converter'
2485 
2486     def converter_init(self, *, allow_fd=False, nullable=False):
2487         # right now path_t doesn't support default values.
2488         # to support a default value, you'll need to override initialize().
2489         if self.default not in (unspecified, None):
2490             fail("Can't specify a default to the path_t converter!")
2491 
2492         if self.c_default not in (None, 'Py_None'):
2493             raise RuntimeError("Can't specify a c_default to the path_t converter!")
2494 
2495         self.nullable = nullable
2496         self.allow_fd = allow_fd
2497 
2498     def pre_render(self):
2499         def strify(value):
2500             if isinstance(value, str):
2501                 return value
2502             return str(int(bool(value)))
2503 
2504         # add self.py_name here when merging with posixmodule conversion
2505         self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2506             self.function.name,
2507             self.name,
2508             strify(self.nullable),
2509             strify(self.allow_fd),
2510             )
2511 
2512     def cleanup(self):
2513         return "path_cleanup(&" + self.name + ");\n"
2514 
2515 
2516 class dir_fd_converter(CConverter):
2517     type = 'int'
2518 
2519     def converter_init(self, requires=None):
2520         if self.default in (unspecified, None):
2521             self.c_default = 'DEFAULT_DIR_FD'
2522         if isinstance(requires, str):
2523             self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2524         else:
2525             self.converter = 'dir_fd_converter'
2526 
2527 class fildes_converter(CConverter):
2528     type = 'int'
2529     converter = 'fildes_converter'
2530 
2531 class uid_t_converter(CConverter):
2532     type = "uid_t"
2533     converter = '_Py_Uid_Converter'
2534 
2535 class gid_t_converter(CConverter):
2536     type = "gid_t"
2537     converter = '_Py_Gid_Converter'
2538 
2539 class dev_t_converter(CConverter):
2540     type = 'dev_t'
2541     converter = '_Py_Dev_Converter'
2542 
2543 class dev_t_return_converter(unsigned_long_return_converter):
2544     type = 'dev_t'
2545     conversion_fn = '_PyLong_FromDev'
2546     unsigned_cast = '(dev_t)'
2547 
2548 class FSConverter_converter(CConverter):
2549     type = 'PyObject *'
2550     converter = 'PyUnicode_FSConverter'
2551     def converter_init(self):
2552         if self.default is not unspecified:
2553             fail("FSConverter_converter does not support default values")
2554         self.c_default = 'NULL'
2555 
2556     def cleanup(self):
2557         return "Py_XDECREF(" + self.name + ");\n"
2558 
2559 class pid_t_converter(CConverter):
2560     type = 'pid_t'
2561     format_unit = '" _Py_PARSE_PID "'
2562 
2563 class idtype_t_converter(int_converter):
2564     type = 'idtype_t'
2565 
2566 class id_t_converter(CConverter):
2567     type = 'id_t'
2568     format_unit = '" _Py_PARSE_PID "'
2569 
2570 class intptr_t_converter(CConverter):
2571     type = 'intptr_t'
2572     format_unit = '" _Py_PARSE_INTPTR "'
2573 
2574 class Py_off_t_converter(CConverter):
2575     type = 'Py_off_t'
2576     converter = 'Py_off_t_converter'
2577 
2578 class Py_off_t_return_converter(long_return_converter):
2579     type = 'Py_off_t'
2580     conversion_fn = 'PyLong_FromPy_off_t'
2581 
2582 class path_confname_converter(CConverter):
2583     type="int"
2584     converter="conv_path_confname"
2585 
2586 class confstr_confname_converter(path_confname_converter):
2587     converter='conv_confstr_confname'
2588 
2589 class sysconf_confname_converter(path_confname_converter):
2590     converter="conv_sysconf_confname"
2591 
2592 class sched_param_converter(CConverter):
2593     type = 'struct sched_param'
2594     converter = 'convert_sched_param'
2595     impl_by_reference = True;
2596 
2597 [python start generated code]*/
2598 /*[python end generated code: output=da39a3ee5e6b4b0d input=418fce0e01144461]*/
2599 
2600 /*[clinic input]
2601 
2602 os.stat
2603 
2604     path : path_t(allow_fd=True)
2605         Path to be examined; can be string, bytes, a path-like object or
2606         open-file-descriptor int.
2607 
2608     *
2609 
2610     dir_fd : dir_fd(requires='fstatat') = None
2611         If not None, it should be a file descriptor open to a directory,
2612         and path should be a relative string; path will then be relative to
2613         that directory.
2614 
2615     follow_symlinks: bool = True
2616         If False, and the last element of the path is a symbolic link,
2617         stat will examine the symbolic link itself instead of the file
2618         the link points to.
2619 
2620 Perform a stat system call on the given path.
2621 
2622 dir_fd and follow_symlinks may not be implemented
2623   on your platform.  If they are unavailable, using them will raise a
2624   NotImplementedError.
2625 
2626 It's an error to use dir_fd or follow_symlinks when specifying path as
2627   an open file descriptor.
2628 
2629 [clinic start generated code]*/
2630 
2631 static PyObject *
os_stat_impl(PyObject * module,path_t * path,int dir_fd,int follow_symlinks)2632 os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2633 /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2634 {
2635     return posix_do_stat("stat", path, dir_fd, follow_symlinks);
2636 }
2637 
2638 
2639 /*[clinic input]
2640 os.lstat
2641 
2642     path : path_t
2643 
2644     *
2645 
2646     dir_fd : dir_fd(requires='fstatat') = None
2647 
2648 Perform a stat system call on the given path, without following symbolic links.
2649 
2650 Like stat(), but do not follow symbolic links.
2651 Equivalent to stat(path, follow_symlinks=False).
2652 [clinic start generated code]*/
2653 
2654 static PyObject *
os_lstat_impl(PyObject * module,path_t * path,int dir_fd)2655 os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2656 /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2657 {
2658     int follow_symlinks = 0;
2659     return posix_do_stat("lstat", path, dir_fd, follow_symlinks);
2660 }
2661 
2662 
2663 /*[clinic input]
2664 os.access -> bool
2665 
2666     path: path_t
2667         Path to be tested; can be string, bytes, or a path-like object.
2668 
2669     mode: int
2670         Operating-system mode bitfield.  Can be F_OK to test existence,
2671         or the inclusive-OR of R_OK, W_OK, and X_OK.
2672 
2673     *
2674 
2675     dir_fd : dir_fd(requires='faccessat') = None
2676         If not None, it should be a file descriptor open to a directory,
2677         and path should be relative; path will then be relative to that
2678         directory.
2679 
2680     effective_ids: bool = False
2681         If True, access will use the effective uid/gid instead of
2682         the real uid/gid.
2683 
2684     follow_symlinks: bool = True
2685         If False, and the last element of the path is a symbolic link,
2686         access will examine the symbolic link itself instead of the file
2687         the link points to.
2688 
2689 Use the real uid/gid to test for access to a path.
2690 
2691 {parameters}
2692 dir_fd, effective_ids, and follow_symlinks may not be implemented
2693   on your platform.  If they are unavailable, using them will raise a
2694   NotImplementedError.
2695 
2696 Note that most operations will use the effective uid/gid, therefore this
2697   routine can be used in a suid/sgid environment to test if the invoking user
2698   has the specified access to the path.
2699 
2700 [clinic start generated code]*/
2701 
2702 static int
os_access_impl(PyObject * module,path_t * path,int mode,int dir_fd,int effective_ids,int follow_symlinks)2703 os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2704                int effective_ids, int follow_symlinks)
2705 /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
2706 {
2707     int return_value;
2708 
2709 #ifdef MS_WINDOWS
2710     DWORD attr;
2711 #else
2712     int result;
2713 #endif
2714 
2715 #ifndef HAVE_FACCESSAT
2716     if (follow_symlinks_specified("access", follow_symlinks))
2717         return -1;
2718 
2719     if (effective_ids) {
2720         argument_unavailable_error("access", "effective_ids");
2721         return -1;
2722     }
2723 #endif
2724 
2725 #ifdef MS_WINDOWS
2726     Py_BEGIN_ALLOW_THREADS
2727     attr = GetFileAttributesW(path->wide);
2728     Py_END_ALLOW_THREADS
2729 
2730     /*
2731      * Access is possible if
2732      *   * we didn't get a -1, and
2733      *     * write access wasn't requested,
2734      *     * or the file isn't read-only,
2735      *     * or it's a directory.
2736      * (Directories cannot be read-only on Windows.)
2737     */
2738     return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
2739             (!(mode & 2) ||
2740             !(attr & FILE_ATTRIBUTE_READONLY) ||
2741             (attr & FILE_ATTRIBUTE_DIRECTORY));
2742 #else
2743 
2744     Py_BEGIN_ALLOW_THREADS
2745 #ifdef HAVE_FACCESSAT
2746     if ((dir_fd != DEFAULT_DIR_FD) ||
2747         effective_ids ||
2748         !follow_symlinks) {
2749         int flags = 0;
2750         if (!follow_symlinks)
2751             flags |= AT_SYMLINK_NOFOLLOW;
2752         if (effective_ids)
2753             flags |= AT_EACCESS;
2754         result = faccessat(dir_fd, path->narrow, mode, flags);
2755     }
2756     else
2757 #endif
2758         result = access(path->narrow, mode);
2759     Py_END_ALLOW_THREADS
2760     return_value = !result;
2761 #endif
2762 
2763     return return_value;
2764 }
2765 
2766 #ifndef F_OK
2767 #define F_OK 0
2768 #endif
2769 #ifndef R_OK
2770 #define R_OK 4
2771 #endif
2772 #ifndef W_OK
2773 #define W_OK 2
2774 #endif
2775 #ifndef X_OK
2776 #define X_OK 1
2777 #endif
2778 
2779 
2780 #ifdef HAVE_TTYNAME
2781 /*[clinic input]
2782 os.ttyname
2783 
2784     fd: int
2785         Integer file descriptor handle.
2786 
2787     /
2788 
2789 Return the name of the terminal device connected to 'fd'.
2790 [clinic start generated code]*/
2791 
2792 static PyObject *
os_ttyname_impl(PyObject * module,int fd)2793 os_ttyname_impl(PyObject *module, int fd)
2794 /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
2795 {
2796     char *ret;
2797 
2798     ret = ttyname(fd);
2799     if (ret == NULL) {
2800         return posix_error();
2801     }
2802     return PyUnicode_DecodeFSDefault(ret);
2803 }
2804 #endif
2805 
2806 #ifdef HAVE_CTERMID
2807 /*[clinic input]
2808 os.ctermid
2809 
2810 Return the name of the controlling terminal for this process.
2811 [clinic start generated code]*/
2812 
2813 static PyObject *
os_ctermid_impl(PyObject * module)2814 os_ctermid_impl(PyObject *module)
2815 /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
2816 {
2817     char *ret;
2818     char buffer[L_ctermid];
2819 
2820 #ifdef USE_CTERMID_R
2821     ret = ctermid_r(buffer);
2822 #else
2823     ret = ctermid(buffer);
2824 #endif
2825     if (ret == NULL)
2826         return posix_error();
2827     return PyUnicode_DecodeFSDefault(buffer);
2828 }
2829 #endif /* HAVE_CTERMID */
2830 
2831 
2832 /*[clinic input]
2833 os.chdir
2834 
2835     path: path_t(allow_fd='PATH_HAVE_FCHDIR')
2836 
2837 Change the current working directory to the specified path.
2838 
2839 path may always be specified as a string.
2840 On some platforms, path may also be specified as an open file descriptor.
2841   If this functionality is unavailable, using it raises an exception.
2842 [clinic start generated code]*/
2843 
2844 static PyObject *
os_chdir_impl(PyObject * module,path_t * path)2845 os_chdir_impl(PyObject *module, path_t *path)
2846 /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
2847 {
2848     int result;
2849 
2850     if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
2851         return NULL;
2852     }
2853 
2854     Py_BEGIN_ALLOW_THREADS
2855 #ifdef MS_WINDOWS
2856     /* on unix, success = 0, on windows, success = !0 */
2857     result = !win32_wchdir(path->wide);
2858 #else
2859 #ifdef HAVE_FCHDIR
2860     if (path->fd != -1)
2861         result = fchdir(path->fd);
2862     else
2863 #endif
2864         result = chdir(path->narrow);
2865 #endif
2866     Py_END_ALLOW_THREADS
2867 
2868     if (result) {
2869         return path_error(path);
2870     }
2871 
2872     Py_RETURN_NONE;
2873 }
2874 
2875 
2876 #ifdef HAVE_FCHDIR
2877 /*[clinic input]
2878 os.fchdir
2879 
2880     fd: fildes
2881 
2882 Change to the directory of the given file descriptor.
2883 
2884 fd must be opened on a directory, not a file.
2885 Equivalent to os.chdir(fd).
2886 
2887 [clinic start generated code]*/
2888 
2889 static PyObject *
os_fchdir_impl(PyObject * module,int fd)2890 os_fchdir_impl(PyObject *module, int fd)
2891 /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
2892 {
2893     if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
2894         return NULL;
2895     }
2896     return posix_fildes_fd(fd, fchdir);
2897 }
2898 #endif /* HAVE_FCHDIR */
2899 
2900 
2901 /*[clinic input]
2902 os.chmod
2903 
2904     path: path_t(allow_fd='PATH_HAVE_FCHMOD')
2905         Path to be modified.  May always be specified as a str, bytes, or a path-like object.
2906         On some platforms, path may also be specified as an open file descriptor.
2907         If this functionality is unavailable, using it raises an exception.
2908 
2909     mode: int
2910         Operating-system mode bitfield.
2911 
2912     *
2913 
2914     dir_fd : dir_fd(requires='fchmodat') = None
2915         If not None, it should be a file descriptor open to a directory,
2916         and path should be relative; path will then be relative to that
2917         directory.
2918 
2919     follow_symlinks: bool = True
2920         If False, and the last element of the path is a symbolic link,
2921         chmod will modify the symbolic link itself instead of the file
2922         the link points to.
2923 
2924 Change the access permissions of a file.
2925 
2926 It is an error to use dir_fd or follow_symlinks when specifying path as
2927   an open file descriptor.
2928 dir_fd and follow_symlinks may not be implemented on your platform.
2929   If they are unavailable, using them will raise a NotImplementedError.
2930 
2931 [clinic start generated code]*/
2932 
2933 static PyObject *
os_chmod_impl(PyObject * module,path_t * path,int mode,int dir_fd,int follow_symlinks)2934 os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2935               int follow_symlinks)
2936 /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
2937 {
2938     int result;
2939 
2940 #ifdef MS_WINDOWS
2941     DWORD attr;
2942 #endif
2943 
2944 #ifdef HAVE_FCHMODAT
2945     int fchmodat_nofollow_unsupported = 0;
2946 #endif
2947 
2948 #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
2949     if (follow_symlinks_specified("chmod", follow_symlinks))
2950         return NULL;
2951 #endif
2952 
2953     if (PySys_Audit("os.chmod", "Oii", path->object, mode,
2954                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
2955         return NULL;
2956     }
2957 
2958 #ifdef MS_WINDOWS
2959     Py_BEGIN_ALLOW_THREADS
2960     attr = GetFileAttributesW(path->wide);
2961     if (attr == INVALID_FILE_ATTRIBUTES)
2962         result = 0;
2963     else {
2964         if (mode & _S_IWRITE)
2965             attr &= ~FILE_ATTRIBUTE_READONLY;
2966         else
2967             attr |= FILE_ATTRIBUTE_READONLY;
2968         result = SetFileAttributesW(path->wide, attr);
2969     }
2970     Py_END_ALLOW_THREADS
2971 
2972     if (!result) {
2973         return path_error(path);
2974     }
2975 #else /* MS_WINDOWS */
2976     Py_BEGIN_ALLOW_THREADS
2977 #ifdef HAVE_FCHMOD
2978     if (path->fd != -1)
2979         result = fchmod(path->fd, mode);
2980     else
2981 #endif
2982 #ifdef HAVE_LCHMOD
2983     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2984         result = lchmod(path->narrow, mode);
2985     else
2986 #endif
2987 #ifdef HAVE_FCHMODAT
2988     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2989         /*
2990          * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
2991          * The documentation specifically shows how to use it,
2992          * and then says it isn't implemented yet.
2993          * (true on linux with glibc 2.15, and openindiana 3.x)
2994          *
2995          * Once it is supported, os.chmod will automatically
2996          * support dir_fd and follow_symlinks=False.  (Hopefully.)
2997          * Until then, we need to be careful what exception we raise.
2998          */
2999         result = fchmodat(dir_fd, path->narrow, mode,
3000                           follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3001         /*
3002          * But wait!  We can't throw the exception without allowing threads,
3003          * and we can't do that in this nested scope.  (Macro trickery, sigh.)
3004          */
3005         fchmodat_nofollow_unsupported =
3006                          result &&
3007                          ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3008                          !follow_symlinks;
3009     }
3010     else
3011 #endif
3012         result = chmod(path->narrow, mode);
3013     Py_END_ALLOW_THREADS
3014 
3015     if (result) {
3016 #ifdef HAVE_FCHMODAT
3017         if (fchmodat_nofollow_unsupported) {
3018             if (dir_fd != DEFAULT_DIR_FD)
3019                 dir_fd_and_follow_symlinks_invalid("chmod",
3020                                                    dir_fd, follow_symlinks);
3021             else
3022                 follow_symlinks_specified("chmod", follow_symlinks);
3023             return NULL;
3024         }
3025         else
3026 #endif
3027         return path_error(path);
3028     }
3029 #endif
3030 
3031     Py_RETURN_NONE;
3032 }
3033 
3034 
3035 #ifdef HAVE_FCHMOD
3036 /*[clinic input]
3037 os.fchmod
3038 
3039     fd: int
3040     mode: int
3041 
3042 Change the access permissions of the file given by file descriptor fd.
3043 
3044 Equivalent to os.chmod(fd, mode).
3045 [clinic start generated code]*/
3046 
3047 static PyObject *
os_fchmod_impl(PyObject * module,int fd,int mode)3048 os_fchmod_impl(PyObject *module, int fd, int mode)
3049 /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
3050 {
3051     int res;
3052     int async_err = 0;
3053 
3054     if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3055         return NULL;
3056     }
3057 
3058     do {
3059         Py_BEGIN_ALLOW_THREADS
3060         res = fchmod(fd, mode);
3061         Py_END_ALLOW_THREADS
3062     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3063     if (res != 0)
3064         return (!async_err) ? posix_error() : NULL;
3065 
3066     Py_RETURN_NONE;
3067 }
3068 #endif /* HAVE_FCHMOD */
3069 
3070 
3071 #ifdef HAVE_LCHMOD
3072 /*[clinic input]
3073 os.lchmod
3074 
3075     path: path_t
3076     mode: int
3077 
3078 Change the access permissions of a file, without following symbolic links.
3079 
3080 If path is a symlink, this affects the link itself rather than the target.
3081 Equivalent to chmod(path, mode, follow_symlinks=False)."
3082 [clinic start generated code]*/
3083 
3084 static PyObject *
os_lchmod_impl(PyObject * module,path_t * path,int mode)3085 os_lchmod_impl(PyObject *module, path_t *path, int mode)
3086 /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3087 {
3088     int res;
3089     if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3090         return NULL;
3091     }
3092     Py_BEGIN_ALLOW_THREADS
3093     res = lchmod(path->narrow, mode);
3094     Py_END_ALLOW_THREADS
3095     if (res < 0) {
3096         path_error(path);
3097         return NULL;
3098     }
3099     Py_RETURN_NONE;
3100 }
3101 #endif /* HAVE_LCHMOD */
3102 
3103 
3104 #ifdef HAVE_CHFLAGS
3105 /*[clinic input]
3106 os.chflags
3107 
3108     path: path_t
3109     flags: unsigned_long(bitwise=True)
3110     follow_symlinks: bool=True
3111 
3112 Set file flags.
3113 
3114 If follow_symlinks is False, and the last element of the path is a symbolic
3115   link, chflags will change flags on the symbolic link itself instead of the
3116   file the link points to.
3117 follow_symlinks may not be implemented on your platform.  If it is
3118 unavailable, using it will raise a NotImplementedError.
3119 
3120 [clinic start generated code]*/
3121 
3122 static PyObject *
os_chflags_impl(PyObject * module,path_t * path,unsigned long flags,int follow_symlinks)3123 os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3124                 int follow_symlinks)
3125 /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3126 {
3127     int result;
3128 
3129 #ifndef HAVE_LCHFLAGS
3130     if (follow_symlinks_specified("chflags", follow_symlinks))
3131         return NULL;
3132 #endif
3133 
3134     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3135         return NULL;
3136     }
3137 
3138     Py_BEGIN_ALLOW_THREADS
3139 #ifdef HAVE_LCHFLAGS
3140     if (!follow_symlinks)
3141         result = lchflags(path->narrow, flags);
3142     else
3143 #endif
3144         result = chflags(path->narrow, flags);
3145     Py_END_ALLOW_THREADS
3146 
3147     if (result)
3148         return path_error(path);
3149 
3150     Py_RETURN_NONE;
3151 }
3152 #endif /* HAVE_CHFLAGS */
3153 
3154 
3155 #ifdef HAVE_LCHFLAGS
3156 /*[clinic input]
3157 os.lchflags
3158 
3159     path: path_t
3160     flags: unsigned_long(bitwise=True)
3161 
3162 Set file flags.
3163 
3164 This function will not follow symbolic links.
3165 Equivalent to chflags(path, flags, follow_symlinks=False).
3166 [clinic start generated code]*/
3167 
3168 static PyObject *
os_lchflags_impl(PyObject * module,path_t * path,unsigned long flags)3169 os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3170 /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3171 {
3172     int res;
3173     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3174         return NULL;
3175     }
3176     Py_BEGIN_ALLOW_THREADS
3177     res = lchflags(path->narrow, flags);
3178     Py_END_ALLOW_THREADS
3179     if (res < 0) {
3180         return path_error(path);
3181     }
3182     Py_RETURN_NONE;
3183 }
3184 #endif /* HAVE_LCHFLAGS */
3185 
3186 
3187 #ifdef HAVE_CHROOT
3188 /*[clinic input]
3189 os.chroot
3190     path: path_t
3191 
3192 Change root directory to path.
3193 
3194 [clinic start generated code]*/
3195 
3196 static PyObject *
os_chroot_impl(PyObject * module,path_t * path)3197 os_chroot_impl(PyObject *module, path_t *path)
3198 /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3199 {
3200     int res;
3201     Py_BEGIN_ALLOW_THREADS
3202     res = chroot(path->narrow);
3203     Py_END_ALLOW_THREADS
3204     if (res < 0)
3205         return path_error(path);
3206     Py_RETURN_NONE;
3207 }
3208 #endif /* HAVE_CHROOT */
3209 
3210 
3211 #ifdef HAVE_FSYNC
3212 /*[clinic input]
3213 os.fsync
3214 
3215     fd: fildes
3216 
3217 Force write of fd to disk.
3218 [clinic start generated code]*/
3219 
3220 static PyObject *
os_fsync_impl(PyObject * module,int fd)3221 os_fsync_impl(PyObject *module, int fd)
3222 /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3223 {
3224     return posix_fildes_fd(fd, fsync);
3225 }
3226 #endif /* HAVE_FSYNC */
3227 
3228 
3229 #ifdef HAVE_SYNC
3230 /*[clinic input]
3231 os.sync
3232 
3233 Force write of everything to disk.
3234 [clinic start generated code]*/
3235 
3236 static PyObject *
os_sync_impl(PyObject * module)3237 os_sync_impl(PyObject *module)
3238 /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3239 {
3240     Py_BEGIN_ALLOW_THREADS
3241     sync();
3242     Py_END_ALLOW_THREADS
3243     Py_RETURN_NONE;
3244 }
3245 #endif /* HAVE_SYNC */
3246 
3247 
3248 #ifdef HAVE_FDATASYNC
3249 #ifdef __hpux
3250 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3251 #endif
3252 
3253 /*[clinic input]
3254 os.fdatasync
3255 
3256     fd: fildes
3257 
3258 Force write of fd to disk without forcing update of metadata.
3259 [clinic start generated code]*/
3260 
3261 static PyObject *
os_fdatasync_impl(PyObject * module,int fd)3262 os_fdatasync_impl(PyObject *module, int fd)
3263 /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3264 {
3265     return posix_fildes_fd(fd, fdatasync);
3266 }
3267 #endif /* HAVE_FDATASYNC */
3268 
3269 
3270 #ifdef HAVE_CHOWN
3271 /*[clinic input]
3272 os.chown
3273 
3274     path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3275         Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3276 
3277     uid: uid_t
3278 
3279     gid: gid_t
3280 
3281     *
3282 
3283     dir_fd : dir_fd(requires='fchownat') = None
3284         If not None, it should be a file descriptor open to a directory,
3285         and path should be relative; path will then be relative to that
3286         directory.
3287 
3288     follow_symlinks: bool = True
3289         If False, and the last element of the path is a symbolic link,
3290         stat will examine the symbolic link itself instead of the file
3291         the link points to.
3292 
3293 Change the owner and group id of path to the numeric uid and gid.\
3294 
3295 path may always be specified as a string.
3296 On some platforms, path may also be specified as an open file descriptor.
3297   If this functionality is unavailable, using it raises an exception.
3298 If dir_fd is not None, it should be a file descriptor open to a directory,
3299   and path should be relative; path will then be relative to that directory.
3300 If follow_symlinks is False, and the last element of the path is a symbolic
3301   link, chown will modify the symbolic link itself instead of the file the
3302   link points to.
3303 It is an error to use dir_fd or follow_symlinks when specifying path as
3304   an open file descriptor.
3305 dir_fd and follow_symlinks may not be implemented on your platform.
3306   If they are unavailable, using them will raise a NotImplementedError.
3307 
3308 [clinic start generated code]*/
3309 
3310 static PyObject *
os_chown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid,int dir_fd,int follow_symlinks)3311 os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3312               int dir_fd, int follow_symlinks)
3313 /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3314 {
3315     int result;
3316 
3317 #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3318     if (follow_symlinks_specified("chown", follow_symlinks))
3319         return NULL;
3320 #endif
3321     if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3322         fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3323         return NULL;
3324 
3325 #ifdef __APPLE__
3326     /*
3327      * This is for Mac OS X 10.3, which doesn't have lchown.
3328      * (But we still have an lchown symbol because of weak-linking.)
3329      * It doesn't have fchownat either.  So there's no possibility
3330      * of a graceful failover.
3331      */
3332     if ((!follow_symlinks) && (lchown == NULL)) {
3333         follow_symlinks_specified("chown", follow_symlinks);
3334         return NULL;
3335     }
3336 #endif
3337 
3338     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3339                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3340         return NULL;
3341     }
3342 
3343     Py_BEGIN_ALLOW_THREADS
3344 #ifdef HAVE_FCHOWN
3345     if (path->fd != -1)
3346         result = fchown(path->fd, uid, gid);
3347     else
3348 #endif
3349 #ifdef HAVE_LCHOWN
3350     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3351         result = lchown(path->narrow, uid, gid);
3352     else
3353 #endif
3354 #ifdef HAVE_FCHOWNAT
3355     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
3356         result = fchownat(dir_fd, path->narrow, uid, gid,
3357                           follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3358     else
3359 #endif
3360         result = chown(path->narrow, uid, gid);
3361     Py_END_ALLOW_THREADS
3362 
3363     if (result)
3364         return path_error(path);
3365 
3366     Py_RETURN_NONE;
3367 }
3368 #endif /* HAVE_CHOWN */
3369 
3370 
3371 #ifdef HAVE_FCHOWN
3372 /*[clinic input]
3373 os.fchown
3374 
3375     fd: int
3376     uid: uid_t
3377     gid: gid_t
3378 
3379 Change the owner and group id of the file specified by file descriptor.
3380 
3381 Equivalent to os.chown(fd, uid, gid).
3382 
3383 [clinic start generated code]*/
3384 
3385 static PyObject *
os_fchown_impl(PyObject * module,int fd,uid_t uid,gid_t gid)3386 os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3387 /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3388 {
3389     int res;
3390     int async_err = 0;
3391 
3392     if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
3393         return NULL;
3394     }
3395 
3396     do {
3397         Py_BEGIN_ALLOW_THREADS
3398         res = fchown(fd, uid, gid);
3399         Py_END_ALLOW_THREADS
3400     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3401     if (res != 0)
3402         return (!async_err) ? posix_error() : NULL;
3403 
3404     Py_RETURN_NONE;
3405 }
3406 #endif /* HAVE_FCHOWN */
3407 
3408 
3409 #ifdef HAVE_LCHOWN
3410 /*[clinic input]
3411 os.lchown
3412 
3413     path : path_t
3414     uid: uid_t
3415     gid: gid_t
3416 
3417 Change the owner and group id of path to the numeric uid and gid.
3418 
3419 This function will not follow symbolic links.
3420 Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3421 [clinic start generated code]*/
3422 
3423 static PyObject *
os_lchown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid)3424 os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3425 /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3426 {
3427     int res;
3428     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
3429         return NULL;
3430     }
3431     Py_BEGIN_ALLOW_THREADS
3432     res = lchown(path->narrow, uid, gid);
3433     Py_END_ALLOW_THREADS
3434     if (res < 0) {
3435         return path_error(path);
3436     }
3437     Py_RETURN_NONE;
3438 }
3439 #endif /* HAVE_LCHOWN */
3440 
3441 
3442 static PyObject *
posix_getcwd(int use_bytes)3443 posix_getcwd(int use_bytes)
3444 {
3445 #ifdef MS_WINDOWS
3446     wchar_t wbuf[MAXPATHLEN];
3447     wchar_t *wbuf2 = wbuf;
3448     DWORD len;
3449 
3450     Py_BEGIN_ALLOW_THREADS
3451     len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3452     /* If the buffer is large enough, len does not include the
3453        terminating \0. If the buffer is too small, len includes
3454        the space needed for the terminator. */
3455     if (len >= Py_ARRAY_LENGTH(wbuf)) {
3456         if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3457             wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3458         }
3459         else {
3460             wbuf2 = NULL;
3461         }
3462         if (wbuf2) {
3463             len = GetCurrentDirectoryW(len, wbuf2);
3464         }
3465     }
3466     Py_END_ALLOW_THREADS
3467 
3468     if (!wbuf2) {
3469         PyErr_NoMemory();
3470         return NULL;
3471     }
3472     if (!len) {
3473         if (wbuf2 != wbuf)
3474             PyMem_RawFree(wbuf2);
3475         return PyErr_SetFromWindowsErr(0);
3476     }
3477 
3478     PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3479     if (wbuf2 != wbuf) {
3480         PyMem_RawFree(wbuf2);
3481     }
3482 
3483     if (use_bytes) {
3484         if (resobj == NULL) {
3485             return NULL;
3486         }
3487         Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3488     }
3489 
3490     return resobj;
3491 #else
3492     const size_t chunk = 1024;
3493 
3494     char *buf = NULL;
3495     char *cwd = NULL;
3496     size_t buflen = 0;
3497 
3498     Py_BEGIN_ALLOW_THREADS
3499     do {
3500         char *newbuf;
3501         if (buflen <= PY_SSIZE_T_MAX - chunk) {
3502             buflen += chunk;
3503             newbuf = PyMem_RawRealloc(buf, buflen);
3504         }
3505         else {
3506             newbuf = NULL;
3507         }
3508         if (newbuf == NULL) {
3509             PyMem_RawFree(buf);
3510             buf = NULL;
3511             break;
3512         }
3513         buf = newbuf;
3514 
3515         cwd = getcwd(buf, buflen);
3516     } while (cwd == NULL && errno == ERANGE);
3517     Py_END_ALLOW_THREADS
3518 
3519     if (buf == NULL) {
3520         return PyErr_NoMemory();
3521     }
3522     if (cwd == NULL) {
3523         PyMem_RawFree(buf);
3524         return posix_error();
3525     }
3526 
3527     PyObject *obj;
3528     if (use_bytes) {
3529         obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3530     }
3531     else {
3532         obj = PyUnicode_DecodeFSDefault(buf);
3533     }
3534     PyMem_RawFree(buf);
3535 
3536     return obj;
3537 #endif   /* !MS_WINDOWS */
3538 }
3539 
3540 
3541 /*[clinic input]
3542 os.getcwd
3543 
3544 Return a unicode string representing the current working directory.
3545 [clinic start generated code]*/
3546 
3547 static PyObject *
os_getcwd_impl(PyObject * module)3548 os_getcwd_impl(PyObject *module)
3549 /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3550 {
3551     return posix_getcwd(0);
3552 }
3553 
3554 
3555 /*[clinic input]
3556 os.getcwdb
3557 
3558 Return a bytes string representing the current working directory.
3559 [clinic start generated code]*/
3560 
3561 static PyObject *
os_getcwdb_impl(PyObject * module)3562 os_getcwdb_impl(PyObject *module)
3563 /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3564 {
3565     return posix_getcwd(1);
3566 }
3567 
3568 
3569 #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3570 #define HAVE_LINK 1
3571 #endif
3572 
3573 #ifdef HAVE_LINK
3574 /*[clinic input]
3575 
3576 os.link
3577 
3578     src : path_t
3579     dst : path_t
3580     *
3581     src_dir_fd : dir_fd = None
3582     dst_dir_fd : dir_fd = None
3583     follow_symlinks: bool = True
3584 
3585 Create a hard link to a file.
3586 
3587 If either src_dir_fd or dst_dir_fd is not None, it should be a file
3588   descriptor open to a directory, and the respective path string (src or dst)
3589   should be relative; the path will then be relative to that directory.
3590 If follow_symlinks is False, and the last element of src is a symbolic
3591   link, link will create a link to the symbolic link itself instead of the
3592   file the link points to.
3593 src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3594   platform.  If they are unavailable, using them will raise a
3595   NotImplementedError.
3596 [clinic start generated code]*/
3597 
3598 static PyObject *
os_link_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int follow_symlinks)3599 os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3600              int dst_dir_fd, int follow_symlinks)
3601 /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3602 {
3603 #ifdef MS_WINDOWS
3604     BOOL result = FALSE;
3605 #else
3606     int result;
3607 #endif
3608 
3609 #ifndef HAVE_LINKAT
3610     if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3611         argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3612         return NULL;
3613     }
3614 #endif
3615 
3616 #ifndef MS_WINDOWS
3617     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3618         PyErr_SetString(PyExc_NotImplementedError,
3619                         "link: src and dst must be the same type");
3620         return NULL;
3621     }
3622 #endif
3623 
3624     if (PySys_Audit("os.link", "OOii", src->object, dst->object,
3625                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
3626                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
3627         return NULL;
3628     }
3629 
3630 #ifdef MS_WINDOWS
3631     Py_BEGIN_ALLOW_THREADS
3632     result = CreateHardLinkW(dst->wide, src->wide, NULL);
3633     Py_END_ALLOW_THREADS
3634 
3635     if (!result)
3636         return path_error2(src, dst);
3637 #else
3638     Py_BEGIN_ALLOW_THREADS
3639 #ifdef HAVE_LINKAT
3640     if ((src_dir_fd != DEFAULT_DIR_FD) ||
3641         (dst_dir_fd != DEFAULT_DIR_FD) ||
3642         (!follow_symlinks))
3643         result = linkat(src_dir_fd, src->narrow,
3644             dst_dir_fd, dst->narrow,
3645             follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3646     else
3647 #endif /* HAVE_LINKAT */
3648         result = link(src->narrow, dst->narrow);
3649     Py_END_ALLOW_THREADS
3650 
3651     if (result)
3652         return path_error2(src, dst);
3653 #endif /* MS_WINDOWS */
3654 
3655     Py_RETURN_NONE;
3656 }
3657 #endif
3658 
3659 
3660 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3661 static PyObject *
_listdir_windows_no_opendir(path_t * path,PyObject * list)3662 _listdir_windows_no_opendir(path_t *path, PyObject *list)
3663 {
3664     PyObject *v;
3665     HANDLE hFindFile = INVALID_HANDLE_VALUE;
3666     BOOL result;
3667     wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
3668     /* only claim to have space for MAX_PATH */
3669     Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
3670     wchar_t *wnamebuf = NULL;
3671 
3672     WIN32_FIND_DATAW wFileData;
3673     const wchar_t *po_wchars;
3674 
3675     if (!path->wide) { /* Default arg: "." */
3676         po_wchars = L".";
3677         len = 1;
3678     } else {
3679         po_wchars = path->wide;
3680         len = wcslen(path->wide);
3681     }
3682     /* The +5 is so we can append "\\*.*\0" */
3683     wnamebuf = PyMem_New(wchar_t, len + 5);
3684     if (!wnamebuf) {
3685         PyErr_NoMemory();
3686         goto exit;
3687     }
3688     wcscpy(wnamebuf, po_wchars);
3689     if (len > 0) {
3690         wchar_t wch = wnamebuf[len-1];
3691         if (wch != SEP && wch != ALTSEP && wch != L':')
3692             wnamebuf[len++] = SEP;
3693         wcscpy(wnamebuf + len, L"*.*");
3694     }
3695     if ((list = PyList_New(0)) == NULL) {
3696         goto exit;
3697     }
3698     Py_BEGIN_ALLOW_THREADS
3699     hFindFile = FindFirstFileW(wnamebuf, &wFileData);
3700     Py_END_ALLOW_THREADS
3701     if (hFindFile == INVALID_HANDLE_VALUE) {
3702         int error = GetLastError();
3703         if (error == ERROR_FILE_NOT_FOUND)
3704             goto exit;
3705         Py_DECREF(list);
3706         list = path_error(path);
3707         goto exit;
3708     }
3709     do {
3710         /* Skip over . and .. */
3711         if (wcscmp(wFileData.cFileName, L".") != 0 &&
3712             wcscmp(wFileData.cFileName, L"..") != 0) {
3713             v = PyUnicode_FromWideChar(wFileData.cFileName,
3714                                        wcslen(wFileData.cFileName));
3715             if (path->narrow && v) {
3716                 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
3717             }
3718             if (v == NULL) {
3719                 Py_DECREF(list);
3720                 list = NULL;
3721                 break;
3722             }
3723             if (PyList_Append(list, v) != 0) {
3724                 Py_DECREF(v);
3725                 Py_DECREF(list);
3726                 list = NULL;
3727                 break;
3728             }
3729             Py_DECREF(v);
3730         }
3731         Py_BEGIN_ALLOW_THREADS
3732         result = FindNextFileW(hFindFile, &wFileData);
3733         Py_END_ALLOW_THREADS
3734         /* FindNextFile sets error to ERROR_NO_MORE_FILES if
3735            it got to the end of the directory. */
3736         if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
3737             Py_DECREF(list);
3738             list = path_error(path);
3739             goto exit;
3740         }
3741     } while (result == TRUE);
3742 
3743 exit:
3744     if (hFindFile != INVALID_HANDLE_VALUE) {
3745         if (FindClose(hFindFile) == FALSE) {
3746             if (list != NULL) {
3747                 Py_DECREF(list);
3748                 list = path_error(path);
3749             }
3750         }
3751     }
3752     PyMem_Free(wnamebuf);
3753 
3754     return list;
3755 }  /* end of _listdir_windows_no_opendir */
3756 
3757 #else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
3758 
3759 static PyObject *
_posix_listdir(path_t * path,PyObject * list)3760 _posix_listdir(path_t *path, PyObject *list)
3761 {
3762     PyObject *v;
3763     DIR *dirp = NULL;
3764     struct dirent *ep;
3765     int return_str; /* if false, return bytes */
3766 #ifdef HAVE_FDOPENDIR
3767     int fd = -1;
3768 #endif
3769 
3770     errno = 0;
3771 #ifdef HAVE_FDOPENDIR
3772     if (path->fd != -1) {
3773         /* closedir() closes the FD, so we duplicate it */
3774         fd = _Py_dup(path->fd);
3775         if (fd == -1)
3776             return NULL;
3777 
3778         return_str = 1;
3779 
3780         Py_BEGIN_ALLOW_THREADS
3781         dirp = fdopendir(fd);
3782         Py_END_ALLOW_THREADS
3783     }
3784     else
3785 #endif
3786     {
3787         const char *name;
3788         if (path->narrow) {
3789             name = path->narrow;
3790             /* only return bytes if they specified a bytes-like object */
3791             return_str = !PyObject_CheckBuffer(path->object);
3792         }
3793         else {
3794             name = ".";
3795             return_str = 1;
3796         }
3797 
3798         Py_BEGIN_ALLOW_THREADS
3799         dirp = opendir(name);
3800         Py_END_ALLOW_THREADS
3801     }
3802 
3803     if (dirp == NULL) {
3804         list = path_error(path);
3805 #ifdef HAVE_FDOPENDIR
3806         if (fd != -1) {
3807             Py_BEGIN_ALLOW_THREADS
3808             close(fd);
3809             Py_END_ALLOW_THREADS
3810         }
3811 #endif
3812         goto exit;
3813     }
3814     if ((list = PyList_New(0)) == NULL) {
3815         goto exit;
3816     }
3817     for (;;) {
3818         errno = 0;
3819         Py_BEGIN_ALLOW_THREADS
3820         ep = readdir(dirp);
3821         Py_END_ALLOW_THREADS
3822         if (ep == NULL) {
3823             if (errno == 0) {
3824                 break;
3825             } else {
3826                 Py_DECREF(list);
3827                 list = path_error(path);
3828                 goto exit;
3829             }
3830         }
3831         if (ep->d_name[0] == '.' &&
3832             (NAMLEN(ep) == 1 ||
3833              (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
3834             continue;
3835         if (return_str)
3836             v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
3837         else
3838             v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
3839         if (v == NULL) {
3840             Py_CLEAR(list);
3841             break;
3842         }
3843         if (PyList_Append(list, v) != 0) {
3844             Py_DECREF(v);
3845             Py_CLEAR(list);
3846             break;
3847         }
3848         Py_DECREF(v);
3849     }
3850 
3851 exit:
3852     if (dirp != NULL) {
3853         Py_BEGIN_ALLOW_THREADS
3854 #ifdef HAVE_FDOPENDIR
3855         if (fd > -1)
3856             rewinddir(dirp);
3857 #endif
3858         closedir(dirp);
3859         Py_END_ALLOW_THREADS
3860     }
3861 
3862     return list;
3863 }  /* end of _posix_listdir */
3864 #endif  /* which OS */
3865 
3866 
3867 /*[clinic input]
3868 os.listdir
3869 
3870     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
3871 
3872 Return a list containing the names of the files in the directory.
3873 
3874 path can be specified as either str, bytes, or a path-like object.  If path is bytes,
3875   the filenames returned will also be bytes; in all other circumstances
3876   the filenames returned will be str.
3877 If path is None, uses the path='.'.
3878 On some platforms, path may also be specified as an open file descriptor;\
3879   the file descriptor must refer to a directory.
3880   If this functionality is unavailable, using it raises NotImplementedError.
3881 
3882 The list is in arbitrary order.  It does not include the special
3883 entries '.' and '..' even if they are present in the directory.
3884 
3885 
3886 [clinic start generated code]*/
3887 
3888 static PyObject *
os_listdir_impl(PyObject * module,path_t * path)3889 os_listdir_impl(PyObject *module, path_t *path)
3890 /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
3891 {
3892     if (PySys_Audit("os.listdir", "O",
3893                     path->object ? path->object : Py_None) < 0) {
3894         return NULL;
3895     }
3896 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3897     return _listdir_windows_no_opendir(path, NULL);
3898 #else
3899     return _posix_listdir(path, NULL);
3900 #endif
3901 }
3902 
3903 #ifdef MS_WINDOWS
3904 /* A helper function for abspath on win32 */
3905 /*[clinic input]
3906 os._getfullpathname
3907 
3908     path: path_t
3909     /
3910 
3911 [clinic start generated code]*/
3912 
3913 static PyObject *
os__getfullpathname_impl(PyObject * module,path_t * path)3914 os__getfullpathname_impl(PyObject *module, path_t *path)
3915 /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
3916 {
3917     wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
3918     wchar_t *wtemp;
3919     DWORD result;
3920     PyObject *v;
3921 
3922     result = GetFullPathNameW(path->wide,
3923                               Py_ARRAY_LENGTH(woutbuf),
3924                               woutbuf, &wtemp);
3925     if (result > Py_ARRAY_LENGTH(woutbuf)) {
3926         woutbufp = PyMem_New(wchar_t, result);
3927         if (!woutbufp)
3928             return PyErr_NoMemory();
3929         result = GetFullPathNameW(path->wide, result, woutbufp, &wtemp);
3930     }
3931     if (result) {
3932         v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp));
3933         if (path->narrow)
3934             Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
3935     } else
3936         v = win32_error_object("GetFullPathNameW", path->object);
3937     if (woutbufp != woutbuf)
3938         PyMem_Free(woutbufp);
3939     return v;
3940 }
3941 
3942 
3943 /*[clinic input]
3944 os._getfinalpathname
3945 
3946     path: path_t
3947     /
3948 
3949 A helper function for samepath on windows.
3950 [clinic start generated code]*/
3951 
3952 static PyObject *
os__getfinalpathname_impl(PyObject * module,path_t * path)3953 os__getfinalpathname_impl(PyObject *module, path_t *path)
3954 /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
3955 {
3956     HANDLE hFile;
3957     wchar_t buf[MAXPATHLEN], *target_path = buf;
3958     int buf_size = Py_ARRAY_LENGTH(buf);
3959     int result_length;
3960     PyObject *result;
3961 
3962     Py_BEGIN_ALLOW_THREADS
3963     hFile = CreateFileW(
3964         path->wide,
3965         0, /* desired access */
3966         0, /* share mode */
3967         NULL, /* security attributes */
3968         OPEN_EXISTING,
3969         /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
3970         FILE_FLAG_BACKUP_SEMANTICS,
3971         NULL);
3972     Py_END_ALLOW_THREADS
3973 
3974     if (hFile == INVALID_HANDLE_VALUE) {
3975         return win32_error_object("CreateFileW", path->object);
3976     }
3977 
3978     /* We have a good handle to the target, use it to determine the
3979        target path name. */
3980     while (1) {
3981         Py_BEGIN_ALLOW_THREADS
3982         result_length = GetFinalPathNameByHandleW(hFile, target_path,
3983                                                   buf_size, VOLUME_NAME_DOS);
3984         Py_END_ALLOW_THREADS
3985 
3986         if (!result_length) {
3987             result = win32_error_object("GetFinalPathNameByHandleW",
3988                                          path->object);
3989             goto cleanup;
3990         }
3991 
3992         if (result_length < buf_size) {
3993             break;
3994         }
3995 
3996         wchar_t *tmp;
3997         tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
3998                             result_length * sizeof(*tmp));
3999         if (!tmp) {
4000             result = PyErr_NoMemory();
4001             goto cleanup;
4002         }
4003 
4004         buf_size = result_length;
4005         target_path = tmp;
4006     }
4007 
4008     result = PyUnicode_FromWideChar(target_path, result_length);
4009     if (result && path->narrow) {
4010         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4011     }
4012 
4013 cleanup:
4014     if (target_path != buf) {
4015         PyMem_Free(target_path);
4016     }
4017     CloseHandle(hFile);
4018     return result;
4019 }
4020 
4021 
4022 /*[clinic input]
4023 os._getvolumepathname
4024 
4025     path: path_t
4026 
4027 A helper function for ismount on Win32.
4028 [clinic start generated code]*/
4029 
4030 static PyObject *
os__getvolumepathname_impl(PyObject * module,path_t * path)4031 os__getvolumepathname_impl(PyObject *module, path_t *path)
4032 /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
4033 {
4034     PyObject *result;
4035     wchar_t *mountpath=NULL;
4036     size_t buflen;
4037     BOOL ret;
4038 
4039     /* Volume path should be shorter than entire path */
4040     buflen = Py_MAX(path->length, MAX_PATH);
4041 
4042     if (buflen > PY_DWORD_MAX) {
4043         PyErr_SetString(PyExc_OverflowError, "path too long");
4044         return NULL;
4045     }
4046 
4047     mountpath = PyMem_New(wchar_t, buflen);
4048     if (mountpath == NULL)
4049         return PyErr_NoMemory();
4050 
4051     Py_BEGIN_ALLOW_THREADS
4052     ret = GetVolumePathNameW(path->wide, mountpath,
4053                              Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
4054     Py_END_ALLOW_THREADS
4055 
4056     if (!ret) {
4057         result = win32_error_object("_getvolumepathname", path->object);
4058         goto exit;
4059     }
4060     result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
4061     if (path->narrow)
4062         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4063 
4064 exit:
4065     PyMem_Free(mountpath);
4066     return result;
4067 }
4068 
4069 
4070 /*[clinic input]
4071 os._path_splitroot
4072 
4073     path: path_t
4074 
4075 Removes everything after the root on Win32.
4076 [clinic start generated code]*/
4077 
4078 static PyObject *
os__path_splitroot_impl(PyObject * module,path_t * path)4079 os__path_splitroot_impl(PyObject *module, path_t *path)
4080 /*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/
4081 {
4082     wchar_t *buffer;
4083     wchar_t *end;
4084     PyObject *result = NULL;
4085 
4086     buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
4087     if (!buffer) {
4088         return NULL;
4089     }
4090     wcscpy(buffer, path->wide);
4091     for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
4092         *p = L'\\';
4093     }
4094 
4095     Py_BEGIN_ALLOW_THREADS
4096     if (buffer[0] && buffer[1] == L':') {
4097         if (buffer[2] == L'\\') {
4098             end = &buffer[3];
4099         } else {
4100             end = &buffer[2];
4101         }
4102     } else {
4103         end = PathSkipRootW(buffer);
4104     }
4105     Py_END_ALLOW_THREADS
4106     if (!end || end == buffer) {
4107         result = Py_BuildValue("sO", "", path->object);
4108     } else if (!*end) {
4109         result = Py_BuildValue("Os", path->object, "");
4110     } else {
4111         size_t rootLen = (size_t)(end - buffer);
4112         result = Py_BuildValue("NN",
4113             PyUnicode_FromWideChar(path->wide, rootLen),
4114             PyUnicode_FromWideChar(path->wide + rootLen, -1)
4115         );
4116     }
4117     PyMem_Free(buffer);
4118 
4119     return result;
4120 }
4121 
4122 
4123 #endif /* MS_WINDOWS */
4124 
4125 
4126 /*[clinic input]
4127 os.mkdir
4128 
4129     path : path_t
4130 
4131     mode: int = 0o777
4132 
4133     *
4134 
4135     dir_fd : dir_fd(requires='mkdirat') = None
4136 
4137 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4138 
4139 Create a directory.
4140 
4141 If dir_fd is not None, it should be a file descriptor open to a directory,
4142   and path should be relative; path will then be relative to that directory.
4143 dir_fd may not be implemented on your platform.
4144   If it is unavailable, using it will raise a NotImplementedError.
4145 
4146 The mode argument is ignored on Windows.
4147 [clinic start generated code]*/
4148 
4149 static PyObject *
os_mkdir_impl(PyObject * module,path_t * path,int mode,int dir_fd)4150 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4151 /*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/
4152 {
4153     int result;
4154 
4155     if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4156                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4157         return NULL;
4158     }
4159 
4160 #ifdef MS_WINDOWS
4161     Py_BEGIN_ALLOW_THREADS
4162     result = CreateDirectoryW(path->wide, NULL);
4163     Py_END_ALLOW_THREADS
4164 
4165     if (!result)
4166         return path_error(path);
4167 #else
4168     Py_BEGIN_ALLOW_THREADS
4169 #if HAVE_MKDIRAT
4170     if (dir_fd != DEFAULT_DIR_FD)
4171         result = mkdirat(dir_fd, path->narrow, mode);
4172     else
4173 #endif
4174 #if defined(__WATCOMC__) && !defined(__QNX__)
4175         result = mkdir(path->narrow);
4176 #else
4177         result = mkdir(path->narrow, mode);
4178 #endif
4179     Py_END_ALLOW_THREADS
4180     if (result < 0)
4181         return path_error(path);
4182 #endif /* MS_WINDOWS */
4183     Py_RETURN_NONE;
4184 }
4185 
4186 
4187 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4188 #if defined(HAVE_SYS_RESOURCE_H)
4189 #include <sys/resource.h>
4190 #endif
4191 
4192 
4193 #ifdef HAVE_NICE
4194 /*[clinic input]
4195 os.nice
4196 
4197     increment: int
4198     /
4199 
4200 Add increment to the priority of process and return the new priority.
4201 [clinic start generated code]*/
4202 
4203 static PyObject *
os_nice_impl(PyObject * module,int increment)4204 os_nice_impl(PyObject *module, int increment)
4205 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4206 {
4207     int value;
4208 
4209     /* There are two flavours of 'nice': one that returns the new
4210        priority (as required by almost all standards out there) and the
4211        Linux/FreeBSD one, which returns '0' on success and advices
4212        the use of getpriority() to get the new priority.
4213 
4214        If we are of the nice family that returns the new priority, we
4215        need to clear errno before the call, and check if errno is filled
4216        before calling posix_error() on a returnvalue of -1, because the
4217        -1 may be the actual new priority! */
4218 
4219     errno = 0;
4220     value = nice(increment);
4221 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4222     if (value == 0)
4223         value = getpriority(PRIO_PROCESS, 0);
4224 #endif
4225     if (value == -1 && errno != 0)
4226         /* either nice() or getpriority() returned an error */
4227         return posix_error();
4228     return PyLong_FromLong((long) value);
4229 }
4230 #endif /* HAVE_NICE */
4231 
4232 
4233 #ifdef HAVE_GETPRIORITY
4234 /*[clinic input]
4235 os.getpriority
4236 
4237     which: int
4238     who: int
4239 
4240 Return program scheduling priority.
4241 [clinic start generated code]*/
4242 
4243 static PyObject *
os_getpriority_impl(PyObject * module,int which,int who)4244 os_getpriority_impl(PyObject *module, int which, int who)
4245 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4246 {
4247     int retval;
4248 
4249     errno = 0;
4250     retval = getpriority(which, who);
4251     if (errno != 0)
4252         return posix_error();
4253     return PyLong_FromLong((long)retval);
4254 }
4255 #endif /* HAVE_GETPRIORITY */
4256 
4257 
4258 #ifdef HAVE_SETPRIORITY
4259 /*[clinic input]
4260 os.setpriority
4261 
4262     which: int
4263     who: int
4264     priority: int
4265 
4266 Set program scheduling priority.
4267 [clinic start generated code]*/
4268 
4269 static PyObject *
os_setpriority_impl(PyObject * module,int which,int who,int priority)4270 os_setpriority_impl(PyObject *module, int which, int who, int priority)
4271 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4272 {
4273     int retval;
4274 
4275     retval = setpriority(which, who, priority);
4276     if (retval == -1)
4277         return posix_error();
4278     Py_RETURN_NONE;
4279 }
4280 #endif /* HAVE_SETPRIORITY */
4281 
4282 
4283 static PyObject *
internal_rename(path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int is_replace)4284 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4285 {
4286     const char *function_name = is_replace ? "replace" : "rename";
4287     int dir_fd_specified;
4288 
4289 #ifdef MS_WINDOWS
4290     BOOL result;
4291     int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4292 #else
4293     int result;
4294 #endif
4295 
4296     dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4297                        (dst_dir_fd != DEFAULT_DIR_FD);
4298 #ifndef HAVE_RENAMEAT
4299     if (dir_fd_specified) {
4300         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4301         return NULL;
4302     }
4303 #endif
4304 
4305     if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
4306                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4307                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4308         return NULL;
4309     }
4310 
4311 #ifdef MS_WINDOWS
4312     Py_BEGIN_ALLOW_THREADS
4313     result = MoveFileExW(src->wide, dst->wide, flags);
4314     Py_END_ALLOW_THREADS
4315 
4316     if (!result)
4317         return path_error2(src, dst);
4318 
4319 #else
4320     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4321         PyErr_Format(PyExc_ValueError,
4322                      "%s: src and dst must be the same type", function_name);
4323         return NULL;
4324     }
4325 
4326     Py_BEGIN_ALLOW_THREADS
4327 #ifdef HAVE_RENAMEAT
4328     if (dir_fd_specified)
4329         result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4330     else
4331 #endif
4332     result = rename(src->narrow, dst->narrow);
4333     Py_END_ALLOW_THREADS
4334 
4335     if (result)
4336         return path_error2(src, dst);
4337 #endif
4338     Py_RETURN_NONE;
4339 }
4340 
4341 
4342 /*[clinic input]
4343 os.rename
4344 
4345     src : path_t
4346     dst : path_t
4347     *
4348     src_dir_fd : dir_fd = None
4349     dst_dir_fd : dir_fd = None
4350 
4351 Rename a file or directory.
4352 
4353 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4354   descriptor open to a directory, and the respective path string (src or dst)
4355   should be relative; the path will then be relative to that directory.
4356 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4357   If they are unavailable, using them will raise a NotImplementedError.
4358 [clinic start generated code]*/
4359 
4360 static PyObject *
os_rename_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4361 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4362                int dst_dir_fd)
4363 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4364 {
4365     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4366 }
4367 
4368 
4369 /*[clinic input]
4370 os.replace = os.rename
4371 
4372 Rename a file or directory, overwriting the destination.
4373 
4374 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4375   descriptor open to a directory, and the respective path string (src or dst)
4376   should be relative; the path will then be relative to that directory.
4377 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4378   If they are unavailable, using them will raise a NotImplementedError.
4379 [clinic start generated code]*/
4380 
4381 static PyObject *
os_replace_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4382 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4383                 int dst_dir_fd)
4384 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4385 {
4386     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4387 }
4388 
4389 
4390 /*[clinic input]
4391 os.rmdir
4392 
4393     path: path_t
4394     *
4395     dir_fd: dir_fd(requires='unlinkat') = None
4396 
4397 Remove a directory.
4398 
4399 If dir_fd is not None, it should be a file descriptor open to a directory,
4400   and path should be relative; path will then be relative to that directory.
4401 dir_fd may not be implemented on your platform.
4402   If it is unavailable, using it will raise a NotImplementedError.
4403 [clinic start generated code]*/
4404 
4405 static PyObject *
os_rmdir_impl(PyObject * module,path_t * path,int dir_fd)4406 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4407 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4408 {
4409     int result;
4410 
4411     if (PySys_Audit("os.rmdir", "Oi", path->object,
4412                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4413         return NULL;
4414     }
4415 
4416     Py_BEGIN_ALLOW_THREADS
4417 #ifdef MS_WINDOWS
4418     /* Windows, success=1, UNIX, success=0 */
4419     result = !RemoveDirectoryW(path->wide);
4420 #else
4421 #ifdef HAVE_UNLINKAT
4422     if (dir_fd != DEFAULT_DIR_FD)
4423         result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4424     else
4425 #endif
4426         result = rmdir(path->narrow);
4427 #endif
4428     Py_END_ALLOW_THREADS
4429 
4430     if (result)
4431         return path_error(path);
4432 
4433     Py_RETURN_NONE;
4434 }
4435 
4436 
4437 #ifdef HAVE_SYSTEM
4438 #ifdef MS_WINDOWS
4439 /*[clinic input]
4440 os.system -> long
4441 
4442     command: Py_UNICODE
4443 
4444 Execute the command in a subshell.
4445 [clinic start generated code]*/
4446 
4447 static long
os_system_impl(PyObject * module,const Py_UNICODE * command)4448 os_system_impl(PyObject *module, const Py_UNICODE *command)
4449 /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4450 {
4451     long result;
4452 
4453     if (PySys_Audit("os.system", "(u)", command) < 0) {
4454         return -1;
4455     }
4456 
4457     Py_BEGIN_ALLOW_THREADS
4458     _Py_BEGIN_SUPPRESS_IPH
4459     result = _wsystem(command);
4460     _Py_END_SUPPRESS_IPH
4461     Py_END_ALLOW_THREADS
4462     return result;
4463 }
4464 #else /* MS_WINDOWS */
4465 /*[clinic input]
4466 os.system -> long
4467 
4468     command: FSConverter
4469 
4470 Execute the command in a subshell.
4471 [clinic start generated code]*/
4472 
4473 static long
os_system_impl(PyObject * module,PyObject * command)4474 os_system_impl(PyObject *module, PyObject *command)
4475 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4476 {
4477     long result;
4478     const char *bytes = PyBytes_AsString(command);
4479 
4480     if (PySys_Audit("os.system", "(O)", command) < 0) {
4481         return -1;
4482     }
4483 
4484     Py_BEGIN_ALLOW_THREADS
4485     result = system(bytes);
4486     Py_END_ALLOW_THREADS
4487     return result;
4488 }
4489 #endif
4490 #endif /* HAVE_SYSTEM */
4491 
4492 
4493 /*[clinic input]
4494 os.umask
4495 
4496     mask: int
4497     /
4498 
4499 Set the current numeric umask and return the previous umask.
4500 [clinic start generated code]*/
4501 
4502 static PyObject *
os_umask_impl(PyObject * module,int mask)4503 os_umask_impl(PyObject *module, int mask)
4504 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4505 {
4506     int i = (int)umask(mask);
4507     if (i < 0)
4508         return posix_error();
4509     return PyLong_FromLong((long)i);
4510 }
4511 
4512 #ifdef MS_WINDOWS
4513 
4514 /* override the default DeleteFileW behavior so that directory
4515 symlinks can be removed with this function, the same as with
4516 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)4517 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
4518 {
4519     WIN32_FILE_ATTRIBUTE_DATA info;
4520     WIN32_FIND_DATAW find_data;
4521     HANDLE find_data_handle;
4522     int is_directory = 0;
4523     int is_link = 0;
4524 
4525     if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
4526         is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4527 
4528         /* Get WIN32_FIND_DATA structure for the path to determine if
4529            it is a symlink */
4530         if(is_directory &&
4531            info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
4532             find_data_handle = FindFirstFileW(lpFileName, &find_data);
4533 
4534             if(find_data_handle != INVALID_HANDLE_VALUE) {
4535                 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
4536                    IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
4537                 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
4538                           find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
4539                 FindClose(find_data_handle);
4540             }
4541         }
4542     }
4543 
4544     if (is_directory && is_link)
4545         return RemoveDirectoryW(lpFileName);
4546 
4547     return DeleteFileW(lpFileName);
4548 }
4549 #endif /* MS_WINDOWS */
4550 
4551 
4552 /*[clinic input]
4553 os.unlink
4554 
4555     path: path_t
4556     *
4557     dir_fd: dir_fd(requires='unlinkat')=None
4558 
4559 Remove a file (same as remove()).
4560 
4561 If dir_fd is not None, it should be a file descriptor open to a directory,
4562   and path should be relative; path will then be relative to that directory.
4563 dir_fd may not be implemented on your platform.
4564   If it is unavailable, using it will raise a NotImplementedError.
4565 
4566 [clinic start generated code]*/
4567 
4568 static PyObject *
os_unlink_impl(PyObject * module,path_t * path,int dir_fd)4569 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
4570 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
4571 {
4572     int result;
4573 
4574     if (PySys_Audit("os.remove", "Oi", path->object,
4575                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4576         return NULL;
4577     }
4578 
4579     Py_BEGIN_ALLOW_THREADS
4580     _Py_BEGIN_SUPPRESS_IPH
4581 #ifdef MS_WINDOWS
4582     /* Windows, success=1, UNIX, success=0 */
4583     result = !Py_DeleteFileW(path->wide);
4584 #else
4585 #ifdef HAVE_UNLINKAT
4586     if (dir_fd != DEFAULT_DIR_FD)
4587         result = unlinkat(dir_fd, path->narrow, 0);
4588     else
4589 #endif /* HAVE_UNLINKAT */
4590         result = unlink(path->narrow);
4591 #endif
4592     _Py_END_SUPPRESS_IPH
4593     Py_END_ALLOW_THREADS
4594 
4595     if (result)
4596         return path_error(path);
4597 
4598     Py_RETURN_NONE;
4599 }
4600 
4601 
4602 /*[clinic input]
4603 os.remove = os.unlink
4604 
4605 Remove a file (same as unlink()).
4606 
4607 If dir_fd is not None, it should be a file descriptor open to a directory,
4608   and path should be relative; path will then be relative to that directory.
4609 dir_fd may not be implemented on your platform.
4610   If it is unavailable, using it will raise a NotImplementedError.
4611 [clinic start generated code]*/
4612 
4613 static PyObject *
os_remove_impl(PyObject * module,path_t * path,int dir_fd)4614 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
4615 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
4616 {
4617     return os_unlink_impl(module, path, dir_fd);
4618 }
4619 
4620 
4621 static PyStructSequence_Field uname_result_fields[] = {
4622     {"sysname",    "operating system name"},
4623     {"nodename",   "name of machine on network (implementation-defined)"},
4624     {"release",    "operating system release"},
4625     {"version",    "operating system version"},
4626     {"machine",    "hardware identifier"},
4627     {NULL}
4628 };
4629 
4630 PyDoc_STRVAR(uname_result__doc__,
4631 "uname_result: Result from os.uname().\n\n\
4632 This object may be accessed either as a tuple of\n\
4633   (sysname, nodename, release, version, machine),\n\
4634 or via the attributes sysname, nodename, release, version, and machine.\n\
4635 \n\
4636 See os.uname for more information.");
4637 
4638 static PyStructSequence_Desc uname_result_desc = {
4639     "uname_result", /* name */
4640     uname_result__doc__, /* doc */
4641     uname_result_fields,
4642     5
4643 };
4644 
4645 static PyTypeObject* UnameResultType;
4646 
4647 
4648 #ifdef HAVE_UNAME
4649 /*[clinic input]
4650 os.uname
4651 
4652 Return an object identifying the current operating system.
4653 
4654 The object behaves like a named tuple with the following fields:
4655   (sysname, nodename, release, version, machine)
4656 
4657 [clinic start generated code]*/
4658 
4659 static PyObject *
os_uname_impl(PyObject * module)4660 os_uname_impl(PyObject *module)
4661 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
4662 {
4663     struct utsname u;
4664     int res;
4665     PyObject *value;
4666 
4667     Py_BEGIN_ALLOW_THREADS
4668     res = uname(&u);
4669     Py_END_ALLOW_THREADS
4670     if (res < 0)
4671         return posix_error();
4672 
4673     value = PyStructSequence_New(UnameResultType);
4674     if (value == NULL)
4675         return NULL;
4676 
4677 #define SET(i, field) \
4678     { \
4679     PyObject *o = PyUnicode_DecodeFSDefault(field); \
4680     if (!o) { \
4681         Py_DECREF(value); \
4682         return NULL; \
4683     } \
4684     PyStructSequence_SET_ITEM(value, i, o); \
4685     } \
4686 
4687     SET(0, u.sysname);
4688     SET(1, u.nodename);
4689     SET(2, u.release);
4690     SET(3, u.version);
4691     SET(4, u.machine);
4692 
4693 #undef SET
4694 
4695     return value;
4696 }
4697 #endif /* HAVE_UNAME */
4698 
4699 
4700 
4701 typedef struct {
4702     int    now;
4703     time_t atime_s;
4704     long   atime_ns;
4705     time_t mtime_s;
4706     long   mtime_ns;
4707 } utime_t;
4708 
4709 /*
4710  * these macros assume that "ut" is a pointer to a utime_t
4711  * they also intentionally leak the declaration of a pointer named "time"
4712  */
4713 #define UTIME_TO_TIMESPEC \
4714     struct timespec ts[2]; \
4715     struct timespec *time; \
4716     if (ut->now) \
4717         time = NULL; \
4718     else { \
4719         ts[0].tv_sec = ut->atime_s; \
4720         ts[0].tv_nsec = ut->atime_ns; \
4721         ts[1].tv_sec = ut->mtime_s; \
4722         ts[1].tv_nsec = ut->mtime_ns; \
4723         time = ts; \
4724     } \
4725 
4726 #define UTIME_TO_TIMEVAL \
4727     struct timeval tv[2]; \
4728     struct timeval *time; \
4729     if (ut->now) \
4730         time = NULL; \
4731     else { \
4732         tv[0].tv_sec = ut->atime_s; \
4733         tv[0].tv_usec = ut->atime_ns / 1000; \
4734         tv[1].tv_sec = ut->mtime_s; \
4735         tv[1].tv_usec = ut->mtime_ns / 1000; \
4736         time = tv; \
4737     } \
4738 
4739 #define UTIME_TO_UTIMBUF \
4740     struct utimbuf u; \
4741     struct utimbuf *time; \
4742     if (ut->now) \
4743         time = NULL; \
4744     else { \
4745         u.actime = ut->atime_s; \
4746         u.modtime = ut->mtime_s; \
4747         time = &u; \
4748     }
4749 
4750 #define UTIME_TO_TIME_T \
4751     time_t timet[2]; \
4752     time_t *time; \
4753     if (ut->now) \
4754         time = NULL; \
4755     else { \
4756         timet[0] = ut->atime_s; \
4757         timet[1] = ut->mtime_s; \
4758         time = timet; \
4759     } \
4760 
4761 
4762 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
4763 
4764 static int
utime_dir_fd(utime_t * ut,int dir_fd,const char * path,int follow_symlinks)4765 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
4766 {
4767 #ifdef HAVE_UTIMENSAT
4768     int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
4769     UTIME_TO_TIMESPEC;
4770     return utimensat(dir_fd, path, time, flags);
4771 #elif defined(HAVE_FUTIMESAT)
4772     UTIME_TO_TIMEVAL;
4773     /*
4774      * follow_symlinks will never be false here;
4775      * we only allow !follow_symlinks and dir_fd together
4776      * if we have utimensat()
4777      */
4778     assert(follow_symlinks);
4779     return futimesat(dir_fd, path, time);
4780 #endif
4781 }
4782 
4783     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
4784 #else
4785     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
4786 #endif
4787 
4788 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
4789 
4790 static int
utime_fd(utime_t * ut,int fd)4791 utime_fd(utime_t *ut, int fd)
4792 {
4793 #ifdef HAVE_FUTIMENS
4794     UTIME_TO_TIMESPEC;
4795     return futimens(fd, time);
4796 #else
4797     UTIME_TO_TIMEVAL;
4798     return futimes(fd, time);
4799 #endif
4800 }
4801 
4802     #define PATH_UTIME_HAVE_FD 1
4803 #else
4804     #define PATH_UTIME_HAVE_FD 0
4805 #endif
4806 
4807 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
4808 #  define UTIME_HAVE_NOFOLLOW_SYMLINKS
4809 #endif
4810 
4811 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
4812 
4813 static int
utime_nofollow_symlinks(utime_t * ut,const char * path)4814 utime_nofollow_symlinks(utime_t *ut, const char *path)
4815 {
4816 #ifdef HAVE_UTIMENSAT
4817     UTIME_TO_TIMESPEC;
4818     return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
4819 #else
4820     UTIME_TO_TIMEVAL;
4821     return lutimes(path, time);
4822 #endif
4823 }
4824 
4825 #endif
4826 
4827 #ifndef MS_WINDOWS
4828 
4829 static int
utime_default(utime_t * ut,const char * path)4830 utime_default(utime_t *ut, const char *path)
4831 {
4832 #ifdef HAVE_UTIMENSAT
4833     UTIME_TO_TIMESPEC;
4834     return utimensat(DEFAULT_DIR_FD, path, time, 0);
4835 #elif defined(HAVE_UTIMES)
4836     UTIME_TO_TIMEVAL;
4837     return utimes(path, time);
4838 #elif defined(HAVE_UTIME_H)
4839     UTIME_TO_UTIMBUF;
4840     return utime(path, time);
4841 #else
4842     UTIME_TO_TIME_T;
4843     return utime(path, time);
4844 #endif
4845 }
4846 
4847 #endif
4848 
4849 static int
split_py_long_to_s_and_ns(PyObject * py_long,time_t * s,long * ns)4850 split_py_long_to_s_and_ns(PyObject *py_long, time_t *s, long *ns)
4851 {
4852     int result = 0;
4853     PyObject *divmod;
4854     divmod = PyNumber_Divmod(py_long, billion);
4855     if (!divmod)
4856         goto exit;
4857     if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
4858         PyErr_Format(PyExc_TypeError,
4859                      "%.200s.__divmod__() must return a 2-tuple, not %.200s",
4860                      Py_TYPE(py_long)->tp_name, Py_TYPE(divmod)->tp_name);
4861         goto exit;
4862     }
4863     *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
4864     if ((*s == -1) && PyErr_Occurred())
4865         goto exit;
4866     *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
4867     if ((*ns == -1) && PyErr_Occurred())
4868         goto exit;
4869 
4870     result = 1;
4871 exit:
4872     Py_XDECREF(divmod);
4873     return result;
4874 }
4875 
4876 
4877 /*[clinic input]
4878 os.utime
4879 
4880     path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
4881     times: object = None
4882     *
4883     ns: object = NULL
4884     dir_fd: dir_fd(requires='futimensat') = None
4885     follow_symlinks: bool=True
4886 
4887 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
4888 
4889 Set the access and modified time of path.
4890 
4891 path may always be specified as a string.
4892 On some platforms, path may also be specified as an open file descriptor.
4893   If this functionality is unavailable, using it raises an exception.
4894 
4895 If times is not None, it must be a tuple (atime, mtime);
4896     atime and mtime should be expressed as float seconds since the epoch.
4897 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
4898     atime_ns and mtime_ns should be expressed as integer nanoseconds
4899     since the epoch.
4900 If times is None and ns is unspecified, utime uses the current time.
4901 Specifying tuples for both times and ns is an error.
4902 
4903 If dir_fd is not None, it should be a file descriptor open to a directory,
4904   and path should be relative; path will then be relative to that directory.
4905 If follow_symlinks is False, and the last element of the path is a symbolic
4906   link, utime will modify the symbolic link itself instead of the file the
4907   link points to.
4908 It is an error to use dir_fd or follow_symlinks when specifying path
4909   as an open file descriptor.
4910 dir_fd and follow_symlinks may not be available on your platform.
4911   If they are unavailable, using them will raise a NotImplementedError.
4912 
4913 [clinic start generated code]*/
4914 
4915 static PyObject *
os_utime_impl(PyObject * module,path_t * path,PyObject * times,PyObject * ns,int dir_fd,int follow_symlinks)4916 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
4917               int dir_fd, int follow_symlinks)
4918 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
4919 {
4920 #ifdef MS_WINDOWS
4921     HANDLE hFile;
4922     FILETIME atime, mtime;
4923 #else
4924     int result;
4925 #endif
4926 
4927     utime_t utime;
4928 
4929     memset(&utime, 0, sizeof(utime_t));
4930 
4931     if (times != Py_None && ns) {
4932         PyErr_SetString(PyExc_ValueError,
4933                      "utime: you may specify either 'times'"
4934                      " or 'ns' but not both");
4935         return NULL;
4936     }
4937 
4938     if (times != Py_None) {
4939         time_t a_sec, m_sec;
4940         long a_nsec, m_nsec;
4941         if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
4942             PyErr_SetString(PyExc_TypeError,
4943                          "utime: 'times' must be either"
4944                          " a tuple of two ints or None");
4945             return NULL;
4946         }
4947         utime.now = 0;
4948         if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
4949                                      &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
4950             _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
4951                                      &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
4952             return NULL;
4953         }
4954         utime.atime_s = a_sec;
4955         utime.atime_ns = a_nsec;
4956         utime.mtime_s = m_sec;
4957         utime.mtime_ns = m_nsec;
4958     }
4959     else if (ns) {
4960         if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
4961             PyErr_SetString(PyExc_TypeError,
4962                          "utime: 'ns' must be a tuple of two ints");
4963             return NULL;
4964         }
4965         utime.now = 0;
4966         if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0),
4967                                       &utime.atime_s, &utime.atime_ns) ||
4968             !split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1),
4969                                        &utime.mtime_s, &utime.mtime_ns)) {
4970             return NULL;
4971         }
4972     }
4973     else {
4974         /* times and ns are both None/unspecified. use "now". */
4975         utime.now = 1;
4976     }
4977 
4978 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
4979     if (follow_symlinks_specified("utime", follow_symlinks))
4980         return NULL;
4981 #endif
4982 
4983     if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
4984         dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
4985         fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
4986         return NULL;
4987 
4988 #if !defined(HAVE_UTIMENSAT)
4989     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
4990         PyErr_SetString(PyExc_ValueError,
4991                      "utime: cannot use dir_fd and follow_symlinks "
4992                      "together on this platform");
4993         return NULL;
4994     }
4995 #endif
4996 
4997     if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
4998                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4999         return NULL;
5000     }
5001 
5002 #ifdef MS_WINDOWS
5003     Py_BEGIN_ALLOW_THREADS
5004     hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
5005                         NULL, OPEN_EXISTING,
5006                         FILE_FLAG_BACKUP_SEMANTICS, NULL);
5007     Py_END_ALLOW_THREADS
5008     if (hFile == INVALID_HANDLE_VALUE) {
5009         path_error(path);
5010         return NULL;
5011     }
5012 
5013     if (utime.now) {
5014         GetSystemTimeAsFileTime(&mtime);
5015         atime = mtime;
5016     }
5017     else {
5018         _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
5019         _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
5020     }
5021     if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
5022         /* Avoid putting the file name into the error here,
5023            as that may confuse the user into believing that
5024            something is wrong with the file, when it also
5025            could be the time stamp that gives a problem. */
5026         PyErr_SetFromWindowsErr(0);
5027         CloseHandle(hFile);
5028         return NULL;
5029     }
5030     CloseHandle(hFile);
5031 #else /* MS_WINDOWS */
5032     Py_BEGIN_ALLOW_THREADS
5033 
5034 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5035     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
5036         result = utime_nofollow_symlinks(&utime, path->narrow);
5037     else
5038 #endif
5039 
5040 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5041     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
5042         result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
5043     else
5044 #endif
5045 
5046 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5047     if (path->fd != -1)
5048         result = utime_fd(&utime, path->fd);
5049     else
5050 #endif
5051 
5052     result = utime_default(&utime, path->narrow);
5053 
5054     Py_END_ALLOW_THREADS
5055 
5056     if (result < 0) {
5057         /* see previous comment about not putting filename in error here */
5058         posix_error();
5059         return NULL;
5060     }
5061 
5062 #endif /* MS_WINDOWS */
5063 
5064     Py_RETURN_NONE;
5065 }
5066 
5067 /* Process operations */
5068 
5069 
5070 /*[clinic input]
5071 os._exit
5072 
5073     status: int
5074 
5075 Exit to the system with specified status, without normal exit processing.
5076 [clinic start generated code]*/
5077 
5078 static PyObject *
os__exit_impl(PyObject * module,int status)5079 os__exit_impl(PyObject *module, int status)
5080 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5081 {
5082     _exit(status);
5083     return NULL; /* Make gcc -Wall happy */
5084 }
5085 
5086 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5087 #define EXECV_CHAR wchar_t
5088 #else
5089 #define EXECV_CHAR char
5090 #endif
5091 
5092 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5093 static void
free_string_array(EXECV_CHAR ** array,Py_ssize_t count)5094 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5095 {
5096     Py_ssize_t i;
5097     for (i = 0; i < count; i++)
5098         PyMem_Free(array[i]);
5099     PyMem_DEL(array);
5100 }
5101 
5102 static int
fsconvert_strdup(PyObject * o,EXECV_CHAR ** out)5103 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5104 {
5105     Py_ssize_t size;
5106     PyObject *ub;
5107     int result = 0;
5108 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5109     if (!PyUnicode_FSDecoder(o, &ub))
5110         return 0;
5111     *out = PyUnicode_AsWideCharString(ub, &size);
5112     if (*out)
5113         result = 1;
5114 #else
5115     if (!PyUnicode_FSConverter(o, &ub))
5116         return 0;
5117     size = PyBytes_GET_SIZE(ub);
5118     *out = PyMem_Malloc(size + 1);
5119     if (*out) {
5120         memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5121         result = 1;
5122     } else
5123         PyErr_NoMemory();
5124 #endif
5125     Py_DECREF(ub);
5126     return result;
5127 }
5128 #endif
5129 
5130 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5131 static EXECV_CHAR**
parse_envlist(PyObject * env,Py_ssize_t * envc_ptr)5132 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5133 {
5134     Py_ssize_t i, pos, envc;
5135     PyObject *keys=NULL, *vals=NULL;
5136     PyObject *key, *val, *key2, *val2, *keyval;
5137     EXECV_CHAR **envlist;
5138 
5139     i = PyMapping_Size(env);
5140     if (i < 0)
5141         return NULL;
5142     envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5143     if (envlist == NULL) {
5144         PyErr_NoMemory();
5145         return NULL;
5146     }
5147     envc = 0;
5148     keys = PyMapping_Keys(env);
5149     if (!keys)
5150         goto error;
5151     vals = PyMapping_Values(env);
5152     if (!vals)
5153         goto error;
5154     if (!PyList_Check(keys) || !PyList_Check(vals)) {
5155         PyErr_Format(PyExc_TypeError,
5156                      "env.keys() or env.values() is not a list");
5157         goto error;
5158     }
5159 
5160     for (pos = 0; pos < i; pos++) {
5161         key = PyList_GetItem(keys, pos);
5162         val = PyList_GetItem(vals, pos);
5163         if (!key || !val)
5164             goto error;
5165 
5166 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5167         if (!PyUnicode_FSDecoder(key, &key2))
5168             goto error;
5169         if (!PyUnicode_FSDecoder(val, &val2)) {
5170             Py_DECREF(key2);
5171             goto error;
5172         }
5173         /* Search from index 1 because on Windows starting '=' is allowed for
5174            defining hidden environment variables. */
5175         if (PyUnicode_GET_LENGTH(key2) == 0 ||
5176             PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5177         {
5178             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5179             Py_DECREF(key2);
5180             Py_DECREF(val2);
5181             goto error;
5182         }
5183         keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5184 #else
5185         if (!PyUnicode_FSConverter(key, &key2))
5186             goto error;
5187         if (!PyUnicode_FSConverter(val, &val2)) {
5188             Py_DECREF(key2);
5189             goto error;
5190         }
5191         if (PyBytes_GET_SIZE(key2) == 0 ||
5192             strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5193         {
5194             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5195             Py_DECREF(key2);
5196             Py_DECREF(val2);
5197             goto error;
5198         }
5199         keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5200                                              PyBytes_AS_STRING(val2));
5201 #endif
5202         Py_DECREF(key2);
5203         Py_DECREF(val2);
5204         if (!keyval)
5205             goto error;
5206 
5207         if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5208             Py_DECREF(keyval);
5209             goto error;
5210         }
5211 
5212         Py_DECREF(keyval);
5213     }
5214     Py_DECREF(vals);
5215     Py_DECREF(keys);
5216 
5217     envlist[envc] = 0;
5218     *envc_ptr = envc;
5219     return envlist;
5220 
5221 error:
5222     Py_XDECREF(keys);
5223     Py_XDECREF(vals);
5224     free_string_array(envlist, envc);
5225     return NULL;
5226 }
5227 
5228 static EXECV_CHAR**
parse_arglist(PyObject * argv,Py_ssize_t * argc)5229 parse_arglist(PyObject* argv, Py_ssize_t *argc)
5230 {
5231     int i;
5232     EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5233     if (argvlist == NULL) {
5234         PyErr_NoMemory();
5235         return NULL;
5236     }
5237     for (i = 0; i < *argc; i++) {
5238         PyObject* item = PySequence_ITEM(argv, i);
5239         if (item == NULL)
5240             goto fail;
5241         if (!fsconvert_strdup(item, &argvlist[i])) {
5242             Py_DECREF(item);
5243             goto fail;
5244         }
5245         Py_DECREF(item);
5246     }
5247     argvlist[*argc] = NULL;
5248     return argvlist;
5249 fail:
5250     *argc = i;
5251     free_string_array(argvlist, *argc);
5252     return NULL;
5253 }
5254 
5255 #endif
5256 
5257 
5258 #ifdef HAVE_EXECV
5259 /*[clinic input]
5260 os.execv
5261 
5262     path: path_t
5263         Path of executable file.
5264     argv: object
5265         Tuple or list of strings.
5266     /
5267 
5268 Execute an executable path with arguments, replacing current process.
5269 [clinic start generated code]*/
5270 
5271 static PyObject *
os_execv_impl(PyObject * module,path_t * path,PyObject * argv)5272 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5273 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5274 {
5275     EXECV_CHAR **argvlist;
5276     Py_ssize_t argc;
5277 
5278     /* execv has two arguments: (path, argv), where
5279        argv is a list or tuple of strings. */
5280 
5281     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5282         PyErr_SetString(PyExc_TypeError,
5283                         "execv() arg 2 must be a tuple or list");
5284         return NULL;
5285     }
5286     argc = PySequence_Size(argv);
5287     if (argc < 1) {
5288         PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5289         return NULL;
5290     }
5291 
5292     argvlist = parse_arglist(argv, &argc);
5293     if (argvlist == NULL) {
5294         return NULL;
5295     }
5296     if (!argvlist[0][0]) {
5297         PyErr_SetString(PyExc_ValueError,
5298             "execv() arg 2 first element cannot be empty");
5299         free_string_array(argvlist, argc);
5300         return NULL;
5301     }
5302 
5303     if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5304         free_string_array(argvlist, argc);
5305         return NULL;
5306     }
5307 
5308     _Py_BEGIN_SUPPRESS_IPH
5309 #ifdef HAVE_WEXECV
5310     _wexecv(path->wide, argvlist);
5311 #else
5312     execv(path->narrow, argvlist);
5313 #endif
5314     _Py_END_SUPPRESS_IPH
5315 
5316     /* If we get here it's definitely an error */
5317 
5318     free_string_array(argvlist, argc);
5319     return posix_error();
5320 }
5321 
5322 
5323 /*[clinic input]
5324 os.execve
5325 
5326     path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5327         Path of executable file.
5328     argv: object
5329         Tuple or list of strings.
5330     env: object
5331         Dictionary of strings mapping to strings.
5332 
5333 Execute an executable path with arguments, replacing current process.
5334 [clinic start generated code]*/
5335 
5336 static PyObject *
os_execve_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env)5337 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5338 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5339 {
5340     EXECV_CHAR **argvlist = NULL;
5341     EXECV_CHAR **envlist;
5342     Py_ssize_t argc, envc;
5343 
5344     /* execve has three arguments: (path, argv, env), where
5345        argv is a list or tuple of strings and env is a dictionary
5346        like posix.environ. */
5347 
5348     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5349         PyErr_SetString(PyExc_TypeError,
5350                         "execve: argv must be a tuple or list");
5351         goto fail_0;
5352     }
5353     argc = PySequence_Size(argv);
5354     if (argc < 1) {
5355         PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5356         return NULL;
5357     }
5358 
5359     if (!PyMapping_Check(env)) {
5360         PyErr_SetString(PyExc_TypeError,
5361                         "execve: environment must be a mapping object");
5362         goto fail_0;
5363     }
5364 
5365     argvlist = parse_arglist(argv, &argc);
5366     if (argvlist == NULL) {
5367         goto fail_0;
5368     }
5369     if (!argvlist[0][0]) {
5370         PyErr_SetString(PyExc_ValueError,
5371             "execve: argv first element cannot be empty");
5372         goto fail_0;
5373     }
5374 
5375     envlist = parse_envlist(env, &envc);
5376     if (envlist == NULL)
5377         goto fail_0;
5378 
5379     if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5380         goto fail_1;
5381     }
5382 
5383     _Py_BEGIN_SUPPRESS_IPH
5384 #ifdef HAVE_FEXECVE
5385     if (path->fd > -1)
5386         fexecve(path->fd, argvlist, envlist);
5387     else
5388 #endif
5389 #ifdef HAVE_WEXECV
5390         _wexecve(path->wide, argvlist, envlist);
5391 #else
5392         execve(path->narrow, argvlist, envlist);
5393 #endif
5394     _Py_END_SUPPRESS_IPH
5395 
5396     /* If we get here it's definitely an error */
5397 
5398     posix_path_error(path);
5399   fail_1:
5400     free_string_array(envlist, envc);
5401   fail_0:
5402     if (argvlist)
5403         free_string_array(argvlist, argc);
5404     return NULL;
5405 }
5406 
5407 #endif /* HAVE_EXECV */
5408 
5409 #ifdef HAVE_POSIX_SPAWN
5410 
5411 enum posix_spawn_file_actions_identifier {
5412     POSIX_SPAWN_OPEN,
5413     POSIX_SPAWN_CLOSE,
5414     POSIX_SPAWN_DUP2
5415 };
5416 
5417 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
5418 static int
5419 convert_sched_param(PyObject *param, struct sched_param *res);
5420 #endif
5421 
5422 static int
parse_posix_spawn_flags(const char * func_name,PyObject * setpgroup,int resetids,int setsid,PyObject * setsigmask,PyObject * setsigdef,PyObject * scheduler,posix_spawnattr_t * attrp)5423 parse_posix_spawn_flags(const char *func_name, PyObject *setpgroup,
5424                         int resetids, int setsid, PyObject *setsigmask,
5425                         PyObject *setsigdef, PyObject *scheduler,
5426                         posix_spawnattr_t *attrp)
5427 {
5428     long all_flags = 0;
5429 
5430     errno = posix_spawnattr_init(attrp);
5431     if (errno) {
5432         posix_error();
5433         return -1;
5434     }
5435 
5436     if (setpgroup) {
5437         pid_t pgid = PyLong_AsPid(setpgroup);
5438         if (pgid == (pid_t)-1 && PyErr_Occurred()) {
5439             goto fail;
5440         }
5441         errno = posix_spawnattr_setpgroup(attrp, pgid);
5442         if (errno) {
5443             posix_error();
5444             goto fail;
5445         }
5446         all_flags |= POSIX_SPAWN_SETPGROUP;
5447     }
5448 
5449     if (resetids) {
5450         all_flags |= POSIX_SPAWN_RESETIDS;
5451     }
5452 
5453     if (setsid) {
5454 #ifdef POSIX_SPAWN_SETSID
5455         all_flags |= POSIX_SPAWN_SETSID;
5456 #elif defined(POSIX_SPAWN_SETSID_NP)
5457         all_flags |= POSIX_SPAWN_SETSID_NP;
5458 #else
5459         argument_unavailable_error(func_name, "setsid");
5460         return -1;
5461 #endif
5462     }
5463 
5464    if (setsigmask) {
5465         sigset_t set;
5466         if (!_Py_Sigset_Converter(setsigmask, &set)) {
5467             goto fail;
5468         }
5469         errno = posix_spawnattr_setsigmask(attrp, &set);
5470         if (errno) {
5471             posix_error();
5472             goto fail;
5473         }
5474         all_flags |= POSIX_SPAWN_SETSIGMASK;
5475     }
5476 
5477     if (setsigdef) {
5478         sigset_t set;
5479         if (!_Py_Sigset_Converter(setsigdef, &set)) {
5480             goto fail;
5481         }
5482         errno = posix_spawnattr_setsigdefault(attrp, &set);
5483         if (errno) {
5484             posix_error();
5485             goto fail;
5486         }
5487         all_flags |= POSIX_SPAWN_SETSIGDEF;
5488     }
5489 
5490     if (scheduler) {
5491 #ifdef POSIX_SPAWN_SETSCHEDULER
5492         PyObject *py_schedpolicy;
5493         struct sched_param schedparam;
5494 
5495         if (!PyArg_ParseTuple(scheduler, "OO&"
5496                         ";A scheduler tuple must have two elements",
5497                         &py_schedpolicy, convert_sched_param, &schedparam)) {
5498             goto fail;
5499         }
5500         if (py_schedpolicy != Py_None) {
5501             int schedpolicy = _PyLong_AsInt(py_schedpolicy);
5502 
5503             if (schedpolicy == -1 && PyErr_Occurred()) {
5504                 goto fail;
5505             }
5506             errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
5507             if (errno) {
5508                 posix_error();
5509                 goto fail;
5510             }
5511             all_flags |= POSIX_SPAWN_SETSCHEDULER;
5512         }
5513         errno = posix_spawnattr_setschedparam(attrp, &schedparam);
5514         if (errno) {
5515             posix_error();
5516             goto fail;
5517         }
5518         all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
5519 #else
5520         PyErr_SetString(PyExc_NotImplementedError,
5521                 "The scheduler option is not supported in this system.");
5522         goto fail;
5523 #endif
5524     }
5525 
5526     errno = posix_spawnattr_setflags(attrp, all_flags);
5527     if (errno) {
5528         posix_error();
5529         goto fail;
5530     }
5531 
5532     return 0;
5533 
5534 fail:
5535     (void)posix_spawnattr_destroy(attrp);
5536     return -1;
5537 }
5538 
5539 static int
parse_file_actions(PyObject * file_actions,posix_spawn_file_actions_t * file_actionsp,PyObject * temp_buffer)5540 parse_file_actions(PyObject *file_actions,
5541                    posix_spawn_file_actions_t *file_actionsp,
5542                    PyObject *temp_buffer)
5543 {
5544     PyObject *seq;
5545     PyObject *file_action = NULL;
5546     PyObject *tag_obj;
5547 
5548     seq = PySequence_Fast(file_actions,
5549                           "file_actions must be a sequence or None");
5550     if (seq == NULL) {
5551         return -1;
5552     }
5553 
5554     errno = posix_spawn_file_actions_init(file_actionsp);
5555     if (errno) {
5556         posix_error();
5557         Py_DECREF(seq);
5558         return -1;
5559     }
5560 
5561     for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
5562         file_action = PySequence_Fast_GET_ITEM(seq, i);
5563         Py_INCREF(file_action);
5564         if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
5565             PyErr_SetString(PyExc_TypeError,
5566                 "Each file_actions element must be a non-empty tuple");
5567             goto fail;
5568         }
5569         long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
5570         if (tag == -1 && PyErr_Occurred()) {
5571             goto fail;
5572         }
5573 
5574         /* Populate the file_actions object */
5575         switch (tag) {
5576             case POSIX_SPAWN_OPEN: {
5577                 int fd, oflag;
5578                 PyObject *path;
5579                 unsigned long mode;
5580                 if (!PyArg_ParseTuple(file_action, "OiO&ik"
5581                         ";A open file_action tuple must have 5 elements",
5582                         &tag_obj, &fd, PyUnicode_FSConverter, &path,
5583                         &oflag, &mode))
5584                 {
5585                     goto fail;
5586                 }
5587                 if (PyList_Append(temp_buffer, path)) {
5588                     Py_DECREF(path);
5589                     goto fail;
5590                 }
5591                 errno = posix_spawn_file_actions_addopen(file_actionsp,
5592                         fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
5593                 Py_DECREF(path);
5594                 if (errno) {
5595                     posix_error();
5596                     goto fail;
5597                 }
5598                 break;
5599             }
5600             case POSIX_SPAWN_CLOSE: {
5601                 int fd;
5602                 if (!PyArg_ParseTuple(file_action, "Oi"
5603                         ";A close file_action tuple must have 2 elements",
5604                         &tag_obj, &fd))
5605                 {
5606                     goto fail;
5607                 }
5608                 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
5609                 if (errno) {
5610                     posix_error();
5611                     goto fail;
5612                 }
5613                 break;
5614             }
5615             case POSIX_SPAWN_DUP2: {
5616                 int fd1, fd2;
5617                 if (!PyArg_ParseTuple(file_action, "Oii"
5618                         ";A dup2 file_action tuple must have 3 elements",
5619                         &tag_obj, &fd1, &fd2))
5620                 {
5621                     goto fail;
5622                 }
5623                 errno = posix_spawn_file_actions_adddup2(file_actionsp,
5624                                                          fd1, fd2);
5625                 if (errno) {
5626                     posix_error();
5627                     goto fail;
5628                 }
5629                 break;
5630             }
5631             default: {
5632                 PyErr_SetString(PyExc_TypeError,
5633                                 "Unknown file_actions identifier");
5634                 goto fail;
5635             }
5636         }
5637         Py_DECREF(file_action);
5638     }
5639 
5640     Py_DECREF(seq);
5641     return 0;
5642 
5643 fail:
5644     Py_DECREF(seq);
5645     Py_DECREF(file_action);
5646     (void)posix_spawn_file_actions_destroy(file_actionsp);
5647     return -1;
5648 }
5649 
5650 
5651 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)5652 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
5653                PyObject *env, PyObject *file_actions,
5654                PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
5655                PyObject *setsigdef, PyObject *scheduler)
5656 {
5657     const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
5658     EXECV_CHAR **argvlist = NULL;
5659     EXECV_CHAR **envlist = NULL;
5660     posix_spawn_file_actions_t file_actions_buf;
5661     posix_spawn_file_actions_t *file_actionsp = NULL;
5662     posix_spawnattr_t attr;
5663     posix_spawnattr_t *attrp = NULL;
5664     Py_ssize_t argc, envc;
5665     PyObject *result = NULL;
5666     PyObject *temp_buffer = NULL;
5667     pid_t pid;
5668     int err_code;
5669 
5670     /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
5671        argv is a list or tuple of strings and env is a dictionary
5672        like posix.environ. */
5673 
5674     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5675         PyErr_Format(PyExc_TypeError,
5676                      "%s: argv must be a tuple or list", func_name);
5677         goto exit;
5678     }
5679     argc = PySequence_Size(argv);
5680     if (argc < 1) {
5681         PyErr_Format(PyExc_ValueError,
5682                      "%s: argv must not be empty", func_name);
5683         return NULL;
5684     }
5685 
5686     if (!PyMapping_Check(env)) {
5687         PyErr_Format(PyExc_TypeError,
5688                      "%s: environment must be a mapping object", func_name);
5689         goto exit;
5690     }
5691 
5692     argvlist = parse_arglist(argv, &argc);
5693     if (argvlist == NULL) {
5694         goto exit;
5695     }
5696     if (!argvlist[0][0]) {
5697         PyErr_Format(PyExc_ValueError,
5698                      "%s: argv first element cannot be empty", func_name);
5699         goto exit;
5700     }
5701 
5702     envlist = parse_envlist(env, &envc);
5703     if (envlist == NULL) {
5704         goto exit;
5705     }
5706 
5707     if (file_actions != NULL && file_actions != Py_None) {
5708         /* There is a bug in old versions of glibc that makes some of the
5709          * helper functions for manipulating file actions not copy the provided
5710          * buffers. The problem is that posix_spawn_file_actions_addopen does not
5711          * copy the value of path for some old versions of glibc (<2.20).
5712          * The use of temp_buffer here is a workaround that keeps the
5713          * python objects that own the buffers alive until posix_spawn gets called.
5714          * Check https://bugs.python.org/issue33630 and
5715          * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
5716         temp_buffer = PyList_New(0);
5717         if (!temp_buffer) {
5718             goto exit;
5719         }
5720         if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
5721             goto exit;
5722         }
5723         file_actionsp = &file_actions_buf;
5724     }
5725 
5726     if (parse_posix_spawn_flags(func_name, setpgroup, resetids, setsid,
5727                                 setsigmask, setsigdef, scheduler, &attr)) {
5728         goto exit;
5729     }
5730     attrp = &attr;
5731 
5732     if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
5733         goto exit;
5734     }
5735 
5736     _Py_BEGIN_SUPPRESS_IPH
5737 #ifdef HAVE_POSIX_SPAWNP
5738     if (use_posix_spawnp) {
5739         err_code = posix_spawnp(&pid, path->narrow,
5740                                 file_actionsp, attrp, argvlist, envlist);
5741     }
5742     else
5743 #endif /* HAVE_POSIX_SPAWNP */
5744     {
5745         err_code = posix_spawn(&pid, path->narrow,
5746                                file_actionsp, attrp, argvlist, envlist);
5747     }
5748     _Py_END_SUPPRESS_IPH
5749 
5750     if (err_code) {
5751         errno = err_code;
5752         PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
5753         goto exit;
5754     }
5755 #ifdef _Py_MEMORY_SANITIZER
5756     __msan_unpoison(&pid, sizeof(pid));
5757 #endif
5758     result = PyLong_FromPid(pid);
5759 
5760 exit:
5761     if (file_actionsp) {
5762         (void)posix_spawn_file_actions_destroy(file_actionsp);
5763     }
5764     if (attrp) {
5765         (void)posix_spawnattr_destroy(attrp);
5766     }
5767     if (envlist) {
5768         free_string_array(envlist, envc);
5769     }
5770     if (argvlist) {
5771         free_string_array(argvlist, argc);
5772     }
5773     Py_XDECREF(temp_buffer);
5774     return result;
5775 }
5776 
5777 
5778 /*[clinic input]
5779 
5780 os.posix_spawn
5781     path: path_t
5782         Path of executable file.
5783     argv: object
5784         Tuple or list of strings.
5785     env: object
5786         Dictionary of strings mapping to strings.
5787     /
5788     *
5789     file_actions: object(c_default='NULL') = ()
5790         A sequence of file action tuples.
5791     setpgroup: object = NULL
5792         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
5793     resetids: bool(accept={int}) = False
5794         If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
5795     setsid: bool(accept={int}) = False
5796         If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
5797     setsigmask: object(c_default='NULL') = ()
5798         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
5799     setsigdef: object(c_default='NULL') = ()
5800         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
5801     scheduler: object = NULL
5802         A tuple with the scheduler policy (optional) and parameters.
5803 
5804 Execute the program specified by path in a new process.
5805 [clinic start generated code]*/
5806 
5807 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)5808 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
5809                     PyObject *env, PyObject *file_actions,
5810                     PyObject *setpgroup, int resetids, int setsid,
5811                     PyObject *setsigmask, PyObject *setsigdef,
5812                     PyObject *scheduler)
5813 /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
5814 {
5815     return py_posix_spawn(0, module, path, argv, env, file_actions,
5816                           setpgroup, resetids, setsid, setsigmask, setsigdef,
5817                           scheduler);
5818 }
5819  #endif /* HAVE_POSIX_SPAWN */
5820 
5821 
5822 
5823 #ifdef HAVE_POSIX_SPAWNP
5824 /*[clinic input]
5825 
5826 os.posix_spawnp
5827     path: path_t
5828         Path of executable file.
5829     argv: object
5830         Tuple or list of strings.
5831     env: object
5832         Dictionary of strings mapping to strings.
5833     /
5834     *
5835     file_actions: object(c_default='NULL') = ()
5836         A sequence of file action tuples.
5837     setpgroup: object = NULL
5838         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
5839     resetids: bool(accept={int}) = False
5840         If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
5841     setsid: bool(accept={int}) = False
5842         If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
5843     setsigmask: object(c_default='NULL') = ()
5844         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
5845     setsigdef: object(c_default='NULL') = ()
5846         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
5847     scheduler: object = NULL
5848         A tuple with the scheduler policy (optional) and parameters.
5849 
5850 Execute the program specified by path in a new process.
5851 [clinic start generated code]*/
5852 
5853 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)5854 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
5855                      PyObject *env, PyObject *file_actions,
5856                      PyObject *setpgroup, int resetids, int setsid,
5857                      PyObject *setsigmask, PyObject *setsigdef,
5858                      PyObject *scheduler)
5859 /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
5860 {
5861     return py_posix_spawn(1, module, path, argv, env, file_actions,
5862                           setpgroup, resetids, setsid, setsigmask, setsigdef,
5863                           scheduler);
5864 }
5865 #endif /* HAVE_POSIX_SPAWNP */
5866 
5867 #ifdef HAVE_RTPSPAWN
5868 static intptr_t
_rtp_spawn(int mode,const char * rtpFileName,const char * argv[],const char * envp[])5869 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
5870                const char  *envp[])
5871 {
5872      RTP_ID rtpid;
5873      int status;
5874      pid_t res;
5875      int async_err = 0;
5876 
5877      /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
5878         uStackSize=0 cannot be used, the default stack size is too small for
5879         Python. */
5880      if (envp) {
5881          rtpid = rtpSpawn(rtpFileName, argv, envp,
5882                           100, 0x1000000, 0, VX_FP_TASK);
5883      }
5884      else {
5885          rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
5886                           100, 0x1000000, 0, VX_FP_TASK);
5887      }
5888      if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
5889          do {
5890              res = waitpid((pid_t)rtpid, &status, 0);
5891          } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
5892 
5893          if (res < 0)
5894              return RTP_ID_ERROR;
5895          return ((intptr_t)status);
5896      }
5897      return ((intptr_t)rtpid);
5898 }
5899 #endif
5900 
5901 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
5902 /*[clinic input]
5903 os.spawnv
5904 
5905     mode: int
5906         Mode of process creation.
5907     path: path_t
5908         Path of executable file.
5909     argv: object
5910         Tuple or list of strings.
5911     /
5912 
5913 Execute the program specified by path in a new process.
5914 [clinic start generated code]*/
5915 
5916 static PyObject *
os_spawnv_impl(PyObject * module,int mode,path_t * path,PyObject * argv)5917 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
5918 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
5919 {
5920     EXECV_CHAR **argvlist;
5921     int i;
5922     Py_ssize_t argc;
5923     intptr_t spawnval;
5924     PyObject *(*getitem)(PyObject *, Py_ssize_t);
5925 
5926     /* spawnv has three arguments: (mode, path, argv), where
5927        argv is a list or tuple of strings. */
5928 
5929     if (PyList_Check(argv)) {
5930         argc = PyList_Size(argv);
5931         getitem = PyList_GetItem;
5932     }
5933     else if (PyTuple_Check(argv)) {
5934         argc = PyTuple_Size(argv);
5935         getitem = PyTuple_GetItem;
5936     }
5937     else {
5938         PyErr_SetString(PyExc_TypeError,
5939                         "spawnv() arg 2 must be a tuple or list");
5940         return NULL;
5941     }
5942     if (argc == 0) {
5943         PyErr_SetString(PyExc_ValueError,
5944             "spawnv() arg 2 cannot be empty");
5945         return NULL;
5946     }
5947 
5948     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
5949     if (argvlist == NULL) {
5950         return PyErr_NoMemory();
5951     }
5952     for (i = 0; i < argc; i++) {
5953         if (!fsconvert_strdup((*getitem)(argv, i),
5954                               &argvlist[i])) {
5955             free_string_array(argvlist, i);
5956             PyErr_SetString(
5957                 PyExc_TypeError,
5958                 "spawnv() arg 2 must contain only strings");
5959             return NULL;
5960         }
5961         if (i == 0 && !argvlist[0][0]) {
5962             free_string_array(argvlist, i + 1);
5963             PyErr_SetString(
5964                 PyExc_ValueError,
5965                 "spawnv() arg 2 first element cannot be empty");
5966             return NULL;
5967         }
5968     }
5969     argvlist[argc] = NULL;
5970 
5971 #if !defined(HAVE_RTPSPAWN)
5972     if (mode == _OLD_P_OVERLAY)
5973         mode = _P_OVERLAY;
5974 #endif
5975 
5976     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
5977                     Py_None) < 0) {
5978         free_string_array(argvlist, argc);
5979         return NULL;
5980     }
5981 
5982     Py_BEGIN_ALLOW_THREADS
5983     _Py_BEGIN_SUPPRESS_IPH
5984 #ifdef HAVE_WSPAWNV
5985     spawnval = _wspawnv(mode, path->wide, argvlist);
5986 #elif defined(HAVE_RTPSPAWN)
5987     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
5988 #else
5989     spawnval = _spawnv(mode, path->narrow, argvlist);
5990 #endif
5991     _Py_END_SUPPRESS_IPH
5992     Py_END_ALLOW_THREADS
5993 
5994     free_string_array(argvlist, argc);
5995 
5996     if (spawnval == -1)
5997         return posix_error();
5998     else
5999         return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6000 }
6001 
6002 /*[clinic input]
6003 os.spawnve
6004 
6005     mode: int
6006         Mode of process creation.
6007     path: path_t
6008         Path of executable file.
6009     argv: object
6010         Tuple or list of strings.
6011     env: object
6012         Dictionary of strings mapping to strings.
6013     /
6014 
6015 Execute the program specified by path in a new process.
6016 [clinic start generated code]*/
6017 
6018 static PyObject *
os_spawnve_impl(PyObject * module,int mode,path_t * path,PyObject * argv,PyObject * env)6019 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
6020                 PyObject *env)
6021 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
6022 {
6023     EXECV_CHAR **argvlist;
6024     EXECV_CHAR **envlist;
6025     PyObject *res = NULL;
6026     Py_ssize_t argc, i, envc;
6027     intptr_t spawnval;
6028     PyObject *(*getitem)(PyObject *, Py_ssize_t);
6029     Py_ssize_t lastarg = 0;
6030 
6031     /* spawnve has four arguments: (mode, path, argv, env), where
6032        argv is a list or tuple of strings and env is a dictionary
6033        like posix.environ. */
6034 
6035     if (PyList_Check(argv)) {
6036         argc = PyList_Size(argv);
6037         getitem = PyList_GetItem;
6038     }
6039     else if (PyTuple_Check(argv)) {
6040         argc = PyTuple_Size(argv);
6041         getitem = PyTuple_GetItem;
6042     }
6043     else {
6044         PyErr_SetString(PyExc_TypeError,
6045                         "spawnve() arg 2 must be a tuple or list");
6046         goto fail_0;
6047     }
6048     if (argc == 0) {
6049         PyErr_SetString(PyExc_ValueError,
6050             "spawnve() arg 2 cannot be empty");
6051         goto fail_0;
6052     }
6053     if (!PyMapping_Check(env)) {
6054         PyErr_SetString(PyExc_TypeError,
6055                         "spawnve() arg 3 must be a mapping object");
6056         goto fail_0;
6057     }
6058 
6059     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6060     if (argvlist == NULL) {
6061         PyErr_NoMemory();
6062         goto fail_0;
6063     }
6064     for (i = 0; i < argc; i++) {
6065         if (!fsconvert_strdup((*getitem)(argv, i),
6066                               &argvlist[i]))
6067         {
6068             lastarg = i;
6069             goto fail_1;
6070         }
6071         if (i == 0 && !argvlist[0][0]) {
6072             lastarg = i + 1;
6073             PyErr_SetString(
6074                 PyExc_ValueError,
6075                 "spawnv() arg 2 first element cannot be empty");
6076             goto fail_1;
6077         }
6078     }
6079     lastarg = argc;
6080     argvlist[argc] = NULL;
6081 
6082     envlist = parse_envlist(env, &envc);
6083     if (envlist == NULL)
6084         goto fail_1;
6085 
6086 #if !defined(HAVE_RTPSPAWN)
6087     if (mode == _OLD_P_OVERLAY)
6088         mode = _P_OVERLAY;
6089 #endif
6090 
6091     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6092         goto fail_2;
6093     }
6094 
6095     Py_BEGIN_ALLOW_THREADS
6096     _Py_BEGIN_SUPPRESS_IPH
6097 #ifdef HAVE_WSPAWNV
6098     spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6099 #elif defined(HAVE_RTPSPAWN)
6100     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6101                            (const char **)envlist);
6102 #else
6103     spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6104 #endif
6105     _Py_END_SUPPRESS_IPH
6106     Py_END_ALLOW_THREADS
6107 
6108     if (spawnval == -1)
6109         (void) posix_error();
6110     else
6111         res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6112 
6113   fail_2:
6114     while (--envc >= 0)
6115         PyMem_DEL(envlist[envc]);
6116     PyMem_DEL(envlist);
6117   fail_1:
6118     free_string_array(argvlist, lastarg);
6119   fail_0:
6120     return res;
6121 }
6122 
6123 #endif /* HAVE_SPAWNV */
6124 
6125 
6126 #ifdef HAVE_FORK
6127 
6128 /* Helper function to validate arguments.
6129    Returns 0 on success.  non-zero on failure with a TypeError raised.
6130    If obj is non-NULL it must be callable.  */
6131 static int
check_null_or_callable(PyObject * obj,const char * obj_name)6132 check_null_or_callable(PyObject *obj, const char* obj_name)
6133 {
6134     if (obj && !PyCallable_Check(obj)) {
6135         PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6136                      obj_name, Py_TYPE(obj)->tp_name);
6137         return -1;
6138     }
6139     return 0;
6140 }
6141 
6142 /*[clinic input]
6143 os.register_at_fork
6144 
6145     *
6146     before: object=NULL
6147         A callable to be called in the parent before the fork() syscall.
6148     after_in_child: object=NULL
6149         A callable to be called in the child after fork().
6150     after_in_parent: object=NULL
6151         A callable to be called in the parent after fork().
6152 
6153 Register callables to be called when forking a new process.
6154 
6155 'before' callbacks are called in reverse order.
6156 'after_in_child' and 'after_in_parent' callbacks are called in order.
6157 
6158 [clinic start generated code]*/
6159 
6160 static PyObject *
os_register_at_fork_impl(PyObject * module,PyObject * before,PyObject * after_in_child,PyObject * after_in_parent)6161 os_register_at_fork_impl(PyObject *module, PyObject *before,
6162                          PyObject *after_in_child, PyObject *after_in_parent)
6163 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6164 {
6165     PyInterpreterState *interp;
6166 
6167     if (!before && !after_in_child && !after_in_parent) {
6168         PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6169         return NULL;
6170     }
6171     if (check_null_or_callable(before, "before") ||
6172         check_null_or_callable(after_in_child, "after_in_child") ||
6173         check_null_or_callable(after_in_parent, "after_in_parent")) {
6174         return NULL;
6175     }
6176     interp = _PyInterpreterState_Get();
6177 
6178     if (register_at_forker(&interp->before_forkers, before)) {
6179         return NULL;
6180     }
6181     if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6182         return NULL;
6183     }
6184     if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6185         return NULL;
6186     }
6187     Py_RETURN_NONE;
6188 }
6189 #endif /* HAVE_FORK */
6190 
6191 
6192 #ifdef HAVE_FORK1
6193 /*[clinic input]
6194 os.fork1
6195 
6196 Fork a child process with a single multiplexed (i.e., not bound) thread.
6197 
6198 Return 0 to child process and PID of child to parent process.
6199 [clinic start generated code]*/
6200 
6201 static PyObject *
os_fork1_impl(PyObject * module)6202 os_fork1_impl(PyObject *module)
6203 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6204 {
6205     pid_t pid;
6206 
6207     if (_PyInterpreterState_Get() != PyInterpreterState_Main()) {
6208         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6209         return NULL;
6210     }
6211     PyOS_BeforeFork();
6212     pid = fork1();
6213     if (pid == 0) {
6214         /* child: this clobbers and resets the import lock. */
6215         PyOS_AfterFork_Child();
6216     } else {
6217         /* parent: release the import lock. */
6218         PyOS_AfterFork_Parent();
6219     }
6220     if (pid == -1)
6221         return posix_error();
6222     return PyLong_FromPid(pid);
6223 }
6224 #endif /* HAVE_FORK1 */
6225 
6226 
6227 #ifdef HAVE_FORK
6228 /*[clinic input]
6229 os.fork
6230 
6231 Fork a child process.
6232 
6233 Return 0 to child process and PID of child to parent process.
6234 [clinic start generated code]*/
6235 
6236 static PyObject *
os_fork_impl(PyObject * module)6237 os_fork_impl(PyObject *module)
6238 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6239 {
6240     pid_t pid;
6241 
6242     if (_PyInterpreterState_Get() != PyInterpreterState_Main()) {
6243         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6244         return NULL;
6245     }
6246     if (PySys_Audit("os.fork", NULL) < 0) {
6247         return NULL;
6248     }
6249     PyOS_BeforeFork();
6250     pid = fork();
6251     if (pid == 0) {
6252         /* child: this clobbers and resets the import lock. */
6253         PyOS_AfterFork_Child();
6254     } else {
6255         /* parent: release the import lock. */
6256         PyOS_AfterFork_Parent();
6257     }
6258     if (pid == -1)
6259         return posix_error();
6260     return PyLong_FromPid(pid);
6261 }
6262 #endif /* HAVE_FORK */
6263 
6264 
6265 #ifdef HAVE_SCHED_H
6266 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6267 /*[clinic input]
6268 os.sched_get_priority_max
6269 
6270     policy: int
6271 
6272 Get the maximum scheduling priority for policy.
6273 [clinic start generated code]*/
6274 
6275 static PyObject *
os_sched_get_priority_max_impl(PyObject * module,int policy)6276 os_sched_get_priority_max_impl(PyObject *module, int policy)
6277 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6278 {
6279     int max;
6280 
6281     max = sched_get_priority_max(policy);
6282     if (max < 0)
6283         return posix_error();
6284     return PyLong_FromLong(max);
6285 }
6286 
6287 
6288 /*[clinic input]
6289 os.sched_get_priority_min
6290 
6291     policy: int
6292 
6293 Get the minimum scheduling priority for policy.
6294 [clinic start generated code]*/
6295 
6296 static PyObject *
os_sched_get_priority_min_impl(PyObject * module,int policy)6297 os_sched_get_priority_min_impl(PyObject *module, int policy)
6298 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6299 {
6300     int min = sched_get_priority_min(policy);
6301     if (min < 0)
6302         return posix_error();
6303     return PyLong_FromLong(min);
6304 }
6305 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6306 
6307 
6308 #ifdef HAVE_SCHED_SETSCHEDULER
6309 /*[clinic input]
6310 os.sched_getscheduler
6311     pid: pid_t
6312     /
6313 
6314 Get the scheduling policy for the process identifiedy by pid.
6315 
6316 Passing 0 for pid returns the scheduling policy for the calling process.
6317 [clinic start generated code]*/
6318 
6319 static PyObject *
os_sched_getscheduler_impl(PyObject * module,pid_t pid)6320 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6321 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=5f14cfd1f189e1a0]*/
6322 {
6323     int policy;
6324 
6325     policy = sched_getscheduler(pid);
6326     if (policy < 0)
6327         return posix_error();
6328     return PyLong_FromLong(policy);
6329 }
6330 #endif /* HAVE_SCHED_SETSCHEDULER */
6331 
6332 
6333 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6334 /*[clinic input]
6335 class os.sched_param "PyObject *" "SchedParamType"
6336 
6337 @classmethod
6338 os.sched_param.__new__
6339 
6340     sched_priority: object
6341         A scheduling parameter.
6342 
6343 Current has only one field: sched_priority");
6344 [clinic start generated code]*/
6345 
6346 static PyObject *
os_sched_param_impl(PyTypeObject * type,PyObject * sched_priority)6347 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6348 /*[clinic end generated code: output=48f4067d60f48c13 input=ab4de35a9a7811f2]*/
6349 {
6350     PyObject *res;
6351 
6352     res = PyStructSequence_New(type);
6353     if (!res)
6354         return NULL;
6355     Py_INCREF(sched_priority);
6356     PyStructSequence_SET_ITEM(res, 0, sched_priority);
6357     return res;
6358 }
6359 
6360 
6361 PyDoc_VAR(os_sched_param__doc__);
6362 
6363 static PyStructSequence_Field sched_param_fields[] = {
6364     {"sched_priority", "the scheduling priority"},
6365     {0}
6366 };
6367 
6368 static PyStructSequence_Desc sched_param_desc = {
6369     "sched_param", /* name */
6370     os_sched_param__doc__, /* doc */
6371     sched_param_fields,
6372     1
6373 };
6374 
6375 static int
convert_sched_param(PyObject * param,struct sched_param * res)6376 convert_sched_param(PyObject *param, struct sched_param *res)
6377 {
6378     long priority;
6379 
6380     if (Py_TYPE(param) != SchedParamType) {
6381         PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
6382         return 0;
6383     }
6384     priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
6385     if (priority == -1 && PyErr_Occurred())
6386         return 0;
6387     if (priority > INT_MAX || priority < INT_MIN) {
6388         PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
6389         return 0;
6390     }
6391     res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
6392     return 1;
6393 }
6394 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
6395 
6396 
6397 #ifdef HAVE_SCHED_SETSCHEDULER
6398 /*[clinic input]
6399 os.sched_setscheduler
6400 
6401     pid: pid_t
6402     policy: int
6403     param: sched_param
6404     /
6405 
6406 Set the scheduling policy for the process identified by pid.
6407 
6408 If pid is 0, the calling process is changed.
6409 param is an instance of sched_param.
6410 [clinic start generated code]*/
6411 
6412 static PyObject *
os_sched_setscheduler_impl(PyObject * module,pid_t pid,int policy,struct sched_param * param)6413 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
6414                            struct sched_param *param)
6415 /*[clinic end generated code: output=b0ac0a70d3b1d705 input=c581f9469a5327dd]*/
6416 {
6417     /*
6418     ** sched_setscheduler() returns 0 in Linux, but the previous
6419     ** scheduling policy under Solaris/Illumos, and others.
6420     ** On error, -1 is returned in all Operating Systems.
6421     */
6422     if (sched_setscheduler(pid, policy, param) == -1)
6423         return posix_error();
6424     Py_RETURN_NONE;
6425 }
6426 #endif  /* HAVE_SCHED_SETSCHEDULER*/
6427 
6428 
6429 #ifdef HAVE_SCHED_SETPARAM
6430 /*[clinic input]
6431 os.sched_getparam
6432     pid: pid_t
6433     /
6434 
6435 Returns scheduling parameters for the process identified by pid.
6436 
6437 If pid is 0, returns parameters for the calling process.
6438 Return value is an instance of sched_param.
6439 [clinic start generated code]*/
6440 
6441 static PyObject *
os_sched_getparam_impl(PyObject * module,pid_t pid)6442 os_sched_getparam_impl(PyObject *module, pid_t pid)
6443 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
6444 {
6445     struct sched_param param;
6446     PyObject *result;
6447     PyObject *priority;
6448 
6449     if (sched_getparam(pid, &param))
6450         return posix_error();
6451     result = PyStructSequence_New(SchedParamType);
6452     if (!result)
6453         return NULL;
6454     priority = PyLong_FromLong(param.sched_priority);
6455     if (!priority) {
6456         Py_DECREF(result);
6457         return NULL;
6458     }
6459     PyStructSequence_SET_ITEM(result, 0, priority);
6460     return result;
6461 }
6462 
6463 
6464 /*[clinic input]
6465 os.sched_setparam
6466     pid: pid_t
6467     param: sched_param
6468     /
6469 
6470 Set scheduling parameters for the process identified by pid.
6471 
6472 If pid is 0, sets parameters for the calling process.
6473 param should be an instance of sched_param.
6474 [clinic start generated code]*/
6475 
6476 static PyObject *
os_sched_setparam_impl(PyObject * module,pid_t pid,struct sched_param * param)6477 os_sched_setparam_impl(PyObject *module, pid_t pid,
6478                        struct sched_param *param)
6479 /*[clinic end generated code: output=8af013f78a32b591 input=6b8d6dfcecdc21bd]*/
6480 {
6481     if (sched_setparam(pid, param))
6482         return posix_error();
6483     Py_RETURN_NONE;
6484 }
6485 #endif /* HAVE_SCHED_SETPARAM */
6486 
6487 
6488 #ifdef HAVE_SCHED_RR_GET_INTERVAL
6489 /*[clinic input]
6490 os.sched_rr_get_interval -> double
6491     pid: pid_t
6492     /
6493 
6494 Return the round-robin quantum for the process identified by pid, in seconds.
6495 
6496 Value returned is a float.
6497 [clinic start generated code]*/
6498 
6499 static double
os_sched_rr_get_interval_impl(PyObject * module,pid_t pid)6500 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
6501 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
6502 {
6503     struct timespec interval;
6504     if (sched_rr_get_interval(pid, &interval)) {
6505         posix_error();
6506         return -1.0;
6507     }
6508 #ifdef _Py_MEMORY_SANITIZER
6509     __msan_unpoison(&interval, sizeof(interval));
6510 #endif
6511     return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
6512 }
6513 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
6514 
6515 
6516 /*[clinic input]
6517 os.sched_yield
6518 
6519 Voluntarily relinquish the CPU.
6520 [clinic start generated code]*/
6521 
6522 static PyObject *
os_sched_yield_impl(PyObject * module)6523 os_sched_yield_impl(PyObject *module)
6524 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
6525 {
6526     if (sched_yield())
6527         return posix_error();
6528     Py_RETURN_NONE;
6529 }
6530 
6531 #ifdef HAVE_SCHED_SETAFFINITY
6532 /* The minimum number of CPUs allocated in a cpu_set_t */
6533 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
6534 
6535 /*[clinic input]
6536 os.sched_setaffinity
6537     pid: pid_t
6538     mask : object
6539     /
6540 
6541 Set the CPU affinity of the process identified by pid to mask.
6542 
6543 mask should be an iterable of integers identifying CPUs.
6544 [clinic start generated code]*/
6545 
6546 static PyObject *
os_sched_setaffinity_impl(PyObject * module,pid_t pid,PyObject * mask)6547 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
6548 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
6549 {
6550     int ncpus;
6551     size_t setsize;
6552     cpu_set_t *cpu_set = NULL;
6553     PyObject *iterator = NULL, *item;
6554 
6555     iterator = PyObject_GetIter(mask);
6556     if (iterator == NULL)
6557         return NULL;
6558 
6559     ncpus = NCPUS_START;
6560     setsize = CPU_ALLOC_SIZE(ncpus);
6561     cpu_set = CPU_ALLOC(ncpus);
6562     if (cpu_set == NULL) {
6563         PyErr_NoMemory();
6564         goto error;
6565     }
6566     CPU_ZERO_S(setsize, cpu_set);
6567 
6568     while ((item = PyIter_Next(iterator))) {
6569         long cpu;
6570         if (!PyLong_Check(item)) {
6571             PyErr_Format(PyExc_TypeError,
6572                         "expected an iterator of ints, "
6573                         "but iterator yielded %R",
6574                         Py_TYPE(item));
6575             Py_DECREF(item);
6576             goto error;
6577         }
6578         cpu = PyLong_AsLong(item);
6579         Py_DECREF(item);
6580         if (cpu < 0) {
6581             if (!PyErr_Occurred())
6582                 PyErr_SetString(PyExc_ValueError, "negative CPU number");
6583             goto error;
6584         }
6585         if (cpu > INT_MAX - 1) {
6586             PyErr_SetString(PyExc_OverflowError, "CPU number too large");
6587             goto error;
6588         }
6589         if (cpu >= ncpus) {
6590             /* Grow CPU mask to fit the CPU number */
6591             int newncpus = ncpus;
6592             cpu_set_t *newmask;
6593             size_t newsetsize;
6594             while (newncpus <= cpu) {
6595                 if (newncpus > INT_MAX / 2)
6596                     newncpus = cpu + 1;
6597                 else
6598                     newncpus = newncpus * 2;
6599             }
6600             newmask = CPU_ALLOC(newncpus);
6601             if (newmask == NULL) {
6602                 PyErr_NoMemory();
6603                 goto error;
6604             }
6605             newsetsize = CPU_ALLOC_SIZE(newncpus);
6606             CPU_ZERO_S(newsetsize, newmask);
6607             memcpy(newmask, cpu_set, setsize);
6608             CPU_FREE(cpu_set);
6609             setsize = newsetsize;
6610             cpu_set = newmask;
6611             ncpus = newncpus;
6612         }
6613         CPU_SET_S(cpu, setsize, cpu_set);
6614     }
6615     if (PyErr_Occurred()) {
6616         goto error;
6617     }
6618     Py_CLEAR(iterator);
6619 
6620     if (sched_setaffinity(pid, setsize, cpu_set)) {
6621         posix_error();
6622         goto error;
6623     }
6624     CPU_FREE(cpu_set);
6625     Py_RETURN_NONE;
6626 
6627 error:
6628     if (cpu_set)
6629         CPU_FREE(cpu_set);
6630     Py_XDECREF(iterator);
6631     return NULL;
6632 }
6633 
6634 
6635 /*[clinic input]
6636 os.sched_getaffinity
6637     pid: pid_t
6638     /
6639 
6640 Return the affinity of the process identified by pid (or the current process if zero).
6641 
6642 The affinity is returned as a set of CPU identifiers.
6643 [clinic start generated code]*/
6644 
6645 static PyObject *
os_sched_getaffinity_impl(PyObject * module,pid_t pid)6646 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
6647 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
6648 {
6649     int cpu, ncpus, count;
6650     size_t setsize;
6651     cpu_set_t *mask = NULL;
6652     PyObject *res = NULL;
6653 
6654     ncpus = NCPUS_START;
6655     while (1) {
6656         setsize = CPU_ALLOC_SIZE(ncpus);
6657         mask = CPU_ALLOC(ncpus);
6658         if (mask == NULL)
6659             return PyErr_NoMemory();
6660         if (sched_getaffinity(pid, setsize, mask) == 0)
6661             break;
6662         CPU_FREE(mask);
6663         if (errno != EINVAL)
6664             return posix_error();
6665         if (ncpus > INT_MAX / 2) {
6666             PyErr_SetString(PyExc_OverflowError, "could not allocate "
6667                             "a large enough CPU set");
6668             return NULL;
6669         }
6670         ncpus = ncpus * 2;
6671     }
6672 
6673     res = PySet_New(NULL);
6674     if (res == NULL)
6675         goto error;
6676     for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
6677         if (CPU_ISSET_S(cpu, setsize, mask)) {
6678             PyObject *cpu_num = PyLong_FromLong(cpu);
6679             --count;
6680             if (cpu_num == NULL)
6681                 goto error;
6682             if (PySet_Add(res, cpu_num)) {
6683                 Py_DECREF(cpu_num);
6684                 goto error;
6685             }
6686             Py_DECREF(cpu_num);
6687         }
6688     }
6689     CPU_FREE(mask);
6690     return res;
6691 
6692 error:
6693     if (mask)
6694         CPU_FREE(mask);
6695     Py_XDECREF(res);
6696     return NULL;
6697 }
6698 
6699 #endif /* HAVE_SCHED_SETAFFINITY */
6700 
6701 #endif /* HAVE_SCHED_H */
6702 
6703 
6704 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
6705 /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
6706 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
6707 #define DEV_PTY_FILE "/dev/ptc"
6708 #define HAVE_DEV_PTMX
6709 #else
6710 #define DEV_PTY_FILE "/dev/ptmx"
6711 #endif
6712 
6713 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
6714 #ifdef HAVE_PTY_H
6715 #include <pty.h>
6716 #else
6717 #ifdef HAVE_LIBUTIL_H
6718 #include <libutil.h>
6719 #else
6720 #ifdef HAVE_UTIL_H
6721 #include <util.h>
6722 #endif /* HAVE_UTIL_H */
6723 #endif /* HAVE_LIBUTIL_H */
6724 #endif /* HAVE_PTY_H */
6725 #ifdef HAVE_STROPTS_H
6726 #include <stropts.h>
6727 #endif
6728 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */
6729 
6730 
6731 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
6732 /*[clinic input]
6733 os.openpty
6734 
6735 Open a pseudo-terminal.
6736 
6737 Return a tuple of (master_fd, slave_fd) containing open file descriptors
6738 for both the master and slave ends.
6739 [clinic start generated code]*/
6740 
6741 static PyObject *
os_openpty_impl(PyObject * module)6742 os_openpty_impl(PyObject *module)
6743 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
6744 {
6745     int master_fd = -1, slave_fd = -1;
6746 #ifndef HAVE_OPENPTY
6747     char * slave_name;
6748 #endif
6749 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
6750     PyOS_sighandler_t sig_saved;
6751 #if defined(__sun) && defined(__SVR4)
6752     extern char *ptsname(int fildes);
6753 #endif
6754 #endif
6755 
6756 #ifdef HAVE_OPENPTY
6757     if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
6758         goto posix_error;
6759 
6760     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
6761         goto error;
6762     if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
6763         goto error;
6764 
6765 #elif defined(HAVE__GETPTY)
6766     slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
6767     if (slave_name == NULL)
6768         goto posix_error;
6769     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
6770         goto error;
6771 
6772     slave_fd = _Py_open(slave_name, O_RDWR);
6773     if (slave_fd < 0)
6774         goto error;
6775 
6776 #else
6777     master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
6778     if (master_fd < 0)
6779         goto posix_error;
6780 
6781     sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
6782 
6783     /* change permission of slave */
6784     if (grantpt(master_fd) < 0) {
6785         PyOS_setsig(SIGCHLD, sig_saved);
6786         goto posix_error;
6787     }
6788 
6789     /* unlock slave */
6790     if (unlockpt(master_fd) < 0) {
6791         PyOS_setsig(SIGCHLD, sig_saved);
6792         goto posix_error;
6793     }
6794 
6795     PyOS_setsig(SIGCHLD, sig_saved);
6796 
6797     slave_name = ptsname(master_fd); /* get name of slave */
6798     if (slave_name == NULL)
6799         goto posix_error;
6800 
6801     slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
6802     if (slave_fd == -1)
6803         goto error;
6804 
6805     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
6806         goto posix_error;
6807 
6808 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
6809     ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
6810     ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
6811 #ifndef __hpux
6812     ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
6813 #endif /* __hpux */
6814 #endif /* HAVE_CYGWIN */
6815 #endif /* HAVE_OPENPTY */
6816 
6817     return Py_BuildValue("(ii)", master_fd, slave_fd);
6818 
6819 posix_error:
6820     posix_error();
6821 error:
6822     if (master_fd != -1)
6823         close(master_fd);
6824     if (slave_fd != -1)
6825         close(slave_fd);
6826     return NULL;
6827 }
6828 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
6829 
6830 
6831 #ifdef HAVE_FORKPTY
6832 /*[clinic input]
6833 os.forkpty
6834 
6835 Fork a new process with a new pseudo-terminal as controlling tty.
6836 
6837 Returns a tuple of (pid, master_fd).
6838 Like fork(), return pid of 0 to the child process,
6839 and pid of child to the parent process.
6840 To both, return fd of newly opened pseudo-terminal.
6841 [clinic start generated code]*/
6842 
6843 static PyObject *
os_forkpty_impl(PyObject * module)6844 os_forkpty_impl(PyObject *module)
6845 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
6846 {
6847     int master_fd = -1;
6848     pid_t pid;
6849 
6850     if (_PyInterpreterState_Get() != PyInterpreterState_Main()) {
6851         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6852         return NULL;
6853     }
6854     if (PySys_Audit("os.forkpty", NULL) < 0) {
6855         return NULL;
6856     }
6857     PyOS_BeforeFork();
6858     pid = forkpty(&master_fd, NULL, NULL, NULL);
6859     if (pid == 0) {
6860         /* child: this clobbers and resets the import lock. */
6861         PyOS_AfterFork_Child();
6862     } else {
6863         /* parent: release the import lock. */
6864         PyOS_AfterFork_Parent();
6865     }
6866     if (pid == -1)
6867         return posix_error();
6868     return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
6869 }
6870 #endif /* HAVE_FORKPTY */
6871 
6872 
6873 #ifdef HAVE_GETEGID
6874 /*[clinic input]
6875 os.getegid
6876 
6877 Return the current process's effective group id.
6878 [clinic start generated code]*/
6879 
6880 static PyObject *
os_getegid_impl(PyObject * module)6881 os_getegid_impl(PyObject *module)
6882 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
6883 {
6884     return _PyLong_FromGid(getegid());
6885 }
6886 #endif /* HAVE_GETEGID */
6887 
6888 
6889 #ifdef HAVE_GETEUID
6890 /*[clinic input]
6891 os.geteuid
6892 
6893 Return the current process's effective user id.
6894 [clinic start generated code]*/
6895 
6896 static PyObject *
os_geteuid_impl(PyObject * module)6897 os_geteuid_impl(PyObject *module)
6898 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
6899 {
6900     return _PyLong_FromUid(geteuid());
6901 }
6902 #endif /* HAVE_GETEUID */
6903 
6904 
6905 #ifdef HAVE_GETGID
6906 /*[clinic input]
6907 os.getgid
6908 
6909 Return the current process's group id.
6910 [clinic start generated code]*/
6911 
6912 static PyObject *
os_getgid_impl(PyObject * module)6913 os_getgid_impl(PyObject *module)
6914 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
6915 {
6916     return _PyLong_FromGid(getgid());
6917 }
6918 #endif /* HAVE_GETGID */
6919 
6920 
6921 #ifdef HAVE_GETPID
6922 /*[clinic input]
6923 os.getpid
6924 
6925 Return the current process id.
6926 [clinic start generated code]*/
6927 
6928 static PyObject *
os_getpid_impl(PyObject * module)6929 os_getpid_impl(PyObject *module)
6930 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
6931 {
6932     return PyLong_FromPid(getpid());
6933 }
6934 #endif /* HAVE_GETPID */
6935 
6936 #ifdef NGROUPS_MAX
6937 #define MAX_GROUPS NGROUPS_MAX
6938 #else
6939     /* defined to be 16 on Solaris7, so this should be a small number */
6940 #define MAX_GROUPS 64
6941 #endif
6942 
6943 #ifdef HAVE_GETGROUPLIST
6944 
6945 /* AC 3.5: funny apple logic below */
6946 PyDoc_STRVAR(posix_getgrouplist__doc__,
6947 "getgrouplist(user, group) -> list of groups to which a user belongs\n\n\
6948 Returns a list of groups to which a user belongs.\n\n\
6949     user: username to lookup\n\
6950     group: base group id of the user");
6951 
6952 static PyObject *
posix_getgrouplist(PyObject * self,PyObject * args)6953 posix_getgrouplist(PyObject *self, PyObject *args)
6954 {
6955     const char *user;
6956     int i, ngroups;
6957     PyObject *list;
6958 #ifdef __APPLE__
6959     int *groups, basegid;
6960 #else
6961     gid_t *groups, basegid;
6962 #endif
6963 
6964     /*
6965      * NGROUPS_MAX is defined by POSIX.1 as the maximum
6966      * number of supplimental groups a users can belong to.
6967      * We have to increment it by one because
6968      * getgrouplist() returns both the supplemental groups
6969      * and the primary group, i.e. all of the groups the
6970      * user belongs to.
6971      */
6972     ngroups = 1 + MAX_GROUPS;
6973 
6974 #ifdef __APPLE__
6975     if (!PyArg_ParseTuple(args, "si:getgrouplist", &user, &basegid))
6976         return NULL;
6977 #else
6978     if (!PyArg_ParseTuple(args, "sO&:getgrouplist", &user,
6979                           _Py_Gid_Converter, &basegid))
6980         return NULL;
6981 #endif
6982 
6983     while (1) {
6984 #ifdef __APPLE__
6985         groups = PyMem_New(int, ngroups);
6986 #else
6987         groups = PyMem_New(gid_t, ngroups);
6988 #endif
6989         if (groups == NULL) {
6990             return PyErr_NoMemory();
6991         }
6992 
6993         int old_ngroups = ngroups;
6994         if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
6995             /* Success */
6996             break;
6997         }
6998 
6999         /* getgrouplist() fails if the group list is too small */
7000         PyMem_Free(groups);
7001 
7002         if (ngroups > old_ngroups) {
7003             /* If the group list is too small, the glibc implementation of
7004                getgrouplist() sets ngroups to the total number of groups and
7005                returns -1. */
7006         }
7007         else {
7008             /* Double the group list size */
7009             if (ngroups > INT_MAX / 2) {
7010                 return PyErr_NoMemory();
7011             }
7012             ngroups *= 2;
7013         }
7014 
7015         /* Retry getgrouplist() with a larger group list */
7016     }
7017 
7018 #ifdef _Py_MEMORY_SANITIZER
7019     /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
7020     __msan_unpoison(&ngroups, sizeof(ngroups));
7021     __msan_unpoison(groups, ngroups*sizeof(*groups));
7022 #endif
7023 
7024     list = PyList_New(ngroups);
7025     if (list == NULL) {
7026         PyMem_Del(groups);
7027         return NULL;
7028     }
7029 
7030     for (i = 0; i < ngroups; i++) {
7031 #ifdef __APPLE__
7032         PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7033 #else
7034         PyObject *o = _PyLong_FromGid(groups[i]);
7035 #endif
7036         if (o == NULL) {
7037             Py_DECREF(list);
7038             PyMem_Del(groups);
7039             return NULL;
7040         }
7041         PyList_SET_ITEM(list, i, o);
7042     }
7043 
7044     PyMem_Del(groups);
7045 
7046     return list;
7047 }
7048 #endif /* HAVE_GETGROUPLIST */
7049 
7050 
7051 #ifdef HAVE_GETGROUPS
7052 /*[clinic input]
7053 os.getgroups
7054 
7055 Return list of supplemental group IDs for the process.
7056 [clinic start generated code]*/
7057 
7058 static PyObject *
os_getgroups_impl(PyObject * module)7059 os_getgroups_impl(PyObject *module)
7060 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
7061 {
7062     PyObject *result = NULL;
7063     gid_t grouplist[MAX_GROUPS];
7064 
7065     /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
7066      * This is a helper variable to store the intermediate result when
7067      * that happens.
7068      *
7069      * To keep the code readable the OSX behaviour is unconditional,
7070      * according to the POSIX spec this should be safe on all unix-y
7071      * systems.
7072      */
7073     gid_t* alt_grouplist = grouplist;
7074     int n;
7075 
7076 #ifdef __APPLE__
7077     /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if
7078      * there are more groups than can fit in grouplist.  Therefore, on OS X
7079      * always first call getgroups with length 0 to get the actual number
7080      * of groups.
7081      */
7082     n = getgroups(0, NULL);
7083     if (n < 0) {
7084         return posix_error();
7085     } else if (n <= MAX_GROUPS) {
7086         /* groups will fit in existing array */
7087         alt_grouplist = grouplist;
7088     } else {
7089         alt_grouplist = PyMem_New(gid_t, n);
7090         if (alt_grouplist == NULL) {
7091             return PyErr_NoMemory();
7092         }
7093     }
7094 
7095     n = getgroups(n, alt_grouplist);
7096     if (n == -1) {
7097         if (alt_grouplist != grouplist) {
7098             PyMem_Free(alt_grouplist);
7099         }
7100         return posix_error();
7101     }
7102 #else
7103     n = getgroups(MAX_GROUPS, grouplist);
7104     if (n < 0) {
7105         if (errno == EINVAL) {
7106             n = getgroups(0, NULL);
7107             if (n == -1) {
7108                 return posix_error();
7109             }
7110             if (n == 0) {
7111                 /* Avoid malloc(0) */
7112                 alt_grouplist = grouplist;
7113             } else {
7114                 alt_grouplist = PyMem_New(gid_t, n);
7115                 if (alt_grouplist == NULL) {
7116                     return PyErr_NoMemory();
7117                 }
7118                 n = getgroups(n, alt_grouplist);
7119                 if (n == -1) {
7120                     PyMem_Free(alt_grouplist);
7121                     return posix_error();
7122                 }
7123             }
7124         } else {
7125             return posix_error();
7126         }
7127     }
7128 #endif
7129 
7130     result = PyList_New(n);
7131     if (result != NULL) {
7132         int i;
7133         for (i = 0; i < n; ++i) {
7134             PyObject *o = _PyLong_FromGid(alt_grouplist[i]);
7135             if (o == NULL) {
7136                 Py_DECREF(result);
7137                 result = NULL;
7138                 break;
7139             }
7140             PyList_SET_ITEM(result, i, o);
7141         }
7142     }
7143 
7144     if (alt_grouplist != grouplist) {
7145         PyMem_Free(alt_grouplist);
7146     }
7147 
7148     return result;
7149 }
7150 #endif /* HAVE_GETGROUPS */
7151 
7152 #ifdef HAVE_INITGROUPS
7153 PyDoc_STRVAR(posix_initgroups__doc__,
7154 "initgroups(username, gid) -> None\n\n\
7155 Call the system initgroups() to initialize the group access list with all of\n\
7156 the groups of which the specified username is a member, plus the specified\n\
7157 group id.");
7158 
7159 /* AC 3.5: funny apple logic */
7160 static PyObject *
posix_initgroups(PyObject * self,PyObject * args)7161 posix_initgroups(PyObject *self, PyObject *args)
7162 {
7163     PyObject *oname;
7164     const char *username;
7165     int res;
7166 #ifdef __APPLE__
7167     int gid;
7168 #else
7169     gid_t gid;
7170 #endif
7171 
7172 #ifdef __APPLE__
7173     if (!PyArg_ParseTuple(args, "O&i:initgroups",
7174                           PyUnicode_FSConverter, &oname,
7175                           &gid))
7176 #else
7177     if (!PyArg_ParseTuple(args, "O&O&:initgroups",
7178                           PyUnicode_FSConverter, &oname,
7179                           _Py_Gid_Converter, &gid))
7180 #endif
7181         return NULL;
7182     username = PyBytes_AS_STRING(oname);
7183 
7184     res = initgroups(username, gid);
7185     Py_DECREF(oname);
7186     if (res == -1)
7187         return PyErr_SetFromErrno(PyExc_OSError);
7188 
7189     Py_RETURN_NONE;
7190 }
7191 #endif /* HAVE_INITGROUPS */
7192 
7193 
7194 #ifdef HAVE_GETPGID
7195 /*[clinic input]
7196 os.getpgid
7197 
7198     pid: pid_t
7199 
7200 Call the system call getpgid(), and return the result.
7201 [clinic start generated code]*/
7202 
7203 static PyObject *
os_getpgid_impl(PyObject * module,pid_t pid)7204 os_getpgid_impl(PyObject *module, pid_t pid)
7205 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7206 {
7207     pid_t pgid = getpgid(pid);
7208     if (pgid < 0)
7209         return posix_error();
7210     return PyLong_FromPid(pgid);
7211 }
7212 #endif /* HAVE_GETPGID */
7213 
7214 
7215 #ifdef HAVE_GETPGRP
7216 /*[clinic input]
7217 os.getpgrp
7218 
7219 Return the current process group id.
7220 [clinic start generated code]*/
7221 
7222 static PyObject *
os_getpgrp_impl(PyObject * module)7223 os_getpgrp_impl(PyObject *module)
7224 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7225 {
7226 #ifdef GETPGRP_HAVE_ARG
7227     return PyLong_FromPid(getpgrp(0));
7228 #else /* GETPGRP_HAVE_ARG */
7229     return PyLong_FromPid(getpgrp());
7230 #endif /* GETPGRP_HAVE_ARG */
7231 }
7232 #endif /* HAVE_GETPGRP */
7233 
7234 
7235 #ifdef HAVE_SETPGRP
7236 /*[clinic input]
7237 os.setpgrp
7238 
7239 Make the current process the leader of its process group.
7240 [clinic start generated code]*/
7241 
7242 static PyObject *
os_setpgrp_impl(PyObject * module)7243 os_setpgrp_impl(PyObject *module)
7244 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7245 {
7246 #ifdef SETPGRP_HAVE_ARG
7247     if (setpgrp(0, 0) < 0)
7248 #else /* SETPGRP_HAVE_ARG */
7249     if (setpgrp() < 0)
7250 #endif /* SETPGRP_HAVE_ARG */
7251         return posix_error();
7252     Py_RETURN_NONE;
7253 }
7254 #endif /* HAVE_SETPGRP */
7255 
7256 #ifdef HAVE_GETPPID
7257 
7258 #ifdef MS_WINDOWS
7259 #include <tlhelp32.h>
7260 
7261 static PyObject*
win32_getppid()7262 win32_getppid()
7263 {
7264     HANDLE snapshot;
7265     pid_t mypid;
7266     PyObject* result = NULL;
7267     BOOL have_record;
7268     PROCESSENTRY32 pe;
7269 
7270     mypid = getpid(); /* This function never fails */
7271 
7272     snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7273     if (snapshot == INVALID_HANDLE_VALUE)
7274         return PyErr_SetFromWindowsErr(GetLastError());
7275 
7276     pe.dwSize = sizeof(pe);
7277     have_record = Process32First(snapshot, &pe);
7278     while (have_record) {
7279         if (mypid == (pid_t)pe.th32ProcessID) {
7280             /* We could cache the ulong value in a static variable. */
7281             result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7282             break;
7283         }
7284 
7285         have_record = Process32Next(snapshot, &pe);
7286     }
7287 
7288     /* If our loop exits and our pid was not found (result will be NULL)
7289      * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7290      * error anyway, so let's raise it. */
7291     if (!result)
7292         result = PyErr_SetFromWindowsErr(GetLastError());
7293 
7294     CloseHandle(snapshot);
7295 
7296     return result;
7297 }
7298 #endif /*MS_WINDOWS*/
7299 
7300 
7301 /*[clinic input]
7302 os.getppid
7303 
7304 Return the parent's process id.
7305 
7306 If the parent process has already exited, Windows machines will still
7307 return its id; others systems will return the id of the 'init' process (1).
7308 [clinic start generated code]*/
7309 
7310 static PyObject *
os_getppid_impl(PyObject * module)7311 os_getppid_impl(PyObject *module)
7312 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7313 {
7314 #ifdef MS_WINDOWS
7315     return win32_getppid();
7316 #else
7317     return PyLong_FromPid(getppid());
7318 #endif
7319 }
7320 #endif /* HAVE_GETPPID */
7321 
7322 
7323 #ifdef HAVE_GETLOGIN
7324 /*[clinic input]
7325 os.getlogin
7326 
7327 Return the actual login name.
7328 [clinic start generated code]*/
7329 
7330 static PyObject *
os_getlogin_impl(PyObject * module)7331 os_getlogin_impl(PyObject *module)
7332 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7333 {
7334     PyObject *result = NULL;
7335 #ifdef MS_WINDOWS
7336     wchar_t user_name[UNLEN + 1];
7337     DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7338 
7339     if (GetUserNameW(user_name, &num_chars)) {
7340         /* num_chars is the number of unicode chars plus null terminator */
7341         result = PyUnicode_FromWideChar(user_name, num_chars - 1);
7342     }
7343     else
7344         result = PyErr_SetFromWindowsErr(GetLastError());
7345 #else
7346     char *name;
7347     int old_errno = errno;
7348 
7349     errno = 0;
7350     name = getlogin();
7351     if (name == NULL) {
7352         if (errno)
7353             posix_error();
7354         else
7355             PyErr_SetString(PyExc_OSError, "unable to determine login name");
7356     }
7357     else
7358         result = PyUnicode_DecodeFSDefault(name);
7359     errno = old_errno;
7360 #endif
7361     return result;
7362 }
7363 #endif /* HAVE_GETLOGIN */
7364 
7365 
7366 #ifdef HAVE_GETUID
7367 /*[clinic input]
7368 os.getuid
7369 
7370 Return the current process's user id.
7371 [clinic start generated code]*/
7372 
7373 static PyObject *
os_getuid_impl(PyObject * module)7374 os_getuid_impl(PyObject *module)
7375 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7376 {
7377     return _PyLong_FromUid(getuid());
7378 }
7379 #endif /* HAVE_GETUID */
7380 
7381 
7382 #ifdef MS_WINDOWS
7383 #define HAVE_KILL
7384 #endif /* MS_WINDOWS */
7385 
7386 #ifdef HAVE_KILL
7387 /*[clinic input]
7388 os.kill
7389 
7390     pid: pid_t
7391     signal: Py_ssize_t
7392     /
7393 
7394 Kill a process with a signal.
7395 [clinic start generated code]*/
7396 
7397 static PyObject *
os_kill_impl(PyObject * module,pid_t pid,Py_ssize_t signal)7398 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
7399 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
7400 {
7401     if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
7402         return NULL;
7403     }
7404 #ifndef MS_WINDOWS
7405     if (kill(pid, (int)signal) == -1)
7406         return posix_error();
7407     Py_RETURN_NONE;
7408 #else /* !MS_WINDOWS */
7409     PyObject *result;
7410     DWORD sig = (DWORD)signal;
7411     DWORD err;
7412     HANDLE handle;
7413 
7414     /* Console processes which share a common console can be sent CTRL+C or
7415        CTRL+BREAK events, provided they handle said events. */
7416     if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
7417         if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
7418             err = GetLastError();
7419             PyErr_SetFromWindowsErr(err);
7420         }
7421         else
7422             Py_RETURN_NONE;
7423     }
7424 
7425     /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
7426        attempt to open and terminate the process. */
7427     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
7428     if (handle == NULL) {
7429         err = GetLastError();
7430         return PyErr_SetFromWindowsErr(err);
7431     }
7432 
7433     if (TerminateProcess(handle, sig) == 0) {
7434         err = GetLastError();
7435         result = PyErr_SetFromWindowsErr(err);
7436     } else {
7437         Py_INCREF(Py_None);
7438         result = Py_None;
7439     }
7440 
7441     CloseHandle(handle);
7442     return result;
7443 #endif /* !MS_WINDOWS */
7444 }
7445 #endif /* HAVE_KILL */
7446 
7447 
7448 #ifdef HAVE_KILLPG
7449 /*[clinic input]
7450 os.killpg
7451 
7452     pgid: pid_t
7453     signal: int
7454     /
7455 
7456 Kill a process group with a signal.
7457 [clinic start generated code]*/
7458 
7459 static PyObject *
os_killpg_impl(PyObject * module,pid_t pgid,int signal)7460 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
7461 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
7462 {
7463     if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
7464         return NULL;
7465     }
7466     /* XXX some man pages make the `pgid` parameter an int, others
7467        a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
7468        take the same type. Moreover, pid_t is always at least as wide as
7469        int (else compilation of this module fails), which is safe. */
7470     if (killpg(pgid, signal) == -1)
7471         return posix_error();
7472     Py_RETURN_NONE;
7473 }
7474 #endif /* HAVE_KILLPG */
7475 
7476 
7477 #ifdef HAVE_PLOCK
7478 #ifdef HAVE_SYS_LOCK_H
7479 #include <sys/lock.h>
7480 #endif
7481 
7482 /*[clinic input]
7483 os.plock
7484     op: int
7485     /
7486 
7487 Lock program segments into memory.");
7488 [clinic start generated code]*/
7489 
7490 static PyObject *
os_plock_impl(PyObject * module,int op)7491 os_plock_impl(PyObject *module, int op)
7492 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
7493 {
7494     if (plock(op) == -1)
7495         return posix_error();
7496     Py_RETURN_NONE;
7497 }
7498 #endif /* HAVE_PLOCK */
7499 
7500 
7501 #ifdef HAVE_SETUID
7502 /*[clinic input]
7503 os.setuid
7504 
7505     uid: uid_t
7506     /
7507 
7508 Set the current process's user id.
7509 [clinic start generated code]*/
7510 
7511 static PyObject *
os_setuid_impl(PyObject * module,uid_t uid)7512 os_setuid_impl(PyObject *module, uid_t uid)
7513 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
7514 {
7515     if (setuid(uid) < 0)
7516         return posix_error();
7517     Py_RETURN_NONE;
7518 }
7519 #endif /* HAVE_SETUID */
7520 
7521 
7522 #ifdef HAVE_SETEUID
7523 /*[clinic input]
7524 os.seteuid
7525 
7526     euid: uid_t
7527     /
7528 
7529 Set the current process's effective user id.
7530 [clinic start generated code]*/
7531 
7532 static PyObject *
os_seteuid_impl(PyObject * module,uid_t euid)7533 os_seteuid_impl(PyObject *module, uid_t euid)
7534 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
7535 {
7536     if (seteuid(euid) < 0)
7537         return posix_error();
7538     Py_RETURN_NONE;
7539 }
7540 #endif /* HAVE_SETEUID */
7541 
7542 
7543 #ifdef HAVE_SETEGID
7544 /*[clinic input]
7545 os.setegid
7546 
7547     egid: gid_t
7548     /
7549 
7550 Set the current process's effective group id.
7551 [clinic start generated code]*/
7552 
7553 static PyObject *
os_setegid_impl(PyObject * module,gid_t egid)7554 os_setegid_impl(PyObject *module, gid_t egid)
7555 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
7556 {
7557     if (setegid(egid) < 0)
7558         return posix_error();
7559     Py_RETURN_NONE;
7560 }
7561 #endif /* HAVE_SETEGID */
7562 
7563 
7564 #ifdef HAVE_SETREUID
7565 /*[clinic input]
7566 os.setreuid
7567 
7568     ruid: uid_t
7569     euid: uid_t
7570     /
7571 
7572 Set the current process's real and effective user ids.
7573 [clinic start generated code]*/
7574 
7575 static PyObject *
os_setreuid_impl(PyObject * module,uid_t ruid,uid_t euid)7576 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
7577 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
7578 {
7579     if (setreuid(ruid, euid) < 0) {
7580         return posix_error();
7581     } else {
7582         Py_RETURN_NONE;
7583     }
7584 }
7585 #endif /* HAVE_SETREUID */
7586 
7587 
7588 #ifdef HAVE_SETREGID
7589 /*[clinic input]
7590 os.setregid
7591 
7592     rgid: gid_t
7593     egid: gid_t
7594     /
7595 
7596 Set the current process's real and effective group ids.
7597 [clinic start generated code]*/
7598 
7599 static PyObject *
os_setregid_impl(PyObject * module,gid_t rgid,gid_t egid)7600 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
7601 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
7602 {
7603     if (setregid(rgid, egid) < 0)
7604         return posix_error();
7605     Py_RETURN_NONE;
7606 }
7607 #endif /* HAVE_SETREGID */
7608 
7609 
7610 #ifdef HAVE_SETGID
7611 /*[clinic input]
7612 os.setgid
7613     gid: gid_t
7614     /
7615 
7616 Set the current process's group id.
7617 [clinic start generated code]*/
7618 
7619 static PyObject *
os_setgid_impl(PyObject * module,gid_t gid)7620 os_setgid_impl(PyObject *module, gid_t gid)
7621 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
7622 {
7623     if (setgid(gid) < 0)
7624         return posix_error();
7625     Py_RETURN_NONE;
7626 }
7627 #endif /* HAVE_SETGID */
7628 
7629 
7630 #ifdef HAVE_SETGROUPS
7631 /*[clinic input]
7632 os.setgroups
7633 
7634     groups: object
7635     /
7636 
7637 Set the groups of the current process to list.
7638 [clinic start generated code]*/
7639 
7640 static PyObject *
os_setgroups(PyObject * module,PyObject * groups)7641 os_setgroups(PyObject *module, PyObject *groups)
7642 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
7643 {
7644     Py_ssize_t i, len;
7645     gid_t grouplist[MAX_GROUPS];
7646 
7647     if (!PySequence_Check(groups)) {
7648         PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
7649         return NULL;
7650     }
7651     len = PySequence_Size(groups);
7652     if (len < 0) {
7653         return NULL;
7654     }
7655     if (len > MAX_GROUPS) {
7656         PyErr_SetString(PyExc_ValueError, "too many groups");
7657         return NULL;
7658     }
7659     for(i = 0; i < len; i++) {
7660         PyObject *elem;
7661         elem = PySequence_GetItem(groups, i);
7662         if (!elem)
7663             return NULL;
7664         if (!PyLong_Check(elem)) {
7665             PyErr_SetString(PyExc_TypeError,
7666                             "groups must be integers");
7667             Py_DECREF(elem);
7668             return NULL;
7669         } else {
7670             if (!_Py_Gid_Converter(elem, &grouplist[i])) {
7671                 Py_DECREF(elem);
7672                 return NULL;
7673             }
7674         }
7675         Py_DECREF(elem);
7676     }
7677 
7678     if (setgroups(len, grouplist) < 0)
7679         return posix_error();
7680     Py_RETURN_NONE;
7681 }
7682 #endif /* HAVE_SETGROUPS */
7683 
7684 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
7685 static PyObject *
wait_helper(pid_t pid,int status,struct rusage * ru)7686 wait_helper(pid_t pid, int status, struct rusage *ru)
7687 {
7688     PyObject *result;
7689     static PyObject *struct_rusage;
7690     _Py_IDENTIFIER(struct_rusage);
7691 
7692     if (pid == -1)
7693         return posix_error();
7694 
7695     if (struct_rusage == NULL) {
7696         PyObject *m = PyImport_ImportModuleNoBlock("resource");
7697         if (m == NULL)
7698             return NULL;
7699         struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage);
7700         Py_DECREF(m);
7701         if (struct_rusage == NULL)
7702             return NULL;
7703     }
7704 
7705     /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
7706     result = PyStructSequence_New((PyTypeObject*) struct_rusage);
7707     if (!result)
7708         return NULL;
7709 
7710 #ifndef doubletime
7711 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
7712 #endif
7713 
7714     PyStructSequence_SET_ITEM(result, 0,
7715                               PyFloat_FromDouble(doubletime(ru->ru_utime)));
7716     PyStructSequence_SET_ITEM(result, 1,
7717                               PyFloat_FromDouble(doubletime(ru->ru_stime)));
7718 #define SET_INT(result, index, value)\
7719         PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
7720     SET_INT(result, 2, ru->ru_maxrss);
7721     SET_INT(result, 3, ru->ru_ixrss);
7722     SET_INT(result, 4, ru->ru_idrss);
7723     SET_INT(result, 5, ru->ru_isrss);
7724     SET_INT(result, 6, ru->ru_minflt);
7725     SET_INT(result, 7, ru->ru_majflt);
7726     SET_INT(result, 8, ru->ru_nswap);
7727     SET_INT(result, 9, ru->ru_inblock);
7728     SET_INT(result, 10, ru->ru_oublock);
7729     SET_INT(result, 11, ru->ru_msgsnd);
7730     SET_INT(result, 12, ru->ru_msgrcv);
7731     SET_INT(result, 13, ru->ru_nsignals);
7732     SET_INT(result, 14, ru->ru_nvcsw);
7733     SET_INT(result, 15, ru->ru_nivcsw);
7734 #undef SET_INT
7735 
7736     if (PyErr_Occurred()) {
7737         Py_DECREF(result);
7738         return NULL;
7739     }
7740 
7741     return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
7742 }
7743 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
7744 
7745 
7746 #ifdef HAVE_WAIT3
7747 /*[clinic input]
7748 os.wait3
7749 
7750     options: int
7751 Wait for completion of a child process.
7752 
7753 Returns a tuple of information about the child process:
7754   (pid, status, rusage)
7755 [clinic start generated code]*/
7756 
7757 static PyObject *
os_wait3_impl(PyObject * module,int options)7758 os_wait3_impl(PyObject *module, int options)
7759 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
7760 {
7761     pid_t pid;
7762     struct rusage ru;
7763     int async_err = 0;
7764     WAIT_TYPE status;
7765     WAIT_STATUS_INT(status) = 0;
7766 
7767     do {
7768         Py_BEGIN_ALLOW_THREADS
7769         pid = wait3(&status, options, &ru);
7770         Py_END_ALLOW_THREADS
7771     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7772     if (pid < 0)
7773         return (!async_err) ? posix_error() : NULL;
7774 
7775     return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
7776 }
7777 #endif /* HAVE_WAIT3 */
7778 
7779 
7780 #ifdef HAVE_WAIT4
7781 /*[clinic input]
7782 
7783 os.wait4
7784 
7785     pid: pid_t
7786     options: int
7787 
7788 Wait for completion of a specific child process.
7789 
7790 Returns a tuple of information about the child process:
7791   (pid, status, rusage)
7792 [clinic start generated code]*/
7793 
7794 static PyObject *
os_wait4_impl(PyObject * module,pid_t pid,int options)7795 os_wait4_impl(PyObject *module, pid_t pid, int options)
7796 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
7797 {
7798     pid_t res;
7799     struct rusage ru;
7800     int async_err = 0;
7801     WAIT_TYPE status;
7802     WAIT_STATUS_INT(status) = 0;
7803 
7804     do {
7805         Py_BEGIN_ALLOW_THREADS
7806         res = wait4(pid, &status, options, &ru);
7807         Py_END_ALLOW_THREADS
7808     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7809     if (res < 0)
7810         return (!async_err) ? posix_error() : NULL;
7811 
7812     return wait_helper(res, WAIT_STATUS_INT(status), &ru);
7813 }
7814 #endif /* HAVE_WAIT4 */
7815 
7816 
7817 #if defined(HAVE_WAITID) && !defined(__APPLE__)
7818 /*[clinic input]
7819 os.waitid
7820 
7821     idtype: idtype_t
7822         Must be one of be P_PID, P_PGID or P_ALL.
7823     id: id_t
7824         The id to wait on.
7825     options: int
7826         Constructed from the ORing of one or more of WEXITED, WSTOPPED
7827         or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
7828     /
7829 
7830 Returns the result of waiting for a process or processes.
7831 
7832 Returns either waitid_result or None if WNOHANG is specified and there are
7833 no children in a waitable state.
7834 [clinic start generated code]*/
7835 
7836 static PyObject *
os_waitid_impl(PyObject * module,idtype_t idtype,id_t id,int options)7837 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
7838 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
7839 {
7840     PyObject *result;
7841     int res;
7842     int async_err = 0;
7843     siginfo_t si;
7844     si.si_pid = 0;
7845 
7846     do {
7847         Py_BEGIN_ALLOW_THREADS
7848         res = waitid(idtype, id, &si, options);
7849         Py_END_ALLOW_THREADS
7850     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7851     if (res < 0)
7852         return (!async_err) ? posix_error() : NULL;
7853 
7854     if (si.si_pid == 0)
7855         Py_RETURN_NONE;
7856 
7857     result = PyStructSequence_New(WaitidResultType);
7858     if (!result)
7859         return NULL;
7860 
7861     PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
7862     PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
7863     PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
7864     PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
7865     PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
7866     if (PyErr_Occurred()) {
7867         Py_DECREF(result);
7868         return NULL;
7869     }
7870 
7871     return result;
7872 }
7873 #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
7874 
7875 
7876 #if defined(HAVE_WAITPID)
7877 /*[clinic input]
7878 os.waitpid
7879     pid: pid_t
7880     options: int
7881     /
7882 
7883 Wait for completion of a given child process.
7884 
7885 Returns a tuple of information regarding the child process:
7886     (pid, status)
7887 
7888 The options argument is ignored on Windows.
7889 [clinic start generated code]*/
7890 
7891 static PyObject *
os_waitpid_impl(PyObject * module,pid_t pid,int options)7892 os_waitpid_impl(PyObject *module, pid_t pid, int options)
7893 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
7894 {
7895     pid_t res;
7896     int async_err = 0;
7897     WAIT_TYPE status;
7898     WAIT_STATUS_INT(status) = 0;
7899 
7900     do {
7901         Py_BEGIN_ALLOW_THREADS
7902         res = waitpid(pid, &status, options);
7903         Py_END_ALLOW_THREADS
7904     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7905     if (res < 0)
7906         return (!async_err) ? posix_error() : NULL;
7907 
7908     return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
7909 }
7910 #elif defined(HAVE_CWAIT)
7911 /* MS C has a variant of waitpid() that's usable for most purposes. */
7912 /*[clinic input]
7913 os.waitpid
7914     pid: intptr_t
7915     options: int
7916     /
7917 
7918 Wait for completion of a given process.
7919 
7920 Returns a tuple of information regarding the process:
7921     (pid, status << 8)
7922 
7923 The options argument is ignored on Windows.
7924 [clinic start generated code]*/
7925 
7926 static PyObject *
os_waitpid_impl(PyObject * module,intptr_t pid,int options)7927 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
7928 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
7929 {
7930     int status;
7931     intptr_t res;
7932     int async_err = 0;
7933 
7934     do {
7935         Py_BEGIN_ALLOW_THREADS
7936         _Py_BEGIN_SUPPRESS_IPH
7937         res = _cwait(&status, pid, options);
7938         _Py_END_SUPPRESS_IPH
7939         Py_END_ALLOW_THREADS
7940     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7941     if (res < 0)
7942         return (!async_err) ? posix_error() : NULL;
7943 
7944     unsigned long long ustatus = (unsigned int)status;
7945 
7946     /* shift the status left a byte so this is more like the POSIX waitpid */
7947     return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
7948 }
7949 #endif
7950 
7951 
7952 #ifdef HAVE_WAIT
7953 /*[clinic input]
7954 os.wait
7955 
7956 Wait for completion of a child process.
7957 
7958 Returns a tuple of information about the child process:
7959     (pid, status)
7960 [clinic start generated code]*/
7961 
7962 static PyObject *
os_wait_impl(PyObject * module)7963 os_wait_impl(PyObject *module)
7964 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
7965 {
7966     pid_t pid;
7967     int async_err = 0;
7968     WAIT_TYPE status;
7969     WAIT_STATUS_INT(status) = 0;
7970 
7971     do {
7972         Py_BEGIN_ALLOW_THREADS
7973         pid = wait(&status);
7974         Py_END_ALLOW_THREADS
7975     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7976     if (pid < 0)
7977         return (!async_err) ? posix_error() : NULL;
7978 
7979     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
7980 }
7981 #endif /* HAVE_WAIT */
7982 
7983 
7984 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
7985 /*[clinic input]
7986 os.readlink
7987 
7988     path: path_t
7989     *
7990     dir_fd: dir_fd(requires='readlinkat') = None
7991 
7992 Return a string representing the path to which the symbolic link points.
7993 
7994 If dir_fd is not None, it should be a file descriptor open to a directory,
7995 and path should be relative; path will then be relative to that directory.
7996 
7997 dir_fd may not be implemented on your platform.  If it is unavailable,
7998 using it will raise a NotImplementedError.
7999 [clinic start generated code]*/
8000 
8001 static PyObject *
os_readlink_impl(PyObject * module,path_t * path,int dir_fd)8002 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
8003 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
8004 {
8005 #if defined(HAVE_READLINK)
8006     char buffer[MAXPATHLEN+1];
8007     ssize_t length;
8008 
8009     Py_BEGIN_ALLOW_THREADS
8010 #ifdef HAVE_READLINKAT
8011     if (dir_fd != DEFAULT_DIR_FD)
8012         length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
8013     else
8014 #endif
8015         length = readlink(path->narrow, buffer, MAXPATHLEN);
8016     Py_END_ALLOW_THREADS
8017 
8018     if (length < 0) {
8019         return path_error(path);
8020     }
8021     buffer[length] = '\0';
8022 
8023     if (PyUnicode_Check(path->object))
8024         return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
8025     else
8026         return PyBytes_FromStringAndSize(buffer, length);
8027 #elif defined(MS_WINDOWS)
8028     DWORD n_bytes_returned;
8029     DWORD io_result = 0;
8030     HANDLE reparse_point_handle;
8031     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
8032     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
8033     PyObject *result = NULL;
8034 
8035     /* First get a handle to the reparse point */
8036     Py_BEGIN_ALLOW_THREADS
8037     reparse_point_handle = CreateFileW(
8038         path->wide,
8039         0,
8040         0,
8041         0,
8042         OPEN_EXISTING,
8043         FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
8044         0);
8045     if (reparse_point_handle != INVALID_HANDLE_VALUE) {
8046         /* New call DeviceIoControl to read the reparse point */
8047         io_result = DeviceIoControl(
8048             reparse_point_handle,
8049             FSCTL_GET_REPARSE_POINT,
8050             0, 0, /* in buffer */
8051             target_buffer, sizeof(target_buffer),
8052             &n_bytes_returned,
8053             0 /* we're not using OVERLAPPED_IO */
8054             );
8055         CloseHandle(reparse_point_handle);
8056     }
8057     Py_END_ALLOW_THREADS
8058 
8059     if (io_result == 0) {
8060         return path_error(path);
8061     }
8062 
8063     wchar_t *name = NULL;
8064     Py_ssize_t nameLen = 0;
8065     if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
8066     {
8067         name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
8068                            rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
8069         nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8070     }
8071     else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
8072     {
8073         name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8074                            rdb->MountPointReparseBuffer.SubstituteNameOffset);
8075         nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8076     }
8077     else
8078     {
8079         PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8080     }
8081     if (name) {
8082         if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8083             /* Our buffer is mutable, so this is okay */
8084             name[1] = L'\\';
8085         }
8086         result = PyUnicode_FromWideChar(name, nameLen);
8087         if (result && path->narrow) {
8088             Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8089         }
8090     }
8091     return result;
8092 #endif
8093 }
8094 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8095 
8096 #if defined(MS_WINDOWS)
8097 
8098 /* Remove the last portion of the path - return 0 on success */
8099 static int
_dirnameW(WCHAR * path)8100 _dirnameW(WCHAR *path)
8101 {
8102     WCHAR *ptr;
8103     size_t length = wcsnlen_s(path, MAX_PATH);
8104     if (length == MAX_PATH) {
8105         return -1;
8106     }
8107 
8108     /* walk the path from the end until a backslash is encountered */
8109     for(ptr = path + length; ptr != path; ptr--) {
8110         if (*ptr == L'\\' || *ptr == L'/') {
8111             break;
8112         }
8113     }
8114     *ptr = 0;
8115     return 0;
8116 }
8117 
8118 #endif
8119 
8120 #ifdef HAVE_SYMLINK
8121 
8122 #if defined(MS_WINDOWS)
8123 
8124 /* Is this path absolute? */
8125 static int
_is_absW(const WCHAR * path)8126 _is_absW(const WCHAR *path)
8127 {
8128     return path[0] == L'\\' || path[0] == L'/' ||
8129         (path[0] && path[1] == L':');
8130 }
8131 
8132 /* join root and rest with a backslash - return 0 on success */
8133 static int
_joinW(WCHAR * dest_path,const WCHAR * root,const WCHAR * rest)8134 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8135 {
8136     if (_is_absW(rest)) {
8137         return wcscpy_s(dest_path, MAX_PATH, rest);
8138     }
8139 
8140     if (wcscpy_s(dest_path, MAX_PATH, root)) {
8141         return -1;
8142     }
8143 
8144     if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8145         return -1;
8146     }
8147 
8148     return wcscat_s(dest_path, MAX_PATH, rest);
8149 }
8150 
8151 /* Return True if the path at src relative to dest is a directory */
8152 static int
_check_dirW(LPCWSTR src,LPCWSTR dest)8153 _check_dirW(LPCWSTR src, LPCWSTR dest)
8154 {
8155     WIN32_FILE_ATTRIBUTE_DATA src_info;
8156     WCHAR dest_parent[MAX_PATH];
8157     WCHAR src_resolved[MAX_PATH] = L"";
8158 
8159     /* dest_parent = os.path.dirname(dest) */
8160     if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8161         _dirnameW(dest_parent)) {
8162         return 0;
8163     }
8164     /* src_resolved = os.path.join(dest_parent, src) */
8165     if (_joinW(src_resolved, dest_parent, src)) {
8166         return 0;
8167     }
8168     return (
8169         GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8170         && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8171     );
8172 }
8173 #endif
8174 
8175 
8176 /*[clinic input]
8177 os.symlink
8178     src: path_t
8179     dst: path_t
8180     target_is_directory: bool = False
8181     *
8182     dir_fd: dir_fd(requires='symlinkat')=None
8183 
8184 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8185 
8186 Create a symbolic link pointing to src named dst.
8187 
8188 target_is_directory is required on Windows if the target is to be
8189   interpreted as a directory.  (On Windows, symlink requires
8190   Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8191   target_is_directory is ignored on non-Windows platforms.
8192 
8193 If dir_fd is not None, it should be a file descriptor open to a directory,
8194   and path should be relative; path will then be relative to that directory.
8195 dir_fd may not be implemented on your platform.
8196   If it is unavailable, using it will raise a NotImplementedError.
8197 
8198 [clinic start generated code]*/
8199 
8200 static PyObject *
os_symlink_impl(PyObject * module,path_t * src,path_t * dst,int target_is_directory,int dir_fd)8201 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8202                 int target_is_directory, int dir_fd)
8203 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8204 {
8205 #ifdef MS_WINDOWS
8206     DWORD result;
8207     DWORD flags = 0;
8208 
8209     /* Assumed true, set to false if detected to not be available. */
8210     static int windows_has_symlink_unprivileged_flag = TRUE;
8211 #else
8212     int result;
8213 #endif
8214 
8215     if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8216                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8217         return NULL;
8218     }
8219 
8220 #ifdef MS_WINDOWS
8221 
8222     if (windows_has_symlink_unprivileged_flag) {
8223         /* Allow non-admin symlinks if system allows it. */
8224         flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8225     }
8226 
8227     Py_BEGIN_ALLOW_THREADS
8228     _Py_BEGIN_SUPPRESS_IPH
8229     /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8230     if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8231         flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8232     }
8233 
8234     result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8235     _Py_END_SUPPRESS_IPH
8236     Py_END_ALLOW_THREADS
8237 
8238     if (windows_has_symlink_unprivileged_flag && !result &&
8239         ERROR_INVALID_PARAMETER == GetLastError()) {
8240 
8241         Py_BEGIN_ALLOW_THREADS
8242         _Py_BEGIN_SUPPRESS_IPH
8243         /* This error might be caused by
8244         SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8245         Try again, and update windows_has_symlink_unprivileged_flag if we
8246         are successful this time.
8247 
8248         NOTE: There is a risk of a race condition here if there are other
8249         conditions than the flag causing ERROR_INVALID_PARAMETER, and
8250         another process (or thread) changes that condition in between our
8251         calls to CreateSymbolicLink.
8252         */
8253         flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8254         result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8255         _Py_END_SUPPRESS_IPH
8256         Py_END_ALLOW_THREADS
8257 
8258         if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8259             windows_has_symlink_unprivileged_flag = FALSE;
8260         }
8261     }
8262 
8263     if (!result)
8264         return path_error2(src, dst);
8265 
8266 #else
8267 
8268     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8269         PyErr_SetString(PyExc_ValueError,
8270             "symlink: src and dst must be the same type");
8271         return NULL;
8272     }
8273 
8274     Py_BEGIN_ALLOW_THREADS
8275 #if HAVE_SYMLINKAT
8276     if (dir_fd != DEFAULT_DIR_FD)
8277         result = symlinkat(src->narrow, dir_fd, dst->narrow);
8278     else
8279 #endif
8280         result = symlink(src->narrow, dst->narrow);
8281     Py_END_ALLOW_THREADS
8282 
8283     if (result)
8284         return path_error2(src, dst);
8285 #endif
8286 
8287     Py_RETURN_NONE;
8288 }
8289 #endif /* HAVE_SYMLINK */
8290 
8291 
8292 
8293 
8294 static PyStructSequence_Field times_result_fields[] = {
8295     {"user",    "user time"},
8296     {"system",   "system time"},
8297     {"children_user",    "user time of children"},
8298     {"children_system",    "system time of children"},
8299     {"elapsed",    "elapsed time since an arbitrary point in the past"},
8300     {NULL}
8301 };
8302 
8303 PyDoc_STRVAR(times_result__doc__,
8304 "times_result: Result from os.times().\n\n\
8305 This object may be accessed either as a tuple of\n\
8306   (user, system, children_user, children_system, elapsed),\n\
8307 or via the attributes user, system, children_user, children_system,\n\
8308 and elapsed.\n\
8309 \n\
8310 See os.times for more information.");
8311 
8312 static PyStructSequence_Desc times_result_desc = {
8313     "times_result", /* name */
8314     times_result__doc__, /* doc */
8315     times_result_fields,
8316     5
8317 };
8318 
8319 static PyTypeObject* TimesResultType;
8320 
8321 #ifdef MS_WINDOWS
8322 #define HAVE_TIMES  /* mandatory, for the method table */
8323 #endif
8324 
8325 #ifdef HAVE_TIMES
8326 
8327 static PyObject *
build_times_result(double user,double system,double children_user,double children_system,double elapsed)8328 build_times_result(double user, double system,
8329     double children_user, double children_system,
8330     double elapsed)
8331 {
8332     PyObject *value = PyStructSequence_New(TimesResultType);
8333     if (value == NULL)
8334         return NULL;
8335 
8336 #define SET(i, field) \
8337     { \
8338     PyObject *o = PyFloat_FromDouble(field); \
8339     if (!o) { \
8340         Py_DECREF(value); \
8341         return NULL; \
8342     } \
8343     PyStructSequence_SET_ITEM(value, i, o); \
8344     } \
8345 
8346     SET(0, user);
8347     SET(1, system);
8348     SET(2, children_user);
8349     SET(3, children_system);
8350     SET(4, elapsed);
8351 
8352 #undef SET
8353 
8354     return value;
8355 }
8356 
8357 
8358 #ifndef MS_WINDOWS
8359 #define NEED_TICKS_PER_SECOND
8360 static long ticks_per_second = -1;
8361 #endif /* MS_WINDOWS */
8362 
8363 /*[clinic input]
8364 os.times
8365 
8366 Return a collection containing process timing information.
8367 
8368 The object returned behaves like a named tuple with these fields:
8369   (utime, stime, cutime, cstime, elapsed_time)
8370 All fields are floating point numbers.
8371 [clinic start generated code]*/
8372 
8373 static PyObject *
os_times_impl(PyObject * module)8374 os_times_impl(PyObject *module)
8375 /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
8376 #ifdef MS_WINDOWS
8377 {
8378     FILETIME create, exit, kernel, user;
8379     HANDLE hProc;
8380     hProc = GetCurrentProcess();
8381     GetProcessTimes(hProc, &create, &exit, &kernel, &user);
8382     /* The fields of a FILETIME structure are the hi and lo part
8383        of a 64-bit value expressed in 100 nanosecond units.
8384        1e7 is one second in such units; 1e-7 the inverse.
8385        429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
8386     */
8387     return build_times_result(
8388         (double)(user.dwHighDateTime*429.4967296 +
8389                  user.dwLowDateTime*1e-7),
8390         (double)(kernel.dwHighDateTime*429.4967296 +
8391                  kernel.dwLowDateTime*1e-7),
8392         (double)0,
8393         (double)0,
8394         (double)0);
8395 }
8396 #else /* MS_WINDOWS */
8397 {
8398 
8399 
8400     struct tms t;
8401     clock_t c;
8402     errno = 0;
8403     c = times(&t);
8404     if (c == (clock_t) -1)
8405         return posix_error();
8406     return build_times_result(
8407                          (double)t.tms_utime / ticks_per_second,
8408                          (double)t.tms_stime / ticks_per_second,
8409                          (double)t.tms_cutime / ticks_per_second,
8410                          (double)t.tms_cstime / ticks_per_second,
8411                          (double)c / ticks_per_second);
8412 }
8413 #endif /* MS_WINDOWS */
8414 #endif /* HAVE_TIMES */
8415 
8416 
8417 #ifdef HAVE_GETSID
8418 /*[clinic input]
8419 os.getsid
8420 
8421     pid: pid_t
8422     /
8423 
8424 Call the system call getsid(pid) and return the result.
8425 [clinic start generated code]*/
8426 
8427 static PyObject *
os_getsid_impl(PyObject * module,pid_t pid)8428 os_getsid_impl(PyObject *module, pid_t pid)
8429 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
8430 {
8431     int sid;
8432     sid = getsid(pid);
8433     if (sid < 0)
8434         return posix_error();
8435     return PyLong_FromLong((long)sid);
8436 }
8437 #endif /* HAVE_GETSID */
8438 
8439 
8440 #ifdef HAVE_SETSID
8441 /*[clinic input]
8442 os.setsid
8443 
8444 Call the system call setsid().
8445 [clinic start generated code]*/
8446 
8447 static PyObject *
os_setsid_impl(PyObject * module)8448 os_setsid_impl(PyObject *module)
8449 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
8450 {
8451     if (setsid() < 0)
8452         return posix_error();
8453     Py_RETURN_NONE;
8454 }
8455 #endif /* HAVE_SETSID */
8456 
8457 
8458 #ifdef HAVE_SETPGID
8459 /*[clinic input]
8460 os.setpgid
8461 
8462     pid: pid_t
8463     pgrp: pid_t
8464     /
8465 
8466 Call the system call setpgid(pid, pgrp).
8467 [clinic start generated code]*/
8468 
8469 static PyObject *
os_setpgid_impl(PyObject * module,pid_t pid,pid_t pgrp)8470 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
8471 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
8472 {
8473     if (setpgid(pid, pgrp) < 0)
8474         return posix_error();
8475     Py_RETURN_NONE;
8476 }
8477 #endif /* HAVE_SETPGID */
8478 
8479 
8480 #ifdef HAVE_TCGETPGRP
8481 /*[clinic input]
8482 os.tcgetpgrp
8483 
8484     fd: int
8485     /
8486 
8487 Return the process group associated with the terminal specified by fd.
8488 [clinic start generated code]*/
8489 
8490 static PyObject *
os_tcgetpgrp_impl(PyObject * module,int fd)8491 os_tcgetpgrp_impl(PyObject *module, int fd)
8492 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
8493 {
8494     pid_t pgid = tcgetpgrp(fd);
8495     if (pgid < 0)
8496         return posix_error();
8497     return PyLong_FromPid(pgid);
8498 }
8499 #endif /* HAVE_TCGETPGRP */
8500 
8501 
8502 #ifdef HAVE_TCSETPGRP
8503 /*[clinic input]
8504 os.tcsetpgrp
8505 
8506     fd: int
8507     pgid: pid_t
8508     /
8509 
8510 Set the process group associated with the terminal specified by fd.
8511 [clinic start generated code]*/
8512 
8513 static PyObject *
os_tcsetpgrp_impl(PyObject * module,int fd,pid_t pgid)8514 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
8515 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
8516 {
8517     if (tcsetpgrp(fd, pgid) < 0)
8518         return posix_error();
8519     Py_RETURN_NONE;
8520 }
8521 #endif /* HAVE_TCSETPGRP */
8522 
8523 /* Functions acting on file descriptors */
8524 
8525 #ifdef O_CLOEXEC
8526 extern int _Py_open_cloexec_works;
8527 #endif
8528 
8529 
8530 /*[clinic input]
8531 os.open -> int
8532     path: path_t
8533     flags: int
8534     mode: int = 0o777
8535     *
8536     dir_fd: dir_fd(requires='openat') = None
8537 
8538 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
8539 
8540 Open a file for low level IO.  Returns a file descriptor (integer).
8541 
8542 If dir_fd is not None, it should be a file descriptor open to a directory,
8543   and path should be relative; path will then be relative to that directory.
8544 dir_fd may not be implemented on your platform.
8545   If it is unavailable, using it will raise a NotImplementedError.
8546 [clinic start generated code]*/
8547 
8548 static int
os_open_impl(PyObject * module,path_t * path,int flags,int mode,int dir_fd)8549 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
8550 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
8551 {
8552     int fd;
8553     int async_err = 0;
8554 
8555 #ifdef O_CLOEXEC
8556     int *atomic_flag_works = &_Py_open_cloexec_works;
8557 #elif !defined(MS_WINDOWS)
8558     int *atomic_flag_works = NULL;
8559 #endif
8560 
8561 #ifdef MS_WINDOWS
8562     flags |= O_NOINHERIT;
8563 #elif defined(O_CLOEXEC)
8564     flags |= O_CLOEXEC;
8565 #endif
8566 
8567     if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
8568         return -1;
8569     }
8570 
8571     _Py_BEGIN_SUPPRESS_IPH
8572     do {
8573         Py_BEGIN_ALLOW_THREADS
8574 #ifdef MS_WINDOWS
8575         fd = _wopen(path->wide, flags, mode);
8576 #else
8577 #ifdef HAVE_OPENAT
8578         if (dir_fd != DEFAULT_DIR_FD)
8579             fd = openat(dir_fd, path->narrow, flags, mode);
8580         else
8581 #endif /* HAVE_OPENAT */
8582             fd = open(path->narrow, flags, mode);
8583 #endif /* !MS_WINDOWS */
8584         Py_END_ALLOW_THREADS
8585     } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8586     _Py_END_SUPPRESS_IPH
8587 
8588     if (fd < 0) {
8589         if (!async_err)
8590             PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
8591         return -1;
8592     }
8593 
8594 #ifndef MS_WINDOWS
8595     if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
8596         close(fd);
8597         return -1;
8598     }
8599 #endif
8600 
8601     return fd;
8602 }
8603 
8604 
8605 /*[clinic input]
8606 os.close
8607 
8608     fd: int
8609 
8610 Close a file descriptor.
8611 [clinic start generated code]*/
8612 
8613 static PyObject *
os_close_impl(PyObject * module,int fd)8614 os_close_impl(PyObject *module, int fd)
8615 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
8616 {
8617     int res;
8618     /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
8619      * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
8620      * for more details.
8621      */
8622     Py_BEGIN_ALLOW_THREADS
8623     _Py_BEGIN_SUPPRESS_IPH
8624     res = close(fd);
8625     _Py_END_SUPPRESS_IPH
8626     Py_END_ALLOW_THREADS
8627     if (res < 0)
8628         return posix_error();
8629     Py_RETURN_NONE;
8630 }
8631 
8632 /* Our selection logic for which function to use is as follows:
8633  * 1. If close_range(2) is available, always prefer that; it's better for
8634  *    contiguous ranges like this than fdwalk(3) which entails iterating over
8635  *    the entire fd space and simply doing nothing for those outside the range.
8636  * 2. If closefrom(2) is available, we'll attempt to use that next if we're
8637  *    closing up to sysconf(_SC_OPEN_MAX).
8638  * 2a. Fallback to fdwalk(3) if we're not closing up to sysconf(_SC_OPEN_MAX),
8639  *    as that will be more performant if the range happens to have any chunk of
8640  *    non-opened fd in the middle.
8641  * 2b. If fdwalk(3) isn't available, just do a plain close(2) loop.
8642  */
8643 #if defined(__FreeBSD__) || defined(__DragonFly__)
8644 #define USE_CLOSEFROM
8645 #endif /* __FreeBSD__ */
8646 
8647 #ifdef HAVE_FDWALK
8648 #define USE_FDWALK
8649 #endif /* HAVE_FDWALK */
8650 
8651 #ifdef USE_FDWALK
8652 static int
_fdwalk_close_func(void * lohi,int fd)8653 _fdwalk_close_func(void *lohi, int fd)
8654 {
8655     int lo = ((int *)lohi)[0];
8656     int hi = ((int *)lohi)[1];
8657 
8658     if (fd >= hi)
8659         return 1;
8660     else if (fd >= lo)
8661         close(fd);
8662     return 0;
8663 }
8664 #endif /* USE_FDWALK */
8665 
8666 /* Closes all file descriptors in [first, last], ignoring errors. */
8667 void
_Py_closerange(int first,int last)8668 _Py_closerange(int first, int last)
8669 {
8670     first = Py_MAX(first, 0);
8671     _Py_BEGIN_SUPPRESS_IPH
8672 #ifdef HAVE_CLOSE_RANGE
8673     if (close_range(first, last, 0) == 0 || errno != ENOSYS) {
8674         /* Any errors encountered while closing file descriptors are ignored;
8675          * ENOSYS means no kernel support, though,
8676          * so we'll fallback to the other methods. */
8677     }
8678     else
8679 #endif /* HAVE_CLOSE_RANGE */
8680 #ifdef USE_CLOSEFROM
8681     if (last >= sysconf(_SC_OPEN_MAX)) {
8682         /* Any errors encountered while closing file descriptors are ignored */
8683         closefrom(first);
8684     }
8685     else
8686 #endif /* USE_CLOSEFROM */
8687 #ifdef USE_FDWALK
8688     {
8689         int lohi[2];
8690         lohi[0] = first;
8691         lohi[1] = last + 1;
8692         fdwalk(_fdwalk_close_func, lohi);
8693     }
8694 #else
8695     {
8696         for (int i = first; i <= last; i++) {
8697             /* Ignore errors */
8698             (void)close(i);
8699         }
8700     }
8701 #endif /* USE_FDWALK */
8702     _Py_END_SUPPRESS_IPH
8703 }
8704 
8705 /*[clinic input]
8706 os.closerange
8707 
8708     fd_low: int
8709     fd_high: int
8710     /
8711 
8712 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
8713 [clinic start generated code]*/
8714 
8715 static PyObject *
os_closerange_impl(PyObject * module,int fd_low,int fd_high)8716 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
8717 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
8718 {
8719     Py_BEGIN_ALLOW_THREADS
8720     _Py_closerange(fd_low, fd_high - 1);
8721     Py_END_ALLOW_THREADS
8722     Py_RETURN_NONE;
8723 }
8724 
8725 
8726 /*[clinic input]
8727 os.dup -> int
8728 
8729     fd: int
8730     /
8731 
8732 Return a duplicate of a file descriptor.
8733 [clinic start generated code]*/
8734 
8735 static int
os_dup_impl(PyObject * module,int fd)8736 os_dup_impl(PyObject *module, int fd)
8737 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
8738 {
8739     return _Py_dup(fd);
8740 }
8741 
8742 
8743 /*[clinic input]
8744 os.dup2 -> int
8745     fd: int
8746     fd2: int
8747     inheritable: bool=True
8748 
8749 Duplicate file descriptor.
8750 [clinic start generated code]*/
8751 
8752 static int
os_dup2_impl(PyObject * module,int fd,int fd2,int inheritable)8753 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
8754 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
8755 {
8756     int res = 0;
8757 #if defined(HAVE_DUP3) && \
8758     !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
8759     /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
8760     static int dup3_works = -1;
8761 #endif
8762 
8763     if (fd < 0 || fd2 < 0) {
8764         posix_error();
8765         return -1;
8766     }
8767 
8768     /* dup2() can fail with EINTR if the target FD is already open, because it
8769      * then has to be closed. See os_close_impl() for why we don't handle EINTR
8770      * upon close(), and therefore below.
8771      */
8772 #ifdef MS_WINDOWS
8773     Py_BEGIN_ALLOW_THREADS
8774     _Py_BEGIN_SUPPRESS_IPH
8775     res = dup2(fd, fd2);
8776     _Py_END_SUPPRESS_IPH
8777     Py_END_ALLOW_THREADS
8778     if (res < 0) {
8779         posix_error();
8780         return -1;
8781     }
8782     res = fd2; // msvcrt dup2 returns 0 on success.
8783 
8784     /* Character files like console cannot be make non-inheritable */
8785     if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
8786         close(fd2);
8787         return -1;
8788     }
8789 
8790 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
8791     Py_BEGIN_ALLOW_THREADS
8792     if (!inheritable)
8793         res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
8794     else
8795         res = dup2(fd, fd2);
8796     Py_END_ALLOW_THREADS
8797     if (res < 0) {
8798         posix_error();
8799         return -1;
8800     }
8801 
8802 #else
8803 
8804 #ifdef HAVE_DUP3
8805     if (!inheritable && dup3_works != 0) {
8806         Py_BEGIN_ALLOW_THREADS
8807         res = dup3(fd, fd2, O_CLOEXEC);
8808         Py_END_ALLOW_THREADS
8809         if (res < 0) {
8810             if (dup3_works == -1)
8811                 dup3_works = (errno != ENOSYS);
8812             if (dup3_works) {
8813                 posix_error();
8814                 return -1;
8815             }
8816         }
8817     }
8818 
8819     if (inheritable || dup3_works == 0)
8820     {
8821 #endif
8822         Py_BEGIN_ALLOW_THREADS
8823         res = dup2(fd, fd2);
8824         Py_END_ALLOW_THREADS
8825         if (res < 0) {
8826             posix_error();
8827             return -1;
8828         }
8829 
8830         if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
8831             close(fd2);
8832             return -1;
8833         }
8834 #ifdef HAVE_DUP3
8835     }
8836 #endif
8837 
8838 #endif
8839 
8840     return res;
8841 }
8842 
8843 
8844 #ifdef HAVE_LOCKF
8845 /*[clinic input]
8846 os.lockf
8847 
8848     fd: int
8849         An open file descriptor.
8850     command: int
8851         One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
8852     length: Py_off_t
8853         The number of bytes to lock, starting at the current position.
8854     /
8855 
8856 Apply, test or remove a POSIX lock on an open file descriptor.
8857 
8858 [clinic start generated code]*/
8859 
8860 static PyObject *
os_lockf_impl(PyObject * module,int fd,int command,Py_off_t length)8861 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
8862 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
8863 {
8864     int res;
8865 
8866     if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
8867         return NULL;
8868     }
8869 
8870     Py_BEGIN_ALLOW_THREADS
8871     res = lockf(fd, command, length);
8872     Py_END_ALLOW_THREADS
8873 
8874     if (res < 0)
8875         return posix_error();
8876 
8877     Py_RETURN_NONE;
8878 }
8879 #endif /* HAVE_LOCKF */
8880 
8881 
8882 /*[clinic input]
8883 os.lseek -> Py_off_t
8884 
8885     fd: int
8886     position: Py_off_t
8887     how: int
8888     /
8889 
8890 Set the position of a file descriptor.  Return the new position.
8891 
8892 Return the new cursor position in number of bytes
8893 relative to the beginning of the file.
8894 [clinic start generated code]*/
8895 
8896 static Py_off_t
os_lseek_impl(PyObject * module,int fd,Py_off_t position,int how)8897 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
8898 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
8899 {
8900     Py_off_t result;
8901 
8902 #ifdef SEEK_SET
8903     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
8904     switch (how) {
8905         case 0: how = SEEK_SET; break;
8906         case 1: how = SEEK_CUR; break;
8907         case 2: how = SEEK_END; break;
8908     }
8909 #endif /* SEEK_END */
8910 
8911     Py_BEGIN_ALLOW_THREADS
8912     _Py_BEGIN_SUPPRESS_IPH
8913 #ifdef MS_WINDOWS
8914     result = _lseeki64(fd, position, how);
8915 #else
8916     result = lseek(fd, position, how);
8917 #endif
8918     _Py_END_SUPPRESS_IPH
8919     Py_END_ALLOW_THREADS
8920     if (result < 0)
8921         posix_error();
8922 
8923     return result;
8924 }
8925 
8926 
8927 /*[clinic input]
8928 os.read
8929     fd: int
8930     length: Py_ssize_t
8931     /
8932 
8933 Read from a file descriptor.  Returns a bytes object.
8934 [clinic start generated code]*/
8935 
8936 static PyObject *
os_read_impl(PyObject * module,int fd,Py_ssize_t length)8937 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
8938 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
8939 {
8940     Py_ssize_t n;
8941     PyObject *buffer;
8942 
8943     if (length < 0) {
8944         errno = EINVAL;
8945         return posix_error();
8946     }
8947 
8948     length = Py_MIN(length, _PY_READ_MAX);
8949 
8950     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
8951     if (buffer == NULL)
8952         return NULL;
8953 
8954     n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
8955     if (n == -1) {
8956         Py_DECREF(buffer);
8957         return NULL;
8958     }
8959 
8960     if (n != length)
8961         _PyBytes_Resize(&buffer, n);
8962 
8963     return buffer;
8964 }
8965 
8966 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
8967                                 || defined(__APPLE__))) \
8968     || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
8969     || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
8970 static int
iov_setup(struct iovec ** iov,Py_buffer ** buf,PyObject * seq,Py_ssize_t cnt,int type)8971 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
8972 {
8973     Py_ssize_t i, j;
8974 
8975     *iov = PyMem_New(struct iovec, cnt);
8976     if (*iov == NULL) {
8977         PyErr_NoMemory();
8978         return -1;
8979     }
8980 
8981     *buf = PyMem_New(Py_buffer, cnt);
8982     if (*buf == NULL) {
8983         PyMem_Del(*iov);
8984         PyErr_NoMemory();
8985         return -1;
8986     }
8987 
8988     for (i = 0; i < cnt; i++) {
8989         PyObject *item = PySequence_GetItem(seq, i);
8990         if (item == NULL)
8991             goto fail;
8992         if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
8993             Py_DECREF(item);
8994             goto fail;
8995         }
8996         Py_DECREF(item);
8997         (*iov)[i].iov_base = (*buf)[i].buf;
8998         (*iov)[i].iov_len = (*buf)[i].len;
8999     }
9000     return 0;
9001 
9002 fail:
9003     PyMem_Del(*iov);
9004     for (j = 0; j < i; j++) {
9005         PyBuffer_Release(&(*buf)[j]);
9006     }
9007     PyMem_Del(*buf);
9008     return -1;
9009 }
9010 
9011 static void
iov_cleanup(struct iovec * iov,Py_buffer * buf,int cnt)9012 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9013 {
9014     int i;
9015     PyMem_Del(iov);
9016     for (i = 0; i < cnt; i++) {
9017         PyBuffer_Release(&buf[i]);
9018     }
9019     PyMem_Del(buf);
9020 }
9021 #endif
9022 
9023 
9024 #ifdef HAVE_READV
9025 /*[clinic input]
9026 os.readv -> Py_ssize_t
9027 
9028     fd: int
9029     buffers: object
9030     /
9031 
9032 Read from a file descriptor fd into an iterable of buffers.
9033 
9034 The buffers should be mutable buffers accepting bytes.
9035 readv will transfer data into each buffer until it is full
9036 and then move on to the next buffer in the sequence to hold
9037 the rest of the data.
9038 
9039 readv returns the total number of bytes read,
9040 which may be less than the total capacity of all the buffers.
9041 [clinic start generated code]*/
9042 
9043 static Py_ssize_t
os_readv_impl(PyObject * module,int fd,PyObject * buffers)9044 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9045 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9046 {
9047     Py_ssize_t cnt, n;
9048     int async_err = 0;
9049     struct iovec *iov;
9050     Py_buffer *buf;
9051 
9052     if (!PySequence_Check(buffers)) {
9053         PyErr_SetString(PyExc_TypeError,
9054             "readv() arg 2 must be a sequence");
9055         return -1;
9056     }
9057 
9058     cnt = PySequence_Size(buffers);
9059     if (cnt < 0)
9060         return -1;
9061 
9062     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9063         return -1;
9064 
9065     do {
9066         Py_BEGIN_ALLOW_THREADS
9067         n = readv(fd, iov, cnt);
9068         Py_END_ALLOW_THREADS
9069     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9070 
9071     iov_cleanup(iov, buf, cnt);
9072     if (n < 0) {
9073         if (!async_err)
9074             posix_error();
9075         return -1;
9076     }
9077 
9078     return n;
9079 }
9080 #endif /* HAVE_READV */
9081 
9082 
9083 #ifdef HAVE_PREAD
9084 /*[clinic input]
9085 # TODO length should be size_t!  but Python doesn't support parsing size_t yet.
9086 os.pread
9087 
9088     fd: int
9089     length: int
9090     offset: Py_off_t
9091     /
9092 
9093 Read a number of bytes from a file descriptor starting at a particular offset.
9094 
9095 Read length bytes from file descriptor fd, starting at offset bytes from
9096 the beginning of the file.  The file offset remains unchanged.
9097 [clinic start generated code]*/
9098 
9099 static PyObject *
os_pread_impl(PyObject * module,int fd,int length,Py_off_t offset)9100 os_pread_impl(PyObject *module, int fd, int length, Py_off_t offset)
9101 /*[clinic end generated code: output=435b29ee32b54a78 input=084948dcbaa35d4c]*/
9102 {
9103     Py_ssize_t n;
9104     int async_err = 0;
9105     PyObject *buffer;
9106 
9107     if (length < 0) {
9108         errno = EINVAL;
9109         return posix_error();
9110     }
9111     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9112     if (buffer == NULL)
9113         return NULL;
9114 
9115     do {
9116         Py_BEGIN_ALLOW_THREADS
9117         _Py_BEGIN_SUPPRESS_IPH
9118         n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9119         _Py_END_SUPPRESS_IPH
9120         Py_END_ALLOW_THREADS
9121     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9122 
9123     if (n < 0) {
9124         Py_DECREF(buffer);
9125         return (!async_err) ? posix_error() : NULL;
9126     }
9127     if (n != length)
9128         _PyBytes_Resize(&buffer, n);
9129     return buffer;
9130 }
9131 #endif /* HAVE_PREAD */
9132 
9133 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9134 /*[clinic input]
9135 os.preadv -> Py_ssize_t
9136 
9137     fd: int
9138     buffers: object
9139     offset: Py_off_t
9140     flags: int = 0
9141     /
9142 
9143 Reads from a file descriptor into a number of mutable bytes-like objects.
9144 
9145 Combines the functionality of readv() and pread(). As readv(), it will
9146 transfer data into each buffer until it is full and then move on to the next
9147 buffer in the sequence to hold the rest of the data. Its fourth argument,
9148 specifies the file offset at which the input operation is to be performed. It
9149 will return the total number of bytes read (which can be less than the total
9150 capacity of all the objects).
9151 
9152 The flags argument contains a bitwise OR of zero or more of the following flags:
9153 
9154 - RWF_HIPRI
9155 - RWF_NOWAIT
9156 
9157 Using non-zero flags requires Linux 4.6 or newer.
9158 [clinic start generated code]*/
9159 
9160 static Py_ssize_t
os_preadv_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9161 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9162                int flags)
9163 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9164 {
9165     Py_ssize_t cnt, n;
9166     int async_err = 0;
9167     struct iovec *iov;
9168     Py_buffer *buf;
9169 
9170     if (!PySequence_Check(buffers)) {
9171         PyErr_SetString(PyExc_TypeError,
9172             "preadv2() arg 2 must be a sequence");
9173         return -1;
9174     }
9175 
9176     cnt = PySequence_Size(buffers);
9177     if (cnt < 0) {
9178         return -1;
9179     }
9180 
9181 #ifndef HAVE_PREADV2
9182     if(flags != 0) {
9183         argument_unavailable_error("preadv2", "flags");
9184         return -1;
9185     }
9186 #endif
9187 
9188     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9189         return -1;
9190     }
9191 #ifdef HAVE_PREADV2
9192     do {
9193         Py_BEGIN_ALLOW_THREADS
9194         _Py_BEGIN_SUPPRESS_IPH
9195         n = preadv2(fd, iov, cnt, offset, flags);
9196         _Py_END_SUPPRESS_IPH
9197         Py_END_ALLOW_THREADS
9198     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9199 #else
9200     do {
9201         Py_BEGIN_ALLOW_THREADS
9202         _Py_BEGIN_SUPPRESS_IPH
9203         n = preadv(fd, iov, cnt, offset);
9204         _Py_END_SUPPRESS_IPH
9205         Py_END_ALLOW_THREADS
9206     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9207 #endif
9208 
9209     iov_cleanup(iov, buf, cnt);
9210     if (n < 0) {
9211         if (!async_err) {
9212             posix_error();
9213         }
9214         return -1;
9215     }
9216 
9217     return n;
9218 }
9219 #endif /* HAVE_PREADV */
9220 
9221 
9222 /*[clinic input]
9223 os.write -> Py_ssize_t
9224 
9225     fd: int
9226     data: Py_buffer
9227     /
9228 
9229 Write a bytes object to a file descriptor.
9230 [clinic start generated code]*/
9231 
9232 static Py_ssize_t
os_write_impl(PyObject * module,int fd,Py_buffer * data)9233 os_write_impl(PyObject *module, int fd, Py_buffer *data)
9234 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9235 {
9236     return _Py_write(fd, data->buf, data->len);
9237 }
9238 
9239 #ifdef HAVE_SENDFILE
9240 PyDoc_STRVAR(posix_sendfile__doc__,
9241 "sendfile(out, in, offset, count) -> byteswritten\n\
9242 sendfile(out, in, offset, count[, headers][, trailers], flags=0)\n\
9243             -> byteswritten\n\
9244 Copy count bytes from file descriptor in to file descriptor out.");
9245 
9246 /* AC 3.5: don't bother converting, has optional group*/
9247 static PyObject *
posix_sendfile(PyObject * self,PyObject * args,PyObject * kwdict)9248 posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
9249 {
9250     int in, out;
9251     Py_ssize_t ret;
9252     int async_err = 0;
9253     off_t offset;
9254 
9255 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9256 #ifndef __APPLE__
9257     Py_ssize_t len;
9258 #endif
9259     PyObject *headers = NULL, *trailers = NULL;
9260     Py_buffer *hbuf, *tbuf;
9261     off_t sbytes;
9262     struct sf_hdtr sf;
9263     int flags = 0;
9264     /* Beware that "in" clashes with Python's own "in" operator keyword */
9265     static char *keywords[] = {"out", "in",
9266                                 "offset", "count",
9267                                 "headers", "trailers", "flags", NULL};
9268 
9269     sf.headers = NULL;
9270     sf.trailers = NULL;
9271 
9272 #ifdef __APPLE__
9273     if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile",
9274         keywords, &out, &in, Py_off_t_converter, &offset, Py_off_t_converter, &sbytes,
9275 #else
9276     if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile",
9277         keywords, &out, &in, Py_off_t_converter, &offset, &len,
9278 #endif
9279                 &headers, &trailers, &flags))
9280             return NULL;
9281     if (headers != NULL) {
9282         if (!PySequence_Check(headers)) {
9283             PyErr_SetString(PyExc_TypeError,
9284                 "sendfile() headers must be a sequence");
9285             return NULL;
9286         } else {
9287             Py_ssize_t i = PySequence_Size(headers);
9288             if (i < 0)
9289                 return NULL;
9290             if (i > INT_MAX) {
9291                 PyErr_SetString(PyExc_OverflowError,
9292                     "sendfile() header is too large");
9293                 return NULL;
9294             }
9295             if (i > 0) {
9296                 sf.hdr_cnt = (int)i;
9297                 if (iov_setup(&(sf.headers), &hbuf,
9298                               headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9299                     return NULL;
9300 #ifdef __APPLE__
9301                 for (i = 0; i < sf.hdr_cnt; i++) {
9302                     Py_ssize_t blen = sf.headers[i].iov_len;
9303 # define OFF_T_MAX 0x7fffffffffffffff
9304                     if (sbytes >= OFF_T_MAX - blen) {
9305                         PyErr_SetString(PyExc_OverflowError,
9306                             "sendfile() header is too large");
9307                         return NULL;
9308                     }
9309                     sbytes += blen;
9310                 }
9311 #endif
9312             }
9313         }
9314     }
9315     if (trailers != NULL) {
9316         if (!PySequence_Check(trailers)) {
9317             PyErr_SetString(PyExc_TypeError,
9318                 "sendfile() trailers must be a sequence");
9319             return NULL;
9320         } else {
9321             Py_ssize_t i = PySequence_Size(trailers);
9322             if (i < 0)
9323                 return NULL;
9324             if (i > INT_MAX) {
9325                 PyErr_SetString(PyExc_OverflowError,
9326                     "sendfile() trailer is too large");
9327                 return NULL;
9328             }
9329             if (i > 0) {
9330                 sf.trl_cnt = (int)i;
9331                 if (iov_setup(&(sf.trailers), &tbuf,
9332                               trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
9333                     return NULL;
9334             }
9335         }
9336     }
9337 
9338     _Py_BEGIN_SUPPRESS_IPH
9339     do {
9340         Py_BEGIN_ALLOW_THREADS
9341 #ifdef __APPLE__
9342         ret = sendfile(in, out, offset, &sbytes, &sf, flags);
9343 #else
9344         ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);
9345 #endif
9346         Py_END_ALLOW_THREADS
9347     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9348     _Py_END_SUPPRESS_IPH
9349 
9350     if (sf.headers != NULL)
9351         iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
9352     if (sf.trailers != NULL)
9353         iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
9354 
9355     if (ret < 0) {
9356         if ((errno == EAGAIN) || (errno == EBUSY)) {
9357             if (sbytes != 0) {
9358                 // some data has been sent
9359                 goto done;
9360             }
9361             else {
9362                 // no data has been sent; upper application is supposed
9363                 // to retry on EAGAIN or EBUSY
9364                 return posix_error();
9365             }
9366         }
9367         return (!async_err) ? posix_error() : NULL;
9368     }
9369     goto done;
9370 
9371 done:
9372     #if !defined(HAVE_LARGEFILE_SUPPORT)
9373         return Py_BuildValue("l", sbytes);
9374     #else
9375         return Py_BuildValue("L", sbytes);
9376     #endif
9377 
9378 #else
9379     Py_ssize_t count;
9380     PyObject *offobj;
9381     static char *keywords[] = {"out", "in",
9382                                 "offset", "count", NULL};
9383     if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",
9384             keywords, &out, &in, &offobj, &count))
9385         return NULL;
9386 #ifdef __linux__
9387     if (offobj == Py_None) {
9388         do {
9389             Py_BEGIN_ALLOW_THREADS
9390             ret = sendfile(out, in, NULL, count);
9391             Py_END_ALLOW_THREADS
9392         } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9393         if (ret < 0)
9394             return (!async_err) ? posix_error() : NULL;
9395         return Py_BuildValue("n", ret);
9396     }
9397 #endif
9398     if (!Py_off_t_converter(offobj, &offset))
9399         return NULL;
9400 
9401 
9402 #if defined(__sun) && defined(__SVR4)
9403     // On illumos specifically sendfile() may perform a partial write but
9404     // return -1/an error (in one confirmed case the destination socket
9405     // had a 5 second timeout set and errno was EAGAIN) and it's on the client
9406     // code to check if the offset parameter was modified by sendfile().
9407     //
9408     // We need this variable to track said change.
9409     off_t original_offset = offset;
9410 #endif
9411 
9412     do {
9413         Py_BEGIN_ALLOW_THREADS
9414         ret = sendfile(out, in, &offset, count);
9415 #if defined(__sun) && defined(__SVR4)
9416         // This handles illumos-specific sendfile() partial write behavior,
9417         // see a comment above for more details.
9418         if (ret < 0 && offset != original_offset) {
9419             ret = offset - original_offset;
9420         }
9421 #endif
9422         Py_END_ALLOW_THREADS
9423     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9424     if (ret < 0)
9425         return (!async_err) ? posix_error() : NULL;
9426     return Py_BuildValue("n", ret);
9427 #endif
9428 }
9429 #endif /* HAVE_SENDFILE */
9430 
9431 
9432 #if defined(__APPLE__)
9433 /*[clinic input]
9434 os._fcopyfile
9435 
9436     infd: int
9437     outfd: int
9438     flags: int
9439     /
9440 
9441 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
9442 [clinic start generated code]*/
9443 
9444 static PyObject *
os__fcopyfile_impl(PyObject * module,int infd,int outfd,int flags)9445 os__fcopyfile_impl(PyObject *module, int infd, int outfd, int flags)
9446 /*[clinic end generated code: output=8e8885c721ec38e3 input=69e0770e600cb44f]*/
9447 {
9448     int ret;
9449 
9450     Py_BEGIN_ALLOW_THREADS
9451     ret = fcopyfile(infd, outfd, NULL, flags);
9452     Py_END_ALLOW_THREADS
9453     if (ret < 0)
9454         return posix_error();
9455     Py_RETURN_NONE;
9456 }
9457 #endif
9458 
9459 
9460 /*[clinic input]
9461 os.fstat
9462 
9463     fd : int
9464 
9465 Perform a stat system call on the given file descriptor.
9466 
9467 Like stat(), but for an open file descriptor.
9468 Equivalent to os.stat(fd).
9469 [clinic start generated code]*/
9470 
9471 static PyObject *
os_fstat_impl(PyObject * module,int fd)9472 os_fstat_impl(PyObject *module, int fd)
9473 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
9474 {
9475     STRUCT_STAT st;
9476     int res;
9477     int async_err = 0;
9478 
9479     do {
9480         Py_BEGIN_ALLOW_THREADS
9481         res = FSTAT(fd, &st);
9482         Py_END_ALLOW_THREADS
9483     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9484     if (res != 0) {
9485 #ifdef MS_WINDOWS
9486         return PyErr_SetFromWindowsErr(0);
9487 #else
9488         return (!async_err) ? posix_error() : NULL;
9489 #endif
9490     }
9491 
9492     return _pystat_fromstructstat(&st);
9493 }
9494 
9495 
9496 /*[clinic input]
9497 os.isatty -> bool
9498     fd: int
9499     /
9500 
9501 Return True if the fd is connected to a terminal.
9502 
9503 Return True if the file descriptor is an open file descriptor
9504 connected to the slave end of a terminal.
9505 [clinic start generated code]*/
9506 
9507 static int
os_isatty_impl(PyObject * module,int fd)9508 os_isatty_impl(PyObject *module, int fd)
9509 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
9510 {
9511     int return_value;
9512     _Py_BEGIN_SUPPRESS_IPH
9513     return_value = isatty(fd);
9514     _Py_END_SUPPRESS_IPH
9515     return return_value;
9516 }
9517 
9518 
9519 #ifdef HAVE_PIPE
9520 /*[clinic input]
9521 os.pipe
9522 
9523 Create a pipe.
9524 
9525 Returns a tuple of two file descriptors:
9526   (read_fd, write_fd)
9527 [clinic start generated code]*/
9528 
9529 static PyObject *
os_pipe_impl(PyObject * module)9530 os_pipe_impl(PyObject *module)
9531 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
9532 {
9533     int fds[2];
9534 #ifdef MS_WINDOWS
9535     HANDLE read, write;
9536     SECURITY_ATTRIBUTES attr;
9537     BOOL ok;
9538 #else
9539     int res;
9540 #endif
9541 
9542 #ifdef MS_WINDOWS
9543     attr.nLength = sizeof(attr);
9544     attr.lpSecurityDescriptor = NULL;
9545     attr.bInheritHandle = FALSE;
9546 
9547     Py_BEGIN_ALLOW_THREADS
9548     _Py_BEGIN_SUPPRESS_IPH
9549     ok = CreatePipe(&read, &write, &attr, 0);
9550     if (ok) {
9551         fds[0] = _open_osfhandle((intptr_t)read, _O_RDONLY);
9552         fds[1] = _open_osfhandle((intptr_t)write, _O_WRONLY);
9553         if (fds[0] == -1 || fds[1] == -1) {
9554             CloseHandle(read);
9555             CloseHandle(write);
9556             ok = 0;
9557         }
9558     }
9559     _Py_END_SUPPRESS_IPH
9560     Py_END_ALLOW_THREADS
9561 
9562     if (!ok)
9563         return PyErr_SetFromWindowsErr(0);
9564 #else
9565 
9566 #ifdef HAVE_PIPE2
9567     Py_BEGIN_ALLOW_THREADS
9568     res = pipe2(fds, O_CLOEXEC);
9569     Py_END_ALLOW_THREADS
9570 
9571     if (res != 0 && errno == ENOSYS)
9572     {
9573 #endif
9574         Py_BEGIN_ALLOW_THREADS
9575         res = pipe(fds);
9576         Py_END_ALLOW_THREADS
9577 
9578         if (res == 0) {
9579             if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
9580                 close(fds[0]);
9581                 close(fds[1]);
9582                 return NULL;
9583             }
9584             if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
9585                 close(fds[0]);
9586                 close(fds[1]);
9587                 return NULL;
9588             }
9589         }
9590 #ifdef HAVE_PIPE2
9591     }
9592 #endif
9593 
9594     if (res != 0)
9595         return PyErr_SetFromErrno(PyExc_OSError);
9596 #endif /* !MS_WINDOWS */
9597     return Py_BuildValue("(ii)", fds[0], fds[1]);
9598 }
9599 #endif  /* HAVE_PIPE */
9600 
9601 
9602 #ifdef HAVE_PIPE2
9603 /*[clinic input]
9604 os.pipe2
9605 
9606     flags: int
9607     /
9608 
9609 Create a pipe with flags set atomically.
9610 
9611 Returns a tuple of two file descriptors:
9612   (read_fd, write_fd)
9613 
9614 flags can be constructed by ORing together one or more of these values:
9615 O_NONBLOCK, O_CLOEXEC.
9616 [clinic start generated code]*/
9617 
9618 static PyObject *
os_pipe2_impl(PyObject * module,int flags)9619 os_pipe2_impl(PyObject *module, int flags)
9620 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
9621 {
9622     int fds[2];
9623     int res;
9624 
9625     res = pipe2(fds, flags);
9626     if (res != 0)
9627         return posix_error();
9628     return Py_BuildValue("(ii)", fds[0], fds[1]);
9629 }
9630 #endif /* HAVE_PIPE2 */
9631 
9632 
9633 #ifdef HAVE_WRITEV
9634 /*[clinic input]
9635 os.writev -> Py_ssize_t
9636     fd: int
9637     buffers: object
9638     /
9639 
9640 Iterate over buffers, and write the contents of each to a file descriptor.
9641 
9642 Returns the total number of bytes written.
9643 buffers must be a sequence of bytes-like objects.
9644 [clinic start generated code]*/
9645 
9646 static Py_ssize_t
os_writev_impl(PyObject * module,int fd,PyObject * buffers)9647 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
9648 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
9649 {
9650     Py_ssize_t cnt;
9651     Py_ssize_t result;
9652     int async_err = 0;
9653     struct iovec *iov;
9654     Py_buffer *buf;
9655 
9656     if (!PySequence_Check(buffers)) {
9657         PyErr_SetString(PyExc_TypeError,
9658             "writev() arg 2 must be a sequence");
9659         return -1;
9660     }
9661     cnt = PySequence_Size(buffers);
9662     if (cnt < 0)
9663         return -1;
9664 
9665     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
9666         return -1;
9667     }
9668 
9669     do {
9670         Py_BEGIN_ALLOW_THREADS
9671         result = writev(fd, iov, cnt);
9672         Py_END_ALLOW_THREADS
9673     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9674 
9675     iov_cleanup(iov, buf, cnt);
9676     if (result < 0 && !async_err)
9677         posix_error();
9678 
9679     return result;
9680 }
9681 #endif /* HAVE_WRITEV */
9682 
9683 
9684 #ifdef HAVE_PWRITE
9685 /*[clinic input]
9686 os.pwrite -> Py_ssize_t
9687 
9688     fd: int
9689     buffer: Py_buffer
9690     offset: Py_off_t
9691     /
9692 
9693 Write bytes to a file descriptor starting at a particular offset.
9694 
9695 Write buffer to fd, starting at offset bytes from the beginning of
9696 the file.  Returns the number of bytes writte.  Does not change the
9697 current file offset.
9698 [clinic start generated code]*/
9699 
9700 static Py_ssize_t
os_pwrite_impl(PyObject * module,int fd,Py_buffer * buffer,Py_off_t offset)9701 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
9702 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
9703 {
9704     Py_ssize_t size;
9705     int async_err = 0;
9706 
9707     do {
9708         Py_BEGIN_ALLOW_THREADS
9709         _Py_BEGIN_SUPPRESS_IPH
9710         size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
9711         _Py_END_SUPPRESS_IPH
9712         Py_END_ALLOW_THREADS
9713     } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9714 
9715     if (size < 0 && !async_err)
9716         posix_error();
9717     return size;
9718 }
9719 #endif /* HAVE_PWRITE */
9720 
9721 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9722 /*[clinic input]
9723 os.pwritev -> Py_ssize_t
9724 
9725     fd: int
9726     buffers: object
9727     offset: Py_off_t
9728     flags: int = 0
9729     /
9730 
9731 Writes the contents of bytes-like objects to a file descriptor at a given offset.
9732 
9733 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
9734 of bytes-like objects. Buffers are processed in array order. Entire contents of first
9735 buffer is written before proceeding to second, and so on. The operating system may
9736 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
9737 This function writes the contents of each object to the file descriptor and returns
9738 the total number of bytes written.
9739 
9740 The flags argument contains a bitwise OR of zero or more of the following flags:
9741 
9742 - RWF_DSYNC
9743 - RWF_SYNC
9744 
9745 Using non-zero flags requires Linux 4.7 or newer.
9746 [clinic start generated code]*/
9747 
9748 static Py_ssize_t
os_pwritev_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9749 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9750                 int flags)
9751 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=803dc5ddbf0cfd3b]*/
9752 {
9753     Py_ssize_t cnt;
9754     Py_ssize_t result;
9755     int async_err = 0;
9756     struct iovec *iov;
9757     Py_buffer *buf;
9758 
9759     if (!PySequence_Check(buffers)) {
9760         PyErr_SetString(PyExc_TypeError,
9761             "pwritev() arg 2 must be a sequence");
9762         return -1;
9763     }
9764 
9765     cnt = PySequence_Size(buffers);
9766     if (cnt < 0) {
9767         return -1;
9768     }
9769 
9770 #ifndef HAVE_PWRITEV2
9771     if(flags != 0) {
9772         argument_unavailable_error("pwritev2", "flags");
9773         return -1;
9774     }
9775 #endif
9776 
9777     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
9778         return -1;
9779     }
9780 #ifdef HAVE_PWRITEV2
9781     do {
9782         Py_BEGIN_ALLOW_THREADS
9783         _Py_BEGIN_SUPPRESS_IPH
9784         result = pwritev2(fd, iov, cnt, offset, flags);
9785         _Py_END_SUPPRESS_IPH
9786         Py_END_ALLOW_THREADS
9787     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9788 #else
9789     do {
9790         Py_BEGIN_ALLOW_THREADS
9791         _Py_BEGIN_SUPPRESS_IPH
9792         result = pwritev(fd, iov, cnt, offset);
9793         _Py_END_SUPPRESS_IPH
9794         Py_END_ALLOW_THREADS
9795     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9796 #endif
9797 
9798     iov_cleanup(iov, buf, cnt);
9799     if (result < 0) {
9800         if (!async_err) {
9801             posix_error();
9802         }
9803         return -1;
9804     }
9805 
9806     return result;
9807 }
9808 #endif /* HAVE_PWRITEV */
9809 
9810 #ifdef HAVE_COPY_FILE_RANGE
9811 /*[clinic input]
9812 
9813 os.copy_file_range
9814     src: int
9815         Source file descriptor.
9816     dst: int
9817         Destination file descriptor.
9818     count: Py_ssize_t
9819         Number of bytes to copy.
9820     offset_src: object = None
9821         Starting offset in src.
9822     offset_dst: object = None
9823         Starting offset in dst.
9824 
9825 Copy count bytes from one file descriptor to another.
9826 
9827 If offset_src is None, then src is read from the current position;
9828 respectively for offset_dst.
9829 [clinic start generated code]*/
9830 
9831 static PyObject *
os_copy_file_range_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst)9832 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
9833                         PyObject *offset_src, PyObject *offset_dst)
9834 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
9835 {
9836     off_t offset_src_val, offset_dst_val;
9837     off_t *p_offset_src = NULL;
9838     off_t *p_offset_dst = NULL;
9839     Py_ssize_t ret;
9840     int async_err = 0;
9841     /* The flags argument is provided to allow
9842      * for future extensions and currently must be to 0. */
9843     int flags = 0;
9844 
9845 
9846     if (count < 0) {
9847         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
9848         return NULL;
9849     }
9850 
9851     if (offset_src != Py_None) {
9852         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
9853             return NULL;
9854         }
9855         p_offset_src = &offset_src_val;
9856     }
9857 
9858     if (offset_dst != Py_None) {
9859         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
9860             return NULL;
9861         }
9862         p_offset_dst = &offset_dst_val;
9863     }
9864 
9865     do {
9866         Py_BEGIN_ALLOW_THREADS
9867         ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
9868         Py_END_ALLOW_THREADS
9869     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9870 
9871     if (ret < 0) {
9872         return (!async_err) ? posix_error() : NULL;
9873     }
9874 
9875     return PyLong_FromSsize_t(ret);
9876 }
9877 #endif /* HAVE_COPY_FILE_RANGE*/
9878 
9879 #ifdef HAVE_MKFIFO
9880 /*[clinic input]
9881 os.mkfifo
9882 
9883     path: path_t
9884     mode: int=0o666
9885     *
9886     dir_fd: dir_fd(requires='mkfifoat')=None
9887 
9888 Create a "fifo" (a POSIX named pipe).
9889 
9890 If dir_fd is not None, it should be a file descriptor open to a directory,
9891   and path should be relative; path will then be relative to that directory.
9892 dir_fd may not be implemented on your platform.
9893   If it is unavailable, using it will raise a NotImplementedError.
9894 [clinic start generated code]*/
9895 
9896 static PyObject *
os_mkfifo_impl(PyObject * module,path_t * path,int mode,int dir_fd)9897 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
9898 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
9899 {
9900     int result;
9901     int async_err = 0;
9902 
9903     do {
9904         Py_BEGIN_ALLOW_THREADS
9905 #ifdef HAVE_MKFIFOAT
9906         if (dir_fd != DEFAULT_DIR_FD)
9907             result = mkfifoat(dir_fd, path->narrow, mode);
9908         else
9909 #endif
9910             result = mkfifo(path->narrow, mode);
9911         Py_END_ALLOW_THREADS
9912     } while (result != 0 && errno == EINTR &&
9913              !(async_err = PyErr_CheckSignals()));
9914     if (result != 0)
9915         return (!async_err) ? posix_error() : NULL;
9916 
9917     Py_RETURN_NONE;
9918 }
9919 #endif /* HAVE_MKFIFO */
9920 
9921 
9922 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
9923 /*[clinic input]
9924 os.mknod
9925 
9926     path: path_t
9927     mode: int=0o600
9928     device: dev_t=0
9929     *
9930     dir_fd: dir_fd(requires='mknodat')=None
9931 
9932 Create a node in the file system.
9933 
9934 Create a node in the file system (file, device special file or named pipe)
9935 at path.  mode specifies both the permissions to use and the
9936 type of node to be created, being combined (bitwise OR) with one of
9937 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
9938 device defines the newly created device special file (probably using
9939 os.makedev()).  Otherwise device is ignored.
9940 
9941 If dir_fd is not None, it should be a file descriptor open to a directory,
9942   and path should be relative; path will then be relative to that directory.
9943 dir_fd may not be implemented on your platform.
9944   If it is unavailable, using it will raise a NotImplementedError.
9945 [clinic start generated code]*/
9946 
9947 static PyObject *
os_mknod_impl(PyObject * module,path_t * path,int mode,dev_t device,int dir_fd)9948 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
9949               int dir_fd)
9950 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
9951 {
9952     int result;
9953     int async_err = 0;
9954 
9955     do {
9956         Py_BEGIN_ALLOW_THREADS
9957 #ifdef HAVE_MKNODAT
9958         if (dir_fd != DEFAULT_DIR_FD)
9959             result = mknodat(dir_fd, path->narrow, mode, device);
9960         else
9961 #endif
9962             result = mknod(path->narrow, mode, device);
9963         Py_END_ALLOW_THREADS
9964     } while (result != 0 && errno == EINTR &&
9965              !(async_err = PyErr_CheckSignals()));
9966     if (result != 0)
9967         return (!async_err) ? posix_error() : NULL;
9968 
9969     Py_RETURN_NONE;
9970 }
9971 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
9972 
9973 
9974 #ifdef HAVE_DEVICE_MACROS
9975 /*[clinic input]
9976 os.major -> unsigned_int
9977 
9978     device: dev_t
9979     /
9980 
9981 Extracts a device major number from a raw device number.
9982 [clinic start generated code]*/
9983 
9984 static unsigned int
os_major_impl(PyObject * module,dev_t device)9985 os_major_impl(PyObject *module, dev_t device)
9986 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
9987 {
9988     return major(device);
9989 }
9990 
9991 
9992 /*[clinic input]
9993 os.minor -> unsigned_int
9994 
9995     device: dev_t
9996     /
9997 
9998 Extracts a device minor number from a raw device number.
9999 [clinic start generated code]*/
10000 
10001 static unsigned int
os_minor_impl(PyObject * module,dev_t device)10002 os_minor_impl(PyObject *module, dev_t device)
10003 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10004 {
10005     return minor(device);
10006 }
10007 
10008 
10009 /*[clinic input]
10010 os.makedev -> dev_t
10011 
10012     major: int
10013     minor: int
10014     /
10015 
10016 Composes a raw device number from the major and minor device numbers.
10017 [clinic start generated code]*/
10018 
10019 static dev_t
os_makedev_impl(PyObject * module,int major,int minor)10020 os_makedev_impl(PyObject *module, int major, int minor)
10021 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10022 {
10023     return makedev(major, minor);
10024 }
10025 #endif /* HAVE_DEVICE_MACROS */
10026 
10027 
10028 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10029 /*[clinic input]
10030 os.ftruncate
10031 
10032     fd: int
10033     length: Py_off_t
10034     /
10035 
10036 Truncate a file, specified by file descriptor, to a specific length.
10037 [clinic start generated code]*/
10038 
10039 static PyObject *
os_ftruncate_impl(PyObject * module,int fd,Py_off_t length)10040 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10041 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10042 {
10043     int result;
10044     int async_err = 0;
10045 
10046     if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10047         return NULL;
10048     }
10049 
10050     do {
10051         Py_BEGIN_ALLOW_THREADS
10052         _Py_BEGIN_SUPPRESS_IPH
10053 #ifdef MS_WINDOWS
10054         result = _chsize_s(fd, length);
10055 #else
10056         result = ftruncate(fd, length);
10057 #endif
10058         _Py_END_SUPPRESS_IPH
10059         Py_END_ALLOW_THREADS
10060     } while (result != 0 && errno == EINTR &&
10061              !(async_err = PyErr_CheckSignals()));
10062     if (result != 0)
10063         return (!async_err) ? posix_error() : NULL;
10064     Py_RETURN_NONE;
10065 }
10066 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10067 
10068 
10069 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10070 /*[clinic input]
10071 os.truncate
10072     path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10073     length: Py_off_t
10074 
10075 Truncate a file, specified by path, to a specific length.
10076 
10077 On some platforms, path may also be specified as an open file descriptor.
10078   If this functionality is unavailable, using it raises an exception.
10079 [clinic start generated code]*/
10080 
10081 static PyObject *
os_truncate_impl(PyObject * module,path_t * path,Py_off_t length)10082 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10083 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10084 {
10085     int result;
10086 #ifdef MS_WINDOWS
10087     int fd;
10088 #endif
10089 
10090     if (path->fd != -1)
10091         return os_ftruncate_impl(module, path->fd, length);
10092 
10093     if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10094         return NULL;
10095     }
10096 
10097     Py_BEGIN_ALLOW_THREADS
10098     _Py_BEGIN_SUPPRESS_IPH
10099 #ifdef MS_WINDOWS
10100     fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10101     if (fd < 0)
10102         result = -1;
10103     else {
10104         result = _chsize_s(fd, length);
10105         close(fd);
10106         if (result < 0)
10107             errno = result;
10108     }
10109 #else
10110     result = truncate(path->narrow, length);
10111 #endif
10112     _Py_END_SUPPRESS_IPH
10113     Py_END_ALLOW_THREADS
10114     if (result < 0)
10115         return posix_path_error(path);
10116 
10117     Py_RETURN_NONE;
10118 }
10119 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10120 
10121 
10122 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10123    and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10124    defined, which is the case in Python on AIX. AIX bug report:
10125    http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10126 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10127 #  define POSIX_FADVISE_AIX_BUG
10128 #endif
10129 
10130 
10131 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10132 /*[clinic input]
10133 os.posix_fallocate
10134 
10135     fd: int
10136     offset: Py_off_t
10137     length: Py_off_t
10138     /
10139 
10140 Ensure a file has allocated at least a particular number of bytes on disk.
10141 
10142 Ensure that the file specified by fd encompasses a range of bytes
10143 starting at offset bytes from the beginning and continuing for length bytes.
10144 [clinic start generated code]*/
10145 
10146 static PyObject *
os_posix_fallocate_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length)10147 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10148                         Py_off_t length)
10149 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10150 {
10151     int result;
10152     int async_err = 0;
10153 
10154     do {
10155         Py_BEGIN_ALLOW_THREADS
10156         result = posix_fallocate(fd, offset, length);
10157         Py_END_ALLOW_THREADS
10158     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10159 
10160     if (result == 0)
10161         Py_RETURN_NONE;
10162 
10163     if (async_err)
10164         return NULL;
10165 
10166     errno = result;
10167     return posix_error();
10168 }
10169 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
10170 
10171 
10172 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
10173 /*[clinic input]
10174 os.posix_fadvise
10175 
10176     fd: int
10177     offset: Py_off_t
10178     length: Py_off_t
10179     advice: int
10180     /
10181 
10182 Announce an intention to access data in a specific pattern.
10183 
10184 Announce an intention to access data in a specific pattern, thus allowing
10185 the kernel to make optimizations.
10186 The advice applies to the region of the file specified by fd starting at
10187 offset and continuing for length bytes.
10188 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
10189 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
10190 POSIX_FADV_DONTNEED.
10191 [clinic start generated code]*/
10192 
10193 static PyObject *
os_posix_fadvise_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length,int advice)10194 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
10195                       Py_off_t length, int advice)
10196 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
10197 {
10198     int result;
10199     int async_err = 0;
10200 
10201     do {
10202         Py_BEGIN_ALLOW_THREADS
10203         result = posix_fadvise(fd, offset, length, advice);
10204         Py_END_ALLOW_THREADS
10205     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10206 
10207     if (result == 0)
10208         Py_RETURN_NONE;
10209 
10210     if (async_err)
10211         return NULL;
10212 
10213     errno = result;
10214     return posix_error();
10215 }
10216 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
10217 
10218 #ifdef HAVE_PUTENV
10219 
10220 /* Save putenv() parameters as values here, so we can collect them when they
10221  * get re-set with another call for the same key. */
10222 static PyObject *posix_putenv_garbage;
10223 
10224 static void
posix_putenv_garbage_setitem(PyObject * name,PyObject * value)10225 posix_putenv_garbage_setitem(PyObject *name, PyObject *value)
10226 {
10227     /* Install the first arg and newstr in posix_putenv_garbage;
10228      * this will cause previous value to be collected.  This has to
10229      * happen after the real putenv() call because the old value
10230      * was still accessible until then. */
10231     if (PyDict_SetItem(posix_putenv_garbage, name, value))
10232         /* really not much we can do; just leak */
10233         PyErr_Clear();
10234     else
10235         Py_DECREF(value);
10236 }
10237 
10238 
10239 #ifdef MS_WINDOWS
10240 /*[clinic input]
10241 os.putenv
10242 
10243     name: unicode
10244     value: unicode
10245     /
10246 
10247 Change or add an environment variable.
10248 [clinic start generated code]*/
10249 
10250 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10251 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10252 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
10253 {
10254     const wchar_t *env;
10255     Py_ssize_t size;
10256 
10257     /* Search from index 1 because on Windows starting '=' is allowed for
10258        defining hidden environment variables. */
10259     if (PyUnicode_GET_LENGTH(name) == 0 ||
10260         PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
10261     {
10262         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10263         return NULL;
10264     }
10265     PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value);
10266     if (unicode == NULL) {
10267         return NULL;
10268     }
10269 
10270     env = PyUnicode_AsUnicodeAndSize(unicode, &size);
10271     if (env == NULL)
10272         goto error;
10273     if (size > _MAX_ENV) {
10274         PyErr_Format(PyExc_ValueError,
10275                      "the environment variable is longer than %u characters",
10276                      _MAX_ENV);
10277         goto error;
10278     }
10279     if (wcslen(env) != (size_t)size) {
10280         PyErr_SetString(PyExc_ValueError, "embedded null character");
10281         goto error;
10282     }
10283 
10284     if (_wputenv(env)) {
10285         posix_error();
10286         goto error;
10287     }
10288 
10289     posix_putenv_garbage_setitem(name, unicode);
10290     Py_RETURN_NONE;
10291 
10292 error:
10293     Py_DECREF(unicode);
10294     return NULL;
10295 }
10296 #else /* MS_WINDOWS */
10297 /*[clinic input]
10298 os.putenv
10299 
10300     name: FSConverter
10301     value: FSConverter
10302     /
10303 
10304 Change or add an environment variable.
10305 [clinic start generated code]*/
10306 
10307 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10308 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10309 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
10310 {
10311     PyObject *bytes = NULL;
10312     char *env;
10313     const char *name_string = PyBytes_AS_STRING(name);
10314     const char *value_string = PyBytes_AS_STRING(value);
10315 
10316     if (strchr(name_string, '=') != NULL) {
10317         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10318         return NULL;
10319     }
10320     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10321         return NULL;
10322     }
10323     bytes = PyBytes_FromFormat("%s=%s", name_string, value_string);
10324     if (bytes == NULL) {
10325         return NULL;
10326     }
10327 
10328     env = PyBytes_AS_STRING(bytes);
10329     if (putenv(env)) {
10330         Py_DECREF(bytes);
10331         return posix_error();
10332     }
10333 
10334     posix_putenv_garbage_setitem(name, bytes);
10335     Py_RETURN_NONE;
10336 }
10337 #endif /* MS_WINDOWS */
10338 #endif /* HAVE_PUTENV */
10339 
10340 
10341 #ifdef HAVE_UNSETENV
10342 /*[clinic input]
10343 os.unsetenv
10344     name: FSConverter
10345     /
10346 
10347 Delete an environment variable.
10348 [clinic start generated code]*/
10349 
10350 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)10351 os_unsetenv_impl(PyObject *module, PyObject *name)
10352 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
10353 {
10354 #ifndef HAVE_BROKEN_UNSETENV
10355     int err;
10356 #endif
10357 
10358     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
10359         return NULL;
10360     }
10361 
10362 #ifdef HAVE_BROKEN_UNSETENV
10363     unsetenv(PyBytes_AS_STRING(name));
10364 #else
10365     err = unsetenv(PyBytes_AS_STRING(name));
10366     if (err)
10367         return posix_error();
10368 #endif
10369 
10370     /* Remove the key from posix_putenv_garbage;
10371      * this will cause it to be collected.  This has to
10372      * happen after the real unsetenv() call because the
10373      * old value was still accessible until then.
10374      */
10375     if (PyDict_DelItem(posix_putenv_garbage, name)) {
10376         /* really not much we can do; just leak */
10377         if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
10378             return NULL;
10379         }
10380         PyErr_Clear();
10381     }
10382     Py_RETURN_NONE;
10383 }
10384 #endif /* HAVE_UNSETENV */
10385 
10386 
10387 /*[clinic input]
10388 os.strerror
10389 
10390     code: int
10391     /
10392 
10393 Translate an error code to a message string.
10394 [clinic start generated code]*/
10395 
10396 static PyObject *
os_strerror_impl(PyObject * module,int code)10397 os_strerror_impl(PyObject *module, int code)
10398 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
10399 {
10400     char *message = strerror(code);
10401     if (message == NULL) {
10402         PyErr_SetString(PyExc_ValueError,
10403                         "strerror() argument out of range");
10404         return NULL;
10405     }
10406     return PyUnicode_DecodeLocale(message, "surrogateescape");
10407 }
10408 
10409 
10410 #ifdef HAVE_SYS_WAIT_H
10411 #ifdef WCOREDUMP
10412 /*[clinic input]
10413 os.WCOREDUMP -> bool
10414 
10415     status: int
10416     /
10417 
10418 Return True if the process returning status was dumped to a core file.
10419 [clinic start generated code]*/
10420 
10421 static int
os_WCOREDUMP_impl(PyObject * module,int status)10422 os_WCOREDUMP_impl(PyObject *module, int status)
10423 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
10424 {
10425     WAIT_TYPE wait_status;
10426     WAIT_STATUS_INT(wait_status) = status;
10427     return WCOREDUMP(wait_status);
10428 }
10429 #endif /* WCOREDUMP */
10430 
10431 
10432 #ifdef WIFCONTINUED
10433 /*[clinic input]
10434 os.WIFCONTINUED -> bool
10435 
10436     status: int
10437 
10438 Return True if a particular process was continued from a job control stop.
10439 
10440 Return True if the process returning status was continued from a
10441 job control stop.
10442 [clinic start generated code]*/
10443 
10444 static int
os_WIFCONTINUED_impl(PyObject * module,int status)10445 os_WIFCONTINUED_impl(PyObject *module, int status)
10446 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
10447 {
10448     WAIT_TYPE wait_status;
10449     WAIT_STATUS_INT(wait_status) = status;
10450     return WIFCONTINUED(wait_status);
10451 }
10452 #endif /* WIFCONTINUED */
10453 
10454 
10455 #ifdef WIFSTOPPED
10456 /*[clinic input]
10457 os.WIFSTOPPED -> bool
10458 
10459     status: int
10460 
10461 Return True if the process returning status was stopped.
10462 [clinic start generated code]*/
10463 
10464 static int
os_WIFSTOPPED_impl(PyObject * module,int status)10465 os_WIFSTOPPED_impl(PyObject *module, int status)
10466 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
10467 {
10468     WAIT_TYPE wait_status;
10469     WAIT_STATUS_INT(wait_status) = status;
10470     return WIFSTOPPED(wait_status);
10471 }
10472 #endif /* WIFSTOPPED */
10473 
10474 
10475 #ifdef WIFSIGNALED
10476 /*[clinic input]
10477 os.WIFSIGNALED -> bool
10478 
10479     status: int
10480 
10481 Return True if the process returning status was terminated by a signal.
10482 [clinic start generated code]*/
10483 
10484 static int
os_WIFSIGNALED_impl(PyObject * module,int status)10485 os_WIFSIGNALED_impl(PyObject *module, int status)
10486 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
10487 {
10488     WAIT_TYPE wait_status;
10489     WAIT_STATUS_INT(wait_status) = status;
10490     return WIFSIGNALED(wait_status);
10491 }
10492 #endif /* WIFSIGNALED */
10493 
10494 
10495 #ifdef WIFEXITED
10496 /*[clinic input]
10497 os.WIFEXITED -> bool
10498 
10499     status: int
10500 
10501 Return True if the process returning status exited via the exit() system call.
10502 [clinic start generated code]*/
10503 
10504 static int
os_WIFEXITED_impl(PyObject * module,int status)10505 os_WIFEXITED_impl(PyObject *module, int status)
10506 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
10507 {
10508     WAIT_TYPE wait_status;
10509     WAIT_STATUS_INT(wait_status) = status;
10510     return WIFEXITED(wait_status);
10511 }
10512 #endif /* WIFEXITED */
10513 
10514 
10515 #ifdef WEXITSTATUS
10516 /*[clinic input]
10517 os.WEXITSTATUS -> int
10518 
10519     status: int
10520 
10521 Return the process return code from status.
10522 [clinic start generated code]*/
10523 
10524 static int
os_WEXITSTATUS_impl(PyObject * module,int status)10525 os_WEXITSTATUS_impl(PyObject *module, int status)
10526 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
10527 {
10528     WAIT_TYPE wait_status;
10529     WAIT_STATUS_INT(wait_status) = status;
10530     return WEXITSTATUS(wait_status);
10531 }
10532 #endif /* WEXITSTATUS */
10533 
10534 
10535 #ifdef WTERMSIG
10536 /*[clinic input]
10537 os.WTERMSIG -> int
10538 
10539     status: int
10540 
10541 Return the signal that terminated the process that provided the status value.
10542 [clinic start generated code]*/
10543 
10544 static int
os_WTERMSIG_impl(PyObject * module,int status)10545 os_WTERMSIG_impl(PyObject *module, int status)
10546 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
10547 {
10548     WAIT_TYPE wait_status;
10549     WAIT_STATUS_INT(wait_status) = status;
10550     return WTERMSIG(wait_status);
10551 }
10552 #endif /* WTERMSIG */
10553 
10554 
10555 #ifdef WSTOPSIG
10556 /*[clinic input]
10557 os.WSTOPSIG -> int
10558 
10559     status: int
10560 
10561 Return the signal that stopped the process that provided the status value.
10562 [clinic start generated code]*/
10563 
10564 static int
os_WSTOPSIG_impl(PyObject * module,int status)10565 os_WSTOPSIG_impl(PyObject *module, int status)
10566 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
10567 {
10568     WAIT_TYPE wait_status;
10569     WAIT_STATUS_INT(wait_status) = status;
10570     return WSTOPSIG(wait_status);
10571 }
10572 #endif /* WSTOPSIG */
10573 #endif /* HAVE_SYS_WAIT_H */
10574 
10575 
10576 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
10577 #ifdef _SCO_DS
10578 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
10579    needed definitions in sys/statvfs.h */
10580 #define _SVID3
10581 #endif
10582 #include <sys/statvfs.h>
10583 
10584 static PyObject*
_pystatvfs_fromstructstatvfs(struct statvfs st)10585 _pystatvfs_fromstructstatvfs(struct statvfs st) {
10586     PyObject *v = PyStructSequence_New(StatVFSResultType);
10587     if (v == NULL)
10588         return NULL;
10589 
10590 #if !defined(HAVE_LARGEFILE_SUPPORT)
10591     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
10592     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
10593     PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
10594     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
10595     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
10596     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
10597     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
10598     PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
10599     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
10600     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
10601 #else
10602     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
10603     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
10604     PyStructSequence_SET_ITEM(v, 2,
10605                               PyLong_FromLongLong((long long) st.f_blocks));
10606     PyStructSequence_SET_ITEM(v, 3,
10607                               PyLong_FromLongLong((long long) st.f_bfree));
10608     PyStructSequence_SET_ITEM(v, 4,
10609                               PyLong_FromLongLong((long long) st.f_bavail));
10610     PyStructSequence_SET_ITEM(v, 5,
10611                               PyLong_FromLongLong((long long) st.f_files));
10612     PyStructSequence_SET_ITEM(v, 6,
10613                               PyLong_FromLongLong((long long) st.f_ffree));
10614     PyStructSequence_SET_ITEM(v, 7,
10615                               PyLong_FromLongLong((long long) st.f_favail));
10616     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
10617     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
10618 #endif
10619 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
10620  * (issue #32390). */
10621 #if defined(_AIX) && defined(_ALL_SOURCE)
10622     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
10623 #else
10624     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
10625 #endif
10626     if (PyErr_Occurred()) {
10627         Py_DECREF(v);
10628         return NULL;
10629     }
10630 
10631     return v;
10632 }
10633 
10634 
10635 /*[clinic input]
10636 os.fstatvfs
10637     fd: int
10638     /
10639 
10640 Perform an fstatvfs system call on the given fd.
10641 
10642 Equivalent to statvfs(fd).
10643 [clinic start generated code]*/
10644 
10645 static PyObject *
os_fstatvfs_impl(PyObject * module,int fd)10646 os_fstatvfs_impl(PyObject *module, int fd)
10647 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
10648 {
10649     int result;
10650     int async_err = 0;
10651     struct statvfs st;
10652 
10653     do {
10654         Py_BEGIN_ALLOW_THREADS
10655         result = fstatvfs(fd, &st);
10656         Py_END_ALLOW_THREADS
10657     } while (result != 0 && errno == EINTR &&
10658              !(async_err = PyErr_CheckSignals()));
10659     if (result != 0)
10660         return (!async_err) ? posix_error() : NULL;
10661 
10662     return _pystatvfs_fromstructstatvfs(st);
10663 }
10664 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
10665 
10666 
10667 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
10668 #include <sys/statvfs.h>
10669 /*[clinic input]
10670 os.statvfs
10671 
10672     path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
10673 
10674 Perform a statvfs system call on the given path.
10675 
10676 path may always be specified as a string.
10677 On some platforms, path may also be specified as an open file descriptor.
10678   If this functionality is unavailable, using it raises an exception.
10679 [clinic start generated code]*/
10680 
10681 static PyObject *
os_statvfs_impl(PyObject * module,path_t * path)10682 os_statvfs_impl(PyObject *module, path_t *path)
10683 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
10684 {
10685     int result;
10686     struct statvfs st;
10687 
10688     Py_BEGIN_ALLOW_THREADS
10689 #ifdef HAVE_FSTATVFS
10690     if (path->fd != -1) {
10691 #ifdef __APPLE__
10692         /* handle weak-linking on Mac OS X 10.3 */
10693         if (fstatvfs == NULL) {
10694             fd_specified("statvfs", path->fd);
10695             return NULL;
10696         }
10697 #endif
10698         result = fstatvfs(path->fd, &st);
10699     }
10700     else
10701 #endif
10702         result = statvfs(path->narrow, &st);
10703     Py_END_ALLOW_THREADS
10704 
10705     if (result) {
10706         return path_error(path);
10707     }
10708 
10709     return _pystatvfs_fromstructstatvfs(st);
10710 }
10711 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
10712 
10713 
10714 #ifdef MS_WINDOWS
10715 /*[clinic input]
10716 os._getdiskusage
10717 
10718     path: path_t
10719 
10720 Return disk usage statistics about the given path as a (total, free) tuple.
10721 [clinic start generated code]*/
10722 
10723 static PyObject *
os__getdiskusage_impl(PyObject * module,path_t * path)10724 os__getdiskusage_impl(PyObject *module, path_t *path)
10725 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
10726 {
10727     BOOL retval;
10728     ULARGE_INTEGER _, total, free;
10729     DWORD err = 0;
10730 
10731     Py_BEGIN_ALLOW_THREADS
10732     retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
10733     Py_END_ALLOW_THREADS
10734     if (retval == 0) {
10735         if (GetLastError() == ERROR_DIRECTORY) {
10736             wchar_t *dir_path = NULL;
10737 
10738             dir_path = PyMem_New(wchar_t, path->length + 1);
10739             if (dir_path == NULL) {
10740                 return PyErr_NoMemory();
10741             }
10742 
10743             wcscpy_s(dir_path, path->length + 1, path->wide);
10744 
10745             if (_dirnameW(dir_path) != -1) {
10746                 Py_BEGIN_ALLOW_THREADS
10747                 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
10748                 Py_END_ALLOW_THREADS
10749             }
10750             /* Record the last error in case it's modified by PyMem_Free. */
10751             err = GetLastError();
10752             PyMem_Free(dir_path);
10753             if (retval) {
10754                 goto success;
10755             }
10756         }
10757         return PyErr_SetFromWindowsErr(err);
10758     }
10759 
10760 success:
10761     return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
10762 }
10763 #endif /* MS_WINDOWS */
10764 
10765 
10766 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
10767  * It maps strings representing configuration variable names to
10768  * integer values, allowing those functions to be called with the
10769  * magic names instead of polluting the module's namespace with tons of
10770  * rarely-used constants.  There are three separate tables that use
10771  * these definitions.
10772  *
10773  * This code is always included, even if none of the interfaces that
10774  * need it are included.  The #if hackery needed to avoid it would be
10775  * sufficiently pervasive that it's not worth the loss of readability.
10776  */
10777 struct constdef {
10778     const char *name;
10779     int value;
10780 };
10781 
10782 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)10783 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
10784               size_t tablesize)
10785 {
10786     if (PyLong_Check(arg)) {
10787         int value = _PyLong_AsInt(arg);
10788         if (value == -1 && PyErr_Occurred())
10789             return 0;
10790         *valuep = value;
10791         return 1;
10792     }
10793     else {
10794         /* look up the value in the table using a binary search */
10795         size_t lo = 0;
10796         size_t mid;
10797         size_t hi = tablesize;
10798         int cmp;
10799         const char *confname;
10800         if (!PyUnicode_Check(arg)) {
10801             PyErr_SetString(PyExc_TypeError,
10802                 "configuration names must be strings or integers");
10803             return 0;
10804         }
10805         confname = PyUnicode_AsUTF8(arg);
10806         if (confname == NULL)
10807             return 0;
10808         while (lo < hi) {
10809             mid = (lo + hi) / 2;
10810             cmp = strcmp(confname, table[mid].name);
10811             if (cmp < 0)
10812                 hi = mid;
10813             else if (cmp > 0)
10814                 lo = mid + 1;
10815             else {
10816                 *valuep = table[mid].value;
10817                 return 1;
10818             }
10819         }
10820         PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
10821         return 0;
10822     }
10823 }
10824 
10825 
10826 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
10827 static struct constdef  posix_constants_pathconf[] = {
10828 #ifdef _PC_ABI_AIO_XFER_MAX
10829     {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
10830 #endif
10831 #ifdef _PC_ABI_ASYNC_IO
10832     {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
10833 #endif
10834 #ifdef _PC_ASYNC_IO
10835     {"PC_ASYNC_IO",     _PC_ASYNC_IO},
10836 #endif
10837 #ifdef _PC_CHOWN_RESTRICTED
10838     {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
10839 #endif
10840 #ifdef _PC_FILESIZEBITS
10841     {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
10842 #endif
10843 #ifdef _PC_LAST
10844     {"PC_LAST", _PC_LAST},
10845 #endif
10846 #ifdef _PC_LINK_MAX
10847     {"PC_LINK_MAX",     _PC_LINK_MAX},
10848 #endif
10849 #ifdef _PC_MAX_CANON
10850     {"PC_MAX_CANON",    _PC_MAX_CANON},
10851 #endif
10852 #ifdef _PC_MAX_INPUT
10853     {"PC_MAX_INPUT",    _PC_MAX_INPUT},
10854 #endif
10855 #ifdef _PC_NAME_MAX
10856     {"PC_NAME_MAX",     _PC_NAME_MAX},
10857 #endif
10858 #ifdef _PC_NO_TRUNC
10859     {"PC_NO_TRUNC",     _PC_NO_TRUNC},
10860 #endif
10861 #ifdef _PC_PATH_MAX
10862     {"PC_PATH_MAX",     _PC_PATH_MAX},
10863 #endif
10864 #ifdef _PC_PIPE_BUF
10865     {"PC_PIPE_BUF",     _PC_PIPE_BUF},
10866 #endif
10867 #ifdef _PC_PRIO_IO
10868     {"PC_PRIO_IO",      _PC_PRIO_IO},
10869 #endif
10870 #ifdef _PC_SOCK_MAXBUF
10871     {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
10872 #endif
10873 #ifdef _PC_SYNC_IO
10874     {"PC_SYNC_IO",      _PC_SYNC_IO},
10875 #endif
10876 #ifdef _PC_VDISABLE
10877     {"PC_VDISABLE",     _PC_VDISABLE},
10878 #endif
10879 #ifdef _PC_ACL_ENABLED
10880     {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
10881 #endif
10882 #ifdef _PC_MIN_HOLE_SIZE
10883     {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
10884 #endif
10885 #ifdef _PC_ALLOC_SIZE_MIN
10886     {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
10887 #endif
10888 #ifdef _PC_REC_INCR_XFER_SIZE
10889     {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
10890 #endif
10891 #ifdef _PC_REC_MAX_XFER_SIZE
10892     {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
10893 #endif
10894 #ifdef _PC_REC_MIN_XFER_SIZE
10895     {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
10896 #endif
10897 #ifdef _PC_REC_XFER_ALIGN
10898     {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
10899 #endif
10900 #ifdef _PC_SYMLINK_MAX
10901     {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
10902 #endif
10903 #ifdef _PC_XATTR_ENABLED
10904     {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
10905 #endif
10906 #ifdef _PC_XATTR_EXISTS
10907     {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
10908 #endif
10909 #ifdef _PC_TIMESTAMP_RESOLUTION
10910     {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
10911 #endif
10912 };
10913 
10914 static int
conv_path_confname(PyObject * arg,int * valuep)10915 conv_path_confname(PyObject *arg, int *valuep)
10916 {
10917     return conv_confname(arg, valuep, posix_constants_pathconf,
10918                          sizeof(posix_constants_pathconf)
10919                            / sizeof(struct constdef));
10920 }
10921 #endif
10922 
10923 
10924 #ifdef HAVE_FPATHCONF
10925 /*[clinic input]
10926 os.fpathconf -> long
10927 
10928     fd: int
10929     name: path_confname
10930     /
10931 
10932 Return the configuration limit name for the file descriptor fd.
10933 
10934 If there is no limit, return -1.
10935 [clinic start generated code]*/
10936 
10937 static long
os_fpathconf_impl(PyObject * module,int fd,int name)10938 os_fpathconf_impl(PyObject *module, int fd, int name)
10939 /*[clinic end generated code: output=d5b7042425fc3e21 input=5942a024d3777810]*/
10940 {
10941     long limit;
10942 
10943     errno = 0;
10944     limit = fpathconf(fd, name);
10945     if (limit == -1 && errno != 0)
10946         posix_error();
10947 
10948     return limit;
10949 }
10950 #endif /* HAVE_FPATHCONF */
10951 
10952 
10953 #ifdef HAVE_PATHCONF
10954 /*[clinic input]
10955 os.pathconf -> long
10956     path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
10957     name: path_confname
10958 
10959 Return the configuration limit name for the file or directory path.
10960 
10961 If there is no limit, return -1.
10962 On some platforms, path may also be specified as an open file descriptor.
10963   If this functionality is unavailable, using it raises an exception.
10964 [clinic start generated code]*/
10965 
10966 static long
os_pathconf_impl(PyObject * module,path_t * path,int name)10967 os_pathconf_impl(PyObject *module, path_t *path, int name)
10968 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
10969 {
10970     long limit;
10971 
10972     errno = 0;
10973 #ifdef HAVE_FPATHCONF
10974     if (path->fd != -1)
10975         limit = fpathconf(path->fd, name);
10976     else
10977 #endif
10978         limit = pathconf(path->narrow, name);
10979     if (limit == -1 && errno != 0) {
10980         if (errno == EINVAL)
10981             /* could be a path or name problem */
10982             posix_error();
10983         else
10984             path_error(path);
10985     }
10986 
10987     return limit;
10988 }
10989 #endif /* HAVE_PATHCONF */
10990 
10991 #ifdef HAVE_CONFSTR
10992 static struct constdef posix_constants_confstr[] = {
10993 #ifdef _CS_ARCHITECTURE
10994     {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
10995 #endif
10996 #ifdef _CS_GNU_LIBC_VERSION
10997     {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
10998 #endif
10999 #ifdef _CS_GNU_LIBPTHREAD_VERSION
11000     {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
11001 #endif
11002 #ifdef _CS_HOSTNAME
11003     {"CS_HOSTNAME",     _CS_HOSTNAME},
11004 #endif
11005 #ifdef _CS_HW_PROVIDER
11006     {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
11007 #endif
11008 #ifdef _CS_HW_SERIAL
11009     {"CS_HW_SERIAL",    _CS_HW_SERIAL},
11010 #endif
11011 #ifdef _CS_INITTAB_NAME
11012     {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11013 #endif
11014 #ifdef _CS_LFS64_CFLAGS
11015     {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11016 #endif
11017 #ifdef _CS_LFS64_LDFLAGS
11018     {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
11019 #endif
11020 #ifdef _CS_LFS64_LIBS
11021     {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
11022 #endif
11023 #ifdef _CS_LFS64_LINTFLAGS
11024     {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
11025 #endif
11026 #ifdef _CS_LFS_CFLAGS
11027     {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
11028 #endif
11029 #ifdef _CS_LFS_LDFLAGS
11030     {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
11031 #endif
11032 #ifdef _CS_LFS_LIBS
11033     {"CS_LFS_LIBS",     _CS_LFS_LIBS},
11034 #endif
11035 #ifdef _CS_LFS_LINTFLAGS
11036     {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
11037 #endif
11038 #ifdef _CS_MACHINE
11039     {"CS_MACHINE",      _CS_MACHINE},
11040 #endif
11041 #ifdef _CS_PATH
11042     {"CS_PATH", _CS_PATH},
11043 #endif
11044 #ifdef _CS_RELEASE
11045     {"CS_RELEASE",      _CS_RELEASE},
11046 #endif
11047 #ifdef _CS_SRPC_DOMAIN
11048     {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
11049 #endif
11050 #ifdef _CS_SYSNAME
11051     {"CS_SYSNAME",      _CS_SYSNAME},
11052 #endif
11053 #ifdef _CS_VERSION
11054     {"CS_VERSION",      _CS_VERSION},
11055 #endif
11056 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11057     {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
11058 #endif
11059 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11060     {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
11061 #endif
11062 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11063     {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
11064 #endif
11065 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11066     {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11067 #endif
11068 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11069     {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11070 #endif
11071 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11072     {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11073 #endif
11074 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11075     {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
11076 #endif
11077 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11078     {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11079 #endif
11080 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11081     {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
11082 #endif
11083 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11084     {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
11085 #endif
11086 #ifdef _CS_XBS5_LP64_OFF64_LIBS
11087     {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11088 #endif
11089 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11090     {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
11091 #endif
11092 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11093     {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11094 #endif
11095 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11096     {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11097 #endif
11098 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11099     {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
11100 #endif
11101 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11102     {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11103 #endif
11104 #ifdef _MIPS_CS_AVAIL_PROCESSORS
11105     {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
11106 #endif
11107 #ifdef _MIPS_CS_BASE
11108     {"MIPS_CS_BASE",    _MIPS_CS_BASE},
11109 #endif
11110 #ifdef _MIPS_CS_HOSTID
11111     {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
11112 #endif
11113 #ifdef _MIPS_CS_HW_NAME
11114     {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11115 #endif
11116 #ifdef _MIPS_CS_NUM_PROCESSORS
11117     {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
11118 #endif
11119 #ifdef _MIPS_CS_OSREL_MAJ
11120     {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
11121 #endif
11122 #ifdef _MIPS_CS_OSREL_MIN
11123     {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
11124 #endif
11125 #ifdef _MIPS_CS_OSREL_PATCH
11126     {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
11127 #endif
11128 #ifdef _MIPS_CS_OS_NAME
11129     {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11130 #endif
11131 #ifdef _MIPS_CS_OS_PROVIDER
11132     {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
11133 #endif
11134 #ifdef _MIPS_CS_PROCESSORS
11135     {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
11136 #endif
11137 #ifdef _MIPS_CS_SERIAL
11138     {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
11139 #endif
11140 #ifdef _MIPS_CS_VENDOR
11141     {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
11142 #endif
11143 };
11144 
11145 static int
conv_confstr_confname(PyObject * arg,int * valuep)11146 conv_confstr_confname(PyObject *arg, int *valuep)
11147 {
11148     return conv_confname(arg, valuep, posix_constants_confstr,
11149                          sizeof(posix_constants_confstr)
11150                            / sizeof(struct constdef));
11151 }
11152 
11153 
11154 /*[clinic input]
11155 os.confstr
11156 
11157     name: confstr_confname
11158     /
11159 
11160 Return a string-valued system configuration variable.
11161 [clinic start generated code]*/
11162 
11163 static PyObject *
os_confstr_impl(PyObject * module,int name)11164 os_confstr_impl(PyObject *module, int name)
11165 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11166 {
11167     PyObject *result = NULL;
11168     char buffer[255];
11169     size_t len;
11170 
11171     errno = 0;
11172     len = confstr(name, buffer, sizeof(buffer));
11173     if (len == 0) {
11174         if (errno) {
11175             posix_error();
11176             return NULL;
11177         }
11178         else {
11179             Py_RETURN_NONE;
11180         }
11181     }
11182 
11183     if (len >= sizeof(buffer)) {
11184         size_t len2;
11185         char *buf = PyMem_Malloc(len);
11186         if (buf == NULL)
11187             return PyErr_NoMemory();
11188         len2 = confstr(name, buf, len);
11189         assert(len == len2);
11190         result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11191         PyMem_Free(buf);
11192     }
11193     else
11194         result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11195     return result;
11196 }
11197 #endif /* HAVE_CONFSTR */
11198 
11199 
11200 #ifdef HAVE_SYSCONF
11201 static struct constdef posix_constants_sysconf[] = {
11202 #ifdef _SC_2_CHAR_TERM
11203     {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
11204 #endif
11205 #ifdef _SC_2_C_BIND
11206     {"SC_2_C_BIND",     _SC_2_C_BIND},
11207 #endif
11208 #ifdef _SC_2_C_DEV
11209     {"SC_2_C_DEV",      _SC_2_C_DEV},
11210 #endif
11211 #ifdef _SC_2_C_VERSION
11212     {"SC_2_C_VERSION",  _SC_2_C_VERSION},
11213 #endif
11214 #ifdef _SC_2_FORT_DEV
11215     {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
11216 #endif
11217 #ifdef _SC_2_FORT_RUN
11218     {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
11219 #endif
11220 #ifdef _SC_2_LOCALEDEF
11221     {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
11222 #endif
11223 #ifdef _SC_2_SW_DEV
11224     {"SC_2_SW_DEV",     _SC_2_SW_DEV},
11225 #endif
11226 #ifdef _SC_2_UPE
11227     {"SC_2_UPE",        _SC_2_UPE},
11228 #endif
11229 #ifdef _SC_2_VERSION
11230     {"SC_2_VERSION",    _SC_2_VERSION},
11231 #endif
11232 #ifdef _SC_ABI_ASYNCHRONOUS_IO
11233     {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
11234 #endif
11235 #ifdef _SC_ACL
11236     {"SC_ACL",  _SC_ACL},
11237 #endif
11238 #ifdef _SC_AIO_LISTIO_MAX
11239     {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
11240 #endif
11241 #ifdef _SC_AIO_MAX
11242     {"SC_AIO_MAX",      _SC_AIO_MAX},
11243 #endif
11244 #ifdef _SC_AIO_PRIO_DELTA_MAX
11245     {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
11246 #endif
11247 #ifdef _SC_ARG_MAX
11248     {"SC_ARG_MAX",      _SC_ARG_MAX},
11249 #endif
11250 #ifdef _SC_ASYNCHRONOUS_IO
11251     {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
11252 #endif
11253 #ifdef _SC_ATEXIT_MAX
11254     {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
11255 #endif
11256 #ifdef _SC_AUDIT
11257     {"SC_AUDIT",        _SC_AUDIT},
11258 #endif
11259 #ifdef _SC_AVPHYS_PAGES
11260     {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
11261 #endif
11262 #ifdef _SC_BC_BASE_MAX
11263     {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
11264 #endif
11265 #ifdef _SC_BC_DIM_MAX
11266     {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
11267 #endif
11268 #ifdef _SC_BC_SCALE_MAX
11269     {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
11270 #endif
11271 #ifdef _SC_BC_STRING_MAX
11272     {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
11273 #endif
11274 #ifdef _SC_CAP
11275     {"SC_CAP",  _SC_CAP},
11276 #endif
11277 #ifdef _SC_CHARCLASS_NAME_MAX
11278     {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
11279 #endif
11280 #ifdef _SC_CHAR_BIT
11281     {"SC_CHAR_BIT",     _SC_CHAR_BIT},
11282 #endif
11283 #ifdef _SC_CHAR_MAX
11284     {"SC_CHAR_MAX",     _SC_CHAR_MAX},
11285 #endif
11286 #ifdef _SC_CHAR_MIN
11287     {"SC_CHAR_MIN",     _SC_CHAR_MIN},
11288 #endif
11289 #ifdef _SC_CHILD_MAX
11290     {"SC_CHILD_MAX",    _SC_CHILD_MAX},
11291 #endif
11292 #ifdef _SC_CLK_TCK
11293     {"SC_CLK_TCK",      _SC_CLK_TCK},
11294 #endif
11295 #ifdef _SC_COHER_BLKSZ
11296     {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
11297 #endif
11298 #ifdef _SC_COLL_WEIGHTS_MAX
11299     {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
11300 #endif
11301 #ifdef _SC_DCACHE_ASSOC
11302     {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
11303 #endif
11304 #ifdef _SC_DCACHE_BLKSZ
11305     {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
11306 #endif
11307 #ifdef _SC_DCACHE_LINESZ
11308     {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
11309 #endif
11310 #ifdef _SC_DCACHE_SZ
11311     {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
11312 #endif
11313 #ifdef _SC_DCACHE_TBLKSZ
11314     {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
11315 #endif
11316 #ifdef _SC_DELAYTIMER_MAX
11317     {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
11318 #endif
11319 #ifdef _SC_EQUIV_CLASS_MAX
11320     {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
11321 #endif
11322 #ifdef _SC_EXPR_NEST_MAX
11323     {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
11324 #endif
11325 #ifdef _SC_FSYNC
11326     {"SC_FSYNC",        _SC_FSYNC},
11327 #endif
11328 #ifdef _SC_GETGR_R_SIZE_MAX
11329     {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
11330 #endif
11331 #ifdef _SC_GETPW_R_SIZE_MAX
11332     {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
11333 #endif
11334 #ifdef _SC_ICACHE_ASSOC
11335     {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
11336 #endif
11337 #ifdef _SC_ICACHE_BLKSZ
11338     {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
11339 #endif
11340 #ifdef _SC_ICACHE_LINESZ
11341     {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
11342 #endif
11343 #ifdef _SC_ICACHE_SZ
11344     {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
11345 #endif
11346 #ifdef _SC_INF
11347     {"SC_INF",  _SC_INF},
11348 #endif
11349 #ifdef _SC_INT_MAX
11350     {"SC_INT_MAX",      _SC_INT_MAX},
11351 #endif
11352 #ifdef _SC_INT_MIN
11353     {"SC_INT_MIN",      _SC_INT_MIN},
11354 #endif
11355 #ifdef _SC_IOV_MAX
11356     {"SC_IOV_MAX",      _SC_IOV_MAX},
11357 #endif
11358 #ifdef _SC_IP_SECOPTS
11359     {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
11360 #endif
11361 #ifdef _SC_JOB_CONTROL
11362     {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
11363 #endif
11364 #ifdef _SC_KERN_POINTERS
11365     {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
11366 #endif
11367 #ifdef _SC_KERN_SIM
11368     {"SC_KERN_SIM",     _SC_KERN_SIM},
11369 #endif
11370 #ifdef _SC_LINE_MAX
11371     {"SC_LINE_MAX",     _SC_LINE_MAX},
11372 #endif
11373 #ifdef _SC_LOGIN_NAME_MAX
11374     {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
11375 #endif
11376 #ifdef _SC_LOGNAME_MAX
11377     {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
11378 #endif
11379 #ifdef _SC_LONG_BIT
11380     {"SC_LONG_BIT",     _SC_LONG_BIT},
11381 #endif
11382 #ifdef _SC_MAC
11383     {"SC_MAC",  _SC_MAC},
11384 #endif
11385 #ifdef _SC_MAPPED_FILES
11386     {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
11387 #endif
11388 #ifdef _SC_MAXPID
11389     {"SC_MAXPID",       _SC_MAXPID},
11390 #endif
11391 #ifdef _SC_MB_LEN_MAX
11392     {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
11393 #endif
11394 #ifdef _SC_MEMLOCK
11395     {"SC_MEMLOCK",      _SC_MEMLOCK},
11396 #endif
11397 #ifdef _SC_MEMLOCK_RANGE
11398     {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
11399 #endif
11400 #ifdef _SC_MEMORY_PROTECTION
11401     {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
11402 #endif
11403 #ifdef _SC_MESSAGE_PASSING
11404     {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
11405 #endif
11406 #ifdef _SC_MMAP_FIXED_ALIGNMENT
11407     {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
11408 #endif
11409 #ifdef _SC_MQ_OPEN_MAX
11410     {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
11411 #endif
11412 #ifdef _SC_MQ_PRIO_MAX
11413     {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
11414 #endif
11415 #ifdef _SC_NACLS_MAX
11416     {"SC_NACLS_MAX",    _SC_NACLS_MAX},
11417 #endif
11418 #ifdef _SC_NGROUPS_MAX
11419     {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
11420 #endif
11421 #ifdef _SC_NL_ARGMAX
11422     {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
11423 #endif
11424 #ifdef _SC_NL_LANGMAX
11425     {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
11426 #endif
11427 #ifdef _SC_NL_MSGMAX
11428     {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
11429 #endif
11430 #ifdef _SC_NL_NMAX
11431     {"SC_NL_NMAX",      _SC_NL_NMAX},
11432 #endif
11433 #ifdef _SC_NL_SETMAX
11434     {"SC_NL_SETMAX",    _SC_NL_SETMAX},
11435 #endif
11436 #ifdef _SC_NL_TEXTMAX
11437     {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
11438 #endif
11439 #ifdef _SC_NPROCESSORS_CONF
11440     {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
11441 #endif
11442 #ifdef _SC_NPROCESSORS_ONLN
11443     {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
11444 #endif
11445 #ifdef _SC_NPROC_CONF
11446     {"SC_NPROC_CONF",   _SC_NPROC_CONF},
11447 #endif
11448 #ifdef _SC_NPROC_ONLN
11449     {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
11450 #endif
11451 #ifdef _SC_NZERO
11452     {"SC_NZERO",        _SC_NZERO},
11453 #endif
11454 #ifdef _SC_OPEN_MAX
11455     {"SC_OPEN_MAX",     _SC_OPEN_MAX},
11456 #endif
11457 #ifdef _SC_PAGESIZE
11458     {"SC_PAGESIZE",     _SC_PAGESIZE},
11459 #endif
11460 #ifdef _SC_PAGE_SIZE
11461     {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
11462 #endif
11463 #ifdef _SC_PASS_MAX
11464     {"SC_PASS_MAX",     _SC_PASS_MAX},
11465 #endif
11466 #ifdef _SC_PHYS_PAGES
11467     {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
11468 #endif
11469 #ifdef _SC_PII
11470     {"SC_PII",  _SC_PII},
11471 #endif
11472 #ifdef _SC_PII_INTERNET
11473     {"SC_PII_INTERNET", _SC_PII_INTERNET},
11474 #endif
11475 #ifdef _SC_PII_INTERNET_DGRAM
11476     {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
11477 #endif
11478 #ifdef _SC_PII_INTERNET_STREAM
11479     {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
11480 #endif
11481 #ifdef _SC_PII_OSI
11482     {"SC_PII_OSI",      _SC_PII_OSI},
11483 #endif
11484 #ifdef _SC_PII_OSI_CLTS
11485     {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
11486 #endif
11487 #ifdef _SC_PII_OSI_COTS
11488     {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
11489 #endif
11490 #ifdef _SC_PII_OSI_M
11491     {"SC_PII_OSI_M",    _SC_PII_OSI_M},
11492 #endif
11493 #ifdef _SC_PII_SOCKET
11494     {"SC_PII_SOCKET",   _SC_PII_SOCKET},
11495 #endif
11496 #ifdef _SC_PII_XTI
11497     {"SC_PII_XTI",      _SC_PII_XTI},
11498 #endif
11499 #ifdef _SC_POLL
11500     {"SC_POLL", _SC_POLL},
11501 #endif
11502 #ifdef _SC_PRIORITIZED_IO
11503     {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
11504 #endif
11505 #ifdef _SC_PRIORITY_SCHEDULING
11506     {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
11507 #endif
11508 #ifdef _SC_REALTIME_SIGNALS
11509     {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
11510 #endif
11511 #ifdef _SC_RE_DUP_MAX
11512     {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
11513 #endif
11514 #ifdef _SC_RTSIG_MAX
11515     {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
11516 #endif
11517 #ifdef _SC_SAVED_IDS
11518     {"SC_SAVED_IDS",    _SC_SAVED_IDS},
11519 #endif
11520 #ifdef _SC_SCHAR_MAX
11521     {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
11522 #endif
11523 #ifdef _SC_SCHAR_MIN
11524     {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
11525 #endif
11526 #ifdef _SC_SELECT
11527     {"SC_SELECT",       _SC_SELECT},
11528 #endif
11529 #ifdef _SC_SEMAPHORES
11530     {"SC_SEMAPHORES",   _SC_SEMAPHORES},
11531 #endif
11532 #ifdef _SC_SEM_NSEMS_MAX
11533     {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
11534 #endif
11535 #ifdef _SC_SEM_VALUE_MAX
11536     {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
11537 #endif
11538 #ifdef _SC_SHARED_MEMORY_OBJECTS
11539     {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
11540 #endif
11541 #ifdef _SC_SHRT_MAX
11542     {"SC_SHRT_MAX",     _SC_SHRT_MAX},
11543 #endif
11544 #ifdef _SC_SHRT_MIN
11545     {"SC_SHRT_MIN",     _SC_SHRT_MIN},
11546 #endif
11547 #ifdef _SC_SIGQUEUE_MAX
11548     {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
11549 #endif
11550 #ifdef _SC_SIGRT_MAX
11551     {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
11552 #endif
11553 #ifdef _SC_SIGRT_MIN
11554     {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
11555 #endif
11556 #ifdef _SC_SOFTPOWER
11557     {"SC_SOFTPOWER",    _SC_SOFTPOWER},
11558 #endif
11559 #ifdef _SC_SPLIT_CACHE
11560     {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
11561 #endif
11562 #ifdef _SC_SSIZE_MAX
11563     {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
11564 #endif
11565 #ifdef _SC_STACK_PROT
11566     {"SC_STACK_PROT",   _SC_STACK_PROT},
11567 #endif
11568 #ifdef _SC_STREAM_MAX
11569     {"SC_STREAM_MAX",   _SC_STREAM_MAX},
11570 #endif
11571 #ifdef _SC_SYNCHRONIZED_IO
11572     {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
11573 #endif
11574 #ifdef _SC_THREADS
11575     {"SC_THREADS",      _SC_THREADS},
11576 #endif
11577 #ifdef _SC_THREAD_ATTR_STACKADDR
11578     {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
11579 #endif
11580 #ifdef _SC_THREAD_ATTR_STACKSIZE
11581     {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
11582 #endif
11583 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
11584     {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
11585 #endif
11586 #ifdef _SC_THREAD_KEYS_MAX
11587     {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
11588 #endif
11589 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
11590     {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
11591 #endif
11592 #ifdef _SC_THREAD_PRIO_INHERIT
11593     {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
11594 #endif
11595 #ifdef _SC_THREAD_PRIO_PROTECT
11596     {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
11597 #endif
11598 #ifdef _SC_THREAD_PROCESS_SHARED
11599     {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
11600 #endif
11601 #ifdef _SC_THREAD_SAFE_FUNCTIONS
11602     {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
11603 #endif
11604 #ifdef _SC_THREAD_STACK_MIN
11605     {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
11606 #endif
11607 #ifdef _SC_THREAD_THREADS_MAX
11608     {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
11609 #endif
11610 #ifdef _SC_TIMERS
11611     {"SC_TIMERS",       _SC_TIMERS},
11612 #endif
11613 #ifdef _SC_TIMER_MAX
11614     {"SC_TIMER_MAX",    _SC_TIMER_MAX},
11615 #endif
11616 #ifdef _SC_TTY_NAME_MAX
11617     {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
11618 #endif
11619 #ifdef _SC_TZNAME_MAX
11620     {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
11621 #endif
11622 #ifdef _SC_T_IOV_MAX
11623     {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
11624 #endif
11625 #ifdef _SC_UCHAR_MAX
11626     {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
11627 #endif
11628 #ifdef _SC_UINT_MAX
11629     {"SC_UINT_MAX",     _SC_UINT_MAX},
11630 #endif
11631 #ifdef _SC_UIO_MAXIOV
11632     {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
11633 #endif
11634 #ifdef _SC_ULONG_MAX
11635     {"SC_ULONG_MAX",    _SC_ULONG_MAX},
11636 #endif
11637 #ifdef _SC_USHRT_MAX
11638     {"SC_USHRT_MAX",    _SC_USHRT_MAX},
11639 #endif
11640 #ifdef _SC_VERSION
11641     {"SC_VERSION",      _SC_VERSION},
11642 #endif
11643 #ifdef _SC_WORD_BIT
11644     {"SC_WORD_BIT",     _SC_WORD_BIT},
11645 #endif
11646 #ifdef _SC_XBS5_ILP32_OFF32
11647     {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
11648 #endif
11649 #ifdef _SC_XBS5_ILP32_OFFBIG
11650     {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
11651 #endif
11652 #ifdef _SC_XBS5_LP64_OFF64
11653     {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
11654 #endif
11655 #ifdef _SC_XBS5_LPBIG_OFFBIG
11656     {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
11657 #endif
11658 #ifdef _SC_XOPEN_CRYPT
11659     {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
11660 #endif
11661 #ifdef _SC_XOPEN_ENH_I18N
11662     {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
11663 #endif
11664 #ifdef _SC_XOPEN_LEGACY
11665     {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
11666 #endif
11667 #ifdef _SC_XOPEN_REALTIME
11668     {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
11669 #endif
11670 #ifdef _SC_XOPEN_REALTIME_THREADS
11671     {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
11672 #endif
11673 #ifdef _SC_XOPEN_SHM
11674     {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
11675 #endif
11676 #ifdef _SC_XOPEN_UNIX
11677     {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
11678 #endif
11679 #ifdef _SC_XOPEN_VERSION
11680     {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
11681 #endif
11682 #ifdef _SC_XOPEN_XCU_VERSION
11683     {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
11684 #endif
11685 #ifdef _SC_XOPEN_XPG2
11686     {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
11687 #endif
11688 #ifdef _SC_XOPEN_XPG3
11689     {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
11690 #endif
11691 #ifdef _SC_XOPEN_XPG4
11692     {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
11693 #endif
11694 };
11695 
11696 static int
conv_sysconf_confname(PyObject * arg,int * valuep)11697 conv_sysconf_confname(PyObject *arg, int *valuep)
11698 {
11699     return conv_confname(arg, valuep, posix_constants_sysconf,
11700                          sizeof(posix_constants_sysconf)
11701                            / sizeof(struct constdef));
11702 }
11703 
11704 
11705 /*[clinic input]
11706 os.sysconf -> long
11707     name: sysconf_confname
11708     /
11709 
11710 Return an integer-valued system configuration variable.
11711 [clinic start generated code]*/
11712 
11713 static long
os_sysconf_impl(PyObject * module,int name)11714 os_sysconf_impl(PyObject *module, int name)
11715 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
11716 {
11717     long value;
11718 
11719     errno = 0;
11720     value = sysconf(name);
11721     if (value == -1 && errno != 0)
11722         posix_error();
11723     return value;
11724 }
11725 #endif /* HAVE_SYSCONF */
11726 
11727 
11728 /* This code is used to ensure that the tables of configuration value names
11729  * are in sorted order as required by conv_confname(), and also to build
11730  * the exported dictionaries that are used to publish information about the
11731  * names available on the host platform.
11732  *
11733  * Sorting the table at runtime ensures that the table is properly ordered
11734  * when used, even for platforms we're not able to test on.  It also makes
11735  * it easier to add additional entries to the tables.
11736  */
11737 
11738 static int
cmp_constdefs(const void * v1,const void * v2)11739 cmp_constdefs(const void *v1,  const void *v2)
11740 {
11741     const struct constdef *c1 =
11742     (const struct constdef *) v1;
11743     const struct constdef *c2 =
11744     (const struct constdef *) v2;
11745 
11746     return strcmp(c1->name, c2->name);
11747 }
11748 
11749 static int
setup_confname_table(struct constdef * table,size_t tablesize,const char * tablename,PyObject * module)11750 setup_confname_table(struct constdef *table, size_t tablesize,
11751                      const char *tablename, PyObject *module)
11752 {
11753     PyObject *d = NULL;
11754     size_t i;
11755 
11756     qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
11757     d = PyDict_New();
11758     if (d == NULL)
11759         return -1;
11760 
11761     for (i=0; i < tablesize; ++i) {
11762         PyObject *o = PyLong_FromLong(table[i].value);
11763         if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
11764             Py_XDECREF(o);
11765             Py_DECREF(d);
11766             return -1;
11767         }
11768         Py_DECREF(o);
11769     }
11770     return PyModule_AddObject(module, tablename, d);
11771 }
11772 
11773 /* Return -1 on failure, 0 on success. */
11774 static int
setup_confname_tables(PyObject * module)11775 setup_confname_tables(PyObject *module)
11776 {
11777 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11778     if (setup_confname_table(posix_constants_pathconf,
11779                              sizeof(posix_constants_pathconf)
11780                                / sizeof(struct constdef),
11781                              "pathconf_names", module))
11782         return -1;
11783 #endif
11784 #ifdef HAVE_CONFSTR
11785     if (setup_confname_table(posix_constants_confstr,
11786                              sizeof(posix_constants_confstr)
11787                                / sizeof(struct constdef),
11788                              "confstr_names", module))
11789         return -1;
11790 #endif
11791 #ifdef HAVE_SYSCONF
11792     if (setup_confname_table(posix_constants_sysconf,
11793                              sizeof(posix_constants_sysconf)
11794                                / sizeof(struct constdef),
11795                              "sysconf_names", module))
11796         return -1;
11797 #endif
11798     return 0;
11799 }
11800 
11801 
11802 /*[clinic input]
11803 os.abort
11804 
11805 Abort the interpreter immediately.
11806 
11807 This function 'dumps core' or otherwise fails in the hardest way possible
11808 on the hosting operating system.  This function never returns.
11809 [clinic start generated code]*/
11810 
11811 static PyObject *
os_abort_impl(PyObject * module)11812 os_abort_impl(PyObject *module)
11813 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
11814 {
11815     abort();
11816     /*NOTREACHED*/
11817 #ifndef __clang__
11818     /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
11819        GCC emits a warning without "return NULL;" (compiler bug?), but Clang
11820        is smarter and emits a warning on the return. */
11821     Py_FatalError("abort() called from Python code didn't abort!");
11822     return NULL;
11823 #endif
11824 }
11825 
11826 #ifdef MS_WINDOWS
11827 /* Grab ShellExecute dynamically from shell32 */
11828 static int has_ShellExecute = -1;
11829 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
11830                                               LPCWSTR, INT);
11831 static int
check_ShellExecute()11832 check_ShellExecute()
11833 {
11834     HINSTANCE hShell32;
11835 
11836     /* only recheck */
11837     if (-1 == has_ShellExecute) {
11838         Py_BEGIN_ALLOW_THREADS
11839         /* Security note: this call is not vulnerable to "DLL hijacking".
11840            SHELL32 is part of "KnownDLLs" and so Windows always load
11841            the system SHELL32.DLL, even if there is another SHELL32.DLL
11842            in the DLL search path. */
11843         hShell32 = LoadLibraryW(L"SHELL32");
11844         if (hShell32) {
11845             *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
11846                                             "ShellExecuteW");
11847             has_ShellExecute = Py_ShellExecuteW != NULL;
11848         } else {
11849             has_ShellExecute = 0;
11850         }
11851         Py_END_ALLOW_THREADS
11852     }
11853     return has_ShellExecute;
11854 }
11855 
11856 
11857 /*[clinic input]
11858 os.startfile
11859     filepath: path_t
11860     operation: Py_UNICODE = NULL
11861 
11862 Start a file with its associated application.
11863 
11864 When "operation" is not specified or "open", this acts like
11865 double-clicking the file in Explorer, or giving the file name as an
11866 argument to the DOS "start" command: the file is opened with whatever
11867 application (if any) its extension is associated.
11868 When another "operation" is given, it specifies what should be done with
11869 the file.  A typical operation is "print".
11870 
11871 startfile returns as soon as the associated application is launched.
11872 There is no option to wait for the application to close, and no way
11873 to retrieve the application's exit status.
11874 
11875 The filepath is relative to the current directory.  If you want to use
11876 an absolute path, make sure the first character is not a slash ("/");
11877 the underlying Win32 ShellExecute function doesn't work if it is.
11878 [clinic start generated code]*/
11879 
11880 static PyObject *
os_startfile_impl(PyObject * module,path_t * filepath,const Py_UNICODE * operation)11881 os_startfile_impl(PyObject *module, path_t *filepath,
11882                   const Py_UNICODE *operation)
11883 /*[clinic end generated code: output=66dc311c94d50797 input=c940888a5390f039]*/
11884 {
11885     HINSTANCE rc;
11886 
11887     if(!check_ShellExecute()) {
11888         /* If the OS doesn't have ShellExecute, return a
11889            NotImplementedError. */
11890         return PyErr_Format(PyExc_NotImplementedError,
11891             "startfile not available on this platform");
11892     }
11893 
11894     if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
11895         return NULL;
11896     }
11897 
11898     Py_BEGIN_ALLOW_THREADS
11899     rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
11900                           NULL, NULL, SW_SHOWNORMAL);
11901     Py_END_ALLOW_THREADS
11902 
11903     if (rc <= (HINSTANCE)32) {
11904         win32_error_object("startfile", filepath->object);
11905         return NULL;
11906     }
11907     Py_RETURN_NONE;
11908 }
11909 #endif /* MS_WINDOWS */
11910 
11911 
11912 #ifdef HAVE_GETLOADAVG
11913 /*[clinic input]
11914 os.getloadavg
11915 
11916 Return average recent system load information.
11917 
11918 Return the number of processes in the system run queue averaged over
11919 the last 1, 5, and 15 minutes as a tuple of three floats.
11920 Raises OSError if the load average was unobtainable.
11921 [clinic start generated code]*/
11922 
11923 static PyObject *
os_getloadavg_impl(PyObject * module)11924 os_getloadavg_impl(PyObject *module)
11925 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
11926 {
11927     double loadavg[3];
11928     if (getloadavg(loadavg, 3)!=3) {
11929         PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
11930         return NULL;
11931     } else
11932         return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
11933 }
11934 #endif /* HAVE_GETLOADAVG */
11935 
11936 
11937 /*[clinic input]
11938 os.device_encoding
11939     fd: int
11940 
11941 Return a string describing the encoding of a terminal's file descriptor.
11942 
11943 The file descriptor must be attached to a terminal.
11944 If the device is not a terminal, return None.
11945 [clinic start generated code]*/
11946 
11947 static PyObject *
os_device_encoding_impl(PyObject * module,int fd)11948 os_device_encoding_impl(PyObject *module, int fd)
11949 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
11950 {
11951     return _Py_device_encoding(fd);
11952 }
11953 
11954 
11955 #ifdef HAVE_SETRESUID
11956 /*[clinic input]
11957 os.setresuid
11958 
11959     ruid: uid_t
11960     euid: uid_t
11961     suid: uid_t
11962     /
11963 
11964 Set the current process's real, effective, and saved user ids.
11965 [clinic start generated code]*/
11966 
11967 static PyObject *
os_setresuid_impl(PyObject * module,uid_t ruid,uid_t euid,uid_t suid)11968 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
11969 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
11970 {
11971     if (setresuid(ruid, euid, suid) < 0)
11972         return posix_error();
11973     Py_RETURN_NONE;
11974 }
11975 #endif /* HAVE_SETRESUID */
11976 
11977 
11978 #ifdef HAVE_SETRESGID
11979 /*[clinic input]
11980 os.setresgid
11981 
11982     rgid: gid_t
11983     egid: gid_t
11984     sgid: gid_t
11985     /
11986 
11987 Set the current process's real, effective, and saved group ids.
11988 [clinic start generated code]*/
11989 
11990 static PyObject *
os_setresgid_impl(PyObject * module,gid_t rgid,gid_t egid,gid_t sgid)11991 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
11992 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
11993 {
11994     if (setresgid(rgid, egid, sgid) < 0)
11995         return posix_error();
11996     Py_RETURN_NONE;
11997 }
11998 #endif /* HAVE_SETRESGID */
11999 
12000 
12001 #ifdef HAVE_GETRESUID
12002 /*[clinic input]
12003 os.getresuid
12004 
12005 Return a tuple of the current process's real, effective, and saved user ids.
12006 [clinic start generated code]*/
12007 
12008 static PyObject *
os_getresuid_impl(PyObject * module)12009 os_getresuid_impl(PyObject *module)
12010 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12011 {
12012     uid_t ruid, euid, suid;
12013     if (getresuid(&ruid, &euid, &suid) < 0)
12014         return posix_error();
12015     return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12016                                   _PyLong_FromUid(euid),
12017                                   _PyLong_FromUid(suid));
12018 }
12019 #endif /* HAVE_GETRESUID */
12020 
12021 
12022 #ifdef HAVE_GETRESGID
12023 /*[clinic input]
12024 os.getresgid
12025 
12026 Return a tuple of the current process's real, effective, and saved group ids.
12027 [clinic start generated code]*/
12028 
12029 static PyObject *
os_getresgid_impl(PyObject * module)12030 os_getresgid_impl(PyObject *module)
12031 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12032 {
12033     gid_t rgid, egid, sgid;
12034     if (getresgid(&rgid, &egid, &sgid) < 0)
12035         return posix_error();
12036     return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12037                                   _PyLong_FromGid(egid),
12038                                   _PyLong_FromGid(sgid));
12039 }
12040 #endif /* HAVE_GETRESGID */
12041 
12042 
12043 #ifdef USE_XATTRS
12044 /*[clinic input]
12045 os.getxattr
12046 
12047     path: path_t(allow_fd=True)
12048     attribute: path_t
12049     *
12050     follow_symlinks: bool = True
12051 
12052 Return the value of extended attribute attribute on path.
12053 
12054 path may be either a string, a path-like object, or an open file descriptor.
12055 If follow_symlinks is False, and the last element of the path is a symbolic
12056   link, getxattr will examine the symbolic link itself instead of the file
12057   the link points to.
12058 
12059 [clinic start generated code]*/
12060 
12061 static PyObject *
os_getxattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12062 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12063                  int follow_symlinks)
12064 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12065 {
12066     Py_ssize_t i;
12067     PyObject *buffer = NULL;
12068 
12069     if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12070         return NULL;
12071 
12072     if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12073         return NULL;
12074     }
12075 
12076     for (i = 0; ; i++) {
12077         void *ptr;
12078         ssize_t result;
12079         static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12080         Py_ssize_t buffer_size = buffer_sizes[i];
12081         if (!buffer_size) {
12082             path_error(path);
12083             return NULL;
12084         }
12085         buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12086         if (!buffer)
12087             return NULL;
12088         ptr = PyBytes_AS_STRING(buffer);
12089 
12090         Py_BEGIN_ALLOW_THREADS;
12091         if (path->fd >= 0)
12092             result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12093         else if (follow_symlinks)
12094             result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12095         else
12096             result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12097         Py_END_ALLOW_THREADS;
12098 
12099         if (result < 0) {
12100             Py_DECREF(buffer);
12101             if (errno == ERANGE)
12102                 continue;
12103             path_error(path);
12104             return NULL;
12105         }
12106 
12107         if (result != buffer_size) {
12108             /* Can only shrink. */
12109             _PyBytes_Resize(&buffer, result);
12110         }
12111         break;
12112     }
12113 
12114     return buffer;
12115 }
12116 
12117 
12118 /*[clinic input]
12119 os.setxattr
12120 
12121     path: path_t(allow_fd=True)
12122     attribute: path_t
12123     value: Py_buffer
12124     flags: int = 0
12125     *
12126     follow_symlinks: bool = True
12127 
12128 Set extended attribute attribute on path to value.
12129 
12130 path may be either a string, a path-like object,  or an open file descriptor.
12131 If follow_symlinks is False, and the last element of the path is a symbolic
12132   link, setxattr will modify the symbolic link itself instead of the file
12133   the link points to.
12134 
12135 [clinic start generated code]*/
12136 
12137 static PyObject *
os_setxattr_impl(PyObject * module,path_t * path,path_t * attribute,Py_buffer * value,int flags,int follow_symlinks)12138 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12139                  Py_buffer *value, int flags, int follow_symlinks)
12140 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12141 {
12142     ssize_t result;
12143 
12144     if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12145         return NULL;
12146 
12147     if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12148                     value->buf, value->len, flags) < 0) {
12149         return NULL;
12150     }
12151 
12152     Py_BEGIN_ALLOW_THREADS;
12153     if (path->fd > -1)
12154         result = fsetxattr(path->fd, attribute->narrow,
12155                            value->buf, value->len, flags);
12156     else if (follow_symlinks)
12157         result = setxattr(path->narrow, attribute->narrow,
12158                            value->buf, value->len, flags);
12159     else
12160         result = lsetxattr(path->narrow, attribute->narrow,
12161                            value->buf, value->len, flags);
12162     Py_END_ALLOW_THREADS;
12163 
12164     if (result) {
12165         path_error(path);
12166         return NULL;
12167     }
12168 
12169     Py_RETURN_NONE;
12170 }
12171 
12172 
12173 /*[clinic input]
12174 os.removexattr
12175 
12176     path: path_t(allow_fd=True)
12177     attribute: path_t
12178     *
12179     follow_symlinks: bool = True
12180 
12181 Remove extended attribute attribute on path.
12182 
12183 path may be either a string, a path-like object, or an open file descriptor.
12184 If follow_symlinks is False, and the last element of the path is a symbolic
12185   link, removexattr will modify the symbolic link itself instead of the file
12186   the link points to.
12187 
12188 [clinic start generated code]*/
12189 
12190 static PyObject *
os_removexattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12191 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
12192                     int follow_symlinks)
12193 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
12194 {
12195     ssize_t result;
12196 
12197     if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
12198         return NULL;
12199 
12200     if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
12201         return NULL;
12202     }
12203 
12204     Py_BEGIN_ALLOW_THREADS;
12205     if (path->fd > -1)
12206         result = fremovexattr(path->fd, attribute->narrow);
12207     else if (follow_symlinks)
12208         result = removexattr(path->narrow, attribute->narrow);
12209     else
12210         result = lremovexattr(path->narrow, attribute->narrow);
12211     Py_END_ALLOW_THREADS;
12212 
12213     if (result) {
12214         return path_error(path);
12215     }
12216 
12217     Py_RETURN_NONE;
12218 }
12219 
12220 
12221 /*[clinic input]
12222 os.listxattr
12223 
12224     path: path_t(allow_fd=True, nullable=True) = None
12225     *
12226     follow_symlinks: bool = True
12227 
12228 Return a list of extended attributes on path.
12229 
12230 path may be either None, a string, a path-like object, or an open file descriptor.
12231 if path is None, listxattr will examine the current directory.
12232 If follow_symlinks is False, and the last element of the path is a symbolic
12233   link, listxattr will examine the symbolic link itself instead of the file
12234   the link points to.
12235 [clinic start generated code]*/
12236 
12237 static PyObject *
os_listxattr_impl(PyObject * module,path_t * path,int follow_symlinks)12238 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
12239 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
12240 {
12241     Py_ssize_t i;
12242     PyObject *result = NULL;
12243     const char *name;
12244     char *buffer = NULL;
12245 
12246     if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
12247         goto exit;
12248 
12249     if (PySys_Audit("os.listxattr", "(O)",
12250                     path->object ? path->object : Py_None) < 0) {
12251         return NULL;
12252     }
12253 
12254     name = path->narrow ? path->narrow : ".";
12255 
12256     for (i = 0; ; i++) {
12257         const char *start, *trace, *end;
12258         ssize_t length;
12259         static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
12260         Py_ssize_t buffer_size = buffer_sizes[i];
12261         if (!buffer_size) {
12262             /* ERANGE */
12263             path_error(path);
12264             break;
12265         }
12266         buffer = PyMem_MALLOC(buffer_size);
12267         if (!buffer) {
12268             PyErr_NoMemory();
12269             break;
12270         }
12271 
12272         Py_BEGIN_ALLOW_THREADS;
12273         if (path->fd > -1)
12274             length = flistxattr(path->fd, buffer, buffer_size);
12275         else if (follow_symlinks)
12276             length = listxattr(name, buffer, buffer_size);
12277         else
12278             length = llistxattr(name, buffer, buffer_size);
12279         Py_END_ALLOW_THREADS;
12280 
12281         if (length < 0) {
12282             if (errno == ERANGE) {
12283                 PyMem_FREE(buffer);
12284                 buffer = NULL;
12285                 continue;
12286             }
12287             path_error(path);
12288             break;
12289         }
12290 
12291         result = PyList_New(0);
12292         if (!result) {
12293             goto exit;
12294         }
12295 
12296         end = buffer + length;
12297         for (trace = start = buffer; trace != end; trace++) {
12298             if (!*trace) {
12299                 int error;
12300                 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
12301                                                                  trace - start);
12302                 if (!attribute) {
12303                     Py_DECREF(result);
12304                     result = NULL;
12305                     goto exit;
12306                 }
12307                 error = PyList_Append(result, attribute);
12308                 Py_DECREF(attribute);
12309                 if (error) {
12310                     Py_DECREF(result);
12311                     result = NULL;
12312                     goto exit;
12313                 }
12314                 start = trace + 1;
12315             }
12316         }
12317     break;
12318     }
12319 exit:
12320     if (buffer)
12321         PyMem_FREE(buffer);
12322     return result;
12323 }
12324 #endif /* USE_XATTRS */
12325 
12326 
12327 /*[clinic input]
12328 os.urandom
12329 
12330     size: Py_ssize_t
12331     /
12332 
12333 Return a bytes object containing random bytes suitable for cryptographic use.
12334 [clinic start generated code]*/
12335 
12336 static PyObject *
os_urandom_impl(PyObject * module,Py_ssize_t size)12337 os_urandom_impl(PyObject *module, Py_ssize_t size)
12338 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
12339 {
12340     PyObject *bytes;
12341     int result;
12342 
12343     if (size < 0)
12344         return PyErr_Format(PyExc_ValueError,
12345                             "negative argument not allowed");
12346     bytes = PyBytes_FromStringAndSize(NULL, size);
12347     if (bytes == NULL)
12348         return NULL;
12349 
12350     result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
12351     if (result == -1) {
12352         Py_DECREF(bytes);
12353         return NULL;
12354     }
12355     return bytes;
12356 }
12357 
12358 #ifdef HAVE_MEMFD_CREATE
12359 /*[clinic input]
12360 os.memfd_create
12361 
12362     name: FSConverter
12363     flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
12364 
12365 [clinic start generated code]*/
12366 
12367 static PyObject *
os_memfd_create_impl(PyObject * module,PyObject * name,unsigned int flags)12368 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
12369 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
12370 {
12371     int fd;
12372     const char *bytes = PyBytes_AS_STRING(name);
12373     Py_BEGIN_ALLOW_THREADS
12374     fd = memfd_create(bytes, flags);
12375     Py_END_ALLOW_THREADS
12376     if (fd == -1) {
12377         return PyErr_SetFromErrno(PyExc_OSError);
12378     }
12379     return PyLong_FromLong(fd);
12380 }
12381 #endif
12382 
12383 /* Terminal size querying */
12384 
12385 static PyTypeObject* TerminalSizeType;
12386 
12387 PyDoc_STRVAR(TerminalSize_docstring,
12388     "A tuple of (columns, lines) for holding terminal window size");
12389 
12390 static PyStructSequence_Field TerminalSize_fields[] = {
12391     {"columns", "width of the terminal window in characters"},
12392     {"lines", "height of the terminal window in characters"},
12393     {NULL, NULL}
12394 };
12395 
12396 static PyStructSequence_Desc TerminalSize_desc = {
12397     "os.terminal_size",
12398     TerminalSize_docstring,
12399     TerminalSize_fields,
12400     2,
12401 };
12402 
12403 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
12404 /* AC 3.5: fd should accept None */
12405 PyDoc_STRVAR(termsize__doc__,
12406     "Return the size of the terminal window as (columns, lines).\n"        \
12407     "\n"                                                                   \
12408     "The optional argument fd (default standard output) specifies\n"       \
12409     "which file descriptor should be queried.\n"                           \
12410     "\n"                                                                   \
12411     "If the file descriptor is not connected to a terminal, an OSError\n"  \
12412     "is thrown.\n"                                                         \
12413     "\n"                                                                   \
12414     "This function will only be defined if an implementation is\n"         \
12415     "available for this system.\n"                                         \
12416     "\n"                                                                   \
12417     "shutil.get_terminal_size is the high-level function which should\n"  \
12418     "normally be used, os.get_terminal_size is the low-level implementation.");
12419 
12420 static PyObject*
get_terminal_size(PyObject * self,PyObject * args)12421 get_terminal_size(PyObject *self, PyObject *args)
12422 {
12423     int columns, lines;
12424     PyObject *termsize;
12425 
12426     int fd = fileno(stdout);
12427     /* Under some conditions stdout may not be connected and
12428      * fileno(stdout) may point to an invalid file descriptor. For example
12429      * GUI apps don't have valid standard streams by default.
12430      *
12431      * If this happens, and the optional fd argument is not present,
12432      * the ioctl below will fail returning EBADF. This is what we want.
12433      */
12434 
12435     if (!PyArg_ParseTuple(args, "|i", &fd))
12436         return NULL;
12437 
12438 #ifdef TERMSIZE_USE_IOCTL
12439     {
12440         struct winsize w;
12441         if (ioctl(fd, TIOCGWINSZ, &w))
12442             return PyErr_SetFromErrno(PyExc_OSError);
12443         columns = w.ws_col;
12444         lines = w.ws_row;
12445     }
12446 #endif /* TERMSIZE_USE_IOCTL */
12447 
12448 #ifdef TERMSIZE_USE_CONIO
12449     {
12450         DWORD nhandle;
12451         HANDLE handle;
12452         CONSOLE_SCREEN_BUFFER_INFO csbi;
12453         switch (fd) {
12454         case 0: nhandle = STD_INPUT_HANDLE;
12455             break;
12456         case 1: nhandle = STD_OUTPUT_HANDLE;
12457             break;
12458         case 2: nhandle = STD_ERROR_HANDLE;
12459             break;
12460         default:
12461             return PyErr_Format(PyExc_ValueError, "bad file descriptor");
12462         }
12463         handle = GetStdHandle(nhandle);
12464         if (handle == NULL)
12465             return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
12466         if (handle == INVALID_HANDLE_VALUE)
12467             return PyErr_SetFromWindowsErr(0);
12468 
12469         if (!GetConsoleScreenBufferInfo(handle, &csbi))
12470             return PyErr_SetFromWindowsErr(0);
12471 
12472         columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
12473         lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
12474     }
12475 #endif /* TERMSIZE_USE_CONIO */
12476 
12477     termsize = PyStructSequence_New(TerminalSizeType);
12478     if (termsize == NULL)
12479         return NULL;
12480     PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
12481     PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
12482     if (PyErr_Occurred()) {
12483         Py_DECREF(termsize);
12484         return NULL;
12485     }
12486     return termsize;
12487 }
12488 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
12489 
12490 
12491 /*[clinic input]
12492 os.cpu_count
12493 
12494 Return the number of CPUs in the system; return None if indeterminable.
12495 
12496 This number is not equivalent to the number of CPUs the current process can
12497 use.  The number of usable CPUs can be obtained with
12498 ``len(os.sched_getaffinity(0))``
12499 [clinic start generated code]*/
12500 
12501 static PyObject *
os_cpu_count_impl(PyObject * module)12502 os_cpu_count_impl(PyObject *module)
12503 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
12504 {
12505     int ncpu = 0;
12506 #ifdef MS_WINDOWS
12507     /* Declare prototype here to avoid pulling in all of the Win7 APIs in 3.8 */
12508     DWORD WINAPI GetActiveProcessorCount(WORD group);
12509     ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
12510 #elif defined(__hpux)
12511     ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
12512 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
12513     ncpu = sysconf(_SC_NPROCESSORS_ONLN);
12514 #elif defined(__DragonFly__) || \
12515       defined(__OpenBSD__)   || \
12516       defined(__FreeBSD__)   || \
12517       defined(__NetBSD__)    || \
12518       defined(__APPLE__)
12519     int mib[2];
12520     size_t len = sizeof(ncpu);
12521     mib[0] = CTL_HW;
12522     mib[1] = HW_NCPU;
12523     if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
12524         ncpu = 0;
12525 #endif
12526     if (ncpu >= 1)
12527         return PyLong_FromLong(ncpu);
12528     else
12529         Py_RETURN_NONE;
12530 }
12531 
12532 
12533 /*[clinic input]
12534 os.get_inheritable -> bool
12535 
12536     fd: int
12537     /
12538 
12539 Get the close-on-exe flag of the specified file descriptor.
12540 [clinic start generated code]*/
12541 
12542 static int
os_get_inheritable_impl(PyObject * module,int fd)12543 os_get_inheritable_impl(PyObject *module, int fd)
12544 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
12545 {
12546     int return_value;
12547     _Py_BEGIN_SUPPRESS_IPH
12548     return_value = _Py_get_inheritable(fd);
12549     _Py_END_SUPPRESS_IPH
12550     return return_value;
12551 }
12552 
12553 
12554 /*[clinic input]
12555 os.set_inheritable
12556     fd: int
12557     inheritable: int
12558     /
12559 
12560 Set the inheritable flag of the specified file descriptor.
12561 [clinic start generated code]*/
12562 
12563 static PyObject *
os_set_inheritable_impl(PyObject * module,int fd,int inheritable)12564 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
12565 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
12566 {
12567     int result;
12568 
12569     _Py_BEGIN_SUPPRESS_IPH
12570     result = _Py_set_inheritable(fd, inheritable, NULL);
12571     _Py_END_SUPPRESS_IPH
12572     if (result < 0)
12573         return NULL;
12574     Py_RETURN_NONE;
12575 }
12576 
12577 
12578 #ifdef MS_WINDOWS
12579 /*[clinic input]
12580 os.get_handle_inheritable -> bool
12581     handle: intptr_t
12582     /
12583 
12584 Get the close-on-exe flag of the specified file descriptor.
12585 [clinic start generated code]*/
12586 
12587 static int
os_get_handle_inheritable_impl(PyObject * module,intptr_t handle)12588 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
12589 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
12590 {
12591     DWORD flags;
12592 
12593     if (!GetHandleInformation((HANDLE)handle, &flags)) {
12594         PyErr_SetFromWindowsErr(0);
12595         return -1;
12596     }
12597 
12598     return flags & HANDLE_FLAG_INHERIT;
12599 }
12600 
12601 
12602 /*[clinic input]
12603 os.set_handle_inheritable
12604     handle: intptr_t
12605     inheritable: bool
12606     /
12607 
12608 Set the inheritable flag of the specified handle.
12609 [clinic start generated code]*/
12610 
12611 static PyObject *
os_set_handle_inheritable_impl(PyObject * module,intptr_t handle,int inheritable)12612 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
12613                                int inheritable)
12614 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
12615 {
12616     DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
12617     if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
12618         PyErr_SetFromWindowsErr(0);
12619         return NULL;
12620     }
12621     Py_RETURN_NONE;
12622 }
12623 #endif /* MS_WINDOWS */
12624 
12625 #ifndef MS_WINDOWS
12626 /*[clinic input]
12627 os.get_blocking -> bool
12628     fd: int
12629     /
12630 
12631 Get the blocking mode of the file descriptor.
12632 
12633 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
12634 [clinic start generated code]*/
12635 
12636 static int
os_get_blocking_impl(PyObject * module,int fd)12637 os_get_blocking_impl(PyObject *module, int fd)
12638 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
12639 {
12640     int blocking;
12641 
12642     _Py_BEGIN_SUPPRESS_IPH
12643     blocking = _Py_get_blocking(fd);
12644     _Py_END_SUPPRESS_IPH
12645     return blocking;
12646 }
12647 
12648 /*[clinic input]
12649 os.set_blocking
12650     fd: int
12651     blocking: bool(accept={int})
12652     /
12653 
12654 Set the blocking mode of the specified file descriptor.
12655 
12656 Set the O_NONBLOCK flag if blocking is False,
12657 clear the O_NONBLOCK flag otherwise.
12658 [clinic start generated code]*/
12659 
12660 static PyObject *
os_set_blocking_impl(PyObject * module,int fd,int blocking)12661 os_set_blocking_impl(PyObject *module, int fd, int blocking)
12662 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
12663 {
12664     int result;
12665 
12666     _Py_BEGIN_SUPPRESS_IPH
12667     result = _Py_set_blocking(fd, blocking);
12668     _Py_END_SUPPRESS_IPH
12669     if (result < 0)
12670         return NULL;
12671     Py_RETURN_NONE;
12672 }
12673 #endif   /* !MS_WINDOWS */
12674 
12675 
12676 /*[clinic input]
12677 class os.DirEntry "DirEntry *" "&DirEntryType"
12678 [clinic start generated code]*/
12679 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3138f09f7c683f1d]*/
12680 
12681 typedef struct {
12682     PyObject_HEAD
12683     PyObject *name;
12684     PyObject *path;
12685     PyObject *stat;
12686     PyObject *lstat;
12687 #ifdef MS_WINDOWS
12688     struct _Py_stat_struct win32_lstat;
12689     uint64_t win32_file_index;
12690     int got_file_index;
12691 #else /* POSIX */
12692 #ifdef HAVE_DIRENT_D_TYPE
12693     unsigned char d_type;
12694 #endif
12695     ino_t d_ino;
12696     int dir_fd;
12697 #endif
12698 } DirEntry;
12699 
12700 static void
DirEntry_dealloc(DirEntry * entry)12701 DirEntry_dealloc(DirEntry *entry)
12702 {
12703     Py_XDECREF(entry->name);
12704     Py_XDECREF(entry->path);
12705     Py_XDECREF(entry->stat);
12706     Py_XDECREF(entry->lstat);
12707     Py_TYPE(entry)->tp_free((PyObject *)entry);
12708 }
12709 
12710 /* Forward reference */
12711 static int
12712 DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits);
12713 
12714 /*[clinic input]
12715 os.DirEntry.is_symlink -> bool
12716 
12717 Return True if the entry is a symbolic link; cached per entry.
12718 [clinic start generated code]*/
12719 
12720 static int
os_DirEntry_is_symlink_impl(DirEntry * self)12721 os_DirEntry_is_symlink_impl(DirEntry *self)
12722 /*[clinic end generated code: output=42244667d7bcfc25 input=1605a1b4b96976c3]*/
12723 {
12724 #ifdef MS_WINDOWS
12725     return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
12726 #elif defined(HAVE_DIRENT_D_TYPE)
12727     /* POSIX */
12728     if (self->d_type != DT_UNKNOWN)
12729         return self->d_type == DT_LNK;
12730     else
12731         return DirEntry_test_mode(self, 0, S_IFLNK);
12732 #else
12733     /* POSIX without d_type */
12734     return DirEntry_test_mode(self, 0, S_IFLNK);
12735 #endif
12736 }
12737 
12738 static PyObject *
DirEntry_fetch_stat(DirEntry * self,int follow_symlinks)12739 DirEntry_fetch_stat(DirEntry *self, int follow_symlinks)
12740 {
12741     int result;
12742     STRUCT_STAT st;
12743     PyObject *ub;
12744 
12745 #ifdef MS_WINDOWS
12746     if (!PyUnicode_FSDecoder(self->path, &ub))
12747         return NULL;
12748     const wchar_t *path = PyUnicode_AsUnicode(ub);
12749 #else /* POSIX */
12750     if (!PyUnicode_FSConverter(self->path, &ub))
12751         return NULL;
12752     const char *path = PyBytes_AS_STRING(ub);
12753     if (self->dir_fd != DEFAULT_DIR_FD) {
12754 #ifdef HAVE_FSTATAT
12755         result = fstatat(self->dir_fd, path, &st,
12756                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
12757 #else
12758         PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
12759         return NULL;
12760 #endif /* HAVE_FSTATAT */
12761     }
12762     else
12763 #endif
12764     {
12765         if (follow_symlinks)
12766             result = STAT(path, &st);
12767         else
12768             result = LSTAT(path, &st);
12769     }
12770     Py_DECREF(ub);
12771 
12772     if (result != 0)
12773         return path_object_error(self->path);
12774 
12775     return _pystat_fromstructstat(&st);
12776 }
12777 
12778 static PyObject *
DirEntry_get_lstat(DirEntry * self)12779 DirEntry_get_lstat(DirEntry *self)
12780 {
12781     if (!self->lstat) {
12782 #ifdef MS_WINDOWS
12783         self->lstat = _pystat_fromstructstat(&self->win32_lstat);
12784 #else /* POSIX */
12785         self->lstat = DirEntry_fetch_stat(self, 0);
12786 #endif
12787     }
12788     Py_XINCREF(self->lstat);
12789     return self->lstat;
12790 }
12791 
12792 /*[clinic input]
12793 os.DirEntry.stat
12794     *
12795     follow_symlinks: bool = True
12796 
12797 Return stat_result object for the entry; cached per entry.
12798 [clinic start generated code]*/
12799 
12800 static PyObject *
os_DirEntry_stat_impl(DirEntry * self,int follow_symlinks)12801 os_DirEntry_stat_impl(DirEntry *self, int follow_symlinks)
12802 /*[clinic end generated code: output=008593b3a6d01305 input=280d14c1d6f1d00d]*/
12803 {
12804     if (!follow_symlinks)
12805         return DirEntry_get_lstat(self);
12806 
12807     if (!self->stat) {
12808         int result = os_DirEntry_is_symlink_impl(self);
12809         if (result == -1)
12810             return NULL;
12811         else if (result)
12812             self->stat = DirEntry_fetch_stat(self, 1);
12813         else
12814             self->stat = DirEntry_get_lstat(self);
12815     }
12816 
12817     Py_XINCREF(self->stat);
12818     return self->stat;
12819 }
12820 
12821 /* Set exception and return -1 on error, 0 for False, 1 for True */
12822 static int
DirEntry_test_mode(DirEntry * self,int follow_symlinks,unsigned short mode_bits)12823 DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits)
12824 {
12825     PyObject *stat = NULL;
12826     PyObject *st_mode = NULL;
12827     long mode;
12828     int result;
12829 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
12830     int is_symlink;
12831     int need_stat;
12832 #endif
12833 #ifdef MS_WINDOWS
12834     unsigned long dir_bits;
12835 #endif
12836     _Py_IDENTIFIER(st_mode);
12837 
12838 #ifdef MS_WINDOWS
12839     is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
12840     need_stat = follow_symlinks && is_symlink;
12841 #elif defined(HAVE_DIRENT_D_TYPE)
12842     is_symlink = self->d_type == DT_LNK;
12843     need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
12844 #endif
12845 
12846 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
12847     if (need_stat) {
12848 #endif
12849         stat = os_DirEntry_stat_impl(self, follow_symlinks);
12850         if (!stat) {
12851             if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
12852                 /* If file doesn't exist (anymore), then return False
12853                    (i.e., say it's not a file/directory) */
12854                 PyErr_Clear();
12855                 return 0;
12856             }
12857             goto error;
12858         }
12859         st_mode = _PyObject_GetAttrId(stat, &PyId_st_mode);
12860         if (!st_mode)
12861             goto error;
12862 
12863         mode = PyLong_AsLong(st_mode);
12864         if (mode == -1 && PyErr_Occurred())
12865             goto error;
12866         Py_CLEAR(st_mode);
12867         Py_CLEAR(stat);
12868         result = (mode & S_IFMT) == mode_bits;
12869 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
12870     }
12871     else if (is_symlink) {
12872         assert(mode_bits != S_IFLNK);
12873         result = 0;
12874     }
12875     else {
12876         assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
12877 #ifdef MS_WINDOWS
12878         dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
12879         if (mode_bits == S_IFDIR)
12880             result = dir_bits != 0;
12881         else
12882             result = dir_bits == 0;
12883 #else /* POSIX */
12884         if (mode_bits == S_IFDIR)
12885             result = self->d_type == DT_DIR;
12886         else
12887             result = self->d_type == DT_REG;
12888 #endif
12889     }
12890 #endif
12891 
12892     return result;
12893 
12894 error:
12895     Py_XDECREF(st_mode);
12896     Py_XDECREF(stat);
12897     return -1;
12898 }
12899 
12900 /*[clinic input]
12901 os.DirEntry.is_dir -> bool
12902     *
12903     follow_symlinks: bool = True
12904 
12905 Return True if the entry is a directory; cached per entry.
12906 [clinic start generated code]*/
12907 
12908 static int
os_DirEntry_is_dir_impl(DirEntry * self,int follow_symlinks)12909 os_DirEntry_is_dir_impl(DirEntry *self, int follow_symlinks)
12910 /*[clinic end generated code: output=ad2e8d54365da287 input=0135232766f53f58]*/
12911 {
12912     return DirEntry_test_mode(self, follow_symlinks, S_IFDIR);
12913 }
12914 
12915 /*[clinic input]
12916 os.DirEntry.is_file -> bool
12917     *
12918     follow_symlinks: bool = True
12919 
12920 Return True if the entry is a file; cached per entry.
12921 [clinic start generated code]*/
12922 
12923 static int
os_DirEntry_is_file_impl(DirEntry * self,int follow_symlinks)12924 os_DirEntry_is_file_impl(DirEntry *self, int follow_symlinks)
12925 /*[clinic end generated code: output=8462ade481d8a476 input=0dc90be168b041ee]*/
12926 {
12927     return DirEntry_test_mode(self, follow_symlinks, S_IFREG);
12928 }
12929 
12930 /*[clinic input]
12931 os.DirEntry.inode
12932 
12933 Return inode of the entry; cached per entry.
12934 [clinic start generated code]*/
12935 
12936 static PyObject *
os_DirEntry_inode_impl(DirEntry * self)12937 os_DirEntry_inode_impl(DirEntry *self)
12938 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
12939 {
12940 #ifdef MS_WINDOWS
12941     if (!self->got_file_index) {
12942         PyObject *unicode;
12943         const wchar_t *path;
12944         STRUCT_STAT stat;
12945         int result;
12946 
12947         if (!PyUnicode_FSDecoder(self->path, &unicode))
12948             return NULL;
12949         path = PyUnicode_AsUnicode(unicode);
12950         result = LSTAT(path, &stat);
12951         Py_DECREF(unicode);
12952 
12953         if (result != 0)
12954             return path_object_error(self->path);
12955 
12956         self->win32_file_index = stat.st_ino;
12957         self->got_file_index = 1;
12958     }
12959     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->win32_file_index));
12960     return PyLong_FromUnsignedLongLong(self->win32_file_index);
12961 #else /* POSIX */
12962     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->d_ino));
12963     return PyLong_FromUnsignedLongLong(self->d_ino);
12964 #endif
12965 }
12966 
12967 static PyObject *
DirEntry_repr(DirEntry * self)12968 DirEntry_repr(DirEntry *self)
12969 {
12970     return PyUnicode_FromFormat("<DirEntry %R>", self->name);
12971 }
12972 
12973 /*[clinic input]
12974 os.DirEntry.__fspath__
12975 
12976 Returns the path for the entry.
12977 [clinic start generated code]*/
12978 
12979 static PyObject *
os_DirEntry___fspath___impl(DirEntry * self)12980 os_DirEntry___fspath___impl(DirEntry *self)
12981 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
12982 {
12983     Py_INCREF(self->path);
12984     return self->path;
12985 }
12986 
12987 static PyMemberDef DirEntry_members[] = {
12988     {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
12989      "the entry's base filename, relative to scandir() \"path\" argument"},
12990     {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
12991      "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
12992     {NULL}
12993 };
12994 
12995 #include "clinic/posixmodule.c.h"
12996 
12997 static PyMethodDef DirEntry_methods[] = {
12998     OS_DIRENTRY_IS_DIR_METHODDEF
12999     OS_DIRENTRY_IS_FILE_METHODDEF
13000     OS_DIRENTRY_IS_SYMLINK_METHODDEF
13001     OS_DIRENTRY_STAT_METHODDEF
13002     OS_DIRENTRY_INODE_METHODDEF
13003     OS_DIRENTRY___FSPATH___METHODDEF
13004     {NULL}
13005 };
13006 
13007 static PyTypeObject DirEntryType = {
13008     PyVarObject_HEAD_INIT(NULL, 0)
13009     MODNAME ".DirEntry",                    /* tp_name */
13010     sizeof(DirEntry),                       /* tp_basicsize */
13011     0,                                      /* tp_itemsize */
13012     /* methods */
13013     (destructor)DirEntry_dealloc,           /* tp_dealloc */
13014     0,                                      /* tp_vectorcall_offset */
13015     0,                                      /* tp_getattr */
13016     0,                                      /* tp_setattr */
13017     0,                                      /* tp_as_async */
13018     (reprfunc)DirEntry_repr,                /* tp_repr */
13019     0,                                      /* tp_as_number */
13020     0,                                      /* tp_as_sequence */
13021     0,                                      /* tp_as_mapping */
13022     0,                                      /* tp_hash */
13023     0,                                      /* tp_call */
13024     0,                                      /* tp_str */
13025     0,                                      /* tp_getattro */
13026     0,                                      /* tp_setattro */
13027     0,                                      /* tp_as_buffer */
13028     Py_TPFLAGS_DEFAULT,                     /* tp_flags */
13029     0,                                      /* tp_doc */
13030     0,                                      /* tp_traverse */
13031     0,                                      /* tp_clear */
13032     0,                                      /* tp_richcompare */
13033     0,                                      /* tp_weaklistoffset */
13034     0,                                      /* tp_iter */
13035     0,                                      /* tp_iternext */
13036     DirEntry_methods,                       /* tp_methods */
13037     DirEntry_members,                       /* tp_members */
13038 };
13039 
13040 #ifdef MS_WINDOWS
13041 
13042 static wchar_t *
join_path_filenameW(const wchar_t * path_wide,const wchar_t * filename)13043 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
13044 {
13045     Py_ssize_t path_len;
13046     Py_ssize_t size;
13047     wchar_t *result;
13048     wchar_t ch;
13049 
13050     if (!path_wide) { /* Default arg: "." */
13051         path_wide = L".";
13052         path_len = 1;
13053     }
13054     else {
13055         path_len = wcslen(path_wide);
13056     }
13057 
13058     /* The +1's are for the path separator and the NUL */
13059     size = path_len + 1 + wcslen(filename) + 1;
13060     result = PyMem_New(wchar_t, size);
13061     if (!result) {
13062         PyErr_NoMemory();
13063         return NULL;
13064     }
13065     wcscpy(result, path_wide);
13066     if (path_len > 0) {
13067         ch = result[path_len - 1];
13068         if (ch != SEP && ch != ALTSEP && ch != L':')
13069             result[path_len++] = SEP;
13070         wcscpy(result + path_len, filename);
13071     }
13072     return result;
13073 }
13074 
13075 static PyObject *
DirEntry_from_find_data(path_t * path,WIN32_FIND_DATAW * dataW)13076 DirEntry_from_find_data(path_t *path, WIN32_FIND_DATAW *dataW)
13077 {
13078     DirEntry *entry;
13079     BY_HANDLE_FILE_INFORMATION file_info;
13080     ULONG reparse_tag;
13081     wchar_t *joined_path;
13082 
13083     entry = PyObject_New(DirEntry, &DirEntryType);
13084     if (!entry)
13085         return NULL;
13086     entry->name = NULL;
13087     entry->path = NULL;
13088     entry->stat = NULL;
13089     entry->lstat = NULL;
13090     entry->got_file_index = 0;
13091 
13092     entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
13093     if (!entry->name)
13094         goto error;
13095     if (path->narrow) {
13096         Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
13097         if (!entry->name)
13098             goto error;
13099     }
13100 
13101     joined_path = join_path_filenameW(path->wide, dataW->cFileName);
13102     if (!joined_path)
13103         goto error;
13104 
13105     entry->path = PyUnicode_FromWideChar(joined_path, -1);
13106     PyMem_Free(joined_path);
13107     if (!entry->path)
13108         goto error;
13109     if (path->narrow) {
13110         Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
13111         if (!entry->path)
13112             goto error;
13113     }
13114 
13115     find_data_to_file_info(dataW, &file_info, &reparse_tag);
13116     _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
13117 
13118     return (PyObject *)entry;
13119 
13120 error:
13121     Py_DECREF(entry);
13122     return NULL;
13123 }
13124 
13125 #else /* POSIX */
13126 
13127 static char *
join_path_filename(const char * path_narrow,const char * filename,Py_ssize_t filename_len)13128 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
13129 {
13130     Py_ssize_t path_len;
13131     Py_ssize_t size;
13132     char *result;
13133 
13134     if (!path_narrow) { /* Default arg: "." */
13135         path_narrow = ".";
13136         path_len = 1;
13137     }
13138     else {
13139         path_len = strlen(path_narrow);
13140     }
13141 
13142     if (filename_len == -1)
13143         filename_len = strlen(filename);
13144 
13145     /* The +1's are for the path separator and the NUL */
13146     size = path_len + 1 + filename_len + 1;
13147     result = PyMem_New(char, size);
13148     if (!result) {
13149         PyErr_NoMemory();
13150         return NULL;
13151     }
13152     strcpy(result, path_narrow);
13153     if (path_len > 0 && result[path_len - 1] != '/')
13154         result[path_len++] = '/';
13155     strcpy(result + path_len, filename);
13156     return result;
13157 }
13158 
13159 static PyObject *
DirEntry_from_posix_info(path_t * path,const char * name,Py_ssize_t name_len,ino_t d_ino,unsigned char d_type)13160 DirEntry_from_posix_info(path_t *path, const char *name, Py_ssize_t name_len,
13161                          ino_t d_ino
13162 #ifdef HAVE_DIRENT_D_TYPE
13163                          , unsigned char d_type
13164 #endif
13165                          )
13166 {
13167     DirEntry *entry;
13168     char *joined_path;
13169 
13170     entry = PyObject_New(DirEntry, &DirEntryType);
13171     if (!entry)
13172         return NULL;
13173     entry->name = NULL;
13174     entry->path = NULL;
13175     entry->stat = NULL;
13176     entry->lstat = NULL;
13177 
13178     if (path->fd != -1) {
13179         entry->dir_fd = path->fd;
13180         joined_path = NULL;
13181     }
13182     else {
13183         entry->dir_fd = DEFAULT_DIR_FD;
13184         joined_path = join_path_filename(path->narrow, name, name_len);
13185         if (!joined_path)
13186             goto error;
13187     }
13188 
13189     if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
13190         entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
13191         if (joined_path)
13192             entry->path = PyUnicode_DecodeFSDefault(joined_path);
13193     }
13194     else {
13195         entry->name = PyBytes_FromStringAndSize(name, name_len);
13196         if (joined_path)
13197             entry->path = PyBytes_FromString(joined_path);
13198     }
13199     PyMem_Free(joined_path);
13200     if (!entry->name)
13201         goto error;
13202 
13203     if (path->fd != -1) {
13204         entry->path = entry->name;
13205         Py_INCREF(entry->path);
13206     }
13207     else if (!entry->path)
13208         goto error;
13209 
13210 #ifdef HAVE_DIRENT_D_TYPE
13211     entry->d_type = d_type;
13212 #endif
13213     entry->d_ino = d_ino;
13214 
13215     return (PyObject *)entry;
13216 
13217 error:
13218     Py_XDECREF(entry);
13219     return NULL;
13220 }
13221 
13222 #endif
13223 
13224 
13225 typedef struct {
13226     PyObject_HEAD
13227     path_t path;
13228 #ifdef MS_WINDOWS
13229     HANDLE handle;
13230     WIN32_FIND_DATAW file_data;
13231     int first_time;
13232 #else /* POSIX */
13233     DIR *dirp;
13234 #endif
13235 #ifdef HAVE_FDOPENDIR
13236     int fd;
13237 #endif
13238 } ScandirIterator;
13239 
13240 #ifdef MS_WINDOWS
13241 
13242 static int
ScandirIterator_is_closed(ScandirIterator * iterator)13243 ScandirIterator_is_closed(ScandirIterator *iterator)
13244 {
13245     return iterator->handle == INVALID_HANDLE_VALUE;
13246 }
13247 
13248 static void
ScandirIterator_closedir(ScandirIterator * iterator)13249 ScandirIterator_closedir(ScandirIterator *iterator)
13250 {
13251     HANDLE handle = iterator->handle;
13252 
13253     if (handle == INVALID_HANDLE_VALUE)
13254         return;
13255 
13256     iterator->handle = INVALID_HANDLE_VALUE;
13257     Py_BEGIN_ALLOW_THREADS
13258     FindClose(handle);
13259     Py_END_ALLOW_THREADS
13260 }
13261 
13262 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)13263 ScandirIterator_iternext(ScandirIterator *iterator)
13264 {
13265     WIN32_FIND_DATAW *file_data = &iterator->file_data;
13266     BOOL success;
13267     PyObject *entry;
13268 
13269     /* Happens if the iterator is iterated twice, or closed explicitly */
13270     if (iterator->handle == INVALID_HANDLE_VALUE)
13271         return NULL;
13272 
13273     while (1) {
13274         if (!iterator->first_time) {
13275             Py_BEGIN_ALLOW_THREADS
13276             success = FindNextFileW(iterator->handle, file_data);
13277             Py_END_ALLOW_THREADS
13278             if (!success) {
13279                 /* Error or no more files */
13280                 if (GetLastError() != ERROR_NO_MORE_FILES)
13281                     path_error(&iterator->path);
13282                 break;
13283             }
13284         }
13285         iterator->first_time = 0;
13286 
13287         /* Skip over . and .. */
13288         if (wcscmp(file_data->cFileName, L".") != 0 &&
13289             wcscmp(file_data->cFileName, L"..") != 0) {
13290             entry = DirEntry_from_find_data(&iterator->path, file_data);
13291             if (!entry)
13292                 break;
13293             return entry;
13294         }
13295 
13296         /* Loop till we get a non-dot directory or finish iterating */
13297     }
13298 
13299     /* Error or no more files */
13300     ScandirIterator_closedir(iterator);
13301     return NULL;
13302 }
13303 
13304 #else /* POSIX */
13305 
13306 static int
ScandirIterator_is_closed(ScandirIterator * iterator)13307 ScandirIterator_is_closed(ScandirIterator *iterator)
13308 {
13309     return !iterator->dirp;
13310 }
13311 
13312 static void
ScandirIterator_closedir(ScandirIterator * iterator)13313 ScandirIterator_closedir(ScandirIterator *iterator)
13314 {
13315     DIR *dirp = iterator->dirp;
13316 
13317     if (!dirp)
13318         return;
13319 
13320     iterator->dirp = NULL;
13321     Py_BEGIN_ALLOW_THREADS
13322 #ifdef HAVE_FDOPENDIR
13323     if (iterator->path.fd != -1)
13324         rewinddir(dirp);
13325 #endif
13326     closedir(dirp);
13327     Py_END_ALLOW_THREADS
13328     return;
13329 }
13330 
13331 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)13332 ScandirIterator_iternext(ScandirIterator *iterator)
13333 {
13334     struct dirent *direntp;
13335     Py_ssize_t name_len;
13336     int is_dot;
13337     PyObject *entry;
13338 
13339     /* Happens if the iterator is iterated twice, or closed explicitly */
13340     if (!iterator->dirp)
13341         return NULL;
13342 
13343     while (1) {
13344         errno = 0;
13345         Py_BEGIN_ALLOW_THREADS
13346         direntp = readdir(iterator->dirp);
13347         Py_END_ALLOW_THREADS
13348 
13349         if (!direntp) {
13350             /* Error or no more files */
13351             if (errno != 0)
13352                 path_error(&iterator->path);
13353             break;
13354         }
13355 
13356         /* Skip over . and .. */
13357         name_len = NAMLEN(direntp);
13358         is_dot = direntp->d_name[0] == '.' &&
13359                  (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
13360         if (!is_dot) {
13361             entry = DirEntry_from_posix_info(&iterator->path, direntp->d_name,
13362                                             name_len, direntp->d_ino
13363 #ifdef HAVE_DIRENT_D_TYPE
13364                                             , direntp->d_type
13365 #endif
13366                                             );
13367             if (!entry)
13368                 break;
13369             return entry;
13370         }
13371 
13372         /* Loop till we get a non-dot directory or finish iterating */
13373     }
13374 
13375     /* Error or no more files */
13376     ScandirIterator_closedir(iterator);
13377     return NULL;
13378 }
13379 
13380 #endif
13381 
13382 static PyObject *
ScandirIterator_close(ScandirIterator * self,PyObject * args)13383 ScandirIterator_close(ScandirIterator *self, PyObject *args)
13384 {
13385     ScandirIterator_closedir(self);
13386     Py_RETURN_NONE;
13387 }
13388 
13389 static PyObject *
ScandirIterator_enter(PyObject * self,PyObject * args)13390 ScandirIterator_enter(PyObject *self, PyObject *args)
13391 {
13392     Py_INCREF(self);
13393     return self;
13394 }
13395 
13396 static PyObject *
ScandirIterator_exit(ScandirIterator * self,PyObject * args)13397 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
13398 {
13399     ScandirIterator_closedir(self);
13400     Py_RETURN_NONE;
13401 }
13402 
13403 static void
ScandirIterator_finalize(ScandirIterator * iterator)13404 ScandirIterator_finalize(ScandirIterator *iterator)
13405 {
13406     PyObject *error_type, *error_value, *error_traceback;
13407 
13408     /* Save the current exception, if any. */
13409     PyErr_Fetch(&error_type, &error_value, &error_traceback);
13410 
13411     if (!ScandirIterator_is_closed(iterator)) {
13412         ScandirIterator_closedir(iterator);
13413 
13414         if (PyErr_ResourceWarning((PyObject *)iterator, 1,
13415                                   "unclosed scandir iterator %R", iterator)) {
13416             /* Spurious errors can appear at shutdown */
13417             if (PyErr_ExceptionMatches(PyExc_Warning)) {
13418                 PyErr_WriteUnraisable((PyObject *) iterator);
13419             }
13420         }
13421     }
13422 
13423     path_cleanup(&iterator->path);
13424 
13425     /* Restore the saved exception. */
13426     PyErr_Restore(error_type, error_value, error_traceback);
13427 }
13428 
13429 static void
ScandirIterator_dealloc(ScandirIterator * iterator)13430 ScandirIterator_dealloc(ScandirIterator *iterator)
13431 {
13432     if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
13433         return;
13434 
13435     Py_TYPE(iterator)->tp_free((PyObject *)iterator);
13436 }
13437 
13438 static PyMethodDef ScandirIterator_methods[] = {
13439     {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
13440     {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
13441     {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
13442     {NULL}
13443 };
13444 
13445 static PyTypeObject ScandirIteratorType = {
13446     PyVarObject_HEAD_INIT(NULL, 0)
13447     MODNAME ".ScandirIterator",             /* tp_name */
13448     sizeof(ScandirIterator),                /* tp_basicsize */
13449     0,                                      /* tp_itemsize */
13450     /* methods */
13451     (destructor)ScandirIterator_dealloc,    /* tp_dealloc */
13452     0,                                      /* tp_vectorcall_offset */
13453     0,                                      /* tp_getattr */
13454     0,                                      /* tp_setattr */
13455     0,                                      /* tp_as_async */
13456     0,                                      /* tp_repr */
13457     0,                                      /* tp_as_number */
13458     0,                                      /* tp_as_sequence */
13459     0,                                      /* tp_as_mapping */
13460     0,                                      /* tp_hash */
13461     0,                                      /* tp_call */
13462     0,                                      /* tp_str */
13463     0,                                      /* tp_getattro */
13464     0,                                      /* tp_setattro */
13465     0,                                      /* tp_as_buffer */
13466     Py_TPFLAGS_DEFAULT,                     /* tp_flags */
13467     0,                                      /* tp_doc */
13468     0,                                      /* tp_traverse */
13469     0,                                      /* tp_clear */
13470     0,                                      /* tp_richcompare */
13471     0,                                      /* tp_weaklistoffset */
13472     PyObject_SelfIter,                      /* tp_iter */
13473     (iternextfunc)ScandirIterator_iternext, /* tp_iternext */
13474     ScandirIterator_methods,                /* tp_methods */
13475     0,                                      /* tp_members */
13476     0,                                      /* tp_getset */
13477     0,                                      /* tp_base */
13478     0,                                      /* tp_dict */
13479     0,                                      /* tp_descr_get */
13480     0,                                      /* tp_descr_set */
13481     0,                                      /* tp_dictoffset */
13482     0,                                      /* tp_init */
13483     0,                                      /* tp_alloc */
13484     0,                                      /* tp_new */
13485     0,                                      /* tp_free */
13486     0,                                      /* tp_is_gc */
13487     0,                                      /* tp_bases */
13488     0,                                      /* tp_mro */
13489     0,                                      /* tp_cache */
13490     0,                                      /* tp_subclasses */
13491     0,                                      /* tp_weaklist */
13492     0,                                      /* tp_del */
13493     0,                                      /* tp_version_tag */
13494     (destructor)ScandirIterator_finalize,   /* tp_finalize */
13495 };
13496 
13497 /*[clinic input]
13498 os.scandir
13499 
13500     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
13501 
13502 Return an iterator of DirEntry objects for given path.
13503 
13504 path can be specified as either str, bytes, or a path-like object.  If path
13505 is bytes, the names of yielded DirEntry objects will also be bytes; in
13506 all other circumstances they will be str.
13507 
13508 If path is None, uses the path='.'.
13509 [clinic start generated code]*/
13510 
13511 static PyObject *
os_scandir_impl(PyObject * module,path_t * path)13512 os_scandir_impl(PyObject *module, path_t *path)
13513 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
13514 {
13515     ScandirIterator *iterator;
13516 #ifdef MS_WINDOWS
13517     wchar_t *path_strW;
13518 #else
13519     const char *path_str;
13520 #ifdef HAVE_FDOPENDIR
13521     int fd = -1;
13522 #endif
13523 #endif
13524 
13525     if (PySys_Audit("os.scandir", "O",
13526                     path->object ? path->object : Py_None) < 0) {
13527         return NULL;
13528     }
13529 
13530     iterator = PyObject_New(ScandirIterator, &ScandirIteratorType);
13531     if (!iterator)
13532         return NULL;
13533 
13534 #ifdef MS_WINDOWS
13535     iterator->handle = INVALID_HANDLE_VALUE;
13536 #else
13537     iterator->dirp = NULL;
13538 #endif
13539 
13540     memcpy(&iterator->path, path, sizeof(path_t));
13541     /* Move the ownership to iterator->path */
13542     path->object = NULL;
13543     path->cleanup = NULL;
13544 
13545 #ifdef MS_WINDOWS
13546     iterator->first_time = 1;
13547 
13548     path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
13549     if (!path_strW)
13550         goto error;
13551 
13552     Py_BEGIN_ALLOW_THREADS
13553     iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
13554     Py_END_ALLOW_THREADS
13555 
13556     PyMem_Free(path_strW);
13557 
13558     if (iterator->handle == INVALID_HANDLE_VALUE) {
13559         path_error(&iterator->path);
13560         goto error;
13561     }
13562 #else /* POSIX */
13563     errno = 0;
13564 #ifdef HAVE_FDOPENDIR
13565     if (path->fd != -1) {
13566         /* closedir() closes the FD, so we duplicate it */
13567         fd = _Py_dup(path->fd);
13568         if (fd == -1)
13569             goto error;
13570 
13571         Py_BEGIN_ALLOW_THREADS
13572         iterator->dirp = fdopendir(fd);
13573         Py_END_ALLOW_THREADS
13574     }
13575     else
13576 #endif
13577     {
13578         if (iterator->path.narrow)
13579             path_str = iterator->path.narrow;
13580         else
13581             path_str = ".";
13582 
13583         Py_BEGIN_ALLOW_THREADS
13584         iterator->dirp = opendir(path_str);
13585         Py_END_ALLOW_THREADS
13586     }
13587 
13588     if (!iterator->dirp) {
13589         path_error(&iterator->path);
13590 #ifdef HAVE_FDOPENDIR
13591         if (fd != -1) {
13592             Py_BEGIN_ALLOW_THREADS
13593             close(fd);
13594             Py_END_ALLOW_THREADS
13595         }
13596 #endif
13597         goto error;
13598     }
13599 #endif
13600 
13601     return (PyObject *)iterator;
13602 
13603 error:
13604     Py_DECREF(iterator);
13605     return NULL;
13606 }
13607 
13608 /*
13609     Return the file system path representation of the object.
13610 
13611     If the object is str or bytes, then allow it to pass through with
13612     an incremented refcount. If the object defines __fspath__(), then
13613     return the result of that method. All other types raise a TypeError.
13614 */
13615 PyObject *
PyOS_FSPath(PyObject * path)13616 PyOS_FSPath(PyObject *path)
13617 {
13618     /* For error message reasons, this function is manually inlined in
13619        path_converter(). */
13620     _Py_IDENTIFIER(__fspath__);
13621     PyObject *func = NULL;
13622     PyObject *path_repr = NULL;
13623 
13624     if (PyUnicode_Check(path) || PyBytes_Check(path)) {
13625         Py_INCREF(path);
13626         return path;
13627     }
13628 
13629     func = _PyObject_LookupSpecial(path, &PyId___fspath__);
13630     if (NULL == func) {
13631         return PyErr_Format(PyExc_TypeError,
13632                             "expected str, bytes or os.PathLike object, "
13633                             "not %.200s",
13634                             Py_TYPE(path)->tp_name);
13635     }
13636 
13637     path_repr = _PyObject_CallNoArg(func);
13638     Py_DECREF(func);
13639     if (NULL == path_repr) {
13640         return NULL;
13641     }
13642 
13643     if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
13644         PyErr_Format(PyExc_TypeError,
13645                      "expected %.200s.__fspath__() to return str or bytes, "
13646                      "not %.200s", Py_TYPE(path)->tp_name,
13647                      Py_TYPE(path_repr)->tp_name);
13648         Py_DECREF(path_repr);
13649         return NULL;
13650     }
13651 
13652     return path_repr;
13653 }
13654 
13655 /*[clinic input]
13656 os.fspath
13657 
13658     path: object
13659 
13660 Return the file system path representation of the object.
13661 
13662 If the object is str or bytes, then allow it to pass through as-is. If the
13663 object defines __fspath__(), then return the result of that method. All other
13664 types raise a TypeError.
13665 [clinic start generated code]*/
13666 
13667 static PyObject *
os_fspath_impl(PyObject * module,PyObject * path)13668 os_fspath_impl(PyObject *module, PyObject *path)
13669 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
13670 {
13671     return PyOS_FSPath(path);
13672 }
13673 
13674 #ifdef HAVE_GETRANDOM_SYSCALL
13675 /*[clinic input]
13676 os.getrandom
13677 
13678     size: Py_ssize_t
13679     flags: int=0
13680 
13681 Obtain a series of random bytes.
13682 [clinic start generated code]*/
13683 
13684 static PyObject *
os_getrandom_impl(PyObject * module,Py_ssize_t size,int flags)13685 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
13686 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
13687 {
13688     PyObject *bytes;
13689     Py_ssize_t n;
13690 
13691     if (size < 0) {
13692         errno = EINVAL;
13693         return posix_error();
13694     }
13695 
13696     bytes = PyBytes_FromStringAndSize(NULL, size);
13697     if (bytes == NULL) {
13698         PyErr_NoMemory();
13699         return NULL;
13700     }
13701 
13702     while (1) {
13703         n = syscall(SYS_getrandom,
13704                     PyBytes_AS_STRING(bytes),
13705                     PyBytes_GET_SIZE(bytes),
13706                     flags);
13707         if (n < 0 && errno == EINTR) {
13708             if (PyErr_CheckSignals() < 0) {
13709                 goto error;
13710             }
13711 
13712             /* getrandom() was interrupted by a signal: retry */
13713             continue;
13714         }
13715         break;
13716     }
13717 
13718     if (n < 0) {
13719         PyErr_SetFromErrno(PyExc_OSError);
13720         goto error;
13721     }
13722 
13723     if (n != size) {
13724         _PyBytes_Resize(&bytes, n);
13725     }
13726 
13727     return bytes;
13728 
13729 error:
13730     Py_DECREF(bytes);
13731     return NULL;
13732 }
13733 #endif   /* HAVE_GETRANDOM_SYSCALL */
13734 
13735 #ifdef MS_WINDOWS
13736 /* bpo-36085: Helper functions for managing DLL search directories
13737  * on win32
13738  */
13739 
13740 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
13741 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
13742 
13743 /*[clinic input]
13744 os._add_dll_directory
13745 
13746     path: path_t
13747 
13748 Add a path to the DLL search path.
13749 
13750 This search path is used when resolving dependencies for imported
13751 extension modules (the module itself is resolved through sys.path),
13752 and also by ctypes.
13753 
13754 Returns an opaque value that may be passed to os.remove_dll_directory
13755 to remove this directory from the search path.
13756 [clinic start generated code]*/
13757 
13758 static PyObject *
os__add_dll_directory_impl(PyObject * module,path_t * path)13759 os__add_dll_directory_impl(PyObject *module, path_t *path)
13760 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
13761 {
13762     HMODULE hKernel32;
13763     PAddDllDirectory AddDllDirectory;
13764     DLL_DIRECTORY_COOKIE cookie = 0;
13765     DWORD err = 0;
13766 
13767     if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
13768         return NULL;
13769     }
13770 
13771     /* For Windows 7, we have to load this. As this will be a fairly
13772        infrequent operation, just do it each time. Kernel32 is always
13773        loaded. */
13774     Py_BEGIN_ALLOW_THREADS
13775     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
13776         !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
13777             hKernel32, "AddDllDirectory")) ||
13778         !(cookie = (*AddDllDirectory)(path->wide))) {
13779         err = GetLastError();
13780     }
13781     Py_END_ALLOW_THREADS
13782 
13783     if (err) {
13784         return win32_error_object_err("add_dll_directory",
13785                                       path->object, err);
13786     }
13787 
13788     return PyCapsule_New(cookie, "DLL directory cookie", NULL);
13789 }
13790 
13791 /*[clinic input]
13792 os._remove_dll_directory
13793 
13794     cookie: object
13795 
13796 Removes a path from the DLL search path.
13797 
13798 The parameter is an opaque value that was returned from
13799 os.add_dll_directory. You can only remove directories that you added
13800 yourself.
13801 [clinic start generated code]*/
13802 
13803 static PyObject *
os__remove_dll_directory_impl(PyObject * module,PyObject * cookie)13804 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
13805 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
13806 {
13807     HMODULE hKernel32;
13808     PRemoveDllDirectory RemoveDllDirectory;
13809     DLL_DIRECTORY_COOKIE cookieValue;
13810     DWORD err = 0;
13811 
13812     if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
13813         PyErr_SetString(PyExc_TypeError,
13814             "Provided cookie was not returned from os.add_dll_directory");
13815         return NULL;
13816     }
13817 
13818     cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
13819         cookie, "DLL directory cookie");
13820 
13821     /* For Windows 7, we have to load this. As this will be a fairly
13822        infrequent operation, just do it each time. Kernel32 is always
13823        loaded. */
13824     Py_BEGIN_ALLOW_THREADS
13825     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
13826         !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
13827             hKernel32, "RemoveDllDirectory")) ||
13828         !(*RemoveDllDirectory)(cookieValue)) {
13829         err = GetLastError();
13830     }
13831     Py_END_ALLOW_THREADS
13832 
13833     if (err) {
13834         return win32_error_object_err("remove_dll_directory",
13835                                       NULL, err);
13836     }
13837 
13838     if (PyCapsule_SetName(cookie, NULL)) {
13839         return NULL;
13840     }
13841 
13842     Py_RETURN_NONE;
13843 }
13844 
13845 #endif
13846 
13847 static PyMethodDef posix_methods[] = {
13848 
13849     OS_STAT_METHODDEF
13850     OS_ACCESS_METHODDEF
13851     OS_TTYNAME_METHODDEF
13852     OS_CHDIR_METHODDEF
13853     OS_CHFLAGS_METHODDEF
13854     OS_CHMOD_METHODDEF
13855     OS_FCHMOD_METHODDEF
13856     OS_LCHMOD_METHODDEF
13857     OS_CHOWN_METHODDEF
13858     OS_FCHOWN_METHODDEF
13859     OS_LCHOWN_METHODDEF
13860     OS_LCHFLAGS_METHODDEF
13861     OS_CHROOT_METHODDEF
13862     OS_CTERMID_METHODDEF
13863     OS_GETCWD_METHODDEF
13864     OS_GETCWDB_METHODDEF
13865     OS_LINK_METHODDEF
13866     OS_LISTDIR_METHODDEF
13867     OS_LSTAT_METHODDEF
13868     OS_MKDIR_METHODDEF
13869     OS_NICE_METHODDEF
13870     OS_GETPRIORITY_METHODDEF
13871     OS_SETPRIORITY_METHODDEF
13872     OS_POSIX_SPAWN_METHODDEF
13873     OS_POSIX_SPAWNP_METHODDEF
13874     OS_READLINK_METHODDEF
13875     OS_COPY_FILE_RANGE_METHODDEF
13876     OS_RENAME_METHODDEF
13877     OS_REPLACE_METHODDEF
13878     OS_RMDIR_METHODDEF
13879     OS_SYMLINK_METHODDEF
13880     OS_SYSTEM_METHODDEF
13881     OS_UMASK_METHODDEF
13882     OS_UNAME_METHODDEF
13883     OS_UNLINK_METHODDEF
13884     OS_REMOVE_METHODDEF
13885     OS_UTIME_METHODDEF
13886     OS_TIMES_METHODDEF
13887     OS__EXIT_METHODDEF
13888     OS__FCOPYFILE_METHODDEF
13889     OS_EXECV_METHODDEF
13890     OS_EXECVE_METHODDEF
13891     OS_SPAWNV_METHODDEF
13892     OS_SPAWNVE_METHODDEF
13893     OS_FORK1_METHODDEF
13894     OS_FORK_METHODDEF
13895     OS_REGISTER_AT_FORK_METHODDEF
13896     OS_SCHED_GET_PRIORITY_MAX_METHODDEF
13897     OS_SCHED_GET_PRIORITY_MIN_METHODDEF
13898     OS_SCHED_GETPARAM_METHODDEF
13899     OS_SCHED_GETSCHEDULER_METHODDEF
13900     OS_SCHED_RR_GET_INTERVAL_METHODDEF
13901     OS_SCHED_SETPARAM_METHODDEF
13902     OS_SCHED_SETSCHEDULER_METHODDEF
13903     OS_SCHED_YIELD_METHODDEF
13904     OS_SCHED_SETAFFINITY_METHODDEF
13905     OS_SCHED_GETAFFINITY_METHODDEF
13906     OS_OPENPTY_METHODDEF
13907     OS_FORKPTY_METHODDEF
13908     OS_GETEGID_METHODDEF
13909     OS_GETEUID_METHODDEF
13910     OS_GETGID_METHODDEF
13911 #ifdef HAVE_GETGROUPLIST
13912     {"getgrouplist",    posix_getgrouplist, METH_VARARGS, posix_getgrouplist__doc__},
13913 #endif
13914     OS_GETGROUPS_METHODDEF
13915     OS_GETPID_METHODDEF
13916     OS_GETPGRP_METHODDEF
13917     OS_GETPPID_METHODDEF
13918     OS_GETUID_METHODDEF
13919     OS_GETLOGIN_METHODDEF
13920     OS_KILL_METHODDEF
13921     OS_KILLPG_METHODDEF
13922     OS_PLOCK_METHODDEF
13923 #ifdef MS_WINDOWS
13924     OS_STARTFILE_METHODDEF
13925 #endif
13926     OS_SETUID_METHODDEF
13927     OS_SETEUID_METHODDEF
13928     OS_SETREUID_METHODDEF
13929     OS_SETGID_METHODDEF
13930     OS_SETEGID_METHODDEF
13931     OS_SETREGID_METHODDEF
13932     OS_SETGROUPS_METHODDEF
13933 #ifdef HAVE_INITGROUPS
13934     {"initgroups",      posix_initgroups, METH_VARARGS, posix_initgroups__doc__},
13935 #endif /* HAVE_INITGROUPS */
13936     OS_GETPGID_METHODDEF
13937     OS_SETPGRP_METHODDEF
13938     OS_WAIT_METHODDEF
13939     OS_WAIT3_METHODDEF
13940     OS_WAIT4_METHODDEF
13941     OS_WAITID_METHODDEF
13942     OS_WAITPID_METHODDEF
13943     OS_GETSID_METHODDEF
13944     OS_SETSID_METHODDEF
13945     OS_SETPGID_METHODDEF
13946     OS_TCGETPGRP_METHODDEF
13947     OS_TCSETPGRP_METHODDEF
13948     OS_OPEN_METHODDEF
13949     OS_CLOSE_METHODDEF
13950     OS_CLOSERANGE_METHODDEF
13951     OS_DEVICE_ENCODING_METHODDEF
13952     OS_DUP_METHODDEF
13953     OS_DUP2_METHODDEF
13954     OS_LOCKF_METHODDEF
13955     OS_LSEEK_METHODDEF
13956     OS_READ_METHODDEF
13957     OS_READV_METHODDEF
13958     OS_PREAD_METHODDEF
13959     OS_PREADV_METHODDEF
13960     OS_WRITE_METHODDEF
13961     OS_WRITEV_METHODDEF
13962     OS_PWRITE_METHODDEF
13963     OS_PWRITEV_METHODDEF
13964 #ifdef HAVE_SENDFILE
13965     {"sendfile",        (PyCFunction)(void(*)(void))posix_sendfile, METH_VARARGS | METH_KEYWORDS,
13966                             posix_sendfile__doc__},
13967 #endif
13968     OS_FSTAT_METHODDEF
13969     OS_ISATTY_METHODDEF
13970     OS_PIPE_METHODDEF
13971     OS_PIPE2_METHODDEF
13972     OS_MKFIFO_METHODDEF
13973     OS_MKNOD_METHODDEF
13974     OS_MAJOR_METHODDEF
13975     OS_MINOR_METHODDEF
13976     OS_MAKEDEV_METHODDEF
13977     OS_FTRUNCATE_METHODDEF
13978     OS_TRUNCATE_METHODDEF
13979     OS_POSIX_FALLOCATE_METHODDEF
13980     OS_POSIX_FADVISE_METHODDEF
13981     OS_PUTENV_METHODDEF
13982     OS_UNSETENV_METHODDEF
13983     OS_STRERROR_METHODDEF
13984     OS_FCHDIR_METHODDEF
13985     OS_FSYNC_METHODDEF
13986     OS_SYNC_METHODDEF
13987     OS_FDATASYNC_METHODDEF
13988     OS_WCOREDUMP_METHODDEF
13989     OS_WIFCONTINUED_METHODDEF
13990     OS_WIFSTOPPED_METHODDEF
13991     OS_WIFSIGNALED_METHODDEF
13992     OS_WIFEXITED_METHODDEF
13993     OS_WEXITSTATUS_METHODDEF
13994     OS_WTERMSIG_METHODDEF
13995     OS_WSTOPSIG_METHODDEF
13996     OS_FSTATVFS_METHODDEF
13997     OS_STATVFS_METHODDEF
13998     OS_CONFSTR_METHODDEF
13999     OS_SYSCONF_METHODDEF
14000     OS_FPATHCONF_METHODDEF
14001     OS_PATHCONF_METHODDEF
14002     OS_ABORT_METHODDEF
14003     OS__GETFULLPATHNAME_METHODDEF
14004     OS__GETDISKUSAGE_METHODDEF
14005     OS__GETFINALPATHNAME_METHODDEF
14006     OS__GETVOLUMEPATHNAME_METHODDEF
14007     OS__PATH_SPLITROOT_METHODDEF
14008     OS_GETLOADAVG_METHODDEF
14009     OS_URANDOM_METHODDEF
14010     OS_SETRESUID_METHODDEF
14011     OS_SETRESGID_METHODDEF
14012     OS_GETRESUID_METHODDEF
14013     OS_GETRESGID_METHODDEF
14014 
14015     OS_GETXATTR_METHODDEF
14016     OS_SETXATTR_METHODDEF
14017     OS_REMOVEXATTR_METHODDEF
14018     OS_LISTXATTR_METHODDEF
14019 
14020 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
14021     {"get_terminal_size", get_terminal_size, METH_VARARGS, termsize__doc__},
14022 #endif
14023     OS_CPU_COUNT_METHODDEF
14024     OS_GET_INHERITABLE_METHODDEF
14025     OS_SET_INHERITABLE_METHODDEF
14026     OS_GET_HANDLE_INHERITABLE_METHODDEF
14027     OS_SET_HANDLE_INHERITABLE_METHODDEF
14028 #ifndef MS_WINDOWS
14029     OS_GET_BLOCKING_METHODDEF
14030     OS_SET_BLOCKING_METHODDEF
14031 #endif
14032     OS_SCANDIR_METHODDEF
14033     OS_FSPATH_METHODDEF
14034     OS_GETRANDOM_METHODDEF
14035     OS_MEMFD_CREATE_METHODDEF
14036 #ifdef MS_WINDOWS
14037     OS__ADD_DLL_DIRECTORY_METHODDEF
14038     OS__REMOVE_DLL_DIRECTORY_METHODDEF
14039 #endif
14040     {NULL,              NULL}            /* Sentinel */
14041 };
14042 
14043 static int
all_ins(PyObject * m)14044 all_ins(PyObject *m)
14045 {
14046 #ifdef F_OK
14047     if (PyModule_AddIntMacro(m, F_OK)) return -1;
14048 #endif
14049 #ifdef R_OK
14050     if (PyModule_AddIntMacro(m, R_OK)) return -1;
14051 #endif
14052 #ifdef W_OK
14053     if (PyModule_AddIntMacro(m, W_OK)) return -1;
14054 #endif
14055 #ifdef X_OK
14056     if (PyModule_AddIntMacro(m, X_OK)) return -1;
14057 #endif
14058 #ifdef NGROUPS_MAX
14059     if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
14060 #endif
14061 #ifdef TMP_MAX
14062     if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
14063 #endif
14064 #ifdef WCONTINUED
14065     if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
14066 #endif
14067 #ifdef WNOHANG
14068     if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
14069 #endif
14070 #ifdef WUNTRACED
14071     if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
14072 #endif
14073 #ifdef O_RDONLY
14074     if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
14075 #endif
14076 #ifdef O_WRONLY
14077     if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
14078 #endif
14079 #ifdef O_RDWR
14080     if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
14081 #endif
14082 #ifdef O_NDELAY
14083     if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
14084 #endif
14085 #ifdef O_NONBLOCK
14086     if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
14087 #endif
14088 #ifdef O_APPEND
14089     if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
14090 #endif
14091 #ifdef O_DSYNC
14092     if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
14093 #endif
14094 #ifdef O_RSYNC
14095     if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
14096 #endif
14097 #ifdef O_SYNC
14098     if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
14099 #endif
14100 #ifdef O_NOCTTY
14101     if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
14102 #endif
14103 #ifdef O_CREAT
14104     if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
14105 #endif
14106 #ifdef O_EXCL
14107     if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
14108 #endif
14109 #ifdef O_TRUNC
14110     if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
14111 #endif
14112 #ifdef O_BINARY
14113     if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
14114 #endif
14115 #ifdef O_TEXT
14116     if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
14117 #endif
14118 #ifdef O_XATTR
14119     if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
14120 #endif
14121 #ifdef O_LARGEFILE
14122     if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
14123 #endif
14124 #ifndef __GNU__
14125 #ifdef O_SHLOCK
14126     if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
14127 #endif
14128 #ifdef O_EXLOCK
14129     if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
14130 #endif
14131 #endif
14132 #ifdef O_EXEC
14133     if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
14134 #endif
14135 #ifdef O_SEARCH
14136     if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
14137 #endif
14138 #ifdef O_PATH
14139     if (PyModule_AddIntMacro(m, O_PATH)) return -1;
14140 #endif
14141 #ifdef O_TTY_INIT
14142     if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
14143 #endif
14144 #ifdef O_TMPFILE
14145     if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
14146 #endif
14147 #ifdef PRIO_PROCESS
14148     if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
14149 #endif
14150 #ifdef PRIO_PGRP
14151     if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
14152 #endif
14153 #ifdef PRIO_USER
14154     if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
14155 #endif
14156 #ifdef O_CLOEXEC
14157     if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
14158 #endif
14159 #ifdef O_ACCMODE
14160     if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
14161 #endif
14162 
14163 
14164 #ifdef SEEK_HOLE
14165     if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
14166 #endif
14167 #ifdef SEEK_DATA
14168     if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
14169 #endif
14170 
14171 /* MS Windows */
14172 #ifdef O_NOINHERIT
14173     /* Don't inherit in child processes. */
14174     if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
14175 #endif
14176 #ifdef _O_SHORT_LIVED
14177     /* Optimize for short life (keep in memory). */
14178     /* MS forgot to define this one with a non-underscore form too. */
14179     if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
14180 #endif
14181 #ifdef O_TEMPORARY
14182     /* Automatically delete when last handle is closed. */
14183     if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
14184 #endif
14185 #ifdef O_RANDOM
14186     /* Optimize for random access. */
14187     if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
14188 #endif
14189 #ifdef O_SEQUENTIAL
14190     /* Optimize for sequential access. */
14191     if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
14192 #endif
14193 
14194 /* GNU extensions. */
14195 #ifdef O_ASYNC
14196     /* Send a SIGIO signal whenever input or output
14197        becomes available on file descriptor */
14198     if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
14199 #endif
14200 #ifdef O_DIRECT
14201     /* Direct disk access. */
14202     if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
14203 #endif
14204 #ifdef O_DIRECTORY
14205     /* Must be a directory.      */
14206     if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
14207 #endif
14208 #ifdef O_NOFOLLOW
14209     /* Do not follow links.      */
14210     if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
14211 #endif
14212 #ifdef O_NOLINKS
14213     /* Fails if link count of the named file is greater than 1 */
14214     if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
14215 #endif
14216 #ifdef O_NOATIME
14217     /* Do not update the access time. */
14218     if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
14219 #endif
14220 
14221     /* These come from sysexits.h */
14222 #ifdef EX_OK
14223     if (PyModule_AddIntMacro(m, EX_OK)) return -1;
14224 #endif /* EX_OK */
14225 #ifdef EX_USAGE
14226     if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
14227 #endif /* EX_USAGE */
14228 #ifdef EX_DATAERR
14229     if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
14230 #endif /* EX_DATAERR */
14231 #ifdef EX_NOINPUT
14232     if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
14233 #endif /* EX_NOINPUT */
14234 #ifdef EX_NOUSER
14235     if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
14236 #endif /* EX_NOUSER */
14237 #ifdef EX_NOHOST
14238     if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
14239 #endif /* EX_NOHOST */
14240 #ifdef EX_UNAVAILABLE
14241     if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
14242 #endif /* EX_UNAVAILABLE */
14243 #ifdef EX_SOFTWARE
14244     if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
14245 #endif /* EX_SOFTWARE */
14246 #ifdef EX_OSERR
14247     if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
14248 #endif /* EX_OSERR */
14249 #ifdef EX_OSFILE
14250     if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
14251 #endif /* EX_OSFILE */
14252 #ifdef EX_CANTCREAT
14253     if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
14254 #endif /* EX_CANTCREAT */
14255 #ifdef EX_IOERR
14256     if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
14257 #endif /* EX_IOERR */
14258 #ifdef EX_TEMPFAIL
14259     if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
14260 #endif /* EX_TEMPFAIL */
14261 #ifdef EX_PROTOCOL
14262     if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
14263 #endif /* EX_PROTOCOL */
14264 #ifdef EX_NOPERM
14265     if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
14266 #endif /* EX_NOPERM */
14267 #ifdef EX_CONFIG
14268     if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
14269 #endif /* EX_CONFIG */
14270 #ifdef EX_NOTFOUND
14271     if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
14272 #endif /* EX_NOTFOUND */
14273 
14274     /* statvfs */
14275 #ifdef ST_RDONLY
14276     if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
14277 #endif /* ST_RDONLY */
14278 #ifdef ST_NOSUID
14279     if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
14280 #endif /* ST_NOSUID */
14281 
14282        /* GNU extensions */
14283 #ifdef ST_NODEV
14284     if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
14285 #endif /* ST_NODEV */
14286 #ifdef ST_NOEXEC
14287     if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
14288 #endif /* ST_NOEXEC */
14289 #ifdef ST_SYNCHRONOUS
14290     if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
14291 #endif /* ST_SYNCHRONOUS */
14292 #ifdef ST_MANDLOCK
14293     if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
14294 #endif /* ST_MANDLOCK */
14295 #ifdef ST_WRITE
14296     if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
14297 #endif /* ST_WRITE */
14298 #ifdef ST_APPEND
14299     if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
14300 #endif /* ST_APPEND */
14301 #ifdef ST_NOATIME
14302     if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
14303 #endif /* ST_NOATIME */
14304 #ifdef ST_NODIRATIME
14305     if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
14306 #endif /* ST_NODIRATIME */
14307 #ifdef ST_RELATIME
14308     if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
14309 #endif /* ST_RELATIME */
14310 
14311     /* FreeBSD sendfile() constants */
14312 #ifdef SF_NODISKIO
14313     if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
14314 #endif
14315 #ifdef SF_MNOWAIT
14316     if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
14317 #endif
14318 #ifdef SF_SYNC
14319     if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
14320 #endif
14321 
14322     /* constants for posix_fadvise */
14323 #ifdef POSIX_FADV_NORMAL
14324     if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
14325 #endif
14326 #ifdef POSIX_FADV_SEQUENTIAL
14327     if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
14328 #endif
14329 #ifdef POSIX_FADV_RANDOM
14330     if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
14331 #endif
14332 #ifdef POSIX_FADV_NOREUSE
14333     if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
14334 #endif
14335 #ifdef POSIX_FADV_WILLNEED
14336     if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
14337 #endif
14338 #ifdef POSIX_FADV_DONTNEED
14339     if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
14340 #endif
14341 
14342     /* constants for waitid */
14343 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
14344     if (PyModule_AddIntMacro(m, P_PID)) return -1;
14345     if (PyModule_AddIntMacro(m, P_PGID)) return -1;
14346     if (PyModule_AddIntMacro(m, P_ALL)) return -1;
14347 #endif
14348 #ifdef WEXITED
14349     if (PyModule_AddIntMacro(m, WEXITED)) return -1;
14350 #endif
14351 #ifdef WNOWAIT
14352     if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
14353 #endif
14354 #ifdef WSTOPPED
14355     if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
14356 #endif
14357 #ifdef CLD_EXITED
14358     if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
14359 #endif
14360 #ifdef CLD_DUMPED
14361     if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
14362 #endif
14363 #ifdef CLD_TRAPPED
14364     if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
14365 #endif
14366 #ifdef CLD_CONTINUED
14367     if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
14368 #endif
14369 
14370     /* constants for lockf */
14371 #ifdef F_LOCK
14372     if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
14373 #endif
14374 #ifdef F_TLOCK
14375     if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
14376 #endif
14377 #ifdef F_ULOCK
14378     if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
14379 #endif
14380 #ifdef F_TEST
14381     if (PyModule_AddIntMacro(m, F_TEST)) return -1;
14382 #endif
14383 
14384 #ifdef RWF_DSYNC
14385     if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
14386 #endif
14387 #ifdef RWF_HIPRI
14388     if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
14389 #endif
14390 #ifdef RWF_SYNC
14391     if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
14392 #endif
14393 #ifdef RWF_NOWAIT
14394     if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
14395 #endif
14396 
14397 /* constants for posix_spawn */
14398 #ifdef HAVE_POSIX_SPAWN
14399     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
14400     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
14401     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
14402 #endif
14403 
14404 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
14405     if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
14406     if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
14407     if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
14408 #endif
14409 #ifdef HAVE_SPAWNV
14410     if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
14411     if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
14412 #endif
14413 
14414 #ifdef HAVE_SCHED_H
14415 #ifdef SCHED_OTHER
14416     if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
14417 #endif
14418 #ifdef SCHED_FIFO
14419     if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
14420 #endif
14421 #ifdef SCHED_RR
14422     if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
14423 #endif
14424 #ifdef SCHED_SPORADIC
14425     if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
14426 #endif
14427 #ifdef SCHED_BATCH
14428     if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
14429 #endif
14430 #ifdef SCHED_IDLE
14431     if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
14432 #endif
14433 #ifdef SCHED_RESET_ON_FORK
14434     if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
14435 #endif
14436 #ifdef SCHED_SYS
14437     if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
14438 #endif
14439 #ifdef SCHED_IA
14440     if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
14441 #endif
14442 #ifdef SCHED_FSS
14443     if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
14444 #endif
14445 #ifdef SCHED_FX
14446     if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
14447 #endif
14448 #endif
14449 
14450 #ifdef USE_XATTRS
14451     if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
14452     if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
14453     if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
14454 #endif
14455 
14456 #if HAVE_DECL_RTLD_LAZY
14457     if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
14458 #endif
14459 #if HAVE_DECL_RTLD_NOW
14460     if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
14461 #endif
14462 #if HAVE_DECL_RTLD_GLOBAL
14463     if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
14464 #endif
14465 #if HAVE_DECL_RTLD_LOCAL
14466     if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
14467 #endif
14468 #if HAVE_DECL_RTLD_NODELETE
14469     if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
14470 #endif
14471 #if HAVE_DECL_RTLD_NOLOAD
14472     if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
14473 #endif
14474 #if HAVE_DECL_RTLD_DEEPBIND
14475     if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
14476 #endif
14477 #if HAVE_DECL_RTLD_MEMBER
14478     if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
14479 #endif
14480 
14481 #ifdef HAVE_GETRANDOM_SYSCALL
14482     if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
14483     if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
14484 #endif
14485 #ifdef HAVE_MEMFD_CREATE
14486     if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
14487     if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
14488 #ifdef MFD_HUGETLB
14489     if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
14490 #endif
14491 #ifdef MFD_HUGE_SHIFT
14492     if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
14493 #endif
14494 #ifdef MFD_HUGE_MASK
14495     if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
14496 #endif
14497 #ifdef MFD_HUGE_64KB
14498     if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
14499 #endif
14500 #ifdef MFD_HUGE_512KB
14501     if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
14502 #endif
14503 #ifdef MFD_HUGE_1MB
14504     if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
14505 #endif
14506 #ifdef MFD_HUGE_2MB
14507     if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
14508 #endif
14509 #ifdef MFD_HUGE_8MB
14510     if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
14511 #endif
14512 #ifdef MFD_HUGE_16MB
14513     if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
14514 #endif
14515 #ifdef MFD_HUGE_32MB
14516     if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
14517 #endif
14518 #ifdef MFD_HUGE_256MB
14519     if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
14520 #endif
14521 #ifdef MFD_HUGE_512MB
14522     if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
14523 #endif
14524 #ifdef MFD_HUGE_1GB
14525     if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
14526 #endif
14527 #ifdef MFD_HUGE_2GB
14528     if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
14529 #endif
14530 #ifdef MFD_HUGE_16GB
14531     if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
14532 #endif
14533 #endif
14534 
14535 #if defined(__APPLE__)
14536     if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
14537 #endif
14538 
14539 #ifdef MS_WINDOWS
14540     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
14541     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
14542     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
14543     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
14544     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
14545 #endif
14546 
14547     return 0;
14548 }
14549 
14550 
14551 static struct PyModuleDef posixmodule = {
14552     PyModuleDef_HEAD_INIT,
14553     MODNAME,
14554     posix__doc__,
14555     -1,
14556     posix_methods,
14557     NULL,
14558     NULL,
14559     NULL,
14560     NULL
14561 };
14562 
14563 
14564 static const char * const have_functions[] = {
14565 
14566 #ifdef HAVE_FACCESSAT
14567     "HAVE_FACCESSAT",
14568 #endif
14569 
14570 #ifdef HAVE_FCHDIR
14571     "HAVE_FCHDIR",
14572 #endif
14573 
14574 #ifdef HAVE_FCHMOD
14575     "HAVE_FCHMOD",
14576 #endif
14577 
14578 #ifdef HAVE_FCHMODAT
14579     "HAVE_FCHMODAT",
14580 #endif
14581 
14582 #ifdef HAVE_FCHOWN
14583     "HAVE_FCHOWN",
14584 #endif
14585 
14586 #ifdef HAVE_FCHOWNAT
14587     "HAVE_FCHOWNAT",
14588 #endif
14589 
14590 #ifdef HAVE_FEXECVE
14591     "HAVE_FEXECVE",
14592 #endif
14593 
14594 #ifdef HAVE_FDOPENDIR
14595     "HAVE_FDOPENDIR",
14596 #endif
14597 
14598 #ifdef HAVE_FPATHCONF
14599     "HAVE_FPATHCONF",
14600 #endif
14601 
14602 #ifdef HAVE_FSTATAT
14603     "HAVE_FSTATAT",
14604 #endif
14605 
14606 #ifdef HAVE_FSTATVFS
14607     "HAVE_FSTATVFS",
14608 #endif
14609 
14610 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
14611     "HAVE_FTRUNCATE",
14612 #endif
14613 
14614 #ifdef HAVE_FUTIMENS
14615     "HAVE_FUTIMENS",
14616 #endif
14617 
14618 #ifdef HAVE_FUTIMES
14619     "HAVE_FUTIMES",
14620 #endif
14621 
14622 #ifdef HAVE_FUTIMESAT
14623     "HAVE_FUTIMESAT",
14624 #endif
14625 
14626 #ifdef HAVE_LINKAT
14627     "HAVE_LINKAT",
14628 #endif
14629 
14630 #ifdef HAVE_LCHFLAGS
14631     "HAVE_LCHFLAGS",
14632 #endif
14633 
14634 #ifdef HAVE_LCHMOD
14635     "HAVE_LCHMOD",
14636 #endif
14637 
14638 #ifdef HAVE_LCHOWN
14639     "HAVE_LCHOWN",
14640 #endif
14641 
14642 #ifdef HAVE_LSTAT
14643     "HAVE_LSTAT",
14644 #endif
14645 
14646 #ifdef HAVE_LUTIMES
14647     "HAVE_LUTIMES",
14648 #endif
14649 
14650 #ifdef HAVE_MEMFD_CREATE
14651     "HAVE_MEMFD_CREATE",
14652 #endif
14653 
14654 #ifdef HAVE_MKDIRAT
14655     "HAVE_MKDIRAT",
14656 #endif
14657 
14658 #ifdef HAVE_MKFIFOAT
14659     "HAVE_MKFIFOAT",
14660 #endif
14661 
14662 #ifdef HAVE_MKNODAT
14663     "HAVE_MKNODAT",
14664 #endif
14665 
14666 #ifdef HAVE_OPENAT
14667     "HAVE_OPENAT",
14668 #endif
14669 
14670 #ifdef HAVE_READLINKAT
14671     "HAVE_READLINKAT",
14672 #endif
14673 
14674 #ifdef HAVE_RENAMEAT
14675     "HAVE_RENAMEAT",
14676 #endif
14677 
14678 #ifdef HAVE_SYMLINKAT
14679     "HAVE_SYMLINKAT",
14680 #endif
14681 
14682 #ifdef HAVE_UNLINKAT
14683     "HAVE_UNLINKAT",
14684 #endif
14685 
14686 #ifdef HAVE_UTIMENSAT
14687     "HAVE_UTIMENSAT",
14688 #endif
14689 
14690 #ifdef MS_WINDOWS
14691     "MS_WINDOWS",
14692 #endif
14693 
14694     NULL
14695 };
14696 
14697 
14698 PyMODINIT_FUNC
INITFUNC(void)14699 INITFUNC(void)
14700 {
14701     PyObject *m, *v;
14702     PyObject *list;
14703     const char * const *trace;
14704 
14705     m = PyModule_Create(&posixmodule);
14706     if (m == NULL)
14707         return NULL;
14708 
14709     /* Initialize environ dictionary */
14710     v = convertenviron();
14711     Py_XINCREF(v);
14712     if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
14713         return NULL;
14714     Py_DECREF(v);
14715 
14716     if (all_ins(m))
14717         return NULL;
14718 
14719     if (setup_confname_tables(m))
14720         return NULL;
14721 
14722     Py_INCREF(PyExc_OSError);
14723     PyModule_AddObject(m, "error", PyExc_OSError);
14724 
14725 #ifdef HAVE_PUTENV
14726     if (posix_putenv_garbage == NULL)
14727         posix_putenv_garbage = PyDict_New();
14728 #endif
14729 
14730     if (!initialized) {
14731 #if defined(HAVE_WAITID) && !defined(__APPLE__)
14732         waitid_result_desc.name = MODNAME ".waitid_result";
14733         WaitidResultType = PyStructSequence_NewType(&waitid_result_desc);
14734         if (WaitidResultType == NULL) {
14735             return NULL;
14736         }
14737 #endif
14738 
14739         stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
14740         stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
14741         stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
14742         stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
14743         StatResultType = PyStructSequence_NewType(&stat_result_desc);
14744         if (StatResultType == NULL) {
14745             return NULL;
14746         }
14747         structseq_new = StatResultType->tp_new;
14748         StatResultType->tp_new = statresult_new;
14749 
14750         statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
14751         StatVFSResultType = PyStructSequence_NewType(&statvfs_result_desc);
14752         if (StatVFSResultType == NULL) {
14753             return NULL;
14754         }
14755 #ifdef NEED_TICKS_PER_SECOND
14756 #  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
14757         ticks_per_second = sysconf(_SC_CLK_TCK);
14758 #  elif defined(HZ)
14759         ticks_per_second = HZ;
14760 #  else
14761         ticks_per_second = 60; /* magic fallback value; may be bogus */
14762 #  endif
14763 #endif
14764 
14765 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
14766         sched_param_desc.name = MODNAME ".sched_param";
14767         SchedParamType = PyStructSequence_NewType(&sched_param_desc);
14768         if (SchedParamType == NULL) {
14769             return NULL;
14770         }
14771         SchedParamType->tp_new = os_sched_param;
14772 #endif
14773 
14774         /* initialize TerminalSize_info */
14775         TerminalSizeType = PyStructSequence_NewType(&TerminalSize_desc);
14776         if (TerminalSizeType == NULL) {
14777             return NULL;
14778         }
14779 
14780         /* initialize scandir types */
14781         if (PyType_Ready(&ScandirIteratorType) < 0)
14782             return NULL;
14783         if (PyType_Ready(&DirEntryType) < 0)
14784             return NULL;
14785     }
14786 #if defined(HAVE_WAITID) && !defined(__APPLE__)
14787     Py_INCREF((PyObject*) WaitidResultType);
14788     PyModule_AddObject(m, "waitid_result", (PyObject*) WaitidResultType);
14789 #endif
14790     Py_INCREF((PyObject*) StatResultType);
14791     PyModule_AddObject(m, "stat_result", (PyObject*) StatResultType);
14792     Py_INCREF((PyObject*) StatVFSResultType);
14793     PyModule_AddObject(m, "statvfs_result",
14794                        (PyObject*) StatVFSResultType);
14795 
14796 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
14797     Py_INCREF(SchedParamType);
14798     PyModule_AddObject(m, "sched_param", (PyObject *)SchedParamType);
14799 #endif
14800 
14801     times_result_desc.name = MODNAME ".times_result";
14802     TimesResultType = PyStructSequence_NewType(&times_result_desc);
14803     if (TimesResultType == NULL) {
14804         return NULL;
14805     }
14806     PyModule_AddObject(m, "times_result", (PyObject *)TimesResultType);
14807 
14808     uname_result_desc.name = MODNAME ".uname_result";
14809     UnameResultType = PyStructSequence_NewType(&uname_result_desc);
14810     if (UnameResultType == NULL) {
14811         return NULL;
14812     }
14813     PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
14814 
14815 #ifdef __APPLE__
14816     /*
14817      * Step 2 of weak-linking support on Mac OS X.
14818      *
14819      * The code below removes functions that are not available on the
14820      * currently active platform.
14821      *
14822      * This block allow one to use a python binary that was build on
14823      * OSX 10.4 on OSX 10.3, without losing access to new APIs on
14824      * OSX 10.4.
14825      */
14826 #ifdef HAVE_FSTATVFS
14827     if (fstatvfs == NULL) {
14828         if (PyObject_DelAttrString(m, "fstatvfs") == -1) {
14829             return NULL;
14830         }
14831     }
14832 #endif /* HAVE_FSTATVFS */
14833 
14834 #ifdef HAVE_STATVFS
14835     if (statvfs == NULL) {
14836         if (PyObject_DelAttrString(m, "statvfs") == -1) {
14837             return NULL;
14838         }
14839     }
14840 #endif /* HAVE_STATVFS */
14841 
14842 # ifdef HAVE_LCHOWN
14843     if (lchown == NULL) {
14844         if (PyObject_DelAttrString(m, "lchown") == -1) {
14845             return NULL;
14846         }
14847     }
14848 #endif /* HAVE_LCHOWN */
14849 
14850 
14851 #endif /* __APPLE__ */
14852 
14853     Py_INCREF(TerminalSizeType);
14854     PyModule_AddObject(m, "terminal_size", (PyObject*)TerminalSizeType);
14855 
14856     billion = PyLong_FromLong(1000000000);
14857     if (!billion)
14858         return NULL;
14859 
14860     /* suppress "function not used" warnings */
14861     {
14862     int ignored;
14863     fd_specified("", -1);
14864     follow_symlinks_specified("", 1);
14865     dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
14866     dir_fd_converter(Py_None, &ignored);
14867     dir_fd_unavailable(Py_None, &ignored);
14868     }
14869 
14870     /*
14871      * provide list of locally available functions
14872      * so os.py can populate support_* lists
14873      */
14874     list = PyList_New(0);
14875     if (!list)
14876         return NULL;
14877     for (trace = have_functions; *trace; trace++) {
14878         PyObject *unicode = PyUnicode_DecodeASCII(*trace, strlen(*trace), NULL);
14879         if (!unicode)
14880             return NULL;
14881         if (PyList_Append(list, unicode))
14882             return NULL;
14883         Py_DECREF(unicode);
14884     }
14885     PyModule_AddObject(m, "_have_functions", list);
14886 
14887     Py_INCREF((PyObject *) &DirEntryType);
14888     PyModule_AddObject(m, "DirEntry", (PyObject *)&DirEntryType);
14889 
14890     initialized = 1;
14891 
14892     return m;
14893 }
14894 
14895 #ifdef __cplusplus
14896 }
14897 #endif
14898