/src/Python-3.8.3/Modules/posixmodule.c
Line  | Count  | Source  | 
1  |  |  | 
2  |  | /* POSIX module implementation */  | 
3  |  |  | 
4  |  | /* This file is also used for Windows NT/MS-Win.  In that case the  | 
5  |  |    module actually calls itself 'nt', not 'posix', and a few  | 
6  |  |    functions are either unimplemented or implemented differently.  The source  | 
7  |  |    assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent  | 
8  |  |    of the compiler used.  Different compilers define their own feature  | 
9  |  |    test macro, e.g. '_MSC_VER'. */  | 
10  |  |  | 
11  |  |  | 
12  |  |  | 
13  |  | #ifdef __APPLE__  | 
14  |  |    /*  | 
15  |  |     * Step 1 of support for weak-linking a number of symbols existing on  | 
16  |  |     * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block  | 
17  |  |     * at the end of this file for more information.  | 
18  |  |     */  | 
19  |  | #  pragma weak lchown  | 
20  |  | #  pragma weak statvfs  | 
21  |  | #  pragma weak fstatvfs  | 
22  |  |  | 
23  |  | #endif /* __APPLE__ */  | 
24  |  |  | 
25  |  | #define PY_SSIZE_T_CLEAN  | 
26  |  |  | 
27  |  | #include "Python.h"  | 
28  |  | #ifdef MS_WINDOWS  | 
29  |  |    /* include <windows.h> early to avoid conflict with pycore_condvar.h:  | 
30  |  |  | 
31  |  |         #define WIN32_LEAN_AND_MEAN  | 
32  |  |         #include <windows.h>  | 
33  |  |  | 
34  |  |       FSCTL_GET_REPARSE_POINT is not exported with WIN32_LEAN_AND_MEAN. */  | 
35  |  | #  include <windows.h>  | 
36  |  | #endif  | 
37  |  |  | 
38  |  | #include "pycore_ceval.h"     /* _PyEval_ReInitThreads() */  | 
39  |  | #include "pycore_pystate.h"   /* _PyRuntime */  | 
40  |  | #include "pythread.h"  | 
41  |  | #include "structmember.h"  | 
42  |  | #ifndef MS_WINDOWS  | 
43  |  | #  include "posixmodule.h"  | 
44  |  | #else  | 
45  |  | #  include "winreparse.h"  | 
46  |  | #endif  | 
47  |  |  | 
48  |  | /* On android API level 21, 'AT_EACCESS' is not declared although  | 
49  |  |  * HAVE_FACCESSAT is defined. */  | 
50  |  | #ifdef __ANDROID__  | 
51  |  | #undef HAVE_FACCESSAT  | 
52  |  | #endif  | 
53  |  |  | 
54  |  | #include <stdio.h>  /* needed for ctermid() */  | 
55  |  |  | 
56  |  | #ifdef __cplusplus  | 
57  |  | extern "C" { | 
58  |  | #endif  | 
59  |  |  | 
60  |  | PyDoc_STRVAR(posix__doc__,  | 
61  |  | "This module provides access to operating system functionality that is\n\  | 
62  |  | standardized by the C Standard and the POSIX standard (a thinly\n\  | 
63  |  | disguised Unix interface).  Refer to the library manual and\n\  | 
64  |  | corresponding Unix manual entries for more information on calls.");  | 
65  |  |  | 
66  |  |  | 
67  |  | #ifdef HAVE_SYS_UIO_H  | 
68  |  | #include <sys/uio.h>  | 
69  |  | #endif  | 
70  |  |  | 
71  |  | #ifdef HAVE_SYS_SYSMACROS_H  | 
72  |  | /* GNU C Library: major(), minor(), makedev() */  | 
73  |  | #include <sys/sysmacros.h>  | 
74  |  | #endif  | 
75  |  |  | 
76  |  | #ifdef HAVE_SYS_TYPES_H  | 
77  |  | #include <sys/types.h>  | 
78  |  | #endif /* HAVE_SYS_TYPES_H */  | 
79  |  |  | 
80  |  | #ifdef HAVE_SYS_STAT_H  | 
81  |  | #include <sys/stat.h>  | 
82  |  | #endif /* HAVE_SYS_STAT_H */  | 
83  |  |  | 
84  |  | #ifdef HAVE_SYS_WAIT_H  | 
85  |  | #include <sys/wait.h>           /* For WNOHANG */  | 
86  |  | #endif  | 
87  |  |  | 
88  |  | #ifdef HAVE_SIGNAL_H  | 
89  |  | #include <signal.h>  | 
90  |  | #endif  | 
91  |  |  | 
92  |  | #ifdef HAVE_FCNTL_H  | 
93  |  | #include <fcntl.h>  | 
94  |  | #endif /* HAVE_FCNTL_H */  | 
95  |  |  | 
96  |  | #ifdef HAVE_GRP_H  | 
97  |  | #include <grp.h>  | 
98  |  | #endif  | 
99  |  |  | 
100  |  | #ifdef HAVE_SYSEXITS_H  | 
101  |  | #include <sysexits.h>  | 
102  |  | #endif /* HAVE_SYSEXITS_H */  | 
103  |  |  | 
104  |  | #ifdef HAVE_SYS_LOADAVG_H  | 
105  |  | #include <sys/loadavg.h>  | 
106  |  | #endif  | 
107  |  |  | 
108  |  | #ifdef HAVE_SYS_SENDFILE_H  | 
109  |  | #include <sys/sendfile.h>  | 
110  |  | #endif  | 
111  |  |  | 
112  |  | #if defined(__APPLE__)  | 
113  |  | #include <copyfile.h>  | 
114  |  | #endif  | 
115  |  |  | 
116  |  | #ifdef HAVE_SCHED_H  | 
117  |  | #include <sched.h>  | 
118  |  | #endif  | 
119  |  |  | 
120  |  | #ifdef HAVE_COPY_FILE_RANGE  | 
121  |  | #include <unistd.h>  | 
122  |  | #endif  | 
123  |  |  | 
124  |  | #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)  | 
125  |  | #undef HAVE_SCHED_SETAFFINITY  | 
126  |  | #endif  | 
127  |  |  | 
128  |  | #if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)  | 
129  |  | #define USE_XATTRS  | 
130  |  | #endif  | 
131  |  |  | 
132  |  | #ifdef USE_XATTRS  | 
133  |  | #include <sys/xattr.h>  | 
134  |  | #endif  | 
135  |  |  | 
136  |  | #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)  | 
137  |  | #ifdef HAVE_SYS_SOCKET_H  | 
138  |  | #include <sys/socket.h>  | 
139  |  | #endif  | 
140  |  | #endif  | 
141  |  |  | 
142  |  | #ifdef HAVE_DLFCN_H  | 
143  |  | #include <dlfcn.h>  | 
144  |  | #endif  | 
145  |  |  | 
146  |  | #ifdef __hpux  | 
147  |  | #include <sys/mpctl.h>  | 
148  |  | #endif  | 
149  |  |  | 
150  |  | #if defined(__DragonFly__) || \  | 
151  |  |     defined(__OpenBSD__)   || \  | 
152  |  |     defined(__FreeBSD__)   || \  | 
153  |  |     defined(__NetBSD__)    || \  | 
154  |  |     defined(__APPLE__)  | 
155  |  | #include <sys/sysctl.h>  | 
156  |  | #endif  | 
157  |  |  | 
158  |  | #ifdef HAVE_LINUX_RANDOM_H  | 
159  |  | #  include <linux/random.h>  | 
160  |  | #endif  | 
161  |  | #ifdef HAVE_GETRANDOM_SYSCALL  | 
162  |  | #  include <sys/syscall.h>  | 
163  |  | #endif  | 
164  |  |  | 
165  |  | #if defined(MS_WINDOWS)  | 
166  |  | #  define TERMSIZE_USE_CONIO  | 
167  |  | #elif defined(HAVE_SYS_IOCTL_H)  | 
168  |  | #  include <sys/ioctl.h>  | 
169  |  | #  if defined(HAVE_TERMIOS_H)  | 
170  |  | #    include <termios.h>  | 
171  |  | #  endif  | 
172  |  | #  if defined(TIOCGWINSZ)  | 
173  |  | #    define TERMSIZE_USE_IOCTL  | 
174  |  | #  endif  | 
175  |  | #endif /* MS_WINDOWS */  | 
176  |  |  | 
177  |  | /* Various compilers have only certain posix functions */  | 
178  |  | /* XXX Gosh I wish these were all moved into pyconfig.h */  | 
179  |  | #if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */  | 
180  |  | #define HAVE_OPENDIR    1  | 
181  |  | #define HAVE_SYSTEM     1  | 
182  |  | #include <process.h>  | 
183  |  | #else  | 
184  |  | #ifdef _MSC_VER         /* Microsoft compiler */  | 
185  |  | #define HAVE_GETPPID    1  | 
186  |  | #define HAVE_GETLOGIN   1  | 
187  |  | #define HAVE_SPAWNV     1  | 
188  |  | #define HAVE_EXECV      1  | 
189  |  | #define HAVE_WSPAWNV    1  | 
190  |  | #define HAVE_WEXECV     1  | 
191  |  | #define HAVE_PIPE       1  | 
192  |  | #define HAVE_SYSTEM     1  | 
193  |  | #define HAVE_CWAIT      1  | 
194  |  | #define HAVE_FSYNC      1  | 
195  |  | #define fsync _commit  | 
196  |  | #else  | 
197  |  | /* Unix functions that the configure script doesn't check for */  | 
198  |  | #ifndef __VXWORKS__  | 
199  |  | #define HAVE_EXECV      1  | 
200  |  | #define HAVE_FORK       1  | 
201  |  | #if defined(__USLC__) && defined(__SCO_VERSION__)       /* SCO UDK Compiler */  | 
202  |  | #define HAVE_FORK1      1  | 
203  |  | #endif  | 
204  |  | #endif  | 
205  |  | #define HAVE_GETEGID    1  | 
206  |  | #define HAVE_GETEUID    1  | 
207  |  | #define HAVE_GETGID     1  | 
208  |  | #define HAVE_GETPPID    1  | 
209  |  | #define HAVE_GETUID     1  | 
210  |  | #define HAVE_KILL       1  | 
211  |  | #define HAVE_OPENDIR    1  | 
212  |  | #define HAVE_PIPE       1  | 
213  |  | #define HAVE_SYSTEM     1  | 
214  |  | #define HAVE_WAIT       1  | 
215  |  | #define HAVE_TTYNAME    1  | 
216  |  | #endif  /* _MSC_VER */  | 
217  |  | #endif  /* ! __WATCOMC__ || __QNX__ */  | 
218  |  |  | 
219  |  |  | 
220  |  | /*[clinic input]  | 
221  |  | # one of the few times we lie about this name!  | 
222  |  | module os  | 
223  |  | [clinic start generated code]*/  | 
224  |  | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/  | 
225  |  |  | 
226  |  | #ifndef _MSC_VER  | 
227  |  |  | 
228  |  | #if defined(__sgi)&&_COMPILER_VERSION>=700  | 
229  |  | /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode  | 
230  |  |    (default) */  | 
231  |  | extern char        *ctermid_r(char *);  | 
232  |  | #endif  | 
233  |  |  | 
234  |  | #endif /* !_MSC_VER */  | 
235  |  |  | 
236  |  | #if defined(__VXWORKS__)  | 
237  |  | #include <vxCpuLib.h>  | 
238  |  | #include <rtpLib.h>  | 
239  |  | #include <wait.h>  | 
240  |  | #include <taskLib.h>  | 
241  |  | #ifndef _P_WAIT  | 
242  |  | #define _P_WAIT          0  | 
243  |  | #define _P_NOWAIT        1  | 
244  |  | #define _P_NOWAITO       1  | 
245  |  | #endif  | 
246  |  | #endif /* __VXWORKS__ */  | 
247  |  |  | 
248  |  | #ifdef HAVE_POSIX_SPAWN  | 
249  |  | #include <spawn.h>  | 
250  |  | #endif  | 
251  |  |  | 
252  |  | #ifdef HAVE_UTIME_H  | 
253  |  | #include <utime.h>  | 
254  |  | #endif /* HAVE_UTIME_H */  | 
255  |  |  | 
256  |  | #ifdef HAVE_SYS_UTIME_H  | 
257  |  | #include <sys/utime.h>  | 
258  |  | #define HAVE_UTIME_H /* pretend we do for the rest of this file */  | 
259  |  | #endif /* HAVE_SYS_UTIME_H */  | 
260  |  |  | 
261  |  | #ifdef HAVE_SYS_TIMES_H  | 
262  |  | #include <sys/times.h>  | 
263  |  | #endif /* HAVE_SYS_TIMES_H */  | 
264  |  |  | 
265  |  | #ifdef HAVE_SYS_PARAM_H  | 
266  |  | #include <sys/param.h>  | 
267  |  | #endif /* HAVE_SYS_PARAM_H */  | 
268  |  |  | 
269  |  | #ifdef HAVE_SYS_UTSNAME_H  | 
270  |  | #include <sys/utsname.h>  | 
271  |  | #endif /* HAVE_SYS_UTSNAME_H */  | 
272  |  |  | 
273  |  | #ifdef HAVE_DIRENT_H  | 
274  |  | #include <dirent.h>  | 
275  | 4.71k  | #define NAMLEN(dirent) strlen((dirent)->d_name)  | 
276  |  | #else  | 
277  |  | #if defined(__WATCOMC__) && !defined(__QNX__)  | 
278  |  | #include <direct.h>  | 
279  |  | #define NAMLEN(dirent) strlen((dirent)->d_name)  | 
280  |  | #else  | 
281  |  | #define dirent direct  | 
282  |  | #define NAMLEN(dirent) (dirent)->d_namlen  | 
283  |  | #endif  | 
284  |  | #ifdef HAVE_SYS_NDIR_H  | 
285  |  | #include <sys/ndir.h>  | 
286  |  | #endif  | 
287  |  | #ifdef HAVE_SYS_DIR_H  | 
288  |  | #include <sys/dir.h>  | 
289  |  | #endif  | 
290  |  | #ifdef HAVE_NDIR_H  | 
291  |  | #include <ndir.h>  | 
292  |  | #endif  | 
293  |  | #endif  | 
294  |  |  | 
295  |  | #ifdef _MSC_VER  | 
296  |  | #ifdef HAVE_DIRECT_H  | 
297  |  | #include <direct.h>  | 
298  |  | #endif  | 
299  |  | #ifdef HAVE_IO_H  | 
300  |  | #include <io.h>  | 
301  |  | #endif  | 
302  |  | #ifdef HAVE_PROCESS_H  | 
303  |  | #include <process.h>  | 
304  |  | #endif  | 
305  |  | #ifndef IO_REPARSE_TAG_SYMLINK  | 
306  |  | #define IO_REPARSE_TAG_SYMLINK (0xA000000CL)  | 
307  |  | #endif  | 
308  |  | #ifndef IO_REPARSE_TAG_MOUNT_POINT  | 
309  |  | #define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)  | 
310  |  | #endif  | 
311  |  | #include "osdefs.h"  | 
312  |  | #include <malloc.h>  | 
313  |  | #include <windows.h>  | 
314  |  | #include <shellapi.h>   /* for ShellExecute() */  | 
315  |  | #include <lmcons.h>     /* for UNLEN */  | 
316  |  | #define HAVE_SYMLINK  | 
317  |  | #endif /* _MSC_VER */  | 
318  |  |  | 
319  |  | #ifndef MAXPATHLEN  | 
320  |  | #if defined(PATH_MAX) && PATH_MAX > 1024  | 
321  |  | #define MAXPATHLEN PATH_MAX  | 
322  |  | #else  | 
323  |  | #define MAXPATHLEN 1024  | 
324  |  | #endif  | 
325  |  | #endif /* MAXPATHLEN */  | 
326  |  |  | 
327  |  | #ifdef UNION_WAIT  | 
328  |  | /* Emulate some macros on systems that have a union instead of macros */  | 
329  |  |  | 
330  |  | #ifndef WIFEXITED  | 
331  |  | #define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)  | 
332  |  | #endif  | 
333  |  |  | 
334  |  | #ifndef WEXITSTATUS  | 
335  |  | #define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)  | 
336  |  | #endif  | 
337  |  |  | 
338  |  | #ifndef WTERMSIG  | 
339  |  | #define WTERMSIG(u_wait) ((u_wait).w_termsig)  | 
340  |  | #endif  | 
341  |  |  | 
342  |  | #define WAIT_TYPE union wait  | 
343  |  | #define WAIT_STATUS_INT(s) (s.w_status)  | 
344  |  |  | 
345  |  | #else /* !UNION_WAIT */  | 
346  | 0  | #define WAIT_TYPE int  | 
347  | 0  | #define WAIT_STATUS_INT(s) (s)  | 
348  |  | #endif /* UNION_WAIT */  | 
349  |  |  | 
350  |  | /* Don't use the "_r" form if we don't need it (also, won't have a  | 
351  |  |    prototype for it, at least on Solaris -- maybe others as well?). */  | 
352  |  | #if defined(HAVE_CTERMID_R)  | 
353  |  | #define USE_CTERMID_R  | 
354  |  | #endif  | 
355  |  |  | 
356  |  | /* choose the appropriate stat and fstat functions and return structs */  | 
357  |  | #undef STAT  | 
358  |  | #undef FSTAT  | 
359  |  | #undef STRUCT_STAT  | 
360  |  | #ifdef MS_WINDOWS  | 
361  |  | #       define STAT win32_stat  | 
362  |  | #       define LSTAT win32_lstat  | 
363  |  | #       define FSTAT _Py_fstat_noraise  | 
364  |  | #       define STRUCT_STAT struct _Py_stat_struct  | 
365  |  | #else  | 
366  | 1.08k  | #       define STAT stat  | 
367  | 0  | #       define LSTAT lstat  | 
368  | 0  | #       define FSTAT fstat  | 
369  | 1.08k  | #       define STRUCT_STAT struct stat  | 
370  |  | #endif  | 
371  |  |  | 
372  |  | #if defined(MAJOR_IN_MKDEV)  | 
373  |  | #include <sys/mkdev.h>  | 
374  |  | #else  | 
375  |  | #if defined(MAJOR_IN_SYSMACROS)  | 
376  |  | #include <sys/sysmacros.h>  | 
377  |  | #endif  | 
378  |  | #if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)  | 
379  |  | #include <sys/mkdev.h>  | 
380  |  | #endif  | 
381  |  | #endif  | 
382  |  |  | 
383  |  | #ifdef MS_WINDOWS  | 
384  |  | #define INITFUNC PyInit_nt  | 
385  |  | #define MODNAME "nt"  | 
386  |  | #else  | 
387  |  | #define INITFUNC PyInit_posix  | 
388  | 56  | #define MODNAME "posix"  | 
389  |  | #endif  | 
390  |  |  | 
391  |  | #if defined(__sun)  | 
392  |  | /* Something to implement in autoconf, not present in autoconf 2.69 */  | 
393  |  | #define HAVE_STRUCT_STAT_ST_FSTYPE 1  | 
394  |  | #endif  | 
395  |  |  | 
396  |  | /* memfd_create is either defined in sys/mman.h or sys/memfd.h  | 
397  |  |  * linux/memfd.h defines additional flags  | 
398  |  |  */  | 
399  |  | #ifdef HAVE_SYS_MMAN_H  | 
400  |  | #include <sys/mman.h>  | 
401  |  | #endif  | 
402  |  | #ifdef HAVE_SYS_MEMFD_H  | 
403  |  | #include <sys/memfd.h>  | 
404  |  | #endif  | 
405  |  | #ifdef HAVE_LINUX_MEMFD_H  | 
406  |  | #include <linux/memfd.h>  | 
407  |  | #endif  | 
408  |  |  | 
409  |  | #ifdef _Py_MEMORY_SANITIZER  | 
410  |  | # include <sanitizer/msan_interface.h>  | 
411  |  | #endif  | 
412  |  |  | 
413  |  | #ifdef HAVE_FORK  | 
414  |  | static void  | 
415  |  | run_at_forkers(PyObject *lst, int reverse)  | 
416  | 0  | { | 
417  | 0  |     Py_ssize_t i;  | 
418  | 0  |     PyObject *cpy;  | 
419  |  | 
  | 
420  | 0  |     if (lst != NULL) { | 
421  | 0  |         assert(PyList_CheckExact(lst));  | 
422  |  |  | 
423  |  |         /* Use a list copy in case register_at_fork() is called from  | 
424  |  |          * one of the callbacks.  | 
425  |  |          */  | 
426  | 0  |         cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));  | 
427  | 0  |         if (cpy == NULL)  | 
428  | 0  |             PyErr_WriteUnraisable(lst);  | 
429  | 0  |         else { | 
430  | 0  |             if (reverse)  | 
431  | 0  |                 PyList_Reverse(cpy);  | 
432  | 0  |             for (i = 0; i < PyList_GET_SIZE(cpy); i++) { | 
433  | 0  |                 PyObject *func, *res;  | 
434  | 0  |                 func = PyList_GET_ITEM(cpy, i);  | 
435  | 0  |                 res = PyObject_CallObject(func, NULL);  | 
436  | 0  |                 if (res == NULL)  | 
437  | 0  |                     PyErr_WriteUnraisable(func);  | 
438  | 0  |                 else  | 
439  | 0  |                     Py_DECREF(res);  | 
440  | 0  |             }  | 
441  | 0  |             Py_DECREF(cpy);  | 
442  | 0  |         }  | 
443  | 0  |     }  | 
444  | 0  | }  | 
445  |  |  | 
446  |  | void  | 
447  |  | PyOS_BeforeFork(void)  | 
448  | 0  | { | 
449  | 0  |     run_at_forkers(_PyInterpreterState_Get()->before_forkers, 1);  | 
450  |  | 
  | 
451  | 0  |     _PyImport_AcquireLock();  | 
452  | 0  | }  | 
453  |  |  | 
454  |  | void  | 
455  |  | PyOS_AfterFork_Parent(void)  | 
456  | 0  | { | 
457  | 0  |     if (_PyImport_ReleaseLock() <= 0)  | 
458  | 0  |         Py_FatalError("failed releasing import lock after fork"); | 
459  |  |  | 
460  | 0  |     run_at_forkers(_PyInterpreterState_Get()->after_forkers_parent, 0);  | 
461  | 0  | }  | 
462  |  |  | 
463  |  | void  | 
464  |  | PyOS_AfterFork_Child(void)  | 
465  | 0  | { | 
466  | 0  |     _PyRuntimeState *runtime = &_PyRuntime;  | 
467  | 0  |     _PyGILState_Reinit(runtime);  | 
468  | 0  |     _PyEval_ReInitThreads(runtime);  | 
469  | 0  |     _PyImport_ReInitLock();  | 
470  | 0  |     _PySignal_AfterFork();  | 
471  | 0  |     _PyRuntimeState_ReInitThreads(runtime);  | 
472  | 0  |     _PyInterpreterState_DeleteExceptMain(runtime);  | 
473  |  | 
  | 
474  | 0  |     run_at_forkers(_PyInterpreterState_Get()->after_forkers_child, 0);  | 
475  | 0  | }  | 
476  |  |  | 
477  |  | static int  | 
478  |  | register_at_forker(PyObject **lst, PyObject *func)  | 
479  | 6  | { | 
480  | 6  |     if (func == NULL)  /* nothing to register? do nothing. */  | 
481  | 2  |         return 0;  | 
482  | 4  |     if (*lst == NULL) { | 
483  | 3  |         *lst = PyList_New(0);  | 
484  | 3  |         if (*lst == NULL)  | 
485  | 0  |             return -1;  | 
486  | 3  |     }  | 
487  | 4  |     return PyList_Append(*lst, func);  | 
488  | 4  | }  | 
489  |  | #endif  | 
490  |  |  | 
491  |  | /* Legacy wrapper */  | 
492  |  | void  | 
493  |  | PyOS_AfterFork(void)  | 
494  | 0  | { | 
495  | 0  | #ifdef HAVE_FORK  | 
496  | 0  |     PyOS_AfterFork_Child();  | 
497  | 0  | #endif  | 
498  | 0  | }  | 
499  |  |  | 
500  |  |  | 
501  |  | #ifdef MS_WINDOWS  | 
502  |  | /* defined in fileutils.c */  | 
503  |  | void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);  | 
504  |  | void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,  | 
505  |  |                                             ULONG, struct _Py_stat_struct *);  | 
506  |  | #endif  | 
507  |  |  | 
508  |  |  | 
509  |  | #ifndef MS_WINDOWS  | 
510  |  | PyObject *  | 
511  |  | _PyLong_FromUid(uid_t uid)  | 
512  | 854  | { | 
513  | 854  |     if (uid == (uid_t)-1)  | 
514  | 0  |         return PyLong_FromLong(-1);  | 
515  | 854  |     return PyLong_FromUnsignedLong(uid);  | 
516  | 854  | }  | 
517  |  |  | 
518  |  | PyObject *  | 
519  |  | _PyLong_FromGid(gid_t gid)  | 
520  | 854  | { | 
521  | 854  |     if (gid == (gid_t)-1)  | 
522  | 0  |         return PyLong_FromLong(-1);  | 
523  | 854  |     return PyLong_FromUnsignedLong(gid);  | 
524  | 854  | }  | 
525  |  |  | 
526  |  | int  | 
527  |  | _Py_Uid_Converter(PyObject *obj, void *p)  | 
528  | 0  | { | 
529  | 0  |     uid_t uid;  | 
530  | 0  |     PyObject *index;  | 
531  | 0  |     int overflow;  | 
532  | 0  |     long result;  | 
533  | 0  |     unsigned long uresult;  | 
534  |  | 
  | 
535  | 0  |     index = PyNumber_Index(obj);  | 
536  | 0  |     if (index == NULL) { | 
537  | 0  |         PyErr_Format(PyExc_TypeError,  | 
538  | 0  |                      "uid should be integer, not %.200s",  | 
539  | 0  |                      Py_TYPE(obj)->tp_name);  | 
540  | 0  |         return 0;  | 
541  | 0  |     }  | 
542  |  |  | 
543  |  |     /*  | 
544  |  |      * Handling uid_t is complicated for two reasons:  | 
545  |  |      *  * Although uid_t is (always?) unsigned, it still  | 
546  |  |      *    accepts -1.  | 
547  |  |      *  * We don't know its size in advance--it may be  | 
548  |  |      *    bigger than an int, or it may be smaller than  | 
549  |  |      *    a long.  | 
550  |  |      *  | 
551  |  |      * So a bit of defensive programming is in order.  | 
552  |  |      * Start with interpreting the value passed  | 
553  |  |      * in as a signed long and see if it works.  | 
554  |  |      */  | 
555  |  |  | 
556  | 0  |     result = PyLong_AsLongAndOverflow(index, &overflow);  | 
557  |  | 
  | 
558  | 0  |     if (!overflow) { | 
559  | 0  |         uid = (uid_t)result;  | 
560  |  | 
  | 
561  | 0  |         if (result == -1) { | 
562  | 0  |             if (PyErr_Occurred())  | 
563  | 0  |                 goto fail;  | 
564  |  |             /* It's a legitimate -1, we're done. */  | 
565  | 0  |             goto success;  | 
566  | 0  |         }  | 
567  |  |  | 
568  |  |         /* Any other negative number is disallowed. */  | 
569  | 0  |         if (result < 0)  | 
570  | 0  |             goto underflow;  | 
571  |  |  | 
572  |  |         /* Ensure the value wasn't truncated. */  | 
573  | 0  |         if (sizeof(uid_t) < sizeof(long) &&  | 
574  | 0  |             (long)uid != result)  | 
575  | 0  |             goto underflow;  | 
576  | 0  |         goto success;  | 
577  | 0  |     }  | 
578  |  |  | 
579  | 0  |     if (overflow < 0)  | 
580  | 0  |         goto underflow;  | 
581  |  |  | 
582  |  |     /*  | 
583  |  |      * Okay, the value overflowed a signed long.  If it  | 
584  |  |      * fits in an *unsigned* long, it may still be okay,  | 
585  |  |      * as uid_t may be unsigned long on this platform.  | 
586  |  |      */  | 
587  | 0  |     uresult = PyLong_AsUnsignedLong(index);  | 
588  | 0  |     if (PyErr_Occurred()) { | 
589  | 0  |         if (PyErr_ExceptionMatches(PyExc_OverflowError))  | 
590  | 0  |             goto overflow;  | 
591  | 0  |         goto fail;  | 
592  | 0  |     }  | 
593  |  |  | 
594  | 0  |     uid = (uid_t)uresult;  | 
595  |  |  | 
596  |  |     /*  | 
597  |  |      * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,  | 
598  |  |      * but this value would get interpreted as (uid_t)-1  by chown  | 
599  |  |      * and its siblings.   That's not what the user meant!  So we  | 
600  |  |      * throw an overflow exception instead.   (We already  | 
601  |  |      * handled a real -1 with PyLong_AsLongAndOverflow() above.)  | 
602  |  |      */  | 
603  | 0  |     if (uid == (uid_t)-1)  | 
604  | 0  |         goto overflow;  | 
605  |  |  | 
606  |  |     /* Ensure the value wasn't truncated. */  | 
607  | 0  |     if (sizeof(uid_t) < sizeof(long) &&  | 
608  | 0  |         (unsigned long)uid != uresult)  | 
609  | 0  |         goto overflow;  | 
610  |  |     /* fallthrough */  | 
611  |  |  | 
612  | 0  | success:  | 
613  | 0  |     Py_DECREF(index);  | 
614  | 0  |     *(uid_t *)p = uid;  | 
615  | 0  |     return 1;  | 
616  |  |  | 
617  | 0  | underflow:  | 
618  | 0  |     PyErr_SetString(PyExc_OverflowError,  | 
619  | 0  |                     "uid is less than minimum");  | 
620  | 0  |     goto fail;  | 
621  |  |  | 
622  | 0  | overflow:  | 
623  | 0  |     PyErr_SetString(PyExc_OverflowError,  | 
624  | 0  |                     "uid is greater than maximum");  | 
625  |  |     /* fallthrough */  | 
626  |  | 
  | 
627  | 0  | fail:  | 
628  | 0  |     Py_DECREF(index);  | 
629  | 0  |     return 0;  | 
630  | 0  | }  | 
631  |  |  | 
632  |  | int  | 
633  |  | _Py_Gid_Converter(PyObject *obj, void *p)  | 
634  | 0  | { | 
635  | 0  |     gid_t gid;  | 
636  | 0  |     PyObject *index;  | 
637  | 0  |     int overflow;  | 
638  | 0  |     long result;  | 
639  | 0  |     unsigned long uresult;  | 
640  |  | 
  | 
641  | 0  |     index = PyNumber_Index(obj);  | 
642  | 0  |     if (index == NULL) { | 
643  | 0  |         PyErr_Format(PyExc_TypeError,  | 
644  | 0  |                      "gid should be integer, not %.200s",  | 
645  | 0  |                      Py_TYPE(obj)->tp_name);  | 
646  | 0  |         return 0;  | 
647  | 0  |     }  | 
648  |  |  | 
649  |  |     /*  | 
650  |  |      * Handling gid_t is complicated for two reasons:  | 
651  |  |      *  * Although gid_t is (always?) unsigned, it still  | 
652  |  |      *    accepts -1.  | 
653  |  |      *  * We don't know its size in advance--it may be  | 
654  |  |      *    bigger than an int, or it may be smaller than  | 
655  |  |      *    a long.  | 
656  |  |      *  | 
657  |  |      * So a bit of defensive programming is in order.  | 
658  |  |      * Start with interpreting the value passed  | 
659  |  |      * in as a signed long and see if it works.  | 
660  |  |      */  | 
661  |  |  | 
662  | 0  |     result = PyLong_AsLongAndOverflow(index, &overflow);  | 
663  |  | 
  | 
664  | 0  |     if (!overflow) { | 
665  | 0  |         gid = (gid_t)result;  | 
666  |  | 
  | 
667  | 0  |         if (result == -1) { | 
668  | 0  |             if (PyErr_Occurred())  | 
669  | 0  |                 goto fail;  | 
670  |  |             /* It's a legitimate -1, we're done. */  | 
671  | 0  |             goto success;  | 
672  | 0  |         }  | 
673  |  |  | 
674  |  |         /* Any other negative number is disallowed. */  | 
675  | 0  |         if (result < 0) { | 
676  | 0  |             goto underflow;  | 
677  | 0  |         }  | 
678  |  |  | 
679  |  |         /* Ensure the value wasn't truncated. */  | 
680  | 0  |         if (sizeof(gid_t) < sizeof(long) &&  | 
681  | 0  |             (long)gid != result)  | 
682  | 0  |             goto underflow;  | 
683  | 0  |         goto success;  | 
684  | 0  |     }  | 
685  |  |  | 
686  | 0  |     if (overflow < 0)  | 
687  | 0  |         goto underflow;  | 
688  |  |  | 
689  |  |     /*  | 
690  |  |      * Okay, the value overflowed a signed long.  If it  | 
691  |  |      * fits in an *unsigned* long, it may still be okay,  | 
692  |  |      * as gid_t may be unsigned long on this platform.  | 
693  |  |      */  | 
694  | 0  |     uresult = PyLong_AsUnsignedLong(index);  | 
695  | 0  |     if (PyErr_Occurred()) { | 
696  | 0  |         if (PyErr_ExceptionMatches(PyExc_OverflowError))  | 
697  | 0  |             goto overflow;  | 
698  | 0  |         goto fail;  | 
699  | 0  |     }  | 
700  |  |  | 
701  | 0  |     gid = (gid_t)uresult;  | 
702  |  |  | 
703  |  |     /*  | 
704  |  |      * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,  | 
705  |  |      * but this value would get interpreted as (gid_t)-1  by chown  | 
706  |  |      * and its siblings.   That's not what the user meant!  So we  | 
707  |  |      * throw an overflow exception instead.   (We already  | 
708  |  |      * handled a real -1 with PyLong_AsLongAndOverflow() above.)  | 
709  |  |      */  | 
710  | 0  |     if (gid == (gid_t)-1)  | 
711  | 0  |         goto overflow;  | 
712  |  |  | 
713  |  |     /* Ensure the value wasn't truncated. */  | 
714  | 0  |     if (sizeof(gid_t) < sizeof(long) &&  | 
715  | 0  |         (unsigned long)gid != uresult)  | 
716  | 0  |         goto overflow;  | 
717  |  |     /* fallthrough */  | 
718  |  |  | 
719  | 0  | success:  | 
720  | 0  |     Py_DECREF(index);  | 
721  | 0  |     *(gid_t *)p = gid;  | 
722  | 0  |     return 1;  | 
723  |  |  | 
724  | 0  | underflow:  | 
725  | 0  |     PyErr_SetString(PyExc_OverflowError,  | 
726  | 0  |                     "gid is less than minimum");  | 
727  | 0  |     goto fail;  | 
728  |  |  | 
729  | 0  | overflow:  | 
730  | 0  |     PyErr_SetString(PyExc_OverflowError,  | 
731  | 0  |                     "gid is greater than maximum");  | 
732  |  |     /* fallthrough */  | 
733  |  | 
  | 
734  | 0  | fail:  | 
735  | 0  |     Py_DECREF(index);  | 
736  | 0  |     return 0;  | 
737  | 0  | }  | 
738  |  | #endif /* MS_WINDOWS */  | 
739  |  |  | 
740  |  |  | 
741  | 0  | #define _PyLong_FromDev PyLong_FromLongLong  | 
742  |  |  | 
743  |  |  | 
744  |  | #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)  | 
745  |  | static int  | 
746  |  | _Py_Dev_Converter(PyObject *obj, void *p)  | 
747  | 0  | { | 
748  | 0  |     *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);  | 
749  | 0  |     if (PyErr_Occurred())  | 
750  | 0  |         return 0;  | 
751  | 0  |     return 1;  | 
752  | 0  | }  | 
753  |  | #endif /* HAVE_MKNOD && HAVE_MAKEDEV */  | 
754  |  |  | 
755  |  |  | 
756  |  | #ifdef AT_FDCWD  | 
757  |  | /*  | 
758  |  |  * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);  | 
759  |  |  * without the int cast, the value gets interpreted as uint (4291925331),  | 
760  |  |  * which doesn't play nicely with all the initializer lines in this file that  | 
761  |  |  * look like this:  | 
762  |  |  *      int dir_fd = DEFAULT_DIR_FD;  | 
763  |  |  */  | 
764  | 4.40k  | #define DEFAULT_DIR_FD (int)AT_FDCWD  | 
765  |  | #else  | 
766  |  | #define DEFAULT_DIR_FD (-100)  | 
767  |  | #endif  | 
768  |  |  | 
769  |  | static int  | 
770  |  | _fd_converter(PyObject *o, int *p)  | 
771  | 0  | { | 
772  | 0  |     int overflow;  | 
773  | 0  |     long long_value;  | 
774  |  | 
  | 
775  | 0  |     PyObject *index = PyNumber_Index(o);  | 
776  | 0  |     if (index == NULL) { | 
777  | 0  |         return 0;  | 
778  | 0  |     }  | 
779  |  |  | 
780  | 0  |     assert(PyLong_Check(index));  | 
781  | 0  |     long_value = PyLong_AsLongAndOverflow(index, &overflow);  | 
782  | 0  |     Py_DECREF(index);  | 
783  | 0  |     assert(!PyErr_Occurred());  | 
784  | 0  |     if (overflow > 0 || long_value > INT_MAX) { | 
785  | 0  |         PyErr_SetString(PyExc_OverflowError,  | 
786  | 0  |                         "fd is greater than maximum");  | 
787  | 0  |         return 0;  | 
788  | 0  |     }  | 
789  | 0  |     if (overflow < 0 || long_value < INT_MIN) { | 
790  | 0  |         PyErr_SetString(PyExc_OverflowError,  | 
791  | 0  |                         "fd is less than minimum");  | 
792  | 0  |         return 0;  | 
793  | 0  |     }  | 
794  |  |  | 
795  | 0  |     *p = (int)long_value;  | 
796  | 0  |     return 1;  | 
797  | 0  | }  | 
798  |  |  | 
799  |  | static int  | 
800  |  | dir_fd_converter(PyObject *o, void *p)  | 
801  | 28  | { | 
802  | 28  |     if (o == Py_None) { | 
803  | 28  |         *(int *)p = DEFAULT_DIR_FD;  | 
804  | 28  |         return 1;  | 
805  | 28  |     }  | 
806  | 0  |     else if (PyIndex_Check(o)) { | 
807  | 0  |         return _fd_converter(o, (int *)p);  | 
808  | 0  |     }  | 
809  | 0  |     else { | 
810  | 0  |         PyErr_Format(PyExc_TypeError,  | 
811  | 0  |                      "argument should be integer or None, not %.200s",  | 
812  | 0  |                      Py_TYPE(o)->tp_name);  | 
813  | 0  |         return 0;  | 
814  | 0  |     }  | 
815  | 28  | }  | 
816  |  |  | 
817  |  |  | 
818  |  | /*  | 
819  |  |  * A PyArg_ParseTuple "converter" function  | 
820  |  |  * that handles filesystem paths in the manner  | 
821  |  |  * preferred by the os module.  | 
822  |  |  *  | 
823  |  |  * path_converter accepts (Unicode) strings and their  | 
824  |  |  * subclasses, and bytes and their subclasses.  What  | 
825  |  |  * it does with the argument depends on the platform:  | 
826  |  |  *  | 
827  |  |  *   * On Windows, if we get a (Unicode) string we  | 
828  |  |  *     extract the wchar_t * and return it; if we get  | 
829  |  |  *     bytes we decode to wchar_t * and return that.  | 
830  |  |  *  | 
831  |  |  *   * On all other platforms, strings are encoded  | 
832  |  |  *     to bytes using PyUnicode_FSConverter, then we  | 
833  |  |  *     extract the char * from the bytes object and  | 
834  |  |  *     return that.  | 
835  |  |  *  | 
836  |  |  * path_converter also optionally accepts signed  | 
837  |  |  * integers (representing open file descriptors) instead  | 
838  |  |  * of path strings.  | 
839  |  |  *  | 
840  |  |  * Input fields:  | 
841  |  |  *   path.nullable  | 
842  |  |  *     If nonzero, the path is permitted to be None.  | 
843  |  |  *   path.allow_fd  | 
844  |  |  *     If nonzero, the path is permitted to be a file handle  | 
845  |  |  *     (a signed int) instead of a string.  | 
846  |  |  *   path.function_name  | 
847  |  |  *     If non-NULL, path_converter will use that as the name  | 
848  |  |  *     of the function in error messages.  | 
849  |  |  *     (If path.function_name is NULL it omits the function name.)  | 
850  |  |  *   path.argument_name  | 
851  |  |  *     If non-NULL, path_converter will use that as the name  | 
852  |  |  *     of the parameter in error messages.  | 
853  |  |  *     (If path.argument_name is NULL it uses "path".)  | 
854  |  |  *  | 
855  |  |  * Output fields:  | 
856  |  |  *   path.wide  | 
857  |  |  *     Points to the path if it was expressed as Unicode  | 
858  |  |  *     and was not encoded.  (Only used on Windows.)  | 
859  |  |  *   path.narrow  | 
860  |  |  *     Points to the path if it was expressed as bytes,  | 
861  |  |  *     or it was Unicode and was encoded to bytes. (On Windows,  | 
862  |  |  *     is a non-zero integer if the path was expressed as bytes.  | 
863  |  |  *     The type is deliberately incompatible to prevent misuse.)  | 
864  |  |  *   path.fd  | 
865  |  |  *     Contains a file descriptor if path.accept_fd was true  | 
866  |  |  *     and the caller provided a signed integer instead of any  | 
867  |  |  *     sort of string.  | 
868  |  |  *  | 
869  |  |  *     WARNING: if your "path" parameter is optional, and is  | 
870  |  |  *     unspecified, path_converter will never get called.  | 
871  |  |  *     So if you set allow_fd, you *MUST* initialize path.fd = -1  | 
872  |  |  *     yourself!  | 
873  |  |  *   path.length  | 
874  |  |  *     The length of the path in characters, if specified as  | 
875  |  |  *     a string.  | 
876  |  |  *   path.object  | 
877  |  |  *     The original object passed in (if get a PathLike object,  | 
878  |  |  *     the result of PyOS_FSPath() is treated as the original object).  | 
879  |  |  *     Own a reference to the object.  | 
880  |  |  *   path.cleanup  | 
881  |  |  *     For internal use only.  May point to a temporary object.  | 
882  |  |  *     (Pay no attention to the man behind the curtain.)  | 
883  |  |  *  | 
884  |  |  *   At most one of path.wide or path.narrow will be non-NULL.  | 
885  |  |  *   If path was None and path.nullable was set,  | 
886  |  |  *     or if path was an integer and path.allow_fd was set,  | 
887  |  |  *     both path.wide and path.narrow will be NULL  | 
888  |  |  *     and path.length will be 0.  | 
889  |  |  *  | 
890  |  |  *   path_converter takes care to not write to the path_t  | 
891  |  |  *   unless it's successful.  However it must reset the  | 
892  |  |  *   "cleanup" field each time it's called.  | 
893  |  |  *  | 
894  |  |  * Use as follows:  | 
895  |  |  *      path_t path;  | 
896  |  |  *      memset(&path, 0, sizeof(path));  | 
897  |  |  *      PyArg_ParseTuple(args, "O&", path_converter, &path);  | 
898  |  |  *      // ... use values from path ...  | 
899  |  |  *      path_cleanup(&path);  | 
900  |  |  *  | 
901  |  |  * (Note that if PyArg_Parse fails you don't need to call  | 
902  |  |  * path_cleanup().  However it is safe to do so.)  | 
903  |  |  */  | 
904  |  | typedef struct { | 
905  |  |     const char *function_name;  | 
906  |  |     const char *argument_name;  | 
907  |  |     int nullable;  | 
908  |  |     int allow_fd;  | 
909  |  |     const wchar_t *wide;  | 
910  |  | #ifdef MS_WINDOWS  | 
911  |  |     BOOL narrow;  | 
912  |  | #else  | 
913  |  |     const char *narrow;  | 
914  |  | #endif  | 
915  |  |     int fd;  | 
916  |  |     Py_ssize_t length;  | 
917  |  |     PyObject *object;  | 
918  |  |     PyObject *cleanup;  | 
919  |  | } path_t;  | 
920  |  |  | 
921  |  | #ifdef MS_WINDOWS  | 
922  |  | #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \  | 
923  |  |     {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL} | 
924  |  | #else  | 
925  |  | #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \  | 
926  | 1.11k  |     {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL} | 
927  |  | #endif  | 
928  |  |  | 
929  |  | static void  | 
930  |  | path_cleanup(path_t *path)  | 
931  | 1.11k  | { | 
932  | 1.11k  |     Py_CLEAR(path->object);  | 
933  | 1.11k  |     Py_CLEAR(path->cleanup);  | 
934  | 1.11k  | }  | 
935  |  |  | 
936  |  | static int  | 
937  |  | path_converter(PyObject *o, void *p)  | 
938  | 1.11k  | { | 
939  | 1.11k  |     path_t *path = (path_t *)p;  | 
940  | 1.11k  |     PyObject *bytes = NULL;  | 
941  | 1.11k  |     Py_ssize_t length = 0;  | 
942  | 1.11k  |     int is_index, is_buffer, is_bytes, is_unicode;  | 
943  | 1.11k  |     const char *narrow;  | 
944  |  | #ifdef MS_WINDOWS  | 
945  |  |     PyObject *wo = NULL;  | 
946  |  |     const wchar_t *wide;  | 
947  |  | #endif  | 
948  |  |  | 
949  | 1.11k  | #define FORMAT_EXCEPTION(exc, fmt) \  | 
950  | 1.11k  |     PyErr_Format(exc, "%s%s" fmt, \  | 
951  | 0  |         path->function_name ? path->function_name : "", \  | 
952  | 0  |         path->function_name ? ": "                : "", \  | 
953  | 0  |         path->argument_name ? path->argument_name : "path")  | 
954  |  |  | 
955  |  |     /* Py_CLEANUP_SUPPORTED support */  | 
956  | 1.11k  |     if (o == NULL) { | 
957  | 0  |         path_cleanup(path);  | 
958  | 0  |         return 1;  | 
959  | 0  |     }  | 
960  |  |  | 
961  |  |     /* Ensure it's always safe to call path_cleanup(). */  | 
962  | 1.11k  |     path->object = path->cleanup = NULL;  | 
963  |  |     /* path->object owns a reference to the original object */  | 
964  | 1.11k  |     Py_INCREF(o);  | 
965  |  |  | 
966  | 1.11k  |     if ((o == Py_None) && path->nullable) { | 
967  | 0  |         path->wide = NULL;  | 
968  |  | #ifdef MS_WINDOWS  | 
969  |  |         path->narrow = FALSE;  | 
970  |  | #else  | 
971  | 0  |         path->narrow = NULL;  | 
972  | 0  | #endif  | 
973  | 0  |         path->fd = -1;  | 
974  | 0  |         goto success_exit;  | 
975  | 0  |     }  | 
976  |  |  | 
977  |  |     /* Only call this here so that we don't treat the return value of  | 
978  |  |        os.fspath() as an fd or buffer. */  | 
979  | 1.11k  |     is_index = path->allow_fd && PyIndex_Check(o);  | 
980  | 1.11k  |     is_buffer = PyObject_CheckBuffer(o);  | 
981  | 1.11k  |     is_bytes = PyBytes_Check(o);  | 
982  | 1.11k  |     is_unicode = PyUnicode_Check(o);  | 
983  |  |  | 
984  | 1.11k  |     if (!is_index && !is_buffer && !is_unicode && !is_bytes) { | 
985  |  |         /* Inline PyOS_FSPath() for better error messages. */  | 
986  | 0  |         _Py_IDENTIFIER(__fspath__);  | 
987  | 0  |         PyObject *func, *res;  | 
988  |  | 
  | 
989  | 0  |         func = _PyObject_LookupSpecial(o, &PyId___fspath__);  | 
990  | 0  |         if (NULL == func) { | 
991  | 0  |             goto error_format;  | 
992  | 0  |         }  | 
993  | 0  |         res = _PyObject_CallNoArg(func);  | 
994  | 0  |         Py_DECREF(func);  | 
995  | 0  |         if (NULL == res) { | 
996  | 0  |             goto error_exit;  | 
997  | 0  |         }  | 
998  | 0  |         else if (PyUnicode_Check(res)) { | 
999  | 0  |             is_unicode = 1;  | 
1000  | 0  |         }  | 
1001  | 0  |         else if (PyBytes_Check(res)) { | 
1002  | 0  |             is_bytes = 1;  | 
1003  | 0  |         }  | 
1004  | 0  |         else { | 
1005  | 0  |             PyErr_Format(PyExc_TypeError,  | 
1006  | 0  |                  "expected %.200s.__fspath__() to return str or bytes, "  | 
1007  | 0  |                  "not %.200s", Py_TYPE(o)->tp_name,  | 
1008  | 0  |                  Py_TYPE(res)->tp_name);  | 
1009  | 0  |             Py_DECREF(res);  | 
1010  | 0  |             goto error_exit;  | 
1011  | 0  |         }  | 
1012  |  |  | 
1013  |  |         /* still owns a reference to the original object */  | 
1014  | 0  |         Py_DECREF(o);  | 
1015  | 0  |         o = res;  | 
1016  | 0  |     }  | 
1017  |  |  | 
1018  | 1.11k  |     if (is_unicode) { | 
1019  |  | #ifdef MS_WINDOWS  | 
1020  |  |         wide = PyUnicode_AsUnicodeAndSize(o, &length);  | 
1021  |  |         if (!wide) { | 
1022  |  |             goto error_exit;  | 
1023  |  |         }  | 
1024  |  |         if (length > 32767) { | 
1025  |  |             FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");  | 
1026  |  |             goto error_exit;  | 
1027  |  |         }  | 
1028  |  |         if (wcslen(wide) != length) { | 
1029  |  |             FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");  | 
1030  |  |             goto error_exit;  | 
1031  |  |         }  | 
1032  |  |  | 
1033  |  |         path->wide = wide;  | 
1034  |  |         path->narrow = FALSE;  | 
1035  |  |         path->fd = -1;  | 
1036  |  |         goto success_exit;  | 
1037  |  | #else  | 
1038  | 1.11k  |         if (!PyUnicode_FSConverter(o, &bytes)) { | 
1039  | 0  |             goto error_exit;  | 
1040  | 0  |         }  | 
1041  | 1.11k  | #endif  | 
1042  | 1.11k  |     }  | 
1043  | 0  |     else if (is_bytes) { | 
1044  | 0  |         bytes = o;  | 
1045  | 0  |         Py_INCREF(bytes);  | 
1046  | 0  |     }  | 
1047  | 0  |     else if (is_buffer) { | 
1048  |  |         /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code  | 
1049  |  |            after removing support of non-bytes buffer objects. */  | 
1050  | 0  |         if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,  | 
1051  | 0  |             "%s%s%s should be %s, not %.200s",  | 
1052  | 0  |             path->function_name ? path->function_name : "",  | 
1053  | 0  |             path->function_name ? ": "                : "",  | 
1054  | 0  |             path->argument_name ? path->argument_name : "path",  | 
1055  | 0  |             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "  | 
1056  | 0  |                                                "integer or None" :  | 
1057  | 0  |             path->allow_fd ? "string, bytes, os.PathLike or integer" :  | 
1058  | 0  |             path->nullable ? "string, bytes, os.PathLike or None" :  | 
1059  | 0  |                              "string, bytes or os.PathLike",  | 
1060  | 0  |             Py_TYPE(o)->tp_name)) { | 
1061  | 0  |             goto error_exit;  | 
1062  | 0  |         }  | 
1063  | 0  |         bytes = PyBytes_FromObject(o);  | 
1064  | 0  |         if (!bytes) { | 
1065  | 0  |             goto error_exit;  | 
1066  | 0  |         }  | 
1067  | 0  |     }  | 
1068  | 0  |     else if (is_index) { | 
1069  | 0  |         if (!_fd_converter(o, &path->fd)) { | 
1070  | 0  |             goto error_exit;  | 
1071  | 0  |         }  | 
1072  | 0  |         path->wide = NULL;  | 
1073  |  | #ifdef MS_WINDOWS  | 
1074  |  |         path->narrow = FALSE;  | 
1075  |  | #else  | 
1076  | 0  |         path->narrow = NULL;  | 
1077  | 0  | #endif  | 
1078  | 0  |         goto success_exit;  | 
1079  | 0  |     }  | 
1080  | 0  |     else { | 
1081  | 0  |  error_format:  | 
1082  | 0  |         PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",  | 
1083  | 0  |             path->function_name ? path->function_name : "",  | 
1084  | 0  |             path->function_name ? ": "                : "",  | 
1085  | 0  |             path->argument_name ? path->argument_name : "path",  | 
1086  | 0  |             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "  | 
1087  | 0  |                                                "integer or None" :  | 
1088  | 0  |             path->allow_fd ? "string, bytes, os.PathLike or integer" :  | 
1089  | 0  |             path->nullable ? "string, bytes, os.PathLike or None" :  | 
1090  | 0  |                              "string, bytes or os.PathLike",  | 
1091  | 0  |             Py_TYPE(o)->tp_name);  | 
1092  | 0  |         goto error_exit;  | 
1093  | 0  |     }  | 
1094  |  |  | 
1095  | 1.11k  |     length = PyBytes_GET_SIZE(bytes);  | 
1096  | 1.11k  |     narrow = PyBytes_AS_STRING(bytes);  | 
1097  | 1.11k  |     if ((size_t)length != strlen(narrow)) { | 
1098  | 0  |         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");  | 
1099  | 0  |         goto error_exit;  | 
1100  | 0  |     }  | 
1101  |  |  | 
1102  |  | #ifdef MS_WINDOWS  | 
1103  |  |     wo = PyUnicode_DecodeFSDefaultAndSize(  | 
1104  |  |         narrow,  | 
1105  |  |         length  | 
1106  |  |     );  | 
1107  |  |     if (!wo) { | 
1108  |  |         goto error_exit;  | 
1109  |  |     }  | 
1110  |  |  | 
1111  |  |     wide = PyUnicode_AsUnicodeAndSize(wo, &length);  | 
1112  |  |     if (!wide) { | 
1113  |  |         goto error_exit;  | 
1114  |  |     }  | 
1115  |  |     if (length > 32767) { | 
1116  |  |         FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");  | 
1117  |  |         goto error_exit;  | 
1118  |  |     }  | 
1119  |  |     if (wcslen(wide) != length) { | 
1120  |  |         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");  | 
1121  |  |         goto error_exit;  | 
1122  |  |     }  | 
1123  |  |     path->wide = wide;  | 
1124  |  |     path->narrow = TRUE;  | 
1125  |  |     path->cleanup = wo;  | 
1126  |  |     Py_DECREF(bytes);  | 
1127  |  | #else  | 
1128  | 1.11k  |     path->wide = NULL;  | 
1129  | 1.11k  |     path->narrow = narrow;  | 
1130  | 1.11k  |     if (bytes == o) { | 
1131  |  |         /* Still a reference owned by path->object, don't have to  | 
1132  |  |            worry about path->narrow is used after free. */  | 
1133  | 0  |         Py_DECREF(bytes);  | 
1134  | 0  |     }  | 
1135  | 1.11k  |     else { | 
1136  | 1.11k  |         path->cleanup = bytes;  | 
1137  | 1.11k  |     }  | 
1138  | 1.11k  | #endif  | 
1139  | 1.11k  |     path->fd = -1;  | 
1140  |  |  | 
1141  | 1.11k  |  success_exit:  | 
1142  | 1.11k  |     path->length = length;  | 
1143  | 1.11k  |     path->object = o;  | 
1144  | 1.11k  |     return Py_CLEANUP_SUPPORTED;  | 
1145  |  |  | 
1146  | 0  |  error_exit:  | 
1147  | 0  |     Py_XDECREF(o);  | 
1148  | 0  |     Py_XDECREF(bytes);  | 
1149  |  | #ifdef MS_WINDOWS  | 
1150  |  |     Py_XDECREF(wo);  | 
1151  |  | #endif  | 
1152  | 0  |     return 0;  | 
1153  | 1.11k  | }  | 
1154  |  |  | 
1155  |  | static void  | 
1156  |  | argument_unavailable_error(const char *function_name, const char *argument_name)  | 
1157  | 0  | { | 
1158  | 0  |     PyErr_Format(PyExc_NotImplementedError,  | 
1159  | 0  |         "%s%s%s unavailable on this platform",  | 
1160  | 0  |         (function_name != NULL) ? function_name : "",  | 
1161  | 0  |         (function_name != NULL) ? ": ": "",  | 
1162  | 0  |         argument_name);  | 
1163  | 0  | }  | 
1164  |  |  | 
1165  |  | static int  | 
1166  |  | dir_fd_unavailable(PyObject *o, void *p)  | 
1167  | 14  | { | 
1168  | 14  |     int dir_fd;  | 
1169  | 14  |     if (!dir_fd_converter(o, &dir_fd))  | 
1170  | 0  |         return 0;  | 
1171  | 14  |     if (dir_fd != DEFAULT_DIR_FD) { | 
1172  | 0  |         argument_unavailable_error(NULL, "dir_fd");  | 
1173  | 0  |         return 0;  | 
1174  | 0  |     }  | 
1175  | 14  |     *(int *)p = dir_fd;  | 
1176  | 14  |     return 1;  | 
1177  | 14  | }  | 
1178  |  |  | 
1179  |  | static int  | 
1180  |  | fd_specified(const char *function_name, int fd)  | 
1181  | 14  | { | 
1182  | 14  |     if (fd == -1)  | 
1183  | 14  |         return 0;  | 
1184  |  |  | 
1185  | 0  |     argument_unavailable_error(function_name, "fd");  | 
1186  | 0  |     return 1;  | 
1187  | 14  | }  | 
1188  |  |  | 
1189  |  | static int  | 
1190  |  | follow_symlinks_specified(const char *function_name, int follow_symlinks)  | 
1191  | 14  | { | 
1192  | 14  |     if (follow_symlinks)  | 
1193  | 14  |         return 0;  | 
1194  |  |  | 
1195  | 0  |     argument_unavailable_error(function_name, "follow_symlinks");  | 
1196  | 0  |     return 1;  | 
1197  | 14  | }  | 
1198  |  |  | 
1199  |  | static int  | 
1200  |  | path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)  | 
1201  | 1.08k  | { | 
1202  | 1.08k  |     if (!path->wide && (dir_fd != DEFAULT_DIR_FD)  | 
1203  | 0  | #ifndef MS_WINDOWS  | 
1204  | 0  |         && !path->narrow  | 
1205  | 1.08k  | #endif  | 
1206  | 1.08k  |     ) { | 
1207  | 0  |         PyErr_Format(PyExc_ValueError,  | 
1208  | 0  |                      "%s: can't specify dir_fd without matching path",  | 
1209  | 0  |                      function_name);  | 
1210  | 0  |         return 1;  | 
1211  | 0  |     }  | 
1212  | 1.08k  |     return 0;  | 
1213  | 1.08k  | }  | 
1214  |  |  | 
1215  |  | static int  | 
1216  |  | dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)  | 
1217  | 1.08k  | { | 
1218  | 1.08k  |     if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) { | 
1219  | 0  |         PyErr_Format(PyExc_ValueError,  | 
1220  | 0  |                      "%s: can't specify both dir_fd and fd",  | 
1221  | 0  |                      function_name);  | 
1222  | 0  |         return 1;  | 
1223  | 0  |     }  | 
1224  | 1.08k  |     return 0;  | 
1225  | 1.08k  | }  | 
1226  |  |  | 
1227  |  | static int  | 
1228  |  | fd_and_follow_symlinks_invalid(const char *function_name, int fd,  | 
1229  |  |                                int follow_symlinks)  | 
1230  | 1.08k  | { | 
1231  | 1.08k  |     if ((fd > 0) && (!follow_symlinks)) { | 
1232  | 0  |         PyErr_Format(PyExc_ValueError,  | 
1233  | 0  |                      "%s: cannot use fd and follow_symlinks together",  | 
1234  | 0  |                      function_name);  | 
1235  | 0  |         return 1;  | 
1236  | 0  |     }  | 
1237  | 1.08k  |     return 0;  | 
1238  | 1.08k  | }  | 
1239  |  |  | 
1240  |  | static int  | 
1241  |  | dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,  | 
1242  |  |                                    int follow_symlinks)  | 
1243  | 14  | { | 
1244  | 14  |     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { | 
1245  | 0  |         PyErr_Format(PyExc_ValueError,  | 
1246  | 0  |                      "%s: cannot use dir_fd and follow_symlinks together",  | 
1247  | 0  |                      function_name);  | 
1248  | 0  |         return 1;  | 
1249  | 0  |     }  | 
1250  | 14  |     return 0;  | 
1251  | 14  | }  | 
1252  |  |  | 
1253  |  | #ifdef MS_WINDOWS  | 
1254  |  |     typedef long long Py_off_t;  | 
1255  |  | #else  | 
1256  |  |     typedef off_t Py_off_t;  | 
1257  |  | #endif  | 
1258  |  |  | 
1259  |  | static int  | 
1260  |  | Py_off_t_converter(PyObject *arg, void *addr)  | 
1261  | 0  | { | 
1262  |  | #ifdef HAVE_LARGEFILE_SUPPORT  | 
1263  |  |     *((Py_off_t *)addr) = PyLong_AsLongLong(arg);  | 
1264  |  | #else  | 
1265  | 0  |     *((Py_off_t *)addr) = PyLong_AsLong(arg);  | 
1266  | 0  | #endif  | 
1267  | 0  |     if (PyErr_Occurred())  | 
1268  | 0  |         return 0;  | 
1269  | 0  |     return 1;  | 
1270  | 0  | }  | 
1271  |  |  | 
1272  |  | static PyObject *  | 
1273  |  | PyLong_FromPy_off_t(Py_off_t offset)  | 
1274  | 0  | { | 
1275  |  | #ifdef HAVE_LARGEFILE_SUPPORT  | 
1276  |  |     return PyLong_FromLongLong(offset);  | 
1277  |  | #else  | 
1278  | 0  |     return PyLong_FromLong(offset);  | 
1279  | 0  | #endif  | 
1280  | 0  | }  | 
1281  |  |  | 
1282  |  | #ifdef HAVE_SIGSET_T  | 
1283  |  | /* Convert an iterable of integers to a sigset.  | 
1284  |  |    Return 1 on success, return 0 and raise an exception on error. */  | 
1285  |  | int  | 
1286  |  | _Py_Sigset_Converter(PyObject *obj, void *addr)  | 
1287  | 0  | { | 
1288  | 0  |     sigset_t *mask = (sigset_t *)addr;  | 
1289  | 0  |     PyObject *iterator, *item;  | 
1290  | 0  |     long signum;  | 
1291  | 0  |     int overflow;  | 
1292  |  |  | 
1293  |  |     // The extra parens suppress the unreachable-code warning with clang on MacOS  | 
1294  | 0  |     if (sigemptyset(mask) < (0)) { | 
1295  |  |         /* Probably only if mask == NULL. */  | 
1296  | 0  |         PyErr_SetFromErrno(PyExc_OSError);  | 
1297  | 0  |         return 0;  | 
1298  | 0  |     }  | 
1299  |  |  | 
1300  | 0  |     iterator = PyObject_GetIter(obj);  | 
1301  | 0  |     if (iterator == NULL) { | 
1302  | 0  |         return 0;  | 
1303  | 0  |     }  | 
1304  |  |  | 
1305  | 0  |     while ((item = PyIter_Next(iterator)) != NULL) { | 
1306  | 0  |         signum = PyLong_AsLongAndOverflow(item, &overflow);  | 
1307  | 0  |         Py_DECREF(item);  | 
1308  | 0  |         if (signum <= 0 || signum >= NSIG) { | 
1309  | 0  |             if (overflow || signum != -1 || !PyErr_Occurred()) { | 
1310  | 0  |                 PyErr_Format(PyExc_ValueError,  | 
1311  | 0  |                              "signal number %ld out of range", signum);  | 
1312  | 0  |             }  | 
1313  | 0  |             goto error;  | 
1314  | 0  |         }  | 
1315  | 0  |         if (sigaddset(mask, (int)signum)) { | 
1316  | 0  |             if (errno != EINVAL) { | 
1317  |  |                 /* Probably impossible */  | 
1318  | 0  |                 PyErr_SetFromErrno(PyExc_OSError);  | 
1319  | 0  |                 goto error;  | 
1320  | 0  |             }  | 
1321  |  |             /* For backwards compatibility, allow idioms such as  | 
1322  |  |              * `range(1, NSIG)` but warn about invalid signal numbers  | 
1323  |  |              */  | 
1324  | 0  |             const char msg[] =  | 
1325  | 0  |                 "invalid signal number %ld, please use valid_signals()";  | 
1326  | 0  |             if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) { | 
1327  | 0  |                 goto error;  | 
1328  | 0  |             }  | 
1329  | 0  |         }  | 
1330  | 0  |     }  | 
1331  | 0  |     if (!PyErr_Occurred()) { | 
1332  | 0  |         Py_DECREF(iterator);  | 
1333  | 0  |         return 1;  | 
1334  | 0  |     }  | 
1335  |  |  | 
1336  | 0  | error:  | 
1337  | 0  |     Py_DECREF(iterator);  | 
1338  | 0  |     return 0;  | 
1339  | 0  | }  | 
1340  |  | #endif /* HAVE_SIGSET_T */  | 
1341  |  |  | 
1342  |  | #ifdef MS_WINDOWS  | 
1343  |  |  | 
1344  |  | static int  | 
1345  |  | win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)  | 
1346  |  | { | 
1347  |  |     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];  | 
1348  |  |     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;  | 
1349  |  |     DWORD n_bytes_returned;  | 
1350  |  |  | 
1351  |  |     if (0 == DeviceIoControl(  | 
1352  |  |         reparse_point_handle,  | 
1353  |  |         FSCTL_GET_REPARSE_POINT,  | 
1354  |  |         NULL, 0, /* in buffer */  | 
1355  |  |         target_buffer, sizeof(target_buffer),  | 
1356  |  |         &n_bytes_returned,  | 
1357  |  |         NULL)) /* we're not using OVERLAPPED_IO */  | 
1358  |  |         return FALSE;  | 
1359  |  |  | 
1360  |  |     if (reparse_tag)  | 
1361  |  |         *reparse_tag = rdb->ReparseTag;  | 
1362  |  |  | 
1363  |  |     return TRUE;  | 
1364  |  | }  | 
1365  |  |  | 
1366  |  | #endif /* MS_WINDOWS */  | 
1367  |  |  | 
1368  |  | /* Return a dictionary corresponding to the POSIX environment table */  | 
1369  |  | #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))  | 
1370  |  | /* On Darwin/MacOSX a shared library or framework has no access to  | 
1371  |  | ** environ directly, we must obtain it with _NSGetEnviron(). See also  | 
1372  |  | ** man environ(7).  | 
1373  |  | */  | 
1374  |  | #include <crt_externs.h>  | 
1375  |  | #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))  | 
1376  |  | extern char **environ;  | 
1377  |  | #endif /* !_MSC_VER */  | 
1378  |  |  | 
1379  |  | static PyObject *  | 
1380  |  | convertenviron(void)  | 
1381  | 14  | { | 
1382  | 14  |     PyObject *d;  | 
1383  |  | #ifdef MS_WINDOWS  | 
1384  |  |     wchar_t **e;  | 
1385  |  | #else  | 
1386  | 14  |     char **e;  | 
1387  | 14  | #endif  | 
1388  |  |  | 
1389  | 14  |     d = PyDict_New();  | 
1390  | 14  |     if (d == NULL)  | 
1391  | 0  |         return NULL;  | 
1392  |  | #ifdef MS_WINDOWS  | 
1393  |  |     /* _wenviron must be initialized in this way if the program is started  | 
1394  |  |        through main() instead of wmain(). */  | 
1395  |  |     _wgetenv(L"");  | 
1396  |  |     e = _wenviron;  | 
1397  |  | #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))  | 
1398  |  |     /* environ is not accessible as an extern in a shared object on OSX; use  | 
1399  |  |        _NSGetEnviron to resolve it. The value changes if you add environment  | 
1400  |  |        variables between calls to Py_Initialize, so don't cache the value. */  | 
1401  |  |     e = *_NSGetEnviron();  | 
1402  |  | #else  | 
1403  | 14  |     e = environ;  | 
1404  | 14  | #endif  | 
1405  | 14  |     if (e == NULL)  | 
1406  | 0  |         return d;  | 
1407  | 546  |     for (; *e != NULL; e++) { | 
1408  | 532  |         PyObject *k;  | 
1409  | 532  |         PyObject *v;  | 
1410  |  | #ifdef MS_WINDOWS  | 
1411  |  |         const wchar_t *p = wcschr(*e, L'=');  | 
1412  |  | #else  | 
1413  | 532  |         const char *p = strchr(*e, '=');  | 
1414  | 532  | #endif  | 
1415  | 532  |         if (p == NULL)  | 
1416  | 0  |             continue;  | 
1417  |  | #ifdef MS_WINDOWS  | 
1418  |  |         k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));  | 
1419  |  | #else  | 
1420  | 532  |         k = PyBytes_FromStringAndSize(*e, (int)(p-*e));  | 
1421  | 532  | #endif  | 
1422  | 532  |         if (k == NULL) { | 
1423  | 0  |             Py_DECREF(d);  | 
1424  | 0  |             return NULL;  | 
1425  | 0  |         }  | 
1426  |  | #ifdef MS_WINDOWS  | 
1427  |  |         v = PyUnicode_FromWideChar(p+1, wcslen(p+1));  | 
1428  |  | #else  | 
1429  | 532  |         v = PyBytes_FromStringAndSize(p+1, strlen(p+1));  | 
1430  | 532  | #endif  | 
1431  | 532  |         if (v == NULL) { | 
1432  | 0  |             Py_DECREF(k);  | 
1433  | 0  |             Py_DECREF(d);  | 
1434  | 0  |             return NULL;  | 
1435  | 0  |         }  | 
1436  | 532  |         if (PyDict_GetItemWithError(d, k) == NULL) { | 
1437  | 532  |             if (PyErr_Occurred() || PyDict_SetItem(d, k, v) != 0) { | 
1438  | 0  |                 Py_DECREF(v);  | 
1439  | 0  |                 Py_DECREF(k);  | 
1440  | 0  |                 Py_DECREF(d);  | 
1441  | 0  |                 return NULL;  | 
1442  | 0  |             }  | 
1443  | 532  |         }  | 
1444  | 532  |         Py_DECREF(k);  | 
1445  | 532  |         Py_DECREF(v);  | 
1446  | 532  |     }  | 
1447  | 14  |     return d;  | 
1448  | 14  | }  | 
1449  |  |  | 
1450  |  | /* Set a POSIX-specific error from errno, and return NULL */  | 
1451  |  |  | 
1452  |  | static PyObject *  | 
1453  |  | posix_error(void)  | 
1454  | 0  | { | 
1455  | 0  |     return PyErr_SetFromErrno(PyExc_OSError);  | 
1456  | 0  | }  | 
1457  |  |  | 
1458  |  | #ifdef MS_WINDOWS  | 
1459  |  | static PyObject *  | 
1460  |  | win32_error(const char* function, const char* filename)  | 
1461  |  | { | 
1462  |  |     /* XXX We should pass the function name along in the future.  | 
1463  |  |        (winreg.c also wants to pass the function name.)  | 
1464  |  |        This would however require an additional param to the  | 
1465  |  |        Windows error object, which is non-trivial.  | 
1466  |  |     */  | 
1467  |  |     errno = GetLastError();  | 
1468  |  |     if (filename)  | 
1469  |  |         return PyErr_SetFromWindowsErrWithFilename(errno, filename);  | 
1470  |  |     else  | 
1471  |  |         return PyErr_SetFromWindowsErr(errno);  | 
1472  |  | }  | 
1473  |  |  | 
1474  |  | static PyObject *  | 
1475  |  | win32_error_object_err(const char* function, PyObject* filename, DWORD err)  | 
1476  |  | { | 
1477  |  |     /* XXX - see win32_error for comments on 'function' */  | 
1478  |  |     if (filename)  | 
1479  |  |         return PyErr_SetExcFromWindowsErrWithFilenameObject(  | 
1480  |  |                     PyExc_OSError,  | 
1481  |  |                     err,  | 
1482  |  |                     filename);  | 
1483  |  |     else  | 
1484  |  |         return PyErr_SetFromWindowsErr(err);  | 
1485  |  | }  | 
1486  |  |  | 
1487  |  | static PyObject *  | 
1488  |  | win32_error_object(const char* function, PyObject* filename)  | 
1489  |  | { | 
1490  |  |     errno = GetLastError();  | 
1491  |  |     return win32_error_object_err(function, filename, errno);  | 
1492  |  | }  | 
1493  |  |  | 
1494  |  | #endif /* MS_WINDOWS */  | 
1495  |  |  | 
1496  |  | static PyObject *  | 
1497  |  | posix_path_object_error(PyObject *path)  | 
1498  | 230  | { | 
1499  | 230  |     return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);  | 
1500  | 230  | }  | 
1501  |  |  | 
1502  |  | static PyObject *  | 
1503  |  | path_object_error(PyObject *path)  | 
1504  | 230  | { | 
1505  |  | #ifdef MS_WINDOWS  | 
1506  |  |     return PyErr_SetExcFromWindowsErrWithFilenameObject(  | 
1507  |  |                 PyExc_OSError, 0, path);  | 
1508  |  | #else  | 
1509  | 230  |     return posix_path_object_error(path);  | 
1510  | 230  | #endif  | 
1511  | 230  | }  | 
1512  |  |  | 
1513  |  | static PyObject *  | 
1514  |  | path_object_error2(PyObject *path, PyObject *path2)  | 
1515  | 0  | { | 
1516  |  | #ifdef MS_WINDOWS  | 
1517  |  |     return PyErr_SetExcFromWindowsErrWithFilenameObjects(  | 
1518  |  |                 PyExc_OSError, 0, path, path2);  | 
1519  |  | #else  | 
1520  | 0  |     return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);  | 
1521  | 0  | #endif  | 
1522  | 0  | }  | 
1523  |  |  | 
1524  |  | static PyObject *  | 
1525  |  | path_error(path_t *path)  | 
1526  | 230  | { | 
1527  | 230  |     return path_object_error(path->object);  | 
1528  | 230  | }  | 
1529  |  |  | 
1530  |  | static PyObject *  | 
1531  |  | posix_path_error(path_t *path)  | 
1532  | 0  | { | 
1533  | 0  |     return posix_path_object_error(path->object);  | 
1534  | 0  | }  | 
1535  |  |  | 
1536  |  | static PyObject *  | 
1537  |  | path_error2(path_t *path, path_t *path2)  | 
1538  | 0  | { | 
1539  | 0  |     return path_object_error2(path->object, path2->object);  | 
1540  | 0  | }  | 
1541  |  |  | 
1542  |  |  | 
1543  |  | /* POSIX generic methods */  | 
1544  |  |  | 
1545  |  | static int  | 
1546  |  | fildes_converter(PyObject *o, void *p)  | 
1547  | 0  | { | 
1548  | 0  |     int fd;  | 
1549  | 0  |     int *pointer = (int *)p;  | 
1550  | 0  |     fd = PyObject_AsFileDescriptor(o);  | 
1551  | 0  |     if (fd < 0)  | 
1552  | 0  |         return 0;  | 
1553  | 0  |     *pointer = fd;  | 
1554  | 0  |     return 1;  | 
1555  | 0  | }  | 
1556  |  |  | 
1557  |  | static PyObject *  | 
1558  |  | posix_fildes_fd(int fd, int (*func)(int))  | 
1559  | 0  | { | 
1560  | 0  |     int res;  | 
1561  | 0  |     int async_err = 0;  | 
1562  |  | 
  | 
1563  | 0  |     do { | 
1564  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
1565  | 0  |         _Py_BEGIN_SUPPRESS_IPH  | 
1566  | 0  |         res = (*func)(fd);  | 
1567  | 0  |         _Py_END_SUPPRESS_IPH  | 
1568  | 0  |         Py_END_ALLOW_THREADS  | 
1569  | 0  |     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
1570  | 0  |     if (res != 0)  | 
1571  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
1572  | 0  |     Py_RETURN_NONE;  | 
1573  | 0  | }  | 
1574  |  |  | 
1575  |  |  | 
1576  |  | #ifdef MS_WINDOWS  | 
1577  |  | /* This is a reimplementation of the C library's chdir function,  | 
1578  |  |    but one that produces Win32 errors instead of DOS error codes.  | 
1579  |  |    chdir is essentially a wrapper around SetCurrentDirectory; however,  | 
1580  |  |    it also needs to set "magic" environment variables indicating  | 
1581  |  |    the per-drive current directory, which are of the form =<drive>: */  | 
1582  |  | static BOOL __stdcall  | 
1583  |  | win32_wchdir(LPCWSTR path)  | 
1584  |  | { | 
1585  |  |     wchar_t path_buf[MAX_PATH], *new_path = path_buf;  | 
1586  |  |     int result;  | 
1587  |  |     wchar_t env[4] = L"=x:";  | 
1588  |  |  | 
1589  |  |     if(!SetCurrentDirectoryW(path))  | 
1590  |  |         return FALSE;  | 
1591  |  |     result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);  | 
1592  |  |     if (!result)  | 
1593  |  |         return FALSE;  | 
1594  |  |     if (result > Py_ARRAY_LENGTH(path_buf)) { | 
1595  |  |         new_path = PyMem_RawMalloc(result * sizeof(wchar_t));  | 
1596  |  |         if (!new_path) { | 
1597  |  |             SetLastError(ERROR_OUTOFMEMORY);  | 
1598  |  |             return FALSE;  | 
1599  |  |         }  | 
1600  |  |         result = GetCurrentDirectoryW(result, new_path);  | 
1601  |  |         if (!result) { | 
1602  |  |             PyMem_RawFree(new_path);  | 
1603  |  |             return FALSE;  | 
1604  |  |         }  | 
1605  |  |     }  | 
1606  |  |     int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||  | 
1607  |  |                             wcsncmp(new_path, L"//", 2) == 0);  | 
1608  |  |     if (!is_unc_like_path) { | 
1609  |  |         env[1] = new_path[0];  | 
1610  |  |         result = SetEnvironmentVariableW(env, new_path);  | 
1611  |  |     }  | 
1612  |  |     if (new_path != path_buf)  | 
1613  |  |         PyMem_RawFree(new_path);  | 
1614  |  |     return result ? TRUE : FALSE;  | 
1615  |  | }  | 
1616  |  | #endif  | 
1617  |  |  | 
1618  |  | #ifdef MS_WINDOWS  | 
1619  |  | /* The CRT of Windows has a number of flaws wrt. its stat() implementation:  | 
1620  |  |    - time stamps are restricted to second resolution  | 
1621  |  |    - file modification times suffer from forth-and-back conversions between  | 
1622  |  |      UTC and local time  | 
1623  |  |    Therefore, we implement our own stat, based on the Win32 API directly.  | 
1624  |  | */  | 
1625  |  | #define HAVE_STAT_NSEC 1  | 
1626  |  | #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1  | 
1627  |  | #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1  | 
1628  |  |  | 
1629  |  | static void  | 
1630  |  | find_data_to_file_info(WIN32_FIND_DATAW *pFileData,  | 
1631  |  |                        BY_HANDLE_FILE_INFORMATION *info,  | 
1632  |  |                        ULONG *reparse_tag)  | 
1633  |  | { | 
1634  |  |     memset(info, 0, sizeof(*info));  | 
1635  |  |     info->dwFileAttributes = pFileData->dwFileAttributes;  | 
1636  |  |     info->ftCreationTime   = pFileData->ftCreationTime;  | 
1637  |  |     info->ftLastAccessTime = pFileData->ftLastAccessTime;  | 
1638  |  |     info->ftLastWriteTime  = pFileData->ftLastWriteTime;  | 
1639  |  |     info->nFileSizeHigh    = pFileData->nFileSizeHigh;  | 
1640  |  |     info->nFileSizeLow     = pFileData->nFileSizeLow;  | 
1641  |  | /*  info->nNumberOfLinks   = 1; */  | 
1642  |  |     if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)  | 
1643  |  |         *reparse_tag = pFileData->dwReserved0;  | 
1644  |  |     else  | 
1645  |  |         *reparse_tag = 0;  | 
1646  |  | }  | 
1647  |  |  | 
1648  |  | static BOOL  | 
1649  |  | attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)  | 
1650  |  | { | 
1651  |  |     HANDLE hFindFile;  | 
1652  |  |     WIN32_FIND_DATAW FileData;  | 
1653  |  |     hFindFile = FindFirstFileW(pszFile, &FileData);  | 
1654  |  |     if (hFindFile == INVALID_HANDLE_VALUE)  | 
1655  |  |         return FALSE;  | 
1656  |  |     FindClose(hFindFile);  | 
1657  |  |     find_data_to_file_info(&FileData, info, reparse_tag);  | 
1658  |  |     return TRUE;  | 
1659  |  | }  | 
1660  |  |  | 
1661  |  | static int  | 
1662  |  | win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,  | 
1663  |  |                  BOOL traverse)  | 
1664  |  | { | 
1665  |  |     HANDLE hFile;  | 
1666  |  |     BY_HANDLE_FILE_INFORMATION fileInfo;  | 
1667  |  |     FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 }; | 
1668  |  |     DWORD fileType, error;  | 
1669  |  |     BOOL isUnhandledTag = FALSE;  | 
1670  |  |     int retval = 0;  | 
1671  |  |  | 
1672  |  |     DWORD access = FILE_READ_ATTRIBUTES;  | 
1673  |  |     DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */  | 
1674  |  |     if (!traverse) { | 
1675  |  |         flags |= FILE_FLAG_OPEN_REPARSE_POINT;  | 
1676  |  |     }  | 
1677  |  |  | 
1678  |  |     hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);  | 
1679  |  |     if (hFile == INVALID_HANDLE_VALUE) { | 
1680  |  |         /* Either the path doesn't exist, or the caller lacks access. */  | 
1681  |  |         error = GetLastError();  | 
1682  |  |         switch (error) { | 
1683  |  |         case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */  | 
1684  |  |         case ERROR_SHARING_VIOLATION: /* It's a paging file. */  | 
1685  |  |             /* Try reading the parent directory. */  | 
1686  |  |             if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) { | 
1687  |  |                 /* Cannot read the parent directory. */  | 
1688  |  |                 SetLastError(error);  | 
1689  |  |                 return -1;  | 
1690  |  |             }  | 
1691  |  |             if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { | 
1692  |  |                 if (traverse ||  | 
1693  |  |                     !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { | 
1694  |  |                     /* The stat call has to traverse but cannot, so fail. */  | 
1695  |  |                     SetLastError(error);  | 
1696  |  |                     return -1;  | 
1697  |  |                 }  | 
1698  |  |             }  | 
1699  |  |             break;  | 
1700  |  |  | 
1701  |  |         case ERROR_INVALID_PARAMETER:  | 
1702  |  |             /* \\.\con requires read or write access. */  | 
1703  |  |             hFile = CreateFileW(path, access | GENERIC_READ,  | 
1704  |  |                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,  | 
1705  |  |                         OPEN_EXISTING, flags, NULL);  | 
1706  |  |             if (hFile == INVALID_HANDLE_VALUE) { | 
1707  |  |                 SetLastError(error);  | 
1708  |  |                 return -1;  | 
1709  |  |             }  | 
1710  |  |             break;  | 
1711  |  |  | 
1712  |  |         case ERROR_CANT_ACCESS_FILE:  | 
1713  |  |             /* bpo37834: open unhandled reparse points if traverse fails. */  | 
1714  |  |             if (traverse) { | 
1715  |  |                 traverse = FALSE;  | 
1716  |  |                 isUnhandledTag = TRUE;  | 
1717  |  |                 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,  | 
1718  |  |                             flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);  | 
1719  |  |             }  | 
1720  |  |             if (hFile == INVALID_HANDLE_VALUE) { | 
1721  |  |                 SetLastError(error);  | 
1722  |  |                 return -1;  | 
1723  |  |             }  | 
1724  |  |             break;  | 
1725  |  |  | 
1726  |  |         default:  | 
1727  |  |             return -1;  | 
1728  |  |         }  | 
1729  |  |     }  | 
1730  |  |  | 
1731  |  |     if (hFile != INVALID_HANDLE_VALUE) { | 
1732  |  |         /* Handle types other than files on disk. */  | 
1733  |  |         fileType = GetFileType(hFile);  | 
1734  |  |         if (fileType != FILE_TYPE_DISK) { | 
1735  |  |             if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) { | 
1736  |  |                 retval = -1;  | 
1737  |  |                 goto cleanup;  | 
1738  |  |             }  | 
1739  |  |             DWORD fileAttributes = GetFileAttributesW(path);  | 
1740  |  |             memset(result, 0, sizeof(*result));  | 
1741  |  |             if (fileAttributes != INVALID_FILE_ATTRIBUTES &&  | 
1742  |  |                 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) { | 
1743  |  |                 /* \\.\pipe\ or \\.\mailslot\ */  | 
1744  |  |                 result->st_mode = _S_IFDIR;  | 
1745  |  |             } else if (fileType == FILE_TYPE_CHAR) { | 
1746  |  |                 /* \\.\nul */  | 
1747  |  |                 result->st_mode = _S_IFCHR;  | 
1748  |  |             } else if (fileType == FILE_TYPE_PIPE) { | 
1749  |  |                 /* \\.\pipe\spam */  | 
1750  |  |                 result->st_mode = _S_IFIFO;  | 
1751  |  |             }  | 
1752  |  |             /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */  | 
1753  |  |             goto cleanup;  | 
1754  |  |         }  | 
1755  |  |  | 
1756  |  |         /* Query the reparse tag, and traverse a non-link. */  | 
1757  |  |         if (!traverse) { | 
1758  |  |             if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,  | 
1759  |  |                     &tagInfo, sizeof(tagInfo))) { | 
1760  |  |                 /* Allow devices that do not support FileAttributeTagInfo. */  | 
1761  |  |                 switch (GetLastError()) { | 
1762  |  |                 case ERROR_INVALID_PARAMETER:  | 
1763  |  |                 case ERROR_INVALID_FUNCTION:  | 
1764  |  |                 case ERROR_NOT_SUPPORTED:  | 
1765  |  |                     tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;  | 
1766  |  |                     tagInfo.ReparseTag = 0;  | 
1767  |  |                     break;  | 
1768  |  |                 default:  | 
1769  |  |                     retval = -1;  | 
1770  |  |                     goto cleanup;  | 
1771  |  |                 }  | 
1772  |  |             } else if (tagInfo.FileAttributes &  | 
1773  |  |                          FILE_ATTRIBUTE_REPARSE_POINT) { | 
1774  |  |                 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { | 
1775  |  |                     if (isUnhandledTag) { | 
1776  |  |                         /* Traversing previously failed for either this link  | 
1777  |  |                            or its target. */  | 
1778  |  |                         SetLastError(ERROR_CANT_ACCESS_FILE);  | 
1779  |  |                         retval = -1;  | 
1780  |  |                         goto cleanup;  | 
1781  |  |                     }  | 
1782  |  |                 /* Traverse a non-link, but not if traversing already failed  | 
1783  |  |                    for an unhandled tag. */  | 
1784  |  |                 } else if (!isUnhandledTag) { | 
1785  |  |                     CloseHandle(hFile);  | 
1786  |  |                     return win32_xstat_impl(path, result, TRUE);  | 
1787  |  |                 }  | 
1788  |  |             }  | 
1789  |  |         }  | 
1790  |  |  | 
1791  |  |         if (!GetFileInformationByHandle(hFile, &fileInfo)) { | 
1792  |  |             switch (GetLastError()) { | 
1793  |  |             case ERROR_INVALID_PARAMETER:  | 
1794  |  |             case ERROR_INVALID_FUNCTION:  | 
1795  |  |             case ERROR_NOT_SUPPORTED:  | 
1796  |  |                 /* Volumes and physical disks are block devices, e.g.  | 
1797  |  |                    \\.\C: and \\.\PhysicalDrive0. */  | 
1798  |  |                 memset(result, 0, sizeof(*result));  | 
1799  |  |                 result->st_mode = 0x6000; /* S_IFBLK */  | 
1800  |  |                 goto cleanup;  | 
1801  |  |             }  | 
1802  |  |             retval = -1;  | 
1803  |  |             goto cleanup;  | 
1804  |  |         }  | 
1805  |  |     }  | 
1806  |  |  | 
1807  |  |     _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);  | 
1808  |  |  | 
1809  |  |     if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { | 
1810  |  |         /* Fix the file execute permissions. This hack sets S_IEXEC if  | 
1811  |  |            the filename has an extension that is commonly used by files  | 
1812  |  |            that CreateProcessW can execute. A real implementation calls  | 
1813  |  |            GetSecurityInfo, OpenThreadToken/OpenProcessToken, and  | 
1814  |  |            AccessCheck to check for generic read, write, and execute  | 
1815  |  |            access. */  | 
1816  |  |         const wchar_t *fileExtension = wcsrchr(path, '.');  | 
1817  |  |         if (fileExtension) { | 
1818  |  |             if (_wcsicmp(fileExtension, L".exe") == 0 ||  | 
1819  |  |                 _wcsicmp(fileExtension, L".bat") == 0 ||  | 
1820  |  |                 _wcsicmp(fileExtension, L".cmd") == 0 ||  | 
1821  |  |                 _wcsicmp(fileExtension, L".com") == 0) { | 
1822  |  |                 result->st_mode |= 0111;  | 
1823  |  |             }  | 
1824  |  |         }  | 
1825  |  |     }  | 
1826  |  |  | 
1827  |  | cleanup:  | 
1828  |  |     if (hFile != INVALID_HANDLE_VALUE) { | 
1829  |  |         /* Preserve last error if we are failing */  | 
1830  |  |         error = retval ? GetLastError() : 0;  | 
1831  |  |         if (!CloseHandle(hFile)) { | 
1832  |  |             retval = -1;  | 
1833  |  |         } else if (retval) { | 
1834  |  |             /* Restore last error */  | 
1835  |  |             SetLastError(error);  | 
1836  |  |         }  | 
1837  |  |     }  | 
1838  |  |  | 
1839  |  |     return retval;  | 
1840  |  | }  | 
1841  |  |  | 
1842  |  | static int  | 
1843  |  | win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)  | 
1844  |  | { | 
1845  |  |     /* Protocol violation: we explicitly clear errno, instead of  | 
1846  |  |        setting it to a POSIX error. Callers should use GetLastError. */  | 
1847  |  |     int code = win32_xstat_impl(path, result, traverse);  | 
1848  |  |     errno = 0;  | 
1849  |  |     return code;  | 
1850  |  | }  | 
1851  |  | /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w  | 
1852  |  |  | 
1853  |  |    In Posix, stat automatically traverses symlinks and returns the stat  | 
1854  |  |    structure for the target.  In Windows, the equivalent GetFileAttributes by  | 
1855  |  |    default does not traverse symlinks and instead returns attributes for  | 
1856  |  |    the symlink.  | 
1857  |  |  | 
1858  |  |    Instead, we will open the file (which *does* traverse symlinks by default)  | 
1859  |  |    and GetFileInformationByHandle(). */  | 
1860  |  |  | 
1861  |  | static int  | 
1862  |  | win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)  | 
1863  |  | { | 
1864  |  |     return win32_xstat(path, result, FALSE);  | 
1865  |  | }  | 
1866  |  |  | 
1867  |  | static int  | 
1868  |  | win32_stat(const wchar_t* path, struct _Py_stat_struct *result)  | 
1869  |  | { | 
1870  |  |     return win32_xstat(path, result, TRUE);  | 
1871  |  | }  | 
1872  |  |  | 
1873  |  | #endif /* MS_WINDOWS */  | 
1874  |  |  | 
1875  |  | PyDoc_STRVAR(stat_result__doc__,  | 
1876  |  | "stat_result: Result from stat, fstat, or lstat.\n\n\  | 
1877  |  | This object may be accessed either as a tuple of\n\  | 
1878  |  |   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\  | 
1879  |  | or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\  | 
1880  |  | \n\  | 
1881  |  | Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\  | 
1882  |  | or st_flags, they are available as attributes only.\n\  | 
1883  |  | \n\  | 
1884  |  | See os.stat for more information.");  | 
1885  |  |  | 
1886  |  | static PyStructSequence_Field stat_result_fields[] = { | 
1887  |  |     {"st_mode",    "protection bits"}, | 
1888  |  |     {"st_ino",     "inode"}, | 
1889  |  |     {"st_dev",     "device"}, | 
1890  |  |     {"st_nlink",   "number of hard links"}, | 
1891  |  |     {"st_uid",     "user ID of owner"}, | 
1892  |  |     {"st_gid",     "group ID of owner"}, | 
1893  |  |     {"st_size",    "total size, in bytes"}, | 
1894  |  |     /* The NULL is replaced with PyStructSequence_UnnamedField later. */  | 
1895  |  |     {NULL,   "integer time of last access"}, | 
1896  |  |     {NULL,   "integer time of last modification"}, | 
1897  |  |     {NULL,   "integer time of last change"}, | 
1898  |  |     {"st_atime",   "time of last access"}, | 
1899  |  |     {"st_mtime",   "time of last modification"}, | 
1900  |  |     {"st_ctime",   "time of last change"}, | 
1901  |  |     {"st_atime_ns",   "time of last access in nanoseconds"}, | 
1902  |  |     {"st_mtime_ns",   "time of last modification in nanoseconds"}, | 
1903  |  |     {"st_ctime_ns",   "time of last change in nanoseconds"}, | 
1904  |  | #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE  | 
1905  |  |     {"st_blksize", "blocksize for filesystem I/O"}, | 
1906  |  | #endif  | 
1907  |  | #ifdef HAVE_STRUCT_STAT_ST_BLOCKS  | 
1908  |  |     {"st_blocks",  "number of blocks allocated"}, | 
1909  |  | #endif  | 
1910  |  | #ifdef HAVE_STRUCT_STAT_ST_RDEV  | 
1911  |  |     {"st_rdev",    "device type (if inode device)"}, | 
1912  |  | #endif  | 
1913  |  | #ifdef HAVE_STRUCT_STAT_ST_FLAGS  | 
1914  |  |     {"st_flags",   "user defined flags for file"}, | 
1915  |  | #endif  | 
1916  |  | #ifdef HAVE_STRUCT_STAT_ST_GEN  | 
1917  |  |     {"st_gen",    "generation number"}, | 
1918  |  | #endif  | 
1919  |  | #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME  | 
1920  |  |     {"st_birthtime",   "time of creation"}, | 
1921  |  | #endif  | 
1922  |  | #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES  | 
1923  |  |     {"st_file_attributes", "Windows file attribute bits"}, | 
1924  |  | #endif  | 
1925  |  | #ifdef HAVE_STRUCT_STAT_ST_FSTYPE  | 
1926  |  |     {"st_fstype",  "Type of filesystem"}, | 
1927  |  | #endif  | 
1928  |  | #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG  | 
1929  |  |     {"st_reparse_tag", "Windows reparse tag"}, | 
1930  |  | #endif  | 
1931  |  |     {0} | 
1932  |  | };  | 
1933  |  |  | 
1934  |  | #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE  | 
1935  |  | #define ST_BLKSIZE_IDX 16  | 
1936  |  | #else  | 
1937  |  | #define ST_BLKSIZE_IDX 15  | 
1938  |  | #endif  | 
1939  |  |  | 
1940  |  | #ifdef HAVE_STRUCT_STAT_ST_BLOCKS  | 
1941  |  | #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)  | 
1942  |  | #else  | 
1943  |  | #define ST_BLOCKS_IDX ST_BLKSIZE_IDX  | 
1944  |  | #endif  | 
1945  |  |  | 
1946  |  | #ifdef HAVE_STRUCT_STAT_ST_RDEV  | 
1947  |  | #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)  | 
1948  |  | #else  | 
1949  |  | #define ST_RDEV_IDX ST_BLOCKS_IDX  | 
1950  |  | #endif  | 
1951  |  |  | 
1952  |  | #ifdef HAVE_STRUCT_STAT_ST_FLAGS  | 
1953  |  | #define ST_FLAGS_IDX (ST_RDEV_IDX+1)  | 
1954  |  | #else  | 
1955  |  | #define ST_FLAGS_IDX ST_RDEV_IDX  | 
1956  |  | #endif  | 
1957  |  |  | 
1958  |  | #ifdef HAVE_STRUCT_STAT_ST_GEN  | 
1959  |  | #define ST_GEN_IDX (ST_FLAGS_IDX+1)  | 
1960  |  | #else  | 
1961  |  | #define ST_GEN_IDX ST_FLAGS_IDX  | 
1962  |  | #endif  | 
1963  |  |  | 
1964  |  | #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME  | 
1965  |  | #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)  | 
1966  |  | #else  | 
1967  |  | #define ST_BIRTHTIME_IDX ST_GEN_IDX  | 
1968  |  | #endif  | 
1969  |  |  | 
1970  |  | #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES  | 
1971  |  | #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)  | 
1972  |  | #else  | 
1973  |  | #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX  | 
1974  |  | #endif  | 
1975  |  |  | 
1976  |  | #ifdef HAVE_STRUCT_STAT_ST_FSTYPE  | 
1977  |  | #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)  | 
1978  |  | #else  | 
1979  |  | #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX  | 
1980  |  | #endif  | 
1981  |  |  | 
1982  |  | #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG  | 
1983  |  | #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)  | 
1984  |  | #else  | 
1985  |  | #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX  | 
1986  |  | #endif  | 
1987  |  |  | 
1988  |  | static PyStructSequence_Desc stat_result_desc = { | 
1989  |  |     "stat_result", /* name */  | 
1990  |  |     stat_result__doc__, /* doc */  | 
1991  |  |     stat_result_fields,  | 
1992  |  |     10  | 
1993  |  | };  | 
1994  |  |  | 
1995  |  | PyDoc_STRVAR(statvfs_result__doc__,  | 
1996  |  | "statvfs_result: Result from statvfs or fstatvfs.\n\n\  | 
1997  |  | This object may be accessed either as a tuple of\n\  | 
1998  |  |   (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\  | 
1999  |  | or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\  | 
2000  |  | \n\  | 
2001  |  | See os.statvfs for more information.");  | 
2002  |  |  | 
2003  |  | static PyStructSequence_Field statvfs_result_fields[] = { | 
2004  |  |     {"f_bsize",  }, | 
2005  |  |     {"f_frsize", }, | 
2006  |  |     {"f_blocks", }, | 
2007  |  |     {"f_bfree",  }, | 
2008  |  |     {"f_bavail", }, | 
2009  |  |     {"f_files",  }, | 
2010  |  |     {"f_ffree",  }, | 
2011  |  |     {"f_favail", }, | 
2012  |  |     {"f_flag",   }, | 
2013  |  |     {"f_namemax",}, | 
2014  |  |     {"f_fsid",   }, | 
2015  |  |     {0} | 
2016  |  | };  | 
2017  |  |  | 
2018  |  | static PyStructSequence_Desc statvfs_result_desc = { | 
2019  |  |     "statvfs_result", /* name */  | 
2020  |  |     statvfs_result__doc__, /* doc */  | 
2021  |  |     statvfs_result_fields,  | 
2022  |  |     10  | 
2023  |  | };  | 
2024  |  |  | 
2025  |  | #if defined(HAVE_WAITID) && !defined(__APPLE__)  | 
2026  |  | PyDoc_STRVAR(waitid_result__doc__,  | 
2027  |  | "waitid_result: Result from waitid.\n\n\  | 
2028  |  | This object may be accessed either as a tuple of\n\  | 
2029  |  |   (si_pid, si_uid, si_signo, si_status, si_code),\n\  | 
2030  |  | or via the attributes si_pid, si_uid, and so on.\n\  | 
2031  |  | \n\  | 
2032  |  | See os.waitid for more information.");  | 
2033  |  |  | 
2034  |  | static PyStructSequence_Field waitid_result_fields[] = { | 
2035  |  |     {"si_pid",  }, | 
2036  |  |     {"si_uid", }, | 
2037  |  |     {"si_signo", }, | 
2038  |  |     {"si_status",  }, | 
2039  |  |     {"si_code", }, | 
2040  |  |     {0} | 
2041  |  | };  | 
2042  |  |  | 
2043  |  | static PyStructSequence_Desc waitid_result_desc = { | 
2044  |  |     "waitid_result", /* name */  | 
2045  |  |     waitid_result__doc__, /* doc */  | 
2046  |  |     waitid_result_fields,  | 
2047  |  |     5  | 
2048  |  | };  | 
2049  |  | static PyTypeObject* WaitidResultType;  | 
2050  |  | #endif  | 
2051  |  |  | 
2052  |  | static int initialized;  | 
2053  |  | static PyTypeObject* StatResultType;  | 
2054  |  | static PyTypeObject* StatVFSResultType;  | 
2055  |  | #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)  | 
2056  |  | static PyTypeObject* SchedParamType;  | 
2057  |  | #endif  | 
2058  |  | static newfunc structseq_new;  | 
2059  |  |  | 
2060  |  | static PyObject *  | 
2061  |  | statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)  | 
2062  | 0  | { | 
2063  | 0  |     PyStructSequence *result;  | 
2064  | 0  |     int i;  | 
2065  |  | 
  | 
2066  | 0  |     result = (PyStructSequence*)structseq_new(type, args, kwds);  | 
2067  | 0  |     if (!result)  | 
2068  | 0  |         return NULL;  | 
2069  |  |     /* If we have been initialized from a tuple,  | 
2070  |  |        st_?time might be set to None. Initialize it  | 
2071  |  |        from the int slots.  */  | 
2072  | 0  |     for (i = 7; i <= 9; i++) { | 
2073  | 0  |         if (result->ob_item[i+3] == Py_None) { | 
2074  | 0  |             Py_DECREF(Py_None);  | 
2075  | 0  |             Py_INCREF(result->ob_item[i]);  | 
2076  | 0  |             result->ob_item[i+3] = result->ob_item[i];  | 
2077  | 0  |         }  | 
2078  | 0  |     }  | 
2079  | 0  |     return (PyObject*)result;  | 
2080  | 0  | }  | 
2081  |  |  | 
2082  |  |  | 
2083  |  | static PyObject *billion = NULL;  | 
2084  |  |  | 
2085  |  | static void  | 
2086  |  | fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)  | 
2087  | 2.56k  | { | 
2088  | 2.56k  |     PyObject *s = _PyLong_FromTime_t(sec);  | 
2089  | 2.56k  |     PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);  | 
2090  | 2.56k  |     PyObject *s_in_ns = NULL;  | 
2091  | 2.56k  |     PyObject *ns_total = NULL;  | 
2092  | 2.56k  |     PyObject *float_s = NULL;  | 
2093  |  |  | 
2094  | 2.56k  |     if (!(s && ns_fractional))  | 
2095  | 0  |         goto exit;  | 
2096  |  |  | 
2097  | 2.56k  |     s_in_ns = PyNumber_Multiply(s, billion);  | 
2098  | 2.56k  |     if (!s_in_ns)  | 
2099  | 0  |         goto exit;  | 
2100  |  |  | 
2101  | 2.56k  |     ns_total = PyNumber_Add(s_in_ns, ns_fractional);  | 
2102  | 2.56k  |     if (!ns_total)  | 
2103  | 0  |         goto exit;  | 
2104  |  |  | 
2105  | 2.56k  |     float_s = PyFloat_FromDouble(sec + 1e-9*nsec);  | 
2106  | 2.56k  |     if (!float_s) { | 
2107  | 0  |         goto exit;  | 
2108  | 0  |     }  | 
2109  |  |  | 
2110  | 2.56k  |     PyStructSequence_SET_ITEM(v, index, s);  | 
2111  | 2.56k  |     PyStructSequence_SET_ITEM(v, index+3, float_s);  | 
2112  | 2.56k  |     PyStructSequence_SET_ITEM(v, index+6, ns_total);  | 
2113  | 2.56k  |     s = NULL;  | 
2114  | 2.56k  |     float_s = NULL;  | 
2115  | 2.56k  |     ns_total = NULL;  | 
2116  | 2.56k  | exit:  | 
2117  | 2.56k  |     Py_XDECREF(s);  | 
2118  | 2.56k  |     Py_XDECREF(ns_fractional);  | 
2119  | 2.56k  |     Py_XDECREF(s_in_ns);  | 
2120  | 2.56k  |     Py_XDECREF(ns_total);  | 
2121  | 2.56k  |     Py_XDECREF(float_s);  | 
2122  | 2.56k  | }  | 
2123  |  |  | 
2124  |  | /* pack a system stat C structure into the Python stat tuple  | 
2125  |  |    (used by posix_stat() and posix_fstat()) */  | 
2126  |  | static PyObject*  | 
2127  |  | _pystat_fromstructstat(STRUCT_STAT *st)  | 
2128  | 854  | { | 
2129  | 854  |     unsigned long ansec, mnsec, cnsec;  | 
2130  | 854  |     PyObject *v = PyStructSequence_New(StatResultType);  | 
2131  | 854  |     if (v == NULL)  | 
2132  | 0  |         return NULL;  | 
2133  |  |  | 
2134  | 854  |     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));  | 
2135  | 854  |     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(st->st_ino));  | 
2136  | 854  |     PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));  | 
2137  |  | #ifdef MS_WINDOWS  | 
2138  |  |     PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));  | 
2139  |  | #else  | 
2140  | 854  |     PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));  | 
2141  | 854  | #endif  | 
2142  | 854  |     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));  | 
2143  |  | #if defined(MS_WINDOWS)  | 
2144  |  |     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));  | 
2145  |  |     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));  | 
2146  |  | #else  | 
2147  | 854  |     PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));  | 
2148  | 854  |     PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));  | 
2149  | 854  | #endif  | 
2150  | 854  |     Py_BUILD_ASSERT(sizeof(long long) >= sizeof(st->st_size));  | 
2151  | 854  |     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));  | 
2152  |  |  | 
2153  | 854  | #if defined(HAVE_STAT_TV_NSEC)  | 
2154  | 854  |     ansec = st->st_atim.tv_nsec;  | 
2155  | 854  |     mnsec = st->st_mtim.tv_nsec;  | 
2156  | 854  |     cnsec = st->st_ctim.tv_nsec;  | 
2157  |  | #elif defined(HAVE_STAT_TV_NSEC2)  | 
2158  |  |     ansec = st->st_atimespec.tv_nsec;  | 
2159  |  |     mnsec = st->st_mtimespec.tv_nsec;  | 
2160  |  |     cnsec = st->st_ctimespec.tv_nsec;  | 
2161  |  | #elif defined(HAVE_STAT_NSEC)  | 
2162  |  |     ansec = st->st_atime_nsec;  | 
2163  |  |     mnsec = st->st_mtime_nsec;  | 
2164  |  |     cnsec = st->st_ctime_nsec;  | 
2165  |  | #else  | 
2166  |  |     ansec = mnsec = cnsec = 0;  | 
2167  |  | #endif  | 
2168  | 854  |     fill_time(v, 7, st->st_atime, ansec);  | 
2169  | 854  |     fill_time(v, 8, st->st_mtime, mnsec);  | 
2170  | 854  |     fill_time(v, 9, st->st_ctime, cnsec);  | 
2171  |  |  | 
2172  | 854  | #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE  | 
2173  | 854  |     PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,  | 
2174  | 854  |                               PyLong_FromLong((long)st->st_blksize));  | 
2175  | 854  | #endif  | 
2176  | 854  | #ifdef HAVE_STRUCT_STAT_ST_BLOCKS  | 
2177  | 854  |     PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,  | 
2178  | 854  |                               PyLong_FromLong((long)st->st_blocks));  | 
2179  | 854  | #endif  | 
2180  | 854  | #ifdef HAVE_STRUCT_STAT_ST_RDEV  | 
2181  | 854  |     PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,  | 
2182  | 854  |                               PyLong_FromLong((long)st->st_rdev));  | 
2183  | 854  | #endif  | 
2184  |  | #ifdef HAVE_STRUCT_STAT_ST_GEN  | 
2185  |  |     PyStructSequence_SET_ITEM(v, ST_GEN_IDX,  | 
2186  |  |                               PyLong_FromLong((long)st->st_gen));  | 
2187  |  | #endif  | 
2188  |  | #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME  | 
2189  |  |     { | 
2190  |  |       PyObject *val;  | 
2191  |  |       unsigned long bsec,bnsec;  | 
2192  |  |       bsec = (long)st->st_birthtime;  | 
2193  |  | #ifdef HAVE_STAT_TV_NSEC2  | 
2194  |  |       bnsec = st->st_birthtimespec.tv_nsec;  | 
2195  |  | #else  | 
2196  |  |       bnsec = 0;  | 
2197  |  | #endif  | 
2198  |  |       val = PyFloat_FromDouble(bsec + 1e-9*bnsec);  | 
2199  |  |       PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,  | 
2200  |  |                                 val);  | 
2201  |  |     }  | 
2202  |  | #endif  | 
2203  |  | #ifdef HAVE_STRUCT_STAT_ST_FLAGS  | 
2204  |  |     PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,  | 
2205  |  |                               PyLong_FromLong((long)st->st_flags));  | 
2206  |  | #endif  | 
2207  |  | #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES  | 
2208  |  |     PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,  | 
2209  |  |                               PyLong_FromUnsignedLong(st->st_file_attributes));  | 
2210  |  | #endif  | 
2211  |  | #ifdef HAVE_STRUCT_STAT_ST_FSTYPE  | 
2212  |  |    PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,  | 
2213  |  |                               PyUnicode_FromString(st->st_fstype));  | 
2214  |  | #endif  | 
2215  |  | #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG  | 
2216  |  |     PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,  | 
2217  |  |                               PyLong_FromUnsignedLong(st->st_reparse_tag));  | 
2218  |  | #endif  | 
2219  |  |  | 
2220  | 854  |     if (PyErr_Occurred()) { | 
2221  | 0  |         Py_DECREF(v);  | 
2222  | 0  |         return NULL;  | 
2223  | 0  |     }  | 
2224  |  |  | 
2225  | 854  |     return v;  | 
2226  | 854  | }  | 
2227  |  |  | 
2228  |  | /* POSIX methods */  | 
2229  |  |  | 
2230  |  |  | 
2231  |  | static PyObject *  | 
2232  |  | posix_do_stat(const char *function_name, path_t *path,  | 
2233  |  |               int dir_fd, int follow_symlinks)  | 
2234  | 1.08k  | { | 
2235  | 1.08k  |     STRUCT_STAT st;  | 
2236  | 1.08k  |     int result;  | 
2237  |  |  | 
2238  |  | #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)  | 
2239  |  |     if (follow_symlinks_specified(function_name, follow_symlinks))  | 
2240  |  |         return NULL;  | 
2241  |  | #endif  | 
2242  |  |  | 
2243  | 1.08k  |     if (path_and_dir_fd_invalid("stat", path, dir_fd) || | 
2244  | 1.08k  |         dir_fd_and_fd_invalid("stat", dir_fd, path->fd) || | 
2245  | 1.08k  |         fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks)) | 
2246  | 0  |         return NULL;  | 
2247  |  |  | 
2248  | 1.08k  |     Py_BEGIN_ALLOW_THREADS  | 
2249  | 1.08k  |     if (path->fd != -1)  | 
2250  | 0  |         result = FSTAT(path->fd, &st);  | 
2251  |  | #ifdef MS_WINDOWS  | 
2252  |  |     else if (follow_symlinks)  | 
2253  |  |         result = win32_stat(path->wide, &st);  | 
2254  |  |     else  | 
2255  |  |         result = win32_lstat(path->wide, &st);  | 
2256  |  | #else  | 
2257  | 1.08k  |     else  | 
2258  | 1.08k  | #if defined(HAVE_LSTAT)  | 
2259  | 1.08k  |     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))  | 
2260  | 0  |         result = LSTAT(path->narrow, &st);  | 
2261  | 1.08k  |     else  | 
2262  | 1.08k  | #endif /* HAVE_LSTAT */  | 
2263  | 1.08k  | #ifdef HAVE_FSTATAT  | 
2264  | 1.08k  |     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks)  | 
2265  | 0  |         result = fstatat(dir_fd, path->narrow, &st,  | 
2266  | 0  |                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);  | 
2267  | 1.08k  |     else  | 
2268  | 1.08k  | #endif /* HAVE_FSTATAT */  | 
2269  | 1.08k  |         result = STAT(path->narrow, &st);  | 
2270  | 1.08k  | #endif /* MS_WINDOWS */  | 
2271  | 1.08k  |     Py_END_ALLOW_THREADS  | 
2272  |  |  | 
2273  | 1.08k  |     if (result != 0) { | 
2274  | 230  |         return path_error(path);  | 
2275  | 230  |     }  | 
2276  |  |  | 
2277  | 854  |     return _pystat_fromstructstat(&st);  | 
2278  | 1.08k  | }  | 
2279  |  |  | 
2280  |  | /*[python input]  | 
2281  |  |  | 
2282  |  | for s in """  | 
2283  |  |  | 
2284  |  | FACCESSAT  | 
2285  |  | FCHMODAT  | 
2286  |  | FCHOWNAT  | 
2287  |  | FSTATAT  | 
2288  |  | LINKAT  | 
2289  |  | MKDIRAT  | 
2290  |  | MKFIFOAT  | 
2291  |  | MKNODAT  | 
2292  |  | OPENAT  | 
2293  |  | READLINKAT  | 
2294  |  | SYMLINKAT  | 
2295  |  | UNLINKAT  | 
2296  |  |  | 
2297  |  | """.strip().split():  | 
2298  |  |     s = s.strip()  | 
2299  |  |     print(""" | 
2300  |  | #ifdef HAVE_{s} | 
2301  |  |     #define {s}_DIR_FD_CONVERTER dir_fd_converter | 
2302  |  | #else  | 
2303  |  |     #define {s}_DIR_FD_CONVERTER dir_fd_unavailable | 
2304  |  | #endif  | 
2305  |  | """.rstrip().format(s=s))  | 
2306  |  |  | 
2307  |  | for s in """  | 
2308  |  |  | 
2309  |  | FCHDIR  | 
2310  |  | FCHMOD  | 
2311  |  | FCHOWN  | 
2312  |  | FDOPENDIR  | 
2313  |  | FEXECVE  | 
2314  |  | FPATHCONF  | 
2315  |  | FSTATVFS  | 
2316  |  | FTRUNCATE  | 
2317  |  |  | 
2318  |  | """.strip().split():  | 
2319  |  |     s = s.strip()  | 
2320  |  |     print(""" | 
2321  |  | #ifdef HAVE_{s} | 
2322  |  |     #define PATH_HAVE_{s} 1 | 
2323  |  | #else  | 
2324  |  |     #define PATH_HAVE_{s} 0 | 
2325  |  | #endif  | 
2326  |  |  | 
2327  |  | """.rstrip().format(s=s))  | 
2328  |  | [python start generated code]*/  | 
2329  |  |  | 
2330  |  | #ifdef HAVE_FACCESSAT  | 
2331  | 0  |     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter  | 
2332  |  | #else  | 
2333  |  |     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable  | 
2334  |  | #endif  | 
2335  |  |  | 
2336  |  | #ifdef HAVE_FCHMODAT  | 
2337  | 0  |     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter  | 
2338  |  | #else  | 
2339  |  |     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable  | 
2340  |  | #endif  | 
2341  |  |  | 
2342  |  | #ifdef HAVE_FCHOWNAT  | 
2343  | 0  |     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter  | 
2344  |  | #else  | 
2345  |  |     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable  | 
2346  |  | #endif  | 
2347  |  |  | 
2348  |  | #ifdef HAVE_FSTATAT  | 
2349  | 0  |     #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter  | 
2350  |  | #else  | 
2351  |  |     #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable  | 
2352  |  | #endif  | 
2353  |  |  | 
2354  |  | #ifdef HAVE_LINKAT  | 
2355  |  |     #define LINKAT_DIR_FD_CONVERTER dir_fd_converter  | 
2356  |  | #else  | 
2357  |  |     #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable  | 
2358  |  | #endif  | 
2359  |  |  | 
2360  |  | #ifdef HAVE_MKDIRAT  | 
2361  | 0  |     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter  | 
2362  |  | #else  | 
2363  |  |     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable  | 
2364  |  | #endif  | 
2365  |  |  | 
2366  |  | #ifdef HAVE_MKFIFOAT  | 
2367  | 0  |     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter  | 
2368  |  | #else  | 
2369  |  |     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable  | 
2370  |  | #endif  | 
2371  |  |  | 
2372  |  | #ifdef HAVE_MKNODAT  | 
2373  | 0  |     #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter  | 
2374  |  | #else  | 
2375  |  |     #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable  | 
2376  |  | #endif  | 
2377  |  |  | 
2378  |  | #ifdef HAVE_OPENAT  | 
2379  | 0  |     #define OPENAT_DIR_FD_CONVERTER dir_fd_converter  | 
2380  |  | #else  | 
2381  |  |     #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable  | 
2382  |  | #endif  | 
2383  |  |  | 
2384  |  | #ifdef HAVE_READLINKAT  | 
2385  | 0  |     #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter  | 
2386  |  | #else  | 
2387  |  |     #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable  | 
2388  |  | #endif  | 
2389  |  |  | 
2390  |  | #ifdef HAVE_SYMLINKAT  | 
2391  | 0  |     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter  | 
2392  |  | #else  | 
2393  |  |     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable  | 
2394  |  | #endif  | 
2395  |  |  | 
2396  |  | #ifdef HAVE_UNLINKAT  | 
2397  | 0  |     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter  | 
2398  |  | #else  | 
2399  |  |     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable  | 
2400  |  | #endif  | 
2401  |  |  | 
2402  |  | #ifdef HAVE_FCHDIR  | 
2403  |  |     #define PATH_HAVE_FCHDIR 1  | 
2404  |  | #else  | 
2405  |  |     #define PATH_HAVE_FCHDIR 0  | 
2406  |  | #endif  | 
2407  |  |  | 
2408  |  | #ifdef HAVE_FCHMOD  | 
2409  |  |     #define PATH_HAVE_FCHMOD 1  | 
2410  |  | #else  | 
2411  |  |     #define PATH_HAVE_FCHMOD 0  | 
2412  |  | #endif  | 
2413  |  |  | 
2414  |  | #ifdef HAVE_FCHOWN  | 
2415  |  |     #define PATH_HAVE_FCHOWN 1  | 
2416  |  | #else  | 
2417  |  |     #define PATH_HAVE_FCHOWN 0  | 
2418  |  | #endif  | 
2419  |  |  | 
2420  |  | #ifdef HAVE_FDOPENDIR  | 
2421  |  |     #define PATH_HAVE_FDOPENDIR 1  | 
2422  |  | #else  | 
2423  |  |     #define PATH_HAVE_FDOPENDIR 0  | 
2424  |  | #endif  | 
2425  |  |  | 
2426  |  | #ifdef HAVE_FEXECVE  | 
2427  |  |     #define PATH_HAVE_FEXECVE 1  | 
2428  |  | #else  | 
2429  |  |     #define PATH_HAVE_FEXECVE 0  | 
2430  |  | #endif  | 
2431  |  |  | 
2432  |  | #ifdef HAVE_FPATHCONF  | 
2433  |  |     #define PATH_HAVE_FPATHCONF 1  | 
2434  |  | #else  | 
2435  |  |     #define PATH_HAVE_FPATHCONF 0  | 
2436  |  | #endif  | 
2437  |  |  | 
2438  |  | #ifdef HAVE_FSTATVFS  | 
2439  |  |     #define PATH_HAVE_FSTATVFS 1  | 
2440  |  | #else  | 
2441  |  |     #define PATH_HAVE_FSTATVFS 0  | 
2442  |  | #endif  | 
2443  |  |  | 
2444  |  | #ifdef HAVE_FTRUNCATE  | 
2445  |  |     #define PATH_HAVE_FTRUNCATE 1  | 
2446  |  | #else  | 
2447  |  |     #define PATH_HAVE_FTRUNCATE 0  | 
2448  |  | #endif  | 
2449  |  | /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/  | 
2450  |  |  | 
2451  |  | #ifdef MS_WINDOWS  | 
2452  |  |     #undef PATH_HAVE_FTRUNCATE  | 
2453  |  |     #define PATH_HAVE_FTRUNCATE 1  | 
2454  |  | #endif  | 
2455  |  |  | 
2456  |  | /*[python input]  | 
2457  |  |  | 
2458  |  | class path_t_converter(CConverter):  | 
2459  |  |  | 
2460  |  |     type = "path_t"  | 
2461  |  |     impl_by_reference = True  | 
2462  |  |     parse_by_reference = True  | 
2463  |  |  | 
2464  |  |     converter = 'path_converter'  | 
2465  |  |  | 
2466  |  |     def converter_init(self, *, allow_fd=False, nullable=False):  | 
2467  |  |         # right now path_t doesn't support default values.  | 
2468  |  |         # to support a default value, you'll need to override initialize().  | 
2469  |  |         if self.default not in (unspecified, None):  | 
2470  |  |             fail("Can't specify a default to the path_t converter!") | 
2471  |  |  | 
2472  |  |         if self.c_default not in (None, 'Py_None'):  | 
2473  |  |             raise RuntimeError("Can't specify a c_default to the path_t converter!") | 
2474  |  |  | 
2475  |  |         self.nullable = nullable  | 
2476  |  |         self.allow_fd = allow_fd  | 
2477  |  |  | 
2478  |  |     def pre_render(self):  | 
2479  |  |         def strify(value):  | 
2480  |  |             if isinstance(value, str):  | 
2481  |  |                 return value  | 
2482  |  |             return str(int(bool(value)))  | 
2483  |  |  | 
2484  |  |         # add self.py_name here when merging with posixmodule conversion  | 
2485  |  |         self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format( | 
2486  |  |             self.function.name,  | 
2487  |  |             self.name,  | 
2488  |  |             strify(self.nullable),  | 
2489  |  |             strify(self.allow_fd),  | 
2490  |  |             )  | 
2491  |  |  | 
2492  |  |     def cleanup(self):  | 
2493  |  |         return "path_cleanup(&" + self.name + ");\n"  | 
2494  |  |  | 
2495  |  |  | 
2496  |  | class dir_fd_converter(CConverter):  | 
2497  |  |     type = 'int'  | 
2498  |  |  | 
2499  |  |     def converter_init(self, requires=None):  | 
2500  |  |         if self.default in (unspecified, None):  | 
2501  |  |             self.c_default = 'DEFAULT_DIR_FD'  | 
2502  |  |         if isinstance(requires, str):  | 
2503  |  |             self.converter = requires.upper() + '_DIR_FD_CONVERTER'  | 
2504  |  |         else:  | 
2505  |  |             self.converter = 'dir_fd_converter'  | 
2506  |  |  | 
2507  |  | class fildes_converter(CConverter):  | 
2508  |  |     type = 'int'  | 
2509  |  |     converter = 'fildes_converter'  | 
2510  |  |  | 
2511  |  | class uid_t_converter(CConverter):  | 
2512  |  |     type = "uid_t"  | 
2513  |  |     converter = '_Py_Uid_Converter'  | 
2514  |  |  | 
2515  |  | class gid_t_converter(CConverter):  | 
2516  |  |     type = "gid_t"  | 
2517  |  |     converter = '_Py_Gid_Converter'  | 
2518  |  |  | 
2519  |  | class dev_t_converter(CConverter):  | 
2520  |  |     type = 'dev_t'  | 
2521  |  |     converter = '_Py_Dev_Converter'  | 
2522  |  |  | 
2523  |  | class dev_t_return_converter(unsigned_long_return_converter):  | 
2524  |  |     type = 'dev_t'  | 
2525  |  |     conversion_fn = '_PyLong_FromDev'  | 
2526  |  |     unsigned_cast = '(dev_t)'  | 
2527  |  |  | 
2528  |  | class FSConverter_converter(CConverter):  | 
2529  |  |     type = 'PyObject *'  | 
2530  |  |     converter = 'PyUnicode_FSConverter'  | 
2531  |  |     def converter_init(self):  | 
2532  |  |         if self.default is not unspecified:  | 
2533  |  |             fail("FSConverter_converter does not support default values") | 
2534  |  |         self.c_default = 'NULL'  | 
2535  |  |  | 
2536  |  |     def cleanup(self):  | 
2537  |  |         return "Py_XDECREF(" + self.name + ");\n" | 
2538  |  |  | 
2539  |  | class pid_t_converter(CConverter):  | 
2540  |  |     type = 'pid_t'  | 
2541  |  |     format_unit = '" _Py_PARSE_PID "'  | 
2542  |  |  | 
2543  |  | class idtype_t_converter(int_converter):  | 
2544  |  |     type = 'idtype_t'  | 
2545  |  |  | 
2546  |  | class id_t_converter(CConverter):  | 
2547  |  |     type = 'id_t'  | 
2548  |  |     format_unit = '" _Py_PARSE_PID "'  | 
2549  |  |  | 
2550  |  | class intptr_t_converter(CConverter):  | 
2551  |  |     type = 'intptr_t'  | 
2552  |  |     format_unit = '" _Py_PARSE_INTPTR "'  | 
2553  |  |  | 
2554  |  | class Py_off_t_converter(CConverter):  | 
2555  |  |     type = 'Py_off_t'  | 
2556  |  |     converter = 'Py_off_t_converter'  | 
2557  |  |  | 
2558  |  | class Py_off_t_return_converter(long_return_converter):  | 
2559  |  |     type = 'Py_off_t'  | 
2560  |  |     conversion_fn = 'PyLong_FromPy_off_t'  | 
2561  |  |  | 
2562  |  | class path_confname_converter(CConverter):  | 
2563  |  |     type="int"  | 
2564  |  |     converter="conv_path_confname"  | 
2565  |  |  | 
2566  |  | class confstr_confname_converter(path_confname_converter):  | 
2567  |  |     converter='conv_confstr_confname'  | 
2568  |  |  | 
2569  |  | class sysconf_confname_converter(path_confname_converter):  | 
2570  |  |     converter="conv_sysconf_confname"  | 
2571  |  |  | 
2572  |  | class sched_param_converter(CConverter):  | 
2573  |  |     type = 'struct sched_param'  | 
2574  |  |     converter = 'convert_sched_param'  | 
2575  |  |     impl_by_reference = True;  | 
2576  |  |  | 
2577  |  | [python start generated code]*/  | 
2578  |  | /*[python end generated code: output=da39a3ee5e6b4b0d input=418fce0e01144461]*/  | 
2579  |  |  | 
2580  |  | /*[clinic input]  | 
2581  |  |  | 
2582  |  | os.stat  | 
2583  |  |  | 
2584  |  |     path : path_t(allow_fd=True)  | 
2585  |  |         Path to be examined; can be string, bytes, a path-like object or  | 
2586  |  |         open-file-descriptor int.  | 
2587  |  |  | 
2588  |  |     *  | 
2589  |  |  | 
2590  |  |     dir_fd : dir_fd(requires='fstatat') = None  | 
2591  |  |         If not None, it should be a file descriptor open to a directory,  | 
2592  |  |         and path should be a relative string; path will then be relative to  | 
2593  |  |         that directory.  | 
2594  |  |  | 
2595  |  |     follow_symlinks: bool = True  | 
2596  |  |         If False, and the last element of the path is a symbolic link,  | 
2597  |  |         stat will examine the symbolic link itself instead of the file  | 
2598  |  |         the link points to.  | 
2599  |  |  | 
2600  |  | Perform a stat system call on the given path.  | 
2601  |  |  | 
2602  |  | dir_fd and follow_symlinks may not be implemented  | 
2603  |  |   on your platform.  If they are unavailable, using them will raise a  | 
2604  |  |   NotImplementedError.  | 
2605  |  |  | 
2606  |  | It's an error to use dir_fd or follow_symlinks when specifying path as  | 
2607  |  |   an open file descriptor.  | 
2608  |  |  | 
2609  |  | [clinic start generated code]*/  | 
2610  |  |  | 
2611  |  | static PyObject *  | 
2612  |  | os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)  | 
2613  |  | /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/  | 
2614  | 1.08k  | { | 
2615  | 1.08k  |     return posix_do_stat("stat", path, dir_fd, follow_symlinks); | 
2616  | 1.08k  | }  | 
2617  |  |  | 
2618  |  |  | 
2619  |  | /*[clinic input]  | 
2620  |  | os.lstat  | 
2621  |  |  | 
2622  |  |     path : path_t  | 
2623  |  |  | 
2624  |  |     *  | 
2625  |  |  | 
2626  |  |     dir_fd : dir_fd(requires='fstatat') = None  | 
2627  |  |  | 
2628  |  | Perform a stat system call on the given path, without following symbolic links.  | 
2629  |  |  | 
2630  |  | Like stat(), but do not follow symbolic links.  | 
2631  |  | Equivalent to stat(path, follow_symlinks=False).  | 
2632  |  | [clinic start generated code]*/  | 
2633  |  |  | 
2634  |  | static PyObject *  | 
2635  |  | os_lstat_impl(PyObject *module, path_t *path, int dir_fd)  | 
2636  |  | /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/  | 
2637  | 0  | { | 
2638  | 0  |     int follow_symlinks = 0;  | 
2639  | 0  |     return posix_do_stat("lstat", path, dir_fd, follow_symlinks); | 
2640  | 0  | }  | 
2641  |  |  | 
2642  |  |  | 
2643  |  | /*[clinic input]  | 
2644  |  | os.access -> bool  | 
2645  |  |  | 
2646  |  |     path: path_t  | 
2647  |  |         Path to be tested; can be string, bytes, or a path-like object.  | 
2648  |  |  | 
2649  |  |     mode: int  | 
2650  |  |         Operating-system mode bitfield.  Can be F_OK to test existence,  | 
2651  |  |         or the inclusive-OR of R_OK, W_OK, and X_OK.  | 
2652  |  |  | 
2653  |  |     *  | 
2654  |  |  | 
2655  |  |     dir_fd : dir_fd(requires='faccessat') = None  | 
2656  |  |         If not None, it should be a file descriptor open to a directory,  | 
2657  |  |         and path should be relative; path will then be relative to that  | 
2658  |  |         directory.  | 
2659  |  |  | 
2660  |  |     effective_ids: bool = False  | 
2661  |  |         If True, access will use the effective uid/gid instead of  | 
2662  |  |         the real uid/gid.  | 
2663  |  |  | 
2664  |  |     follow_symlinks: bool = True  | 
2665  |  |         If False, and the last element of the path is a symbolic link,  | 
2666  |  |         access will examine the symbolic link itself instead of the file  | 
2667  |  |         the link points to.  | 
2668  |  |  | 
2669  |  | Use the real uid/gid to test for access to a path.  | 
2670  |  |  | 
2671  |  | {parameters} | 
2672  |  | dir_fd, effective_ids, and follow_symlinks may not be implemented  | 
2673  |  |   on your platform.  If they are unavailable, using them will raise a  | 
2674  |  |   NotImplementedError.  | 
2675  |  |  | 
2676  |  | Note that most operations will use the effective uid/gid, therefore this  | 
2677  |  |   routine can be used in a suid/sgid environment to test if the invoking user  | 
2678  |  |   has the specified access to the path.  | 
2679  |  |  | 
2680  |  | [clinic start generated code]*/  | 
2681  |  |  | 
2682  |  | static int  | 
2683  |  | os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,  | 
2684  |  |                int effective_ids, int follow_symlinks)  | 
2685  |  | /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/  | 
2686  | 0  | { | 
2687  | 0  |     int return_value;  | 
2688  |  | 
  | 
2689  |  | #ifdef MS_WINDOWS  | 
2690  |  |     DWORD attr;  | 
2691  |  | #else  | 
2692  | 0  |     int result;  | 
2693  | 0  | #endif  | 
2694  |  | 
  | 
2695  |  | #ifndef HAVE_FACCESSAT  | 
2696  |  |     if (follow_symlinks_specified("access", follow_symlinks)) | 
2697  |  |         return -1;  | 
2698  |  |  | 
2699  |  |     if (effective_ids) { | 
2700  |  |         argument_unavailable_error("access", "effective_ids"); | 
2701  |  |         return -1;  | 
2702  |  |     }  | 
2703  |  | #endif  | 
2704  |  | 
  | 
2705  |  | #ifdef MS_WINDOWS  | 
2706  |  |     Py_BEGIN_ALLOW_THREADS  | 
2707  |  |     attr = GetFileAttributesW(path->wide);  | 
2708  |  |     Py_END_ALLOW_THREADS  | 
2709  |  |  | 
2710  |  |     /*  | 
2711  |  |      * Access is possible if  | 
2712  |  |      *   * we didn't get a -1, and  | 
2713  |  |      *     * write access wasn't requested,  | 
2714  |  |      *     * or the file isn't read-only,  | 
2715  |  |      *     * or it's a directory.  | 
2716  |  |      * (Directories cannot be read-only on Windows.)  | 
2717  |  |     */  | 
2718  |  |     return_value = (attr != INVALID_FILE_ATTRIBUTES) &&  | 
2719  |  |             (!(mode & 2) ||  | 
2720  |  |             !(attr & FILE_ATTRIBUTE_READONLY) ||  | 
2721  |  |             (attr & FILE_ATTRIBUTE_DIRECTORY));  | 
2722  |  | #else  | 
2723  |  | 
  | 
2724  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
2725  | 0  | #ifdef HAVE_FACCESSAT  | 
2726  | 0  |     if ((dir_fd != DEFAULT_DIR_FD) ||  | 
2727  | 0  |         effective_ids ||  | 
2728  | 0  |         !follow_symlinks) { | 
2729  | 0  |         int flags = 0;  | 
2730  | 0  |         if (!follow_symlinks)  | 
2731  | 0  |             flags |= AT_SYMLINK_NOFOLLOW;  | 
2732  | 0  |         if (effective_ids)  | 
2733  | 0  |             flags |= AT_EACCESS;  | 
2734  | 0  |         result = faccessat(dir_fd, path->narrow, mode, flags);  | 
2735  | 0  |     }  | 
2736  | 0  |     else  | 
2737  | 0  | #endif  | 
2738  | 0  |         result = access(path->narrow, mode);  | 
2739  | 0  |     Py_END_ALLOW_THREADS  | 
2740  | 0  |     return_value = !result;  | 
2741  | 0  | #endif  | 
2742  |  | 
  | 
2743  | 0  |     return return_value;  | 
2744  | 0  | }  | 
2745  |  |  | 
2746  |  | #ifndef F_OK  | 
2747  |  | #define F_OK 0  | 
2748  |  | #endif  | 
2749  |  | #ifndef R_OK  | 
2750  |  | #define R_OK 4  | 
2751  |  | #endif  | 
2752  |  | #ifndef W_OK  | 
2753  |  | #define W_OK 2  | 
2754  |  | #endif  | 
2755  |  | #ifndef X_OK  | 
2756  |  | #define X_OK 1  | 
2757  |  | #endif  | 
2758  |  |  | 
2759  |  |  | 
2760  |  | #ifdef HAVE_TTYNAME  | 
2761  |  | /*[clinic input]  | 
2762  |  | os.ttyname  | 
2763  |  |  | 
2764  |  |     fd: int  | 
2765  |  |         Integer file descriptor handle.  | 
2766  |  |  | 
2767  |  |     /  | 
2768  |  |  | 
2769  |  | Return the name of the terminal device connected to 'fd'.  | 
2770  |  | [clinic start generated code]*/  | 
2771  |  |  | 
2772  |  | static PyObject *  | 
2773  |  | os_ttyname_impl(PyObject *module, int fd)  | 
2774  |  | /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/  | 
2775  | 0  | { | 
2776  | 0  |     char *ret;  | 
2777  |  | 
  | 
2778  | 0  |     ret = ttyname(fd);  | 
2779  | 0  |     if (ret == NULL) { | 
2780  | 0  |         return posix_error();  | 
2781  | 0  |     }  | 
2782  | 0  |     return PyUnicode_DecodeFSDefault(ret);  | 
2783  | 0  | }  | 
2784  |  | #endif  | 
2785  |  |  | 
2786  |  | #ifdef HAVE_CTERMID  | 
2787  |  | /*[clinic input]  | 
2788  |  | os.ctermid  | 
2789  |  |  | 
2790  |  | Return the name of the controlling terminal for this process.  | 
2791  |  | [clinic start generated code]*/  | 
2792  |  |  | 
2793  |  | static PyObject *  | 
2794  |  | os_ctermid_impl(PyObject *module)  | 
2795  |  | /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/  | 
2796  | 0  | { | 
2797  | 0  |     char *ret;  | 
2798  | 0  |     char buffer[L_ctermid];  | 
2799  |  | 
  | 
2800  |  | #ifdef USE_CTERMID_R  | 
2801  |  |     ret = ctermid_r(buffer);  | 
2802  |  | #else  | 
2803  | 0  |     ret = ctermid(buffer);  | 
2804  | 0  | #endif  | 
2805  | 0  |     if (ret == NULL)  | 
2806  | 0  |         return posix_error();  | 
2807  | 0  |     return PyUnicode_DecodeFSDefault(buffer);  | 
2808  | 0  | }  | 
2809  |  | #endif /* HAVE_CTERMID */  | 
2810  |  |  | 
2811  |  |  | 
2812  |  | /*[clinic input]  | 
2813  |  | os.chdir  | 
2814  |  |  | 
2815  |  |     path: path_t(allow_fd='PATH_HAVE_FCHDIR')  | 
2816  |  |  | 
2817  |  | Change the current working directory to the specified path.  | 
2818  |  |  | 
2819  |  | path may always be specified as a string.  | 
2820  |  | On some platforms, path may also be specified as an open file descriptor.  | 
2821  |  |   If this functionality is unavailable, using it raises an exception.  | 
2822  |  | [clinic start generated code]*/  | 
2823  |  |  | 
2824  |  | static PyObject *  | 
2825  |  | os_chdir_impl(PyObject *module, path_t *path)  | 
2826  |  | /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/  | 
2827  | 0  | { | 
2828  | 0  |     int result;  | 
2829  |  | 
  | 
2830  | 0  |     if (PySys_Audit("os.chdir", "(O)", path->object) < 0) { | 
2831  | 0  |         return NULL;  | 
2832  | 0  |     }  | 
2833  |  |  | 
2834  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
2835  |  | #ifdef MS_WINDOWS  | 
2836  |  |     /* on unix, success = 0, on windows, success = !0 */  | 
2837  |  |     result = !win32_wchdir(path->wide);  | 
2838  |  | #else  | 
2839  | 0  | #ifdef HAVE_FCHDIR  | 
2840  | 0  |     if (path->fd != -1)  | 
2841  | 0  |         result = fchdir(path->fd);  | 
2842  | 0  |     else  | 
2843  | 0  | #endif  | 
2844  | 0  |         result = chdir(path->narrow);  | 
2845  | 0  | #endif  | 
2846  | 0  |     Py_END_ALLOW_THREADS  | 
2847  |  | 
  | 
2848  | 0  |     if (result) { | 
2849  | 0  |         return path_error(path);  | 
2850  | 0  |     }  | 
2851  |  |  | 
2852  | 0  |     Py_RETURN_NONE;  | 
2853  | 0  | }  | 
2854  |  |  | 
2855  |  |  | 
2856  |  | #ifdef HAVE_FCHDIR  | 
2857  |  | /*[clinic input]  | 
2858  |  | os.fchdir  | 
2859  |  |  | 
2860  |  |     fd: fildes  | 
2861  |  |  | 
2862  |  | Change to the directory of the given file descriptor.  | 
2863  |  |  | 
2864  |  | fd must be opened on a directory, not a file.  | 
2865  |  | Equivalent to os.chdir(fd).  | 
2866  |  |  | 
2867  |  | [clinic start generated code]*/  | 
2868  |  |  | 
2869  |  | static PyObject *  | 
2870  |  | os_fchdir_impl(PyObject *module, int fd)  | 
2871  |  | /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/  | 
2872  | 0  | { | 
2873  | 0  |     if (PySys_Audit("os.chdir", "(i)", fd) < 0) { | 
2874  | 0  |         return NULL;  | 
2875  | 0  |     }  | 
2876  | 0  |     return posix_fildes_fd(fd, fchdir);  | 
2877  | 0  | }  | 
2878  |  | #endif /* HAVE_FCHDIR */  | 
2879  |  |  | 
2880  |  |  | 
2881  |  | /*[clinic input]  | 
2882  |  | os.chmod  | 
2883  |  |  | 
2884  |  |     path: path_t(allow_fd='PATH_HAVE_FCHMOD')  | 
2885  |  |         Path to be modified.  May always be specified as a str, bytes, or a path-like object.  | 
2886  |  |         On some platforms, path may also be specified as an open file descriptor.  | 
2887  |  |         If this functionality is unavailable, using it raises an exception.  | 
2888  |  |  | 
2889  |  |     mode: int  | 
2890  |  |         Operating-system mode bitfield.  | 
2891  |  |  | 
2892  |  |     *  | 
2893  |  |  | 
2894  |  |     dir_fd : dir_fd(requires='fchmodat') = None  | 
2895  |  |         If not None, it should be a file descriptor open to a directory,  | 
2896  |  |         and path should be relative; path will then be relative to that  | 
2897  |  |         directory.  | 
2898  |  |  | 
2899  |  |     follow_symlinks: bool = True  | 
2900  |  |         If False, and the last element of the path is a symbolic link,  | 
2901  |  |         chmod will modify the symbolic link itself instead of the file  | 
2902  |  |         the link points to.  | 
2903  |  |  | 
2904  |  | Change the access permissions of a file.  | 
2905  |  |  | 
2906  |  | It is an error to use dir_fd or follow_symlinks when specifying path as  | 
2907  |  |   an open file descriptor.  | 
2908  |  | dir_fd and follow_symlinks may not be implemented on your platform.  | 
2909  |  |   If they are unavailable, using them will raise a NotImplementedError.  | 
2910  |  |  | 
2911  |  | [clinic start generated code]*/  | 
2912  |  |  | 
2913  |  | static PyObject *  | 
2914  |  | os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,  | 
2915  |  |               int follow_symlinks)  | 
2916  |  | /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/  | 
2917  | 0  | { | 
2918  | 0  |     int result;  | 
2919  |  | 
  | 
2920  |  | #ifdef MS_WINDOWS  | 
2921  |  |     DWORD attr;  | 
2922  |  | #endif  | 
2923  |  | 
  | 
2924  | 0  | #ifdef HAVE_FCHMODAT  | 
2925  | 0  |     int fchmodat_nofollow_unsupported = 0;  | 
2926  | 0  | #endif  | 
2927  |  | 
  | 
2928  |  | #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))  | 
2929  |  |     if (follow_symlinks_specified("chmod", follow_symlinks)) | 
2930  |  |         return NULL;  | 
2931  |  | #endif  | 
2932  |  | 
  | 
2933  | 0  |     if (PySys_Audit("os.chmod", "Oii", path->object, mode, | 
2934  | 0  |                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { | 
2935  | 0  |         return NULL;  | 
2936  | 0  |     }  | 
2937  |  |  | 
2938  |  | #ifdef MS_WINDOWS  | 
2939  |  |     Py_BEGIN_ALLOW_THREADS  | 
2940  |  |     attr = GetFileAttributesW(path->wide);  | 
2941  |  |     if (attr == INVALID_FILE_ATTRIBUTES)  | 
2942  |  |         result = 0;  | 
2943  |  |     else { | 
2944  |  |         if (mode & _S_IWRITE)  | 
2945  |  |             attr &= ~FILE_ATTRIBUTE_READONLY;  | 
2946  |  |         else  | 
2947  |  |             attr |= FILE_ATTRIBUTE_READONLY;  | 
2948  |  |         result = SetFileAttributesW(path->wide, attr);  | 
2949  |  |     }  | 
2950  |  |     Py_END_ALLOW_THREADS  | 
2951  |  |  | 
2952  |  |     if (!result) { | 
2953  |  |         return path_error(path);  | 
2954  |  |     }  | 
2955  |  | #else /* MS_WINDOWS */  | 
2956  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
2957  | 0  | #ifdef HAVE_FCHMOD  | 
2958  | 0  |     if (path->fd != -1)  | 
2959  | 0  |         result = fchmod(path->fd, mode);  | 
2960  | 0  |     else  | 
2961  | 0  | #endif  | 
2962  |  | #ifdef HAVE_LCHMOD  | 
2963  |  |     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))  | 
2964  |  |         result = lchmod(path->narrow, mode);  | 
2965  |  |     else  | 
2966  |  | #endif  | 
2967  | 0  | #ifdef HAVE_FCHMODAT  | 
2968  | 0  |     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) { | 
2969  |  |         /*  | 
2970  |  |          * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!  | 
2971  |  |          * The documentation specifically shows how to use it,  | 
2972  |  |          * and then says it isn't implemented yet.  | 
2973  |  |          * (true on linux with glibc 2.15, and openindiana 3.x)  | 
2974  |  |          *  | 
2975  |  |          * Once it is supported, os.chmod will automatically  | 
2976  |  |          * support dir_fd and follow_symlinks=False.  (Hopefully.)  | 
2977  |  |          * Until then, we need to be careful what exception we raise.  | 
2978  |  |          */  | 
2979  | 0  |         result = fchmodat(dir_fd, path->narrow, mode,  | 
2980  | 0  |                           follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);  | 
2981  |  |         /*  | 
2982  |  |          * But wait!  We can't throw the exception without allowing threads,  | 
2983  |  |          * and we can't do that in this nested scope.  (Macro trickery, sigh.)  | 
2984  |  |          */  | 
2985  | 0  |         fchmodat_nofollow_unsupported =  | 
2986  | 0  |                          result &&  | 
2987  | 0  |                          ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&  | 
2988  | 0  |                          !follow_symlinks;  | 
2989  | 0  |     }  | 
2990  | 0  |     else  | 
2991  | 0  | #endif  | 
2992  | 0  |         result = chmod(path->narrow, mode);  | 
2993  | 0  |     Py_END_ALLOW_THREADS  | 
2994  |  | 
  | 
2995  | 0  |     if (result) { | 
2996  | 0  | #ifdef HAVE_FCHMODAT  | 
2997  | 0  |         if (fchmodat_nofollow_unsupported) { | 
2998  | 0  |             if (dir_fd != DEFAULT_DIR_FD)  | 
2999  | 0  |                 dir_fd_and_follow_symlinks_invalid("chmod", | 
3000  | 0  |                                                    dir_fd, follow_symlinks);  | 
3001  | 0  |             else  | 
3002  | 0  |                 follow_symlinks_specified("chmod", follow_symlinks); | 
3003  | 0  |             return NULL;  | 
3004  | 0  |         }  | 
3005  | 0  |         else  | 
3006  | 0  | #endif  | 
3007  | 0  |         return path_error(path);  | 
3008  | 0  |     }  | 
3009  | 0  | #endif  | 
3010  |  |  | 
3011  | 0  |     Py_RETURN_NONE;  | 
3012  | 0  | }  | 
3013  |  |  | 
3014  |  |  | 
3015  |  | #ifdef HAVE_FCHMOD  | 
3016  |  | /*[clinic input]  | 
3017  |  | os.fchmod  | 
3018  |  |  | 
3019  |  |     fd: int  | 
3020  |  |     mode: int  | 
3021  |  |  | 
3022  |  | Change the access permissions of the file given by file descriptor fd.  | 
3023  |  |  | 
3024  |  | Equivalent to os.chmod(fd, mode).  | 
3025  |  | [clinic start generated code]*/  | 
3026  |  |  | 
3027  |  | static PyObject *  | 
3028  |  | os_fchmod_impl(PyObject *module, int fd, int mode)  | 
3029  |  | /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/  | 
3030  | 0  | { | 
3031  | 0  |     int res;  | 
3032  | 0  |     int async_err = 0;  | 
3033  |  | 
  | 
3034  | 0  |     if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) { | 
3035  | 0  |         return NULL;  | 
3036  | 0  |     }  | 
3037  |  |  | 
3038  | 0  |     do { | 
3039  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
3040  | 0  |         res = fchmod(fd, mode);  | 
3041  | 0  |         Py_END_ALLOW_THREADS  | 
3042  | 0  |     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
3043  | 0  |     if (res != 0)  | 
3044  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
3045  |  |  | 
3046  | 0  |     Py_RETURN_NONE;  | 
3047  | 0  | }  | 
3048  |  | #endif /* HAVE_FCHMOD */  | 
3049  |  |  | 
3050  |  |  | 
3051  |  | #ifdef HAVE_LCHMOD  | 
3052  |  | /*[clinic input]  | 
3053  |  | os.lchmod  | 
3054  |  |  | 
3055  |  |     path: path_t  | 
3056  |  |     mode: int  | 
3057  |  |  | 
3058  |  | Change the access permissions of a file, without following symbolic links.  | 
3059  |  |  | 
3060  |  | If path is a symlink, this affects the link itself rather than the target.  | 
3061  |  | Equivalent to chmod(path, mode, follow_symlinks=False)."  | 
3062  |  | [clinic start generated code]*/  | 
3063  |  |  | 
3064  |  | static PyObject *  | 
3065  |  | os_lchmod_impl(PyObject *module, path_t *path, int mode)  | 
3066  |  | /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/  | 
3067  |  | { | 
3068  |  |     int res;  | 
3069  |  |     if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) { | 
3070  |  |         return NULL;  | 
3071  |  |     }  | 
3072  |  |     Py_BEGIN_ALLOW_THREADS  | 
3073  |  |     res = lchmod(path->narrow, mode);  | 
3074  |  |     Py_END_ALLOW_THREADS  | 
3075  |  |     if (res < 0) { | 
3076  |  |         path_error(path);  | 
3077  |  |         return NULL;  | 
3078  |  |     }  | 
3079  |  |     Py_RETURN_NONE;  | 
3080  |  | }  | 
3081  |  | #endif /* HAVE_LCHMOD */  | 
3082  |  |  | 
3083  |  |  | 
3084  |  | #ifdef HAVE_CHFLAGS  | 
3085  |  | /*[clinic input]  | 
3086  |  | os.chflags  | 
3087  |  |  | 
3088  |  |     path: path_t  | 
3089  |  |     flags: unsigned_long(bitwise=True)  | 
3090  |  |     follow_symlinks: bool=True  | 
3091  |  |  | 
3092  |  | Set file flags.  | 
3093  |  |  | 
3094  |  | If follow_symlinks is False, and the last element of the path is a symbolic  | 
3095  |  |   link, chflags will change flags on the symbolic link itself instead of the  | 
3096  |  |   file the link points to.  | 
3097  |  | follow_symlinks may not be implemented on your platform.  If it is  | 
3098  |  | unavailable, using it will raise a NotImplementedError.  | 
3099  |  |  | 
3100  |  | [clinic start generated code]*/  | 
3101  |  |  | 
3102  |  | static PyObject *  | 
3103  |  | os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,  | 
3104  |  |                 int follow_symlinks)  | 
3105  |  | /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/  | 
3106  |  | { | 
3107  |  |     int result;  | 
3108  |  |  | 
3109  |  | #ifndef HAVE_LCHFLAGS  | 
3110  |  |     if (follow_symlinks_specified("chflags", follow_symlinks)) | 
3111  |  |         return NULL;  | 
3112  |  | #endif  | 
3113  |  |  | 
3114  |  |     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) { | 
3115  |  |         return NULL;  | 
3116  |  |     }  | 
3117  |  |  | 
3118  |  |     Py_BEGIN_ALLOW_THREADS  | 
3119  |  | #ifdef HAVE_LCHFLAGS  | 
3120  |  |     if (!follow_symlinks)  | 
3121  |  |         result = lchflags(path->narrow, flags);  | 
3122  |  |     else  | 
3123  |  | #endif  | 
3124  |  |         result = chflags(path->narrow, flags);  | 
3125  |  |     Py_END_ALLOW_THREADS  | 
3126  |  |  | 
3127  |  |     if (result)  | 
3128  |  |         return path_error(path);  | 
3129  |  |  | 
3130  |  |     Py_RETURN_NONE;  | 
3131  |  | }  | 
3132  |  | #endif /* HAVE_CHFLAGS */  | 
3133  |  |  | 
3134  |  |  | 
3135  |  | #ifdef HAVE_LCHFLAGS  | 
3136  |  | /*[clinic input]  | 
3137  |  | os.lchflags  | 
3138  |  |  | 
3139  |  |     path: path_t  | 
3140  |  |     flags: unsigned_long(bitwise=True)  | 
3141  |  |  | 
3142  |  | Set file flags.  | 
3143  |  |  | 
3144  |  | This function will not follow symbolic links.  | 
3145  |  | Equivalent to chflags(path, flags, follow_symlinks=False).  | 
3146  |  | [clinic start generated code]*/  | 
3147  |  |  | 
3148  |  | static PyObject *  | 
3149  |  | os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)  | 
3150  |  | /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/  | 
3151  |  | { | 
3152  |  |     int res;  | 
3153  |  |     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) { | 
3154  |  |         return NULL;  | 
3155  |  |     }  | 
3156  |  |     Py_BEGIN_ALLOW_THREADS  | 
3157  |  |     res = lchflags(path->narrow, flags);  | 
3158  |  |     Py_END_ALLOW_THREADS  | 
3159  |  |     if (res < 0) { | 
3160  |  |         return path_error(path);  | 
3161  |  |     }  | 
3162  |  |     Py_RETURN_NONE;  | 
3163  |  | }  | 
3164  |  | #endif /* HAVE_LCHFLAGS */  | 
3165  |  |  | 
3166  |  |  | 
3167  |  | #ifdef HAVE_CHROOT  | 
3168  |  | /*[clinic input]  | 
3169  |  | os.chroot  | 
3170  |  |     path: path_t  | 
3171  |  |  | 
3172  |  | Change root directory to path.  | 
3173  |  |  | 
3174  |  | [clinic start generated code]*/  | 
3175  |  |  | 
3176  |  | static PyObject *  | 
3177  |  | os_chroot_impl(PyObject *module, path_t *path)  | 
3178  |  | /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/  | 
3179  | 0  | { | 
3180  | 0  |     int res;  | 
3181  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
3182  | 0  |     res = chroot(path->narrow);  | 
3183  | 0  |     Py_END_ALLOW_THREADS  | 
3184  | 0  |     if (res < 0)  | 
3185  | 0  |         return path_error(path);  | 
3186  | 0  |     Py_RETURN_NONE;  | 
3187  | 0  | }  | 
3188  |  | #endif /* HAVE_CHROOT */  | 
3189  |  |  | 
3190  |  |  | 
3191  |  | #ifdef HAVE_FSYNC  | 
3192  |  | /*[clinic input]  | 
3193  |  | os.fsync  | 
3194  |  |  | 
3195  |  |     fd: fildes  | 
3196  |  |  | 
3197  |  | Force write of fd to disk.  | 
3198  |  | [clinic start generated code]*/  | 
3199  |  |  | 
3200  |  | static PyObject *  | 
3201  |  | os_fsync_impl(PyObject *module, int fd)  | 
3202  |  | /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/  | 
3203  | 0  | { | 
3204  | 0  |     return posix_fildes_fd(fd, fsync);  | 
3205  | 0  | }  | 
3206  |  | #endif /* HAVE_FSYNC */  | 
3207  |  |  | 
3208  |  |  | 
3209  |  | #ifdef HAVE_SYNC  | 
3210  |  | /*[clinic input]  | 
3211  |  | os.sync  | 
3212  |  |  | 
3213  |  | Force write of everything to disk.  | 
3214  |  | [clinic start generated code]*/  | 
3215  |  |  | 
3216  |  | static PyObject *  | 
3217  |  | os_sync_impl(PyObject *module)  | 
3218  |  | /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/  | 
3219  | 0  | { | 
3220  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
3221  | 0  |     sync();  | 
3222  | 0  |     Py_END_ALLOW_THREADS  | 
3223  | 0  |     Py_RETURN_NONE;  | 
3224  | 0  | }  | 
3225  |  | #endif /* HAVE_SYNC */  | 
3226  |  |  | 
3227  |  |  | 
3228  |  | #ifdef HAVE_FDATASYNC  | 
3229  |  | #ifdef __hpux  | 
3230  |  | extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */  | 
3231  |  | #endif  | 
3232  |  |  | 
3233  |  | /*[clinic input]  | 
3234  |  | os.fdatasync  | 
3235  |  |  | 
3236  |  |     fd: fildes  | 
3237  |  |  | 
3238  |  | Force write of fd to disk without forcing update of metadata.  | 
3239  |  | [clinic start generated code]*/  | 
3240  |  |  | 
3241  |  | static PyObject *  | 
3242  |  | os_fdatasync_impl(PyObject *module, int fd)  | 
3243  |  | /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/  | 
3244  | 0  | { | 
3245  | 0  |     return posix_fildes_fd(fd, fdatasync);  | 
3246  | 0  | }  | 
3247  |  | #endif /* HAVE_FDATASYNC */  | 
3248  |  |  | 
3249  |  |  | 
3250  |  | #ifdef HAVE_CHOWN  | 
3251  |  | /*[clinic input]  | 
3252  |  | os.chown  | 
3253  |  |  | 
3254  |  |     path : path_t(allow_fd='PATH_HAVE_FCHOWN')  | 
3255  |  |         Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.  | 
3256  |  |  | 
3257  |  |     uid: uid_t  | 
3258  |  |  | 
3259  |  |     gid: gid_t  | 
3260  |  |  | 
3261  |  |     *  | 
3262  |  |  | 
3263  |  |     dir_fd : dir_fd(requires='fchownat') = None  | 
3264  |  |         If not None, it should be a file descriptor open to a directory,  | 
3265  |  |         and path should be relative; path will then be relative to that  | 
3266  |  |         directory.  | 
3267  |  |  | 
3268  |  |     follow_symlinks: bool = True  | 
3269  |  |         If False, and the last element of the path is a symbolic link,  | 
3270  |  |         stat will examine the symbolic link itself instead of the file  | 
3271  |  |         the link points to.  | 
3272  |  |  | 
3273  |  | Change the owner and group id of path to the numeric uid and gid.\  | 
3274  |  |  | 
3275  |  | path may always be specified as a string.  | 
3276  |  | On some platforms, path may also be specified as an open file descriptor.  | 
3277  |  |   If this functionality is unavailable, using it raises an exception.  | 
3278  |  | If dir_fd is not None, it should be a file descriptor open to a directory,  | 
3279  |  |   and path should be relative; path will then be relative to that directory.  | 
3280  |  | If follow_symlinks is False, and the last element of the path is a symbolic  | 
3281  |  |   link, chown will modify the symbolic link itself instead of the file the  | 
3282  |  |   link points to.  | 
3283  |  | It is an error to use dir_fd or follow_symlinks when specifying path as  | 
3284  |  |   an open file descriptor.  | 
3285  |  | dir_fd and follow_symlinks may not be implemented on your platform.  | 
3286  |  |   If they are unavailable, using them will raise a NotImplementedError.  | 
3287  |  |  | 
3288  |  | [clinic start generated code]*/  | 
3289  |  |  | 
3290  |  | static PyObject *  | 
3291  |  | os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,  | 
3292  |  |               int dir_fd, int follow_symlinks)  | 
3293  |  | /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/  | 
3294  | 0  | { | 
3295  | 0  |     int result;  | 
3296  |  | 
  | 
3297  |  | #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))  | 
3298  |  |     if (follow_symlinks_specified("chown", follow_symlinks)) | 
3299  |  |         return NULL;  | 
3300  |  | #endif  | 
3301  | 0  |     if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) || | 
3302  | 0  |         fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks)) | 
3303  | 0  |         return NULL;  | 
3304  |  |  | 
3305  |  | #ifdef __APPLE__  | 
3306  |  |     /*  | 
3307  |  |      * This is for Mac OS X 10.3, which doesn't have lchown.  | 
3308  |  |      * (But we still have an lchown symbol because of weak-linking.)  | 
3309  |  |      * It doesn't have fchownat either.  So there's no possibility  | 
3310  |  |      * of a graceful failover.  | 
3311  |  |      */  | 
3312  |  |     if ((!follow_symlinks) && (lchown == NULL)) { | 
3313  |  |         follow_symlinks_specified("chown", follow_symlinks); | 
3314  |  |         return NULL;  | 
3315  |  |     }  | 
3316  |  | #endif  | 
3317  |  |  | 
3318  | 0  |     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, | 
3319  | 0  |                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { | 
3320  | 0  |         return NULL;  | 
3321  | 0  |     }  | 
3322  |  |  | 
3323  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
3324  | 0  | #ifdef HAVE_FCHOWN  | 
3325  | 0  |     if (path->fd != -1)  | 
3326  | 0  |         result = fchown(path->fd, uid, gid);  | 
3327  | 0  |     else  | 
3328  | 0  | #endif  | 
3329  | 0  | #ifdef HAVE_LCHOWN  | 
3330  | 0  |     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))  | 
3331  | 0  |         result = lchown(path->narrow, uid, gid);  | 
3332  | 0  |     else  | 
3333  | 0  | #endif  | 
3334  | 0  | #ifdef HAVE_FCHOWNAT  | 
3335  | 0  |     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))  | 
3336  | 0  |         result = fchownat(dir_fd, path->narrow, uid, gid,  | 
3337  | 0  |                           follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);  | 
3338  | 0  |     else  | 
3339  | 0  | #endif  | 
3340  | 0  |         result = chown(path->narrow, uid, gid);  | 
3341  | 0  |     Py_END_ALLOW_THREADS  | 
3342  |  | 
  | 
3343  | 0  |     if (result)  | 
3344  | 0  |         return path_error(path);  | 
3345  |  |  | 
3346  | 0  |     Py_RETURN_NONE;  | 
3347  | 0  | }  | 
3348  |  | #endif /* HAVE_CHOWN */  | 
3349  |  |  | 
3350  |  |  | 
3351  |  | #ifdef HAVE_FCHOWN  | 
3352  |  | /*[clinic input]  | 
3353  |  | os.fchown  | 
3354  |  |  | 
3355  |  |     fd: int  | 
3356  |  |     uid: uid_t  | 
3357  |  |     gid: gid_t  | 
3358  |  |  | 
3359  |  | Change the owner and group id of the file specified by file descriptor.  | 
3360  |  |  | 
3361  |  | Equivalent to os.chown(fd, uid, gid).  | 
3362  |  |  | 
3363  |  | [clinic start generated code]*/  | 
3364  |  |  | 
3365  |  | static PyObject *  | 
3366  |  | os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)  | 
3367  |  | /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/  | 
3368  | 0  | { | 
3369  | 0  |     int res;  | 
3370  | 0  |     int async_err = 0;  | 
3371  |  | 
  | 
3372  | 0  |     if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) { | 
3373  | 0  |         return NULL;  | 
3374  | 0  |     }  | 
3375  |  |  | 
3376  | 0  |     do { | 
3377  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
3378  | 0  |         res = fchown(fd, uid, gid);  | 
3379  | 0  |         Py_END_ALLOW_THREADS  | 
3380  | 0  |     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
3381  | 0  |     if (res != 0)  | 
3382  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
3383  |  |  | 
3384  | 0  |     Py_RETURN_NONE;  | 
3385  | 0  | }  | 
3386  |  | #endif /* HAVE_FCHOWN */  | 
3387  |  |  | 
3388  |  |  | 
3389  |  | #ifdef HAVE_LCHOWN  | 
3390  |  | /*[clinic input]  | 
3391  |  | os.lchown  | 
3392  |  |  | 
3393  |  |     path : path_t  | 
3394  |  |     uid: uid_t  | 
3395  |  |     gid: gid_t  | 
3396  |  |  | 
3397  |  | Change the owner and group id of path to the numeric uid and gid.  | 
3398  |  |  | 
3399  |  | This function will not follow symbolic links.  | 
3400  |  | Equivalent to os.chown(path, uid, gid, follow_symlinks=False).  | 
3401  |  | [clinic start generated code]*/  | 
3402  |  |  | 
3403  |  | static PyObject *  | 
3404  |  | os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)  | 
3405  |  | /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/  | 
3406  | 0  | { | 
3407  | 0  |     int res;  | 
3408  | 0  |     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) { | 
3409  | 0  |         return NULL;  | 
3410  | 0  |     }  | 
3411  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
3412  | 0  |     res = lchown(path->narrow, uid, gid);  | 
3413  | 0  |     Py_END_ALLOW_THREADS  | 
3414  | 0  |     if (res < 0) { | 
3415  | 0  |         return path_error(path);  | 
3416  | 0  |     }  | 
3417  | 0  |     Py_RETURN_NONE;  | 
3418  | 0  | }  | 
3419  |  | #endif /* HAVE_LCHOWN */  | 
3420  |  |  | 
3421  |  |  | 
3422  |  | static PyObject *  | 
3423  |  | posix_getcwd(int use_bytes)  | 
3424  | 0  | { | 
3425  |  | #ifdef MS_WINDOWS  | 
3426  |  |     wchar_t wbuf[MAXPATHLEN];  | 
3427  |  |     wchar_t *wbuf2 = wbuf;  | 
3428  |  |     DWORD len;  | 
3429  |  |  | 
3430  |  |     Py_BEGIN_ALLOW_THREADS  | 
3431  |  |     len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);  | 
3432  |  |     /* If the buffer is large enough, len does not include the  | 
3433  |  |        terminating \0. If the buffer is too small, len includes  | 
3434  |  |        the space needed for the terminator. */  | 
3435  |  |     if (len >= Py_ARRAY_LENGTH(wbuf)) { | 
3436  |  |         if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) { | 
3437  |  |             wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));  | 
3438  |  |         }  | 
3439  |  |         else { | 
3440  |  |             wbuf2 = NULL;  | 
3441  |  |         }  | 
3442  |  |         if (wbuf2) { | 
3443  |  |             len = GetCurrentDirectoryW(len, wbuf2);  | 
3444  |  |         }  | 
3445  |  |     }  | 
3446  |  |     Py_END_ALLOW_THREADS  | 
3447  |  |  | 
3448  |  |     if (!wbuf2) { | 
3449  |  |         PyErr_NoMemory();  | 
3450  |  |         return NULL;  | 
3451  |  |     }  | 
3452  |  |     if (!len) { | 
3453  |  |         if (wbuf2 != wbuf)  | 
3454  |  |             PyMem_RawFree(wbuf2);  | 
3455  |  |         return PyErr_SetFromWindowsErr(0);  | 
3456  |  |     }  | 
3457  |  |  | 
3458  |  |     PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);  | 
3459  |  |     if (wbuf2 != wbuf) { | 
3460  |  |         PyMem_RawFree(wbuf2);  | 
3461  |  |     }  | 
3462  |  |  | 
3463  |  |     if (use_bytes) { | 
3464  |  |         if (resobj == NULL) { | 
3465  |  |             return NULL;  | 
3466  |  |         }  | 
3467  |  |         Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));  | 
3468  |  |     }  | 
3469  |  |  | 
3470  |  |     return resobj;  | 
3471  |  | #else  | 
3472  | 0  |     const size_t chunk = 1024;  | 
3473  |  | 
  | 
3474  | 0  |     char *buf = NULL;  | 
3475  | 0  |     char *cwd = NULL;  | 
3476  | 0  |     size_t buflen = 0;  | 
3477  |  | 
  | 
3478  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
3479  | 0  |     do { | 
3480  | 0  |         char *newbuf;  | 
3481  | 0  |         if (buflen <= PY_SSIZE_T_MAX - chunk) { | 
3482  | 0  |             buflen += chunk;  | 
3483  | 0  |             newbuf = PyMem_RawRealloc(buf, buflen);  | 
3484  | 0  |         }  | 
3485  | 0  |         else { | 
3486  | 0  |             newbuf = NULL;  | 
3487  | 0  |         }  | 
3488  | 0  |         if (newbuf == NULL) { | 
3489  | 0  |             PyMem_RawFree(buf);  | 
3490  | 0  |             buf = NULL;  | 
3491  | 0  |             break;  | 
3492  | 0  |         }  | 
3493  | 0  |         buf = newbuf;  | 
3494  |  | 
  | 
3495  | 0  |         cwd = getcwd(buf, buflen);  | 
3496  | 0  |     } while (cwd == NULL && errno == ERANGE);  | 
3497  | 0  |     Py_END_ALLOW_THREADS  | 
3498  |  | 
  | 
3499  | 0  |     if (buf == NULL) { | 
3500  | 0  |         return PyErr_NoMemory();  | 
3501  | 0  |     }  | 
3502  | 0  |     if (cwd == NULL) { | 
3503  | 0  |         PyMem_RawFree(buf);  | 
3504  | 0  |         return posix_error();  | 
3505  | 0  |     }  | 
3506  |  |  | 
3507  | 0  |     PyObject *obj;  | 
3508  | 0  |     if (use_bytes) { | 
3509  | 0  |         obj = PyBytes_FromStringAndSize(buf, strlen(buf));  | 
3510  | 0  |     }  | 
3511  | 0  |     else { | 
3512  | 0  |         obj = PyUnicode_DecodeFSDefault(buf);  | 
3513  | 0  |     }  | 
3514  | 0  |     PyMem_RawFree(buf);  | 
3515  |  | 
  | 
3516  | 0  |     return obj;  | 
3517  | 0  | #endif   /* !MS_WINDOWS */  | 
3518  | 0  | }  | 
3519  |  |  | 
3520  |  |  | 
3521  |  | /*[clinic input]  | 
3522  |  | os.getcwd  | 
3523  |  |  | 
3524  |  | Return a unicode string representing the current working directory.  | 
3525  |  | [clinic start generated code]*/  | 
3526  |  |  | 
3527  |  | static PyObject *  | 
3528  |  | os_getcwd_impl(PyObject *module)  | 
3529  |  | /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/  | 
3530  | 0  | { | 
3531  | 0  |     return posix_getcwd(0);  | 
3532  | 0  | }  | 
3533  |  |  | 
3534  |  |  | 
3535  |  | /*[clinic input]  | 
3536  |  | os.getcwdb  | 
3537  |  |  | 
3538  |  | Return a bytes string representing the current working directory.  | 
3539  |  | [clinic start generated code]*/  | 
3540  |  |  | 
3541  |  | static PyObject *  | 
3542  |  | os_getcwdb_impl(PyObject *module)  | 
3543  |  | /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/  | 
3544  | 0  | { | 
3545  | 0  |     return posix_getcwd(1);  | 
3546  | 0  | }  | 
3547  |  |  | 
3548  |  |  | 
3549  |  | #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))  | 
3550  |  | #define HAVE_LINK 1  | 
3551  |  | #endif  | 
3552  |  |  | 
3553  |  | #ifdef HAVE_LINK  | 
3554  |  | /*[clinic input]  | 
3555  |  |  | 
3556  |  | os.link  | 
3557  |  |  | 
3558  |  |     src : path_t  | 
3559  |  |     dst : path_t  | 
3560  |  |     *  | 
3561  |  |     src_dir_fd : dir_fd = None  | 
3562  |  |     dst_dir_fd : dir_fd = None  | 
3563  |  |     follow_symlinks: bool = True  | 
3564  |  |  | 
3565  |  | Create a hard link to a file.  | 
3566  |  |  | 
3567  |  | If either src_dir_fd or dst_dir_fd is not None, it should be a file  | 
3568  |  |   descriptor open to a directory, and the respective path string (src or dst)  | 
3569  |  |   should be relative; the path will then be relative to that directory.  | 
3570  |  | If follow_symlinks is False, and the last element of src is a symbolic  | 
3571  |  |   link, link will create a link to the symbolic link itself instead of the  | 
3572  |  |   file the link points to.  | 
3573  |  | src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your  | 
3574  |  |   platform.  If they are unavailable, using them will raise a  | 
3575  |  |   NotImplementedError.  | 
3576  |  | [clinic start generated code]*/  | 
3577  |  |  | 
3578  |  | static PyObject *  | 
3579  |  | os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,  | 
3580  |  |              int dst_dir_fd, int follow_symlinks)  | 
3581  |  | /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/  | 
3582  | 0  | { | 
3583  |  | #ifdef MS_WINDOWS  | 
3584  |  |     BOOL result = FALSE;  | 
3585  |  | #else  | 
3586  | 0  |     int result;  | 
3587  | 0  | #endif  | 
3588  |  | 
  | 
3589  |  | #ifndef HAVE_LINKAT  | 
3590  |  |     if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) { | 
3591  |  |         argument_unavailable_error("link", "src_dir_fd and dst_dir_fd"); | 
3592  |  |         return NULL;  | 
3593  |  |     }  | 
3594  |  | #endif  | 
3595  |  | 
  | 
3596  | 0  | #ifndef MS_WINDOWS  | 
3597  | 0  |     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { | 
3598  | 0  |         PyErr_SetString(PyExc_NotImplementedError,  | 
3599  | 0  |                         "link: src and dst must be the same type");  | 
3600  | 0  |         return NULL;  | 
3601  | 0  |     }  | 
3602  | 0  | #endif  | 
3603  |  |  | 
3604  | 0  |     if (PySys_Audit("os.link", "OOii", src->object, dst->object, | 
3605  | 0  |                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,  | 
3606  | 0  |                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) { | 
3607  | 0  |         return NULL;  | 
3608  | 0  |     }  | 
3609  |  |  | 
3610  |  | #ifdef MS_WINDOWS  | 
3611  |  |     Py_BEGIN_ALLOW_THREADS  | 
3612  |  |     result = CreateHardLinkW(dst->wide, src->wide, NULL);  | 
3613  |  |     Py_END_ALLOW_THREADS  | 
3614  |  |  | 
3615  |  |     if (!result)  | 
3616  |  |         return path_error2(src, dst);  | 
3617  |  | #else  | 
3618  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
3619  | 0  | #ifdef HAVE_LINKAT  | 
3620  | 0  |     if ((src_dir_fd != DEFAULT_DIR_FD) ||  | 
3621  | 0  |         (dst_dir_fd != DEFAULT_DIR_FD) ||  | 
3622  | 0  |         (!follow_symlinks))  | 
3623  | 0  |         result = linkat(src_dir_fd, src->narrow,  | 
3624  | 0  |             dst_dir_fd, dst->narrow,  | 
3625  | 0  |             follow_symlinks ? AT_SYMLINK_FOLLOW : 0);  | 
3626  | 0  |     else  | 
3627  | 0  | #endif /* HAVE_LINKAT */  | 
3628  | 0  |         result = link(src->narrow, dst->narrow);  | 
3629  | 0  |     Py_END_ALLOW_THREADS  | 
3630  |  | 
  | 
3631  | 0  |     if (result)  | 
3632  | 0  |         return path_error2(src, dst);  | 
3633  | 0  | #endif /* MS_WINDOWS */  | 
3634  |  |  | 
3635  | 0  |     Py_RETURN_NONE;  | 
3636  | 0  | }  | 
3637  |  | #endif  | 
3638  |  |  | 
3639  |  |  | 
3640  |  | #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)  | 
3641  |  | static PyObject *  | 
3642  |  | _listdir_windows_no_opendir(path_t *path, PyObject *list)  | 
3643  |  | { | 
3644  |  |     PyObject *v;  | 
3645  |  |     HANDLE hFindFile = INVALID_HANDLE_VALUE;  | 
3646  |  |     BOOL result;  | 
3647  |  |     wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */  | 
3648  |  |     /* only claim to have space for MAX_PATH */  | 
3649  |  |     Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;  | 
3650  |  |     wchar_t *wnamebuf = NULL;  | 
3651  |  |  | 
3652  |  |     WIN32_FIND_DATAW wFileData;  | 
3653  |  |     const wchar_t *po_wchars;  | 
3654  |  |  | 
3655  |  |     if (!path->wide) { /* Default arg: "." */ | 
3656  |  |         po_wchars = L".";  | 
3657  |  |         len = 1;  | 
3658  |  |     } else { | 
3659  |  |         po_wchars = path->wide;  | 
3660  |  |         len = wcslen(path->wide);  | 
3661  |  |     }  | 
3662  |  |     /* The +5 is so we can append "\\*.*\0" */  | 
3663  |  |     wnamebuf = PyMem_New(wchar_t, len + 5);  | 
3664  |  |     if (!wnamebuf) { | 
3665  |  |         PyErr_NoMemory();  | 
3666  |  |         goto exit;  | 
3667  |  |     }  | 
3668  |  |     wcscpy(wnamebuf, po_wchars);  | 
3669  |  |     if (len > 0) { | 
3670  |  |         wchar_t wch = wnamebuf[len-1];  | 
3671  |  |         if (wch != SEP && wch != ALTSEP && wch != L':')  | 
3672  |  |             wnamebuf[len++] = SEP;  | 
3673  |  |         wcscpy(wnamebuf + len, L"*.*");  | 
3674  |  |     }  | 
3675  |  |     if ((list = PyList_New(0)) == NULL) { | 
3676  |  |         goto exit;  | 
3677  |  |     }  | 
3678  |  |     Py_BEGIN_ALLOW_THREADS  | 
3679  |  |     hFindFile = FindFirstFileW(wnamebuf, &wFileData);  | 
3680  |  |     Py_END_ALLOW_THREADS  | 
3681  |  |     if (hFindFile == INVALID_HANDLE_VALUE) { | 
3682  |  |         int error = GetLastError();  | 
3683  |  |         if (error == ERROR_FILE_NOT_FOUND)  | 
3684  |  |             goto exit;  | 
3685  |  |         Py_DECREF(list);  | 
3686  |  |         list = path_error(path);  | 
3687  |  |         goto exit;  | 
3688  |  |     }  | 
3689  |  |     do { | 
3690  |  |         /* Skip over . and .. */  | 
3691  |  |         if (wcscmp(wFileData.cFileName, L".") != 0 &&  | 
3692  |  |             wcscmp(wFileData.cFileName, L"..") != 0) { | 
3693  |  |             v = PyUnicode_FromWideChar(wFileData.cFileName,  | 
3694  |  |                                        wcslen(wFileData.cFileName));  | 
3695  |  |             if (path->narrow && v) { | 
3696  |  |                 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));  | 
3697  |  |             }  | 
3698  |  |             if (v == NULL) { | 
3699  |  |                 Py_DECREF(list);  | 
3700  |  |                 list = NULL;  | 
3701  |  |                 break;  | 
3702  |  |             }  | 
3703  |  |             if (PyList_Append(list, v) != 0) { | 
3704  |  |                 Py_DECREF(v);  | 
3705  |  |                 Py_DECREF(list);  | 
3706  |  |                 list = NULL;  | 
3707  |  |                 break;  | 
3708  |  |             }  | 
3709  |  |             Py_DECREF(v);  | 
3710  |  |         }  | 
3711  |  |         Py_BEGIN_ALLOW_THREADS  | 
3712  |  |         result = FindNextFileW(hFindFile, &wFileData);  | 
3713  |  |         Py_END_ALLOW_THREADS  | 
3714  |  |         /* FindNextFile sets error to ERROR_NO_MORE_FILES if  | 
3715  |  |            it got to the end of the directory. */  | 
3716  |  |         if (!result && GetLastError() != ERROR_NO_MORE_FILES) { | 
3717  |  |             Py_DECREF(list);  | 
3718  |  |             list = path_error(path);  | 
3719  |  |             goto exit;  | 
3720  |  |         }  | 
3721  |  |     } while (result == TRUE);  | 
3722  |  |  | 
3723  |  | exit:  | 
3724  |  |     if (hFindFile != INVALID_HANDLE_VALUE) { | 
3725  |  |         if (FindClose(hFindFile) == FALSE) { | 
3726  |  |             if (list != NULL) { | 
3727  |  |                 Py_DECREF(list);  | 
3728  |  |                 list = path_error(path);  | 
3729  |  |             }  | 
3730  |  |         }  | 
3731  |  |     }  | 
3732  |  |     PyMem_Free(wnamebuf);  | 
3733  |  |  | 
3734  |  |     return list;  | 
3735  |  | }  /* end of _listdir_windows_no_opendir */  | 
3736  |  |  | 
3737  |  | #else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */  | 
3738  |  |  | 
3739  |  | static PyObject *  | 
3740  |  | _posix_listdir(path_t *path, PyObject *list)  | 
3741  | 29  | { | 
3742  | 29  |     PyObject *v;  | 
3743  | 29  |     DIR *dirp = NULL;  | 
3744  | 29  |     struct dirent *ep;  | 
3745  | 29  |     int return_str; /* if false, return bytes */  | 
3746  | 29  | #ifdef HAVE_FDOPENDIR  | 
3747  | 29  |     int fd = -1;  | 
3748  | 29  | #endif  | 
3749  |  |  | 
3750  | 29  |     errno = 0;  | 
3751  | 29  | #ifdef HAVE_FDOPENDIR  | 
3752  | 29  |     if (path->fd != -1) { | 
3753  |  |         /* closedir() closes the FD, so we duplicate it */  | 
3754  | 0  |         fd = _Py_dup(path->fd);  | 
3755  | 0  |         if (fd == -1)  | 
3756  | 0  |             return NULL;  | 
3757  |  |  | 
3758  | 0  |         return_str = 1;  | 
3759  |  | 
  | 
3760  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
3761  | 0  |         dirp = fdopendir(fd);  | 
3762  | 0  |         Py_END_ALLOW_THREADS  | 
3763  | 0  |     }  | 
3764  | 29  |     else  | 
3765  | 29  | #endif  | 
3766  | 29  |     { | 
3767  | 29  |         const char *name;  | 
3768  | 29  |         if (path->narrow) { | 
3769  | 29  |             name = path->narrow;  | 
3770  |  |             /* only return bytes if they specified a bytes-like object */  | 
3771  | 29  |             return_str = !PyObject_CheckBuffer(path->object);  | 
3772  | 29  |         }  | 
3773  | 0  |         else { | 
3774  | 0  |             name = ".";  | 
3775  | 0  |             return_str = 1;  | 
3776  | 0  |         }  | 
3777  |  |  | 
3778  | 29  |         Py_BEGIN_ALLOW_THREADS  | 
3779  | 29  |         dirp = opendir(name);  | 
3780  | 29  |         Py_END_ALLOW_THREADS  | 
3781  | 29  |     }  | 
3782  |  |  | 
3783  | 29  |     if (dirp == NULL) { | 
3784  | 0  |         list = path_error(path);  | 
3785  | 0  | #ifdef HAVE_FDOPENDIR  | 
3786  | 0  |         if (fd != -1) { | 
3787  | 0  |             Py_BEGIN_ALLOW_THREADS  | 
3788  | 0  |             close(fd);  | 
3789  | 0  |             Py_END_ALLOW_THREADS  | 
3790  | 0  |         }  | 
3791  | 0  | #endif  | 
3792  | 0  |         goto exit;  | 
3793  | 0  |     }  | 
3794  | 29  |     if ((list = PyList_New(0)) == NULL) { | 
3795  | 0  |         goto exit;  | 
3796  | 0  |     }  | 
3797  | 4.71k  |     for (;;) { | 
3798  | 4.71k  |         errno = 0;  | 
3799  | 4.71k  |         Py_BEGIN_ALLOW_THREADS  | 
3800  | 4.71k  |         ep = readdir(dirp);  | 
3801  | 4.71k  |         Py_END_ALLOW_THREADS  | 
3802  | 4.71k  |         if (ep == NULL) { | 
3803  | 29  |             if (errno == 0) { | 
3804  | 29  |                 break;  | 
3805  | 29  |             } else { | 
3806  | 0  |                 Py_DECREF(list);  | 
3807  | 0  |                 list = path_error(path);  | 
3808  | 0  |                 goto exit;  | 
3809  | 0  |             }  | 
3810  | 29  |         }  | 
3811  | 4.68k  |         if (ep->d_name[0] == '.' &&  | 
3812  | 58  |             (NAMLEN(ep) == 1 ||  | 
3813  | 29  |              (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))  | 
3814  | 58  |             continue;  | 
3815  | 4.62k  |         if (return_str)  | 
3816  | 4.62k  |             v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));  | 
3817  | 0  |         else  | 
3818  | 0  |             v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));  | 
3819  | 4.62k  |         if (v == NULL) { | 
3820  | 0  |             Py_CLEAR(list);  | 
3821  | 0  |             break;  | 
3822  | 0  |         }  | 
3823  | 4.62k  |         if (PyList_Append(list, v) != 0) { | 
3824  | 0  |             Py_DECREF(v);  | 
3825  | 0  |             Py_CLEAR(list);  | 
3826  | 0  |             break;  | 
3827  | 0  |         }  | 
3828  | 4.62k  |         Py_DECREF(v);  | 
3829  | 4.62k  |     }  | 
3830  |  |  | 
3831  | 29  | exit:  | 
3832  | 29  |     if (dirp != NULL) { | 
3833  | 29  |         Py_BEGIN_ALLOW_THREADS  | 
3834  | 29  | #ifdef HAVE_FDOPENDIR  | 
3835  | 29  |         if (fd > -1)  | 
3836  | 0  |             rewinddir(dirp);  | 
3837  | 29  | #endif  | 
3838  | 29  |         closedir(dirp);  | 
3839  | 29  |         Py_END_ALLOW_THREADS  | 
3840  | 29  |     }  | 
3841  |  |  | 
3842  | 29  |     return list;  | 
3843  | 29  | }  /* end of _posix_listdir */  | 
3844  |  | #endif  /* which OS */  | 
3845  |  |  | 
3846  |  |  | 
3847  |  | /*[clinic input]  | 
3848  |  | os.listdir  | 
3849  |  |  | 
3850  |  |     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None  | 
3851  |  |  | 
3852  |  | Return a list containing the names of the files in the directory.  | 
3853  |  |  | 
3854  |  | path can be specified as either str, bytes, or a path-like object.  If path is bytes,  | 
3855  |  |   the filenames returned will also be bytes; in all other circumstances  | 
3856  |  |   the filenames returned will be str.  | 
3857  |  | If path is None, uses the path='.'.  | 
3858  |  | On some platforms, path may also be specified as an open file descriptor;\  | 
3859  |  |   the file descriptor must refer to a directory.  | 
3860  |  |   If this functionality is unavailable, using it raises NotImplementedError.  | 
3861  |  |  | 
3862  |  | The list is in arbitrary order.  It does not include the special  | 
3863  |  | entries '.' and '..' even if they are present in the directory.  | 
3864  |  |  | 
3865  |  |  | 
3866  |  | [clinic start generated code]*/  | 
3867  |  |  | 
3868  |  | static PyObject *  | 
3869  |  | os_listdir_impl(PyObject *module, path_t *path)  | 
3870  |  | /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/  | 
3871  | 29  | { | 
3872  | 29  |     if (PySys_Audit("os.listdir", "O", | 
3873  | 29  |                     path->object ? path->object : Py_None) < 0) { | 
3874  | 0  |         return NULL;  | 
3875  | 0  |     }  | 
3876  |  | #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)  | 
3877  |  |     return _listdir_windows_no_opendir(path, NULL);  | 
3878  |  | #else  | 
3879  | 29  |     return _posix_listdir(path, NULL);  | 
3880  | 29  | #endif  | 
3881  | 29  | }  | 
3882  |  |  | 
3883  |  | #ifdef MS_WINDOWS  | 
3884  |  | /* A helper function for abspath on win32 */  | 
3885  |  | /*[clinic input]  | 
3886  |  | os._getfullpathname  | 
3887  |  |  | 
3888  |  |     path: path_t  | 
3889  |  |     /  | 
3890  |  |  | 
3891  |  | [clinic start generated code]*/  | 
3892  |  |  | 
3893  |  | static PyObject *  | 
3894  |  | os__getfullpathname_impl(PyObject *module, path_t *path)  | 
3895  |  | /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/  | 
3896  |  | { | 
3897  |  |     wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;  | 
3898  |  |     wchar_t *wtemp;  | 
3899  |  |     DWORD result;  | 
3900  |  |     PyObject *v;  | 
3901  |  |  | 
3902  |  |     result = GetFullPathNameW(path->wide,  | 
3903  |  |                               Py_ARRAY_LENGTH(woutbuf),  | 
3904  |  |                               woutbuf, &wtemp);  | 
3905  |  |     if (result > Py_ARRAY_LENGTH(woutbuf)) { | 
3906  |  |         woutbufp = PyMem_New(wchar_t, result);  | 
3907  |  |         if (!woutbufp)  | 
3908  |  |             return PyErr_NoMemory();  | 
3909  |  |         result = GetFullPathNameW(path->wide, result, woutbufp, &wtemp);  | 
3910  |  |     }  | 
3911  |  |     if (result) { | 
3912  |  |         v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp));  | 
3913  |  |         if (path->narrow)  | 
3914  |  |             Py_SETREF(v, PyUnicode_EncodeFSDefault(v));  | 
3915  |  |     } else  | 
3916  |  |         v = win32_error_object("GetFullPathNameW", path->object); | 
3917  |  |     if (woutbufp != woutbuf)  | 
3918  |  |         PyMem_Free(woutbufp);  | 
3919  |  |     return v;  | 
3920  |  | }  | 
3921  |  |  | 
3922  |  |  | 
3923  |  | /*[clinic input]  | 
3924  |  | os._getfinalpathname  | 
3925  |  |  | 
3926  |  |     path: path_t  | 
3927  |  |     /  | 
3928  |  |  | 
3929  |  | A helper function for samepath on windows.  | 
3930  |  | [clinic start generated code]*/  | 
3931  |  |  | 
3932  |  | static PyObject *  | 
3933  |  | os__getfinalpathname_impl(PyObject *module, path_t *path)  | 
3934  |  | /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/  | 
3935  |  | { | 
3936  |  |     HANDLE hFile;  | 
3937  |  |     wchar_t buf[MAXPATHLEN], *target_path = buf;  | 
3938  |  |     int buf_size = Py_ARRAY_LENGTH(buf);  | 
3939  |  |     int result_length;  | 
3940  |  |     PyObject *result;  | 
3941  |  |  | 
3942  |  |     Py_BEGIN_ALLOW_THREADS  | 
3943  |  |     hFile = CreateFileW(  | 
3944  |  |         path->wide,  | 
3945  |  |         0, /* desired access */  | 
3946  |  |         0, /* share mode */  | 
3947  |  |         NULL, /* security attributes */  | 
3948  |  |         OPEN_EXISTING,  | 
3949  |  |         /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */  | 
3950  |  |         FILE_FLAG_BACKUP_SEMANTICS,  | 
3951  |  |         NULL);  | 
3952  |  |     Py_END_ALLOW_THREADS  | 
3953  |  |  | 
3954  |  |     if (hFile == INVALID_HANDLE_VALUE) { | 
3955  |  |         return win32_error_object("CreateFileW", path->object); | 
3956  |  |     }  | 
3957  |  |  | 
3958  |  |     /* We have a good handle to the target, use it to determine the  | 
3959  |  |        target path name. */  | 
3960  |  |     while (1) { | 
3961  |  |         Py_BEGIN_ALLOW_THREADS  | 
3962  |  |         result_length = GetFinalPathNameByHandleW(hFile, target_path,  | 
3963  |  |                                                   buf_size, VOLUME_NAME_DOS);  | 
3964  |  |         Py_END_ALLOW_THREADS  | 
3965  |  |  | 
3966  |  |         if (!result_length) { | 
3967  |  |             result = win32_error_object("GetFinalPathNameByHandleW", | 
3968  |  |                                          path->object);  | 
3969  |  |             goto cleanup;  | 
3970  |  |         }  | 
3971  |  |  | 
3972  |  |         if (result_length < buf_size) { | 
3973  |  |             break;  | 
3974  |  |         }  | 
3975  |  |  | 
3976  |  |         wchar_t *tmp;  | 
3977  |  |         tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,  | 
3978  |  |                             result_length * sizeof(*tmp));  | 
3979  |  |         if (!tmp) { | 
3980  |  |             result = PyErr_NoMemory();  | 
3981  |  |             goto cleanup;  | 
3982  |  |         }  | 
3983  |  |  | 
3984  |  |         buf_size = result_length;  | 
3985  |  |         target_path = tmp;  | 
3986  |  |     }  | 
3987  |  |  | 
3988  |  |     result = PyUnicode_FromWideChar(target_path, result_length);  | 
3989  |  |     if (result && path->narrow) { | 
3990  |  |         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));  | 
3991  |  |     }  | 
3992  |  |  | 
3993  |  | cleanup:  | 
3994  |  |     if (target_path != buf) { | 
3995  |  |         PyMem_Free(target_path);  | 
3996  |  |     }  | 
3997  |  |     CloseHandle(hFile);  | 
3998  |  |     return result;  | 
3999  |  | }  | 
4000  |  |  | 
4001  |  |  | 
4002  |  | /*[clinic input]  | 
4003  |  | os._getvolumepathname  | 
4004  |  |  | 
4005  |  |     path: path_t  | 
4006  |  |  | 
4007  |  | A helper function for ismount on Win32.  | 
4008  |  | [clinic start generated code]*/  | 
4009  |  |  | 
4010  |  | static PyObject *  | 
4011  |  | os__getvolumepathname_impl(PyObject *module, path_t *path)  | 
4012  |  | /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/  | 
4013  |  | { | 
4014  |  |     PyObject *result;  | 
4015  |  |     wchar_t *mountpath=NULL;  | 
4016  |  |     size_t buflen;  | 
4017  |  |     BOOL ret;  | 
4018  |  |  | 
4019  |  |     /* Volume path should be shorter than entire path */  | 
4020  |  |     buflen = Py_MAX(path->length, MAX_PATH);  | 
4021  |  |  | 
4022  |  |     if (buflen > PY_DWORD_MAX) { | 
4023  |  |         PyErr_SetString(PyExc_OverflowError, "path too long");  | 
4024  |  |         return NULL;  | 
4025  |  |     }  | 
4026  |  |  | 
4027  |  |     mountpath = PyMem_New(wchar_t, buflen);  | 
4028  |  |     if (mountpath == NULL)  | 
4029  |  |         return PyErr_NoMemory();  | 
4030  |  |  | 
4031  |  |     Py_BEGIN_ALLOW_THREADS  | 
4032  |  |     ret = GetVolumePathNameW(path->wide, mountpath,  | 
4033  |  |                              Py_SAFE_DOWNCAST(buflen, size_t, DWORD));  | 
4034  |  |     Py_END_ALLOW_THREADS  | 
4035  |  |  | 
4036  |  |     if (!ret) { | 
4037  |  |         result = win32_error_object("_getvolumepathname", path->object); | 
4038  |  |         goto exit;  | 
4039  |  |     }  | 
4040  |  |     result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));  | 
4041  |  |     if (path->narrow)  | 
4042  |  |         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));  | 
4043  |  |  | 
4044  |  | exit:  | 
4045  |  |     PyMem_Free(mountpath);  | 
4046  |  |     return result;  | 
4047  |  | }  | 
4048  |  |  | 
4049  |  | #endif /* MS_WINDOWS */  | 
4050  |  |  | 
4051  |  |  | 
4052  |  | /*[clinic input]  | 
4053  |  | os.mkdir  | 
4054  |  |  | 
4055  |  |     path : path_t  | 
4056  |  |  | 
4057  |  |     mode: int = 0o777  | 
4058  |  |  | 
4059  |  |     *  | 
4060  |  |  | 
4061  |  |     dir_fd : dir_fd(requires='mkdirat') = None  | 
4062  |  |  | 
4063  |  | # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\  | 
4064  |  |  | 
4065  |  | Create a directory.  | 
4066  |  |  | 
4067  |  | If dir_fd is not None, it should be a file descriptor open to a directory,  | 
4068  |  |   and path should be relative; path will then be relative to that directory.  | 
4069  |  | dir_fd may not be implemented on your platform.  | 
4070  |  |   If it is unavailable, using it will raise a NotImplementedError.  | 
4071  |  |  | 
4072  |  | The mode argument is ignored on Windows.  | 
4073  |  | [clinic start generated code]*/  | 
4074  |  |  | 
4075  |  | static PyObject *  | 
4076  |  | os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)  | 
4077  |  | /*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/  | 
4078  | 0  | { | 
4079  | 0  |     int result;  | 
4080  |  | 
  | 
4081  | 0  |     if (PySys_Audit("os.mkdir", "Oii", path->object, mode, | 
4082  | 0  |                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { | 
4083  | 0  |         return NULL;  | 
4084  | 0  |     }  | 
4085  |  |  | 
4086  |  | #ifdef MS_WINDOWS  | 
4087  |  |     Py_BEGIN_ALLOW_THREADS  | 
4088  |  |     result = CreateDirectoryW(path->wide, NULL);  | 
4089  |  |     Py_END_ALLOW_THREADS  | 
4090  |  |  | 
4091  |  |     if (!result)  | 
4092  |  |         return path_error(path);  | 
4093  |  | #else  | 
4094  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
4095  | 0  | #if HAVE_MKDIRAT  | 
4096  | 0  |     if (dir_fd != DEFAULT_DIR_FD)  | 
4097  | 0  |         result = mkdirat(dir_fd, path->narrow, mode);  | 
4098  | 0  |     else  | 
4099  | 0  | #endif  | 
4100  |  | #if defined(__WATCOMC__) && !defined(__QNX__)  | 
4101  |  |         result = mkdir(path->narrow);  | 
4102  |  | #else  | 
4103  | 0  |         result = mkdir(path->narrow, mode);  | 
4104  | 0  | #endif  | 
4105  | 0  |     Py_END_ALLOW_THREADS  | 
4106  | 0  |     if (result < 0)  | 
4107  | 0  |         return path_error(path);  | 
4108  | 0  | #endif /* MS_WINDOWS */  | 
4109  | 0  |     Py_RETURN_NONE;  | 
4110  | 0  | }  | 
4111  |  |  | 
4112  |  |  | 
4113  |  | /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */  | 
4114  |  | #if defined(HAVE_SYS_RESOURCE_H)  | 
4115  |  | #include <sys/resource.h>  | 
4116  |  | #endif  | 
4117  |  |  | 
4118  |  |  | 
4119  |  | #ifdef HAVE_NICE  | 
4120  |  | /*[clinic input]  | 
4121  |  | os.nice  | 
4122  |  |  | 
4123  |  |     increment: int  | 
4124  |  |     /  | 
4125  |  |  | 
4126  |  | Add increment to the priority of process and return the new priority.  | 
4127  |  | [clinic start generated code]*/  | 
4128  |  |  | 
4129  |  | static PyObject *  | 
4130  |  | os_nice_impl(PyObject *module, int increment)  | 
4131  |  | /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/  | 
4132  | 0  | { | 
4133  | 0  |     int value;  | 
4134  |  |  | 
4135  |  |     /* There are two flavours of 'nice': one that returns the new  | 
4136  |  |        priority (as required by almost all standards out there) and the  | 
4137  |  |        Linux/FreeBSD one, which returns '0' on success and advices  | 
4138  |  |        the use of getpriority() to get the new priority.  | 
4139  |  |  | 
4140  |  |        If we are of the nice family that returns the new priority, we  | 
4141  |  |        need to clear errno before the call, and check if errno is filled  | 
4142  |  |        before calling posix_error() on a returnvalue of -1, because the  | 
4143  |  |        -1 may be the actual new priority! */  | 
4144  |  | 
  | 
4145  | 0  |     errno = 0;  | 
4146  | 0  |     value = nice(increment);  | 
4147  |  | #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)  | 
4148  |  |     if (value == 0)  | 
4149  |  |         value = getpriority(PRIO_PROCESS, 0);  | 
4150  |  | #endif  | 
4151  | 0  |     if (value == -1 && errno != 0)  | 
4152  |  |         /* either nice() or getpriority() returned an error */  | 
4153  | 0  |         return posix_error();  | 
4154  | 0  |     return PyLong_FromLong((long) value);  | 
4155  | 0  | }  | 
4156  |  | #endif /* HAVE_NICE */  | 
4157  |  |  | 
4158  |  |  | 
4159  |  | #ifdef HAVE_GETPRIORITY  | 
4160  |  | /*[clinic input]  | 
4161  |  | os.getpriority  | 
4162  |  |  | 
4163  |  |     which: int  | 
4164  |  |     who: int  | 
4165  |  |  | 
4166  |  | Return program scheduling priority.  | 
4167  |  | [clinic start generated code]*/  | 
4168  |  |  | 
4169  |  | static PyObject *  | 
4170  |  | os_getpriority_impl(PyObject *module, int which, int who)  | 
4171  |  | /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/  | 
4172  | 0  | { | 
4173  | 0  |     int retval;  | 
4174  |  | 
  | 
4175  | 0  |     errno = 0;  | 
4176  | 0  |     retval = getpriority(which, who);  | 
4177  | 0  |     if (errno != 0)  | 
4178  | 0  |         return posix_error();  | 
4179  | 0  |     return PyLong_FromLong((long)retval);  | 
4180  | 0  | }  | 
4181  |  | #endif /* HAVE_GETPRIORITY */  | 
4182  |  |  | 
4183  |  |  | 
4184  |  | #ifdef HAVE_SETPRIORITY  | 
4185  |  | /*[clinic input]  | 
4186  |  | os.setpriority  | 
4187  |  |  | 
4188  |  |     which: int  | 
4189  |  |     who: int  | 
4190  |  |     priority: int  | 
4191  |  |  | 
4192  |  | Set program scheduling priority.  | 
4193  |  | [clinic start generated code]*/  | 
4194  |  |  | 
4195  |  | static PyObject *  | 
4196  |  | os_setpriority_impl(PyObject *module, int which, int who, int priority)  | 
4197  |  | /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/  | 
4198  | 0  | { | 
4199  | 0  |     int retval;  | 
4200  |  | 
  | 
4201  | 0  |     retval = setpriority(which, who, priority);  | 
4202  | 0  |     if (retval == -1)  | 
4203  | 0  |         return posix_error();  | 
4204  | 0  |     Py_RETURN_NONE;  | 
4205  | 0  | }  | 
4206  |  | #endif /* HAVE_SETPRIORITY */  | 
4207  |  |  | 
4208  |  |  | 
4209  |  | static PyObject *  | 
4210  |  | internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)  | 
4211  | 0  | { | 
4212  | 0  |     const char *function_name = is_replace ? "replace" : "rename";  | 
4213  | 0  |     int dir_fd_specified;  | 
4214  |  | 
  | 
4215  |  | #ifdef MS_WINDOWS  | 
4216  |  |     BOOL result;  | 
4217  |  |     int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;  | 
4218  |  | #else  | 
4219  | 0  |     int result;  | 
4220  | 0  | #endif  | 
4221  |  | 
  | 
4222  | 0  |     dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||  | 
4223  | 0  |                        (dst_dir_fd != DEFAULT_DIR_FD);  | 
4224  |  | #ifndef HAVE_RENAMEAT  | 
4225  |  |     if (dir_fd_specified) { | 
4226  |  |         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");  | 
4227  |  |         return NULL;  | 
4228  |  |     }  | 
4229  |  | #endif  | 
4230  |  | 
  | 
4231  | 0  |     if (PySys_Audit("os.rename", "OOii", src->object, dst->object, | 
4232  | 0  |                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,  | 
4233  | 0  |                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) { | 
4234  | 0  |         return NULL;  | 
4235  | 0  |     }  | 
4236  |  |  | 
4237  |  | #ifdef MS_WINDOWS  | 
4238  |  |     Py_BEGIN_ALLOW_THREADS  | 
4239  |  |     result = MoveFileExW(src->wide, dst->wide, flags);  | 
4240  |  |     Py_END_ALLOW_THREADS  | 
4241  |  |  | 
4242  |  |     if (!result)  | 
4243  |  |         return path_error2(src, dst);  | 
4244  |  |  | 
4245  |  | #else  | 
4246  | 0  |     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { | 
4247  | 0  |         PyErr_Format(PyExc_ValueError,  | 
4248  | 0  |                      "%s: src and dst must be the same type", function_name);  | 
4249  | 0  |         return NULL;  | 
4250  | 0  |     }  | 
4251  |  |  | 
4252  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
4253  | 0  | #ifdef HAVE_RENAMEAT  | 
4254  | 0  |     if (dir_fd_specified)  | 
4255  | 0  |         result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);  | 
4256  | 0  |     else  | 
4257  | 0  | #endif  | 
4258  | 0  |     result = rename(src->narrow, dst->narrow);  | 
4259  | 0  |     Py_END_ALLOW_THREADS  | 
4260  |  | 
  | 
4261  | 0  |     if (result)  | 
4262  | 0  |         return path_error2(src, dst);  | 
4263  | 0  | #endif  | 
4264  | 0  |     Py_RETURN_NONE;  | 
4265  | 0  | }  | 
4266  |  |  | 
4267  |  |  | 
4268  |  | /*[clinic input]  | 
4269  |  | os.rename  | 
4270  |  |  | 
4271  |  |     src : path_t  | 
4272  |  |     dst : path_t  | 
4273  |  |     *  | 
4274  |  |     src_dir_fd : dir_fd = None  | 
4275  |  |     dst_dir_fd : dir_fd = None  | 
4276  |  |  | 
4277  |  | Rename a file or directory.  | 
4278  |  |  | 
4279  |  | If either src_dir_fd or dst_dir_fd is not None, it should be a file  | 
4280  |  |   descriptor open to a directory, and the respective path string (src or dst)  | 
4281  |  |   should be relative; the path will then be relative to that directory.  | 
4282  |  | src_dir_fd and dst_dir_fd, may not be implemented on your platform.  | 
4283  |  |   If they are unavailable, using them will raise a NotImplementedError.  | 
4284  |  | [clinic start generated code]*/  | 
4285  |  |  | 
4286  |  | static PyObject *  | 
4287  |  | os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,  | 
4288  |  |                int dst_dir_fd)  | 
4289  |  | /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/  | 
4290  | 0  | { | 
4291  | 0  |     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);  | 
4292  | 0  | }  | 
4293  |  |  | 
4294  |  |  | 
4295  |  | /*[clinic input]  | 
4296  |  | os.replace = os.rename  | 
4297  |  |  | 
4298  |  | Rename a file or directory, overwriting the destination.  | 
4299  |  |  | 
4300  |  | If either src_dir_fd or dst_dir_fd is not None, it should be a file  | 
4301  |  |   descriptor open to a directory, and the respective path string (src or dst)  | 
4302  |  |   should be relative; the path will then be relative to that directory.  | 
4303  |  | src_dir_fd and dst_dir_fd, may not be implemented on your platform.  | 
4304  |  |   If they are unavailable, using them will raise a NotImplementedError.  | 
4305  |  | [clinic start generated code]*/  | 
4306  |  |  | 
4307  |  | static PyObject *  | 
4308  |  | os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,  | 
4309  |  |                 int dst_dir_fd)  | 
4310  |  | /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/  | 
4311  | 0  | { | 
4312  | 0  |     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);  | 
4313  | 0  | }  | 
4314  |  |  | 
4315  |  |  | 
4316  |  | /*[clinic input]  | 
4317  |  | os.rmdir  | 
4318  |  |  | 
4319  |  |     path: path_t  | 
4320  |  |     *  | 
4321  |  |     dir_fd: dir_fd(requires='unlinkat') = None  | 
4322  |  |  | 
4323  |  | Remove a directory.  | 
4324  |  |  | 
4325  |  | If dir_fd is not None, it should be a file descriptor open to a directory,  | 
4326  |  |   and path should be relative; path will then be relative to that directory.  | 
4327  |  | dir_fd may not be implemented on your platform.  | 
4328  |  |   If it is unavailable, using it will raise a NotImplementedError.  | 
4329  |  | [clinic start generated code]*/  | 
4330  |  |  | 
4331  |  | static PyObject *  | 
4332  |  | os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)  | 
4333  |  | /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/  | 
4334  | 0  | { | 
4335  | 0  |     int result;  | 
4336  |  | 
  | 
4337  | 0  |     if (PySys_Audit("os.rmdir", "Oi", path->object, | 
4338  | 0  |                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { | 
4339  | 0  |         return NULL;  | 
4340  | 0  |     }  | 
4341  |  |  | 
4342  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
4343  |  | #ifdef MS_WINDOWS  | 
4344  |  |     /* Windows, success=1, UNIX, success=0 */  | 
4345  |  |     result = !RemoveDirectoryW(path->wide);  | 
4346  |  | #else  | 
4347  | 0  | #ifdef HAVE_UNLINKAT  | 
4348  | 0  |     if (dir_fd != DEFAULT_DIR_FD)  | 
4349  | 0  |         result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);  | 
4350  | 0  |     else  | 
4351  | 0  | #endif  | 
4352  | 0  |         result = rmdir(path->narrow);  | 
4353  | 0  | #endif  | 
4354  | 0  |     Py_END_ALLOW_THREADS  | 
4355  |  | 
  | 
4356  | 0  |     if (result)  | 
4357  | 0  |         return path_error(path);  | 
4358  |  |  | 
4359  | 0  |     Py_RETURN_NONE;  | 
4360  | 0  | }  | 
4361  |  |  | 
4362  |  |  | 
4363  |  | #ifdef HAVE_SYSTEM  | 
4364  |  | #ifdef MS_WINDOWS  | 
4365  |  | /*[clinic input]  | 
4366  |  | os.system -> long  | 
4367  |  |  | 
4368  |  |     command: Py_UNICODE  | 
4369  |  |  | 
4370  |  | Execute the command in a subshell.  | 
4371  |  | [clinic start generated code]*/  | 
4372  |  |  | 
4373  |  | static long  | 
4374  |  | os_system_impl(PyObject *module, const Py_UNICODE *command)  | 
4375  |  | /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/  | 
4376  |  | { | 
4377  |  |     long result;  | 
4378  |  |  | 
4379  |  |     if (PySys_Audit("os.system", "(u)", command) < 0) { | 
4380  |  |         return -1;  | 
4381  |  |     }  | 
4382  |  |  | 
4383  |  |     Py_BEGIN_ALLOW_THREADS  | 
4384  |  |     _Py_BEGIN_SUPPRESS_IPH  | 
4385  |  |     result = _wsystem(command);  | 
4386  |  |     _Py_END_SUPPRESS_IPH  | 
4387  |  |     Py_END_ALLOW_THREADS  | 
4388  |  |     return result;  | 
4389  |  | }  | 
4390  |  | #else /* MS_WINDOWS */  | 
4391  |  | /*[clinic input]  | 
4392  |  | os.system -> long  | 
4393  |  |  | 
4394  |  |     command: FSConverter  | 
4395  |  |  | 
4396  |  | Execute the command in a subshell.  | 
4397  |  | [clinic start generated code]*/  | 
4398  |  |  | 
4399  |  | static long  | 
4400  |  | os_system_impl(PyObject *module, PyObject *command)  | 
4401  |  | /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/  | 
4402  | 0  | { | 
4403  | 0  |     long result;  | 
4404  | 0  |     const char *bytes = PyBytes_AsString(command);  | 
4405  |  | 
  | 
4406  | 0  |     if (PySys_Audit("os.system", "(O)", command) < 0) { | 
4407  | 0  |         return -1;  | 
4408  | 0  |     }  | 
4409  |  |  | 
4410  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
4411  | 0  |     result = system(bytes);  | 
4412  | 0  |     Py_END_ALLOW_THREADS  | 
4413  | 0  |     return result;  | 
4414  | 0  | }  | 
4415  |  | #endif  | 
4416  |  | #endif /* HAVE_SYSTEM */  | 
4417  |  |  | 
4418  |  |  | 
4419  |  | /*[clinic input]  | 
4420  |  | os.umask  | 
4421  |  |  | 
4422  |  |     mask: int  | 
4423  |  |     /  | 
4424  |  |  | 
4425  |  | Set the current numeric umask and return the previous umask.  | 
4426  |  | [clinic start generated code]*/  | 
4427  |  |  | 
4428  |  | static PyObject *  | 
4429  |  | os_umask_impl(PyObject *module, int mask)  | 
4430  |  | /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/  | 
4431  | 0  | { | 
4432  | 0  |     int i = (int)umask(mask);  | 
4433  | 0  |     if (i < 0)  | 
4434  | 0  |         return posix_error();  | 
4435  | 0  |     return PyLong_FromLong((long)i);  | 
4436  | 0  | }  | 
4437  |  |  | 
4438  |  | #ifdef MS_WINDOWS  | 
4439  |  |  | 
4440  |  | /* override the default DeleteFileW behavior so that directory  | 
4441  |  | symlinks can be removed with this function, the same as with  | 
4442  |  | Unix symlinks */  | 
4443  |  | BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)  | 
4444  |  | { | 
4445  |  |     WIN32_FILE_ATTRIBUTE_DATA info;  | 
4446  |  |     WIN32_FIND_DATAW find_data;  | 
4447  |  |     HANDLE find_data_handle;  | 
4448  |  |     int is_directory = 0;  | 
4449  |  |     int is_link = 0;  | 
4450  |  |  | 
4451  |  |     if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) { | 
4452  |  |         is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;  | 
4453  |  |  | 
4454  |  |         /* Get WIN32_FIND_DATA structure for the path to determine if  | 
4455  |  |            it is a symlink */  | 
4456  |  |         if(is_directory &&  | 
4457  |  |            info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { | 
4458  |  |             find_data_handle = FindFirstFileW(lpFileName, &find_data);  | 
4459  |  |  | 
4460  |  |             if(find_data_handle != INVALID_HANDLE_VALUE) { | 
4461  |  |                 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and  | 
4462  |  |                    IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */  | 
4463  |  |                 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||  | 
4464  |  |                           find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;  | 
4465  |  |                 FindClose(find_data_handle);  | 
4466  |  |             }  | 
4467  |  |         }  | 
4468  |  |     }  | 
4469  |  |  | 
4470  |  |     if (is_directory && is_link)  | 
4471  |  |         return RemoveDirectoryW(lpFileName);  | 
4472  |  |  | 
4473  |  |     return DeleteFileW(lpFileName);  | 
4474  |  | }  | 
4475  |  | #endif /* MS_WINDOWS */  | 
4476  |  |  | 
4477  |  |  | 
4478  |  | /*[clinic input]  | 
4479  |  | os.unlink  | 
4480  |  |  | 
4481  |  |     path: path_t  | 
4482  |  |     *  | 
4483  |  |     dir_fd: dir_fd(requires='unlinkat')=None  | 
4484  |  |  | 
4485  |  | Remove a file (same as remove()).  | 
4486  |  |  | 
4487  |  | If dir_fd is not None, it should be a file descriptor open to a directory,  | 
4488  |  |   and path should be relative; path will then be relative to that directory.  | 
4489  |  | dir_fd may not be implemented on your platform.  | 
4490  |  |   If it is unavailable, using it will raise a NotImplementedError.  | 
4491  |  |  | 
4492  |  | [clinic start generated code]*/  | 
4493  |  |  | 
4494  |  | static PyObject *  | 
4495  |  | os_unlink_impl(PyObject *module, path_t *path, int dir_fd)  | 
4496  |  | /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/  | 
4497  | 0  | { | 
4498  | 0  |     int result;  | 
4499  |  | 
  | 
4500  | 0  |     if (PySys_Audit("os.remove", "Oi", path->object, | 
4501  | 0  |                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { | 
4502  | 0  |         return NULL;  | 
4503  | 0  |     }  | 
4504  |  |  | 
4505  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
4506  | 0  |     _Py_BEGIN_SUPPRESS_IPH  | 
4507  |  | #ifdef MS_WINDOWS  | 
4508  |  |     /* Windows, success=1, UNIX, success=0 */  | 
4509  |  |     result = !Py_DeleteFileW(path->wide);  | 
4510  |  | #else  | 
4511  | 0  | #ifdef HAVE_UNLINKAT  | 
4512  | 0  |     if (dir_fd != DEFAULT_DIR_FD)  | 
4513  | 0  |         result = unlinkat(dir_fd, path->narrow, 0);  | 
4514  | 0  |     else  | 
4515  | 0  | #endif /* HAVE_UNLINKAT */  | 
4516  | 0  |         result = unlink(path->narrow);  | 
4517  | 0  | #endif  | 
4518  | 0  |     _Py_END_SUPPRESS_IPH  | 
4519  | 0  |     Py_END_ALLOW_THREADS  | 
4520  |  | 
  | 
4521  | 0  |     if (result)  | 
4522  | 0  |         return path_error(path);  | 
4523  |  |  | 
4524  | 0  |     Py_RETURN_NONE;  | 
4525  | 0  | }  | 
4526  |  |  | 
4527  |  |  | 
4528  |  | /*[clinic input]  | 
4529  |  | os.remove = os.unlink  | 
4530  |  |  | 
4531  |  | Remove a file (same as unlink()).  | 
4532  |  |  | 
4533  |  | If dir_fd is not None, it should be a file descriptor open to a directory,  | 
4534  |  |   and path should be relative; path will then be relative to that directory.  | 
4535  |  | dir_fd may not be implemented on your platform.  | 
4536  |  |   If it is unavailable, using it will raise a NotImplementedError.  | 
4537  |  | [clinic start generated code]*/  | 
4538  |  |  | 
4539  |  | static PyObject *  | 
4540  |  | os_remove_impl(PyObject *module, path_t *path, int dir_fd)  | 
4541  |  | /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/  | 
4542  | 0  | { | 
4543  | 0  |     return os_unlink_impl(module, path, dir_fd);  | 
4544  | 0  | }  | 
4545  |  |  | 
4546  |  |  | 
4547  |  | static PyStructSequence_Field uname_result_fields[] = { | 
4548  |  |     {"sysname",    "operating system name"}, | 
4549  |  |     {"nodename",   "name of machine on network (implementation-defined)"}, | 
4550  |  |     {"release",    "operating system release"}, | 
4551  |  |     {"version",    "operating system version"}, | 
4552  |  |     {"machine",    "hardware identifier"}, | 
4553  |  |     {NULL} | 
4554  |  | };  | 
4555  |  |  | 
4556  |  | PyDoc_STRVAR(uname_result__doc__,  | 
4557  |  | "uname_result: Result from os.uname().\n\n\  | 
4558  |  | This object may be accessed either as a tuple of\n\  | 
4559  |  |   (sysname, nodename, release, version, machine),\n\  | 
4560  |  | or via the attributes sysname, nodename, release, version, and machine.\n\  | 
4561  |  | \n\  | 
4562  |  | See os.uname for more information.");  | 
4563  |  |  | 
4564  |  | static PyStructSequence_Desc uname_result_desc = { | 
4565  |  |     "uname_result", /* name */  | 
4566  |  |     uname_result__doc__, /* doc */  | 
4567  |  |     uname_result_fields,  | 
4568  |  |     5  | 
4569  |  | };  | 
4570  |  |  | 
4571  |  | static PyTypeObject* UnameResultType;  | 
4572  |  |  | 
4573  |  |  | 
4574  |  | #ifdef HAVE_UNAME  | 
4575  |  | /*[clinic input]  | 
4576  |  | os.uname  | 
4577  |  |  | 
4578  |  | Return an object identifying the current operating system.  | 
4579  |  |  | 
4580  |  | The object behaves like a named tuple with the following fields:  | 
4581  |  |   (sysname, nodename, release, version, machine)  | 
4582  |  |  | 
4583  |  | [clinic start generated code]*/  | 
4584  |  |  | 
4585  |  | static PyObject *  | 
4586  |  | os_uname_impl(PyObject *module)  | 
4587  |  | /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/  | 
4588  | 0  | { | 
4589  | 0  |     struct utsname u;  | 
4590  | 0  |     int res;  | 
4591  | 0  |     PyObject *value;  | 
4592  |  | 
  | 
4593  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
4594  | 0  |     res = uname(&u);  | 
4595  | 0  |     Py_END_ALLOW_THREADS  | 
4596  | 0  |     if (res < 0)  | 
4597  | 0  |         return posix_error();  | 
4598  |  |  | 
4599  | 0  |     value = PyStructSequence_New(UnameResultType);  | 
4600  | 0  |     if (value == NULL)  | 
4601  | 0  |         return NULL;  | 
4602  |  |  | 
4603  | 0  | #define SET(i, field) \  | 
4604  | 0  |     { \ | 
4605  | 0  |     PyObject *o = PyUnicode_DecodeFSDefault(field); \  | 
4606  | 0  |     if (!o) { \ | 
4607  | 0  |         Py_DECREF(value); \  | 
4608  | 0  |         return NULL; \  | 
4609  | 0  |     } \  | 
4610  | 0  |     PyStructSequence_SET_ITEM(value, i, o); \  | 
4611  | 0  |     } \  | 
4612  | 0  |  | 
4613  | 0  |     SET(0, u.sysname);  | 
4614  | 0  |     SET(1, u.nodename);  | 
4615  | 0  |     SET(2, u.release);  | 
4616  | 0  |     SET(3, u.version);  | 
4617  | 0  |     SET(4, u.machine);  | 
4618  |  | 
  | 
4619  | 0  | #undef SET  | 
4620  |  | 
  | 
4621  | 0  |     return value;  | 
4622  | 0  | }  | 
4623  |  | #endif /* HAVE_UNAME */  | 
4624  |  |  | 
4625  |  |  | 
4626  |  |  | 
4627  |  | typedef struct { | 
4628  |  |     int    now;  | 
4629  |  |     time_t atime_s;  | 
4630  |  |     long   atime_ns;  | 
4631  |  |     time_t mtime_s;  | 
4632  |  |     long   mtime_ns;  | 
4633  |  | } utime_t;  | 
4634  |  |  | 
4635  |  | /*  | 
4636  |  |  * these macros assume that "ut" is a pointer to a utime_t  | 
4637  |  |  * they also intentionally leak the declaration of a pointer named "time"  | 
4638  |  |  */  | 
4639  |  | #define UTIME_TO_TIMESPEC \  | 
4640  | 0  |     struct timespec ts[2]; \  | 
4641  | 0  |     struct timespec *time; \  | 
4642  | 0  |     if (ut->now) \  | 
4643  | 0  |         time = NULL; \  | 
4644  | 0  |     else { \ | 
4645  | 0  |         ts[0].tv_sec = ut->atime_s; \  | 
4646  | 0  |         ts[0].tv_nsec = ut->atime_ns; \  | 
4647  | 0  |         ts[1].tv_sec = ut->mtime_s; \  | 
4648  | 0  |         ts[1].tv_nsec = ut->mtime_ns; \  | 
4649  | 0  |         time = ts; \  | 
4650  | 0  |     } \  | 
4651  |  |  | 
4652  |  | #define UTIME_TO_TIMEVAL \  | 
4653  |  |     struct timeval tv[2]; \  | 
4654  |  |     struct timeval *time; \  | 
4655  |  |     if (ut->now) \  | 
4656  |  |         time = NULL; \  | 
4657  |  |     else { \ | 
4658  |  |         tv[0].tv_sec = ut->atime_s; \  | 
4659  |  |         tv[0].tv_usec = ut->atime_ns / 1000; \  | 
4660  |  |         tv[1].tv_sec = ut->mtime_s; \  | 
4661  |  |         tv[1].tv_usec = ut->mtime_ns / 1000; \  | 
4662  |  |         time = tv; \  | 
4663  |  |     } \  | 
4664  |  |  | 
4665  |  | #define UTIME_TO_UTIMBUF \  | 
4666  |  |     struct utimbuf u; \  | 
4667  |  |     struct utimbuf *time; \  | 
4668  |  |     if (ut->now) \  | 
4669  |  |         time = NULL; \  | 
4670  |  |     else { \ | 
4671  |  |         u.actime = ut->atime_s; \  | 
4672  |  |         u.modtime = ut->mtime_s; \  | 
4673  |  |         time = &u; \  | 
4674  |  |     }  | 
4675  |  |  | 
4676  |  | #define UTIME_TO_TIME_T \  | 
4677  |  |     time_t timet[2]; \  | 
4678  |  |     time_t *time; \  | 
4679  |  |     if (ut->now) \  | 
4680  |  |         time = NULL; \  | 
4681  |  |     else { \ | 
4682  |  |         timet[0] = ut->atime_s; \  | 
4683  |  |         timet[1] = ut->mtime_s; \  | 
4684  |  |         time = timet; \  | 
4685  |  |     } \  | 
4686  |  |  | 
4687  |  |  | 
4688  |  | #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)  | 
4689  |  |  | 
4690  |  | static int  | 
4691  |  | utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)  | 
4692  | 0  | { | 
4693  | 0  | #ifdef HAVE_UTIMENSAT  | 
4694  | 0  |     int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;  | 
4695  | 0  |     UTIME_TO_TIMESPEC;  | 
4696  | 0  |     return utimensat(dir_fd, path, time, flags);  | 
4697  |  | #elif defined(HAVE_FUTIMESAT)  | 
4698  |  |     UTIME_TO_TIMEVAL;  | 
4699  |  |     /*  | 
4700  |  |      * follow_symlinks will never be false here;  | 
4701  |  |      * we only allow !follow_symlinks and dir_fd together  | 
4702  |  |      * if we have utimensat()  | 
4703  |  |      */  | 
4704  |  |     assert(follow_symlinks);  | 
4705  |  |     return futimesat(dir_fd, path, time);  | 
4706  |  | #endif  | 
4707  | 0  | }  | 
4708  |  |  | 
4709  | 0  |     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter  | 
4710  |  | #else  | 
4711  |  |     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable  | 
4712  |  | #endif  | 
4713  |  |  | 
4714  |  | #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)  | 
4715  |  |  | 
4716  |  | static int  | 
4717  |  | utime_fd(utime_t *ut, int fd)  | 
4718  | 0  | { | 
4719  | 0  | #ifdef HAVE_FUTIMENS  | 
4720  | 0  |     UTIME_TO_TIMESPEC;  | 
4721  | 0  |     return futimens(fd, time);  | 
4722  |  | #else  | 
4723  |  |     UTIME_TO_TIMEVAL;  | 
4724  |  |     return futimes(fd, time);  | 
4725  |  | #endif  | 
4726  | 0  | }  | 
4727  |  |  | 
4728  |  |     #define PATH_UTIME_HAVE_FD 1  | 
4729  |  | #else  | 
4730  |  |     #define PATH_UTIME_HAVE_FD 0  | 
4731  |  | #endif  | 
4732  |  |  | 
4733  |  | #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)  | 
4734  |  | #  define UTIME_HAVE_NOFOLLOW_SYMLINKS  | 
4735  |  | #endif  | 
4736  |  |  | 
4737  |  | #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS  | 
4738  |  |  | 
4739  |  | static int  | 
4740  |  | utime_nofollow_symlinks(utime_t *ut, const char *path)  | 
4741  | 0  | { | 
4742  | 0  | #ifdef HAVE_UTIMENSAT  | 
4743  | 0  |     UTIME_TO_TIMESPEC;  | 
4744  | 0  |     return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);  | 
4745  |  | #else  | 
4746  |  |     UTIME_TO_TIMEVAL;  | 
4747  |  |     return lutimes(path, time);  | 
4748  |  | #endif  | 
4749  | 0  | }  | 
4750  |  |  | 
4751  |  | #endif  | 
4752  |  |  | 
4753  |  | #ifndef MS_WINDOWS  | 
4754  |  |  | 
4755  |  | static int  | 
4756  |  | utime_default(utime_t *ut, const char *path)  | 
4757  | 0  | { | 
4758  | 0  | #ifdef HAVE_UTIMENSAT  | 
4759  | 0  |     UTIME_TO_TIMESPEC;  | 
4760  | 0  |     return utimensat(DEFAULT_DIR_FD, path, time, 0);  | 
4761  |  | #elif defined(HAVE_UTIMES)  | 
4762  |  |     UTIME_TO_TIMEVAL;  | 
4763  |  |     return utimes(path, time);  | 
4764  |  | #elif defined(HAVE_UTIME_H)  | 
4765  |  |     UTIME_TO_UTIMBUF;  | 
4766  |  |     return utime(path, time);  | 
4767  |  | #else  | 
4768  |  |     UTIME_TO_TIME_T;  | 
4769  |  |     return utime(path, time);  | 
4770  |  | #endif  | 
4771  | 0  | }  | 
4772  |  |  | 
4773  |  | #endif  | 
4774  |  |  | 
4775  |  | static int  | 
4776  |  | split_py_long_to_s_and_ns(PyObject *py_long, time_t *s, long *ns)  | 
4777  | 0  | { | 
4778  | 0  |     int result = 0;  | 
4779  | 0  |     PyObject *divmod;  | 
4780  | 0  |     divmod = PyNumber_Divmod(py_long, billion);  | 
4781  | 0  |     if (!divmod)  | 
4782  | 0  |         goto exit;  | 
4783  | 0  |     if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) { | 
4784  | 0  |         PyErr_Format(PyExc_TypeError,  | 
4785  | 0  |                      "%.200s.__divmod__() must return a 2-tuple, not %.200s",  | 
4786  | 0  |                      Py_TYPE(py_long)->tp_name, Py_TYPE(divmod)->tp_name);  | 
4787  | 0  |         goto exit;  | 
4788  | 0  |     }  | 
4789  | 0  |     *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));  | 
4790  | 0  |     if ((*s == -1) && PyErr_Occurred())  | 
4791  | 0  |         goto exit;  | 
4792  | 0  |     *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));  | 
4793  | 0  |     if ((*ns == -1) && PyErr_Occurred())  | 
4794  | 0  |         goto exit;  | 
4795  |  |  | 
4796  | 0  |     result = 1;  | 
4797  | 0  | exit:  | 
4798  | 0  |     Py_XDECREF(divmod);  | 
4799  | 0  |     return result;  | 
4800  | 0  | }  | 
4801  |  |  | 
4802  |  |  | 
4803  |  | /*[clinic input]  | 
4804  |  | os.utime  | 
4805  |  |  | 
4806  |  |     path: path_t(allow_fd='PATH_UTIME_HAVE_FD')  | 
4807  |  |     times: object = None  | 
4808  |  |     *  | 
4809  |  |     ns: object = NULL  | 
4810  |  |     dir_fd: dir_fd(requires='futimensat') = None  | 
4811  |  |     follow_symlinks: bool=True  | 
4812  |  |  | 
4813  |  | # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\  | 
4814  |  |  | 
4815  |  | Set the access and modified time of path.  | 
4816  |  |  | 
4817  |  | path may always be specified as a string.  | 
4818  |  | On some platforms, path may also be specified as an open file descriptor.  | 
4819  |  |   If this functionality is unavailable, using it raises an exception.  | 
4820  |  |  | 
4821  |  | If times is not None, it must be a tuple (atime, mtime);  | 
4822  |  |     atime and mtime should be expressed as float seconds since the epoch.  | 
4823  |  | If ns is specified, it must be a tuple (atime_ns, mtime_ns);  | 
4824  |  |     atime_ns and mtime_ns should be expressed as integer nanoseconds  | 
4825  |  |     since the epoch.  | 
4826  |  | If times is None and ns is unspecified, utime uses the current time.  | 
4827  |  | Specifying tuples for both times and ns is an error.  | 
4828  |  |  | 
4829  |  | If dir_fd is not None, it should be a file descriptor open to a directory,  | 
4830  |  |   and path should be relative; path will then be relative to that directory.  | 
4831  |  | If follow_symlinks is False, and the last element of the path is a symbolic  | 
4832  |  |   link, utime will modify the symbolic link itself instead of the file the  | 
4833  |  |   link points to.  | 
4834  |  | It is an error to use dir_fd or follow_symlinks when specifying path  | 
4835  |  |   as an open file descriptor.  | 
4836  |  | dir_fd and follow_symlinks may not be available on your platform.  | 
4837  |  |   If they are unavailable, using them will raise a NotImplementedError.  | 
4838  |  |  | 
4839  |  | [clinic start generated code]*/  | 
4840  |  |  | 
4841  |  | static PyObject *  | 
4842  |  | os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,  | 
4843  |  |               int dir_fd, int follow_symlinks)  | 
4844  |  | /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/  | 
4845  | 0  | { | 
4846  |  | #ifdef MS_WINDOWS  | 
4847  |  |     HANDLE hFile;  | 
4848  |  |     FILETIME atime, mtime;  | 
4849  |  | #else  | 
4850  | 0  |     int result;  | 
4851  | 0  | #endif  | 
4852  |  | 
  | 
4853  | 0  |     utime_t utime;  | 
4854  |  | 
  | 
4855  | 0  |     memset(&utime, 0, sizeof(utime_t));  | 
4856  |  | 
  | 
4857  | 0  |     if (times != Py_None && ns) { | 
4858  | 0  |         PyErr_SetString(PyExc_ValueError,  | 
4859  | 0  |                      "utime: you may specify either 'times'"  | 
4860  | 0  |                      " or 'ns' but not both");  | 
4861  | 0  |         return NULL;  | 
4862  | 0  |     }  | 
4863  |  |  | 
4864  | 0  |     if (times != Py_None) { | 
4865  | 0  |         time_t a_sec, m_sec;  | 
4866  | 0  |         long a_nsec, m_nsec;  | 
4867  | 0  |         if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) { | 
4868  | 0  |             PyErr_SetString(PyExc_TypeError,  | 
4869  | 0  |                          "utime: 'times' must be either"  | 
4870  | 0  |                          " a tuple of two ints or None");  | 
4871  | 0  |             return NULL;  | 
4872  | 0  |         }  | 
4873  | 0  |         utime.now = 0;  | 
4874  | 0  |         if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),  | 
4875  | 0  |                                      &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||  | 
4876  | 0  |             _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),  | 
4877  | 0  |                                      &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) { | 
4878  | 0  |             return NULL;  | 
4879  | 0  |         }  | 
4880  | 0  |         utime.atime_s = a_sec;  | 
4881  | 0  |         utime.atime_ns = a_nsec;  | 
4882  | 0  |         utime.mtime_s = m_sec;  | 
4883  | 0  |         utime.mtime_ns = m_nsec;  | 
4884  | 0  |     }  | 
4885  | 0  |     else if (ns) { | 
4886  | 0  |         if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) { | 
4887  | 0  |             PyErr_SetString(PyExc_TypeError,  | 
4888  | 0  |                          "utime: 'ns' must be a tuple of two ints");  | 
4889  | 0  |             return NULL;  | 
4890  | 0  |         }  | 
4891  | 0  |         utime.now = 0;  | 
4892  | 0  |         if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0),  | 
4893  | 0  |                                       &utime.atime_s, &utime.atime_ns) ||  | 
4894  | 0  |             !split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1),  | 
4895  | 0  |                                        &utime.mtime_s, &utime.mtime_ns)) { | 
4896  | 0  |             return NULL;  | 
4897  | 0  |         }  | 
4898  | 0  |     }  | 
4899  | 0  |     else { | 
4900  |  |         /* times and ns are both None/unspecified. use "now". */  | 
4901  | 0  |         utime.now = 1;  | 
4902  | 0  |     }  | 
4903  |  |  | 
4904  |  | #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)  | 
4905  |  |     if (follow_symlinks_specified("utime", follow_symlinks)) | 
4906  |  |         return NULL;  | 
4907  |  | #endif  | 
4908  |  |  | 
4909  | 0  |     if (path_and_dir_fd_invalid("utime", path, dir_fd) || | 
4910  | 0  |         dir_fd_and_fd_invalid("utime", dir_fd, path->fd) || | 
4911  | 0  |         fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks)) | 
4912  | 0  |         return NULL;  | 
4913  |  |  | 
4914  |  | #if !defined(HAVE_UTIMENSAT)  | 
4915  |  |     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { | 
4916  |  |         PyErr_SetString(PyExc_ValueError,  | 
4917  |  |                      "utime: cannot use dir_fd and follow_symlinks "  | 
4918  |  |                      "together on this platform");  | 
4919  |  |         return NULL;  | 
4920  |  |     }  | 
4921  |  | #endif  | 
4922  |  |  | 
4923  | 0  |     if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None, | 
4924  | 0  |                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { | 
4925  | 0  |         return NULL;  | 
4926  | 0  |     }  | 
4927  |  |  | 
4928  |  | #ifdef MS_WINDOWS  | 
4929  |  |     Py_BEGIN_ALLOW_THREADS  | 
4930  |  |     hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,  | 
4931  |  |                         NULL, OPEN_EXISTING,  | 
4932  |  |                         FILE_FLAG_BACKUP_SEMANTICS, NULL);  | 
4933  |  |     Py_END_ALLOW_THREADS  | 
4934  |  |     if (hFile == INVALID_HANDLE_VALUE) { | 
4935  |  |         path_error(path);  | 
4936  |  |         return NULL;  | 
4937  |  |     }  | 
4938  |  |  | 
4939  |  |     if (utime.now) { | 
4940  |  |         GetSystemTimeAsFileTime(&mtime);  | 
4941  |  |         atime = mtime;  | 
4942  |  |     }  | 
4943  |  |     else { | 
4944  |  |         _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);  | 
4945  |  |         _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);  | 
4946  |  |     }  | 
4947  |  |     if (!SetFileTime(hFile, NULL, &atime, &mtime)) { | 
4948  |  |         /* Avoid putting the file name into the error here,  | 
4949  |  |            as that may confuse the user into believing that  | 
4950  |  |            something is wrong with the file, when it also  | 
4951  |  |            could be the time stamp that gives a problem. */  | 
4952  |  |         PyErr_SetFromWindowsErr(0);  | 
4953  |  |         CloseHandle(hFile);  | 
4954  |  |         return NULL;  | 
4955  |  |     }  | 
4956  |  |     CloseHandle(hFile);  | 
4957  |  | #else /* MS_WINDOWS */  | 
4958  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
4959  |  | 
  | 
4960  | 0  | #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS  | 
4961  | 0  |     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))  | 
4962  | 0  |         result = utime_nofollow_symlinks(&utime, path->narrow);  | 
4963  | 0  |     else  | 
4964  | 0  | #endif  | 
4965  |  |  | 
4966  | 0  | #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)  | 
4967  | 0  |     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))  | 
4968  | 0  |         result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);  | 
4969  | 0  |     else  | 
4970  | 0  | #endif  | 
4971  |  |  | 
4972  | 0  | #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)  | 
4973  | 0  |     if (path->fd != -1)  | 
4974  | 0  |         result = utime_fd(&utime, path->fd);  | 
4975  | 0  |     else  | 
4976  | 0  | #endif  | 
4977  |  |  | 
4978  | 0  |     result = utime_default(&utime, path->narrow);  | 
4979  |  | 
  | 
4980  | 0  |     Py_END_ALLOW_THREADS  | 
4981  |  | 
  | 
4982  | 0  |     if (result < 0) { | 
4983  |  |         /* see previous comment about not putting filename in error here */  | 
4984  | 0  |         posix_error();  | 
4985  | 0  |         return NULL;  | 
4986  | 0  |     }  | 
4987  |  |  | 
4988  | 0  | #endif /* MS_WINDOWS */  | 
4989  |  |  | 
4990  | 0  |     Py_RETURN_NONE;  | 
4991  | 0  | }  | 
4992  |  |  | 
4993  |  | /* Process operations */  | 
4994  |  |  | 
4995  |  |  | 
4996  |  | /*[clinic input]  | 
4997  |  | os._exit  | 
4998  |  |  | 
4999  |  |     status: int  | 
5000  |  |  | 
5001  |  | Exit to the system with specified status, without normal exit processing.  | 
5002  |  | [clinic start generated code]*/  | 
5003  |  |  | 
5004  |  | static PyObject *  | 
5005  |  | os__exit_impl(PyObject *module, int status)  | 
5006  |  | /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/  | 
5007  | 0  | { | 
5008  | 0  |     _exit(status);  | 
5009  | 0  |     return NULL; /* Make gcc -Wall happy */  | 
5010  | 0  | }  | 
5011  |  |  | 
5012  |  | #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)  | 
5013  |  | #define EXECV_CHAR wchar_t  | 
5014  |  | #else  | 
5015  | 0  | #define EXECV_CHAR char  | 
5016  |  | #endif  | 
5017  |  |  | 
5018  |  | #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)  | 
5019  |  | static void  | 
5020  |  | free_string_array(EXECV_CHAR **array, Py_ssize_t count)  | 
5021  | 0  | { | 
5022  | 0  |     Py_ssize_t i;  | 
5023  | 0  |     for (i = 0; i < count; i++)  | 
5024  | 0  |         PyMem_Free(array[i]);  | 
5025  | 0  |     PyMem_DEL(array);  | 
5026  | 0  | }  | 
5027  |  |  | 
5028  |  | static int  | 
5029  |  | fsconvert_strdup(PyObject *o, EXECV_CHAR **out)  | 
5030  | 0  | { | 
5031  | 0  |     Py_ssize_t size;  | 
5032  | 0  |     PyObject *ub;  | 
5033  | 0  |     int result = 0;  | 
5034  |  | #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)  | 
5035  |  |     if (!PyUnicode_FSDecoder(o, &ub))  | 
5036  |  |         return 0;  | 
5037  |  |     *out = PyUnicode_AsWideCharString(ub, &size);  | 
5038  |  |     if (*out)  | 
5039  |  |         result = 1;  | 
5040  |  | #else  | 
5041  | 0  |     if (!PyUnicode_FSConverter(o, &ub))  | 
5042  | 0  |         return 0;  | 
5043  | 0  |     size = PyBytes_GET_SIZE(ub);  | 
5044  | 0  |     *out = PyMem_Malloc(size + 1);  | 
5045  | 0  |     if (*out) { | 
5046  | 0  |         memcpy(*out, PyBytes_AS_STRING(ub), size + 1);  | 
5047  | 0  |         result = 1;  | 
5048  | 0  |     } else  | 
5049  | 0  |         PyErr_NoMemory();  | 
5050  | 0  | #endif  | 
5051  | 0  |     Py_DECREF(ub);  | 
5052  | 0  |     return result;  | 
5053  | 0  | }  | 
5054  |  | #endif  | 
5055  |  |  | 
5056  |  | #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)  | 
5057  |  | static EXECV_CHAR**  | 
5058  |  | parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)  | 
5059  | 0  | { | 
5060  | 0  |     Py_ssize_t i, pos, envc;  | 
5061  | 0  |     PyObject *keys=NULL, *vals=NULL;  | 
5062  | 0  |     PyObject *key, *val, *key2, *val2, *keyval;  | 
5063  | 0  |     EXECV_CHAR **envlist;  | 
5064  |  | 
  | 
5065  | 0  |     i = PyMapping_Size(env);  | 
5066  | 0  |     if (i < 0)  | 
5067  | 0  |         return NULL;  | 
5068  | 0  |     envlist = PyMem_NEW(EXECV_CHAR *, i + 1);  | 
5069  | 0  |     if (envlist == NULL) { | 
5070  | 0  |         PyErr_NoMemory();  | 
5071  | 0  |         return NULL;  | 
5072  | 0  |     }  | 
5073  | 0  |     envc = 0;  | 
5074  | 0  |     keys = PyMapping_Keys(env);  | 
5075  | 0  |     if (!keys)  | 
5076  | 0  |         goto error;  | 
5077  | 0  |     vals = PyMapping_Values(env);  | 
5078  | 0  |     if (!vals)  | 
5079  | 0  |         goto error;  | 
5080  | 0  |     if (!PyList_Check(keys) || !PyList_Check(vals)) { | 
5081  | 0  |         PyErr_Format(PyExc_TypeError,  | 
5082  | 0  |                      "env.keys() or env.values() is not a list");  | 
5083  | 0  |         goto error;  | 
5084  | 0  |     }  | 
5085  |  |  | 
5086  | 0  |     for (pos = 0; pos < i; pos++) { | 
5087  | 0  |         key = PyList_GetItem(keys, pos);  | 
5088  | 0  |         val = PyList_GetItem(vals, pos);  | 
5089  | 0  |         if (!key || !val)  | 
5090  | 0  |             goto error;  | 
5091  |  |  | 
5092  |  | #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)  | 
5093  |  |         if (!PyUnicode_FSDecoder(key, &key2))  | 
5094  |  |             goto error;  | 
5095  |  |         if (!PyUnicode_FSDecoder(val, &val2)) { | 
5096  |  |             Py_DECREF(key2);  | 
5097  |  |             goto error;  | 
5098  |  |         }  | 
5099  |  |         /* Search from index 1 because on Windows starting '=' is allowed for  | 
5100  |  |            defining hidden environment variables. */  | 
5101  |  |         if (PyUnicode_GET_LENGTH(key2) == 0 ||  | 
5102  |  |             PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)  | 
5103  |  |         { | 
5104  |  |             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");  | 
5105  |  |             Py_DECREF(key2);  | 
5106  |  |             Py_DECREF(val2);  | 
5107  |  |             goto error;  | 
5108  |  |         }  | 
5109  |  |         keyval = PyUnicode_FromFormat("%U=%U", key2, val2); | 
5110  |  | #else  | 
5111  | 0  |         if (!PyUnicode_FSConverter(key, &key2))  | 
5112  | 0  |             goto error;  | 
5113  | 0  |         if (!PyUnicode_FSConverter(val, &val2)) { | 
5114  | 0  |             Py_DECREF(key2);  | 
5115  | 0  |             goto error;  | 
5116  | 0  |         }  | 
5117  | 0  |         if (PyBytes_GET_SIZE(key2) == 0 ||  | 
5118  | 0  |             strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)  | 
5119  | 0  |         { | 
5120  | 0  |             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");  | 
5121  | 0  |             Py_DECREF(key2);  | 
5122  | 0  |             Py_DECREF(val2);  | 
5123  | 0  |             goto error;  | 
5124  | 0  |         }  | 
5125  | 0  |         keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2), | 
5126  | 0  |                                              PyBytes_AS_STRING(val2));  | 
5127  | 0  | #endif  | 
5128  | 0  |         Py_DECREF(key2);  | 
5129  | 0  |         Py_DECREF(val2);  | 
5130  | 0  |         if (!keyval)  | 
5131  | 0  |             goto error;  | 
5132  |  |  | 
5133  | 0  |         if (!fsconvert_strdup(keyval, &envlist[envc++])) { | 
5134  | 0  |             Py_DECREF(keyval);  | 
5135  | 0  |             goto error;  | 
5136  | 0  |         }  | 
5137  |  |  | 
5138  | 0  |         Py_DECREF(keyval);  | 
5139  | 0  |     }  | 
5140  | 0  |     Py_DECREF(vals);  | 
5141  | 0  |     Py_DECREF(keys);  | 
5142  |  | 
  | 
5143  | 0  |     envlist[envc] = 0;  | 
5144  | 0  |     *envc_ptr = envc;  | 
5145  | 0  |     return envlist;  | 
5146  |  |  | 
5147  | 0  | error:  | 
5148  | 0  |     Py_XDECREF(keys);  | 
5149  | 0  |     Py_XDECREF(vals);  | 
5150  | 0  |     free_string_array(envlist, envc);  | 
5151  | 0  |     return NULL;  | 
5152  | 0  | }  | 
5153  |  |  | 
5154  |  | static EXECV_CHAR**  | 
5155  |  | parse_arglist(PyObject* argv, Py_ssize_t *argc)  | 
5156  | 0  | { | 
5157  | 0  |     int i;  | 
5158  | 0  |     EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);  | 
5159  | 0  |     if (argvlist == NULL) { | 
5160  | 0  |         PyErr_NoMemory();  | 
5161  | 0  |         return NULL;  | 
5162  | 0  |     }  | 
5163  | 0  |     for (i = 0; i < *argc; i++) { | 
5164  | 0  |         PyObject* item = PySequence_ITEM(argv, i);  | 
5165  | 0  |         if (item == NULL)  | 
5166  | 0  |             goto fail;  | 
5167  | 0  |         if (!fsconvert_strdup(item, &argvlist[i])) { | 
5168  | 0  |             Py_DECREF(item);  | 
5169  | 0  |             goto fail;  | 
5170  | 0  |         }  | 
5171  | 0  |         Py_DECREF(item);  | 
5172  | 0  |     }  | 
5173  | 0  |     argvlist[*argc] = NULL;  | 
5174  | 0  |     return argvlist;  | 
5175  | 0  | fail:  | 
5176  | 0  |     *argc = i;  | 
5177  | 0  |     free_string_array(argvlist, *argc);  | 
5178  | 0  |     return NULL;  | 
5179  | 0  | }  | 
5180  |  |  | 
5181  |  | #endif  | 
5182  |  |  | 
5183  |  |  | 
5184  |  | #ifdef HAVE_EXECV  | 
5185  |  | /*[clinic input]  | 
5186  |  | os.execv  | 
5187  |  |  | 
5188  |  |     path: path_t  | 
5189  |  |         Path of executable file.  | 
5190  |  |     argv: object  | 
5191  |  |         Tuple or list of strings.  | 
5192  |  |     /  | 
5193  |  |  | 
5194  |  | Execute an executable path with arguments, replacing current process.  | 
5195  |  | [clinic start generated code]*/  | 
5196  |  |  | 
5197  |  | static PyObject *  | 
5198  |  | os_execv_impl(PyObject *module, path_t *path, PyObject *argv)  | 
5199  |  | /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/  | 
5200  | 0  | { | 
5201  | 0  |     EXECV_CHAR **argvlist;  | 
5202  | 0  |     Py_ssize_t argc;  | 
5203  |  |  | 
5204  |  |     /* execv has two arguments: (path, argv), where  | 
5205  |  |        argv is a list or tuple of strings. */  | 
5206  |  | 
  | 
5207  | 0  |     if (!PyList_Check(argv) && !PyTuple_Check(argv)) { | 
5208  | 0  |         PyErr_SetString(PyExc_TypeError,  | 
5209  | 0  |                         "execv() arg 2 must be a tuple or list");  | 
5210  | 0  |         return NULL;  | 
5211  | 0  |     }  | 
5212  | 0  |     argc = PySequence_Size(argv);  | 
5213  | 0  |     if (argc < 1) { | 
5214  | 0  |         PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");  | 
5215  | 0  |         return NULL;  | 
5216  | 0  |     }  | 
5217  |  |  | 
5218  | 0  |     argvlist = parse_arglist(argv, &argc);  | 
5219  | 0  |     if (argvlist == NULL) { | 
5220  | 0  |         return NULL;  | 
5221  | 0  |     }  | 
5222  | 0  |     if (!argvlist[0][0]) { | 
5223  | 0  |         PyErr_SetString(PyExc_ValueError,  | 
5224  | 0  |             "execv() arg 2 first element cannot be empty");  | 
5225  | 0  |         free_string_array(argvlist, argc);  | 
5226  | 0  |         return NULL;  | 
5227  | 0  |     }  | 
5228  |  |  | 
5229  | 0  |     if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) { | 
5230  | 0  |         free_string_array(argvlist, argc);  | 
5231  | 0  |         return NULL;  | 
5232  | 0  |     }  | 
5233  |  |  | 
5234  | 0  |     _Py_BEGIN_SUPPRESS_IPH  | 
5235  |  | #ifdef HAVE_WEXECV  | 
5236  |  |     _wexecv(path->wide, argvlist);  | 
5237  |  | #else  | 
5238  | 0  |     execv(path->narrow, argvlist);  | 
5239  | 0  | #endif  | 
5240  | 0  |     _Py_END_SUPPRESS_IPH  | 
5241  |  |  | 
5242  |  |     /* If we get here it's definitely an error */  | 
5243  |  | 
  | 
5244  | 0  |     free_string_array(argvlist, argc);  | 
5245  | 0  |     return posix_error();  | 
5246  | 0  | }  | 
5247  |  |  | 
5248  |  |  | 
5249  |  | /*[clinic input]  | 
5250  |  | os.execve  | 
5251  |  |  | 
5252  |  |     path: path_t(allow_fd='PATH_HAVE_FEXECVE')  | 
5253  |  |         Path of executable file.  | 
5254  |  |     argv: object  | 
5255  |  |         Tuple or list of strings.  | 
5256  |  |     env: object  | 
5257  |  |         Dictionary of strings mapping to strings.  | 
5258  |  |  | 
5259  |  | Execute an executable path with arguments, replacing current process.  | 
5260  |  | [clinic start generated code]*/  | 
5261  |  |  | 
5262  |  | static PyObject *  | 
5263  |  | os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)  | 
5264  |  | /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/  | 
5265  | 0  | { | 
5266  | 0  |     EXECV_CHAR **argvlist = NULL;  | 
5267  | 0  |     EXECV_CHAR **envlist;  | 
5268  | 0  |     Py_ssize_t argc, envc;  | 
5269  |  |  | 
5270  |  |     /* execve has three arguments: (path, argv, env), where  | 
5271  |  |        argv is a list or tuple of strings and env is a dictionary  | 
5272  |  |        like posix.environ. */  | 
5273  |  | 
  | 
5274  | 0  |     if (!PyList_Check(argv) && !PyTuple_Check(argv)) { | 
5275  | 0  |         PyErr_SetString(PyExc_TypeError,  | 
5276  | 0  |                         "execve: argv must be a tuple or list");  | 
5277  | 0  |         goto fail_0;  | 
5278  | 0  |     }  | 
5279  | 0  |     argc = PySequence_Size(argv);  | 
5280  | 0  |     if (argc < 1) { | 
5281  | 0  |         PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");  | 
5282  | 0  |         return NULL;  | 
5283  | 0  |     }  | 
5284  |  |  | 
5285  | 0  |     if (!PyMapping_Check(env)) { | 
5286  | 0  |         PyErr_SetString(PyExc_TypeError,  | 
5287  | 0  |                         "execve: environment must be a mapping object");  | 
5288  | 0  |         goto fail_0;  | 
5289  | 0  |     }  | 
5290  |  |  | 
5291  | 0  |     argvlist = parse_arglist(argv, &argc);  | 
5292  | 0  |     if (argvlist == NULL) { | 
5293  | 0  |         goto fail_0;  | 
5294  | 0  |     }  | 
5295  | 0  |     if (!argvlist[0][0]) { | 
5296  | 0  |         PyErr_SetString(PyExc_ValueError,  | 
5297  | 0  |             "execve: argv first element cannot be empty");  | 
5298  | 0  |         goto fail_0;  | 
5299  | 0  |     }  | 
5300  |  |  | 
5301  | 0  |     envlist = parse_envlist(env, &envc);  | 
5302  | 0  |     if (envlist == NULL)  | 
5303  | 0  |         goto fail_0;  | 
5304  |  |  | 
5305  | 0  |     if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) { | 
5306  | 0  |         goto fail_1;  | 
5307  | 0  |     }  | 
5308  |  |  | 
5309  | 0  |     _Py_BEGIN_SUPPRESS_IPH  | 
5310  | 0  | #ifdef HAVE_FEXECVE  | 
5311  | 0  |     if (path->fd > -1)  | 
5312  | 0  |         fexecve(path->fd, argvlist, envlist);  | 
5313  | 0  |     else  | 
5314  | 0  | #endif  | 
5315  |  | #ifdef HAVE_WEXECV  | 
5316  |  |         _wexecve(path->wide, argvlist, envlist);  | 
5317  |  | #else  | 
5318  | 0  |         execve(path->narrow, argvlist, envlist);  | 
5319  | 0  | #endif  | 
5320  | 0  |     _Py_END_SUPPRESS_IPH  | 
5321  |  |  | 
5322  |  |     /* If we get here it's definitely an error */  | 
5323  |  | 
  | 
5324  | 0  |     posix_path_error(path);  | 
5325  | 0  |   fail_1:  | 
5326  | 0  |     free_string_array(envlist, envc);  | 
5327  | 0  |   fail_0:  | 
5328  | 0  |     if (argvlist)  | 
5329  | 0  |         free_string_array(argvlist, argc);  | 
5330  | 0  |     return NULL;  | 
5331  | 0  | }  | 
5332  |  |  | 
5333  |  | #endif /* HAVE_EXECV */  | 
5334  |  |  | 
5335  |  | #ifdef HAVE_POSIX_SPAWN  | 
5336  |  |  | 
5337  |  | enum posix_spawn_file_actions_identifier { | 
5338  |  |     POSIX_SPAWN_OPEN,  | 
5339  |  |     POSIX_SPAWN_CLOSE,  | 
5340  |  |     POSIX_SPAWN_DUP2  | 
5341  |  | };  | 
5342  |  |  | 
5343  |  | #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)  | 
5344  |  | static int  | 
5345  |  | convert_sched_param(PyObject *param, struct sched_param *res);  | 
5346  |  | #endif  | 
5347  |  |  | 
5348  |  | static int  | 
5349  |  | parse_posix_spawn_flags(const char *func_name, PyObject *setpgroup,  | 
5350  |  |                         int resetids, int setsid, PyObject *setsigmask,  | 
5351  |  |                         PyObject *setsigdef, PyObject *scheduler,  | 
5352  |  |                         posix_spawnattr_t *attrp)  | 
5353  | 0  | { | 
5354  | 0  |     long all_flags = 0;  | 
5355  |  | 
  | 
5356  | 0  |     errno = posix_spawnattr_init(attrp);  | 
5357  | 0  |     if (errno) { | 
5358  | 0  |         posix_error();  | 
5359  | 0  |         return -1;  | 
5360  | 0  |     }  | 
5361  |  |  | 
5362  | 0  |     if (setpgroup) { | 
5363  | 0  |         pid_t pgid = PyLong_AsPid(setpgroup);  | 
5364  | 0  |         if (pgid == (pid_t)-1 && PyErr_Occurred()) { | 
5365  | 0  |             goto fail;  | 
5366  | 0  |         }  | 
5367  | 0  |         errno = posix_spawnattr_setpgroup(attrp, pgid);  | 
5368  | 0  |         if (errno) { | 
5369  | 0  |             posix_error();  | 
5370  | 0  |             goto fail;  | 
5371  | 0  |         }  | 
5372  | 0  |         all_flags |= POSIX_SPAWN_SETPGROUP;  | 
5373  | 0  |     }  | 
5374  |  |  | 
5375  | 0  |     if (resetids) { | 
5376  | 0  |         all_flags |= POSIX_SPAWN_RESETIDS;  | 
5377  | 0  |     }  | 
5378  |  | 
  | 
5379  | 0  |     if (setsid) { | 
5380  | 0  | #ifdef POSIX_SPAWN_SETSID  | 
5381  | 0  |         all_flags |= POSIX_SPAWN_SETSID;  | 
5382  |  | #elif defined(POSIX_SPAWN_SETSID_NP)  | 
5383  |  |         all_flags |= POSIX_SPAWN_SETSID_NP;  | 
5384  |  | #else  | 
5385  |  |         argument_unavailable_error(func_name, "setsid");  | 
5386  |  |         return -1;  | 
5387  |  | #endif  | 
5388  | 0  |     }  | 
5389  |  | 
  | 
5390  | 0  |    if (setsigmask) { | 
5391  | 0  |         sigset_t set;  | 
5392  | 0  |         if (!_Py_Sigset_Converter(setsigmask, &set)) { | 
5393  | 0  |             goto fail;  | 
5394  | 0  |         }  | 
5395  | 0  |         errno = posix_spawnattr_setsigmask(attrp, &set);  | 
5396  | 0  |         if (errno) { | 
5397  | 0  |             posix_error();  | 
5398  | 0  |             goto fail;  | 
5399  | 0  |         }  | 
5400  | 0  |         all_flags |= POSIX_SPAWN_SETSIGMASK;  | 
5401  | 0  |     }  | 
5402  |  |  | 
5403  | 0  |     if (setsigdef) { | 
5404  | 0  |         sigset_t set;  | 
5405  | 0  |         if (!_Py_Sigset_Converter(setsigdef, &set)) { | 
5406  | 0  |             goto fail;  | 
5407  | 0  |         }  | 
5408  | 0  |         errno = posix_spawnattr_setsigdefault(attrp, &set);  | 
5409  | 0  |         if (errno) { | 
5410  | 0  |             posix_error();  | 
5411  | 0  |             goto fail;  | 
5412  | 0  |         }  | 
5413  | 0  |         all_flags |= POSIX_SPAWN_SETSIGDEF;  | 
5414  | 0  |     }  | 
5415  |  |  | 
5416  | 0  |     if (scheduler) { | 
5417  | 0  | #ifdef POSIX_SPAWN_SETSCHEDULER  | 
5418  | 0  |         PyObject *py_schedpolicy;  | 
5419  | 0  |         struct sched_param schedparam;  | 
5420  |  | 
  | 
5421  | 0  |         if (!PyArg_ParseTuple(scheduler, "OO&"  | 
5422  | 0  |                         ";A scheduler tuple must have two elements",  | 
5423  | 0  |                         &py_schedpolicy, convert_sched_param, &schedparam)) { | 
5424  | 0  |             goto fail;  | 
5425  | 0  |         }  | 
5426  | 0  |         if (py_schedpolicy != Py_None) { | 
5427  | 0  |             int schedpolicy = _PyLong_AsInt(py_schedpolicy);  | 
5428  |  | 
  | 
5429  | 0  |             if (schedpolicy == -1 && PyErr_Occurred()) { | 
5430  | 0  |                 goto fail;  | 
5431  | 0  |             }  | 
5432  | 0  |             errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);  | 
5433  | 0  |             if (errno) { | 
5434  | 0  |                 posix_error();  | 
5435  | 0  |                 goto fail;  | 
5436  | 0  |             }  | 
5437  | 0  |             all_flags |= POSIX_SPAWN_SETSCHEDULER;  | 
5438  | 0  |         }  | 
5439  | 0  |         errno = posix_spawnattr_setschedparam(attrp, &schedparam);  | 
5440  | 0  |         if (errno) { | 
5441  | 0  |             posix_error();  | 
5442  | 0  |             goto fail;  | 
5443  | 0  |         }  | 
5444  | 0  |         all_flags |= POSIX_SPAWN_SETSCHEDPARAM;  | 
5445  |  | #else  | 
5446  |  |         PyErr_SetString(PyExc_NotImplementedError,  | 
5447  |  |                 "The scheduler option is not supported in this system.");  | 
5448  |  |         goto fail;  | 
5449  |  | #endif  | 
5450  | 0  |     }  | 
5451  |  |  | 
5452  | 0  |     errno = posix_spawnattr_setflags(attrp, all_flags);  | 
5453  | 0  |     if (errno) { | 
5454  | 0  |         posix_error();  | 
5455  | 0  |         goto fail;  | 
5456  | 0  |     }  | 
5457  |  |  | 
5458  | 0  |     return 0;  | 
5459  |  |  | 
5460  | 0  | fail:  | 
5461  | 0  |     (void)posix_spawnattr_destroy(attrp);  | 
5462  | 0  |     return -1;  | 
5463  | 0  | }  | 
5464  |  |  | 
5465  |  | static int  | 
5466  |  | parse_file_actions(PyObject *file_actions,  | 
5467  |  |                    posix_spawn_file_actions_t *file_actionsp,  | 
5468  |  |                    PyObject *temp_buffer)  | 
5469  | 0  | { | 
5470  | 0  |     PyObject *seq;  | 
5471  | 0  |     PyObject *file_action = NULL;  | 
5472  | 0  |     PyObject *tag_obj;  | 
5473  |  | 
  | 
5474  | 0  |     seq = PySequence_Fast(file_actions,  | 
5475  | 0  |                           "file_actions must be a sequence or None");  | 
5476  | 0  |     if (seq == NULL) { | 
5477  | 0  |         return -1;  | 
5478  | 0  |     }  | 
5479  |  |  | 
5480  | 0  |     errno = posix_spawn_file_actions_init(file_actionsp);  | 
5481  | 0  |     if (errno) { | 
5482  | 0  |         posix_error();  | 
5483  | 0  |         Py_DECREF(seq);  | 
5484  | 0  |         return -1;  | 
5485  | 0  |     }  | 
5486  |  |  | 
5487  | 0  |     for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) { | 
5488  | 0  |         file_action = PySequence_Fast_GET_ITEM(seq, i);  | 
5489  | 0  |         Py_INCREF(file_action);  | 
5490  | 0  |         if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) { | 
5491  | 0  |             PyErr_SetString(PyExc_TypeError,  | 
5492  | 0  |                 "Each file_actions element must be a non-empty tuple");  | 
5493  | 0  |             goto fail;  | 
5494  | 0  |         }  | 
5495  | 0  |         long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));  | 
5496  | 0  |         if (tag == -1 && PyErr_Occurred()) { | 
5497  | 0  |             goto fail;  | 
5498  | 0  |         }  | 
5499  |  |  | 
5500  |  |         /* Populate the file_actions object */  | 
5501  | 0  |         switch (tag) { | 
5502  | 0  |             case POSIX_SPAWN_OPEN: { | 
5503  | 0  |                 int fd, oflag;  | 
5504  | 0  |                 PyObject *path;  | 
5505  | 0  |                 unsigned long mode;  | 
5506  | 0  |                 if (!PyArg_ParseTuple(file_action, "OiO&ik"  | 
5507  | 0  |                         ";A open file_action tuple must have 5 elements",  | 
5508  | 0  |                         &tag_obj, &fd, PyUnicode_FSConverter, &path,  | 
5509  | 0  |                         &oflag, &mode))  | 
5510  | 0  |                 { | 
5511  | 0  |                     goto fail;  | 
5512  | 0  |                 }  | 
5513  | 0  |                 if (PyList_Append(temp_buffer, path)) { | 
5514  | 0  |                     Py_DECREF(path);  | 
5515  | 0  |                     goto fail;  | 
5516  | 0  |                 }  | 
5517  | 0  |                 errno = posix_spawn_file_actions_addopen(file_actionsp,  | 
5518  | 0  |                         fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);  | 
5519  | 0  |                 Py_DECREF(path);  | 
5520  | 0  |                 if (errno) { | 
5521  | 0  |                     posix_error();  | 
5522  | 0  |                     goto fail;  | 
5523  | 0  |                 }  | 
5524  | 0  |                 break;  | 
5525  | 0  |             }  | 
5526  | 0  |             case POSIX_SPAWN_CLOSE: { | 
5527  | 0  |                 int fd;  | 
5528  | 0  |                 if (!PyArg_ParseTuple(file_action, "Oi"  | 
5529  | 0  |                         ";A close file_action tuple must have 2 elements",  | 
5530  | 0  |                         &tag_obj, &fd))  | 
5531  | 0  |                 { | 
5532  | 0  |                     goto fail;  | 
5533  | 0  |                 }  | 
5534  | 0  |                 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);  | 
5535  | 0  |                 if (errno) { | 
5536  | 0  |                     posix_error();  | 
5537  | 0  |                     goto fail;  | 
5538  | 0  |                 }  | 
5539  | 0  |                 break;  | 
5540  | 0  |             }  | 
5541  | 0  |             case POSIX_SPAWN_DUP2: { | 
5542  | 0  |                 int fd1, fd2;  | 
5543  | 0  |                 if (!PyArg_ParseTuple(file_action, "Oii"  | 
5544  | 0  |                         ";A dup2 file_action tuple must have 3 elements",  | 
5545  | 0  |                         &tag_obj, &fd1, &fd2))  | 
5546  | 0  |                 { | 
5547  | 0  |                     goto fail;  | 
5548  | 0  |                 }  | 
5549  | 0  |                 errno = posix_spawn_file_actions_adddup2(file_actionsp,  | 
5550  | 0  |                                                          fd1, fd2);  | 
5551  | 0  |                 if (errno) { | 
5552  | 0  |                     posix_error();  | 
5553  | 0  |                     goto fail;  | 
5554  | 0  |                 }  | 
5555  | 0  |                 break;  | 
5556  | 0  |             }  | 
5557  | 0  |             default: { | 
5558  | 0  |                 PyErr_SetString(PyExc_TypeError,  | 
5559  | 0  |                                 "Unknown file_actions identifier");  | 
5560  | 0  |                 goto fail;  | 
5561  | 0  |             }  | 
5562  | 0  |         }  | 
5563  | 0  |         Py_DECREF(file_action);  | 
5564  | 0  |     }  | 
5565  |  |  | 
5566  | 0  |     Py_DECREF(seq);  | 
5567  | 0  |     return 0;  | 
5568  |  |  | 
5569  | 0  | fail:  | 
5570  | 0  |     Py_DECREF(seq);  | 
5571  | 0  |     Py_DECREF(file_action);  | 
5572  | 0  |     (void)posix_spawn_file_actions_destroy(file_actionsp);  | 
5573  | 0  |     return -1;  | 
5574  | 0  | }  | 
5575  |  |  | 
5576  |  |  | 
5577  |  | static PyObject *  | 
5578  |  | py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,  | 
5579  |  |                PyObject *env, PyObject *file_actions,  | 
5580  |  |                PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,  | 
5581  |  |                PyObject *setsigdef, PyObject *scheduler)  | 
5582  | 0  | { | 
5583  | 0  |     const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";  | 
5584  | 0  |     EXECV_CHAR **argvlist = NULL;  | 
5585  | 0  |     EXECV_CHAR **envlist = NULL;  | 
5586  | 0  |     posix_spawn_file_actions_t file_actions_buf;  | 
5587  | 0  |     posix_spawn_file_actions_t *file_actionsp = NULL;  | 
5588  | 0  |     posix_spawnattr_t attr;  | 
5589  | 0  |     posix_spawnattr_t *attrp = NULL;  | 
5590  | 0  |     Py_ssize_t argc, envc;  | 
5591  | 0  |     PyObject *result = NULL;  | 
5592  | 0  |     PyObject *temp_buffer = NULL;  | 
5593  | 0  |     pid_t pid;  | 
5594  | 0  |     int err_code;  | 
5595  |  |  | 
5596  |  |     /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where  | 
5597  |  |        argv is a list or tuple of strings and env is a dictionary  | 
5598  |  |        like posix.environ. */  | 
5599  |  | 
  | 
5600  | 0  |     if (!PyList_Check(argv) && !PyTuple_Check(argv)) { | 
5601  | 0  |         PyErr_Format(PyExc_TypeError,  | 
5602  | 0  |                      "%s: argv must be a tuple or list", func_name);  | 
5603  | 0  |         goto exit;  | 
5604  | 0  |     }  | 
5605  | 0  |     argc = PySequence_Size(argv);  | 
5606  | 0  |     if (argc < 1) { | 
5607  | 0  |         PyErr_Format(PyExc_ValueError,  | 
5608  | 0  |                      "%s: argv must not be empty", func_name);  | 
5609  | 0  |         return NULL;  | 
5610  | 0  |     }  | 
5611  |  |  | 
5612  | 0  |     if (!PyMapping_Check(env)) { | 
5613  | 0  |         PyErr_Format(PyExc_TypeError,  | 
5614  | 0  |                      "%s: environment must be a mapping object", func_name);  | 
5615  | 0  |         goto exit;  | 
5616  | 0  |     }  | 
5617  |  |  | 
5618  | 0  |     argvlist = parse_arglist(argv, &argc);  | 
5619  | 0  |     if (argvlist == NULL) { | 
5620  | 0  |         goto exit;  | 
5621  | 0  |     }  | 
5622  | 0  |     if (!argvlist[0][0]) { | 
5623  | 0  |         PyErr_Format(PyExc_ValueError,  | 
5624  | 0  |                      "%s: argv first element cannot be empty", func_name);  | 
5625  | 0  |         goto exit;  | 
5626  | 0  |     }  | 
5627  |  |  | 
5628  | 0  |     envlist = parse_envlist(env, &envc);  | 
5629  | 0  |     if (envlist == NULL) { | 
5630  | 0  |         goto exit;  | 
5631  | 0  |     }  | 
5632  |  |  | 
5633  | 0  |     if (file_actions != NULL && file_actions != Py_None) { | 
5634  |  |         /* There is a bug in old versions of glibc that makes some of the  | 
5635  |  |          * helper functions for manipulating file actions not copy the provided  | 
5636  |  |          * buffers. The problem is that posix_spawn_file_actions_addopen does not  | 
5637  |  |          * copy the value of path for some old versions of glibc (<2.20).  | 
5638  |  |          * The use of temp_buffer here is a workaround that keeps the  | 
5639  |  |          * python objects that own the buffers alive until posix_spawn gets called.  | 
5640  |  |          * Check https://bugs.python.org/issue33630 and  | 
5641  |  |          * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/  | 
5642  | 0  |         temp_buffer = PyList_New(0);  | 
5643  | 0  |         if (!temp_buffer) { | 
5644  | 0  |             goto exit;  | 
5645  | 0  |         }  | 
5646  | 0  |         if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) { | 
5647  | 0  |             goto exit;  | 
5648  | 0  |         }  | 
5649  | 0  |         file_actionsp = &file_actions_buf;  | 
5650  | 0  |     }  | 
5651  |  |  | 
5652  | 0  |     if (parse_posix_spawn_flags(func_name, setpgroup, resetids, setsid,  | 
5653  | 0  |                                 setsigmask, setsigdef, scheduler, &attr)) { | 
5654  | 0  |         goto exit;  | 
5655  | 0  |     }  | 
5656  | 0  |     attrp = &attr;  | 
5657  |  | 
  | 
5658  | 0  |     if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) { | 
5659  | 0  |         goto exit;  | 
5660  | 0  |     }  | 
5661  |  |  | 
5662  | 0  |     _Py_BEGIN_SUPPRESS_IPH  | 
5663  | 0  | #ifdef HAVE_POSIX_SPAWNP  | 
5664  | 0  |     if (use_posix_spawnp) { | 
5665  | 0  |         err_code = posix_spawnp(&pid, path->narrow,  | 
5666  | 0  |                                 file_actionsp, attrp, argvlist, envlist);  | 
5667  | 0  |     }  | 
5668  | 0  |     else  | 
5669  | 0  | #endif /* HAVE_POSIX_SPAWNP */  | 
5670  | 0  |     { | 
5671  | 0  |         err_code = posix_spawn(&pid, path->narrow,  | 
5672  | 0  |                                file_actionsp, attrp, argvlist, envlist);  | 
5673  | 0  |     }  | 
5674  | 0  |     _Py_END_SUPPRESS_IPH  | 
5675  |  | 
  | 
5676  | 0  |     if (err_code) { | 
5677  | 0  |         errno = err_code;  | 
5678  | 0  |         PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);  | 
5679  | 0  |         goto exit;  | 
5680  | 0  |     }  | 
5681  |  | #ifdef _Py_MEMORY_SANITIZER  | 
5682  |  |     __msan_unpoison(&pid, sizeof(pid));  | 
5683  |  | #endif  | 
5684  | 0  |     result = PyLong_FromPid(pid);  | 
5685  |  | 
  | 
5686  | 0  | exit:  | 
5687  | 0  |     if (file_actionsp) { | 
5688  | 0  |         (void)posix_spawn_file_actions_destroy(file_actionsp);  | 
5689  | 0  |     }  | 
5690  | 0  |     if (attrp) { | 
5691  | 0  |         (void)posix_spawnattr_destroy(attrp);  | 
5692  | 0  |     }  | 
5693  | 0  |     if (envlist) { | 
5694  | 0  |         free_string_array(envlist, envc);  | 
5695  | 0  |     }  | 
5696  | 0  |     if (argvlist) { | 
5697  | 0  |         free_string_array(argvlist, argc);  | 
5698  | 0  |     }  | 
5699  | 0  |     Py_XDECREF(temp_buffer);  | 
5700  | 0  |     return result;  | 
5701  | 0  | }  | 
5702  |  |  | 
5703  |  |  | 
5704  |  | /*[clinic input]  | 
5705  |  |  | 
5706  |  | os.posix_spawn  | 
5707  |  |     path: path_t  | 
5708  |  |         Path of executable file.  | 
5709  |  |     argv: object  | 
5710  |  |         Tuple or list of strings.  | 
5711  |  |     env: object  | 
5712  |  |         Dictionary of strings mapping to strings.  | 
5713  |  |     /  | 
5714  |  |     *  | 
5715  |  |     file_actions: object(c_default='NULL') = ()  | 
5716  |  |         A sequence of file action tuples.  | 
5717  |  |     setpgroup: object = NULL  | 
5718  |  |         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.  | 
5719  |  |     resetids: bool(accept={int}) = False | 
5720  |  |         If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.  | 
5721  |  |     setsid: bool(accept={int}) = False | 
5722  |  |         If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.  | 
5723  |  |     setsigmask: object(c_default='NULL') = ()  | 
5724  |  |         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.  | 
5725  |  |     setsigdef: object(c_default='NULL') = ()  | 
5726  |  |         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.  | 
5727  |  |     scheduler: object = NULL  | 
5728  |  |         A tuple with the scheduler policy (optional) and parameters.  | 
5729  |  |  | 
5730  |  | Execute the program specified by path in a new process.  | 
5731  |  | [clinic start generated code]*/  | 
5732  |  |  | 
5733  |  | static PyObject *  | 
5734  |  | os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,  | 
5735  |  |                     PyObject *env, PyObject *file_actions,  | 
5736  |  |                     PyObject *setpgroup, int resetids, int setsid,  | 
5737  |  |                     PyObject *setsigmask, PyObject *setsigdef,  | 
5738  |  |                     PyObject *scheduler)  | 
5739  |  | /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/  | 
5740  | 0  | { | 
5741  | 0  |     return py_posix_spawn(0, module, path, argv, env, file_actions,  | 
5742  | 0  |                           setpgroup, resetids, setsid, setsigmask, setsigdef,  | 
5743  | 0  |                           scheduler);  | 
5744  | 0  | }  | 
5745  |  |  #endif /* HAVE_POSIX_SPAWN */  | 
5746  |  |  | 
5747  |  |  | 
5748  |  |  | 
5749  |  | #ifdef HAVE_POSIX_SPAWNP  | 
5750  |  | /*[clinic input]  | 
5751  |  |  | 
5752  |  | os.posix_spawnp  | 
5753  |  |     path: path_t  | 
5754  |  |         Path of executable file.  | 
5755  |  |     argv: object  | 
5756  |  |         Tuple or list of strings.  | 
5757  |  |     env: object  | 
5758  |  |         Dictionary of strings mapping to strings.  | 
5759  |  |     /  | 
5760  |  |     *  | 
5761  |  |     file_actions: object(c_default='NULL') = ()  | 
5762  |  |         A sequence of file action tuples.  | 
5763  |  |     setpgroup: object = NULL  | 
5764  |  |         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.  | 
5765  |  |     resetids: bool(accept={int}) = False | 
5766  |  |         If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.  | 
5767  |  |     setsid: bool(accept={int}) = False | 
5768  |  |         If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.  | 
5769  |  |     setsigmask: object(c_default='NULL') = ()  | 
5770  |  |         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.  | 
5771  |  |     setsigdef: object(c_default='NULL') = ()  | 
5772  |  |         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.  | 
5773  |  |     scheduler: object = NULL  | 
5774  |  |         A tuple with the scheduler policy (optional) and parameters.  | 
5775  |  |  | 
5776  |  | Execute the program specified by path in a new process.  | 
5777  |  | [clinic start generated code]*/  | 
5778  |  |  | 
5779  |  | static PyObject *  | 
5780  |  | os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,  | 
5781  |  |                      PyObject *env, PyObject *file_actions,  | 
5782  |  |                      PyObject *setpgroup, int resetids, int setsid,  | 
5783  |  |                      PyObject *setsigmask, PyObject *setsigdef,  | 
5784  |  |                      PyObject *scheduler)  | 
5785  |  | /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/  | 
5786  | 0  | { | 
5787  | 0  |     return py_posix_spawn(1, module, path, argv, env, file_actions,  | 
5788  | 0  |                           setpgroup, resetids, setsid, setsigmask, setsigdef,  | 
5789  | 0  |                           scheduler);  | 
5790  | 0  | }  | 
5791  |  | #endif /* HAVE_POSIX_SPAWNP */  | 
5792  |  |  | 
5793  |  | #ifdef HAVE_RTPSPAWN  | 
5794  |  | static intptr_t  | 
5795  |  | _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],  | 
5796  |  |                const char  *envp[])  | 
5797  |  | { | 
5798  |  |      RTP_ID rtpid;  | 
5799  |  |      int status;  | 
5800  |  |      pid_t res;  | 
5801  |  |      int async_err = 0;  | 
5802  |  |  | 
5803  |  |      /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.  | 
5804  |  |         uStackSize=0 cannot be used, the default stack size is too small for  | 
5805  |  |         Python. */  | 
5806  |  |      if (envp) { | 
5807  |  |          rtpid = rtpSpawn(rtpFileName, argv, envp,  | 
5808  |  |                           100, 0x1000000, 0, VX_FP_TASK);  | 
5809  |  |      }  | 
5810  |  |      else { | 
5811  |  |          rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,  | 
5812  |  |                           100, 0x1000000, 0, VX_FP_TASK);  | 
5813  |  |      }  | 
5814  |  |      if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) { | 
5815  |  |          do { | 
5816  |  |              res = waitpid((pid_t)rtpid, &status, 0);  | 
5817  |  |          } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
5818  |  |  | 
5819  |  |          if (res < 0)  | 
5820  |  |              return RTP_ID_ERROR;  | 
5821  |  |          return ((intptr_t)status);  | 
5822  |  |      }  | 
5823  |  |      return ((intptr_t)rtpid);  | 
5824  |  | }  | 
5825  |  | #endif  | 
5826  |  |  | 
5827  |  | #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)  | 
5828  |  | /*[clinic input]  | 
5829  |  | os.spawnv  | 
5830  |  |  | 
5831  |  |     mode: int  | 
5832  |  |         Mode of process creation.  | 
5833  |  |     path: path_t  | 
5834  |  |         Path of executable file.  | 
5835  |  |     argv: object  | 
5836  |  |         Tuple or list of strings.  | 
5837  |  |     /  | 
5838  |  |  | 
5839  |  | Execute the program specified by path in a new process.  | 
5840  |  | [clinic start generated code]*/  | 
5841  |  |  | 
5842  |  | static PyObject *  | 
5843  |  | os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)  | 
5844  |  | /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/  | 
5845  |  | { | 
5846  |  |     EXECV_CHAR **argvlist;  | 
5847  |  |     int i;  | 
5848  |  |     Py_ssize_t argc;  | 
5849  |  |     intptr_t spawnval;  | 
5850  |  |     PyObject *(*getitem)(PyObject *, Py_ssize_t);  | 
5851  |  |  | 
5852  |  |     /* spawnv has three arguments: (mode, path, argv), where  | 
5853  |  |        argv is a list or tuple of strings. */  | 
5854  |  |  | 
5855  |  |     if (PyList_Check(argv)) { | 
5856  |  |         argc = PyList_Size(argv);  | 
5857  |  |         getitem = PyList_GetItem;  | 
5858  |  |     }  | 
5859  |  |     else if (PyTuple_Check(argv)) { | 
5860  |  |         argc = PyTuple_Size(argv);  | 
5861  |  |         getitem = PyTuple_GetItem;  | 
5862  |  |     }  | 
5863  |  |     else { | 
5864  |  |         PyErr_SetString(PyExc_TypeError,  | 
5865  |  |                         "spawnv() arg 2 must be a tuple or list");  | 
5866  |  |         return NULL;  | 
5867  |  |     }  | 
5868  |  |     if (argc == 0) { | 
5869  |  |         PyErr_SetString(PyExc_ValueError,  | 
5870  |  |             "spawnv() arg 2 cannot be empty");  | 
5871  |  |         return NULL;  | 
5872  |  |     }  | 
5873  |  |  | 
5874  |  |     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);  | 
5875  |  |     if (argvlist == NULL) { | 
5876  |  |         return PyErr_NoMemory();  | 
5877  |  |     }  | 
5878  |  |     for (i = 0; i < argc; i++) { | 
5879  |  |         if (!fsconvert_strdup((*getitem)(argv, i),  | 
5880  |  |                               &argvlist[i])) { | 
5881  |  |             free_string_array(argvlist, i);  | 
5882  |  |             PyErr_SetString(  | 
5883  |  |                 PyExc_TypeError,  | 
5884  |  |                 "spawnv() arg 2 must contain only strings");  | 
5885  |  |             return NULL;  | 
5886  |  |         }  | 
5887  |  |         if (i == 0 && !argvlist[0][0]) { | 
5888  |  |             free_string_array(argvlist, i + 1);  | 
5889  |  |             PyErr_SetString(  | 
5890  |  |                 PyExc_ValueError,  | 
5891  |  |                 "spawnv() arg 2 first element cannot be empty");  | 
5892  |  |             return NULL;  | 
5893  |  |         }  | 
5894  |  |     }  | 
5895  |  |     argvlist[argc] = NULL;  | 
5896  |  |  | 
5897  |  | #if !defined(HAVE_RTPSPAWN)  | 
5898  |  |     if (mode == _OLD_P_OVERLAY)  | 
5899  |  |         mode = _P_OVERLAY;  | 
5900  |  | #endif  | 
5901  |  |  | 
5902  |  |     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, | 
5903  |  |                     Py_None) < 0) { | 
5904  |  |         free_string_array(argvlist, argc);  | 
5905  |  |         return NULL;  | 
5906  |  |     }  | 
5907  |  |  | 
5908  |  |     Py_BEGIN_ALLOW_THREADS  | 
5909  |  |     _Py_BEGIN_SUPPRESS_IPH  | 
5910  |  | #ifdef HAVE_WSPAWNV  | 
5911  |  |     spawnval = _wspawnv(mode, path->wide, argvlist);  | 
5912  |  | #elif defined(HAVE_RTPSPAWN)  | 
5913  |  |     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);  | 
5914  |  | #else  | 
5915  |  |     spawnval = _spawnv(mode, path->narrow, argvlist);  | 
5916  |  | #endif  | 
5917  |  |     _Py_END_SUPPRESS_IPH  | 
5918  |  |     Py_END_ALLOW_THREADS  | 
5919  |  |  | 
5920  |  |     free_string_array(argvlist, argc);  | 
5921  |  |  | 
5922  |  |     if (spawnval == -1)  | 
5923  |  |         return posix_error();  | 
5924  |  |     else  | 
5925  |  |         return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);  | 
5926  |  | }  | 
5927  |  |  | 
5928  |  | /*[clinic input]  | 
5929  |  | os.spawnve  | 
5930  |  |  | 
5931  |  |     mode: int  | 
5932  |  |         Mode of process creation.  | 
5933  |  |     path: path_t  | 
5934  |  |         Path of executable file.  | 
5935  |  |     argv: object  | 
5936  |  |         Tuple or list of strings.  | 
5937  |  |     env: object  | 
5938  |  |         Dictionary of strings mapping to strings.  | 
5939  |  |     /  | 
5940  |  |  | 
5941  |  | Execute the program specified by path in a new process.  | 
5942  |  | [clinic start generated code]*/  | 
5943  |  |  | 
5944  |  | static PyObject *  | 
5945  |  | os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,  | 
5946  |  |                 PyObject *env)  | 
5947  |  | /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/  | 
5948  |  | { | 
5949  |  |     EXECV_CHAR **argvlist;  | 
5950  |  |     EXECV_CHAR **envlist;  | 
5951  |  |     PyObject *res = NULL;  | 
5952  |  |     Py_ssize_t argc, i, envc;  | 
5953  |  |     intptr_t spawnval;  | 
5954  |  |     PyObject *(*getitem)(PyObject *, Py_ssize_t);  | 
5955  |  |     Py_ssize_t lastarg = 0;  | 
5956  |  |  | 
5957  |  |     /* spawnve has four arguments: (mode, path, argv, env), where  | 
5958  |  |        argv is a list or tuple of strings and env is a dictionary  | 
5959  |  |        like posix.environ. */  | 
5960  |  |  | 
5961  |  |     if (PyList_Check(argv)) { | 
5962  |  |         argc = PyList_Size(argv);  | 
5963  |  |         getitem = PyList_GetItem;  | 
5964  |  |     }  | 
5965  |  |     else if (PyTuple_Check(argv)) { | 
5966  |  |         argc = PyTuple_Size(argv);  | 
5967  |  |         getitem = PyTuple_GetItem;  | 
5968  |  |     }  | 
5969  |  |     else { | 
5970  |  |         PyErr_SetString(PyExc_TypeError,  | 
5971  |  |                         "spawnve() arg 2 must be a tuple or list");  | 
5972  |  |         goto fail_0;  | 
5973  |  |     }  | 
5974  |  |     if (argc == 0) { | 
5975  |  |         PyErr_SetString(PyExc_ValueError,  | 
5976  |  |             "spawnve() arg 2 cannot be empty");  | 
5977  |  |         goto fail_0;  | 
5978  |  |     }  | 
5979  |  |     if (!PyMapping_Check(env)) { | 
5980  |  |         PyErr_SetString(PyExc_TypeError,  | 
5981  |  |                         "spawnve() arg 3 must be a mapping object");  | 
5982  |  |         goto fail_0;  | 
5983  |  |     }  | 
5984  |  |  | 
5985  |  |     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);  | 
5986  |  |     if (argvlist == NULL) { | 
5987  |  |         PyErr_NoMemory();  | 
5988  |  |         goto fail_0;  | 
5989  |  |     }  | 
5990  |  |     for (i = 0; i < argc; i++) { | 
5991  |  |         if (!fsconvert_strdup((*getitem)(argv, i),  | 
5992  |  |                               &argvlist[i]))  | 
5993  |  |         { | 
5994  |  |             lastarg = i;  | 
5995  |  |             goto fail_1;  | 
5996  |  |         }  | 
5997  |  |         if (i == 0 && !argvlist[0][0]) { | 
5998  |  |             lastarg = i + 1;  | 
5999  |  |             PyErr_SetString(  | 
6000  |  |                 PyExc_ValueError,  | 
6001  |  |                 "spawnv() arg 2 first element cannot be empty");  | 
6002  |  |             goto fail_1;  | 
6003  |  |         }  | 
6004  |  |     }  | 
6005  |  |     lastarg = argc;  | 
6006  |  |     argvlist[argc] = NULL;  | 
6007  |  |  | 
6008  |  |     envlist = parse_envlist(env, &envc);  | 
6009  |  |     if (envlist == NULL)  | 
6010  |  |         goto fail_1;  | 
6011  |  |  | 
6012  |  | #if !defined(HAVE_RTPSPAWN)  | 
6013  |  |     if (mode == _OLD_P_OVERLAY)  | 
6014  |  |         mode = _P_OVERLAY;  | 
6015  |  | #endif  | 
6016  |  |  | 
6017  |  |     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) { | 
6018  |  |         goto fail_2;  | 
6019  |  |     }  | 
6020  |  |  | 
6021  |  |     Py_BEGIN_ALLOW_THREADS  | 
6022  |  |     _Py_BEGIN_SUPPRESS_IPH  | 
6023  |  | #ifdef HAVE_WSPAWNV  | 
6024  |  |     spawnval = _wspawnve(mode, path->wide, argvlist, envlist);  | 
6025  |  | #elif defined(HAVE_RTPSPAWN)  | 
6026  |  |     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,  | 
6027  |  |                            (const char **)envlist);  | 
6028  |  | #else  | 
6029  |  |     spawnval = _spawnve(mode, path->narrow, argvlist, envlist);  | 
6030  |  | #endif  | 
6031  |  |     _Py_END_SUPPRESS_IPH  | 
6032  |  |     Py_END_ALLOW_THREADS  | 
6033  |  |  | 
6034  |  |     if (spawnval == -1)  | 
6035  |  |         (void) posix_error();  | 
6036  |  |     else  | 
6037  |  |         res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);  | 
6038  |  |  | 
6039  |  |   fail_2:  | 
6040  |  |     while (--envc >= 0)  | 
6041  |  |         PyMem_DEL(envlist[envc]);  | 
6042  |  |     PyMem_DEL(envlist);  | 
6043  |  |   fail_1:  | 
6044  |  |     free_string_array(argvlist, lastarg);  | 
6045  |  |   fail_0:  | 
6046  |  |     return res;  | 
6047  |  | }  | 
6048  |  |  | 
6049  |  | #endif /* HAVE_SPAWNV */  | 
6050  |  |  | 
6051  |  |  | 
6052  |  | #ifdef HAVE_FORK  | 
6053  |  |  | 
6054  |  | /* Helper function to validate arguments.  | 
6055  |  |    Returns 0 on success.  non-zero on failure with a TypeError raised.  | 
6056  |  |    If obj is non-NULL it must be callable.  */  | 
6057  |  | static int  | 
6058  |  | check_null_or_callable(PyObject *obj, const char* obj_name)  | 
6059  | 6  | { | 
6060  | 6  |     if (obj && !PyCallable_Check(obj)) { | 
6061  | 0  |         PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",  | 
6062  | 0  |                      obj_name, Py_TYPE(obj)->tp_name);  | 
6063  | 0  |         return -1;  | 
6064  | 0  |     }  | 
6065  | 6  |     return 0;  | 
6066  | 6  | }  | 
6067  |  |  | 
6068  |  | /*[clinic input]  | 
6069  |  | os.register_at_fork  | 
6070  |  |  | 
6071  |  |     *  | 
6072  |  |     before: object=NULL  | 
6073  |  |         A callable to be called in the parent before the fork() syscall.  | 
6074  |  |     after_in_child: object=NULL  | 
6075  |  |         A callable to be called in the child after fork().  | 
6076  |  |     after_in_parent: object=NULL  | 
6077  |  |         A callable to be called in the parent after fork().  | 
6078  |  |  | 
6079  |  | Register callables to be called when forking a new process.  | 
6080  |  |  | 
6081  |  | 'before' callbacks are called in reverse order.  | 
6082  |  | 'after_in_child' and 'after_in_parent' callbacks are called in order.  | 
6083  |  |  | 
6084  |  | [clinic start generated code]*/  | 
6085  |  |  | 
6086  |  | static PyObject *  | 
6087  |  | os_register_at_fork_impl(PyObject *module, PyObject *before,  | 
6088  |  |                          PyObject *after_in_child, PyObject *after_in_parent)  | 
6089  |  | /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/  | 
6090  | 2  | { | 
6091  | 2  |     PyInterpreterState *interp;  | 
6092  |  |  | 
6093  | 2  |     if (!before && !after_in_child && !after_in_parent) { | 
6094  | 0  |         PyErr_SetString(PyExc_TypeError, "At least one argument is required.");  | 
6095  | 0  |         return NULL;  | 
6096  | 0  |     }  | 
6097  | 2  |     if (check_null_or_callable(before, "before") ||  | 
6098  | 2  |         check_null_or_callable(after_in_child, "after_in_child") ||  | 
6099  | 2  |         check_null_or_callable(after_in_parent, "after_in_parent")) { | 
6100  | 0  |         return NULL;  | 
6101  | 0  |     }  | 
6102  | 2  |     interp = _PyInterpreterState_Get();  | 
6103  |  |  | 
6104  | 2  |     if (register_at_forker(&interp->before_forkers, before)) { | 
6105  | 0  |         return NULL;  | 
6106  | 0  |     }  | 
6107  | 2  |     if (register_at_forker(&interp->after_forkers_child, after_in_child)) { | 
6108  | 0  |         return NULL;  | 
6109  | 0  |     }  | 
6110  | 2  |     if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) { | 
6111  | 0  |         return NULL;  | 
6112  | 0  |     }  | 
6113  | 2  |     Py_RETURN_NONE;  | 
6114  | 2  | }  | 
6115  |  | #endif /* HAVE_FORK */  | 
6116  |  |  | 
6117  |  |  | 
6118  |  | #ifdef HAVE_FORK1  | 
6119  |  | /*[clinic input]  | 
6120  |  | os.fork1  | 
6121  |  |  | 
6122  |  | Fork a child process with a single multiplexed (i.e., not bound) thread.  | 
6123  |  |  | 
6124  |  | Return 0 to child process and PID of child to parent process.  | 
6125  |  | [clinic start generated code]*/  | 
6126  |  |  | 
6127  |  | static PyObject *  | 
6128  |  | os_fork1_impl(PyObject *module)  | 
6129  |  | /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/  | 
6130  |  | { | 
6131  |  |     pid_t pid;  | 
6132  |  |  | 
6133  |  |     if (_PyInterpreterState_Get() != PyInterpreterState_Main()) { | 
6134  |  |         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");  | 
6135  |  |         return NULL;  | 
6136  |  |     }  | 
6137  |  |     PyOS_BeforeFork();  | 
6138  |  |     pid = fork1();  | 
6139  |  |     if (pid == 0) { | 
6140  |  |         /* child: this clobbers and resets the import lock. */  | 
6141  |  |         PyOS_AfterFork_Child();  | 
6142  |  |     } else { | 
6143  |  |         /* parent: release the import lock. */  | 
6144  |  |         PyOS_AfterFork_Parent();  | 
6145  |  |     }  | 
6146  |  |     if (pid == -1)  | 
6147  |  |         return posix_error();  | 
6148  |  |     return PyLong_FromPid(pid);  | 
6149  |  | }  | 
6150  |  | #endif /* HAVE_FORK1 */  | 
6151  |  |  | 
6152  |  |  | 
6153  |  | #ifdef HAVE_FORK  | 
6154  |  | /*[clinic input]  | 
6155  |  | os.fork  | 
6156  |  |  | 
6157  |  | Fork a child process.  | 
6158  |  |  | 
6159  |  | Return 0 to child process and PID of child to parent process.  | 
6160  |  | [clinic start generated code]*/  | 
6161  |  |  | 
6162  |  | static PyObject *  | 
6163  |  | os_fork_impl(PyObject *module)  | 
6164  |  | /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/  | 
6165  | 0  | { | 
6166  | 0  |     pid_t pid;  | 
6167  |  | 
  | 
6168  | 0  |     if (_PyInterpreterState_Get() != PyInterpreterState_Main()) { | 
6169  | 0  |         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");  | 
6170  | 0  |         return NULL;  | 
6171  | 0  |     }  | 
6172  | 0  |     if (PySys_Audit("os.fork", NULL) < 0) { | 
6173  | 0  |         return NULL;  | 
6174  | 0  |     }  | 
6175  | 0  |     PyOS_BeforeFork();  | 
6176  | 0  |     pid = fork();  | 
6177  | 0  |     if (pid == 0) { | 
6178  |  |         /* child: this clobbers and resets the import lock. */  | 
6179  | 0  |         PyOS_AfterFork_Child();  | 
6180  | 0  |     } else { | 
6181  |  |         /* parent: release the import lock. */  | 
6182  | 0  |         PyOS_AfterFork_Parent();  | 
6183  | 0  |     }  | 
6184  | 0  |     if (pid == -1)  | 
6185  | 0  |         return posix_error();  | 
6186  | 0  |     return PyLong_FromPid(pid);  | 
6187  | 0  | }  | 
6188  |  | #endif /* HAVE_FORK */  | 
6189  |  |  | 
6190  |  |  | 
6191  |  | #ifdef HAVE_SCHED_H  | 
6192  |  | #ifdef HAVE_SCHED_GET_PRIORITY_MAX  | 
6193  |  | /*[clinic input]  | 
6194  |  | os.sched_get_priority_max  | 
6195  |  |  | 
6196  |  |     policy: int  | 
6197  |  |  | 
6198  |  | Get the maximum scheduling priority for policy.  | 
6199  |  | [clinic start generated code]*/  | 
6200  |  |  | 
6201  |  | static PyObject *  | 
6202  |  | os_sched_get_priority_max_impl(PyObject *module, int policy)  | 
6203  |  | /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/  | 
6204  | 0  | { | 
6205  | 0  |     int max;  | 
6206  |  | 
  | 
6207  | 0  |     max = sched_get_priority_max(policy);  | 
6208  | 0  |     if (max < 0)  | 
6209  | 0  |         return posix_error();  | 
6210  | 0  |     return PyLong_FromLong(max);  | 
6211  | 0  | }  | 
6212  |  |  | 
6213  |  |  | 
6214  |  | /*[clinic input]  | 
6215  |  | os.sched_get_priority_min  | 
6216  |  |  | 
6217  |  |     policy: int  | 
6218  |  |  | 
6219  |  | Get the minimum scheduling priority for policy.  | 
6220  |  | [clinic start generated code]*/  | 
6221  |  |  | 
6222  |  | static PyObject *  | 
6223  |  | os_sched_get_priority_min_impl(PyObject *module, int policy)  | 
6224  |  | /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/  | 
6225  | 0  | { | 
6226  | 0  |     int min = sched_get_priority_min(policy);  | 
6227  | 0  |     if (min < 0)  | 
6228  | 0  |         return posix_error();  | 
6229  | 0  |     return PyLong_FromLong(min);  | 
6230  | 0  | }  | 
6231  |  | #endif /* HAVE_SCHED_GET_PRIORITY_MAX */  | 
6232  |  |  | 
6233  |  |  | 
6234  |  | #ifdef HAVE_SCHED_SETSCHEDULER  | 
6235  |  | /*[clinic input]  | 
6236  |  | os.sched_getscheduler  | 
6237  |  |     pid: pid_t  | 
6238  |  |     /  | 
6239  |  |  | 
6240  |  | Get the scheduling policy for the process identifiedy by pid.  | 
6241  |  |  | 
6242  |  | Passing 0 for pid returns the scheduling policy for the calling process.  | 
6243  |  | [clinic start generated code]*/  | 
6244  |  |  | 
6245  |  | static PyObject *  | 
6246  |  | os_sched_getscheduler_impl(PyObject *module, pid_t pid)  | 
6247  |  | /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=5f14cfd1f189e1a0]*/  | 
6248  | 0  | { | 
6249  | 0  |     int policy;  | 
6250  |  | 
  | 
6251  | 0  |     policy = sched_getscheduler(pid);  | 
6252  | 0  |     if (policy < 0)  | 
6253  | 0  |         return posix_error();  | 
6254  | 0  |     return PyLong_FromLong(policy);  | 
6255  | 0  | }  | 
6256  |  | #endif /* HAVE_SCHED_SETSCHEDULER */  | 
6257  |  |  | 
6258  |  |  | 
6259  |  | #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)  | 
6260  |  | /*[clinic input]  | 
6261  |  | class os.sched_param "PyObject *" "SchedParamType"  | 
6262  |  |  | 
6263  |  | @classmethod  | 
6264  |  | os.sched_param.__new__  | 
6265  |  |  | 
6266  |  |     sched_priority: object  | 
6267  |  |         A scheduling parameter.  | 
6268  |  |  | 
6269  |  | Current has only one field: sched_priority");  | 
6270  |  | [clinic start generated code]*/  | 
6271  |  |  | 
6272  |  | static PyObject *  | 
6273  |  | os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)  | 
6274  |  | /*[clinic end generated code: output=48f4067d60f48c13 input=ab4de35a9a7811f2]*/  | 
6275  | 0  | { | 
6276  | 0  |     PyObject *res;  | 
6277  |  | 
  | 
6278  | 0  |     res = PyStructSequence_New(type);  | 
6279  | 0  |     if (!res)  | 
6280  | 0  |         return NULL;  | 
6281  | 0  |     Py_INCREF(sched_priority);  | 
6282  | 0  |     PyStructSequence_SET_ITEM(res, 0, sched_priority);  | 
6283  | 0  |     return res;  | 
6284  | 0  | }  | 
6285  |  |  | 
6286  |  |  | 
6287  |  | PyDoc_VAR(os_sched_param__doc__);  | 
6288  |  |  | 
6289  |  | static PyStructSequence_Field sched_param_fields[] = { | 
6290  |  |     {"sched_priority", "the scheduling priority"}, | 
6291  |  |     {0} | 
6292  |  | };  | 
6293  |  |  | 
6294  |  | static PyStructSequence_Desc sched_param_desc = { | 
6295  |  |     "sched_param", /* name */  | 
6296  |  |     os_sched_param__doc__, /* doc */  | 
6297  |  |     sched_param_fields,  | 
6298  |  |     1  | 
6299  |  | };  | 
6300  |  |  | 
6301  |  | static int  | 
6302  |  | convert_sched_param(PyObject *param, struct sched_param *res)  | 
6303  | 0  | { | 
6304  | 0  |     long priority;  | 
6305  |  | 
  | 
6306  | 0  |     if (Py_TYPE(param) != SchedParamType) { | 
6307  | 0  |         PyErr_SetString(PyExc_TypeError, "must have a sched_param object");  | 
6308  | 0  |         return 0;  | 
6309  | 0  |     }  | 
6310  | 0  |     priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));  | 
6311  | 0  |     if (priority == -1 && PyErr_Occurred())  | 
6312  | 0  |         return 0;  | 
6313  | 0  |     if (priority > INT_MAX || priority < INT_MIN) { | 
6314  | 0  |         PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");  | 
6315  | 0  |         return 0;  | 
6316  | 0  |     }  | 
6317  | 0  |     res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);  | 
6318  | 0  |     return 1;  | 
6319  | 0  | }  | 
6320  |  | #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */  | 
6321  |  |  | 
6322  |  |  | 
6323  |  | #ifdef HAVE_SCHED_SETSCHEDULER  | 
6324  |  | /*[clinic input]  | 
6325  |  | os.sched_setscheduler  | 
6326  |  |  | 
6327  |  |     pid: pid_t  | 
6328  |  |     policy: int  | 
6329  |  |     param: sched_param  | 
6330  |  |     /  | 
6331  |  |  | 
6332  |  | Set the scheduling policy for the process identified by pid.  | 
6333  |  |  | 
6334  |  | If pid is 0, the calling process is changed.  | 
6335  |  | param is an instance of sched_param.  | 
6336  |  | [clinic start generated code]*/  | 
6337  |  |  | 
6338  |  | static PyObject *  | 
6339  |  | os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,  | 
6340  |  |                            struct sched_param *param)  | 
6341  |  | /*[clinic end generated code: output=b0ac0a70d3b1d705 input=c581f9469a5327dd]*/  | 
6342  | 0  | { | 
6343  |  |     /*  | 
6344  |  |     ** sched_setscheduler() returns 0 in Linux, but the previous  | 
6345  |  |     ** scheduling policy under Solaris/Illumos, and others.  | 
6346  |  |     ** On error, -1 is returned in all Operating Systems.  | 
6347  |  |     */  | 
6348  | 0  |     if (sched_setscheduler(pid, policy, param) == -1)  | 
6349  | 0  |         return posix_error();  | 
6350  | 0  |     Py_RETURN_NONE;  | 
6351  | 0  | }  | 
6352  |  | #endif  /* HAVE_SCHED_SETSCHEDULER*/  | 
6353  |  |  | 
6354  |  |  | 
6355  |  | #ifdef HAVE_SCHED_SETPARAM  | 
6356  |  | /*[clinic input]  | 
6357  |  | os.sched_getparam  | 
6358  |  |     pid: pid_t  | 
6359  |  |     /  | 
6360  |  |  | 
6361  |  | Returns scheduling parameters for the process identified by pid.  | 
6362  |  |  | 
6363  |  | If pid is 0, returns parameters for the calling process.  | 
6364  |  | Return value is an instance of sched_param.  | 
6365  |  | [clinic start generated code]*/  | 
6366  |  |  | 
6367  |  | static PyObject *  | 
6368  |  | os_sched_getparam_impl(PyObject *module, pid_t pid)  | 
6369  |  | /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/  | 
6370  | 0  | { | 
6371  | 0  |     struct sched_param param;  | 
6372  | 0  |     PyObject *result;  | 
6373  | 0  |     PyObject *priority;  | 
6374  |  | 
  | 
6375  | 0  |     if (sched_getparam(pid, ¶m))  | 
6376  | 0  |         return posix_error();  | 
6377  | 0  |     result = PyStructSequence_New(SchedParamType);  | 
6378  | 0  |     if (!result)  | 
6379  | 0  |         return NULL;  | 
6380  | 0  |     priority = PyLong_FromLong(param.sched_priority);  | 
6381  | 0  |     if (!priority) { | 
6382  | 0  |         Py_DECREF(result);  | 
6383  | 0  |         return NULL;  | 
6384  | 0  |     }  | 
6385  | 0  |     PyStructSequence_SET_ITEM(result, 0, priority);  | 
6386  | 0  |     return result;  | 
6387  | 0  | }  | 
6388  |  |  | 
6389  |  |  | 
6390  |  | /*[clinic input]  | 
6391  |  | os.sched_setparam  | 
6392  |  |     pid: pid_t  | 
6393  |  |     param: sched_param  | 
6394  |  |     /  | 
6395  |  |  | 
6396  |  | Set scheduling parameters for the process identified by pid.  | 
6397  |  |  | 
6398  |  | If pid is 0, sets parameters for the calling process.  | 
6399  |  | param should be an instance of sched_param.  | 
6400  |  | [clinic start generated code]*/  | 
6401  |  |  | 
6402  |  | static PyObject *  | 
6403  |  | os_sched_setparam_impl(PyObject *module, pid_t pid,  | 
6404  |  |                        struct sched_param *param)  | 
6405  |  | /*[clinic end generated code: output=8af013f78a32b591 input=6b8d6dfcecdc21bd]*/  | 
6406  | 0  | { | 
6407  | 0  |     if (sched_setparam(pid, param))  | 
6408  | 0  |         return posix_error();  | 
6409  | 0  |     Py_RETURN_NONE;  | 
6410  | 0  | }  | 
6411  |  | #endif /* HAVE_SCHED_SETPARAM */  | 
6412  |  |  | 
6413  |  |  | 
6414  |  | #ifdef HAVE_SCHED_RR_GET_INTERVAL  | 
6415  |  | /*[clinic input]  | 
6416  |  | os.sched_rr_get_interval -> double  | 
6417  |  |     pid: pid_t  | 
6418  |  |     /  | 
6419  |  |  | 
6420  |  | Return the round-robin quantum for the process identified by pid, in seconds.  | 
6421  |  |  | 
6422  |  | Value returned is a float.  | 
6423  |  | [clinic start generated code]*/  | 
6424  |  |  | 
6425  |  | static double  | 
6426  |  | os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)  | 
6427  |  | /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/  | 
6428  | 0  | { | 
6429  | 0  |     struct timespec interval;  | 
6430  | 0  |     if (sched_rr_get_interval(pid, &interval)) { | 
6431  | 0  |         posix_error();  | 
6432  | 0  |         return -1.0;  | 
6433  | 0  |     }  | 
6434  |  | #ifdef _Py_MEMORY_SANITIZER  | 
6435  |  |     __msan_unpoison(&interval, sizeof(interval));  | 
6436  |  | #endif  | 
6437  | 0  |     return (double)interval.tv_sec + 1e-9*interval.tv_nsec;  | 
6438  | 0  | }  | 
6439  |  | #endif /* HAVE_SCHED_RR_GET_INTERVAL */  | 
6440  |  |  | 
6441  |  |  | 
6442  |  | /*[clinic input]  | 
6443  |  | os.sched_yield  | 
6444  |  |  | 
6445  |  | Voluntarily relinquish the CPU.  | 
6446  |  | [clinic start generated code]*/  | 
6447  |  |  | 
6448  |  | static PyObject *  | 
6449  |  | os_sched_yield_impl(PyObject *module)  | 
6450  |  | /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/  | 
6451  | 0  | { | 
6452  | 0  |     if (sched_yield())  | 
6453  | 0  |         return posix_error();  | 
6454  | 0  |     Py_RETURN_NONE;  | 
6455  | 0  | }  | 
6456  |  |  | 
6457  |  | #ifdef HAVE_SCHED_SETAFFINITY  | 
6458  |  | /* The minimum number of CPUs allocated in a cpu_set_t */  | 
6459  |  | static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;  | 
6460  |  |  | 
6461  |  | /*[clinic input]  | 
6462  |  | os.sched_setaffinity  | 
6463  |  |     pid: pid_t  | 
6464  |  |     mask : object  | 
6465  |  |     /  | 
6466  |  |  | 
6467  |  | Set the CPU affinity of the process identified by pid to mask.  | 
6468  |  |  | 
6469  |  | mask should be an iterable of integers identifying CPUs.  | 
6470  |  | [clinic start generated code]*/  | 
6471  |  |  | 
6472  |  | static PyObject *  | 
6473  |  | os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)  | 
6474  |  | /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/  | 
6475  | 0  | { | 
6476  | 0  |     int ncpus;  | 
6477  | 0  |     size_t setsize;  | 
6478  | 0  |     cpu_set_t *cpu_set = NULL;  | 
6479  | 0  |     PyObject *iterator = NULL, *item;  | 
6480  |  | 
  | 
6481  | 0  |     iterator = PyObject_GetIter(mask);  | 
6482  | 0  |     if (iterator == NULL)  | 
6483  | 0  |         return NULL;  | 
6484  |  |  | 
6485  | 0  |     ncpus = NCPUS_START;  | 
6486  | 0  |     setsize = CPU_ALLOC_SIZE(ncpus);  | 
6487  | 0  |     cpu_set = CPU_ALLOC(ncpus);  | 
6488  | 0  |     if (cpu_set == NULL) { | 
6489  | 0  |         PyErr_NoMemory();  | 
6490  | 0  |         goto error;  | 
6491  | 0  |     }  | 
6492  | 0  |     CPU_ZERO_S(setsize, cpu_set);  | 
6493  |  | 
  | 
6494  | 0  |     while ((item = PyIter_Next(iterator))) { | 
6495  | 0  |         long cpu;  | 
6496  | 0  |         if (!PyLong_Check(item)) { | 
6497  | 0  |             PyErr_Format(PyExc_TypeError,  | 
6498  | 0  |                         "expected an iterator of ints, "  | 
6499  | 0  |                         "but iterator yielded %R",  | 
6500  | 0  |                         Py_TYPE(item));  | 
6501  | 0  |             Py_DECREF(item);  | 
6502  | 0  |             goto error;  | 
6503  | 0  |         }  | 
6504  | 0  |         cpu = PyLong_AsLong(item);  | 
6505  | 0  |         Py_DECREF(item);  | 
6506  | 0  |         if (cpu < 0) { | 
6507  | 0  |             if (!PyErr_Occurred())  | 
6508  | 0  |                 PyErr_SetString(PyExc_ValueError, "negative CPU number");  | 
6509  | 0  |             goto error;  | 
6510  | 0  |         }  | 
6511  | 0  |         if (cpu > INT_MAX - 1) { | 
6512  | 0  |             PyErr_SetString(PyExc_OverflowError, "CPU number too large");  | 
6513  | 0  |             goto error;  | 
6514  | 0  |         }  | 
6515  | 0  |         if (cpu >= ncpus) { | 
6516  |  |             /* Grow CPU mask to fit the CPU number */  | 
6517  | 0  |             int newncpus = ncpus;  | 
6518  | 0  |             cpu_set_t *newmask;  | 
6519  | 0  |             size_t newsetsize;  | 
6520  | 0  |             while (newncpus <= cpu) { | 
6521  | 0  |                 if (newncpus > INT_MAX / 2)  | 
6522  | 0  |                     newncpus = cpu + 1;  | 
6523  | 0  |                 else  | 
6524  | 0  |                     newncpus = newncpus * 2;  | 
6525  | 0  |             }  | 
6526  | 0  |             newmask = CPU_ALLOC(newncpus);  | 
6527  | 0  |             if (newmask == NULL) { | 
6528  | 0  |                 PyErr_NoMemory();  | 
6529  | 0  |                 goto error;  | 
6530  | 0  |             }  | 
6531  | 0  |             newsetsize = CPU_ALLOC_SIZE(newncpus);  | 
6532  | 0  |             CPU_ZERO_S(newsetsize, newmask);  | 
6533  | 0  |             memcpy(newmask, cpu_set, setsize);  | 
6534  | 0  |             CPU_FREE(cpu_set);  | 
6535  | 0  |             setsize = newsetsize;  | 
6536  | 0  |             cpu_set = newmask;  | 
6537  | 0  |             ncpus = newncpus;  | 
6538  | 0  |         }  | 
6539  | 0  |         CPU_SET_S(cpu, setsize, cpu_set);  | 
6540  | 0  |     }  | 
6541  | 0  |     if (PyErr_Occurred()) { | 
6542  | 0  |         goto error;  | 
6543  | 0  |     }  | 
6544  | 0  |     Py_CLEAR(iterator);  | 
6545  |  | 
  | 
6546  | 0  |     if (sched_setaffinity(pid, setsize, cpu_set)) { | 
6547  | 0  |         posix_error();  | 
6548  | 0  |         goto error;  | 
6549  | 0  |     }  | 
6550  | 0  |     CPU_FREE(cpu_set);  | 
6551  | 0  |     Py_RETURN_NONE;  | 
6552  |  |  | 
6553  | 0  | error:  | 
6554  | 0  |     if (cpu_set)  | 
6555  | 0  |         CPU_FREE(cpu_set);  | 
6556  | 0  |     Py_XDECREF(iterator);  | 
6557  | 0  |     return NULL;  | 
6558  | 0  | }  | 
6559  |  |  | 
6560  |  |  | 
6561  |  | /*[clinic input]  | 
6562  |  | os.sched_getaffinity  | 
6563  |  |     pid: pid_t  | 
6564  |  |     /  | 
6565  |  |  | 
6566  |  | Return the affinity of the process identified by pid (or the current process if zero).  | 
6567  |  |  | 
6568  |  | The affinity is returned as a set of CPU identifiers.  | 
6569  |  | [clinic start generated code]*/  | 
6570  |  |  | 
6571  |  | static PyObject *  | 
6572  |  | os_sched_getaffinity_impl(PyObject *module, pid_t pid)  | 
6573  |  | /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/  | 
6574  | 0  | { | 
6575  | 0  |     int cpu, ncpus, count;  | 
6576  | 0  |     size_t setsize;  | 
6577  | 0  |     cpu_set_t *mask = NULL;  | 
6578  | 0  |     PyObject *res = NULL;  | 
6579  |  | 
  | 
6580  | 0  |     ncpus = NCPUS_START;  | 
6581  | 0  |     while (1) { | 
6582  | 0  |         setsize = CPU_ALLOC_SIZE(ncpus);  | 
6583  | 0  |         mask = CPU_ALLOC(ncpus);  | 
6584  | 0  |         if (mask == NULL)  | 
6585  | 0  |             return PyErr_NoMemory();  | 
6586  | 0  |         if (sched_getaffinity(pid, setsize, mask) == 0)  | 
6587  | 0  |             break;  | 
6588  | 0  |         CPU_FREE(mask);  | 
6589  | 0  |         if (errno != EINVAL)  | 
6590  | 0  |             return posix_error();  | 
6591  | 0  |         if (ncpus > INT_MAX / 2) { | 
6592  | 0  |             PyErr_SetString(PyExc_OverflowError, "could not allocate "  | 
6593  | 0  |                             "a large enough CPU set");  | 
6594  | 0  |             return NULL;  | 
6595  | 0  |         }  | 
6596  | 0  |         ncpus = ncpus * 2;  | 
6597  | 0  |     }  | 
6598  |  |  | 
6599  | 0  |     res = PySet_New(NULL);  | 
6600  | 0  |     if (res == NULL)  | 
6601  | 0  |         goto error;  | 
6602  | 0  |     for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) { | 
6603  | 0  |         if (CPU_ISSET_S(cpu, setsize, mask)) { | 
6604  | 0  |             PyObject *cpu_num = PyLong_FromLong(cpu);  | 
6605  | 0  |             --count;  | 
6606  | 0  |             if (cpu_num == NULL)  | 
6607  | 0  |                 goto error;  | 
6608  | 0  |             if (PySet_Add(res, cpu_num)) { | 
6609  | 0  |                 Py_DECREF(cpu_num);  | 
6610  | 0  |                 goto error;  | 
6611  | 0  |             }  | 
6612  | 0  |             Py_DECREF(cpu_num);  | 
6613  | 0  |         }  | 
6614  | 0  |     }  | 
6615  | 0  |     CPU_FREE(mask);  | 
6616  | 0  |     return res;  | 
6617  |  |  | 
6618  | 0  | error:  | 
6619  | 0  |     if (mask)  | 
6620  | 0  |         CPU_FREE(mask);  | 
6621  | 0  |     Py_XDECREF(res);  | 
6622  | 0  |     return NULL;  | 
6623  | 0  | }  | 
6624  |  |  | 
6625  |  | #endif /* HAVE_SCHED_SETAFFINITY */  | 
6626  |  |  | 
6627  |  | #endif /* HAVE_SCHED_H */  | 
6628  |  |  | 
6629  |  |  | 
6630  |  | /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */  | 
6631  |  | /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */  | 
6632  |  | #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)  | 
6633  |  | #define DEV_PTY_FILE "/dev/ptc"  | 
6634  |  | #define HAVE_DEV_PTMX  | 
6635  |  | #else  | 
6636  |  | #define DEV_PTY_FILE "/dev/ptmx"  | 
6637  |  | #endif  | 
6638  |  |  | 
6639  |  | #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)  | 
6640  |  | #ifdef HAVE_PTY_H  | 
6641  |  | #include <pty.h>  | 
6642  |  | #else  | 
6643  |  | #ifdef HAVE_LIBUTIL_H  | 
6644  |  | #include <libutil.h>  | 
6645  |  | #else  | 
6646  |  | #ifdef HAVE_UTIL_H  | 
6647  |  | #include <util.h>  | 
6648  |  | #endif /* HAVE_UTIL_H */  | 
6649  |  | #endif /* HAVE_LIBUTIL_H */  | 
6650  |  | #endif /* HAVE_PTY_H */  | 
6651  |  | #ifdef HAVE_STROPTS_H  | 
6652  |  | #include <stropts.h>  | 
6653  |  | #endif  | 
6654  |  | #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */  | 
6655  |  |  | 
6656  |  |  | 
6657  |  | #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)  | 
6658  |  | /*[clinic input]  | 
6659  |  | os.openpty  | 
6660  |  |  | 
6661  |  | Open a pseudo-terminal.  | 
6662  |  |  | 
6663  |  | Return a tuple of (master_fd, slave_fd) containing open file descriptors  | 
6664  |  | for both the master and slave ends.  | 
6665  |  | [clinic start generated code]*/  | 
6666  |  |  | 
6667  |  | static PyObject *  | 
6668  |  | os_openpty_impl(PyObject *module)  | 
6669  |  | /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/  | 
6670  | 0  | { | 
6671  | 0  |     int master_fd = -1, slave_fd = -1;  | 
6672  |  | #ifndef HAVE_OPENPTY  | 
6673  |  |     char * slave_name;  | 
6674  |  | #endif  | 
6675  |  | #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)  | 
6676  |  |     PyOS_sighandler_t sig_saved;  | 
6677  |  | #if defined(__sun) && defined(__SVR4)  | 
6678  |  |     extern char *ptsname(int fildes);  | 
6679  |  | #endif  | 
6680  |  | #endif  | 
6681  |  | 
  | 
6682  | 0  | #ifdef HAVE_OPENPTY  | 
6683  | 0  |     if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)  | 
6684  | 0  |         goto posix_error;  | 
6685  |  |  | 
6686  | 0  |     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)  | 
6687  | 0  |         goto error;  | 
6688  | 0  |     if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)  | 
6689  | 0  |         goto error;  | 
6690  |  |  | 
6691  |  | #elif defined(HAVE__GETPTY)  | 
6692  |  |     slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);  | 
6693  |  |     if (slave_name == NULL)  | 
6694  |  |         goto posix_error;  | 
6695  |  |     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)  | 
6696  |  |         goto error;  | 
6697  |  |  | 
6698  |  |     slave_fd = _Py_open(slave_name, O_RDWR);  | 
6699  |  |     if (slave_fd < 0)  | 
6700  |  |         goto error;  | 
6701  |  |  | 
6702  |  | #else  | 
6703  |  |     master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */  | 
6704  |  |     if (master_fd < 0)  | 
6705  |  |         goto posix_error;  | 
6706  |  |  | 
6707  |  |     sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);  | 
6708  |  |  | 
6709  |  |     /* change permission of slave */  | 
6710  |  |     if (grantpt(master_fd) < 0) { | 
6711  |  |         PyOS_setsig(SIGCHLD, sig_saved);  | 
6712  |  |         goto posix_error;  | 
6713  |  |     }  | 
6714  |  |  | 
6715  |  |     /* unlock slave */  | 
6716  |  |     if (unlockpt(master_fd) < 0) { | 
6717  |  |         PyOS_setsig(SIGCHLD, sig_saved);  | 
6718  |  |         goto posix_error;  | 
6719  |  |     }  | 
6720  |  |  | 
6721  |  |     PyOS_setsig(SIGCHLD, sig_saved);  | 
6722  |  |  | 
6723  |  |     slave_name = ptsname(master_fd); /* get name of slave */  | 
6724  |  |     if (slave_name == NULL)  | 
6725  |  |         goto posix_error;  | 
6726  |  |  | 
6727  |  |     slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */  | 
6728  |  |     if (slave_fd == -1)  | 
6729  |  |         goto error;  | 
6730  |  |  | 
6731  |  |     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)  | 
6732  |  |         goto posix_error;  | 
6733  |  |  | 
6734  |  | #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)  | 
6735  |  |     ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */  | 
6736  |  |     ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */  | 
6737  |  | #ifndef __hpux  | 
6738  |  |     ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */  | 
6739  |  | #endif /* __hpux */  | 
6740  |  | #endif /* HAVE_CYGWIN */  | 
6741  |  | #endif /* HAVE_OPENPTY */  | 
6742  |  |  | 
6743  | 0  |     return Py_BuildValue("(ii)", master_fd, slave_fd); | 
6744  |  |  | 
6745  | 0  | posix_error:  | 
6746  | 0  |     posix_error();  | 
6747  | 0  | error:  | 
6748  | 0  |     if (master_fd != -1)  | 
6749  | 0  |         close(master_fd);  | 
6750  | 0  |     if (slave_fd != -1)  | 
6751  | 0  |         close(slave_fd);  | 
6752  | 0  |     return NULL;  | 
6753  | 0  | }  | 
6754  |  | #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */  | 
6755  |  |  | 
6756  |  |  | 
6757  |  | #ifdef HAVE_FORKPTY  | 
6758  |  | /*[clinic input]  | 
6759  |  | os.forkpty  | 
6760  |  |  | 
6761  |  | Fork a new process with a new pseudo-terminal as controlling tty.  | 
6762  |  |  | 
6763  |  | Returns a tuple of (pid, master_fd).  | 
6764  |  | Like fork(), return pid of 0 to the child process,  | 
6765  |  | and pid of child to the parent process.  | 
6766  |  | To both, return fd of newly opened pseudo-terminal.  | 
6767  |  | [clinic start generated code]*/  | 
6768  |  |  | 
6769  |  | static PyObject *  | 
6770  |  | os_forkpty_impl(PyObject *module)  | 
6771  |  | /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/  | 
6772  | 0  | { | 
6773  | 0  |     int master_fd = -1;  | 
6774  | 0  |     pid_t pid;  | 
6775  |  | 
  | 
6776  | 0  |     if (_PyInterpreterState_Get() != PyInterpreterState_Main()) { | 
6777  | 0  |         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");  | 
6778  | 0  |         return NULL;  | 
6779  | 0  |     }  | 
6780  | 0  |     if (PySys_Audit("os.forkpty", NULL) < 0) { | 
6781  | 0  |         return NULL;  | 
6782  | 0  |     }  | 
6783  | 0  |     PyOS_BeforeFork();  | 
6784  | 0  |     pid = forkpty(&master_fd, NULL, NULL, NULL);  | 
6785  | 0  |     if (pid == 0) { | 
6786  |  |         /* child: this clobbers and resets the import lock. */  | 
6787  | 0  |         PyOS_AfterFork_Child();  | 
6788  | 0  |     } else { | 
6789  |  |         /* parent: release the import lock. */  | 
6790  | 0  |         PyOS_AfterFork_Parent();  | 
6791  | 0  |     }  | 
6792  | 0  |     if (pid == -1)  | 
6793  | 0  |         return posix_error();  | 
6794  | 0  |     return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd); | 
6795  | 0  | }  | 
6796  |  | #endif /* HAVE_FORKPTY */  | 
6797  |  |  | 
6798  |  |  | 
6799  |  | #ifdef HAVE_GETEGID  | 
6800  |  | /*[clinic input]  | 
6801  |  | os.getegid  | 
6802  |  |  | 
6803  |  | Return the current process's effective group id.  | 
6804  |  | [clinic start generated code]*/  | 
6805  |  |  | 
6806  |  | static PyObject *  | 
6807  |  | os_getegid_impl(PyObject *module)  | 
6808  |  | /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/  | 
6809  | 0  | { | 
6810  | 0  |     return _PyLong_FromGid(getegid());  | 
6811  | 0  | }  | 
6812  |  | #endif /* HAVE_GETEGID */  | 
6813  |  |  | 
6814  |  |  | 
6815  |  | #ifdef HAVE_GETEUID  | 
6816  |  | /*[clinic input]  | 
6817  |  | os.geteuid  | 
6818  |  |  | 
6819  |  | Return the current process's effective user id.  | 
6820  |  | [clinic start generated code]*/  | 
6821  |  |  | 
6822  |  | static PyObject *  | 
6823  |  | os_geteuid_impl(PyObject *module)  | 
6824  |  | /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/  | 
6825  | 0  | { | 
6826  | 0  |     return _PyLong_FromUid(geteuid());  | 
6827  | 0  | }  | 
6828  |  | #endif /* HAVE_GETEUID */  | 
6829  |  |  | 
6830  |  |  | 
6831  |  | #ifdef HAVE_GETGID  | 
6832  |  | /*[clinic input]  | 
6833  |  | os.getgid  | 
6834  |  |  | 
6835  |  | Return the current process's group id.  | 
6836  |  | [clinic start generated code]*/  | 
6837  |  |  | 
6838  |  | static PyObject *  | 
6839  |  | os_getgid_impl(PyObject *module)  | 
6840  |  | /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/  | 
6841  | 0  | { | 
6842  | 0  |     return _PyLong_FromGid(getgid());  | 
6843  | 0  | }  | 
6844  |  | #endif /* HAVE_GETGID */  | 
6845  |  |  | 
6846  |  |  | 
6847  |  | #ifdef HAVE_GETPID  | 
6848  |  | /*[clinic input]  | 
6849  |  | os.getpid  | 
6850  |  |  | 
6851  |  | Return the current process id.  | 
6852  |  | [clinic start generated code]*/  | 
6853  |  |  | 
6854  |  | static PyObject *  | 
6855  |  | os_getpid_impl(PyObject *module)  | 
6856  |  | /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/  | 
6857  | 14  | { | 
6858  | 14  |     return PyLong_FromPid(getpid());  | 
6859  | 14  | }  | 
6860  |  | #endif /* HAVE_GETPID */  | 
6861  |  |  | 
6862  |  | #ifdef NGROUPS_MAX  | 
6863  | 0  | #define MAX_GROUPS NGROUPS_MAX  | 
6864  |  | #else  | 
6865  |  |     /* defined to be 16 on Solaris7, so this should be a small number */  | 
6866  |  | #define MAX_GROUPS 64  | 
6867  |  | #endif  | 
6868  |  |  | 
6869  |  | #ifdef HAVE_GETGROUPLIST  | 
6870  |  |  | 
6871  |  | /* AC 3.5: funny apple logic below */  | 
6872  |  | PyDoc_STRVAR(posix_getgrouplist__doc__,  | 
6873  |  | "getgrouplist(user, group) -> list of groups to which a user belongs\n\n\  | 
6874  |  | Returns a list of groups to which a user belongs.\n\n\  | 
6875  |  |     user: username to lookup\n\  | 
6876  |  |     group: base group id of the user");  | 
6877  |  |  | 
6878  |  | static PyObject *  | 
6879  |  | posix_getgrouplist(PyObject *self, PyObject *args)  | 
6880  | 0  | { | 
6881  | 0  |     const char *user;  | 
6882  | 0  |     int i, ngroups;  | 
6883  | 0  |     PyObject *list;  | 
6884  |  | #ifdef __APPLE__  | 
6885  |  |     int *groups, basegid;  | 
6886  |  | #else  | 
6887  | 0  |     gid_t *groups, basegid;  | 
6888  | 0  | #endif  | 
6889  |  |  | 
6890  |  |     /*  | 
6891  |  |      * NGROUPS_MAX is defined by POSIX.1 as the maximum  | 
6892  |  |      * number of supplimental groups a users can belong to.  | 
6893  |  |      * We have to increment it by one because  | 
6894  |  |      * getgrouplist() returns both the supplemental groups  | 
6895  |  |      * and the primary group, i.e. all of the groups the  | 
6896  |  |      * user belongs to.  | 
6897  |  |      */  | 
6898  | 0  |     ngroups = 1 + MAX_GROUPS;  | 
6899  |  | 
  | 
6900  |  | #ifdef __APPLE__  | 
6901  |  |     if (!PyArg_ParseTuple(args, "si:getgrouplist", &user, &basegid))  | 
6902  |  |         return NULL;  | 
6903  |  | #else  | 
6904  | 0  |     if (!PyArg_ParseTuple(args, "sO&:getgrouplist", &user,  | 
6905  | 0  |                           _Py_Gid_Converter, &basegid))  | 
6906  | 0  |         return NULL;  | 
6907  | 0  | #endif  | 
6908  |  |  | 
6909  | 0  |     while (1) { | 
6910  |  | #ifdef __APPLE__  | 
6911  |  |         groups = PyMem_New(int, ngroups);  | 
6912  |  | #else  | 
6913  | 0  |         groups = PyMem_New(gid_t, ngroups);  | 
6914  | 0  | #endif  | 
6915  | 0  |         if (groups == NULL) { | 
6916  | 0  |             return PyErr_NoMemory();  | 
6917  | 0  |         }  | 
6918  |  |  | 
6919  | 0  |         int old_ngroups = ngroups;  | 
6920  | 0  |         if (getgrouplist(user, basegid, groups, &ngroups) != -1) { | 
6921  |  |             /* Success */  | 
6922  | 0  |             break;  | 
6923  | 0  |         }  | 
6924  |  |  | 
6925  |  |         /* getgrouplist() fails if the group list is too small */  | 
6926  | 0  |         PyMem_Free(groups);  | 
6927  |  | 
  | 
6928  | 0  |         if (ngroups > old_ngroups) { | 
6929  |  |             /* If the group list is too small, the glibc implementation of  | 
6930  |  |                getgrouplist() sets ngroups to the total number of groups and  | 
6931  |  |                returns -1. */  | 
6932  | 0  |         }  | 
6933  | 0  |         else { | 
6934  |  |             /* Double the group list size */  | 
6935  | 0  |             if (ngroups > INT_MAX / 2) { | 
6936  | 0  |                 return PyErr_NoMemory();  | 
6937  | 0  |             }  | 
6938  | 0  |             ngroups *= 2;  | 
6939  | 0  |         }  | 
6940  |  |  | 
6941  |  |         /* Retry getgrouplist() with a larger group list */  | 
6942  | 0  |     }  | 
6943  |  |  | 
6944  |  | #ifdef _Py_MEMORY_SANITIZER  | 
6945  |  |     /* Clang memory sanitizer libc intercepts don't know getgrouplist. */  | 
6946  |  |     __msan_unpoison(&ngroups, sizeof(ngroups));  | 
6947  |  |     __msan_unpoison(groups, ngroups*sizeof(*groups));  | 
6948  |  | #endif  | 
6949  |  |  | 
6950  | 0  |     list = PyList_New(ngroups);  | 
6951  | 0  |     if (list == NULL) { | 
6952  | 0  |         PyMem_Del(groups);  | 
6953  | 0  |         return NULL;  | 
6954  | 0  |     }  | 
6955  |  |  | 
6956  | 0  |     for (i = 0; i < ngroups; i++) { | 
6957  |  | #ifdef __APPLE__  | 
6958  |  |         PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);  | 
6959  |  | #else  | 
6960  | 0  |         PyObject *o = _PyLong_FromGid(groups[i]);  | 
6961  | 0  | #endif  | 
6962  | 0  |         if (o == NULL) { | 
6963  | 0  |             Py_DECREF(list);  | 
6964  | 0  |             PyMem_Del(groups);  | 
6965  | 0  |             return NULL;  | 
6966  | 0  |         }  | 
6967  | 0  |         PyList_SET_ITEM(list, i, o);  | 
6968  | 0  |     }  | 
6969  |  |  | 
6970  | 0  |     PyMem_Del(groups);  | 
6971  |  | 
  | 
6972  | 0  |     return list;  | 
6973  | 0  | }  | 
6974  |  | #endif /* HAVE_GETGROUPLIST */  | 
6975  |  |  | 
6976  |  |  | 
6977  |  | #ifdef HAVE_GETGROUPS  | 
6978  |  | /*[clinic input]  | 
6979  |  | os.getgroups  | 
6980  |  |  | 
6981  |  | Return list of supplemental group IDs for the process.  | 
6982  |  | [clinic start generated code]*/  | 
6983  |  |  | 
6984  |  | static PyObject *  | 
6985  |  | os_getgroups_impl(PyObject *module)  | 
6986  |  | /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/  | 
6987  | 0  | { | 
6988  | 0  |     PyObject *result = NULL;  | 
6989  | 0  |     gid_t grouplist[MAX_GROUPS];  | 
6990  |  |  | 
6991  |  |     /* On MacOSX getgroups(2) can return more than MAX_GROUPS results  | 
6992  |  |      * This is a helper variable to store the intermediate result when  | 
6993  |  |      * that happens.  | 
6994  |  |      *  | 
6995  |  |      * To keep the code readable the OSX behaviour is unconditional,  | 
6996  |  |      * according to the POSIX spec this should be safe on all unix-y  | 
6997  |  |      * systems.  | 
6998  |  |      */  | 
6999  | 0  |     gid_t* alt_grouplist = grouplist;  | 
7000  | 0  |     int n;  | 
7001  |  | 
  | 
7002  |  | #ifdef __APPLE__  | 
7003  |  |     /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if  | 
7004  |  |      * there are more groups than can fit in grouplist.  Therefore, on OS X  | 
7005  |  |      * always first call getgroups with length 0 to get the actual number  | 
7006  |  |      * of groups.  | 
7007  |  |      */  | 
7008  |  |     n = getgroups(0, NULL);  | 
7009  |  |     if (n < 0) { | 
7010  |  |         return posix_error();  | 
7011  |  |     } else if (n <= MAX_GROUPS) { | 
7012  |  |         /* groups will fit in existing array */  | 
7013  |  |         alt_grouplist = grouplist;  | 
7014  |  |     } else { | 
7015  |  |         alt_grouplist = PyMem_New(gid_t, n);  | 
7016  |  |         if (alt_grouplist == NULL) { | 
7017  |  |             return PyErr_NoMemory();  | 
7018  |  |         }  | 
7019  |  |     }  | 
7020  |  |  | 
7021  |  |     n = getgroups(n, alt_grouplist);  | 
7022  |  |     if (n == -1) { | 
7023  |  |         if (alt_grouplist != grouplist) { | 
7024  |  |             PyMem_Free(alt_grouplist);  | 
7025  |  |         }  | 
7026  |  |         return posix_error();  | 
7027  |  |     }  | 
7028  |  | #else  | 
7029  | 0  |     n = getgroups(MAX_GROUPS, grouplist);  | 
7030  | 0  |     if (n < 0) { | 
7031  | 0  |         if (errno == EINVAL) { | 
7032  | 0  |             n = getgroups(0, NULL);  | 
7033  | 0  |             if (n == -1) { | 
7034  | 0  |                 return posix_error();  | 
7035  | 0  |             }  | 
7036  | 0  |             if (n == 0) { | 
7037  |  |                 /* Avoid malloc(0) */  | 
7038  | 0  |                 alt_grouplist = grouplist;  | 
7039  | 0  |             } else { | 
7040  | 0  |                 alt_grouplist = PyMem_New(gid_t, n);  | 
7041  | 0  |                 if (alt_grouplist == NULL) { | 
7042  | 0  |                     return PyErr_NoMemory();  | 
7043  | 0  |                 }  | 
7044  | 0  |                 n = getgroups(n, alt_grouplist);  | 
7045  | 0  |                 if (n == -1) { | 
7046  | 0  |                     PyMem_Free(alt_grouplist);  | 
7047  | 0  |                     return posix_error();  | 
7048  | 0  |                 }  | 
7049  | 0  |             }  | 
7050  | 0  |         } else { | 
7051  | 0  |             return posix_error();  | 
7052  | 0  |         }  | 
7053  | 0  |     }  | 
7054  | 0  | #endif  | 
7055  |  |  | 
7056  | 0  |     result = PyList_New(n);  | 
7057  | 0  |     if (result != NULL) { | 
7058  | 0  |         int i;  | 
7059  | 0  |         for (i = 0; i < n; ++i) { | 
7060  | 0  |             PyObject *o = _PyLong_FromGid(alt_grouplist[i]);  | 
7061  | 0  |             if (o == NULL) { | 
7062  | 0  |                 Py_DECREF(result);  | 
7063  | 0  |                 result = NULL;  | 
7064  | 0  |                 break;  | 
7065  | 0  |             }  | 
7066  | 0  |             PyList_SET_ITEM(result, i, o);  | 
7067  | 0  |         }  | 
7068  | 0  |     }  | 
7069  |  | 
  | 
7070  | 0  |     if (alt_grouplist != grouplist) { | 
7071  | 0  |         PyMem_Free(alt_grouplist);  | 
7072  | 0  |     }  | 
7073  |  | 
  | 
7074  | 0  |     return result;  | 
7075  | 0  | }  | 
7076  |  | #endif /* HAVE_GETGROUPS */  | 
7077  |  |  | 
7078  |  | #ifdef HAVE_INITGROUPS  | 
7079  |  | PyDoc_STRVAR(posix_initgroups__doc__,  | 
7080  |  | "initgroups(username, gid) -> None\n\n\  | 
7081  |  | Call the system initgroups() to initialize the group access list with all of\n\  | 
7082  |  | the groups of which the specified username is a member, plus the specified\n\  | 
7083  |  | group id.");  | 
7084  |  |  | 
7085  |  | /* AC 3.5: funny apple logic */  | 
7086  |  | static PyObject *  | 
7087  |  | posix_initgroups(PyObject *self, PyObject *args)  | 
7088  | 0  | { | 
7089  | 0  |     PyObject *oname;  | 
7090  | 0  |     const char *username;  | 
7091  | 0  |     int res;  | 
7092  |  | #ifdef __APPLE__  | 
7093  |  |     int gid;  | 
7094  |  | #else  | 
7095  | 0  |     gid_t gid;  | 
7096  | 0  | #endif  | 
7097  |  | 
  | 
7098  |  | #ifdef __APPLE__  | 
7099  |  |     if (!PyArg_ParseTuple(args, "O&i:initgroups",  | 
7100  |  |                           PyUnicode_FSConverter, &oname,  | 
7101  |  |                           &gid))  | 
7102  |  | #else  | 
7103  | 0  |     if (!PyArg_ParseTuple(args, "O&O&:initgroups",  | 
7104  | 0  |                           PyUnicode_FSConverter, &oname,  | 
7105  | 0  |                           _Py_Gid_Converter, &gid))  | 
7106  | 0  | #endif  | 
7107  | 0  |         return NULL;  | 
7108  | 0  |     username = PyBytes_AS_STRING(oname);  | 
7109  |  | 
  | 
7110  | 0  |     res = initgroups(username, gid);  | 
7111  | 0  |     Py_DECREF(oname);  | 
7112  | 0  |     if (res == -1)  | 
7113  | 0  |         return PyErr_SetFromErrno(PyExc_OSError);  | 
7114  |  |  | 
7115  | 0  |     Py_RETURN_NONE;  | 
7116  | 0  | }  | 
7117  |  | #endif /* HAVE_INITGROUPS */  | 
7118  |  |  | 
7119  |  |  | 
7120  |  | #ifdef HAVE_GETPGID  | 
7121  |  | /*[clinic input]  | 
7122  |  | os.getpgid  | 
7123  |  |  | 
7124  |  |     pid: pid_t  | 
7125  |  |  | 
7126  |  | Call the system call getpgid(), and return the result.  | 
7127  |  | [clinic start generated code]*/  | 
7128  |  |  | 
7129  |  | static PyObject *  | 
7130  |  | os_getpgid_impl(PyObject *module, pid_t pid)  | 
7131  |  | /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/  | 
7132  | 0  | { | 
7133  | 0  |     pid_t pgid = getpgid(pid);  | 
7134  | 0  |     if (pgid < 0)  | 
7135  | 0  |         return posix_error();  | 
7136  | 0  |     return PyLong_FromPid(pgid);  | 
7137  | 0  | }  | 
7138  |  | #endif /* HAVE_GETPGID */  | 
7139  |  |  | 
7140  |  |  | 
7141  |  | #ifdef HAVE_GETPGRP  | 
7142  |  | /*[clinic input]  | 
7143  |  | os.getpgrp  | 
7144  |  |  | 
7145  |  | Return the current process group id.  | 
7146  |  | [clinic start generated code]*/  | 
7147  |  |  | 
7148  |  | static PyObject *  | 
7149  |  | os_getpgrp_impl(PyObject *module)  | 
7150  |  | /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/  | 
7151  | 0  | { | 
7152  |  | #ifdef GETPGRP_HAVE_ARG  | 
7153  |  |     return PyLong_FromPid(getpgrp(0));  | 
7154  |  | #else /* GETPGRP_HAVE_ARG */  | 
7155  | 0  |     return PyLong_FromPid(getpgrp());  | 
7156  | 0  | #endif /* GETPGRP_HAVE_ARG */  | 
7157  | 0  | }  | 
7158  |  | #endif /* HAVE_GETPGRP */  | 
7159  |  |  | 
7160  |  |  | 
7161  |  | #ifdef HAVE_SETPGRP  | 
7162  |  | /*[clinic input]  | 
7163  |  | os.setpgrp  | 
7164  |  |  | 
7165  |  | Make the current process the leader of its process group.  | 
7166  |  | [clinic start generated code]*/  | 
7167  |  |  | 
7168  |  | static PyObject *  | 
7169  |  | os_setpgrp_impl(PyObject *module)  | 
7170  |  | /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/  | 
7171  | 0  | { | 
7172  |  | #ifdef SETPGRP_HAVE_ARG  | 
7173  |  |     if (setpgrp(0, 0) < 0)  | 
7174  |  | #else /* SETPGRP_HAVE_ARG */  | 
7175  | 0  |     if (setpgrp() < 0)  | 
7176  | 0  | #endif /* SETPGRP_HAVE_ARG */  | 
7177  | 0  |         return posix_error();  | 
7178  | 0  |     Py_RETURN_NONE;  | 
7179  | 0  | }  | 
7180  |  | #endif /* HAVE_SETPGRP */  | 
7181  |  |  | 
7182  |  | #ifdef HAVE_GETPPID  | 
7183  |  |  | 
7184  |  | #ifdef MS_WINDOWS  | 
7185  |  | #include <tlhelp32.h>  | 
7186  |  |  | 
7187  |  | static PyObject*  | 
7188  |  | win32_getppid()  | 
7189  |  | { | 
7190  |  |     HANDLE snapshot;  | 
7191  |  |     pid_t mypid;  | 
7192  |  |     PyObject* result = NULL;  | 
7193  |  |     BOOL have_record;  | 
7194  |  |     PROCESSENTRY32 pe;  | 
7195  |  |  | 
7196  |  |     mypid = getpid(); /* This function never fails */  | 
7197  |  |  | 
7198  |  |     snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);  | 
7199  |  |     if (snapshot == INVALID_HANDLE_VALUE)  | 
7200  |  |         return PyErr_SetFromWindowsErr(GetLastError());  | 
7201  |  |  | 
7202  |  |     pe.dwSize = sizeof(pe);  | 
7203  |  |     have_record = Process32First(snapshot, &pe);  | 
7204  |  |     while (have_record) { | 
7205  |  |         if (mypid == (pid_t)pe.th32ProcessID) { | 
7206  |  |             /* We could cache the ulong value in a static variable. */  | 
7207  |  |             result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);  | 
7208  |  |             break;  | 
7209  |  |         }  | 
7210  |  |  | 
7211  |  |         have_record = Process32Next(snapshot, &pe);  | 
7212  |  |     }  | 
7213  |  |  | 
7214  |  |     /* If our loop exits and our pid was not found (result will be NULL)  | 
7215  |  |      * then GetLastError will return ERROR_NO_MORE_FILES. This is an  | 
7216  |  |      * error anyway, so let's raise it. */  | 
7217  |  |     if (!result)  | 
7218  |  |         result = PyErr_SetFromWindowsErr(GetLastError());  | 
7219  |  |  | 
7220  |  |     CloseHandle(snapshot);  | 
7221  |  |  | 
7222  |  |     return result;  | 
7223  |  | }  | 
7224  |  | #endif /*MS_WINDOWS*/  | 
7225  |  |  | 
7226  |  |  | 
7227  |  | /*[clinic input]  | 
7228  |  | os.getppid  | 
7229  |  |  | 
7230  |  | Return the parent's process id.  | 
7231  |  |  | 
7232  |  | If the parent process has already exited, Windows machines will still  | 
7233  |  | return its id; others systems will return the id of the 'init' process (1).  | 
7234  |  | [clinic start generated code]*/  | 
7235  |  |  | 
7236  |  | static PyObject *  | 
7237  |  | os_getppid_impl(PyObject *module)  | 
7238  |  | /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/  | 
7239  | 0  | { | 
7240  |  | #ifdef MS_WINDOWS  | 
7241  |  |     return win32_getppid();  | 
7242  |  | #else  | 
7243  | 0  |     return PyLong_FromPid(getppid());  | 
7244  | 0  | #endif  | 
7245  | 0  | }  | 
7246  |  | #endif /* HAVE_GETPPID */  | 
7247  |  |  | 
7248  |  |  | 
7249  |  | #ifdef HAVE_GETLOGIN  | 
7250  |  | /*[clinic input]  | 
7251  |  | os.getlogin  | 
7252  |  |  | 
7253  |  | Return the actual login name.  | 
7254  |  | [clinic start generated code]*/  | 
7255  |  |  | 
7256  |  | static PyObject *  | 
7257  |  | os_getlogin_impl(PyObject *module)  | 
7258  |  | /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/  | 
7259  | 0  | { | 
7260  | 0  |     PyObject *result = NULL;  | 
7261  |  | #ifdef MS_WINDOWS  | 
7262  |  |     wchar_t user_name[UNLEN + 1];  | 
7263  |  |     DWORD num_chars = Py_ARRAY_LENGTH(user_name);  | 
7264  |  |  | 
7265  |  |     if (GetUserNameW(user_name, &num_chars)) { | 
7266  |  |         /* num_chars is the number of unicode chars plus null terminator */  | 
7267  |  |         result = PyUnicode_FromWideChar(user_name, num_chars - 1);  | 
7268  |  |     }  | 
7269  |  |     else  | 
7270  |  |         result = PyErr_SetFromWindowsErr(GetLastError());  | 
7271  |  | #else  | 
7272  | 0  |     char *name;  | 
7273  | 0  |     int old_errno = errno;  | 
7274  |  | 
  | 
7275  | 0  |     errno = 0;  | 
7276  | 0  |     name = getlogin();  | 
7277  | 0  |     if (name == NULL) { | 
7278  | 0  |         if (errno)  | 
7279  | 0  |             posix_error();  | 
7280  | 0  |         else  | 
7281  | 0  |             PyErr_SetString(PyExc_OSError, "unable to determine login name");  | 
7282  | 0  |     }  | 
7283  | 0  |     else  | 
7284  | 0  |         result = PyUnicode_DecodeFSDefault(name);  | 
7285  | 0  |     errno = old_errno;  | 
7286  | 0  | #endif  | 
7287  | 0  |     return result;  | 
7288  | 0  | }  | 
7289  |  | #endif /* HAVE_GETLOGIN */  | 
7290  |  |  | 
7291  |  |  | 
7292  |  | #ifdef HAVE_GETUID  | 
7293  |  | /*[clinic input]  | 
7294  |  | os.getuid  | 
7295  |  |  | 
7296  |  | Return the current process's user id.  | 
7297  |  | [clinic start generated code]*/  | 
7298  |  |  | 
7299  |  | static PyObject *  | 
7300  |  | os_getuid_impl(PyObject *module)  | 
7301  |  | /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/  | 
7302  | 0  | { | 
7303  | 0  |     return _PyLong_FromUid(getuid());  | 
7304  | 0  | }  | 
7305  |  | #endif /* HAVE_GETUID */  | 
7306  |  |  | 
7307  |  |  | 
7308  |  | #ifdef MS_WINDOWS  | 
7309  |  | #define HAVE_KILL  | 
7310  |  | #endif /* MS_WINDOWS */  | 
7311  |  |  | 
7312  |  | #ifdef HAVE_KILL  | 
7313  |  | /*[clinic input]  | 
7314  |  | os.kill  | 
7315  |  |  | 
7316  |  |     pid: pid_t  | 
7317  |  |     signal: Py_ssize_t  | 
7318  |  |     /  | 
7319  |  |  | 
7320  |  | Kill a process with a signal.  | 
7321  |  | [clinic start generated code]*/  | 
7322  |  |  | 
7323  |  | static PyObject *  | 
7324  |  | os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)  | 
7325  |  | /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/  | 
7326  | 0  | { | 
7327  | 0  |     if (PySys_Audit("os.kill", "in", pid, signal) < 0) { | 
7328  | 0  |         return NULL;  | 
7329  | 0  |     }  | 
7330  | 0  | #ifndef MS_WINDOWS  | 
7331  | 0  |     if (kill(pid, (int)signal) == -1)  | 
7332  | 0  |         return posix_error();  | 
7333  | 0  |     Py_RETURN_NONE;  | 
7334  |  | #else /* !MS_WINDOWS */  | 
7335  |  |     PyObject *result;  | 
7336  |  |     DWORD sig = (DWORD)signal;  | 
7337  |  |     DWORD err;  | 
7338  |  |     HANDLE handle;  | 
7339  |  |  | 
7340  |  |     /* Console processes which share a common console can be sent CTRL+C or  | 
7341  |  |        CTRL+BREAK events, provided they handle said events. */  | 
7342  |  |     if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) { | 
7343  |  |         if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) { | 
7344  |  |             err = GetLastError();  | 
7345  |  |             PyErr_SetFromWindowsErr(err);  | 
7346  |  |         }  | 
7347  |  |         else  | 
7348  |  |             Py_RETURN_NONE;  | 
7349  |  |     }  | 
7350  |  |  | 
7351  |  |     /* If the signal is outside of what GenerateConsoleCtrlEvent can use,  | 
7352  |  |        attempt to open and terminate the process. */  | 
7353  |  |     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);  | 
7354  |  |     if (handle == NULL) { | 
7355  |  |         err = GetLastError();  | 
7356  |  |         return PyErr_SetFromWindowsErr(err);  | 
7357  |  |     }  | 
7358  |  |  | 
7359  |  |     if (TerminateProcess(handle, sig) == 0) { | 
7360  |  |         err = GetLastError();  | 
7361  |  |         result = PyErr_SetFromWindowsErr(err);  | 
7362  |  |     } else { | 
7363  |  |         Py_INCREF(Py_None);  | 
7364  |  |         result = Py_None;  | 
7365  |  |     }  | 
7366  |  |  | 
7367  |  |     CloseHandle(handle);  | 
7368  |  |     return result;  | 
7369  |  | #endif /* !MS_WINDOWS */  | 
7370  | 0  | }  | 
7371  |  | #endif /* HAVE_KILL */  | 
7372  |  |  | 
7373  |  |  | 
7374  |  | #ifdef HAVE_KILLPG  | 
7375  |  | /*[clinic input]  | 
7376  |  | os.killpg  | 
7377  |  |  | 
7378  |  |     pgid: pid_t  | 
7379  |  |     signal: int  | 
7380  |  |     /  | 
7381  |  |  | 
7382  |  | Kill a process group with a signal.  | 
7383  |  | [clinic start generated code]*/  | 
7384  |  |  | 
7385  |  | static PyObject *  | 
7386  |  | os_killpg_impl(PyObject *module, pid_t pgid, int signal)  | 
7387  |  | /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/  | 
7388  | 0  | { | 
7389  | 0  |     if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) { | 
7390  | 0  |         return NULL;  | 
7391  | 0  |     }  | 
7392  |  |     /* XXX some man pages make the `pgid` parameter an int, others  | 
7393  |  |        a pid_t. Since getpgrp() returns a pid_t, we assume killpg should  | 
7394  |  |        take the same type. Moreover, pid_t is always at least as wide as  | 
7395  |  |        int (else compilation of this module fails), which is safe. */  | 
7396  | 0  |     if (killpg(pgid, signal) == -1)  | 
7397  | 0  |         return posix_error();  | 
7398  | 0  |     Py_RETURN_NONE;  | 
7399  | 0  | }  | 
7400  |  | #endif /* HAVE_KILLPG */  | 
7401  |  |  | 
7402  |  |  | 
7403  |  | #ifdef HAVE_PLOCK  | 
7404  |  | #ifdef HAVE_SYS_LOCK_H  | 
7405  |  | #include <sys/lock.h>  | 
7406  |  | #endif  | 
7407  |  |  | 
7408  |  | /*[clinic input]  | 
7409  |  | os.plock  | 
7410  |  |     op: int  | 
7411  |  |     /  | 
7412  |  |  | 
7413  |  | Lock program segments into memory.");  | 
7414  |  | [clinic start generated code]*/  | 
7415  |  |  | 
7416  |  | static PyObject *  | 
7417  |  | os_plock_impl(PyObject *module, int op)  | 
7418  |  | /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/  | 
7419  |  | { | 
7420  |  |     if (plock(op) == -1)  | 
7421  |  |         return posix_error();  | 
7422  |  |     Py_RETURN_NONE;  | 
7423  |  | }  | 
7424  |  | #endif /* HAVE_PLOCK */  | 
7425  |  |  | 
7426  |  |  | 
7427  |  | #ifdef HAVE_SETUID  | 
7428  |  | /*[clinic input]  | 
7429  |  | os.setuid  | 
7430  |  |  | 
7431  |  |     uid: uid_t  | 
7432  |  |     /  | 
7433  |  |  | 
7434  |  | Set the current process's user id.  | 
7435  |  | [clinic start generated code]*/  | 
7436  |  |  | 
7437  |  | static PyObject *  | 
7438  |  | os_setuid_impl(PyObject *module, uid_t uid)  | 
7439  |  | /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/  | 
7440  | 0  | { | 
7441  | 0  |     if (setuid(uid) < 0)  | 
7442  | 0  |         return posix_error();  | 
7443  | 0  |     Py_RETURN_NONE;  | 
7444  | 0  | }  | 
7445  |  | #endif /* HAVE_SETUID */  | 
7446  |  |  | 
7447  |  |  | 
7448  |  | #ifdef HAVE_SETEUID  | 
7449  |  | /*[clinic input]  | 
7450  |  | os.seteuid  | 
7451  |  |  | 
7452  |  |     euid: uid_t  | 
7453  |  |     /  | 
7454  |  |  | 
7455  |  | Set the current process's effective user id.  | 
7456  |  | [clinic start generated code]*/  | 
7457  |  |  | 
7458  |  | static PyObject *  | 
7459  |  | os_seteuid_impl(PyObject *module, uid_t euid)  | 
7460  |  | /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/  | 
7461  | 0  | { | 
7462  | 0  |     if (seteuid(euid) < 0)  | 
7463  | 0  |         return posix_error();  | 
7464  | 0  |     Py_RETURN_NONE;  | 
7465  | 0  | }  | 
7466  |  | #endif /* HAVE_SETEUID */  | 
7467  |  |  | 
7468  |  |  | 
7469  |  | #ifdef HAVE_SETEGID  | 
7470  |  | /*[clinic input]  | 
7471  |  | os.setegid  | 
7472  |  |  | 
7473  |  |     egid: gid_t  | 
7474  |  |     /  | 
7475  |  |  | 
7476  |  | Set the current process's effective group id.  | 
7477  |  | [clinic start generated code]*/  | 
7478  |  |  | 
7479  |  | static PyObject *  | 
7480  |  | os_setegid_impl(PyObject *module, gid_t egid)  | 
7481  |  | /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/  | 
7482  | 0  | { | 
7483  | 0  |     if (setegid(egid) < 0)  | 
7484  | 0  |         return posix_error();  | 
7485  | 0  |     Py_RETURN_NONE;  | 
7486  | 0  | }  | 
7487  |  | #endif /* HAVE_SETEGID */  | 
7488  |  |  | 
7489  |  |  | 
7490  |  | #ifdef HAVE_SETREUID  | 
7491  |  | /*[clinic input]  | 
7492  |  | os.setreuid  | 
7493  |  |  | 
7494  |  |     ruid: uid_t  | 
7495  |  |     euid: uid_t  | 
7496  |  |     /  | 
7497  |  |  | 
7498  |  | Set the current process's real and effective user ids.  | 
7499  |  | [clinic start generated code]*/  | 
7500  |  |  | 
7501  |  | static PyObject *  | 
7502  |  | os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)  | 
7503  |  | /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/  | 
7504  | 0  | { | 
7505  | 0  |     if (setreuid(ruid, euid) < 0) { | 
7506  | 0  |         return posix_error();  | 
7507  | 0  |     } else { | 
7508  | 0  |         Py_RETURN_NONE;  | 
7509  | 0  |     }  | 
7510  | 0  | }  | 
7511  |  | #endif /* HAVE_SETREUID */  | 
7512  |  |  | 
7513  |  |  | 
7514  |  | #ifdef HAVE_SETREGID  | 
7515  |  | /*[clinic input]  | 
7516  |  | os.setregid  | 
7517  |  |  | 
7518  |  |     rgid: gid_t  | 
7519  |  |     egid: gid_t  | 
7520  |  |     /  | 
7521  |  |  | 
7522  |  | Set the current process's real and effective group ids.  | 
7523  |  | [clinic start generated code]*/  | 
7524  |  |  | 
7525  |  | static PyObject *  | 
7526  |  | os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)  | 
7527  |  | /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/  | 
7528  | 0  | { | 
7529  | 0  |     if (setregid(rgid, egid) < 0)  | 
7530  | 0  |         return posix_error();  | 
7531  | 0  |     Py_RETURN_NONE;  | 
7532  | 0  | }  | 
7533  |  | #endif /* HAVE_SETREGID */  | 
7534  |  |  | 
7535  |  |  | 
7536  |  | #ifdef HAVE_SETGID  | 
7537  |  | /*[clinic input]  | 
7538  |  | os.setgid  | 
7539  |  |     gid: gid_t  | 
7540  |  |     /  | 
7541  |  |  | 
7542  |  | Set the current process's group id.  | 
7543  |  | [clinic start generated code]*/  | 
7544  |  |  | 
7545  |  | static PyObject *  | 
7546  |  | os_setgid_impl(PyObject *module, gid_t gid)  | 
7547  |  | /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/  | 
7548  | 0  | { | 
7549  | 0  |     if (setgid(gid) < 0)  | 
7550  | 0  |         return posix_error();  | 
7551  | 0  |     Py_RETURN_NONE;  | 
7552  | 0  | }  | 
7553  |  | #endif /* HAVE_SETGID */  | 
7554  |  |  | 
7555  |  |  | 
7556  |  | #ifdef HAVE_SETGROUPS  | 
7557  |  | /*[clinic input]  | 
7558  |  | os.setgroups  | 
7559  |  |  | 
7560  |  |     groups: object  | 
7561  |  |     /  | 
7562  |  |  | 
7563  |  | Set the groups of the current process to list.  | 
7564  |  | [clinic start generated code]*/  | 
7565  |  |  | 
7566  |  | static PyObject *  | 
7567  |  | os_setgroups(PyObject *module, PyObject *groups)  | 
7568  |  | /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/  | 
7569  | 0  | { | 
7570  | 0  |     Py_ssize_t i, len;  | 
7571  | 0  |     gid_t grouplist[MAX_GROUPS];  | 
7572  |  | 
  | 
7573  | 0  |     if (!PySequence_Check(groups)) { | 
7574  | 0  |         PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");  | 
7575  | 0  |         return NULL;  | 
7576  | 0  |     }  | 
7577  | 0  |     len = PySequence_Size(groups);  | 
7578  | 0  |     if (len < 0) { | 
7579  | 0  |         return NULL;  | 
7580  | 0  |     }  | 
7581  | 0  |     if (len > MAX_GROUPS) { | 
7582  | 0  |         PyErr_SetString(PyExc_ValueError, "too many groups");  | 
7583  | 0  |         return NULL;  | 
7584  | 0  |     }  | 
7585  | 0  |     for(i = 0; i < len; i++) { | 
7586  | 0  |         PyObject *elem;  | 
7587  | 0  |         elem = PySequence_GetItem(groups, i);  | 
7588  | 0  |         if (!elem)  | 
7589  | 0  |             return NULL;  | 
7590  | 0  |         if (!PyLong_Check(elem)) { | 
7591  | 0  |             PyErr_SetString(PyExc_TypeError,  | 
7592  | 0  |                             "groups must be integers");  | 
7593  | 0  |             Py_DECREF(elem);  | 
7594  | 0  |             return NULL;  | 
7595  | 0  |         } else { | 
7596  | 0  |             if (!_Py_Gid_Converter(elem, &grouplist[i])) { | 
7597  | 0  |                 Py_DECREF(elem);  | 
7598  | 0  |                 return NULL;  | 
7599  | 0  |             }  | 
7600  | 0  |         }  | 
7601  | 0  |         Py_DECREF(elem);  | 
7602  | 0  |     }  | 
7603  |  |  | 
7604  | 0  |     if (setgroups(len, grouplist) < 0)  | 
7605  | 0  |         return posix_error();  | 
7606  | 0  |     Py_RETURN_NONE;  | 
7607  | 0  | }  | 
7608  |  | #endif /* HAVE_SETGROUPS */  | 
7609  |  |  | 
7610  |  | #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)  | 
7611  |  | static PyObject *  | 
7612  |  | wait_helper(pid_t pid, int status, struct rusage *ru)  | 
7613  | 0  | { | 
7614  | 0  |     PyObject *result;  | 
7615  | 0  |     static PyObject *struct_rusage;  | 
7616  | 0  |     _Py_IDENTIFIER(struct_rusage);  | 
7617  |  | 
  | 
7618  | 0  |     if (pid == -1)  | 
7619  | 0  |         return posix_error();  | 
7620  |  |  | 
7621  | 0  |     if (struct_rusage == NULL) { | 
7622  | 0  |         PyObject *m = PyImport_ImportModuleNoBlock("resource"); | 
7623  | 0  |         if (m == NULL)  | 
7624  | 0  |             return NULL;  | 
7625  | 0  |         struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage);  | 
7626  | 0  |         Py_DECREF(m);  | 
7627  | 0  |         if (struct_rusage == NULL)  | 
7628  | 0  |             return NULL;  | 
7629  | 0  |     }  | 
7630  |  |  | 
7631  |  |     /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */  | 
7632  | 0  |     result = PyStructSequence_New((PyTypeObject*) struct_rusage);  | 
7633  | 0  |     if (!result)  | 
7634  | 0  |         return NULL;  | 
7635  |  |  | 
7636  | 0  | #ifndef doubletime  | 
7637  | 0  | #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)  | 
7638  | 0  | #endif  | 
7639  |  |  | 
7640  | 0  |     PyStructSequence_SET_ITEM(result, 0,  | 
7641  | 0  |                               PyFloat_FromDouble(doubletime(ru->ru_utime)));  | 
7642  | 0  |     PyStructSequence_SET_ITEM(result, 1,  | 
7643  | 0  |                               PyFloat_FromDouble(doubletime(ru->ru_stime)));  | 
7644  | 0  | #define SET_INT(result, index, value)\  | 
7645  | 0  |         PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))  | 
7646  | 0  |     SET_INT(result, 2, ru->ru_maxrss);  | 
7647  | 0  |     SET_INT(result, 3, ru->ru_ixrss);  | 
7648  | 0  |     SET_INT(result, 4, ru->ru_idrss);  | 
7649  | 0  |     SET_INT(result, 5, ru->ru_isrss);  | 
7650  | 0  |     SET_INT(result, 6, ru->ru_minflt);  | 
7651  | 0  |     SET_INT(result, 7, ru->ru_majflt);  | 
7652  | 0  |     SET_INT(result, 8, ru->ru_nswap);  | 
7653  | 0  |     SET_INT(result, 9, ru->ru_inblock);  | 
7654  | 0  |     SET_INT(result, 10, ru->ru_oublock);  | 
7655  | 0  |     SET_INT(result, 11, ru->ru_msgsnd);  | 
7656  | 0  |     SET_INT(result, 12, ru->ru_msgrcv);  | 
7657  | 0  |     SET_INT(result, 13, ru->ru_nsignals);  | 
7658  | 0  |     SET_INT(result, 14, ru->ru_nvcsw);  | 
7659  | 0  |     SET_INT(result, 15, ru->ru_nivcsw);  | 
7660  | 0  | #undef SET_INT  | 
7661  |  | 
  | 
7662  | 0  |     if (PyErr_Occurred()) { | 
7663  | 0  |         Py_DECREF(result);  | 
7664  | 0  |         return NULL;  | 
7665  | 0  |     }  | 
7666  |  |  | 
7667  | 0  |     return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result); | 
7668  | 0  | }  | 
7669  |  | #endif /* HAVE_WAIT3 || HAVE_WAIT4 */  | 
7670  |  |  | 
7671  |  |  | 
7672  |  | #ifdef HAVE_WAIT3  | 
7673  |  | /*[clinic input]  | 
7674  |  | os.wait3  | 
7675  |  |  | 
7676  |  |     options: int  | 
7677  |  | Wait for completion of a child process.  | 
7678  |  |  | 
7679  |  | Returns a tuple of information about the child process:  | 
7680  |  |   (pid, status, rusage)  | 
7681  |  | [clinic start generated code]*/  | 
7682  |  |  | 
7683  |  | static PyObject *  | 
7684  |  | os_wait3_impl(PyObject *module, int options)  | 
7685  |  | /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/  | 
7686  | 0  | { | 
7687  | 0  |     pid_t pid;  | 
7688  | 0  |     struct rusage ru;  | 
7689  | 0  |     int async_err = 0;  | 
7690  | 0  |     WAIT_TYPE status;  | 
7691  | 0  |     WAIT_STATUS_INT(status) = 0;  | 
7692  |  | 
  | 
7693  | 0  |     do { | 
7694  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
7695  | 0  |         pid = wait3(&status, options, &ru);  | 
7696  | 0  |         Py_END_ALLOW_THREADS  | 
7697  | 0  |     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
7698  | 0  |     if (pid < 0)  | 
7699  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
7700  |  |  | 
7701  | 0  |     return wait_helper(pid, WAIT_STATUS_INT(status), &ru);  | 
7702  | 0  | }  | 
7703  |  | #endif /* HAVE_WAIT3 */  | 
7704  |  |  | 
7705  |  |  | 
7706  |  | #ifdef HAVE_WAIT4  | 
7707  |  | /*[clinic input]  | 
7708  |  |  | 
7709  |  | os.wait4  | 
7710  |  |  | 
7711  |  |     pid: pid_t  | 
7712  |  |     options: int  | 
7713  |  |  | 
7714  |  | Wait for completion of a specific child process.  | 
7715  |  |  | 
7716  |  | Returns a tuple of information about the child process:  | 
7717  |  |   (pid, status, rusage)  | 
7718  |  | [clinic start generated code]*/  | 
7719  |  |  | 
7720  |  | static PyObject *  | 
7721  |  | os_wait4_impl(PyObject *module, pid_t pid, int options)  | 
7722  |  | /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/  | 
7723  | 0  | { | 
7724  | 0  |     pid_t res;  | 
7725  | 0  |     struct rusage ru;  | 
7726  | 0  |     int async_err = 0;  | 
7727  | 0  |     WAIT_TYPE status;  | 
7728  | 0  |     WAIT_STATUS_INT(status) = 0;  | 
7729  |  | 
  | 
7730  | 0  |     do { | 
7731  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
7732  | 0  |         res = wait4(pid, &status, options, &ru);  | 
7733  | 0  |         Py_END_ALLOW_THREADS  | 
7734  | 0  |     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
7735  | 0  |     if (res < 0)  | 
7736  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
7737  |  |  | 
7738  | 0  |     return wait_helper(res, WAIT_STATUS_INT(status), &ru);  | 
7739  | 0  | }  | 
7740  |  | #endif /* HAVE_WAIT4 */  | 
7741  |  |  | 
7742  |  |  | 
7743  |  | #if defined(HAVE_WAITID) && !defined(__APPLE__)  | 
7744  |  | /*[clinic input]  | 
7745  |  | os.waitid  | 
7746  |  |  | 
7747  |  |     idtype: idtype_t  | 
7748  |  |         Must be one of be P_PID, P_PGID or P_ALL.  | 
7749  |  |     id: id_t  | 
7750  |  |         The id to wait on.  | 
7751  |  |     options: int  | 
7752  |  |         Constructed from the ORing of one or more of WEXITED, WSTOPPED  | 
7753  |  |         or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.  | 
7754  |  |     /  | 
7755  |  |  | 
7756  |  | Returns the result of waiting for a process or processes.  | 
7757  |  |  | 
7758  |  | Returns either waitid_result or None if WNOHANG is specified and there are  | 
7759  |  | no children in a waitable state.  | 
7760  |  | [clinic start generated code]*/  | 
7761  |  |  | 
7762  |  | static PyObject *  | 
7763  |  | os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)  | 
7764  |  | /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/  | 
7765  | 0  | { | 
7766  | 0  |     PyObject *result;  | 
7767  | 0  |     int res;  | 
7768  | 0  |     int async_err = 0;  | 
7769  | 0  |     siginfo_t si;  | 
7770  | 0  |     si.si_pid = 0;  | 
7771  |  | 
  | 
7772  | 0  |     do { | 
7773  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
7774  | 0  |         res = waitid(idtype, id, &si, options);  | 
7775  | 0  |         Py_END_ALLOW_THREADS  | 
7776  | 0  |     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
7777  | 0  |     if (res < 0)  | 
7778  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
7779  |  |  | 
7780  | 0  |     if (si.si_pid == 0)  | 
7781  | 0  |         Py_RETURN_NONE;  | 
7782  |  |  | 
7783  | 0  |     result = PyStructSequence_New(WaitidResultType);  | 
7784  | 0  |     if (!result)  | 
7785  | 0  |         return NULL;  | 
7786  |  |  | 
7787  | 0  |     PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));  | 
7788  | 0  |     PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));  | 
7789  | 0  |     PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));  | 
7790  | 0  |     PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));  | 
7791  | 0  |     PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));  | 
7792  | 0  |     if (PyErr_Occurred()) { | 
7793  | 0  |         Py_DECREF(result);  | 
7794  | 0  |         return NULL;  | 
7795  | 0  |     }  | 
7796  |  |  | 
7797  | 0  |     return result;  | 
7798  | 0  | }  | 
7799  |  | #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */  | 
7800  |  |  | 
7801  |  |  | 
7802  |  | #if defined(HAVE_WAITPID)  | 
7803  |  | /*[clinic input]  | 
7804  |  | os.waitpid  | 
7805  |  |     pid: pid_t  | 
7806  |  |     options: int  | 
7807  |  |     /  | 
7808  |  |  | 
7809  |  | Wait for completion of a given child process.  | 
7810  |  |  | 
7811  |  | Returns a tuple of information regarding the child process:  | 
7812  |  |     (pid, status)  | 
7813  |  |  | 
7814  |  | The options argument is ignored on Windows.  | 
7815  |  | [clinic start generated code]*/  | 
7816  |  |  | 
7817  |  | static PyObject *  | 
7818  |  | os_waitpid_impl(PyObject *module, pid_t pid, int options)  | 
7819  |  | /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/  | 
7820  | 0  | { | 
7821  | 0  |     pid_t res;  | 
7822  | 0  |     int async_err = 0;  | 
7823  | 0  |     WAIT_TYPE status;  | 
7824  | 0  |     WAIT_STATUS_INT(status) = 0;  | 
7825  |  | 
  | 
7826  | 0  |     do { | 
7827  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
7828  | 0  |         res = waitpid(pid, &status, options);  | 
7829  | 0  |         Py_END_ALLOW_THREADS  | 
7830  | 0  |     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
7831  | 0  |     if (res < 0)  | 
7832  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
7833  |  |  | 
7834  | 0  |     return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status)); | 
7835  | 0  | }  | 
7836  |  | #elif defined(HAVE_CWAIT)  | 
7837  |  | /* MS C has a variant of waitpid() that's usable for most purposes. */  | 
7838  |  | /*[clinic input]  | 
7839  |  | os.waitpid  | 
7840  |  |     pid: intptr_t  | 
7841  |  |     options: int  | 
7842  |  |     /  | 
7843  |  |  | 
7844  |  | Wait for completion of a given process.  | 
7845  |  |  | 
7846  |  | Returns a tuple of information regarding the process:  | 
7847  |  |     (pid, status << 8)  | 
7848  |  |  | 
7849  |  | The options argument is ignored on Windows.  | 
7850  |  | [clinic start generated code]*/  | 
7851  |  |  | 
7852  |  | static PyObject *  | 
7853  |  | os_waitpid_impl(PyObject *module, intptr_t pid, int options)  | 
7854  |  | /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/  | 
7855  |  | { | 
7856  |  |     int status;  | 
7857  |  |     intptr_t res;  | 
7858  |  |     int async_err = 0;  | 
7859  |  |  | 
7860  |  |     do { | 
7861  |  |         Py_BEGIN_ALLOW_THREADS  | 
7862  |  |         _Py_BEGIN_SUPPRESS_IPH  | 
7863  |  |         res = _cwait(&status, pid, options);  | 
7864  |  |         _Py_END_SUPPRESS_IPH  | 
7865  |  |         Py_END_ALLOW_THREADS  | 
7866  |  |     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
7867  |  |     if (res < 0)  | 
7868  |  |         return (!async_err) ? posix_error() : NULL;  | 
7869  |  |  | 
7870  |  |     unsigned long long ustatus = (unsigned int)status;  | 
7871  |  |  | 
7872  |  |     /* shift the status left a byte so this is more like the POSIX waitpid */  | 
7873  |  |     return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);  | 
7874  |  | }  | 
7875  |  | #endif  | 
7876  |  |  | 
7877  |  |  | 
7878  |  | #ifdef HAVE_WAIT  | 
7879  |  | /*[clinic input]  | 
7880  |  | os.wait  | 
7881  |  |  | 
7882  |  | Wait for completion of a child process.  | 
7883  |  |  | 
7884  |  | Returns a tuple of information about the child process:  | 
7885  |  |     (pid, status)  | 
7886  |  | [clinic start generated code]*/  | 
7887  |  |  | 
7888  |  | static PyObject *  | 
7889  |  | os_wait_impl(PyObject *module)  | 
7890  |  | /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/  | 
7891  | 0  | { | 
7892  | 0  |     pid_t pid;  | 
7893  | 0  |     int async_err = 0;  | 
7894  | 0  |     WAIT_TYPE status;  | 
7895  | 0  |     WAIT_STATUS_INT(status) = 0;  | 
7896  |  | 
  | 
7897  | 0  |     do { | 
7898  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
7899  | 0  |         pid = wait(&status);  | 
7900  | 0  |         Py_END_ALLOW_THREADS  | 
7901  | 0  |     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
7902  | 0  |     if (pid < 0)  | 
7903  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
7904  |  |  | 
7905  | 0  |     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); | 
7906  | 0  | }  | 
7907  |  | #endif /* HAVE_WAIT */  | 
7908  |  |  | 
7909  |  |  | 
7910  |  | #if defined(HAVE_READLINK) || defined(MS_WINDOWS)  | 
7911  |  | /*[clinic input]  | 
7912  |  | os.readlink  | 
7913  |  |  | 
7914  |  |     path: path_t  | 
7915  |  |     *  | 
7916  |  |     dir_fd: dir_fd(requires='readlinkat') = None  | 
7917  |  |  | 
7918  |  | Return a string representing the path to which the symbolic link points.  | 
7919  |  |  | 
7920  |  | If dir_fd is not None, it should be a file descriptor open to a directory,  | 
7921  |  | and path should be relative; path will then be relative to that directory.  | 
7922  |  |  | 
7923  |  | dir_fd may not be implemented on your platform.  If it is unavailable,  | 
7924  |  | using it will raise a NotImplementedError.  | 
7925  |  | [clinic start generated code]*/  | 
7926  |  |  | 
7927  |  | static PyObject *  | 
7928  |  | os_readlink_impl(PyObject *module, path_t *path, int dir_fd)  | 
7929  |  | /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/  | 
7930  | 0  | { | 
7931  | 0  | #if defined(HAVE_READLINK)  | 
7932  | 0  |     char buffer[MAXPATHLEN+1];  | 
7933  | 0  |     ssize_t length;  | 
7934  |  | 
  | 
7935  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
7936  | 0  | #ifdef HAVE_READLINKAT  | 
7937  | 0  |     if (dir_fd != DEFAULT_DIR_FD)  | 
7938  | 0  |         length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);  | 
7939  | 0  |     else  | 
7940  | 0  | #endif  | 
7941  | 0  |         length = readlink(path->narrow, buffer, MAXPATHLEN);  | 
7942  | 0  |     Py_END_ALLOW_THREADS  | 
7943  |  | 
  | 
7944  | 0  |     if (length < 0) { | 
7945  | 0  |         return path_error(path);  | 
7946  | 0  |     }  | 
7947  | 0  |     buffer[length] = '\0';  | 
7948  |  | 
  | 
7949  | 0  |     if (PyUnicode_Check(path->object))  | 
7950  | 0  |         return PyUnicode_DecodeFSDefaultAndSize(buffer, length);  | 
7951  | 0  |     else  | 
7952  | 0  |         return PyBytes_FromStringAndSize(buffer, length);  | 
7953  |  | #elif defined(MS_WINDOWS)  | 
7954  |  |     DWORD n_bytes_returned;  | 
7955  |  |     DWORD io_result = 0;  | 
7956  |  |     HANDLE reparse_point_handle;  | 
7957  |  |     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];  | 
7958  |  |     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;  | 
7959  |  |     PyObject *result = NULL;  | 
7960  |  |  | 
7961  |  |     /* First get a handle to the reparse point */  | 
7962  |  |     Py_BEGIN_ALLOW_THREADS  | 
7963  |  |     reparse_point_handle = CreateFileW(  | 
7964  |  |         path->wide,  | 
7965  |  |         0,  | 
7966  |  |         0,  | 
7967  |  |         0,  | 
7968  |  |         OPEN_EXISTING,  | 
7969  |  |         FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,  | 
7970  |  |         0);  | 
7971  |  |     if (reparse_point_handle != INVALID_HANDLE_VALUE) { | 
7972  |  |         /* New call DeviceIoControl to read the reparse point */  | 
7973  |  |         io_result = DeviceIoControl(  | 
7974  |  |             reparse_point_handle,  | 
7975  |  |             FSCTL_GET_REPARSE_POINT,  | 
7976  |  |             0, 0, /* in buffer */  | 
7977  |  |             target_buffer, sizeof(target_buffer),  | 
7978  |  |             &n_bytes_returned,  | 
7979  |  |             0 /* we're not using OVERLAPPED_IO */  | 
7980  |  |             );  | 
7981  |  |         CloseHandle(reparse_point_handle);  | 
7982  |  |     }  | 
7983  |  |     Py_END_ALLOW_THREADS  | 
7984  |  |  | 
7985  |  |     if (io_result == 0) { | 
7986  |  |         return path_error(path);  | 
7987  |  |     }  | 
7988  |  |  | 
7989  |  |     wchar_t *name = NULL;  | 
7990  |  |     Py_ssize_t nameLen = 0;  | 
7991  |  |     if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)  | 
7992  |  |     { | 
7993  |  |         name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +  | 
7994  |  |                            rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);  | 
7995  |  |         nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);  | 
7996  |  |     }  | 
7997  |  |     else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)  | 
7998  |  |     { | 
7999  |  |         name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +  | 
8000  |  |                            rdb->MountPointReparseBuffer.SubstituteNameOffset);  | 
8001  |  |         nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);  | 
8002  |  |     }  | 
8003  |  |     else  | 
8004  |  |     { | 
8005  |  |         PyErr_SetString(PyExc_ValueError, "not a symbolic link");  | 
8006  |  |     }  | 
8007  |  |     if (name) { | 
8008  |  |         if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) { | 
8009  |  |             /* Our buffer is mutable, so this is okay */  | 
8010  |  |             name[1] = L'\\';  | 
8011  |  |         }  | 
8012  |  |         result = PyUnicode_FromWideChar(name, nameLen);  | 
8013  |  |         if (result && path->narrow) { | 
8014  |  |             Py_SETREF(result, PyUnicode_EncodeFSDefault(result));  | 
8015  |  |         }  | 
8016  |  |     }  | 
8017  |  |     return result;  | 
8018  |  | #endif  | 
8019  | 0  | }  | 
8020  |  | #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */  | 
8021  |  |  | 
8022  |  | #ifdef HAVE_SYMLINK  | 
8023  |  |  | 
8024  |  | #if defined(MS_WINDOWS)  | 
8025  |  |  | 
8026  |  | /* Remove the last portion of the path - return 0 on success */  | 
8027  |  | static int  | 
8028  |  | _dirnameW(WCHAR *path)  | 
8029  |  | { | 
8030  |  |     WCHAR *ptr;  | 
8031  |  |     size_t length = wcsnlen_s(path, MAX_PATH);  | 
8032  |  |     if (length == MAX_PATH) { | 
8033  |  |         return -1;  | 
8034  |  |     }  | 
8035  |  |  | 
8036  |  |     /* walk the path from the end until a backslash is encountered */  | 
8037  |  |     for(ptr = path + length; ptr != path; ptr--) { | 
8038  |  |         if (*ptr == L'\\' || *ptr == L'/') { | 
8039  |  |             break;  | 
8040  |  |         }  | 
8041  |  |     }  | 
8042  |  |     *ptr = 0;  | 
8043  |  |     return 0;  | 
8044  |  | }  | 
8045  |  |  | 
8046  |  | /* Is this path absolute? */  | 
8047  |  | static int  | 
8048  |  | _is_absW(const WCHAR *path)  | 
8049  |  | { | 
8050  |  |     return path[0] == L'\\' || path[0] == L'/' ||  | 
8051  |  |         (path[0] && path[1] == L':');  | 
8052  |  | }  | 
8053  |  |  | 
8054  |  | /* join root and rest with a backslash - return 0 on success */  | 
8055  |  | static int  | 
8056  |  | _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)  | 
8057  |  | { | 
8058  |  |     if (_is_absW(rest)) { | 
8059  |  |         return wcscpy_s(dest_path, MAX_PATH, rest);  | 
8060  |  |     }  | 
8061  |  |  | 
8062  |  |     if (wcscpy_s(dest_path, MAX_PATH, root)) { | 
8063  |  |         return -1;  | 
8064  |  |     }  | 
8065  |  |  | 
8066  |  |     if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) { | 
8067  |  |         return -1;  | 
8068  |  |     }  | 
8069  |  |  | 
8070  |  |     return wcscat_s(dest_path, MAX_PATH, rest);  | 
8071  |  | }  | 
8072  |  |  | 
8073  |  | /* Return True if the path at src relative to dest is a directory */  | 
8074  |  | static int  | 
8075  |  | _check_dirW(LPCWSTR src, LPCWSTR dest)  | 
8076  |  | { | 
8077  |  |     WIN32_FILE_ATTRIBUTE_DATA src_info;  | 
8078  |  |     WCHAR dest_parent[MAX_PATH];  | 
8079  |  |     WCHAR src_resolved[MAX_PATH] = L"";  | 
8080  |  |  | 
8081  |  |     /* dest_parent = os.path.dirname(dest) */  | 
8082  |  |     if (wcscpy_s(dest_parent, MAX_PATH, dest) ||  | 
8083  |  |         _dirnameW(dest_parent)) { | 
8084  |  |         return 0;  | 
8085  |  |     }  | 
8086  |  |     /* src_resolved = os.path.join(dest_parent, src) */  | 
8087  |  |     if (_joinW(src_resolved, dest_parent, src)) { | 
8088  |  |         return 0;  | 
8089  |  |     }  | 
8090  |  |     return (  | 
8091  |  |         GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)  | 
8092  |  |         && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY  | 
8093  |  |     );  | 
8094  |  | }  | 
8095  |  | #endif  | 
8096  |  |  | 
8097  |  |  | 
8098  |  | /*[clinic input]  | 
8099  |  | os.symlink  | 
8100  |  |     src: path_t  | 
8101  |  |     dst: path_t  | 
8102  |  |     target_is_directory: bool = False  | 
8103  |  |     *  | 
8104  |  |     dir_fd: dir_fd(requires='symlinkat')=None  | 
8105  |  |  | 
8106  |  | # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\  | 
8107  |  |  | 
8108  |  | Create a symbolic link pointing to src named dst.  | 
8109  |  |  | 
8110  |  | target_is_directory is required on Windows if the target is to be  | 
8111  |  |   interpreted as a directory.  (On Windows, symlink requires  | 
8112  |  |   Windows 6.0 or greater, and raises a NotImplementedError otherwise.)  | 
8113  |  |   target_is_directory is ignored on non-Windows platforms.  | 
8114  |  |  | 
8115  |  | If dir_fd is not None, it should be a file descriptor open to a directory,  | 
8116  |  |   and path should be relative; path will then be relative to that directory.  | 
8117  |  | dir_fd may not be implemented on your platform.  | 
8118  |  |   If it is unavailable, using it will raise a NotImplementedError.  | 
8119  |  |  | 
8120  |  | [clinic start generated code]*/  | 
8121  |  |  | 
8122  |  | static PyObject *  | 
8123  |  | os_symlink_impl(PyObject *module, path_t *src, path_t *dst,  | 
8124  |  |                 int target_is_directory, int dir_fd)  | 
8125  |  | /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/  | 
8126  | 0  | { | 
8127  |  | #ifdef MS_WINDOWS  | 
8128  |  |     DWORD result;  | 
8129  |  |     DWORD flags = 0;  | 
8130  |  |  | 
8131  |  |     /* Assumed true, set to false if detected to not be available. */  | 
8132  |  |     static int windows_has_symlink_unprivileged_flag = TRUE;  | 
8133  |  | #else  | 
8134  | 0  |     int result;  | 
8135  | 0  | #endif  | 
8136  |  | 
  | 
8137  | 0  |     if (PySys_Audit("os.symlink", "OOi", src->object, dst->object, | 
8138  | 0  |                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { | 
8139  | 0  |         return NULL;  | 
8140  | 0  |     }  | 
8141  |  |  | 
8142  |  | #ifdef MS_WINDOWS  | 
8143  |  |  | 
8144  |  |     if (windows_has_symlink_unprivileged_flag) { | 
8145  |  |         /* Allow non-admin symlinks if system allows it. */  | 
8146  |  |         flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;  | 
8147  |  |     }  | 
8148  |  |  | 
8149  |  |     Py_BEGIN_ALLOW_THREADS  | 
8150  |  |     _Py_BEGIN_SUPPRESS_IPH  | 
8151  |  |     /* if src is a directory, ensure flags==1 (target_is_directory bit) */  | 
8152  |  |     if (target_is_directory || _check_dirW(src->wide, dst->wide)) { | 
8153  |  |         flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;  | 
8154  |  |     }  | 
8155  |  |  | 
8156  |  |     result = CreateSymbolicLinkW(dst->wide, src->wide, flags);  | 
8157  |  |     _Py_END_SUPPRESS_IPH  | 
8158  |  |     Py_END_ALLOW_THREADS  | 
8159  |  |  | 
8160  |  |     if (windows_has_symlink_unprivileged_flag && !result &&  | 
8161  |  |         ERROR_INVALID_PARAMETER == GetLastError()) { | 
8162  |  |  | 
8163  |  |         Py_BEGIN_ALLOW_THREADS  | 
8164  |  |         _Py_BEGIN_SUPPRESS_IPH  | 
8165  |  |         /* This error might be caused by  | 
8166  |  |         SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.  | 
8167  |  |         Try again, and update windows_has_symlink_unprivileged_flag if we  | 
8168  |  |         are successful this time.  | 
8169  |  |  | 
8170  |  |         NOTE: There is a risk of a race condition here if there are other  | 
8171  |  |         conditions than the flag causing ERROR_INVALID_PARAMETER, and  | 
8172  |  |         another process (or thread) changes that condition in between our  | 
8173  |  |         calls to CreateSymbolicLink.  | 
8174  |  |         */  | 
8175  |  |         flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);  | 
8176  |  |         result = CreateSymbolicLinkW(dst->wide, src->wide, flags);  | 
8177  |  |         _Py_END_SUPPRESS_IPH  | 
8178  |  |         Py_END_ALLOW_THREADS  | 
8179  |  |  | 
8180  |  |         if (result || ERROR_INVALID_PARAMETER != GetLastError()) { | 
8181  |  |             windows_has_symlink_unprivileged_flag = FALSE;  | 
8182  |  |         }  | 
8183  |  |     }  | 
8184  |  |  | 
8185  |  |     if (!result)  | 
8186  |  |         return path_error2(src, dst);  | 
8187  |  |  | 
8188  |  | #else  | 
8189  |  |  | 
8190  | 0  |     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { | 
8191  | 0  |         PyErr_SetString(PyExc_ValueError,  | 
8192  | 0  |             "symlink: src and dst must be the same type");  | 
8193  | 0  |         return NULL;  | 
8194  | 0  |     }  | 
8195  |  |  | 
8196  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
8197  | 0  | #if HAVE_SYMLINKAT  | 
8198  | 0  |     if (dir_fd != DEFAULT_DIR_FD)  | 
8199  | 0  |         result = symlinkat(src->narrow, dir_fd, dst->narrow);  | 
8200  | 0  |     else  | 
8201  | 0  | #endif  | 
8202  | 0  |         result = symlink(src->narrow, dst->narrow);  | 
8203  | 0  |     Py_END_ALLOW_THREADS  | 
8204  |  | 
  | 
8205  | 0  |     if (result)  | 
8206  | 0  |         return path_error2(src, dst);  | 
8207  | 0  | #endif  | 
8208  |  |  | 
8209  | 0  |     Py_RETURN_NONE;  | 
8210  | 0  | }  | 
8211  |  | #endif /* HAVE_SYMLINK */  | 
8212  |  |  | 
8213  |  |  | 
8214  |  |  | 
8215  |  |  | 
8216  |  | static PyStructSequence_Field times_result_fields[] = { | 
8217  |  |     {"user",    "user time"}, | 
8218  |  |     {"system",   "system time"}, | 
8219  |  |     {"children_user",    "user time of children"}, | 
8220  |  |     {"children_system",    "system time of children"}, | 
8221  |  |     {"elapsed",    "elapsed time since an arbitrary point in the past"}, | 
8222  |  |     {NULL} | 
8223  |  | };  | 
8224  |  |  | 
8225  |  | PyDoc_STRVAR(times_result__doc__,  | 
8226  |  | "times_result: Result from os.times().\n\n\  | 
8227  |  | This object may be accessed either as a tuple of\n\  | 
8228  |  |   (user, system, children_user, children_system, elapsed),\n\  | 
8229  |  | or via the attributes user, system, children_user, children_system,\n\  | 
8230  |  | and elapsed.\n\  | 
8231  |  | \n\  | 
8232  |  | See os.times for more information.");  | 
8233  |  |  | 
8234  |  | static PyStructSequence_Desc times_result_desc = { | 
8235  |  |     "times_result", /* name */  | 
8236  |  |     times_result__doc__, /* doc */  | 
8237  |  |     times_result_fields,  | 
8238  |  |     5  | 
8239  |  | };  | 
8240  |  |  | 
8241  |  | static PyTypeObject* TimesResultType;  | 
8242  |  |  | 
8243  |  | #ifdef MS_WINDOWS  | 
8244  |  | #define HAVE_TIMES  /* mandatory, for the method table */  | 
8245  |  | #endif  | 
8246  |  |  | 
8247  |  | #ifdef HAVE_TIMES  | 
8248  |  |  | 
8249  |  | static PyObject *  | 
8250  |  | build_times_result(double user, double system,  | 
8251  |  |     double children_user, double children_system,  | 
8252  |  |     double elapsed)  | 
8253  | 0  | { | 
8254  | 0  |     PyObject *value = PyStructSequence_New(TimesResultType);  | 
8255  | 0  |     if (value == NULL)  | 
8256  | 0  |         return NULL;  | 
8257  |  |  | 
8258  | 0  | #define SET(i, field) \  | 
8259  | 0  |     { \ | 
8260  | 0  |     PyObject *o = PyFloat_FromDouble(field); \  | 
8261  | 0  |     if (!o) { \ | 
8262  | 0  |         Py_DECREF(value); \  | 
8263  | 0  |         return NULL; \  | 
8264  | 0  |     } \  | 
8265  | 0  |     PyStructSequence_SET_ITEM(value, i, o); \  | 
8266  | 0  |     } \  | 
8267  | 0  |  | 
8268  | 0  |     SET(0, user);  | 
8269  | 0  |     SET(1, system);  | 
8270  | 0  |     SET(2, children_user);  | 
8271  | 0  |     SET(3, children_system);  | 
8272  | 0  |     SET(4, elapsed);  | 
8273  |  | 
  | 
8274  | 0  | #undef SET  | 
8275  |  | 
  | 
8276  | 0  |     return value;  | 
8277  | 0  | }  | 
8278  |  |  | 
8279  |  |  | 
8280  |  | #ifndef MS_WINDOWS  | 
8281  |  | #define NEED_TICKS_PER_SECOND  | 
8282  |  | static long ticks_per_second = -1;  | 
8283  |  | #endif /* MS_WINDOWS */  | 
8284  |  |  | 
8285  |  | /*[clinic input]  | 
8286  |  | os.times  | 
8287  |  |  | 
8288  |  | Return a collection containing process timing information.  | 
8289  |  |  | 
8290  |  | The object returned behaves like a named tuple with these fields:  | 
8291  |  |   (utime, stime, cutime, cstime, elapsed_time)  | 
8292  |  | All fields are floating point numbers.  | 
8293  |  | [clinic start generated code]*/  | 
8294  |  |  | 
8295  |  | static PyObject *  | 
8296  |  | os_times_impl(PyObject *module)  | 
8297  |  | /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/  | 
8298  |  | #ifdef MS_WINDOWS  | 
8299  |  | { | 
8300  |  |     FILETIME create, exit, kernel, user;  | 
8301  |  |     HANDLE hProc;  | 
8302  |  |     hProc = GetCurrentProcess();  | 
8303  |  |     GetProcessTimes(hProc, &create, &exit, &kernel, &user);  | 
8304  |  |     /* The fields of a FILETIME structure are the hi and lo part  | 
8305  |  |        of a 64-bit value expressed in 100 nanosecond units.  | 
8306  |  |        1e7 is one second in such units; 1e-7 the inverse.  | 
8307  |  |        429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.  | 
8308  |  |     */  | 
8309  |  |     return build_times_result(  | 
8310  |  |         (double)(user.dwHighDateTime*429.4967296 +  | 
8311  |  |                  user.dwLowDateTime*1e-7),  | 
8312  |  |         (double)(kernel.dwHighDateTime*429.4967296 +  | 
8313  |  |                  kernel.dwLowDateTime*1e-7),  | 
8314  |  |         (double)0,  | 
8315  |  |         (double)0,  | 
8316  |  |         (double)0);  | 
8317  |  | }  | 
8318  |  | #else /* MS_WINDOWS */  | 
8319  | 0  | { | 
8320  |  |  | 
8321  |  | 
  | 
8322  | 0  |     struct tms t;  | 
8323  | 0  |     clock_t c;  | 
8324  | 0  |     errno = 0;  | 
8325  | 0  |     c = times(&t);  | 
8326  | 0  |     if (c == (clock_t) -1)  | 
8327  | 0  |         return posix_error();  | 
8328  | 0  |     return build_times_result(  | 
8329  | 0  |                          (double)t.tms_utime / ticks_per_second,  | 
8330  | 0  |                          (double)t.tms_stime / ticks_per_second,  | 
8331  | 0  |                          (double)t.tms_cutime / ticks_per_second,  | 
8332  | 0  |                          (double)t.tms_cstime / ticks_per_second,  | 
8333  | 0  |                          (double)c / ticks_per_second);  | 
8334  | 0  | }  | 
8335  |  | #endif /* MS_WINDOWS */  | 
8336  |  | #endif /* HAVE_TIMES */  | 
8337  |  |  | 
8338  |  |  | 
8339  |  | #ifdef HAVE_GETSID  | 
8340  |  | /*[clinic input]  | 
8341  |  | os.getsid  | 
8342  |  |  | 
8343  |  |     pid: pid_t  | 
8344  |  |     /  | 
8345  |  |  | 
8346  |  | Call the system call getsid(pid) and return the result.  | 
8347  |  | [clinic start generated code]*/  | 
8348  |  |  | 
8349  |  | static PyObject *  | 
8350  |  | os_getsid_impl(PyObject *module, pid_t pid)  | 
8351  |  | /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/  | 
8352  | 0  | { | 
8353  | 0  |     int sid;  | 
8354  | 0  |     sid = getsid(pid);  | 
8355  | 0  |     if (sid < 0)  | 
8356  | 0  |         return posix_error();  | 
8357  | 0  |     return PyLong_FromLong((long)sid);  | 
8358  | 0  | }  | 
8359  |  | #endif /* HAVE_GETSID */  | 
8360  |  |  | 
8361  |  |  | 
8362  |  | #ifdef HAVE_SETSID  | 
8363  |  | /*[clinic input]  | 
8364  |  | os.setsid  | 
8365  |  |  | 
8366  |  | Call the system call setsid().  | 
8367  |  | [clinic start generated code]*/  | 
8368  |  |  | 
8369  |  | static PyObject *  | 
8370  |  | os_setsid_impl(PyObject *module)  | 
8371  |  | /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/  | 
8372  | 0  | { | 
8373  | 0  |     if (setsid() < 0)  | 
8374  | 0  |         return posix_error();  | 
8375  | 0  |     Py_RETURN_NONE;  | 
8376  | 0  | }  | 
8377  |  | #endif /* HAVE_SETSID */  | 
8378  |  |  | 
8379  |  |  | 
8380  |  | #ifdef HAVE_SETPGID  | 
8381  |  | /*[clinic input]  | 
8382  |  | os.setpgid  | 
8383  |  |  | 
8384  |  |     pid: pid_t  | 
8385  |  |     pgrp: pid_t  | 
8386  |  |     /  | 
8387  |  |  | 
8388  |  | Call the system call setpgid(pid, pgrp).  | 
8389  |  | [clinic start generated code]*/  | 
8390  |  |  | 
8391  |  | static PyObject *  | 
8392  |  | os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)  | 
8393  |  | /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/  | 
8394  | 0  | { | 
8395  | 0  |     if (setpgid(pid, pgrp) < 0)  | 
8396  | 0  |         return posix_error();  | 
8397  | 0  |     Py_RETURN_NONE;  | 
8398  | 0  | }  | 
8399  |  | #endif /* HAVE_SETPGID */  | 
8400  |  |  | 
8401  |  |  | 
8402  |  | #ifdef HAVE_TCGETPGRP  | 
8403  |  | /*[clinic input]  | 
8404  |  | os.tcgetpgrp  | 
8405  |  |  | 
8406  |  |     fd: int  | 
8407  |  |     /  | 
8408  |  |  | 
8409  |  | Return the process group associated with the terminal specified by fd.  | 
8410  |  | [clinic start generated code]*/  | 
8411  |  |  | 
8412  |  | static PyObject *  | 
8413  |  | os_tcgetpgrp_impl(PyObject *module, int fd)  | 
8414  |  | /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/  | 
8415  | 0  | { | 
8416  | 0  |     pid_t pgid = tcgetpgrp(fd);  | 
8417  | 0  |     if (pgid < 0)  | 
8418  | 0  |         return posix_error();  | 
8419  | 0  |     return PyLong_FromPid(pgid);  | 
8420  | 0  | }  | 
8421  |  | #endif /* HAVE_TCGETPGRP */  | 
8422  |  |  | 
8423  |  |  | 
8424  |  | #ifdef HAVE_TCSETPGRP  | 
8425  |  | /*[clinic input]  | 
8426  |  | os.tcsetpgrp  | 
8427  |  |  | 
8428  |  |     fd: int  | 
8429  |  |     pgid: pid_t  | 
8430  |  |     /  | 
8431  |  |  | 
8432  |  | Set the process group associated with the terminal specified by fd.  | 
8433  |  | [clinic start generated code]*/  | 
8434  |  |  | 
8435  |  | static PyObject *  | 
8436  |  | os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)  | 
8437  |  | /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/  | 
8438  | 0  | { | 
8439  | 0  |     if (tcsetpgrp(fd, pgid) < 0)  | 
8440  | 0  |         return posix_error();  | 
8441  | 0  |     Py_RETURN_NONE;  | 
8442  | 0  | }  | 
8443  |  | #endif /* HAVE_TCSETPGRP */  | 
8444  |  |  | 
8445  |  | /* Functions acting on file descriptors */  | 
8446  |  |  | 
8447  |  | #ifdef O_CLOEXEC  | 
8448  |  | extern int _Py_open_cloexec_works;  | 
8449  |  | #endif  | 
8450  |  |  | 
8451  |  |  | 
8452  |  | /*[clinic input]  | 
8453  |  | os.open -> int  | 
8454  |  |     path: path_t  | 
8455  |  |     flags: int  | 
8456  |  |     mode: int = 0o777  | 
8457  |  |     *  | 
8458  |  |     dir_fd: dir_fd(requires='openat') = None  | 
8459  |  |  | 
8460  |  | # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\  | 
8461  |  |  | 
8462  |  | Open a file for low level IO.  Returns a file descriptor (integer).  | 
8463  |  |  | 
8464  |  | If dir_fd is not None, it should be a file descriptor open to a directory,  | 
8465  |  |   and path should be relative; path will then be relative to that directory.  | 
8466  |  | dir_fd may not be implemented on your platform.  | 
8467  |  |   If it is unavailable, using it will raise a NotImplementedError.  | 
8468  |  | [clinic start generated code]*/  | 
8469  |  |  | 
8470  |  | static int  | 
8471  |  | os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)  | 
8472  |  | /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/  | 
8473  | 0  | { | 
8474  | 0  |     int fd;  | 
8475  | 0  |     int async_err = 0;  | 
8476  |  | 
  | 
8477  | 0  | #ifdef O_CLOEXEC  | 
8478  | 0  |     int *atomic_flag_works = &_Py_open_cloexec_works;  | 
8479  |  | #elif !defined(MS_WINDOWS)  | 
8480  |  |     int *atomic_flag_works = NULL;  | 
8481  |  | #endif  | 
8482  |  | 
  | 
8483  |  | #ifdef MS_WINDOWS  | 
8484  |  |     flags |= O_NOINHERIT;  | 
8485  |  | #elif defined(O_CLOEXEC)  | 
8486  | 0  |     flags |= O_CLOEXEC;  | 
8487  | 0  | #endif  | 
8488  |  | 
  | 
8489  | 0  |     if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) { | 
8490  | 0  |         return -1;  | 
8491  | 0  |     }  | 
8492  |  |  | 
8493  | 0  |     _Py_BEGIN_SUPPRESS_IPH  | 
8494  | 0  |     do { | 
8495  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
8496  |  | #ifdef MS_WINDOWS  | 
8497  |  |         fd = _wopen(path->wide, flags, mode);  | 
8498  |  | #else  | 
8499  | 0  | #ifdef HAVE_OPENAT  | 
8500  | 0  |         if (dir_fd != DEFAULT_DIR_FD)  | 
8501  | 0  |             fd = openat(dir_fd, path->narrow, flags, mode);  | 
8502  | 0  |         else  | 
8503  | 0  | #endif /* HAVE_OPENAT */  | 
8504  | 0  |             fd = open(path->narrow, flags, mode);  | 
8505  | 0  | #endif /* !MS_WINDOWS */  | 
8506  | 0  |         Py_END_ALLOW_THREADS  | 
8507  | 0  |     } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
8508  | 0  |     _Py_END_SUPPRESS_IPH  | 
8509  |  | 
  | 
8510  | 0  |     if (fd < 0) { | 
8511  | 0  |         if (!async_err)  | 
8512  | 0  |             PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);  | 
8513  | 0  |         return -1;  | 
8514  | 0  |     }  | 
8515  |  |  | 
8516  | 0  | #ifndef MS_WINDOWS  | 
8517  | 0  |     if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) { | 
8518  | 0  |         close(fd);  | 
8519  | 0  |         return -1;  | 
8520  | 0  |     }  | 
8521  | 0  | #endif  | 
8522  |  |  | 
8523  | 0  |     return fd;  | 
8524  | 0  | }  | 
8525  |  |  | 
8526  |  |  | 
8527  |  | /*[clinic input]  | 
8528  |  | os.close  | 
8529  |  |  | 
8530  |  |     fd: int  | 
8531  |  |  | 
8532  |  | Close a file descriptor.  | 
8533  |  | [clinic start generated code]*/  | 
8534  |  |  | 
8535  |  | static PyObject *  | 
8536  |  | os_close_impl(PyObject *module, int fd)  | 
8537  |  | /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/  | 
8538  | 0  | { | 
8539  | 0  |     int res;  | 
8540  |  |     /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/  | 
8541  |  |      * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html  | 
8542  |  |      * for more details.  | 
8543  |  |      */  | 
8544  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
8545  | 0  |     _Py_BEGIN_SUPPRESS_IPH  | 
8546  | 0  |     res = close(fd);  | 
8547  | 0  |     _Py_END_SUPPRESS_IPH  | 
8548  | 0  |     Py_END_ALLOW_THREADS  | 
8549  | 0  |     if (res < 0)  | 
8550  | 0  |         return posix_error();  | 
8551  | 0  |     Py_RETURN_NONE;  | 
8552  | 0  | }  | 
8553  |  |  | 
8554  |  |  | 
8555  |  | #ifdef HAVE_FDWALK  | 
8556  |  | static int  | 
8557  |  | _fdwalk_close_func(void *lohi, int fd)  | 
8558  |  | { | 
8559  |  |     int lo = ((int *)lohi)[0];  | 
8560  |  |     int hi = ((int *)lohi)[1];  | 
8561  |  |  | 
8562  |  |     if (fd >= hi)  | 
8563  |  |         return 1;  | 
8564  |  |     else if (fd >= lo)  | 
8565  |  |         close(fd);  | 
8566  |  |     return 0;  | 
8567  |  | }  | 
8568  |  | #endif /* HAVE_FDWALK */  | 
8569  |  |  | 
8570  |  | /*[clinic input]  | 
8571  |  | os.closerange  | 
8572  |  |  | 
8573  |  |     fd_low: int  | 
8574  |  |     fd_high: int  | 
8575  |  |     /  | 
8576  |  |  | 
8577  |  | Closes all file descriptors in [fd_low, fd_high), ignoring errors.  | 
8578  |  | [clinic start generated code]*/  | 
8579  |  |  | 
8580  |  | static PyObject *  | 
8581  |  | os_closerange_impl(PyObject *module, int fd_low, int fd_high)  | 
8582  |  | /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/  | 
8583  | 0  | { | 
8584  |  | #ifdef HAVE_FDWALK  | 
8585  |  |     int lohi[2];  | 
8586  |  | #else  | 
8587  | 0  |     int i;  | 
8588  | 0  | #endif  | 
8589  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
8590  | 0  |     _Py_BEGIN_SUPPRESS_IPH  | 
8591  |  | #ifdef HAVE_FDWALK  | 
8592  |  |     lohi[0] = Py_MAX(fd_low, 0);  | 
8593  |  |     lohi[1] = fd_high;  | 
8594  |  |     fdwalk(_fdwalk_close_func, lohi);  | 
8595  |  | #else  | 
8596  | 0  |     for (i = Py_MAX(fd_low, 0); i < fd_high; i++)  | 
8597  | 0  |         close(i);  | 
8598  | 0  | #endif  | 
8599  | 0  |     _Py_END_SUPPRESS_IPH  | 
8600  | 0  |     Py_END_ALLOW_THREADS  | 
8601  | 0  |     Py_RETURN_NONE;  | 
8602  | 0  | }  | 
8603  |  |  | 
8604  |  |  | 
8605  |  | /*[clinic input]  | 
8606  |  | os.dup -> int  | 
8607  |  |  | 
8608  |  |     fd: int  | 
8609  |  |     /  | 
8610  |  |  | 
8611  |  | Return a duplicate of a file descriptor.  | 
8612  |  | [clinic start generated code]*/  | 
8613  |  |  | 
8614  |  | static int  | 
8615  |  | os_dup_impl(PyObject *module, int fd)  | 
8616  |  | /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/  | 
8617  | 0  | { | 
8618  | 0  |     return _Py_dup(fd);  | 
8619  | 0  | }  | 
8620  |  |  | 
8621  |  |  | 
8622  |  | /*[clinic input]  | 
8623  |  | os.dup2 -> int  | 
8624  |  |     fd: int  | 
8625  |  |     fd2: int  | 
8626  |  |     inheritable: bool=True  | 
8627  |  |  | 
8628  |  | Duplicate file descriptor.  | 
8629  |  | [clinic start generated code]*/  | 
8630  |  |  | 
8631  |  | static int  | 
8632  |  | os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)  | 
8633  |  | /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/  | 
8634  | 0  | { | 
8635  | 0  |     int res = 0;  | 
8636  | 0  | #if defined(HAVE_DUP3) && \  | 
8637  | 0  |     !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))  | 
8638  |  |     /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */  | 
8639  | 0  |     static int dup3_works = -1;  | 
8640  | 0  | #endif  | 
8641  |  | 
  | 
8642  | 0  |     if (fd < 0 || fd2 < 0) { | 
8643  | 0  |         posix_error();  | 
8644  | 0  |         return -1;  | 
8645  | 0  |     }  | 
8646  |  |  | 
8647  |  |     /* dup2() can fail with EINTR if the target FD is already open, because it  | 
8648  |  |      * then has to be closed. See os_close_impl() for why we don't handle EINTR  | 
8649  |  |      * upon close(), and therefore below.  | 
8650  |  |      */  | 
8651  |  | #ifdef MS_WINDOWS  | 
8652  |  |     Py_BEGIN_ALLOW_THREADS  | 
8653  |  |     _Py_BEGIN_SUPPRESS_IPH  | 
8654  |  |     res = dup2(fd, fd2);  | 
8655  |  |     _Py_END_SUPPRESS_IPH  | 
8656  |  |     Py_END_ALLOW_THREADS  | 
8657  |  |     if (res < 0) { | 
8658  |  |         posix_error();  | 
8659  |  |         return -1;  | 
8660  |  |     }  | 
8661  |  |     res = fd2; // msvcrt dup2 returns 0 on success.  | 
8662  |  |  | 
8663  |  |     /* Character files like console cannot be make non-inheritable */  | 
8664  |  |     if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { | 
8665  |  |         close(fd2);  | 
8666  |  |         return -1;  | 
8667  |  |     }  | 
8668  |  |  | 
8669  |  | #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)  | 
8670  |  |     Py_BEGIN_ALLOW_THREADS  | 
8671  |  |     if (!inheritable)  | 
8672  |  |         res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);  | 
8673  |  |     else  | 
8674  |  |         res = dup2(fd, fd2);  | 
8675  |  |     Py_END_ALLOW_THREADS  | 
8676  |  |     if (res < 0) { | 
8677  |  |         posix_error();  | 
8678  |  |         return -1;  | 
8679  |  |     }  | 
8680  |  |  | 
8681  |  | #else  | 
8682  |  |  | 
8683  | 0  | #ifdef HAVE_DUP3  | 
8684  | 0  |     if (!inheritable && dup3_works != 0) { | 
8685  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
8686  | 0  |         res = dup3(fd, fd2, O_CLOEXEC);  | 
8687  | 0  |         Py_END_ALLOW_THREADS  | 
8688  | 0  |         if (res < 0) { | 
8689  | 0  |             if (dup3_works == -1)  | 
8690  | 0  |                 dup3_works = (errno != ENOSYS);  | 
8691  | 0  |             if (dup3_works) { | 
8692  | 0  |                 posix_error();  | 
8693  | 0  |                 return -1;  | 
8694  | 0  |             }  | 
8695  | 0  |         }  | 
8696  | 0  |     }  | 
8697  |  |  | 
8698  | 0  |     if (inheritable || dup3_works == 0)  | 
8699  | 0  |     { | 
8700  | 0  | #endif  | 
8701  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
8702  | 0  |         res = dup2(fd, fd2);  | 
8703  | 0  |         Py_END_ALLOW_THREADS  | 
8704  | 0  |         if (res < 0) { | 
8705  | 0  |             posix_error();  | 
8706  | 0  |             return -1;  | 
8707  | 0  |         }  | 
8708  |  |  | 
8709  | 0  |         if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { | 
8710  | 0  |             close(fd2);  | 
8711  | 0  |             return -1;  | 
8712  | 0  |         }  | 
8713  | 0  | #ifdef HAVE_DUP3  | 
8714  | 0  |     }  | 
8715  | 0  | #endif  | 
8716  |  |  | 
8717  | 0  | #endif  | 
8718  |  |  | 
8719  | 0  |     return res;  | 
8720  | 0  | }  | 
8721  |  |  | 
8722  |  |  | 
8723  |  | #ifdef HAVE_LOCKF  | 
8724  |  | /*[clinic input]  | 
8725  |  | os.lockf  | 
8726  |  |  | 
8727  |  |     fd: int  | 
8728  |  |         An open file descriptor.  | 
8729  |  |     command: int  | 
8730  |  |         One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.  | 
8731  |  |     length: Py_off_t  | 
8732  |  |         The number of bytes to lock, starting at the current position.  | 
8733  |  |     /  | 
8734  |  |  | 
8735  |  | Apply, test or remove a POSIX lock on an open file descriptor.  | 
8736  |  |  | 
8737  |  | [clinic start generated code]*/  | 
8738  |  |  | 
8739  |  | static PyObject *  | 
8740  |  | os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)  | 
8741  |  | /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/  | 
8742  | 0  | { | 
8743  | 0  |     int res;  | 
8744  |  | 
  | 
8745  | 0  |     if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) { | 
8746  | 0  |         return NULL;  | 
8747  | 0  |     }  | 
8748  |  |  | 
8749  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
8750  | 0  |     res = lockf(fd, command, length);  | 
8751  | 0  |     Py_END_ALLOW_THREADS  | 
8752  |  | 
  | 
8753  | 0  |     if (res < 0)  | 
8754  | 0  |         return posix_error();  | 
8755  |  |  | 
8756  | 0  |     Py_RETURN_NONE;  | 
8757  | 0  | }  | 
8758  |  | #endif /* HAVE_LOCKF */  | 
8759  |  |  | 
8760  |  |  | 
8761  |  | /*[clinic input]  | 
8762  |  | os.lseek -> Py_off_t  | 
8763  |  |  | 
8764  |  |     fd: int  | 
8765  |  |     position: Py_off_t  | 
8766  |  |     how: int  | 
8767  |  |     /  | 
8768  |  |  | 
8769  |  | Set the position of a file descriptor.  Return the new position.  | 
8770  |  |  | 
8771  |  | Return the new cursor position in number of bytes  | 
8772  |  | relative to the beginning of the file.  | 
8773  |  | [clinic start generated code]*/  | 
8774  |  |  | 
8775  |  | static Py_off_t  | 
8776  |  | os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)  | 
8777  |  | /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/  | 
8778  | 0  | { | 
8779  | 0  |     Py_off_t result;  | 
8780  |  | 
  | 
8781  | 0  | #ifdef SEEK_SET  | 
8782  |  |     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ | 
8783  | 0  |     switch (how) { | 
8784  | 0  |         case 0: how = SEEK_SET; break;  | 
8785  | 0  |         case 1: how = SEEK_CUR; break;  | 
8786  | 0  |         case 2: how = SEEK_END; break;  | 
8787  | 0  |     }  | 
8788  | 0  | #endif /* SEEK_END */  | 
8789  |  |  | 
8790  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
8791  | 0  |     _Py_BEGIN_SUPPRESS_IPH  | 
8792  |  | #ifdef MS_WINDOWS  | 
8793  |  |     result = _lseeki64(fd, position, how);  | 
8794  |  | #else  | 
8795  | 0  |     result = lseek(fd, position, how);  | 
8796  | 0  | #endif  | 
8797  | 0  |     _Py_END_SUPPRESS_IPH  | 
8798  | 0  |     Py_END_ALLOW_THREADS  | 
8799  | 0  |     if (result < 0)  | 
8800  | 0  |         posix_error();  | 
8801  |  | 
  | 
8802  | 0  |     return result;  | 
8803  | 0  | }  | 
8804  |  |  | 
8805  |  |  | 
8806  |  | /*[clinic input]  | 
8807  |  | os.read  | 
8808  |  |     fd: int  | 
8809  |  |     length: Py_ssize_t  | 
8810  |  |     /  | 
8811  |  |  | 
8812  |  | Read from a file descriptor.  Returns a bytes object.  | 
8813  |  | [clinic start generated code]*/  | 
8814  |  |  | 
8815  |  | static PyObject *  | 
8816  |  | os_read_impl(PyObject *module, int fd, Py_ssize_t length)  | 
8817  |  | /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/  | 
8818  | 0  | { | 
8819  | 0  |     Py_ssize_t n;  | 
8820  | 0  |     PyObject *buffer;  | 
8821  |  | 
  | 
8822  | 0  |     if (length < 0) { | 
8823  | 0  |         errno = EINVAL;  | 
8824  | 0  |         return posix_error();  | 
8825  | 0  |     }  | 
8826  |  |  | 
8827  | 0  |     length = Py_MIN(length, _PY_READ_MAX);  | 
8828  |  | 
  | 
8829  | 0  |     buffer = PyBytes_FromStringAndSize((char *)NULL, length);  | 
8830  | 0  |     if (buffer == NULL)  | 
8831  | 0  |         return NULL;  | 
8832  |  |  | 
8833  | 0  |     n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);  | 
8834  | 0  |     if (n == -1) { | 
8835  | 0  |         Py_DECREF(buffer);  | 
8836  | 0  |         return NULL;  | 
8837  | 0  |     }  | 
8838  |  |  | 
8839  | 0  |     if (n != length)  | 
8840  | 0  |         _PyBytes_Resize(&buffer, n);  | 
8841  |  | 
  | 
8842  | 0  |     return buffer;  | 
8843  | 0  | }  | 
8844  |  |  | 
8845  |  | #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \  | 
8846  |  |                                 || defined(__APPLE__))) \  | 
8847  |  |     || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \  | 
8848  |  |     || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)  | 
8849  |  | static int  | 
8850  |  | iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)  | 
8851  | 0  | { | 
8852  | 0  |     Py_ssize_t i, j;  | 
8853  |  | 
  | 
8854  | 0  |     *iov = PyMem_New(struct iovec, cnt);  | 
8855  | 0  |     if (*iov == NULL) { | 
8856  | 0  |         PyErr_NoMemory();  | 
8857  | 0  |         return -1;  | 
8858  | 0  |     }  | 
8859  |  |  | 
8860  | 0  |     *buf = PyMem_New(Py_buffer, cnt);  | 
8861  | 0  |     if (*buf == NULL) { | 
8862  | 0  |         PyMem_Del(*iov);  | 
8863  | 0  |         PyErr_NoMemory();  | 
8864  | 0  |         return -1;  | 
8865  | 0  |     }  | 
8866  |  |  | 
8867  | 0  |     for (i = 0; i < cnt; i++) { | 
8868  | 0  |         PyObject *item = PySequence_GetItem(seq, i);  | 
8869  | 0  |         if (item == NULL)  | 
8870  | 0  |             goto fail;  | 
8871  | 0  |         if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) { | 
8872  | 0  |             Py_DECREF(item);  | 
8873  | 0  |             goto fail;  | 
8874  | 0  |         }  | 
8875  | 0  |         Py_DECREF(item);  | 
8876  | 0  |         (*iov)[i].iov_base = (*buf)[i].buf;  | 
8877  | 0  |         (*iov)[i].iov_len = (*buf)[i].len;  | 
8878  | 0  |     }  | 
8879  | 0  |     return 0;  | 
8880  |  |  | 
8881  | 0  | fail:  | 
8882  | 0  |     PyMem_Del(*iov);  | 
8883  | 0  |     for (j = 0; j < i; j++) { | 
8884  | 0  |         PyBuffer_Release(&(*buf)[j]);  | 
8885  | 0  |     }  | 
8886  | 0  |     PyMem_Del(*buf);  | 
8887  | 0  |     return -1;  | 
8888  | 0  | }  | 
8889  |  |  | 
8890  |  | static void  | 
8891  |  | iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)  | 
8892  | 0  | { | 
8893  | 0  |     int i;  | 
8894  | 0  |     PyMem_Del(iov);  | 
8895  | 0  |     for (i = 0; i < cnt; i++) { | 
8896  | 0  |         PyBuffer_Release(&buf[i]);  | 
8897  | 0  |     }  | 
8898  | 0  |     PyMem_Del(buf);  | 
8899  | 0  | }  | 
8900  |  | #endif  | 
8901  |  |  | 
8902  |  |  | 
8903  |  | #ifdef HAVE_READV  | 
8904  |  | /*[clinic input]  | 
8905  |  | os.readv -> Py_ssize_t  | 
8906  |  |  | 
8907  |  |     fd: int  | 
8908  |  |     buffers: object  | 
8909  |  |     /  | 
8910  |  |  | 
8911  |  | Read from a file descriptor fd into an iterable of buffers.  | 
8912  |  |  | 
8913  |  | The buffers should be mutable buffers accepting bytes.  | 
8914  |  | readv will transfer data into each buffer until it is full  | 
8915  |  | and then move on to the next buffer in the sequence to hold  | 
8916  |  | the rest of the data.  | 
8917  |  |  | 
8918  |  | readv returns the total number of bytes read,  | 
8919  |  | which may be less than the total capacity of all the buffers.  | 
8920  |  | [clinic start generated code]*/  | 
8921  |  |  | 
8922  |  | static Py_ssize_t  | 
8923  |  | os_readv_impl(PyObject *module, int fd, PyObject *buffers)  | 
8924  |  | /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/  | 
8925  | 0  | { | 
8926  | 0  |     Py_ssize_t cnt, n;  | 
8927  | 0  |     int async_err = 0;  | 
8928  | 0  |     struct iovec *iov;  | 
8929  | 0  |     Py_buffer *buf;  | 
8930  |  | 
  | 
8931  | 0  |     if (!PySequence_Check(buffers)) { | 
8932  | 0  |         PyErr_SetString(PyExc_TypeError,  | 
8933  | 0  |             "readv() arg 2 must be a sequence");  | 
8934  | 0  |         return -1;  | 
8935  | 0  |     }  | 
8936  |  |  | 
8937  | 0  |     cnt = PySequence_Size(buffers);  | 
8938  | 0  |     if (cnt < 0)  | 
8939  | 0  |         return -1;  | 
8940  |  |  | 
8941  | 0  |     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)  | 
8942  | 0  |         return -1;  | 
8943  |  |  | 
8944  | 0  |     do { | 
8945  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
8946  | 0  |         n = readv(fd, iov, cnt);  | 
8947  | 0  |         Py_END_ALLOW_THREADS  | 
8948  | 0  |     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
8949  |  | 
  | 
8950  | 0  |     iov_cleanup(iov, buf, cnt);  | 
8951  | 0  |     if (n < 0) { | 
8952  | 0  |         if (!async_err)  | 
8953  | 0  |             posix_error();  | 
8954  | 0  |         return -1;  | 
8955  | 0  |     }  | 
8956  |  |  | 
8957  | 0  |     return n;  | 
8958  | 0  | }  | 
8959  |  | #endif /* HAVE_READV */  | 
8960  |  |  | 
8961  |  |  | 
8962  |  | #ifdef HAVE_PREAD  | 
8963  |  | /*[clinic input]  | 
8964  |  | # TODO length should be size_t!  but Python doesn't support parsing size_t yet.  | 
8965  |  | os.pread  | 
8966  |  |  | 
8967  |  |     fd: int  | 
8968  |  |     length: int  | 
8969  |  |     offset: Py_off_t  | 
8970  |  |     /  | 
8971  |  |  | 
8972  |  | Read a number of bytes from a file descriptor starting at a particular offset.  | 
8973  |  |  | 
8974  |  | Read length bytes from file descriptor fd, starting at offset bytes from  | 
8975  |  | the beginning of the file.  The file offset remains unchanged.  | 
8976  |  | [clinic start generated code]*/  | 
8977  |  |  | 
8978  |  | static PyObject *  | 
8979  |  | os_pread_impl(PyObject *module, int fd, int length, Py_off_t offset)  | 
8980  |  | /*[clinic end generated code: output=435b29ee32b54a78 input=084948dcbaa35d4c]*/  | 
8981  | 0  | { | 
8982  | 0  |     Py_ssize_t n;  | 
8983  | 0  |     int async_err = 0;  | 
8984  | 0  |     PyObject *buffer;  | 
8985  |  | 
  | 
8986  | 0  |     if (length < 0) { | 
8987  | 0  |         errno = EINVAL;  | 
8988  | 0  |         return posix_error();  | 
8989  | 0  |     }  | 
8990  | 0  |     buffer = PyBytes_FromStringAndSize((char *)NULL, length);  | 
8991  | 0  |     if (buffer == NULL)  | 
8992  | 0  |         return NULL;  | 
8993  |  |  | 
8994  | 0  |     do { | 
8995  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
8996  | 0  |         _Py_BEGIN_SUPPRESS_IPH  | 
8997  | 0  |         n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);  | 
8998  | 0  |         _Py_END_SUPPRESS_IPH  | 
8999  | 0  |         Py_END_ALLOW_THREADS  | 
9000  | 0  |     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
9001  |  | 
  | 
9002  | 0  |     if (n < 0) { | 
9003  | 0  |         Py_DECREF(buffer);  | 
9004  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
9005  | 0  |     }  | 
9006  | 0  |     if (n != length)  | 
9007  | 0  |         _PyBytes_Resize(&buffer, n);  | 
9008  | 0  |     return buffer;  | 
9009  | 0  | }  | 
9010  |  | #endif /* HAVE_PREAD */  | 
9011  |  |  | 
9012  |  | #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)  | 
9013  |  | /*[clinic input]  | 
9014  |  | os.preadv -> Py_ssize_t  | 
9015  |  |  | 
9016  |  |     fd: int  | 
9017  |  |     buffers: object  | 
9018  |  |     offset: Py_off_t  | 
9019  |  |     flags: int = 0  | 
9020  |  |     /  | 
9021  |  |  | 
9022  |  | Reads from a file descriptor into a number of mutable bytes-like objects.  | 
9023  |  |  | 
9024  |  | Combines the functionality of readv() and pread(). As readv(), it will  | 
9025  |  | transfer data into each buffer until it is full and then move on to the next  | 
9026  |  | buffer in the sequence to hold the rest of the data. Its fourth argument,  | 
9027  |  | specifies the file offset at which the input operation is to be performed. It  | 
9028  |  | will return the total number of bytes read (which can be less than the total  | 
9029  |  | capacity of all the objects).  | 
9030  |  |  | 
9031  |  | The flags argument contains a bitwise OR of zero or more of the following flags:  | 
9032  |  |  | 
9033  |  | - RWF_HIPRI  | 
9034  |  | - RWF_NOWAIT  | 
9035  |  |  | 
9036  |  | Using non-zero flags requires Linux 4.6 or newer.  | 
9037  |  | [clinic start generated code]*/  | 
9038  |  |  | 
9039  |  | static Py_ssize_t  | 
9040  |  | os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,  | 
9041  |  |                int flags)  | 
9042  |  | /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/  | 
9043  | 0  | { | 
9044  | 0  |     Py_ssize_t cnt, n;  | 
9045  | 0  |     int async_err = 0;  | 
9046  | 0  |     struct iovec *iov;  | 
9047  | 0  |     Py_buffer *buf;  | 
9048  |  | 
  | 
9049  | 0  |     if (!PySequence_Check(buffers)) { | 
9050  | 0  |         PyErr_SetString(PyExc_TypeError,  | 
9051  | 0  |             "preadv2() arg 2 must be a sequence");  | 
9052  | 0  |         return -1;  | 
9053  | 0  |     }  | 
9054  |  |  | 
9055  | 0  |     cnt = PySequence_Size(buffers);  | 
9056  | 0  |     if (cnt < 0) { | 
9057  | 0  |         return -1;  | 
9058  | 0  |     }  | 
9059  |  |  | 
9060  |  | #ifndef HAVE_PREADV2  | 
9061  |  |     if(flags != 0) { | 
9062  |  |         argument_unavailable_error("preadv2", "flags"); | 
9063  |  |         return -1;  | 
9064  |  |     }  | 
9065  |  | #endif  | 
9066  |  |  | 
9067  | 0  |     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) { | 
9068  | 0  |         return -1;  | 
9069  | 0  |     }  | 
9070  | 0  | #ifdef HAVE_PREADV2  | 
9071  | 0  |     do { | 
9072  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
9073  | 0  |         _Py_BEGIN_SUPPRESS_IPH  | 
9074  | 0  |         n = preadv2(fd, iov, cnt, offset, flags);  | 
9075  | 0  |         _Py_END_SUPPRESS_IPH  | 
9076  | 0  |         Py_END_ALLOW_THREADS  | 
9077  | 0  |     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
9078  |  | #else  | 
9079  |  |     do { | 
9080  |  |         Py_BEGIN_ALLOW_THREADS  | 
9081  |  |         _Py_BEGIN_SUPPRESS_IPH  | 
9082  |  |         n = preadv(fd, iov, cnt, offset);  | 
9083  |  |         _Py_END_SUPPRESS_IPH  | 
9084  |  |         Py_END_ALLOW_THREADS  | 
9085  |  |     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
9086  |  | #endif  | 
9087  |  | 
  | 
9088  | 0  |     iov_cleanup(iov, buf, cnt);  | 
9089  | 0  |     if (n < 0) { | 
9090  | 0  |         if (!async_err) { | 
9091  | 0  |             posix_error();  | 
9092  | 0  |         }  | 
9093  | 0  |         return -1;  | 
9094  | 0  |     }  | 
9095  |  |  | 
9096  | 0  |     return n;  | 
9097  | 0  | }  | 
9098  |  | #endif /* HAVE_PREADV */  | 
9099  |  |  | 
9100  |  |  | 
9101  |  | /*[clinic input]  | 
9102  |  | os.write -> Py_ssize_t  | 
9103  |  |  | 
9104  |  |     fd: int  | 
9105  |  |     data: Py_buffer  | 
9106  |  |     /  | 
9107  |  |  | 
9108  |  | Write a bytes object to a file descriptor.  | 
9109  |  | [clinic start generated code]*/  | 
9110  |  |  | 
9111  |  | static Py_ssize_t  | 
9112  |  | os_write_impl(PyObject *module, int fd, Py_buffer *data)  | 
9113  |  | /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/  | 
9114  | 0  | { | 
9115  | 0  |     return _Py_write(fd, data->buf, data->len);  | 
9116  | 0  | }  | 
9117  |  |  | 
9118  |  | #ifdef HAVE_SENDFILE  | 
9119  |  | PyDoc_STRVAR(posix_sendfile__doc__,  | 
9120  |  | "sendfile(out, in, offset, count) -> byteswritten\n\  | 
9121  |  | sendfile(out, in, offset, count[, headers][, trailers], flags=0)\n\  | 
9122  |  |             -> byteswritten\n\  | 
9123  |  | Copy count bytes from file descriptor in to file descriptor out.");  | 
9124  |  |  | 
9125  |  | /* AC 3.5: don't bother converting, has optional group*/  | 
9126  |  | static PyObject *  | 
9127  |  | posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)  | 
9128  | 0  | { | 
9129  | 0  |     int in, out;  | 
9130  | 0  |     Py_ssize_t ret;  | 
9131  | 0  |     int async_err = 0;  | 
9132  | 0  |     off_t offset;  | 
9133  |  | 
  | 
9134  |  | #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)  | 
9135  |  | #ifndef __APPLE__  | 
9136  |  |     Py_ssize_t len;  | 
9137  |  | #endif  | 
9138  |  |     PyObject *headers = NULL, *trailers = NULL;  | 
9139  |  |     Py_buffer *hbuf, *tbuf;  | 
9140  |  |     off_t sbytes;  | 
9141  |  |     struct sf_hdtr sf;  | 
9142  |  |     int flags = 0;  | 
9143  |  |     /* Beware that "in" clashes with Python's own "in" operator keyword */  | 
9144  |  |     static char *keywords[] = {"out", "in", | 
9145  |  |                                 "offset", "count",  | 
9146  |  |                                 "headers", "trailers", "flags", NULL};  | 
9147  |  |  | 
9148  |  |     sf.headers = NULL;  | 
9149  |  |     sf.trailers = NULL;  | 
9150  |  |  | 
9151  |  | #ifdef __APPLE__  | 
9152  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile",  | 
9153  |  |         keywords, &out, &in, Py_off_t_converter, &offset, Py_off_t_converter, &sbytes,  | 
9154  |  | #else  | 
9155  |  |     if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile",  | 
9156  |  |         keywords, &out, &in, Py_off_t_converter, &offset, &len,  | 
9157  |  | #endif  | 
9158  |  |                 &headers, &trailers, &flags))  | 
9159  |  |             return NULL;  | 
9160  |  |     if (headers != NULL) { | 
9161  |  |         if (!PySequence_Check(headers)) { | 
9162  |  |             PyErr_SetString(PyExc_TypeError,  | 
9163  |  |                 "sendfile() headers must be a sequence");  | 
9164  |  |             return NULL;  | 
9165  |  |         } else { | 
9166  |  |             Py_ssize_t i = PySequence_Size(headers);  | 
9167  |  |             if (i < 0)  | 
9168  |  |                 return NULL;  | 
9169  |  |             if (i > INT_MAX) { | 
9170  |  |                 PyErr_SetString(PyExc_OverflowError,  | 
9171  |  |                     "sendfile() header is too large");  | 
9172  |  |                 return NULL;  | 
9173  |  |             }  | 
9174  |  |             if (i > 0) { | 
9175  |  |                 sf.hdr_cnt = (int)i;  | 
9176  |  |                 if (iov_setup(&(sf.headers), &hbuf,  | 
9177  |  |                               headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)  | 
9178  |  |                     return NULL;  | 
9179  |  | #ifdef __APPLE__  | 
9180  |  |                 for (i = 0; i < sf.hdr_cnt; i++) { | 
9181  |  |                     Py_ssize_t blen = sf.headers[i].iov_len;  | 
9182  |  | # define OFF_T_MAX 0x7fffffffffffffff  | 
9183  |  |                     if (sbytes >= OFF_T_MAX - blen) { | 
9184  |  |                         PyErr_SetString(PyExc_OverflowError,  | 
9185  |  |                             "sendfile() header is too large");  | 
9186  |  |                         return NULL;  | 
9187  |  |                     }  | 
9188  |  |                     sbytes += blen;  | 
9189  |  |                 }  | 
9190  |  | #endif  | 
9191  |  |             }  | 
9192  |  |         }  | 
9193  |  |     }  | 
9194  |  |     if (trailers != NULL) { | 
9195  |  |         if (!PySequence_Check(trailers)) { | 
9196  |  |             PyErr_SetString(PyExc_TypeError,  | 
9197  |  |                 "sendfile() trailers must be a sequence");  | 
9198  |  |             return NULL;  | 
9199  |  |         } else { | 
9200  |  |             Py_ssize_t i = PySequence_Size(trailers);  | 
9201  |  |             if (i < 0)  | 
9202  |  |                 return NULL;  | 
9203  |  |             if (i > INT_MAX) { | 
9204  |  |                 PyErr_SetString(PyExc_OverflowError,  | 
9205  |  |                     "sendfile() trailer is too large");  | 
9206  |  |                 return NULL;  | 
9207  |  |             }  | 
9208  |  |             if (i > 0) { | 
9209  |  |                 sf.trl_cnt = (int)i;  | 
9210  |  |                 if (iov_setup(&(sf.trailers), &tbuf,  | 
9211  |  |                               trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)  | 
9212  |  |                     return NULL;  | 
9213  |  |             }  | 
9214  |  |         }  | 
9215  |  |     }  | 
9216  |  |  | 
9217  |  |     _Py_BEGIN_SUPPRESS_IPH  | 
9218  |  |     do { | 
9219  |  |         Py_BEGIN_ALLOW_THREADS  | 
9220  |  | #ifdef __APPLE__  | 
9221  |  |         ret = sendfile(in, out, offset, &sbytes, &sf, flags);  | 
9222  |  | #else  | 
9223  |  |         ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);  | 
9224  |  | #endif  | 
9225  |  |         Py_END_ALLOW_THREADS  | 
9226  |  |     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
9227  |  |     _Py_END_SUPPRESS_IPH  | 
9228  |  |  | 
9229  |  |     if (sf.headers != NULL)  | 
9230  |  |         iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);  | 
9231  |  |     if (sf.trailers != NULL)  | 
9232  |  |         iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);  | 
9233  |  |  | 
9234  |  |     if (ret < 0) { | 
9235  |  |         if ((errno == EAGAIN) || (errno == EBUSY)) { | 
9236  |  |             if (sbytes != 0) { | 
9237  |  |                 // some data has been sent  | 
9238  |  |                 goto done;  | 
9239  |  |             }  | 
9240  |  |             else { | 
9241  |  |                 // no data has been sent; upper application is supposed  | 
9242  |  |                 // to retry on EAGAIN or EBUSY  | 
9243  |  |                 return posix_error();  | 
9244  |  |             }  | 
9245  |  |         }  | 
9246  |  |         return (!async_err) ? posix_error() : NULL;  | 
9247  |  |     }  | 
9248  |  |     goto done;  | 
9249  |  |  | 
9250  |  | done:  | 
9251  |  |     #if !defined(HAVE_LARGEFILE_SUPPORT)  | 
9252  |  |         return Py_BuildValue("l", sbytes); | 
9253  |  |     #else  | 
9254  |  |         return Py_BuildValue("L", sbytes); | 
9255  |  |     #endif  | 
9256  |  |  | 
9257  |  | #else  | 
9258  | 0  |     Py_ssize_t count;  | 
9259  | 0  |     PyObject *offobj;  | 
9260  | 0  |     static char *keywords[] = {"out", "in", | 
9261  | 0  |                                 "offset", "count", NULL};  | 
9262  | 0  |     if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",  | 
9263  | 0  |             keywords, &out, &in, &offobj, &count))  | 
9264  | 0  |         return NULL;  | 
9265  | 0  | #ifdef __linux__  | 
9266  | 0  |     if (offobj == Py_None) { | 
9267  | 0  |         do { | 
9268  | 0  |             Py_BEGIN_ALLOW_THREADS  | 
9269  | 0  |             ret = sendfile(out, in, NULL, count);  | 
9270  | 0  |             Py_END_ALLOW_THREADS  | 
9271  | 0  |         } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
9272  | 0  |         if (ret < 0)  | 
9273  | 0  |             return (!async_err) ? posix_error() : NULL;  | 
9274  | 0  |         return Py_BuildValue("n", ret); | 
9275  | 0  |     }  | 
9276  | 0  | #endif  | 
9277  | 0  |     if (!Py_off_t_converter(offobj, &offset))  | 
9278  | 0  |         return NULL;  | 
9279  |  |  | 
9280  | 0  |     do { | 
9281  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
9282  | 0  |         ret = sendfile(out, in, &offset, count);  | 
9283  | 0  |         Py_END_ALLOW_THREADS  | 
9284  | 0  |     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
9285  | 0  |     if (ret < 0)  | 
9286  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
9287  | 0  |     return Py_BuildValue("n", ret); | 
9288  | 0  | #endif  | 
9289  | 0  | }  | 
9290  |  | #endif /* HAVE_SENDFILE */  | 
9291  |  |  | 
9292  |  |  | 
9293  |  | #if defined(__APPLE__)  | 
9294  |  | /*[clinic input]  | 
9295  |  | os._fcopyfile  | 
9296  |  |  | 
9297  |  |     infd: int  | 
9298  |  |     outfd: int  | 
9299  |  |     flags: int  | 
9300  |  |     /  | 
9301  |  |  | 
9302  |  | Efficiently copy content or metadata of 2 regular file descriptors (macOS).  | 
9303  |  | [clinic start generated code]*/  | 
9304  |  |  | 
9305  |  | static PyObject *  | 
9306  |  | os__fcopyfile_impl(PyObject *module, int infd, int outfd, int flags)  | 
9307  |  | /*[clinic end generated code: output=8e8885c721ec38e3 input=69e0770e600cb44f]*/  | 
9308  |  | { | 
9309  |  |     int ret;  | 
9310  |  |  | 
9311  |  |     Py_BEGIN_ALLOW_THREADS  | 
9312  |  |     ret = fcopyfile(infd, outfd, NULL, flags);  | 
9313  |  |     Py_END_ALLOW_THREADS  | 
9314  |  |     if (ret < 0)  | 
9315  |  |         return posix_error();  | 
9316  |  |     Py_RETURN_NONE;  | 
9317  |  | }  | 
9318  |  | #endif  | 
9319  |  |  | 
9320  |  |  | 
9321  |  | /*[clinic input]  | 
9322  |  | os.fstat  | 
9323  |  |  | 
9324  |  |     fd : int  | 
9325  |  |  | 
9326  |  | Perform a stat system call on the given file descriptor.  | 
9327  |  |  | 
9328  |  | Like stat(), but for an open file descriptor.  | 
9329  |  | Equivalent to os.stat(fd).  | 
9330  |  | [clinic start generated code]*/  | 
9331  |  |  | 
9332  |  | static PyObject *  | 
9333  |  | os_fstat_impl(PyObject *module, int fd)  | 
9334  |  | /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/  | 
9335  | 0  | { | 
9336  | 0  |     STRUCT_STAT st;  | 
9337  | 0  |     int res;  | 
9338  | 0  |     int async_err = 0;  | 
9339  |  | 
  | 
9340  | 0  |     do { | 
9341  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
9342  | 0  |         res = FSTAT(fd, &st);  | 
9343  | 0  |         Py_END_ALLOW_THREADS  | 
9344  | 0  |     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
9345  | 0  |     if (res != 0) { | 
9346  |  | #ifdef MS_WINDOWS  | 
9347  |  |         return PyErr_SetFromWindowsErr(0);  | 
9348  |  | #else  | 
9349  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
9350  | 0  | #endif  | 
9351  | 0  |     }  | 
9352  |  |  | 
9353  | 0  |     return _pystat_fromstructstat(&st);  | 
9354  | 0  | }  | 
9355  |  |  | 
9356  |  |  | 
9357  |  | /*[clinic input]  | 
9358  |  | os.isatty -> bool  | 
9359  |  |     fd: int  | 
9360  |  |     /  | 
9361  |  |  | 
9362  |  | Return True if the fd is connected to a terminal.  | 
9363  |  |  | 
9364  |  | Return True if the file descriptor is an open file descriptor  | 
9365  |  | connected to the slave end of a terminal.  | 
9366  |  | [clinic start generated code]*/  | 
9367  |  |  | 
9368  |  | static int  | 
9369  |  | os_isatty_impl(PyObject *module, int fd)  | 
9370  |  | /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/  | 
9371  | 0  | { | 
9372  | 0  |     int return_value;  | 
9373  | 0  |     _Py_BEGIN_SUPPRESS_IPH  | 
9374  | 0  |     return_value = isatty(fd);  | 
9375  | 0  |     _Py_END_SUPPRESS_IPH  | 
9376  | 0  |     return return_value;  | 
9377  | 0  | }  | 
9378  |  |  | 
9379  |  |  | 
9380  |  | #ifdef HAVE_PIPE  | 
9381  |  | /*[clinic input]  | 
9382  |  | os.pipe  | 
9383  |  |  | 
9384  |  | Create a pipe.  | 
9385  |  |  | 
9386  |  | Returns a tuple of two file descriptors:  | 
9387  |  |   (read_fd, write_fd)  | 
9388  |  | [clinic start generated code]*/  | 
9389  |  |  | 
9390  |  | static PyObject *  | 
9391  |  | os_pipe_impl(PyObject *module)  | 
9392  |  | /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/  | 
9393  | 0  | { | 
9394  | 0  |     int fds[2];  | 
9395  |  | #ifdef MS_WINDOWS  | 
9396  |  |     HANDLE read, write;  | 
9397  |  |     SECURITY_ATTRIBUTES attr;  | 
9398  |  |     BOOL ok;  | 
9399  |  | #else  | 
9400  | 0  |     int res;  | 
9401  | 0  | #endif  | 
9402  |  | 
  | 
9403  |  | #ifdef MS_WINDOWS  | 
9404  |  |     attr.nLength = sizeof(attr);  | 
9405  |  |     attr.lpSecurityDescriptor = NULL;  | 
9406  |  |     attr.bInheritHandle = FALSE;  | 
9407  |  |  | 
9408  |  |     Py_BEGIN_ALLOW_THREADS  | 
9409  |  |     _Py_BEGIN_SUPPRESS_IPH  | 
9410  |  |     ok = CreatePipe(&read, &write, &attr, 0);  | 
9411  |  |     if (ok) { | 
9412  |  |         fds[0] = _open_osfhandle((intptr_t)read, _O_RDONLY);  | 
9413  |  |         fds[1] = _open_osfhandle((intptr_t)write, _O_WRONLY);  | 
9414  |  |         if (fds[0] == -1 || fds[1] == -1) { | 
9415  |  |             CloseHandle(read);  | 
9416  |  |             CloseHandle(write);  | 
9417  |  |             ok = 0;  | 
9418  |  |         }  | 
9419  |  |     }  | 
9420  |  |     _Py_END_SUPPRESS_IPH  | 
9421  |  |     Py_END_ALLOW_THREADS  | 
9422  |  |  | 
9423  |  |     if (!ok)  | 
9424  |  |         return PyErr_SetFromWindowsErr(0);  | 
9425  |  | #else  | 
9426  |  | 
  | 
9427  | 0  | #ifdef HAVE_PIPE2  | 
9428  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
9429  | 0  |     res = pipe2(fds, O_CLOEXEC);  | 
9430  | 0  |     Py_END_ALLOW_THREADS  | 
9431  |  | 
  | 
9432  | 0  |     if (res != 0 && errno == ENOSYS)  | 
9433  | 0  |     { | 
9434  | 0  | #endif  | 
9435  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
9436  | 0  |         res = pipe(fds);  | 
9437  | 0  |         Py_END_ALLOW_THREADS  | 
9438  |  | 
  | 
9439  | 0  |         if (res == 0) { | 
9440  | 0  |             if (_Py_set_inheritable(fds[0], 0, NULL) < 0) { | 
9441  | 0  |                 close(fds[0]);  | 
9442  | 0  |                 close(fds[1]);  | 
9443  | 0  |                 return NULL;  | 
9444  | 0  |             }  | 
9445  | 0  |             if (_Py_set_inheritable(fds[1], 0, NULL) < 0) { | 
9446  | 0  |                 close(fds[0]);  | 
9447  | 0  |                 close(fds[1]);  | 
9448  | 0  |                 return NULL;  | 
9449  | 0  |             }  | 
9450  | 0  |         }  | 
9451  | 0  | #ifdef HAVE_PIPE2  | 
9452  | 0  |     }  | 
9453  | 0  | #endif  | 
9454  |  |  | 
9455  | 0  |     if (res != 0)  | 
9456  | 0  |         return PyErr_SetFromErrno(PyExc_OSError);  | 
9457  | 0  | #endif /* !MS_WINDOWS */  | 
9458  | 0  |     return Py_BuildValue("(ii)", fds[0], fds[1]); | 
9459  | 0  | }  | 
9460  |  | #endif  /* HAVE_PIPE */  | 
9461  |  |  | 
9462  |  |  | 
9463  |  | #ifdef HAVE_PIPE2  | 
9464  |  | /*[clinic input]  | 
9465  |  | os.pipe2  | 
9466  |  |  | 
9467  |  |     flags: int  | 
9468  |  |     /  | 
9469  |  |  | 
9470  |  | Create a pipe with flags set atomically.  | 
9471  |  |  | 
9472  |  | Returns a tuple of two file descriptors:  | 
9473  |  |   (read_fd, write_fd)  | 
9474  |  |  | 
9475  |  | flags can be constructed by ORing together one or more of these values:  | 
9476  |  | O_NONBLOCK, O_CLOEXEC.  | 
9477  |  | [clinic start generated code]*/  | 
9478  |  |  | 
9479  |  | static PyObject *  | 
9480  |  | os_pipe2_impl(PyObject *module, int flags)  | 
9481  |  | /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/  | 
9482  | 0  | { | 
9483  | 0  |     int fds[2];  | 
9484  | 0  |     int res;  | 
9485  |  | 
  | 
9486  | 0  |     res = pipe2(fds, flags);  | 
9487  | 0  |     if (res != 0)  | 
9488  | 0  |         return posix_error();  | 
9489  | 0  |     return Py_BuildValue("(ii)", fds[0], fds[1]); | 
9490  | 0  | }  | 
9491  |  | #endif /* HAVE_PIPE2 */  | 
9492  |  |  | 
9493  |  |  | 
9494  |  | #ifdef HAVE_WRITEV  | 
9495  |  | /*[clinic input]  | 
9496  |  | os.writev -> Py_ssize_t  | 
9497  |  |     fd: int  | 
9498  |  |     buffers: object  | 
9499  |  |     /  | 
9500  |  |  | 
9501  |  | Iterate over buffers, and write the contents of each to a file descriptor.  | 
9502  |  |  | 
9503  |  | Returns the total number of bytes written.  | 
9504  |  | buffers must be a sequence of bytes-like objects.  | 
9505  |  | [clinic start generated code]*/  | 
9506  |  |  | 
9507  |  | static Py_ssize_t  | 
9508  |  | os_writev_impl(PyObject *module, int fd, PyObject *buffers)  | 
9509  |  | /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/  | 
9510  | 0  | { | 
9511  | 0  |     Py_ssize_t cnt;  | 
9512  | 0  |     Py_ssize_t result;  | 
9513  | 0  |     int async_err = 0;  | 
9514  | 0  |     struct iovec *iov;  | 
9515  | 0  |     Py_buffer *buf;  | 
9516  |  | 
  | 
9517  | 0  |     if (!PySequence_Check(buffers)) { | 
9518  | 0  |         PyErr_SetString(PyExc_TypeError,  | 
9519  | 0  |             "writev() arg 2 must be a sequence");  | 
9520  | 0  |         return -1;  | 
9521  | 0  |     }  | 
9522  | 0  |     cnt = PySequence_Size(buffers);  | 
9523  | 0  |     if (cnt < 0)  | 
9524  | 0  |         return -1;  | 
9525  |  |  | 
9526  | 0  |     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { | 
9527  | 0  |         return -1;  | 
9528  | 0  |     }  | 
9529  |  |  | 
9530  | 0  |     do { | 
9531  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
9532  | 0  |         result = writev(fd, iov, cnt);  | 
9533  | 0  |         Py_END_ALLOW_THREADS  | 
9534  | 0  |     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
9535  |  | 
  | 
9536  | 0  |     iov_cleanup(iov, buf, cnt);  | 
9537  | 0  |     if (result < 0 && !async_err)  | 
9538  | 0  |         posix_error();  | 
9539  |  | 
  | 
9540  | 0  |     return result;  | 
9541  | 0  | }  | 
9542  |  | #endif /* HAVE_WRITEV */  | 
9543  |  |  | 
9544  |  |  | 
9545  |  | #ifdef HAVE_PWRITE  | 
9546  |  | /*[clinic input]  | 
9547  |  | os.pwrite -> Py_ssize_t  | 
9548  |  |  | 
9549  |  |     fd: int  | 
9550  |  |     buffer: Py_buffer  | 
9551  |  |     offset: Py_off_t  | 
9552  |  |     /  | 
9553  |  |  | 
9554  |  | Write bytes to a file descriptor starting at a particular offset.  | 
9555  |  |  | 
9556  |  | Write buffer to fd, starting at offset bytes from the beginning of  | 
9557  |  | the file.  Returns the number of bytes writte.  Does not change the  | 
9558  |  | current file offset.  | 
9559  |  | [clinic start generated code]*/  | 
9560  |  |  | 
9561  |  | static Py_ssize_t  | 
9562  |  | os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)  | 
9563  |  | /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/  | 
9564  | 0  | { | 
9565  | 0  |     Py_ssize_t size;  | 
9566  | 0  |     int async_err = 0;  | 
9567  |  | 
  | 
9568  | 0  |     do { | 
9569  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
9570  | 0  |         _Py_BEGIN_SUPPRESS_IPH  | 
9571  | 0  |         size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);  | 
9572  | 0  |         _Py_END_SUPPRESS_IPH  | 
9573  | 0  |         Py_END_ALLOW_THREADS  | 
9574  | 0  |     } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
9575  |  | 
  | 
9576  | 0  |     if (size < 0 && !async_err)  | 
9577  | 0  |         posix_error();  | 
9578  | 0  |     return size;  | 
9579  | 0  | }  | 
9580  |  | #endif /* HAVE_PWRITE */  | 
9581  |  |  | 
9582  |  | #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)  | 
9583  |  | /*[clinic input]  | 
9584  |  | os.pwritev -> Py_ssize_t  | 
9585  |  |  | 
9586  |  |     fd: int  | 
9587  |  |     buffers: object  | 
9588  |  |     offset: Py_off_t  | 
9589  |  |     flags: int = 0  | 
9590  |  |     /  | 
9591  |  |  | 
9592  |  | Writes the contents of bytes-like objects to a file descriptor at a given offset.  | 
9593  |  |  | 
9594  |  | Combines the functionality of writev() and pwrite(). All buffers must be a sequence  | 
9595  |  | of bytes-like objects. Buffers are processed in array order. Entire contents of first  | 
9596  |  | buffer is written before proceeding to second, and so on. The operating system may  | 
9597  |  | set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.  | 
9598  |  | This function writes the contents of each object to the file descriptor and returns  | 
9599  |  | the total number of bytes written.  | 
9600  |  |  | 
9601  |  | The flags argument contains a bitwise OR of zero or more of the following flags:  | 
9602  |  |  | 
9603  |  | - RWF_DSYNC  | 
9604  |  | - RWF_SYNC  | 
9605  |  |  | 
9606  |  | Using non-zero flags requires Linux 4.7 or newer.  | 
9607  |  | [clinic start generated code]*/  | 
9608  |  |  | 
9609  |  | static Py_ssize_t  | 
9610  |  | os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,  | 
9611  |  |                 int flags)  | 
9612  |  | /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=803dc5ddbf0cfd3b]*/  | 
9613  | 0  | { | 
9614  | 0  |     Py_ssize_t cnt;  | 
9615  | 0  |     Py_ssize_t result;  | 
9616  | 0  |     int async_err = 0;  | 
9617  | 0  |     struct iovec *iov;  | 
9618  | 0  |     Py_buffer *buf;  | 
9619  |  | 
  | 
9620  | 0  |     if (!PySequence_Check(buffers)) { | 
9621  | 0  |         PyErr_SetString(PyExc_TypeError,  | 
9622  | 0  |             "pwritev() arg 2 must be a sequence");  | 
9623  | 0  |         return -1;  | 
9624  | 0  |     }  | 
9625  |  |  | 
9626  | 0  |     cnt = PySequence_Size(buffers);  | 
9627  | 0  |     if (cnt < 0) { | 
9628  | 0  |         return -1;  | 
9629  | 0  |     }  | 
9630  |  |  | 
9631  |  | #ifndef HAVE_PWRITEV2  | 
9632  |  |     if(flags != 0) { | 
9633  |  |         argument_unavailable_error("pwritev2", "flags"); | 
9634  |  |         return -1;  | 
9635  |  |     }  | 
9636  |  | #endif  | 
9637  |  |  | 
9638  | 0  |     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { | 
9639  | 0  |         return -1;  | 
9640  | 0  |     }  | 
9641  | 0  | #ifdef HAVE_PWRITEV2  | 
9642  | 0  |     do { | 
9643  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
9644  | 0  |         _Py_BEGIN_SUPPRESS_IPH  | 
9645  | 0  |         result = pwritev2(fd, iov, cnt, offset, flags);  | 
9646  | 0  |         _Py_END_SUPPRESS_IPH  | 
9647  | 0  |         Py_END_ALLOW_THREADS  | 
9648  | 0  |     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
9649  |  | #else  | 
9650  |  |     do { | 
9651  |  |         Py_BEGIN_ALLOW_THREADS  | 
9652  |  |         _Py_BEGIN_SUPPRESS_IPH  | 
9653  |  |         result = pwritev(fd, iov, cnt, offset);  | 
9654  |  |         _Py_END_SUPPRESS_IPH  | 
9655  |  |         Py_END_ALLOW_THREADS  | 
9656  |  |     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
9657  |  | #endif  | 
9658  |  | 
  | 
9659  | 0  |     iov_cleanup(iov, buf, cnt);  | 
9660  | 0  |     if (result < 0) { | 
9661  | 0  |         if (!async_err) { | 
9662  | 0  |             posix_error();  | 
9663  | 0  |         }  | 
9664  | 0  |         return -1;  | 
9665  | 0  |     }  | 
9666  |  |  | 
9667  | 0  |     return result;  | 
9668  | 0  | }  | 
9669  |  | #endif /* HAVE_PWRITEV */  | 
9670  |  |  | 
9671  |  | #ifdef HAVE_COPY_FILE_RANGE  | 
9672  |  | /*[clinic input]  | 
9673  |  |  | 
9674  |  | os.copy_file_range  | 
9675  |  |     src: int  | 
9676  |  |         Source file descriptor.  | 
9677  |  |     dst: int  | 
9678  |  |         Destination file descriptor.  | 
9679  |  |     count: Py_ssize_t  | 
9680  |  |         Number of bytes to copy.  | 
9681  |  |     offset_src: object = None  | 
9682  |  |         Starting offset in src.  | 
9683  |  |     offset_dst: object = None  | 
9684  |  |         Starting offset in dst.  | 
9685  |  |  | 
9686  |  | Copy count bytes from one file descriptor to another.  | 
9687  |  |  | 
9688  |  | If offset_src is None, then src is read from the current position;  | 
9689  |  | respectively for offset_dst.  | 
9690  |  | [clinic start generated code]*/  | 
9691  |  |  | 
9692  |  | static PyObject *  | 
9693  |  | os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,  | 
9694  |  |                         PyObject *offset_src, PyObject *offset_dst)  | 
9695  |  | /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/  | 
9696  | 0  | { | 
9697  | 0  |     off_t offset_src_val, offset_dst_val;  | 
9698  | 0  |     off_t *p_offset_src = NULL;  | 
9699  | 0  |     off_t *p_offset_dst = NULL;  | 
9700  | 0  |     Py_ssize_t ret;  | 
9701  | 0  |     int async_err = 0;  | 
9702  |  |     /* The flags argument is provided to allow  | 
9703  |  |      * for future extensions and currently must be to 0. */  | 
9704  | 0  |     int flags = 0;  | 
9705  |  |  | 
9706  |  | 
  | 
9707  | 0  |     if (count < 0) { | 
9708  | 0  |         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");  | 
9709  | 0  |         return NULL;  | 
9710  | 0  |     }  | 
9711  |  |  | 
9712  | 0  |     if (offset_src != Py_None) { | 
9713  | 0  |         if (!Py_off_t_converter(offset_src, &offset_src_val)) { | 
9714  | 0  |             return NULL;  | 
9715  | 0  |         }  | 
9716  | 0  |         p_offset_src = &offset_src_val;  | 
9717  | 0  |     }  | 
9718  |  |  | 
9719  | 0  |     if (offset_dst != Py_None) { | 
9720  | 0  |         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) { | 
9721  | 0  |             return NULL;  | 
9722  | 0  |         }  | 
9723  | 0  |         p_offset_dst = &offset_dst_val;  | 
9724  | 0  |     }  | 
9725  |  |  | 
9726  | 0  |     do { | 
9727  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
9728  | 0  |         ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);  | 
9729  | 0  |         Py_END_ALLOW_THREADS  | 
9730  | 0  |     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));  | 
9731  |  | 
  | 
9732  | 0  |     if (ret < 0) { | 
9733  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
9734  | 0  |     }  | 
9735  |  |  | 
9736  | 0  |     return PyLong_FromSsize_t(ret);  | 
9737  | 0  | }  | 
9738  |  | #endif /* HAVE_COPY_FILE_RANGE*/  | 
9739  |  |  | 
9740  |  | #ifdef HAVE_MKFIFO  | 
9741  |  | /*[clinic input]  | 
9742  |  | os.mkfifo  | 
9743  |  |  | 
9744  |  |     path: path_t  | 
9745  |  |     mode: int=0o666  | 
9746  |  |     *  | 
9747  |  |     dir_fd: dir_fd(requires='mkfifoat')=None  | 
9748  |  |  | 
9749  |  | Create a "fifo" (a POSIX named pipe).  | 
9750  |  |  | 
9751  |  | If dir_fd is not None, it should be a file descriptor open to a directory,  | 
9752  |  |   and path should be relative; path will then be relative to that directory.  | 
9753  |  | dir_fd may not be implemented on your platform.  | 
9754  |  |   If it is unavailable, using it will raise a NotImplementedError.  | 
9755  |  | [clinic start generated code]*/  | 
9756  |  |  | 
9757  |  | static PyObject *  | 
9758  |  | os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)  | 
9759  |  | /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/  | 
9760  | 0  | { | 
9761  | 0  |     int result;  | 
9762  | 0  |     int async_err = 0;  | 
9763  |  | 
  | 
9764  | 0  |     do { | 
9765  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
9766  | 0  | #ifdef HAVE_MKFIFOAT  | 
9767  | 0  |         if (dir_fd != DEFAULT_DIR_FD)  | 
9768  | 0  |             result = mkfifoat(dir_fd, path->narrow, mode);  | 
9769  | 0  |         else  | 
9770  | 0  | #endif  | 
9771  | 0  |             result = mkfifo(path->narrow, mode);  | 
9772  | 0  |         Py_END_ALLOW_THREADS  | 
9773  | 0  |     } while (result != 0 && errno == EINTR &&  | 
9774  | 0  |              !(async_err = PyErr_CheckSignals()));  | 
9775  | 0  |     if (result != 0)  | 
9776  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
9777  |  |  | 
9778  | 0  |     Py_RETURN_NONE;  | 
9779  | 0  | }  | 
9780  |  | #endif /* HAVE_MKFIFO */  | 
9781  |  |  | 
9782  |  |  | 
9783  |  | #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)  | 
9784  |  | /*[clinic input]  | 
9785  |  | os.mknod  | 
9786  |  |  | 
9787  |  |     path: path_t  | 
9788  |  |     mode: int=0o600  | 
9789  |  |     device: dev_t=0  | 
9790  |  |     *  | 
9791  |  |     dir_fd: dir_fd(requires='mknodat')=None  | 
9792  |  |  | 
9793  |  | Create a node in the file system.  | 
9794  |  |  | 
9795  |  | Create a node in the file system (file, device special file or named pipe)  | 
9796  |  | at path.  mode specifies both the permissions to use and the  | 
9797  |  | type of node to be created, being combined (bitwise OR) with one of  | 
9798  |  | S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,  | 
9799  |  | device defines the newly created device special file (probably using  | 
9800  |  | os.makedev()).  Otherwise device is ignored.  | 
9801  |  |  | 
9802  |  | If dir_fd is not None, it should be a file descriptor open to a directory,  | 
9803  |  |   and path should be relative; path will then be relative to that directory.  | 
9804  |  | dir_fd may not be implemented on your platform.  | 
9805  |  |   If it is unavailable, using it will raise a NotImplementedError.  | 
9806  |  | [clinic start generated code]*/  | 
9807  |  |  | 
9808  |  | static PyObject *  | 
9809  |  | os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,  | 
9810  |  |               int dir_fd)  | 
9811  |  | /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/  | 
9812  | 0  | { | 
9813  | 0  |     int result;  | 
9814  | 0  |     int async_err = 0;  | 
9815  |  | 
  | 
9816  | 0  |     do { | 
9817  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
9818  | 0  | #ifdef HAVE_MKNODAT  | 
9819  | 0  |         if (dir_fd != DEFAULT_DIR_FD)  | 
9820  | 0  |             result = mknodat(dir_fd, path->narrow, mode, device);  | 
9821  | 0  |         else  | 
9822  | 0  | #endif  | 
9823  | 0  |             result = mknod(path->narrow, mode, device);  | 
9824  | 0  |         Py_END_ALLOW_THREADS  | 
9825  | 0  |     } while (result != 0 && errno == EINTR &&  | 
9826  | 0  |              !(async_err = PyErr_CheckSignals()));  | 
9827  | 0  |     if (result != 0)  | 
9828  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
9829  |  |  | 
9830  | 0  |     Py_RETURN_NONE;  | 
9831  | 0  | }  | 
9832  |  | #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */  | 
9833  |  |  | 
9834  |  |  | 
9835  |  | #ifdef HAVE_DEVICE_MACROS  | 
9836  |  | /*[clinic input]  | 
9837  |  | os.major -> unsigned_int  | 
9838  |  |  | 
9839  |  |     device: dev_t  | 
9840  |  |     /  | 
9841  |  |  | 
9842  |  | Extracts a device major number from a raw device number.  | 
9843  |  | [clinic start generated code]*/  | 
9844  |  |  | 
9845  |  | static unsigned int  | 
9846  |  | os_major_impl(PyObject *module, dev_t device)  | 
9847  |  | /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/  | 
9848  | 0  | { | 
9849  | 0  |     return major(device);  | 
9850  | 0  | }  | 
9851  |  |  | 
9852  |  |  | 
9853  |  | /*[clinic input]  | 
9854  |  | os.minor -> unsigned_int  | 
9855  |  |  | 
9856  |  |     device: dev_t  | 
9857  |  |     /  | 
9858  |  |  | 
9859  |  | Extracts a device minor number from a raw device number.  | 
9860  |  | [clinic start generated code]*/  | 
9861  |  |  | 
9862  |  | static unsigned int  | 
9863  |  | os_minor_impl(PyObject *module, dev_t device)  | 
9864  |  | /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/  | 
9865  | 0  | { | 
9866  | 0  |     return minor(device);  | 
9867  | 0  | }  | 
9868  |  |  | 
9869  |  |  | 
9870  |  | /*[clinic input]  | 
9871  |  | os.makedev -> dev_t  | 
9872  |  |  | 
9873  |  |     major: int  | 
9874  |  |     minor: int  | 
9875  |  |     /  | 
9876  |  |  | 
9877  |  | Composes a raw device number from the major and minor device numbers.  | 
9878  |  | [clinic start generated code]*/  | 
9879  |  |  | 
9880  |  | static dev_t  | 
9881  |  | os_makedev_impl(PyObject *module, int major, int minor)  | 
9882  |  | /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/  | 
9883  | 0  | { | 
9884  | 0  |     return makedev(major, minor);  | 
9885  | 0  | }  | 
9886  |  | #endif /* HAVE_DEVICE_MACROS */  | 
9887  |  |  | 
9888  |  |  | 
9889  |  | #if defined HAVE_FTRUNCATE || defined MS_WINDOWS  | 
9890  |  | /*[clinic input]  | 
9891  |  | os.ftruncate  | 
9892  |  |  | 
9893  |  |     fd: int  | 
9894  |  |     length: Py_off_t  | 
9895  |  |     /  | 
9896  |  |  | 
9897  |  | Truncate a file, specified by file descriptor, to a specific length.  | 
9898  |  | [clinic start generated code]*/  | 
9899  |  |  | 
9900  |  | static PyObject *  | 
9901  |  | os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)  | 
9902  |  | /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/  | 
9903  | 0  | { | 
9904  | 0  |     int result;  | 
9905  | 0  |     int async_err = 0;  | 
9906  |  | 
  | 
9907  | 0  |     if (PySys_Audit("os.truncate", "in", fd, length) < 0) { | 
9908  | 0  |         return NULL;  | 
9909  | 0  |     }  | 
9910  |  |  | 
9911  | 0  |     do { | 
9912  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
9913  | 0  |         _Py_BEGIN_SUPPRESS_IPH  | 
9914  |  | #ifdef MS_WINDOWS  | 
9915  |  |         result = _chsize_s(fd, length);  | 
9916  |  | #else  | 
9917  | 0  |         result = ftruncate(fd, length);  | 
9918  | 0  | #endif  | 
9919  | 0  |         _Py_END_SUPPRESS_IPH  | 
9920  | 0  |         Py_END_ALLOW_THREADS  | 
9921  | 0  |     } while (result != 0 && errno == EINTR &&  | 
9922  | 0  |              !(async_err = PyErr_CheckSignals()));  | 
9923  | 0  |     if (result != 0)  | 
9924  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
9925  | 0  |     Py_RETURN_NONE;  | 
9926  | 0  | }  | 
9927  |  | #endif /* HAVE_FTRUNCATE || MS_WINDOWS */  | 
9928  |  |  | 
9929  |  |  | 
9930  |  | #if defined HAVE_TRUNCATE || defined MS_WINDOWS  | 
9931  |  | /*[clinic input]  | 
9932  |  | os.truncate  | 
9933  |  |     path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')  | 
9934  |  |     length: Py_off_t  | 
9935  |  |  | 
9936  |  | Truncate a file, specified by path, to a specific length.  | 
9937  |  |  | 
9938  |  | On some platforms, path may also be specified as an open file descriptor.  | 
9939  |  |   If this functionality is unavailable, using it raises an exception.  | 
9940  |  | [clinic start generated code]*/  | 
9941  |  |  | 
9942  |  | static PyObject *  | 
9943  |  | os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)  | 
9944  |  | /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/  | 
9945  | 0  | { | 
9946  | 0  |     int result;  | 
9947  |  | #ifdef MS_WINDOWS  | 
9948  |  |     int fd;  | 
9949  |  | #endif  | 
9950  |  | 
  | 
9951  | 0  |     if (path->fd != -1)  | 
9952  | 0  |         return os_ftruncate_impl(module, path->fd, length);  | 
9953  |  |  | 
9954  | 0  |     if (PySys_Audit("os.truncate", "On", path->object, length) < 0) { | 
9955  | 0  |         return NULL;  | 
9956  | 0  |     }  | 
9957  |  |  | 
9958  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
9959  | 0  |     _Py_BEGIN_SUPPRESS_IPH  | 
9960  |  | #ifdef MS_WINDOWS  | 
9961  |  |     fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);  | 
9962  |  |     if (fd < 0)  | 
9963  |  |         result = -1;  | 
9964  |  |     else { | 
9965  |  |         result = _chsize_s(fd, length);  | 
9966  |  |         close(fd);  | 
9967  |  |         if (result < 0)  | 
9968  |  |             errno = result;  | 
9969  |  |     }  | 
9970  |  | #else  | 
9971  | 0  |     result = truncate(path->narrow, length);  | 
9972  | 0  | #endif  | 
9973  | 0  |     _Py_END_SUPPRESS_IPH  | 
9974  | 0  |     Py_END_ALLOW_THREADS  | 
9975  | 0  |     if (result < 0)  | 
9976  | 0  |         return posix_path_error(path);  | 
9977  |  |  | 
9978  | 0  |     Py_RETURN_NONE;  | 
9979  | 0  | }  | 
9980  |  | #endif /* HAVE_TRUNCATE || MS_WINDOWS */  | 
9981  |  |  | 
9982  |  |  | 
9983  |  | /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()  | 
9984  |  |    and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is  | 
9985  |  |    defined, which is the case in Python on AIX. AIX bug report:  | 
9986  |  |    http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */  | 
9987  |  | #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)  | 
9988  |  | #  define POSIX_FADVISE_AIX_BUG  | 
9989  |  | #endif  | 
9990  |  |  | 
9991  |  |  | 
9992  |  | #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)  | 
9993  |  | /*[clinic input]  | 
9994  |  | os.posix_fallocate  | 
9995  |  |  | 
9996  |  |     fd: int  | 
9997  |  |     offset: Py_off_t  | 
9998  |  |     length: Py_off_t  | 
9999  |  |     /  | 
10000  |  |  | 
10001  |  | Ensure a file has allocated at least a particular number of bytes on disk.  | 
10002  |  |  | 
10003  |  | Ensure that the file specified by fd encompasses a range of bytes  | 
10004  |  | starting at offset bytes from the beginning and continuing for length bytes.  | 
10005  |  | [clinic start generated code]*/  | 
10006  |  |  | 
10007  |  | static PyObject *  | 
10008  |  | os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,  | 
10009  |  |                         Py_off_t length)  | 
10010  |  | /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/  | 
10011  | 0  | { | 
10012  | 0  |     int result;  | 
10013  | 0  |     int async_err = 0;  | 
10014  |  | 
  | 
10015  | 0  |     do { | 
10016  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
10017  | 0  |         result = posix_fallocate(fd, offset, length);  | 
10018  | 0  |         Py_END_ALLOW_THREADS  | 
10019  | 0  |     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));  | 
10020  |  | 
  | 
10021  | 0  |     if (result == 0)  | 
10022  | 0  |         Py_RETURN_NONE;  | 
10023  |  |  | 
10024  | 0  |     if (async_err)  | 
10025  | 0  |         return NULL;  | 
10026  |  |  | 
10027  | 0  |     errno = result;  | 
10028  | 0  |     return posix_error();  | 
10029  | 0  | }  | 
10030  |  | #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */  | 
10031  |  |  | 
10032  |  |  | 
10033  |  | #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)  | 
10034  |  | /*[clinic input]  | 
10035  |  | os.posix_fadvise  | 
10036  |  |  | 
10037  |  |     fd: int  | 
10038  |  |     offset: Py_off_t  | 
10039  |  |     length: Py_off_t  | 
10040  |  |     advice: int  | 
10041  |  |     /  | 
10042  |  |  | 
10043  |  | Announce an intention to access data in a specific pattern.  | 
10044  |  |  | 
10045  |  | Announce an intention to access data in a specific pattern, thus allowing  | 
10046  |  | the kernel to make optimizations.  | 
10047  |  | The advice applies to the region of the file specified by fd starting at  | 
10048  |  | offset and continuing for length bytes.  | 
10049  |  | advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,  | 
10050  |  | POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or  | 
10051  |  | POSIX_FADV_DONTNEED.  | 
10052  |  | [clinic start generated code]*/  | 
10053  |  |  | 
10054  |  | static PyObject *  | 
10055  |  | os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,  | 
10056  |  |                       Py_off_t length, int advice)  | 
10057  |  | /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/  | 
10058  | 0  | { | 
10059  | 0  |     int result;  | 
10060  | 0  |     int async_err = 0;  | 
10061  |  | 
  | 
10062  | 0  |     do { | 
10063  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
10064  | 0  |         result = posix_fadvise(fd, offset, length, advice);  | 
10065  | 0  |         Py_END_ALLOW_THREADS  | 
10066  | 0  |     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));  | 
10067  |  | 
  | 
10068  | 0  |     if (result == 0)  | 
10069  | 0  |         Py_RETURN_NONE;  | 
10070  |  |  | 
10071  | 0  |     if (async_err)  | 
10072  | 0  |         return NULL;  | 
10073  |  |  | 
10074  | 0  |     errno = result;  | 
10075  | 0  |     return posix_error();  | 
10076  | 0  | }  | 
10077  |  | #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */  | 
10078  |  |  | 
10079  |  | #ifdef HAVE_PUTENV  | 
10080  |  |  | 
10081  |  | /* Save putenv() parameters as values here, so we can collect them when they  | 
10082  |  |  * get re-set with another call for the same key. */  | 
10083  |  | static PyObject *posix_putenv_garbage;  | 
10084  |  |  | 
10085  |  | static void  | 
10086  |  | posix_putenv_garbage_setitem(PyObject *name, PyObject *value)  | 
10087  | 0  | { | 
10088  |  |     /* Install the first arg and newstr in posix_putenv_garbage;  | 
10089  |  |      * this will cause previous value to be collected.  This has to  | 
10090  |  |      * happen after the real putenv() call because the old value  | 
10091  |  |      * was still accessible until then. */  | 
10092  | 0  |     if (PyDict_SetItem(posix_putenv_garbage, name, value))  | 
10093  |  |         /* really not much we can do; just leak */  | 
10094  | 0  |         PyErr_Clear();  | 
10095  | 0  |     else  | 
10096  | 0  |         Py_DECREF(value);  | 
10097  | 0  | }  | 
10098  |  |  | 
10099  |  |  | 
10100  |  | #ifdef MS_WINDOWS  | 
10101  |  | /*[clinic input]  | 
10102  |  | os.putenv  | 
10103  |  |  | 
10104  |  |     name: unicode  | 
10105  |  |     value: unicode  | 
10106  |  |     /  | 
10107  |  |  | 
10108  |  | Change or add an environment variable.  | 
10109  |  | [clinic start generated code]*/  | 
10110  |  |  | 
10111  |  | static PyObject *  | 
10112  |  | os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)  | 
10113  |  | /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/  | 
10114  |  | { | 
10115  |  |     const wchar_t *env;  | 
10116  |  |     Py_ssize_t size;  | 
10117  |  |  | 
10118  |  |     /* Search from index 1 because on Windows starting '=' is allowed for  | 
10119  |  |        defining hidden environment variables. */  | 
10120  |  |     if (PyUnicode_GET_LENGTH(name) == 0 ||  | 
10121  |  |         PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)  | 
10122  |  |     { | 
10123  |  |         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");  | 
10124  |  |         return NULL;  | 
10125  |  |     }  | 
10126  |  |     PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value); | 
10127  |  |     if (unicode == NULL) { | 
10128  |  |         return NULL;  | 
10129  |  |     }  | 
10130  |  |  | 
10131  |  |     env = PyUnicode_AsUnicodeAndSize(unicode, &size);  | 
10132  |  |     if (env == NULL)  | 
10133  |  |         goto error;  | 
10134  |  |     if (size > _MAX_ENV) { | 
10135  |  |         PyErr_Format(PyExc_ValueError,  | 
10136  |  |                      "the environment variable is longer than %u characters",  | 
10137  |  |                      _MAX_ENV);  | 
10138  |  |         goto error;  | 
10139  |  |     }  | 
10140  |  |     if (wcslen(env) != (size_t)size) { | 
10141  |  |         PyErr_SetString(PyExc_ValueError, "embedded null character");  | 
10142  |  |         goto error;  | 
10143  |  |     }  | 
10144  |  |  | 
10145  |  |     if (_wputenv(env)) { | 
10146  |  |         posix_error();  | 
10147  |  |         goto error;  | 
10148  |  |     }  | 
10149  |  |  | 
10150  |  |     posix_putenv_garbage_setitem(name, unicode);  | 
10151  |  |     Py_RETURN_NONE;  | 
10152  |  |  | 
10153  |  | error:  | 
10154  |  |     Py_DECREF(unicode);  | 
10155  |  |     return NULL;  | 
10156  |  | }  | 
10157  |  | #else /* MS_WINDOWS */  | 
10158  |  | /*[clinic input]  | 
10159  |  | os.putenv  | 
10160  |  |  | 
10161  |  |     name: FSConverter  | 
10162  |  |     value: FSConverter  | 
10163  |  |     /  | 
10164  |  |  | 
10165  |  | Change or add an environment variable.  | 
10166  |  | [clinic start generated code]*/  | 
10167  |  |  | 
10168  |  | static PyObject *  | 
10169  |  | os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)  | 
10170  |  | /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/  | 
10171  | 0  | { | 
10172  | 0  |     PyObject *bytes = NULL;  | 
10173  | 0  |     char *env;  | 
10174  | 0  |     const char *name_string = PyBytes_AS_STRING(name);  | 
10175  | 0  |     const char *value_string = PyBytes_AS_STRING(value);  | 
10176  |  | 
  | 
10177  | 0  |     if (strchr(name_string, '=') != NULL) { | 
10178  | 0  |         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");  | 
10179  | 0  |         return NULL;  | 
10180  | 0  |     }  | 
10181  | 0  |     if (PySys_Audit("os.putenv", "OO", name, value) < 0) { | 
10182  | 0  |         return NULL;  | 
10183  | 0  |     }  | 
10184  | 0  |     bytes = PyBytes_FromFormat("%s=%s", name_string, value_string); | 
10185  | 0  |     if (bytes == NULL) { | 
10186  | 0  |         return NULL;  | 
10187  | 0  |     }  | 
10188  |  |  | 
10189  | 0  |     env = PyBytes_AS_STRING(bytes);  | 
10190  | 0  |     if (putenv(env)) { | 
10191  | 0  |         Py_DECREF(bytes);  | 
10192  | 0  |         return posix_error();  | 
10193  | 0  |     }  | 
10194  |  |  | 
10195  | 0  |     posix_putenv_garbage_setitem(name, bytes);  | 
10196  | 0  |     Py_RETURN_NONE;  | 
10197  | 0  | }  | 
10198  |  | #endif /* MS_WINDOWS */  | 
10199  |  | #endif /* HAVE_PUTENV */  | 
10200  |  |  | 
10201  |  |  | 
10202  |  | #ifdef HAVE_UNSETENV  | 
10203  |  | /*[clinic input]  | 
10204  |  | os.unsetenv  | 
10205  |  |     name: FSConverter  | 
10206  |  |     /  | 
10207  |  |  | 
10208  |  | Delete an environment variable.  | 
10209  |  | [clinic start generated code]*/  | 
10210  |  |  | 
10211  |  | static PyObject *  | 
10212  |  | os_unsetenv_impl(PyObject *module, PyObject *name)  | 
10213  |  | /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/  | 
10214  | 0  | { | 
10215  | 0  | #ifndef HAVE_BROKEN_UNSETENV  | 
10216  | 0  |     int err;  | 
10217  | 0  | #endif  | 
10218  |  | 
  | 
10219  | 0  |     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) { | 
10220  | 0  |         return NULL;  | 
10221  | 0  |     }  | 
10222  |  |  | 
10223  |  | #ifdef HAVE_BROKEN_UNSETENV  | 
10224  |  |     unsetenv(PyBytes_AS_STRING(name));  | 
10225  |  | #else  | 
10226  | 0  |     err = unsetenv(PyBytes_AS_STRING(name));  | 
10227  | 0  |     if (err)  | 
10228  | 0  |         return posix_error();  | 
10229  | 0  | #endif  | 
10230  |  |  | 
10231  |  |     /* Remove the key from posix_putenv_garbage;  | 
10232  |  |      * this will cause it to be collected.  This has to  | 
10233  |  |      * happen after the real unsetenv() call because the  | 
10234  |  |      * old value was still accessible until then.  | 
10235  |  |      */  | 
10236  | 0  |     if (PyDict_DelItem(posix_putenv_garbage, name)) { | 
10237  |  |         /* really not much we can do; just leak */  | 
10238  | 0  |         if (!PyErr_ExceptionMatches(PyExc_KeyError)) { | 
10239  | 0  |             return NULL;  | 
10240  | 0  |         }  | 
10241  | 0  |         PyErr_Clear();  | 
10242  | 0  |     }  | 
10243  | 0  |     Py_RETURN_NONE;  | 
10244  | 0  | }  | 
10245  |  | #endif /* HAVE_UNSETENV */  | 
10246  |  |  | 
10247  |  |  | 
10248  |  | /*[clinic input]  | 
10249  |  | os.strerror  | 
10250  |  |  | 
10251  |  |     code: int  | 
10252  |  |     /  | 
10253  |  |  | 
10254  |  | Translate an error code to a message string.  | 
10255  |  | [clinic start generated code]*/  | 
10256  |  |  | 
10257  |  | static PyObject *  | 
10258  |  | os_strerror_impl(PyObject *module, int code)  | 
10259  |  | /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/  | 
10260  | 0  | { | 
10261  | 0  |     char *message = strerror(code);  | 
10262  | 0  |     if (message == NULL) { | 
10263  | 0  |         PyErr_SetString(PyExc_ValueError,  | 
10264  | 0  |                         "strerror() argument out of range");  | 
10265  | 0  |         return NULL;  | 
10266  | 0  |     }  | 
10267  | 0  |     return PyUnicode_DecodeLocale(message, "surrogateescape");  | 
10268  | 0  | }  | 
10269  |  |  | 
10270  |  |  | 
10271  |  | #ifdef HAVE_SYS_WAIT_H  | 
10272  |  | #ifdef WCOREDUMP  | 
10273  |  | /*[clinic input]  | 
10274  |  | os.WCOREDUMP -> bool  | 
10275  |  |  | 
10276  |  |     status: int  | 
10277  |  |     /  | 
10278  |  |  | 
10279  |  | Return True if the process returning status was dumped to a core file.  | 
10280  |  | [clinic start generated code]*/  | 
10281  |  |  | 
10282  |  | static int  | 
10283  |  | os_WCOREDUMP_impl(PyObject *module, int status)  | 
10284  |  | /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/  | 
10285  | 0  | { | 
10286  | 0  |     WAIT_TYPE wait_status;  | 
10287  | 0  |     WAIT_STATUS_INT(wait_status) = status;  | 
10288  | 0  |     return WCOREDUMP(wait_status);  | 
10289  | 0  | }  | 
10290  |  | #endif /* WCOREDUMP */  | 
10291  |  |  | 
10292  |  |  | 
10293  |  | #ifdef WIFCONTINUED  | 
10294  |  | /*[clinic input]  | 
10295  |  | os.WIFCONTINUED -> bool  | 
10296  |  |  | 
10297  |  |     status: int  | 
10298  |  |  | 
10299  |  | Return True if a particular process was continued from a job control stop.  | 
10300  |  |  | 
10301  |  | Return True if the process returning status was continued from a  | 
10302  |  | job control stop.  | 
10303  |  | [clinic start generated code]*/  | 
10304  |  |  | 
10305  |  | static int  | 
10306  |  | os_WIFCONTINUED_impl(PyObject *module, int status)  | 
10307  |  | /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/  | 
10308  | 0  | { | 
10309  | 0  |     WAIT_TYPE wait_status;  | 
10310  | 0  |     WAIT_STATUS_INT(wait_status) = status;  | 
10311  | 0  |     return WIFCONTINUED(wait_status);  | 
10312  | 0  | }  | 
10313  |  | #endif /* WIFCONTINUED */  | 
10314  |  |  | 
10315  |  |  | 
10316  |  | #ifdef WIFSTOPPED  | 
10317  |  | /*[clinic input]  | 
10318  |  | os.WIFSTOPPED -> bool  | 
10319  |  |  | 
10320  |  |     status: int  | 
10321  |  |  | 
10322  |  | Return True if the process returning status was stopped.  | 
10323  |  | [clinic start generated code]*/  | 
10324  |  |  | 
10325  |  | static int  | 
10326  |  | os_WIFSTOPPED_impl(PyObject *module, int status)  | 
10327  |  | /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/  | 
10328  | 0  | { | 
10329  | 0  |     WAIT_TYPE wait_status;  | 
10330  | 0  |     WAIT_STATUS_INT(wait_status) = status;  | 
10331  | 0  |     return WIFSTOPPED(wait_status);  | 
10332  | 0  | }  | 
10333  |  | #endif /* WIFSTOPPED */  | 
10334  |  |  | 
10335  |  |  | 
10336  |  | #ifdef WIFSIGNALED  | 
10337  |  | /*[clinic input]  | 
10338  |  | os.WIFSIGNALED -> bool  | 
10339  |  |  | 
10340  |  |     status: int  | 
10341  |  |  | 
10342  |  | Return True if the process returning status was terminated by a signal.  | 
10343  |  | [clinic start generated code]*/  | 
10344  |  |  | 
10345  |  | static int  | 
10346  |  | os_WIFSIGNALED_impl(PyObject *module, int status)  | 
10347  |  | /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/  | 
10348  | 0  | { | 
10349  | 0  |     WAIT_TYPE wait_status;  | 
10350  | 0  |     WAIT_STATUS_INT(wait_status) = status;  | 
10351  | 0  |     return WIFSIGNALED(wait_status);  | 
10352  | 0  | }  | 
10353  |  | #endif /* WIFSIGNALED */  | 
10354  |  |  | 
10355  |  |  | 
10356  |  | #ifdef WIFEXITED  | 
10357  |  | /*[clinic input]  | 
10358  |  | os.WIFEXITED -> bool  | 
10359  |  |  | 
10360  |  |     status: int  | 
10361  |  |  | 
10362  |  | Return True if the process returning status exited via the exit() system call.  | 
10363  |  | [clinic start generated code]*/  | 
10364  |  |  | 
10365  |  | static int  | 
10366  |  | os_WIFEXITED_impl(PyObject *module, int status)  | 
10367  |  | /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/  | 
10368  | 0  | { | 
10369  | 0  |     WAIT_TYPE wait_status;  | 
10370  | 0  |     WAIT_STATUS_INT(wait_status) = status;  | 
10371  | 0  |     return WIFEXITED(wait_status);  | 
10372  | 0  | }  | 
10373  |  | #endif /* WIFEXITED */  | 
10374  |  |  | 
10375  |  |  | 
10376  |  | #ifdef WEXITSTATUS  | 
10377  |  | /*[clinic input]  | 
10378  |  | os.WEXITSTATUS -> int  | 
10379  |  |  | 
10380  |  |     status: int  | 
10381  |  |  | 
10382  |  | Return the process return code from status.  | 
10383  |  | [clinic start generated code]*/  | 
10384  |  |  | 
10385  |  | static int  | 
10386  |  | os_WEXITSTATUS_impl(PyObject *module, int status)  | 
10387  |  | /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/  | 
10388  | 0  | { | 
10389  | 0  |     WAIT_TYPE wait_status;  | 
10390  | 0  |     WAIT_STATUS_INT(wait_status) = status;  | 
10391  | 0  |     return WEXITSTATUS(wait_status);  | 
10392  | 0  | }  | 
10393  |  | #endif /* WEXITSTATUS */  | 
10394  |  |  | 
10395  |  |  | 
10396  |  | #ifdef WTERMSIG  | 
10397  |  | /*[clinic input]  | 
10398  |  | os.WTERMSIG -> int  | 
10399  |  |  | 
10400  |  |     status: int  | 
10401  |  |  | 
10402  |  | Return the signal that terminated the process that provided the status value.  | 
10403  |  | [clinic start generated code]*/  | 
10404  |  |  | 
10405  |  | static int  | 
10406  |  | os_WTERMSIG_impl(PyObject *module, int status)  | 
10407  |  | /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/  | 
10408  | 0  | { | 
10409  | 0  |     WAIT_TYPE wait_status;  | 
10410  | 0  |     WAIT_STATUS_INT(wait_status) = status;  | 
10411  | 0  |     return WTERMSIG(wait_status);  | 
10412  | 0  | }  | 
10413  |  | #endif /* WTERMSIG */  | 
10414  |  |  | 
10415  |  |  | 
10416  |  | #ifdef WSTOPSIG  | 
10417  |  | /*[clinic input]  | 
10418  |  | os.WSTOPSIG -> int  | 
10419  |  |  | 
10420  |  |     status: int  | 
10421  |  |  | 
10422  |  | Return the signal that stopped the process that provided the status value.  | 
10423  |  | [clinic start generated code]*/  | 
10424  |  |  | 
10425  |  | static int  | 
10426  |  | os_WSTOPSIG_impl(PyObject *module, int status)  | 
10427  |  | /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/  | 
10428  | 0  | { | 
10429  | 0  |     WAIT_TYPE wait_status;  | 
10430  | 0  |     WAIT_STATUS_INT(wait_status) = status;  | 
10431  | 0  |     return WSTOPSIG(wait_status);  | 
10432  | 0  | }  | 
10433  |  | #endif /* WSTOPSIG */  | 
10434  |  | #endif /* HAVE_SYS_WAIT_H */  | 
10435  |  |  | 
10436  |  |  | 
10437  |  | #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)  | 
10438  |  | #ifdef _SCO_DS  | 
10439  |  | /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the  | 
10440  |  |    needed definitions in sys/statvfs.h */  | 
10441  |  | #define _SVID3  | 
10442  |  | #endif  | 
10443  |  | #include <sys/statvfs.h>  | 
10444  |  |  | 
10445  |  | static PyObject*  | 
10446  | 0  | _pystatvfs_fromstructstatvfs(struct statvfs st) { | 
10447  | 0  |     PyObject *v = PyStructSequence_New(StatVFSResultType);  | 
10448  | 0  |     if (v == NULL)  | 
10449  | 0  |         return NULL;  | 
10450  |  |  | 
10451  | 0  | #if !defined(HAVE_LARGEFILE_SUPPORT)  | 
10452  | 0  |     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));  | 
10453  | 0  |     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));  | 
10454  | 0  |     PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));  | 
10455  | 0  |     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));  | 
10456  | 0  |     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));  | 
10457  | 0  |     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));  | 
10458  | 0  |     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));  | 
10459  | 0  |     PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));  | 
10460  | 0  |     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));  | 
10461  | 0  |     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));  | 
10462  |  | #else  | 
10463  |  |     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));  | 
10464  |  |     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));  | 
10465  |  |     PyStructSequence_SET_ITEM(v, 2,  | 
10466  |  |                               PyLong_FromLongLong((long long) st.f_blocks));  | 
10467  |  |     PyStructSequence_SET_ITEM(v, 3,  | 
10468  |  |                               PyLong_FromLongLong((long long) st.f_bfree));  | 
10469  |  |     PyStructSequence_SET_ITEM(v, 4,  | 
10470  |  |                               PyLong_FromLongLong((long long) st.f_bavail));  | 
10471  |  |     PyStructSequence_SET_ITEM(v, 5,  | 
10472  |  |                               PyLong_FromLongLong((long long) st.f_files));  | 
10473  |  |     PyStructSequence_SET_ITEM(v, 6,  | 
10474  |  |                               PyLong_FromLongLong((long long) st.f_ffree));  | 
10475  |  |     PyStructSequence_SET_ITEM(v, 7,  | 
10476  |  |                               PyLong_FromLongLong((long long) st.f_favail));  | 
10477  |  |     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));  | 
10478  |  |     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));  | 
10479  |  | #endif  | 
10480  |  | /* The _ALL_SOURCE feature test macro defines f_fsid as a structure  | 
10481  |  |  * (issue #32390). */  | 
10482  |  | #if defined(_AIX) && defined(_ALL_SOURCE)  | 
10483  |  |     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));  | 
10484  |  | #else  | 
10485  | 0  |     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));  | 
10486  | 0  | #endif  | 
10487  | 0  |     if (PyErr_Occurred()) { | 
10488  | 0  |         Py_DECREF(v);  | 
10489  | 0  |         return NULL;  | 
10490  | 0  |     }  | 
10491  |  |  | 
10492  | 0  |     return v;  | 
10493  | 0  | }  | 
10494  |  |  | 
10495  |  |  | 
10496  |  | /*[clinic input]  | 
10497  |  | os.fstatvfs  | 
10498  |  |     fd: int  | 
10499  |  |     /  | 
10500  |  |  | 
10501  |  | Perform an fstatvfs system call on the given fd.  | 
10502  |  |  | 
10503  |  | Equivalent to statvfs(fd).  | 
10504  |  | [clinic start generated code]*/  | 
10505  |  |  | 
10506  |  | static PyObject *  | 
10507  |  | os_fstatvfs_impl(PyObject *module, int fd)  | 
10508  |  | /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/  | 
10509  | 0  | { | 
10510  | 0  |     int result;  | 
10511  | 0  |     int async_err = 0;  | 
10512  | 0  |     struct statvfs st;  | 
10513  |  | 
  | 
10514  | 0  |     do { | 
10515  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
10516  | 0  |         result = fstatvfs(fd, &st);  | 
10517  | 0  |         Py_END_ALLOW_THREADS  | 
10518  | 0  |     } while (result != 0 && errno == EINTR &&  | 
10519  | 0  |              !(async_err = PyErr_CheckSignals()));  | 
10520  | 0  |     if (result != 0)  | 
10521  | 0  |         return (!async_err) ? posix_error() : NULL;  | 
10522  |  |  | 
10523  | 0  |     return _pystatvfs_fromstructstatvfs(st);  | 
10524  | 0  | }  | 
10525  |  | #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */  | 
10526  |  |  | 
10527  |  |  | 
10528  |  | #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)  | 
10529  |  | #include <sys/statvfs.h>  | 
10530  |  | /*[clinic input]  | 
10531  |  | os.statvfs  | 
10532  |  |  | 
10533  |  |     path: path_t(allow_fd='PATH_HAVE_FSTATVFS')  | 
10534  |  |  | 
10535  |  | Perform a statvfs system call on the given path.  | 
10536  |  |  | 
10537  |  | path may always be specified as a string.  | 
10538  |  | On some platforms, path may also be specified as an open file descriptor.  | 
10539  |  |   If this functionality is unavailable, using it raises an exception.  | 
10540  |  | [clinic start generated code]*/  | 
10541  |  |  | 
10542  |  | static PyObject *  | 
10543  |  | os_statvfs_impl(PyObject *module, path_t *path)  | 
10544  |  | /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/  | 
10545  | 0  | { | 
10546  | 0  |     int result;  | 
10547  | 0  |     struct statvfs st;  | 
10548  |  | 
  | 
10549  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
10550  | 0  | #ifdef HAVE_FSTATVFS  | 
10551  | 0  |     if (path->fd != -1) { | 
10552  |  | #ifdef __APPLE__  | 
10553  |  |         /* handle weak-linking on Mac OS X 10.3 */  | 
10554  |  |         if (fstatvfs == NULL) { | 
10555  |  |             fd_specified("statvfs", path->fd); | 
10556  |  |             return NULL;  | 
10557  |  |         }  | 
10558  |  | #endif  | 
10559  | 0  |         result = fstatvfs(path->fd, &st);  | 
10560  | 0  |     }  | 
10561  | 0  |     else  | 
10562  | 0  | #endif  | 
10563  | 0  |         result = statvfs(path->narrow, &st);  | 
10564  | 0  |     Py_END_ALLOW_THREADS  | 
10565  |  | 
  | 
10566  | 0  |     if (result) { | 
10567  | 0  |         return path_error(path);  | 
10568  | 0  |     }  | 
10569  |  |  | 
10570  | 0  |     return _pystatvfs_fromstructstatvfs(st);  | 
10571  | 0  | }  | 
10572  |  | #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */  | 
10573  |  |  | 
10574  |  |  | 
10575  |  | #ifdef MS_WINDOWS  | 
10576  |  | /*[clinic input]  | 
10577  |  | os._getdiskusage  | 
10578  |  |  | 
10579  |  |     path: path_t  | 
10580  |  |  | 
10581  |  | Return disk usage statistics about the given path as a (total, free) tuple.  | 
10582  |  | [clinic start generated code]*/  | 
10583  |  |  | 
10584  |  | static PyObject *  | 
10585  |  | os__getdiskusage_impl(PyObject *module, path_t *path)  | 
10586  |  | /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/  | 
10587  |  | { | 
10588  |  |     BOOL retval;  | 
10589  |  |     ULARGE_INTEGER _, total, free;  | 
10590  |  |     DWORD err = 0;  | 
10591  |  |  | 
10592  |  |     Py_BEGIN_ALLOW_THREADS  | 
10593  |  |     retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);  | 
10594  |  |     Py_END_ALLOW_THREADS  | 
10595  |  |     if (retval == 0) { | 
10596  |  |         if (GetLastError() == ERROR_DIRECTORY) { | 
10597  |  |             wchar_t *dir_path = NULL;  | 
10598  |  |  | 
10599  |  |             dir_path = PyMem_New(wchar_t, path->length + 1);  | 
10600  |  |             if (dir_path == NULL) { | 
10601  |  |                 return PyErr_NoMemory();  | 
10602  |  |             }  | 
10603  |  |  | 
10604  |  |             wcscpy_s(dir_path, path->length + 1, path->wide);  | 
10605  |  |  | 
10606  |  |             if (_dirnameW(dir_path) != -1) { | 
10607  |  |                 Py_BEGIN_ALLOW_THREADS  | 
10608  |  |                 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);  | 
10609  |  |                 Py_END_ALLOW_THREADS  | 
10610  |  |             }  | 
10611  |  |             /* Record the last error in case it's modified by PyMem_Free. */  | 
10612  |  |             err = GetLastError();  | 
10613  |  |             PyMem_Free(dir_path);  | 
10614  |  |             if (retval) { | 
10615  |  |                 goto success;  | 
10616  |  |             }  | 
10617  |  |         }  | 
10618  |  |         return PyErr_SetFromWindowsErr(err);  | 
10619  |  |     }  | 
10620  |  |  | 
10621  |  | success:  | 
10622  |  |     return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); | 
10623  |  | }  | 
10624  |  | #endif /* MS_WINDOWS */  | 
10625  |  |  | 
10626  |  |  | 
10627  |  | /* This is used for fpathconf(), pathconf(), confstr() and sysconf().  | 
10628  |  |  * It maps strings representing configuration variable names to  | 
10629  |  |  * integer values, allowing those functions to be called with the  | 
10630  |  |  * magic names instead of polluting the module's namespace with tons of  | 
10631  |  |  * rarely-used constants.  There are three separate tables that use  | 
10632  |  |  * these definitions.  | 
10633  |  |  *  | 
10634  |  |  * This code is always included, even if none of the interfaces that  | 
10635  |  |  * need it are included.  The #if hackery needed to avoid it would be  | 
10636  |  |  * sufficiently pervasive that it's not worth the loss of readability.  | 
10637  |  |  */  | 
10638  |  | struct constdef { | 
10639  |  |     const char *name;  | 
10640  |  |     int value;  | 
10641  |  | };  | 
10642  |  |  | 
10643  |  | static int  | 
10644  |  | conv_confname(PyObject *arg, int *valuep, struct constdef *table,  | 
10645  |  |               size_t tablesize)  | 
10646  | 0  | { | 
10647  | 0  |     if (PyLong_Check(arg)) { | 
10648  | 0  |         int value = _PyLong_AsInt(arg);  | 
10649  | 0  |         if (value == -1 && PyErr_Occurred())  | 
10650  | 0  |             return 0;  | 
10651  | 0  |         *valuep = value;  | 
10652  | 0  |         return 1;  | 
10653  | 0  |     }  | 
10654  | 0  |     else { | 
10655  |  |         /* look up the value in the table using a binary search */  | 
10656  | 0  |         size_t lo = 0;  | 
10657  | 0  |         size_t mid;  | 
10658  | 0  |         size_t hi = tablesize;  | 
10659  | 0  |         int cmp;  | 
10660  | 0  |         const char *confname;  | 
10661  | 0  |         if (!PyUnicode_Check(arg)) { | 
10662  | 0  |             PyErr_SetString(PyExc_TypeError,  | 
10663  | 0  |                 "configuration names must be strings or integers");  | 
10664  | 0  |             return 0;  | 
10665  | 0  |         }  | 
10666  | 0  |         confname = PyUnicode_AsUTF8(arg);  | 
10667  | 0  |         if (confname == NULL)  | 
10668  | 0  |             return 0;  | 
10669  | 0  |         while (lo < hi) { | 
10670  | 0  |             mid = (lo + hi) / 2;  | 
10671  | 0  |             cmp = strcmp(confname, table[mid].name);  | 
10672  | 0  |             if (cmp < 0)  | 
10673  | 0  |                 hi = mid;  | 
10674  | 0  |             else if (cmp > 0)  | 
10675  | 0  |                 lo = mid + 1;  | 
10676  | 0  |             else { | 
10677  | 0  |                 *valuep = table[mid].value;  | 
10678  | 0  |                 return 1;  | 
10679  | 0  |             }  | 
10680  | 0  |         }  | 
10681  | 0  |         PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");  | 
10682  | 0  |         return 0;  | 
10683  | 0  |     }  | 
10684  | 0  | }  | 
10685  |  |  | 
10686  |  |  | 
10687  |  | #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)  | 
10688  |  | static struct constdef  posix_constants_pathconf[] = { | 
10689  |  | #ifdef _PC_ABI_AIO_XFER_MAX  | 
10690  |  |     {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX}, | 
10691  |  | #endif  | 
10692  |  | #ifdef _PC_ABI_ASYNC_IO  | 
10693  |  |     {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO}, | 
10694  |  | #endif  | 
10695  |  | #ifdef _PC_ASYNC_IO  | 
10696  |  |     {"PC_ASYNC_IO",     _PC_ASYNC_IO}, | 
10697  |  | #endif  | 
10698  |  | #ifdef _PC_CHOWN_RESTRICTED  | 
10699  |  |     {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED}, | 
10700  |  | #endif  | 
10701  |  | #ifdef _PC_FILESIZEBITS  | 
10702  |  |     {"PC_FILESIZEBITS", _PC_FILESIZEBITS}, | 
10703  |  | #endif  | 
10704  |  | #ifdef _PC_LAST  | 
10705  |  |     {"PC_LAST", _PC_LAST}, | 
10706  |  | #endif  | 
10707  |  | #ifdef _PC_LINK_MAX  | 
10708  |  |     {"PC_LINK_MAX",     _PC_LINK_MAX}, | 
10709  |  | #endif  | 
10710  |  | #ifdef _PC_MAX_CANON  | 
10711  |  |     {"PC_MAX_CANON",    _PC_MAX_CANON}, | 
10712  |  | #endif  | 
10713  |  | #ifdef _PC_MAX_INPUT  | 
10714  |  |     {"PC_MAX_INPUT",    _PC_MAX_INPUT}, | 
10715  |  | #endif  | 
10716  |  | #ifdef _PC_NAME_MAX  | 
10717  |  |     {"PC_NAME_MAX",     _PC_NAME_MAX}, | 
10718  |  | #endif  | 
10719  |  | #ifdef _PC_NO_TRUNC  | 
10720  |  |     {"PC_NO_TRUNC",     _PC_NO_TRUNC}, | 
10721  |  | #endif  | 
10722  |  | #ifdef _PC_PATH_MAX  | 
10723  |  |     {"PC_PATH_MAX",     _PC_PATH_MAX}, | 
10724  |  | #endif  | 
10725  |  | #ifdef _PC_PIPE_BUF  | 
10726  |  |     {"PC_PIPE_BUF",     _PC_PIPE_BUF}, | 
10727  |  | #endif  | 
10728  |  | #ifdef _PC_PRIO_IO  | 
10729  |  |     {"PC_PRIO_IO",      _PC_PRIO_IO}, | 
10730  |  | #endif  | 
10731  |  | #ifdef _PC_SOCK_MAXBUF  | 
10732  |  |     {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF}, | 
10733  |  | #endif  | 
10734  |  | #ifdef _PC_SYNC_IO  | 
10735  |  |     {"PC_SYNC_IO",      _PC_SYNC_IO}, | 
10736  |  | #endif  | 
10737  |  | #ifdef _PC_VDISABLE  | 
10738  |  |     {"PC_VDISABLE",     _PC_VDISABLE}, | 
10739  |  | #endif  | 
10740  |  | #ifdef _PC_ACL_ENABLED  | 
10741  |  |     {"PC_ACL_ENABLED",  _PC_ACL_ENABLED}, | 
10742  |  | #endif  | 
10743  |  | #ifdef _PC_MIN_HOLE_SIZE  | 
10744  |  |     {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE}, | 
10745  |  | #endif  | 
10746  |  | #ifdef _PC_ALLOC_SIZE_MIN  | 
10747  |  |     {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN}, | 
10748  |  | #endif  | 
10749  |  | #ifdef _PC_REC_INCR_XFER_SIZE  | 
10750  |  |     {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE}, | 
10751  |  | #endif  | 
10752  |  | #ifdef _PC_REC_MAX_XFER_SIZE  | 
10753  |  |     {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE}, | 
10754  |  | #endif  | 
10755  |  | #ifdef _PC_REC_MIN_XFER_SIZE  | 
10756  |  |     {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE}, | 
10757  |  | #endif  | 
10758  |  | #ifdef _PC_REC_XFER_ALIGN  | 
10759  |  |     {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN}, | 
10760  |  | #endif  | 
10761  |  | #ifdef _PC_SYMLINK_MAX  | 
10762  |  |     {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX}, | 
10763  |  | #endif  | 
10764  |  | #ifdef _PC_XATTR_ENABLED  | 
10765  |  |     {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED}, | 
10766  |  | #endif  | 
10767  |  | #ifdef _PC_XATTR_EXISTS  | 
10768  |  |     {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS}, | 
10769  |  | #endif  | 
10770  |  | #ifdef _PC_TIMESTAMP_RESOLUTION  | 
10771  |  |     {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION}, | 
10772  |  | #endif  | 
10773  |  | };  | 
10774  |  |  | 
10775  |  | static int  | 
10776  |  | conv_path_confname(PyObject *arg, int *valuep)  | 
10777  | 0  | { | 
10778  | 0  |     return conv_confname(arg, valuep, posix_constants_pathconf,  | 
10779  | 0  |                          sizeof(posix_constants_pathconf)  | 
10780  | 0  |                            / sizeof(struct constdef));  | 
10781  | 0  | }  | 
10782  |  | #endif  | 
10783  |  |  | 
10784  |  |  | 
10785  |  | #ifdef HAVE_FPATHCONF  | 
10786  |  | /*[clinic input]  | 
10787  |  | os.fpathconf -> long  | 
10788  |  |  | 
10789  |  |     fd: int  | 
10790  |  |     name: path_confname  | 
10791  |  |     /  | 
10792  |  |  | 
10793  |  | Return the configuration limit name for the file descriptor fd.  | 
10794  |  |  | 
10795  |  | If there is no limit, return -1.  | 
10796  |  | [clinic start generated code]*/  | 
10797  |  |  | 
10798  |  | static long  | 
10799  |  | os_fpathconf_impl(PyObject *module, int fd, int name)  | 
10800  |  | /*[clinic end generated code: output=d5b7042425fc3e21 input=5942a024d3777810]*/  | 
10801  | 0  | { | 
10802  | 0  |     long limit;  | 
10803  |  | 
  | 
10804  | 0  |     errno = 0;  | 
10805  | 0  |     limit = fpathconf(fd, name);  | 
10806  | 0  |     if (limit == -1 && errno != 0)  | 
10807  | 0  |         posix_error();  | 
10808  |  | 
  | 
10809  | 0  |     return limit;  | 
10810  | 0  | }  | 
10811  |  | #endif /* HAVE_FPATHCONF */  | 
10812  |  |  | 
10813  |  |  | 
10814  |  | #ifdef HAVE_PATHCONF  | 
10815  |  | /*[clinic input]  | 
10816  |  | os.pathconf -> long  | 
10817  |  |     path: path_t(allow_fd='PATH_HAVE_FPATHCONF')  | 
10818  |  |     name: path_confname  | 
10819  |  |  | 
10820  |  | Return the configuration limit name for the file or directory path.  | 
10821  |  |  | 
10822  |  | If there is no limit, return -1.  | 
10823  |  | On some platforms, path may also be specified as an open file descriptor.  | 
10824  |  |   If this functionality is unavailable, using it raises an exception.  | 
10825  |  | [clinic start generated code]*/  | 
10826  |  |  | 
10827  |  | static long  | 
10828  |  | os_pathconf_impl(PyObject *module, path_t *path, int name)  | 
10829  |  | /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/  | 
10830  | 0  | { | 
10831  | 0  |     long limit;  | 
10832  |  | 
  | 
10833  | 0  |     errno = 0;  | 
10834  | 0  | #ifdef HAVE_FPATHCONF  | 
10835  | 0  |     if (path->fd != -1)  | 
10836  | 0  |         limit = fpathconf(path->fd, name);  | 
10837  | 0  |     else  | 
10838  | 0  | #endif  | 
10839  | 0  |         limit = pathconf(path->narrow, name);  | 
10840  | 0  |     if (limit == -1 && errno != 0) { | 
10841  | 0  |         if (errno == EINVAL)  | 
10842  |  |             /* could be a path or name problem */  | 
10843  | 0  |             posix_error();  | 
10844  | 0  |         else  | 
10845  | 0  |             path_error(path);  | 
10846  | 0  |     }  | 
10847  |  | 
  | 
10848  | 0  |     return limit;  | 
10849  | 0  | }  | 
10850  |  | #endif /* HAVE_PATHCONF */  | 
10851  |  |  | 
10852  |  | #ifdef HAVE_CONFSTR  | 
10853  |  | static struct constdef posix_constants_confstr[] = { | 
10854  |  | #ifdef _CS_ARCHITECTURE  | 
10855  |  |     {"CS_ARCHITECTURE", _CS_ARCHITECTURE}, | 
10856  |  | #endif  | 
10857  |  | #ifdef _CS_GNU_LIBC_VERSION  | 
10858  |  |     {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION}, | 
10859  |  | #endif  | 
10860  |  | #ifdef _CS_GNU_LIBPTHREAD_VERSION  | 
10861  |  |     {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION}, | 
10862  |  | #endif  | 
10863  |  | #ifdef _CS_HOSTNAME  | 
10864  |  |     {"CS_HOSTNAME",     _CS_HOSTNAME}, | 
10865  |  | #endif  | 
10866  |  | #ifdef _CS_HW_PROVIDER  | 
10867  |  |     {"CS_HW_PROVIDER",  _CS_HW_PROVIDER}, | 
10868  |  | #endif  | 
10869  |  | #ifdef _CS_HW_SERIAL  | 
10870  |  |     {"CS_HW_SERIAL",    _CS_HW_SERIAL}, | 
10871  |  | #endif  | 
10872  |  | #ifdef _CS_INITTAB_NAME  | 
10873  |  |     {"CS_INITTAB_NAME", _CS_INITTAB_NAME}, | 
10874  |  | #endif  | 
10875  |  | #ifdef _CS_LFS64_CFLAGS  | 
10876  |  |     {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS}, | 
10877  |  | #endif  | 
10878  |  | #ifdef _CS_LFS64_LDFLAGS  | 
10879  |  |     {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS}, | 
10880  |  | #endif  | 
10881  |  | #ifdef _CS_LFS64_LIBS  | 
10882  |  |     {"CS_LFS64_LIBS",   _CS_LFS64_LIBS}, | 
10883  |  | #endif  | 
10884  |  | #ifdef _CS_LFS64_LINTFLAGS  | 
10885  |  |     {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS}, | 
10886  |  | #endif  | 
10887  |  | #ifdef _CS_LFS_CFLAGS  | 
10888  |  |     {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS}, | 
10889  |  | #endif  | 
10890  |  | #ifdef _CS_LFS_LDFLAGS  | 
10891  |  |     {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS}, | 
10892  |  | #endif  | 
10893  |  | #ifdef _CS_LFS_LIBS  | 
10894  |  |     {"CS_LFS_LIBS",     _CS_LFS_LIBS}, | 
10895  |  | #endif  | 
10896  |  | #ifdef _CS_LFS_LINTFLAGS  | 
10897  |  |     {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS}, | 
10898  |  | #endif  | 
10899  |  | #ifdef _CS_MACHINE  | 
10900  |  |     {"CS_MACHINE",      _CS_MACHINE}, | 
10901  |  | #endif  | 
10902  |  | #ifdef _CS_PATH  | 
10903  |  |     {"CS_PATH", _CS_PATH}, | 
10904  |  | #endif  | 
10905  |  | #ifdef _CS_RELEASE  | 
10906  |  |     {"CS_RELEASE",      _CS_RELEASE}, | 
10907  |  | #endif  | 
10908  |  | #ifdef _CS_SRPC_DOMAIN  | 
10909  |  |     {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN}, | 
10910  |  | #endif  | 
10911  |  | #ifdef _CS_SYSNAME  | 
10912  |  |     {"CS_SYSNAME",      _CS_SYSNAME}, | 
10913  |  | #endif  | 
10914  |  | #ifdef _CS_VERSION  | 
10915  |  |     {"CS_VERSION",      _CS_VERSION}, | 
10916  |  | #endif  | 
10917  |  | #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS  | 
10918  |  |     {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS}, | 
10919  |  | #endif  | 
10920  |  | #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS  | 
10921  |  |     {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS}, | 
10922  |  | #endif  | 
10923  |  | #ifdef _CS_XBS5_ILP32_OFF32_LIBS  | 
10924  |  |     {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS}, | 
10925  |  | #endif  | 
10926  |  | #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS  | 
10927  |  |     {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS}, | 
10928  |  | #endif  | 
10929  |  | #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS  | 
10930  |  |     {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS}, | 
10931  |  | #endif  | 
10932  |  | #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS  | 
10933  |  |     {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS}, | 
10934  |  | #endif  | 
10935  |  | #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS  | 
10936  |  |     {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS}, | 
10937  |  | #endif  | 
10938  |  | #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS  | 
10939  |  |     {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS}, | 
10940  |  | #endif  | 
10941  |  | #ifdef _CS_XBS5_LP64_OFF64_CFLAGS  | 
10942  |  |     {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS}, | 
10943  |  | #endif  | 
10944  |  | #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS  | 
10945  |  |     {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS}, | 
10946  |  | #endif  | 
10947  |  | #ifdef _CS_XBS5_LP64_OFF64_LIBS  | 
10948  |  |     {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS}, | 
10949  |  | #endif  | 
10950  |  | #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS  | 
10951  |  |     {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS}, | 
10952  |  | #endif  | 
10953  |  | #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS  | 
10954  |  |     {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS}, | 
10955  |  | #endif  | 
10956  |  | #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS  | 
10957  |  |     {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS}, | 
10958  |  | #endif  | 
10959  |  | #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS  | 
10960  |  |     {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS}, | 
10961  |  | #endif  | 
10962  |  | #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS  | 
10963  |  |     {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS}, | 
10964  |  | #endif  | 
10965  |  | #ifdef _MIPS_CS_AVAIL_PROCESSORS  | 
10966  |  |     {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS}, | 
10967  |  | #endif  | 
10968  |  | #ifdef _MIPS_CS_BASE  | 
10969  |  |     {"MIPS_CS_BASE",    _MIPS_CS_BASE}, | 
10970  |  | #endif  | 
10971  |  | #ifdef _MIPS_CS_HOSTID  | 
10972  |  |     {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID}, | 
10973  |  | #endif  | 
10974  |  | #ifdef _MIPS_CS_HW_NAME  | 
10975  |  |     {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME}, | 
10976  |  | #endif  | 
10977  |  | #ifdef _MIPS_CS_NUM_PROCESSORS  | 
10978  |  |     {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS}, | 
10979  |  | #endif  | 
10980  |  | #ifdef _MIPS_CS_OSREL_MAJ  | 
10981  |  |     {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ}, | 
10982  |  | #endif  | 
10983  |  | #ifdef _MIPS_CS_OSREL_MIN  | 
10984  |  |     {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN}, | 
10985  |  | #endif  | 
10986  |  | #ifdef _MIPS_CS_OSREL_PATCH  | 
10987  |  |     {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH}, | 
10988  |  | #endif  | 
10989  |  | #ifdef _MIPS_CS_OS_NAME  | 
10990  |  |     {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME}, | 
10991  |  | #endif  | 
10992  |  | #ifdef _MIPS_CS_OS_PROVIDER  | 
10993  |  |     {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER}, | 
10994  |  | #endif  | 
10995  |  | #ifdef _MIPS_CS_PROCESSORS  | 
10996  |  |     {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS}, | 
10997  |  | #endif  | 
10998  |  | #ifdef _MIPS_CS_SERIAL  | 
10999  |  |     {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL}, | 
11000  |  | #endif  | 
11001  |  | #ifdef _MIPS_CS_VENDOR  | 
11002  |  |     {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR}, | 
11003  |  | #endif  | 
11004  |  | };  | 
11005  |  |  | 
11006  |  | static int  | 
11007  |  | conv_confstr_confname(PyObject *arg, int *valuep)  | 
11008  | 0  | { | 
11009  | 0  |     return conv_confname(arg, valuep, posix_constants_confstr,  | 
11010  | 0  |                          sizeof(posix_constants_confstr)  | 
11011  | 0  |                            / sizeof(struct constdef));  | 
11012  | 0  | }  | 
11013  |  |  | 
11014  |  |  | 
11015  |  | /*[clinic input]  | 
11016  |  | os.confstr  | 
11017  |  |  | 
11018  |  |     name: confstr_confname  | 
11019  |  |     /  | 
11020  |  |  | 
11021  |  | Return a string-valued system configuration variable.  | 
11022  |  | [clinic start generated code]*/  | 
11023  |  |  | 
11024  |  | static PyObject *  | 
11025  |  | os_confstr_impl(PyObject *module, int name)  | 
11026  |  | /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/  | 
11027  | 0  | { | 
11028  | 0  |     PyObject *result = NULL;  | 
11029  | 0  |     char buffer[255];  | 
11030  | 0  |     size_t len;  | 
11031  |  | 
  | 
11032  | 0  |     errno = 0;  | 
11033  | 0  |     len = confstr(name, buffer, sizeof(buffer));  | 
11034  | 0  |     if (len == 0) { | 
11035  | 0  |         if (errno) { | 
11036  | 0  |             posix_error();  | 
11037  | 0  |             return NULL;  | 
11038  | 0  |         }  | 
11039  | 0  |         else { | 
11040  | 0  |             Py_RETURN_NONE;  | 
11041  | 0  |         }  | 
11042  | 0  |     }  | 
11043  |  |  | 
11044  | 0  |     if (len >= sizeof(buffer)) { | 
11045  | 0  |         size_t len2;  | 
11046  | 0  |         char *buf = PyMem_Malloc(len);  | 
11047  | 0  |         if (buf == NULL)  | 
11048  | 0  |             return PyErr_NoMemory();  | 
11049  | 0  |         len2 = confstr(name, buf, len);  | 
11050  | 0  |         assert(len == len2);  | 
11051  | 0  |         result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);  | 
11052  | 0  |         PyMem_Free(buf);  | 
11053  | 0  |     }  | 
11054  | 0  |     else  | 
11055  | 0  |         result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);  | 
11056  | 0  |     return result;  | 
11057  | 0  | }  | 
11058  |  | #endif /* HAVE_CONFSTR */  | 
11059  |  |  | 
11060  |  |  | 
11061  |  | #ifdef HAVE_SYSCONF  | 
11062  |  | static struct constdef posix_constants_sysconf[] = { | 
11063  |  | #ifdef _SC_2_CHAR_TERM  | 
11064  |  |     {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM}, | 
11065  |  | #endif  | 
11066  |  | #ifdef _SC_2_C_BIND  | 
11067  |  |     {"SC_2_C_BIND",     _SC_2_C_BIND}, | 
11068  |  | #endif  | 
11069  |  | #ifdef _SC_2_C_DEV  | 
11070  |  |     {"SC_2_C_DEV",      _SC_2_C_DEV}, | 
11071  |  | #endif  | 
11072  |  | #ifdef _SC_2_C_VERSION  | 
11073  |  |     {"SC_2_C_VERSION",  _SC_2_C_VERSION}, | 
11074  |  | #endif  | 
11075  |  | #ifdef _SC_2_FORT_DEV  | 
11076  |  |     {"SC_2_FORT_DEV",   _SC_2_FORT_DEV}, | 
11077  |  | #endif  | 
11078  |  | #ifdef _SC_2_FORT_RUN  | 
11079  |  |     {"SC_2_FORT_RUN",   _SC_2_FORT_RUN}, | 
11080  |  | #endif  | 
11081  |  | #ifdef _SC_2_LOCALEDEF  | 
11082  |  |     {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF}, | 
11083  |  | #endif  | 
11084  |  | #ifdef _SC_2_SW_DEV  | 
11085  |  |     {"SC_2_SW_DEV",     _SC_2_SW_DEV}, | 
11086  |  | #endif  | 
11087  |  | #ifdef _SC_2_UPE  | 
11088  |  |     {"SC_2_UPE",        _SC_2_UPE}, | 
11089  |  | #endif  | 
11090  |  | #ifdef _SC_2_VERSION  | 
11091  |  |     {"SC_2_VERSION",    _SC_2_VERSION}, | 
11092  |  | #endif  | 
11093  |  | #ifdef _SC_ABI_ASYNCHRONOUS_IO  | 
11094  |  |     {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO}, | 
11095  |  | #endif  | 
11096  |  | #ifdef _SC_ACL  | 
11097  |  |     {"SC_ACL",  _SC_ACL}, | 
11098  |  | #endif  | 
11099  |  | #ifdef _SC_AIO_LISTIO_MAX  | 
11100  |  |     {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX}, | 
11101  |  | #endif  | 
11102  |  | #ifdef _SC_AIO_MAX  | 
11103  |  |     {"SC_AIO_MAX",      _SC_AIO_MAX}, | 
11104  |  | #endif  | 
11105  |  | #ifdef _SC_AIO_PRIO_DELTA_MAX  | 
11106  |  |     {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX}, | 
11107  |  | #endif  | 
11108  |  | #ifdef _SC_ARG_MAX  | 
11109  |  |     {"SC_ARG_MAX",      _SC_ARG_MAX}, | 
11110  |  | #endif  | 
11111  |  | #ifdef _SC_ASYNCHRONOUS_IO  | 
11112  |  |     {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO}, | 
11113  |  | #endif  | 
11114  |  | #ifdef _SC_ATEXIT_MAX  | 
11115  |  |     {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX}, | 
11116  |  | #endif  | 
11117  |  | #ifdef _SC_AUDIT  | 
11118  |  |     {"SC_AUDIT",        _SC_AUDIT}, | 
11119  |  | #endif  | 
11120  |  | #ifdef _SC_AVPHYS_PAGES  | 
11121  |  |     {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES}, | 
11122  |  | #endif  | 
11123  |  | #ifdef _SC_BC_BASE_MAX  | 
11124  |  |     {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX}, | 
11125  |  | #endif  | 
11126  |  | #ifdef _SC_BC_DIM_MAX  | 
11127  |  |     {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX}, | 
11128  |  | #endif  | 
11129  |  | #ifdef _SC_BC_SCALE_MAX  | 
11130  |  |     {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX}, | 
11131  |  | #endif  | 
11132  |  | #ifdef _SC_BC_STRING_MAX  | 
11133  |  |     {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX}, | 
11134  |  | #endif  | 
11135  |  | #ifdef _SC_CAP  | 
11136  |  |     {"SC_CAP",  _SC_CAP}, | 
11137  |  | #endif  | 
11138  |  | #ifdef _SC_CHARCLASS_NAME_MAX  | 
11139  |  |     {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX}, | 
11140  |  | #endif  | 
11141  |  | #ifdef _SC_CHAR_BIT  | 
11142  |  |     {"SC_CHAR_BIT",     _SC_CHAR_BIT}, | 
11143  |  | #endif  | 
11144  |  | #ifdef _SC_CHAR_MAX  | 
11145  |  |     {"SC_CHAR_MAX",     _SC_CHAR_MAX}, | 
11146  |  | #endif  | 
11147  |  | #ifdef _SC_CHAR_MIN  | 
11148  |  |     {"SC_CHAR_MIN",     _SC_CHAR_MIN}, | 
11149  |  | #endif  | 
11150  |  | #ifdef _SC_CHILD_MAX  | 
11151  |  |     {"SC_CHILD_MAX",    _SC_CHILD_MAX}, | 
11152  |  | #endif  | 
11153  |  | #ifdef _SC_CLK_TCK  | 
11154  |  |     {"SC_CLK_TCK",      _SC_CLK_TCK}, | 
11155  |  | #endif  | 
11156  |  | #ifdef _SC_COHER_BLKSZ  | 
11157  |  |     {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ}, | 
11158  |  | #endif  | 
11159  |  | #ifdef _SC_COLL_WEIGHTS_MAX  | 
11160  |  |     {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX}, | 
11161  |  | #endif  | 
11162  |  | #ifdef _SC_DCACHE_ASSOC  | 
11163  |  |     {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC}, | 
11164  |  | #endif  | 
11165  |  | #ifdef _SC_DCACHE_BLKSZ  | 
11166  |  |     {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ}, | 
11167  |  | #endif  | 
11168  |  | #ifdef _SC_DCACHE_LINESZ  | 
11169  |  |     {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ}, | 
11170  |  | #endif  | 
11171  |  | #ifdef _SC_DCACHE_SZ  | 
11172  |  |     {"SC_DCACHE_SZ",    _SC_DCACHE_SZ}, | 
11173  |  | #endif  | 
11174  |  | #ifdef _SC_DCACHE_TBLKSZ  | 
11175  |  |     {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ}, | 
11176  |  | #endif  | 
11177  |  | #ifdef _SC_DELAYTIMER_MAX  | 
11178  |  |     {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX}, | 
11179  |  | #endif  | 
11180  |  | #ifdef _SC_EQUIV_CLASS_MAX  | 
11181  |  |     {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX}, | 
11182  |  | #endif  | 
11183  |  | #ifdef _SC_EXPR_NEST_MAX  | 
11184  |  |     {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX}, | 
11185  |  | #endif  | 
11186  |  | #ifdef _SC_FSYNC  | 
11187  |  |     {"SC_FSYNC",        _SC_FSYNC}, | 
11188  |  | #endif  | 
11189  |  | #ifdef _SC_GETGR_R_SIZE_MAX  | 
11190  |  |     {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX}, | 
11191  |  | #endif  | 
11192  |  | #ifdef _SC_GETPW_R_SIZE_MAX  | 
11193  |  |     {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX}, | 
11194  |  | #endif  | 
11195  |  | #ifdef _SC_ICACHE_ASSOC  | 
11196  |  |     {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC}, | 
11197  |  | #endif  | 
11198  |  | #ifdef _SC_ICACHE_BLKSZ  | 
11199  |  |     {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ}, | 
11200  |  | #endif  | 
11201  |  | #ifdef _SC_ICACHE_LINESZ  | 
11202  |  |     {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ}, | 
11203  |  | #endif  | 
11204  |  | #ifdef _SC_ICACHE_SZ  | 
11205  |  |     {"SC_ICACHE_SZ",    _SC_ICACHE_SZ}, | 
11206  |  | #endif  | 
11207  |  | #ifdef _SC_INF  | 
11208  |  |     {"SC_INF",  _SC_INF}, | 
11209  |  | #endif  | 
11210  |  | #ifdef _SC_INT_MAX  | 
11211  |  |     {"SC_INT_MAX",      _SC_INT_MAX}, | 
11212  |  | #endif  | 
11213  |  | #ifdef _SC_INT_MIN  | 
11214  |  |     {"SC_INT_MIN",      _SC_INT_MIN}, | 
11215  |  | #endif  | 
11216  |  | #ifdef _SC_IOV_MAX  | 
11217  |  |     {"SC_IOV_MAX",      _SC_IOV_MAX}, | 
11218  |  | #endif  | 
11219  |  | #ifdef _SC_IP_SECOPTS  | 
11220  |  |     {"SC_IP_SECOPTS",   _SC_IP_SECOPTS}, | 
11221  |  | #endif  | 
11222  |  | #ifdef _SC_JOB_CONTROL  | 
11223  |  |     {"SC_JOB_CONTROL",  _SC_JOB_CONTROL}, | 
11224  |  | #endif  | 
11225  |  | #ifdef _SC_KERN_POINTERS  | 
11226  |  |     {"SC_KERN_POINTERS",        _SC_KERN_POINTERS}, | 
11227  |  | #endif  | 
11228  |  | #ifdef _SC_KERN_SIM  | 
11229  |  |     {"SC_KERN_SIM",     _SC_KERN_SIM}, | 
11230  |  | #endif  | 
11231  |  | #ifdef _SC_LINE_MAX  | 
11232  |  |     {"SC_LINE_MAX",     _SC_LINE_MAX}, | 
11233  |  | #endif  | 
11234  |  | #ifdef _SC_LOGIN_NAME_MAX  | 
11235  |  |     {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX}, | 
11236  |  | #endif  | 
11237  |  | #ifdef _SC_LOGNAME_MAX  | 
11238  |  |     {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX}, | 
11239  |  | #endif  | 
11240  |  | #ifdef _SC_LONG_BIT  | 
11241  |  |     {"SC_LONG_BIT",     _SC_LONG_BIT}, | 
11242  |  | #endif  | 
11243  |  | #ifdef _SC_MAC  | 
11244  |  |     {"SC_MAC",  _SC_MAC}, | 
11245  |  | #endif  | 
11246  |  | #ifdef _SC_MAPPED_FILES  | 
11247  |  |     {"SC_MAPPED_FILES", _SC_MAPPED_FILES}, | 
11248  |  | #endif  | 
11249  |  | #ifdef _SC_MAXPID  | 
11250  |  |     {"SC_MAXPID",       _SC_MAXPID}, | 
11251  |  | #endif  | 
11252  |  | #ifdef _SC_MB_LEN_MAX  | 
11253  |  |     {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX}, | 
11254  |  | #endif  | 
11255  |  | #ifdef _SC_MEMLOCK  | 
11256  |  |     {"SC_MEMLOCK",      _SC_MEMLOCK}, | 
11257  |  | #endif  | 
11258  |  | #ifdef _SC_MEMLOCK_RANGE  | 
11259  |  |     {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE}, | 
11260  |  | #endif  | 
11261  |  | #ifdef _SC_MEMORY_PROTECTION  | 
11262  |  |     {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION}, | 
11263  |  | #endif  | 
11264  |  | #ifdef _SC_MESSAGE_PASSING  | 
11265  |  |     {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING}, | 
11266  |  | #endif  | 
11267  |  | #ifdef _SC_MMAP_FIXED_ALIGNMENT  | 
11268  |  |     {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT}, | 
11269  |  | #endif  | 
11270  |  | #ifdef _SC_MQ_OPEN_MAX  | 
11271  |  |     {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX}, | 
11272  |  | #endif  | 
11273  |  | #ifdef _SC_MQ_PRIO_MAX  | 
11274  |  |     {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX}, | 
11275  |  | #endif  | 
11276  |  | #ifdef _SC_NACLS_MAX  | 
11277  |  |     {"SC_NACLS_MAX",    _SC_NACLS_MAX}, | 
11278  |  | #endif  | 
11279  |  | #ifdef _SC_NGROUPS_MAX  | 
11280  |  |     {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX}, | 
11281  |  | #endif  | 
11282  |  | #ifdef _SC_NL_ARGMAX  | 
11283  |  |     {"SC_NL_ARGMAX",    _SC_NL_ARGMAX}, | 
11284  |  | #endif  | 
11285  |  | #ifdef _SC_NL_LANGMAX  | 
11286  |  |     {"SC_NL_LANGMAX",   _SC_NL_LANGMAX}, | 
11287  |  | #endif  | 
11288  |  | #ifdef _SC_NL_MSGMAX  | 
11289  |  |     {"SC_NL_MSGMAX",    _SC_NL_MSGMAX}, | 
11290  |  | #endif  | 
11291  |  | #ifdef _SC_NL_NMAX  | 
11292  |  |     {"SC_NL_NMAX",      _SC_NL_NMAX}, | 
11293  |  | #endif  | 
11294  |  | #ifdef _SC_NL_SETMAX  | 
11295  |  |     {"SC_NL_SETMAX",    _SC_NL_SETMAX}, | 
11296  |  | #endif  | 
11297  |  | #ifdef _SC_NL_TEXTMAX  | 
11298  |  |     {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX}, | 
11299  |  | #endif  | 
11300  |  | #ifdef _SC_NPROCESSORS_CONF  | 
11301  |  |     {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF}, | 
11302  |  | #endif  | 
11303  |  | #ifdef _SC_NPROCESSORS_ONLN  | 
11304  |  |     {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN}, | 
11305  |  | #endif  | 
11306  |  | #ifdef _SC_NPROC_CONF  | 
11307  |  |     {"SC_NPROC_CONF",   _SC_NPROC_CONF}, | 
11308  |  | #endif  | 
11309  |  | #ifdef _SC_NPROC_ONLN  | 
11310  |  |     {"SC_NPROC_ONLN",   _SC_NPROC_ONLN}, | 
11311  |  | #endif  | 
11312  |  | #ifdef _SC_NZERO  | 
11313  |  |     {"SC_NZERO",        _SC_NZERO}, | 
11314  |  | #endif  | 
11315  |  | #ifdef _SC_OPEN_MAX  | 
11316  |  |     {"SC_OPEN_MAX",     _SC_OPEN_MAX}, | 
11317  |  | #endif  | 
11318  |  | #ifdef _SC_PAGESIZE  | 
11319  |  |     {"SC_PAGESIZE",     _SC_PAGESIZE}, | 
11320  |  | #endif  | 
11321  |  | #ifdef _SC_PAGE_SIZE  | 
11322  |  |     {"SC_PAGE_SIZE",    _SC_PAGE_SIZE}, | 
11323  |  | #endif  | 
11324  |  | #ifdef _SC_PASS_MAX  | 
11325  |  |     {"SC_PASS_MAX",     _SC_PASS_MAX}, | 
11326  |  | #endif  | 
11327  |  | #ifdef _SC_PHYS_PAGES  | 
11328  |  |     {"SC_PHYS_PAGES",   _SC_PHYS_PAGES}, | 
11329  |  | #endif  | 
11330  |  | #ifdef _SC_PII  | 
11331  |  |     {"SC_PII",  _SC_PII}, | 
11332  |  | #endif  | 
11333  |  | #ifdef _SC_PII_INTERNET  | 
11334  |  |     {"SC_PII_INTERNET", _SC_PII_INTERNET}, | 
11335  |  | #endif  | 
11336  |  | #ifdef _SC_PII_INTERNET_DGRAM  | 
11337  |  |     {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM}, | 
11338  |  | #endif  | 
11339  |  | #ifdef _SC_PII_INTERNET_STREAM  | 
11340  |  |     {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM}, | 
11341  |  | #endif  | 
11342  |  | #ifdef _SC_PII_OSI  | 
11343  |  |     {"SC_PII_OSI",      _SC_PII_OSI}, | 
11344  |  | #endif  | 
11345  |  | #ifdef _SC_PII_OSI_CLTS  | 
11346  |  |     {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS}, | 
11347  |  | #endif  | 
11348  |  | #ifdef _SC_PII_OSI_COTS  | 
11349  |  |     {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS}, | 
11350  |  | #endif  | 
11351  |  | #ifdef _SC_PII_OSI_M  | 
11352  |  |     {"SC_PII_OSI_M",    _SC_PII_OSI_M}, | 
11353  |  | #endif  | 
11354  |  | #ifdef _SC_PII_SOCKET  | 
11355  |  |     {"SC_PII_SOCKET",   _SC_PII_SOCKET}, | 
11356  |  | #endif  | 
11357  |  | #ifdef _SC_PII_XTI  | 
11358  |  |     {"SC_PII_XTI",      _SC_PII_XTI}, | 
11359  |  | #endif  | 
11360  |  | #ifdef _SC_POLL  | 
11361  |  |     {"SC_POLL", _SC_POLL}, | 
11362  |  | #endif  | 
11363  |  | #ifdef _SC_PRIORITIZED_IO  | 
11364  |  |     {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO}, | 
11365  |  | #endif  | 
11366  |  | #ifdef _SC_PRIORITY_SCHEDULING  | 
11367  |  |     {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING}, | 
11368  |  | #endif  | 
11369  |  | #ifdef _SC_REALTIME_SIGNALS  | 
11370  |  |     {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS}, | 
11371  |  | #endif  | 
11372  |  | #ifdef _SC_RE_DUP_MAX  | 
11373  |  |     {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX}, | 
11374  |  | #endif  | 
11375  |  | #ifdef _SC_RTSIG_MAX  | 
11376  |  |     {"SC_RTSIG_MAX",    _SC_RTSIG_MAX}, | 
11377  |  | #endif  | 
11378  |  | #ifdef _SC_SAVED_IDS  | 
11379  |  |     {"SC_SAVED_IDS",    _SC_SAVED_IDS}, | 
11380  |  | #endif  | 
11381  |  | #ifdef _SC_SCHAR_MAX  | 
11382  |  |     {"SC_SCHAR_MAX",    _SC_SCHAR_MAX}, | 
11383  |  | #endif  | 
11384  |  | #ifdef _SC_SCHAR_MIN  | 
11385  |  |     {"SC_SCHAR_MIN",    _SC_SCHAR_MIN}, | 
11386  |  | #endif  | 
11387  |  | #ifdef _SC_SELECT  | 
11388  |  |     {"SC_SELECT",       _SC_SELECT}, | 
11389  |  | #endif  | 
11390  |  | #ifdef _SC_SEMAPHORES  | 
11391  |  |     {"SC_SEMAPHORES",   _SC_SEMAPHORES}, | 
11392  |  | #endif  | 
11393  |  | #ifdef _SC_SEM_NSEMS_MAX  | 
11394  |  |     {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX}, | 
11395  |  | #endif  | 
11396  |  | #ifdef _SC_SEM_VALUE_MAX  | 
11397  |  |     {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX}, | 
11398  |  | #endif  | 
11399  |  | #ifdef _SC_SHARED_MEMORY_OBJECTS  | 
11400  |  |     {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS}, | 
11401  |  | #endif  | 
11402  |  | #ifdef _SC_SHRT_MAX  | 
11403  |  |     {"SC_SHRT_MAX",     _SC_SHRT_MAX}, | 
11404  |  | #endif  | 
11405  |  | #ifdef _SC_SHRT_MIN  | 
11406  |  |     {"SC_SHRT_MIN",     _SC_SHRT_MIN}, | 
11407  |  | #endif  | 
11408  |  | #ifdef _SC_SIGQUEUE_MAX  | 
11409  |  |     {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX}, | 
11410  |  | #endif  | 
11411  |  | #ifdef _SC_SIGRT_MAX  | 
11412  |  |     {"SC_SIGRT_MAX",    _SC_SIGRT_MAX}, | 
11413  |  | #endif  | 
11414  |  | #ifdef _SC_SIGRT_MIN  | 
11415  |  |     {"SC_SIGRT_MIN",    _SC_SIGRT_MIN}, | 
11416  |  | #endif  | 
11417  |  | #ifdef _SC_SOFTPOWER  | 
11418  |  |     {"SC_SOFTPOWER",    _SC_SOFTPOWER}, | 
11419  |  | #endif  | 
11420  |  | #ifdef _SC_SPLIT_CACHE  | 
11421  |  |     {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE}, | 
11422  |  | #endif  | 
11423  |  | #ifdef _SC_SSIZE_MAX  | 
11424  |  |     {"SC_SSIZE_MAX",    _SC_SSIZE_MAX}, | 
11425  |  | #endif  | 
11426  |  | #ifdef _SC_STACK_PROT  | 
11427  |  |     {"SC_STACK_PROT",   _SC_STACK_PROT}, | 
11428  |  | #endif  | 
11429  |  | #ifdef _SC_STREAM_MAX  | 
11430  |  |     {"SC_STREAM_MAX",   _SC_STREAM_MAX}, | 
11431  |  | #endif  | 
11432  |  | #ifdef _SC_SYNCHRONIZED_IO  | 
11433  |  |     {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO}, | 
11434  |  | #endif  | 
11435  |  | #ifdef _SC_THREADS  | 
11436  |  |     {"SC_THREADS",      _SC_THREADS}, | 
11437  |  | #endif  | 
11438  |  | #ifdef _SC_THREAD_ATTR_STACKADDR  | 
11439  |  |     {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR}, | 
11440  |  | #endif  | 
11441  |  | #ifdef _SC_THREAD_ATTR_STACKSIZE  | 
11442  |  |     {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE}, | 
11443  |  | #endif  | 
11444  |  | #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS  | 
11445  |  |     {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS}, | 
11446  |  | #endif  | 
11447  |  | #ifdef _SC_THREAD_KEYS_MAX  | 
11448  |  |     {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX}, | 
11449  |  | #endif  | 
11450  |  | #ifdef _SC_THREAD_PRIORITY_SCHEDULING  | 
11451  |  |     {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING}, | 
11452  |  | #endif  | 
11453  |  | #ifdef _SC_THREAD_PRIO_INHERIT  | 
11454  |  |     {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT}, | 
11455  |  | #endif  | 
11456  |  | #ifdef _SC_THREAD_PRIO_PROTECT  | 
11457  |  |     {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT}, | 
11458  |  | #endif  | 
11459  |  | #ifdef _SC_THREAD_PROCESS_SHARED  | 
11460  |  |     {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED}, | 
11461  |  | #endif  | 
11462  |  | #ifdef _SC_THREAD_SAFE_FUNCTIONS  | 
11463  |  |     {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS}, | 
11464  |  | #endif  | 
11465  |  | #ifdef _SC_THREAD_STACK_MIN  | 
11466  |  |     {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN}, | 
11467  |  | #endif  | 
11468  |  | #ifdef _SC_THREAD_THREADS_MAX  | 
11469  |  |     {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX}, | 
11470  |  | #endif  | 
11471  |  | #ifdef _SC_TIMERS  | 
11472  |  |     {"SC_TIMERS",       _SC_TIMERS}, | 
11473  |  | #endif  | 
11474  |  | #ifdef _SC_TIMER_MAX  | 
11475  |  |     {"SC_TIMER_MAX",    _SC_TIMER_MAX}, | 
11476  |  | #endif  | 
11477  |  | #ifdef _SC_TTY_NAME_MAX  | 
11478  |  |     {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX}, | 
11479  |  | #endif  | 
11480  |  | #ifdef _SC_TZNAME_MAX  | 
11481  |  |     {"SC_TZNAME_MAX",   _SC_TZNAME_MAX}, | 
11482  |  | #endif  | 
11483  |  | #ifdef _SC_T_IOV_MAX  | 
11484  |  |     {"SC_T_IOV_MAX",    _SC_T_IOV_MAX}, | 
11485  |  | #endif  | 
11486  |  | #ifdef _SC_UCHAR_MAX  | 
11487  |  |     {"SC_UCHAR_MAX",    _SC_UCHAR_MAX}, | 
11488  |  | #endif  | 
11489  |  | #ifdef _SC_UINT_MAX  | 
11490  |  |     {"SC_UINT_MAX",     _SC_UINT_MAX}, | 
11491  |  | #endif  | 
11492  |  | #ifdef _SC_UIO_MAXIOV  | 
11493  |  |     {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV}, | 
11494  |  | #endif  | 
11495  |  | #ifdef _SC_ULONG_MAX  | 
11496  |  |     {"SC_ULONG_MAX",    _SC_ULONG_MAX}, | 
11497  |  | #endif  | 
11498  |  | #ifdef _SC_USHRT_MAX  | 
11499  |  |     {"SC_USHRT_MAX",    _SC_USHRT_MAX}, | 
11500  |  | #endif  | 
11501  |  | #ifdef _SC_VERSION  | 
11502  |  |     {"SC_VERSION",      _SC_VERSION}, | 
11503  |  | #endif  | 
11504  |  | #ifdef _SC_WORD_BIT  | 
11505  |  |     {"SC_WORD_BIT",     _SC_WORD_BIT}, | 
11506  |  | #endif  | 
11507  |  | #ifdef _SC_XBS5_ILP32_OFF32  | 
11508  |  |     {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32}, | 
11509  |  | #endif  | 
11510  |  | #ifdef _SC_XBS5_ILP32_OFFBIG  | 
11511  |  |     {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG}, | 
11512  |  | #endif  | 
11513  |  | #ifdef _SC_XBS5_LP64_OFF64  | 
11514  |  |     {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64}, | 
11515  |  | #endif  | 
11516  |  | #ifdef _SC_XBS5_LPBIG_OFFBIG  | 
11517  |  |     {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG}, | 
11518  |  | #endif  | 
11519  |  | #ifdef _SC_XOPEN_CRYPT  | 
11520  |  |     {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT}, | 
11521  |  | #endif  | 
11522  |  | #ifdef _SC_XOPEN_ENH_I18N  | 
11523  |  |     {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N}, | 
11524  |  | #endif  | 
11525  |  | #ifdef _SC_XOPEN_LEGACY  | 
11526  |  |     {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY}, | 
11527  |  | #endif  | 
11528  |  | #ifdef _SC_XOPEN_REALTIME  | 
11529  |  |     {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME}, | 
11530  |  | #endif  | 
11531  |  | #ifdef _SC_XOPEN_REALTIME_THREADS  | 
11532  |  |     {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS}, | 
11533  |  | #endif  | 
11534  |  | #ifdef _SC_XOPEN_SHM  | 
11535  |  |     {"SC_XOPEN_SHM",    _SC_XOPEN_SHM}, | 
11536  |  | #endif  | 
11537  |  | #ifdef _SC_XOPEN_UNIX  | 
11538  |  |     {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX}, | 
11539  |  | #endif  | 
11540  |  | #ifdef _SC_XOPEN_VERSION  | 
11541  |  |     {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION}, | 
11542  |  | #endif  | 
11543  |  | #ifdef _SC_XOPEN_XCU_VERSION  | 
11544  |  |     {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION}, | 
11545  |  | #endif  | 
11546  |  | #ifdef _SC_XOPEN_XPG2  | 
11547  |  |     {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2}, | 
11548  |  | #endif  | 
11549  |  | #ifdef _SC_XOPEN_XPG3  | 
11550  |  |     {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3}, | 
11551  |  | #endif  | 
11552  |  | #ifdef _SC_XOPEN_XPG4  | 
11553  |  |     {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4}, | 
11554  |  | #endif  | 
11555  |  | };  | 
11556  |  |  | 
11557  |  | static int  | 
11558  |  | conv_sysconf_confname(PyObject *arg, int *valuep)  | 
11559  | 0  | { | 
11560  | 0  |     return conv_confname(arg, valuep, posix_constants_sysconf,  | 
11561  | 0  |                          sizeof(posix_constants_sysconf)  | 
11562  | 0  |                            / sizeof(struct constdef));  | 
11563  | 0  | }  | 
11564  |  |  | 
11565  |  |  | 
11566  |  | /*[clinic input]  | 
11567  |  | os.sysconf -> long  | 
11568  |  |     name: sysconf_confname  | 
11569  |  |     /  | 
11570  |  |  | 
11571  |  | Return an integer-valued system configuration variable.  | 
11572  |  | [clinic start generated code]*/  | 
11573  |  |  | 
11574  |  | static long  | 
11575  |  | os_sysconf_impl(PyObject *module, int name)  | 
11576  |  | /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/  | 
11577  | 0  | { | 
11578  | 0  |     long value;  | 
11579  |  | 
  | 
11580  | 0  |     errno = 0;  | 
11581  | 0  |     value = sysconf(name);  | 
11582  | 0  |     if (value == -1 && errno != 0)  | 
11583  | 0  |         posix_error();  | 
11584  | 0  |     return value;  | 
11585  | 0  | }  | 
11586  |  | #endif /* HAVE_SYSCONF */  | 
11587  |  |  | 
11588  |  |  | 
11589  |  | /* This code is used to ensure that the tables of configuration value names  | 
11590  |  |  * are in sorted order as required by conv_confname(), and also to build  | 
11591  |  |  * the exported dictionaries that are used to publish information about the  | 
11592  |  |  * names available on the host platform.  | 
11593  |  |  *  | 
11594  |  |  * Sorting the table at runtime ensures that the table is properly ordered  | 
11595  |  |  * when used, even for platforms we're not able to test on.  It also makes  | 
11596  |  |  * it easier to add additional entries to the tables.  | 
11597  |  |  */  | 
11598  |  |  | 
11599  |  | static int  | 
11600  |  | cmp_constdefs(const void *v1,  const void *v2)  | 
11601  | 7.93k  | { | 
11602  | 7.93k  |     const struct constdef *c1 =  | 
11603  | 7.93k  |     (const struct constdef *) v1;  | 
11604  | 7.93k  |     const struct constdef *c2 =  | 
11605  | 7.93k  |     (const struct constdef *) v2;  | 
11606  |  |  | 
11607  | 7.93k  |     return strcmp(c1->name, c2->name);  | 
11608  | 7.93k  | }  | 
11609  |  |  | 
11610  |  | static int  | 
11611  |  | setup_confname_table(struct constdef *table, size_t tablesize,  | 
11612  |  |                      const char *tablename, PyObject *module)  | 
11613  | 42  | { | 
11614  | 42  |     PyObject *d = NULL;  | 
11615  | 42  |     size_t i;  | 
11616  |  |  | 
11617  | 42  |     qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);  | 
11618  | 42  |     d = PyDict_New();  | 
11619  | 42  |     if (d == NULL)  | 
11620  | 0  |         return -1;  | 
11621  |  |  | 
11622  | 2.57k  |     for (i=0; i < tablesize; ++i) { | 
11623  | 2.53k  |         PyObject *o = PyLong_FromLong(table[i].value);  | 
11624  | 2.53k  |         if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) { | 
11625  | 0  |             Py_XDECREF(o);  | 
11626  | 0  |             Py_DECREF(d);  | 
11627  | 0  |             return -1;  | 
11628  | 0  |         }  | 
11629  | 2.53k  |         Py_DECREF(o);  | 
11630  | 2.53k  |     }  | 
11631  | 42  |     return PyModule_AddObject(module, tablename, d);  | 
11632  | 42  | }  | 
11633  |  |  | 
11634  |  | /* Return -1 on failure, 0 on success. */  | 
11635  |  | static int  | 
11636  |  | setup_confname_tables(PyObject *module)  | 
11637  | 14  | { | 
11638  | 14  | #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)  | 
11639  | 14  |     if (setup_confname_table(posix_constants_pathconf,  | 
11640  | 14  |                              sizeof(posix_constants_pathconf)  | 
11641  | 14  |                                / sizeof(struct constdef),  | 
11642  | 14  |                              "pathconf_names", module))  | 
11643  | 0  |         return -1;  | 
11644  | 14  | #endif  | 
11645  | 14  | #ifdef HAVE_CONFSTR  | 
11646  | 14  |     if (setup_confname_table(posix_constants_confstr,  | 
11647  | 14  |                              sizeof(posix_constants_confstr)  | 
11648  | 14  |                                / sizeof(struct constdef),  | 
11649  | 14  |                              "confstr_names", module))  | 
11650  | 0  |         return -1;  | 
11651  | 14  | #endif  | 
11652  | 14  | #ifdef HAVE_SYSCONF  | 
11653  | 14  |     if (setup_confname_table(posix_constants_sysconf,  | 
11654  | 14  |                              sizeof(posix_constants_sysconf)  | 
11655  | 14  |                                / sizeof(struct constdef),  | 
11656  | 14  |                              "sysconf_names", module))  | 
11657  | 0  |         return -1;  | 
11658  | 14  | #endif  | 
11659  | 14  |     return 0;  | 
11660  | 14  | }  | 
11661  |  |  | 
11662  |  |  | 
11663  |  | /*[clinic input]  | 
11664  |  | os.abort  | 
11665  |  |  | 
11666  |  | Abort the interpreter immediately.  | 
11667  |  |  | 
11668  |  | This function 'dumps core' or otherwise fails in the hardest way possible  | 
11669  |  | on the hosting operating system.  This function never returns.  | 
11670  |  | [clinic start generated code]*/  | 
11671  |  |  | 
11672  |  | static PyObject *  | 
11673  |  | os_abort_impl(PyObject *module)  | 
11674  |  | /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/  | 
11675  | 0  | { | 
11676  | 0  |     abort();  | 
11677  |  |     /*NOTREACHED*/  | 
11678  |  | #ifndef __clang__  | 
11679  |  |     /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).  | 
11680  |  |        GCC emits a warning without "return NULL;" (compiler bug?), but Clang  | 
11681  |  |        is smarter and emits a warning on the return. */  | 
11682  |  |     Py_FatalError("abort() called from Python code didn't abort!"); | 
11683  |  |     return NULL;  | 
11684  |  | #endif  | 
11685  | 0  | }  | 
11686  |  |  | 
11687  |  | #ifdef MS_WINDOWS  | 
11688  |  | /* Grab ShellExecute dynamically from shell32 */  | 
11689  |  | static int has_ShellExecute = -1;  | 
11690  |  | static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,  | 
11691  |  |                                               LPCWSTR, INT);  | 
11692  |  | static int  | 
11693  |  | check_ShellExecute()  | 
11694  |  | { | 
11695  |  |     HINSTANCE hShell32;  | 
11696  |  |  | 
11697  |  |     /* only recheck */  | 
11698  |  |     if (-1 == has_ShellExecute) { | 
11699  |  |         Py_BEGIN_ALLOW_THREADS  | 
11700  |  |         /* Security note: this call is not vulnerable to "DLL hijacking".  | 
11701  |  |            SHELL32 is part of "KnownDLLs" and so Windows always load  | 
11702  |  |            the system SHELL32.DLL, even if there is another SHELL32.DLL  | 
11703  |  |            in the DLL search path. */  | 
11704  |  |         hShell32 = LoadLibraryW(L"SHELL32");  | 
11705  |  |         if (hShell32) { | 
11706  |  |             *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,  | 
11707  |  |                                             "ShellExecuteW");  | 
11708  |  |             has_ShellExecute = Py_ShellExecuteW != NULL;  | 
11709  |  |         } else { | 
11710  |  |             has_ShellExecute = 0;  | 
11711  |  |         }  | 
11712  |  |         Py_END_ALLOW_THREADS  | 
11713  |  |     }  | 
11714  |  |     return has_ShellExecute;  | 
11715  |  | }  | 
11716  |  |  | 
11717  |  |  | 
11718  |  | /*[clinic input]  | 
11719  |  | os.startfile  | 
11720  |  |     filepath: path_t  | 
11721  |  |     operation: Py_UNICODE = NULL  | 
11722  |  |  | 
11723  |  | Start a file with its associated application.  | 
11724  |  |  | 
11725  |  | When "operation" is not specified or "open", this acts like  | 
11726  |  | double-clicking the file in Explorer, or giving the file name as an  | 
11727  |  | argument to the DOS "start" command: the file is opened with whatever  | 
11728  |  | application (if any) its extension is associated.  | 
11729  |  | When another "operation" is given, it specifies what should be done with  | 
11730  |  | the file.  A typical operation is "print".  | 
11731  |  |  | 
11732  |  | startfile returns as soon as the associated application is launched.  | 
11733  |  | There is no option to wait for the application to close, and no way  | 
11734  |  | to retrieve the application's exit status.  | 
11735  |  |  | 
11736  |  | The filepath is relative to the current directory.  If you want to use  | 
11737  |  | an absolute path, make sure the first character is not a slash ("/"); | 
11738  |  | the underlying Win32 ShellExecute function doesn't work if it is.  | 
11739  |  | [clinic start generated code]*/  | 
11740  |  |  | 
11741  |  | static PyObject *  | 
11742  |  | os_startfile_impl(PyObject *module, path_t *filepath,  | 
11743  |  |                   const Py_UNICODE *operation)  | 
11744  |  | /*[clinic end generated code: output=66dc311c94d50797 input=c940888a5390f039]*/  | 
11745  |  | { | 
11746  |  |     HINSTANCE rc;  | 
11747  |  |  | 
11748  |  |     if(!check_ShellExecute()) { | 
11749  |  |         /* If the OS doesn't have ShellExecute, return a  | 
11750  |  |            NotImplementedError. */  | 
11751  |  |         return PyErr_Format(PyExc_NotImplementedError,  | 
11752  |  |             "startfile not available on this platform");  | 
11753  |  |     }  | 
11754  |  |  | 
11755  |  |     if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) { | 
11756  |  |         return NULL;  | 
11757  |  |     }  | 
11758  |  |  | 
11759  |  |     Py_BEGIN_ALLOW_THREADS  | 
11760  |  |     rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,  | 
11761  |  |                           NULL, NULL, SW_SHOWNORMAL);  | 
11762  |  |     Py_END_ALLOW_THREADS  | 
11763  |  |  | 
11764  |  |     if (rc <= (HINSTANCE)32) { | 
11765  |  |         win32_error_object("startfile", filepath->object); | 
11766  |  |         return NULL;  | 
11767  |  |     }  | 
11768  |  |     Py_RETURN_NONE;  | 
11769  |  | }  | 
11770  |  | #endif /* MS_WINDOWS */  | 
11771  |  |  | 
11772  |  |  | 
11773  |  | #ifdef HAVE_GETLOADAVG  | 
11774  |  | /*[clinic input]  | 
11775  |  | os.getloadavg  | 
11776  |  |  | 
11777  |  | Return average recent system load information.  | 
11778  |  |  | 
11779  |  | Return the number of processes in the system run queue averaged over  | 
11780  |  | the last 1, 5, and 15 minutes as a tuple of three floats.  | 
11781  |  | Raises OSError if the load average was unobtainable.  | 
11782  |  | [clinic start generated code]*/  | 
11783  |  |  | 
11784  |  | static PyObject *  | 
11785  |  | os_getloadavg_impl(PyObject *module)  | 
11786  |  | /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/  | 
11787  | 0  | { | 
11788  | 0  |     double loadavg[3];  | 
11789  | 0  |     if (getloadavg(loadavg, 3)!=3) { | 
11790  | 0  |         PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");  | 
11791  | 0  |         return NULL;  | 
11792  | 0  |     } else  | 
11793  | 0  |         return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]); | 
11794  | 0  | }  | 
11795  |  | #endif /* HAVE_GETLOADAVG */  | 
11796  |  |  | 
11797  |  |  | 
11798  |  | /*[clinic input]  | 
11799  |  | os.device_encoding  | 
11800  |  |     fd: int  | 
11801  |  |  | 
11802  |  | Return a string describing the encoding of a terminal's file descriptor.  | 
11803  |  |  | 
11804  |  | The file descriptor must be attached to a terminal.  | 
11805  |  | If the device is not a terminal, return None.  | 
11806  |  | [clinic start generated code]*/  | 
11807  |  |  | 
11808  |  | static PyObject *  | 
11809  |  | os_device_encoding_impl(PyObject *module, int fd)  | 
11810  |  | /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/  | 
11811  | 0  | { | 
11812  | 0  |     return _Py_device_encoding(fd);  | 
11813  | 0  | }  | 
11814  |  |  | 
11815  |  |  | 
11816  |  | #ifdef HAVE_SETRESUID  | 
11817  |  | /*[clinic input]  | 
11818  |  | os.setresuid  | 
11819  |  |  | 
11820  |  |     ruid: uid_t  | 
11821  |  |     euid: uid_t  | 
11822  |  |     suid: uid_t  | 
11823  |  |     /  | 
11824  |  |  | 
11825  |  | Set the current process's real, effective, and saved user ids.  | 
11826  |  | [clinic start generated code]*/  | 
11827  |  |  | 
11828  |  | static PyObject *  | 
11829  |  | os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)  | 
11830  |  | /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/  | 
11831  | 0  | { | 
11832  | 0  |     if (setresuid(ruid, euid, suid) < 0)  | 
11833  | 0  |         return posix_error();  | 
11834  | 0  |     Py_RETURN_NONE;  | 
11835  | 0  | }  | 
11836  |  | #endif /* HAVE_SETRESUID */  | 
11837  |  |  | 
11838  |  |  | 
11839  |  | #ifdef HAVE_SETRESGID  | 
11840  |  | /*[clinic input]  | 
11841  |  | os.setresgid  | 
11842  |  |  | 
11843  |  |     rgid: gid_t  | 
11844  |  |     egid: gid_t  | 
11845  |  |     sgid: gid_t  | 
11846  |  |     /  | 
11847  |  |  | 
11848  |  | Set the current process's real, effective, and saved group ids.  | 
11849  |  | [clinic start generated code]*/  | 
11850  |  |  | 
11851  |  | static PyObject *  | 
11852  |  | os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)  | 
11853  |  | /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/  | 
11854  | 0  | { | 
11855  | 0  |     if (setresgid(rgid, egid, sgid) < 0)  | 
11856  | 0  |         return posix_error();  | 
11857  | 0  |     Py_RETURN_NONE;  | 
11858  | 0  | }  | 
11859  |  | #endif /* HAVE_SETRESGID */  | 
11860  |  |  | 
11861  |  |  | 
11862  |  | #ifdef HAVE_GETRESUID  | 
11863  |  | /*[clinic input]  | 
11864  |  | os.getresuid  | 
11865  |  |  | 
11866  |  | Return a tuple of the current process's real, effective, and saved user ids.  | 
11867  |  | [clinic start generated code]*/  | 
11868  |  |  | 
11869  |  | static PyObject *  | 
11870  |  | os_getresuid_impl(PyObject *module)  | 
11871  |  | /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/  | 
11872  | 0  | { | 
11873  | 0  |     uid_t ruid, euid, suid;  | 
11874  | 0  |     if (getresuid(&ruid, &euid, &suid) < 0)  | 
11875  | 0  |         return posix_error();  | 
11876  | 0  |     return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid), | 
11877  | 0  |                                   _PyLong_FromUid(euid),  | 
11878  | 0  |                                   _PyLong_FromUid(suid));  | 
11879  | 0  | }  | 
11880  |  | #endif /* HAVE_GETRESUID */  | 
11881  |  |  | 
11882  |  |  | 
11883  |  | #ifdef HAVE_GETRESGID  | 
11884  |  | /*[clinic input]  | 
11885  |  | os.getresgid  | 
11886  |  |  | 
11887  |  | Return a tuple of the current process's real, effective, and saved group ids.  | 
11888  |  | [clinic start generated code]*/  | 
11889  |  |  | 
11890  |  | static PyObject *  | 
11891  |  | os_getresgid_impl(PyObject *module)  | 
11892  |  | /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/  | 
11893  | 0  | { | 
11894  | 0  |     gid_t rgid, egid, sgid;  | 
11895  | 0  |     if (getresgid(&rgid, &egid, &sgid) < 0)  | 
11896  | 0  |         return posix_error();  | 
11897  | 0  |     return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid), | 
11898  | 0  |                                   _PyLong_FromGid(egid),  | 
11899  | 0  |                                   _PyLong_FromGid(sgid));  | 
11900  | 0  | }  | 
11901  |  | #endif /* HAVE_GETRESGID */  | 
11902  |  |  | 
11903  |  |  | 
11904  |  | #ifdef USE_XATTRS  | 
11905  |  | /*[clinic input]  | 
11906  |  | os.getxattr  | 
11907  |  |  | 
11908  |  |     path: path_t(allow_fd=True)  | 
11909  |  |     attribute: path_t  | 
11910  |  |     *  | 
11911  |  |     follow_symlinks: bool = True  | 
11912  |  |  | 
11913  |  | Return the value of extended attribute attribute on path.  | 
11914  |  |  | 
11915  |  | path may be either a string, a path-like object, or an open file descriptor.  | 
11916  |  | If follow_symlinks is False, and the last element of the path is a symbolic  | 
11917  |  |   link, getxattr will examine the symbolic link itself instead of the file  | 
11918  |  |   the link points to.  | 
11919  |  |  | 
11920  |  | [clinic start generated code]*/  | 
11921  |  |  | 
11922  |  | static PyObject *  | 
11923  |  | os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,  | 
11924  |  |                  int follow_symlinks)  | 
11925  |  | /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/  | 
11926  | 0  | { | 
11927  | 0  |     Py_ssize_t i;  | 
11928  | 0  |     PyObject *buffer = NULL;  | 
11929  |  | 
  | 
11930  | 0  |     if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks)) | 
11931  | 0  |         return NULL;  | 
11932  |  |  | 
11933  | 0  |     if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) { | 
11934  | 0  |         return NULL;  | 
11935  | 0  |     }  | 
11936  |  |  | 
11937  | 0  |     for (i = 0; ; i++) { | 
11938  | 0  |         void *ptr;  | 
11939  | 0  |         ssize_t result;  | 
11940  | 0  |         static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0}; | 
11941  | 0  |         Py_ssize_t buffer_size = buffer_sizes[i];  | 
11942  | 0  |         if (!buffer_size) { | 
11943  | 0  |             path_error(path);  | 
11944  | 0  |             return NULL;  | 
11945  | 0  |         }  | 
11946  | 0  |         buffer = PyBytes_FromStringAndSize(NULL, buffer_size);  | 
11947  | 0  |         if (!buffer)  | 
11948  | 0  |             return NULL;  | 
11949  | 0  |         ptr = PyBytes_AS_STRING(buffer);  | 
11950  |  | 
  | 
11951  | 0  |         Py_BEGIN_ALLOW_THREADS;  | 
11952  | 0  |         if (path->fd >= 0)  | 
11953  | 0  |             result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);  | 
11954  | 0  |         else if (follow_symlinks)  | 
11955  | 0  |             result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);  | 
11956  | 0  |         else  | 
11957  | 0  |             result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);  | 
11958  | 0  |         Py_END_ALLOW_THREADS;  | 
11959  |  | 
  | 
11960  | 0  |         if (result < 0) { | 
11961  | 0  |             Py_DECREF(buffer);  | 
11962  | 0  |             if (errno == ERANGE)  | 
11963  | 0  |                 continue;  | 
11964  | 0  |             path_error(path);  | 
11965  | 0  |             return NULL;  | 
11966  | 0  |         }  | 
11967  |  |  | 
11968  | 0  |         if (result != buffer_size) { | 
11969  |  |             /* Can only shrink. */  | 
11970  | 0  |             _PyBytes_Resize(&buffer, result);  | 
11971  | 0  |         }  | 
11972  | 0  |         break;  | 
11973  | 0  |     }  | 
11974  |  |  | 
11975  | 0  |     return buffer;  | 
11976  | 0  | }  | 
11977  |  |  | 
11978  |  |  | 
11979  |  | /*[clinic input]  | 
11980  |  | os.setxattr  | 
11981  |  |  | 
11982  |  |     path: path_t(allow_fd=True)  | 
11983  |  |     attribute: path_t  | 
11984  |  |     value: Py_buffer  | 
11985  |  |     flags: int = 0  | 
11986  |  |     *  | 
11987  |  |     follow_symlinks: bool = True  | 
11988  |  |  | 
11989  |  | Set extended attribute attribute on path to value.  | 
11990  |  |  | 
11991  |  | path may be either a string, a path-like object,  or an open file descriptor.  | 
11992  |  | If follow_symlinks is False, and the last element of the path is a symbolic  | 
11993  |  |   link, setxattr will modify the symbolic link itself instead of the file  | 
11994  |  |   the link points to.  | 
11995  |  |  | 
11996  |  | [clinic start generated code]*/  | 
11997  |  |  | 
11998  |  | static PyObject *  | 
11999  |  | os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,  | 
12000  |  |                  Py_buffer *value, int flags, int follow_symlinks)  | 
12001  |  | /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/  | 
12002  | 0  | { | 
12003  | 0  |     ssize_t result;  | 
12004  |  | 
  | 
12005  | 0  |     if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks)) | 
12006  | 0  |         return NULL;  | 
12007  |  |  | 
12008  | 0  |     if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object, | 
12009  | 0  |                     value->buf, value->len, flags) < 0) { | 
12010  | 0  |         return NULL;  | 
12011  | 0  |     }  | 
12012  |  |  | 
12013  | 0  |     Py_BEGIN_ALLOW_THREADS;  | 
12014  | 0  |     if (path->fd > -1)  | 
12015  | 0  |         result = fsetxattr(path->fd, attribute->narrow,  | 
12016  | 0  |                            value->buf, value->len, flags);  | 
12017  | 0  |     else if (follow_symlinks)  | 
12018  | 0  |         result = setxattr(path->narrow, attribute->narrow,  | 
12019  | 0  |                            value->buf, value->len, flags);  | 
12020  | 0  |     else  | 
12021  | 0  |         result = lsetxattr(path->narrow, attribute->narrow,  | 
12022  | 0  |                            value->buf, value->len, flags);  | 
12023  | 0  |     Py_END_ALLOW_THREADS;  | 
12024  |  | 
  | 
12025  | 0  |     if (result) { | 
12026  | 0  |         path_error(path);  | 
12027  | 0  |         return NULL;  | 
12028  | 0  |     }  | 
12029  |  |  | 
12030  | 0  |     Py_RETURN_NONE;  | 
12031  | 0  | }  | 
12032  |  |  | 
12033  |  |  | 
12034  |  | /*[clinic input]  | 
12035  |  | os.removexattr  | 
12036  |  |  | 
12037  |  |     path: path_t(allow_fd=True)  | 
12038  |  |     attribute: path_t  | 
12039  |  |     *  | 
12040  |  |     follow_symlinks: bool = True  | 
12041  |  |  | 
12042  |  | Remove extended attribute attribute on path.  | 
12043  |  |  | 
12044  |  | path may be either a string, a path-like object, or an open file descriptor.  | 
12045  |  | If follow_symlinks is False, and the last element of the path is a symbolic  | 
12046  |  |   link, removexattr will modify the symbolic link itself instead of the file  | 
12047  |  |   the link points to.  | 
12048  |  |  | 
12049  |  | [clinic start generated code]*/  | 
12050  |  |  | 
12051  |  | static PyObject *  | 
12052  |  | os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,  | 
12053  |  |                     int follow_symlinks)  | 
12054  |  | /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/  | 
12055  | 0  | { | 
12056  | 0  |     ssize_t result;  | 
12057  |  | 
  | 
12058  | 0  |     if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks)) | 
12059  | 0  |         return NULL;  | 
12060  |  |  | 
12061  | 0  |     if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) { | 
12062  | 0  |         return NULL;  | 
12063  | 0  |     }  | 
12064  |  |  | 
12065  | 0  |     Py_BEGIN_ALLOW_THREADS;  | 
12066  | 0  |     if (path->fd > -1)  | 
12067  | 0  |         result = fremovexattr(path->fd, attribute->narrow);  | 
12068  | 0  |     else if (follow_symlinks)  | 
12069  | 0  |         result = removexattr(path->narrow, attribute->narrow);  | 
12070  | 0  |     else  | 
12071  | 0  |         result = lremovexattr(path->narrow, attribute->narrow);  | 
12072  | 0  |     Py_END_ALLOW_THREADS;  | 
12073  |  | 
  | 
12074  | 0  |     if (result) { | 
12075  | 0  |         return path_error(path);  | 
12076  | 0  |     }  | 
12077  |  |  | 
12078  | 0  |     Py_RETURN_NONE;  | 
12079  | 0  | }  | 
12080  |  |  | 
12081  |  |  | 
12082  |  | /*[clinic input]  | 
12083  |  | os.listxattr  | 
12084  |  |  | 
12085  |  |     path: path_t(allow_fd=True, nullable=True) = None  | 
12086  |  |     *  | 
12087  |  |     follow_symlinks: bool = True  | 
12088  |  |  | 
12089  |  | Return a list of extended attributes on path.  | 
12090  |  |  | 
12091  |  | path may be either None, a string, a path-like object, or an open file descriptor.  | 
12092  |  | if path is None, listxattr will examine the current directory.  | 
12093  |  | If follow_symlinks is False, and the last element of the path is a symbolic  | 
12094  |  |   link, listxattr will examine the symbolic link itself instead of the file  | 
12095  |  |   the link points to.  | 
12096  |  | [clinic start generated code]*/  | 
12097  |  |  | 
12098  |  | static PyObject *  | 
12099  |  | os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)  | 
12100  |  | /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/  | 
12101  | 0  | { | 
12102  | 0  |     Py_ssize_t i;  | 
12103  | 0  |     PyObject *result = NULL;  | 
12104  | 0  |     const char *name;  | 
12105  | 0  |     char *buffer = NULL;  | 
12106  |  | 
  | 
12107  | 0  |     if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks)) | 
12108  | 0  |         goto exit;  | 
12109  |  |  | 
12110  | 0  |     if (PySys_Audit("os.listxattr", "(O)", | 
12111  | 0  |                     path->object ? path->object : Py_None) < 0) { | 
12112  | 0  |         return NULL;  | 
12113  | 0  |     }  | 
12114  |  |  | 
12115  | 0  |     name = path->narrow ? path->narrow : ".";  | 
12116  |  | 
  | 
12117  | 0  |     for (i = 0; ; i++) { | 
12118  | 0  |         const char *start, *trace, *end;  | 
12119  | 0  |         ssize_t length;  | 
12120  | 0  |         static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 }; | 
12121  | 0  |         Py_ssize_t buffer_size = buffer_sizes[i];  | 
12122  | 0  |         if (!buffer_size) { | 
12123  |  |             /* ERANGE */  | 
12124  | 0  |             path_error(path);  | 
12125  | 0  |             break;  | 
12126  | 0  |         }  | 
12127  | 0  |         buffer = PyMem_MALLOC(buffer_size);  | 
12128  | 0  |         if (!buffer) { | 
12129  | 0  |             PyErr_NoMemory();  | 
12130  | 0  |             break;  | 
12131  | 0  |         }  | 
12132  |  |  | 
12133  | 0  |         Py_BEGIN_ALLOW_THREADS;  | 
12134  | 0  |         if (path->fd > -1)  | 
12135  | 0  |             length = flistxattr(path->fd, buffer, buffer_size);  | 
12136  | 0  |         else if (follow_symlinks)  | 
12137  | 0  |             length = listxattr(name, buffer, buffer_size);  | 
12138  | 0  |         else  | 
12139  | 0  |             length = llistxattr(name, buffer, buffer_size);  | 
12140  | 0  |         Py_END_ALLOW_THREADS;  | 
12141  |  | 
  | 
12142  | 0  |         if (length < 0) { | 
12143  | 0  |             if (errno == ERANGE) { | 
12144  | 0  |                 PyMem_FREE(buffer);  | 
12145  | 0  |                 buffer = NULL;  | 
12146  | 0  |                 continue;  | 
12147  | 0  |             }  | 
12148  | 0  |             path_error(path);  | 
12149  | 0  |             break;  | 
12150  | 0  |         }  | 
12151  |  |  | 
12152  | 0  |         result = PyList_New(0);  | 
12153  | 0  |         if (!result) { | 
12154  | 0  |             goto exit;  | 
12155  | 0  |         }  | 
12156  |  |  | 
12157  | 0  |         end = buffer + length;  | 
12158  | 0  |         for (trace = start = buffer; trace != end; trace++) { | 
12159  | 0  |             if (!*trace) { | 
12160  | 0  |                 int error;  | 
12161  | 0  |                 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,  | 
12162  | 0  |                                                                  trace - start);  | 
12163  | 0  |                 if (!attribute) { | 
12164  | 0  |                     Py_DECREF(result);  | 
12165  | 0  |                     result = NULL;  | 
12166  | 0  |                     goto exit;  | 
12167  | 0  |                 }  | 
12168  | 0  |                 error = PyList_Append(result, attribute);  | 
12169  | 0  |                 Py_DECREF(attribute);  | 
12170  | 0  |                 if (error) { | 
12171  | 0  |                     Py_DECREF(result);  | 
12172  | 0  |                     result = NULL;  | 
12173  | 0  |                     goto exit;  | 
12174  | 0  |                 }  | 
12175  | 0  |                 start = trace + 1;  | 
12176  | 0  |             }  | 
12177  | 0  |         }  | 
12178  | 0  |     break;  | 
12179  | 0  |     }  | 
12180  | 0  | exit:  | 
12181  | 0  |     if (buffer)  | 
12182  | 0  |         PyMem_FREE(buffer);  | 
12183  | 0  |     return result;  | 
12184  | 0  | }  | 
12185  |  | #endif /* USE_XATTRS */  | 
12186  |  |  | 
12187  |  |  | 
12188  |  | /*[clinic input]  | 
12189  |  | os.urandom  | 
12190  |  |  | 
12191  |  |     size: Py_ssize_t  | 
12192  |  |     /  | 
12193  |  |  | 
12194  |  | Return a bytes object containing random bytes suitable for cryptographic use.  | 
12195  |  | [clinic start generated code]*/  | 
12196  |  |  | 
12197  |  | static PyObject *  | 
12198  |  | os_urandom_impl(PyObject *module, Py_ssize_t size)  | 
12199  |  | /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/  | 
12200  | 0  | { | 
12201  | 0  |     PyObject *bytes;  | 
12202  | 0  |     int result;  | 
12203  |  | 
  | 
12204  | 0  |     if (size < 0)  | 
12205  | 0  |         return PyErr_Format(PyExc_ValueError,  | 
12206  | 0  |                             "negative argument not allowed");  | 
12207  | 0  |     bytes = PyBytes_FromStringAndSize(NULL, size);  | 
12208  | 0  |     if (bytes == NULL)  | 
12209  | 0  |         return NULL;  | 
12210  |  |  | 
12211  | 0  |     result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));  | 
12212  | 0  |     if (result == -1) { | 
12213  | 0  |         Py_DECREF(bytes);  | 
12214  | 0  |         return NULL;  | 
12215  | 0  |     }  | 
12216  | 0  |     return bytes;  | 
12217  | 0  | }  | 
12218  |  |  | 
12219  |  | #ifdef HAVE_MEMFD_CREATE  | 
12220  |  | /*[clinic input]  | 
12221  |  | os.memfd_create  | 
12222  |  |  | 
12223  |  |     name: FSConverter  | 
12224  |  |     flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC  | 
12225  |  |  | 
12226  |  | [clinic start generated code]*/  | 
12227  |  |  | 
12228  |  | static PyObject *  | 
12229  |  | os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)  | 
12230  |  | /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/  | 
12231  | 0  | { | 
12232  | 0  |     int fd;  | 
12233  | 0  |     const char *bytes = PyBytes_AS_STRING(name);  | 
12234  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
12235  | 0  |     fd = memfd_create(bytes, flags);  | 
12236  | 0  |     Py_END_ALLOW_THREADS  | 
12237  | 0  |     if (fd == -1) { | 
12238  | 0  |         return PyErr_SetFromErrno(PyExc_OSError);  | 
12239  | 0  |     }  | 
12240  | 0  |     return PyLong_FromLong(fd);  | 
12241  | 0  | }  | 
12242  |  | #endif  | 
12243  |  |  | 
12244  |  | /* Terminal size querying */  | 
12245  |  |  | 
12246  |  | static PyTypeObject* TerminalSizeType;  | 
12247  |  |  | 
12248  |  | PyDoc_STRVAR(TerminalSize_docstring,  | 
12249  |  |     "A tuple of (columns, lines) for holding terminal window size");  | 
12250  |  |  | 
12251  |  | static PyStructSequence_Field TerminalSize_fields[] = { | 
12252  |  |     {"columns", "width of the terminal window in characters"}, | 
12253  |  |     {"lines", "height of the terminal window in characters"}, | 
12254  |  |     {NULL, NULL} | 
12255  |  | };  | 
12256  |  |  | 
12257  |  | static PyStructSequence_Desc TerminalSize_desc = { | 
12258  |  |     "os.terminal_size",  | 
12259  |  |     TerminalSize_docstring,  | 
12260  |  |     TerminalSize_fields,  | 
12261  |  |     2,  | 
12262  |  | };  | 
12263  |  |  | 
12264  |  | #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)  | 
12265  |  | /* AC 3.5: fd should accept None */  | 
12266  |  | PyDoc_STRVAR(termsize__doc__,  | 
12267  |  |     "Return the size of the terminal window as (columns, lines).\n"        \  | 
12268  |  |     "\n"                                                                   \  | 
12269  |  |     "The optional argument fd (default standard output) specifies\n"       \  | 
12270  |  |     "which file descriptor should be queried.\n"                           \  | 
12271  |  |     "\n"                                                                   \  | 
12272  |  |     "If the file descriptor is not connected to a terminal, an OSError\n"  \  | 
12273  |  |     "is thrown.\n"                                                         \  | 
12274  |  |     "\n"                                                                   \  | 
12275  |  |     "This function will only be defined if an implementation is\n"         \  | 
12276  |  |     "available for this system.\n"                                         \  | 
12277  |  |     "\n"                                                                   \  | 
12278  |  |     "shutil.get_terminal_size is the high-level function which should\n"  \  | 
12279  |  |     "normally be used, os.get_terminal_size is the low-level implementation.");  | 
12280  |  |  | 
12281  |  | static PyObject*  | 
12282  |  | get_terminal_size(PyObject *self, PyObject *args)  | 
12283  | 0  | { | 
12284  | 0  |     int columns, lines;  | 
12285  | 0  |     PyObject *termsize;  | 
12286  |  | 
  | 
12287  | 0  |     int fd = fileno(stdout);  | 
12288  |  |     /* Under some conditions stdout may not be connected and  | 
12289  |  |      * fileno(stdout) may point to an invalid file descriptor. For example  | 
12290  |  |      * GUI apps don't have valid standard streams by default.  | 
12291  |  |      *  | 
12292  |  |      * If this happens, and the optional fd argument is not present,  | 
12293  |  |      * the ioctl below will fail returning EBADF. This is what we want.  | 
12294  |  |      */  | 
12295  |  | 
  | 
12296  | 0  |     if (!PyArg_ParseTuple(args, "|i", &fd))  | 
12297  | 0  |         return NULL;  | 
12298  |  |  | 
12299  | 0  | #ifdef TERMSIZE_USE_IOCTL  | 
12300  | 0  |     { | 
12301  | 0  |         struct winsize w;  | 
12302  | 0  |         if (ioctl(fd, TIOCGWINSZ, &w))  | 
12303  | 0  |             return PyErr_SetFromErrno(PyExc_OSError);  | 
12304  | 0  |         columns = w.ws_col;  | 
12305  | 0  |         lines = w.ws_row;  | 
12306  | 0  |     }  | 
12307  | 0  | #endif /* TERMSIZE_USE_IOCTL */  | 
12308  |  |  | 
12309  |  | #ifdef TERMSIZE_USE_CONIO  | 
12310  |  |     { | 
12311  |  |         DWORD nhandle;  | 
12312  |  |         HANDLE handle;  | 
12313  |  |         CONSOLE_SCREEN_BUFFER_INFO csbi;  | 
12314  |  |         switch (fd) { | 
12315  |  |         case 0: nhandle = STD_INPUT_HANDLE;  | 
12316  |  |             break;  | 
12317  |  |         case 1: nhandle = STD_OUTPUT_HANDLE;  | 
12318  |  |             break;  | 
12319  |  |         case 2: nhandle = STD_ERROR_HANDLE;  | 
12320  |  |             break;  | 
12321  |  |         default:  | 
12322  |  |             return PyErr_Format(PyExc_ValueError, "bad file descriptor");  | 
12323  |  |         }  | 
12324  |  |         handle = GetStdHandle(nhandle);  | 
12325  |  |         if (handle == NULL)  | 
12326  |  |             return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");  | 
12327  |  |         if (handle == INVALID_HANDLE_VALUE)  | 
12328  |  |             return PyErr_SetFromWindowsErr(0);  | 
12329  |  |  | 
12330  |  |         if (!GetConsoleScreenBufferInfo(handle, &csbi))  | 
12331  |  |             return PyErr_SetFromWindowsErr(0);  | 
12332  |  |  | 
12333  |  |         columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;  | 
12334  |  |         lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;  | 
12335  |  |     }  | 
12336  |  | #endif /* TERMSIZE_USE_CONIO */  | 
12337  |  |  | 
12338  | 0  |     termsize = PyStructSequence_New(TerminalSizeType);  | 
12339  | 0  |     if (termsize == NULL)  | 
12340  | 0  |         return NULL;  | 
12341  | 0  |     PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));  | 
12342  | 0  |     PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));  | 
12343  | 0  |     if (PyErr_Occurred()) { | 
12344  | 0  |         Py_DECREF(termsize);  | 
12345  | 0  |         return NULL;  | 
12346  | 0  |     }  | 
12347  | 0  |     return termsize;  | 
12348  | 0  | }  | 
12349  |  | #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */  | 
12350  |  |  | 
12351  |  |  | 
12352  |  | /*[clinic input]  | 
12353  |  | os.cpu_count  | 
12354  |  |  | 
12355  |  | Return the number of CPUs in the system; return None if indeterminable.  | 
12356  |  |  | 
12357  |  | This number is not equivalent to the number of CPUs the current process can  | 
12358  |  | use.  The number of usable CPUs can be obtained with  | 
12359  |  | ``len(os.sched_getaffinity(0))``  | 
12360  |  | [clinic start generated code]*/  | 
12361  |  |  | 
12362  |  | static PyObject *  | 
12363  |  | os_cpu_count_impl(PyObject *module)  | 
12364  |  | /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/  | 
12365  | 0  | { | 
12366  | 0  |     int ncpu = 0;  | 
12367  |  | #ifdef MS_WINDOWS  | 
12368  |  |     /* Declare prototype here to avoid pulling in all of the Win7 APIs in 3.8 */  | 
12369  |  |     DWORD WINAPI GetActiveProcessorCount(WORD group);  | 
12370  |  |     ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);  | 
12371  |  | #elif defined(__hpux)  | 
12372  |  |     ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);  | 
12373  |  | #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)  | 
12374  | 0  |     ncpu = sysconf(_SC_NPROCESSORS_ONLN);  | 
12375  |  | #elif defined(__DragonFly__) || \  | 
12376  |  |       defined(__OpenBSD__)   || \  | 
12377  |  |       defined(__FreeBSD__)   || \  | 
12378  |  |       defined(__NetBSD__)    || \  | 
12379  |  |       defined(__APPLE__)  | 
12380  |  |     int mib[2];  | 
12381  |  |     size_t len = sizeof(ncpu);  | 
12382  |  |     mib[0] = CTL_HW;  | 
12383  |  |     mib[1] = HW_NCPU;  | 
12384  |  |     if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)  | 
12385  |  |         ncpu = 0;  | 
12386  |  | #endif  | 
12387  | 0  |     if (ncpu >= 1)  | 
12388  | 0  |         return PyLong_FromLong(ncpu);  | 
12389  | 0  |     else  | 
12390  | 0  |         Py_RETURN_NONE;  | 
12391  | 0  | }  | 
12392  |  |  | 
12393  |  |  | 
12394  |  | /*[clinic input]  | 
12395  |  | os.get_inheritable -> bool  | 
12396  |  |  | 
12397  |  |     fd: int  | 
12398  |  |     /  | 
12399  |  |  | 
12400  |  | Get the close-on-exe flag of the specified file descriptor.  | 
12401  |  | [clinic start generated code]*/  | 
12402  |  |  | 
12403  |  | static int  | 
12404  |  | os_get_inheritable_impl(PyObject *module, int fd)  | 
12405  |  | /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/  | 
12406  | 0  | { | 
12407  | 0  |     int return_value;  | 
12408  | 0  |     _Py_BEGIN_SUPPRESS_IPH  | 
12409  | 0  |     return_value = _Py_get_inheritable(fd);  | 
12410  | 0  |     _Py_END_SUPPRESS_IPH  | 
12411  | 0  |     return return_value;  | 
12412  | 0  | }  | 
12413  |  |  | 
12414  |  |  | 
12415  |  | /*[clinic input]  | 
12416  |  | os.set_inheritable  | 
12417  |  |     fd: int  | 
12418  |  |     inheritable: int  | 
12419  |  |     /  | 
12420  |  |  | 
12421  |  | Set the inheritable flag of the specified file descriptor.  | 
12422  |  | [clinic start generated code]*/  | 
12423  |  |  | 
12424  |  | static PyObject *  | 
12425  |  | os_set_inheritable_impl(PyObject *module, int fd, int inheritable)  | 
12426  |  | /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/  | 
12427  | 0  | { | 
12428  | 0  |     int result;  | 
12429  |  | 
  | 
12430  | 0  |     _Py_BEGIN_SUPPRESS_IPH  | 
12431  | 0  |     result = _Py_set_inheritable(fd, inheritable, NULL);  | 
12432  | 0  |     _Py_END_SUPPRESS_IPH  | 
12433  | 0  |     if (result < 0)  | 
12434  | 0  |         return NULL;  | 
12435  | 0  |     Py_RETURN_NONE;  | 
12436  | 0  | }  | 
12437  |  |  | 
12438  |  |  | 
12439  |  | #ifdef MS_WINDOWS  | 
12440  |  | /*[clinic input]  | 
12441  |  | os.get_handle_inheritable -> bool  | 
12442  |  |     handle: intptr_t  | 
12443  |  |     /  | 
12444  |  |  | 
12445  |  | Get the close-on-exe flag of the specified file descriptor.  | 
12446  |  | [clinic start generated code]*/  | 
12447  |  |  | 
12448  |  | static int  | 
12449  |  | os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)  | 
12450  |  | /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/  | 
12451  |  | { | 
12452  |  |     DWORD flags;  | 
12453  |  |  | 
12454  |  |     if (!GetHandleInformation((HANDLE)handle, &flags)) { | 
12455  |  |         PyErr_SetFromWindowsErr(0);  | 
12456  |  |         return -1;  | 
12457  |  |     }  | 
12458  |  |  | 
12459  |  |     return flags & HANDLE_FLAG_INHERIT;  | 
12460  |  | }  | 
12461  |  |  | 
12462  |  |  | 
12463  |  | /*[clinic input]  | 
12464  |  | os.set_handle_inheritable  | 
12465  |  |     handle: intptr_t  | 
12466  |  |     inheritable: bool  | 
12467  |  |     /  | 
12468  |  |  | 
12469  |  | Set the inheritable flag of the specified handle.  | 
12470  |  | [clinic start generated code]*/  | 
12471  |  |  | 
12472  |  | static PyObject *  | 
12473  |  | os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,  | 
12474  |  |                                int inheritable)  | 
12475  |  | /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/  | 
12476  |  | { | 
12477  |  |     DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;  | 
12478  |  |     if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) { | 
12479  |  |         PyErr_SetFromWindowsErr(0);  | 
12480  |  |         return NULL;  | 
12481  |  |     }  | 
12482  |  |     Py_RETURN_NONE;  | 
12483  |  | }  | 
12484  |  | #endif /* MS_WINDOWS */  | 
12485  |  |  | 
12486  |  | #ifndef MS_WINDOWS  | 
12487  |  | /*[clinic input]  | 
12488  |  | os.get_blocking -> bool  | 
12489  |  |     fd: int  | 
12490  |  |     /  | 
12491  |  |  | 
12492  |  | Get the blocking mode of the file descriptor.  | 
12493  |  |  | 
12494  |  | Return False if the O_NONBLOCK flag is set, True if the flag is cleared.  | 
12495  |  | [clinic start generated code]*/  | 
12496  |  |  | 
12497  |  | static int  | 
12498  |  | os_get_blocking_impl(PyObject *module, int fd)  | 
12499  |  | /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/  | 
12500  | 0  | { | 
12501  | 0  |     int blocking;  | 
12502  |  | 
  | 
12503  | 0  |     _Py_BEGIN_SUPPRESS_IPH  | 
12504  | 0  |     blocking = _Py_get_blocking(fd);  | 
12505  | 0  |     _Py_END_SUPPRESS_IPH  | 
12506  | 0  |     return blocking;  | 
12507  | 0  | }  | 
12508  |  |  | 
12509  |  | /*[clinic input]  | 
12510  |  | os.set_blocking  | 
12511  |  |     fd: int  | 
12512  |  |     blocking: bool(accept={int}) | 
12513  |  |     /  | 
12514  |  |  | 
12515  |  | Set the blocking mode of the specified file descriptor.  | 
12516  |  |  | 
12517  |  | Set the O_NONBLOCK flag if blocking is False,  | 
12518  |  | clear the O_NONBLOCK flag otherwise.  | 
12519  |  | [clinic start generated code]*/  | 
12520  |  |  | 
12521  |  | static PyObject *  | 
12522  |  | os_set_blocking_impl(PyObject *module, int fd, int blocking)  | 
12523  |  | /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/  | 
12524  | 0  | { | 
12525  | 0  |     int result;  | 
12526  |  | 
  | 
12527  | 0  |     _Py_BEGIN_SUPPRESS_IPH  | 
12528  | 0  |     result = _Py_set_blocking(fd, blocking);  | 
12529  | 0  |     _Py_END_SUPPRESS_IPH  | 
12530  | 0  |     if (result < 0)  | 
12531  | 0  |         return NULL;  | 
12532  | 0  |     Py_RETURN_NONE;  | 
12533  | 0  | }  | 
12534  |  | #endif   /* !MS_WINDOWS */  | 
12535  |  |  | 
12536  |  |  | 
12537  |  | /*[clinic input]  | 
12538  |  | class os.DirEntry "DirEntry *" "&DirEntryType"  | 
12539  |  | [clinic start generated code]*/  | 
12540  |  | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3138f09f7c683f1d]*/  | 
12541  |  |  | 
12542  |  | typedef struct { | 
12543  |  |     PyObject_HEAD  | 
12544  |  |     PyObject *name;  | 
12545  |  |     PyObject *path;  | 
12546  |  |     PyObject *stat;  | 
12547  |  |     PyObject *lstat;  | 
12548  |  | #ifdef MS_WINDOWS  | 
12549  |  |     struct _Py_stat_struct win32_lstat;  | 
12550  |  |     uint64_t win32_file_index;  | 
12551  |  |     int got_file_index;  | 
12552  |  | #else /* POSIX */  | 
12553  |  | #ifdef HAVE_DIRENT_D_TYPE  | 
12554  |  |     unsigned char d_type;  | 
12555  |  | #endif  | 
12556  |  |     ino_t d_ino;  | 
12557  |  |     int dir_fd;  | 
12558  |  | #endif  | 
12559  |  | } DirEntry;  | 
12560  |  |  | 
12561  |  | static void  | 
12562  |  | DirEntry_dealloc(DirEntry *entry)  | 
12563  | 0  | { | 
12564  | 0  |     Py_XDECREF(entry->name);  | 
12565  | 0  |     Py_XDECREF(entry->path);  | 
12566  | 0  |     Py_XDECREF(entry->stat);  | 
12567  | 0  |     Py_XDECREF(entry->lstat);  | 
12568  | 0  |     Py_TYPE(entry)->tp_free((PyObject *)entry);  | 
12569  | 0  | }  | 
12570  |  |  | 
12571  |  | /* Forward reference */  | 
12572  |  | static int  | 
12573  |  | DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits);  | 
12574  |  |  | 
12575  |  | /*[clinic input]  | 
12576  |  | os.DirEntry.is_symlink -> bool  | 
12577  |  |  | 
12578  |  | Return True if the entry is a symbolic link; cached per entry.  | 
12579  |  | [clinic start generated code]*/  | 
12580  |  |  | 
12581  |  | static int  | 
12582  |  | os_DirEntry_is_symlink_impl(DirEntry *self)  | 
12583  |  | /*[clinic end generated code: output=42244667d7bcfc25 input=1605a1b4b96976c3]*/  | 
12584  | 0  | { | 
12585  |  | #ifdef MS_WINDOWS  | 
12586  |  |     return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;  | 
12587  |  | #elif defined(HAVE_DIRENT_D_TYPE)  | 
12588  |  |     /* POSIX */  | 
12589  | 0  |     if (self->d_type != DT_UNKNOWN)  | 
12590  | 0  |         return self->d_type == DT_LNK;  | 
12591  | 0  |     else  | 
12592  | 0  |         return DirEntry_test_mode(self, 0, S_IFLNK);  | 
12593  |  | #else  | 
12594  |  |     /* POSIX without d_type */  | 
12595  |  |     return DirEntry_test_mode(self, 0, S_IFLNK);  | 
12596  |  | #endif  | 
12597  | 0  | }  | 
12598  |  |  | 
12599  |  | static PyObject *  | 
12600  |  | DirEntry_fetch_stat(DirEntry *self, int follow_symlinks)  | 
12601  | 0  | { | 
12602  | 0  |     int result;  | 
12603  | 0  |     STRUCT_STAT st;  | 
12604  | 0  |     PyObject *ub;  | 
12605  |  | 
  | 
12606  |  | #ifdef MS_WINDOWS  | 
12607  |  |     if (!PyUnicode_FSDecoder(self->path, &ub))  | 
12608  |  |         return NULL;  | 
12609  |  |     const wchar_t *path = PyUnicode_AsUnicode(ub);  | 
12610  |  | #else /* POSIX */  | 
12611  | 0  |     if (!PyUnicode_FSConverter(self->path, &ub))  | 
12612  | 0  |         return NULL;  | 
12613  | 0  |     const char *path = PyBytes_AS_STRING(ub);  | 
12614  | 0  |     if (self->dir_fd != DEFAULT_DIR_FD) { | 
12615  | 0  | #ifdef HAVE_FSTATAT  | 
12616  | 0  |         result = fstatat(self->dir_fd, path, &st,  | 
12617  | 0  |                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);  | 
12618  |  | #else  | 
12619  |  |         PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");  | 
12620  |  |         return NULL;  | 
12621  |  | #endif /* HAVE_FSTATAT */  | 
12622  | 0  |     }  | 
12623  | 0  |     else  | 
12624  | 0  | #endif  | 
12625  | 0  |     { | 
12626  | 0  |         if (follow_symlinks)  | 
12627  | 0  |             result = STAT(path, &st);  | 
12628  | 0  |         else  | 
12629  | 0  |             result = LSTAT(path, &st);  | 
12630  | 0  |     }  | 
12631  | 0  |     Py_DECREF(ub);  | 
12632  |  | 
  | 
12633  | 0  |     if (result != 0)  | 
12634  | 0  |         return path_object_error(self->path);  | 
12635  |  |  | 
12636  | 0  |     return _pystat_fromstructstat(&st);  | 
12637  | 0  | }  | 
12638  |  |  | 
12639  |  | static PyObject *  | 
12640  |  | DirEntry_get_lstat(DirEntry *self)  | 
12641  | 0  | { | 
12642  | 0  |     if (!self->lstat) { | 
12643  |  | #ifdef MS_WINDOWS  | 
12644  |  |         self->lstat = _pystat_fromstructstat(&self->win32_lstat);  | 
12645  |  | #else /* POSIX */  | 
12646  | 0  |         self->lstat = DirEntry_fetch_stat(self, 0);  | 
12647  | 0  | #endif  | 
12648  | 0  |     }  | 
12649  | 0  |     Py_XINCREF(self->lstat);  | 
12650  | 0  |     return self->lstat;  | 
12651  | 0  | }  | 
12652  |  |  | 
12653  |  | /*[clinic input]  | 
12654  |  | os.DirEntry.stat  | 
12655  |  |     *  | 
12656  |  |     follow_symlinks: bool = True  | 
12657  |  |  | 
12658  |  | Return stat_result object for the entry; cached per entry.  | 
12659  |  | [clinic start generated code]*/  | 
12660  |  |  | 
12661  |  | static PyObject *  | 
12662  |  | os_DirEntry_stat_impl(DirEntry *self, int follow_symlinks)  | 
12663  |  | /*[clinic end generated code: output=008593b3a6d01305 input=280d14c1d6f1d00d]*/  | 
12664  | 0  | { | 
12665  | 0  |     if (!follow_symlinks)  | 
12666  | 0  |         return DirEntry_get_lstat(self);  | 
12667  |  |  | 
12668  | 0  |     if (!self->stat) { | 
12669  | 0  |         int result = os_DirEntry_is_symlink_impl(self);  | 
12670  | 0  |         if (result == -1)  | 
12671  | 0  |             return NULL;  | 
12672  | 0  |         else if (result)  | 
12673  | 0  |             self->stat = DirEntry_fetch_stat(self, 1);  | 
12674  | 0  |         else  | 
12675  | 0  |             self->stat = DirEntry_get_lstat(self);  | 
12676  | 0  |     }  | 
12677  |  |  | 
12678  | 0  |     Py_XINCREF(self->stat);  | 
12679  | 0  |     return self->stat;  | 
12680  | 0  | }  | 
12681  |  |  | 
12682  |  | /* Set exception and return -1 on error, 0 for False, 1 for True */  | 
12683  |  | static int  | 
12684  |  | DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits)  | 
12685  | 0  | { | 
12686  | 0  |     PyObject *stat = NULL;  | 
12687  | 0  |     PyObject *st_mode = NULL;  | 
12688  | 0  |     long mode;  | 
12689  | 0  |     int result;  | 
12690  | 0  | #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)  | 
12691  | 0  |     int is_symlink;  | 
12692  | 0  |     int need_stat;  | 
12693  | 0  | #endif  | 
12694  |  | #ifdef MS_WINDOWS  | 
12695  |  |     unsigned long dir_bits;  | 
12696  |  | #endif  | 
12697  | 0  |     _Py_IDENTIFIER(st_mode);  | 
12698  |  | 
  | 
12699  |  | #ifdef MS_WINDOWS  | 
12700  |  |     is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;  | 
12701  |  |     need_stat = follow_symlinks && is_symlink;  | 
12702  |  | #elif defined(HAVE_DIRENT_D_TYPE)  | 
12703  | 0  |     is_symlink = self->d_type == DT_LNK;  | 
12704  | 0  |     need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);  | 
12705  | 0  | #endif  | 
12706  |  | 
  | 
12707  | 0  | #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)  | 
12708  | 0  |     if (need_stat) { | 
12709  | 0  | #endif  | 
12710  | 0  |         stat = os_DirEntry_stat_impl(self, follow_symlinks);  | 
12711  | 0  |         if (!stat) { | 
12712  | 0  |             if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) { | 
12713  |  |                 /* If file doesn't exist (anymore), then return False  | 
12714  |  |                    (i.e., say it's not a file/directory) */  | 
12715  | 0  |                 PyErr_Clear();  | 
12716  | 0  |                 return 0;  | 
12717  | 0  |             }  | 
12718  | 0  |             goto error;  | 
12719  | 0  |         }  | 
12720  | 0  |         st_mode = _PyObject_GetAttrId(stat, &PyId_st_mode);  | 
12721  | 0  |         if (!st_mode)  | 
12722  | 0  |             goto error;  | 
12723  |  |  | 
12724  | 0  |         mode = PyLong_AsLong(st_mode);  | 
12725  | 0  |         if (mode == -1 && PyErr_Occurred())  | 
12726  | 0  |             goto error;  | 
12727  | 0  |         Py_CLEAR(st_mode);  | 
12728  | 0  |         Py_CLEAR(stat);  | 
12729  | 0  |         result = (mode & S_IFMT) == mode_bits;  | 
12730  | 0  | #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)  | 
12731  | 0  |     }  | 
12732  | 0  |     else if (is_symlink) { | 
12733  | 0  |         assert(mode_bits != S_IFLNK);  | 
12734  | 0  |         result = 0;  | 
12735  | 0  |     }  | 
12736  | 0  |     else { | 
12737  | 0  |         assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);  | 
12738  |  | #ifdef MS_WINDOWS  | 
12739  |  |         dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;  | 
12740  |  |         if (mode_bits == S_IFDIR)  | 
12741  |  |             result = dir_bits != 0;  | 
12742  |  |         else  | 
12743  |  |             result = dir_bits == 0;  | 
12744  |  | #else /* POSIX */  | 
12745  | 0  |         if (mode_bits == S_IFDIR)  | 
12746  | 0  |             result = self->d_type == DT_DIR;  | 
12747  | 0  |         else  | 
12748  | 0  |             result = self->d_type == DT_REG;  | 
12749  | 0  | #endif  | 
12750  | 0  |     }  | 
12751  | 0  | #endif  | 
12752  |  |  | 
12753  | 0  |     return result;  | 
12754  |  |  | 
12755  | 0  | error:  | 
12756  | 0  |     Py_XDECREF(st_mode);  | 
12757  | 0  |     Py_XDECREF(stat);  | 
12758  | 0  |     return -1;  | 
12759  | 0  | }  | 
12760  |  |  | 
12761  |  | /*[clinic input]  | 
12762  |  | os.DirEntry.is_dir -> bool  | 
12763  |  |     *  | 
12764  |  |     follow_symlinks: bool = True  | 
12765  |  |  | 
12766  |  | Return True if the entry is a directory; cached per entry.  | 
12767  |  | [clinic start generated code]*/  | 
12768  |  |  | 
12769  |  | static int  | 
12770  |  | os_DirEntry_is_dir_impl(DirEntry *self, int follow_symlinks)  | 
12771  |  | /*[clinic end generated code: output=ad2e8d54365da287 input=0135232766f53f58]*/  | 
12772  | 0  | { | 
12773  | 0  |     return DirEntry_test_mode(self, follow_symlinks, S_IFDIR);  | 
12774  | 0  | }  | 
12775  |  |  | 
12776  |  | /*[clinic input]  | 
12777  |  | os.DirEntry.is_file -> bool  | 
12778  |  |     *  | 
12779  |  |     follow_symlinks: bool = True  | 
12780  |  |  | 
12781  |  | Return True if the entry is a file; cached per entry.  | 
12782  |  | [clinic start generated code]*/  | 
12783  |  |  | 
12784  |  | static int  | 
12785  |  | os_DirEntry_is_file_impl(DirEntry *self, int follow_symlinks)  | 
12786  |  | /*[clinic end generated code: output=8462ade481d8a476 input=0dc90be168b041ee]*/  | 
12787  | 0  | { | 
12788  | 0  |     return DirEntry_test_mode(self, follow_symlinks, S_IFREG);  | 
12789  | 0  | }  | 
12790  |  |  | 
12791  |  | /*[clinic input]  | 
12792  |  | os.DirEntry.inode  | 
12793  |  |  | 
12794  |  | Return inode of the entry; cached per entry.  | 
12795  |  | [clinic start generated code]*/  | 
12796  |  |  | 
12797  |  | static PyObject *  | 
12798  |  | os_DirEntry_inode_impl(DirEntry *self)  | 
12799  |  | /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/  | 
12800  | 0  | { | 
12801  |  | #ifdef MS_WINDOWS  | 
12802  |  |     if (!self->got_file_index) { | 
12803  |  |         PyObject *unicode;  | 
12804  |  |         const wchar_t *path;  | 
12805  |  |         STRUCT_STAT stat;  | 
12806  |  |         int result;  | 
12807  |  |  | 
12808  |  |         if (!PyUnicode_FSDecoder(self->path, &unicode))  | 
12809  |  |             return NULL;  | 
12810  |  |         path = PyUnicode_AsUnicode(unicode);  | 
12811  |  |         result = LSTAT(path, &stat);  | 
12812  |  |         Py_DECREF(unicode);  | 
12813  |  |  | 
12814  |  |         if (result != 0)  | 
12815  |  |             return path_object_error(self->path);  | 
12816  |  |  | 
12817  |  |         self->win32_file_index = stat.st_ino;  | 
12818  |  |         self->got_file_index = 1;  | 
12819  |  |     }  | 
12820  |  |     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->win32_file_index));  | 
12821  |  |     return PyLong_FromUnsignedLongLong(self->win32_file_index);  | 
12822  |  | #else /* POSIX */  | 
12823  | 0  |     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->d_ino));  | 
12824  | 0  |     return PyLong_FromUnsignedLongLong(self->d_ino);  | 
12825  | 0  | #endif  | 
12826  | 0  | }  | 
12827  |  |  | 
12828  |  | static PyObject *  | 
12829  |  | DirEntry_repr(DirEntry *self)  | 
12830  | 0  | { | 
12831  | 0  |     return PyUnicode_FromFormat("<DirEntry %R>", self->name); | 
12832  | 0  | }  | 
12833  |  |  | 
12834  |  | /*[clinic input]  | 
12835  |  | os.DirEntry.__fspath__  | 
12836  |  |  | 
12837  |  | Returns the path for the entry.  | 
12838  |  | [clinic start generated code]*/  | 
12839  |  |  | 
12840  |  | static PyObject *  | 
12841  |  | os_DirEntry___fspath___impl(DirEntry *self)  | 
12842  |  | /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/  | 
12843  | 0  | { | 
12844  | 0  |     Py_INCREF(self->path);  | 
12845  | 0  |     return self->path;  | 
12846  | 0  | }  | 
12847  |  |  | 
12848  |  | static PyMemberDef DirEntry_members[] = { | 
12849  |  |     {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY, | 
12850  |  |      "the entry's base filename, relative to scandir() \"path\" argument"},  | 
12851  |  |     {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY, | 
12852  |  |      "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},  | 
12853  |  |     {NULL} | 
12854  |  | };  | 
12855  |  |  | 
12856  |  | #include "clinic/posixmodule.c.h"  | 
12857  |  |  | 
12858  |  | static PyMethodDef DirEntry_methods[] = { | 
12859  |  |     OS_DIRENTRY_IS_DIR_METHODDEF  | 
12860  |  |     OS_DIRENTRY_IS_FILE_METHODDEF  | 
12861  |  |     OS_DIRENTRY_IS_SYMLINK_METHODDEF  | 
12862  |  |     OS_DIRENTRY_STAT_METHODDEF  | 
12863  |  |     OS_DIRENTRY_INODE_METHODDEF  | 
12864  |  |     OS_DIRENTRY___FSPATH___METHODDEF  | 
12865  |  |     {NULL} | 
12866  |  | };  | 
12867  |  |  | 
12868  |  | static PyTypeObject DirEntryType = { | 
12869  |  |     PyVarObject_HEAD_INIT(NULL, 0)  | 
12870  |  |     MODNAME ".DirEntry",                    /* tp_name */  | 
12871  |  |     sizeof(DirEntry),                       /* tp_basicsize */  | 
12872  |  |     0,                                      /* tp_itemsize */  | 
12873  |  |     /* methods */  | 
12874  |  |     (destructor)DirEntry_dealloc,           /* tp_dealloc */  | 
12875  |  |     0,                                      /* tp_vectorcall_offset */  | 
12876  |  |     0,                                      /* tp_getattr */  | 
12877  |  |     0,                                      /* tp_setattr */  | 
12878  |  |     0,                                      /* tp_as_async */  | 
12879  |  |     (reprfunc)DirEntry_repr,                /* tp_repr */  | 
12880  |  |     0,                                      /* tp_as_number */  | 
12881  |  |     0,                                      /* tp_as_sequence */  | 
12882  |  |     0,                                      /* tp_as_mapping */  | 
12883  |  |     0,                                      /* tp_hash */  | 
12884  |  |     0,                                      /* tp_call */  | 
12885  |  |     0,                                      /* tp_str */  | 
12886  |  |     0,                                      /* tp_getattro */  | 
12887  |  |     0,                                      /* tp_setattro */  | 
12888  |  |     0,                                      /* tp_as_buffer */  | 
12889  |  |     Py_TPFLAGS_DEFAULT,                     /* tp_flags */  | 
12890  |  |     0,                                      /* tp_doc */  | 
12891  |  |     0,                                      /* tp_traverse */  | 
12892  |  |     0,                                      /* tp_clear */  | 
12893  |  |     0,                                      /* tp_richcompare */  | 
12894  |  |     0,                                      /* tp_weaklistoffset */  | 
12895  |  |     0,                                      /* tp_iter */  | 
12896  |  |     0,                                      /* tp_iternext */  | 
12897  |  |     DirEntry_methods,                       /* tp_methods */  | 
12898  |  |     DirEntry_members,                       /* tp_members */  | 
12899  |  | };  | 
12900  |  |  | 
12901  |  | #ifdef MS_WINDOWS  | 
12902  |  |  | 
12903  |  | static wchar_t *  | 
12904  |  | join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)  | 
12905  |  | { | 
12906  |  |     Py_ssize_t path_len;  | 
12907  |  |     Py_ssize_t size;  | 
12908  |  |     wchar_t *result;  | 
12909  |  |     wchar_t ch;  | 
12910  |  |  | 
12911  |  |     if (!path_wide) { /* Default arg: "." */ | 
12912  |  |         path_wide = L".";  | 
12913  |  |         path_len = 1;  | 
12914  |  |     }  | 
12915  |  |     else { | 
12916  |  |         path_len = wcslen(path_wide);  | 
12917  |  |     }  | 
12918  |  |  | 
12919  |  |     /* The +1's are for the path separator and the NUL */  | 
12920  |  |     size = path_len + 1 + wcslen(filename) + 1;  | 
12921  |  |     result = PyMem_New(wchar_t, size);  | 
12922  |  |     if (!result) { | 
12923  |  |         PyErr_NoMemory();  | 
12924  |  |         return NULL;  | 
12925  |  |     }  | 
12926  |  |     wcscpy(result, path_wide);  | 
12927  |  |     if (path_len > 0) { | 
12928  |  |         ch = result[path_len - 1];  | 
12929  |  |         if (ch != SEP && ch != ALTSEP && ch != L':')  | 
12930  |  |             result[path_len++] = SEP;  | 
12931  |  |         wcscpy(result + path_len, filename);  | 
12932  |  |     }  | 
12933  |  |     return result;  | 
12934  |  | }  | 
12935  |  |  | 
12936  |  | static PyObject *  | 
12937  |  | DirEntry_from_find_data(path_t *path, WIN32_FIND_DATAW *dataW)  | 
12938  |  | { | 
12939  |  |     DirEntry *entry;  | 
12940  |  |     BY_HANDLE_FILE_INFORMATION file_info;  | 
12941  |  |     ULONG reparse_tag;  | 
12942  |  |     wchar_t *joined_path;  | 
12943  |  |  | 
12944  |  |     entry = PyObject_New(DirEntry, &DirEntryType);  | 
12945  |  |     if (!entry)  | 
12946  |  |         return NULL;  | 
12947  |  |     entry->name = NULL;  | 
12948  |  |     entry->path = NULL;  | 
12949  |  |     entry->stat = NULL;  | 
12950  |  |     entry->lstat = NULL;  | 
12951  |  |     entry->got_file_index = 0;  | 
12952  |  |  | 
12953  |  |     entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);  | 
12954  |  |     if (!entry->name)  | 
12955  |  |         goto error;  | 
12956  |  |     if (path->narrow) { | 
12957  |  |         Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));  | 
12958  |  |         if (!entry->name)  | 
12959  |  |             goto error;  | 
12960  |  |     }  | 
12961  |  |  | 
12962  |  |     joined_path = join_path_filenameW(path->wide, dataW->cFileName);  | 
12963  |  |     if (!joined_path)  | 
12964  |  |         goto error;  | 
12965  |  |  | 
12966  |  |     entry->path = PyUnicode_FromWideChar(joined_path, -1);  | 
12967  |  |     PyMem_Free(joined_path);  | 
12968  |  |     if (!entry->path)  | 
12969  |  |         goto error;  | 
12970  |  |     if (path->narrow) { | 
12971  |  |         Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));  | 
12972  |  |         if (!entry->path)  | 
12973  |  |             goto error;  | 
12974  |  |     }  | 
12975  |  |  | 
12976  |  |     find_data_to_file_info(dataW, &file_info, &reparse_tag);  | 
12977  |  |     _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);  | 
12978  |  |  | 
12979  |  |     return (PyObject *)entry;  | 
12980  |  |  | 
12981  |  | error:  | 
12982  |  |     Py_DECREF(entry);  | 
12983  |  |     return NULL;  | 
12984  |  | }  | 
12985  |  |  | 
12986  |  | #else /* POSIX */  | 
12987  |  |  | 
12988  |  | static char *  | 
12989  |  | join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)  | 
12990  | 0  | { | 
12991  | 0  |     Py_ssize_t path_len;  | 
12992  | 0  |     Py_ssize_t size;  | 
12993  | 0  |     char *result;  | 
12994  |  | 
  | 
12995  | 0  |     if (!path_narrow) { /* Default arg: "." */ | 
12996  | 0  |         path_narrow = ".";  | 
12997  | 0  |         path_len = 1;  | 
12998  | 0  |     }  | 
12999  | 0  |     else { | 
13000  | 0  |         path_len = strlen(path_narrow);  | 
13001  | 0  |     }  | 
13002  |  | 
  | 
13003  | 0  |     if (filename_len == -1)  | 
13004  | 0  |         filename_len = strlen(filename);  | 
13005  |  |  | 
13006  |  |     /* The +1's are for the path separator and the NUL */  | 
13007  | 0  |     size = path_len + 1 + filename_len + 1;  | 
13008  | 0  |     result = PyMem_New(char, size);  | 
13009  | 0  |     if (!result) { | 
13010  | 0  |         PyErr_NoMemory();  | 
13011  | 0  |         return NULL;  | 
13012  | 0  |     }  | 
13013  | 0  |     strcpy(result, path_narrow);  | 
13014  | 0  |     if (path_len > 0 && result[path_len - 1] != '/')  | 
13015  | 0  |         result[path_len++] = '/';  | 
13016  | 0  |     strcpy(result + path_len, filename);  | 
13017  | 0  |     return result;  | 
13018  | 0  | }  | 
13019  |  |  | 
13020  |  | static PyObject *  | 
13021  |  | DirEntry_from_posix_info(path_t *path, const char *name, Py_ssize_t name_len,  | 
13022  |  |                          ino_t d_ino  | 
13023  |  | #ifdef HAVE_DIRENT_D_TYPE  | 
13024  |  |                          , unsigned char d_type  | 
13025  |  | #endif  | 
13026  |  |                          )  | 
13027  | 0  | { | 
13028  | 0  |     DirEntry *entry;  | 
13029  | 0  |     char *joined_path;  | 
13030  |  | 
  | 
13031  | 0  |     entry = PyObject_New(DirEntry, &DirEntryType);  | 
13032  | 0  |     if (!entry)  | 
13033  | 0  |         return NULL;  | 
13034  | 0  |     entry->name = NULL;  | 
13035  | 0  |     entry->path = NULL;  | 
13036  | 0  |     entry->stat = NULL;  | 
13037  | 0  |     entry->lstat = NULL;  | 
13038  |  | 
  | 
13039  | 0  |     if (path->fd != -1) { | 
13040  | 0  |         entry->dir_fd = path->fd;  | 
13041  | 0  |         joined_path = NULL;  | 
13042  | 0  |     }  | 
13043  | 0  |     else { | 
13044  | 0  |         entry->dir_fd = DEFAULT_DIR_FD;  | 
13045  | 0  |         joined_path = join_path_filename(path->narrow, name, name_len);  | 
13046  | 0  |         if (!joined_path)  | 
13047  | 0  |             goto error;  | 
13048  | 0  |     }  | 
13049  |  |  | 
13050  | 0  |     if (!path->narrow || !PyObject_CheckBuffer(path->object)) { | 
13051  | 0  |         entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);  | 
13052  | 0  |         if (joined_path)  | 
13053  | 0  |             entry->path = PyUnicode_DecodeFSDefault(joined_path);  | 
13054  | 0  |     }  | 
13055  | 0  |     else { | 
13056  | 0  |         entry->name = PyBytes_FromStringAndSize(name, name_len);  | 
13057  | 0  |         if (joined_path)  | 
13058  | 0  |             entry->path = PyBytes_FromString(joined_path);  | 
13059  | 0  |     }  | 
13060  | 0  |     PyMem_Free(joined_path);  | 
13061  | 0  |     if (!entry->name)  | 
13062  | 0  |         goto error;  | 
13063  |  |  | 
13064  | 0  |     if (path->fd != -1) { | 
13065  | 0  |         entry->path = entry->name;  | 
13066  | 0  |         Py_INCREF(entry->path);  | 
13067  | 0  |     }  | 
13068  | 0  |     else if (!entry->path)  | 
13069  | 0  |         goto error;  | 
13070  |  |  | 
13071  | 0  | #ifdef HAVE_DIRENT_D_TYPE  | 
13072  | 0  |     entry->d_type = d_type;  | 
13073  | 0  | #endif  | 
13074  | 0  |     entry->d_ino = d_ino;  | 
13075  |  | 
  | 
13076  | 0  |     return (PyObject *)entry;  | 
13077  |  |  | 
13078  | 0  | error:  | 
13079  | 0  |     Py_XDECREF(entry);  | 
13080  | 0  |     return NULL;  | 
13081  | 0  | }  | 
13082  |  |  | 
13083  |  | #endif  | 
13084  |  |  | 
13085  |  |  | 
13086  |  | typedef struct { | 
13087  |  |     PyObject_HEAD  | 
13088  |  |     path_t path;  | 
13089  |  | #ifdef MS_WINDOWS  | 
13090  |  |     HANDLE handle;  | 
13091  |  |     WIN32_FIND_DATAW file_data;  | 
13092  |  |     int first_time;  | 
13093  |  | #else /* POSIX */  | 
13094  |  |     DIR *dirp;  | 
13095  |  | #endif  | 
13096  |  | #ifdef HAVE_FDOPENDIR  | 
13097  |  |     int fd;  | 
13098  |  | #endif  | 
13099  |  | } ScandirIterator;  | 
13100  |  |  | 
13101  |  | #ifdef MS_WINDOWS  | 
13102  |  |  | 
13103  |  | static int  | 
13104  |  | ScandirIterator_is_closed(ScandirIterator *iterator)  | 
13105  |  | { | 
13106  |  |     return iterator->handle == INVALID_HANDLE_VALUE;  | 
13107  |  | }  | 
13108  |  |  | 
13109  |  | static void  | 
13110  |  | ScandirIterator_closedir(ScandirIterator *iterator)  | 
13111  |  | { | 
13112  |  |     HANDLE handle = iterator->handle;  | 
13113  |  |  | 
13114  |  |     if (handle == INVALID_HANDLE_VALUE)  | 
13115  |  |         return;  | 
13116  |  |  | 
13117  |  |     iterator->handle = INVALID_HANDLE_VALUE;  | 
13118  |  |     Py_BEGIN_ALLOW_THREADS  | 
13119  |  |     FindClose(handle);  | 
13120  |  |     Py_END_ALLOW_THREADS  | 
13121  |  | }  | 
13122  |  |  | 
13123  |  | static PyObject *  | 
13124  |  | ScandirIterator_iternext(ScandirIterator *iterator)  | 
13125  |  | { | 
13126  |  |     WIN32_FIND_DATAW *file_data = &iterator->file_data;  | 
13127  |  |     BOOL success;  | 
13128  |  |     PyObject *entry;  | 
13129  |  |  | 
13130  |  |     /* Happens if the iterator is iterated twice, or closed explicitly */  | 
13131  |  |     if (iterator->handle == INVALID_HANDLE_VALUE)  | 
13132  |  |         return NULL;  | 
13133  |  |  | 
13134  |  |     while (1) { | 
13135  |  |         if (!iterator->first_time) { | 
13136  |  |             Py_BEGIN_ALLOW_THREADS  | 
13137  |  |             success = FindNextFileW(iterator->handle, file_data);  | 
13138  |  |             Py_END_ALLOW_THREADS  | 
13139  |  |             if (!success) { | 
13140  |  |                 /* Error or no more files */  | 
13141  |  |                 if (GetLastError() != ERROR_NO_MORE_FILES)  | 
13142  |  |                     path_error(&iterator->path);  | 
13143  |  |                 break;  | 
13144  |  |             }  | 
13145  |  |         }  | 
13146  |  |         iterator->first_time = 0;  | 
13147  |  |  | 
13148  |  |         /* Skip over . and .. */  | 
13149  |  |         if (wcscmp(file_data->cFileName, L".") != 0 &&  | 
13150  |  |             wcscmp(file_data->cFileName, L"..") != 0) { | 
13151  |  |             entry = DirEntry_from_find_data(&iterator->path, file_data);  | 
13152  |  |             if (!entry)  | 
13153  |  |                 break;  | 
13154  |  |             return entry;  | 
13155  |  |         }  | 
13156  |  |  | 
13157  |  |         /* Loop till we get a non-dot directory or finish iterating */  | 
13158  |  |     }  | 
13159  |  |  | 
13160  |  |     /* Error or no more files */  | 
13161  |  |     ScandirIterator_closedir(iterator);  | 
13162  |  |     return NULL;  | 
13163  |  | }  | 
13164  |  |  | 
13165  |  | #else /* POSIX */  | 
13166  |  |  | 
13167  |  | static int  | 
13168  |  | ScandirIterator_is_closed(ScandirIterator *iterator)  | 
13169  | 0  | { | 
13170  | 0  |     return !iterator->dirp;  | 
13171  | 0  | }  | 
13172  |  |  | 
13173  |  | static void  | 
13174  |  | ScandirIterator_closedir(ScandirIterator *iterator)  | 
13175  | 0  | { | 
13176  | 0  |     DIR *dirp = iterator->dirp;  | 
13177  |  | 
  | 
13178  | 0  |     if (!dirp)  | 
13179  | 0  |         return;  | 
13180  |  |  | 
13181  | 0  |     iterator->dirp = NULL;  | 
13182  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
13183  | 0  | #ifdef HAVE_FDOPENDIR  | 
13184  | 0  |     if (iterator->path.fd != -1)  | 
13185  | 0  |         rewinddir(dirp);  | 
13186  | 0  | #endif  | 
13187  | 0  |     closedir(dirp);  | 
13188  | 0  |     Py_END_ALLOW_THREADS  | 
13189  | 0  |     return;  | 
13190  | 0  | }  | 
13191  |  |  | 
13192  |  | static PyObject *  | 
13193  |  | ScandirIterator_iternext(ScandirIterator *iterator)  | 
13194  | 0  | { | 
13195  | 0  |     struct dirent *direntp;  | 
13196  | 0  |     Py_ssize_t name_len;  | 
13197  | 0  |     int is_dot;  | 
13198  | 0  |     PyObject *entry;  | 
13199  |  |  | 
13200  |  |     /* Happens if the iterator is iterated twice, or closed explicitly */  | 
13201  | 0  |     if (!iterator->dirp)  | 
13202  | 0  |         return NULL;  | 
13203  |  |  | 
13204  | 0  |     while (1) { | 
13205  | 0  |         errno = 0;  | 
13206  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
13207  | 0  |         direntp = readdir(iterator->dirp);  | 
13208  | 0  |         Py_END_ALLOW_THREADS  | 
13209  |  | 
  | 
13210  | 0  |         if (!direntp) { | 
13211  |  |             /* Error or no more files */  | 
13212  | 0  |             if (errno != 0)  | 
13213  | 0  |                 path_error(&iterator->path);  | 
13214  | 0  |             break;  | 
13215  | 0  |         }  | 
13216  |  |  | 
13217  |  |         /* Skip over . and .. */  | 
13218  | 0  |         name_len = NAMLEN(direntp);  | 
13219  | 0  |         is_dot = direntp->d_name[0] == '.' &&  | 
13220  | 0  |                  (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));  | 
13221  | 0  |         if (!is_dot) { | 
13222  | 0  |             entry = DirEntry_from_posix_info(&iterator->path, direntp->d_name,  | 
13223  | 0  |                                             name_len, direntp->d_ino  | 
13224  | 0  | #ifdef HAVE_DIRENT_D_TYPE  | 
13225  | 0  |                                             , direntp->d_type  | 
13226  | 0  | #endif  | 
13227  | 0  |                                             );  | 
13228  | 0  |             if (!entry)  | 
13229  | 0  |                 break;  | 
13230  | 0  |             return entry;  | 
13231  | 0  |         }  | 
13232  |  |  | 
13233  |  |         /* Loop till we get a non-dot directory or finish iterating */  | 
13234  | 0  |     }  | 
13235  |  |  | 
13236  |  |     /* Error or no more files */  | 
13237  | 0  |     ScandirIterator_closedir(iterator);  | 
13238  | 0  |     return NULL;  | 
13239  | 0  | }  | 
13240  |  |  | 
13241  |  | #endif  | 
13242  |  |  | 
13243  |  | static PyObject *  | 
13244  |  | ScandirIterator_close(ScandirIterator *self, PyObject *args)  | 
13245  | 0  | { | 
13246  | 0  |     ScandirIterator_closedir(self);  | 
13247  | 0  |     Py_RETURN_NONE;  | 
13248  | 0  | }  | 
13249  |  |  | 
13250  |  | static PyObject *  | 
13251  |  | ScandirIterator_enter(PyObject *self, PyObject *args)  | 
13252  | 0  | { | 
13253  | 0  |     Py_INCREF(self);  | 
13254  | 0  |     return self;  | 
13255  | 0  | }  | 
13256  |  |  | 
13257  |  | static PyObject *  | 
13258  |  | ScandirIterator_exit(ScandirIterator *self, PyObject *args)  | 
13259  | 0  | { | 
13260  | 0  |     ScandirIterator_closedir(self);  | 
13261  | 0  |     Py_RETURN_NONE;  | 
13262  | 0  | }  | 
13263  |  |  | 
13264  |  | static void  | 
13265  |  | ScandirIterator_finalize(ScandirIterator *iterator)  | 
13266  | 0  | { | 
13267  | 0  |     PyObject *error_type, *error_value, *error_traceback;  | 
13268  |  |  | 
13269  |  |     /* Save the current exception, if any. */  | 
13270  | 0  |     PyErr_Fetch(&error_type, &error_value, &error_traceback);  | 
13271  |  | 
  | 
13272  | 0  |     if (!ScandirIterator_is_closed(iterator)) { | 
13273  | 0  |         ScandirIterator_closedir(iterator);  | 
13274  |  | 
  | 
13275  | 0  |         if (PyErr_ResourceWarning((PyObject *)iterator, 1,  | 
13276  | 0  |                                   "unclosed scandir iterator %R", iterator)) { | 
13277  |  |             /* Spurious errors can appear at shutdown */  | 
13278  | 0  |             if (PyErr_ExceptionMatches(PyExc_Warning)) { | 
13279  | 0  |                 PyErr_WriteUnraisable((PyObject *) iterator);  | 
13280  | 0  |             }  | 
13281  | 0  |         }  | 
13282  | 0  |     }  | 
13283  |  | 
  | 
13284  | 0  |     path_cleanup(&iterator->path);  | 
13285  |  |  | 
13286  |  |     /* Restore the saved exception. */  | 
13287  | 0  |     PyErr_Restore(error_type, error_value, error_traceback);  | 
13288  | 0  | }  | 
13289  |  |  | 
13290  |  | static void  | 
13291  |  | ScandirIterator_dealloc(ScandirIterator *iterator)  | 
13292  | 0  | { | 
13293  | 0  |     if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)  | 
13294  | 0  |         return;  | 
13295  |  |  | 
13296  | 0  |     Py_TYPE(iterator)->tp_free((PyObject *)iterator);  | 
13297  | 0  | }  | 
13298  |  |  | 
13299  |  | static PyMethodDef ScandirIterator_methods[] = { | 
13300  |  |     {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS}, | 
13301  |  |     {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS}, | 
13302  |  |     {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS}, | 
13303  |  |     {NULL} | 
13304  |  | };  | 
13305  |  |  | 
13306  |  | static PyTypeObject ScandirIteratorType = { | 
13307  |  |     PyVarObject_HEAD_INIT(NULL, 0)  | 
13308  |  |     MODNAME ".ScandirIterator",             /* tp_name */  | 
13309  |  |     sizeof(ScandirIterator),                /* tp_basicsize */  | 
13310  |  |     0,                                      /* tp_itemsize */  | 
13311  |  |     /* methods */  | 
13312  |  |     (destructor)ScandirIterator_dealloc,    /* tp_dealloc */  | 
13313  |  |     0,                                      /* tp_vectorcall_offset */  | 
13314  |  |     0,                                      /* tp_getattr */  | 
13315  |  |     0,                                      /* tp_setattr */  | 
13316  |  |     0,                                      /* tp_as_async */  | 
13317  |  |     0,                                      /* tp_repr */  | 
13318  |  |     0,                                      /* tp_as_number */  | 
13319  |  |     0,                                      /* tp_as_sequence */  | 
13320  |  |     0,                                      /* tp_as_mapping */  | 
13321  |  |     0,                                      /* tp_hash */  | 
13322  |  |     0,                                      /* tp_call */  | 
13323  |  |     0,                                      /* tp_str */  | 
13324  |  |     0,                                      /* tp_getattro */  | 
13325  |  |     0,                                      /* tp_setattro */  | 
13326  |  |     0,                                      /* tp_as_buffer */  | 
13327  |  |     Py_TPFLAGS_DEFAULT,                     /* tp_flags */  | 
13328  |  |     0,                                      /* tp_doc */  | 
13329  |  |     0,                                      /* tp_traverse */  | 
13330  |  |     0,                                      /* tp_clear */  | 
13331  |  |     0,                                      /* tp_richcompare */  | 
13332  |  |     0,                                      /* tp_weaklistoffset */  | 
13333  |  |     PyObject_SelfIter,                      /* tp_iter */  | 
13334  |  |     (iternextfunc)ScandirIterator_iternext, /* tp_iternext */  | 
13335  |  |     ScandirIterator_methods,                /* tp_methods */  | 
13336  |  |     0,                                      /* tp_members */  | 
13337  |  |     0,                                      /* tp_getset */  | 
13338  |  |     0,                                      /* tp_base */  | 
13339  |  |     0,                                      /* tp_dict */  | 
13340  |  |     0,                                      /* tp_descr_get */  | 
13341  |  |     0,                                      /* tp_descr_set */  | 
13342  |  |     0,                                      /* tp_dictoffset */  | 
13343  |  |     0,                                      /* tp_init */  | 
13344  |  |     0,                                      /* tp_alloc */  | 
13345  |  |     0,                                      /* tp_new */  | 
13346  |  |     0,                                      /* tp_free */  | 
13347  |  |     0,                                      /* tp_is_gc */  | 
13348  |  |     0,                                      /* tp_bases */  | 
13349  |  |     0,                                      /* tp_mro */  | 
13350  |  |     0,                                      /* tp_cache */  | 
13351  |  |     0,                                      /* tp_subclasses */  | 
13352  |  |     0,                                      /* tp_weaklist */  | 
13353  |  |     0,                                      /* tp_del */  | 
13354  |  |     0,                                      /* tp_version_tag */  | 
13355  |  |     (destructor)ScandirIterator_finalize,   /* tp_finalize */  | 
13356  |  | };  | 
13357  |  |  | 
13358  |  | /*[clinic input]  | 
13359  |  | os.scandir  | 
13360  |  |  | 
13361  |  |     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None  | 
13362  |  |  | 
13363  |  | Return an iterator of DirEntry objects for given path.  | 
13364  |  |  | 
13365  |  | path can be specified as either str, bytes, or a path-like object.  If path  | 
13366  |  | is bytes, the names of yielded DirEntry objects will also be bytes; in  | 
13367  |  | all other circumstances they will be str.  | 
13368  |  |  | 
13369  |  | If path is None, uses the path='.'.  | 
13370  |  | [clinic start generated code]*/  | 
13371  |  |  | 
13372  |  | static PyObject *  | 
13373  |  | os_scandir_impl(PyObject *module, path_t *path)  | 
13374  |  | /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/  | 
13375  | 0  | { | 
13376  | 0  |     ScandirIterator *iterator;  | 
13377  |  | #ifdef MS_WINDOWS  | 
13378  |  |     wchar_t *path_strW;  | 
13379  |  | #else  | 
13380  | 0  |     const char *path_str;  | 
13381  | 0  | #ifdef HAVE_FDOPENDIR  | 
13382  | 0  |     int fd = -1;  | 
13383  | 0  | #endif  | 
13384  | 0  | #endif  | 
13385  |  | 
  | 
13386  | 0  |     if (PySys_Audit("os.scandir", "O", | 
13387  | 0  |                     path->object ? path->object : Py_None) < 0) { | 
13388  | 0  |         return NULL;  | 
13389  | 0  |     }  | 
13390  |  |  | 
13391  | 0  |     iterator = PyObject_New(ScandirIterator, &ScandirIteratorType);  | 
13392  | 0  |     if (!iterator)  | 
13393  | 0  |         return NULL;  | 
13394  |  |  | 
13395  |  | #ifdef MS_WINDOWS  | 
13396  |  |     iterator->handle = INVALID_HANDLE_VALUE;  | 
13397  |  | #else  | 
13398  | 0  |     iterator->dirp = NULL;  | 
13399  | 0  | #endif  | 
13400  |  | 
  | 
13401  | 0  |     memcpy(&iterator->path, path, sizeof(path_t));  | 
13402  |  |     /* Move the ownership to iterator->path */  | 
13403  | 0  |     path->object = NULL;  | 
13404  | 0  |     path->cleanup = NULL;  | 
13405  |  | 
  | 
13406  |  | #ifdef MS_WINDOWS  | 
13407  |  |     iterator->first_time = 1;  | 
13408  |  |  | 
13409  |  |     path_strW = join_path_filenameW(iterator->path.wide, L"*.*");  | 
13410  |  |     if (!path_strW)  | 
13411  |  |         goto error;  | 
13412  |  |  | 
13413  |  |     Py_BEGIN_ALLOW_THREADS  | 
13414  |  |     iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);  | 
13415  |  |     Py_END_ALLOW_THREADS  | 
13416  |  |  | 
13417  |  |     PyMem_Free(path_strW);  | 
13418  |  |  | 
13419  |  |     if (iterator->handle == INVALID_HANDLE_VALUE) { | 
13420  |  |         path_error(&iterator->path);  | 
13421  |  |         goto error;  | 
13422  |  |     }  | 
13423  |  | #else /* POSIX */  | 
13424  | 0  |     errno = 0;  | 
13425  | 0  | #ifdef HAVE_FDOPENDIR  | 
13426  | 0  |     if (path->fd != -1) { | 
13427  |  |         /* closedir() closes the FD, so we duplicate it */  | 
13428  | 0  |         fd = _Py_dup(path->fd);  | 
13429  | 0  |         if (fd == -1)  | 
13430  | 0  |             goto error;  | 
13431  |  |  | 
13432  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
13433  | 0  |         iterator->dirp = fdopendir(fd);  | 
13434  | 0  |         Py_END_ALLOW_THREADS  | 
13435  | 0  |     }  | 
13436  | 0  |     else  | 
13437  | 0  | #endif  | 
13438  | 0  |     { | 
13439  | 0  |         if (iterator->path.narrow)  | 
13440  | 0  |             path_str = iterator->path.narrow;  | 
13441  | 0  |         else  | 
13442  | 0  |             path_str = ".";  | 
13443  |  | 
  | 
13444  | 0  |         Py_BEGIN_ALLOW_THREADS  | 
13445  | 0  |         iterator->dirp = opendir(path_str);  | 
13446  | 0  |         Py_END_ALLOW_THREADS  | 
13447  | 0  |     }  | 
13448  |  |  | 
13449  | 0  |     if (!iterator->dirp) { | 
13450  | 0  |         path_error(&iterator->path);  | 
13451  | 0  | #ifdef HAVE_FDOPENDIR  | 
13452  | 0  |         if (fd != -1) { | 
13453  | 0  |             Py_BEGIN_ALLOW_THREADS  | 
13454  | 0  |             close(fd);  | 
13455  | 0  |             Py_END_ALLOW_THREADS  | 
13456  | 0  |         }  | 
13457  | 0  | #endif  | 
13458  | 0  |         goto error;  | 
13459  | 0  |     }  | 
13460  | 0  | #endif  | 
13461  |  |  | 
13462  | 0  |     return (PyObject *)iterator;  | 
13463  |  |  | 
13464  | 0  | error:  | 
13465  | 0  |     Py_DECREF(iterator);  | 
13466  | 0  |     return NULL;  | 
13467  | 0  | }  | 
13468  |  |  | 
13469  |  | /*  | 
13470  |  |     Return the file system path representation of the object.  | 
13471  |  |  | 
13472  |  |     If the object is str or bytes, then allow it to pass through with  | 
13473  |  |     an incremented refcount. If the object defines __fspath__(), then  | 
13474  |  |     return the result of that method. All other types raise a TypeError.  | 
13475  |  | */  | 
13476  |  | PyObject *  | 
13477  |  | PyOS_FSPath(PyObject *path)  | 
13478  | 3.03k  | { | 
13479  |  |     /* For error message reasons, this function is manually inlined in  | 
13480  |  |        path_converter(). */  | 
13481  | 3.03k  |     _Py_IDENTIFIER(__fspath__);  | 
13482  | 3.03k  |     PyObject *func = NULL;  | 
13483  | 3.03k  |     PyObject *path_repr = NULL;  | 
13484  |  |  | 
13485  | 3.03k  |     if (PyUnicode_Check(path) || PyBytes_Check(path)) { | 
13486  | 3.03k  |         Py_INCREF(path);  | 
13487  | 3.03k  |         return path;  | 
13488  | 3.03k  |     }  | 
13489  |  |  | 
13490  | 0  |     func = _PyObject_LookupSpecial(path, &PyId___fspath__);  | 
13491  | 0  |     if (NULL == func) { | 
13492  | 0  |         return PyErr_Format(PyExc_TypeError,  | 
13493  | 0  |                             "expected str, bytes or os.PathLike object, "  | 
13494  | 0  |                             "not %.200s",  | 
13495  | 0  |                             Py_TYPE(path)->tp_name);  | 
13496  | 0  |     }  | 
13497  |  |  | 
13498  | 0  |     path_repr = _PyObject_CallNoArg(func);  | 
13499  | 0  |     Py_DECREF(func);  | 
13500  | 0  |     if (NULL == path_repr) { | 
13501  | 0  |         return NULL;  | 
13502  | 0  |     }  | 
13503  |  |  | 
13504  | 0  |     if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) { | 
13505  | 0  |         PyErr_Format(PyExc_TypeError,  | 
13506  | 0  |                      "expected %.200s.__fspath__() to return str or bytes, "  | 
13507  | 0  |                      "not %.200s", Py_TYPE(path)->tp_name,  | 
13508  | 0  |                      Py_TYPE(path_repr)->tp_name);  | 
13509  | 0  |         Py_DECREF(path_repr);  | 
13510  | 0  |         return NULL;  | 
13511  | 0  |     }  | 
13512  |  |  | 
13513  | 0  |     return path_repr;  | 
13514  | 0  | }  | 
13515  |  |  | 
13516  |  | /*[clinic input]  | 
13517  |  | os.fspath  | 
13518  |  |  | 
13519  |  |     path: object  | 
13520  |  |  | 
13521  |  | Return the file system path representation of the object.  | 
13522  |  |  | 
13523  |  | If the object is str or bytes, then allow it to pass through as-is. If the  | 
13524  |  | object defines __fspath__(), then return the result of that method. All other  | 
13525  |  | types raise a TypeError.  | 
13526  |  | [clinic start generated code]*/  | 
13527  |  |  | 
13528  |  | static PyObject *  | 
13529  |  | os_fspath_impl(PyObject *module, PyObject *path)  | 
13530  |  | /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/  | 
13531  | 1.44k  | { | 
13532  | 1.44k  |     return PyOS_FSPath(path);  | 
13533  | 1.44k  | }  | 
13534  |  |  | 
13535  |  | #ifdef HAVE_GETRANDOM_SYSCALL  | 
13536  |  | /*[clinic input]  | 
13537  |  | os.getrandom  | 
13538  |  |  | 
13539  |  |     size: Py_ssize_t  | 
13540  |  |     flags: int=0  | 
13541  |  |  | 
13542  |  | Obtain a series of random bytes.  | 
13543  |  | [clinic start generated code]*/  | 
13544  |  |  | 
13545  |  | static PyObject *  | 
13546  |  | os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)  | 
13547  |  | /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/  | 
13548  | 0  | { | 
13549  | 0  |     PyObject *bytes;  | 
13550  | 0  |     Py_ssize_t n;  | 
13551  |  | 
  | 
13552  | 0  |     if (size < 0) { | 
13553  | 0  |         errno = EINVAL;  | 
13554  | 0  |         return posix_error();  | 
13555  | 0  |     }  | 
13556  |  |  | 
13557  | 0  |     bytes = PyBytes_FromStringAndSize(NULL, size);  | 
13558  | 0  |     if (bytes == NULL) { | 
13559  | 0  |         PyErr_NoMemory();  | 
13560  | 0  |         return NULL;  | 
13561  | 0  |     }  | 
13562  |  |  | 
13563  | 0  |     while (1) { | 
13564  | 0  |         n = syscall(SYS_getrandom,  | 
13565  | 0  |                     PyBytes_AS_STRING(bytes),  | 
13566  | 0  |                     PyBytes_GET_SIZE(bytes),  | 
13567  | 0  |                     flags);  | 
13568  | 0  |         if (n < 0 && errno == EINTR) { | 
13569  | 0  |             if (PyErr_CheckSignals() < 0) { | 
13570  | 0  |                 goto error;  | 
13571  | 0  |             }  | 
13572  |  |  | 
13573  |  |             /* getrandom() was interrupted by a signal: retry */  | 
13574  | 0  |             continue;  | 
13575  | 0  |         }  | 
13576  | 0  |         break;  | 
13577  | 0  |     }  | 
13578  |  |  | 
13579  | 0  |     if (n < 0) { | 
13580  | 0  |         PyErr_SetFromErrno(PyExc_OSError);  | 
13581  | 0  |         goto error;  | 
13582  | 0  |     }  | 
13583  |  |  | 
13584  | 0  |     if (n != size) { | 
13585  | 0  |         _PyBytes_Resize(&bytes, n);  | 
13586  | 0  |     }  | 
13587  |  | 
  | 
13588  | 0  |     return bytes;  | 
13589  |  |  | 
13590  | 0  | error:  | 
13591  | 0  |     Py_DECREF(bytes);  | 
13592  | 0  |     return NULL;  | 
13593  | 0  | }  | 
13594  |  | #endif   /* HAVE_GETRANDOM_SYSCALL */  | 
13595  |  |  | 
13596  |  | #ifdef MS_WINDOWS  | 
13597  |  | /* bpo-36085: Helper functions for managing DLL search directories  | 
13598  |  |  * on win32  | 
13599  |  |  */  | 
13600  |  |  | 
13601  |  | typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);  | 
13602  |  | typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);  | 
13603  |  |  | 
13604  |  | /*[clinic input]  | 
13605  |  | os._add_dll_directory  | 
13606  |  |  | 
13607  |  |     path: path_t  | 
13608  |  |  | 
13609  |  | Add a path to the DLL search path.  | 
13610  |  |  | 
13611  |  | This search path is used when resolving dependencies for imported  | 
13612  |  | extension modules (the module itself is resolved through sys.path),  | 
13613  |  | and also by ctypes.  | 
13614  |  |  | 
13615  |  | Returns an opaque value that may be passed to os.remove_dll_directory  | 
13616  |  | to remove this directory from the search path.  | 
13617  |  | [clinic start generated code]*/  | 
13618  |  |  | 
13619  |  | static PyObject *  | 
13620  |  | os__add_dll_directory_impl(PyObject *module, path_t *path)  | 
13621  |  | /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/  | 
13622  |  | { | 
13623  |  |     HMODULE hKernel32;  | 
13624  |  |     PAddDllDirectory AddDllDirectory;  | 
13625  |  |     DLL_DIRECTORY_COOKIE cookie = 0;  | 
13626  |  |     DWORD err = 0;  | 
13627  |  |  | 
13628  |  |     if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) { | 
13629  |  |         return NULL;  | 
13630  |  |     }  | 
13631  |  |  | 
13632  |  |     /* For Windows 7, we have to load this. As this will be a fairly  | 
13633  |  |        infrequent operation, just do it each time. Kernel32 is always  | 
13634  |  |        loaded. */  | 
13635  |  |     Py_BEGIN_ALLOW_THREADS  | 
13636  |  |     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||  | 
13637  |  |         !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(  | 
13638  |  |             hKernel32, "AddDllDirectory")) ||  | 
13639  |  |         !(cookie = (*AddDllDirectory)(path->wide))) { | 
13640  |  |         err = GetLastError();  | 
13641  |  |     }  | 
13642  |  |     Py_END_ALLOW_THREADS  | 
13643  |  |  | 
13644  |  |     if (err) { | 
13645  |  |         return win32_error_object_err("add_dll_directory", | 
13646  |  |                                       path->object, err);  | 
13647  |  |     }  | 
13648  |  |  | 
13649  |  |     return PyCapsule_New(cookie, "DLL directory cookie", NULL);  | 
13650  |  | }  | 
13651  |  |  | 
13652  |  | /*[clinic input]  | 
13653  |  | os._remove_dll_directory  | 
13654  |  |  | 
13655  |  |     cookie: object  | 
13656  |  |  | 
13657  |  | Removes a path from the DLL search path.  | 
13658  |  |  | 
13659  |  | The parameter is an opaque value that was returned from  | 
13660  |  | os.add_dll_directory. You can only remove directories that you added  | 
13661  |  | yourself.  | 
13662  |  | [clinic start generated code]*/  | 
13663  |  |  | 
13664  |  | static PyObject *  | 
13665  |  | os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)  | 
13666  |  | /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/  | 
13667  |  | { | 
13668  |  |     HMODULE hKernel32;  | 
13669  |  |     PRemoveDllDirectory RemoveDllDirectory;  | 
13670  |  |     DLL_DIRECTORY_COOKIE cookieValue;  | 
13671  |  |     DWORD err = 0;  | 
13672  |  |  | 
13673  |  |     if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) { | 
13674  |  |         PyErr_SetString(PyExc_TypeError,  | 
13675  |  |             "Provided cookie was not returned from os.add_dll_directory");  | 
13676  |  |         return NULL;  | 
13677  |  |     }  | 
13678  |  |  | 
13679  |  |     cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(  | 
13680  |  |         cookie, "DLL directory cookie");  | 
13681  |  |  | 
13682  |  |     /* For Windows 7, we have to load this. As this will be a fairly  | 
13683  |  |        infrequent operation, just do it each time. Kernel32 is always  | 
13684  |  |        loaded. */  | 
13685  |  |     Py_BEGIN_ALLOW_THREADS  | 
13686  |  |     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||  | 
13687  |  |         !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(  | 
13688  |  |             hKernel32, "RemoveDllDirectory")) ||  | 
13689  |  |         !(*RemoveDllDirectory)(cookieValue)) { | 
13690  |  |         err = GetLastError();  | 
13691  |  |     }  | 
13692  |  |     Py_END_ALLOW_THREADS  | 
13693  |  |  | 
13694  |  |     if (err) { | 
13695  |  |         return win32_error_object_err("remove_dll_directory", | 
13696  |  |                                       NULL, err);  | 
13697  |  |     }  | 
13698  |  |  | 
13699  |  |     if (PyCapsule_SetName(cookie, NULL)) { | 
13700  |  |         return NULL;  | 
13701  |  |     }  | 
13702  |  |  | 
13703  |  |     Py_RETURN_NONE;  | 
13704  |  | }  | 
13705  |  |  | 
13706  |  | #endif  | 
13707  |  |  | 
13708  |  | static PyMethodDef posix_methods[] = { | 
13709  |  |  | 
13710  |  |     OS_STAT_METHODDEF  | 
13711  |  |     OS_ACCESS_METHODDEF  | 
13712  |  |     OS_TTYNAME_METHODDEF  | 
13713  |  |     OS_CHDIR_METHODDEF  | 
13714  |  |     OS_CHFLAGS_METHODDEF  | 
13715  |  |     OS_CHMOD_METHODDEF  | 
13716  |  |     OS_FCHMOD_METHODDEF  | 
13717  |  |     OS_LCHMOD_METHODDEF  | 
13718  |  |     OS_CHOWN_METHODDEF  | 
13719  |  |     OS_FCHOWN_METHODDEF  | 
13720  |  |     OS_LCHOWN_METHODDEF  | 
13721  |  |     OS_LCHFLAGS_METHODDEF  | 
13722  |  |     OS_CHROOT_METHODDEF  | 
13723  |  |     OS_CTERMID_METHODDEF  | 
13724  |  |     OS_GETCWD_METHODDEF  | 
13725  |  |     OS_GETCWDB_METHODDEF  | 
13726  |  |     OS_LINK_METHODDEF  | 
13727  |  |     OS_LISTDIR_METHODDEF  | 
13728  |  |     OS_LSTAT_METHODDEF  | 
13729  |  |     OS_MKDIR_METHODDEF  | 
13730  |  |     OS_NICE_METHODDEF  | 
13731  |  |     OS_GETPRIORITY_METHODDEF  | 
13732  |  |     OS_SETPRIORITY_METHODDEF  | 
13733  |  |     OS_POSIX_SPAWN_METHODDEF  | 
13734  |  |     OS_POSIX_SPAWNP_METHODDEF  | 
13735  |  |     OS_READLINK_METHODDEF  | 
13736  |  |     OS_COPY_FILE_RANGE_METHODDEF  | 
13737  |  |     OS_RENAME_METHODDEF  | 
13738  |  |     OS_REPLACE_METHODDEF  | 
13739  |  |     OS_RMDIR_METHODDEF  | 
13740  |  |     OS_SYMLINK_METHODDEF  | 
13741  |  |     OS_SYSTEM_METHODDEF  | 
13742  |  |     OS_UMASK_METHODDEF  | 
13743  |  |     OS_UNAME_METHODDEF  | 
13744  |  |     OS_UNLINK_METHODDEF  | 
13745  |  |     OS_REMOVE_METHODDEF  | 
13746  |  |     OS_UTIME_METHODDEF  | 
13747  |  |     OS_TIMES_METHODDEF  | 
13748  |  |     OS__EXIT_METHODDEF  | 
13749  |  |     OS__FCOPYFILE_METHODDEF  | 
13750  |  |     OS_EXECV_METHODDEF  | 
13751  |  |     OS_EXECVE_METHODDEF  | 
13752  |  |     OS_SPAWNV_METHODDEF  | 
13753  |  |     OS_SPAWNVE_METHODDEF  | 
13754  |  |     OS_FORK1_METHODDEF  | 
13755  |  |     OS_FORK_METHODDEF  | 
13756  |  |     OS_REGISTER_AT_FORK_METHODDEF  | 
13757  |  |     OS_SCHED_GET_PRIORITY_MAX_METHODDEF  | 
13758  |  |     OS_SCHED_GET_PRIORITY_MIN_METHODDEF  | 
13759  |  |     OS_SCHED_GETPARAM_METHODDEF  | 
13760  |  |     OS_SCHED_GETSCHEDULER_METHODDEF  | 
13761  |  |     OS_SCHED_RR_GET_INTERVAL_METHODDEF  | 
13762  |  |     OS_SCHED_SETPARAM_METHODDEF  | 
13763  |  |     OS_SCHED_SETSCHEDULER_METHODDEF  | 
13764  |  |     OS_SCHED_YIELD_METHODDEF  | 
13765  |  |     OS_SCHED_SETAFFINITY_METHODDEF  | 
13766  |  |     OS_SCHED_GETAFFINITY_METHODDEF  | 
13767  |  |     OS_OPENPTY_METHODDEF  | 
13768  |  |     OS_FORKPTY_METHODDEF  | 
13769  |  |     OS_GETEGID_METHODDEF  | 
13770  |  |     OS_GETEUID_METHODDEF  | 
13771  |  |     OS_GETGID_METHODDEF  | 
13772  |  | #ifdef HAVE_GETGROUPLIST  | 
13773  |  |     {"getgrouplist",    posix_getgrouplist, METH_VARARGS, posix_getgrouplist__doc__}, | 
13774  |  | #endif  | 
13775  |  |     OS_GETGROUPS_METHODDEF  | 
13776  |  |     OS_GETPID_METHODDEF  | 
13777  |  |     OS_GETPGRP_METHODDEF  | 
13778  |  |     OS_GETPPID_METHODDEF  | 
13779  |  |     OS_GETUID_METHODDEF  | 
13780  |  |     OS_GETLOGIN_METHODDEF  | 
13781  |  |     OS_KILL_METHODDEF  | 
13782  |  |     OS_KILLPG_METHODDEF  | 
13783  |  |     OS_PLOCK_METHODDEF  | 
13784  |  | #ifdef MS_WINDOWS  | 
13785  |  |     OS_STARTFILE_METHODDEF  | 
13786  |  | #endif  | 
13787  |  |     OS_SETUID_METHODDEF  | 
13788  |  |     OS_SETEUID_METHODDEF  | 
13789  |  |     OS_SETREUID_METHODDEF  | 
13790  |  |     OS_SETGID_METHODDEF  | 
13791  |  |     OS_SETEGID_METHODDEF  | 
13792  |  |     OS_SETREGID_METHODDEF  | 
13793  |  |     OS_SETGROUPS_METHODDEF  | 
13794  |  | #ifdef HAVE_INITGROUPS  | 
13795  |  |     {"initgroups",      posix_initgroups, METH_VARARGS, posix_initgroups__doc__}, | 
13796  |  | #endif /* HAVE_INITGROUPS */  | 
13797  |  |     OS_GETPGID_METHODDEF  | 
13798  |  |     OS_SETPGRP_METHODDEF  | 
13799  |  |     OS_WAIT_METHODDEF  | 
13800  |  |     OS_WAIT3_METHODDEF  | 
13801  |  |     OS_WAIT4_METHODDEF  | 
13802  |  |     OS_WAITID_METHODDEF  | 
13803  |  |     OS_WAITPID_METHODDEF  | 
13804  |  |     OS_GETSID_METHODDEF  | 
13805  |  |     OS_SETSID_METHODDEF  | 
13806  |  |     OS_SETPGID_METHODDEF  | 
13807  |  |     OS_TCGETPGRP_METHODDEF  | 
13808  |  |     OS_TCSETPGRP_METHODDEF  | 
13809  |  |     OS_OPEN_METHODDEF  | 
13810  |  |     OS_CLOSE_METHODDEF  | 
13811  |  |     OS_CLOSERANGE_METHODDEF  | 
13812  |  |     OS_DEVICE_ENCODING_METHODDEF  | 
13813  |  |     OS_DUP_METHODDEF  | 
13814  |  |     OS_DUP2_METHODDEF  | 
13815  |  |     OS_LOCKF_METHODDEF  | 
13816  |  |     OS_LSEEK_METHODDEF  | 
13817  |  |     OS_READ_METHODDEF  | 
13818  |  |     OS_READV_METHODDEF  | 
13819  |  |     OS_PREAD_METHODDEF  | 
13820  |  |     OS_PREADV_METHODDEF  | 
13821  |  |     OS_WRITE_METHODDEF  | 
13822  |  |     OS_WRITEV_METHODDEF  | 
13823  |  |     OS_PWRITE_METHODDEF  | 
13824  |  |     OS_PWRITEV_METHODDEF  | 
13825  |  | #ifdef HAVE_SENDFILE  | 
13826  |  |     {"sendfile",        (PyCFunction)(void(*)(void))posix_sendfile, METH_VARARGS | METH_KEYWORDS, | 
13827  |  |                             posix_sendfile__doc__},  | 
13828  |  | #endif  | 
13829  |  |     OS_FSTAT_METHODDEF  | 
13830  |  |     OS_ISATTY_METHODDEF  | 
13831  |  |     OS_PIPE_METHODDEF  | 
13832  |  |     OS_PIPE2_METHODDEF  | 
13833  |  |     OS_MKFIFO_METHODDEF  | 
13834  |  |     OS_MKNOD_METHODDEF  | 
13835  |  |     OS_MAJOR_METHODDEF  | 
13836  |  |     OS_MINOR_METHODDEF  | 
13837  |  |     OS_MAKEDEV_METHODDEF  | 
13838  |  |     OS_FTRUNCATE_METHODDEF  | 
13839  |  |     OS_TRUNCATE_METHODDEF  | 
13840  |  |     OS_POSIX_FALLOCATE_METHODDEF  | 
13841  |  |     OS_POSIX_FADVISE_METHODDEF  | 
13842  |  |     OS_PUTENV_METHODDEF  | 
13843  |  |     OS_UNSETENV_METHODDEF  | 
13844  |  |     OS_STRERROR_METHODDEF  | 
13845  |  |     OS_FCHDIR_METHODDEF  | 
13846  |  |     OS_FSYNC_METHODDEF  | 
13847  |  |     OS_SYNC_METHODDEF  | 
13848  |  |     OS_FDATASYNC_METHODDEF  | 
13849  |  |     OS_WCOREDUMP_METHODDEF  | 
13850  |  |     OS_WIFCONTINUED_METHODDEF  | 
13851  |  |     OS_WIFSTOPPED_METHODDEF  | 
13852  |  |     OS_WIFSIGNALED_METHODDEF  | 
13853  |  |     OS_WIFEXITED_METHODDEF  | 
13854  |  |     OS_WEXITSTATUS_METHODDEF  | 
13855  |  |     OS_WTERMSIG_METHODDEF  | 
13856  |  |     OS_WSTOPSIG_METHODDEF  | 
13857  |  |     OS_FSTATVFS_METHODDEF  | 
13858  |  |     OS_STATVFS_METHODDEF  | 
13859  |  |     OS_CONFSTR_METHODDEF  | 
13860  |  |     OS_SYSCONF_METHODDEF  | 
13861  |  |     OS_FPATHCONF_METHODDEF  | 
13862  |  |     OS_PATHCONF_METHODDEF  | 
13863  |  |     OS_ABORT_METHODDEF  | 
13864  |  |     OS__GETFULLPATHNAME_METHODDEF  | 
13865  |  |     OS__GETDISKUSAGE_METHODDEF  | 
13866  |  |     OS__GETFINALPATHNAME_METHODDEF  | 
13867  |  |     OS__GETVOLUMEPATHNAME_METHODDEF  | 
13868  |  |     OS_GETLOADAVG_METHODDEF  | 
13869  |  |     OS_URANDOM_METHODDEF  | 
13870  |  |     OS_SETRESUID_METHODDEF  | 
13871  |  |     OS_SETRESGID_METHODDEF  | 
13872  |  |     OS_GETRESUID_METHODDEF  | 
13873  |  |     OS_GETRESGID_METHODDEF  | 
13874  |  |  | 
13875  |  |     OS_GETXATTR_METHODDEF  | 
13876  |  |     OS_SETXATTR_METHODDEF  | 
13877  |  |     OS_REMOVEXATTR_METHODDEF  | 
13878  |  |     OS_LISTXATTR_METHODDEF  | 
13879  |  |  | 
13880  |  | #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)  | 
13881  |  |     {"get_terminal_size", get_terminal_size, METH_VARARGS, termsize__doc__}, | 
13882  |  | #endif  | 
13883  |  |     OS_CPU_COUNT_METHODDEF  | 
13884  |  |     OS_GET_INHERITABLE_METHODDEF  | 
13885  |  |     OS_SET_INHERITABLE_METHODDEF  | 
13886  |  |     OS_GET_HANDLE_INHERITABLE_METHODDEF  | 
13887  |  |     OS_SET_HANDLE_INHERITABLE_METHODDEF  | 
13888  |  | #ifndef MS_WINDOWS  | 
13889  |  |     OS_GET_BLOCKING_METHODDEF  | 
13890  |  |     OS_SET_BLOCKING_METHODDEF  | 
13891  |  | #endif  | 
13892  |  |     OS_SCANDIR_METHODDEF  | 
13893  |  |     OS_FSPATH_METHODDEF  | 
13894  |  |     OS_GETRANDOM_METHODDEF  | 
13895  |  |     OS_MEMFD_CREATE_METHODDEF  | 
13896  |  | #ifdef MS_WINDOWS  | 
13897  |  |     OS__ADD_DLL_DIRECTORY_METHODDEF  | 
13898  |  |     OS__REMOVE_DLL_DIRECTORY_METHODDEF  | 
13899  |  | #endif  | 
13900  |  |     {NULL,              NULL}            /* Sentinel */ | 
13901  |  | };  | 
13902  |  |  | 
13903  |  | static int  | 
13904  |  | all_ins(PyObject *m)  | 
13905  | 14  | { | 
13906  | 14  | #ifdef F_OK  | 
13907  | 14  |     if (PyModule_AddIntMacro(m, F_OK)) return -1;  | 
13908  | 14  | #endif  | 
13909  | 14  | #ifdef R_OK  | 
13910  | 14  |     if (PyModule_AddIntMacro(m, R_OK)) return -1;  | 
13911  | 14  | #endif  | 
13912  | 14  | #ifdef W_OK  | 
13913  | 14  |     if (PyModule_AddIntMacro(m, W_OK)) return -1;  | 
13914  | 14  | #endif  | 
13915  | 14  | #ifdef X_OK  | 
13916  | 14  |     if (PyModule_AddIntMacro(m, X_OK)) return -1;  | 
13917  | 14  | #endif  | 
13918  | 14  | #ifdef NGROUPS_MAX  | 
13919  | 14  |     if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;  | 
13920  | 14  | #endif  | 
13921  | 14  | #ifdef TMP_MAX  | 
13922  | 14  |     if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;  | 
13923  | 14  | #endif  | 
13924  | 14  | #ifdef WCONTINUED  | 
13925  | 14  |     if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;  | 
13926  | 14  | #endif  | 
13927  | 14  | #ifdef WNOHANG  | 
13928  | 14  |     if (PyModule_AddIntMacro(m, WNOHANG)) return -1;  | 
13929  | 14  | #endif  | 
13930  | 14  | #ifdef WUNTRACED  | 
13931  | 14  |     if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;  | 
13932  | 14  | #endif  | 
13933  | 14  | #ifdef O_RDONLY  | 
13934  | 14  |     if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;  | 
13935  | 14  | #endif  | 
13936  | 14  | #ifdef O_WRONLY  | 
13937  | 14  |     if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;  | 
13938  | 14  | #endif  | 
13939  | 14  | #ifdef O_RDWR  | 
13940  | 14  |     if (PyModule_AddIntMacro(m, O_RDWR)) return -1;  | 
13941  | 14  | #endif  | 
13942  | 14  | #ifdef O_NDELAY  | 
13943  | 14  |     if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;  | 
13944  | 14  | #endif  | 
13945  | 14  | #ifdef O_NONBLOCK  | 
13946  | 14  |     if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;  | 
13947  | 14  | #endif  | 
13948  | 14  | #ifdef O_APPEND  | 
13949  | 14  |     if (PyModule_AddIntMacro(m, O_APPEND)) return -1;  | 
13950  | 14  | #endif  | 
13951  | 14  | #ifdef O_DSYNC  | 
13952  | 14  |     if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;  | 
13953  | 14  | #endif  | 
13954  | 14  | #ifdef O_RSYNC  | 
13955  | 14  |     if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;  | 
13956  | 14  | #endif  | 
13957  | 14  | #ifdef O_SYNC  | 
13958  | 14  |     if (PyModule_AddIntMacro(m, O_SYNC)) return -1;  | 
13959  | 14  | #endif  | 
13960  | 14  | #ifdef O_NOCTTY  | 
13961  | 14  |     if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;  | 
13962  | 14  | #endif  | 
13963  | 14  | #ifdef O_CREAT  | 
13964  | 14  |     if (PyModule_AddIntMacro(m, O_CREAT)) return -1;  | 
13965  | 14  | #endif  | 
13966  | 14  | #ifdef O_EXCL  | 
13967  | 14  |     if (PyModule_AddIntMacro(m, O_EXCL)) return -1;  | 
13968  | 14  | #endif  | 
13969  | 14  | #ifdef O_TRUNC  | 
13970  | 14  |     if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;  | 
13971  | 14  | #endif  | 
13972  |  | #ifdef O_BINARY  | 
13973  |  |     if (PyModule_AddIntMacro(m, O_BINARY)) return -1;  | 
13974  |  | #endif  | 
13975  |  | #ifdef O_TEXT  | 
13976  |  |     if (PyModule_AddIntMacro(m, O_TEXT)) return -1;  | 
13977  |  | #endif  | 
13978  |  | #ifdef O_XATTR  | 
13979  |  |     if (PyModule_AddIntMacro(m, O_XATTR)) return -1;  | 
13980  |  | #endif  | 
13981  | 14  | #ifdef O_LARGEFILE  | 
13982  | 14  |     if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;  | 
13983  | 14  | #endif  | 
13984  | 14  | #ifndef __GNU__  | 
13985  |  | #ifdef O_SHLOCK  | 
13986  |  |     if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;  | 
13987  |  | #endif  | 
13988  |  | #ifdef O_EXLOCK  | 
13989  |  |     if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;  | 
13990  |  | #endif  | 
13991  | 14  | #endif  | 
13992  |  | #ifdef O_EXEC  | 
13993  |  |     if (PyModule_AddIntMacro(m, O_EXEC)) return -1;  | 
13994  |  | #endif  | 
13995  |  | #ifdef O_SEARCH  | 
13996  |  |     if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;  | 
13997  |  | #endif  | 
13998  | 14  | #ifdef O_PATH  | 
13999  | 14  |     if (PyModule_AddIntMacro(m, O_PATH)) return -1;  | 
14000  | 14  | #endif  | 
14001  |  | #ifdef O_TTY_INIT  | 
14002  |  |     if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;  | 
14003  |  | #endif  | 
14004  | 14  | #ifdef O_TMPFILE  | 
14005  | 14  |     if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;  | 
14006  | 14  | #endif  | 
14007  | 14  | #ifdef PRIO_PROCESS  | 
14008  | 14  |     if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;  | 
14009  | 14  | #endif  | 
14010  | 14  | #ifdef PRIO_PGRP  | 
14011  | 14  |     if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;  | 
14012  | 14  | #endif  | 
14013  | 14  | #ifdef PRIO_USER  | 
14014  | 14  |     if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;  | 
14015  | 14  | #endif  | 
14016  | 14  | #ifdef O_CLOEXEC  | 
14017  | 14  |     if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;  | 
14018  | 14  | #endif  | 
14019  | 14  | #ifdef O_ACCMODE  | 
14020  | 14  |     if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;  | 
14021  | 14  | #endif  | 
14022  |  |  | 
14023  |  |  | 
14024  | 14  | #ifdef SEEK_HOLE  | 
14025  | 14  |     if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;  | 
14026  | 14  | #endif  | 
14027  | 14  | #ifdef SEEK_DATA  | 
14028  | 14  |     if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;  | 
14029  | 14  | #endif  | 
14030  |  |  | 
14031  |  | /* MS Windows */  | 
14032  |  | #ifdef O_NOINHERIT  | 
14033  |  |     /* Don't inherit in child processes. */  | 
14034  |  |     if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;  | 
14035  |  | #endif  | 
14036  |  | #ifdef _O_SHORT_LIVED  | 
14037  |  |     /* Optimize for short life (keep in memory). */  | 
14038  |  |     /* MS forgot to define this one with a non-underscore form too. */  | 
14039  |  |     if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;  | 
14040  |  | #endif  | 
14041  |  | #ifdef O_TEMPORARY  | 
14042  |  |     /* Automatically delete when last handle is closed. */  | 
14043  |  |     if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;  | 
14044  |  | #endif  | 
14045  |  | #ifdef O_RANDOM  | 
14046  |  |     /* Optimize for random access. */  | 
14047  |  |     if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;  | 
14048  |  | #endif  | 
14049  |  | #ifdef O_SEQUENTIAL  | 
14050  |  |     /* Optimize for sequential access. */  | 
14051  |  |     if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;  | 
14052  |  | #endif  | 
14053  |  |  | 
14054  |  | /* GNU extensions. */  | 
14055  | 14  | #ifdef O_ASYNC  | 
14056  |  |     /* Send a SIGIO signal whenever input or output  | 
14057  |  |        becomes available on file descriptor */  | 
14058  | 14  |     if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;  | 
14059  | 14  | #endif  | 
14060  | 14  | #ifdef O_DIRECT  | 
14061  |  |     /* Direct disk access. */  | 
14062  | 14  |     if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;  | 
14063  | 14  | #endif  | 
14064  | 14  | #ifdef O_DIRECTORY  | 
14065  |  |     /* Must be a directory.      */  | 
14066  | 14  |     if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;  | 
14067  | 14  | #endif  | 
14068  | 14  | #ifdef O_NOFOLLOW  | 
14069  |  |     /* Do not follow links.      */  | 
14070  | 14  |     if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;  | 
14071  | 14  | #endif  | 
14072  |  | #ifdef O_NOLINKS  | 
14073  |  |     /* Fails if link count of the named file is greater than 1 */  | 
14074  |  |     if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;  | 
14075  |  | #endif  | 
14076  | 14  | #ifdef O_NOATIME  | 
14077  |  |     /* Do not update the access time. */  | 
14078  | 14  |     if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;  | 
14079  | 14  | #endif  | 
14080  |  |  | 
14081  |  |     /* These come from sysexits.h */  | 
14082  | 14  | #ifdef EX_OK  | 
14083  | 14  |     if (PyModule_AddIntMacro(m, EX_OK)) return -1;  | 
14084  | 14  | #endif /* EX_OK */  | 
14085  | 14  | #ifdef EX_USAGE  | 
14086  | 14  |     if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;  | 
14087  | 14  | #endif /* EX_USAGE */  | 
14088  | 14  | #ifdef EX_DATAERR  | 
14089  | 14  |     if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;  | 
14090  | 14  | #endif /* EX_DATAERR */  | 
14091  | 14  | #ifdef EX_NOINPUT  | 
14092  | 14  |     if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;  | 
14093  | 14  | #endif /* EX_NOINPUT */  | 
14094  | 14  | #ifdef EX_NOUSER  | 
14095  | 14  |     if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;  | 
14096  | 14  | #endif /* EX_NOUSER */  | 
14097  | 14  | #ifdef EX_NOHOST  | 
14098  | 14  |     if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;  | 
14099  | 14  | #endif /* EX_NOHOST */  | 
14100  | 14  | #ifdef EX_UNAVAILABLE  | 
14101  | 14  |     if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;  | 
14102  | 14  | #endif /* EX_UNAVAILABLE */  | 
14103  | 14  | #ifdef EX_SOFTWARE  | 
14104  | 14  |     if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;  | 
14105  | 14  | #endif /* EX_SOFTWARE */  | 
14106  | 14  | #ifdef EX_OSERR  | 
14107  | 14  |     if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;  | 
14108  | 14  | #endif /* EX_OSERR */  | 
14109  | 14  | #ifdef EX_OSFILE  | 
14110  | 14  |     if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;  | 
14111  | 14  | #endif /* EX_OSFILE */  | 
14112  | 14  | #ifdef EX_CANTCREAT  | 
14113  | 14  |     if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;  | 
14114  | 14  | #endif /* EX_CANTCREAT */  | 
14115  | 14  | #ifdef EX_IOERR  | 
14116  | 14  |     if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;  | 
14117  | 14  | #endif /* EX_IOERR */  | 
14118  | 14  | #ifdef EX_TEMPFAIL  | 
14119  | 14  |     if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;  | 
14120  | 14  | #endif /* EX_TEMPFAIL */  | 
14121  | 14  | #ifdef EX_PROTOCOL  | 
14122  | 14  |     if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;  | 
14123  | 14  | #endif /* EX_PROTOCOL */  | 
14124  | 14  | #ifdef EX_NOPERM  | 
14125  | 14  |     if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;  | 
14126  | 14  | #endif /* EX_NOPERM */  | 
14127  | 14  | #ifdef EX_CONFIG  | 
14128  | 14  |     if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;  | 
14129  | 14  | #endif /* EX_CONFIG */  | 
14130  |  | #ifdef EX_NOTFOUND  | 
14131  |  |     if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;  | 
14132  |  | #endif /* EX_NOTFOUND */  | 
14133  |  |  | 
14134  |  |     /* statvfs */  | 
14135  | 14  | #ifdef ST_RDONLY  | 
14136  | 14  |     if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;  | 
14137  | 14  | #endif /* ST_RDONLY */  | 
14138  | 14  | #ifdef ST_NOSUID  | 
14139  | 14  |     if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;  | 
14140  | 14  | #endif /* ST_NOSUID */  | 
14141  |  |  | 
14142  |  |        /* GNU extensions */  | 
14143  | 14  | #ifdef ST_NODEV  | 
14144  | 14  |     if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;  | 
14145  | 14  | #endif /* ST_NODEV */  | 
14146  | 14  | #ifdef ST_NOEXEC  | 
14147  | 14  |     if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;  | 
14148  | 14  | #endif /* ST_NOEXEC */  | 
14149  | 14  | #ifdef ST_SYNCHRONOUS  | 
14150  | 14  |     if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;  | 
14151  | 14  | #endif /* ST_SYNCHRONOUS */  | 
14152  | 14  | #ifdef ST_MANDLOCK  | 
14153  | 14  |     if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;  | 
14154  | 14  | #endif /* ST_MANDLOCK */  | 
14155  | 14  | #ifdef ST_WRITE  | 
14156  | 14  |     if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;  | 
14157  | 14  | #endif /* ST_WRITE */  | 
14158  | 14  | #ifdef ST_APPEND  | 
14159  | 14  |     if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;  | 
14160  | 14  | #endif /* ST_APPEND */  | 
14161  | 14  | #ifdef ST_NOATIME  | 
14162  | 14  |     if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;  | 
14163  | 14  | #endif /* ST_NOATIME */  | 
14164  | 14  | #ifdef ST_NODIRATIME  | 
14165  | 14  |     if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;  | 
14166  | 14  | #endif /* ST_NODIRATIME */  | 
14167  | 14  | #ifdef ST_RELATIME  | 
14168  | 14  |     if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;  | 
14169  | 14  | #endif /* ST_RELATIME */  | 
14170  |  |  | 
14171  |  |     /* FreeBSD sendfile() constants */  | 
14172  |  | #ifdef SF_NODISKIO  | 
14173  |  |     if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;  | 
14174  |  | #endif  | 
14175  |  | #ifdef SF_MNOWAIT  | 
14176  |  |     if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;  | 
14177  |  | #endif  | 
14178  |  | #ifdef SF_SYNC  | 
14179  |  |     if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;  | 
14180  |  | #endif  | 
14181  |  |  | 
14182  |  |     /* constants for posix_fadvise */  | 
14183  | 14  | #ifdef POSIX_FADV_NORMAL  | 
14184  | 14  |     if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;  | 
14185  | 14  | #endif  | 
14186  | 14  | #ifdef POSIX_FADV_SEQUENTIAL  | 
14187  | 14  |     if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;  | 
14188  | 14  | #endif  | 
14189  | 14  | #ifdef POSIX_FADV_RANDOM  | 
14190  | 14  |     if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;  | 
14191  | 14  | #endif  | 
14192  | 14  | #ifdef POSIX_FADV_NOREUSE  | 
14193  | 14  |     if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;  | 
14194  | 14  | #endif  | 
14195  | 14  | #ifdef POSIX_FADV_WILLNEED  | 
14196  | 14  |     if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;  | 
14197  | 14  | #endif  | 
14198  | 14  | #ifdef POSIX_FADV_DONTNEED  | 
14199  | 14  |     if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;  | 
14200  | 14  | #endif  | 
14201  |  |  | 
14202  |  |     /* constants for waitid */  | 
14203  | 14  | #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)  | 
14204  | 14  |     if (PyModule_AddIntMacro(m, P_PID)) return -1;  | 
14205  | 14  |     if (PyModule_AddIntMacro(m, P_PGID)) return -1;  | 
14206  | 14  |     if (PyModule_AddIntMacro(m, P_ALL)) return -1;  | 
14207  | 14  | #endif  | 
14208  | 14  | #ifdef WEXITED  | 
14209  | 14  |     if (PyModule_AddIntMacro(m, WEXITED)) return -1;  | 
14210  | 14  | #endif  | 
14211  | 14  | #ifdef WNOWAIT  | 
14212  | 14  |     if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;  | 
14213  | 14  | #endif  | 
14214  | 14  | #ifdef WSTOPPED  | 
14215  | 14  |     if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;  | 
14216  | 14  | #endif  | 
14217  | 14  | #ifdef CLD_EXITED  | 
14218  | 14  |     if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;  | 
14219  | 14  | #endif  | 
14220  | 14  | #ifdef CLD_DUMPED  | 
14221  | 14  |     if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;  | 
14222  | 14  | #endif  | 
14223  | 14  | #ifdef CLD_TRAPPED  | 
14224  | 14  |     if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;  | 
14225  | 14  | #endif  | 
14226  | 14  | #ifdef CLD_CONTINUED  | 
14227  | 14  |     if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;  | 
14228  | 14  | #endif  | 
14229  |  |  | 
14230  |  |     /* constants for lockf */  | 
14231  | 14  | #ifdef F_LOCK  | 
14232  | 14  |     if (PyModule_AddIntMacro(m, F_LOCK)) return -1;  | 
14233  | 14  | #endif  | 
14234  | 14  | #ifdef F_TLOCK  | 
14235  | 14  |     if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;  | 
14236  | 14  | #endif  | 
14237  | 14  | #ifdef F_ULOCK  | 
14238  | 14  |     if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;  | 
14239  | 14  | #endif  | 
14240  | 14  | #ifdef F_TEST  | 
14241  | 14  |     if (PyModule_AddIntMacro(m, F_TEST)) return -1;  | 
14242  | 14  | #endif  | 
14243  |  |  | 
14244  | 14  | #ifdef RWF_DSYNC  | 
14245  | 14  |     if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;  | 
14246  | 14  | #endif  | 
14247  | 14  | #ifdef RWF_HIPRI  | 
14248  | 14  |     if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;  | 
14249  | 14  | #endif  | 
14250  | 14  | #ifdef RWF_SYNC  | 
14251  | 14  |     if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;  | 
14252  | 14  | #endif  | 
14253  | 14  | #ifdef RWF_NOWAIT  | 
14254  | 14  |     if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;  | 
14255  | 14  | #endif  | 
14256  |  |  | 
14257  |  | /* constants for posix_spawn */  | 
14258  | 14  | #ifdef HAVE_POSIX_SPAWN  | 
14259  | 14  |     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;  | 
14260  | 14  |     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;  | 
14261  | 14  |     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;  | 
14262  | 14  | #endif  | 
14263  |  |  | 
14264  |  | #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)  | 
14265  |  |     if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;  | 
14266  |  |     if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;  | 
14267  |  |     if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;  | 
14268  |  | #endif  | 
14269  |  | #ifdef HAVE_SPAWNV  | 
14270  |  |     if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;  | 
14271  |  |     if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;  | 
14272  |  | #endif  | 
14273  |  |  | 
14274  | 14  | #ifdef HAVE_SCHED_H  | 
14275  | 14  | #ifdef SCHED_OTHER  | 
14276  | 14  |     if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;  | 
14277  | 14  | #endif  | 
14278  | 14  | #ifdef SCHED_FIFO  | 
14279  | 14  |     if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;  | 
14280  | 14  | #endif  | 
14281  | 14  | #ifdef SCHED_RR  | 
14282  | 14  |     if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;  | 
14283  | 14  | #endif  | 
14284  |  | #ifdef SCHED_SPORADIC  | 
14285  |  |     if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;  | 
14286  |  | #endif  | 
14287  | 14  | #ifdef SCHED_BATCH  | 
14288  | 14  |     if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;  | 
14289  | 14  | #endif  | 
14290  | 14  | #ifdef SCHED_IDLE  | 
14291  | 14  |     if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;  | 
14292  | 14  | #endif  | 
14293  | 14  | #ifdef SCHED_RESET_ON_FORK  | 
14294  | 14  |     if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;  | 
14295  | 14  | #endif  | 
14296  |  | #ifdef SCHED_SYS  | 
14297  |  |     if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;  | 
14298  |  | #endif  | 
14299  |  | #ifdef SCHED_IA  | 
14300  |  |     if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;  | 
14301  |  | #endif  | 
14302  |  | #ifdef SCHED_FSS  | 
14303  |  |     if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;  | 
14304  |  | #endif  | 
14305  |  | #ifdef SCHED_FX  | 
14306  |  |     if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;  | 
14307  |  | #endif  | 
14308  | 14  | #endif  | 
14309  |  |  | 
14310  | 14  | #ifdef USE_XATTRS  | 
14311  | 14  |     if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;  | 
14312  | 14  |     if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;  | 
14313  | 14  |     if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;  | 
14314  | 14  | #endif  | 
14315  |  |  | 
14316  | 14  | #if HAVE_DECL_RTLD_LAZY  | 
14317  | 14  |     if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;  | 
14318  | 14  | #endif  | 
14319  | 14  | #if HAVE_DECL_RTLD_NOW  | 
14320  | 14  |     if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;  | 
14321  | 14  | #endif  | 
14322  | 14  | #if HAVE_DECL_RTLD_GLOBAL  | 
14323  | 14  |     if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;  | 
14324  | 14  | #endif  | 
14325  | 14  | #if HAVE_DECL_RTLD_LOCAL  | 
14326  | 14  |     if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;  | 
14327  | 14  | #endif  | 
14328  | 14  | #if HAVE_DECL_RTLD_NODELETE  | 
14329  | 14  |     if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;  | 
14330  | 14  | #endif  | 
14331  | 14  | #if HAVE_DECL_RTLD_NOLOAD  | 
14332  | 14  |     if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;  | 
14333  | 14  | #endif  | 
14334  | 14  | #if HAVE_DECL_RTLD_DEEPBIND  | 
14335  | 14  |     if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;  | 
14336  | 14  | #endif  | 
14337  |  | #if HAVE_DECL_RTLD_MEMBER  | 
14338  |  |     if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;  | 
14339  |  | #endif  | 
14340  |  |  | 
14341  | 14  | #ifdef HAVE_GETRANDOM_SYSCALL  | 
14342  | 14  |     if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;  | 
14343  | 14  |     if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;  | 
14344  | 14  | #endif  | 
14345  | 14  | #ifdef HAVE_MEMFD_CREATE  | 
14346  | 14  |     if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;  | 
14347  | 14  |     if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;  | 
14348  | 14  | #ifdef MFD_HUGETLB  | 
14349  | 14  |     if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;  | 
14350  | 14  | #endif  | 
14351  | 14  | #ifdef MFD_HUGE_SHIFT  | 
14352  | 14  |     if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;  | 
14353  | 14  | #endif  | 
14354  | 14  | #ifdef MFD_HUGE_MASK  | 
14355  | 14  |     if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;  | 
14356  | 14  | #endif  | 
14357  | 14  | #ifdef MFD_HUGE_64KB  | 
14358  | 14  |     if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;  | 
14359  | 14  | #endif  | 
14360  | 14  | #ifdef MFD_HUGE_512KB  | 
14361  | 14  |     if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;  | 
14362  | 14  | #endif  | 
14363  | 14  | #ifdef MFD_HUGE_1MB  | 
14364  | 14  |     if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;  | 
14365  | 14  | #endif  | 
14366  | 14  | #ifdef MFD_HUGE_2MB  | 
14367  | 14  |     if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;  | 
14368  | 14  | #endif  | 
14369  | 14  | #ifdef MFD_HUGE_8MB  | 
14370  | 14  |     if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;  | 
14371  | 14  | #endif  | 
14372  | 14  | #ifdef MFD_HUGE_16MB  | 
14373  | 14  |     if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;  | 
14374  | 14  | #endif  | 
14375  | 14  | #ifdef MFD_HUGE_32MB  | 
14376  | 14  |     if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;  | 
14377  | 14  | #endif  | 
14378  | 14  | #ifdef MFD_HUGE_256MB  | 
14379  | 14  |     if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;  | 
14380  | 14  | #endif  | 
14381  | 14  | #ifdef MFD_HUGE_512MB  | 
14382  | 14  |     if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;  | 
14383  | 14  | #endif  | 
14384  | 14  | #ifdef MFD_HUGE_1GB  | 
14385  | 14  |     if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;  | 
14386  | 14  | #endif  | 
14387  | 14  | #ifdef MFD_HUGE_2GB  | 
14388  | 14  |     if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;  | 
14389  | 14  | #endif  | 
14390  | 14  | #ifdef MFD_HUGE_16GB  | 
14391  | 14  |     if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;  | 
14392  | 14  | #endif  | 
14393  | 14  | #endif  | 
14394  |  |  | 
14395  |  | #if defined(__APPLE__)  | 
14396  |  |     if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;  | 
14397  |  | #endif  | 
14398  |  |  | 
14399  |  | #ifdef MS_WINDOWS  | 
14400  |  |     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;  | 
14401  |  |     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;  | 
14402  |  |     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;  | 
14403  |  |     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;  | 
14404  |  |     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;  | 
14405  |  | #endif  | 
14406  |  |  | 
14407  | 14  |     return 0;  | 
14408  | 14  | }  | 
14409  |  |  | 
14410  |  |  | 
14411  |  | static struct PyModuleDef posixmodule = { | 
14412  |  |     PyModuleDef_HEAD_INIT,  | 
14413  |  |     MODNAME,  | 
14414  |  |     posix__doc__,  | 
14415  |  |     -1,  | 
14416  |  |     posix_methods,  | 
14417  |  |     NULL,  | 
14418  |  |     NULL,  | 
14419  |  |     NULL,  | 
14420  |  |     NULL  | 
14421  |  | };  | 
14422  |  |  | 
14423  |  |  | 
14424  |  | static const char * const have_functions[] = { | 
14425  |  |  | 
14426  |  | #ifdef HAVE_FACCESSAT  | 
14427  |  |     "HAVE_FACCESSAT",  | 
14428  |  | #endif  | 
14429  |  |  | 
14430  |  | #ifdef HAVE_FCHDIR  | 
14431  |  |     "HAVE_FCHDIR",  | 
14432  |  | #endif  | 
14433  |  |  | 
14434  |  | #ifdef HAVE_FCHMOD  | 
14435  |  |     "HAVE_FCHMOD",  | 
14436  |  | #endif  | 
14437  |  |  | 
14438  |  | #ifdef HAVE_FCHMODAT  | 
14439  |  |     "HAVE_FCHMODAT",  | 
14440  |  | #endif  | 
14441  |  |  | 
14442  |  | #ifdef HAVE_FCHOWN  | 
14443  |  |     "HAVE_FCHOWN",  | 
14444  |  | #endif  | 
14445  |  |  | 
14446  |  | #ifdef HAVE_FCHOWNAT  | 
14447  |  |     "HAVE_FCHOWNAT",  | 
14448  |  | #endif  | 
14449  |  |  | 
14450  |  | #ifdef HAVE_FEXECVE  | 
14451  |  |     "HAVE_FEXECVE",  | 
14452  |  | #endif  | 
14453  |  |  | 
14454  |  | #ifdef HAVE_FDOPENDIR  | 
14455  |  |     "HAVE_FDOPENDIR",  | 
14456  |  | #endif  | 
14457  |  |  | 
14458  |  | #ifdef HAVE_FPATHCONF  | 
14459  |  |     "HAVE_FPATHCONF",  | 
14460  |  | #endif  | 
14461  |  |  | 
14462  |  | #ifdef HAVE_FSTATAT  | 
14463  |  |     "HAVE_FSTATAT",  | 
14464  |  | #endif  | 
14465  |  |  | 
14466  |  | #ifdef HAVE_FSTATVFS  | 
14467  |  |     "HAVE_FSTATVFS",  | 
14468  |  | #endif  | 
14469  |  |  | 
14470  |  | #if defined HAVE_FTRUNCATE || defined MS_WINDOWS  | 
14471  |  |     "HAVE_FTRUNCATE",  | 
14472  |  | #endif  | 
14473  |  |  | 
14474  |  | #ifdef HAVE_FUTIMENS  | 
14475  |  |     "HAVE_FUTIMENS",  | 
14476  |  | #endif  | 
14477  |  |  | 
14478  |  | #ifdef HAVE_FUTIMES  | 
14479  |  |     "HAVE_FUTIMES",  | 
14480  |  | #endif  | 
14481  |  |  | 
14482  |  | #ifdef HAVE_FUTIMESAT  | 
14483  |  |     "HAVE_FUTIMESAT",  | 
14484  |  | #endif  | 
14485  |  |  | 
14486  |  | #ifdef HAVE_LINKAT  | 
14487  |  |     "HAVE_LINKAT",  | 
14488  |  | #endif  | 
14489  |  |  | 
14490  |  | #ifdef HAVE_LCHFLAGS  | 
14491  |  |     "HAVE_LCHFLAGS",  | 
14492  |  | #endif  | 
14493  |  |  | 
14494  |  | #ifdef HAVE_LCHMOD  | 
14495  |  |     "HAVE_LCHMOD",  | 
14496  |  | #endif  | 
14497  |  |  | 
14498  |  | #ifdef HAVE_LCHOWN  | 
14499  |  |     "HAVE_LCHOWN",  | 
14500  |  | #endif  | 
14501  |  |  | 
14502  |  | #ifdef HAVE_LSTAT  | 
14503  |  |     "HAVE_LSTAT",  | 
14504  |  | #endif  | 
14505  |  |  | 
14506  |  | #ifdef HAVE_LUTIMES  | 
14507  |  |     "HAVE_LUTIMES",  | 
14508  |  | #endif  | 
14509  |  |  | 
14510  |  | #ifdef HAVE_MEMFD_CREATE  | 
14511  |  |     "HAVE_MEMFD_CREATE",  | 
14512  |  | #endif  | 
14513  |  |  | 
14514  |  | #ifdef HAVE_MKDIRAT  | 
14515  |  |     "HAVE_MKDIRAT",  | 
14516  |  | #endif  | 
14517  |  |  | 
14518  |  | #ifdef HAVE_MKFIFOAT  | 
14519  |  |     "HAVE_MKFIFOAT",  | 
14520  |  | #endif  | 
14521  |  |  | 
14522  |  | #ifdef HAVE_MKNODAT  | 
14523  |  |     "HAVE_MKNODAT",  | 
14524  |  | #endif  | 
14525  |  |  | 
14526  |  | #ifdef HAVE_OPENAT  | 
14527  |  |     "HAVE_OPENAT",  | 
14528  |  | #endif  | 
14529  |  |  | 
14530  |  | #ifdef HAVE_READLINKAT  | 
14531  |  |     "HAVE_READLINKAT",  | 
14532  |  | #endif  | 
14533  |  |  | 
14534  |  | #ifdef HAVE_RENAMEAT  | 
14535  |  |     "HAVE_RENAMEAT",  | 
14536  |  | #endif  | 
14537  |  |  | 
14538  |  | #ifdef HAVE_SYMLINKAT  | 
14539  |  |     "HAVE_SYMLINKAT",  | 
14540  |  | #endif  | 
14541  |  |  | 
14542  |  | #ifdef HAVE_UNLINKAT  | 
14543  |  |     "HAVE_UNLINKAT",  | 
14544  |  | #endif  | 
14545  |  |  | 
14546  |  | #ifdef HAVE_UTIMENSAT  | 
14547  |  |     "HAVE_UTIMENSAT",  | 
14548  |  | #endif  | 
14549  |  |  | 
14550  |  | #ifdef MS_WINDOWS  | 
14551  |  |     "MS_WINDOWS",  | 
14552  |  | #endif  | 
14553  |  |  | 
14554  |  |     NULL  | 
14555  |  | };  | 
14556  |  |  | 
14557  |  |  | 
14558  |  | PyMODINIT_FUNC  | 
14559  |  | INITFUNC(void)  | 
14560  | 14  | { | 
14561  | 14  |     PyObject *m, *v;  | 
14562  | 14  |     PyObject *list;  | 
14563  | 14  |     const char * const *trace;  | 
14564  |  |  | 
14565  | 14  |     m = PyModule_Create(&posixmodule);  | 
14566  | 14  |     if (m == NULL)  | 
14567  | 0  |         return NULL;  | 
14568  |  |  | 
14569  |  |     /* Initialize environ dictionary */  | 
14570  | 14  |     v = convertenviron();  | 
14571  | 14  |     Py_XINCREF(v);  | 
14572  | 14  |     if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)  | 
14573  | 0  |         return NULL;  | 
14574  | 14  |     Py_DECREF(v);  | 
14575  |  |  | 
14576  | 14  |     if (all_ins(m))  | 
14577  | 0  |         return NULL;  | 
14578  |  |  | 
14579  | 14  |     if (setup_confname_tables(m))  | 
14580  | 0  |         return NULL;  | 
14581  |  |  | 
14582  | 14  |     Py_INCREF(PyExc_OSError);  | 
14583  | 14  |     PyModule_AddObject(m, "error", PyExc_OSError);  | 
14584  |  |  | 
14585  | 14  | #ifdef HAVE_PUTENV  | 
14586  | 14  |     if (posix_putenv_garbage == NULL)  | 
14587  | 14  |         posix_putenv_garbage = PyDict_New();  | 
14588  | 14  | #endif  | 
14589  |  |  | 
14590  | 14  |     if (!initialized) { | 
14591  | 14  | #if defined(HAVE_WAITID) && !defined(__APPLE__)  | 
14592  | 14  |         waitid_result_desc.name = MODNAME ".waitid_result";  | 
14593  | 14  |         WaitidResultType = PyStructSequence_NewType(&waitid_result_desc);  | 
14594  | 14  |         if (WaitidResultType == NULL) { | 
14595  | 0  |             return NULL;  | 
14596  | 0  |         }  | 
14597  | 14  | #endif  | 
14598  |  |  | 
14599  | 14  |         stat_result_desc.name = "os.stat_result"; /* see issue #19209 */  | 
14600  | 14  |         stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;  | 
14601  | 14  |         stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;  | 
14602  | 14  |         stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;  | 
14603  | 14  |         StatResultType = PyStructSequence_NewType(&stat_result_desc);  | 
14604  | 14  |         if (StatResultType == NULL) { | 
14605  | 0  |             return NULL;  | 
14606  | 0  |         }  | 
14607  | 14  |         structseq_new = StatResultType->tp_new;  | 
14608  | 14  |         StatResultType->tp_new = statresult_new;  | 
14609  |  |  | 
14610  | 14  |         statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */  | 
14611  | 14  |         StatVFSResultType = PyStructSequence_NewType(&statvfs_result_desc);  | 
14612  | 14  |         if (StatVFSResultType == NULL) { | 
14613  | 0  |             return NULL;  | 
14614  | 0  |         }  | 
14615  | 14  | #ifdef NEED_TICKS_PER_SECOND  | 
14616  | 14  | #  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)  | 
14617  | 14  |         ticks_per_second = sysconf(_SC_CLK_TCK);  | 
14618  |  | #  elif defined(HZ)  | 
14619  |  |         ticks_per_second = HZ;  | 
14620  |  | #  else  | 
14621  |  |         ticks_per_second = 60; /* magic fallback value; may be bogus */  | 
14622  |  | #  endif  | 
14623  | 14  | #endif  | 
14624  |  |  | 
14625  | 14  | #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)  | 
14626  | 14  |         sched_param_desc.name = MODNAME ".sched_param";  | 
14627  | 14  |         SchedParamType = PyStructSequence_NewType(&sched_param_desc);  | 
14628  | 14  |         if (SchedParamType == NULL) { | 
14629  | 0  |             return NULL;  | 
14630  | 0  |         }  | 
14631  | 14  |         SchedParamType->tp_new = os_sched_param;  | 
14632  | 14  | #endif  | 
14633  |  |  | 
14634  |  |         /* initialize TerminalSize_info */  | 
14635  | 14  |         TerminalSizeType = PyStructSequence_NewType(&TerminalSize_desc);  | 
14636  | 14  |         if (TerminalSizeType == NULL) { | 
14637  | 0  |             return NULL;  | 
14638  | 0  |         }  | 
14639  |  |  | 
14640  |  |         /* initialize scandir types */  | 
14641  | 14  |         if (PyType_Ready(&ScandirIteratorType) < 0)  | 
14642  | 0  |             return NULL;  | 
14643  | 14  |         if (PyType_Ready(&DirEntryType) < 0)  | 
14644  | 0  |             return NULL;  | 
14645  | 14  |     }  | 
14646  | 14  | #if defined(HAVE_WAITID) && !defined(__APPLE__)  | 
14647  | 14  |     Py_INCREF((PyObject*) WaitidResultType);  | 
14648  | 14  |     PyModule_AddObject(m, "waitid_result", (PyObject*) WaitidResultType);  | 
14649  | 14  | #endif  | 
14650  | 14  |     Py_INCREF((PyObject*) StatResultType);  | 
14651  | 14  |     PyModule_AddObject(m, "stat_result", (PyObject*) StatResultType);  | 
14652  | 14  |     Py_INCREF((PyObject*) StatVFSResultType);  | 
14653  | 14  |     PyModule_AddObject(m, "statvfs_result",  | 
14654  | 14  |                        (PyObject*) StatVFSResultType);  | 
14655  |  |  | 
14656  | 14  | #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)  | 
14657  | 14  |     Py_INCREF(SchedParamType);  | 
14658  | 14  |     PyModule_AddObject(m, "sched_param", (PyObject *)SchedParamType);  | 
14659  | 14  | #endif  | 
14660  |  |  | 
14661  | 14  |     times_result_desc.name = MODNAME ".times_result";  | 
14662  | 14  |     TimesResultType = PyStructSequence_NewType(×_result_desc);  | 
14663  | 14  |     if (TimesResultType == NULL) { | 
14664  | 0  |         return NULL;  | 
14665  | 0  |     }  | 
14666  | 14  |     PyModule_AddObject(m, "times_result", (PyObject *)TimesResultType);  | 
14667  |  |  | 
14668  | 14  |     uname_result_desc.name = MODNAME ".uname_result";  | 
14669  | 14  |     UnameResultType = PyStructSequence_NewType(&uname_result_desc);  | 
14670  | 14  |     if (UnameResultType == NULL) { | 
14671  | 0  |         return NULL;  | 
14672  | 0  |     }  | 
14673  | 14  |     PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);  | 
14674  |  |  | 
14675  |  | #ifdef __APPLE__  | 
14676  |  |     /*  | 
14677  |  |      * Step 2 of weak-linking support on Mac OS X.  | 
14678  |  |      *  | 
14679  |  |      * The code below removes functions that are not available on the  | 
14680  |  |      * currently active platform.  | 
14681  |  |      *  | 
14682  |  |      * This block allow one to use a python binary that was build on  | 
14683  |  |      * OSX 10.4 on OSX 10.3, without losing access to new APIs on  | 
14684  |  |      * OSX 10.4.  | 
14685  |  |      */  | 
14686  |  | #ifdef HAVE_FSTATVFS  | 
14687  |  |     if (fstatvfs == NULL) { | 
14688  |  |         if (PyObject_DelAttrString(m, "fstatvfs") == -1) { | 
14689  |  |             return NULL;  | 
14690  |  |         }  | 
14691  |  |     }  | 
14692  |  | #endif /* HAVE_FSTATVFS */  | 
14693  |  |  | 
14694  |  | #ifdef HAVE_STATVFS  | 
14695  |  |     if (statvfs == NULL) { | 
14696  |  |         if (PyObject_DelAttrString(m, "statvfs") == -1) { | 
14697  |  |             return NULL;  | 
14698  |  |         }  | 
14699  |  |     }  | 
14700  |  | #endif /* HAVE_STATVFS */  | 
14701  |  |  | 
14702  |  | # ifdef HAVE_LCHOWN  | 
14703  |  |     if (lchown == NULL) { | 
14704  |  |         if (PyObject_DelAttrString(m, "lchown") == -1) { | 
14705  |  |             return NULL;  | 
14706  |  |         }  | 
14707  |  |     }  | 
14708  |  | #endif /* HAVE_LCHOWN */  | 
14709  |  |  | 
14710  |  |  | 
14711  |  | #endif /* __APPLE__ */  | 
14712  |  |  | 
14713  | 14  |     Py_INCREF(TerminalSizeType);  | 
14714  | 14  |     PyModule_AddObject(m, "terminal_size", (PyObject*)TerminalSizeType);  | 
14715  |  |  | 
14716  | 14  |     billion = PyLong_FromLong(1000000000);  | 
14717  | 14  |     if (!billion)  | 
14718  | 0  |         return NULL;  | 
14719  |  |  | 
14720  |  |     /* suppress "function not used" warnings */  | 
14721  | 14  |     { | 
14722  | 14  |     int ignored;  | 
14723  | 14  |     fd_specified("", -1); | 
14724  | 14  |     follow_symlinks_specified("", 1); | 
14725  | 14  |     dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1); | 
14726  | 14  |     dir_fd_converter(Py_None, &ignored);  | 
14727  | 14  |     dir_fd_unavailable(Py_None, &ignored);  | 
14728  | 14  |     }  | 
14729  |  |  | 
14730  |  |     /*  | 
14731  |  |      * provide list of locally available functions  | 
14732  |  |      * so os.py can populate support_* lists  | 
14733  |  |      */  | 
14734  | 14  |     list = PyList_New(0);  | 
14735  | 14  |     if (!list)  | 
14736  | 0  |         return NULL;  | 
14737  | 420  |     for (trace = have_functions; *trace; trace++) { | 
14738  | 406  |         PyObject *unicode = PyUnicode_DecodeASCII(*trace, strlen(*trace), NULL);  | 
14739  | 406  |         if (!unicode)  | 
14740  | 0  |             return NULL;  | 
14741  | 406  |         if (PyList_Append(list, unicode))  | 
14742  | 0  |             return NULL;  | 
14743  | 406  |         Py_DECREF(unicode);  | 
14744  | 406  |     }  | 
14745  | 14  |     PyModule_AddObject(m, "_have_functions", list);  | 
14746  |  |  | 
14747  | 14  |     Py_INCREF((PyObject *) &DirEntryType);  | 
14748  | 14  |     PyModule_AddObject(m, "DirEntry", (PyObject *)&DirEntryType);  | 
14749  |  |  | 
14750  | 14  |     initialized = 1;  | 
14751  |  |  | 
14752  | 14  |     return m;  | 
14753  | 14  | }  | 
14754  |  |  | 
14755  |  | #ifdef __cplusplus  | 
14756  |  | }  | 
14757  |  | #endif  |