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