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