Branch data Line data Source code
1 : : /* POSIX module implementation */
2 : :
3 : : /* This file is also used for Windows NT/MS-Win. In that case the
4 : : module actually calls itself 'nt', not 'posix', and a few
5 : : functions are either unimplemented or implemented differently. The source
6 : : assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
7 : : of the compiler used. Different compilers define their own feature
8 : : test macro, e.g. '_MSC_VER'. */
9 : :
10 : : #define PY_SSIZE_T_CLEAN
11 : :
12 : : #include "Python.h"
13 : :
14 : : #ifdef __VXWORKS__
15 : : # include "pycore_bitutils.h" // _Py_popcount32()
16 : : #endif
17 : : #include "pycore_call.h" // _PyObject_CallNoArgs()
18 : : #include "pycore_ceval.h" // _PyEval_ReInitThreads()
19 : : #include "pycore_fileutils.h" // _Py_closerange()
20 : : #include "pycore_import.h" // _PyImport_ReInitLock()
21 : : #include "pycore_initconfig.h" // _PyStatus_EXCEPTION()
22 : : #include "pycore_moduleobject.h" // _PyModule_GetState()
23 : : #include "pycore_object.h" // _PyObject_LookupSpecial()
24 : : #include "pycore_pystate.h" // _PyInterpreterState_GET()
25 : : #include "pycore_signal.h" // Py_NSIG
26 : :
27 : : #ifdef MS_WINDOWS
28 : : # include <windows.h>
29 : : # if !defined(MS_WINDOWS_GAMES) || defined(MS_WINDOWS_DESKTOP)
30 : : # include <pathcch.h>
31 : : # endif
32 : : # include <winioctl.h>
33 : : # include <lmcons.h> // UNLEN
34 : : # include "osdefs.h" // SEP
35 : : # if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
36 : : # define HAVE_SYMLINK
37 : : # endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
38 : : #endif
39 : :
40 : : #include "structmember.h" // PyMemberDef
41 : : #ifndef MS_WINDOWS
42 : : # include "posixmodule.h"
43 : : #else
44 : : # include "pycore_fileutils_windows.h"
45 : : # include "winreparse.h"
46 : : #endif
47 : :
48 : : #if !defined(EX_OK) && defined(EXIT_SUCCESS)
49 : : # define EX_OK EXIT_SUCCESS
50 : : #endif
51 : :
52 : : /* On android API level 21, 'AT_EACCESS' is not declared although
53 : : * HAVE_FACCESSAT is defined. */
54 : : #ifdef __ANDROID__
55 : : # undef HAVE_FACCESSAT
56 : : #endif
57 : :
58 : : #include <stdio.h> // ctermid()
59 : : #include <stdlib.h> // system()
60 : :
61 : : /*
62 : : * A number of APIs are available on macOS from a certain macOS version.
63 : : * To support building with a new SDK while deploying to older versions
64 : : * the availability test is split into two:
65 : : * - HAVE_<FUNCTION>: The configure check for compile time availability
66 : : * - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
67 : : *
68 : : * The latter is always true when not on macOS, or when using a compiler
69 : : * that does not support __has_builtin (older versions of Xcode).
70 : : *
71 : : * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
72 : : * if (HAVE_<FUNCTION>_RUNTIME) { ... }
73 : : *
74 : : * In mixing the test with other tests or using negations will result in compile
75 : : * errors.
76 : : */
77 : : #if defined(__APPLE__)
78 : :
79 : : #include <mach/mach.h>
80 : :
81 : : #if defined(__has_builtin)
82 : : #if __has_builtin(__builtin_available)
83 : : #define HAVE_BUILTIN_AVAILABLE 1
84 : : #endif
85 : : #endif
86 : :
87 : : #ifdef HAVE_BUILTIN_AVAILABLE
88 : : # define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
89 : : # define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
90 : : # define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
91 : : # define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
92 : : # define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
93 : : # define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
94 : : # define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
95 : : # define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
96 : : # define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
97 : : # define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
98 : : # define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
99 : : # define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
100 : : # define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
101 : : # define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
102 : : # define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
103 : : # define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
104 : : # define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
105 : :
106 : : # define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
107 : :
108 : : #else /* Xcode 8 or earlier */
109 : :
110 : : /* __builtin_available is not present in these compilers, but
111 : : * some of the symbols might be weak linked (10.10 SDK or later
112 : : * deploying on 10.9.
113 : : *
114 : : * Fall back to the older style of availability checking for
115 : : * symbols introduced in macOS 10.10.
116 : : */
117 : :
118 : : # ifdef HAVE_FSTATAT
119 : : # define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
120 : : # endif
121 : :
122 : : # ifdef HAVE_FACCESSAT
123 : : # define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
124 : : # endif
125 : :
126 : : # ifdef HAVE_FCHMODAT
127 : : # define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
128 : : # endif
129 : :
130 : : # ifdef HAVE_FCHOWNAT
131 : : # define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
132 : : # endif
133 : :
134 : : # ifdef HAVE_LINKAT
135 : : # define HAVE_LINKAT_RUNTIME (linkat != NULL)
136 : : # endif
137 : :
138 : : # ifdef HAVE_FDOPENDIR
139 : : # define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
140 : : # endif
141 : :
142 : : # ifdef HAVE_MKDIRAT
143 : : # define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
144 : : # endif
145 : :
146 : : # ifdef HAVE_RENAMEAT
147 : : # define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
148 : : # endif
149 : :
150 : : # ifdef HAVE_UNLINKAT
151 : : # define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
152 : : # endif
153 : :
154 : : # ifdef HAVE_OPENAT
155 : : # define HAVE_OPENAT_RUNTIME (openat != NULL)
156 : : # endif
157 : :
158 : : # ifdef HAVE_READLINKAT
159 : : # define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
160 : : # endif
161 : :
162 : : # ifdef HAVE_SYMLINKAT
163 : : # define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
164 : : # endif
165 : :
166 : : # ifdef HAVE_UTIMENSAT
167 : : # define HAVE_UTIMENSAT_RUNTIME (utimensat != NULL)
168 : : # endif
169 : :
170 : : # ifdef HAVE_FUTIMENS
171 : : # define HAVE_FUTIMENS_RUNTIME (futimens != NULL)
172 : : # endif
173 : :
174 : : # ifdef HAVE_PWRITEV
175 : : # define HAVE_PWRITEV_RUNTIME (pwritev != NULL)
176 : : # endif
177 : :
178 : : #endif
179 : :
180 : : #ifdef HAVE_FUTIMESAT
181 : : /* Some of the logic for weak linking depends on this assertion */
182 : : # error "HAVE_FUTIMESAT unexpectedly defined"
183 : : #endif
184 : :
185 : : #else
186 : : # define HAVE_FSTATAT_RUNTIME 1
187 : : # define HAVE_FACCESSAT_RUNTIME 1
188 : : # define HAVE_FCHMODAT_RUNTIME 1
189 : : # define HAVE_FCHOWNAT_RUNTIME 1
190 : : # define HAVE_LINKAT_RUNTIME 1
191 : : # define HAVE_FDOPENDIR_RUNTIME 1
192 : : # define HAVE_MKDIRAT_RUNTIME 1
193 : : # define HAVE_RENAMEAT_RUNTIME 1
194 : : # define HAVE_UNLINKAT_RUNTIME 1
195 : : # define HAVE_OPENAT_RUNTIME 1
196 : : # define HAVE_READLINKAT_RUNTIME 1
197 : : # define HAVE_SYMLINKAT_RUNTIME 1
198 : : # define HAVE_FUTIMENS_RUNTIME 1
199 : : # define HAVE_UTIMENSAT_RUNTIME 1
200 : : # define HAVE_PWRITEV_RUNTIME 1
201 : : # define HAVE_MKFIFOAT_RUNTIME 1
202 : : # define HAVE_MKNODAT_RUNTIME 1
203 : : #endif
204 : :
205 : :
206 : : #ifdef __cplusplus
207 : : extern "C" {
208 : : #endif
209 : :
210 : : PyDoc_STRVAR(posix__doc__,
211 : : "This module provides access to operating system functionality that is\n\
212 : : standardized by the C Standard and the POSIX standard (a thinly\n\
213 : : disguised Unix interface). Refer to the library manual and\n\
214 : : corresponding Unix manual entries for more information on calls.");
215 : :
216 : :
217 : : #ifdef HAVE_SYS_UIO_H
218 : : # include <sys/uio.h>
219 : : #endif
220 : :
221 : : #ifdef HAVE_SYS_SYSMACROS_H
222 : : /* GNU C Library: major(), minor(), makedev() */
223 : : # include <sys/sysmacros.h>
224 : : #endif
225 : :
226 : : #ifdef HAVE_SYS_TYPES_H
227 : : # include <sys/types.h>
228 : : #endif /* HAVE_SYS_TYPES_H */
229 : :
230 : : #ifdef HAVE_SYS_STAT_H
231 : : # include <sys/stat.h>
232 : : #endif /* HAVE_SYS_STAT_H */
233 : :
234 : : #ifdef HAVE_SYS_WAIT_H
235 : : # include <sys/wait.h> // WNOHANG
236 : : #endif
237 : : #ifdef HAVE_LINUX_WAIT_H
238 : : # include <linux/wait.h> // P_PIDFD
239 : : #endif
240 : :
241 : : #ifdef HAVE_SIGNAL_H
242 : : # include <signal.h>
243 : : #endif
244 : :
245 : : #ifdef HAVE_FCNTL_H
246 : : # include <fcntl.h>
247 : : #endif
248 : :
249 : : #ifdef HAVE_GRP_H
250 : : # include <grp.h>
251 : : #endif
252 : :
253 : : #ifdef HAVE_SYSEXITS_H
254 : : # include <sysexits.h>
255 : : #endif
256 : :
257 : : #ifdef HAVE_SYS_LOADAVG_H
258 : : # include <sys/loadavg.h>
259 : : #endif
260 : :
261 : : #ifdef HAVE_SYS_SENDFILE_H
262 : : # include <sys/sendfile.h>
263 : : #endif
264 : :
265 : : #if defined(__APPLE__)
266 : : # include <copyfile.h>
267 : : #endif
268 : :
269 : : #ifdef HAVE_SCHED_H
270 : : # include <sched.h>
271 : : #endif
272 : :
273 : : #ifdef HAVE_COPY_FILE_RANGE
274 : : # include <unistd.h>
275 : : #endif
276 : :
277 : : #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
278 : : # undef HAVE_SCHED_SETAFFINITY
279 : : #endif
280 : :
281 : : #if defined(HAVE_SYS_XATTR_H) && defined(__linux__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
282 : : # define USE_XATTRS
283 : : # include <linux/limits.h> // Needed for XATTR_SIZE_MAX on musl libc.
284 : : #endif
285 : :
286 : : #ifdef USE_XATTRS
287 : : # include <sys/xattr.h>
288 : : #endif
289 : :
290 : : #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
291 : : # ifdef HAVE_SYS_SOCKET_H
292 : : # include <sys/socket.h>
293 : : # endif
294 : : #endif
295 : :
296 : : #ifdef HAVE_DLFCN_H
297 : : # include <dlfcn.h>
298 : : #endif
299 : :
300 : : #ifdef __hpux
301 : : # include <sys/mpctl.h>
302 : : #endif
303 : :
304 : : #if defined(__DragonFly__) || \
305 : : defined(__OpenBSD__) || \
306 : : defined(__FreeBSD__) || \
307 : : defined(__NetBSD__) || \
308 : : defined(__APPLE__)
309 : : # include <sys/sysctl.h>
310 : : #endif
311 : :
312 : : #ifdef HAVE_LINUX_RANDOM_H
313 : : # include <linux/random.h>
314 : : #endif
315 : : #ifdef HAVE_GETRANDOM_SYSCALL
316 : : # include <sys/syscall.h>
317 : : #endif
318 : :
319 : : #ifdef HAVE_WINDOWS_CONSOLE_IO
320 : : # define TERMSIZE_USE_CONIO
321 : : #elif defined(HAVE_SYS_IOCTL_H)
322 : : # include <sys/ioctl.h>
323 : : # if defined(HAVE_TERMIOS_H)
324 : : # include <termios.h>
325 : : # endif
326 : : # if defined(TIOCGWINSZ)
327 : : # define TERMSIZE_USE_IOCTL
328 : : # endif
329 : : #endif /* HAVE_WINDOWS_CONSOLE_IO */
330 : :
331 : : /* Various compilers have only certain posix functions */
332 : : /* XXX Gosh I wish these were all moved into pyconfig.h */
333 : : #if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */
334 : : # define HAVE_OPENDIR 1
335 : : # define HAVE_SYSTEM 1
336 : : # include <process.h>
337 : : #elif defined( _MSC_VER)
338 : : /* Microsoft compiler */
339 : : # if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
340 : : # define HAVE_GETPPID 1
341 : : # endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_APP | MS_WINDOWS_SYSTEM */
342 : : # if defined(MS_WINDOWS_DESKTOP)
343 : : # define HAVE_GETLOGIN 1
344 : : # endif /* MS_WINDOWS_DESKTOP */
345 : : # if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
346 : : # define HAVE_SPAWNV 1
347 : : # define HAVE_EXECV 1
348 : : # define HAVE_WSPAWNV 1
349 : : # define HAVE_WEXECV 1
350 : : # define HAVE_SYSTEM 1
351 : : # define HAVE_CWAIT 1
352 : : # endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
353 : : # define HAVE_PIPE 1
354 : : # define HAVE_FSYNC 1
355 : : # define fsync _commit
356 : : #endif /* ! __WATCOMC__ || __QNX__ */
357 : :
358 : : /*[clinic input]
359 : : # one of the few times we lie about this name!
360 : : module os
361 : : [clinic start generated code]*/
362 : : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
363 : :
364 : : #ifndef _MSC_VER
365 : :
366 : : #if defined(__sgi)&&_COMPILER_VERSION>=700
367 : : /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
368 : : (default) */
369 : : extern char *ctermid_r(char *);
370 : : #endif
371 : :
372 : : #endif /* !_MSC_VER */
373 : :
374 : : #if defined(__VXWORKS__)
375 : : # include <vxCpuLib.h>
376 : : # include <rtpLib.h>
377 : : # include <wait.h>
378 : : # include <taskLib.h>
379 : : # ifndef _P_WAIT
380 : : # define _P_WAIT 0
381 : : # define _P_NOWAIT 1
382 : : # define _P_NOWAITO 1
383 : : # endif
384 : : #endif /* __VXWORKS__ */
385 : :
386 : : #ifdef HAVE_POSIX_SPAWN
387 : : # include <spawn.h>
388 : : #endif
389 : :
390 : : #ifdef HAVE_UTIME_H
391 : : # include <utime.h>
392 : : #endif /* HAVE_UTIME_H */
393 : :
394 : : #ifdef HAVE_SYS_UTIME_H
395 : : # include <sys/utime.h>
396 : : # define HAVE_UTIME_H /* pretend we do for the rest of this file */
397 : : #endif /* HAVE_SYS_UTIME_H */
398 : :
399 : : #ifdef HAVE_SYS_TIMES_H
400 : : # include <sys/times.h>
401 : : #endif /* HAVE_SYS_TIMES_H */
402 : :
403 : : #ifdef HAVE_SYS_PARAM_H
404 : : # include <sys/param.h>
405 : : #endif /* HAVE_SYS_PARAM_H */
406 : :
407 : : #ifdef HAVE_SYS_UTSNAME_H
408 : : # include <sys/utsname.h>
409 : : #endif /* HAVE_SYS_UTSNAME_H */
410 : :
411 : : #ifdef HAVE_DIRENT_H
412 : : # include <dirent.h>
413 : : # define NAMLEN(dirent) strlen((dirent)->d_name)
414 : : #else
415 : : # if defined(__WATCOMC__) && !defined(__QNX__)
416 : : # include <direct.h>
417 : : # define NAMLEN(dirent) strlen((dirent)->d_name)
418 : : # else
419 : : # define dirent direct
420 : : # define NAMLEN(dirent) (dirent)->d_namlen
421 : : # endif
422 : : # ifdef HAVE_SYS_NDIR_H
423 : : # include <sys/ndir.h>
424 : : # endif
425 : : # ifdef HAVE_SYS_DIR_H
426 : : # include <sys/dir.h>
427 : : # endif
428 : : # ifdef HAVE_NDIR_H
429 : : # include <ndir.h>
430 : : # endif
431 : : #endif
432 : :
433 : : #ifdef _MSC_VER
434 : : # ifdef HAVE_DIRECT_H
435 : : # include <direct.h>
436 : : # endif
437 : : # ifdef HAVE_IO_H
438 : : # include <io.h>
439 : : # endif
440 : : # ifdef HAVE_PROCESS_H
441 : : # include <process.h>
442 : : # endif
443 : : # include <malloc.h>
444 : : #endif /* _MSC_VER */
445 : :
446 : : #ifndef MAXPATHLEN
447 : : # if defined(PATH_MAX) && PATH_MAX > 1024
448 : : # define MAXPATHLEN PATH_MAX
449 : : # else
450 : : # define MAXPATHLEN 1024
451 : : # endif
452 : : #endif /* MAXPATHLEN */
453 : :
454 : : #ifdef UNION_WAIT
455 : : /* Emulate some macros on systems that have a union instead of macros */
456 : : # ifndef WIFEXITED
457 : : # define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
458 : : # endif
459 : : # ifndef WEXITSTATUS
460 : : # define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
461 : : # endif
462 : : # ifndef WTERMSIG
463 : : # define WTERMSIG(u_wait) ((u_wait).w_termsig)
464 : : # endif
465 : : # define WAIT_TYPE union wait
466 : : # define WAIT_STATUS_INT(s) (s.w_status)
467 : : #else
468 : : /* !UNION_WAIT */
469 : : # define WAIT_TYPE int
470 : : # define WAIT_STATUS_INT(s) (s)
471 : : #endif /* UNION_WAIT */
472 : :
473 : : /* Don't use the "_r" form if we don't need it (also, won't have a
474 : : prototype for it, at least on Solaris -- maybe others as well?). */
475 : : #if defined(HAVE_CTERMID_R)
476 : : # define USE_CTERMID_R
477 : : #endif
478 : :
479 : : /* choose the appropriate stat and fstat functions and return structs */
480 : : #undef STAT
481 : : #undef FSTAT
482 : : #undef STRUCT_STAT
483 : : #ifdef MS_WINDOWS
484 : : # define STAT win32_stat
485 : : # define LSTAT win32_lstat
486 : : # define FSTAT _Py_fstat_noraise
487 : : # define STRUCT_STAT struct _Py_stat_struct
488 : : #else
489 : : # define STAT stat
490 : : # define LSTAT lstat
491 : : # define FSTAT fstat
492 : : # define STRUCT_STAT struct stat
493 : : #endif
494 : :
495 : : #if defined(MAJOR_IN_MKDEV)
496 : : # include <sys/mkdev.h>
497 : : #else
498 : : # if defined(MAJOR_IN_SYSMACROS)
499 : : # include <sys/sysmacros.h>
500 : : # endif
501 : : # if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
502 : : # include <sys/mkdev.h>
503 : : # endif
504 : : #endif
505 : :
506 : : #ifdef MS_WINDOWS
507 : : # define INITFUNC PyInit_nt
508 : : # define MODNAME "nt"
509 : : # define MODNAME_OBJ &_Py_ID(nt)
510 : : #else
511 : : # define INITFUNC PyInit_posix
512 : : # define MODNAME "posix"
513 : : # define MODNAME_OBJ &_Py_ID(posix)
514 : : #endif
515 : :
516 : : #if defined(__sun)
517 : : /* Something to implement in autoconf, not present in autoconf 2.69 */
518 : : # define HAVE_STRUCT_STAT_ST_FSTYPE 1
519 : : #endif
520 : :
521 : : /* memfd_create is either defined in sys/mman.h or sys/memfd.h
522 : : * linux/memfd.h defines additional flags
523 : : */
524 : : #ifdef HAVE_SYS_MMAN_H
525 : : # include <sys/mman.h>
526 : : #endif
527 : : #ifdef HAVE_SYS_MEMFD_H
528 : : # include <sys/memfd.h>
529 : : #endif
530 : : #ifdef HAVE_LINUX_MEMFD_H
531 : : # include <linux/memfd.h>
532 : : #endif
533 : :
534 : : /* eventfd() */
535 : : #ifdef HAVE_SYS_EVENTFD_H
536 : : # include <sys/eventfd.h>
537 : : #endif
538 : :
539 : : #ifdef _Py_MEMORY_SANITIZER
540 : : # include <sanitizer/msan_interface.h>
541 : : #endif
542 : :
543 : : #ifdef HAVE_FORK
544 : : static void
545 : 0 : run_at_forkers(PyObject *lst, int reverse)
546 : : {
547 : : Py_ssize_t i;
548 : : PyObject *cpy;
549 : :
550 [ # # ]: 0 : if (lst != NULL) {
551 : : assert(PyList_CheckExact(lst));
552 : :
553 : : /* Use a list copy in case register_at_fork() is called from
554 : : * one of the callbacks.
555 : : */
556 : 0 : cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
557 [ # # ]: 0 : if (cpy == NULL)
558 : 0 : PyErr_WriteUnraisable(lst);
559 : : else {
560 [ # # ]: 0 : if (reverse)
561 : 0 : PyList_Reverse(cpy);
562 [ # # ]: 0 : for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
563 : : PyObject *func, *res;
564 : 0 : func = PyList_GET_ITEM(cpy, i);
565 : 0 : res = _PyObject_CallNoArgs(func);
566 [ # # ]: 0 : if (res == NULL)
567 : 0 : PyErr_WriteUnraisable(func);
568 : : else
569 : 0 : Py_DECREF(res);
570 : : }
571 : 0 : Py_DECREF(cpy);
572 : : }
573 : : }
574 : 0 : }
575 : :
576 : : void
577 : 0 : PyOS_BeforeFork(void)
578 : : {
579 : 0 : PyInterpreterState *interp = _PyInterpreterState_GET();
580 : 0 : run_at_forkers(interp->before_forkers, 1);
581 : :
582 : 0 : _PyImport_AcquireLock(interp);
583 : 0 : }
584 : :
585 : : void
586 : 0 : PyOS_AfterFork_Parent(void)
587 : : {
588 : 0 : PyInterpreterState *interp = _PyInterpreterState_GET();
589 [ # # ]: 0 : if (_PyImport_ReleaseLock(interp) <= 0) {
590 : 0 : Py_FatalError("failed releasing import lock after fork");
591 : : }
592 : :
593 : 0 : run_at_forkers(interp->after_forkers_parent, 0);
594 : 0 : }
595 : :
596 : : void
597 : 0 : PyOS_AfterFork_Child(void)
598 : : {
599 : : PyStatus status;
600 : 0 : _PyRuntimeState *runtime = &_PyRuntime;
601 : :
602 : 0 : status = _PyRuntimeState_ReInitThreads(runtime);
603 [ # # ]: 0 : if (_PyStatus_EXCEPTION(status)) {
604 : 0 : goto fatal_error;
605 : : }
606 : :
607 : 0 : PyThreadState *tstate = _PyThreadState_GET();
608 : 0 : _Py_EnsureTstateNotNULL(tstate);
609 : :
610 : : #ifdef PY_HAVE_THREAD_NATIVE_ID
611 : 0 : tstate->native_thread_id = PyThread_get_thread_native_id();
612 : : #endif
613 : :
614 : 0 : status = _PyEval_ReInitThreads(tstate);
615 [ # # ]: 0 : if (_PyStatus_EXCEPTION(status)) {
616 : 0 : goto fatal_error;
617 : : }
618 : :
619 : 0 : status = _PyImport_ReInitLock(tstate->interp);
620 [ # # ]: 0 : if (_PyStatus_EXCEPTION(status)) {
621 : 0 : goto fatal_error;
622 : : }
623 : :
624 : 0 : _PySignal_AfterFork();
625 : :
626 : 0 : status = _PyInterpreterState_DeleteExceptMain(runtime);
627 [ # # ]: 0 : if (_PyStatus_EXCEPTION(status)) {
628 : 0 : goto fatal_error;
629 : : }
630 : : assert(_PyThreadState_GET() == tstate);
631 : :
632 : 0 : status = _PyPerfTrampoline_AfterFork_Child();
633 [ # # ]: 0 : if (_PyStatus_EXCEPTION(status)) {
634 : 0 : goto fatal_error;
635 : : }
636 : :
637 : 0 : run_at_forkers(tstate->interp->after_forkers_child, 0);
638 : 0 : return;
639 : :
640 : 0 : fatal_error:
641 : 0 : Py_ExitStatusException(status);
642 : : }
643 : :
644 : : static int
645 : 21 : register_at_forker(PyObject **lst, PyObject *func)
646 : : {
647 [ + + ]: 21 : if (func == NULL) /* nothing to register? do nothing. */
648 : 12 : return 0;
649 [ + + ]: 9 : if (*lst == NULL) {
650 : 6 : *lst = PyList_New(0);
651 [ - + ]: 6 : if (*lst == NULL)
652 : 0 : return -1;
653 : : }
654 : 9 : return PyList_Append(*lst, func);
655 : : }
656 : : #endif /* HAVE_FORK */
657 : :
658 : :
659 : : /* Legacy wrapper */
660 : : void
661 : 0 : PyOS_AfterFork(void)
662 : : {
663 : : #ifdef HAVE_FORK
664 : 0 : PyOS_AfterFork_Child();
665 : : #endif
666 : 0 : }
667 : :
668 : :
669 : : #ifdef MS_WINDOWS
670 : : /* defined in fileutils.c */
671 : : void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
672 : : void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, ULONG,
673 : : FILE_BASIC_INFO *, FILE_ID_INFO *,
674 : : struct _Py_stat_struct *);
675 : : void _Py_stat_basic_info_to_stat(FILE_STAT_BASIC_INFORMATION *,
676 : : struct _Py_stat_struct *);
677 : : #endif
678 : :
679 : :
680 : : #ifndef MS_WINDOWS
681 : : PyObject *
682 : 2789 : _PyLong_FromUid(uid_t uid)
683 : : {
684 [ - + ]: 2789 : if (uid == (uid_t)-1)
685 : 0 : return PyLong_FromLong(-1);
686 : 2789 : return PyLong_FromUnsignedLong(uid);
687 : : }
688 : :
689 : : PyObject *
690 : 2789 : _PyLong_FromGid(gid_t gid)
691 : : {
692 [ - + ]: 2789 : if (gid == (gid_t)-1)
693 : 0 : return PyLong_FromLong(-1);
694 : 2789 : return PyLong_FromUnsignedLong(gid);
695 : : }
696 : :
697 : : int
698 : 0 : _Py_Uid_Converter(PyObject *obj, uid_t *p)
699 : : {
700 : : uid_t uid;
701 : : PyObject *index;
702 : : int overflow;
703 : : long result;
704 : : unsigned long uresult;
705 : :
706 : 0 : index = _PyNumber_Index(obj);
707 [ # # ]: 0 : if (index == NULL) {
708 : 0 : PyErr_Format(PyExc_TypeError,
709 : : "uid should be integer, not %.200s",
710 : : _PyType_Name(Py_TYPE(obj)));
711 : 0 : return 0;
712 : : }
713 : :
714 : : /*
715 : : * Handling uid_t is complicated for two reasons:
716 : : * * Although uid_t is (always?) unsigned, it still
717 : : * accepts -1.
718 : : * * We don't know its size in advance--it may be
719 : : * bigger than an int, or it may be smaller than
720 : : * a long.
721 : : *
722 : : * So a bit of defensive programming is in order.
723 : : * Start with interpreting the value passed
724 : : * in as a signed long and see if it works.
725 : : */
726 : :
727 : 0 : result = PyLong_AsLongAndOverflow(index, &overflow);
728 : :
729 [ # # ]: 0 : if (!overflow) {
730 : 0 : uid = (uid_t)result;
731 : :
732 [ # # ]: 0 : if (result == -1) {
733 [ # # ]: 0 : if (PyErr_Occurred())
734 : 0 : goto fail;
735 : : /* It's a legitimate -1, we're done. */
736 : 0 : goto success;
737 : : }
738 : :
739 : : /* Any other negative number is disallowed. */
740 [ # # ]: 0 : if (result < 0)
741 : 0 : goto underflow;
742 : :
743 : : /* Ensure the value wasn't truncated. */
744 : 0 : if (sizeof(uid_t) < sizeof(long) &&
745 [ # # ]: 0 : (long)uid != result)
746 : 0 : goto underflow;
747 : 0 : goto success;
748 : : }
749 : :
750 [ # # ]: 0 : if (overflow < 0)
751 : 0 : goto underflow;
752 : :
753 : : /*
754 : : * Okay, the value overflowed a signed long. If it
755 : : * fits in an *unsigned* long, it may still be okay,
756 : : * as uid_t may be unsigned long on this platform.
757 : : */
758 : 0 : uresult = PyLong_AsUnsignedLong(index);
759 [ # # ]: 0 : if (PyErr_Occurred()) {
760 [ # # ]: 0 : if (PyErr_ExceptionMatches(PyExc_OverflowError))
761 : 0 : goto overflow;
762 : 0 : goto fail;
763 : : }
764 : :
765 : 0 : uid = (uid_t)uresult;
766 : :
767 : : /*
768 : : * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
769 : : * but this value would get interpreted as (uid_t)-1 by chown
770 : : * and its siblings. That's not what the user meant! So we
771 : : * throw an overflow exception instead. (We already
772 : : * handled a real -1 with PyLong_AsLongAndOverflow() above.)
773 : : */
774 [ # # ]: 0 : if (uid == (uid_t)-1)
775 : 0 : goto overflow;
776 : :
777 : : /* Ensure the value wasn't truncated. */
778 : 0 : if (sizeof(uid_t) < sizeof(long) &&
779 [ # # ]: 0 : (unsigned long)uid != uresult)
780 : 0 : goto overflow;
781 : : /* fallthrough */
782 : :
783 : 0 : success:
784 : 0 : Py_DECREF(index);
785 : 0 : *p = uid;
786 : 0 : return 1;
787 : :
788 : 0 : underflow:
789 : 0 : PyErr_SetString(PyExc_OverflowError,
790 : : "uid is less than minimum");
791 : 0 : goto fail;
792 : :
793 : 0 : overflow:
794 : 0 : PyErr_SetString(PyExc_OverflowError,
795 : : "uid is greater than maximum");
796 : : /* fallthrough */
797 : :
798 : 0 : fail:
799 : 0 : Py_DECREF(index);
800 : 0 : return 0;
801 : : }
802 : :
803 : : int
804 : 0 : _Py_Gid_Converter(PyObject *obj, gid_t *p)
805 : : {
806 : : gid_t gid;
807 : : PyObject *index;
808 : : int overflow;
809 : : long result;
810 : : unsigned long uresult;
811 : :
812 : 0 : index = _PyNumber_Index(obj);
813 [ # # ]: 0 : if (index == NULL) {
814 : 0 : PyErr_Format(PyExc_TypeError,
815 : : "gid should be integer, not %.200s",
816 : : _PyType_Name(Py_TYPE(obj)));
817 : 0 : return 0;
818 : : }
819 : :
820 : : /*
821 : : * Handling gid_t is complicated for two reasons:
822 : : * * Although gid_t is (always?) unsigned, it still
823 : : * accepts -1.
824 : : * * We don't know its size in advance--it may be
825 : : * bigger than an int, or it may be smaller than
826 : : * a long.
827 : : *
828 : : * So a bit of defensive programming is in order.
829 : : * Start with interpreting the value passed
830 : : * in as a signed long and see if it works.
831 : : */
832 : :
833 : 0 : result = PyLong_AsLongAndOverflow(index, &overflow);
834 : :
835 [ # # ]: 0 : if (!overflow) {
836 : 0 : gid = (gid_t)result;
837 : :
838 [ # # ]: 0 : if (result == -1) {
839 [ # # ]: 0 : if (PyErr_Occurred())
840 : 0 : goto fail;
841 : : /* It's a legitimate -1, we're done. */
842 : 0 : goto success;
843 : : }
844 : :
845 : : /* Any other negative number is disallowed. */
846 [ # # ]: 0 : if (result < 0) {
847 : 0 : goto underflow;
848 : : }
849 : :
850 : : /* Ensure the value wasn't truncated. */
851 : 0 : if (sizeof(gid_t) < sizeof(long) &&
852 [ # # ]: 0 : (long)gid != result)
853 : 0 : goto underflow;
854 : 0 : goto success;
855 : : }
856 : :
857 [ # # ]: 0 : if (overflow < 0)
858 : 0 : goto underflow;
859 : :
860 : : /*
861 : : * Okay, the value overflowed a signed long. If it
862 : : * fits in an *unsigned* long, it may still be okay,
863 : : * as gid_t may be unsigned long on this platform.
864 : : */
865 : 0 : uresult = PyLong_AsUnsignedLong(index);
866 [ # # ]: 0 : if (PyErr_Occurred()) {
867 [ # # ]: 0 : if (PyErr_ExceptionMatches(PyExc_OverflowError))
868 : 0 : goto overflow;
869 : 0 : goto fail;
870 : : }
871 : :
872 : 0 : gid = (gid_t)uresult;
873 : :
874 : : /*
875 : : * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
876 : : * but this value would get interpreted as (gid_t)-1 by chown
877 : : * and its siblings. That's not what the user meant! So we
878 : : * throw an overflow exception instead. (We already
879 : : * handled a real -1 with PyLong_AsLongAndOverflow() above.)
880 : : */
881 [ # # ]: 0 : if (gid == (gid_t)-1)
882 : 0 : goto overflow;
883 : :
884 : : /* Ensure the value wasn't truncated. */
885 : 0 : if (sizeof(gid_t) < sizeof(long) &&
886 [ # # ]: 0 : (unsigned long)gid != uresult)
887 : 0 : goto overflow;
888 : : /* fallthrough */
889 : :
890 : 0 : success:
891 : 0 : Py_DECREF(index);
892 : 0 : *p = gid;
893 : 0 : return 1;
894 : :
895 : 0 : underflow:
896 : 0 : PyErr_SetString(PyExc_OverflowError,
897 : : "gid is less than minimum");
898 : 0 : goto fail;
899 : :
900 : 0 : overflow:
901 : 0 : PyErr_SetString(PyExc_OverflowError,
902 : : "gid is greater than maximum");
903 : : /* fallthrough */
904 : :
905 : 0 : fail:
906 : 0 : Py_DECREF(index);
907 : 0 : return 0;
908 : : }
909 : : #endif /* MS_WINDOWS */
910 : :
911 : :
912 : : #define _PyLong_FromDev PyLong_FromLongLong
913 : :
914 : :
915 : : #if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
916 : : static int
917 : 0 : _Py_Dev_Converter(PyObject *obj, void *p)
918 : : {
919 : 0 : *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
920 [ # # ]: 0 : if (PyErr_Occurred())
921 : 0 : return 0;
922 : 0 : return 1;
923 : : }
924 : : #endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
925 : :
926 : :
927 : : #ifdef AT_FDCWD
928 : : /*
929 : : * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
930 : : * without the int cast, the value gets interpreted as uint (4291925331),
931 : : * which doesn't play nicely with all the initializer lines in this file that
932 : : * look like this:
933 : : * int dir_fd = DEFAULT_DIR_FD;
934 : : */
935 : : #define DEFAULT_DIR_FD (int)AT_FDCWD
936 : : #else
937 : : #define DEFAULT_DIR_FD (-100)
938 : : #endif
939 : :
940 : : static int
941 : 1 : _fd_converter(PyObject *o, int *p)
942 : : {
943 : : int overflow;
944 : : long long_value;
945 : :
946 : 1 : PyObject *index = _PyNumber_Index(o);
947 [ - + ]: 1 : if (index == NULL) {
948 : 0 : return 0;
949 : : }
950 : :
951 : : assert(PyLong_Check(index));
952 : 1 : long_value = PyLong_AsLongAndOverflow(index, &overflow);
953 : 1 : Py_DECREF(index);
954 : : assert(!PyErr_Occurred());
955 [ + - - + ]: 1 : if (overflow > 0 || long_value > INT_MAX) {
956 : 0 : PyErr_SetString(PyExc_OverflowError,
957 : : "fd is greater than maximum");
958 : 0 : return 0;
959 : : }
960 [ + - - + ]: 1 : if (overflow < 0 || long_value < INT_MIN) {
961 : 0 : PyErr_SetString(PyExc_OverflowError,
962 : : "fd is less than minimum");
963 : 0 : return 0;
964 : : }
965 : :
966 : 1 : *p = (int)long_value;
967 : 1 : return 1;
968 : : }
969 : :
970 : : static int
971 : 55 : dir_fd_converter(PyObject *o, void *p)
972 : : {
973 [ + - ]: 55 : if (o == Py_None) {
974 : 55 : *(int *)p = DEFAULT_DIR_FD;
975 : 55 : return 1;
976 : : }
977 [ # # ]: 0 : else if (PyIndex_Check(o)) {
978 : 0 : return _fd_converter(o, (int *)p);
979 : : }
980 : : else {
981 : 0 : PyErr_Format(PyExc_TypeError,
982 : : "argument should be integer or None, not %.200s",
983 : : _PyType_Name(Py_TYPE(o)));
984 : 0 : return 0;
985 : : }
986 : : }
987 : :
988 : : typedef struct {
989 : : PyObject *billion;
990 : : PyObject *DirEntryType;
991 : : PyObject *ScandirIteratorType;
992 : : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
993 : : PyObject *SchedParamType;
994 : : #endif
995 : : newfunc statresult_new_orig;
996 : : PyObject *StatResultType;
997 : : PyObject *StatVFSResultType;
998 : : PyObject *TerminalSizeType;
999 : : PyObject *TimesResultType;
1000 : : PyObject *UnameResultType;
1001 : : #if defined(HAVE_WAITID) && !defined(__APPLE__)
1002 : : PyObject *WaitidResultType;
1003 : : #endif
1004 : : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
1005 : : PyObject *struct_rusage;
1006 : : #endif
1007 : : PyObject *st_mode;
1008 : : } _posixstate;
1009 : :
1010 : :
1011 : : static inline _posixstate*
1012 : 13058 : get_posix_state(PyObject *module)
1013 : : {
1014 : 13058 : void *state = _PyModule_GetState(module);
1015 : : assert(state != NULL);
1016 : 13058 : return (_posixstate *)state;
1017 : : }
1018 : :
1019 : : /*
1020 : : * A PyArg_ParseTuple "converter" function
1021 : : * that handles filesystem paths in the manner
1022 : : * preferred by the os module.
1023 : : *
1024 : : * path_converter accepts (Unicode) strings and their
1025 : : * subclasses, and bytes and their subclasses. What
1026 : : * it does with the argument depends on the platform:
1027 : : *
1028 : : * * On Windows, if we get a (Unicode) string we
1029 : : * extract the wchar_t * and return it; if we get
1030 : : * bytes we decode to wchar_t * and return that.
1031 : : *
1032 : : * * On all other platforms, strings are encoded
1033 : : * to bytes using PyUnicode_FSConverter, then we
1034 : : * extract the char * from the bytes object and
1035 : : * return that.
1036 : : *
1037 : : * path_converter also optionally accepts signed
1038 : : * integers (representing open file descriptors) instead
1039 : : * of path strings.
1040 : : *
1041 : : * Input fields:
1042 : : * path.nullable
1043 : : * If nonzero, the path is permitted to be None.
1044 : : * path.allow_fd
1045 : : * If nonzero, the path is permitted to be a file handle
1046 : : * (a signed int) instead of a string.
1047 : : * path.function_name
1048 : : * If non-NULL, path_converter will use that as the name
1049 : : * of the function in error messages.
1050 : : * (If path.function_name is NULL it omits the function name.)
1051 : : * path.argument_name
1052 : : * If non-NULL, path_converter will use that as the name
1053 : : * of the parameter in error messages.
1054 : : * (If path.argument_name is NULL it uses "path".)
1055 : : *
1056 : : * Output fields:
1057 : : * path.wide
1058 : : * Points to the path if it was expressed as Unicode
1059 : : * and was not encoded. (Only used on Windows.)
1060 : : * path.narrow
1061 : : * Points to the path if it was expressed as bytes,
1062 : : * or it was Unicode and was encoded to bytes. (On Windows,
1063 : : * is a non-zero integer if the path was expressed as bytes.
1064 : : * The type is deliberately incompatible to prevent misuse.)
1065 : : * path.fd
1066 : : * Contains a file descriptor if path.accept_fd was true
1067 : : * and the caller provided a signed integer instead of any
1068 : : * sort of string.
1069 : : *
1070 : : * WARNING: if your "path" parameter is optional, and is
1071 : : * unspecified, path_converter will never get called.
1072 : : * So if you set allow_fd, you *MUST* initialize path.fd = -1
1073 : : * yourself!
1074 : : * path.length
1075 : : * The length of the path in characters, if specified as
1076 : : * a string.
1077 : : * path.object
1078 : : * The original object passed in (if get a PathLike object,
1079 : : * the result of PyOS_FSPath() is treated as the original object).
1080 : : * Own a reference to the object.
1081 : : * path.cleanup
1082 : : * For internal use only. May point to a temporary object.
1083 : : * (Pay no attention to the man behind the curtain.)
1084 : : *
1085 : : * At most one of path.wide or path.narrow will be non-NULL.
1086 : : * If path was None and path.nullable was set,
1087 : : * or if path was an integer and path.allow_fd was set,
1088 : : * both path.wide and path.narrow will be NULL
1089 : : * and path.length will be 0.
1090 : : *
1091 : : * path_converter takes care to not write to the path_t
1092 : : * unless it's successful. However it must reset the
1093 : : * "cleanup" field each time it's called.
1094 : : *
1095 : : * Use as follows:
1096 : : * path_t path;
1097 : : * memset(&path, 0, sizeof(path));
1098 : : * PyArg_ParseTuple(args, "O&", path_converter, &path);
1099 : : * // ... use values from path ...
1100 : : * path_cleanup(&path);
1101 : : *
1102 : : * (Note that if PyArg_Parse fails you don't need to call
1103 : : * path_cleanup(). However it is safe to do so.)
1104 : : */
1105 : : typedef struct {
1106 : : const char *function_name;
1107 : : const char *argument_name;
1108 : : int nullable;
1109 : : int allow_fd;
1110 : : const wchar_t *wide;
1111 : : #ifdef MS_WINDOWS
1112 : : BOOL narrow;
1113 : : #else
1114 : : const char *narrow;
1115 : : #endif
1116 : : int fd;
1117 : : Py_ssize_t length;
1118 : : PyObject *object;
1119 : : PyObject *cleanup;
1120 : : } path_t;
1121 : :
1122 : : #ifdef MS_WINDOWS
1123 : : #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1124 : : {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
1125 : : #else
1126 : : #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1127 : : {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
1128 : : #endif
1129 : :
1130 : : static void
1131 : 3907 : path_cleanup(path_t *path)
1132 : : {
1133 : 3907 : wchar_t *wide = (wchar_t *)path->wide;
1134 : 3907 : path->wide = NULL;
1135 : 3907 : PyMem_Free(wide);
1136 [ + + ]: 3907 : Py_CLEAR(path->object);
1137 [ + + ]: 3907 : Py_CLEAR(path->cleanup);
1138 : 3907 : }
1139 : :
1140 : : static int
1141 : 3848 : path_converter(PyObject *o, void *p)
1142 : : {
1143 : 3848 : path_t *path = (path_t *)p;
1144 : 3848 : PyObject *bytes = NULL;
1145 : 3848 : Py_ssize_t length = 0;
1146 : : int is_index, is_bytes, is_unicode;
1147 : : const char *narrow;
1148 : : #ifdef MS_WINDOWS
1149 : : PyObject *wo = NULL;
1150 : : wchar_t *wide = NULL;
1151 : : #endif
1152 : :
1153 : : #define FORMAT_EXCEPTION(exc, fmt) \
1154 : : PyErr_Format(exc, "%s%s" fmt, \
1155 : : path->function_name ? path->function_name : "", \
1156 : : path->function_name ? ": " : "", \
1157 : : path->argument_name ? path->argument_name : "path")
1158 : :
1159 : : /* Py_CLEANUP_SUPPORTED support */
1160 [ - + ]: 3848 : if (o == NULL) {
1161 : 0 : path_cleanup(path);
1162 : 0 : return 1;
1163 : : }
1164 : :
1165 : : /* Ensure it's always safe to call path_cleanup(). */
1166 : 3848 : path->object = path->cleanup = NULL;
1167 : : /* path->object owns a reference to the original object */
1168 : 3848 : Py_INCREF(o);
1169 : :
1170 [ - + - - ]: 3848 : if ((o == Py_None) && path->nullable) {
1171 : 0 : path->wide = NULL;
1172 : : #ifdef MS_WINDOWS
1173 : : path->narrow = FALSE;
1174 : : #else
1175 : 0 : path->narrow = NULL;
1176 : : #endif
1177 : 0 : path->fd = -1;
1178 : 0 : goto success_exit;
1179 : : }
1180 : :
1181 : : /* Only call this here so that we don't treat the return value of
1182 : : os.fspath() as an fd or buffer. */
1183 [ + + + + ]: 3848 : is_index = path->allow_fd && PyIndex_Check(o);
1184 : 3848 : is_bytes = PyBytes_Check(o);
1185 : 3848 : is_unicode = PyUnicode_Check(o);
1186 : :
1187 [ + + - + : 3848 : if (!is_index && !is_unicode && !is_bytes) {
- - ]
1188 : : /* Inline PyOS_FSPath() for better error messages. */
1189 : : PyObject *func, *res;
1190 : :
1191 : 0 : func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1192 [ # # ]: 0 : if (NULL == func) {
1193 : 0 : goto error_format;
1194 : : }
1195 : 0 : res = _PyObject_CallNoArgs(func);
1196 : 0 : Py_DECREF(func);
1197 [ # # ]: 0 : if (NULL == res) {
1198 : 0 : goto error_exit;
1199 : : }
1200 [ # # ]: 0 : else if (PyUnicode_Check(res)) {
1201 : 0 : is_unicode = 1;
1202 : : }
1203 [ # # ]: 0 : else if (PyBytes_Check(res)) {
1204 : 0 : is_bytes = 1;
1205 : : }
1206 : : else {
1207 : 0 : PyErr_Format(PyExc_TypeError,
1208 : : "expected %.200s.__fspath__() to return str or bytes, "
1209 : : "not %.200s", _PyType_Name(Py_TYPE(o)),
1210 : : _PyType_Name(Py_TYPE(res)));
1211 : 0 : Py_DECREF(res);
1212 : 0 : goto error_exit;
1213 : : }
1214 : :
1215 : : /* still owns a reference to the original object */
1216 : 0 : Py_SETREF(o, res);
1217 : : }
1218 : :
1219 [ + + ]: 3848 : if (is_unicode) {
1220 : : #ifdef MS_WINDOWS
1221 : : wide = PyUnicode_AsWideCharString(o, &length);
1222 : : if (!wide) {
1223 : : goto error_exit;
1224 : : }
1225 : : if (length > 32767) {
1226 : : FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1227 : : goto error_exit;
1228 : : }
1229 : : if (wcslen(wide) != length) {
1230 : : FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1231 : : goto error_exit;
1232 : : }
1233 : :
1234 : : path->wide = wide;
1235 : : path->narrow = FALSE;
1236 : : path->fd = -1;
1237 : : wide = NULL;
1238 : : goto success_exit;
1239 : : #else
1240 [ - + ]: 3847 : if (!PyUnicode_FSConverter(o, &bytes)) {
1241 : 0 : goto error_exit;
1242 : : }
1243 : : #endif
1244 : : }
1245 [ - + ]: 1 : else if (is_bytes) {
1246 : 0 : bytes = Py_NewRef(o);
1247 : : }
1248 [ + - ]: 1 : else if (is_index) {
1249 [ - + ]: 1 : if (!_fd_converter(o, &path->fd)) {
1250 : 0 : goto error_exit;
1251 : : }
1252 : 1 : path->wide = NULL;
1253 : : #ifdef MS_WINDOWS
1254 : : path->narrow = FALSE;
1255 : : #else
1256 : 1 : path->narrow = NULL;
1257 : : #endif
1258 : 1 : goto success_exit;
1259 : : }
1260 : : else {
1261 : 0 : error_format:
1262 : 0 : PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1263 [ # # ]: 0 : path->function_name ? path->function_name : "",
1264 [ # # ]: 0 : path->function_name ? ": " : "",
1265 [ # # ]: 0 : path->argument_name ? path->argument_name : "path",
1266 [ # # # # ]: 0 : path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1267 : : "integer or None" :
1268 [ # # ]: 0 : path->allow_fd ? "string, bytes, os.PathLike or integer" :
1269 [ # # ]: 0 : path->nullable ? "string, bytes, os.PathLike or None" :
1270 : : "string, bytes or os.PathLike",
1271 : : _PyType_Name(Py_TYPE(o)));
1272 : 0 : goto error_exit;
1273 : : }
1274 : :
1275 : 3847 : length = PyBytes_GET_SIZE(bytes);
1276 : 3847 : narrow = PyBytes_AS_STRING(bytes);
1277 [ - + ]: 3847 : if ((size_t)length != strlen(narrow)) {
1278 [ # # # # : 0 : FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
# # ]
1279 : 0 : goto error_exit;
1280 : : }
1281 : :
1282 : : #ifdef MS_WINDOWS
1283 : : wo = PyUnicode_DecodeFSDefaultAndSize(
1284 : : narrow,
1285 : : length
1286 : : );
1287 : : if (!wo) {
1288 : : goto error_exit;
1289 : : }
1290 : :
1291 : : wide = PyUnicode_AsWideCharString(wo, &length);
1292 : : Py_DECREF(wo);
1293 : : if (!wide) {
1294 : : goto error_exit;
1295 : : }
1296 : : if (length > 32767) {
1297 : : FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1298 : : goto error_exit;
1299 : : }
1300 : : if (wcslen(wide) != length) {
1301 : : FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1302 : : goto error_exit;
1303 : : }
1304 : : path->wide = wide;
1305 : : path->narrow = TRUE;
1306 : : Py_DECREF(bytes);
1307 : : wide = NULL;
1308 : : #else
1309 : 3847 : path->wide = NULL;
1310 : 3847 : path->narrow = narrow;
1311 [ - + ]: 3847 : if (bytes == o) {
1312 : : /* Still a reference owned by path->object, don't have to
1313 : : worry about path->narrow is used after free. */
1314 : 0 : Py_DECREF(bytes);
1315 : : }
1316 : : else {
1317 : 3847 : path->cleanup = bytes;
1318 : : }
1319 : : #endif
1320 : 3847 : path->fd = -1;
1321 : :
1322 : 3848 : success_exit:
1323 : 3848 : path->length = length;
1324 : 3848 : path->object = o;
1325 : 3848 : return Py_CLEANUP_SUPPORTED;
1326 : :
1327 : 0 : error_exit:
1328 : 0 : Py_XDECREF(o);
1329 : 0 : Py_XDECREF(bytes);
1330 : : #ifdef MS_WINDOWS
1331 : : PyMem_Free(wide);
1332 : : #endif
1333 : 0 : return 0;
1334 : : }
1335 : :
1336 : : static void
1337 : 0 : argument_unavailable_error(const char *function_name, const char *argument_name)
1338 : : {
1339 [ # # # # ]: 0 : PyErr_Format(PyExc_NotImplementedError,
1340 : : "%s%s%s unavailable on this platform",
1341 : : (function_name != NULL) ? function_name : "",
1342 : : (function_name != NULL) ? ": ": "",
1343 : : argument_name);
1344 : 0 : }
1345 : :
1346 : : static int
1347 : 26 : dir_fd_unavailable(PyObject *o, void *p)
1348 : : {
1349 : : int dir_fd;
1350 [ - + ]: 26 : if (!dir_fd_converter(o, &dir_fd))
1351 : 0 : return 0;
1352 [ - + ]: 26 : if (dir_fd != DEFAULT_DIR_FD) {
1353 : 0 : argument_unavailable_error(NULL, "dir_fd");
1354 : 0 : return 0;
1355 : : }
1356 : 26 : *(int *)p = dir_fd;
1357 : 26 : return 1;
1358 : : }
1359 : :
1360 : : static int
1361 : 26 : fd_specified(const char *function_name, int fd)
1362 : : {
1363 [ + - ]: 26 : if (fd == -1)
1364 : 26 : return 0;
1365 : :
1366 : 0 : argument_unavailable_error(function_name, "fd");
1367 : 0 : return 1;
1368 : : }
1369 : :
1370 : : static int
1371 : 26 : follow_symlinks_specified(const char *function_name, int follow_symlinks)
1372 : : {
1373 [ + - ]: 26 : if (follow_symlinks)
1374 : 26 : return 0;
1375 : :
1376 : 0 : argument_unavailable_error(function_name, "follow_symlinks");
1377 : 0 : return 1;
1378 : : }
1379 : :
1380 : : static int
1381 : 3204 : path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1382 : : {
1383 [ + - - + ]: 3204 : if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1384 : : #ifndef MS_WINDOWS
1385 [ # # ]: 0 : && !path->narrow
1386 : : #endif
1387 : : ) {
1388 : 0 : PyErr_Format(PyExc_ValueError,
1389 : : "%s: can't specify dir_fd without matching path",
1390 : : function_name);
1391 : 0 : return 1;
1392 : : }
1393 : 3204 : return 0;
1394 : : }
1395 : :
1396 : : static int
1397 : 3204 : dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1398 : : {
1399 [ - + - - ]: 3204 : if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1400 : 0 : PyErr_Format(PyExc_ValueError,
1401 : : "%s: can't specify both dir_fd and fd",
1402 : : function_name);
1403 : 0 : return 1;
1404 : : }
1405 : 3204 : return 0;
1406 : : }
1407 : :
1408 : : static int
1409 : 3204 : fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1410 : : int follow_symlinks)
1411 : : {
1412 [ - + - - ]: 3204 : if ((fd > 0) && (!follow_symlinks)) {
1413 : 0 : PyErr_Format(PyExc_ValueError,
1414 : : "%s: cannot use fd and follow_symlinks together",
1415 : : function_name);
1416 : 0 : return 1;
1417 : : }
1418 : 3204 : return 0;
1419 : : }
1420 : :
1421 : : static int
1422 : 26 : dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1423 : : int follow_symlinks)
1424 : : {
1425 [ - + - - ]: 26 : if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1426 : 0 : PyErr_Format(PyExc_ValueError,
1427 : : "%s: cannot use dir_fd and follow_symlinks together",
1428 : : function_name);
1429 : 0 : return 1;
1430 : : }
1431 : 26 : return 0;
1432 : : }
1433 : :
1434 : : #ifdef MS_WINDOWS
1435 : : typedef long long Py_off_t;
1436 : : #else
1437 : : typedef off_t Py_off_t;
1438 : : #endif
1439 : :
1440 : : static int
1441 : 0 : Py_off_t_converter(PyObject *arg, void *addr)
1442 : : {
1443 : : #ifdef HAVE_LARGEFILE_SUPPORT
1444 : : *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1445 : : #else
1446 : 0 : *((Py_off_t *)addr) = PyLong_AsLong(arg);
1447 : : #endif
1448 [ # # ]: 0 : if (PyErr_Occurred())
1449 : 0 : return 0;
1450 : 0 : return 1;
1451 : : }
1452 : :
1453 : : static PyObject *
1454 : 0 : PyLong_FromPy_off_t(Py_off_t offset)
1455 : : {
1456 : : #ifdef HAVE_LARGEFILE_SUPPORT
1457 : : return PyLong_FromLongLong(offset);
1458 : : #else
1459 : 0 : return PyLong_FromLong(offset);
1460 : : #endif
1461 : : }
1462 : :
1463 : : #ifdef HAVE_SIGSET_T
1464 : : /* Convert an iterable of integers to a sigset.
1465 : : Return 1 on success, return 0 and raise an exception on error. */
1466 : : int
1467 : 0 : _Py_Sigset_Converter(PyObject *obj, void *addr)
1468 : : {
1469 : 0 : sigset_t *mask = (sigset_t *)addr;
1470 : : PyObject *iterator, *item;
1471 : : long signum;
1472 : : int overflow;
1473 : :
1474 : : // The extra parens suppress the unreachable-code warning with clang on MacOS
1475 [ # # ]: 0 : if (sigemptyset(mask) < (0)) {
1476 : : /* Probably only if mask == NULL. */
1477 : 0 : PyErr_SetFromErrno(PyExc_OSError);
1478 : 0 : return 0;
1479 : : }
1480 : :
1481 : 0 : iterator = PyObject_GetIter(obj);
1482 [ # # ]: 0 : if (iterator == NULL) {
1483 : 0 : return 0;
1484 : : }
1485 : :
1486 [ # # ]: 0 : while ((item = PyIter_Next(iterator)) != NULL) {
1487 : 0 : signum = PyLong_AsLongAndOverflow(item, &overflow);
1488 : 0 : Py_DECREF(item);
1489 [ # # # # ]: 0 : if (signum <= 0 || signum >= Py_NSIG) {
1490 [ # # # # : 0 : if (overflow || signum != -1 || !PyErr_Occurred()) {
# # ]
1491 : 0 : PyErr_Format(PyExc_ValueError,
1492 : : "signal number %ld out of range [1; %i]",
1493 : : signum, Py_NSIG - 1);
1494 : : }
1495 : 0 : goto error;
1496 : : }
1497 [ # # ]: 0 : if (sigaddset(mask, (int)signum)) {
1498 [ # # ]: 0 : if (errno != EINVAL) {
1499 : : /* Probably impossible */
1500 : 0 : PyErr_SetFromErrno(PyExc_OSError);
1501 : 0 : goto error;
1502 : : }
1503 : : /* For backwards compatibility, allow idioms such as
1504 : : * `range(1, NSIG)` but warn about invalid signal numbers
1505 : : */
1506 : 0 : const char msg[] =
1507 : : "invalid signal number %ld, please use valid_signals()";
1508 [ # # ]: 0 : if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1509 : 0 : goto error;
1510 : : }
1511 : : }
1512 : : }
1513 [ # # ]: 0 : if (!PyErr_Occurred()) {
1514 : 0 : Py_DECREF(iterator);
1515 : 0 : return 1;
1516 : : }
1517 : :
1518 : 0 : error:
1519 : 0 : Py_DECREF(iterator);
1520 : 0 : return 0;
1521 : : }
1522 : : #endif /* HAVE_SIGSET_T */
1523 : :
1524 : : /* Return a dictionary corresponding to the POSIX environment table */
1525 : : #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1526 : : /* On Darwin/MacOSX a shared library or framework has no access to
1527 : : ** environ directly, we must obtain it with _NSGetEnviron(). See also
1528 : : ** man environ(7).
1529 : : */
1530 : : #include <crt_externs.h>
1531 : : #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1532 : : extern char **environ;
1533 : : #endif /* !_MSC_VER */
1534 : :
1535 : : static PyObject *
1536 : 26 : convertenviron(void)
1537 : : {
1538 : : PyObject *d;
1539 : : #ifdef MS_WINDOWS
1540 : : wchar_t **e;
1541 : : #else
1542 : : char **e;
1543 : : #endif
1544 : :
1545 : 26 : d = PyDict_New();
1546 [ - + ]: 26 : if (d == NULL)
1547 : 0 : return NULL;
1548 : : #ifdef MS_WINDOWS
1549 : : /* _wenviron must be initialized in this way if the program is started
1550 : : through main() instead of wmain(). */
1551 : : (void)_wgetenv(L"");
1552 : : e = _wenviron;
1553 : : #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1554 : : /* environ is not accessible as an extern in a shared object on OSX; use
1555 : : _NSGetEnviron to resolve it. The value changes if you add environment
1556 : : variables between calls to Py_Initialize, so don't cache the value. */
1557 : : e = *_NSGetEnviron();
1558 : : #else
1559 : 26 : e = environ;
1560 : : #endif
1561 [ - + ]: 26 : if (e == NULL)
1562 : 0 : return d;
1563 [ + + ]: 2072 : for (; *e != NULL; e++) {
1564 : : PyObject *k;
1565 : : PyObject *v;
1566 : : #ifdef MS_WINDOWS
1567 : : const wchar_t *p = wcschr(*e, L'=');
1568 : : #else
1569 : 2046 : const char *p = strchr(*e, '=');
1570 : : #endif
1571 [ - + ]: 2046 : if (p == NULL)
1572 : 0 : continue;
1573 : : #ifdef MS_WINDOWS
1574 : : k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1575 : : #else
1576 : 2046 : k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1577 : : #endif
1578 [ - + ]: 2046 : if (k == NULL) {
1579 : 0 : Py_DECREF(d);
1580 : 0 : return NULL;
1581 : : }
1582 : : #ifdef MS_WINDOWS
1583 : : v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1584 : : #else
1585 : 2046 : v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1586 : : #endif
1587 [ - + ]: 2046 : if (v == NULL) {
1588 : 0 : Py_DECREF(k);
1589 : 0 : Py_DECREF(d);
1590 : 0 : return NULL;
1591 : : }
1592 [ - + ]: 2046 : if (PyDict_SetDefault(d, k, v) == NULL) {
1593 : 0 : Py_DECREF(v);
1594 : 0 : Py_DECREF(k);
1595 : 0 : Py_DECREF(d);
1596 : 0 : return NULL;
1597 : : }
1598 : 2046 : Py_DECREF(k);
1599 : 2046 : Py_DECREF(v);
1600 : : }
1601 : 26 : return d;
1602 : : }
1603 : :
1604 : : /* Set a POSIX-specific error from errno, and return NULL */
1605 : :
1606 : : static PyObject *
1607 : 1 : posix_error(void)
1608 : : {
1609 : 1 : return PyErr_SetFromErrno(PyExc_OSError);
1610 : : }
1611 : :
1612 : : #ifdef MS_WINDOWS
1613 : : static PyObject *
1614 : : win32_error(const char* function, const char* filename)
1615 : : {
1616 : : /* XXX We should pass the function name along in the future.
1617 : : (winreg.c also wants to pass the function name.)
1618 : : This would however require an additional param to the
1619 : : Windows error object, which is non-trivial.
1620 : : */
1621 : : errno = GetLastError();
1622 : : if (filename)
1623 : : return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1624 : : else
1625 : : return PyErr_SetFromWindowsErr(errno);
1626 : : }
1627 : :
1628 : : static PyObject *
1629 : : win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1630 : : {
1631 : : /* XXX - see win32_error for comments on 'function' */
1632 : : if (filename)
1633 : : return PyErr_SetExcFromWindowsErrWithFilenameObject(
1634 : : PyExc_OSError,
1635 : : err,
1636 : : filename);
1637 : : else
1638 : : return PyErr_SetFromWindowsErr(err);
1639 : : }
1640 : :
1641 : : static PyObject *
1642 : : win32_error_object(const char* function, PyObject* filename)
1643 : : {
1644 : : errno = GetLastError();
1645 : : return win32_error_object_err(function, filename, errno);
1646 : : }
1647 : :
1648 : : #endif /* MS_WINDOWS */
1649 : :
1650 : : static PyObject *
1651 : 424 : posix_path_object_error(PyObject *path)
1652 : : {
1653 : 424 : return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1654 : : }
1655 : :
1656 : : static PyObject *
1657 : 424 : path_object_error(PyObject *path)
1658 : : {
1659 : : #ifdef MS_WINDOWS
1660 : : return PyErr_SetExcFromWindowsErrWithFilenameObject(
1661 : : PyExc_OSError, 0, path);
1662 : : #else
1663 : 424 : return posix_path_object_error(path);
1664 : : #endif
1665 : : }
1666 : :
1667 : : static PyObject *
1668 : 0 : path_object_error2(PyObject *path, PyObject *path2)
1669 : : {
1670 : : #ifdef MS_WINDOWS
1671 : : return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1672 : : PyExc_OSError, 0, path, path2);
1673 : : #else
1674 : 0 : return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1675 : : #endif
1676 : : }
1677 : :
1678 : : static PyObject *
1679 : 424 : path_error(path_t *path)
1680 : : {
1681 : 424 : return path_object_error(path->object);
1682 : : }
1683 : :
1684 : : static PyObject *
1685 : 0 : posix_path_error(path_t *path)
1686 : : {
1687 : 0 : return posix_path_object_error(path->object);
1688 : : }
1689 : :
1690 : : static PyObject *
1691 : 0 : path_error2(path_t *path, path_t *path2)
1692 : : {
1693 : 0 : return path_object_error2(path->object, path2->object);
1694 : : }
1695 : :
1696 : :
1697 : : /* POSIX generic methods */
1698 : :
1699 : : static PyObject *
1700 : 0 : posix_fildes_fd(int fd, int (*func)(int))
1701 : : {
1702 : : int res;
1703 : 0 : int async_err = 0;
1704 : :
1705 : : do {
1706 : 0 : Py_BEGIN_ALLOW_THREADS
1707 : : _Py_BEGIN_SUPPRESS_IPH
1708 : 0 : res = (*func)(fd);
1709 : : _Py_END_SUPPRESS_IPH
1710 : 0 : Py_END_ALLOW_THREADS
1711 [ # # # # : 0 : } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
1712 [ # # ]: 0 : if (res != 0)
1713 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
1714 : 0 : Py_RETURN_NONE;
1715 : : }
1716 : :
1717 : :
1718 : : #ifdef MS_WINDOWS
1719 : : /* This is a reimplementation of the C library's chdir function,
1720 : : but one that produces Win32 errors instead of DOS error codes.
1721 : : chdir is essentially a wrapper around SetCurrentDirectory; however,
1722 : : it also needs to set "magic" environment variables indicating
1723 : : the per-drive current directory, which are of the form =<drive>: */
1724 : : static BOOL __stdcall
1725 : : win32_wchdir(LPCWSTR path)
1726 : : {
1727 : : wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1728 : : int result;
1729 : : wchar_t env[4] = L"=x:";
1730 : :
1731 : : if(!SetCurrentDirectoryW(path))
1732 : : return FALSE;
1733 : : result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1734 : : if (!result)
1735 : : return FALSE;
1736 : : if (result > Py_ARRAY_LENGTH(path_buf)) {
1737 : : new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1738 : : if (!new_path) {
1739 : : SetLastError(ERROR_OUTOFMEMORY);
1740 : : return FALSE;
1741 : : }
1742 : : result = GetCurrentDirectoryW(result, new_path);
1743 : : if (!result) {
1744 : : PyMem_RawFree(new_path);
1745 : : return FALSE;
1746 : : }
1747 : : }
1748 : : int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1749 : : wcsncmp(new_path, L"//", 2) == 0);
1750 : : if (!is_unc_like_path) {
1751 : : env[1] = new_path[0];
1752 : : result = SetEnvironmentVariableW(env, new_path);
1753 : : }
1754 : : if (new_path != path_buf)
1755 : : PyMem_RawFree(new_path);
1756 : : return result ? TRUE : FALSE;
1757 : : }
1758 : : #endif
1759 : :
1760 : : #ifdef MS_WINDOWS
1761 : : /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1762 : : - time stamps are restricted to second resolution
1763 : : - file modification times suffer from forth-and-back conversions between
1764 : : UTC and local time
1765 : : Therefore, we implement our own stat, based on the Win32 API directly.
1766 : : */
1767 : : #define HAVE_STAT_NSEC 1
1768 : : #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1769 : : #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1770 : :
1771 : : static void
1772 : : find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1773 : : BY_HANDLE_FILE_INFORMATION *info,
1774 : : ULONG *reparse_tag)
1775 : : {
1776 : : memset(info, 0, sizeof(*info));
1777 : : info->dwFileAttributes = pFileData->dwFileAttributes;
1778 : : info->ftCreationTime = pFileData->ftCreationTime;
1779 : : info->ftLastAccessTime = pFileData->ftLastAccessTime;
1780 : : info->ftLastWriteTime = pFileData->ftLastWriteTime;
1781 : : info->nFileSizeHigh = pFileData->nFileSizeHigh;
1782 : : info->nFileSizeLow = pFileData->nFileSizeLow;
1783 : : /* info->nNumberOfLinks = 1; */
1784 : : if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1785 : : *reparse_tag = pFileData->dwReserved0;
1786 : : else
1787 : : *reparse_tag = 0;
1788 : : }
1789 : :
1790 : : static BOOL
1791 : : attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1792 : : {
1793 : : HANDLE hFindFile;
1794 : : WIN32_FIND_DATAW FileData;
1795 : : LPCWSTR filename = pszFile;
1796 : : size_t n = wcslen(pszFile);
1797 : : if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
1798 : : // cannot use PyMem_Malloc here because we do not hold the GIL
1799 : : filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
1800 : : if(!filename) {
1801 : : SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1802 : : return FALSE;
1803 : : }
1804 : : wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
1805 : : while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
1806 : : ((LPWSTR)filename)[n] = L'\0';
1807 : : }
1808 : : if (!n || (n == 1 && filename[1] == L':')) {
1809 : : // Nothing left to query
1810 : : free((void *)filename);
1811 : : return FALSE;
1812 : : }
1813 : : }
1814 : : hFindFile = FindFirstFileW(filename, &FileData);
1815 : : if (pszFile != filename) {
1816 : : free((void *)filename);
1817 : : }
1818 : : if (hFindFile == INVALID_HANDLE_VALUE) {
1819 : : return FALSE;
1820 : : }
1821 : : FindClose(hFindFile);
1822 : : find_data_to_file_info(&FileData, info, reparse_tag);
1823 : : return TRUE;
1824 : : }
1825 : :
1826 : :
1827 : : static void
1828 : : update_st_mode_from_path(const wchar_t *path, DWORD attr,
1829 : : struct _Py_stat_struct *result)
1830 : : {
1831 : : if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
1832 : : /* Fix the file execute permissions. This hack sets S_IEXEC if
1833 : : the filename has an extension that is commonly used by files
1834 : : that CreateProcessW can execute. A real implementation calls
1835 : : GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
1836 : : AccessCheck to check for generic read, write, and execute
1837 : : access. */
1838 : : const wchar_t *fileExtension = wcsrchr(path, '.');
1839 : : if (fileExtension) {
1840 : : if (_wcsicmp(fileExtension, L".exe") == 0 ||
1841 : : _wcsicmp(fileExtension, L".bat") == 0 ||
1842 : : _wcsicmp(fileExtension, L".cmd") == 0 ||
1843 : : _wcsicmp(fileExtension, L".com") == 0) {
1844 : : result->st_mode |= 0111;
1845 : : }
1846 : : }
1847 : : }
1848 : : }
1849 : :
1850 : :
1851 : : static int
1852 : : win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
1853 : : BOOL traverse)
1854 : : {
1855 : : HANDLE hFile;
1856 : : BY_HANDLE_FILE_INFORMATION fileInfo;
1857 : : FILE_BASIC_INFO basicInfo;
1858 : : FILE_ID_INFO idInfo;
1859 : : FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1860 : : DWORD fileType, error;
1861 : : BOOL isUnhandledTag = FALSE;
1862 : : int retval = 0;
1863 : :
1864 : : DWORD access = FILE_READ_ATTRIBUTES;
1865 : : DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1866 : : if (!traverse) {
1867 : : flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1868 : : }
1869 : :
1870 : : hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1871 : : if (hFile == INVALID_HANDLE_VALUE) {
1872 : : /* Either the path doesn't exist, or the caller lacks access. */
1873 : : error = GetLastError();
1874 : : switch (error) {
1875 : : case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */
1876 : : case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1877 : : /* Try reading the parent directory. */
1878 : : if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1879 : : /* Cannot read the parent directory. */
1880 : : switch (GetLastError()) {
1881 : : case ERROR_FILE_NOT_FOUND: /* File cannot be found */
1882 : : case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
1883 : : case ERROR_NOT_READY: /* Drive exists but unavailable */
1884 : : case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
1885 : : break;
1886 : : /* Restore the error from CreateFileW(). */
1887 : : default:
1888 : : SetLastError(error);
1889 : : }
1890 : :
1891 : : return -1;
1892 : : }
1893 : : if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1894 : : if (traverse ||
1895 : : !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1896 : : /* The stat call has to traverse but cannot, so fail. */
1897 : : SetLastError(error);
1898 : : return -1;
1899 : : }
1900 : : }
1901 : : break;
1902 : :
1903 : : case ERROR_INVALID_PARAMETER:
1904 : : /* \\.\con requires read or write access. */
1905 : : hFile = CreateFileW(path, access | GENERIC_READ,
1906 : : FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1907 : : OPEN_EXISTING, flags, NULL);
1908 : : if (hFile == INVALID_HANDLE_VALUE) {
1909 : : SetLastError(error);
1910 : : return -1;
1911 : : }
1912 : : break;
1913 : :
1914 : : case ERROR_CANT_ACCESS_FILE:
1915 : : /* bpo37834: open unhandled reparse points if traverse fails. */
1916 : : if (traverse) {
1917 : : traverse = FALSE;
1918 : : isUnhandledTag = TRUE;
1919 : : hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1920 : : flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1921 : : }
1922 : : if (hFile == INVALID_HANDLE_VALUE) {
1923 : : SetLastError(error);
1924 : : return -1;
1925 : : }
1926 : : break;
1927 : :
1928 : : default:
1929 : : return -1;
1930 : : }
1931 : : }
1932 : :
1933 : : if (hFile != INVALID_HANDLE_VALUE) {
1934 : : /* Handle types other than files on disk. */
1935 : : fileType = GetFileType(hFile);
1936 : : if (fileType != FILE_TYPE_DISK) {
1937 : : if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1938 : : retval = -1;
1939 : : goto cleanup;
1940 : : }
1941 : : DWORD fileAttributes = GetFileAttributesW(path);
1942 : : memset(result, 0, sizeof(*result));
1943 : : if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1944 : : fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1945 : : /* \\.\pipe\ or \\.\mailslot\ */
1946 : : result->st_mode = _S_IFDIR;
1947 : : } else if (fileType == FILE_TYPE_CHAR) {
1948 : : /* \\.\nul */
1949 : : result->st_mode = _S_IFCHR;
1950 : : } else if (fileType == FILE_TYPE_PIPE) {
1951 : : /* \\.\pipe\spam */
1952 : : result->st_mode = _S_IFIFO;
1953 : : }
1954 : : /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1955 : : goto cleanup;
1956 : : }
1957 : :
1958 : : /* Query the reparse tag, and traverse a non-link. */
1959 : : if (!traverse) {
1960 : : if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
1961 : : &tagInfo, sizeof(tagInfo))) {
1962 : : /* Allow devices that do not support FileAttributeTagInfo. */
1963 : : switch (GetLastError()) {
1964 : : case ERROR_INVALID_PARAMETER:
1965 : : case ERROR_INVALID_FUNCTION:
1966 : : case ERROR_NOT_SUPPORTED:
1967 : : tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1968 : : tagInfo.ReparseTag = 0;
1969 : : break;
1970 : : default:
1971 : : retval = -1;
1972 : : goto cleanup;
1973 : : }
1974 : : } else if (tagInfo.FileAttributes &
1975 : : FILE_ATTRIBUTE_REPARSE_POINT) {
1976 : : if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1977 : : if (isUnhandledTag) {
1978 : : /* Traversing previously failed for either this link
1979 : : or its target. */
1980 : : SetLastError(ERROR_CANT_ACCESS_FILE);
1981 : : retval = -1;
1982 : : goto cleanup;
1983 : : }
1984 : : /* Traverse a non-link, but not if traversing already failed
1985 : : for an unhandled tag. */
1986 : : } else if (!isUnhandledTag) {
1987 : : CloseHandle(hFile);
1988 : : return win32_xstat_slow_impl(path, result, TRUE);
1989 : : }
1990 : : }
1991 : : }
1992 : :
1993 : : if (!GetFileInformationByHandle(hFile, &fileInfo) ||
1994 : : !GetFileInformationByHandleEx(hFile, FileBasicInfo,
1995 : : &basicInfo, sizeof(basicInfo)) ||
1996 : : !GetFileInformationByHandleEx(hFile, FileIdInfo,
1997 : : &idInfo, sizeof(idInfo))) {
1998 : : switch (GetLastError()) {
1999 : : case ERROR_INVALID_PARAMETER:
2000 : : case ERROR_INVALID_FUNCTION:
2001 : : case ERROR_NOT_SUPPORTED:
2002 : : /* Volumes and physical disks are block devices, e.g.
2003 : : \\.\C: and \\.\PhysicalDrive0. */
2004 : : memset(result, 0, sizeof(*result));
2005 : : result->st_mode = 0x6000; /* S_IFBLK */
2006 : : goto cleanup;
2007 : : }
2008 : : retval = -1;
2009 : : goto cleanup;
2010 : : }
2011 : : }
2012 : :
2013 : : _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, &basicInfo, &idInfo, result);
2014 : : update_st_mode_from_path(path, fileInfo.dwFileAttributes, result);
2015 : :
2016 : : cleanup:
2017 : : if (hFile != INVALID_HANDLE_VALUE) {
2018 : : /* Preserve last error if we are failing */
2019 : : error = retval ? GetLastError() : 0;
2020 : : if (!CloseHandle(hFile)) {
2021 : : retval = -1;
2022 : : } else if (retval) {
2023 : : /* Restore last error */
2024 : : SetLastError(error);
2025 : : }
2026 : : }
2027 : :
2028 : : return retval;
2029 : : }
2030 : :
2031 : : static int
2032 : : win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
2033 : : BOOL traverse)
2034 : : {
2035 : : FILE_STAT_BASIC_INFORMATION statInfo;
2036 : : if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo,
2037 : : &statInfo, sizeof(statInfo))) {
2038 : : if (// Cannot use fast path for reparse points ...
2039 : : !(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2040 : : // ... unless it's a name surrogate (symlink) and we're not following
2041 : : || (!traverse && IsReparseTagNameSurrogate(statInfo.ReparseTag))
2042 : : ) {
2043 : : _Py_stat_basic_info_to_stat(&statInfo, result);
2044 : : update_st_mode_from_path(path, statInfo.FileAttributes, result);
2045 : : return 0;
2046 : : }
2047 : : } else {
2048 : : switch(GetLastError()) {
2049 : : case ERROR_FILE_NOT_FOUND:
2050 : : case ERROR_PATH_NOT_FOUND:
2051 : : case ERROR_NOT_READY:
2052 : : case ERROR_BAD_NET_NAME:
2053 : : /* These errors aren't worth retrying with the slow path */
2054 : : return -1;
2055 : : case ERROR_NOT_SUPPORTED:
2056 : : /* indicates the API couldn't be loaded */
2057 : : break;
2058 : : }
2059 : : }
2060 : :
2061 : : return win32_xstat_slow_impl(path, result, traverse);
2062 : : }
2063 : :
2064 : : static int
2065 : : win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2066 : : {
2067 : : /* Protocol violation: we explicitly clear errno, instead of
2068 : : setting it to a POSIX error. Callers should use GetLastError. */
2069 : : int code = win32_xstat_impl(path, result, traverse);
2070 : : errno = 0;
2071 : :
2072 : : /* ctime is only deprecated from 3.12, so we copy birthtime across */
2073 : : result->st_ctime = result->st_birthtime;
2074 : : result->st_ctime_nsec = result->st_birthtime_nsec;
2075 : : return code;
2076 : : }
2077 : : /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2078 : :
2079 : : In Posix, stat automatically traverses symlinks and returns the stat
2080 : : structure for the target. In Windows, the equivalent GetFileAttributes by
2081 : : default does not traverse symlinks and instead returns attributes for
2082 : : the symlink.
2083 : :
2084 : : Instead, we will open the file (which *does* traverse symlinks by default)
2085 : : and GetFileInformationByHandle(). */
2086 : :
2087 : : static int
2088 : : win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2089 : : {
2090 : : return win32_xstat(path, result, FALSE);
2091 : : }
2092 : :
2093 : : static int
2094 : : win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2095 : : {
2096 : : return win32_xstat(path, result, TRUE);
2097 : : }
2098 : :
2099 : : #endif /* MS_WINDOWS */
2100 : :
2101 : : PyDoc_STRVAR(stat_result__doc__,
2102 : : "stat_result: Result from stat, fstat, or lstat.\n\n\
2103 : : This object may be accessed either as a tuple of\n\
2104 : : (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2105 : : or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2106 : : \n\
2107 : : Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2108 : : or st_flags, they are available as attributes only.\n\
2109 : : \n\
2110 : : See os.stat for more information.");
2111 : :
2112 : : static PyStructSequence_Field stat_result_fields[] = {
2113 : : {"st_mode", "protection bits"},
2114 : : {"st_ino", "inode"},
2115 : : {"st_dev", "device"},
2116 : : {"st_nlink", "number of hard links"},
2117 : : {"st_uid", "user ID of owner"},
2118 : : {"st_gid", "group ID of owner"},
2119 : : {"st_size", "total size, in bytes"},
2120 : : /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2121 : : {NULL, "integer time of last access"},
2122 : : {NULL, "integer time of last modification"},
2123 : : {NULL, "integer time of last change"},
2124 : : {"st_atime", "time of last access"},
2125 : : {"st_mtime", "time of last modification"},
2126 : : {"st_ctime", "time of last change"},
2127 : : {"st_atime_ns", "time of last access in nanoseconds"},
2128 : : {"st_mtime_ns", "time of last modification in nanoseconds"},
2129 : : {"st_ctime_ns", "time of last change in nanoseconds"},
2130 : : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2131 : : {"st_blksize", "blocksize for filesystem I/O"},
2132 : : #endif
2133 : : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2134 : : {"st_blocks", "number of blocks allocated"},
2135 : : #endif
2136 : : #ifdef HAVE_STRUCT_STAT_ST_RDEV
2137 : : {"st_rdev", "device type (if inode device)"},
2138 : : #endif
2139 : : #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2140 : : {"st_flags", "user defined flags for file"},
2141 : : #endif
2142 : : #ifdef HAVE_STRUCT_STAT_ST_GEN
2143 : : {"st_gen", "generation number"},
2144 : : #endif
2145 : : #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2146 : : {"st_birthtime", "time of creation"},
2147 : : #endif
2148 : : #ifdef MS_WINDOWS
2149 : : {"st_birthtime_ns", "time of creation in nanoseconds"},
2150 : : #endif
2151 : : #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2152 : : {"st_file_attributes", "Windows file attribute bits"},
2153 : : #endif
2154 : : #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2155 : : {"st_fstype", "Type of filesystem"},
2156 : : #endif
2157 : : #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2158 : : {"st_reparse_tag", "Windows reparse tag"},
2159 : : #endif
2160 : : {0}
2161 : : };
2162 : :
2163 : : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2164 : : #define ST_BLKSIZE_IDX 16
2165 : : #else
2166 : : #define ST_BLKSIZE_IDX 15
2167 : : #endif
2168 : :
2169 : : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2170 : : #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2171 : : #else
2172 : : #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2173 : : #endif
2174 : :
2175 : : #ifdef HAVE_STRUCT_STAT_ST_RDEV
2176 : : #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2177 : : #else
2178 : : #define ST_RDEV_IDX ST_BLOCKS_IDX
2179 : : #endif
2180 : :
2181 : : #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2182 : : #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2183 : : #else
2184 : : #define ST_FLAGS_IDX ST_RDEV_IDX
2185 : : #endif
2186 : :
2187 : : #ifdef HAVE_STRUCT_STAT_ST_GEN
2188 : : #define ST_GEN_IDX (ST_FLAGS_IDX+1)
2189 : : #else
2190 : : #define ST_GEN_IDX ST_FLAGS_IDX
2191 : : #endif
2192 : :
2193 : : #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2194 : : #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2195 : : #else
2196 : : #define ST_BIRTHTIME_IDX ST_GEN_IDX
2197 : : #endif
2198 : :
2199 : : #ifdef MS_WINDOWS
2200 : : #define ST_BIRTHTIME_NS_IDX (ST_BIRTHTIME_IDX+1)
2201 : : #else
2202 : : #define ST_BIRTHTIME_NS_IDX ST_BIRTHTIME_IDX
2203 : : #endif
2204 : :
2205 : : #if defined(HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES) || defined(MS_WINDOWS)
2206 : : #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_NS_IDX+1)
2207 : : #else
2208 : : #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_NS_IDX
2209 : : #endif
2210 : :
2211 : : #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2212 : : #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2213 : : #else
2214 : : #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2215 : : #endif
2216 : :
2217 : : #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2218 : : #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2219 : : #else
2220 : : #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2221 : : #endif
2222 : :
2223 : : static PyStructSequence_Desc stat_result_desc = {
2224 : : "stat_result", /* name */
2225 : : stat_result__doc__, /* doc */
2226 : : stat_result_fields,
2227 : : 10
2228 : : };
2229 : :
2230 : : PyDoc_STRVAR(statvfs_result__doc__,
2231 : : "statvfs_result: Result from statvfs or fstatvfs.\n\n\
2232 : : This object may be accessed either as a tuple of\n\
2233 : : (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2234 : : or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2235 : : \n\
2236 : : See os.statvfs for more information.");
2237 : :
2238 : : static PyStructSequence_Field statvfs_result_fields[] = {
2239 : : {"f_bsize", },
2240 : : {"f_frsize", },
2241 : : {"f_blocks", },
2242 : : {"f_bfree", },
2243 : : {"f_bavail", },
2244 : : {"f_files", },
2245 : : {"f_ffree", },
2246 : : {"f_favail", },
2247 : : {"f_flag", },
2248 : : {"f_namemax",},
2249 : : {"f_fsid", },
2250 : : {0}
2251 : : };
2252 : :
2253 : : static PyStructSequence_Desc statvfs_result_desc = {
2254 : : "statvfs_result", /* name */
2255 : : statvfs_result__doc__, /* doc */
2256 : : statvfs_result_fields,
2257 : : 10
2258 : : };
2259 : :
2260 : : #if defined(HAVE_WAITID) && !defined(__APPLE__)
2261 : : PyDoc_STRVAR(waitid_result__doc__,
2262 : : "waitid_result: Result from waitid.\n\n\
2263 : : This object may be accessed either as a tuple of\n\
2264 : : (si_pid, si_uid, si_signo, si_status, si_code),\n\
2265 : : or via the attributes si_pid, si_uid, and so on.\n\
2266 : : \n\
2267 : : See os.waitid for more information.");
2268 : :
2269 : : static PyStructSequence_Field waitid_result_fields[] = {
2270 : : {"si_pid", },
2271 : : {"si_uid", },
2272 : : {"si_signo", },
2273 : : {"si_status", },
2274 : : {"si_code", },
2275 : : {0}
2276 : : };
2277 : :
2278 : : static PyStructSequence_Desc waitid_result_desc = {
2279 : : "waitid_result", /* name */
2280 : : waitid_result__doc__, /* doc */
2281 : : waitid_result_fields,
2282 : : 5
2283 : : };
2284 : : #endif
2285 : :
2286 : : static PyObject *
2287 : 0 : statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2288 : : {
2289 : : PyStructSequence *result;
2290 : : int i;
2291 : :
2292 : : // ht_module doesn't get set in PyStructSequence_NewType(),
2293 : : // so we can't use PyType_GetModule().
2294 : 0 : PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
2295 [ # # ]: 0 : if (mod == NULL) {
2296 : 0 : return NULL;
2297 : : }
2298 : 0 : _posixstate *state = get_posix_state(mod);
2299 : 0 : Py_DECREF(mod);
2300 [ # # ]: 0 : if (state == NULL) {
2301 : 0 : return NULL;
2302 : : }
2303 : : #define structseq_new state->statresult_new_orig
2304 : :
2305 : 0 : result = (PyStructSequence*)structseq_new(type, args, kwds);
2306 [ # # ]: 0 : if (!result)
2307 : 0 : return NULL;
2308 : : /* If we have been initialized from a tuple,
2309 : : st_?time might be set to None. Initialize it
2310 : : from the int slots. */
2311 [ # # ]: 0 : for (i = 7; i <= 9; i++) {
2312 [ # # ]: 0 : if (result->ob_item[i+3] == Py_None) {
2313 : 0 : Py_DECREF(Py_None);
2314 : 0 : result->ob_item[i+3] = Py_NewRef(result->ob_item[i]);
2315 : : }
2316 : : }
2317 : 0 : return (PyObject*)result;
2318 : : }
2319 : :
2320 : : static int
2321 : 52 : _posix_clear(PyObject *module)
2322 : : {
2323 : 52 : _posixstate *state = get_posix_state(module);
2324 [ + + ]: 52 : Py_CLEAR(state->billion);
2325 [ + + ]: 52 : Py_CLEAR(state->DirEntryType);
2326 [ + + ]: 52 : Py_CLEAR(state->ScandirIteratorType);
2327 : : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2328 [ + + ]: 52 : Py_CLEAR(state->SchedParamType);
2329 : : #endif
2330 [ + + ]: 52 : Py_CLEAR(state->StatResultType);
2331 [ + + ]: 52 : Py_CLEAR(state->StatVFSResultType);
2332 [ + + ]: 52 : Py_CLEAR(state->TerminalSizeType);
2333 [ + + ]: 52 : Py_CLEAR(state->TimesResultType);
2334 [ + + ]: 52 : Py_CLEAR(state->UnameResultType);
2335 : : #if defined(HAVE_WAITID) && !defined(__APPLE__)
2336 [ + + ]: 52 : Py_CLEAR(state->WaitidResultType);
2337 : : #endif
2338 : : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2339 [ + + ]: 52 : Py_CLEAR(state->struct_rusage);
2340 : : #endif
2341 [ + + ]: 52 : Py_CLEAR(state->st_mode);
2342 : 52 : return 0;
2343 : : }
2344 : :
2345 : : static int
2346 : 240 : _posix_traverse(PyObject *module, visitproc visit, void *arg)
2347 : : {
2348 : 240 : _posixstate *state = get_posix_state(module);
2349 [ + - - + ]: 240 : Py_VISIT(state->billion);
2350 [ + - - + ]: 240 : Py_VISIT(state->DirEntryType);
2351 [ + - - + ]: 240 : Py_VISIT(state->ScandirIteratorType);
2352 : : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2353 [ + - - + ]: 240 : Py_VISIT(state->SchedParamType);
2354 : : #endif
2355 [ + - - + ]: 240 : Py_VISIT(state->StatResultType);
2356 [ + - - + ]: 240 : Py_VISIT(state->StatVFSResultType);
2357 [ + - - + ]: 240 : Py_VISIT(state->TerminalSizeType);
2358 [ + - - + ]: 240 : Py_VISIT(state->TimesResultType);
2359 [ + - - + ]: 240 : Py_VISIT(state->UnameResultType);
2360 : : #if defined(HAVE_WAITID) && !defined(__APPLE__)
2361 [ + - - + ]: 240 : Py_VISIT(state->WaitidResultType);
2362 : : #endif
2363 : : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2364 [ + - - + ]: 240 : Py_VISIT(state->struct_rusage);
2365 : : #endif
2366 [ + - - + ]: 240 : Py_VISIT(state->st_mode);
2367 : 240 : return 0;
2368 : : }
2369 : :
2370 : : static void
2371 : 26 : _posix_free(void *module)
2372 : : {
2373 : 26 : _posix_clear((PyObject *)module);
2374 : 26 : }
2375 : :
2376 : : static void
2377 : 8349 : fill_time(PyObject *module, PyObject *v, int s_index, int f_index, int ns_index, time_t sec, unsigned long nsec)
2378 : : {
2379 : 8349 : PyObject *s = _PyLong_FromTime_t(sec);
2380 : 8349 : PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2381 : 8349 : PyObject *s_in_ns = NULL;
2382 : 8349 : PyObject *ns_total = NULL;
2383 : 8349 : PyObject *float_s = NULL;
2384 : :
2385 [ + - - + ]: 8349 : if (!(s && ns_fractional))
2386 : 0 : goto exit;
2387 : :
2388 : 8349 : s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2389 [ - + ]: 8349 : if (!s_in_ns)
2390 : 0 : goto exit;
2391 : :
2392 : 8349 : ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2393 [ - + ]: 8349 : if (!ns_total)
2394 : 0 : goto exit;
2395 : :
2396 : 8349 : float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2397 [ - + ]: 8349 : if (!float_s) {
2398 : 0 : goto exit;
2399 : : }
2400 : :
2401 [ + - ]: 8349 : if (s_index >= 0) {
2402 : 8349 : PyStructSequence_SET_ITEM(v, s_index, s);
2403 : 8349 : s = NULL;
2404 : : }
2405 [ + - ]: 8349 : if (f_index >= 0) {
2406 : 8349 : PyStructSequence_SET_ITEM(v, f_index, float_s);
2407 : 8349 : float_s = NULL;
2408 : : }
2409 [ - + ]: 8349 : if (ns_index >= 0) {
2410 : 8349 : PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2411 : 8349 : ns_total = NULL;
2412 : : }
2413 : 0 : exit:
2414 : 8349 : Py_XDECREF(s);
2415 : 8349 : Py_XDECREF(ns_fractional);
2416 : 8349 : Py_XDECREF(s_in_ns);
2417 : 8349 : Py_XDECREF(ns_total);
2418 : 8349 : Py_XDECREF(float_s);
2419 : 8349 : }
2420 : :
2421 : : #ifdef MS_WINDOWS
2422 : : static PyObject*
2423 : : _pystat_l128_from_l64_l64(uint64_t low, uint64_t high)
2424 : : {
2425 : : PyObject *o_low = PyLong_FromUnsignedLongLong(low);
2426 : : if (!o_low || !high) {
2427 : : return o_low;
2428 : : }
2429 : : PyObject *o_high = PyLong_FromUnsignedLongLong(high);
2430 : : PyObject *l64 = o_high ? PyLong_FromLong(64) : NULL;
2431 : : if (!l64) {
2432 : : Py_XDECREF(o_high);
2433 : : Py_DECREF(o_low);
2434 : : return NULL;
2435 : : }
2436 : : Py_SETREF(o_high, PyNumber_Lshift(o_high, l64));
2437 : : Py_DECREF(l64);
2438 : : if (!o_high) {
2439 : : Py_DECREF(o_low);
2440 : : return NULL;
2441 : : }
2442 : : Py_SETREF(o_low, PyNumber_Add(o_low, o_high));
2443 : : Py_DECREF(o_high);
2444 : : return o_low;
2445 : : }
2446 : : #endif
2447 : :
2448 : : /* pack a system stat C structure into the Python stat tuple
2449 : : (used by posix_stat() and posix_fstat()) */
2450 : : static PyObject*
2451 : 2783 : _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2452 : : {
2453 : : unsigned long ansec, mnsec, cnsec;
2454 : 2783 : PyObject *StatResultType = get_posix_state(module)->StatResultType;
2455 : 2783 : PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2456 [ - + ]: 2783 : if (v == NULL)
2457 : 0 : return NULL;
2458 : :
2459 : 2783 : PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2460 : : #ifdef MS_WINDOWS
2461 : : PyStructSequence_SET_ITEM(v, 1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high));
2462 : : PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLongLong(st->st_dev));
2463 : : #else
2464 : : static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2465 : : "stat.st_ino is larger than unsigned long long");
2466 : 2783 : PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2467 : 2783 : PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2468 : : #endif
2469 : 2783 : PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2470 : : #if defined(MS_WINDOWS)
2471 : : PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2472 : : PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2473 : : #else
2474 : 2783 : PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2475 : 2783 : PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2476 : : #endif
2477 : : static_assert(sizeof(long long) >= sizeof(st->st_size),
2478 : : "stat.st_size is larger than long long");
2479 : 2783 : PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2480 : :
2481 : : #if defined(HAVE_STAT_TV_NSEC)
2482 : 2783 : ansec = st->st_atim.tv_nsec;
2483 : 2783 : mnsec = st->st_mtim.tv_nsec;
2484 : 2783 : cnsec = st->st_ctim.tv_nsec;
2485 : : #elif defined(HAVE_STAT_TV_NSEC2)
2486 : : ansec = st->st_atimespec.tv_nsec;
2487 : : mnsec = st->st_mtimespec.tv_nsec;
2488 : : cnsec = st->st_ctimespec.tv_nsec;
2489 : : #elif defined(HAVE_STAT_NSEC)
2490 : : ansec = st->st_atime_nsec;
2491 : : mnsec = st->st_mtime_nsec;
2492 : : cnsec = st->st_ctime_nsec;
2493 : : #else
2494 : : ansec = mnsec = cnsec = 0;
2495 : : #endif
2496 : 2783 : fill_time(module, v, 7, 10, 13, st->st_atime, ansec);
2497 : 2783 : fill_time(module, v, 8, 11, 14, st->st_mtime, mnsec);
2498 : 2783 : fill_time(module, v, 9, 12, 15, st->st_ctime, cnsec);
2499 : :
2500 : : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2501 : 2783 : PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2502 : : PyLong_FromLong((long)st->st_blksize));
2503 : : #endif
2504 : : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2505 : 2783 : PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2506 : : PyLong_FromLong((long)st->st_blocks));
2507 : : #endif
2508 : : #ifdef HAVE_STRUCT_STAT_ST_RDEV
2509 : 2783 : PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2510 : : PyLong_FromLong((long)st->st_rdev));
2511 : : #endif
2512 : : #ifdef HAVE_STRUCT_STAT_ST_GEN
2513 : : PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2514 : : PyLong_FromLong((long)st->st_gen));
2515 : : #endif
2516 : : #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
2517 : : {
2518 : : PyObject *val;
2519 : : unsigned long bsec,bnsec;
2520 : : bsec = (long)st->st_birthtime;
2521 : : #ifdef HAVE_STAT_TV_NSEC2
2522 : : bnsec = st->st_birthtimespec.tv_nsec;
2523 : : #else
2524 : : bnsec = 0;
2525 : : #endif
2526 : : val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2527 : : PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2528 : : val);
2529 : : }
2530 : : #elif defined(MS_WINDOWS)
2531 : : fill_time(module, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX,
2532 : : st->st_birthtime, st->st_birthtime_nsec);
2533 : : #endif
2534 : : #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2535 : : PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2536 : : PyLong_FromLong((long)st->st_flags));
2537 : : #endif
2538 : : #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2539 : : PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2540 : : PyLong_FromUnsignedLong(st->st_file_attributes));
2541 : : #endif
2542 : : #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2543 : : PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2544 : : PyUnicode_FromString(st->st_fstype));
2545 : : #endif
2546 : : #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2547 : : PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2548 : : PyLong_FromUnsignedLong(st->st_reparse_tag));
2549 : : #endif
2550 : :
2551 [ - + ]: 2783 : if (PyErr_Occurred()) {
2552 : 0 : Py_DECREF(v);
2553 : 0 : return NULL;
2554 : : }
2555 : :
2556 : 2783 : return v;
2557 : : }
2558 : :
2559 : : /* POSIX methods */
2560 : :
2561 : :
2562 : : static PyObject *
2563 : 3204 : posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2564 : : int dir_fd, int follow_symlinks)
2565 : : {
2566 : : STRUCT_STAT st;
2567 : : int result;
2568 : :
2569 : : #ifdef HAVE_FSTATAT
2570 : 3204 : int fstatat_unavailable = 0;
2571 : : #endif
2572 : :
2573 : : #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2574 : : if (follow_symlinks_specified(function_name, follow_symlinks))
2575 : : return NULL;
2576 : : #endif
2577 : :
2578 [ + - + - ]: 6408 : if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2579 [ - + ]: 6408 : dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2580 : 3204 : fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2581 : 0 : return NULL;
2582 : :
2583 : 3204 : Py_BEGIN_ALLOW_THREADS
2584 [ - + ]: 3204 : if (path->fd != -1)
2585 : 0 : result = FSTAT(path->fd, &st);
2586 : : #ifdef MS_WINDOWS
2587 : : else if (follow_symlinks)
2588 : : result = win32_stat(path->wide, &st);
2589 : : else
2590 : : result = win32_lstat(path->wide, &st);
2591 : : #else
2592 : : else
2593 : : #if defined(HAVE_LSTAT)
2594 [ + + + - ]: 3204 : if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2595 : 83 : result = LSTAT(path->narrow, &st);
2596 : : else
2597 : : #endif /* HAVE_LSTAT */
2598 : : #ifdef HAVE_FSTATAT
2599 [ + - - + ]: 3121 : if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2600 : 0 : if (HAVE_FSTATAT_RUNTIME) {
2601 [ # # ]: 0 : result = fstatat(dir_fd, path->narrow, &st,
2602 : : follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2603 : :
2604 : : } else {
2605 : : fstatat_unavailable = 1;
2606 : : }
2607 : : } else
2608 : : #endif /* HAVE_FSTATAT */
2609 : 3121 : result = STAT(path->narrow, &st);
2610 : : #endif /* MS_WINDOWS */
2611 : 3204 : Py_END_ALLOW_THREADS
2612 : :
2613 : : #ifdef HAVE_FSTATAT
2614 [ - + ]: 3204 : if (fstatat_unavailable) {
2615 : 0 : argument_unavailable_error("stat", "dir_fd");
2616 : 0 : return NULL;
2617 : : }
2618 : : #endif
2619 : :
2620 [ + + ]: 3204 : if (result != 0) {
2621 : 422 : return path_error(path);
2622 : : }
2623 : :
2624 : 2782 : return _pystat_fromstructstat(module, &st);
2625 : : }
2626 : :
2627 : : /*[python input]
2628 : :
2629 : : for s in """
2630 : :
2631 : : FACCESSAT
2632 : : FCHMODAT
2633 : : FCHOWNAT
2634 : : FSTATAT
2635 : : LINKAT
2636 : : MKDIRAT
2637 : : MKFIFOAT
2638 : : MKNODAT
2639 : : OPENAT
2640 : : READLINKAT
2641 : : SYMLINKAT
2642 : : UNLINKAT
2643 : :
2644 : : """.strip().split():
2645 : : s = s.strip()
2646 : : print("""
2647 : : #ifdef HAVE_{s}
2648 : : #define {s}_DIR_FD_CONVERTER dir_fd_converter
2649 : : #else
2650 : : #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2651 : : #endif
2652 : : """.rstrip().format(s=s))
2653 : :
2654 : : for s in """
2655 : :
2656 : : FCHDIR
2657 : : FCHMOD
2658 : : FCHOWN
2659 : : FDOPENDIR
2660 : : FEXECVE
2661 : : FPATHCONF
2662 : : FSTATVFS
2663 : : FTRUNCATE
2664 : :
2665 : : """.strip().split():
2666 : : s = s.strip()
2667 : : print("""
2668 : : #ifdef HAVE_{s}
2669 : : #define PATH_HAVE_{s} 1
2670 : : #else
2671 : : #define PATH_HAVE_{s} 0
2672 : : #endif
2673 : :
2674 : : """.rstrip().format(s=s))
2675 : : [python start generated code]*/
2676 : :
2677 : : #ifdef HAVE_FACCESSAT
2678 : : #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2679 : : #else
2680 : : #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2681 : : #endif
2682 : :
2683 : : #ifdef HAVE_FCHMODAT
2684 : : #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2685 : : #else
2686 : : #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2687 : : #endif
2688 : :
2689 : : #ifdef HAVE_FCHOWNAT
2690 : : #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2691 : : #else
2692 : : #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2693 : : #endif
2694 : :
2695 : : #ifdef HAVE_FSTATAT
2696 : : #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2697 : : #else
2698 : : #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2699 : : #endif
2700 : :
2701 : : #ifdef HAVE_LINKAT
2702 : : #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2703 : : #else
2704 : : #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2705 : : #endif
2706 : :
2707 : : #ifdef HAVE_MKDIRAT
2708 : : #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2709 : : #else
2710 : : #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2711 : : #endif
2712 : :
2713 : : #ifdef HAVE_MKFIFOAT
2714 : : #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2715 : : #else
2716 : : #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2717 : : #endif
2718 : :
2719 : : #ifdef HAVE_MKNODAT
2720 : : #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2721 : : #else
2722 : : #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2723 : : #endif
2724 : :
2725 : : #ifdef HAVE_OPENAT
2726 : : #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2727 : : #else
2728 : : #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2729 : : #endif
2730 : :
2731 : : #ifdef HAVE_READLINKAT
2732 : : #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2733 : : #else
2734 : : #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2735 : : #endif
2736 : :
2737 : : #ifdef HAVE_SYMLINKAT
2738 : : #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2739 : : #else
2740 : : #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2741 : : #endif
2742 : :
2743 : : #ifdef HAVE_UNLINKAT
2744 : : #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2745 : : #else
2746 : : #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2747 : : #endif
2748 : :
2749 : : #ifdef HAVE_FCHDIR
2750 : : #define PATH_HAVE_FCHDIR 1
2751 : : #else
2752 : : #define PATH_HAVE_FCHDIR 0
2753 : : #endif
2754 : :
2755 : : #ifdef HAVE_FCHMOD
2756 : : #define PATH_HAVE_FCHMOD 1
2757 : : #else
2758 : : #define PATH_HAVE_FCHMOD 0
2759 : : #endif
2760 : :
2761 : : #ifdef HAVE_FCHOWN
2762 : : #define PATH_HAVE_FCHOWN 1
2763 : : #else
2764 : : #define PATH_HAVE_FCHOWN 0
2765 : : #endif
2766 : :
2767 : : #ifdef HAVE_FDOPENDIR
2768 : : #define PATH_HAVE_FDOPENDIR 1
2769 : : #else
2770 : : #define PATH_HAVE_FDOPENDIR 0
2771 : : #endif
2772 : :
2773 : : #ifdef HAVE_FEXECVE
2774 : : #define PATH_HAVE_FEXECVE 1
2775 : : #else
2776 : : #define PATH_HAVE_FEXECVE 0
2777 : : #endif
2778 : :
2779 : : #ifdef HAVE_FPATHCONF
2780 : : #define PATH_HAVE_FPATHCONF 1
2781 : : #else
2782 : : #define PATH_HAVE_FPATHCONF 0
2783 : : #endif
2784 : :
2785 : : #ifdef HAVE_FSTATVFS
2786 : : #define PATH_HAVE_FSTATVFS 1
2787 : : #else
2788 : : #define PATH_HAVE_FSTATVFS 0
2789 : : #endif
2790 : :
2791 : : #ifdef HAVE_FTRUNCATE
2792 : : #define PATH_HAVE_FTRUNCATE 1
2793 : : #else
2794 : : #define PATH_HAVE_FTRUNCATE 0
2795 : : #endif
2796 : : /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2797 : :
2798 : : #ifdef MS_WINDOWS
2799 : : #undef PATH_HAVE_FTRUNCATE
2800 : : #define PATH_HAVE_FTRUNCATE 1
2801 : : #endif
2802 : :
2803 : : /*[python input]
2804 : :
2805 : : class path_t_converter(CConverter):
2806 : :
2807 : : type = "path_t"
2808 : : impl_by_reference = True
2809 : : parse_by_reference = True
2810 : :
2811 : : converter = 'path_converter'
2812 : :
2813 : : def converter_init(self, *, allow_fd=False, nullable=False):
2814 : : # right now path_t doesn't support default values.
2815 : : # to support a default value, you'll need to override initialize().
2816 : : if self.default not in (unspecified, None):
2817 : : fail("Can't specify a default to the path_t converter!")
2818 : :
2819 : : if self.c_default not in (None, 'Py_None'):
2820 : : raise RuntimeError("Can't specify a c_default to the path_t converter!")
2821 : :
2822 : : self.nullable = nullable
2823 : : self.allow_fd = allow_fd
2824 : :
2825 : : def pre_render(self):
2826 : : def strify(value):
2827 : : if isinstance(value, str):
2828 : : return value
2829 : : return str(int(bool(value)))
2830 : :
2831 : : # add self.py_name here when merging with posixmodule conversion
2832 : : self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2833 : : self.function.name,
2834 : : self.name,
2835 : : strify(self.nullable),
2836 : : strify(self.allow_fd),
2837 : : )
2838 : :
2839 : : def cleanup(self):
2840 : : return "path_cleanup(&" + self.name + ");\n"
2841 : :
2842 : :
2843 : : class dir_fd_converter(CConverter):
2844 : : type = 'int'
2845 : :
2846 : : def converter_init(self, requires=None):
2847 : : if self.default in (unspecified, None):
2848 : : self.c_default = 'DEFAULT_DIR_FD'
2849 : : if isinstance(requires, str):
2850 : : self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2851 : : else:
2852 : : self.converter = 'dir_fd_converter'
2853 : :
2854 : : class uid_t_converter(CConverter):
2855 : : type = "uid_t"
2856 : : converter = '_Py_Uid_Converter'
2857 : :
2858 : : class gid_t_converter(CConverter):
2859 : : type = "gid_t"
2860 : : converter = '_Py_Gid_Converter'
2861 : :
2862 : : class dev_t_converter(CConverter):
2863 : : type = 'dev_t'
2864 : : converter = '_Py_Dev_Converter'
2865 : :
2866 : : class dev_t_return_converter(unsigned_long_return_converter):
2867 : : type = 'dev_t'
2868 : : conversion_fn = '_PyLong_FromDev'
2869 : : unsigned_cast = '(dev_t)'
2870 : :
2871 : : class FSConverter_converter(CConverter):
2872 : : type = 'PyObject *'
2873 : : converter = 'PyUnicode_FSConverter'
2874 : : def converter_init(self):
2875 : : if self.default is not unspecified:
2876 : : fail("FSConverter_converter does not support default values")
2877 : : self.c_default = 'NULL'
2878 : :
2879 : : def cleanup(self):
2880 : : return "Py_XDECREF(" + self.name + ");\n"
2881 : :
2882 : : class pid_t_converter(CConverter):
2883 : : type = 'pid_t'
2884 : : format_unit = '" _Py_PARSE_PID "'
2885 : :
2886 : : class idtype_t_converter(int_converter):
2887 : : type = 'idtype_t'
2888 : :
2889 : : class id_t_converter(CConverter):
2890 : : type = 'id_t'
2891 : : format_unit = '" _Py_PARSE_PID "'
2892 : :
2893 : : class intptr_t_converter(CConverter):
2894 : : type = 'intptr_t'
2895 : : format_unit = '" _Py_PARSE_INTPTR "'
2896 : :
2897 : : class Py_off_t_converter(CConverter):
2898 : : type = 'Py_off_t'
2899 : : converter = 'Py_off_t_converter'
2900 : :
2901 : : class Py_off_t_return_converter(long_return_converter):
2902 : : type = 'Py_off_t'
2903 : : conversion_fn = 'PyLong_FromPy_off_t'
2904 : :
2905 : : class path_confname_converter(CConverter):
2906 : : type="int"
2907 : : converter="conv_path_confname"
2908 : :
2909 : : class confstr_confname_converter(path_confname_converter):
2910 : : converter='conv_confstr_confname'
2911 : :
2912 : : class sysconf_confname_converter(path_confname_converter):
2913 : : converter="conv_sysconf_confname"
2914 : :
2915 : : [python start generated code]*/
2916 : : /*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/
2917 : :
2918 : : /*[clinic input]
2919 : :
2920 : : os.stat
2921 : :
2922 : : path : path_t(allow_fd=True)
2923 : : Path to be examined; can be string, bytes, a path-like object or
2924 : : open-file-descriptor int.
2925 : :
2926 : : *
2927 : :
2928 : : dir_fd : dir_fd(requires='fstatat') = None
2929 : : If not None, it should be a file descriptor open to a directory,
2930 : : and path should be a relative string; path will then be relative to
2931 : : that directory.
2932 : :
2933 : : follow_symlinks: bool = True
2934 : : If False, and the last element of the path is a symbolic link,
2935 : : stat will examine the symbolic link itself instead of the file
2936 : : the link points to.
2937 : :
2938 : : Perform a stat system call on the given path.
2939 : :
2940 : : dir_fd and follow_symlinks may not be implemented
2941 : : on your platform. If they are unavailable, using them will raise a
2942 : : NotImplementedError.
2943 : :
2944 : : It's an error to use dir_fd or follow_symlinks when specifying path as
2945 : : an open file descriptor.
2946 : :
2947 : : [clinic start generated code]*/
2948 : :
2949 : : static PyObject *
2950 : 3121 : os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2951 : : /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2952 : : {
2953 : 3121 : return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
2954 : : }
2955 : :
2956 : :
2957 : : /*[clinic input]
2958 : : os.lstat
2959 : :
2960 : : path : path_t
2961 : :
2962 : : *
2963 : :
2964 : : dir_fd : dir_fd(requires='fstatat') = None
2965 : :
2966 : : Perform a stat system call on the given path, without following symbolic links.
2967 : :
2968 : : Like stat(), but do not follow symbolic links.
2969 : : Equivalent to stat(path, follow_symlinks=False).
2970 : : [clinic start generated code]*/
2971 : :
2972 : : static PyObject *
2973 : 83 : os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2974 : : /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2975 : : {
2976 : 83 : int follow_symlinks = 0;
2977 : 83 : return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
2978 : : }
2979 : :
2980 : :
2981 : : /*[clinic input]
2982 : : os.access -> bool
2983 : :
2984 : : path: path_t
2985 : : Path to be tested; can be string, bytes, or a path-like object.
2986 : :
2987 : : mode: int
2988 : : Operating-system mode bitfield. Can be F_OK to test existence,
2989 : : or the inclusive-OR of R_OK, W_OK, and X_OK.
2990 : :
2991 : : *
2992 : :
2993 : : dir_fd : dir_fd(requires='faccessat') = None
2994 : : If not None, it should be a file descriptor open to a directory,
2995 : : and path should be relative; path will then be relative to that
2996 : : directory.
2997 : :
2998 : : effective_ids: bool = False
2999 : : If True, access will use the effective uid/gid instead of
3000 : : the real uid/gid.
3001 : :
3002 : : follow_symlinks: bool = True
3003 : : If False, and the last element of the path is a symbolic link,
3004 : : access will examine the symbolic link itself instead of the file
3005 : : the link points to.
3006 : :
3007 : : Use the real uid/gid to test for access to a path.
3008 : :
3009 : : {parameters}
3010 : : dir_fd, effective_ids, and follow_symlinks may not be implemented
3011 : : on your platform. If they are unavailable, using them will raise a
3012 : : NotImplementedError.
3013 : :
3014 : : Note that most operations will use the effective uid/gid, therefore this
3015 : : routine can be used in a suid/sgid environment to test if the invoking user
3016 : : has the specified access to the path.
3017 : :
3018 : : [clinic start generated code]*/
3019 : :
3020 : : static int
3021 : 0 : os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3022 : : int effective_ids, int follow_symlinks)
3023 : : /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
3024 : : {
3025 : : int return_value;
3026 : :
3027 : : #ifdef MS_WINDOWS
3028 : : DWORD attr;
3029 : : #else
3030 : : int result;
3031 : : #endif
3032 : :
3033 : : #ifdef HAVE_FACCESSAT
3034 : 0 : int faccessat_unavailable = 0;
3035 : : #endif
3036 : :
3037 : : #ifndef HAVE_FACCESSAT
3038 : : if (follow_symlinks_specified("access", follow_symlinks))
3039 : : return -1;
3040 : :
3041 : : if (effective_ids) {
3042 : : argument_unavailable_error("access", "effective_ids");
3043 : : return -1;
3044 : : }
3045 : : #endif
3046 : :
3047 : : #ifdef MS_WINDOWS
3048 : : Py_BEGIN_ALLOW_THREADS
3049 : : attr = GetFileAttributesW(path->wide);
3050 : : Py_END_ALLOW_THREADS
3051 : :
3052 : : /*
3053 : : * Access is possible if
3054 : : * * we didn't get a -1, and
3055 : : * * write access wasn't requested,
3056 : : * * or the file isn't read-only,
3057 : : * * or it's a directory.
3058 : : * (Directories cannot be read-only on Windows.)
3059 : : */
3060 : : return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3061 : : (!(mode & 2) ||
3062 : : !(attr & FILE_ATTRIBUTE_READONLY) ||
3063 : : (attr & FILE_ATTRIBUTE_DIRECTORY));
3064 : : #else
3065 : :
3066 : 0 : Py_BEGIN_ALLOW_THREADS
3067 : : #ifdef HAVE_FACCESSAT
3068 [ # # # # ]: 0 : if ((dir_fd != DEFAULT_DIR_FD) ||
3069 [ # # ]: 0 : effective_ids ||
3070 : : !follow_symlinks) {
3071 : :
3072 : 0 : if (HAVE_FACCESSAT_RUNTIME) {
3073 : 0 : int flags = 0;
3074 [ # # ]: 0 : if (!follow_symlinks)
3075 : 0 : flags |= AT_SYMLINK_NOFOLLOW;
3076 [ # # ]: 0 : if (effective_ids)
3077 : 0 : flags |= AT_EACCESS;
3078 : 0 : result = faccessat(dir_fd, path->narrow, mode, flags);
3079 : : } else {
3080 : : faccessat_unavailable = 1;
3081 : : }
3082 : : }
3083 : : else
3084 : : #endif
3085 : 0 : result = access(path->narrow, mode);
3086 : 0 : Py_END_ALLOW_THREADS
3087 : :
3088 : : #ifdef HAVE_FACCESSAT
3089 [ # # ]: 0 : if (faccessat_unavailable) {
3090 [ # # ]: 0 : if (dir_fd != DEFAULT_DIR_FD) {
3091 : 0 : argument_unavailable_error("access", "dir_fd");
3092 : 0 : return -1;
3093 : : }
3094 [ # # ]: 0 : if (follow_symlinks_specified("access", follow_symlinks))
3095 : 0 : return -1;
3096 : :
3097 [ # # ]: 0 : if (effective_ids) {
3098 : 0 : argument_unavailable_error("access", "effective_ids");
3099 : 0 : return -1;
3100 : : }
3101 : : /* should be unreachable */
3102 : 0 : return -1;
3103 : : }
3104 : : #endif
3105 : 0 : return_value = !result;
3106 : : #endif
3107 : :
3108 : 0 : return return_value;
3109 : : }
3110 : :
3111 : : #ifndef F_OK
3112 : : #define F_OK 0
3113 : : #endif
3114 : : #ifndef R_OK
3115 : : #define R_OK 4
3116 : : #endif
3117 : : #ifndef W_OK
3118 : : #define W_OK 2
3119 : : #endif
3120 : : #ifndef X_OK
3121 : : #define X_OK 1
3122 : : #endif
3123 : :
3124 : :
3125 : : #ifdef HAVE_TTYNAME
3126 : : /*[clinic input]
3127 : : os.ttyname
3128 : :
3129 : : fd: int
3130 : : Integer file descriptor handle.
3131 : :
3132 : : /
3133 : :
3134 : : Return the name of the terminal device connected to 'fd'.
3135 : : [clinic start generated code]*/
3136 : :
3137 : : static PyObject *
3138 : 0 : os_ttyname_impl(PyObject *module, int fd)
3139 : : /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3140 : : {
3141 : :
3142 : 0 : long size = sysconf(_SC_TTY_NAME_MAX);
3143 [ # # ]: 0 : if (size == -1) {
3144 : 0 : return posix_error();
3145 : : }
3146 : 0 : char *buffer = (char *)PyMem_RawMalloc(size);
3147 [ # # ]: 0 : if (buffer == NULL) {
3148 : 0 : return PyErr_NoMemory();
3149 : : }
3150 : 0 : int ret = ttyname_r(fd, buffer, size);
3151 [ # # ]: 0 : if (ret != 0) {
3152 : 0 : PyMem_RawFree(buffer);
3153 : 0 : errno = ret;
3154 : 0 : return posix_error();
3155 : : }
3156 : 0 : PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3157 : 0 : PyMem_RawFree(buffer);
3158 : 0 : return res;
3159 : : }
3160 : : #endif
3161 : :
3162 : : #ifdef HAVE_CTERMID
3163 : : /*[clinic input]
3164 : : os.ctermid
3165 : :
3166 : : Return the name of the controlling terminal for this process.
3167 : : [clinic start generated code]*/
3168 : :
3169 : : static PyObject *
3170 : 0 : os_ctermid_impl(PyObject *module)
3171 : : /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3172 : : {
3173 : : char *ret;
3174 : : char buffer[L_ctermid];
3175 : :
3176 : : #ifdef USE_CTERMID_R
3177 : : ret = ctermid_r(buffer);
3178 : : #else
3179 : 0 : ret = ctermid(buffer);
3180 : : #endif
3181 [ # # ]: 0 : if (ret == NULL)
3182 : 0 : return posix_error();
3183 : 0 : return PyUnicode_DecodeFSDefault(buffer);
3184 : : }
3185 : : #endif /* HAVE_CTERMID */
3186 : :
3187 : :
3188 : : /*[clinic input]
3189 : : os.chdir
3190 : :
3191 : : path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3192 : :
3193 : : Change the current working directory to the specified path.
3194 : :
3195 : : path may always be specified as a string.
3196 : : On some platforms, path may also be specified as an open file descriptor.
3197 : : If this functionality is unavailable, using it raises an exception.
3198 : : [clinic start generated code]*/
3199 : :
3200 : : static PyObject *
3201 : 2 : os_chdir_impl(PyObject *module, path_t *path)
3202 : : /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3203 : : {
3204 : : int result;
3205 : :
3206 [ - + ]: 2 : if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3207 : 0 : return NULL;
3208 : : }
3209 : :
3210 : 2 : Py_BEGIN_ALLOW_THREADS
3211 : : #ifdef MS_WINDOWS
3212 : : /* on unix, success = 0, on windows, success = !0 */
3213 : : result = !win32_wchdir(path->wide);
3214 : : #else
3215 : : #ifdef HAVE_FCHDIR
3216 [ - + ]: 2 : if (path->fd != -1)
3217 : 0 : result = fchdir(path->fd);
3218 : : else
3219 : : #endif
3220 : 2 : result = chdir(path->narrow);
3221 : : #endif
3222 : 2 : Py_END_ALLOW_THREADS
3223 : :
3224 [ - + ]: 2 : if (result) {
3225 : 0 : return path_error(path);
3226 : : }
3227 : :
3228 : 2 : Py_RETURN_NONE;
3229 : : }
3230 : :
3231 : :
3232 : : #ifdef HAVE_FCHDIR
3233 : : /*[clinic input]
3234 : : os.fchdir
3235 : :
3236 : : fd: fildes
3237 : :
3238 : : Change to the directory of the given file descriptor.
3239 : :
3240 : : fd must be opened on a directory, not a file.
3241 : : Equivalent to os.chdir(fd).
3242 : :
3243 : : [clinic start generated code]*/
3244 : :
3245 : : static PyObject *
3246 : 0 : os_fchdir_impl(PyObject *module, int fd)
3247 : : /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3248 : : {
3249 [ # # ]: 0 : if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3250 : 0 : return NULL;
3251 : : }
3252 : 0 : return posix_fildes_fd(fd, fchdir);
3253 : : }
3254 : : #endif /* HAVE_FCHDIR */
3255 : :
3256 : :
3257 : : /*[clinic input]
3258 : : os.chmod
3259 : :
3260 : : path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3261 : : Path to be modified. May always be specified as a str, bytes, or a path-like object.
3262 : : On some platforms, path may also be specified as an open file descriptor.
3263 : : If this functionality is unavailable, using it raises an exception.
3264 : :
3265 : : mode: int
3266 : : Operating-system mode bitfield.
3267 : : Be careful when using number literals for *mode*. The conventional UNIX notation for
3268 : : numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
3269 : : Python.
3270 : :
3271 : : *
3272 : :
3273 : : dir_fd : dir_fd(requires='fchmodat') = None
3274 : : If not None, it should be a file descriptor open to a directory,
3275 : : and path should be relative; path will then be relative to that
3276 : : directory.
3277 : :
3278 : : follow_symlinks: bool = True
3279 : : If False, and the last element of the path is a symbolic link,
3280 : : chmod will modify the symbolic link itself instead of the file
3281 : : the link points to.
3282 : :
3283 : : Change the access permissions of a file.
3284 : :
3285 : : It is an error to use dir_fd or follow_symlinks when specifying path as
3286 : : an open file descriptor.
3287 : : dir_fd and follow_symlinks may not be implemented on your platform.
3288 : : If they are unavailable, using them will raise a NotImplementedError.
3289 : :
3290 : : [clinic start generated code]*/
3291 : :
3292 : : static PyObject *
3293 : 0 : os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3294 : : int follow_symlinks)
3295 : : /*[clinic end generated code: output=5cf6a94915cc7bff input=674a14bc998de09d]*/
3296 : : {
3297 : : int result;
3298 : :
3299 : : #ifdef MS_WINDOWS
3300 : : DWORD attr;
3301 : : #endif
3302 : :
3303 : : #ifdef HAVE_FCHMODAT
3304 : 0 : int fchmodat_nofollow_unsupported = 0;
3305 : 0 : int fchmodat_unsupported = 0;
3306 : : #endif
3307 : :
3308 : : #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
3309 : : if (follow_symlinks_specified("chmod", follow_symlinks))
3310 : : return NULL;
3311 : : #endif
3312 : :
3313 [ # # # # ]: 0 : if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3314 : : dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3315 : 0 : return NULL;
3316 : : }
3317 : :
3318 : : #ifdef MS_WINDOWS
3319 : : Py_BEGIN_ALLOW_THREADS
3320 : : attr = GetFileAttributesW(path->wide);
3321 : : if (attr == INVALID_FILE_ATTRIBUTES)
3322 : : result = 0;
3323 : : else {
3324 : : if (mode & _S_IWRITE)
3325 : : attr &= ~FILE_ATTRIBUTE_READONLY;
3326 : : else
3327 : : attr |= FILE_ATTRIBUTE_READONLY;
3328 : : result = SetFileAttributesW(path->wide, attr);
3329 : : }
3330 : : Py_END_ALLOW_THREADS
3331 : :
3332 : : if (!result) {
3333 : : return path_error(path);
3334 : : }
3335 : : #else /* MS_WINDOWS */
3336 : 0 : Py_BEGIN_ALLOW_THREADS
3337 : : #ifdef HAVE_FCHMOD
3338 [ # # ]: 0 : if (path->fd != -1)
3339 : 0 : result = fchmod(path->fd, mode);
3340 : : else
3341 : : #endif /* HAVE_CHMOD */
3342 : : #ifdef HAVE_LCHMOD
3343 : : if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3344 : : result = lchmod(path->narrow, mode);
3345 : : else
3346 : : #endif /* HAVE_LCHMOD */
3347 : : #ifdef HAVE_FCHMODAT
3348 [ # # # # ]: 0 : if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3349 : 0 : if (HAVE_FCHMODAT_RUNTIME) {
3350 : : /*
3351 : : * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3352 : : * The documentation specifically shows how to use it,
3353 : : * and then says it isn't implemented yet.
3354 : : * (true on linux with glibc 2.15, and openindiana 3.x)
3355 : : *
3356 : : * Once it is supported, os.chmod will automatically
3357 : : * support dir_fd and follow_symlinks=False. (Hopefully.)
3358 : : * Until then, we need to be careful what exception we raise.
3359 : : */
3360 [ # # ]: 0 : result = fchmodat(dir_fd, path->narrow, mode,
3361 : : follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3362 : : /*
3363 : : * But wait! We can't throw the exception without allowing threads,
3364 : : * and we can't do that in this nested scope. (Macro trickery, sigh.)
3365 : : */
3366 : 0 : fchmodat_nofollow_unsupported =
3367 : 0 : result &&
3368 [ # # # # : 0 : ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
# # # # ]
3369 : : !follow_symlinks;
3370 : : } else {
3371 : : fchmodat_unsupported = 1;
3372 : : fchmodat_nofollow_unsupported = 1;
3373 : :
3374 : : result = -1;
3375 : : }
3376 : : }
3377 : : else
3378 : : #endif /* HAVE_FHCMODAT */
3379 : : {
3380 : : #ifdef HAVE_CHMOD
3381 : 0 : result = chmod(path->narrow, mode);
3382 : : #elif defined(__wasi__)
3383 : : // WASI SDK 15.0 does not support chmod.
3384 : : // Ignore missing syscall for now.
3385 : : result = 0;
3386 : : #else
3387 : : result = -1;
3388 : : errno = ENOSYS;
3389 : : #endif
3390 : : }
3391 : 0 : Py_END_ALLOW_THREADS
3392 : :
3393 [ # # ]: 0 : if (result) {
3394 : : #ifdef HAVE_FCHMODAT
3395 [ # # ]: 0 : if (fchmodat_unsupported) {
3396 [ # # ]: 0 : if (dir_fd != DEFAULT_DIR_FD) {
3397 : 0 : argument_unavailable_error("chmod", "dir_fd");
3398 : 0 : return NULL;
3399 : : }
3400 : : }
3401 : :
3402 [ # # ]: 0 : if (fchmodat_nofollow_unsupported) {
3403 [ # # ]: 0 : if (dir_fd != DEFAULT_DIR_FD)
3404 : 0 : dir_fd_and_follow_symlinks_invalid("chmod",
3405 : : dir_fd, follow_symlinks);
3406 : : else
3407 : 0 : follow_symlinks_specified("chmod", follow_symlinks);
3408 : 0 : return NULL;
3409 : : }
3410 : : else
3411 : : #endif /* HAVE_FCHMODAT */
3412 : 0 : return path_error(path);
3413 : : }
3414 : : #endif /* MS_WINDOWS */
3415 : :
3416 : 0 : Py_RETURN_NONE;
3417 : : }
3418 : :
3419 : :
3420 : : #ifdef HAVE_FCHMOD
3421 : : /*[clinic input]
3422 : : os.fchmod
3423 : :
3424 : : fd: int
3425 : : The file descriptor of the file to be modified.
3426 : : mode: int
3427 : : Operating-system mode bitfield.
3428 : : Be careful when using number literals for *mode*. The conventional UNIX notation for
3429 : : numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
3430 : : Python.
3431 : :
3432 : : Change the access permissions of the file given by file descriptor fd.
3433 : :
3434 : : Equivalent to os.chmod(fd, mode).
3435 : : [clinic start generated code]*/
3436 : :
3437 : : static PyObject *
3438 : 0 : os_fchmod_impl(PyObject *module, int fd, int mode)
3439 : : /*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/
3440 : : {
3441 : : int res;
3442 : 0 : int async_err = 0;
3443 : :
3444 [ # # ]: 0 : if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3445 : 0 : return NULL;
3446 : : }
3447 : :
3448 : : do {
3449 : 0 : Py_BEGIN_ALLOW_THREADS
3450 : 0 : res = fchmod(fd, mode);
3451 : 0 : Py_END_ALLOW_THREADS
3452 [ # # # # : 0 : } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
3453 [ # # ]: 0 : if (res != 0)
3454 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
3455 : :
3456 : 0 : Py_RETURN_NONE;
3457 : : }
3458 : : #endif /* HAVE_FCHMOD */
3459 : :
3460 : :
3461 : : #ifdef HAVE_LCHMOD
3462 : : /*[clinic input]
3463 : : os.lchmod
3464 : :
3465 : : path: path_t
3466 : : mode: int
3467 : :
3468 : : Change the access permissions of a file, without following symbolic links.
3469 : :
3470 : : If path is a symlink, this affects the link itself rather than the target.
3471 : : Equivalent to chmod(path, mode, follow_symlinks=False)."
3472 : : [clinic start generated code]*/
3473 : :
3474 : : static PyObject *
3475 : : os_lchmod_impl(PyObject *module, path_t *path, int mode)
3476 : : /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3477 : : {
3478 : : int res;
3479 : : if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3480 : : return NULL;
3481 : : }
3482 : : Py_BEGIN_ALLOW_THREADS
3483 : : res = lchmod(path->narrow, mode);
3484 : : Py_END_ALLOW_THREADS
3485 : : if (res < 0) {
3486 : : path_error(path);
3487 : : return NULL;
3488 : : }
3489 : : Py_RETURN_NONE;
3490 : : }
3491 : : #endif /* HAVE_LCHMOD */
3492 : :
3493 : :
3494 : : #ifdef HAVE_CHFLAGS
3495 : : /*[clinic input]
3496 : : os.chflags
3497 : :
3498 : : path: path_t
3499 : : flags: unsigned_long(bitwise=True)
3500 : : follow_symlinks: bool=True
3501 : :
3502 : : Set file flags.
3503 : :
3504 : : If follow_symlinks is False, and the last element of the path is a symbolic
3505 : : link, chflags will change flags on the symbolic link itself instead of the
3506 : : file the link points to.
3507 : : follow_symlinks may not be implemented on your platform. If it is
3508 : : unavailable, using it will raise a NotImplementedError.
3509 : :
3510 : : [clinic start generated code]*/
3511 : :
3512 : : static PyObject *
3513 : : os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3514 : : int follow_symlinks)
3515 : : /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3516 : : {
3517 : : int result;
3518 : :
3519 : : #ifndef HAVE_LCHFLAGS
3520 : : if (follow_symlinks_specified("chflags", follow_symlinks))
3521 : : return NULL;
3522 : : #endif
3523 : :
3524 : : if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3525 : : return NULL;
3526 : : }
3527 : :
3528 : : Py_BEGIN_ALLOW_THREADS
3529 : : #ifdef HAVE_LCHFLAGS
3530 : : if (!follow_symlinks)
3531 : : result = lchflags(path->narrow, flags);
3532 : : else
3533 : : #endif
3534 : : result = chflags(path->narrow, flags);
3535 : : Py_END_ALLOW_THREADS
3536 : :
3537 : : if (result)
3538 : : return path_error(path);
3539 : :
3540 : : Py_RETURN_NONE;
3541 : : }
3542 : : #endif /* HAVE_CHFLAGS */
3543 : :
3544 : :
3545 : : #ifdef HAVE_LCHFLAGS
3546 : : /*[clinic input]
3547 : : os.lchflags
3548 : :
3549 : : path: path_t
3550 : : flags: unsigned_long(bitwise=True)
3551 : :
3552 : : Set file flags.
3553 : :
3554 : : This function will not follow symbolic links.
3555 : : Equivalent to chflags(path, flags, follow_symlinks=False).
3556 : : [clinic start generated code]*/
3557 : :
3558 : : static PyObject *
3559 : : os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3560 : : /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3561 : : {
3562 : : int res;
3563 : : if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3564 : : return NULL;
3565 : : }
3566 : : Py_BEGIN_ALLOW_THREADS
3567 : : res = lchflags(path->narrow, flags);
3568 : : Py_END_ALLOW_THREADS
3569 : : if (res < 0) {
3570 : : return path_error(path);
3571 : : }
3572 : : Py_RETURN_NONE;
3573 : : }
3574 : : #endif /* HAVE_LCHFLAGS */
3575 : :
3576 : :
3577 : : #ifdef HAVE_CHROOT
3578 : : /*[clinic input]
3579 : : os.chroot
3580 : : path: path_t
3581 : :
3582 : : Change root directory to path.
3583 : :
3584 : : [clinic start generated code]*/
3585 : :
3586 : : static PyObject *
3587 : 0 : os_chroot_impl(PyObject *module, path_t *path)
3588 : : /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3589 : : {
3590 : : int res;
3591 : 0 : Py_BEGIN_ALLOW_THREADS
3592 : 0 : res = chroot(path->narrow);
3593 : 0 : Py_END_ALLOW_THREADS
3594 [ # # ]: 0 : if (res < 0)
3595 : 0 : return path_error(path);
3596 : 0 : Py_RETURN_NONE;
3597 : : }
3598 : : #endif /* HAVE_CHROOT */
3599 : :
3600 : :
3601 : : #ifdef HAVE_FSYNC
3602 : : /*[clinic input]
3603 : : os.fsync
3604 : :
3605 : : fd: fildes
3606 : :
3607 : : Force write of fd to disk.
3608 : : [clinic start generated code]*/
3609 : :
3610 : : static PyObject *
3611 : 0 : os_fsync_impl(PyObject *module, int fd)
3612 : : /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3613 : : {
3614 : 0 : return posix_fildes_fd(fd, fsync);
3615 : : }
3616 : : #endif /* HAVE_FSYNC */
3617 : :
3618 : :
3619 : : #ifdef HAVE_SYNC
3620 : : /*[clinic input]
3621 : : os.sync
3622 : :
3623 : : Force write of everything to disk.
3624 : : [clinic start generated code]*/
3625 : :
3626 : : static PyObject *
3627 : 0 : os_sync_impl(PyObject *module)
3628 : : /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3629 : : {
3630 : 0 : Py_BEGIN_ALLOW_THREADS
3631 : 0 : sync();
3632 : 0 : Py_END_ALLOW_THREADS
3633 : 0 : Py_RETURN_NONE;
3634 : : }
3635 : : #endif /* HAVE_SYNC */
3636 : :
3637 : :
3638 : : #ifdef HAVE_FDATASYNC
3639 : : #ifdef __hpux
3640 : : extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3641 : : #endif
3642 : :
3643 : : /*[clinic input]
3644 : : os.fdatasync
3645 : :
3646 : : fd: fildes
3647 : :
3648 : : Force write of fd to disk without forcing update of metadata.
3649 : : [clinic start generated code]*/
3650 : :
3651 : : static PyObject *
3652 : 0 : os_fdatasync_impl(PyObject *module, int fd)
3653 : : /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3654 : : {
3655 : 0 : return posix_fildes_fd(fd, fdatasync);
3656 : : }
3657 : : #endif /* HAVE_FDATASYNC */
3658 : :
3659 : :
3660 : : #ifdef HAVE_CHOWN
3661 : : /*[clinic input]
3662 : : os.chown
3663 : :
3664 : : path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3665 : : Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3666 : :
3667 : : uid: uid_t
3668 : :
3669 : : gid: gid_t
3670 : :
3671 : : *
3672 : :
3673 : : dir_fd : dir_fd(requires='fchownat') = None
3674 : : If not None, it should be a file descriptor open to a directory,
3675 : : and path should be relative; path will then be relative to that
3676 : : directory.
3677 : :
3678 : : follow_symlinks: bool = True
3679 : : If False, and the last element of the path is a symbolic link,
3680 : : stat will examine the symbolic link itself instead of the file
3681 : : the link points to.
3682 : :
3683 : : Change the owner and group id of path to the numeric uid and gid.\
3684 : :
3685 : : path may always be specified as a string.
3686 : : On some platforms, path may also be specified as an open file descriptor.
3687 : : If this functionality is unavailable, using it raises an exception.
3688 : : If dir_fd is not None, it should be a file descriptor open to a directory,
3689 : : and path should be relative; path will then be relative to that directory.
3690 : : If follow_symlinks is False, and the last element of the path is a symbolic
3691 : : link, chown will modify the symbolic link itself instead of the file the
3692 : : link points to.
3693 : : It is an error to use dir_fd or follow_symlinks when specifying path as
3694 : : an open file descriptor.
3695 : : dir_fd and follow_symlinks may not be implemented on your platform.
3696 : : If they are unavailable, using them will raise a NotImplementedError.
3697 : :
3698 : : [clinic start generated code]*/
3699 : :
3700 : : static PyObject *
3701 : 0 : os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3702 : : int dir_fd, int follow_symlinks)
3703 : : /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3704 : : {
3705 : : int result;
3706 : :
3707 : : #if defined(HAVE_FCHOWNAT)
3708 : 0 : int fchownat_unsupported = 0;
3709 : : #endif
3710 : :
3711 : : #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3712 : : if (follow_symlinks_specified("chown", follow_symlinks))
3713 : : return NULL;
3714 : : #endif
3715 [ # # # # ]: 0 : if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3716 : 0 : fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3717 : 0 : return NULL;
3718 : :
3719 [ # # # # ]: 0 : if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3720 : : dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3721 : 0 : return NULL;
3722 : : }
3723 : :
3724 : 0 : Py_BEGIN_ALLOW_THREADS
3725 : : #ifdef HAVE_FCHOWN
3726 [ # # ]: 0 : if (path->fd != -1)
3727 : 0 : result = fchown(path->fd, uid, gid);
3728 : : else
3729 : : #endif
3730 : : #ifdef HAVE_LCHOWN
3731 [ # # # # ]: 0 : if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3732 : 0 : result = lchown(path->narrow, uid, gid);
3733 : : else
3734 : : #endif
3735 : : #ifdef HAVE_FCHOWNAT
3736 [ # # # # ]: 0 : if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
3737 : 0 : if (HAVE_FCHOWNAT_RUNTIME) {
3738 [ # # ]: 0 : result = fchownat(dir_fd, path->narrow, uid, gid,
3739 : : follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3740 : : } else {
3741 : : fchownat_unsupported = 1;
3742 : : }
3743 : : } else
3744 : : #endif
3745 : 0 : result = chown(path->narrow, uid, gid);
3746 : 0 : Py_END_ALLOW_THREADS
3747 : :
3748 : : #ifdef HAVE_FCHOWNAT
3749 [ # # ]: 0 : if (fchownat_unsupported) {
3750 : : /* This would be incorrect if the current platform
3751 : : * doesn't support lchown.
3752 : : */
3753 : 0 : argument_unavailable_error(NULL, "dir_fd");
3754 : 0 : return NULL;
3755 : : }
3756 : : #endif
3757 : :
3758 [ # # ]: 0 : if (result)
3759 : 0 : return path_error(path);
3760 : :
3761 : 0 : Py_RETURN_NONE;
3762 : : }
3763 : : #endif /* HAVE_CHOWN */
3764 : :
3765 : :
3766 : : #ifdef HAVE_FCHOWN
3767 : : /*[clinic input]
3768 : : os.fchown
3769 : :
3770 : : fd: int
3771 : : uid: uid_t
3772 : : gid: gid_t
3773 : :
3774 : : Change the owner and group id of the file specified by file descriptor.
3775 : :
3776 : : Equivalent to os.chown(fd, uid, gid).
3777 : :
3778 : : [clinic start generated code]*/
3779 : :
3780 : : static PyObject *
3781 : 0 : os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3782 : : /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3783 : : {
3784 : : int res;
3785 : 0 : int async_err = 0;
3786 : :
3787 [ # # ]: 0 : if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
3788 : 0 : return NULL;
3789 : : }
3790 : :
3791 : : do {
3792 : 0 : Py_BEGIN_ALLOW_THREADS
3793 : 0 : res = fchown(fd, uid, gid);
3794 : 0 : Py_END_ALLOW_THREADS
3795 [ # # # # : 0 : } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
3796 [ # # ]: 0 : if (res != 0)
3797 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
3798 : :
3799 : 0 : Py_RETURN_NONE;
3800 : : }
3801 : : #endif /* HAVE_FCHOWN */
3802 : :
3803 : :
3804 : : #ifdef HAVE_LCHOWN
3805 : : /*[clinic input]
3806 : : os.lchown
3807 : :
3808 : : path : path_t
3809 : : uid: uid_t
3810 : : gid: gid_t
3811 : :
3812 : : Change the owner and group id of path to the numeric uid and gid.
3813 : :
3814 : : This function will not follow symbolic links.
3815 : : Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3816 : : [clinic start generated code]*/
3817 : :
3818 : : static PyObject *
3819 : 0 : os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3820 : : /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3821 : : {
3822 : : int res;
3823 [ # # ]: 0 : if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
3824 : 0 : return NULL;
3825 : : }
3826 : 0 : Py_BEGIN_ALLOW_THREADS
3827 : 0 : res = lchown(path->narrow, uid, gid);
3828 : 0 : Py_END_ALLOW_THREADS
3829 [ # # ]: 0 : if (res < 0) {
3830 : 0 : return path_error(path);
3831 : : }
3832 : 0 : Py_RETURN_NONE;
3833 : : }
3834 : : #endif /* HAVE_LCHOWN */
3835 : :
3836 : :
3837 : : static PyObject *
3838 : 96 : posix_getcwd(int use_bytes)
3839 : : {
3840 : : #ifdef MS_WINDOWS
3841 : : wchar_t wbuf[MAXPATHLEN];
3842 : : wchar_t *wbuf2 = wbuf;
3843 : : DWORD len;
3844 : :
3845 : : Py_BEGIN_ALLOW_THREADS
3846 : : len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3847 : : /* If the buffer is large enough, len does not include the
3848 : : terminating \0. If the buffer is too small, len includes
3849 : : the space needed for the terminator. */
3850 : : if (len >= Py_ARRAY_LENGTH(wbuf)) {
3851 : : if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3852 : : wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3853 : : }
3854 : : else {
3855 : : wbuf2 = NULL;
3856 : : }
3857 : : if (wbuf2) {
3858 : : len = GetCurrentDirectoryW(len, wbuf2);
3859 : : }
3860 : : }
3861 : : Py_END_ALLOW_THREADS
3862 : :
3863 : : if (!wbuf2) {
3864 : : PyErr_NoMemory();
3865 : : return NULL;
3866 : : }
3867 : : if (!len) {
3868 : : if (wbuf2 != wbuf)
3869 : : PyMem_RawFree(wbuf2);
3870 : : return PyErr_SetFromWindowsErr(0);
3871 : : }
3872 : :
3873 : : PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3874 : : if (wbuf2 != wbuf) {
3875 : : PyMem_RawFree(wbuf2);
3876 : : }
3877 : :
3878 : : if (use_bytes) {
3879 : : if (resobj == NULL) {
3880 : : return NULL;
3881 : : }
3882 : : Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3883 : : }
3884 : :
3885 : : return resobj;
3886 : : #else
3887 : 96 : const size_t chunk = 1024;
3888 : :
3889 : 96 : char *buf = NULL;
3890 : 96 : char *cwd = NULL;
3891 : 96 : size_t buflen = 0;
3892 : :
3893 : 96 : Py_BEGIN_ALLOW_THREADS
3894 : : do {
3895 : : char *newbuf;
3896 [ + - ]: 96 : if (buflen <= PY_SSIZE_T_MAX - chunk) {
3897 : 96 : buflen += chunk;
3898 : 96 : newbuf = PyMem_RawRealloc(buf, buflen);
3899 : : }
3900 : : else {
3901 : 0 : newbuf = NULL;
3902 : : }
3903 [ - + ]: 96 : if (newbuf == NULL) {
3904 : 0 : PyMem_RawFree(buf);
3905 : 0 : buf = NULL;
3906 : 0 : break;
3907 : : }
3908 : 96 : buf = newbuf;
3909 : :
3910 : 96 : cwd = getcwd(buf, buflen);
3911 [ - + - - ]: 96 : } while (cwd == NULL && errno == ERANGE);
3912 : 96 : Py_END_ALLOW_THREADS
3913 : :
3914 [ - + ]: 96 : if (buf == NULL) {
3915 : 0 : return PyErr_NoMemory();
3916 : : }
3917 [ - + ]: 96 : if (cwd == NULL) {
3918 : 0 : PyMem_RawFree(buf);
3919 : 0 : return posix_error();
3920 : : }
3921 : :
3922 : : PyObject *obj;
3923 [ - + ]: 96 : if (use_bytes) {
3924 : 0 : obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3925 : : }
3926 : : else {
3927 : 96 : obj = PyUnicode_DecodeFSDefault(buf);
3928 : : }
3929 : 96 : PyMem_RawFree(buf);
3930 : :
3931 : 96 : return obj;
3932 : : #endif /* !MS_WINDOWS */
3933 : : }
3934 : :
3935 : :
3936 : : /*[clinic input]
3937 : : os.getcwd
3938 : :
3939 : : Return a unicode string representing the current working directory.
3940 : : [clinic start generated code]*/
3941 : :
3942 : : static PyObject *
3943 : 96 : os_getcwd_impl(PyObject *module)
3944 : : /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3945 : : {
3946 : 96 : return posix_getcwd(0);
3947 : : }
3948 : :
3949 : :
3950 : : /*[clinic input]
3951 : : os.getcwdb
3952 : :
3953 : : Return a bytes string representing the current working directory.
3954 : : [clinic start generated code]*/
3955 : :
3956 : : static PyObject *
3957 : 0 : os_getcwdb_impl(PyObject *module)
3958 : : /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3959 : : {
3960 : 0 : return posix_getcwd(1);
3961 : : }
3962 : :
3963 : :
3964 : : #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3965 : : #define HAVE_LINK 1
3966 : : #endif
3967 : :
3968 : : #ifdef HAVE_LINK
3969 : : /*[clinic input]
3970 : :
3971 : : os.link
3972 : :
3973 : : src : path_t
3974 : : dst : path_t
3975 : : *
3976 : : src_dir_fd : dir_fd = None
3977 : : dst_dir_fd : dir_fd = None
3978 : : follow_symlinks: bool = True
3979 : :
3980 : : Create a hard link to a file.
3981 : :
3982 : : If either src_dir_fd or dst_dir_fd is not None, it should be a file
3983 : : descriptor open to a directory, and the respective path string (src or dst)
3984 : : should be relative; the path will then be relative to that directory.
3985 : : If follow_symlinks is False, and the last element of src is a symbolic
3986 : : link, link will create a link to the symbolic link itself instead of the
3987 : : file the link points to.
3988 : : src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3989 : : platform. If they are unavailable, using them will raise a
3990 : : NotImplementedError.
3991 : : [clinic start generated code]*/
3992 : :
3993 : : static PyObject *
3994 : 0 : os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3995 : : int dst_dir_fd, int follow_symlinks)
3996 : : /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3997 : : {
3998 : : #ifdef MS_WINDOWS
3999 : : BOOL result = FALSE;
4000 : : #else
4001 : : int result;
4002 : : #endif
4003 : : #if defined(HAVE_LINKAT)
4004 : 0 : int linkat_unavailable = 0;
4005 : : #endif
4006 : :
4007 : : #ifndef HAVE_LINKAT
4008 : : if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4009 : : argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4010 : : return NULL;
4011 : : }
4012 : : #endif
4013 : :
4014 : : #ifndef MS_WINDOWS
4015 [ # # # # : 0 : if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
# # # # ]
4016 : 0 : PyErr_SetString(PyExc_NotImplementedError,
4017 : : "link: src and dst must be the same type");
4018 : 0 : return NULL;
4019 : : }
4020 : : #endif
4021 : :
4022 [ # # # # : 0 : if (PySys_Audit("os.link", "OOii", src->object, dst->object,
# # ]
4023 : : src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4024 : : dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4025 : 0 : return NULL;
4026 : : }
4027 : :
4028 : : #ifdef MS_WINDOWS
4029 : : Py_BEGIN_ALLOW_THREADS
4030 : : result = CreateHardLinkW(dst->wide, src->wide, NULL);
4031 : : Py_END_ALLOW_THREADS
4032 : :
4033 : : if (!result)
4034 : : return path_error2(src, dst);
4035 : : #else
4036 : 0 : Py_BEGIN_ALLOW_THREADS
4037 : : #ifdef HAVE_LINKAT
4038 [ # # # # ]: 0 : if ((src_dir_fd != DEFAULT_DIR_FD) ||
4039 [ # # ]: 0 : (dst_dir_fd != DEFAULT_DIR_FD) ||
4040 : : (!follow_symlinks)) {
4041 : :
4042 : 0 : if (HAVE_LINKAT_RUNTIME) {
4043 : :
4044 [ # # ]: 0 : result = linkat(src_dir_fd, src->narrow,
4045 : : dst_dir_fd, dst->narrow,
4046 : : follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4047 : :
4048 : : }
4049 : : #ifdef __APPLE__
4050 : : else {
4051 : : if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
4052 : : /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
4053 : : result = link(src->narrow, dst->narrow);
4054 : : } else {
4055 : : linkat_unavailable = 1;
4056 : : }
4057 : : }
4058 : : #endif
4059 : : }
4060 : : else
4061 : : #endif /* HAVE_LINKAT */
4062 : 0 : result = link(src->narrow, dst->narrow);
4063 : 0 : Py_END_ALLOW_THREADS
4064 : :
4065 : : #ifdef HAVE_LINKAT
4066 [ # # ]: 0 : if (linkat_unavailable) {
4067 : : /* Either or both dir_fd arguments were specified */
4068 [ # # ]: 0 : if (src_dir_fd != DEFAULT_DIR_FD) {
4069 : 0 : argument_unavailable_error("link", "src_dir_fd");
4070 : : } else {
4071 : 0 : argument_unavailable_error("link", "dst_dir_fd");
4072 : : }
4073 : 0 : return NULL;
4074 : : }
4075 : : #endif
4076 : :
4077 [ # # ]: 0 : if (result)
4078 : 0 : return path_error2(src, dst);
4079 : : #endif /* MS_WINDOWS */
4080 : :
4081 : 0 : Py_RETURN_NONE;
4082 : : }
4083 : : #endif
4084 : :
4085 : :
4086 : : #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4087 : : static PyObject *
4088 : : _listdir_windows_no_opendir(path_t *path, PyObject *list)
4089 : : {
4090 : : PyObject *v;
4091 : : HANDLE hFindFile = INVALID_HANDLE_VALUE;
4092 : : BOOL result;
4093 : : wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4094 : : /* only claim to have space for MAX_PATH */
4095 : : Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4096 : : wchar_t *wnamebuf = NULL;
4097 : :
4098 : : WIN32_FIND_DATAW wFileData;
4099 : : const wchar_t *po_wchars;
4100 : :
4101 : : if (!path->wide) { /* Default arg: "." */
4102 : : po_wchars = L".";
4103 : : len = 1;
4104 : : } else {
4105 : : po_wchars = path->wide;
4106 : : len = wcslen(path->wide);
4107 : : }
4108 : : /* The +5 is so we can append "\\*.*\0" */
4109 : : wnamebuf = PyMem_New(wchar_t, len + 5);
4110 : : if (!wnamebuf) {
4111 : : PyErr_NoMemory();
4112 : : goto exit;
4113 : : }
4114 : : wcscpy(wnamebuf, po_wchars);
4115 : : if (len > 0) {
4116 : : wchar_t wch = wnamebuf[len-1];
4117 : : if (wch != SEP && wch != ALTSEP && wch != L':')
4118 : : wnamebuf[len++] = SEP;
4119 : : wcscpy(wnamebuf + len, L"*.*");
4120 : : }
4121 : : if ((list = PyList_New(0)) == NULL) {
4122 : : goto exit;
4123 : : }
4124 : : Py_BEGIN_ALLOW_THREADS
4125 : : hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4126 : : Py_END_ALLOW_THREADS
4127 : : if (hFindFile == INVALID_HANDLE_VALUE) {
4128 : : int error = GetLastError();
4129 : : if (error == ERROR_FILE_NOT_FOUND)
4130 : : goto exit;
4131 : : Py_DECREF(list);
4132 : : list = path_error(path);
4133 : : goto exit;
4134 : : }
4135 : : do {
4136 : : /* Skip over . and .. */
4137 : : if (wcscmp(wFileData.cFileName, L".") != 0 &&
4138 : : wcscmp(wFileData.cFileName, L"..") != 0) {
4139 : : v = PyUnicode_FromWideChar(wFileData.cFileName,
4140 : : wcslen(wFileData.cFileName));
4141 : : if (path->narrow && v) {
4142 : : Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4143 : : }
4144 : : if (v == NULL) {
4145 : : Py_SETREF(list, NULL);
4146 : : break;
4147 : : }
4148 : : if (PyList_Append(list, v) != 0) {
4149 : : Py_DECREF(v);
4150 : : Py_SETREF(list, NULL);
4151 : : break;
4152 : : }
4153 : : Py_DECREF(v);
4154 : : }
4155 : : Py_BEGIN_ALLOW_THREADS
4156 : : result = FindNextFileW(hFindFile, &wFileData);
4157 : : Py_END_ALLOW_THREADS
4158 : : /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4159 : : it got to the end of the directory. */
4160 : : if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4161 : : Py_DECREF(list);
4162 : : list = path_error(path);
4163 : : goto exit;
4164 : : }
4165 : : } while (result == TRUE);
4166 : :
4167 : : exit:
4168 : : if (hFindFile != INVALID_HANDLE_VALUE) {
4169 : : if (FindClose(hFindFile) == FALSE) {
4170 : : if (list != NULL) {
4171 : : Py_DECREF(list);
4172 : : list = path_error(path);
4173 : : }
4174 : : }
4175 : : }
4176 : : PyMem_Free(wnamebuf);
4177 : :
4178 : : return list;
4179 : : } /* end of _listdir_windows_no_opendir */
4180 : :
4181 : : #else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4182 : :
4183 : : static PyObject *
4184 : 89 : _posix_listdir(path_t *path, PyObject *list)
4185 : : {
4186 : : PyObject *v;
4187 : 89 : DIR *dirp = NULL;
4188 : : struct dirent *ep;
4189 : : int return_str; /* if false, return bytes */
4190 : : #ifdef HAVE_FDOPENDIR
4191 : 89 : int fd = -1;
4192 : : #endif
4193 : :
4194 : 89 : errno = 0;
4195 : : #ifdef HAVE_FDOPENDIR
4196 [ - + ]: 89 : if (path->fd != -1) {
4197 : : if (HAVE_FDOPENDIR_RUNTIME) {
4198 : : /* closedir() closes the FD, so we duplicate it */
4199 : 0 : fd = _Py_dup(path->fd);
4200 [ # # ]: 0 : if (fd == -1)
4201 : 0 : return NULL;
4202 : :
4203 : 0 : return_str = 1;
4204 : :
4205 : 0 : Py_BEGIN_ALLOW_THREADS
4206 : 0 : dirp = fdopendir(fd);
4207 : 0 : Py_END_ALLOW_THREADS
4208 : : } else {
4209 : : PyErr_SetString(PyExc_TypeError,
4210 : : "listdir: path should be string, bytes, os.PathLike or None, not int");
4211 : : return NULL;
4212 : : }
4213 : : }
4214 : : else
4215 : : #endif
4216 : : {
4217 : : const char *name;
4218 [ + + ]: 89 : if (path->narrow) {
4219 : 85 : name = path->narrow;
4220 : : /* only return bytes if they specified a bytes object */
4221 : 85 : return_str = !PyBytes_Check(path->object);
4222 : : }
4223 : : else {
4224 : 4 : name = ".";
4225 : 4 : return_str = 1;
4226 : : }
4227 : :
4228 : 89 : Py_BEGIN_ALLOW_THREADS
4229 : 89 : dirp = opendir(name);
4230 : 89 : Py_END_ALLOW_THREADS
4231 : : }
4232 : :
4233 [ - + ]: 89 : if (dirp == NULL) {
4234 : 0 : list = path_error(path);
4235 : : #ifdef HAVE_FDOPENDIR
4236 [ # # ]: 0 : if (fd != -1) {
4237 : 0 : Py_BEGIN_ALLOW_THREADS
4238 : 0 : close(fd);
4239 : 0 : Py_END_ALLOW_THREADS
4240 : : }
4241 : : #endif
4242 : 0 : goto exit;
4243 : : }
4244 [ - + ]: 89 : if ((list = PyList_New(0)) == NULL) {
4245 : 0 : goto exit;
4246 : : }
4247 : : for (;;) {
4248 : 10353 : errno = 0;
4249 : 10353 : Py_BEGIN_ALLOW_THREADS
4250 : 10353 : ep = readdir(dirp);
4251 : 10353 : Py_END_ALLOW_THREADS
4252 [ + + ]: 10353 : if (ep == NULL) {
4253 [ + - ]: 89 : if (errno == 0) {
4254 : 89 : break;
4255 : : } else {
4256 : 0 : Py_DECREF(list);
4257 : 0 : list = path_error(path);
4258 : 0 : goto exit;
4259 : : }
4260 : : }
4261 [ + + ]: 10264 : if (ep->d_name[0] == '.' &&
4262 [ + + ]: 196 : (NAMLEN(ep) == 1 ||
4263 [ + + + - ]: 107 : (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4264 : 178 : continue;
4265 [ + - ]: 10086 : if (return_str)
4266 : 10086 : v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4267 : : else
4268 : 0 : v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4269 [ - + ]: 10086 : if (v == NULL) {
4270 [ # # ]: 0 : Py_CLEAR(list);
4271 : 0 : break;
4272 : : }
4273 [ - + ]: 10086 : if (PyList_Append(list, v) != 0) {
4274 : 0 : Py_DECREF(v);
4275 [ # # ]: 0 : Py_CLEAR(list);
4276 : 0 : break;
4277 : : }
4278 : 10086 : Py_DECREF(v);
4279 : : }
4280 : :
4281 : 89 : exit:
4282 [ + - ]: 89 : if (dirp != NULL) {
4283 : 89 : Py_BEGIN_ALLOW_THREADS
4284 : : #ifdef HAVE_FDOPENDIR
4285 [ - + ]: 89 : if (fd > -1)
4286 : 0 : rewinddir(dirp);
4287 : : #endif
4288 : 89 : closedir(dirp);
4289 : 89 : Py_END_ALLOW_THREADS
4290 : : }
4291 : :
4292 : 89 : return list;
4293 : : } /* end of _posix_listdir */
4294 : : #endif /* which OS */
4295 : :
4296 : :
4297 : : /*[clinic input]
4298 : : os.listdir
4299 : :
4300 : : path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4301 : :
4302 : : Return a list containing the names of the files in the directory.
4303 : :
4304 : : path can be specified as either str, bytes, or a path-like object. If path is bytes,
4305 : : the filenames returned will also be bytes; in all other circumstances
4306 : : the filenames returned will be str.
4307 : : If path is None, uses the path='.'.
4308 : : On some platforms, path may also be specified as an open file descriptor;\
4309 : : the file descriptor must refer to a directory.
4310 : : If this functionality is unavailable, using it raises NotImplementedError.
4311 : :
4312 : : The list is in arbitrary order. It does not include the special
4313 : : entries '.' and '..' even if they are present in the directory.
4314 : :
4315 : :
4316 : : [clinic start generated code]*/
4317 : :
4318 : : static PyObject *
4319 : 89 : os_listdir_impl(PyObject *module, path_t *path)
4320 : : /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4321 : : {
4322 [ - + ]: 89 : if (PySys_Audit("os.listdir", "O",
4323 [ + + ]: 89 : path->object ? path->object : Py_None) < 0) {
4324 : 0 : return NULL;
4325 : : }
4326 : : #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4327 : : return _listdir_windows_no_opendir(path, NULL);
4328 : : #else
4329 : 89 : return _posix_listdir(path, NULL);
4330 : : #endif
4331 : : }
4332 : :
4333 : :
4334 : : #ifdef MS_WINDOWS
4335 : :
4336 : : /*[clinic input]
4337 : : os.listdrives
4338 : :
4339 : : Return a list containing the names of drives in the system.
4340 : :
4341 : : A drive name typically looks like 'C:\\'.
4342 : :
4343 : : [clinic start generated code]*/
4344 : :
4345 : : static PyObject *
4346 : : os_listdrives_impl(PyObject *module)
4347 : : /*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
4348 : : {
4349 : : /* Number of possible drives is limited, so 256 should always be enough.
4350 : : On the day when it is not, listmounts() will have to be used. */
4351 : : wchar_t buffer[256];
4352 : : DWORD buflen = Py_ARRAY_LENGTH(buffer);
4353 : : PyObject *result = NULL;
4354 : : if (PySys_Audit("os.listdrives", NULL) < 0) {
4355 : : return NULL;
4356 : : }
4357 : :
4358 : : Py_BEGIN_ALLOW_THREADS;
4359 : : buflen = GetLogicalDriveStringsW(buflen, buffer);
4360 : : Py_END_ALLOW_THREADS;
4361 : :
4362 : : if (!buflen) {
4363 : : PyErr_SetFromWindowsErr(0);
4364 : : return NULL;
4365 : : } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
4366 : : PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
4367 : : return NULL;
4368 : : }
4369 : :
4370 : : /* buflen includes a null terminator, so remove it */
4371 : : PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
4372 : : if (str) {
4373 : : PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
4374 : : if (nullchar) {
4375 : : result = PyUnicode_Split(str, nullchar, -1);
4376 : : Py_DECREF(nullchar);
4377 : : }
4378 : : Py_DECREF(str);
4379 : : }
4380 : : return result;
4381 : : }
4382 : :
4383 : : /*[clinic input]
4384 : : os.listvolumes
4385 : :
4386 : : Return a list containing the volumes in the system.
4387 : :
4388 : : Volumes are typically represented as a GUID path.
4389 : :
4390 : : [clinic start generated code]*/
4391 : :
4392 : : static PyObject *
4393 : : os_listvolumes_impl(PyObject *module)
4394 : : /*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
4395 : : {
4396 : : PyObject *result = PyList_New(0);
4397 : : HANDLE find = INVALID_HANDLE_VALUE;
4398 : : wchar_t buffer[MAX_PATH + 1];
4399 : : if (!result) {
4400 : : return NULL;
4401 : : }
4402 : : if (PySys_Audit("os.listvolumes", NULL) < 0) {
4403 : : Py_DECREF(result);
4404 : : return NULL;
4405 : : }
4406 : :
4407 : : int err = 0;
4408 : : Py_BEGIN_ALLOW_THREADS;
4409 : : find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
4410 : : if (find == INVALID_HANDLE_VALUE) {
4411 : : err = GetLastError();
4412 : : }
4413 : : Py_END_ALLOW_THREADS;
4414 : :
4415 : : while (!err) {
4416 : : PyObject *s = PyUnicode_FromWideChar(buffer, -1);
4417 : : if (!s || PyList_Append(result, s) < 0) {
4418 : : Py_XDECREF(s);
4419 : : Py_CLEAR(result);
4420 : : break;
4421 : : }
4422 : : Py_DECREF(s);
4423 : :
4424 : : Py_BEGIN_ALLOW_THREADS;
4425 : : if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
4426 : : err = GetLastError();
4427 : : }
4428 : : Py_END_ALLOW_THREADS;
4429 : : }
4430 : :
4431 : : if (find != INVALID_HANDLE_VALUE) {
4432 : : Py_BEGIN_ALLOW_THREADS;
4433 : : FindVolumeClose(find);
4434 : : Py_END_ALLOW_THREADS;
4435 : : }
4436 : : if (err && err != ERROR_NO_MORE_FILES) {
4437 : : PyErr_SetFromWindowsErr(err);
4438 : : Py_XDECREF(result);
4439 : : result = NULL;
4440 : : }
4441 : : return result;
4442 : : }
4443 : :
4444 : :
4445 : : /*[clinic input]
4446 : : os.listmounts
4447 : :
4448 : : volume: path_t
4449 : :
4450 : : Return a list containing mount points for a particular volume.
4451 : :
4452 : : 'volume' should be a GUID path as returned from os.listvolumes.
4453 : :
4454 : : [clinic start generated code]*/
4455 : :
4456 : : static PyObject *
4457 : : os_listmounts_impl(PyObject *module, path_t *volume)
4458 : : /*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
4459 : : {
4460 : : wchar_t default_buffer[MAX_PATH + 1];
4461 : : DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
4462 : : LPWSTR buffer = default_buffer;
4463 : : DWORD attributes;
4464 : : PyObject *str = NULL;
4465 : : PyObject *nullchar = NULL;
4466 : : PyObject *result = NULL;
4467 : :
4468 : : /* Ensure we have a valid volume path before continuing */
4469 : : Py_BEGIN_ALLOW_THREADS
4470 : : attributes = GetFileAttributesW(volume->wide);
4471 : : Py_END_ALLOW_THREADS
4472 : : if (attributes == INVALID_FILE_ATTRIBUTES &&
4473 : : GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
4474 : : {
4475 : : return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
4476 : : }
4477 : :
4478 : : if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
4479 : : return NULL;
4480 : : }
4481 : :
4482 : : while (1) {
4483 : : BOOL success;
4484 : : Py_BEGIN_ALLOW_THREADS
4485 : : success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
4486 : : buflen, &buflen);
4487 : : Py_END_ALLOW_THREADS
4488 : : if (success) {
4489 : : break;
4490 : : }
4491 : : if (GetLastError() != ERROR_MORE_DATA) {
4492 : : PyErr_SetFromWindowsErr(0);
4493 : : goto exit;
4494 : : }
4495 : : if (buffer != default_buffer) {
4496 : : PyMem_Free((void *)buffer);
4497 : : }
4498 : : buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
4499 : : if (!buffer) {
4500 : : PyErr_NoMemory();
4501 : : goto exit;
4502 : : }
4503 : : }
4504 : : if (buflen < 2) {
4505 : : result = PyList_New(0);
4506 : : goto exit;
4507 : : }
4508 : : // buflen includes two null terminators, one for the last string
4509 : : // and one for the array of strings.
4510 : : str = PyUnicode_FromWideChar(buffer, buflen - 2);
4511 : : nullchar = PyUnicode_FromStringAndSize("\0", 1);
4512 : : if (str && nullchar) {
4513 : : result = PyUnicode_Split(str, nullchar, -1);
4514 : : }
4515 : : exit:
4516 : : if (buffer != default_buffer) {
4517 : : PyMem_Free(buffer);
4518 : : }
4519 : : Py_XDECREF(nullchar);
4520 : : Py_XDECREF(str);
4521 : : return result;
4522 : : }
4523 : :
4524 : :
4525 : : int
4526 : : _PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
4527 : : {
4528 : : wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
4529 : : DWORD result;
4530 : :
4531 : : result = GetFullPathNameW(path,
4532 : : Py_ARRAY_LENGTH(woutbuf), woutbuf,
4533 : : NULL);
4534 : : if (!result) {
4535 : : return -1;
4536 : : }
4537 : :
4538 : : if (result >= Py_ARRAY_LENGTH(woutbuf)) {
4539 : : if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4540 : : woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
4541 : : }
4542 : : else {
4543 : : woutbufp = NULL;
4544 : : }
4545 : : if (!woutbufp) {
4546 : : *abspath_p = NULL;
4547 : : return 0;
4548 : : }
4549 : :
4550 : : result = GetFullPathNameW(path, result, woutbufp, NULL);
4551 : : if (!result) {
4552 : : PyMem_RawFree(woutbufp);
4553 : : return -1;
4554 : : }
4555 : : }
4556 : :
4557 : : if (woutbufp != woutbuf) {
4558 : : *abspath_p = woutbufp;
4559 : : return 0;
4560 : : }
4561 : :
4562 : : *abspath_p = _PyMem_RawWcsdup(woutbufp);
4563 : : return 0;
4564 : : }
4565 : :
4566 : :
4567 : : /* A helper function for abspath on win32 */
4568 : : /*[clinic input]
4569 : : os._getfullpathname
4570 : :
4571 : : path: path_t
4572 : : /
4573 : :
4574 : : [clinic start generated code]*/
4575 : :
4576 : : static PyObject *
4577 : : os__getfullpathname_impl(PyObject *module, path_t *path)
4578 : : /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
4579 : : {
4580 : : wchar_t *abspath;
4581 : :
4582 : : if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
4583 : : return win32_error_object("GetFullPathNameW", path->object);
4584 : : }
4585 : : if (abspath == NULL) {
4586 : : return PyErr_NoMemory();
4587 : : }
4588 : :
4589 : : PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
4590 : : PyMem_RawFree(abspath);
4591 : : if (str == NULL) {
4592 : : return NULL;
4593 : : }
4594 : : if (path->narrow) {
4595 : : Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
4596 : : }
4597 : : return str;
4598 : : }
4599 : :
4600 : :
4601 : : /*[clinic input]
4602 : : os._getfinalpathname
4603 : :
4604 : : path: path_t
4605 : : /
4606 : :
4607 : : A helper function for samepath on windows.
4608 : : [clinic start generated code]*/
4609 : :
4610 : : static PyObject *
4611 : : os__getfinalpathname_impl(PyObject *module, path_t *path)
4612 : : /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
4613 : : {
4614 : : HANDLE hFile;
4615 : : wchar_t buf[MAXPATHLEN], *target_path = buf;
4616 : : int buf_size = Py_ARRAY_LENGTH(buf);
4617 : : int result_length;
4618 : : PyObject *result;
4619 : :
4620 : : Py_BEGIN_ALLOW_THREADS
4621 : : hFile = CreateFileW(
4622 : : path->wide,
4623 : : 0, /* desired access */
4624 : : 0, /* share mode */
4625 : : NULL, /* security attributes */
4626 : : OPEN_EXISTING,
4627 : : /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
4628 : : FILE_FLAG_BACKUP_SEMANTICS,
4629 : : NULL);
4630 : : Py_END_ALLOW_THREADS
4631 : :
4632 : : if (hFile == INVALID_HANDLE_VALUE) {
4633 : : return win32_error_object("CreateFileW", path->object);
4634 : : }
4635 : :
4636 : : /* We have a good handle to the target, use it to determine the
4637 : : target path name. */
4638 : : while (1) {
4639 : : Py_BEGIN_ALLOW_THREADS
4640 : : result_length = GetFinalPathNameByHandleW(hFile, target_path,
4641 : : buf_size, VOLUME_NAME_DOS);
4642 : : Py_END_ALLOW_THREADS
4643 : :
4644 : : if (!result_length) {
4645 : : result = win32_error_object("GetFinalPathNameByHandleW",
4646 : : path->object);
4647 : : goto cleanup;
4648 : : }
4649 : :
4650 : : if (result_length < buf_size) {
4651 : : break;
4652 : : }
4653 : :
4654 : : wchar_t *tmp;
4655 : : tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
4656 : : result_length * sizeof(*tmp));
4657 : : if (!tmp) {
4658 : : result = PyErr_NoMemory();
4659 : : goto cleanup;
4660 : : }
4661 : :
4662 : : buf_size = result_length;
4663 : : target_path = tmp;
4664 : : }
4665 : :
4666 : : result = PyUnicode_FromWideChar(target_path, result_length);
4667 : : if (result && path->narrow) {
4668 : : Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4669 : : }
4670 : :
4671 : : cleanup:
4672 : : if (target_path != buf) {
4673 : : PyMem_Free(target_path);
4674 : : }
4675 : : CloseHandle(hFile);
4676 : : return result;
4677 : : }
4678 : :
4679 : :
4680 : : /*[clinic input]
4681 : : os._getvolumepathname
4682 : :
4683 : : path: path_t
4684 : :
4685 : : A helper function for ismount on Win32.
4686 : : [clinic start generated code]*/
4687 : :
4688 : : static PyObject *
4689 : : os__getvolumepathname_impl(PyObject *module, path_t *path)
4690 : : /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
4691 : : {
4692 : : PyObject *result;
4693 : : wchar_t *mountpath=NULL;
4694 : : size_t buflen;
4695 : : BOOL ret;
4696 : :
4697 : : /* Volume path should be shorter than entire path */
4698 : : buflen = Py_MAX(path->length, MAX_PATH);
4699 : :
4700 : : if (buflen > PY_DWORD_MAX) {
4701 : : PyErr_SetString(PyExc_OverflowError, "path too long");
4702 : : return NULL;
4703 : : }
4704 : :
4705 : : mountpath = PyMem_New(wchar_t, buflen);
4706 : : if (mountpath == NULL)
4707 : : return PyErr_NoMemory();
4708 : :
4709 : : Py_BEGIN_ALLOW_THREADS
4710 : : ret = GetVolumePathNameW(path->wide, mountpath,
4711 : : Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
4712 : : Py_END_ALLOW_THREADS
4713 : :
4714 : : if (!ret) {
4715 : : result = win32_error_object("_getvolumepathname", path->object);
4716 : : goto exit;
4717 : : }
4718 : : result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
4719 : : if (path->narrow)
4720 : : Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4721 : :
4722 : : exit:
4723 : : PyMem_Free(mountpath);
4724 : : return result;
4725 : : }
4726 : :
4727 : :
4728 : : /*[clinic input]
4729 : : os._path_splitroot
4730 : :
4731 : : path: path_t
4732 : :
4733 : : Removes everything after the root on Win32.
4734 : : [clinic start generated code]*/
4735 : :
4736 : : static PyObject *
4737 : : os__path_splitroot_impl(PyObject *module, path_t *path)
4738 : : /*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/
4739 : : {
4740 : : wchar_t *buffer;
4741 : : wchar_t *end;
4742 : : PyObject *result = NULL;
4743 : : HRESULT ret;
4744 : :
4745 : : buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
4746 : : if (!buffer) {
4747 : : return NULL;
4748 : : }
4749 : : wcscpy(buffer, path->wide);
4750 : : for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
4751 : : *p = L'\\';
4752 : : }
4753 : :
4754 : : Py_BEGIN_ALLOW_THREADS
4755 : : ret = PathCchSkipRoot(buffer, &end);
4756 : : Py_END_ALLOW_THREADS
4757 : : if (FAILED(ret)) {
4758 : : result = Py_BuildValue("sO", "", path->object);
4759 : : } else if (end != buffer) {
4760 : : size_t rootLen = (size_t)(end - buffer);
4761 : : result = Py_BuildValue("NN",
4762 : : PyUnicode_FromWideChar(path->wide, rootLen),
4763 : : PyUnicode_FromWideChar(path->wide + rootLen, -1)
4764 : : );
4765 : : } else {
4766 : : result = Py_BuildValue("Os", path->object, "");
4767 : : }
4768 : : PyMem_Free(buffer);
4769 : :
4770 : : return result;
4771 : : }
4772 : :
4773 : :
4774 : : /*[clinic input]
4775 : : os._path_isdir
4776 : :
4777 : : path: 'O'
4778 : :
4779 : : Return true if the pathname refers to an existing directory.
4780 : :
4781 : : [clinic start generated code]*/
4782 : :
4783 : : static PyObject *
4784 : : os__path_isdir_impl(PyObject *module, PyObject *path)
4785 : : /*[clinic end generated code: output=00faea0af309669d input=b1d2571cf7291aaf]*/
4786 : : {
4787 : : HANDLE hfile;
4788 : : BOOL close_file = TRUE;
4789 : : FILE_BASIC_INFO info;
4790 : : path_t _path = PATH_T_INITIALIZE("isdir", "path", 0, 1);
4791 : : int result;
4792 : :
4793 : : if (!path_converter(path, &_path)) {
4794 : : path_cleanup(&_path);
4795 : : if (PyErr_ExceptionMatches(PyExc_ValueError)) {
4796 : : PyErr_Clear();
4797 : : Py_RETURN_FALSE;
4798 : : }
4799 : : return NULL;
4800 : : }
4801 : :
4802 : : Py_BEGIN_ALLOW_THREADS
4803 : : if (_path.fd != -1) {
4804 : : hfile = _Py_get_osfhandle_noraise(_path.fd);
4805 : : close_file = FALSE;
4806 : : }
4807 : : else {
4808 : : hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL,
4809 : : OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4810 : : }
4811 : : if (hfile != INVALID_HANDLE_VALUE) {
4812 : : if (GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
4813 : : sizeof(info)))
4814 : : {
4815 : : result = info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4816 : : }
4817 : : else {
4818 : : result = 0;
4819 : : }
4820 : : if (close_file) {
4821 : : CloseHandle(hfile);
4822 : : }
4823 : : }
4824 : : else {
4825 : : STRUCT_STAT st;
4826 : : switch (GetLastError()) {
4827 : : case ERROR_ACCESS_DENIED:
4828 : : case ERROR_SHARING_VIOLATION:
4829 : : case ERROR_CANT_ACCESS_FILE:
4830 : : case ERROR_INVALID_PARAMETER:
4831 : : if (STAT(_path.wide, &st)) {
4832 : : result = 0;
4833 : : }
4834 : : else {
4835 : : result = S_ISDIR(st.st_mode);
4836 : : }
4837 : : break;
4838 : : default:
4839 : : result = 0;
4840 : : }
4841 : : }
4842 : : Py_END_ALLOW_THREADS
4843 : :
4844 : : path_cleanup(&_path);
4845 : : if (result) {
4846 : : Py_RETURN_TRUE;
4847 : : }
4848 : : Py_RETURN_FALSE;
4849 : : }
4850 : :
4851 : :
4852 : : /*[clinic input]
4853 : : os._path_isfile
4854 : :
4855 : : path: 'O'
4856 : :
4857 : : Test whether a path is a regular file
4858 : :
4859 : : [clinic start generated code]*/
4860 : :
4861 : : static PyObject *
4862 : : os__path_isfile_impl(PyObject *module, PyObject *path)
4863 : : /*[clinic end generated code: output=2394ed7c4b5cfd85 input=de22d74960ade365]*/
4864 : : {
4865 : : HANDLE hfile;
4866 : : BOOL close_file = TRUE;
4867 : : FILE_BASIC_INFO info;
4868 : : path_t _path = PATH_T_INITIALIZE("isfile", "path", 0, 1);
4869 : : int result;
4870 : :
4871 : : if (!path_converter(path, &_path)) {
4872 : : path_cleanup(&_path);
4873 : : if (PyErr_ExceptionMatches(PyExc_ValueError)) {
4874 : : PyErr_Clear();
4875 : : Py_RETURN_FALSE;
4876 : : }
4877 : : return NULL;
4878 : : }
4879 : :
4880 : : Py_BEGIN_ALLOW_THREADS
4881 : : if (_path.fd != -1) {
4882 : : hfile = _Py_get_osfhandle_noraise(_path.fd);
4883 : : close_file = FALSE;
4884 : : }
4885 : : else {
4886 : : hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL,
4887 : : OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4888 : : }
4889 : : if (hfile != INVALID_HANDLE_VALUE) {
4890 : : if (GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
4891 : : sizeof(info)))
4892 : : {
4893 : : result = !(info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY);
4894 : : }
4895 : : else {
4896 : : result = 0;
4897 : : }
4898 : : if (close_file) {
4899 : : CloseHandle(hfile);
4900 : : }
4901 : : }
4902 : : else {
4903 : : STRUCT_STAT st;
4904 : : switch (GetLastError()) {
4905 : : case ERROR_ACCESS_DENIED:
4906 : : case ERROR_SHARING_VIOLATION:
4907 : : case ERROR_CANT_ACCESS_FILE:
4908 : : case ERROR_INVALID_PARAMETER:
4909 : : if (STAT(_path.wide, &st)) {
4910 : : result = 0;
4911 : : }
4912 : : else {
4913 : : result = S_ISREG(st.st_mode);
4914 : : }
4915 : : break;
4916 : : default:
4917 : : result = 0;
4918 : : }
4919 : : }
4920 : : Py_END_ALLOW_THREADS
4921 : :
4922 : : path_cleanup(&_path);
4923 : : if (result) {
4924 : : Py_RETURN_TRUE;
4925 : : }
4926 : : Py_RETURN_FALSE;
4927 : : }
4928 : :
4929 : :
4930 : : /*[clinic input]
4931 : : os._path_exists
4932 : :
4933 : : path: 'O'
4934 : :
4935 : : Test whether a path exists. Returns False for broken symbolic links
4936 : :
4937 : : [clinic start generated code]*/
4938 : :
4939 : : static PyObject *
4940 : : os__path_exists_impl(PyObject *module, PyObject *path)
4941 : : /*[clinic end generated code: output=f508c3b35e13a249 input=380f77cdfa0f7ae8]*/
4942 : : {
4943 : : HANDLE hfile;
4944 : : BOOL close_file = TRUE;
4945 : : path_t _path = PATH_T_INITIALIZE("exists", "path", 0, 1);
4946 : : int result;
4947 : :
4948 : : if (!path_converter(path, &_path)) {
4949 : : path_cleanup(&_path);
4950 : : if (PyErr_ExceptionMatches(PyExc_ValueError)) {
4951 : : PyErr_Clear();
4952 : : Py_RETURN_FALSE;
4953 : : }
4954 : : return NULL;
4955 : : }
4956 : :
4957 : : Py_BEGIN_ALLOW_THREADS
4958 : : if (_path.fd != -1) {
4959 : : hfile = _Py_get_osfhandle_noraise(_path.fd);
4960 : : close_file = FALSE;
4961 : : }
4962 : : else {
4963 : : hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL,
4964 : : OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4965 : : }
4966 : : if (hfile != INVALID_HANDLE_VALUE) {
4967 : : result = 1;
4968 : : if (close_file) {
4969 : : CloseHandle(hfile);
4970 : : }
4971 : : }
4972 : : else {
4973 : : STRUCT_STAT st;
4974 : : switch (GetLastError()) {
4975 : : case ERROR_ACCESS_DENIED:
4976 : : case ERROR_SHARING_VIOLATION:
4977 : : case ERROR_CANT_ACCESS_FILE:
4978 : : case ERROR_INVALID_PARAMETER:
4979 : : if (STAT(_path.wide, &st)) {
4980 : : result = 0;
4981 : : }
4982 : : else {
4983 : : result = 1;
4984 : : }
4985 : : break;
4986 : : default:
4987 : : result = 0;
4988 : : }
4989 : : }
4990 : : Py_END_ALLOW_THREADS
4991 : :
4992 : : path_cleanup(&_path);
4993 : : if (result) {
4994 : : Py_RETURN_TRUE;
4995 : : }
4996 : : Py_RETURN_FALSE;
4997 : : }
4998 : :
4999 : :
5000 : : /*[clinic input]
5001 : : os._path_islink
5002 : :
5003 : : path: 'O'
5004 : :
5005 : : Test whether a path is a symbolic link
5006 : :
5007 : : [clinic start generated code]*/
5008 : :
5009 : : static PyObject *
5010 : : os__path_islink_impl(PyObject *module, PyObject *path)
5011 : : /*[clinic end generated code: output=6d8640b1a390c054 input=38a3cb937ccf59bf]*/
5012 : : {
5013 : : HANDLE hfile;
5014 : : BOOL close_file = TRUE;
5015 : : FILE_ATTRIBUTE_TAG_INFO info;
5016 : : path_t _path = PATH_T_INITIALIZE("islink", "path", 0, 1);
5017 : : int result;
5018 : :
5019 : : if (!path_converter(path, &_path)) {
5020 : : path_cleanup(&_path);
5021 : : if (PyErr_ExceptionMatches(PyExc_ValueError)) {
5022 : : PyErr_Clear();
5023 : : Py_RETURN_FALSE;
5024 : : }
5025 : : return NULL;
5026 : : }
5027 : :
5028 : : Py_BEGIN_ALLOW_THREADS
5029 : : if (_path.fd != -1) {
5030 : : hfile = _Py_get_osfhandle_noraise(_path.fd);
5031 : : close_file = FALSE;
5032 : : }
5033 : : else {
5034 : : hfile = CreateFileW(_path.wide, FILE_READ_ATTRIBUTES, 0, NULL,
5035 : : OPEN_EXISTING,
5036 : : FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
5037 : : NULL);
5038 : : }
5039 : : if (hfile != INVALID_HANDLE_VALUE) {
5040 : : if (GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5041 : : sizeof(info)))
5042 : : {
5043 : : result = (info.ReparseTag == IO_REPARSE_TAG_SYMLINK);
5044 : : }
5045 : : else {
5046 : : result = 0;
5047 : : }
5048 : : if (close_file) {
5049 : : CloseHandle(hfile);
5050 : : }
5051 : : }
5052 : : else {
5053 : : STRUCT_STAT st;
5054 : : switch (GetLastError()) {
5055 : : case ERROR_ACCESS_DENIED:
5056 : : case ERROR_SHARING_VIOLATION:
5057 : : case ERROR_CANT_ACCESS_FILE:
5058 : : case ERROR_INVALID_PARAMETER:
5059 : : if (LSTAT(_path.wide, &st)) {
5060 : : result = 0;
5061 : : }
5062 : : else {
5063 : : result = S_ISLNK(st.st_mode);
5064 : : }
5065 : : break;
5066 : : default:
5067 : : result = 0;
5068 : : }
5069 : : }
5070 : : Py_END_ALLOW_THREADS
5071 : :
5072 : : path_cleanup(&_path);
5073 : : if (result) {
5074 : : Py_RETURN_TRUE;
5075 : : }
5076 : : Py_RETURN_FALSE;
5077 : : }
5078 : :
5079 : : #endif /* MS_WINDOWS */
5080 : :
5081 : :
5082 : : /*[clinic input]
5083 : : os._path_normpath
5084 : :
5085 : : path: object
5086 : :
5087 : : Basic path normalization.
5088 : : [clinic start generated code]*/
5089 : :
5090 : : static PyObject *
5091 : 249 : os__path_normpath_impl(PyObject *module, PyObject *path)
5092 : : /*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/
5093 : : {
5094 [ - + ]: 249 : if (!PyUnicode_Check(path)) {
5095 : 0 : PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'",
5096 : 0 : Py_TYPE(path)->tp_name);
5097 : 0 : return NULL;
5098 : : }
5099 : : Py_ssize_t len;
5100 : 249 : wchar_t *buffer = PyUnicode_AsWideCharString(path, &len);
5101 [ - + ]: 249 : if (!buffer) {
5102 : 0 : return NULL;
5103 : : }
5104 : 249 : PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1);
5105 : 249 : PyMem_Free(buffer);
5106 : 249 : return result;
5107 : : }
5108 : :
5109 : : /*[clinic input]
5110 : : os.mkdir
5111 : :
5112 : : path : path_t
5113 : :
5114 : : mode: int = 0o777
5115 : :
5116 : : *
5117 : :
5118 : : dir_fd : dir_fd(requires='mkdirat') = None
5119 : :
5120 : : # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
5121 : :
5122 : : Create a directory.
5123 : :
5124 : : If dir_fd is not None, it should be a file descriptor open to a directory,
5125 : : and path should be relative; path will then be relative to that directory.
5126 : : dir_fd may not be implemented on your platform.
5127 : : If it is unavailable, using it will raise a NotImplementedError.
5128 : :
5129 : : The mode argument is ignored on Windows. Where it is used, the current umask
5130 : : value is first masked out.
5131 : : [clinic start generated code]*/
5132 : :
5133 : : static PyObject *
5134 : 23 : os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
5135 : : /*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
5136 : : {
5137 : : int result;
5138 : : #ifdef HAVE_MKDIRAT
5139 : 23 : int mkdirat_unavailable = 0;
5140 : : #endif
5141 : :
5142 [ - + - + ]: 23 : if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
5143 : : dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5144 : 0 : return NULL;
5145 : : }
5146 : :
5147 : : #ifdef MS_WINDOWS
5148 : : Py_BEGIN_ALLOW_THREADS
5149 : : result = CreateDirectoryW(path->wide, NULL);
5150 : : Py_END_ALLOW_THREADS
5151 : :
5152 : : if (!result)
5153 : : return path_error(path);
5154 : : #else
5155 : 23 : Py_BEGIN_ALLOW_THREADS
5156 : : #if HAVE_MKDIRAT
5157 [ - + ]: 23 : if (dir_fd != DEFAULT_DIR_FD) {
5158 : : if (HAVE_MKDIRAT_RUNTIME) {
5159 : 0 : result = mkdirat(dir_fd, path->narrow, mode);
5160 : :
5161 : : } else {
5162 : : mkdirat_unavailable = 1;
5163 : : }
5164 : : } else
5165 : : #endif
5166 : : #if defined(__WATCOMC__) && !defined(__QNX__)
5167 : : result = mkdir(path->narrow);
5168 : : #else
5169 : 23 : result = mkdir(path->narrow, mode);
5170 : : #endif
5171 : 23 : Py_END_ALLOW_THREADS
5172 : :
5173 : : #if HAVE_MKDIRAT
5174 [ - + ]: 23 : if (mkdirat_unavailable) {
5175 : 0 : argument_unavailable_error(NULL, "dir_fd");
5176 : 0 : return NULL;
5177 : : }
5178 : : #endif
5179 : :
5180 [ + + ]: 23 : if (result < 0)
5181 : 2 : return path_error(path);
5182 : : #endif /* MS_WINDOWS */
5183 : 21 : Py_RETURN_NONE;
5184 : : }
5185 : :
5186 : :
5187 : : /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
5188 : : #if defined(HAVE_SYS_RESOURCE_H)
5189 : : #include <sys/resource.h>
5190 : : #endif
5191 : :
5192 : :
5193 : : #ifdef HAVE_NICE
5194 : : /*[clinic input]
5195 : : os.nice
5196 : :
5197 : : increment: int
5198 : : /
5199 : :
5200 : : Add increment to the priority of process and return the new priority.
5201 : : [clinic start generated code]*/
5202 : :
5203 : : static PyObject *
5204 : 0 : os_nice_impl(PyObject *module, int increment)
5205 : : /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
5206 : : {
5207 : : int value;
5208 : :
5209 : : /* There are two flavours of 'nice': one that returns the new
5210 : : priority (as required by almost all standards out there) and the
5211 : : Linux/FreeBSD one, which returns '0' on success and advices
5212 : : the use of getpriority() to get the new priority.
5213 : :
5214 : : If we are of the nice family that returns the new priority, we
5215 : : need to clear errno before the call, and check if errno is filled
5216 : : before calling posix_error() on a returnvalue of -1, because the
5217 : : -1 may be the actual new priority! */
5218 : :
5219 : 0 : errno = 0;
5220 : 0 : value = nice(increment);
5221 : : #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
5222 : : if (value == 0)
5223 : : value = getpriority(PRIO_PROCESS, 0);
5224 : : #endif
5225 [ # # # # ]: 0 : if (value == -1 && errno != 0)
5226 : : /* either nice() or getpriority() returned an error */
5227 : 0 : return posix_error();
5228 : 0 : return PyLong_FromLong((long) value);
5229 : : }
5230 : : #endif /* HAVE_NICE */
5231 : :
5232 : :
5233 : : #ifdef HAVE_GETPRIORITY
5234 : : /*[clinic input]
5235 : : os.getpriority
5236 : :
5237 : : which: int
5238 : : who: int
5239 : :
5240 : : Return program scheduling priority.
5241 : : [clinic start generated code]*/
5242 : :
5243 : : static PyObject *
5244 : 0 : os_getpriority_impl(PyObject *module, int which, int who)
5245 : : /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
5246 : : {
5247 : : int retval;
5248 : :
5249 : 0 : errno = 0;
5250 : 0 : retval = getpriority(which, who);
5251 [ # # ]: 0 : if (errno != 0)
5252 : 0 : return posix_error();
5253 : 0 : return PyLong_FromLong((long)retval);
5254 : : }
5255 : : #endif /* HAVE_GETPRIORITY */
5256 : :
5257 : :
5258 : : #ifdef HAVE_SETPRIORITY
5259 : : /*[clinic input]
5260 : : os.setpriority
5261 : :
5262 : : which: int
5263 : : who: int
5264 : : priority: int
5265 : :
5266 : : Set program scheduling priority.
5267 : : [clinic start generated code]*/
5268 : :
5269 : : static PyObject *
5270 : 0 : os_setpriority_impl(PyObject *module, int which, int who, int priority)
5271 : : /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
5272 : : {
5273 : : int retval;
5274 : :
5275 : 0 : retval = setpriority(which, who, priority);
5276 [ # # ]: 0 : if (retval == -1)
5277 : 0 : return posix_error();
5278 : 0 : Py_RETURN_NONE;
5279 : : }
5280 : : #endif /* HAVE_SETPRIORITY */
5281 : :
5282 : :
5283 : : static PyObject *
5284 : 159 : internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
5285 : : {
5286 [ + - ]: 159 : const char *function_name = is_replace ? "replace" : "rename";
5287 : : int dir_fd_specified;
5288 : :
5289 : : #ifdef HAVE_RENAMEAT
5290 : 159 : int renameat_unavailable = 0;
5291 : : #endif
5292 : :
5293 : : #ifdef MS_WINDOWS
5294 : : BOOL result;
5295 : : int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
5296 : : #else
5297 : : int result;
5298 : : #endif
5299 : :
5300 [ + - - + ]: 159 : dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
5301 : : (dst_dir_fd != DEFAULT_DIR_FD);
5302 : : #ifndef HAVE_RENAMEAT
5303 : : if (dir_fd_specified) {
5304 : : argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
5305 : : return NULL;
5306 : : }
5307 : : #endif
5308 : :
5309 [ - + - + : 159 : if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
- + ]
5310 : : src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
5311 : : dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
5312 : 0 : return NULL;
5313 : : }
5314 : :
5315 : : #ifdef MS_WINDOWS
5316 : : Py_BEGIN_ALLOW_THREADS
5317 : : result = MoveFileExW(src->wide, dst->wide, flags);
5318 : : Py_END_ALLOW_THREADS
5319 : :
5320 : : if (!result)
5321 : : return path_error2(src, dst);
5322 : :
5323 : : #else
5324 [ + - + - : 159 : if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
- + - - ]
5325 : 0 : PyErr_Format(PyExc_ValueError,
5326 : : "%s: src and dst must be the same type", function_name);
5327 : 0 : return NULL;
5328 : : }
5329 : :
5330 : 159 : Py_BEGIN_ALLOW_THREADS
5331 : : #ifdef HAVE_RENAMEAT
5332 [ - + ]: 159 : if (dir_fd_specified) {
5333 : : if (HAVE_RENAMEAT_RUNTIME) {
5334 : 0 : result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
5335 : : } else {
5336 : : renameat_unavailable = 1;
5337 : : }
5338 : : } else
5339 : : #endif
5340 : 159 : result = rename(src->narrow, dst->narrow);
5341 : 159 : Py_END_ALLOW_THREADS
5342 : :
5343 : :
5344 : : #ifdef HAVE_RENAMEAT
5345 [ - + ]: 159 : if (renameat_unavailable) {
5346 : 0 : argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
5347 : 0 : return NULL;
5348 : : }
5349 : : #endif
5350 : :
5351 [ - + ]: 159 : if (result)
5352 : 0 : return path_error2(src, dst);
5353 : : #endif
5354 : 159 : Py_RETURN_NONE;
5355 : : }
5356 : :
5357 : :
5358 : : /*[clinic input]
5359 : : os.rename
5360 : :
5361 : : src : path_t
5362 : : dst : path_t
5363 : : *
5364 : : src_dir_fd : dir_fd = None
5365 : : dst_dir_fd : dir_fd = None
5366 : :
5367 : : Rename a file or directory.
5368 : :
5369 : : If either src_dir_fd or dst_dir_fd is not None, it should be a file
5370 : : descriptor open to a directory, and the respective path string (src or dst)
5371 : : should be relative; the path will then be relative to that directory.
5372 : : src_dir_fd and dst_dir_fd, may not be implemented on your platform.
5373 : : If they are unavailable, using them will raise a NotImplementedError.
5374 : : [clinic start generated code]*/
5375 : :
5376 : : static PyObject *
5377 : 0 : os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
5378 : : int dst_dir_fd)
5379 : : /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
5380 : : {
5381 : 0 : return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
5382 : : }
5383 : :
5384 : :
5385 : : /*[clinic input]
5386 : : os.replace = os.rename
5387 : :
5388 : : Rename a file or directory, overwriting the destination.
5389 : :
5390 : : If either src_dir_fd or dst_dir_fd is not None, it should be a file
5391 : : descriptor open to a directory, and the respective path string (src or dst)
5392 : : should be relative; the path will then be relative to that directory.
5393 : : src_dir_fd and dst_dir_fd, may not be implemented on your platform.
5394 : : If they are unavailable, using them will raise a NotImplementedError.
5395 : : [clinic start generated code]*/
5396 : :
5397 : : static PyObject *
5398 : 159 : os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
5399 : : int dst_dir_fd)
5400 : : /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
5401 : : {
5402 : 159 : return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
5403 : : }
5404 : :
5405 : :
5406 : : /*[clinic input]
5407 : : os.rmdir
5408 : :
5409 : : path: path_t
5410 : : *
5411 : : dir_fd: dir_fd(requires='unlinkat') = None
5412 : :
5413 : : Remove a directory.
5414 : :
5415 : : If dir_fd is not None, it should be a file descriptor open to a directory,
5416 : : and path should be relative; path will then be relative to that directory.
5417 : : dir_fd may not be implemented on your platform.
5418 : : If it is unavailable, using it will raise a NotImplementedError.
5419 : : [clinic start generated code]*/
5420 : :
5421 : : static PyObject *
5422 : 1 : os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
5423 : : /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
5424 : : {
5425 : : int result;
5426 : : #ifdef HAVE_UNLINKAT
5427 : 1 : int unlinkat_unavailable = 0;
5428 : : #endif
5429 : :
5430 [ - + - + ]: 1 : if (PySys_Audit("os.rmdir", "Oi", path->object,
5431 : : dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5432 : 0 : return NULL;
5433 : : }
5434 : :
5435 : 1 : Py_BEGIN_ALLOW_THREADS
5436 : : #ifdef MS_WINDOWS
5437 : : /* Windows, success=1, UNIX, success=0 */
5438 : : result = !RemoveDirectoryW(path->wide);
5439 : : #else
5440 : : #ifdef HAVE_UNLINKAT
5441 [ - + ]: 1 : if (dir_fd != DEFAULT_DIR_FD) {
5442 : : if (HAVE_UNLINKAT_RUNTIME) {
5443 : 0 : result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
5444 : : } else {
5445 : : unlinkat_unavailable = 1;
5446 : : result = -1;
5447 : : }
5448 : : } else
5449 : : #endif
5450 : 1 : result = rmdir(path->narrow);
5451 : : #endif
5452 : 1 : Py_END_ALLOW_THREADS
5453 : :
5454 : : #ifdef HAVE_UNLINKAT
5455 [ - + ]: 1 : if (unlinkat_unavailable) {
5456 : 0 : argument_unavailable_error("rmdir", "dir_fd");
5457 : 0 : return NULL;
5458 : : }
5459 : : #endif
5460 : :
5461 [ - + ]: 1 : if (result)
5462 : 0 : return path_error(path);
5463 : :
5464 : 1 : Py_RETURN_NONE;
5465 : : }
5466 : :
5467 : :
5468 : : #ifdef HAVE_SYSTEM
5469 : : #ifdef MS_WINDOWS
5470 : : /*[clinic input]
5471 : : os.system -> long
5472 : :
5473 : : command: Py_UNICODE
5474 : :
5475 : : Execute the command in a subshell.
5476 : : [clinic start generated code]*/
5477 : :
5478 : : static long
5479 : : os_system_impl(PyObject *module, const Py_UNICODE *command)
5480 : : /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
5481 : : {
5482 : : long result;
5483 : :
5484 : : if (PySys_Audit("os.system", "(u)", command) < 0) {
5485 : : return -1;
5486 : : }
5487 : :
5488 : : Py_BEGIN_ALLOW_THREADS
5489 : : _Py_BEGIN_SUPPRESS_IPH
5490 : : result = _wsystem(command);
5491 : : _Py_END_SUPPRESS_IPH
5492 : : Py_END_ALLOW_THREADS
5493 : : return result;
5494 : : }
5495 : : #else /* MS_WINDOWS */
5496 : : /*[clinic input]
5497 : : os.system -> long
5498 : :
5499 : : command: FSConverter
5500 : :
5501 : : Execute the command in a subshell.
5502 : : [clinic start generated code]*/
5503 : :
5504 : : static long
5505 : 0 : os_system_impl(PyObject *module, PyObject *command)
5506 : : /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
5507 : : {
5508 : : long result;
5509 : 0 : const char *bytes = PyBytes_AsString(command);
5510 : :
5511 [ # # ]: 0 : if (PySys_Audit("os.system", "(O)", command) < 0) {
5512 : 0 : return -1;
5513 : : }
5514 : :
5515 : 0 : Py_BEGIN_ALLOW_THREADS
5516 : 0 : result = system(bytes);
5517 : 0 : Py_END_ALLOW_THREADS
5518 : 0 : return result;
5519 : : }
5520 : : #endif
5521 : : #endif /* HAVE_SYSTEM */
5522 : :
5523 : :
5524 : : #ifdef HAVE_UMASK
5525 : : /*[clinic input]
5526 : : os.umask
5527 : :
5528 : : mask: int
5529 : : /
5530 : :
5531 : : Set the current numeric umask and return the previous umask.
5532 : : [clinic start generated code]*/
5533 : :
5534 : : static PyObject *
5535 : 0 : os_umask_impl(PyObject *module, int mask)
5536 : : /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
5537 : : {
5538 : 0 : int i = (int)umask(mask);
5539 [ # # ]: 0 : if (i < 0)
5540 : 0 : return posix_error();
5541 : 0 : return PyLong_FromLong((long)i);
5542 : : }
5543 : : #endif
5544 : :
5545 : : #ifdef MS_WINDOWS
5546 : :
5547 : : /* override the default DeleteFileW behavior so that directory
5548 : : symlinks can be removed with this function, the same as with
5549 : : Unix symlinks */
5550 : : BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
5551 : : {
5552 : : WIN32_FILE_ATTRIBUTE_DATA info;
5553 : : WIN32_FIND_DATAW find_data;
5554 : : HANDLE find_data_handle;
5555 : : int is_directory = 0;
5556 : : int is_link = 0;
5557 : :
5558 : : if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
5559 : : is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
5560 : :
5561 : : /* Get WIN32_FIND_DATA structure for the path to determine if
5562 : : it is a symlink */
5563 : : if(is_directory &&
5564 : : info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
5565 : : find_data_handle = FindFirstFileW(lpFileName, &find_data);
5566 : :
5567 : : if(find_data_handle != INVALID_HANDLE_VALUE) {
5568 : : /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
5569 : : IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
5570 : : is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
5571 : : find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
5572 : : FindClose(find_data_handle);
5573 : : }
5574 : : }
5575 : : }
5576 : :
5577 : : if (is_directory && is_link)
5578 : : return RemoveDirectoryW(lpFileName);
5579 : :
5580 : : return DeleteFileW(lpFileName);
5581 : : }
5582 : : #endif /* MS_WINDOWS */
5583 : :
5584 : :
5585 : : /*[clinic input]
5586 : : os.unlink
5587 : :
5588 : : path: path_t
5589 : : *
5590 : : dir_fd: dir_fd(requires='unlinkat')=None
5591 : :
5592 : : Remove a file (same as remove()).
5593 : :
5594 : : If dir_fd is not None, it should be a file descriptor open to a directory,
5595 : : and path should be relative; path will then be relative to that directory.
5596 : : dir_fd may not be implemented on your platform.
5597 : : If it is unavailable, using it will raise a NotImplementedError.
5598 : :
5599 : : [clinic start generated code]*/
5600 : :
5601 : : static PyObject *
5602 : 0 : os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
5603 : : /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
5604 : : {
5605 : : int result;
5606 : : #ifdef HAVE_UNLINKAT
5607 : 0 : int unlinkat_unavailable = 0;
5608 : : #endif
5609 : :
5610 [ # # # # ]: 0 : if (PySys_Audit("os.remove", "Oi", path->object,
5611 : : dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5612 : 0 : return NULL;
5613 : : }
5614 : :
5615 : 0 : Py_BEGIN_ALLOW_THREADS
5616 : : _Py_BEGIN_SUPPRESS_IPH
5617 : : #ifdef MS_WINDOWS
5618 : : /* Windows, success=1, UNIX, success=0 */
5619 : : result = !Py_DeleteFileW(path->wide);
5620 : : #else
5621 : : #ifdef HAVE_UNLINKAT
5622 [ # # ]: 0 : if (dir_fd != DEFAULT_DIR_FD) {
5623 : : if (HAVE_UNLINKAT_RUNTIME) {
5624 : :
5625 : 0 : result = unlinkat(dir_fd, path->narrow, 0);
5626 : : } else {
5627 : : unlinkat_unavailable = 1;
5628 : : }
5629 : : } else
5630 : : #endif /* HAVE_UNLINKAT */
5631 : 0 : result = unlink(path->narrow);
5632 : : #endif
5633 : : _Py_END_SUPPRESS_IPH
5634 : 0 : Py_END_ALLOW_THREADS
5635 : :
5636 : : #ifdef HAVE_UNLINKAT
5637 [ # # ]: 0 : if (unlinkat_unavailable) {
5638 : 0 : argument_unavailable_error(NULL, "dir_fd");
5639 : 0 : return NULL;
5640 : : }
5641 : : #endif
5642 : :
5643 [ # # ]: 0 : if (result)
5644 : 0 : return path_error(path);
5645 : :
5646 : 0 : Py_RETURN_NONE;
5647 : : }
5648 : :
5649 : :
5650 : : /*[clinic input]
5651 : : os.remove = os.unlink
5652 : :
5653 : : Remove a file (same as unlink()).
5654 : :
5655 : : If dir_fd is not None, it should be a file descriptor open to a directory,
5656 : : and path should be relative; path will then be relative to that directory.
5657 : : dir_fd may not be implemented on your platform.
5658 : : If it is unavailable, using it will raise a NotImplementedError.
5659 : : [clinic start generated code]*/
5660 : :
5661 : : static PyObject *
5662 : 0 : os_remove_impl(PyObject *module, path_t *path, int dir_fd)
5663 : : /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
5664 : : {
5665 : 0 : return os_unlink_impl(module, path, dir_fd);
5666 : : }
5667 : :
5668 : :
5669 : : static PyStructSequence_Field uname_result_fields[] = {
5670 : : {"sysname", "operating system name"},
5671 : : {"nodename", "name of machine on network (implementation-defined)"},
5672 : : {"release", "operating system release"},
5673 : : {"version", "operating system version"},
5674 : : {"machine", "hardware identifier"},
5675 : : {NULL}
5676 : : };
5677 : :
5678 : : PyDoc_STRVAR(uname_result__doc__,
5679 : : "uname_result: Result from os.uname().\n\n\
5680 : : This object may be accessed either as a tuple of\n\
5681 : : (sysname, nodename, release, version, machine),\n\
5682 : : or via the attributes sysname, nodename, release, version, and machine.\n\
5683 : : \n\
5684 : : See os.uname for more information.");
5685 : :
5686 : : static PyStructSequence_Desc uname_result_desc = {
5687 : : MODNAME ".uname_result", /* name */
5688 : : uname_result__doc__, /* doc */
5689 : : uname_result_fields,
5690 : : 5
5691 : : };
5692 : :
5693 : : #ifdef HAVE_UNAME
5694 : : /*[clinic input]
5695 : : os.uname
5696 : :
5697 : : Return an object identifying the current operating system.
5698 : :
5699 : : The object behaves like a named tuple with the following fields:
5700 : : (sysname, nodename, release, version, machine)
5701 : :
5702 : : [clinic start generated code]*/
5703 : :
5704 : : static PyObject *
5705 : 3 : os_uname_impl(PyObject *module)
5706 : : /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
5707 : : {
5708 : : struct utsname u;
5709 : : int res;
5710 : : PyObject *value;
5711 : :
5712 : 3 : Py_BEGIN_ALLOW_THREADS
5713 : 3 : res = uname(&u);
5714 : 3 : Py_END_ALLOW_THREADS
5715 [ - + ]: 3 : if (res < 0)
5716 : 0 : return posix_error();
5717 : :
5718 : 3 : PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
5719 : 3 : value = PyStructSequence_New((PyTypeObject *)UnameResultType);
5720 [ - + ]: 3 : if (value == NULL)
5721 : 0 : return NULL;
5722 : :
5723 : : #define SET(i, field) \
5724 : : { \
5725 : : PyObject *o = PyUnicode_DecodeFSDefault(field); \
5726 : : if (!o) { \
5727 : : Py_DECREF(value); \
5728 : : return NULL; \
5729 : : } \
5730 : : PyStructSequence_SET_ITEM(value, i, o); \
5731 : : } \
5732 : :
5733 [ - + ]: 3 : SET(0, u.sysname);
5734 [ - + ]: 3 : SET(1, u.nodename);
5735 [ - + ]: 3 : SET(2, u.release);
5736 [ - + ]: 3 : SET(3, u.version);
5737 [ - + ]: 3 : SET(4, u.machine);
5738 : :
5739 : : #undef SET
5740 : :
5741 : 3 : return value;
5742 : : }
5743 : : #endif /* HAVE_UNAME */
5744 : :
5745 : :
5746 : :
5747 : : typedef struct {
5748 : : int now;
5749 : : time_t atime_s;
5750 : : long atime_ns;
5751 : : time_t mtime_s;
5752 : : long mtime_ns;
5753 : : } utime_t;
5754 : :
5755 : : /*
5756 : : * these macros assume that "ut" is a pointer to a utime_t
5757 : : * they also intentionally leak the declaration of a pointer named "time"
5758 : : */
5759 : : #define UTIME_TO_TIMESPEC \
5760 : : struct timespec ts[2]; \
5761 : : struct timespec *time; \
5762 : : if (ut->now) \
5763 : : time = NULL; \
5764 : : else { \
5765 : : ts[0].tv_sec = ut->atime_s; \
5766 : : ts[0].tv_nsec = ut->atime_ns; \
5767 : : ts[1].tv_sec = ut->mtime_s; \
5768 : : ts[1].tv_nsec = ut->mtime_ns; \
5769 : : time = ts; \
5770 : : } \
5771 : :
5772 : : #define UTIME_TO_TIMEVAL \
5773 : : struct timeval tv[2]; \
5774 : : struct timeval *time; \
5775 : : if (ut->now) \
5776 : : time = NULL; \
5777 : : else { \
5778 : : tv[0].tv_sec = ut->atime_s; \
5779 : : tv[0].tv_usec = ut->atime_ns / 1000; \
5780 : : tv[1].tv_sec = ut->mtime_s; \
5781 : : tv[1].tv_usec = ut->mtime_ns / 1000; \
5782 : : time = tv; \
5783 : : } \
5784 : :
5785 : : #define UTIME_TO_UTIMBUF \
5786 : : struct utimbuf u; \
5787 : : struct utimbuf *time; \
5788 : : if (ut->now) \
5789 : : time = NULL; \
5790 : : else { \
5791 : : u.actime = ut->atime_s; \
5792 : : u.modtime = ut->mtime_s; \
5793 : : time = &u; \
5794 : : }
5795 : :
5796 : : #define UTIME_TO_TIME_T \
5797 : : time_t timet[2]; \
5798 : : time_t *time; \
5799 : : if (ut->now) \
5800 : : time = NULL; \
5801 : : else { \
5802 : : timet[0] = ut->atime_s; \
5803 : : timet[1] = ut->mtime_s; \
5804 : : time = timet; \
5805 : : } \
5806 : :
5807 : :
5808 : : #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5809 : :
5810 : : static int
5811 : 0 : utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
5812 : : {
5813 : : #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5814 : : if (HAVE_UTIMENSAT_RUNTIME) {
5815 : : int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5816 : : UTIME_TO_TIMESPEC;
5817 : : return utimensat(dir_fd, path, time, flags);
5818 : : } else {
5819 : : errno = ENOSYS;
5820 : : return -1;
5821 : : }
5822 : : #elif defined(HAVE_UTIMENSAT)
5823 [ # # ]: 0 : int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5824 [ # # ]: 0 : UTIME_TO_TIMESPEC;
5825 : 0 : return utimensat(dir_fd, path, time, flags);
5826 : : #elif defined(HAVE_FUTIMESAT)
5827 : : UTIME_TO_TIMEVAL;
5828 : : /*
5829 : : * follow_symlinks will never be false here;
5830 : : * we only allow !follow_symlinks and dir_fd together
5831 : : * if we have utimensat()
5832 : : */
5833 : : assert(follow_symlinks);
5834 : : return futimesat(dir_fd, path, time);
5835 : : #endif
5836 : : }
5837 : :
5838 : : #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
5839 : : #else
5840 : : #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
5841 : : #endif
5842 : :
5843 : : #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5844 : :
5845 : : static int
5846 : 0 : utime_fd(utime_t *ut, int fd)
5847 : : {
5848 : : #ifdef HAVE_FUTIMENS
5849 : :
5850 : : if (HAVE_FUTIMENS_RUNTIME) {
5851 : :
5852 [ # # ]: 0 : UTIME_TO_TIMESPEC;
5853 : 0 : return futimens(fd, time);
5854 : :
5855 : : } else
5856 : : #ifndef HAVE_FUTIMES
5857 : : {
5858 : : /* Not sure if this can happen */
5859 : : PyErr_SetString(
5860 : : PyExc_RuntimeError,
5861 : : "neither futimens nor futimes are supported"
5862 : : " on this system");
5863 : : return -1;
5864 : : }
5865 : : #endif
5866 : :
5867 : : #endif
5868 : : #ifdef HAVE_FUTIMES
5869 : : {
5870 : : UTIME_TO_TIMEVAL;
5871 : : return futimes(fd, time);
5872 : : }
5873 : : #endif
5874 : : }
5875 : :
5876 : : #define PATH_UTIME_HAVE_FD 1
5877 : : #else
5878 : : #define PATH_UTIME_HAVE_FD 0
5879 : : #endif
5880 : :
5881 : : #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
5882 : : # define UTIME_HAVE_NOFOLLOW_SYMLINKS
5883 : : #endif
5884 : :
5885 : : #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5886 : :
5887 : : static int
5888 : 0 : utime_nofollow_symlinks(utime_t *ut, const char *path)
5889 : : {
5890 : : #ifdef HAVE_UTIMENSAT
5891 : : if (HAVE_UTIMENSAT_RUNTIME) {
5892 [ # # ]: 0 : UTIME_TO_TIMESPEC;
5893 : 0 : return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
5894 : : } else
5895 : : #ifndef HAVE_LUTIMES
5896 : : {
5897 : : /* Not sure if this can happen */
5898 : : PyErr_SetString(
5899 : : PyExc_RuntimeError,
5900 : : "neither utimensat nor lutimes are supported"
5901 : : " on this system");
5902 : : return -1;
5903 : : }
5904 : : #endif
5905 : : #endif
5906 : :
5907 : : #ifdef HAVE_LUTIMES
5908 : : {
5909 : : UTIME_TO_TIMEVAL;
5910 : : return lutimes(path, time);
5911 : : }
5912 : : #endif
5913 : : }
5914 : :
5915 : : #endif
5916 : :
5917 : : #ifndef MS_WINDOWS
5918 : :
5919 : : static int
5920 : 0 : utime_default(utime_t *ut, const char *path)
5921 : : {
5922 : : #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5923 : : if (HAVE_UTIMENSAT_RUNTIME) {
5924 : : UTIME_TO_TIMESPEC;
5925 : : return utimensat(DEFAULT_DIR_FD, path, time, 0);
5926 : : } else {
5927 : : UTIME_TO_TIMEVAL;
5928 : : return utimes(path, time);
5929 : : }
5930 : : #elif defined(HAVE_UTIMENSAT)
5931 [ # # ]: 0 : UTIME_TO_TIMESPEC;
5932 : 0 : return utimensat(DEFAULT_DIR_FD, path, time, 0);
5933 : : #elif defined(HAVE_UTIMES)
5934 : : UTIME_TO_TIMEVAL;
5935 : : return utimes(path, time);
5936 : : #elif defined(HAVE_UTIME_H)
5937 : : UTIME_TO_UTIMBUF;
5938 : : return utime(path, time);
5939 : : #else
5940 : : UTIME_TO_TIME_T;
5941 : : return utime(path, time);
5942 : : #endif
5943 : : }
5944 : :
5945 : : #endif
5946 : :
5947 : : static int
5948 : 0 : split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5949 : : {
5950 : 0 : int result = 0;
5951 : : PyObject *divmod;
5952 : 0 : divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5953 [ # # ]: 0 : if (!divmod)
5954 : 0 : goto exit;
5955 [ # # # # ]: 0 : if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
5956 : 0 : PyErr_Format(PyExc_TypeError,
5957 : : "%.200s.__divmod__() must return a 2-tuple, not %.200s",
5958 : : _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
5959 : 0 : goto exit;
5960 : : }
5961 : 0 : *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5962 [ # # # # ]: 0 : if ((*s == -1) && PyErr_Occurred())
5963 : 0 : goto exit;
5964 : 0 : *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5965 [ # # # # ]: 0 : if ((*ns == -1) && PyErr_Occurred())
5966 : 0 : goto exit;
5967 : :
5968 : 0 : result = 1;
5969 : 0 : exit:
5970 : 0 : Py_XDECREF(divmod);
5971 : 0 : return result;
5972 : : }
5973 : :
5974 : :
5975 : : /*[clinic input]
5976 : : os.utime
5977 : :
5978 : : path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
5979 : : times: object = None
5980 : : *
5981 : : ns: object = NULL
5982 : : dir_fd: dir_fd(requires='futimensat') = None
5983 : : follow_symlinks: bool=True
5984 : :
5985 : : # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
5986 : :
5987 : : Set the access and modified time of path.
5988 : :
5989 : : path may always be specified as a string.
5990 : : On some platforms, path may also be specified as an open file descriptor.
5991 : : If this functionality is unavailable, using it raises an exception.
5992 : :
5993 : : If times is not None, it must be a tuple (atime, mtime);
5994 : : atime and mtime should be expressed as float seconds since the epoch.
5995 : : If ns is specified, it must be a tuple (atime_ns, mtime_ns);
5996 : : atime_ns and mtime_ns should be expressed as integer nanoseconds
5997 : : since the epoch.
5998 : : If times is None and ns is unspecified, utime uses the current time.
5999 : : Specifying tuples for both times and ns is an error.
6000 : :
6001 : : If dir_fd is not None, it should be a file descriptor open to a directory,
6002 : : and path should be relative; path will then be relative to that directory.
6003 : : If follow_symlinks is False, and the last element of the path is a symbolic
6004 : : link, utime will modify the symbolic link itself instead of the file the
6005 : : link points to.
6006 : : It is an error to use dir_fd or follow_symlinks when specifying path
6007 : : as an open file descriptor.
6008 : : dir_fd and follow_symlinks may not be available on your platform.
6009 : : If they are unavailable, using them will raise a NotImplementedError.
6010 : :
6011 : : [clinic start generated code]*/
6012 : :
6013 : : static PyObject *
6014 : 0 : os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
6015 : : int dir_fd, int follow_symlinks)
6016 : : /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
6017 : : {
6018 : : #ifdef MS_WINDOWS
6019 : : HANDLE hFile;
6020 : : FILETIME atime, mtime;
6021 : : #else
6022 : : int result;
6023 : : #endif
6024 : :
6025 : : utime_t utime;
6026 : :
6027 : 0 : memset(&utime, 0, sizeof(utime_t));
6028 : :
6029 [ # # # # ]: 0 : if (times != Py_None && ns) {
6030 : 0 : PyErr_SetString(PyExc_ValueError,
6031 : : "utime: you may specify either 'times'"
6032 : : " or 'ns' but not both");
6033 : 0 : return NULL;
6034 : : }
6035 : :
6036 [ # # ]: 0 : if (times != Py_None) {
6037 : : time_t a_sec, m_sec;
6038 : : long a_nsec, m_nsec;
6039 [ # # # # ]: 0 : if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
6040 : 0 : PyErr_SetString(PyExc_TypeError,
6041 : : "utime: 'times' must be either"
6042 : : " a tuple of two ints or None");
6043 : 0 : return NULL;
6044 : : }
6045 : 0 : utime.now = 0;
6046 [ # # ]: 0 : if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
6047 [ # # ]: 0 : &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
6048 : 0 : _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
6049 : : &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
6050 : 0 : return NULL;
6051 : : }
6052 : 0 : utime.atime_s = a_sec;
6053 : 0 : utime.atime_ns = a_nsec;
6054 : 0 : utime.mtime_s = m_sec;
6055 : 0 : utime.mtime_ns = m_nsec;
6056 : : }
6057 [ # # ]: 0 : else if (ns) {
6058 [ # # # # ]: 0 : if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
6059 : 0 : PyErr_SetString(PyExc_TypeError,
6060 : : "utime: 'ns' must be a tuple of two ints");
6061 : 0 : return NULL;
6062 : : }
6063 : 0 : utime.now = 0;
6064 [ # # ]: 0 : if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
6065 [ # # ]: 0 : &utime.atime_s, &utime.atime_ns) ||
6066 : 0 : !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
6067 : : &utime.mtime_s, &utime.mtime_ns)) {
6068 : 0 : return NULL;
6069 : : }
6070 : : }
6071 : : else {
6072 : : /* times and ns are both None/unspecified. use "now". */
6073 : 0 : utime.now = 1;
6074 : : }
6075 : :
6076 : : #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
6077 : : if (follow_symlinks_specified("utime", follow_symlinks))
6078 : : return NULL;
6079 : : #endif
6080 : :
6081 [ # # # # ]: 0 : if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
6082 [ # # ]: 0 : dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
6083 : 0 : fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
6084 : 0 : return NULL;
6085 : :
6086 : : #if !defined(HAVE_UTIMENSAT)
6087 : : if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
6088 : : PyErr_SetString(PyExc_ValueError,
6089 : : "utime: cannot use dir_fd and follow_symlinks "
6090 : : "together on this platform");
6091 : : return NULL;
6092 : : }
6093 : : #endif
6094 : :
6095 [ # # # # : 0 : if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
# # ]
6096 : : dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6097 : 0 : return NULL;
6098 : : }
6099 : :
6100 : : #ifdef MS_WINDOWS
6101 : : Py_BEGIN_ALLOW_THREADS
6102 : : hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
6103 : : NULL, OPEN_EXISTING,
6104 : : FILE_FLAG_BACKUP_SEMANTICS, NULL);
6105 : : Py_END_ALLOW_THREADS
6106 : : if (hFile == INVALID_HANDLE_VALUE) {
6107 : : path_error(path);
6108 : : return NULL;
6109 : : }
6110 : :
6111 : : if (utime.now) {
6112 : : GetSystemTimeAsFileTime(&mtime);
6113 : : atime = mtime;
6114 : : }
6115 : : else {
6116 : : _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
6117 : : _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
6118 : : }
6119 : : if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
6120 : : /* Avoid putting the file name into the error here,
6121 : : as that may confuse the user into believing that
6122 : : something is wrong with the file, when it also
6123 : : could be the time stamp that gives a problem. */
6124 : : PyErr_SetFromWindowsErr(0);
6125 : : CloseHandle(hFile);
6126 : : return NULL;
6127 : : }
6128 : : CloseHandle(hFile);
6129 : : #else /* MS_WINDOWS */
6130 : 0 : Py_BEGIN_ALLOW_THREADS
6131 : :
6132 : : #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6133 [ # # # # ]: 0 : if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
6134 : 0 : result = utime_nofollow_symlinks(&utime, path->narrow);
6135 : : else
6136 : : #endif
6137 : :
6138 : : #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6139 [ # # # # ]: 0 : if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
6140 : 0 : result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
6141 : :
6142 : : } else
6143 : : #endif
6144 : :
6145 : : #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6146 [ # # ]: 0 : if (path->fd != -1)
6147 : 0 : result = utime_fd(&utime, path->fd);
6148 : : else
6149 : : #endif
6150 : :
6151 : 0 : result = utime_default(&utime, path->narrow);
6152 : :
6153 : 0 : Py_END_ALLOW_THREADS
6154 : :
6155 : : #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6156 : : /* See utime_dir_fd implementation */
6157 : : if (result == -1 && errno == ENOSYS) {
6158 : : argument_unavailable_error(NULL, "dir_fd");
6159 : : return NULL;
6160 : : }
6161 : : #endif
6162 : :
6163 [ # # ]: 0 : if (result < 0) {
6164 : : /* see previous comment about not putting filename in error here */
6165 : 0 : posix_error();
6166 : 0 : return NULL;
6167 : : }
6168 : :
6169 : : #endif /* MS_WINDOWS */
6170 : :
6171 : 0 : Py_RETURN_NONE;
6172 : : }
6173 : :
6174 : : /* Process operations */
6175 : :
6176 : :
6177 : : /*[clinic input]
6178 : : os._exit
6179 : :
6180 : : status: int
6181 : :
6182 : : Exit to the system with specified status, without normal exit processing.
6183 : : [clinic start generated code]*/
6184 : :
6185 : : static PyObject *
6186 : 0 : os__exit_impl(PyObject *module, int status)
6187 : : /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
6188 : : {
6189 : 0 : _exit(status);
6190 : : return NULL; /* Make gcc -Wall happy */
6191 : : }
6192 : :
6193 : : #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
6194 : : #define EXECV_CHAR wchar_t
6195 : : #else
6196 : : #define EXECV_CHAR char
6197 : : #endif
6198 : :
6199 : : #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
6200 : : static void
6201 : 0 : free_string_array(EXECV_CHAR **array, Py_ssize_t count)
6202 : : {
6203 : : Py_ssize_t i;
6204 [ # # ]: 0 : for (i = 0; i < count; i++)
6205 : 0 : PyMem_Free(array[i]);
6206 : 0 : PyMem_Free(array);
6207 : 0 : }
6208 : :
6209 : : static int
6210 : 0 : fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
6211 : : {
6212 : : Py_ssize_t size;
6213 : : PyObject *ub;
6214 : 0 : int result = 0;
6215 : : #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
6216 : : if (!PyUnicode_FSDecoder(o, &ub))
6217 : : return 0;
6218 : : *out = PyUnicode_AsWideCharString(ub, &size);
6219 : : if (*out)
6220 : : result = 1;
6221 : : #else
6222 [ # # ]: 0 : if (!PyUnicode_FSConverter(o, &ub))
6223 : 0 : return 0;
6224 : 0 : size = PyBytes_GET_SIZE(ub);
6225 : 0 : *out = PyMem_Malloc(size + 1);
6226 [ # # ]: 0 : if (*out) {
6227 : 0 : memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
6228 : 0 : result = 1;
6229 : : } else
6230 : 0 : PyErr_NoMemory();
6231 : : #endif
6232 : 0 : Py_DECREF(ub);
6233 : 0 : return result;
6234 : : }
6235 : : #endif
6236 : :
6237 : : #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
6238 : : static EXECV_CHAR**
6239 : 0 : parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
6240 : : {
6241 : : Py_ssize_t i, pos, envc;
6242 : 0 : PyObject *keys=NULL, *vals=NULL;
6243 : : PyObject *key, *val, *key2, *val2, *keyval;
6244 : : EXECV_CHAR **envlist;
6245 : :
6246 : 0 : i = PyMapping_Size(env);
6247 [ # # ]: 0 : if (i < 0)
6248 : 0 : return NULL;
6249 [ # # ]: 0 : envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
6250 [ # # ]: 0 : if (envlist == NULL) {
6251 : 0 : PyErr_NoMemory();
6252 : 0 : return NULL;
6253 : : }
6254 : 0 : envc = 0;
6255 : 0 : keys = PyMapping_Keys(env);
6256 [ # # ]: 0 : if (!keys)
6257 : 0 : goto error;
6258 : 0 : vals = PyMapping_Values(env);
6259 [ # # ]: 0 : if (!vals)
6260 : 0 : goto error;
6261 [ # # # # ]: 0 : if (!PyList_Check(keys) || !PyList_Check(vals)) {
6262 : 0 : PyErr_Format(PyExc_TypeError,
6263 : : "env.keys() or env.values() is not a list");
6264 : 0 : goto error;
6265 : : }
6266 : :
6267 [ # # ]: 0 : for (pos = 0; pos < i; pos++) {
6268 : 0 : key = PyList_GetItem(keys, pos);
6269 : 0 : val = PyList_GetItem(vals, pos);
6270 [ # # # # ]: 0 : if (!key || !val)
6271 : 0 : goto error;
6272 : :
6273 : : #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
6274 : : if (!PyUnicode_FSDecoder(key, &key2))
6275 : : goto error;
6276 : : if (!PyUnicode_FSDecoder(val, &val2)) {
6277 : : Py_DECREF(key2);
6278 : : goto error;
6279 : : }
6280 : : /* Search from index 1 because on Windows starting '=' is allowed for
6281 : : defining hidden environment variables. */
6282 : : if (PyUnicode_GET_LENGTH(key2) == 0 ||
6283 : : PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
6284 : : {
6285 : : PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
6286 : : Py_DECREF(key2);
6287 : : Py_DECREF(val2);
6288 : : goto error;
6289 : : }
6290 : : keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
6291 : : #else
6292 [ # # ]: 0 : if (!PyUnicode_FSConverter(key, &key2))
6293 : 0 : goto error;
6294 [ # # ]: 0 : if (!PyUnicode_FSConverter(val, &val2)) {
6295 : 0 : Py_DECREF(key2);
6296 : 0 : goto error;
6297 : : }
6298 [ # # ]: 0 : if (PyBytes_GET_SIZE(key2) == 0 ||
6299 [ # # ]: 0 : strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
6300 : : {
6301 : 0 : PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
6302 : 0 : Py_DECREF(key2);
6303 : 0 : Py_DECREF(val2);
6304 : 0 : goto error;
6305 : : }
6306 : 0 : keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
6307 : : PyBytes_AS_STRING(val2));
6308 : : #endif
6309 : 0 : Py_DECREF(key2);
6310 : 0 : Py_DECREF(val2);
6311 [ # # ]: 0 : if (!keyval)
6312 : 0 : goto error;
6313 : :
6314 [ # # ]: 0 : if (!fsconvert_strdup(keyval, &envlist[envc++])) {
6315 : 0 : Py_DECREF(keyval);
6316 : 0 : goto error;
6317 : : }
6318 : :
6319 : 0 : Py_DECREF(keyval);
6320 : : }
6321 : 0 : Py_DECREF(vals);
6322 : 0 : Py_DECREF(keys);
6323 : :
6324 : 0 : envlist[envc] = 0;
6325 : 0 : *envc_ptr = envc;
6326 : 0 : return envlist;
6327 : :
6328 : 0 : error:
6329 : 0 : Py_XDECREF(keys);
6330 : 0 : Py_XDECREF(vals);
6331 : 0 : free_string_array(envlist, envc);
6332 : 0 : return NULL;
6333 : : }
6334 : :
6335 : : static EXECV_CHAR**
6336 : 0 : parse_arglist(PyObject* argv, Py_ssize_t *argc)
6337 : : {
6338 : : int i;
6339 [ # # ]: 0 : EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
6340 [ # # ]: 0 : if (argvlist == NULL) {
6341 : 0 : PyErr_NoMemory();
6342 : 0 : return NULL;
6343 : : }
6344 [ # # ]: 0 : for (i = 0; i < *argc; i++) {
6345 : 0 : PyObject* item = PySequence_ITEM(argv, i);
6346 [ # # ]: 0 : if (item == NULL)
6347 : 0 : goto fail;
6348 [ # # ]: 0 : if (!fsconvert_strdup(item, &argvlist[i])) {
6349 : 0 : Py_DECREF(item);
6350 : 0 : goto fail;
6351 : : }
6352 : 0 : Py_DECREF(item);
6353 : : }
6354 : 0 : argvlist[*argc] = NULL;
6355 : 0 : return argvlist;
6356 : 0 : fail:
6357 : 0 : *argc = i;
6358 : 0 : free_string_array(argvlist, *argc);
6359 : 0 : return NULL;
6360 : : }
6361 : :
6362 : : #endif
6363 : :
6364 : :
6365 : : #ifdef HAVE_EXECV
6366 : : /*[clinic input]
6367 : : os.execv
6368 : :
6369 : : path: path_t
6370 : : Path of executable file.
6371 : : argv: object
6372 : : Tuple or list of strings.
6373 : : /
6374 : :
6375 : : Execute an executable path with arguments, replacing current process.
6376 : : [clinic start generated code]*/
6377 : :
6378 : : static PyObject *
6379 : 0 : os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
6380 : : /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
6381 : : {
6382 : : EXECV_CHAR **argvlist;
6383 : : Py_ssize_t argc;
6384 : :
6385 : 0 : PyInterpreterState *interp = _PyInterpreterState_GET();
6386 [ # # ]: 0 : if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
6387 : 0 : PyErr_SetString(PyExc_RuntimeError,
6388 : : "exec not supported for isolated subinterpreters");
6389 : 0 : return NULL;
6390 : : }
6391 : :
6392 : : /* execv has two arguments: (path, argv), where
6393 : : argv is a list or tuple of strings. */
6394 : :
6395 [ # # # # ]: 0 : if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6396 : 0 : PyErr_SetString(PyExc_TypeError,
6397 : : "execv() arg 2 must be a tuple or list");
6398 : 0 : return NULL;
6399 : : }
6400 : 0 : argc = PySequence_Size(argv);
6401 [ # # ]: 0 : if (argc < 1) {
6402 : 0 : PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
6403 : 0 : return NULL;
6404 : : }
6405 : :
6406 : 0 : argvlist = parse_arglist(argv, &argc);
6407 [ # # ]: 0 : if (argvlist == NULL) {
6408 : 0 : return NULL;
6409 : : }
6410 [ # # ]: 0 : if (!argvlist[0][0]) {
6411 : 0 : PyErr_SetString(PyExc_ValueError,
6412 : : "execv() arg 2 first element cannot be empty");
6413 : 0 : free_string_array(argvlist, argc);
6414 : 0 : return NULL;
6415 : : }
6416 : :
6417 [ # # ]: 0 : if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
6418 : 0 : free_string_array(argvlist, argc);
6419 : 0 : return NULL;
6420 : : }
6421 : :
6422 : : _Py_BEGIN_SUPPRESS_IPH
6423 : : #ifdef HAVE_WEXECV
6424 : : _wexecv(path->wide, argvlist);
6425 : : #else
6426 : 0 : execv(path->narrow, argvlist);
6427 : : #endif
6428 : : _Py_END_SUPPRESS_IPH
6429 : :
6430 : : /* If we get here it's definitely an error */
6431 : :
6432 : 0 : free_string_array(argvlist, argc);
6433 : 0 : return posix_error();
6434 : : }
6435 : :
6436 : :
6437 : : /*[clinic input]
6438 : : os.execve
6439 : :
6440 : : path: path_t(allow_fd='PATH_HAVE_FEXECVE')
6441 : : Path of executable file.
6442 : : argv: object
6443 : : Tuple or list of strings.
6444 : : env: object
6445 : : Dictionary of strings mapping to strings.
6446 : :
6447 : : Execute an executable path with arguments, replacing current process.
6448 : : [clinic start generated code]*/
6449 : :
6450 : : static PyObject *
6451 : 0 : os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
6452 : : /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
6453 : : {
6454 : 0 : EXECV_CHAR **argvlist = NULL;
6455 : : EXECV_CHAR **envlist;
6456 : : Py_ssize_t argc, envc;
6457 : :
6458 : 0 : PyInterpreterState *interp = _PyInterpreterState_GET();
6459 [ # # ]: 0 : if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
6460 : 0 : PyErr_SetString(PyExc_RuntimeError,
6461 : : "exec not supported for isolated subinterpreters");
6462 : 0 : return NULL;
6463 : : }
6464 : :
6465 : : /* execve has three arguments: (path, argv, env), where
6466 : : argv is a list or tuple of strings and env is a dictionary
6467 : : like posix.environ. */
6468 : :
6469 [ # # # # ]: 0 : if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6470 : 0 : PyErr_SetString(PyExc_TypeError,
6471 : : "execve: argv must be a tuple or list");
6472 : 0 : goto fail_0;
6473 : : }
6474 : 0 : argc = PySequence_Size(argv);
6475 [ # # ]: 0 : if (argc < 1) {
6476 : 0 : PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
6477 : 0 : return NULL;
6478 : : }
6479 : :
6480 [ # # ]: 0 : if (!PyMapping_Check(env)) {
6481 : 0 : PyErr_SetString(PyExc_TypeError,
6482 : : "execve: environment must be a mapping object");
6483 : 0 : goto fail_0;
6484 : : }
6485 : :
6486 : 0 : argvlist = parse_arglist(argv, &argc);
6487 [ # # ]: 0 : if (argvlist == NULL) {
6488 : 0 : goto fail_0;
6489 : : }
6490 [ # # ]: 0 : if (!argvlist[0][0]) {
6491 : 0 : PyErr_SetString(PyExc_ValueError,
6492 : : "execve: argv first element cannot be empty");
6493 : 0 : goto fail_0;
6494 : : }
6495 : :
6496 : 0 : envlist = parse_envlist(env, &envc);
6497 [ # # ]: 0 : if (envlist == NULL)
6498 : 0 : goto fail_0;
6499 : :
6500 [ # # ]: 0 : if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
6501 : 0 : goto fail_1;
6502 : : }
6503 : :
6504 : : _Py_BEGIN_SUPPRESS_IPH
6505 : : #ifdef HAVE_FEXECVE
6506 [ # # ]: 0 : if (path->fd > -1)
6507 : 0 : fexecve(path->fd, argvlist, envlist);
6508 : : else
6509 : : #endif
6510 : : #ifdef HAVE_WEXECV
6511 : : _wexecve(path->wide, argvlist, envlist);
6512 : : #else
6513 : 0 : execve(path->narrow, argvlist, envlist);
6514 : : #endif
6515 : : _Py_END_SUPPRESS_IPH
6516 : :
6517 : : /* If we get here it's definitely an error */
6518 : :
6519 : 0 : posix_path_error(path);
6520 : 0 : fail_1:
6521 : 0 : free_string_array(envlist, envc);
6522 : 0 : fail_0:
6523 [ # # ]: 0 : if (argvlist)
6524 : 0 : free_string_array(argvlist, argc);
6525 : 0 : return NULL;
6526 : : }
6527 : :
6528 : : #endif /* HAVE_EXECV */
6529 : :
6530 : : #ifdef HAVE_POSIX_SPAWN
6531 : :
6532 : : enum posix_spawn_file_actions_identifier {
6533 : : POSIX_SPAWN_OPEN,
6534 : : POSIX_SPAWN_CLOSE,
6535 : : POSIX_SPAWN_DUP2
6536 : : };
6537 : :
6538 : : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6539 : : static int
6540 : : convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
6541 : : #endif
6542 : :
6543 : : static int
6544 : 0 : parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
6545 : : int resetids, int setsid, PyObject *setsigmask,
6546 : : PyObject *setsigdef, PyObject *scheduler,
6547 : : posix_spawnattr_t *attrp)
6548 : : {
6549 : 0 : long all_flags = 0;
6550 : :
6551 : 0 : errno = posix_spawnattr_init(attrp);
6552 [ # # ]: 0 : if (errno) {
6553 : 0 : posix_error();
6554 : 0 : return -1;
6555 : : }
6556 : :
6557 [ # # ]: 0 : if (setpgroup) {
6558 : 0 : pid_t pgid = PyLong_AsPid(setpgroup);
6559 [ # # # # ]: 0 : if (pgid == (pid_t)-1 && PyErr_Occurred()) {
6560 : 0 : goto fail;
6561 : : }
6562 : 0 : errno = posix_spawnattr_setpgroup(attrp, pgid);
6563 [ # # ]: 0 : if (errno) {
6564 : 0 : posix_error();
6565 : 0 : goto fail;
6566 : : }
6567 : 0 : all_flags |= POSIX_SPAWN_SETPGROUP;
6568 : : }
6569 : :
6570 [ # # ]: 0 : if (resetids) {
6571 : 0 : all_flags |= POSIX_SPAWN_RESETIDS;
6572 : : }
6573 : :
6574 [ # # ]: 0 : if (setsid) {
6575 : : #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
6576 : : if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
6577 : : #endif
6578 : : #ifdef POSIX_SPAWN_SETSID
6579 : 0 : all_flags |= POSIX_SPAWN_SETSID;
6580 : : #elif defined(POSIX_SPAWN_SETSID_NP)
6581 : : all_flags |= POSIX_SPAWN_SETSID_NP;
6582 : : #else
6583 : : argument_unavailable_error(func_name, "setsid");
6584 : : return -1;
6585 : : #endif
6586 : :
6587 : : #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
6588 : : } else {
6589 : : argument_unavailable_error(func_name, "setsid");
6590 : : return -1;
6591 : : }
6592 : : #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
6593 : :
6594 : : }
6595 : :
6596 : : #ifdef HAVE_SIGSET_T
6597 [ # # ]: 0 : if (setsigmask) {
6598 : : sigset_t set;
6599 [ # # ]: 0 : if (!_Py_Sigset_Converter(setsigmask, &set)) {
6600 : 0 : goto fail;
6601 : : }
6602 : 0 : errno = posix_spawnattr_setsigmask(attrp, &set);
6603 [ # # ]: 0 : if (errno) {
6604 : 0 : posix_error();
6605 : 0 : goto fail;
6606 : : }
6607 : 0 : all_flags |= POSIX_SPAWN_SETSIGMASK;
6608 : : }
6609 : :
6610 [ # # ]: 0 : if (setsigdef) {
6611 : : sigset_t set;
6612 [ # # ]: 0 : if (!_Py_Sigset_Converter(setsigdef, &set)) {
6613 : 0 : goto fail;
6614 : : }
6615 : 0 : errno = posix_spawnattr_setsigdefault(attrp, &set);
6616 [ # # ]: 0 : if (errno) {
6617 : 0 : posix_error();
6618 : 0 : goto fail;
6619 : : }
6620 : 0 : all_flags |= POSIX_SPAWN_SETSIGDEF;
6621 : : }
6622 : : #else
6623 : : if (setsigmask || setsigdef) {
6624 : : PyErr_SetString(PyExc_NotImplementedError,
6625 : : "sigset is not supported on this platform");
6626 : : goto fail;
6627 : : }
6628 : : #endif
6629 : :
6630 [ # # ]: 0 : if (scheduler) {
6631 : : #ifdef POSIX_SPAWN_SETSCHEDULER
6632 : : PyObject *py_schedpolicy;
6633 : : PyObject *schedparam_obj;
6634 : : struct sched_param schedparam;
6635 : :
6636 [ # # ]: 0 : if (!PyArg_ParseTuple(scheduler, "OO"
6637 : : ";A scheduler tuple must have two elements",
6638 : : &py_schedpolicy, &schedparam_obj)) {
6639 : 0 : goto fail;
6640 : : }
6641 [ # # ]: 0 : if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
6642 : 0 : goto fail;
6643 : : }
6644 [ # # ]: 0 : if (py_schedpolicy != Py_None) {
6645 : 0 : int schedpolicy = _PyLong_AsInt(py_schedpolicy);
6646 : :
6647 [ # # # # ]: 0 : if (schedpolicy == -1 && PyErr_Occurred()) {
6648 : 0 : goto fail;
6649 : : }
6650 : 0 : errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
6651 [ # # ]: 0 : if (errno) {
6652 : 0 : posix_error();
6653 : 0 : goto fail;
6654 : : }
6655 : 0 : all_flags |= POSIX_SPAWN_SETSCHEDULER;
6656 : : }
6657 : 0 : errno = posix_spawnattr_setschedparam(attrp, &schedparam);
6658 [ # # ]: 0 : if (errno) {
6659 : 0 : posix_error();
6660 : 0 : goto fail;
6661 : : }
6662 : 0 : all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
6663 : : #else
6664 : : PyErr_SetString(PyExc_NotImplementedError,
6665 : : "The scheduler option is not supported in this system.");
6666 : : goto fail;
6667 : : #endif
6668 : : }
6669 : :
6670 : 0 : errno = posix_spawnattr_setflags(attrp, all_flags);
6671 [ # # ]: 0 : if (errno) {
6672 : 0 : posix_error();
6673 : 0 : goto fail;
6674 : : }
6675 : :
6676 : 0 : return 0;
6677 : :
6678 : 0 : fail:
6679 : 0 : (void)posix_spawnattr_destroy(attrp);
6680 : 0 : return -1;
6681 : : }
6682 : :
6683 : : static int
6684 : 0 : parse_file_actions(PyObject *file_actions,
6685 : : posix_spawn_file_actions_t *file_actionsp,
6686 : : PyObject *temp_buffer)
6687 : : {
6688 : : PyObject *seq;
6689 : 0 : PyObject *file_action = NULL;
6690 : : PyObject *tag_obj;
6691 : :
6692 : 0 : seq = PySequence_Fast(file_actions,
6693 : : "file_actions must be a sequence or None");
6694 [ # # ]: 0 : if (seq == NULL) {
6695 : 0 : return -1;
6696 : : }
6697 : :
6698 : 0 : errno = posix_spawn_file_actions_init(file_actionsp);
6699 [ # # ]: 0 : if (errno) {
6700 : 0 : posix_error();
6701 : 0 : Py_DECREF(seq);
6702 : 0 : return -1;
6703 : : }
6704 : :
6705 [ # # # # ]: 0 : for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
6706 [ # # ]: 0 : file_action = PySequence_Fast_GET_ITEM(seq, i);
6707 : 0 : Py_INCREF(file_action);
6708 [ # # # # ]: 0 : if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
6709 : 0 : PyErr_SetString(PyExc_TypeError,
6710 : : "Each file_actions element must be a non-empty tuple");
6711 : 0 : goto fail;
6712 : : }
6713 : 0 : long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
6714 [ # # # # ]: 0 : if (tag == -1 && PyErr_Occurred()) {
6715 : 0 : goto fail;
6716 : : }
6717 : :
6718 : : /* Populate the file_actions object */
6719 [ # # # # ]: 0 : switch (tag) {
6720 : 0 : case POSIX_SPAWN_OPEN: {
6721 : : int fd, oflag;
6722 : : PyObject *path;
6723 : : unsigned long mode;
6724 [ # # ]: 0 : if (!PyArg_ParseTuple(file_action, "OiO&ik"
6725 : : ";A open file_action tuple must have 5 elements",
6726 : : &tag_obj, &fd, PyUnicode_FSConverter, &path,
6727 : : &oflag, &mode))
6728 : : {
6729 : 0 : goto fail;
6730 : : }
6731 [ # # ]: 0 : if (PyList_Append(temp_buffer, path)) {
6732 : 0 : Py_DECREF(path);
6733 : 0 : goto fail;
6734 : : }
6735 : 0 : errno = posix_spawn_file_actions_addopen(file_actionsp,
6736 : 0 : fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
6737 : 0 : Py_DECREF(path);
6738 [ # # ]: 0 : if (errno) {
6739 : 0 : posix_error();
6740 : 0 : goto fail;
6741 : : }
6742 : 0 : break;
6743 : : }
6744 : 0 : case POSIX_SPAWN_CLOSE: {
6745 : : int fd;
6746 [ # # ]: 0 : if (!PyArg_ParseTuple(file_action, "Oi"
6747 : : ";A close file_action tuple must have 2 elements",
6748 : : &tag_obj, &fd))
6749 : : {
6750 : 0 : goto fail;
6751 : : }
6752 : 0 : errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
6753 [ # # ]: 0 : if (errno) {
6754 : 0 : posix_error();
6755 : 0 : goto fail;
6756 : : }
6757 : 0 : break;
6758 : : }
6759 : 0 : case POSIX_SPAWN_DUP2: {
6760 : : int fd1, fd2;
6761 [ # # ]: 0 : if (!PyArg_ParseTuple(file_action, "Oii"
6762 : : ";A dup2 file_action tuple must have 3 elements",
6763 : : &tag_obj, &fd1, &fd2))
6764 : : {
6765 : 0 : goto fail;
6766 : : }
6767 : 0 : errno = posix_spawn_file_actions_adddup2(file_actionsp,
6768 : : fd1, fd2);
6769 [ # # ]: 0 : if (errno) {
6770 : 0 : posix_error();
6771 : 0 : goto fail;
6772 : : }
6773 : 0 : break;
6774 : : }
6775 : 0 : default: {
6776 : 0 : PyErr_SetString(PyExc_TypeError,
6777 : : "Unknown file_actions identifier");
6778 : 0 : goto fail;
6779 : : }
6780 : : }
6781 : 0 : Py_DECREF(file_action);
6782 : : }
6783 : :
6784 : 0 : Py_DECREF(seq);
6785 : 0 : return 0;
6786 : :
6787 : 0 : fail:
6788 : 0 : Py_DECREF(seq);
6789 : 0 : Py_DECREF(file_action);
6790 : 0 : (void)posix_spawn_file_actions_destroy(file_actionsp);
6791 : 0 : return -1;
6792 : : }
6793 : :
6794 : :
6795 : : static PyObject *
6796 : 0 : py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
6797 : : PyObject *env, PyObject *file_actions,
6798 : : PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
6799 : : PyObject *setsigdef, PyObject *scheduler)
6800 : : {
6801 [ # # ]: 0 : const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
6802 : 0 : EXECV_CHAR **argvlist = NULL;
6803 : 0 : EXECV_CHAR **envlist = NULL;
6804 : : posix_spawn_file_actions_t file_actions_buf;
6805 : 0 : posix_spawn_file_actions_t *file_actionsp = NULL;
6806 : : posix_spawnattr_t attr;
6807 : 0 : posix_spawnattr_t *attrp = NULL;
6808 : : Py_ssize_t argc, envc;
6809 : 0 : PyObject *result = NULL;
6810 : 0 : PyObject *temp_buffer = NULL;
6811 : : pid_t pid;
6812 : : int err_code;
6813 : :
6814 : : /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
6815 : : argv is a list or tuple of strings and env is a dictionary
6816 : : like posix.environ. */
6817 : :
6818 [ # # # # ]: 0 : if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6819 : 0 : PyErr_Format(PyExc_TypeError,
6820 : : "%s: argv must be a tuple or list", func_name);
6821 : 0 : goto exit;
6822 : : }
6823 : 0 : argc = PySequence_Size(argv);
6824 [ # # ]: 0 : if (argc < 1) {
6825 : 0 : PyErr_Format(PyExc_ValueError,
6826 : : "%s: argv must not be empty", func_name);
6827 : 0 : return NULL;
6828 : : }
6829 : :
6830 [ # # ]: 0 : if (!PyMapping_Check(env)) {
6831 : 0 : PyErr_Format(PyExc_TypeError,
6832 : : "%s: environment must be a mapping object", func_name);
6833 : 0 : goto exit;
6834 : : }
6835 : :
6836 : 0 : argvlist = parse_arglist(argv, &argc);
6837 [ # # ]: 0 : if (argvlist == NULL) {
6838 : 0 : goto exit;
6839 : : }
6840 [ # # ]: 0 : if (!argvlist[0][0]) {
6841 : 0 : PyErr_Format(PyExc_ValueError,
6842 : : "%s: argv first element cannot be empty", func_name);
6843 : 0 : goto exit;
6844 : : }
6845 : :
6846 : 0 : envlist = parse_envlist(env, &envc);
6847 [ # # ]: 0 : if (envlist == NULL) {
6848 : 0 : goto exit;
6849 : : }
6850 : :
6851 [ # # # # ]: 0 : if (file_actions != NULL && file_actions != Py_None) {
6852 : : /* There is a bug in old versions of glibc that makes some of the
6853 : : * helper functions for manipulating file actions not copy the provided
6854 : : * buffers. The problem is that posix_spawn_file_actions_addopen does not
6855 : : * copy the value of path for some old versions of glibc (<2.20).
6856 : : * The use of temp_buffer here is a workaround that keeps the
6857 : : * python objects that own the buffers alive until posix_spawn gets called.
6858 : : * Check https://bugs.python.org/issue33630 and
6859 : : * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
6860 : 0 : temp_buffer = PyList_New(0);
6861 [ # # ]: 0 : if (!temp_buffer) {
6862 : 0 : goto exit;
6863 : : }
6864 [ # # ]: 0 : if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
6865 : 0 : goto exit;
6866 : : }
6867 : 0 : file_actionsp = &file_actions_buf;
6868 : : }
6869 : :
6870 [ # # ]: 0 : if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
6871 : : setsigmask, setsigdef, scheduler, &attr)) {
6872 : 0 : goto exit;
6873 : : }
6874 : 0 : attrp = &attr;
6875 : :
6876 [ # # ]: 0 : if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
6877 : 0 : goto exit;
6878 : : }
6879 : :
6880 : : _Py_BEGIN_SUPPRESS_IPH
6881 : : #ifdef HAVE_POSIX_SPAWNP
6882 [ # # ]: 0 : if (use_posix_spawnp) {
6883 : 0 : err_code = posix_spawnp(&pid, path->narrow,
6884 : : file_actionsp, attrp, argvlist, envlist);
6885 : : }
6886 : : else
6887 : : #endif /* HAVE_POSIX_SPAWNP */
6888 : : {
6889 : 0 : err_code = posix_spawn(&pid, path->narrow,
6890 : : file_actionsp, attrp, argvlist, envlist);
6891 : : }
6892 : : _Py_END_SUPPRESS_IPH
6893 : :
6894 [ # # ]: 0 : if (err_code) {
6895 : 0 : errno = err_code;
6896 : 0 : PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
6897 : 0 : goto exit;
6898 : : }
6899 : : #ifdef _Py_MEMORY_SANITIZER
6900 : : __msan_unpoison(&pid, sizeof(pid));
6901 : : #endif
6902 : 0 : result = PyLong_FromPid(pid);
6903 : :
6904 : 0 : exit:
6905 [ # # ]: 0 : if (file_actionsp) {
6906 : 0 : (void)posix_spawn_file_actions_destroy(file_actionsp);
6907 : : }
6908 [ # # ]: 0 : if (attrp) {
6909 : 0 : (void)posix_spawnattr_destroy(attrp);
6910 : : }
6911 [ # # ]: 0 : if (envlist) {
6912 : 0 : free_string_array(envlist, envc);
6913 : : }
6914 [ # # ]: 0 : if (argvlist) {
6915 : 0 : free_string_array(argvlist, argc);
6916 : : }
6917 : 0 : Py_XDECREF(temp_buffer);
6918 : 0 : return result;
6919 : : }
6920 : :
6921 : :
6922 : : /*[clinic input]
6923 : :
6924 : : os.posix_spawn
6925 : : path: path_t
6926 : : Path of executable file.
6927 : : argv: object
6928 : : Tuple or list of strings.
6929 : : env: object
6930 : : Dictionary of strings mapping to strings.
6931 : : /
6932 : : *
6933 : : file_actions: object(c_default='NULL') = ()
6934 : : A sequence of file action tuples.
6935 : : setpgroup: object = NULL
6936 : : The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6937 : : resetids: bool = False
6938 : : If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
6939 : : setsid: bool = False
6940 : : If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6941 : : setsigmask: object(c_default='NULL') = ()
6942 : : The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6943 : : setsigdef: object(c_default='NULL') = ()
6944 : : The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6945 : : scheduler: object = NULL
6946 : : A tuple with the scheduler policy (optional) and parameters.
6947 : :
6948 : : Execute the program specified by path in a new process.
6949 : : [clinic start generated code]*/
6950 : :
6951 : : static PyObject *
6952 : 0 : os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
6953 : : PyObject *env, PyObject *file_actions,
6954 : : PyObject *setpgroup, int resetids, int setsid,
6955 : : PyObject *setsigmask, PyObject *setsigdef,
6956 : : PyObject *scheduler)
6957 : : /*[clinic end generated code: output=14a1098c566bc675 input=808aed1090d84e33]*/
6958 : : {
6959 : 0 : return py_posix_spawn(0, module, path, argv, env, file_actions,
6960 : : setpgroup, resetids, setsid, setsigmask, setsigdef,
6961 : : scheduler);
6962 : : }
6963 : : #endif /* HAVE_POSIX_SPAWN */
6964 : :
6965 : :
6966 : :
6967 : : #ifdef HAVE_POSIX_SPAWNP
6968 : : /*[clinic input]
6969 : :
6970 : : os.posix_spawnp
6971 : : path: path_t
6972 : : Path of executable file.
6973 : : argv: object
6974 : : Tuple or list of strings.
6975 : : env: object
6976 : : Dictionary of strings mapping to strings.
6977 : : /
6978 : : *
6979 : : file_actions: object(c_default='NULL') = ()
6980 : : A sequence of file action tuples.
6981 : : setpgroup: object = NULL
6982 : : The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6983 : : resetids: bool = False
6984 : : If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
6985 : : setsid: bool = False
6986 : : If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6987 : : setsigmask: object(c_default='NULL') = ()
6988 : : The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6989 : : setsigdef: object(c_default='NULL') = ()
6990 : : The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6991 : : scheduler: object = NULL
6992 : : A tuple with the scheduler policy (optional) and parameters.
6993 : :
6994 : : Execute the program specified by path in a new process.
6995 : : [clinic start generated code]*/
6996 : :
6997 : : static PyObject *
6998 : 0 : os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
6999 : : PyObject *env, PyObject *file_actions,
7000 : : PyObject *setpgroup, int resetids, int setsid,
7001 : : PyObject *setsigmask, PyObject *setsigdef,
7002 : : PyObject *scheduler)
7003 : : /*[clinic end generated code: output=7b9aaefe3031238d input=9e89e616116752a1]*/
7004 : : {
7005 : 0 : return py_posix_spawn(1, module, path, argv, env, file_actions,
7006 : : setpgroup, resetids, setsid, setsigmask, setsigdef,
7007 : : scheduler);
7008 : : }
7009 : : #endif /* HAVE_POSIX_SPAWNP */
7010 : :
7011 : : #ifdef HAVE_RTPSPAWN
7012 : : static intptr_t
7013 : : _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
7014 : : const char *envp[])
7015 : : {
7016 : : RTP_ID rtpid;
7017 : : int status;
7018 : : pid_t res;
7019 : : int async_err = 0;
7020 : :
7021 : : /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
7022 : : uStackSize=0 cannot be used, the default stack size is too small for
7023 : : Python. */
7024 : : if (envp) {
7025 : : rtpid = rtpSpawn(rtpFileName, argv, envp,
7026 : : 100, 0x1000000, 0, VX_FP_TASK);
7027 : : }
7028 : : else {
7029 : : rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
7030 : : 100, 0x1000000, 0, VX_FP_TASK);
7031 : : }
7032 : : if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
7033 : : do {
7034 : : res = waitpid((pid_t)rtpid, &status, 0);
7035 : : } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7036 : :
7037 : : if (res < 0)
7038 : : return RTP_ID_ERROR;
7039 : : return ((intptr_t)status);
7040 : : }
7041 : : return ((intptr_t)rtpid);
7042 : : }
7043 : : #endif
7044 : :
7045 : : #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
7046 : : /*[clinic input]
7047 : : os.spawnv
7048 : :
7049 : : mode: int
7050 : : Mode of process creation.
7051 : : path: path_t
7052 : : Path of executable file.
7053 : : argv: object
7054 : : Tuple or list of strings.
7055 : : /
7056 : :
7057 : : Execute the program specified by path in a new process.
7058 : : [clinic start generated code]*/
7059 : :
7060 : : static PyObject *
7061 : : os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
7062 : : /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
7063 : : {
7064 : : EXECV_CHAR **argvlist;
7065 : : int i;
7066 : : Py_ssize_t argc;
7067 : : intptr_t spawnval;
7068 : : PyObject *(*getitem)(PyObject *, Py_ssize_t);
7069 : :
7070 : : /* spawnv has three arguments: (mode, path, argv), where
7071 : : argv is a list or tuple of strings. */
7072 : :
7073 : : if (PyList_Check(argv)) {
7074 : : argc = PyList_Size(argv);
7075 : : getitem = PyList_GetItem;
7076 : : }
7077 : : else if (PyTuple_Check(argv)) {
7078 : : argc = PyTuple_Size(argv);
7079 : : getitem = PyTuple_GetItem;
7080 : : }
7081 : : else {
7082 : : PyErr_SetString(PyExc_TypeError,
7083 : : "spawnv() arg 2 must be a tuple or list");
7084 : : return NULL;
7085 : : }
7086 : : if (argc == 0) {
7087 : : PyErr_SetString(PyExc_ValueError,
7088 : : "spawnv() arg 2 cannot be empty");
7089 : : return NULL;
7090 : : }
7091 : :
7092 : : argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
7093 : : if (argvlist == NULL) {
7094 : : return PyErr_NoMemory();
7095 : : }
7096 : : for (i = 0; i < argc; i++) {
7097 : : if (!fsconvert_strdup((*getitem)(argv, i),
7098 : : &argvlist[i])) {
7099 : : free_string_array(argvlist, i);
7100 : : PyErr_SetString(
7101 : : PyExc_TypeError,
7102 : : "spawnv() arg 2 must contain only strings");
7103 : : return NULL;
7104 : : }
7105 : : if (i == 0 && !argvlist[0][0]) {
7106 : : free_string_array(argvlist, i + 1);
7107 : : PyErr_SetString(
7108 : : PyExc_ValueError,
7109 : : "spawnv() arg 2 first element cannot be empty");
7110 : : return NULL;
7111 : : }
7112 : : }
7113 : : argvlist[argc] = NULL;
7114 : :
7115 : : #if !defined(HAVE_RTPSPAWN)
7116 : : if (mode == _OLD_P_OVERLAY)
7117 : : mode = _P_OVERLAY;
7118 : : #endif
7119 : :
7120 : : if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
7121 : : Py_None) < 0) {
7122 : : free_string_array(argvlist, argc);
7123 : : return NULL;
7124 : : }
7125 : :
7126 : : Py_BEGIN_ALLOW_THREADS
7127 : : _Py_BEGIN_SUPPRESS_IPH
7128 : : #ifdef HAVE_WSPAWNV
7129 : : spawnval = _wspawnv(mode, path->wide, argvlist);
7130 : : #elif defined(HAVE_RTPSPAWN)
7131 : : spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
7132 : : #else
7133 : : spawnval = _spawnv(mode, path->narrow, argvlist);
7134 : : #endif
7135 : : _Py_END_SUPPRESS_IPH
7136 : : Py_END_ALLOW_THREADS
7137 : :
7138 : : free_string_array(argvlist, argc);
7139 : :
7140 : : if (spawnval == -1)
7141 : : return posix_error();
7142 : : else
7143 : : return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
7144 : : }
7145 : :
7146 : : /*[clinic input]
7147 : : os.spawnve
7148 : :
7149 : : mode: int
7150 : : Mode of process creation.
7151 : : path: path_t
7152 : : Path of executable file.
7153 : : argv: object
7154 : : Tuple or list of strings.
7155 : : env: object
7156 : : Dictionary of strings mapping to strings.
7157 : : /
7158 : :
7159 : : Execute the program specified by path in a new process.
7160 : : [clinic start generated code]*/
7161 : :
7162 : : static PyObject *
7163 : : os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
7164 : : PyObject *env)
7165 : : /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
7166 : : {
7167 : : EXECV_CHAR **argvlist;
7168 : : EXECV_CHAR **envlist;
7169 : : PyObject *res = NULL;
7170 : : Py_ssize_t argc, i, envc;
7171 : : intptr_t spawnval;
7172 : : PyObject *(*getitem)(PyObject *, Py_ssize_t);
7173 : : Py_ssize_t lastarg = 0;
7174 : :
7175 : : /* spawnve has four arguments: (mode, path, argv, env), where
7176 : : argv is a list or tuple of strings and env is a dictionary
7177 : : like posix.environ. */
7178 : :
7179 : : if (PyList_Check(argv)) {
7180 : : argc = PyList_Size(argv);
7181 : : getitem = PyList_GetItem;
7182 : : }
7183 : : else if (PyTuple_Check(argv)) {
7184 : : argc = PyTuple_Size(argv);
7185 : : getitem = PyTuple_GetItem;
7186 : : }
7187 : : else {
7188 : : PyErr_SetString(PyExc_TypeError,
7189 : : "spawnve() arg 2 must be a tuple or list");
7190 : : goto fail_0;
7191 : : }
7192 : : if (argc == 0) {
7193 : : PyErr_SetString(PyExc_ValueError,
7194 : : "spawnve() arg 2 cannot be empty");
7195 : : goto fail_0;
7196 : : }
7197 : : if (!PyMapping_Check(env)) {
7198 : : PyErr_SetString(PyExc_TypeError,
7199 : : "spawnve() arg 3 must be a mapping object");
7200 : : goto fail_0;
7201 : : }
7202 : :
7203 : : argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
7204 : : if (argvlist == NULL) {
7205 : : PyErr_NoMemory();
7206 : : goto fail_0;
7207 : : }
7208 : : for (i = 0; i < argc; i++) {
7209 : : if (!fsconvert_strdup((*getitem)(argv, i),
7210 : : &argvlist[i]))
7211 : : {
7212 : : lastarg = i;
7213 : : goto fail_1;
7214 : : }
7215 : : if (i == 0 && !argvlist[0][0]) {
7216 : : lastarg = i + 1;
7217 : : PyErr_SetString(
7218 : : PyExc_ValueError,
7219 : : "spawnv() arg 2 first element cannot be empty");
7220 : : goto fail_1;
7221 : : }
7222 : : }
7223 : : lastarg = argc;
7224 : : argvlist[argc] = NULL;
7225 : :
7226 : : envlist = parse_envlist(env, &envc);
7227 : : if (envlist == NULL)
7228 : : goto fail_1;
7229 : :
7230 : : #if !defined(HAVE_RTPSPAWN)
7231 : : if (mode == _OLD_P_OVERLAY)
7232 : : mode = _P_OVERLAY;
7233 : : #endif
7234 : :
7235 : : if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
7236 : : goto fail_2;
7237 : : }
7238 : :
7239 : : Py_BEGIN_ALLOW_THREADS
7240 : : _Py_BEGIN_SUPPRESS_IPH
7241 : : #ifdef HAVE_WSPAWNV
7242 : : spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
7243 : : #elif defined(HAVE_RTPSPAWN)
7244 : : spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
7245 : : (const char **)envlist);
7246 : : #else
7247 : : spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
7248 : : #endif
7249 : : _Py_END_SUPPRESS_IPH
7250 : : Py_END_ALLOW_THREADS
7251 : :
7252 : : if (spawnval == -1)
7253 : : (void) posix_error();
7254 : : else
7255 : : res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
7256 : :
7257 : : fail_2:
7258 : : while (--envc >= 0) {
7259 : : PyMem_Free(envlist[envc]);
7260 : : }
7261 : : PyMem_Free(envlist);
7262 : : fail_1:
7263 : : free_string_array(argvlist, lastarg);
7264 : : fail_0:
7265 : : return res;
7266 : : }
7267 : :
7268 : : #endif /* HAVE_SPAWNV */
7269 : :
7270 : : #ifdef HAVE_FORK
7271 : :
7272 : : /* Helper function to validate arguments.
7273 : : Returns 0 on success. non-zero on failure with a TypeError raised.
7274 : : If obj is non-NULL it must be callable. */
7275 : : static int
7276 : 21 : check_null_or_callable(PyObject *obj, const char* obj_name)
7277 : : {
7278 [ + + - + ]: 21 : if (obj && !PyCallable_Check(obj)) {
7279 : 0 : PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
7280 : : obj_name, _PyType_Name(Py_TYPE(obj)));
7281 : 0 : return -1;
7282 : : }
7283 : 21 : return 0;
7284 : : }
7285 : :
7286 : : /*[clinic input]
7287 : : os.register_at_fork
7288 : :
7289 : : *
7290 : : before: object=NULL
7291 : : A callable to be called in the parent before the fork() syscall.
7292 : : after_in_child: object=NULL
7293 : : A callable to be called in the child after fork().
7294 : : after_in_parent: object=NULL
7295 : : A callable to be called in the parent after fork().
7296 : :
7297 : : Register callables to be called when forking a new process.
7298 : :
7299 : : 'before' callbacks are called in reverse order.
7300 : : 'after_in_child' and 'after_in_parent' callbacks are called in order.
7301 : :
7302 : : [clinic start generated code]*/
7303 : :
7304 : : static PyObject *
7305 : 7 : os_register_at_fork_impl(PyObject *module, PyObject *before,
7306 : : PyObject *after_in_child, PyObject *after_in_parent)
7307 : : /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
7308 : : {
7309 : : PyInterpreterState *interp;
7310 : :
7311 [ + + - + : 7 : if (!before && !after_in_child && !after_in_parent) {
- - ]
7312 : 0 : PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
7313 : 0 : return NULL;
7314 : : }
7315 [ + - + - ]: 14 : if (check_null_or_callable(before, "before") ||
7316 [ - + ]: 14 : check_null_or_callable(after_in_child, "after_in_child") ||
7317 : 7 : check_null_or_callable(after_in_parent, "after_in_parent")) {
7318 : 0 : return NULL;
7319 : : }
7320 : 7 : interp = _PyInterpreterState_GET();
7321 : :
7322 [ - + ]: 7 : if (register_at_forker(&interp->before_forkers, before)) {
7323 : 0 : return NULL;
7324 : : }
7325 [ - + ]: 7 : if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
7326 : 0 : return NULL;
7327 : : }
7328 [ - + ]: 7 : if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
7329 : 0 : return NULL;
7330 : : }
7331 : 7 : Py_RETURN_NONE;
7332 : : }
7333 : : #endif /* HAVE_FORK */
7334 : :
7335 : : // Common code to raise a warning if we detect there is more than one thread
7336 : : // running in the process. Best effort, silent if unable to count threads.
7337 : : // Constraint: Quick. Never overcounts. Never leaves an error set.
7338 : : //
7339 : : // This code might do an import, thus acquiring the import lock, which
7340 : : // PyOS_BeforeFork() also does. As this should only be called from
7341 : : // the parent process, it is in the same thread so that works.
7342 : 0 : static void warn_about_fork_with_threads(const char* name) {
7343 : : // TODO: Consider making an `os` module API to return the current number
7344 : : // of threads in the process. That'd presumably use this platform code but
7345 : : // raise an error rather than using the inaccurate fallback.
7346 : 0 : Py_ssize_t num_python_threads = 0;
7347 : : #if defined(__APPLE__) && defined(HAVE_GETPID)
7348 : : mach_port_t macos_self = mach_task_self();
7349 : : mach_port_t macos_task;
7350 : : if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
7351 : : thread_array_t macos_threads;
7352 : : mach_msg_type_number_t macos_n_threads;
7353 : : if (task_threads(macos_task, &macos_threads,
7354 : : &macos_n_threads) == KERN_SUCCESS) {
7355 : : num_python_threads = macos_n_threads;
7356 : : }
7357 : : }
7358 : : #elif defined(__linux__)
7359 : : // Linux /proc/self/stat 20th field is the number of threads.
7360 : 0 : FILE* proc_stat = fopen("/proc/self/stat", "r");
7361 [ # # ]: 0 : if (proc_stat) {
7362 : : size_t n;
7363 : : // Size chosen arbitrarily. ~60% more bytes than a 20th column index
7364 : : // observed on the author's workstation.
7365 : : char stat_line[160];
7366 : 0 : n = fread(&stat_line, 1, 159, proc_stat);
7367 : 0 : stat_line[n] = '\0';
7368 : 0 : fclose(proc_stat);
7369 : :
7370 : 0 : char *saveptr = NULL;
7371 : 0 : char *field = strtok_r(stat_line, " ", &saveptr);
7372 : : unsigned int idx;
7373 [ # # # # ]: 0 : for (idx = 19; idx && field; --idx) {
7374 : 0 : field = strtok_r(NULL, " ", &saveptr);
7375 : : }
7376 [ # # # # ]: 0 : if (idx == 0 && field) { // found the 20th field
7377 : 0 : num_python_threads = atoi(field); // 0 on error
7378 : : }
7379 : : }
7380 : : #endif
7381 [ # # ]: 0 : if (num_python_threads <= 0) {
7382 : : // Fall back to just the number our threading module knows about.
7383 : : // An incomplete view of the world, but better than nothing.
7384 : 0 : PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
7385 [ # # ]: 0 : if (!threading) {
7386 : 0 : PyErr_Clear();
7387 : 0 : return;
7388 : : }
7389 : : PyObject *threading_active =
7390 : 0 : PyObject_GetAttr(threading, &_Py_ID(_active));
7391 [ # # ]: 0 : if (!threading_active) {
7392 : 0 : PyErr_Clear();
7393 : 0 : Py_DECREF(threading);
7394 : 0 : return;
7395 : : }
7396 : : PyObject *threading_limbo =
7397 : 0 : PyObject_GetAttr(threading, &_Py_ID(_limbo));
7398 [ # # ]: 0 : if (!threading_limbo) {
7399 : 0 : PyErr_Clear();
7400 : 0 : Py_DECREF(threading);
7401 : 0 : Py_DECREF(threading_active);
7402 : 0 : return;
7403 : : }
7404 : 0 : Py_DECREF(threading);
7405 : : // Duplicating what threading.active_count() does but without holding
7406 : : // threading._active_limbo_lock so our count could be inaccurate if
7407 : : // these dicts are mid-update from another thread. Not a big deal.
7408 : : // Worst case if someone replaced threading._active or threading._limbo
7409 : : // with non-dicts, we get -1 from *Length() below and undercount.
7410 : : // Nobody should, but we're best effort so we clear errors and move on.
7411 : 0 : num_python_threads = (PyMapping_Length(threading_active)
7412 : 0 : + PyMapping_Length(threading_limbo));
7413 : 0 : PyErr_Clear();
7414 : 0 : Py_DECREF(threading_active);
7415 : 0 : Py_DECREF(threading_limbo);
7416 : : }
7417 [ # # ]: 0 : if (num_python_threads > 1) {
7418 : 0 : PyErr_WarnFormat(
7419 : : PyExc_DeprecationWarning, 1,
7420 : : #ifdef HAVE_GETPID
7421 : : "This process (pid=%d) is multi-threaded, "
7422 : : #else
7423 : : "This process is multi-threaded, "
7424 : : #endif
7425 : : "use of %s() may lead to deadlocks in the child.",
7426 : : #ifdef HAVE_GETPID
7427 : : getpid(),
7428 : : #endif
7429 : : name);
7430 : 0 : PyErr_Clear();
7431 : : }
7432 : : }
7433 : :
7434 : : #ifdef HAVE_FORK1
7435 : : /*[clinic input]
7436 : : os.fork1
7437 : :
7438 : : Fork a child process with a single multiplexed (i.e., not bound) thread.
7439 : :
7440 : : Return 0 to child process and PID of child to parent process.
7441 : : [clinic start generated code]*/
7442 : :
7443 : : static PyObject *
7444 : : os_fork1_impl(PyObject *module)
7445 : : /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
7446 : : {
7447 : : pid_t pid;
7448 : :
7449 : : if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
7450 : : PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
7451 : : return NULL;
7452 : : }
7453 : : PyOS_BeforeFork();
7454 : : pid = fork1();
7455 : : if (pid == 0) {
7456 : : /* child: this clobbers and resets the import lock. */
7457 : : PyOS_AfterFork_Child();
7458 : : } else {
7459 : : warn_about_fork_with_threads("fork1");
7460 : : /* parent: release the import lock. */
7461 : : PyOS_AfterFork_Parent();
7462 : : }
7463 : : if (pid == -1)
7464 : : return posix_error();
7465 : : return PyLong_FromPid(pid);
7466 : : }
7467 : : #endif /* HAVE_FORK1 */
7468 : :
7469 : :
7470 : : #ifdef HAVE_FORK
7471 : : /*[clinic input]
7472 : : os.fork
7473 : :
7474 : : Fork a child process.
7475 : :
7476 : : Return 0 to child process and PID of child to parent process.
7477 : : [clinic start generated code]*/
7478 : :
7479 : : static PyObject *
7480 : 0 : os_fork_impl(PyObject *module)
7481 : : /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
7482 : : {
7483 : : pid_t pid;
7484 : 0 : PyInterpreterState *interp = _PyInterpreterState_GET();
7485 [ # # ]: 0 : if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
7486 : 0 : PyErr_SetString(PyExc_RuntimeError,
7487 : : "fork not supported for isolated subinterpreters");
7488 : 0 : return NULL;
7489 : : }
7490 [ # # ]: 0 : if (PySys_Audit("os.fork", NULL) < 0) {
7491 : 0 : return NULL;
7492 : : }
7493 : 0 : PyOS_BeforeFork();
7494 : 0 : pid = fork();
7495 [ # # ]: 0 : if (pid == 0) {
7496 : : /* child: this clobbers and resets the import lock. */
7497 : 0 : PyOS_AfterFork_Child();
7498 : : } else {
7499 : 0 : warn_about_fork_with_threads("fork");
7500 : : /* parent: release the import lock. */
7501 : 0 : PyOS_AfterFork_Parent();
7502 : : }
7503 [ # # ]: 0 : if (pid == -1)
7504 : 0 : return posix_error();
7505 : 0 : return PyLong_FromPid(pid);
7506 : : }
7507 : : #endif /* HAVE_FORK */
7508 : :
7509 : :
7510 : : #ifdef HAVE_SCHED_H
7511 : : #ifdef HAVE_SCHED_GET_PRIORITY_MAX
7512 : : /*[clinic input]
7513 : : os.sched_get_priority_max
7514 : :
7515 : : policy: int
7516 : :
7517 : : Get the maximum scheduling priority for policy.
7518 : : [clinic start generated code]*/
7519 : :
7520 : : static PyObject *
7521 : 0 : os_sched_get_priority_max_impl(PyObject *module, int policy)
7522 : : /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
7523 : : {
7524 : : int max;
7525 : :
7526 : 0 : max = sched_get_priority_max(policy);
7527 [ # # ]: 0 : if (max < 0)
7528 : 0 : return posix_error();
7529 : 0 : return PyLong_FromLong(max);
7530 : : }
7531 : :
7532 : :
7533 : : /*[clinic input]
7534 : : os.sched_get_priority_min
7535 : :
7536 : : policy: int
7537 : :
7538 : : Get the minimum scheduling priority for policy.
7539 : : [clinic start generated code]*/
7540 : :
7541 : : static PyObject *
7542 : 0 : os_sched_get_priority_min_impl(PyObject *module, int policy)
7543 : : /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
7544 : : {
7545 : 0 : int min = sched_get_priority_min(policy);
7546 [ # # ]: 0 : if (min < 0)
7547 : 0 : return posix_error();
7548 : 0 : return PyLong_FromLong(min);
7549 : : }
7550 : : #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
7551 : :
7552 : :
7553 : : #ifdef HAVE_SCHED_SETSCHEDULER
7554 : : /*[clinic input]
7555 : : os.sched_getscheduler
7556 : : pid: pid_t
7557 : : /
7558 : :
7559 : : Get the scheduling policy for the process identified by pid.
7560 : :
7561 : : Passing 0 for pid returns the scheduling policy for the calling process.
7562 : : [clinic start generated code]*/
7563 : :
7564 : : static PyObject *
7565 : 0 : os_sched_getscheduler_impl(PyObject *module, pid_t pid)
7566 : : /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
7567 : : {
7568 : : int policy;
7569 : :
7570 : 0 : policy = sched_getscheduler(pid);
7571 [ # # ]: 0 : if (policy < 0)
7572 : 0 : return posix_error();
7573 : 0 : return PyLong_FromLong(policy);
7574 : : }
7575 : : #endif /* HAVE_SCHED_SETSCHEDULER */
7576 : :
7577 : :
7578 : : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7579 : : /*[clinic input]
7580 : : class os.sched_param "PyObject *" "SchedParamType"
7581 : :
7582 : : @classmethod
7583 : : os.sched_param.__new__
7584 : :
7585 : : sched_priority: object
7586 : : A scheduling parameter.
7587 : :
7588 : : Currently has only one field: sched_priority
7589 : : [clinic start generated code]*/
7590 : :
7591 : : static PyObject *
7592 : 0 : os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
7593 : : /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
7594 : : {
7595 : : PyObject *res;
7596 : :
7597 : 0 : res = PyStructSequence_New(type);
7598 [ # # ]: 0 : if (!res)
7599 : 0 : return NULL;
7600 : 0 : PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
7601 : 0 : return res;
7602 : : }
7603 : :
7604 : : PyDoc_VAR(os_sched_param__doc__);
7605 : :
7606 : : static PyStructSequence_Field sched_param_fields[] = {
7607 : : {"sched_priority", "the scheduling priority"},
7608 : : {0}
7609 : : };
7610 : :
7611 : : static PyStructSequence_Desc sched_param_desc = {
7612 : : "sched_param", /* name */
7613 : : os_sched_param__doc__, /* doc */
7614 : : sched_param_fields,
7615 : : 1
7616 : : };
7617 : :
7618 : : static int
7619 : 0 : convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
7620 : : {
7621 : : long priority;
7622 : :
7623 [ # # ]: 0 : if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
7624 : 0 : PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
7625 : 0 : return 0;
7626 : : }
7627 : 0 : priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
7628 [ # # # # ]: 0 : if (priority == -1 && PyErr_Occurred())
7629 : 0 : return 0;
7630 [ # # # # ]: 0 : if (priority > INT_MAX || priority < INT_MIN) {
7631 : 0 : PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
7632 : 0 : return 0;
7633 : : }
7634 : 0 : res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
7635 : 0 : return 1;
7636 : : }
7637 : : #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
7638 : :
7639 : :
7640 : : #ifdef HAVE_SCHED_SETSCHEDULER
7641 : : /*[clinic input]
7642 : : os.sched_setscheduler
7643 : :
7644 : : pid: pid_t
7645 : : policy: int
7646 : : param as param_obj: object
7647 : : /
7648 : :
7649 : : Set the scheduling policy for the process identified by pid.
7650 : :
7651 : : If pid is 0, the calling process is changed.
7652 : : param is an instance of sched_param.
7653 : : [clinic start generated code]*/
7654 : :
7655 : : static PyObject *
7656 : 0 : os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
7657 : : PyObject *param_obj)
7658 : : /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
7659 : : {
7660 : : struct sched_param param;
7661 [ # # ]: 0 : if (!convert_sched_param(module, param_obj, ¶m)) {
7662 : 0 : return NULL;
7663 : : }
7664 : :
7665 : : /*
7666 : : ** sched_setscheduler() returns 0 in Linux, but the previous
7667 : : ** scheduling policy under Solaris/Illumos, and others.
7668 : : ** On error, -1 is returned in all Operating Systems.
7669 : : */
7670 [ # # ]: 0 : if (sched_setscheduler(pid, policy, ¶m) == -1)
7671 : 0 : return posix_error();
7672 : 0 : Py_RETURN_NONE;
7673 : : }
7674 : : #endif /* HAVE_SCHED_SETSCHEDULER*/
7675 : :
7676 : :
7677 : : #ifdef HAVE_SCHED_SETPARAM
7678 : : /*[clinic input]
7679 : : os.sched_getparam
7680 : : pid: pid_t
7681 : : /
7682 : :
7683 : : Returns scheduling parameters for the process identified by pid.
7684 : :
7685 : : If pid is 0, returns parameters for the calling process.
7686 : : Return value is an instance of sched_param.
7687 : : [clinic start generated code]*/
7688 : :
7689 : : static PyObject *
7690 : 0 : os_sched_getparam_impl(PyObject *module, pid_t pid)
7691 : : /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
7692 : : {
7693 : : struct sched_param param;
7694 : : PyObject *result;
7695 : : PyObject *priority;
7696 : :
7697 [ # # ]: 0 : if (sched_getparam(pid, ¶m))
7698 : 0 : return posix_error();
7699 : 0 : PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
7700 : 0 : result = PyStructSequence_New((PyTypeObject *)SchedParamType);
7701 [ # # ]: 0 : if (!result)
7702 : 0 : return NULL;
7703 : 0 : priority = PyLong_FromLong(param.sched_priority);
7704 [ # # ]: 0 : if (!priority) {
7705 : 0 : Py_DECREF(result);
7706 : 0 : return NULL;
7707 : : }
7708 : 0 : PyStructSequence_SET_ITEM(result, 0, priority);
7709 : 0 : return result;
7710 : : }
7711 : :
7712 : :
7713 : : /*[clinic input]
7714 : : os.sched_setparam
7715 : : pid: pid_t
7716 : : param as param_obj: object
7717 : : /
7718 : :
7719 : : Set scheduling parameters for the process identified by pid.
7720 : :
7721 : : If pid is 0, sets parameters for the calling process.
7722 : : param should be an instance of sched_param.
7723 : : [clinic start generated code]*/
7724 : :
7725 : : static PyObject *
7726 : 0 : os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
7727 : : /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
7728 : : {
7729 : : struct sched_param param;
7730 [ # # ]: 0 : if (!convert_sched_param(module, param_obj, ¶m)) {
7731 : 0 : return NULL;
7732 : : }
7733 : :
7734 [ # # ]: 0 : if (sched_setparam(pid, ¶m))
7735 : 0 : return posix_error();
7736 : 0 : Py_RETURN_NONE;
7737 : : }
7738 : : #endif /* HAVE_SCHED_SETPARAM */
7739 : :
7740 : :
7741 : : #ifdef HAVE_SCHED_RR_GET_INTERVAL
7742 : : /*[clinic input]
7743 : : os.sched_rr_get_interval -> double
7744 : : pid: pid_t
7745 : : /
7746 : :
7747 : : Return the round-robin quantum for the process identified by pid, in seconds.
7748 : :
7749 : : Value returned is a float.
7750 : : [clinic start generated code]*/
7751 : :
7752 : : static double
7753 : 0 : os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
7754 : : /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
7755 : : {
7756 : : struct timespec interval;
7757 [ # # ]: 0 : if (sched_rr_get_interval(pid, &interval)) {
7758 : 0 : posix_error();
7759 : 0 : return -1.0;
7760 : : }
7761 : : #ifdef _Py_MEMORY_SANITIZER
7762 : : __msan_unpoison(&interval, sizeof(interval));
7763 : : #endif
7764 : 0 : return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
7765 : : }
7766 : : #endif /* HAVE_SCHED_RR_GET_INTERVAL */
7767 : :
7768 : :
7769 : : /*[clinic input]
7770 : : os.sched_yield
7771 : :
7772 : : Voluntarily relinquish the CPU.
7773 : : [clinic start generated code]*/
7774 : :
7775 : : static PyObject *
7776 : 0 : os_sched_yield_impl(PyObject *module)
7777 : : /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
7778 : : {
7779 : : int result;
7780 : 0 : Py_BEGIN_ALLOW_THREADS
7781 : 0 : result = sched_yield();
7782 : 0 : Py_END_ALLOW_THREADS
7783 [ # # ]: 0 : if (result < 0) {
7784 : 0 : return posix_error();
7785 : : }
7786 : 0 : Py_RETURN_NONE;
7787 : : }
7788 : :
7789 : : #ifdef HAVE_SCHED_SETAFFINITY
7790 : : /* The minimum number of CPUs allocated in a cpu_set_t */
7791 : : static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
7792 : :
7793 : : /*[clinic input]
7794 : : os.sched_setaffinity
7795 : : pid: pid_t
7796 : : mask : object
7797 : : /
7798 : :
7799 : : Set the CPU affinity of the process identified by pid to mask.
7800 : :
7801 : : mask should be an iterable of integers identifying CPUs.
7802 : : [clinic start generated code]*/
7803 : :
7804 : : static PyObject *
7805 : 0 : os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
7806 : : /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
7807 : : {
7808 : : int ncpus;
7809 : : size_t setsize;
7810 : 0 : cpu_set_t *cpu_set = NULL;
7811 : 0 : PyObject *iterator = NULL, *item;
7812 : :
7813 : 0 : iterator = PyObject_GetIter(mask);
7814 [ # # ]: 0 : if (iterator == NULL)
7815 : 0 : return NULL;
7816 : :
7817 : 0 : ncpus = NCPUS_START;
7818 : 0 : setsize = CPU_ALLOC_SIZE(ncpus);
7819 : 0 : cpu_set = CPU_ALLOC(ncpus);
7820 [ # # ]: 0 : if (cpu_set == NULL) {
7821 : 0 : PyErr_NoMemory();
7822 : 0 : goto error;
7823 : : }
7824 : 0 : CPU_ZERO_S(setsize, cpu_set);
7825 : :
7826 [ # # ]: 0 : while ((item = PyIter_Next(iterator))) {
7827 : : long cpu;
7828 [ # # ]: 0 : if (!PyLong_Check(item)) {
7829 : 0 : PyErr_Format(PyExc_TypeError,
7830 : : "expected an iterator of ints, "
7831 : : "but iterator yielded %R",
7832 : : Py_TYPE(item));
7833 : 0 : Py_DECREF(item);
7834 : 0 : goto error;
7835 : : }
7836 : 0 : cpu = PyLong_AsLong(item);
7837 : 0 : Py_DECREF(item);
7838 [ # # ]: 0 : if (cpu < 0) {
7839 [ # # ]: 0 : if (!PyErr_Occurred())
7840 : 0 : PyErr_SetString(PyExc_ValueError, "negative CPU number");
7841 : 0 : goto error;
7842 : : }
7843 [ # # ]: 0 : if (cpu > INT_MAX - 1) {
7844 : 0 : PyErr_SetString(PyExc_OverflowError, "CPU number too large");
7845 : 0 : goto error;
7846 : : }
7847 [ # # ]: 0 : if (cpu >= ncpus) {
7848 : : /* Grow CPU mask to fit the CPU number */
7849 : 0 : int newncpus = ncpus;
7850 : : cpu_set_t *newmask;
7851 : : size_t newsetsize;
7852 [ # # ]: 0 : while (newncpus <= cpu) {
7853 [ # # ]: 0 : if (newncpus > INT_MAX / 2)
7854 : 0 : newncpus = cpu + 1;
7855 : : else
7856 : 0 : newncpus = newncpus * 2;
7857 : : }
7858 : 0 : newmask = CPU_ALLOC(newncpus);
7859 [ # # ]: 0 : if (newmask == NULL) {
7860 : 0 : PyErr_NoMemory();
7861 : 0 : goto error;
7862 : : }
7863 : 0 : newsetsize = CPU_ALLOC_SIZE(newncpus);
7864 : 0 : CPU_ZERO_S(newsetsize, newmask);
7865 : 0 : memcpy(newmask, cpu_set, setsize);
7866 : 0 : CPU_FREE(cpu_set);
7867 : 0 : setsize = newsetsize;
7868 : 0 : cpu_set = newmask;
7869 : 0 : ncpus = newncpus;
7870 : : }
7871 [ # # ]: 0 : CPU_SET_S(cpu, setsize, cpu_set);
7872 : : }
7873 [ # # ]: 0 : if (PyErr_Occurred()) {
7874 : 0 : goto error;
7875 : : }
7876 [ # # ]: 0 : Py_CLEAR(iterator);
7877 : :
7878 [ # # ]: 0 : if (sched_setaffinity(pid, setsize, cpu_set)) {
7879 : 0 : posix_error();
7880 : 0 : goto error;
7881 : : }
7882 : 0 : CPU_FREE(cpu_set);
7883 : 0 : Py_RETURN_NONE;
7884 : :
7885 : 0 : error:
7886 [ # # ]: 0 : if (cpu_set)
7887 : 0 : CPU_FREE(cpu_set);
7888 : 0 : Py_XDECREF(iterator);
7889 : 0 : return NULL;
7890 : : }
7891 : :
7892 : :
7893 : : /*[clinic input]
7894 : : os.sched_getaffinity
7895 : : pid: pid_t
7896 : : /
7897 : :
7898 : : Return the affinity of the process identified by pid (or the current process if zero).
7899 : :
7900 : : The affinity is returned as a set of CPU identifiers.
7901 : : [clinic start generated code]*/
7902 : :
7903 : : static PyObject *
7904 : 0 : os_sched_getaffinity_impl(PyObject *module, pid_t pid)
7905 : : /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
7906 : : {
7907 : : int cpu, ncpus, count;
7908 : : size_t setsize;
7909 : 0 : cpu_set_t *mask = NULL;
7910 : 0 : PyObject *res = NULL;
7911 : :
7912 : 0 : ncpus = NCPUS_START;
7913 : : while (1) {
7914 : 0 : setsize = CPU_ALLOC_SIZE(ncpus);
7915 : 0 : mask = CPU_ALLOC(ncpus);
7916 [ # # ]: 0 : if (mask == NULL)
7917 : 0 : return PyErr_NoMemory();
7918 [ # # ]: 0 : if (sched_getaffinity(pid, setsize, mask) == 0)
7919 : 0 : break;
7920 : 0 : CPU_FREE(mask);
7921 [ # # ]: 0 : if (errno != EINVAL)
7922 : 0 : return posix_error();
7923 [ # # ]: 0 : if (ncpus > INT_MAX / 2) {
7924 : 0 : PyErr_SetString(PyExc_OverflowError, "could not allocate "
7925 : : "a large enough CPU set");
7926 : 0 : return NULL;
7927 : : }
7928 : 0 : ncpus = ncpus * 2;
7929 : : }
7930 : :
7931 : 0 : res = PySet_New(NULL);
7932 [ # # ]: 0 : if (res == NULL)
7933 : 0 : goto error;
7934 [ # # ]: 0 : for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7935 [ # # # # : 0 : if (CPU_ISSET_S(cpu, setsize, mask)) {
# # ]
7936 : 0 : PyObject *cpu_num = PyLong_FromLong(cpu);
7937 : 0 : --count;
7938 [ # # ]: 0 : if (cpu_num == NULL)
7939 : 0 : goto error;
7940 [ # # ]: 0 : if (PySet_Add(res, cpu_num)) {
7941 : 0 : Py_DECREF(cpu_num);
7942 : 0 : goto error;
7943 : : }
7944 : 0 : Py_DECREF(cpu_num);
7945 : : }
7946 : : }
7947 : 0 : CPU_FREE(mask);
7948 : 0 : return res;
7949 : :
7950 : 0 : error:
7951 [ # # ]: 0 : if (mask)
7952 : 0 : CPU_FREE(mask);
7953 : 0 : Py_XDECREF(res);
7954 : 0 : return NULL;
7955 : : }
7956 : :
7957 : : #endif /* HAVE_SCHED_SETAFFINITY */
7958 : :
7959 : : #endif /* HAVE_SCHED_H */
7960 : :
7961 : :
7962 : : /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
7963 : : #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
7964 : : # define DEV_PTY_FILE "/dev/ptc"
7965 : : # define HAVE_DEV_PTMX
7966 : : #else
7967 : : # define DEV_PTY_FILE "/dev/ptmx"
7968 : : #endif
7969 : :
7970 : : #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
7971 : : #ifdef HAVE_PTY_H
7972 : : #include <pty.h>
7973 : : #ifdef HAVE_UTMP_H
7974 : : #include <utmp.h>
7975 : : #endif /* HAVE_UTMP_H */
7976 : : #elif defined(HAVE_LIBUTIL_H)
7977 : : #include <libutil.h>
7978 : : #elif defined(HAVE_UTIL_H)
7979 : : #include <util.h>
7980 : : #endif /* HAVE_PTY_H */
7981 : : #ifdef HAVE_STROPTS_H
7982 : : #include <stropts.h>
7983 : : #endif
7984 : : #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
7985 : :
7986 : :
7987 : : #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7988 : : /*[clinic input]
7989 : : os.openpty
7990 : :
7991 : : Open a pseudo-terminal.
7992 : :
7993 : : Return a tuple of (master_fd, slave_fd) containing open file descriptors
7994 : : for both the master and slave ends.
7995 : : [clinic start generated code]*/
7996 : :
7997 : : static PyObject *
7998 : 0 : os_openpty_impl(PyObject *module)
7999 : : /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
8000 : : {
8001 : 0 : int master_fd = -1, slave_fd = -1;
8002 : : #ifndef HAVE_OPENPTY
8003 : : char * slave_name;
8004 : : #endif
8005 : : #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
8006 : : PyOS_sighandler_t sig_saved;
8007 : : #if defined(__sun) && defined(__SVR4)
8008 : : extern char *ptsname(int fildes);
8009 : : #endif
8010 : : #endif
8011 : :
8012 : : #ifdef HAVE_OPENPTY
8013 [ # # ]: 0 : if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
8014 : 0 : goto posix_error;
8015 : :
8016 [ # # ]: 0 : if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
8017 : 0 : goto error;
8018 [ # # ]: 0 : if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
8019 : 0 : goto error;
8020 : :
8021 : : #elif defined(HAVE__GETPTY)
8022 : : slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
8023 : : if (slave_name == NULL)
8024 : : goto posix_error;
8025 : : if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
8026 : : goto error;
8027 : :
8028 : : slave_fd = _Py_open(slave_name, O_RDWR);
8029 : : if (slave_fd < 0)
8030 : : goto error;
8031 : :
8032 : : #else
8033 : : master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
8034 : : if (master_fd < 0)
8035 : : goto posix_error;
8036 : :
8037 : : sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
8038 : :
8039 : : /* change permission of slave */
8040 : : if (grantpt(master_fd) < 0) {
8041 : : PyOS_setsig(SIGCHLD, sig_saved);
8042 : : goto posix_error;
8043 : : }
8044 : :
8045 : : /* unlock slave */
8046 : : if (unlockpt(master_fd) < 0) {
8047 : : PyOS_setsig(SIGCHLD, sig_saved);
8048 : : goto posix_error;
8049 : : }
8050 : :
8051 : : PyOS_setsig(SIGCHLD, sig_saved);
8052 : :
8053 : : slave_name = ptsname(master_fd); /* get name of slave */
8054 : : if (slave_name == NULL)
8055 : : goto posix_error;
8056 : :
8057 : : slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
8058 : : if (slave_fd == -1)
8059 : : goto error;
8060 : :
8061 : : if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
8062 : : goto posix_error;
8063 : :
8064 : : #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
8065 : : ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
8066 : : ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
8067 : : #ifndef __hpux
8068 : : ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
8069 : : #endif /* __hpux */
8070 : : #endif /* HAVE_CYGWIN */
8071 : : #endif /* HAVE_OPENPTY */
8072 : :
8073 : 0 : return Py_BuildValue("(ii)", master_fd, slave_fd);
8074 : :
8075 : 0 : posix_error:
8076 : 0 : posix_error();
8077 : 0 : error:
8078 [ # # ]: 0 : if (master_fd != -1)
8079 : 0 : close(master_fd);
8080 [ # # ]: 0 : if (slave_fd != -1)
8081 : 0 : close(slave_fd);
8082 : 0 : return NULL;
8083 : : }
8084 : : #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
8085 : :
8086 : :
8087 : : #if defined(HAVE_SETSID) && defined(TIOCSCTTY)
8088 : : #define HAVE_FALLBACK_LOGIN_TTY 1
8089 : : #endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
8090 : :
8091 : : #if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
8092 : : /*[clinic input]
8093 : : os.login_tty
8094 : :
8095 : : fd: fildes
8096 : : /
8097 : :
8098 : : Prepare the tty of which fd is a file descriptor for a new login session.
8099 : :
8100 : : Make the calling process a session leader; make the tty the
8101 : : controlling tty, the stdin, the stdout, and the stderr of the
8102 : : calling process; close fd.
8103 : : [clinic start generated code]*/
8104 : :
8105 : : static PyObject *
8106 : 0 : os_login_tty_impl(PyObject *module, int fd)
8107 : : /*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
8108 : : {
8109 : : #ifdef HAVE_LOGIN_TTY
8110 [ # # ]: 0 : if (login_tty(fd) == -1) {
8111 : 0 : return posix_error();
8112 : : }
8113 : : #else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
8114 : : /* Establish a new session. */
8115 : : if (setsid() == -1) {
8116 : : return posix_error();
8117 : : }
8118 : :
8119 : : /* The tty becomes the controlling terminal. */
8120 : : if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
8121 : : return posix_error();
8122 : : }
8123 : :
8124 : : /* The tty becomes stdin/stdout/stderr */
8125 : : if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
8126 : : return posix_error();
8127 : : }
8128 : : if (fd > 2) {
8129 : : close(fd);
8130 : : }
8131 : : #endif /* HAVE_LOGIN_TTY */
8132 : 0 : Py_RETURN_NONE;
8133 : : }
8134 : : #endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
8135 : :
8136 : :
8137 : : #ifdef HAVE_FORKPTY
8138 : : /*[clinic input]
8139 : : os.forkpty
8140 : :
8141 : : Fork a new process with a new pseudo-terminal as controlling tty.
8142 : :
8143 : : Returns a tuple of (pid, master_fd).
8144 : : Like fork(), return pid of 0 to the child process,
8145 : : and pid of child to the parent process.
8146 : : To both, return fd of newly opened pseudo-terminal.
8147 : : [clinic start generated code]*/
8148 : :
8149 : : static PyObject *
8150 : 0 : os_forkpty_impl(PyObject *module)
8151 : : /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
8152 : : {
8153 : 0 : int master_fd = -1;
8154 : : pid_t pid;
8155 : :
8156 [ # # ]: 0 : if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
8157 : 0 : PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8158 : 0 : return NULL;
8159 : : }
8160 [ # # ]: 0 : if (PySys_Audit("os.forkpty", NULL) < 0) {
8161 : 0 : return NULL;
8162 : : }
8163 : 0 : PyOS_BeforeFork();
8164 : 0 : pid = forkpty(&master_fd, NULL, NULL, NULL);
8165 [ # # ]: 0 : if (pid == 0) {
8166 : : /* child: this clobbers and resets the import lock. */
8167 : 0 : PyOS_AfterFork_Child();
8168 : : } else {
8169 : 0 : warn_about_fork_with_threads("forkpty");
8170 : : /* parent: release the import lock. */
8171 : 0 : PyOS_AfterFork_Parent();
8172 : : }
8173 [ # # ]: 0 : if (pid == -1) {
8174 : 0 : return posix_error();
8175 : : }
8176 : 0 : return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
8177 : : }
8178 : : #endif /* HAVE_FORKPTY */
8179 : :
8180 : :
8181 : : #ifdef HAVE_GETEGID
8182 : : /*[clinic input]
8183 : : os.getegid
8184 : :
8185 : : Return the current process's effective group id.
8186 : : [clinic start generated code]*/
8187 : :
8188 : : static PyObject *
8189 : 3 : os_getegid_impl(PyObject *module)
8190 : : /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
8191 : : {
8192 : 3 : return _PyLong_FromGid(getegid());
8193 : : }
8194 : : #endif /* HAVE_GETEGID */
8195 : :
8196 : :
8197 : : #ifdef HAVE_GETEUID
8198 : : /*[clinic input]
8199 : : os.geteuid
8200 : :
8201 : : Return the current process's effective user id.
8202 : : [clinic start generated code]*/
8203 : :
8204 : : static PyObject *
8205 : 3 : os_geteuid_impl(PyObject *module)
8206 : : /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
8207 : : {
8208 : 3 : return _PyLong_FromUid(geteuid());
8209 : : }
8210 : : #endif /* HAVE_GETEUID */
8211 : :
8212 : :
8213 : : #ifdef HAVE_GETGID
8214 : : /*[clinic input]
8215 : : os.getgid
8216 : :
8217 : : Return the current process's group id.
8218 : : [clinic start generated code]*/
8219 : :
8220 : : static PyObject *
8221 : 3 : os_getgid_impl(PyObject *module)
8222 : : /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
8223 : : {
8224 : 3 : return _PyLong_FromGid(getgid());
8225 : : }
8226 : : #endif /* HAVE_GETGID */
8227 : :
8228 : :
8229 : : #if defined(HAVE_GETPID)
8230 : : /*[clinic input]
8231 : : os.getpid
8232 : :
8233 : : Return the current process id.
8234 : : [clinic start generated code]*/
8235 : :
8236 : : static PyObject *
8237 : 4 : os_getpid_impl(PyObject *module)
8238 : : /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
8239 : : {
8240 : : #if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
8241 : 4 : return PyLong_FromPid(getpid());
8242 : : #else
8243 : : return PyLong_FromUnsignedLong(GetCurrentProcessId());
8244 : : #endif
8245 : : }
8246 : : #endif /* defined(HAVE_GETPID) */
8247 : :
8248 : : #ifdef NGROUPS_MAX
8249 : : #define MAX_GROUPS NGROUPS_MAX
8250 : : #else
8251 : : /* defined to be 16 on Solaris7, so this should be a small number */
8252 : : #define MAX_GROUPS 64
8253 : : #endif
8254 : :
8255 : : #ifdef HAVE_GETGROUPLIST
8256 : :
8257 : : #ifdef __APPLE__
8258 : : /*[clinic input]
8259 : : os.getgrouplist
8260 : :
8261 : : user: str
8262 : : username to lookup
8263 : : group as basegid: int
8264 : : base group id of the user
8265 : : /
8266 : :
8267 : : Returns a list of groups to which a user belongs.
8268 : : [clinic start generated code]*/
8269 : :
8270 : : static PyObject *
8271 : : os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
8272 : : /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
8273 : : #else
8274 : : /*[clinic input]
8275 : : os.getgrouplist
8276 : :
8277 : : user: str
8278 : : username to lookup
8279 : : group as basegid: gid_t
8280 : : base group id of the user
8281 : : /
8282 : :
8283 : : Returns a list of groups to which a user belongs.
8284 : : [clinic start generated code]*/
8285 : :
8286 : : static PyObject *
8287 : 0 : os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
8288 : : /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
8289 : : #endif
8290 : : {
8291 : : int i, ngroups;
8292 : : PyObject *list;
8293 : : #ifdef __APPLE__
8294 : : int *groups;
8295 : : #else
8296 : : gid_t *groups;
8297 : : #endif
8298 : :
8299 : : /*
8300 : : * NGROUPS_MAX is defined by POSIX.1 as the maximum
8301 : : * number of supplimental groups a users can belong to.
8302 : : * We have to increment it by one because
8303 : : * getgrouplist() returns both the supplemental groups
8304 : : * and the primary group, i.e. all of the groups the
8305 : : * user belongs to.
8306 : : */
8307 : 0 : ngroups = 1 + MAX_GROUPS;
8308 : :
8309 : 0 : while (1) {
8310 : : #ifdef __APPLE__
8311 : : groups = PyMem_New(int, ngroups);
8312 : : #else
8313 [ # # ]: 0 : groups = PyMem_New(gid_t, ngroups);
8314 : : #endif
8315 [ # # ]: 0 : if (groups == NULL) {
8316 : 0 : return PyErr_NoMemory();
8317 : : }
8318 : :
8319 : 0 : int old_ngroups = ngroups;
8320 [ # # ]: 0 : if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
8321 : : /* Success */
8322 : 0 : break;
8323 : : }
8324 : :
8325 : : /* getgrouplist() fails if the group list is too small */
8326 : 0 : PyMem_Free(groups);
8327 : :
8328 [ # # ]: 0 : if (ngroups > old_ngroups) {
8329 : : /* If the group list is too small, the glibc implementation of
8330 : : getgrouplist() sets ngroups to the total number of groups and
8331 : : returns -1. */
8332 : : }
8333 : : else {
8334 : : /* Double the group list size */
8335 [ # # ]: 0 : if (ngroups > INT_MAX / 2) {
8336 : 0 : return PyErr_NoMemory();
8337 : : }
8338 : 0 : ngroups *= 2;
8339 : : }
8340 : :
8341 : : /* Retry getgrouplist() with a larger group list */
8342 : : }
8343 : :
8344 : : #ifdef _Py_MEMORY_SANITIZER
8345 : : /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
8346 : : __msan_unpoison(&ngroups, sizeof(ngroups));
8347 : : __msan_unpoison(groups, ngroups*sizeof(*groups));
8348 : : #endif
8349 : :
8350 : 0 : list = PyList_New(ngroups);
8351 [ # # ]: 0 : if (list == NULL) {
8352 : 0 : PyMem_Free(groups);
8353 : 0 : return NULL;
8354 : : }
8355 : :
8356 [ # # ]: 0 : for (i = 0; i < ngroups; i++) {
8357 : : #ifdef __APPLE__
8358 : : PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
8359 : : #else
8360 : 0 : PyObject *o = _PyLong_FromGid(groups[i]);
8361 : : #endif
8362 [ # # ]: 0 : if (o == NULL) {
8363 : 0 : Py_DECREF(list);
8364 : 0 : PyMem_Free(groups);
8365 : 0 : return NULL;
8366 : : }
8367 : 0 : PyList_SET_ITEM(list, i, o);
8368 : : }
8369 : :
8370 : 0 : PyMem_Free(groups);
8371 : :
8372 : 0 : return list;
8373 : : }
8374 : : #endif /* HAVE_GETGROUPLIST */
8375 : :
8376 : :
8377 : : #ifdef HAVE_GETGROUPS
8378 : : /*[clinic input]
8379 : : os.getgroups
8380 : :
8381 : : Return list of supplemental group IDs for the process.
8382 : : [clinic start generated code]*/
8383 : :
8384 : : static PyObject *
8385 : 0 : os_getgroups_impl(PyObject *module)
8386 : : /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
8387 : : {
8388 : : // Call getgroups with length 0 to get the actual number of groups
8389 : 0 : int n = getgroups(0, NULL);
8390 [ # # ]: 0 : if (n < 0) {
8391 : 0 : return posix_error();
8392 : : }
8393 : :
8394 [ # # ]: 0 : if (n == 0) {
8395 : 0 : return PyList_New(0);
8396 : : }
8397 : :
8398 [ # # ]: 0 : gid_t *grouplist = PyMem_New(gid_t, n);
8399 [ # # ]: 0 : if (grouplist == NULL) {
8400 : 0 : return PyErr_NoMemory();
8401 : : }
8402 : :
8403 : 0 : n = getgroups(n, grouplist);
8404 [ # # ]: 0 : if (n == -1) {
8405 : 0 : PyMem_Free(grouplist);
8406 : 0 : return posix_error();
8407 : : }
8408 : :
8409 : 0 : PyObject *result = PyList_New(n);
8410 [ # # ]: 0 : if (result == NULL) {
8411 : 0 : goto error;
8412 : : }
8413 : :
8414 [ # # ]: 0 : for (int i = 0; i < n; ++i) {
8415 : 0 : PyObject *group = _PyLong_FromGid(grouplist[i]);
8416 [ # # ]: 0 : if (group == NULL) {
8417 : 0 : goto error;
8418 : : }
8419 : 0 : PyList_SET_ITEM(result, i, group);
8420 : : }
8421 : 0 : PyMem_Free(grouplist);
8422 : :
8423 : 0 : return result;
8424 : :
8425 : 0 : error:
8426 : 0 : PyMem_Free(grouplist);
8427 : 0 : Py_XDECREF(result);
8428 : 0 : return NULL;
8429 : : }
8430 : : #endif /* HAVE_GETGROUPS */
8431 : :
8432 : : #ifdef HAVE_INITGROUPS
8433 : : #ifdef __APPLE__
8434 : : /*[clinic input]
8435 : : os.initgroups
8436 : :
8437 : : username as oname: FSConverter
8438 : : gid: int
8439 : : /
8440 : :
8441 : : Initialize the group access list.
8442 : :
8443 : : Call the system initgroups() to initialize the group access list with all of
8444 : : the groups of which the specified username is a member, plus the specified
8445 : : group id.
8446 : : [clinic start generated code]*/
8447 : :
8448 : : static PyObject *
8449 : : os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
8450 : : /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
8451 : : #else
8452 : : /*[clinic input]
8453 : : os.initgroups
8454 : :
8455 : : username as oname: FSConverter
8456 : : gid: gid_t
8457 : : /
8458 : :
8459 : : Initialize the group access list.
8460 : :
8461 : : Call the system initgroups() to initialize the group access list with all of
8462 : : the groups of which the specified username is a member, plus the specified
8463 : : group id.
8464 : : [clinic start generated code]*/
8465 : :
8466 : : static PyObject *
8467 : 0 : os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
8468 : : /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
8469 : : #endif
8470 : : {
8471 : 0 : const char *username = PyBytes_AS_STRING(oname);
8472 : :
8473 [ # # ]: 0 : if (initgroups(username, gid) == -1)
8474 : 0 : return PyErr_SetFromErrno(PyExc_OSError);
8475 : :
8476 : 0 : Py_RETURN_NONE;
8477 : : }
8478 : : #endif /* HAVE_INITGROUPS */
8479 : :
8480 : :
8481 : : #ifdef HAVE_GETPGID
8482 : : /*[clinic input]
8483 : : os.getpgid
8484 : :
8485 : : pid: pid_t
8486 : :
8487 : : Call the system call getpgid(), and return the result.
8488 : : [clinic start generated code]*/
8489 : :
8490 : : static PyObject *
8491 : 0 : os_getpgid_impl(PyObject *module, pid_t pid)
8492 : : /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
8493 : : {
8494 : 0 : pid_t pgid = getpgid(pid);
8495 [ # # ]: 0 : if (pgid < 0)
8496 : 0 : return posix_error();
8497 : 0 : return PyLong_FromPid(pgid);
8498 : : }
8499 : : #endif /* HAVE_GETPGID */
8500 : :
8501 : :
8502 : : #ifdef HAVE_GETPGRP
8503 : : /*[clinic input]
8504 : : os.getpgrp
8505 : :
8506 : : Return the current process group id.
8507 : : [clinic start generated code]*/
8508 : :
8509 : : static PyObject *
8510 : 0 : os_getpgrp_impl(PyObject *module)
8511 : : /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
8512 : : {
8513 : : #ifdef GETPGRP_HAVE_ARG
8514 : : return PyLong_FromPid(getpgrp(0));
8515 : : #else /* GETPGRP_HAVE_ARG */
8516 : 0 : return PyLong_FromPid(getpgrp());
8517 : : #endif /* GETPGRP_HAVE_ARG */
8518 : : }
8519 : : #endif /* HAVE_GETPGRP */
8520 : :
8521 : :
8522 : : #ifdef HAVE_SETPGRP
8523 : : /*[clinic input]
8524 : : os.setpgrp
8525 : :
8526 : : Make the current process the leader of its process group.
8527 : : [clinic start generated code]*/
8528 : :
8529 : : static PyObject *
8530 : 0 : os_setpgrp_impl(PyObject *module)
8531 : : /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
8532 : : {
8533 : : #ifdef SETPGRP_HAVE_ARG
8534 : : if (setpgrp(0, 0) < 0)
8535 : : #else /* SETPGRP_HAVE_ARG */
8536 [ # # ]: 0 : if (setpgrp() < 0)
8537 : : #endif /* SETPGRP_HAVE_ARG */
8538 : 0 : return posix_error();
8539 : 0 : Py_RETURN_NONE;
8540 : : }
8541 : : #endif /* HAVE_SETPGRP */
8542 : :
8543 : : #ifdef HAVE_GETPPID
8544 : :
8545 : : #ifdef MS_WINDOWS
8546 : : #include <processsnapshot.h>
8547 : :
8548 : : static PyObject*
8549 : : win32_getppid()
8550 : : {
8551 : : DWORD error;
8552 : : PyObject* result = NULL;
8553 : : HANDLE process = GetCurrentProcess();
8554 : :
8555 : : HPSS snapshot = NULL;
8556 : : error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
8557 : : if (error != ERROR_SUCCESS) {
8558 : : return PyErr_SetFromWindowsErr(error);
8559 : : }
8560 : :
8561 : : PSS_PROCESS_INFORMATION info;
8562 : : error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
8563 : : sizeof(info));
8564 : : if (error == ERROR_SUCCESS) {
8565 : : result = PyLong_FromUnsignedLong(info.ParentProcessId);
8566 : : }
8567 : : else {
8568 : : result = PyErr_SetFromWindowsErr(error);
8569 : : }
8570 : :
8571 : : PssFreeSnapshot(process, snapshot);
8572 : : return result;
8573 : : }
8574 : : #endif /*MS_WINDOWS*/
8575 : :
8576 : :
8577 : : /*[clinic input]
8578 : : os.getppid
8579 : :
8580 : : Return the parent's process id.
8581 : :
8582 : : If the parent process has already exited, Windows machines will still
8583 : : return its id; others systems will return the id of the 'init' process (1).
8584 : : [clinic start generated code]*/
8585 : :
8586 : : static PyObject *
8587 : 0 : os_getppid_impl(PyObject *module)
8588 : : /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
8589 : : {
8590 : : #ifdef MS_WINDOWS
8591 : : return win32_getppid();
8592 : : #else
8593 : 0 : return PyLong_FromPid(getppid());
8594 : : #endif
8595 : : }
8596 : : #endif /* HAVE_GETPPID */
8597 : :
8598 : :
8599 : : #ifdef HAVE_GETLOGIN
8600 : : /*[clinic input]
8601 : : os.getlogin
8602 : :
8603 : : Return the actual login name.
8604 : : [clinic start generated code]*/
8605 : :
8606 : : static PyObject *
8607 : 0 : os_getlogin_impl(PyObject *module)
8608 : : /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
8609 : : {
8610 : 0 : PyObject *result = NULL;
8611 : : #ifdef MS_WINDOWS
8612 : : wchar_t user_name[UNLEN + 1];
8613 : : DWORD num_chars = Py_ARRAY_LENGTH(user_name);
8614 : :
8615 : : if (GetUserNameW(user_name, &num_chars)) {
8616 : : /* num_chars is the number of unicode chars plus null terminator */
8617 : : result = PyUnicode_FromWideChar(user_name, num_chars - 1);
8618 : : }
8619 : : else
8620 : : result = PyErr_SetFromWindowsErr(GetLastError());
8621 : : #else
8622 : : char *name;
8623 : 0 : int old_errno = errno;
8624 : :
8625 : 0 : errno = 0;
8626 : 0 : name = getlogin();
8627 [ # # ]: 0 : if (name == NULL) {
8628 [ # # ]: 0 : if (errno)
8629 : 0 : posix_error();
8630 : : else
8631 : 0 : PyErr_SetString(PyExc_OSError, "unable to determine login name");
8632 : : }
8633 : : else
8634 : 0 : result = PyUnicode_DecodeFSDefault(name);
8635 : 0 : errno = old_errno;
8636 : : #endif
8637 : 0 : return result;
8638 : : }
8639 : : #endif /* HAVE_GETLOGIN */
8640 : :
8641 : :
8642 : : #ifdef HAVE_GETUID
8643 : : /*[clinic input]
8644 : : os.getuid
8645 : :
8646 : : Return the current process's user id.
8647 : : [clinic start generated code]*/
8648 : :
8649 : : static PyObject *
8650 : 3 : os_getuid_impl(PyObject *module)
8651 : : /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
8652 : : {
8653 : 3 : return _PyLong_FromUid(getuid());
8654 : : }
8655 : : #endif /* HAVE_GETUID */
8656 : :
8657 : :
8658 : : #ifdef MS_WINDOWS
8659 : : #define HAVE_KILL
8660 : : #endif /* MS_WINDOWS */
8661 : :
8662 : : #ifdef HAVE_KILL
8663 : : /*[clinic input]
8664 : : os.kill
8665 : :
8666 : : pid: pid_t
8667 : : signal: Py_ssize_t
8668 : : /
8669 : :
8670 : : Kill a process with a signal.
8671 : : [clinic start generated code]*/
8672 : :
8673 : : static PyObject *
8674 : 0 : os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
8675 : : /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
8676 : : {
8677 [ # # ]: 0 : if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
8678 : 0 : return NULL;
8679 : : }
8680 : : #ifndef MS_WINDOWS
8681 [ # # ]: 0 : if (kill(pid, (int)signal) == -1) {
8682 : 0 : return posix_error();
8683 : : }
8684 : :
8685 : : // Check immediately if the signal was sent to the current process.
8686 : : // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
8687 : : // is cheap.
8688 [ # # ]: 0 : if (PyErr_CheckSignals()) {
8689 : 0 : return NULL;
8690 : : }
8691 : :
8692 : 0 : Py_RETURN_NONE;
8693 : : #else /* !MS_WINDOWS */
8694 : : PyObject *result;
8695 : : DWORD sig = (DWORD)signal;
8696 : : DWORD err;
8697 : : HANDLE handle;
8698 : :
8699 : : #ifdef HAVE_WINDOWS_CONSOLE_IO
8700 : : /* Console processes which share a common console can be sent CTRL+C or
8701 : : CTRL+BREAK events, provided they handle said events. */
8702 : : if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
8703 : : if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
8704 : : err = GetLastError();
8705 : : PyErr_SetFromWindowsErr(err);
8706 : : }
8707 : : else {
8708 : : Py_RETURN_NONE;
8709 : : }
8710 : : }
8711 : : #endif /* HAVE_WINDOWS_CONSOLE_IO */
8712 : :
8713 : : /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
8714 : : attempt to open and terminate the process. */
8715 : : handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
8716 : : if (handle == NULL) {
8717 : : err = GetLastError();
8718 : : return PyErr_SetFromWindowsErr(err);
8719 : : }
8720 : :
8721 : : if (TerminateProcess(handle, sig) == 0) {
8722 : : err = GetLastError();
8723 : : result = PyErr_SetFromWindowsErr(err);
8724 : : } else {
8725 : : result = Py_NewRef(Py_None);
8726 : : }
8727 : :
8728 : : CloseHandle(handle);
8729 : : return result;
8730 : : #endif /* !MS_WINDOWS */
8731 : : }
8732 : : #endif /* HAVE_KILL */
8733 : :
8734 : :
8735 : : #ifdef HAVE_KILLPG
8736 : : /*[clinic input]
8737 : : os.killpg
8738 : :
8739 : : pgid: pid_t
8740 : : signal: int
8741 : : /
8742 : :
8743 : : Kill a process group with a signal.
8744 : : [clinic start generated code]*/
8745 : :
8746 : : static PyObject *
8747 : 0 : os_killpg_impl(PyObject *module, pid_t pgid, int signal)
8748 : : /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
8749 : : {
8750 [ # # ]: 0 : if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
8751 : 0 : return NULL;
8752 : : }
8753 : : /* XXX some man pages make the `pgid` parameter an int, others
8754 : : a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
8755 : : take the same type. Moreover, pid_t is always at least as wide as
8756 : : int (else compilation of this module fails), which is safe. */
8757 [ # # ]: 0 : if (killpg(pgid, signal) == -1)
8758 : 0 : return posix_error();
8759 : 0 : Py_RETURN_NONE;
8760 : : }
8761 : : #endif /* HAVE_KILLPG */
8762 : :
8763 : :
8764 : : #ifdef HAVE_PLOCK
8765 : : #ifdef HAVE_SYS_LOCK_H
8766 : : #include <sys/lock.h>
8767 : : #endif
8768 : :
8769 : : /*[clinic input]
8770 : : os.plock
8771 : : op: int
8772 : : /
8773 : :
8774 : : Lock program segments into memory.");
8775 : : [clinic start generated code]*/
8776 : :
8777 : : static PyObject *
8778 : : os_plock_impl(PyObject *module, int op)
8779 : : /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
8780 : : {
8781 : : if (plock(op) == -1)
8782 : : return posix_error();
8783 : : Py_RETURN_NONE;
8784 : : }
8785 : : #endif /* HAVE_PLOCK */
8786 : :
8787 : :
8788 : : #ifdef HAVE_SETUID
8789 : : /*[clinic input]
8790 : : os.setuid
8791 : :
8792 : : uid: uid_t
8793 : : /
8794 : :
8795 : : Set the current process's user id.
8796 : : [clinic start generated code]*/
8797 : :
8798 : : static PyObject *
8799 : 0 : os_setuid_impl(PyObject *module, uid_t uid)
8800 : : /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
8801 : : {
8802 [ # # ]: 0 : if (setuid(uid) < 0)
8803 : 0 : return posix_error();
8804 : 0 : Py_RETURN_NONE;
8805 : : }
8806 : : #endif /* HAVE_SETUID */
8807 : :
8808 : :
8809 : : #ifdef HAVE_SETEUID
8810 : : /*[clinic input]
8811 : : os.seteuid
8812 : :
8813 : : euid: uid_t
8814 : : /
8815 : :
8816 : : Set the current process's effective user id.
8817 : : [clinic start generated code]*/
8818 : :
8819 : : static PyObject *
8820 : 0 : os_seteuid_impl(PyObject *module, uid_t euid)
8821 : : /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
8822 : : {
8823 [ # # ]: 0 : if (seteuid(euid) < 0)
8824 : 0 : return posix_error();
8825 : 0 : Py_RETURN_NONE;
8826 : : }
8827 : : #endif /* HAVE_SETEUID */
8828 : :
8829 : :
8830 : : #ifdef HAVE_SETEGID
8831 : : /*[clinic input]
8832 : : os.setegid
8833 : :
8834 : : egid: gid_t
8835 : : /
8836 : :
8837 : : Set the current process's effective group id.
8838 : : [clinic start generated code]*/
8839 : :
8840 : : static PyObject *
8841 : 0 : os_setegid_impl(PyObject *module, gid_t egid)
8842 : : /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
8843 : : {
8844 [ # # ]: 0 : if (setegid(egid) < 0)
8845 : 0 : return posix_error();
8846 : 0 : Py_RETURN_NONE;
8847 : : }
8848 : : #endif /* HAVE_SETEGID */
8849 : :
8850 : :
8851 : : #ifdef HAVE_SETREUID
8852 : : /*[clinic input]
8853 : : os.setreuid
8854 : :
8855 : : ruid: uid_t
8856 : : euid: uid_t
8857 : : /
8858 : :
8859 : : Set the current process's real and effective user ids.
8860 : : [clinic start generated code]*/
8861 : :
8862 : : static PyObject *
8863 : 0 : os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
8864 : : /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
8865 : : {
8866 [ # # ]: 0 : if (setreuid(ruid, euid) < 0) {
8867 : 0 : return posix_error();
8868 : : } else {
8869 : 0 : Py_RETURN_NONE;
8870 : : }
8871 : : }
8872 : : #endif /* HAVE_SETREUID */
8873 : :
8874 : :
8875 : : #ifdef HAVE_SETREGID
8876 : : /*[clinic input]
8877 : : os.setregid
8878 : :
8879 : : rgid: gid_t
8880 : : egid: gid_t
8881 : : /
8882 : :
8883 : : Set the current process's real and effective group ids.
8884 : : [clinic start generated code]*/
8885 : :
8886 : : static PyObject *
8887 : 0 : os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
8888 : : /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
8889 : : {
8890 [ # # ]: 0 : if (setregid(rgid, egid) < 0)
8891 : 0 : return posix_error();
8892 : 0 : Py_RETURN_NONE;
8893 : : }
8894 : : #endif /* HAVE_SETREGID */
8895 : :
8896 : :
8897 : : #ifdef HAVE_SETGID
8898 : : /*[clinic input]
8899 : : os.setgid
8900 : : gid: gid_t
8901 : : /
8902 : :
8903 : : Set the current process's group id.
8904 : : [clinic start generated code]*/
8905 : :
8906 : : static PyObject *
8907 : 0 : os_setgid_impl(PyObject *module, gid_t gid)
8908 : : /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
8909 : : {
8910 [ # # ]: 0 : if (setgid(gid) < 0)
8911 : 0 : return posix_error();
8912 : 0 : Py_RETURN_NONE;
8913 : : }
8914 : : #endif /* HAVE_SETGID */
8915 : :
8916 : :
8917 : : #ifdef HAVE_SETGROUPS
8918 : : /*[clinic input]
8919 : : os.setgroups
8920 : :
8921 : : groups: object
8922 : : /
8923 : :
8924 : : Set the groups of the current process to list.
8925 : : [clinic start generated code]*/
8926 : :
8927 : : static PyObject *
8928 : 0 : os_setgroups(PyObject *module, PyObject *groups)
8929 : : /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
8930 : : {
8931 [ # # ]: 0 : if (!PySequence_Check(groups)) {
8932 : 0 : PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
8933 : 0 : return NULL;
8934 : : }
8935 : 0 : Py_ssize_t len = PySequence_Size(groups);
8936 [ # # ]: 0 : if (len < 0) {
8937 : 0 : return NULL;
8938 : : }
8939 [ # # ]: 0 : if (len > MAX_GROUPS) {
8940 : 0 : PyErr_SetString(PyExc_ValueError, "too many groups");
8941 : 0 : return NULL;
8942 : : }
8943 : :
8944 [ # # ]: 0 : gid_t *grouplist = PyMem_New(gid_t, len);
8945 [ # # ]: 0 : for (Py_ssize_t i = 0; i < len; i++) {
8946 : : PyObject *elem;
8947 : 0 : elem = PySequence_GetItem(groups, i);
8948 [ # # ]: 0 : if (!elem) {
8949 : 0 : PyMem_Free(grouplist);
8950 : 0 : return NULL;
8951 : : }
8952 [ # # ]: 0 : if (!PyLong_Check(elem)) {
8953 : 0 : PyErr_SetString(PyExc_TypeError,
8954 : : "groups must be integers");
8955 : 0 : Py_DECREF(elem);
8956 : 0 : PyMem_Free(grouplist);
8957 : 0 : return NULL;
8958 : : } else {
8959 [ # # ]: 0 : if (!_Py_Gid_Converter(elem, &grouplist[i])) {
8960 : 0 : Py_DECREF(elem);
8961 : 0 : PyMem_Free(grouplist);
8962 : 0 : return NULL;
8963 : : }
8964 : : }
8965 : 0 : Py_DECREF(elem);
8966 : : }
8967 : :
8968 [ # # ]: 0 : if (setgroups(len, grouplist) < 0) {
8969 : 0 : PyMem_Free(grouplist);
8970 : 0 : return posix_error();
8971 : : }
8972 : 0 : PyMem_Free(grouplist);
8973 : 0 : Py_RETURN_NONE;
8974 : : }
8975 : : #endif /* HAVE_SETGROUPS */
8976 : :
8977 : : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
8978 : : static PyObject *
8979 : 0 : wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
8980 : : {
8981 : : PyObject *result;
8982 : : PyObject *struct_rusage;
8983 : :
8984 [ # # ]: 0 : if (pid == -1)
8985 : 0 : return posix_error();
8986 : :
8987 : : // If wait succeeded but no child was ready to report status, ru will not
8988 : : // have been populated.
8989 [ # # ]: 0 : if (pid == 0) {
8990 : 0 : memset(ru, 0, sizeof(*ru));
8991 : : }
8992 : :
8993 : 0 : struct_rusage = _PyImport_GetModuleAttrString("resource", "struct_rusage");
8994 [ # # ]: 0 : if (struct_rusage == NULL)
8995 : 0 : return NULL;
8996 : :
8997 : : /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
8998 : 0 : result = PyStructSequence_New((PyTypeObject*) struct_rusage);
8999 : 0 : Py_DECREF(struct_rusage);
9000 [ # # ]: 0 : if (!result)
9001 : 0 : return NULL;
9002 : :
9003 : : #ifndef doubletime
9004 : : #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
9005 : : #endif
9006 : :
9007 : 0 : PyStructSequence_SET_ITEM(result, 0,
9008 : : PyFloat_FromDouble(doubletime(ru->ru_utime)));
9009 : 0 : PyStructSequence_SET_ITEM(result, 1,
9010 : : PyFloat_FromDouble(doubletime(ru->ru_stime)));
9011 : : #define SET_INT(result, index, value)\
9012 : : PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
9013 : 0 : SET_INT(result, 2, ru->ru_maxrss);
9014 : 0 : SET_INT(result, 3, ru->ru_ixrss);
9015 : 0 : SET_INT(result, 4, ru->ru_idrss);
9016 : 0 : SET_INT(result, 5, ru->ru_isrss);
9017 : 0 : SET_INT(result, 6, ru->ru_minflt);
9018 : 0 : SET_INT(result, 7, ru->ru_majflt);
9019 : 0 : SET_INT(result, 8, ru->ru_nswap);
9020 : 0 : SET_INT(result, 9, ru->ru_inblock);
9021 : 0 : SET_INT(result, 10, ru->ru_oublock);
9022 : 0 : SET_INT(result, 11, ru->ru_msgsnd);
9023 : 0 : SET_INT(result, 12, ru->ru_msgrcv);
9024 : 0 : SET_INT(result, 13, ru->ru_nsignals);
9025 : 0 : SET_INT(result, 14, ru->ru_nvcsw);
9026 : 0 : SET_INT(result, 15, ru->ru_nivcsw);
9027 : : #undef SET_INT
9028 : :
9029 [ # # ]: 0 : if (PyErr_Occurred()) {
9030 : 0 : Py_DECREF(result);
9031 : 0 : return NULL;
9032 : : }
9033 : :
9034 : 0 : return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
9035 : : }
9036 : : #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
9037 : :
9038 : :
9039 : : #ifdef HAVE_WAIT3
9040 : : /*[clinic input]
9041 : : os.wait3
9042 : :
9043 : : options: int
9044 : : Wait for completion of a child process.
9045 : :
9046 : : Returns a tuple of information about the child process:
9047 : : (pid, status, rusage)
9048 : : [clinic start generated code]*/
9049 : :
9050 : : static PyObject *
9051 : 0 : os_wait3_impl(PyObject *module, int options)
9052 : : /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
9053 : : {
9054 : : pid_t pid;
9055 : : struct rusage ru;
9056 : 0 : int async_err = 0;
9057 : : WAIT_TYPE status;
9058 : 0 : WAIT_STATUS_INT(status) = 0;
9059 : :
9060 : : do {
9061 : 0 : Py_BEGIN_ALLOW_THREADS
9062 : 0 : pid = wait3(&status, options, &ru);
9063 : 0 : Py_END_ALLOW_THREADS
9064 [ # # # # : 0 : } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
9065 [ # # ]: 0 : if (pid < 0)
9066 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
9067 : :
9068 : 0 : return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
9069 : : }
9070 : : #endif /* HAVE_WAIT3 */
9071 : :
9072 : :
9073 : : #ifdef HAVE_WAIT4
9074 : : /*[clinic input]
9075 : :
9076 : : os.wait4
9077 : :
9078 : : pid: pid_t
9079 : : options: int
9080 : :
9081 : : Wait for completion of a specific child process.
9082 : :
9083 : : Returns a tuple of information about the child process:
9084 : : (pid, status, rusage)
9085 : : [clinic start generated code]*/
9086 : :
9087 : : static PyObject *
9088 : 0 : os_wait4_impl(PyObject *module, pid_t pid, int options)
9089 : : /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
9090 : : {
9091 : : pid_t res;
9092 : : struct rusage ru;
9093 : 0 : int async_err = 0;
9094 : : WAIT_TYPE status;
9095 : 0 : WAIT_STATUS_INT(status) = 0;
9096 : :
9097 : : do {
9098 : 0 : Py_BEGIN_ALLOW_THREADS
9099 : 0 : res = wait4(pid, &status, options, &ru);
9100 : 0 : Py_END_ALLOW_THREADS
9101 [ # # # # : 0 : } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
9102 [ # # ]: 0 : if (res < 0)
9103 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
9104 : :
9105 : 0 : return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
9106 : : }
9107 : : #endif /* HAVE_WAIT4 */
9108 : :
9109 : :
9110 : : #if defined(HAVE_WAITID) && !defined(__APPLE__)
9111 : : /*[clinic input]
9112 : : os.waitid
9113 : :
9114 : : idtype: idtype_t
9115 : : Must be one of be P_PID, P_PGID or P_ALL.
9116 : : id: id_t
9117 : : The id to wait on.
9118 : : options: int
9119 : : Constructed from the ORing of one or more of WEXITED, WSTOPPED
9120 : : or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
9121 : : /
9122 : :
9123 : : Returns the result of waiting for a process or processes.
9124 : :
9125 : : Returns either waitid_result or None if WNOHANG is specified and there are
9126 : : no children in a waitable state.
9127 : : [clinic start generated code]*/
9128 : :
9129 : : static PyObject *
9130 : 0 : os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
9131 : : /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
9132 : : {
9133 : : PyObject *result;
9134 : : int res;
9135 : 0 : int async_err = 0;
9136 : : siginfo_t si;
9137 : 0 : si.si_pid = 0;
9138 : :
9139 : : do {
9140 : 0 : Py_BEGIN_ALLOW_THREADS
9141 : 0 : res = waitid(idtype, id, &si, options);
9142 : 0 : Py_END_ALLOW_THREADS
9143 [ # # # # : 0 : } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
9144 [ # # ]: 0 : if (res < 0)
9145 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
9146 : :
9147 [ # # ]: 0 : if (si.si_pid == 0)
9148 : 0 : Py_RETURN_NONE;
9149 : :
9150 : 0 : PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
9151 : 0 : result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
9152 [ # # ]: 0 : if (!result)
9153 : 0 : return NULL;
9154 : :
9155 : 0 : PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
9156 : 0 : PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
9157 : 0 : PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
9158 : 0 : PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
9159 : 0 : PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
9160 [ # # ]: 0 : if (PyErr_Occurred()) {
9161 : 0 : Py_DECREF(result);
9162 : 0 : return NULL;
9163 : : }
9164 : :
9165 : 0 : return result;
9166 : : }
9167 : : #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
9168 : :
9169 : :
9170 : : #if defined(HAVE_WAITPID)
9171 : : /*[clinic input]
9172 : : os.waitpid
9173 : : pid: pid_t
9174 : : options: int
9175 : : /
9176 : :
9177 : : Wait for completion of a given child process.
9178 : :
9179 : : Returns a tuple of information regarding the child process:
9180 : : (pid, status)
9181 : :
9182 : : The options argument is ignored on Windows.
9183 : : [clinic start generated code]*/
9184 : :
9185 : : static PyObject *
9186 : 1 : os_waitpid_impl(PyObject *module, pid_t pid, int options)
9187 : : /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
9188 : : {
9189 : : pid_t res;
9190 : 1 : int async_err = 0;
9191 : : WAIT_TYPE status;
9192 : 1 : WAIT_STATUS_INT(status) = 0;
9193 : :
9194 : : do {
9195 : 1 : Py_BEGIN_ALLOW_THREADS
9196 : 1 : res = waitpid(pid, &status, options);
9197 : 1 : Py_END_ALLOW_THREADS
9198 [ + - - + : 1 : } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
9199 [ + - ]: 1 : if (res < 0)
9200 [ + - ]: 1 : return (!async_err) ? posix_error() : NULL;
9201 : :
9202 : 0 : return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
9203 : : }
9204 : : #elif defined(HAVE_CWAIT)
9205 : : /* MS C has a variant of waitpid() that's usable for most purposes. */
9206 : : /*[clinic input]
9207 : : os.waitpid
9208 : : pid: intptr_t
9209 : : options: int
9210 : : /
9211 : :
9212 : : Wait for completion of a given process.
9213 : :
9214 : : Returns a tuple of information regarding the process:
9215 : : (pid, status << 8)
9216 : :
9217 : : The options argument is ignored on Windows.
9218 : : [clinic start generated code]*/
9219 : :
9220 : : static PyObject *
9221 : : os_waitpid_impl(PyObject *module, intptr_t pid, int options)
9222 : : /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
9223 : : {
9224 : : int status;
9225 : : intptr_t res;
9226 : : int async_err = 0;
9227 : :
9228 : : do {
9229 : : Py_BEGIN_ALLOW_THREADS
9230 : : _Py_BEGIN_SUPPRESS_IPH
9231 : : res = _cwait(&status, pid, options);
9232 : : _Py_END_SUPPRESS_IPH
9233 : : Py_END_ALLOW_THREADS
9234 : : } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9235 : : if (res < 0)
9236 : : return (!async_err) ? posix_error() : NULL;
9237 : :
9238 : : unsigned long long ustatus = (unsigned int)status;
9239 : :
9240 : : /* shift the status left a byte so this is more like the POSIX waitpid */
9241 : : return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
9242 : : }
9243 : : #endif
9244 : :
9245 : :
9246 : : #ifdef HAVE_WAIT
9247 : : /*[clinic input]
9248 : : os.wait
9249 : :
9250 : : Wait for completion of a child process.
9251 : :
9252 : : Returns a tuple of information about the child process:
9253 : : (pid, status)
9254 : : [clinic start generated code]*/
9255 : :
9256 : : static PyObject *
9257 : 0 : os_wait_impl(PyObject *module)
9258 : : /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
9259 : : {
9260 : : pid_t pid;
9261 : 0 : int async_err = 0;
9262 : : WAIT_TYPE status;
9263 : 0 : WAIT_STATUS_INT(status) = 0;
9264 : :
9265 : : do {
9266 : 0 : Py_BEGIN_ALLOW_THREADS
9267 : 0 : pid = wait(&status);
9268 : 0 : Py_END_ALLOW_THREADS
9269 [ # # # # : 0 : } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
9270 [ # # ]: 0 : if (pid < 0)
9271 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
9272 : :
9273 : 0 : return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
9274 : : }
9275 : : #endif /* HAVE_WAIT */
9276 : :
9277 : : #if defined(__linux__) && defined(__NR_pidfd_open)
9278 : : /*[clinic input]
9279 : : os.pidfd_open
9280 : : pid: pid_t
9281 : : flags: unsigned_int = 0
9282 : :
9283 : : Return a file descriptor referring to the process *pid*.
9284 : :
9285 : : The descriptor can be used to perform process management without races and
9286 : : signals.
9287 : : [clinic start generated code]*/
9288 : :
9289 : : static PyObject *
9290 : 0 : os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
9291 : : /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
9292 : : {
9293 : 0 : int fd = syscall(__NR_pidfd_open, pid, flags);
9294 [ # # ]: 0 : if (fd < 0) {
9295 : 0 : return posix_error();
9296 : : }
9297 : 0 : return PyLong_FromLong(fd);
9298 : : }
9299 : : #endif
9300 : :
9301 : :
9302 : : #ifdef HAVE_SETNS
9303 : : /*[clinic input]
9304 : : os.setns
9305 : : fd: fildes
9306 : : A file descriptor to a namespace.
9307 : : nstype: int = 0
9308 : : Type of namespace.
9309 : :
9310 : : Move the calling thread into different namespaces.
9311 : : [clinic start generated code]*/
9312 : :
9313 : : static PyObject *
9314 : 0 : os_setns_impl(PyObject *module, int fd, int nstype)
9315 : : /*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
9316 : : {
9317 : : int res;
9318 : :
9319 : 0 : Py_BEGIN_ALLOW_THREADS
9320 : 0 : res = setns(fd, nstype);
9321 : 0 : Py_END_ALLOW_THREADS
9322 : :
9323 [ # # ]: 0 : if (res != 0) {
9324 : 0 : return posix_error();
9325 : : }
9326 : :
9327 : 0 : Py_RETURN_NONE;
9328 : : }
9329 : : #endif
9330 : :
9331 : :
9332 : : #ifdef HAVE_UNSHARE
9333 : : /*[clinic input]
9334 : : os.unshare
9335 : : flags: int
9336 : : Namespaces to be unshared.
9337 : :
9338 : : Disassociate parts of a process (or thread) execution context.
9339 : : [clinic start generated code]*/
9340 : :
9341 : : static PyObject *
9342 : 0 : os_unshare_impl(PyObject *module, int flags)
9343 : : /*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
9344 : : {
9345 : : int res;
9346 : :
9347 : 0 : Py_BEGIN_ALLOW_THREADS
9348 : 0 : res = unshare(flags);
9349 : 0 : Py_END_ALLOW_THREADS
9350 : :
9351 [ # # ]: 0 : if (res != 0) {
9352 : 0 : return posix_error();
9353 : : }
9354 : :
9355 : 0 : Py_RETURN_NONE;
9356 : : }
9357 : : #endif
9358 : :
9359 : :
9360 : : #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
9361 : : /*[clinic input]
9362 : : os.readlink
9363 : :
9364 : : path: path_t
9365 : : *
9366 : : dir_fd: dir_fd(requires='readlinkat') = None
9367 : :
9368 : : Return a string representing the path to which the symbolic link points.
9369 : :
9370 : : If dir_fd is not None, it should be a file descriptor open to a directory,
9371 : : and path should be relative; path will then be relative to that directory.
9372 : :
9373 : : dir_fd may not be implemented on your platform. If it is unavailable,
9374 : : using it will raise a NotImplementedError.
9375 : : [clinic start generated code]*/
9376 : :
9377 : : static PyObject *
9378 : 0 : os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
9379 : : /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
9380 : : {
9381 : : #if defined(HAVE_READLINK)
9382 : : char buffer[MAXPATHLEN+1];
9383 : : ssize_t length;
9384 : : #ifdef HAVE_READLINKAT
9385 : 0 : int readlinkat_unavailable = 0;
9386 : : #endif
9387 : :
9388 : 0 : Py_BEGIN_ALLOW_THREADS
9389 : : #ifdef HAVE_READLINKAT
9390 [ # # ]: 0 : if (dir_fd != DEFAULT_DIR_FD) {
9391 : : if (HAVE_READLINKAT_RUNTIME) {
9392 : 0 : length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
9393 : : } else {
9394 : : readlinkat_unavailable = 1;
9395 : : }
9396 : : } else
9397 : : #endif
9398 : 0 : length = readlink(path->narrow, buffer, MAXPATHLEN);
9399 : 0 : Py_END_ALLOW_THREADS
9400 : :
9401 : : #ifdef HAVE_READLINKAT
9402 [ # # ]: 0 : if (readlinkat_unavailable) {
9403 : 0 : argument_unavailable_error(NULL, "dir_fd");
9404 : 0 : return NULL;
9405 : : }
9406 : : #endif
9407 : :
9408 [ # # ]: 0 : if (length < 0) {
9409 : 0 : return path_error(path);
9410 : : }
9411 : 0 : buffer[length] = '\0';
9412 : :
9413 [ # # ]: 0 : if (PyUnicode_Check(path->object))
9414 : 0 : return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
9415 : : else
9416 : 0 : return PyBytes_FromStringAndSize(buffer, length);
9417 : : #elif defined(MS_WINDOWS)
9418 : : DWORD n_bytes_returned;
9419 : : DWORD io_result = 0;
9420 : : HANDLE reparse_point_handle;
9421 : : char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
9422 : : _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
9423 : : PyObject *result = NULL;
9424 : :
9425 : : /* First get a handle to the reparse point */
9426 : : Py_BEGIN_ALLOW_THREADS
9427 : : reparse_point_handle = CreateFileW(
9428 : : path->wide,
9429 : : 0,
9430 : : 0,
9431 : : 0,
9432 : : OPEN_EXISTING,
9433 : : FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
9434 : : 0);
9435 : : if (reparse_point_handle != INVALID_HANDLE_VALUE) {
9436 : : /* New call DeviceIoControl to read the reparse point */
9437 : : io_result = DeviceIoControl(
9438 : : reparse_point_handle,
9439 : : FSCTL_GET_REPARSE_POINT,
9440 : : 0, 0, /* in buffer */
9441 : : target_buffer, sizeof(target_buffer),
9442 : : &n_bytes_returned,
9443 : : 0 /* we're not using OVERLAPPED_IO */
9444 : : );
9445 : : CloseHandle(reparse_point_handle);
9446 : : }
9447 : : Py_END_ALLOW_THREADS
9448 : :
9449 : : if (io_result == 0) {
9450 : : return path_error(path);
9451 : : }
9452 : :
9453 : : wchar_t *name = NULL;
9454 : : Py_ssize_t nameLen = 0;
9455 : : if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
9456 : : {
9457 : : name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
9458 : : rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
9459 : : nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
9460 : : }
9461 : : else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
9462 : : {
9463 : : name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
9464 : : rdb->MountPointReparseBuffer.SubstituteNameOffset);
9465 : : nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
9466 : : }
9467 : : else
9468 : : {
9469 : : PyErr_SetString(PyExc_ValueError, "not a symbolic link");
9470 : : }
9471 : : if (name) {
9472 : : if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
9473 : : /* Our buffer is mutable, so this is okay */
9474 : : name[1] = L'\\';
9475 : : }
9476 : : result = PyUnicode_FromWideChar(name, nameLen);
9477 : : if (result && path->narrow) {
9478 : : Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
9479 : : }
9480 : : }
9481 : : return result;
9482 : : #endif
9483 : : }
9484 : : #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
9485 : :
9486 : : #if defined(MS_WINDOWS)
9487 : :
9488 : : /* Remove the last portion of the path - return 0 on success */
9489 : : static int
9490 : : _dirnameW(WCHAR *path)
9491 : : {
9492 : : WCHAR *ptr;
9493 : : size_t length = wcsnlen_s(path, MAX_PATH);
9494 : : if (length == MAX_PATH) {
9495 : : return -1;
9496 : : }
9497 : :
9498 : : /* walk the path from the end until a backslash is encountered */
9499 : : for(ptr = path + length; ptr != path; ptr--) {
9500 : : if (*ptr == L'\\' || *ptr == L'/') {
9501 : : break;
9502 : : }
9503 : : }
9504 : : *ptr = 0;
9505 : : return 0;
9506 : : }
9507 : :
9508 : : #endif
9509 : :
9510 : : #ifdef HAVE_SYMLINK
9511 : :
9512 : : #if defined(MS_WINDOWS)
9513 : :
9514 : : /* Is this path absolute? */
9515 : : static int
9516 : : _is_absW(const WCHAR *path)
9517 : : {
9518 : : return path[0] == L'\\' || path[0] == L'/' ||
9519 : : (path[0] && path[1] == L':');
9520 : : }
9521 : :
9522 : : /* join root and rest with a backslash - return 0 on success */
9523 : : static int
9524 : : _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
9525 : : {
9526 : : if (_is_absW(rest)) {
9527 : : return wcscpy_s(dest_path, MAX_PATH, rest);
9528 : : }
9529 : :
9530 : : if (wcscpy_s(dest_path, MAX_PATH, root)) {
9531 : : return -1;
9532 : : }
9533 : :
9534 : : if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
9535 : : return -1;
9536 : : }
9537 : :
9538 : : return wcscat_s(dest_path, MAX_PATH, rest);
9539 : : }
9540 : :
9541 : : /* Return True if the path at src relative to dest is a directory */
9542 : : static int
9543 : : _check_dirW(LPCWSTR src, LPCWSTR dest)
9544 : : {
9545 : : WIN32_FILE_ATTRIBUTE_DATA src_info;
9546 : : WCHAR dest_parent[MAX_PATH];
9547 : : WCHAR src_resolved[MAX_PATH] = L"";
9548 : :
9549 : : /* dest_parent = os.path.dirname(dest) */
9550 : : if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
9551 : : _dirnameW(dest_parent)) {
9552 : : return 0;
9553 : : }
9554 : : /* src_resolved = os.path.join(dest_parent, src) */
9555 : : if (_joinW(src_resolved, dest_parent, src)) {
9556 : : return 0;
9557 : : }
9558 : : return (
9559 : : GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
9560 : : && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
9561 : : );
9562 : : }
9563 : : #endif
9564 : :
9565 : :
9566 : : /*[clinic input]
9567 : : os.symlink
9568 : : src: path_t
9569 : : dst: path_t
9570 : : target_is_directory: bool = False
9571 : : *
9572 : : dir_fd: dir_fd(requires='symlinkat')=None
9573 : :
9574 : : # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
9575 : :
9576 : : Create a symbolic link pointing to src named dst.
9577 : :
9578 : : target_is_directory is required on Windows if the target is to be
9579 : : interpreted as a directory. (On Windows, symlink requires
9580 : : Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
9581 : : target_is_directory is ignored on non-Windows platforms.
9582 : :
9583 : : If dir_fd is not None, it should be a file descriptor open to a directory,
9584 : : and path should be relative; path will then be relative to that directory.
9585 : : dir_fd may not be implemented on your platform.
9586 : : If it is unavailable, using it will raise a NotImplementedError.
9587 : :
9588 : : [clinic start generated code]*/
9589 : :
9590 : : static PyObject *
9591 : 0 : os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
9592 : : int target_is_directory, int dir_fd)
9593 : : /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
9594 : : {
9595 : : #ifdef MS_WINDOWS
9596 : : DWORD result;
9597 : : DWORD flags = 0;
9598 : :
9599 : : /* Assumed true, set to false if detected to not be available. */
9600 : : static int windows_has_symlink_unprivileged_flag = TRUE;
9601 : : #else
9602 : : int result;
9603 : : #ifdef HAVE_SYMLINKAT
9604 : 0 : int symlinkat_unavailable = 0;
9605 : : #endif
9606 : : #endif
9607 : :
9608 [ # # # # ]: 0 : if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
9609 : : dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
9610 : 0 : return NULL;
9611 : : }
9612 : :
9613 : : #ifdef MS_WINDOWS
9614 : :
9615 : : if (windows_has_symlink_unprivileged_flag) {
9616 : : /* Allow non-admin symlinks if system allows it. */
9617 : : flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
9618 : : }
9619 : :
9620 : : Py_BEGIN_ALLOW_THREADS
9621 : : _Py_BEGIN_SUPPRESS_IPH
9622 : : /* if src is a directory, ensure flags==1 (target_is_directory bit) */
9623 : : if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
9624 : : flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
9625 : : }
9626 : :
9627 : : result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
9628 : : _Py_END_SUPPRESS_IPH
9629 : : Py_END_ALLOW_THREADS
9630 : :
9631 : : if (windows_has_symlink_unprivileged_flag && !result &&
9632 : : ERROR_INVALID_PARAMETER == GetLastError()) {
9633 : :
9634 : : Py_BEGIN_ALLOW_THREADS
9635 : : _Py_BEGIN_SUPPRESS_IPH
9636 : : /* This error might be caused by
9637 : : SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
9638 : : Try again, and update windows_has_symlink_unprivileged_flag if we
9639 : : are successful this time.
9640 : :
9641 : : NOTE: There is a risk of a race condition here if there are other
9642 : : conditions than the flag causing ERROR_INVALID_PARAMETER, and
9643 : : another process (or thread) changes that condition in between our
9644 : : calls to CreateSymbolicLink.
9645 : : */
9646 : : flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
9647 : : result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
9648 : : _Py_END_SUPPRESS_IPH
9649 : : Py_END_ALLOW_THREADS
9650 : :
9651 : : if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
9652 : : windows_has_symlink_unprivileged_flag = FALSE;
9653 : : }
9654 : : }
9655 : :
9656 : : if (!result)
9657 : : return path_error2(src, dst);
9658 : :
9659 : : #else
9660 : :
9661 [ # # # # : 0 : if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
# # # # ]
9662 : 0 : PyErr_SetString(PyExc_ValueError,
9663 : : "symlink: src and dst must be the same type");
9664 : 0 : return NULL;
9665 : : }
9666 : :
9667 : 0 : Py_BEGIN_ALLOW_THREADS
9668 : : #ifdef HAVE_SYMLINKAT
9669 [ # # ]: 0 : if (dir_fd != DEFAULT_DIR_FD) {
9670 : : if (HAVE_SYMLINKAT_RUNTIME) {
9671 : 0 : result = symlinkat(src->narrow, dir_fd, dst->narrow);
9672 : : } else {
9673 : : symlinkat_unavailable = 1;
9674 : : }
9675 : : } else
9676 : : #endif
9677 : 0 : result = symlink(src->narrow, dst->narrow);
9678 : 0 : Py_END_ALLOW_THREADS
9679 : :
9680 : : #ifdef HAVE_SYMLINKAT
9681 [ # # ]: 0 : if (symlinkat_unavailable) {
9682 : 0 : argument_unavailable_error(NULL, "dir_fd");
9683 : 0 : return NULL;
9684 : : }
9685 : : #endif
9686 : :
9687 [ # # ]: 0 : if (result)
9688 : 0 : return path_error2(src, dst);
9689 : : #endif
9690 : :
9691 : 0 : Py_RETURN_NONE;
9692 : : }
9693 : : #endif /* HAVE_SYMLINK */
9694 : :
9695 : :
9696 : :
9697 : :
9698 : : static PyStructSequence_Field times_result_fields[] = {
9699 : : {"user", "user time"},
9700 : : {"system", "system time"},
9701 : : {"children_user", "user time of children"},
9702 : : {"children_system", "system time of children"},
9703 : : {"elapsed", "elapsed time since an arbitrary point in the past"},
9704 : : {NULL}
9705 : : };
9706 : :
9707 : : PyDoc_STRVAR(times_result__doc__,
9708 : : "times_result: Result from os.times().\n\n\
9709 : : This object may be accessed either as a tuple of\n\
9710 : : (user, system, children_user, children_system, elapsed),\n\
9711 : : or via the attributes user, system, children_user, children_system,\n\
9712 : : and elapsed.\n\
9713 : : \n\
9714 : : See os.times for more information.");
9715 : :
9716 : : static PyStructSequence_Desc times_result_desc = {
9717 : : "times_result", /* name */
9718 : : times_result__doc__, /* doc */
9719 : : times_result_fields,
9720 : : 5
9721 : : };
9722 : :
9723 : : #ifdef MS_WINDOWS
9724 : : #define HAVE_TIMES /* mandatory, for the method table */
9725 : : #endif
9726 : :
9727 : : #ifdef HAVE_TIMES
9728 : :
9729 : : static PyObject *
9730 : 0 : build_times_result(PyObject *module, double user, double system,
9731 : : double children_user, double children_system,
9732 : : double elapsed)
9733 : : {
9734 : 0 : PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
9735 : 0 : PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
9736 [ # # ]: 0 : if (value == NULL)
9737 : 0 : return NULL;
9738 : :
9739 : : #define SET(i, field) \
9740 : : { \
9741 : : PyObject *o = PyFloat_FromDouble(field); \
9742 : : if (!o) { \
9743 : : Py_DECREF(value); \
9744 : : return NULL; \
9745 : : } \
9746 : : PyStructSequence_SET_ITEM(value, i, o); \
9747 : : } \
9748 : :
9749 [ # # ]: 0 : SET(0, user);
9750 [ # # ]: 0 : SET(1, system);
9751 [ # # ]: 0 : SET(2, children_user);
9752 [ # # ]: 0 : SET(3, children_system);
9753 [ # # ]: 0 : SET(4, elapsed);
9754 : :
9755 : : #undef SET
9756 : :
9757 : 0 : return value;
9758 : : }
9759 : :
9760 : :
9761 : : /*[clinic input]
9762 : : os.times
9763 : :
9764 : : Return a collection containing process timing information.
9765 : :
9766 : : The object returned behaves like a named tuple with these fields:
9767 : : (utime, stime, cutime, cstime, elapsed_time)
9768 : : All fields are floating point numbers.
9769 : : [clinic start generated code]*/
9770 : :
9771 : : static PyObject *
9772 : 0 : os_times_impl(PyObject *module)
9773 : : /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
9774 : : #ifdef MS_WINDOWS
9775 : : {
9776 : : FILETIME create, exit, kernel, user;
9777 : : HANDLE hProc;
9778 : : hProc = GetCurrentProcess();
9779 : : GetProcessTimes(hProc, &create, &exit, &kernel, &user);
9780 : : /* The fields of a FILETIME structure are the hi and lo part
9781 : : of a 64-bit value expressed in 100 nanosecond units.
9782 : : 1e7 is one second in such units; 1e-7 the inverse.
9783 : : 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
9784 : : */
9785 : : return build_times_result(module,
9786 : : (double)(user.dwHighDateTime*429.4967296 +
9787 : : user.dwLowDateTime*1e-7),
9788 : : (double)(kernel.dwHighDateTime*429.4967296 +
9789 : : kernel.dwLowDateTime*1e-7),
9790 : : (double)0,
9791 : : (double)0,
9792 : : (double)0);
9793 : : }
9794 : : #else /* MS_WINDOWS */
9795 : : {
9796 : : struct tms t;
9797 : : clock_t c;
9798 : 0 : errno = 0;
9799 : 0 : c = times(&t);
9800 [ # # ]: 0 : if (c == (clock_t) -1) {
9801 : 0 : return posix_error();
9802 : : }
9803 : : assert(_PyRuntime.time.ticks_per_second_initialized);
9804 : : #define ticks_per_second _PyRuntime.time.ticks_per_second
9805 : 0 : return build_times_result(module,
9806 : 0 : (double)t.tms_utime / ticks_per_second,
9807 : 0 : (double)t.tms_stime / ticks_per_second,
9808 : 0 : (double)t.tms_cutime / ticks_per_second,
9809 : 0 : (double)t.tms_cstime / ticks_per_second,
9810 : 0 : (double)c / ticks_per_second);
9811 : : #undef ticks_per_second
9812 : : }
9813 : : #endif /* MS_WINDOWS */
9814 : : #endif /* HAVE_TIMES */
9815 : :
9816 : :
9817 : : #ifdef HAVE_GETSID
9818 : : /*[clinic input]
9819 : : os.getsid
9820 : :
9821 : : pid: pid_t
9822 : : /
9823 : :
9824 : : Call the system call getsid(pid) and return the result.
9825 : : [clinic start generated code]*/
9826 : :
9827 : : static PyObject *
9828 : 0 : os_getsid_impl(PyObject *module, pid_t pid)
9829 : : /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
9830 : : {
9831 : : int sid;
9832 : 0 : sid = getsid(pid);
9833 [ # # ]: 0 : if (sid < 0)
9834 : 0 : return posix_error();
9835 : 0 : return PyLong_FromLong((long)sid);
9836 : : }
9837 : : #endif /* HAVE_GETSID */
9838 : :
9839 : :
9840 : : #ifdef HAVE_SETSID
9841 : : /*[clinic input]
9842 : : os.setsid
9843 : :
9844 : : Call the system call setsid().
9845 : : [clinic start generated code]*/
9846 : :
9847 : : static PyObject *
9848 : 0 : os_setsid_impl(PyObject *module)
9849 : : /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
9850 : : {
9851 [ # # ]: 0 : if (setsid() < 0)
9852 : 0 : return posix_error();
9853 : 0 : Py_RETURN_NONE;
9854 : : }
9855 : : #endif /* HAVE_SETSID */
9856 : :
9857 : :
9858 : : #ifdef HAVE_SETPGID
9859 : : /*[clinic input]
9860 : : os.setpgid
9861 : :
9862 : : pid: pid_t
9863 : : pgrp: pid_t
9864 : : /
9865 : :
9866 : : Call the system call setpgid(pid, pgrp).
9867 : : [clinic start generated code]*/
9868 : :
9869 : : static PyObject *
9870 : 0 : os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
9871 : : /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
9872 : : {
9873 [ # # ]: 0 : if (setpgid(pid, pgrp) < 0)
9874 : 0 : return posix_error();
9875 : 0 : Py_RETURN_NONE;
9876 : : }
9877 : : #endif /* HAVE_SETPGID */
9878 : :
9879 : :
9880 : : #ifdef HAVE_TCGETPGRP
9881 : : /*[clinic input]
9882 : : os.tcgetpgrp
9883 : :
9884 : : fd: int
9885 : : /
9886 : :
9887 : : Return the process group associated with the terminal specified by fd.
9888 : : [clinic start generated code]*/
9889 : :
9890 : : static PyObject *
9891 : 0 : os_tcgetpgrp_impl(PyObject *module, int fd)
9892 : : /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
9893 : : {
9894 : 0 : pid_t pgid = tcgetpgrp(fd);
9895 [ # # ]: 0 : if (pgid < 0)
9896 : 0 : return posix_error();
9897 : 0 : return PyLong_FromPid(pgid);
9898 : : }
9899 : : #endif /* HAVE_TCGETPGRP */
9900 : :
9901 : :
9902 : : #ifdef HAVE_TCSETPGRP
9903 : : /*[clinic input]
9904 : : os.tcsetpgrp
9905 : :
9906 : : fd: int
9907 : : pgid: pid_t
9908 : : /
9909 : :
9910 : : Set the process group associated with the terminal specified by fd.
9911 : : [clinic start generated code]*/
9912 : :
9913 : : static PyObject *
9914 : 0 : os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
9915 : : /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
9916 : : {
9917 [ # # ]: 0 : if (tcsetpgrp(fd, pgid) < 0)
9918 : 0 : return posix_error();
9919 : 0 : Py_RETURN_NONE;
9920 : : }
9921 : : #endif /* HAVE_TCSETPGRP */
9922 : :
9923 : : /* Functions acting on file descriptors */
9924 : :
9925 : : #ifdef O_CLOEXEC
9926 : : extern int _Py_open_cloexec_works;
9927 : : #endif
9928 : :
9929 : :
9930 : : /*[clinic input]
9931 : : os.open -> int
9932 : : path: path_t
9933 : : flags: int
9934 : : mode: int = 0o777
9935 : : *
9936 : : dir_fd: dir_fd(requires='openat') = None
9937 : :
9938 : : # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
9939 : :
9940 : : Open a file for low level IO. Returns a file descriptor (integer).
9941 : :
9942 : : If dir_fd is not None, it should be a file descriptor open to a directory,
9943 : : and path should be relative; path will then be relative to that directory.
9944 : : dir_fd may not be implemented on your platform.
9945 : : If it is unavailable, using it will raise a NotImplementedError.
9946 : : [clinic start generated code]*/
9947 : :
9948 : : static int
9949 : 160 : os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
9950 : : /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
9951 : : {
9952 : : int fd;
9953 : 160 : int async_err = 0;
9954 : : #ifdef HAVE_OPENAT
9955 : 160 : int openat_unavailable = 0;
9956 : : #endif
9957 : :
9958 : : #ifdef O_CLOEXEC
9959 : 160 : int *atomic_flag_works = &_Py_open_cloexec_works;
9960 : : #elif !defined(MS_WINDOWS)
9961 : : int *atomic_flag_works = NULL;
9962 : : #endif
9963 : :
9964 : : #ifdef MS_WINDOWS
9965 : : flags |= O_NOINHERIT;
9966 : : #elif defined(O_CLOEXEC)
9967 : 160 : flags |= O_CLOEXEC;
9968 : : #endif
9969 : :
9970 [ - + ]: 160 : if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
9971 : 0 : return -1;
9972 : : }
9973 : :
9974 : : _Py_BEGIN_SUPPRESS_IPH
9975 : : do {
9976 : 160 : Py_BEGIN_ALLOW_THREADS
9977 : : #ifdef MS_WINDOWS
9978 : : fd = _wopen(path->wide, flags, mode);
9979 : : #else
9980 : : #ifdef HAVE_OPENAT
9981 [ - + ]: 160 : if (dir_fd != DEFAULT_DIR_FD) {
9982 : : if (HAVE_OPENAT_RUNTIME) {
9983 : 0 : fd = openat(dir_fd, path->narrow, flags, mode);
9984 : :
9985 : : } else {
9986 : : openat_unavailable = 1;
9987 : : fd = -1;
9988 : : }
9989 : : } else
9990 : : #endif /* HAVE_OPENAT */
9991 : 160 : fd = open(path->narrow, flags, mode);
9992 : : #endif /* !MS_WINDOWS */
9993 : 160 : Py_END_ALLOW_THREADS
9994 [ - + - - : 160 : } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
9995 : : _Py_END_SUPPRESS_IPH
9996 : :
9997 : : #ifdef HAVE_OPENAT
9998 [ - + ]: 160 : if (openat_unavailable) {
9999 : 0 : argument_unavailable_error(NULL, "dir_fd");
10000 : 0 : return -1;
10001 : : }
10002 : : #endif
10003 : :
10004 [ - + ]: 160 : if (fd < 0) {
10005 [ # # ]: 0 : if (!async_err)
10006 : 0 : PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
10007 : 0 : return -1;
10008 : : }
10009 : :
10010 : : #ifndef MS_WINDOWS
10011 [ - + ]: 160 : if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
10012 : 0 : close(fd);
10013 : 0 : return -1;
10014 : : }
10015 : : #endif
10016 : :
10017 : 160 : return fd;
10018 : : }
10019 : :
10020 : :
10021 : : /*[clinic input]
10022 : : os.close
10023 : :
10024 : : fd: int
10025 : :
10026 : : Close a file descriptor.
10027 : : [clinic start generated code]*/
10028 : :
10029 : : static PyObject *
10030 : 1 : os_close_impl(PyObject *module, int fd)
10031 : : /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
10032 : : {
10033 : : int res;
10034 : : /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
10035 : : * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
10036 : : * for more details.
10037 : : */
10038 : 1 : Py_BEGIN_ALLOW_THREADS
10039 : : _Py_BEGIN_SUPPRESS_IPH
10040 : 1 : res = close(fd);
10041 : : _Py_END_SUPPRESS_IPH
10042 : 1 : Py_END_ALLOW_THREADS
10043 [ - + ]: 1 : if (res < 0)
10044 : 0 : return posix_error();
10045 : 1 : Py_RETURN_NONE;
10046 : : }
10047 : :
10048 : : /*[clinic input]
10049 : : os.closerange
10050 : :
10051 : : fd_low: int
10052 : : fd_high: int
10053 : : /
10054 : :
10055 : : Closes all file descriptors in [fd_low, fd_high), ignoring errors.
10056 : : [clinic start generated code]*/
10057 : :
10058 : : static PyObject *
10059 : 0 : os_closerange_impl(PyObject *module, int fd_low, int fd_high)
10060 : : /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
10061 : : {
10062 : 0 : Py_BEGIN_ALLOW_THREADS
10063 : 0 : _Py_closerange(fd_low, fd_high - 1);
10064 : 0 : Py_END_ALLOW_THREADS
10065 : 0 : Py_RETURN_NONE;
10066 : : }
10067 : :
10068 : :
10069 : : /*[clinic input]
10070 : : os.dup -> int
10071 : :
10072 : : fd: int
10073 : : /
10074 : :
10075 : : Return a duplicate of a file descriptor.
10076 : : [clinic start generated code]*/
10077 : :
10078 : : static int
10079 : 0 : os_dup_impl(PyObject *module, int fd)
10080 : : /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
10081 : : {
10082 : 0 : return _Py_dup(fd);
10083 : : }
10084 : :
10085 : : // dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
10086 : : // dup2.c provides working dup2() if and only if F_DUPFD is available.
10087 : : #if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
10088 : : /*[clinic input]
10089 : : os.dup2 -> int
10090 : : fd: int
10091 : : fd2: int
10092 : : inheritable: bool=True
10093 : :
10094 : : Duplicate file descriptor.
10095 : : [clinic start generated code]*/
10096 : :
10097 : : static int
10098 : 0 : os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
10099 : : /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
10100 : : {
10101 : 0 : int res = 0;
10102 : : #if defined(HAVE_DUP3) && \
10103 : : !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
10104 : : /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
10105 : : static int dup3_works = -1;
10106 : : #endif
10107 : :
10108 : : /* dup2() can fail with EINTR if the target FD is already open, because it
10109 : : * then has to be closed. See os_close_impl() for why we don't handle EINTR
10110 : : * upon close(), and therefore below.
10111 : : */
10112 : : #ifdef MS_WINDOWS
10113 : : Py_BEGIN_ALLOW_THREADS
10114 : : _Py_BEGIN_SUPPRESS_IPH
10115 : : res = dup2(fd, fd2);
10116 : : _Py_END_SUPPRESS_IPH
10117 : : Py_END_ALLOW_THREADS
10118 : : if (res < 0) {
10119 : : posix_error();
10120 : : return -1;
10121 : : }
10122 : : res = fd2; // msvcrt dup2 returns 0 on success.
10123 : :
10124 : : /* Character files like console cannot be make non-inheritable */
10125 : : if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
10126 : : close(fd2);
10127 : : return -1;
10128 : : }
10129 : :
10130 : : #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
10131 : : Py_BEGIN_ALLOW_THREADS
10132 : : if (!inheritable)
10133 : : res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
10134 : : else
10135 : : res = dup2(fd, fd2);
10136 : : Py_END_ALLOW_THREADS
10137 : : if (res < 0) {
10138 : : posix_error();
10139 : : return -1;
10140 : : }
10141 : :
10142 : : #else
10143 : :
10144 : : #ifdef HAVE_DUP3
10145 [ # # # # ]: 0 : if (!inheritable && dup3_works != 0) {
10146 : 0 : Py_BEGIN_ALLOW_THREADS
10147 : 0 : res = dup3(fd, fd2, O_CLOEXEC);
10148 : 0 : Py_END_ALLOW_THREADS
10149 [ # # ]: 0 : if (res < 0) {
10150 [ # # ]: 0 : if (dup3_works == -1)
10151 : 0 : dup3_works = (errno != ENOSYS);
10152 [ # # ]: 0 : if (dup3_works) {
10153 : 0 : posix_error();
10154 : 0 : return -1;
10155 : : }
10156 : : }
10157 : : }
10158 : :
10159 [ # # # # ]: 0 : if (inheritable || dup3_works == 0)
10160 : : {
10161 : : #endif
10162 : 0 : Py_BEGIN_ALLOW_THREADS
10163 : 0 : res = dup2(fd, fd2);
10164 : 0 : Py_END_ALLOW_THREADS
10165 [ # # ]: 0 : if (res < 0) {
10166 : 0 : posix_error();
10167 : 0 : return -1;
10168 : : }
10169 : :
10170 [ # # # # ]: 0 : if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
10171 : 0 : close(fd2);
10172 : 0 : return -1;
10173 : : }
10174 : : #ifdef HAVE_DUP3
10175 : : }
10176 : : #endif
10177 : :
10178 : : #endif
10179 : :
10180 : 0 : return res;
10181 : : }
10182 : : #endif
10183 : :
10184 : :
10185 : : #ifdef HAVE_LOCKF
10186 : : /*[clinic input]
10187 : : os.lockf
10188 : :
10189 : : fd: int
10190 : : An open file descriptor.
10191 : : command: int
10192 : : One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
10193 : : length: Py_off_t
10194 : : The number of bytes to lock, starting at the current position.
10195 : : /
10196 : :
10197 : : Apply, test or remove a POSIX lock on an open file descriptor.
10198 : :
10199 : : [clinic start generated code]*/
10200 : :
10201 : : static PyObject *
10202 : 0 : os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
10203 : : /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
10204 : : {
10205 : : int res;
10206 : :
10207 [ # # ]: 0 : if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
10208 : 0 : return NULL;
10209 : : }
10210 : :
10211 : 0 : Py_BEGIN_ALLOW_THREADS
10212 : 0 : res = lockf(fd, command, length);
10213 : 0 : Py_END_ALLOW_THREADS
10214 : :
10215 [ # # ]: 0 : if (res < 0)
10216 : 0 : return posix_error();
10217 : :
10218 : 0 : Py_RETURN_NONE;
10219 : : }
10220 : : #endif /* HAVE_LOCKF */
10221 : :
10222 : :
10223 : : /*[clinic input]
10224 : : os.lseek -> Py_off_t
10225 : :
10226 : : fd: int
10227 : : position: Py_off_t
10228 : : how: int
10229 : : /
10230 : :
10231 : : Set the position of a file descriptor. Return the new position.
10232 : :
10233 : : Return the new cursor position in number of bytes
10234 : : relative to the beginning of the file.
10235 : : [clinic start generated code]*/
10236 : :
10237 : : static Py_off_t
10238 : 0 : os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
10239 : : /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
10240 : : {
10241 : : Py_off_t result;
10242 : :
10243 : : #ifdef SEEK_SET
10244 : : /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
10245 [ # # # # ]: 0 : switch (how) {
10246 : 0 : case 0: how = SEEK_SET; break;
10247 : 0 : case 1: how = SEEK_CUR; break;
10248 : 0 : case 2: how = SEEK_END; break;
10249 : : }
10250 : : #endif /* SEEK_END */
10251 : :
10252 : 0 : Py_BEGIN_ALLOW_THREADS
10253 : : _Py_BEGIN_SUPPRESS_IPH
10254 : : #ifdef MS_WINDOWS
10255 : : result = _lseeki64(fd, position, how);
10256 : : #else
10257 : 0 : result = lseek(fd, position, how);
10258 : : #endif
10259 : : _Py_END_SUPPRESS_IPH
10260 : 0 : Py_END_ALLOW_THREADS
10261 [ # # ]: 0 : if (result < 0)
10262 : 0 : posix_error();
10263 : :
10264 : 0 : return result;
10265 : : }
10266 : :
10267 : :
10268 : : /*[clinic input]
10269 : : os.read
10270 : : fd: int
10271 : : length: Py_ssize_t
10272 : : /
10273 : :
10274 : : Read from a file descriptor. Returns a bytes object.
10275 : : [clinic start generated code]*/
10276 : :
10277 : : static PyObject *
10278 : 0 : os_read_impl(PyObject *module, int fd, Py_ssize_t length)
10279 : : /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
10280 : : {
10281 : : Py_ssize_t n;
10282 : : PyObject *buffer;
10283 : :
10284 [ # # ]: 0 : if (length < 0) {
10285 : 0 : errno = EINVAL;
10286 : 0 : return posix_error();
10287 : : }
10288 : :
10289 : 0 : length = Py_MIN(length, _PY_READ_MAX);
10290 : :
10291 : 0 : buffer = PyBytes_FromStringAndSize((char *)NULL, length);
10292 [ # # ]: 0 : if (buffer == NULL)
10293 : 0 : return NULL;
10294 : :
10295 : 0 : n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
10296 [ # # ]: 0 : if (n == -1) {
10297 : 0 : Py_DECREF(buffer);
10298 : 0 : return NULL;
10299 : : }
10300 : :
10301 [ # # ]: 0 : if (n != length)
10302 : 0 : _PyBytes_Resize(&buffer, n);
10303 : :
10304 : 0 : return buffer;
10305 : : }
10306 : :
10307 : : #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
10308 : : || defined(__APPLE__))) \
10309 : : || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
10310 : : || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
10311 : : static int
10312 : 0 : iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
10313 : : {
10314 : : Py_ssize_t i, j;
10315 : :
10316 [ # # ]: 0 : *iov = PyMem_New(struct iovec, cnt);
10317 [ # # ]: 0 : if (*iov == NULL) {
10318 : 0 : PyErr_NoMemory();
10319 : 0 : return -1;
10320 : : }
10321 : :
10322 [ # # ]: 0 : *buf = PyMem_New(Py_buffer, cnt);
10323 [ # # ]: 0 : if (*buf == NULL) {
10324 : 0 : PyMem_Free(*iov);
10325 : 0 : PyErr_NoMemory();
10326 : 0 : return -1;
10327 : : }
10328 : :
10329 [ # # ]: 0 : for (i = 0; i < cnt; i++) {
10330 : 0 : PyObject *item = PySequence_GetItem(seq, i);
10331 [ # # ]: 0 : if (item == NULL)
10332 : 0 : goto fail;
10333 [ # # ]: 0 : if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
10334 : 0 : Py_DECREF(item);
10335 : 0 : goto fail;
10336 : : }
10337 : 0 : Py_DECREF(item);
10338 : 0 : (*iov)[i].iov_base = (*buf)[i].buf;
10339 : 0 : (*iov)[i].iov_len = (*buf)[i].len;
10340 : : }
10341 : 0 : return 0;
10342 : :
10343 : 0 : fail:
10344 : 0 : PyMem_Free(*iov);
10345 [ # # ]: 0 : for (j = 0; j < i; j++) {
10346 : 0 : PyBuffer_Release(&(*buf)[j]);
10347 : : }
10348 : 0 : PyMem_Free(*buf);
10349 : 0 : return -1;
10350 : : }
10351 : :
10352 : : static void
10353 : 0 : iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
10354 : : {
10355 : : int i;
10356 : 0 : PyMem_Free(iov);
10357 [ # # ]: 0 : for (i = 0; i < cnt; i++) {
10358 : 0 : PyBuffer_Release(&buf[i]);
10359 : : }
10360 : 0 : PyMem_Free(buf);
10361 : 0 : }
10362 : : #endif
10363 : :
10364 : :
10365 : : #ifdef HAVE_READV
10366 : : /*[clinic input]
10367 : : os.readv -> Py_ssize_t
10368 : :
10369 : : fd: int
10370 : : buffers: object
10371 : : /
10372 : :
10373 : : Read from a file descriptor fd into an iterable of buffers.
10374 : :
10375 : : The buffers should be mutable buffers accepting bytes.
10376 : : readv will transfer data into each buffer until it is full
10377 : : and then move on to the next buffer in the sequence to hold
10378 : : the rest of the data.
10379 : :
10380 : : readv returns the total number of bytes read,
10381 : : which may be less than the total capacity of all the buffers.
10382 : : [clinic start generated code]*/
10383 : :
10384 : : static Py_ssize_t
10385 : 0 : os_readv_impl(PyObject *module, int fd, PyObject *buffers)
10386 : : /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
10387 : : {
10388 : : Py_ssize_t cnt, n;
10389 : 0 : int async_err = 0;
10390 : : struct iovec *iov;
10391 : : Py_buffer *buf;
10392 : :
10393 [ # # ]: 0 : if (!PySequence_Check(buffers)) {
10394 : 0 : PyErr_SetString(PyExc_TypeError,
10395 : : "readv() arg 2 must be a sequence");
10396 : 0 : return -1;
10397 : : }
10398 : :
10399 : 0 : cnt = PySequence_Size(buffers);
10400 [ # # ]: 0 : if (cnt < 0)
10401 : 0 : return -1;
10402 : :
10403 [ # # ]: 0 : if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
10404 : 0 : return -1;
10405 : :
10406 : : do {
10407 : 0 : Py_BEGIN_ALLOW_THREADS
10408 : 0 : n = readv(fd, iov, cnt);
10409 : 0 : Py_END_ALLOW_THREADS
10410 [ # # # # : 0 : } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
10411 : :
10412 : 0 : iov_cleanup(iov, buf, cnt);
10413 [ # # ]: 0 : if (n < 0) {
10414 [ # # ]: 0 : if (!async_err)
10415 : 0 : posix_error();
10416 : 0 : return -1;
10417 : : }
10418 : :
10419 : 0 : return n;
10420 : : }
10421 : : #endif /* HAVE_READV */
10422 : :
10423 : :
10424 : : #ifdef HAVE_PREAD
10425 : : /*[clinic input]
10426 : : os.pread
10427 : :
10428 : : fd: int
10429 : : length: Py_ssize_t
10430 : : offset: Py_off_t
10431 : : /
10432 : :
10433 : : Read a number of bytes from a file descriptor starting at a particular offset.
10434 : :
10435 : : Read length bytes from file descriptor fd, starting at offset bytes from
10436 : : the beginning of the file. The file offset remains unchanged.
10437 : : [clinic start generated code]*/
10438 : :
10439 : : static PyObject *
10440 : 0 : os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
10441 : : /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
10442 : : {
10443 : : Py_ssize_t n;
10444 : 0 : int async_err = 0;
10445 : : PyObject *buffer;
10446 : :
10447 [ # # ]: 0 : if (length < 0) {
10448 : 0 : errno = EINVAL;
10449 : 0 : return posix_error();
10450 : : }
10451 : 0 : buffer = PyBytes_FromStringAndSize((char *)NULL, length);
10452 [ # # ]: 0 : if (buffer == NULL)
10453 : 0 : return NULL;
10454 : :
10455 : : do {
10456 : 0 : Py_BEGIN_ALLOW_THREADS
10457 : : _Py_BEGIN_SUPPRESS_IPH
10458 : 0 : n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
10459 : : _Py_END_SUPPRESS_IPH
10460 : 0 : Py_END_ALLOW_THREADS
10461 [ # # # # : 0 : } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
10462 : :
10463 [ # # ]: 0 : if (n < 0) {
10464 : 0 : Py_DECREF(buffer);
10465 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
10466 : : }
10467 [ # # ]: 0 : if (n != length)
10468 : 0 : _PyBytes_Resize(&buffer, n);
10469 : 0 : return buffer;
10470 : : }
10471 : : #endif /* HAVE_PREAD */
10472 : :
10473 : : #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
10474 : : /*[clinic input]
10475 : : os.preadv -> Py_ssize_t
10476 : :
10477 : : fd: int
10478 : : buffers: object
10479 : : offset: Py_off_t
10480 : : flags: int = 0
10481 : : /
10482 : :
10483 : : Reads from a file descriptor into a number of mutable bytes-like objects.
10484 : :
10485 : : Combines the functionality of readv() and pread(). As readv(), it will
10486 : : transfer data into each buffer until it is full and then move on to the next
10487 : : buffer in the sequence to hold the rest of the data. Its fourth argument,
10488 : : specifies the file offset at which the input operation is to be performed. It
10489 : : will return the total number of bytes read (which can be less than the total
10490 : : capacity of all the objects).
10491 : :
10492 : : The flags argument contains a bitwise OR of zero or more of the following flags:
10493 : :
10494 : : - RWF_HIPRI
10495 : : - RWF_NOWAIT
10496 : :
10497 : : Using non-zero flags requires Linux 4.6 or newer.
10498 : : [clinic start generated code]*/
10499 : :
10500 : : static Py_ssize_t
10501 : 0 : os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
10502 : : int flags)
10503 : : /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
10504 : : {
10505 : : Py_ssize_t cnt, n;
10506 : 0 : int async_err = 0;
10507 : : struct iovec *iov;
10508 : : Py_buffer *buf;
10509 : :
10510 [ # # ]: 0 : if (!PySequence_Check(buffers)) {
10511 : 0 : PyErr_SetString(PyExc_TypeError,
10512 : : "preadv2() arg 2 must be a sequence");
10513 : 0 : return -1;
10514 : : }
10515 : :
10516 : 0 : cnt = PySequence_Size(buffers);
10517 [ # # ]: 0 : if (cnt < 0) {
10518 : 0 : return -1;
10519 : : }
10520 : :
10521 : : #ifndef HAVE_PREADV2
10522 : : if(flags != 0) {
10523 : : argument_unavailable_error("preadv2", "flags");
10524 : : return -1;
10525 : : }
10526 : : #endif
10527 : :
10528 [ # # ]: 0 : if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
10529 : 0 : return -1;
10530 : : }
10531 : : #ifdef HAVE_PREADV2
10532 : : do {
10533 : 0 : Py_BEGIN_ALLOW_THREADS
10534 : : _Py_BEGIN_SUPPRESS_IPH
10535 : 0 : n = preadv2(fd, iov, cnt, offset, flags);
10536 : : _Py_END_SUPPRESS_IPH
10537 : 0 : Py_END_ALLOW_THREADS
10538 [ # # # # : 0 : } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
10539 : : #else
10540 : : do {
10541 : : #if defined(__APPLE__) && defined(__clang__)
10542 : : /* This entire function will be removed from the module dict when the API
10543 : : * is not available.
10544 : : */
10545 : : #pragma clang diagnostic push
10546 : : #pragma clang diagnostic ignored "-Wunguarded-availability"
10547 : : #pragma clang diagnostic ignored "-Wunguarded-availability-new"
10548 : : #endif
10549 : : Py_BEGIN_ALLOW_THREADS
10550 : : _Py_BEGIN_SUPPRESS_IPH
10551 : : n = preadv(fd, iov, cnt, offset);
10552 : : _Py_END_SUPPRESS_IPH
10553 : : Py_END_ALLOW_THREADS
10554 : : } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10555 : :
10556 : : #if defined(__APPLE__) && defined(__clang__)
10557 : : #pragma clang diagnostic pop
10558 : : #endif
10559 : :
10560 : : #endif
10561 : :
10562 : 0 : iov_cleanup(iov, buf, cnt);
10563 [ # # ]: 0 : if (n < 0) {
10564 [ # # ]: 0 : if (!async_err) {
10565 : 0 : posix_error();
10566 : : }
10567 : 0 : return -1;
10568 : : }
10569 : :
10570 : 0 : return n;
10571 : : }
10572 : : #endif /* HAVE_PREADV */
10573 : :
10574 : :
10575 : : /*[clinic input]
10576 : : os.write -> Py_ssize_t
10577 : :
10578 : : fd: int
10579 : : data: Py_buffer
10580 : : /
10581 : :
10582 : : Write a bytes object to a file descriptor.
10583 : : [clinic start generated code]*/
10584 : :
10585 : : static Py_ssize_t
10586 : 0 : os_write_impl(PyObject *module, int fd, Py_buffer *data)
10587 : : /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
10588 : : {
10589 : 0 : return _Py_write(fd, data->buf, data->len);
10590 : : }
10591 : :
10592 : : #ifdef HAVE_SENDFILE
10593 : : #ifdef __APPLE__
10594 : : /*[clinic input]
10595 : : os.sendfile
10596 : :
10597 : : out_fd: int
10598 : : in_fd: int
10599 : : offset: Py_off_t
10600 : : count as sbytes: Py_off_t
10601 : : headers: object(c_default="NULL") = ()
10602 : : trailers: object(c_default="NULL") = ()
10603 : : flags: int = 0
10604 : :
10605 : : Copy count bytes from file descriptor in_fd to file descriptor out_fd.
10606 : : [clinic start generated code]*/
10607 : :
10608 : : static PyObject *
10609 : : os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
10610 : : Py_off_t sbytes, PyObject *headers, PyObject *trailers,
10611 : : int flags)
10612 : : /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
10613 : : #elif defined(__FreeBSD__) || defined(__DragonFly__)
10614 : : /*[clinic input]
10615 : : os.sendfile
10616 : :
10617 : : out_fd: int
10618 : : in_fd: int
10619 : : offset: Py_off_t
10620 : : count: Py_ssize_t
10621 : : headers: object(c_default="NULL") = ()
10622 : : trailers: object(c_default="NULL") = ()
10623 : : flags: int = 0
10624 : :
10625 : : Copy count bytes from file descriptor in_fd to file descriptor out_fd.
10626 : : [clinic start generated code]*/
10627 : :
10628 : : static PyObject *
10629 : : os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
10630 : : Py_ssize_t count, PyObject *headers, PyObject *trailers,
10631 : : int flags)
10632 : : /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
10633 : : #else
10634 : : /*[clinic input]
10635 : : os.sendfile
10636 : :
10637 : : out_fd: int
10638 : : in_fd: int
10639 : : offset as offobj: object
10640 : : count: Py_ssize_t
10641 : :
10642 : : Copy count bytes from file descriptor in_fd to file descriptor out_fd.
10643 : : [clinic start generated code]*/
10644 : :
10645 : : static PyObject *
10646 : 0 : os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
10647 : : Py_ssize_t count)
10648 : : /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
10649 : : #endif
10650 : : {
10651 : : Py_ssize_t ret;
10652 : 0 : int async_err = 0;
10653 : :
10654 : : #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
10655 : : #ifndef __APPLE__
10656 : : off_t sbytes;
10657 : : #endif
10658 : : Py_buffer *hbuf, *tbuf;
10659 : : struct sf_hdtr sf;
10660 : :
10661 : : sf.headers = NULL;
10662 : : sf.trailers = NULL;
10663 : :
10664 : : if (headers != NULL) {
10665 : : if (!PySequence_Check(headers)) {
10666 : : PyErr_SetString(PyExc_TypeError,
10667 : : "sendfile() headers must be a sequence");
10668 : : return NULL;
10669 : : } else {
10670 : : Py_ssize_t i = PySequence_Size(headers);
10671 : : if (i < 0)
10672 : : return NULL;
10673 : : if (i > INT_MAX) {
10674 : : PyErr_SetString(PyExc_OverflowError,
10675 : : "sendfile() header is too large");
10676 : : return NULL;
10677 : : }
10678 : : if (i > 0) {
10679 : : sf.hdr_cnt = (int)i;
10680 : : if (iov_setup(&(sf.headers), &hbuf,
10681 : : headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
10682 : : return NULL;
10683 : : #ifdef __APPLE__
10684 : : for (i = 0; i < sf.hdr_cnt; i++) {
10685 : : Py_ssize_t blen = sf.headers[i].iov_len;
10686 : : # define OFF_T_MAX 0x7fffffffffffffff
10687 : : if (sbytes >= OFF_T_MAX - blen) {
10688 : : PyErr_SetString(PyExc_OverflowError,
10689 : : "sendfile() header is too large");
10690 : : return NULL;
10691 : : }
10692 : : sbytes += blen;
10693 : : }
10694 : : #endif
10695 : : }
10696 : : }
10697 : : }
10698 : : if (trailers != NULL) {
10699 : : if (!PySequence_Check(trailers)) {
10700 : : PyErr_SetString(PyExc_TypeError,
10701 : : "sendfile() trailers must be a sequence");
10702 : : return NULL;
10703 : : } else {
10704 : : Py_ssize_t i = PySequence_Size(trailers);
10705 : : if (i < 0)
10706 : : return NULL;
10707 : : if (i > INT_MAX) {
10708 : : PyErr_SetString(PyExc_OverflowError,
10709 : : "sendfile() trailer is too large");
10710 : : return NULL;
10711 : : }
10712 : : if (i > 0) {
10713 : : sf.trl_cnt = (int)i;
10714 : : if (iov_setup(&(sf.trailers), &tbuf,
10715 : : trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
10716 : : return NULL;
10717 : : }
10718 : : }
10719 : : }
10720 : :
10721 : : _Py_BEGIN_SUPPRESS_IPH
10722 : : do {
10723 : : Py_BEGIN_ALLOW_THREADS
10724 : : #ifdef __APPLE__
10725 : : ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
10726 : : #else
10727 : : ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
10728 : : #endif
10729 : : Py_END_ALLOW_THREADS
10730 : : } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10731 : : _Py_END_SUPPRESS_IPH
10732 : :
10733 : : if (sf.headers != NULL)
10734 : : iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
10735 : : if (sf.trailers != NULL)
10736 : : iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
10737 : :
10738 : : if (ret < 0) {
10739 : : if ((errno == EAGAIN) || (errno == EBUSY)) {
10740 : : if (sbytes != 0) {
10741 : : // some data has been sent
10742 : : goto done;
10743 : : }
10744 : : else {
10745 : : // no data has been sent; upper application is supposed
10746 : : // to retry on EAGAIN or EBUSY
10747 : : return posix_error();
10748 : : }
10749 : : }
10750 : : return (!async_err) ? posix_error() : NULL;
10751 : : }
10752 : : goto done;
10753 : :
10754 : : done:
10755 : : #if !defined(HAVE_LARGEFILE_SUPPORT)
10756 : : return Py_BuildValue("l", sbytes);
10757 : : #else
10758 : : return Py_BuildValue("L", sbytes);
10759 : : #endif
10760 : :
10761 : : #else
10762 : : #ifdef __linux__
10763 [ # # ]: 0 : if (offobj == Py_None) {
10764 : : do {
10765 : 0 : Py_BEGIN_ALLOW_THREADS
10766 : 0 : ret = sendfile(out_fd, in_fd, NULL, count);
10767 : 0 : Py_END_ALLOW_THREADS
10768 [ # # # # : 0 : } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
10769 [ # # ]: 0 : if (ret < 0)
10770 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
10771 : 0 : return Py_BuildValue("n", ret);
10772 : : }
10773 : : #endif
10774 : : off_t offset;
10775 [ # # ]: 0 : if (!Py_off_t_converter(offobj, &offset))
10776 : 0 : return NULL;
10777 : :
10778 : : #if defined(__sun) && defined(__SVR4)
10779 : : // On Solaris, sendfile raises EINVAL rather than returning 0
10780 : : // when the offset is equal or bigger than the in_fd size.
10781 : : struct stat st;
10782 : :
10783 : : do {
10784 : : Py_BEGIN_ALLOW_THREADS
10785 : : ret = fstat(in_fd, &st);
10786 : : Py_END_ALLOW_THREADS
10787 : : } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10788 : : if (ret < 0)
10789 : : return (!async_err) ? posix_error() : NULL;
10790 : :
10791 : : if (offset >= st.st_size) {
10792 : : return Py_BuildValue("i", 0);
10793 : : }
10794 : :
10795 : : // On illumos specifically sendfile() may perform a partial write but
10796 : : // return -1/an error (in one confirmed case the destination socket
10797 : : // had a 5 second timeout set and errno was EAGAIN) and it's on the client
10798 : : // code to check if the offset parameter was modified by sendfile().
10799 : : //
10800 : : // We need this variable to track said change.
10801 : : off_t original_offset = offset;
10802 : : #endif
10803 : :
10804 : : do {
10805 : 0 : Py_BEGIN_ALLOW_THREADS
10806 : 0 : ret = sendfile(out_fd, in_fd, &offset, count);
10807 : : #if defined(__sun) && defined(__SVR4)
10808 : : // This handles illumos-specific sendfile() partial write behavior,
10809 : : // see a comment above for more details.
10810 : : if (ret < 0 && offset != original_offset) {
10811 : : ret = offset - original_offset;
10812 : : }
10813 : : #endif
10814 : 0 : Py_END_ALLOW_THREADS
10815 [ # # # # : 0 : } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
10816 [ # # ]: 0 : if (ret < 0)
10817 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
10818 : 0 : return Py_BuildValue("n", ret);
10819 : : #endif
10820 : : }
10821 : : #endif /* HAVE_SENDFILE */
10822 : :
10823 : :
10824 : : #if defined(__APPLE__)
10825 : : /*[clinic input]
10826 : : os._fcopyfile
10827 : :
10828 : : in_fd: int
10829 : : out_fd: int
10830 : : flags: int
10831 : : /
10832 : :
10833 : : Efficiently copy content or metadata of 2 regular file descriptors (macOS).
10834 : : [clinic start generated code]*/
10835 : :
10836 : : static PyObject *
10837 : : os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
10838 : : /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
10839 : : {
10840 : : int ret;
10841 : :
10842 : : Py_BEGIN_ALLOW_THREADS
10843 : : ret = fcopyfile(in_fd, out_fd, NULL, flags);
10844 : : Py_END_ALLOW_THREADS
10845 : : if (ret < 0)
10846 : : return posix_error();
10847 : : Py_RETURN_NONE;
10848 : : }
10849 : : #endif
10850 : :
10851 : :
10852 : : /*[clinic input]
10853 : : os.fstat
10854 : :
10855 : : fd : int
10856 : :
10857 : : Perform a stat system call on the given file descriptor.
10858 : :
10859 : : Like stat(), but for an open file descriptor.
10860 : : Equivalent to os.stat(fd).
10861 : : [clinic start generated code]*/
10862 : :
10863 : : static PyObject *
10864 : 1 : os_fstat_impl(PyObject *module, int fd)
10865 : : /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
10866 : : {
10867 : : STRUCT_STAT st;
10868 : : int res;
10869 : 1 : int async_err = 0;
10870 : :
10871 : : do {
10872 : 1 : Py_BEGIN_ALLOW_THREADS
10873 : 1 : res = FSTAT(fd, &st);
10874 : 1 : Py_END_ALLOW_THREADS
10875 [ - + - - : 1 : } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
10876 [ - + ]: 1 : if (res != 0) {
10877 : : #ifdef MS_WINDOWS
10878 : : return PyErr_SetFromWindowsErr(0);
10879 : : #else
10880 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
10881 : : #endif
10882 : : }
10883 : :
10884 : 1 : return _pystat_fromstructstat(module, &st);
10885 : : }
10886 : :
10887 : :
10888 : : /*[clinic input]
10889 : : os.isatty -> bool
10890 : : fd: int
10891 : : /
10892 : :
10893 : : Return True if the fd is connected to a terminal.
10894 : :
10895 : : Return True if the file descriptor is an open file descriptor
10896 : : connected to the slave end of a terminal.
10897 : : [clinic start generated code]*/
10898 : :
10899 : : static int
10900 : 0 : os_isatty_impl(PyObject *module, int fd)
10901 : : /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
10902 : : {
10903 : : int return_value;
10904 : 0 : Py_BEGIN_ALLOW_THREADS
10905 : : _Py_BEGIN_SUPPRESS_IPH
10906 : 0 : return_value = isatty(fd);
10907 : : _Py_END_SUPPRESS_IPH
10908 : 0 : Py_END_ALLOW_THREADS
10909 : 0 : return return_value;
10910 : : }
10911 : :
10912 : :
10913 : : #ifdef HAVE_PIPE
10914 : : /*[clinic input]
10915 : : os.pipe
10916 : :
10917 : : Create a pipe.
10918 : :
10919 : : Returns a tuple of two file descriptors:
10920 : : (read_fd, write_fd)
10921 : : [clinic start generated code]*/
10922 : :
10923 : : static PyObject *
10924 : 0 : os_pipe_impl(PyObject *module)
10925 : : /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
10926 : : {
10927 : : int fds[2];
10928 : : #ifdef MS_WINDOWS
10929 : : HANDLE read, write;
10930 : : SECURITY_ATTRIBUTES attr;
10931 : : BOOL ok;
10932 : : #else
10933 : : int res;
10934 : : #endif
10935 : :
10936 : : #ifdef MS_WINDOWS
10937 : : attr.nLength = sizeof(attr);
10938 : : attr.lpSecurityDescriptor = NULL;
10939 : : attr.bInheritHandle = FALSE;
10940 : :
10941 : : Py_BEGIN_ALLOW_THREADS
10942 : : ok = CreatePipe(&read, &write, &attr, 0);
10943 : : if (ok) {
10944 : : fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY);
10945 : : fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY);
10946 : : if (fds[0] == -1 || fds[1] == -1) {
10947 : : CloseHandle(read);
10948 : : CloseHandle(write);
10949 : : ok = 0;
10950 : : }
10951 : : }
10952 : : Py_END_ALLOW_THREADS
10953 : :
10954 : : if (!ok)
10955 : : return PyErr_SetFromWindowsErr(0);
10956 : : #else
10957 : :
10958 : : #ifdef HAVE_PIPE2
10959 : 0 : Py_BEGIN_ALLOW_THREADS
10960 : 0 : res = pipe2(fds, O_CLOEXEC);
10961 : 0 : Py_END_ALLOW_THREADS
10962 : :
10963 [ # # # # ]: 0 : if (res != 0 && errno == ENOSYS)
10964 : : {
10965 : : #endif
10966 : 0 : Py_BEGIN_ALLOW_THREADS
10967 : 0 : res = pipe(fds);
10968 : 0 : Py_END_ALLOW_THREADS
10969 : :
10970 [ # # ]: 0 : if (res == 0) {
10971 [ # # ]: 0 : if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
10972 : 0 : close(fds[0]);
10973 : 0 : close(fds[1]);
10974 : 0 : return NULL;
10975 : : }
10976 [ # # ]: 0 : if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
10977 : 0 : close(fds[0]);
10978 : 0 : close(fds[1]);
10979 : 0 : return NULL;
10980 : : }
10981 : : }
10982 : : #ifdef HAVE_PIPE2
10983 : : }
10984 : : #endif
10985 : :
10986 [ # # ]: 0 : if (res != 0)
10987 : 0 : return PyErr_SetFromErrno(PyExc_OSError);
10988 : : #endif /* !MS_WINDOWS */
10989 : 0 : return Py_BuildValue("(ii)", fds[0], fds[1]);
10990 : : }
10991 : : #endif /* HAVE_PIPE */
10992 : :
10993 : :
10994 : : #ifdef HAVE_PIPE2
10995 : : /*[clinic input]
10996 : : os.pipe2
10997 : :
10998 : : flags: int
10999 : : /
11000 : :
11001 : : Create a pipe with flags set atomically.
11002 : :
11003 : : Returns a tuple of two file descriptors:
11004 : : (read_fd, write_fd)
11005 : :
11006 : : flags can be constructed by ORing together one or more of these values:
11007 : : O_NONBLOCK, O_CLOEXEC.
11008 : : [clinic start generated code]*/
11009 : :
11010 : : static PyObject *
11011 : 0 : os_pipe2_impl(PyObject *module, int flags)
11012 : : /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
11013 : : {
11014 : : int fds[2];
11015 : : int res;
11016 : :
11017 : 0 : res = pipe2(fds, flags);
11018 [ # # ]: 0 : if (res != 0)
11019 : 0 : return posix_error();
11020 : 0 : return Py_BuildValue("(ii)", fds[0], fds[1]);
11021 : : }
11022 : : #endif /* HAVE_PIPE2 */
11023 : :
11024 : :
11025 : : #ifdef HAVE_WRITEV
11026 : : /*[clinic input]
11027 : : os.writev -> Py_ssize_t
11028 : : fd: int
11029 : : buffers: object
11030 : : /
11031 : :
11032 : : Iterate over buffers, and write the contents of each to a file descriptor.
11033 : :
11034 : : Returns the total number of bytes written.
11035 : : buffers must be a sequence of bytes-like objects.
11036 : : [clinic start generated code]*/
11037 : :
11038 : : static Py_ssize_t
11039 : 0 : os_writev_impl(PyObject *module, int fd, PyObject *buffers)
11040 : : /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
11041 : : {
11042 : : Py_ssize_t cnt;
11043 : : Py_ssize_t result;
11044 : 0 : int async_err = 0;
11045 : : struct iovec *iov;
11046 : : Py_buffer *buf;
11047 : :
11048 [ # # ]: 0 : if (!PySequence_Check(buffers)) {
11049 : 0 : PyErr_SetString(PyExc_TypeError,
11050 : : "writev() arg 2 must be a sequence");
11051 : 0 : return -1;
11052 : : }
11053 : 0 : cnt = PySequence_Size(buffers);
11054 [ # # ]: 0 : if (cnt < 0)
11055 : 0 : return -1;
11056 : :
11057 [ # # ]: 0 : if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
11058 : 0 : return -1;
11059 : : }
11060 : :
11061 : : do {
11062 : 0 : Py_BEGIN_ALLOW_THREADS
11063 : 0 : result = writev(fd, iov, cnt);
11064 : 0 : Py_END_ALLOW_THREADS
11065 [ # # # # : 0 : } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
11066 : :
11067 : 0 : iov_cleanup(iov, buf, cnt);
11068 [ # # # # ]: 0 : if (result < 0 && !async_err)
11069 : 0 : posix_error();
11070 : :
11071 : 0 : return result;
11072 : : }
11073 : : #endif /* HAVE_WRITEV */
11074 : :
11075 : :
11076 : : #ifdef HAVE_PWRITE
11077 : : /*[clinic input]
11078 : : os.pwrite -> Py_ssize_t
11079 : :
11080 : : fd: int
11081 : : buffer: Py_buffer
11082 : : offset: Py_off_t
11083 : : /
11084 : :
11085 : : Write bytes to a file descriptor starting at a particular offset.
11086 : :
11087 : : Write buffer to fd, starting at offset bytes from the beginning of
11088 : : the file. Returns the number of bytes writte. Does not change the
11089 : : current file offset.
11090 : : [clinic start generated code]*/
11091 : :
11092 : : static Py_ssize_t
11093 : 0 : os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
11094 : : /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
11095 : : {
11096 : : Py_ssize_t size;
11097 : 0 : int async_err = 0;
11098 : :
11099 : : do {
11100 : 0 : Py_BEGIN_ALLOW_THREADS
11101 : : _Py_BEGIN_SUPPRESS_IPH
11102 : 0 : size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
11103 : : _Py_END_SUPPRESS_IPH
11104 : 0 : Py_END_ALLOW_THREADS
11105 [ # # # # : 0 : } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
11106 : :
11107 [ # # # # ]: 0 : if (size < 0 && !async_err)
11108 : 0 : posix_error();
11109 : 0 : return size;
11110 : : }
11111 : : #endif /* HAVE_PWRITE */
11112 : :
11113 : : #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
11114 : : /*[clinic input]
11115 : : os.pwritev -> Py_ssize_t
11116 : :
11117 : : fd: int
11118 : : buffers: object
11119 : : offset: Py_off_t
11120 : : flags: int = 0
11121 : : /
11122 : :
11123 : : Writes the contents of bytes-like objects to a file descriptor at a given offset.
11124 : :
11125 : : Combines the functionality of writev() and pwrite(). All buffers must be a sequence
11126 : : of bytes-like objects. Buffers are processed in array order. Entire contents of first
11127 : : buffer is written before proceeding to second, and so on. The operating system may
11128 : : set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
11129 : : This function writes the contents of each object to the file descriptor and returns
11130 : : the total number of bytes written.
11131 : :
11132 : : The flags argument contains a bitwise OR of zero or more of the following flags:
11133 : :
11134 : : - RWF_DSYNC
11135 : : - RWF_SYNC
11136 : : - RWF_APPEND
11137 : :
11138 : : Using non-zero flags requires Linux 4.7 or newer.
11139 : : [clinic start generated code]*/
11140 : :
11141 : : static Py_ssize_t
11142 : 0 : os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
11143 : : int flags)
11144 : : /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
11145 : : {
11146 : : Py_ssize_t cnt;
11147 : : Py_ssize_t result;
11148 : 0 : int async_err = 0;
11149 : : struct iovec *iov;
11150 : : Py_buffer *buf;
11151 : :
11152 [ # # ]: 0 : if (!PySequence_Check(buffers)) {
11153 : 0 : PyErr_SetString(PyExc_TypeError,
11154 : : "pwritev() arg 2 must be a sequence");
11155 : 0 : return -1;
11156 : : }
11157 : :
11158 : 0 : cnt = PySequence_Size(buffers);
11159 [ # # ]: 0 : if (cnt < 0) {
11160 : 0 : return -1;
11161 : : }
11162 : :
11163 : : #ifndef HAVE_PWRITEV2
11164 : : if(flags != 0) {
11165 : : argument_unavailable_error("pwritev2", "flags");
11166 : : return -1;
11167 : : }
11168 : : #endif
11169 : :
11170 [ # # ]: 0 : if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
11171 : 0 : return -1;
11172 : : }
11173 : : #ifdef HAVE_PWRITEV2
11174 : : do {
11175 : 0 : Py_BEGIN_ALLOW_THREADS
11176 : : _Py_BEGIN_SUPPRESS_IPH
11177 : 0 : result = pwritev2(fd, iov, cnt, offset, flags);
11178 : : _Py_END_SUPPRESS_IPH
11179 : 0 : Py_END_ALLOW_THREADS
11180 [ # # # # : 0 : } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
11181 : : #else
11182 : :
11183 : : #if defined(__APPLE__) && defined(__clang__)
11184 : : /* This entire function will be removed from the module dict when the API
11185 : : * is not available.
11186 : : */
11187 : : #pragma clang diagnostic push
11188 : : #pragma clang diagnostic ignored "-Wunguarded-availability"
11189 : : #pragma clang diagnostic ignored "-Wunguarded-availability-new"
11190 : : #endif
11191 : : do {
11192 : : Py_BEGIN_ALLOW_THREADS
11193 : : _Py_BEGIN_SUPPRESS_IPH
11194 : : result = pwritev(fd, iov, cnt, offset);
11195 : : _Py_END_SUPPRESS_IPH
11196 : : Py_END_ALLOW_THREADS
11197 : : } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11198 : :
11199 : : #if defined(__APPLE__) && defined(__clang__)
11200 : : #pragma clang diagnostic pop
11201 : : #endif
11202 : :
11203 : : #endif
11204 : :
11205 : 0 : iov_cleanup(iov, buf, cnt);
11206 [ # # ]: 0 : if (result < 0) {
11207 [ # # ]: 0 : if (!async_err) {
11208 : 0 : posix_error();
11209 : : }
11210 : 0 : return -1;
11211 : : }
11212 : :
11213 : 0 : return result;
11214 : : }
11215 : : #endif /* HAVE_PWRITEV */
11216 : :
11217 : : #ifdef HAVE_COPY_FILE_RANGE
11218 : : /*[clinic input]
11219 : :
11220 : : os.copy_file_range
11221 : : src: int
11222 : : Source file descriptor.
11223 : : dst: int
11224 : : Destination file descriptor.
11225 : : count: Py_ssize_t
11226 : : Number of bytes to copy.
11227 : : offset_src: object = None
11228 : : Starting offset in src.
11229 : : offset_dst: object = None
11230 : : Starting offset in dst.
11231 : :
11232 : : Copy count bytes from one file descriptor to another.
11233 : :
11234 : : If offset_src is None, then src is read from the current position;
11235 : : respectively for offset_dst.
11236 : : [clinic start generated code]*/
11237 : :
11238 : : static PyObject *
11239 : 0 : os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
11240 : : PyObject *offset_src, PyObject *offset_dst)
11241 : : /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
11242 : : {
11243 : : off_t offset_src_val, offset_dst_val;
11244 : 0 : off_t *p_offset_src = NULL;
11245 : 0 : off_t *p_offset_dst = NULL;
11246 : : Py_ssize_t ret;
11247 : 0 : int async_err = 0;
11248 : : /* The flags argument is provided to allow
11249 : : * for future extensions and currently must be to 0. */
11250 : 0 : int flags = 0;
11251 : :
11252 : :
11253 [ # # ]: 0 : if (count < 0) {
11254 : 0 : PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
11255 : 0 : return NULL;
11256 : : }
11257 : :
11258 [ # # ]: 0 : if (offset_src != Py_None) {
11259 [ # # ]: 0 : if (!Py_off_t_converter(offset_src, &offset_src_val)) {
11260 : 0 : return NULL;
11261 : : }
11262 : 0 : p_offset_src = &offset_src_val;
11263 : : }
11264 : :
11265 [ # # ]: 0 : if (offset_dst != Py_None) {
11266 [ # # ]: 0 : if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
11267 : 0 : return NULL;
11268 : : }
11269 : 0 : p_offset_dst = &offset_dst_val;
11270 : : }
11271 : :
11272 : : do {
11273 : 0 : Py_BEGIN_ALLOW_THREADS
11274 : 0 : ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
11275 : 0 : Py_END_ALLOW_THREADS
11276 [ # # # # : 0 : } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
11277 : :
11278 [ # # ]: 0 : if (ret < 0) {
11279 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
11280 : : }
11281 : :
11282 : 0 : return PyLong_FromSsize_t(ret);
11283 : : }
11284 : : #endif /* HAVE_COPY_FILE_RANGE*/
11285 : :
11286 : : #if (defined(HAVE_SPLICE) && !defined(_AIX))
11287 : : /*[clinic input]
11288 : :
11289 : : os.splice
11290 : : src: int
11291 : : Source file descriptor.
11292 : : dst: int
11293 : : Destination file descriptor.
11294 : : count: Py_ssize_t
11295 : : Number of bytes to copy.
11296 : : offset_src: object = None
11297 : : Starting offset in src.
11298 : : offset_dst: object = None
11299 : : Starting offset in dst.
11300 : : flags: unsigned_int = 0
11301 : : Flags to modify the semantics of the call.
11302 : :
11303 : : Transfer count bytes from one pipe to a descriptor or vice versa.
11304 : :
11305 : : If offset_src is None, then src is read from the current position;
11306 : : respectively for offset_dst. The offset associated to the file
11307 : : descriptor that refers to a pipe must be None.
11308 : : [clinic start generated code]*/
11309 : :
11310 : : static PyObject *
11311 : 0 : os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
11312 : : PyObject *offset_src, PyObject *offset_dst,
11313 : : unsigned int flags)
11314 : : /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
11315 : : {
11316 : : off_t offset_src_val, offset_dst_val;
11317 : 0 : off_t *p_offset_src = NULL;
11318 : 0 : off_t *p_offset_dst = NULL;
11319 : : Py_ssize_t ret;
11320 : 0 : int async_err = 0;
11321 : :
11322 [ # # ]: 0 : if (count < 0) {
11323 : 0 : PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
11324 : 0 : return NULL;
11325 : : }
11326 : :
11327 [ # # ]: 0 : if (offset_src != Py_None) {
11328 [ # # ]: 0 : if (!Py_off_t_converter(offset_src, &offset_src_val)) {
11329 : 0 : return NULL;
11330 : : }
11331 : 0 : p_offset_src = &offset_src_val;
11332 : : }
11333 : :
11334 [ # # ]: 0 : if (offset_dst != Py_None) {
11335 [ # # ]: 0 : if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
11336 : 0 : return NULL;
11337 : : }
11338 : 0 : p_offset_dst = &offset_dst_val;
11339 : : }
11340 : :
11341 : : do {
11342 : 0 : Py_BEGIN_ALLOW_THREADS
11343 : 0 : ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
11344 : 0 : Py_END_ALLOW_THREADS
11345 [ # # # # : 0 : } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
11346 : :
11347 [ # # ]: 0 : if (ret < 0) {
11348 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
11349 : : }
11350 : :
11351 : 0 : return PyLong_FromSsize_t(ret);
11352 : : }
11353 : : #endif /* HAVE_SPLICE*/
11354 : :
11355 : : #ifdef HAVE_MKFIFO
11356 : : /*[clinic input]
11357 : : os.mkfifo
11358 : :
11359 : : path: path_t
11360 : : mode: int=0o666
11361 : : *
11362 : : dir_fd: dir_fd(requires='mkfifoat')=None
11363 : :
11364 : : Create a "fifo" (a POSIX named pipe).
11365 : :
11366 : : If dir_fd is not None, it should be a file descriptor open to a directory,
11367 : : and path should be relative; path will then be relative to that directory.
11368 : : dir_fd may not be implemented on your platform.
11369 : : If it is unavailable, using it will raise a NotImplementedError.
11370 : : [clinic start generated code]*/
11371 : :
11372 : : static PyObject *
11373 : 0 : os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
11374 : : /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
11375 : : {
11376 : : int result;
11377 : 0 : int async_err = 0;
11378 : : #ifdef HAVE_MKFIFOAT
11379 : 0 : int mkfifoat_unavailable = 0;
11380 : : #endif
11381 : :
11382 : : do {
11383 : 0 : Py_BEGIN_ALLOW_THREADS
11384 : : #ifdef HAVE_MKFIFOAT
11385 [ # # ]: 0 : if (dir_fd != DEFAULT_DIR_FD) {
11386 : : if (HAVE_MKFIFOAT_RUNTIME) {
11387 : 0 : result = mkfifoat(dir_fd, path->narrow, mode);
11388 : :
11389 : : } else {
11390 : : mkfifoat_unavailable = 1;
11391 : : result = 0;
11392 : : }
11393 : : } else
11394 : : #endif
11395 : 0 : result = mkfifo(path->narrow, mode);
11396 : 0 : Py_END_ALLOW_THREADS
11397 [ # # # # ]: 0 : } while (result != 0 && errno == EINTR &&
11398 [ # # ]: 0 : !(async_err = PyErr_CheckSignals()));
11399 : :
11400 : : #ifdef HAVE_MKFIFOAT
11401 [ # # ]: 0 : if (mkfifoat_unavailable) {
11402 : 0 : argument_unavailable_error(NULL, "dir_fd");
11403 : 0 : return NULL;
11404 : : }
11405 : : #endif
11406 : :
11407 [ # # ]: 0 : if (result != 0)
11408 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
11409 : :
11410 : 0 : Py_RETURN_NONE;
11411 : : }
11412 : : #endif /* HAVE_MKFIFO */
11413 : :
11414 : :
11415 : : #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
11416 : : /*[clinic input]
11417 : : os.mknod
11418 : :
11419 : : path: path_t
11420 : : mode: int=0o600
11421 : : device: dev_t=0
11422 : : *
11423 : : dir_fd: dir_fd(requires='mknodat')=None
11424 : :
11425 : : Create a node in the file system.
11426 : :
11427 : : Create a node in the file system (file, device special file or named pipe)
11428 : : at path. mode specifies both the permissions to use and the
11429 : : type of node to be created, being combined (bitwise OR) with one of
11430 : : S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,
11431 : : device defines the newly created device special file (probably using
11432 : : os.makedev()). Otherwise device is ignored.
11433 : :
11434 : : If dir_fd is not None, it should be a file descriptor open to a directory,
11435 : : and path should be relative; path will then be relative to that directory.
11436 : : dir_fd may not be implemented on your platform.
11437 : : If it is unavailable, using it will raise a NotImplementedError.
11438 : : [clinic start generated code]*/
11439 : :
11440 : : static PyObject *
11441 : 0 : os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
11442 : : int dir_fd)
11443 : : /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
11444 : : {
11445 : : int result;
11446 : 0 : int async_err = 0;
11447 : : #ifdef HAVE_MKNODAT
11448 : 0 : int mknodat_unavailable = 0;
11449 : : #endif
11450 : :
11451 : : do {
11452 : 0 : Py_BEGIN_ALLOW_THREADS
11453 : : #ifdef HAVE_MKNODAT
11454 [ # # ]: 0 : if (dir_fd != DEFAULT_DIR_FD) {
11455 : : if (HAVE_MKNODAT_RUNTIME) {
11456 : 0 : result = mknodat(dir_fd, path->narrow, mode, device);
11457 : :
11458 : : } else {
11459 : : mknodat_unavailable = 1;
11460 : : result = 0;
11461 : : }
11462 : : } else
11463 : : #endif
11464 : 0 : result = mknod(path->narrow, mode, device);
11465 : 0 : Py_END_ALLOW_THREADS
11466 [ # # # # ]: 0 : } while (result != 0 && errno == EINTR &&
11467 [ # # ]: 0 : !(async_err = PyErr_CheckSignals()));
11468 : : #ifdef HAVE_MKNODAT
11469 [ # # ]: 0 : if (mknodat_unavailable) {
11470 : 0 : argument_unavailable_error(NULL, "dir_fd");
11471 : 0 : return NULL;
11472 : : }
11473 : : #endif
11474 [ # # ]: 0 : if (result != 0)
11475 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
11476 : :
11477 : 0 : Py_RETURN_NONE;
11478 : : }
11479 : : #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
11480 : :
11481 : :
11482 : : #ifdef HAVE_DEVICE_MACROS
11483 : : /*[clinic input]
11484 : : os.major -> unsigned_int
11485 : :
11486 : : device: dev_t
11487 : : /
11488 : :
11489 : : Extracts a device major number from a raw device number.
11490 : : [clinic start generated code]*/
11491 : :
11492 : : static unsigned int
11493 : 0 : os_major_impl(PyObject *module, dev_t device)
11494 : : /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
11495 : : {
11496 : 0 : return major(device);
11497 : : }
11498 : :
11499 : :
11500 : : /*[clinic input]
11501 : : os.minor -> unsigned_int
11502 : :
11503 : : device: dev_t
11504 : : /
11505 : :
11506 : : Extracts a device minor number from a raw device number.
11507 : : [clinic start generated code]*/
11508 : :
11509 : : static unsigned int
11510 : 0 : os_minor_impl(PyObject *module, dev_t device)
11511 : : /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
11512 : : {
11513 : 0 : return minor(device);
11514 : : }
11515 : :
11516 : :
11517 : : /*[clinic input]
11518 : : os.makedev -> dev_t
11519 : :
11520 : : major: int
11521 : : minor: int
11522 : : /
11523 : :
11524 : : Composes a raw device number from the major and minor device numbers.
11525 : : [clinic start generated code]*/
11526 : :
11527 : : static dev_t
11528 : 0 : os_makedev_impl(PyObject *module, int major, int minor)
11529 : : /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
11530 : : {
11531 : 0 : return makedev(major, minor);
11532 : : }
11533 : : #endif /* HAVE_DEVICE_MACROS */
11534 : :
11535 : :
11536 : : #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
11537 : : /*[clinic input]
11538 : : os.ftruncate
11539 : :
11540 : : fd: int
11541 : : length: Py_off_t
11542 : : /
11543 : :
11544 : : Truncate a file, specified by file descriptor, to a specific length.
11545 : : [clinic start generated code]*/
11546 : :
11547 : : static PyObject *
11548 : 0 : os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
11549 : : /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
11550 : : {
11551 : : int result;
11552 : 0 : int async_err = 0;
11553 : :
11554 [ # # ]: 0 : if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
11555 : 0 : return NULL;
11556 : : }
11557 : :
11558 : : do {
11559 : 0 : Py_BEGIN_ALLOW_THREADS
11560 : : _Py_BEGIN_SUPPRESS_IPH
11561 : : #ifdef MS_WINDOWS
11562 : : result = _chsize_s(fd, length);
11563 : : #else
11564 : 0 : result = ftruncate(fd, length);
11565 : : #endif
11566 : : _Py_END_SUPPRESS_IPH
11567 : 0 : Py_END_ALLOW_THREADS
11568 [ # # # # ]: 0 : } while (result != 0 && errno == EINTR &&
11569 [ # # ]: 0 : !(async_err = PyErr_CheckSignals()));
11570 [ # # ]: 0 : if (result != 0)
11571 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
11572 : 0 : Py_RETURN_NONE;
11573 : : }
11574 : : #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
11575 : :
11576 : :
11577 : : #if defined HAVE_TRUNCATE || defined MS_WINDOWS
11578 : : /*[clinic input]
11579 : : os.truncate
11580 : : path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
11581 : : length: Py_off_t
11582 : :
11583 : : Truncate a file, specified by path, to a specific length.
11584 : :
11585 : : On some platforms, path may also be specified as an open file descriptor.
11586 : : If this functionality is unavailable, using it raises an exception.
11587 : : [clinic start generated code]*/
11588 : :
11589 : : static PyObject *
11590 : 0 : os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
11591 : : /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
11592 : : {
11593 : : int result;
11594 : : #ifdef MS_WINDOWS
11595 : : int fd;
11596 : : #endif
11597 : :
11598 [ # # ]: 0 : if (path->fd != -1)
11599 : 0 : return os_ftruncate_impl(module, path->fd, length);
11600 : :
11601 [ # # ]: 0 : if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
11602 : 0 : return NULL;
11603 : : }
11604 : :
11605 : 0 : Py_BEGIN_ALLOW_THREADS
11606 : : _Py_BEGIN_SUPPRESS_IPH
11607 : : #ifdef MS_WINDOWS
11608 : : fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
11609 : : if (fd < 0)
11610 : : result = -1;
11611 : : else {
11612 : : result = _chsize_s(fd, length);
11613 : : close(fd);
11614 : : if (result < 0)
11615 : : errno = result;
11616 : : }
11617 : : #else
11618 : 0 : result = truncate(path->narrow, length);
11619 : : #endif
11620 : : _Py_END_SUPPRESS_IPH
11621 : 0 : Py_END_ALLOW_THREADS
11622 [ # # ]: 0 : if (result < 0)
11623 : 0 : return posix_path_error(path);
11624 : :
11625 : 0 : Py_RETURN_NONE;
11626 : : }
11627 : : #endif /* HAVE_TRUNCATE || MS_WINDOWS */
11628 : :
11629 : :
11630 : : /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
11631 : : and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
11632 : : defined, which is the case in Python on AIX. AIX bug report:
11633 : : http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
11634 : : #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
11635 : : # define POSIX_FADVISE_AIX_BUG
11636 : : #endif
11637 : :
11638 : :
11639 : : #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
11640 : : /*[clinic input]
11641 : : os.posix_fallocate
11642 : :
11643 : : fd: int
11644 : : offset: Py_off_t
11645 : : length: Py_off_t
11646 : : /
11647 : :
11648 : : Ensure a file has allocated at least a particular number of bytes on disk.
11649 : :
11650 : : Ensure that the file specified by fd encompasses a range of bytes
11651 : : starting at offset bytes from the beginning and continuing for length bytes.
11652 : : [clinic start generated code]*/
11653 : :
11654 : : static PyObject *
11655 : 0 : os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
11656 : : Py_off_t length)
11657 : : /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
11658 : : {
11659 : : int result;
11660 : 0 : int async_err = 0;
11661 : :
11662 : : do {
11663 : 0 : Py_BEGIN_ALLOW_THREADS
11664 : 0 : result = posix_fallocate(fd, offset, length);
11665 : 0 : Py_END_ALLOW_THREADS
11666 [ # # # # ]: 0 : } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
11667 : :
11668 [ # # ]: 0 : if (result == 0)
11669 : 0 : Py_RETURN_NONE;
11670 : :
11671 [ # # ]: 0 : if (async_err)
11672 : 0 : return NULL;
11673 : :
11674 : 0 : errno = result;
11675 : 0 : return posix_error();
11676 : : }
11677 : : #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
11678 : :
11679 : :
11680 : : #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
11681 : : /*[clinic input]
11682 : : os.posix_fadvise
11683 : :
11684 : : fd: int
11685 : : offset: Py_off_t
11686 : : length: Py_off_t
11687 : : advice: int
11688 : : /
11689 : :
11690 : : Announce an intention to access data in a specific pattern.
11691 : :
11692 : : Announce an intention to access data in a specific pattern, thus allowing
11693 : : the kernel to make optimizations.
11694 : : The advice applies to the region of the file specified by fd starting at
11695 : : offset and continuing for length bytes.
11696 : : advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
11697 : : POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
11698 : : POSIX_FADV_DONTNEED.
11699 : : [clinic start generated code]*/
11700 : :
11701 : : static PyObject *
11702 : 0 : os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
11703 : : Py_off_t length, int advice)
11704 : : /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
11705 : : {
11706 : : int result;
11707 : 0 : int async_err = 0;
11708 : :
11709 : : do {
11710 : 0 : Py_BEGIN_ALLOW_THREADS
11711 : 0 : result = posix_fadvise(fd, offset, length, advice);
11712 : 0 : Py_END_ALLOW_THREADS
11713 [ # # # # ]: 0 : } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
11714 : :
11715 [ # # ]: 0 : if (result == 0)
11716 : 0 : Py_RETURN_NONE;
11717 : :
11718 [ # # ]: 0 : if (async_err)
11719 : 0 : return NULL;
11720 : :
11721 : 0 : errno = result;
11722 : 0 : return posix_error();
11723 : : }
11724 : : #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
11725 : :
11726 : :
11727 : : #ifdef MS_WINDOWS
11728 : : static PyObject*
11729 : : win32_putenv(PyObject *name, PyObject *value)
11730 : : {
11731 : : /* Search from index 1 because on Windows starting '=' is allowed for
11732 : : defining hidden environment variables. */
11733 : : if (PyUnicode_GET_LENGTH(name) == 0 ||
11734 : : PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
11735 : : {
11736 : : PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11737 : : return NULL;
11738 : : }
11739 : : PyObject *unicode;
11740 : : if (value != NULL) {
11741 : : unicode = PyUnicode_FromFormat("%U=%U", name, value);
11742 : : }
11743 : : else {
11744 : : unicode = PyUnicode_FromFormat("%U=", name);
11745 : : }
11746 : : if (unicode == NULL) {
11747 : : return NULL;
11748 : : }
11749 : :
11750 : : Py_ssize_t size;
11751 : : /* PyUnicode_AsWideCharString() rejects embedded null characters */
11752 : : wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
11753 : : Py_DECREF(unicode);
11754 : :
11755 : : if (env == NULL) {
11756 : : return NULL;
11757 : : }
11758 : : if (size > _MAX_ENV) {
11759 : : PyErr_Format(PyExc_ValueError,
11760 : : "the environment variable is longer than %u characters",
11761 : : _MAX_ENV);
11762 : : PyMem_Free(env);
11763 : : return NULL;
11764 : : }
11765 : :
11766 : : /* _wputenv() and SetEnvironmentVariableW() update the environment in the
11767 : : Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
11768 : : and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
11769 : :
11770 : : Prefer _wputenv() to be compatible with C libraries using CRT
11771 : : variables and CRT functions using these variables (ex: getenv()). */
11772 : : int err = _wputenv(env);
11773 : : PyMem_Free(env);
11774 : :
11775 : : if (err) {
11776 : : posix_error();
11777 : : return NULL;
11778 : : }
11779 : :
11780 : : Py_RETURN_NONE;
11781 : : }
11782 : : #endif
11783 : :
11784 : :
11785 : : #ifdef MS_WINDOWS
11786 : : /*[clinic input]
11787 : : os.putenv
11788 : :
11789 : : name: unicode
11790 : : value: unicode
11791 : : /
11792 : :
11793 : : Change or add an environment variable.
11794 : : [clinic start generated code]*/
11795 : :
11796 : : static PyObject *
11797 : : os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11798 : : /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
11799 : : {
11800 : : if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11801 : : return NULL;
11802 : : }
11803 : : return win32_putenv(name, value);
11804 : : }
11805 : : #else
11806 : : /*[clinic input]
11807 : : os.putenv
11808 : :
11809 : : name: FSConverter
11810 : : value: FSConverter
11811 : : /
11812 : :
11813 : : Change or add an environment variable.
11814 : : [clinic start generated code]*/
11815 : :
11816 : : static PyObject *
11817 : 1 : os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11818 : : /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
11819 : : {
11820 : 1 : const char *name_string = PyBytes_AS_STRING(name);
11821 : 1 : const char *value_string = PyBytes_AS_STRING(value);
11822 : :
11823 [ - + ]: 1 : if (strchr(name_string, '=') != NULL) {
11824 : 0 : PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11825 : 0 : return NULL;
11826 : : }
11827 : :
11828 [ - + ]: 1 : if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11829 : 0 : return NULL;
11830 : : }
11831 : :
11832 [ - + ]: 1 : if (setenv(name_string, value_string, 1)) {
11833 : 0 : return posix_error();
11834 : : }
11835 : 1 : Py_RETURN_NONE;
11836 : : }
11837 : : #endif /* !defined(MS_WINDOWS) */
11838 : :
11839 : :
11840 : : #ifdef MS_WINDOWS
11841 : : /*[clinic input]
11842 : : os.unsetenv
11843 : : name: unicode
11844 : : /
11845 : :
11846 : : Delete an environment variable.
11847 : : [clinic start generated code]*/
11848 : :
11849 : : static PyObject *
11850 : : os_unsetenv_impl(PyObject *module, PyObject *name)
11851 : : /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
11852 : : {
11853 : : if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11854 : : return NULL;
11855 : : }
11856 : : return win32_putenv(name, NULL);
11857 : : }
11858 : : #else
11859 : : /*[clinic input]
11860 : : os.unsetenv
11861 : : name: FSConverter
11862 : : /
11863 : :
11864 : : Delete an environment variable.
11865 : : [clinic start generated code]*/
11866 : :
11867 : : static PyObject *
11868 : 0 : os_unsetenv_impl(PyObject *module, PyObject *name)
11869 : : /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
11870 : : {
11871 [ # # ]: 0 : if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11872 : 0 : return NULL;
11873 : : }
11874 : : #ifdef HAVE_BROKEN_UNSETENV
11875 : : unsetenv(PyBytes_AS_STRING(name));
11876 : : #else
11877 : 0 : int err = unsetenv(PyBytes_AS_STRING(name));
11878 [ # # ]: 0 : if (err) {
11879 : 0 : return posix_error();
11880 : : }
11881 : : #endif
11882 : :
11883 : 0 : Py_RETURN_NONE;
11884 : : }
11885 : : #endif /* !MS_WINDOWS */
11886 : :
11887 : :
11888 : : /*[clinic input]
11889 : : os.strerror
11890 : :
11891 : : code: int
11892 : : /
11893 : :
11894 : : Translate an error code to a message string.
11895 : : [clinic start generated code]*/
11896 : :
11897 : : static PyObject *
11898 : 0 : os_strerror_impl(PyObject *module, int code)
11899 : : /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
11900 : : {
11901 : 0 : char *message = strerror(code);
11902 [ # # ]: 0 : if (message == NULL) {
11903 : 0 : PyErr_SetString(PyExc_ValueError,
11904 : : "strerror() argument out of range");
11905 : 0 : return NULL;
11906 : : }
11907 : 0 : return PyUnicode_DecodeLocale(message, "surrogateescape");
11908 : : }
11909 : :
11910 : :
11911 : : #ifdef HAVE_SYS_WAIT_H
11912 : : #ifdef WCOREDUMP
11913 : : /*[clinic input]
11914 : : os.WCOREDUMP -> bool
11915 : :
11916 : : status: int
11917 : : /
11918 : :
11919 : : Return True if the process returning status was dumped to a core file.
11920 : : [clinic start generated code]*/
11921 : :
11922 : : static int
11923 : 0 : os_WCOREDUMP_impl(PyObject *module, int status)
11924 : : /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
11925 : : {
11926 : : WAIT_TYPE wait_status;
11927 : 0 : WAIT_STATUS_INT(wait_status) = status;
11928 : 0 : return WCOREDUMP(wait_status);
11929 : : }
11930 : : #endif /* WCOREDUMP */
11931 : :
11932 : :
11933 : : #ifdef WIFCONTINUED
11934 : : /*[clinic input]
11935 : : os.WIFCONTINUED -> bool
11936 : :
11937 : : status: int
11938 : :
11939 : : Return True if a particular process was continued from a job control stop.
11940 : :
11941 : : Return True if the process returning status was continued from a
11942 : : job control stop.
11943 : : [clinic start generated code]*/
11944 : :
11945 : : static int
11946 : 0 : os_WIFCONTINUED_impl(PyObject *module, int status)
11947 : : /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
11948 : : {
11949 : : WAIT_TYPE wait_status;
11950 : 0 : WAIT_STATUS_INT(wait_status) = status;
11951 : 0 : return WIFCONTINUED(wait_status);
11952 : : }
11953 : : #endif /* WIFCONTINUED */
11954 : :
11955 : :
11956 : : #ifdef WIFSTOPPED
11957 : : /*[clinic input]
11958 : : os.WIFSTOPPED -> bool
11959 : :
11960 : : status: int
11961 : :
11962 : : Return True if the process returning status was stopped.
11963 : : [clinic start generated code]*/
11964 : :
11965 : : static int
11966 : 0 : os_WIFSTOPPED_impl(PyObject *module, int status)
11967 : : /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
11968 : : {
11969 : : WAIT_TYPE wait_status;
11970 : 0 : WAIT_STATUS_INT(wait_status) = status;
11971 : 0 : return WIFSTOPPED(wait_status);
11972 : : }
11973 : : #endif /* WIFSTOPPED */
11974 : :
11975 : :
11976 : : #ifdef WIFSIGNALED
11977 : : /*[clinic input]
11978 : : os.WIFSIGNALED -> bool
11979 : :
11980 : : status: int
11981 : :
11982 : : Return True if the process returning status was terminated by a signal.
11983 : : [clinic start generated code]*/
11984 : :
11985 : : static int
11986 : 0 : os_WIFSIGNALED_impl(PyObject *module, int status)
11987 : : /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
11988 : : {
11989 : : WAIT_TYPE wait_status;
11990 : 0 : WAIT_STATUS_INT(wait_status) = status;
11991 : 0 : return WIFSIGNALED(wait_status);
11992 : : }
11993 : : #endif /* WIFSIGNALED */
11994 : :
11995 : :
11996 : : #ifdef WIFEXITED
11997 : : /*[clinic input]
11998 : : os.WIFEXITED -> bool
11999 : :
12000 : : status: int
12001 : :
12002 : : Return True if the process returning status exited via the exit() system call.
12003 : : [clinic start generated code]*/
12004 : :
12005 : : static int
12006 : 0 : os_WIFEXITED_impl(PyObject *module, int status)
12007 : : /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
12008 : : {
12009 : : WAIT_TYPE wait_status;
12010 : 0 : WAIT_STATUS_INT(wait_status) = status;
12011 : 0 : return WIFEXITED(wait_status);
12012 : : }
12013 : : #endif /* WIFEXITED */
12014 : :
12015 : :
12016 : : #ifdef WEXITSTATUS
12017 : : /*[clinic input]
12018 : : os.WEXITSTATUS -> int
12019 : :
12020 : : status: int
12021 : :
12022 : : Return the process return code from status.
12023 : : [clinic start generated code]*/
12024 : :
12025 : : static int
12026 : 0 : os_WEXITSTATUS_impl(PyObject *module, int status)
12027 : : /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
12028 : : {
12029 : : WAIT_TYPE wait_status;
12030 : 0 : WAIT_STATUS_INT(wait_status) = status;
12031 : 0 : return WEXITSTATUS(wait_status);
12032 : : }
12033 : : #endif /* WEXITSTATUS */
12034 : :
12035 : :
12036 : : #ifdef WTERMSIG
12037 : : /*[clinic input]
12038 : : os.WTERMSIG -> int
12039 : :
12040 : : status: int
12041 : :
12042 : : Return the signal that terminated the process that provided the status value.
12043 : : [clinic start generated code]*/
12044 : :
12045 : : static int
12046 : 0 : os_WTERMSIG_impl(PyObject *module, int status)
12047 : : /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
12048 : : {
12049 : : WAIT_TYPE wait_status;
12050 : 0 : WAIT_STATUS_INT(wait_status) = status;
12051 : 0 : return WTERMSIG(wait_status);
12052 : : }
12053 : : #endif /* WTERMSIG */
12054 : :
12055 : :
12056 : : #ifdef WSTOPSIG
12057 : : /*[clinic input]
12058 : : os.WSTOPSIG -> int
12059 : :
12060 : : status: int
12061 : :
12062 : : Return the signal that stopped the process that provided the status value.
12063 : : [clinic start generated code]*/
12064 : :
12065 : : static int
12066 : 0 : os_WSTOPSIG_impl(PyObject *module, int status)
12067 : : /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
12068 : : {
12069 : : WAIT_TYPE wait_status;
12070 : 0 : WAIT_STATUS_INT(wait_status) = status;
12071 : 0 : return WSTOPSIG(wait_status);
12072 : : }
12073 : : #endif /* WSTOPSIG */
12074 : : #endif /* HAVE_SYS_WAIT_H */
12075 : :
12076 : :
12077 : : #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
12078 : : #ifdef _SCO_DS
12079 : : /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
12080 : : needed definitions in sys/statvfs.h */
12081 : : #define _SVID3
12082 : : #endif
12083 : : #include <sys/statvfs.h>
12084 : :
12085 : : static PyObject*
12086 : 0 : _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
12087 : 0 : PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
12088 : 0 : PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
12089 [ # # ]: 0 : if (v == NULL)
12090 : 0 : return NULL;
12091 : :
12092 : : #if !defined(HAVE_LARGEFILE_SUPPORT)
12093 : 0 : PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
12094 : 0 : PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
12095 : 0 : PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
12096 : 0 : PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
12097 : 0 : PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
12098 : 0 : PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
12099 : 0 : PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
12100 : 0 : PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
12101 : 0 : PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
12102 : 0 : PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
12103 : : #else
12104 : : PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
12105 : : PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
12106 : : PyStructSequence_SET_ITEM(v, 2,
12107 : : PyLong_FromLongLong((long long) st.f_blocks));
12108 : : PyStructSequence_SET_ITEM(v, 3,
12109 : : PyLong_FromLongLong((long long) st.f_bfree));
12110 : : PyStructSequence_SET_ITEM(v, 4,
12111 : : PyLong_FromLongLong((long long) st.f_bavail));
12112 : : PyStructSequence_SET_ITEM(v, 5,
12113 : : PyLong_FromLongLong((long long) st.f_files));
12114 : : PyStructSequence_SET_ITEM(v, 6,
12115 : : PyLong_FromLongLong((long long) st.f_ffree));
12116 : : PyStructSequence_SET_ITEM(v, 7,
12117 : : PyLong_FromLongLong((long long) st.f_favail));
12118 : : PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
12119 : : PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
12120 : : #endif
12121 : : /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
12122 : : * (issue #32390). */
12123 : : #if defined(_AIX) && defined(_ALL_SOURCE)
12124 : : PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
12125 : : #else
12126 : 0 : PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
12127 : : #endif
12128 [ # # ]: 0 : if (PyErr_Occurred()) {
12129 : 0 : Py_DECREF(v);
12130 : 0 : return NULL;
12131 : : }
12132 : :
12133 : 0 : return v;
12134 : : }
12135 : :
12136 : :
12137 : : /*[clinic input]
12138 : : os.fstatvfs
12139 : : fd: int
12140 : : /
12141 : :
12142 : : Perform an fstatvfs system call on the given fd.
12143 : :
12144 : : Equivalent to statvfs(fd).
12145 : : [clinic start generated code]*/
12146 : :
12147 : : static PyObject *
12148 : 0 : os_fstatvfs_impl(PyObject *module, int fd)
12149 : : /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
12150 : : {
12151 : : int result;
12152 : 0 : int async_err = 0;
12153 : : struct statvfs st;
12154 : :
12155 : : do {
12156 : 0 : Py_BEGIN_ALLOW_THREADS
12157 : 0 : result = fstatvfs(fd, &st);
12158 : 0 : Py_END_ALLOW_THREADS
12159 [ # # # # ]: 0 : } while (result != 0 && errno == EINTR &&
12160 [ # # ]: 0 : !(async_err = PyErr_CheckSignals()));
12161 [ # # ]: 0 : if (result != 0)
12162 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
12163 : :
12164 : 0 : return _pystatvfs_fromstructstatvfs(module, st);
12165 : : }
12166 : : #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
12167 : :
12168 : :
12169 : : #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
12170 : : #include <sys/statvfs.h>
12171 : : /*[clinic input]
12172 : : os.statvfs
12173 : :
12174 : : path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
12175 : :
12176 : : Perform a statvfs system call on the given path.
12177 : :
12178 : : path may always be specified as a string.
12179 : : On some platforms, path may also be specified as an open file descriptor.
12180 : : If this functionality is unavailable, using it raises an exception.
12181 : : [clinic start generated code]*/
12182 : :
12183 : : static PyObject *
12184 : 0 : os_statvfs_impl(PyObject *module, path_t *path)
12185 : : /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
12186 : : {
12187 : : int result;
12188 : : struct statvfs st;
12189 : :
12190 : 0 : Py_BEGIN_ALLOW_THREADS
12191 : : #ifdef HAVE_FSTATVFS
12192 [ # # ]: 0 : if (path->fd != -1) {
12193 : 0 : result = fstatvfs(path->fd, &st);
12194 : : }
12195 : : else
12196 : : #endif
12197 : 0 : result = statvfs(path->narrow, &st);
12198 : 0 : Py_END_ALLOW_THREADS
12199 : :
12200 [ # # ]: 0 : if (result) {
12201 : 0 : return path_error(path);
12202 : : }
12203 : :
12204 : 0 : return _pystatvfs_fromstructstatvfs(module, st);
12205 : : }
12206 : : #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
12207 : :
12208 : :
12209 : : #ifdef MS_WINDOWS
12210 : : /*[clinic input]
12211 : : os._getdiskusage
12212 : :
12213 : : path: path_t
12214 : :
12215 : : Return disk usage statistics about the given path as a (total, free) tuple.
12216 : : [clinic start generated code]*/
12217 : :
12218 : : static PyObject *
12219 : : os__getdiskusage_impl(PyObject *module, path_t *path)
12220 : : /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
12221 : : {
12222 : : BOOL retval;
12223 : : ULARGE_INTEGER _, total, free;
12224 : : DWORD err = 0;
12225 : :
12226 : : Py_BEGIN_ALLOW_THREADS
12227 : : retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
12228 : : Py_END_ALLOW_THREADS
12229 : : if (retval == 0) {
12230 : : if (GetLastError() == ERROR_DIRECTORY) {
12231 : : wchar_t *dir_path = NULL;
12232 : :
12233 : : dir_path = PyMem_New(wchar_t, path->length + 1);
12234 : : if (dir_path == NULL) {
12235 : : return PyErr_NoMemory();
12236 : : }
12237 : :
12238 : : wcscpy_s(dir_path, path->length + 1, path->wide);
12239 : :
12240 : : if (_dirnameW(dir_path) != -1) {
12241 : : Py_BEGIN_ALLOW_THREADS
12242 : : retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
12243 : : Py_END_ALLOW_THREADS
12244 : : }
12245 : : /* Record the last error in case it's modified by PyMem_Free. */
12246 : : err = GetLastError();
12247 : : PyMem_Free(dir_path);
12248 : : if (retval) {
12249 : : goto success;
12250 : : }
12251 : : }
12252 : : return PyErr_SetFromWindowsErr(err);
12253 : : }
12254 : :
12255 : : success:
12256 : : return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
12257 : : }
12258 : : #endif /* MS_WINDOWS */
12259 : :
12260 : :
12261 : : /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
12262 : : * It maps strings representing configuration variable names to
12263 : : * integer values, allowing those functions to be called with the
12264 : : * magic names instead of polluting the module's namespace with tons of
12265 : : * rarely-used constants. There are three separate tables that use
12266 : : * these definitions.
12267 : : *
12268 : : * This code is always included, even if none of the interfaces that
12269 : : * need it are included. The #if hackery needed to avoid it would be
12270 : : * sufficiently pervasive that it's not worth the loss of readability.
12271 : : */
12272 : : struct constdef {
12273 : : const char *name;
12274 : : int value;
12275 : : };
12276 : :
12277 : : static int
12278 : 2 : conv_confname(PyObject *arg, int *valuep, struct constdef *table,
12279 : : size_t tablesize)
12280 : : {
12281 [ - + ]: 2 : if (PyLong_Check(arg)) {
12282 : 0 : int value = _PyLong_AsInt(arg);
12283 [ # # # # ]: 0 : if (value == -1 && PyErr_Occurred())
12284 : 0 : return 0;
12285 : 0 : *valuep = value;
12286 : 0 : return 1;
12287 : : }
12288 : : else {
12289 : : /* look up the value in the table using a binary search */
12290 : 2 : size_t lo = 0;
12291 : : size_t mid;
12292 : 2 : size_t hi = tablesize;
12293 : : int cmp;
12294 : : const char *confname;
12295 [ - + ]: 2 : if (!PyUnicode_Check(arg)) {
12296 : 0 : PyErr_SetString(PyExc_TypeError,
12297 : : "configuration names must be strings or integers");
12298 : 0 : return 0;
12299 : : }
12300 : 2 : confname = PyUnicode_AsUTF8(arg);
12301 [ - + ]: 2 : if (confname == NULL)
12302 : 0 : return 0;
12303 [ + - ]: 11 : while (lo < hi) {
12304 : 11 : mid = (lo + hi) / 2;
12305 : 11 : cmp = strcmp(confname, table[mid].name);
12306 [ + + ]: 11 : if (cmp < 0)
12307 : 8 : hi = mid;
12308 [ + + ]: 3 : else if (cmp > 0)
12309 : 1 : lo = mid + 1;
12310 : : else {
12311 : 2 : *valuep = table[mid].value;
12312 : 2 : return 1;
12313 : : }
12314 : : }
12315 : 0 : PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
12316 : 0 : return 0;
12317 : : }
12318 : : }
12319 : :
12320 : :
12321 : : #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12322 : : static struct constdef posix_constants_pathconf[] = {
12323 : : #ifdef _PC_ABI_AIO_XFER_MAX
12324 : : {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
12325 : : #endif
12326 : : #ifdef _PC_ABI_ASYNC_IO
12327 : : {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
12328 : : #endif
12329 : : #ifdef _PC_ASYNC_IO
12330 : : {"PC_ASYNC_IO", _PC_ASYNC_IO},
12331 : : #endif
12332 : : #ifdef _PC_CHOWN_RESTRICTED
12333 : : {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
12334 : : #endif
12335 : : #ifdef _PC_FILESIZEBITS
12336 : : {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
12337 : : #endif
12338 : : #ifdef _PC_LAST
12339 : : {"PC_LAST", _PC_LAST},
12340 : : #endif
12341 : : #ifdef _PC_LINK_MAX
12342 : : {"PC_LINK_MAX", _PC_LINK_MAX},
12343 : : #endif
12344 : : #ifdef _PC_MAX_CANON
12345 : : {"PC_MAX_CANON", _PC_MAX_CANON},
12346 : : #endif
12347 : : #ifdef _PC_MAX_INPUT
12348 : : {"PC_MAX_INPUT", _PC_MAX_INPUT},
12349 : : #endif
12350 : : #ifdef _PC_NAME_MAX
12351 : : {"PC_NAME_MAX", _PC_NAME_MAX},
12352 : : #endif
12353 : : #ifdef _PC_NO_TRUNC
12354 : : {"PC_NO_TRUNC", _PC_NO_TRUNC},
12355 : : #endif
12356 : : #ifdef _PC_PATH_MAX
12357 : : {"PC_PATH_MAX", _PC_PATH_MAX},
12358 : : #endif
12359 : : #ifdef _PC_PIPE_BUF
12360 : : {"PC_PIPE_BUF", _PC_PIPE_BUF},
12361 : : #endif
12362 : : #ifdef _PC_PRIO_IO
12363 : : {"PC_PRIO_IO", _PC_PRIO_IO},
12364 : : #endif
12365 : : #ifdef _PC_SOCK_MAXBUF
12366 : : {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
12367 : : #endif
12368 : : #ifdef _PC_SYNC_IO
12369 : : {"PC_SYNC_IO", _PC_SYNC_IO},
12370 : : #endif
12371 : : #ifdef _PC_VDISABLE
12372 : : {"PC_VDISABLE", _PC_VDISABLE},
12373 : : #endif
12374 : : #ifdef _PC_ACL_ENABLED
12375 : : {"PC_ACL_ENABLED", _PC_ACL_ENABLED},
12376 : : #endif
12377 : : #ifdef _PC_MIN_HOLE_SIZE
12378 : : {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE},
12379 : : #endif
12380 : : #ifdef _PC_ALLOC_SIZE_MIN
12381 : : {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN},
12382 : : #endif
12383 : : #ifdef _PC_REC_INCR_XFER_SIZE
12384 : : {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE},
12385 : : #endif
12386 : : #ifdef _PC_REC_MAX_XFER_SIZE
12387 : : {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE},
12388 : : #endif
12389 : : #ifdef _PC_REC_MIN_XFER_SIZE
12390 : : {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE},
12391 : : #endif
12392 : : #ifdef _PC_REC_XFER_ALIGN
12393 : : {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN},
12394 : : #endif
12395 : : #ifdef _PC_SYMLINK_MAX
12396 : : {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX},
12397 : : #endif
12398 : : #ifdef _PC_XATTR_ENABLED
12399 : : {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED},
12400 : : #endif
12401 : : #ifdef _PC_XATTR_EXISTS
12402 : : {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
12403 : : #endif
12404 : : #ifdef _PC_TIMESTAMP_RESOLUTION
12405 : : {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
12406 : : #endif
12407 : : };
12408 : :
12409 : : static int
12410 : 0 : conv_path_confname(PyObject *arg, int *valuep)
12411 : : {
12412 : 0 : return conv_confname(arg, valuep, posix_constants_pathconf,
12413 : : sizeof(posix_constants_pathconf)
12414 : : / sizeof(struct constdef));
12415 : : }
12416 : : #endif
12417 : :
12418 : :
12419 : : #ifdef HAVE_FPATHCONF
12420 : : /*[clinic input]
12421 : : os.fpathconf -> long
12422 : :
12423 : : fd: fildes
12424 : : name: path_confname
12425 : : /
12426 : :
12427 : : Return the configuration limit name for the file descriptor fd.
12428 : :
12429 : : If there is no limit, return -1.
12430 : : [clinic start generated code]*/
12431 : :
12432 : : static long
12433 : 0 : os_fpathconf_impl(PyObject *module, int fd, int name)
12434 : : /*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
12435 : : {
12436 : : long limit;
12437 : :
12438 : 0 : errno = 0;
12439 : 0 : limit = fpathconf(fd, name);
12440 [ # # # # ]: 0 : if (limit == -1 && errno != 0)
12441 : 0 : posix_error();
12442 : :
12443 : 0 : return limit;
12444 : : }
12445 : : #endif /* HAVE_FPATHCONF */
12446 : :
12447 : :
12448 : : #ifdef HAVE_PATHCONF
12449 : : /*[clinic input]
12450 : : os.pathconf -> long
12451 : : path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
12452 : : name: path_confname
12453 : :
12454 : : Return the configuration limit name for the file or directory path.
12455 : :
12456 : : If there is no limit, return -1.
12457 : : On some platforms, path may also be specified as an open file descriptor.
12458 : : If this functionality is unavailable, using it raises an exception.
12459 : : [clinic start generated code]*/
12460 : :
12461 : : static long
12462 : 0 : os_pathconf_impl(PyObject *module, path_t *path, int name)
12463 : : /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
12464 : : {
12465 : : long limit;
12466 : :
12467 : 0 : errno = 0;
12468 : : #ifdef HAVE_FPATHCONF
12469 [ # # ]: 0 : if (path->fd != -1)
12470 : 0 : limit = fpathconf(path->fd, name);
12471 : : else
12472 : : #endif
12473 : 0 : limit = pathconf(path->narrow, name);
12474 [ # # # # ]: 0 : if (limit == -1 && errno != 0) {
12475 [ # # ]: 0 : if (errno == EINVAL)
12476 : : /* could be a path or name problem */
12477 : 0 : posix_error();
12478 : : else
12479 : 0 : path_error(path);
12480 : : }
12481 : :
12482 : 0 : return limit;
12483 : : }
12484 : : #endif /* HAVE_PATHCONF */
12485 : :
12486 : : #ifdef HAVE_CONFSTR
12487 : : static struct constdef posix_constants_confstr[] = {
12488 : : #ifdef _CS_ARCHITECTURE
12489 : : {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
12490 : : #endif
12491 : : #ifdef _CS_GNU_LIBC_VERSION
12492 : : {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION},
12493 : : #endif
12494 : : #ifdef _CS_GNU_LIBPTHREAD_VERSION
12495 : : {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION},
12496 : : #endif
12497 : : #ifdef _CS_HOSTNAME
12498 : : {"CS_HOSTNAME", _CS_HOSTNAME},
12499 : : #endif
12500 : : #ifdef _CS_HW_PROVIDER
12501 : : {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
12502 : : #endif
12503 : : #ifdef _CS_HW_SERIAL
12504 : : {"CS_HW_SERIAL", _CS_HW_SERIAL},
12505 : : #endif
12506 : : #ifdef _CS_INITTAB_NAME
12507 : : {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
12508 : : #endif
12509 : : #ifdef _CS_LFS64_CFLAGS
12510 : : {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
12511 : : #endif
12512 : : #ifdef _CS_LFS64_LDFLAGS
12513 : : {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
12514 : : #endif
12515 : : #ifdef _CS_LFS64_LIBS
12516 : : {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
12517 : : #endif
12518 : : #ifdef _CS_LFS64_LINTFLAGS
12519 : : {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
12520 : : #endif
12521 : : #ifdef _CS_LFS_CFLAGS
12522 : : {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
12523 : : #endif
12524 : : #ifdef _CS_LFS_LDFLAGS
12525 : : {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
12526 : : #endif
12527 : : #ifdef _CS_LFS_LIBS
12528 : : {"CS_LFS_LIBS", _CS_LFS_LIBS},
12529 : : #endif
12530 : : #ifdef _CS_LFS_LINTFLAGS
12531 : : {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
12532 : : #endif
12533 : : #ifdef _CS_MACHINE
12534 : : {"CS_MACHINE", _CS_MACHINE},
12535 : : #endif
12536 : : #ifdef _CS_PATH
12537 : : {"CS_PATH", _CS_PATH},
12538 : : #endif
12539 : : #ifdef _CS_RELEASE
12540 : : {"CS_RELEASE", _CS_RELEASE},
12541 : : #endif
12542 : : #ifdef _CS_SRPC_DOMAIN
12543 : : {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
12544 : : #endif
12545 : : #ifdef _CS_SYSNAME
12546 : : {"CS_SYSNAME", _CS_SYSNAME},
12547 : : #endif
12548 : : #ifdef _CS_VERSION
12549 : : {"CS_VERSION", _CS_VERSION},
12550 : : #endif
12551 : : #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
12552 : : {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
12553 : : #endif
12554 : : #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
12555 : : {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
12556 : : #endif
12557 : : #ifdef _CS_XBS5_ILP32_OFF32_LIBS
12558 : : {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
12559 : : #endif
12560 : : #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
12561 : : {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
12562 : : #endif
12563 : : #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
12564 : : {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
12565 : : #endif
12566 : : #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
12567 : : {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
12568 : : #endif
12569 : : #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
12570 : : {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
12571 : : #endif
12572 : : #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
12573 : : {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
12574 : : #endif
12575 : : #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
12576 : : {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
12577 : : #endif
12578 : : #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
12579 : : {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
12580 : : #endif
12581 : : #ifdef _CS_XBS5_LP64_OFF64_LIBS
12582 : : {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
12583 : : #endif
12584 : : #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
12585 : : {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
12586 : : #endif
12587 : : #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
12588 : : {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
12589 : : #endif
12590 : : #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
12591 : : {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
12592 : : #endif
12593 : : #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
12594 : : {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
12595 : : #endif
12596 : : #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
12597 : : {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
12598 : : #endif
12599 : : #ifdef _MIPS_CS_AVAIL_PROCESSORS
12600 : : {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
12601 : : #endif
12602 : : #ifdef _MIPS_CS_BASE
12603 : : {"MIPS_CS_BASE", _MIPS_CS_BASE},
12604 : : #endif
12605 : : #ifdef _MIPS_CS_HOSTID
12606 : : {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
12607 : : #endif
12608 : : #ifdef _MIPS_CS_HW_NAME
12609 : : {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
12610 : : #endif
12611 : : #ifdef _MIPS_CS_NUM_PROCESSORS
12612 : : {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
12613 : : #endif
12614 : : #ifdef _MIPS_CS_OSREL_MAJ
12615 : : {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
12616 : : #endif
12617 : : #ifdef _MIPS_CS_OSREL_MIN
12618 : : {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
12619 : : #endif
12620 : : #ifdef _MIPS_CS_OSREL_PATCH
12621 : : {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
12622 : : #endif
12623 : : #ifdef _MIPS_CS_OS_NAME
12624 : : {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
12625 : : #endif
12626 : : #ifdef _MIPS_CS_OS_PROVIDER
12627 : : {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
12628 : : #endif
12629 : : #ifdef _MIPS_CS_PROCESSORS
12630 : : {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
12631 : : #endif
12632 : : #ifdef _MIPS_CS_SERIAL
12633 : : {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
12634 : : #endif
12635 : : #ifdef _MIPS_CS_VENDOR
12636 : : {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
12637 : : #endif
12638 : : };
12639 : :
12640 : : static int
12641 : 1 : conv_confstr_confname(PyObject *arg, int *valuep)
12642 : : {
12643 : 1 : return conv_confname(arg, valuep, posix_constants_confstr,
12644 : : sizeof(posix_constants_confstr)
12645 : : / sizeof(struct constdef));
12646 : : }
12647 : :
12648 : :
12649 : : /*[clinic input]
12650 : : os.confstr
12651 : :
12652 : : name: confstr_confname
12653 : : /
12654 : :
12655 : : Return a string-valued system configuration variable.
12656 : : [clinic start generated code]*/
12657 : :
12658 : : static PyObject *
12659 : 1 : os_confstr_impl(PyObject *module, int name)
12660 : : /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
12661 : : {
12662 : 1 : PyObject *result = NULL;
12663 : : char buffer[255];
12664 : : size_t len;
12665 : :
12666 : 1 : errno = 0;
12667 : 1 : len = confstr(name, buffer, sizeof(buffer));
12668 [ - + ]: 1 : if (len == 0) {
12669 [ # # ]: 0 : if (errno) {
12670 : 0 : posix_error();
12671 : 0 : return NULL;
12672 : : }
12673 : : else {
12674 : 0 : Py_RETURN_NONE;
12675 : : }
12676 : : }
12677 : :
12678 [ - + ]: 1 : if (len >= sizeof(buffer)) {
12679 : : size_t len2;
12680 : 0 : char *buf = PyMem_Malloc(len);
12681 [ # # ]: 0 : if (buf == NULL)
12682 : 0 : return PyErr_NoMemory();
12683 : 0 : len2 = confstr(name, buf, len);
12684 : : assert(len == len2);
12685 : 0 : result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
12686 : 0 : PyMem_Free(buf);
12687 : : }
12688 : : else
12689 : 1 : result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
12690 : 1 : return result;
12691 : : }
12692 : : #endif /* HAVE_CONFSTR */
12693 : :
12694 : :
12695 : : #ifdef HAVE_SYSCONF
12696 : : static struct constdef posix_constants_sysconf[] = {
12697 : : #ifdef _SC_2_CHAR_TERM
12698 : : {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
12699 : : #endif
12700 : : #ifdef _SC_2_C_BIND
12701 : : {"SC_2_C_BIND", _SC_2_C_BIND},
12702 : : #endif
12703 : : #ifdef _SC_2_C_DEV
12704 : : {"SC_2_C_DEV", _SC_2_C_DEV},
12705 : : #endif
12706 : : #ifdef _SC_2_C_VERSION
12707 : : {"SC_2_C_VERSION", _SC_2_C_VERSION},
12708 : : #endif
12709 : : #ifdef _SC_2_FORT_DEV
12710 : : {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
12711 : : #endif
12712 : : #ifdef _SC_2_FORT_RUN
12713 : : {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
12714 : : #endif
12715 : : #ifdef _SC_2_LOCALEDEF
12716 : : {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
12717 : : #endif
12718 : : #ifdef _SC_2_SW_DEV
12719 : : {"SC_2_SW_DEV", _SC_2_SW_DEV},
12720 : : #endif
12721 : : #ifdef _SC_2_UPE
12722 : : {"SC_2_UPE", _SC_2_UPE},
12723 : : #endif
12724 : : #ifdef _SC_2_VERSION
12725 : : {"SC_2_VERSION", _SC_2_VERSION},
12726 : : #endif
12727 : : #ifdef _SC_ABI_ASYNCHRONOUS_IO
12728 : : {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
12729 : : #endif
12730 : : #ifdef _SC_ACL
12731 : : {"SC_ACL", _SC_ACL},
12732 : : #endif
12733 : : #ifdef _SC_AIO_LISTIO_MAX
12734 : : {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
12735 : : #endif
12736 : : #ifdef _SC_AIO_MAX
12737 : : {"SC_AIO_MAX", _SC_AIO_MAX},
12738 : : #endif
12739 : : #ifdef _SC_AIO_PRIO_DELTA_MAX
12740 : : {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
12741 : : #endif
12742 : : #ifdef _SC_ARG_MAX
12743 : : {"SC_ARG_MAX", _SC_ARG_MAX},
12744 : : #endif
12745 : : #ifdef _SC_ASYNCHRONOUS_IO
12746 : : {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
12747 : : #endif
12748 : : #ifdef _SC_ATEXIT_MAX
12749 : : {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
12750 : : #endif
12751 : : #ifdef _SC_AUDIT
12752 : : {"SC_AUDIT", _SC_AUDIT},
12753 : : #endif
12754 : : #ifdef _SC_AVPHYS_PAGES
12755 : : {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
12756 : : #endif
12757 : : #ifdef _SC_BC_BASE_MAX
12758 : : {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
12759 : : #endif
12760 : : #ifdef _SC_BC_DIM_MAX
12761 : : {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
12762 : : #endif
12763 : : #ifdef _SC_BC_SCALE_MAX
12764 : : {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
12765 : : #endif
12766 : : #ifdef _SC_BC_STRING_MAX
12767 : : {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
12768 : : #endif
12769 : : #ifdef _SC_CAP
12770 : : {"SC_CAP", _SC_CAP},
12771 : : #endif
12772 : : #ifdef _SC_CHARCLASS_NAME_MAX
12773 : : {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
12774 : : #endif
12775 : : #ifdef _SC_CHAR_BIT
12776 : : {"SC_CHAR_BIT", _SC_CHAR_BIT},
12777 : : #endif
12778 : : #ifdef _SC_CHAR_MAX
12779 : : {"SC_CHAR_MAX", _SC_CHAR_MAX},
12780 : : #endif
12781 : : #ifdef _SC_CHAR_MIN
12782 : : {"SC_CHAR_MIN", _SC_CHAR_MIN},
12783 : : #endif
12784 : : #ifdef _SC_CHILD_MAX
12785 : : {"SC_CHILD_MAX", _SC_CHILD_MAX},
12786 : : #endif
12787 : : #ifdef _SC_CLK_TCK
12788 : : {"SC_CLK_TCK", _SC_CLK_TCK},
12789 : : #endif
12790 : : #ifdef _SC_COHER_BLKSZ
12791 : : {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
12792 : : #endif
12793 : : #ifdef _SC_COLL_WEIGHTS_MAX
12794 : : {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
12795 : : #endif
12796 : : #ifdef _SC_DCACHE_ASSOC
12797 : : {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
12798 : : #endif
12799 : : #ifdef _SC_DCACHE_BLKSZ
12800 : : {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
12801 : : #endif
12802 : : #ifdef _SC_DCACHE_LINESZ
12803 : : {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
12804 : : #endif
12805 : : #ifdef _SC_DCACHE_SZ
12806 : : {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
12807 : : #endif
12808 : : #ifdef _SC_DCACHE_TBLKSZ
12809 : : {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
12810 : : #endif
12811 : : #ifdef _SC_DELAYTIMER_MAX
12812 : : {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
12813 : : #endif
12814 : : #ifdef _SC_EQUIV_CLASS_MAX
12815 : : {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
12816 : : #endif
12817 : : #ifdef _SC_EXPR_NEST_MAX
12818 : : {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
12819 : : #endif
12820 : : #ifdef _SC_FSYNC
12821 : : {"SC_FSYNC", _SC_FSYNC},
12822 : : #endif
12823 : : #ifdef _SC_GETGR_R_SIZE_MAX
12824 : : {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
12825 : : #endif
12826 : : #ifdef _SC_GETPW_R_SIZE_MAX
12827 : : {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
12828 : : #endif
12829 : : #ifdef _SC_ICACHE_ASSOC
12830 : : {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
12831 : : #endif
12832 : : #ifdef _SC_ICACHE_BLKSZ
12833 : : {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
12834 : : #endif
12835 : : #ifdef _SC_ICACHE_LINESZ
12836 : : {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
12837 : : #endif
12838 : : #ifdef _SC_ICACHE_SZ
12839 : : {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
12840 : : #endif
12841 : : #ifdef _SC_INF
12842 : : {"SC_INF", _SC_INF},
12843 : : #endif
12844 : : #ifdef _SC_INT_MAX
12845 : : {"SC_INT_MAX", _SC_INT_MAX},
12846 : : #endif
12847 : : #ifdef _SC_INT_MIN
12848 : : {"SC_INT_MIN", _SC_INT_MIN},
12849 : : #endif
12850 : : #ifdef _SC_IOV_MAX
12851 : : {"SC_IOV_MAX", _SC_IOV_MAX},
12852 : : #endif
12853 : : #ifdef _SC_IP_SECOPTS
12854 : : {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
12855 : : #endif
12856 : : #ifdef _SC_JOB_CONTROL
12857 : : {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
12858 : : #endif
12859 : : #ifdef _SC_KERN_POINTERS
12860 : : {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
12861 : : #endif
12862 : : #ifdef _SC_KERN_SIM
12863 : : {"SC_KERN_SIM", _SC_KERN_SIM},
12864 : : #endif
12865 : : #ifdef _SC_LINE_MAX
12866 : : {"SC_LINE_MAX", _SC_LINE_MAX},
12867 : : #endif
12868 : : #ifdef _SC_LOGIN_NAME_MAX
12869 : : {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
12870 : : #endif
12871 : : #ifdef _SC_LOGNAME_MAX
12872 : : {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
12873 : : #endif
12874 : : #ifdef _SC_LONG_BIT
12875 : : {"SC_LONG_BIT", _SC_LONG_BIT},
12876 : : #endif
12877 : : #ifdef _SC_MAC
12878 : : {"SC_MAC", _SC_MAC},
12879 : : #endif
12880 : : #ifdef _SC_MAPPED_FILES
12881 : : {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
12882 : : #endif
12883 : : #ifdef _SC_MAXPID
12884 : : {"SC_MAXPID", _SC_MAXPID},
12885 : : #endif
12886 : : #ifdef _SC_MB_LEN_MAX
12887 : : {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
12888 : : #endif
12889 : : #ifdef _SC_MEMLOCK
12890 : : {"SC_MEMLOCK", _SC_MEMLOCK},
12891 : : #endif
12892 : : #ifdef _SC_MEMLOCK_RANGE
12893 : : {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
12894 : : #endif
12895 : : #ifdef _SC_MEMORY_PROTECTION
12896 : : {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
12897 : : #endif
12898 : : #ifdef _SC_MESSAGE_PASSING
12899 : : {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
12900 : : #endif
12901 : : #ifdef _SC_MMAP_FIXED_ALIGNMENT
12902 : : {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
12903 : : #endif
12904 : : #ifdef _SC_MQ_OPEN_MAX
12905 : : {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
12906 : : #endif
12907 : : #ifdef _SC_MQ_PRIO_MAX
12908 : : {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},
12909 : : #endif
12910 : : #ifdef _SC_NACLS_MAX
12911 : : {"SC_NACLS_MAX", _SC_NACLS_MAX},
12912 : : #endif
12913 : : #ifdef _SC_NGROUPS_MAX
12914 : : {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX},
12915 : : #endif
12916 : : #ifdef _SC_NL_ARGMAX
12917 : : {"SC_NL_ARGMAX", _SC_NL_ARGMAX},
12918 : : #endif
12919 : : #ifdef _SC_NL_LANGMAX
12920 : : {"SC_NL_LANGMAX", _SC_NL_LANGMAX},
12921 : : #endif
12922 : : #ifdef _SC_NL_MSGMAX
12923 : : {"SC_NL_MSGMAX", _SC_NL_MSGMAX},
12924 : : #endif
12925 : : #ifdef _SC_NL_NMAX
12926 : : {"SC_NL_NMAX", _SC_NL_NMAX},
12927 : : #endif
12928 : : #ifdef _SC_NL_SETMAX
12929 : : {"SC_NL_SETMAX", _SC_NL_SETMAX},
12930 : : #endif
12931 : : #ifdef _SC_NL_TEXTMAX
12932 : : {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX},
12933 : : #endif
12934 : : #ifdef _SC_NPROCESSORS_CONF
12935 : : {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
12936 : : #endif
12937 : : #ifdef _SC_NPROCESSORS_ONLN
12938 : : {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
12939 : : #endif
12940 : : #ifdef _SC_NPROC_CONF
12941 : : {"SC_NPROC_CONF", _SC_NPROC_CONF},
12942 : : #endif
12943 : : #ifdef _SC_NPROC_ONLN
12944 : : {"SC_NPROC_ONLN", _SC_NPROC_ONLN},
12945 : : #endif
12946 : : #ifdef _SC_NZERO
12947 : : {"SC_NZERO", _SC_NZERO},
12948 : : #endif
12949 : : #ifdef _SC_OPEN_MAX
12950 : : {"SC_OPEN_MAX", _SC_OPEN_MAX},
12951 : : #endif
12952 : : #ifdef _SC_PAGESIZE
12953 : : {"SC_PAGESIZE", _SC_PAGESIZE},
12954 : : #endif
12955 : : #ifdef _SC_PAGE_SIZE
12956 : : {"SC_PAGE_SIZE", _SC_PAGE_SIZE},
12957 : : #endif
12958 : : #ifdef _SC_AIX_REALMEM
12959 : : {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
12960 : : #endif
12961 : : #ifdef _SC_PASS_MAX
12962 : : {"SC_PASS_MAX", _SC_PASS_MAX},
12963 : : #endif
12964 : : #ifdef _SC_PHYS_PAGES
12965 : : {"SC_PHYS_PAGES", _SC_PHYS_PAGES},
12966 : : #endif
12967 : : #ifdef _SC_PII
12968 : : {"SC_PII", _SC_PII},
12969 : : #endif
12970 : : #ifdef _SC_PII_INTERNET
12971 : : {"SC_PII_INTERNET", _SC_PII_INTERNET},
12972 : : #endif
12973 : : #ifdef _SC_PII_INTERNET_DGRAM
12974 : : {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM},
12975 : : #endif
12976 : : #ifdef _SC_PII_INTERNET_STREAM
12977 : : {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM},
12978 : : #endif
12979 : : #ifdef _SC_PII_OSI
12980 : : {"SC_PII_OSI", _SC_PII_OSI},
12981 : : #endif
12982 : : #ifdef _SC_PII_OSI_CLTS
12983 : : {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
12984 : : #endif
12985 : : #ifdef _SC_PII_OSI_COTS
12986 : : {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
12987 : : #endif
12988 : : #ifdef _SC_PII_OSI_M
12989 : : {"SC_PII_OSI_M", _SC_PII_OSI_M},
12990 : : #endif
12991 : : #ifdef _SC_PII_SOCKET
12992 : : {"SC_PII_SOCKET", _SC_PII_SOCKET},
12993 : : #endif
12994 : : #ifdef _SC_PII_XTI
12995 : : {"SC_PII_XTI", _SC_PII_XTI},
12996 : : #endif
12997 : : #ifdef _SC_POLL
12998 : : {"SC_POLL", _SC_POLL},
12999 : : #endif
13000 : : #ifdef _SC_PRIORITIZED_IO
13001 : : {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO},
13002 : : #endif
13003 : : #ifdef _SC_PRIORITY_SCHEDULING
13004 : : {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING},
13005 : : #endif
13006 : : #ifdef _SC_REALTIME_SIGNALS
13007 : : {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS},
13008 : : #endif
13009 : : #ifdef _SC_RE_DUP_MAX
13010 : : {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX},
13011 : : #endif
13012 : : #ifdef _SC_RTSIG_MAX
13013 : : {"SC_RTSIG_MAX", _SC_RTSIG_MAX},
13014 : : #endif
13015 : : #ifdef _SC_SAVED_IDS
13016 : : {"SC_SAVED_IDS", _SC_SAVED_IDS},
13017 : : #endif
13018 : : #ifdef _SC_SCHAR_MAX
13019 : : {"SC_SCHAR_MAX", _SC_SCHAR_MAX},
13020 : : #endif
13021 : : #ifdef _SC_SCHAR_MIN
13022 : : {"SC_SCHAR_MIN", _SC_SCHAR_MIN},
13023 : : #endif
13024 : : #ifdef _SC_SELECT
13025 : : {"SC_SELECT", _SC_SELECT},
13026 : : #endif
13027 : : #ifdef _SC_SEMAPHORES
13028 : : {"SC_SEMAPHORES", _SC_SEMAPHORES},
13029 : : #endif
13030 : : #ifdef _SC_SEM_NSEMS_MAX
13031 : : {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX},
13032 : : #endif
13033 : : #ifdef _SC_SEM_VALUE_MAX
13034 : : {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX},
13035 : : #endif
13036 : : #ifdef _SC_SHARED_MEMORY_OBJECTS
13037 : : {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS},
13038 : : #endif
13039 : : #ifdef _SC_SHRT_MAX
13040 : : {"SC_SHRT_MAX", _SC_SHRT_MAX},
13041 : : #endif
13042 : : #ifdef _SC_SHRT_MIN
13043 : : {"SC_SHRT_MIN", _SC_SHRT_MIN},
13044 : : #endif
13045 : : #ifdef _SC_SIGQUEUE_MAX
13046 : : {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
13047 : : #endif
13048 : : #ifdef _SC_SIGRT_MAX
13049 : : {"SC_SIGRT_MAX", _SC_SIGRT_MAX},
13050 : : #endif
13051 : : #ifdef _SC_SIGRT_MIN
13052 : : {"SC_SIGRT_MIN", _SC_SIGRT_MIN},
13053 : : #endif
13054 : : #ifdef _SC_SOFTPOWER
13055 : : {"SC_SOFTPOWER", _SC_SOFTPOWER},
13056 : : #endif
13057 : : #ifdef _SC_SPLIT_CACHE
13058 : : {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE},
13059 : : #endif
13060 : : #ifdef _SC_SSIZE_MAX
13061 : : {"SC_SSIZE_MAX", _SC_SSIZE_MAX},
13062 : : #endif
13063 : : #ifdef _SC_STACK_PROT
13064 : : {"SC_STACK_PROT", _SC_STACK_PROT},
13065 : : #endif
13066 : : #ifdef _SC_STREAM_MAX
13067 : : {"SC_STREAM_MAX", _SC_STREAM_MAX},
13068 : : #endif
13069 : : #ifdef _SC_SYNCHRONIZED_IO
13070 : : {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO},
13071 : : #endif
13072 : : #ifdef _SC_THREADS
13073 : : {"SC_THREADS", _SC_THREADS},
13074 : : #endif
13075 : : #ifdef _SC_THREAD_ATTR_STACKADDR
13076 : : {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR},
13077 : : #endif
13078 : : #ifdef _SC_THREAD_ATTR_STACKSIZE
13079 : : {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE},
13080 : : #endif
13081 : : #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
13082 : : {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
13083 : : #endif
13084 : : #ifdef _SC_THREAD_KEYS_MAX
13085 : : {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
13086 : : #endif
13087 : : #ifdef _SC_THREAD_PRIORITY_SCHEDULING
13088 : : {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING},
13089 : : #endif
13090 : : #ifdef _SC_THREAD_PRIO_INHERIT
13091 : : {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT},
13092 : : #endif
13093 : : #ifdef _SC_THREAD_PRIO_PROTECT
13094 : : {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT},
13095 : : #endif
13096 : : #ifdef _SC_THREAD_PROCESS_SHARED
13097 : : {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED},
13098 : : #endif
13099 : : #ifdef _SC_THREAD_SAFE_FUNCTIONS
13100 : : {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS},
13101 : : #endif
13102 : : #ifdef _SC_THREAD_STACK_MIN
13103 : : {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
13104 : : #endif
13105 : : #ifdef _SC_THREAD_THREADS_MAX
13106 : : {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
13107 : : #endif
13108 : : #ifdef _SC_TIMERS
13109 : : {"SC_TIMERS", _SC_TIMERS},
13110 : : #endif
13111 : : #ifdef _SC_TIMER_MAX
13112 : : {"SC_TIMER_MAX", _SC_TIMER_MAX},
13113 : : #endif
13114 : : #ifdef _SC_TTY_NAME_MAX
13115 : : {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
13116 : : #endif
13117 : : #ifdef _SC_TZNAME_MAX
13118 : : {"SC_TZNAME_MAX", _SC_TZNAME_MAX},
13119 : : #endif
13120 : : #ifdef _SC_T_IOV_MAX
13121 : : {"SC_T_IOV_MAX", _SC_T_IOV_MAX},
13122 : : #endif
13123 : : #ifdef _SC_UCHAR_MAX
13124 : : {"SC_UCHAR_MAX", _SC_UCHAR_MAX},
13125 : : #endif
13126 : : #ifdef _SC_UINT_MAX
13127 : : {"SC_UINT_MAX", _SC_UINT_MAX},
13128 : : #endif
13129 : : #ifdef _SC_UIO_MAXIOV
13130 : : {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV},
13131 : : #endif
13132 : : #ifdef _SC_ULONG_MAX
13133 : : {"SC_ULONG_MAX", _SC_ULONG_MAX},
13134 : : #endif
13135 : : #ifdef _SC_USHRT_MAX
13136 : : {"SC_USHRT_MAX", _SC_USHRT_MAX},
13137 : : #endif
13138 : : #ifdef _SC_VERSION
13139 : : {"SC_VERSION", _SC_VERSION},
13140 : : #endif
13141 : : #ifdef _SC_WORD_BIT
13142 : : {"SC_WORD_BIT", _SC_WORD_BIT},
13143 : : #endif
13144 : : #ifdef _SC_XBS5_ILP32_OFF32
13145 : : {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32},
13146 : : #endif
13147 : : #ifdef _SC_XBS5_ILP32_OFFBIG
13148 : : {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG},
13149 : : #endif
13150 : : #ifdef _SC_XBS5_LP64_OFF64
13151 : : {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64},
13152 : : #endif
13153 : : #ifdef _SC_XBS5_LPBIG_OFFBIG
13154 : : {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG},
13155 : : #endif
13156 : : #ifdef _SC_XOPEN_CRYPT
13157 : : {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT},
13158 : : #endif
13159 : : #ifdef _SC_XOPEN_ENH_I18N
13160 : : {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N},
13161 : : #endif
13162 : : #ifdef _SC_XOPEN_LEGACY
13163 : : {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
13164 : : #endif
13165 : : #ifdef _SC_XOPEN_REALTIME
13166 : : {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME},
13167 : : #endif
13168 : : #ifdef _SC_XOPEN_REALTIME_THREADS
13169 : : {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS},
13170 : : #endif
13171 : : #ifdef _SC_XOPEN_SHM
13172 : : {"SC_XOPEN_SHM", _SC_XOPEN_SHM},
13173 : : #endif
13174 : : #ifdef _SC_XOPEN_UNIX
13175 : : {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX},
13176 : : #endif
13177 : : #ifdef _SC_XOPEN_VERSION
13178 : : {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION},
13179 : : #endif
13180 : : #ifdef _SC_XOPEN_XCU_VERSION
13181 : : {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION},
13182 : : #endif
13183 : : #ifdef _SC_XOPEN_XPG2
13184 : : {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2},
13185 : : #endif
13186 : : #ifdef _SC_XOPEN_XPG3
13187 : : {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3},
13188 : : #endif
13189 : : #ifdef _SC_XOPEN_XPG4
13190 : : {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4},
13191 : : #endif
13192 : : #ifdef _SC_MINSIGSTKSZ
13193 : : {"SC_MINSIGSTKSZ", _SC_MINSIGSTKSZ},
13194 : : #endif
13195 : : };
13196 : :
13197 : : static int
13198 : 1 : conv_sysconf_confname(PyObject *arg, int *valuep)
13199 : : {
13200 : 1 : return conv_confname(arg, valuep, posix_constants_sysconf,
13201 : : sizeof(posix_constants_sysconf)
13202 : : / sizeof(struct constdef));
13203 : : }
13204 : :
13205 : :
13206 : : /*[clinic input]
13207 : : os.sysconf -> long
13208 : : name: sysconf_confname
13209 : : /
13210 : :
13211 : : Return an integer-valued system configuration variable.
13212 : : [clinic start generated code]*/
13213 : :
13214 : : static long
13215 : 1 : os_sysconf_impl(PyObject *module, int name)
13216 : : /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
13217 : : {
13218 : : long value;
13219 : :
13220 : 1 : errno = 0;
13221 : 1 : value = sysconf(name);
13222 [ - + - - ]: 1 : if (value == -1 && errno != 0)
13223 : 0 : posix_error();
13224 : 1 : return value;
13225 : : }
13226 : : #endif /* HAVE_SYSCONF */
13227 : :
13228 : :
13229 : : /* This code is used to ensure that the tables of configuration value names
13230 : : * are in sorted order as required by conv_confname(), and also to build
13231 : : * the exported dictionaries that are used to publish information about the
13232 : : * names available on the host platform.
13233 : : *
13234 : : * Sorting the table at runtime ensures that the table is properly ordered
13235 : : * when used, even for platforms we're not able to test on. It also makes
13236 : : * it easier to add additional entries to the tables.
13237 : : */
13238 : :
13239 : : static int
13240 : 14736 : cmp_constdefs(const void *v1, const void *v2)
13241 : : {
13242 : 14736 : const struct constdef *c1 =
13243 : : (const struct constdef *) v1;
13244 : 14736 : const struct constdef *c2 =
13245 : : (const struct constdef *) v2;
13246 : :
13247 : 14736 : return strcmp(c1->name, c2->name);
13248 : : }
13249 : :
13250 : : static int
13251 : 78 : setup_confname_table(struct constdef *table, size_t tablesize,
13252 : : const char *tablename, PyObject *module)
13253 : : {
13254 : 78 : PyObject *d = NULL;
13255 : : size_t i;
13256 : :
13257 : 78 : qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
13258 : 78 : d = PyDict_New();
13259 [ - + ]: 78 : if (d == NULL)
13260 : 0 : return -1;
13261 : :
13262 [ + + ]: 4784 : for (i=0; i < tablesize; ++i) {
13263 : 4706 : PyObject *o = PyLong_FromLong(table[i].value);
13264 [ + - - + ]: 4706 : if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
13265 : 0 : Py_XDECREF(o);
13266 : 0 : Py_DECREF(d);
13267 : 0 : return -1;
13268 : : }
13269 : 4706 : Py_DECREF(o);
13270 : : }
13271 : 78 : return PyModule_AddObject(module, tablename, d);
13272 : : }
13273 : :
13274 : : /* Return -1 on failure, 0 on success. */
13275 : : static int
13276 : 26 : setup_confname_tables(PyObject *module)
13277 : : {
13278 : : #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
13279 [ - + ]: 26 : if (setup_confname_table(posix_constants_pathconf,
13280 : : sizeof(posix_constants_pathconf)
13281 : : / sizeof(struct constdef),
13282 : : "pathconf_names", module))
13283 : 0 : return -1;
13284 : : #endif
13285 : : #ifdef HAVE_CONFSTR
13286 [ - + ]: 26 : if (setup_confname_table(posix_constants_confstr,
13287 : : sizeof(posix_constants_confstr)
13288 : : / sizeof(struct constdef),
13289 : : "confstr_names", module))
13290 : 0 : return -1;
13291 : : #endif
13292 : : #ifdef HAVE_SYSCONF
13293 [ - + ]: 26 : if (setup_confname_table(posix_constants_sysconf,
13294 : : sizeof(posix_constants_sysconf)
13295 : : / sizeof(struct constdef),
13296 : : "sysconf_names", module))
13297 : 0 : return -1;
13298 : : #endif
13299 : 26 : return 0;
13300 : : }
13301 : :
13302 : :
13303 : : /*[clinic input]
13304 : : os.abort
13305 : :
13306 : : Abort the interpreter immediately.
13307 : :
13308 : : This function 'dumps core' or otherwise fails in the hardest way possible
13309 : : on the hosting operating system. This function never returns.
13310 : : [clinic start generated code]*/
13311 : :
13312 : : static PyObject *
13313 : 0 : os_abort_impl(PyObject *module)
13314 : : /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
13315 : : {
13316 : 0 : abort();
13317 : : /*NOTREACHED*/
13318 : : #ifndef __clang__
13319 : : /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
13320 : : GCC emits a warning without "return NULL;" (compiler bug?), but Clang
13321 : : is smarter and emits a warning on the return. */
13322 : : Py_FatalError("abort() called from Python code didn't abort!");
13323 : : return NULL;
13324 : : #endif
13325 : : }
13326 : :
13327 : : #ifdef MS_WINDOWS
13328 : : /* Grab ShellExecute dynamically from shell32 */
13329 : : static int has_ShellExecute = -1;
13330 : : static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
13331 : : LPCWSTR, INT);
13332 : : static int
13333 : : check_ShellExecute()
13334 : : {
13335 : : HINSTANCE hShell32;
13336 : :
13337 : : /* only recheck */
13338 : : if (-1 == has_ShellExecute) {
13339 : : Py_BEGIN_ALLOW_THREADS
13340 : : /* Security note: this call is not vulnerable to "DLL hijacking".
13341 : : SHELL32 is part of "KnownDLLs" and so Windows always load
13342 : : the system SHELL32.DLL, even if there is another SHELL32.DLL
13343 : : in the DLL search path. */
13344 : : hShell32 = LoadLibraryW(L"SHELL32");
13345 : : if (hShell32) {
13346 : : *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
13347 : : "ShellExecuteW");
13348 : : has_ShellExecute = Py_ShellExecuteW != NULL;
13349 : : } else {
13350 : : has_ShellExecute = 0;
13351 : : }
13352 : : Py_END_ALLOW_THREADS
13353 : : }
13354 : : return has_ShellExecute;
13355 : : }
13356 : :
13357 : :
13358 : : /*[clinic input]
13359 : : os.startfile
13360 : : filepath: path_t
13361 : : operation: Py_UNICODE = NULL
13362 : : arguments: Py_UNICODE = NULL
13363 : : cwd: path_t(nullable=True) = None
13364 : : show_cmd: int = 1
13365 : :
13366 : : Start a file with its associated application.
13367 : :
13368 : : When "operation" is not specified or "open", this acts like
13369 : : double-clicking the file in Explorer, or giving the file name as an
13370 : : argument to the DOS "start" command: the file is opened with whatever
13371 : : application (if any) its extension is associated.
13372 : : When another "operation" is given, it specifies what should be done with
13373 : : the file. A typical operation is "print".
13374 : :
13375 : : "arguments" is passed to the application, but should be omitted if the
13376 : : file is a document.
13377 : :
13378 : : "cwd" is the working directory for the operation. If "filepath" is
13379 : : relative, it will be resolved against this directory. This argument
13380 : : should usually be an absolute path.
13381 : :
13382 : : "show_cmd" can be used to override the recommended visibility option.
13383 : : See the Windows ShellExecute documentation for values.
13384 : :
13385 : : startfile returns as soon as the associated application is launched.
13386 : : There is no option to wait for the application to close, and no way
13387 : : to retrieve the application's exit status.
13388 : :
13389 : : The filepath is relative to the current directory. If you want to use
13390 : : an absolute path, make sure the first character is not a slash ("/");
13391 : : the underlying Win32 ShellExecute function doesn't work if it is.
13392 : : [clinic start generated code]*/
13393 : :
13394 : : static PyObject *
13395 : : os_startfile_impl(PyObject *module, path_t *filepath,
13396 : : const Py_UNICODE *operation, const Py_UNICODE *arguments,
13397 : : path_t *cwd, int show_cmd)
13398 : : /*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/
13399 : : {
13400 : : HINSTANCE rc;
13401 : :
13402 : : if(!check_ShellExecute()) {
13403 : : /* If the OS doesn't have ShellExecute, return a
13404 : : NotImplementedError. */
13405 : : return PyErr_Format(PyExc_NotImplementedError,
13406 : : "startfile not available on this platform");
13407 : : }
13408 : :
13409 : : if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
13410 : : return NULL;
13411 : : }
13412 : : if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
13413 : : arguments, cwd->object ? cwd->object : Py_None,
13414 : : show_cmd) < 0) {
13415 : : return NULL;
13416 : : }
13417 : :
13418 : : Py_BEGIN_ALLOW_THREADS
13419 : : rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
13420 : : arguments, cwd->wide, show_cmd);
13421 : : Py_END_ALLOW_THREADS
13422 : :
13423 : : if (rc <= (HINSTANCE)32) {
13424 : : win32_error_object("startfile", filepath->object);
13425 : : return NULL;
13426 : : }
13427 : : Py_RETURN_NONE;
13428 : : }
13429 : : #endif /* MS_WINDOWS */
13430 : :
13431 : :
13432 : : #ifdef HAVE_GETLOADAVG
13433 : : /*[clinic input]
13434 : : os.getloadavg
13435 : :
13436 : : Return average recent system load information.
13437 : :
13438 : : Return the number of processes in the system run queue averaged over
13439 : : the last 1, 5, and 15 minutes as a tuple of three floats.
13440 : : Raises OSError if the load average was unobtainable.
13441 : : [clinic start generated code]*/
13442 : :
13443 : : static PyObject *
13444 : 2 : os_getloadavg_impl(PyObject *module)
13445 : : /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
13446 : : {
13447 : : double loadavg[3];
13448 [ - + ]: 2 : if (getloadavg(loadavg, 3)!=3) {
13449 : 0 : PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
13450 : 0 : return NULL;
13451 : : } else
13452 : 2 : return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
13453 : : }
13454 : : #endif /* HAVE_GETLOADAVG */
13455 : :
13456 : :
13457 : : /*[clinic input]
13458 : : os.device_encoding
13459 : : fd: int
13460 : :
13461 : : Return a string describing the encoding of a terminal's file descriptor.
13462 : :
13463 : : The file descriptor must be attached to a terminal.
13464 : : If the device is not a terminal, return None.
13465 : : [clinic start generated code]*/
13466 : :
13467 : : static PyObject *
13468 : 0 : os_device_encoding_impl(PyObject *module, int fd)
13469 : : /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
13470 : : {
13471 : 0 : return _Py_device_encoding(fd);
13472 : : }
13473 : :
13474 : :
13475 : : #ifdef HAVE_SETRESUID
13476 : : /*[clinic input]
13477 : : os.setresuid
13478 : :
13479 : : ruid: uid_t
13480 : : euid: uid_t
13481 : : suid: uid_t
13482 : : /
13483 : :
13484 : : Set the current process's real, effective, and saved user ids.
13485 : : [clinic start generated code]*/
13486 : :
13487 : : static PyObject *
13488 : 0 : os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
13489 : : /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
13490 : : {
13491 [ # # ]: 0 : if (setresuid(ruid, euid, suid) < 0)
13492 : 0 : return posix_error();
13493 : 0 : Py_RETURN_NONE;
13494 : : }
13495 : : #endif /* HAVE_SETRESUID */
13496 : :
13497 : :
13498 : : #ifdef HAVE_SETRESGID
13499 : : /*[clinic input]
13500 : : os.setresgid
13501 : :
13502 : : rgid: gid_t
13503 : : egid: gid_t
13504 : : sgid: gid_t
13505 : : /
13506 : :
13507 : : Set the current process's real, effective, and saved group ids.
13508 : : [clinic start generated code]*/
13509 : :
13510 : : static PyObject *
13511 : 0 : os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
13512 : : /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
13513 : : {
13514 [ # # ]: 0 : if (setresgid(rgid, egid, sgid) < 0)
13515 : 0 : return posix_error();
13516 : 0 : Py_RETURN_NONE;
13517 : : }
13518 : : #endif /* HAVE_SETRESGID */
13519 : :
13520 : :
13521 : : #ifdef HAVE_GETRESUID
13522 : : /*[clinic input]
13523 : : os.getresuid
13524 : :
13525 : : Return a tuple of the current process's real, effective, and saved user ids.
13526 : : [clinic start generated code]*/
13527 : :
13528 : : static PyObject *
13529 : 0 : os_getresuid_impl(PyObject *module)
13530 : : /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
13531 : : {
13532 : : uid_t ruid, euid, suid;
13533 [ # # ]: 0 : if (getresuid(&ruid, &euid, &suid) < 0)
13534 : 0 : return posix_error();
13535 : 0 : return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
13536 : : _PyLong_FromUid(euid),
13537 : : _PyLong_FromUid(suid));
13538 : : }
13539 : : #endif /* HAVE_GETRESUID */
13540 : :
13541 : :
13542 : : #ifdef HAVE_GETRESGID
13543 : : /*[clinic input]
13544 : : os.getresgid
13545 : :
13546 : : Return a tuple of the current process's real, effective, and saved group ids.
13547 : : [clinic start generated code]*/
13548 : :
13549 : : static PyObject *
13550 : 0 : os_getresgid_impl(PyObject *module)
13551 : : /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
13552 : : {
13553 : : gid_t rgid, egid, sgid;
13554 [ # # ]: 0 : if (getresgid(&rgid, &egid, &sgid) < 0)
13555 : 0 : return posix_error();
13556 : 0 : return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
13557 : : _PyLong_FromGid(egid),
13558 : : _PyLong_FromGid(sgid));
13559 : : }
13560 : : #endif /* HAVE_GETRESGID */
13561 : :
13562 : :
13563 : : #ifdef USE_XATTRS
13564 : : /*[clinic input]
13565 : : os.getxattr
13566 : :
13567 : : path: path_t(allow_fd=True)
13568 : : attribute: path_t
13569 : : *
13570 : : follow_symlinks: bool = True
13571 : :
13572 : : Return the value of extended attribute attribute on path.
13573 : :
13574 : : path may be either a string, a path-like object, or an open file descriptor.
13575 : : If follow_symlinks is False, and the last element of the path is a symbolic
13576 : : link, getxattr will examine the symbolic link itself instead of the file
13577 : : the link points to.
13578 : :
13579 : : [clinic start generated code]*/
13580 : :
13581 : : static PyObject *
13582 : 0 : os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
13583 : : int follow_symlinks)
13584 : : /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
13585 : : {
13586 : : Py_ssize_t i;
13587 : 0 : PyObject *buffer = NULL;
13588 : :
13589 [ # # ]: 0 : if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
13590 : 0 : return NULL;
13591 : :
13592 [ # # ]: 0 : if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
13593 : 0 : return NULL;
13594 : : }
13595 : :
13596 : 0 : for (i = 0; ; i++) {
13597 : : void *ptr;
13598 : : ssize_t result;
13599 : : static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
13600 : 0 : Py_ssize_t buffer_size = buffer_sizes[i];
13601 [ # # ]: 0 : if (!buffer_size) {
13602 : 0 : path_error(path);
13603 : 0 : return NULL;
13604 : : }
13605 : 0 : buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
13606 [ # # ]: 0 : if (!buffer)
13607 : 0 : return NULL;
13608 : 0 : ptr = PyBytes_AS_STRING(buffer);
13609 : :
13610 : 0 : Py_BEGIN_ALLOW_THREADS;
13611 [ # # ]: 0 : if (path->fd >= 0)
13612 : 0 : result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
13613 [ # # ]: 0 : else if (follow_symlinks)
13614 : 0 : result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
13615 : : else
13616 : 0 : result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
13617 : 0 : Py_END_ALLOW_THREADS;
13618 : :
13619 [ # # ]: 0 : if (result < 0) {
13620 : 0 : Py_DECREF(buffer);
13621 [ # # ]: 0 : if (errno == ERANGE)
13622 : 0 : continue;
13623 : 0 : path_error(path);
13624 : 0 : return NULL;
13625 : : }
13626 : :
13627 [ # # ]: 0 : if (result != buffer_size) {
13628 : : /* Can only shrink. */
13629 : 0 : _PyBytes_Resize(&buffer, result);
13630 : : }
13631 : 0 : break;
13632 : : }
13633 : :
13634 : 0 : return buffer;
13635 : : }
13636 : :
13637 : :
13638 : : /*[clinic input]
13639 : : os.setxattr
13640 : :
13641 : : path: path_t(allow_fd=True)
13642 : : attribute: path_t
13643 : : value: Py_buffer
13644 : : flags: int = 0
13645 : : *
13646 : : follow_symlinks: bool = True
13647 : :
13648 : : Set extended attribute attribute on path to value.
13649 : :
13650 : : path may be either a string, a path-like object, or an open file descriptor.
13651 : : If follow_symlinks is False, and the last element of the path is a symbolic
13652 : : link, setxattr will modify the symbolic link itself instead of the file
13653 : : the link points to.
13654 : :
13655 : : [clinic start generated code]*/
13656 : :
13657 : : static PyObject *
13658 : 0 : os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
13659 : : Py_buffer *value, int flags, int follow_symlinks)
13660 : : /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
13661 : : {
13662 : : ssize_t result;
13663 : :
13664 [ # # ]: 0 : if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
13665 : 0 : return NULL;
13666 : :
13667 [ # # ]: 0 : if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
13668 : : value->buf, value->len, flags) < 0) {
13669 : 0 : return NULL;
13670 : : }
13671 : :
13672 : 0 : Py_BEGIN_ALLOW_THREADS;
13673 [ # # ]: 0 : if (path->fd > -1)
13674 : 0 : result = fsetxattr(path->fd, attribute->narrow,
13675 : 0 : value->buf, value->len, flags);
13676 [ # # ]: 0 : else if (follow_symlinks)
13677 : 0 : result = setxattr(path->narrow, attribute->narrow,
13678 : 0 : value->buf, value->len, flags);
13679 : : else
13680 : 0 : result = lsetxattr(path->narrow, attribute->narrow,
13681 : 0 : value->buf, value->len, flags);
13682 : 0 : Py_END_ALLOW_THREADS;
13683 : :
13684 [ # # ]: 0 : if (result) {
13685 : 0 : path_error(path);
13686 : 0 : return NULL;
13687 : : }
13688 : :
13689 : 0 : Py_RETURN_NONE;
13690 : : }
13691 : :
13692 : :
13693 : : /*[clinic input]
13694 : : os.removexattr
13695 : :
13696 : : path: path_t(allow_fd=True)
13697 : : attribute: path_t
13698 : : *
13699 : : follow_symlinks: bool = True
13700 : :
13701 : : Remove extended attribute attribute on path.
13702 : :
13703 : : path may be either a string, a path-like object, or an open file descriptor.
13704 : : If follow_symlinks is False, and the last element of the path is a symbolic
13705 : : link, removexattr will modify the symbolic link itself instead of the file
13706 : : the link points to.
13707 : :
13708 : : [clinic start generated code]*/
13709 : :
13710 : : static PyObject *
13711 : 0 : os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
13712 : : int follow_symlinks)
13713 : : /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
13714 : : {
13715 : : ssize_t result;
13716 : :
13717 [ # # ]: 0 : if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
13718 : 0 : return NULL;
13719 : :
13720 [ # # ]: 0 : if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
13721 : 0 : return NULL;
13722 : : }
13723 : :
13724 : 0 : Py_BEGIN_ALLOW_THREADS;
13725 [ # # ]: 0 : if (path->fd > -1)
13726 : 0 : result = fremovexattr(path->fd, attribute->narrow);
13727 [ # # ]: 0 : else if (follow_symlinks)
13728 : 0 : result = removexattr(path->narrow, attribute->narrow);
13729 : : else
13730 : 0 : result = lremovexattr(path->narrow, attribute->narrow);
13731 : 0 : Py_END_ALLOW_THREADS;
13732 : :
13733 [ # # ]: 0 : if (result) {
13734 : 0 : return path_error(path);
13735 : : }
13736 : :
13737 : 0 : Py_RETURN_NONE;
13738 : : }
13739 : :
13740 : :
13741 : : /*[clinic input]
13742 : : os.listxattr
13743 : :
13744 : : path: path_t(allow_fd=True, nullable=True) = None
13745 : : *
13746 : : follow_symlinks: bool = True
13747 : :
13748 : : Return a list of extended attributes on path.
13749 : :
13750 : : path may be either None, a string, a path-like object, or an open file descriptor.
13751 : : if path is None, listxattr will examine the current directory.
13752 : : If follow_symlinks is False, and the last element of the path is a symbolic
13753 : : link, listxattr will examine the symbolic link itself instead of the file
13754 : : the link points to.
13755 : : [clinic start generated code]*/
13756 : :
13757 : : static PyObject *
13758 : 0 : os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
13759 : : /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
13760 : : {
13761 : : Py_ssize_t i;
13762 : 0 : PyObject *result = NULL;
13763 : : const char *name;
13764 : 0 : char *buffer = NULL;
13765 : :
13766 [ # # ]: 0 : if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
13767 : 0 : goto exit;
13768 : :
13769 [ # # ]: 0 : if (PySys_Audit("os.listxattr", "(O)",
13770 [ # # ]: 0 : path->object ? path->object : Py_None) < 0) {
13771 : 0 : return NULL;
13772 : : }
13773 : :
13774 [ # # ]: 0 : name = path->narrow ? path->narrow : ".";
13775 : :
13776 : 0 : for (i = 0; ; i++) {
13777 : : const char *start, *trace, *end;
13778 : : ssize_t length;
13779 : : static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
13780 : 0 : Py_ssize_t buffer_size = buffer_sizes[i];
13781 [ # # ]: 0 : if (!buffer_size) {
13782 : : /* ERANGE */
13783 : 0 : path_error(path);
13784 : 0 : break;
13785 : : }
13786 : 0 : buffer = PyMem_Malloc(buffer_size);
13787 [ # # ]: 0 : if (!buffer) {
13788 : 0 : PyErr_NoMemory();
13789 : 0 : break;
13790 : : }
13791 : :
13792 : 0 : Py_BEGIN_ALLOW_THREADS;
13793 [ # # ]: 0 : if (path->fd > -1)
13794 : 0 : length = flistxattr(path->fd, buffer, buffer_size);
13795 [ # # ]: 0 : else if (follow_symlinks)
13796 : 0 : length = listxattr(name, buffer, buffer_size);
13797 : : else
13798 : 0 : length = llistxattr(name, buffer, buffer_size);
13799 : 0 : Py_END_ALLOW_THREADS;
13800 : :
13801 [ # # ]: 0 : if (length < 0) {
13802 [ # # ]: 0 : if (errno == ERANGE) {
13803 : 0 : PyMem_Free(buffer);
13804 : 0 : buffer = NULL;
13805 : 0 : continue;
13806 : : }
13807 : 0 : path_error(path);
13808 : 0 : break;
13809 : : }
13810 : :
13811 : 0 : result = PyList_New(0);
13812 [ # # ]: 0 : if (!result) {
13813 : 0 : goto exit;
13814 : : }
13815 : :
13816 : 0 : end = buffer + length;
13817 [ # # ]: 0 : for (trace = start = buffer; trace != end; trace++) {
13818 [ # # ]: 0 : if (!*trace) {
13819 : : int error;
13820 : 0 : PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
13821 : : trace - start);
13822 [ # # ]: 0 : if (!attribute) {
13823 : 0 : Py_SETREF(result, NULL);
13824 : 0 : goto exit;
13825 : : }
13826 : 0 : error = PyList_Append(result, attribute);
13827 : 0 : Py_DECREF(attribute);
13828 [ # # ]: 0 : if (error) {
13829 : 0 : Py_SETREF(result, NULL);
13830 : 0 : goto exit;
13831 : : }
13832 : 0 : start = trace + 1;
13833 : : }
13834 : : }
13835 : 0 : break;
13836 : : }
13837 : 0 : exit:
13838 [ # # ]: 0 : if (buffer)
13839 : 0 : PyMem_Free(buffer);
13840 : 0 : return result;
13841 : : }
13842 : : #endif /* USE_XATTRS */
13843 : :
13844 : :
13845 : : /*[clinic input]
13846 : : os.urandom
13847 : :
13848 : : size: Py_ssize_t
13849 : : /
13850 : :
13851 : : Return a bytes object containing random bytes suitable for cryptographic use.
13852 : : [clinic start generated code]*/
13853 : :
13854 : : static PyObject *
13855 : 0 : os_urandom_impl(PyObject *module, Py_ssize_t size)
13856 : : /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
13857 : : {
13858 : : PyObject *bytes;
13859 : : int result;
13860 : :
13861 [ # # ]: 0 : if (size < 0)
13862 : 0 : return PyErr_Format(PyExc_ValueError,
13863 : : "negative argument not allowed");
13864 : 0 : bytes = PyBytes_FromStringAndSize(NULL, size);
13865 [ # # ]: 0 : if (bytes == NULL)
13866 : 0 : return NULL;
13867 : :
13868 : 0 : result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
13869 [ # # ]: 0 : if (result == -1) {
13870 : 0 : Py_DECREF(bytes);
13871 : 0 : return NULL;
13872 : : }
13873 : 0 : return bytes;
13874 : : }
13875 : :
13876 : : #ifdef HAVE_MEMFD_CREATE
13877 : : /*[clinic input]
13878 : : os.memfd_create
13879 : :
13880 : : name: FSConverter
13881 : : flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
13882 : :
13883 : : [clinic start generated code]*/
13884 : :
13885 : : static PyObject *
13886 : 0 : os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
13887 : : /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
13888 : : {
13889 : : int fd;
13890 : 0 : const char *bytes = PyBytes_AS_STRING(name);
13891 : 0 : Py_BEGIN_ALLOW_THREADS
13892 : 0 : fd = memfd_create(bytes, flags);
13893 : 0 : Py_END_ALLOW_THREADS
13894 [ # # ]: 0 : if (fd == -1) {
13895 : 0 : return PyErr_SetFromErrno(PyExc_OSError);
13896 : : }
13897 : 0 : return PyLong_FromLong(fd);
13898 : : }
13899 : : #endif
13900 : :
13901 : : #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
13902 : : /*[clinic input]
13903 : : os.eventfd
13904 : :
13905 : : initval: unsigned_int
13906 : : flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
13907 : :
13908 : : Creates and returns an event notification file descriptor.
13909 : : [clinic start generated code]*/
13910 : :
13911 : : static PyObject *
13912 : 0 : os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
13913 : : /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
13914 : :
13915 : : {
13916 : : /* initval is limited to uint32_t, internal counter is uint64_t */
13917 : : int fd;
13918 : 0 : Py_BEGIN_ALLOW_THREADS
13919 : 0 : fd = eventfd(initval, flags);
13920 : 0 : Py_END_ALLOW_THREADS
13921 [ # # ]: 0 : if (fd == -1) {
13922 : 0 : return PyErr_SetFromErrno(PyExc_OSError);
13923 : : }
13924 : 0 : return PyLong_FromLong(fd);
13925 : : }
13926 : :
13927 : : /*[clinic input]
13928 : : os.eventfd_read
13929 : :
13930 : : fd: fildes
13931 : :
13932 : : Read eventfd value
13933 : : [clinic start generated code]*/
13934 : :
13935 : : static PyObject *
13936 : 0 : os_eventfd_read_impl(PyObject *module, int fd)
13937 : : /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
13938 : : {
13939 : : eventfd_t value;
13940 : : int result;
13941 : 0 : Py_BEGIN_ALLOW_THREADS
13942 : 0 : result = eventfd_read(fd, &value);
13943 : 0 : Py_END_ALLOW_THREADS
13944 [ # # ]: 0 : if (result == -1) {
13945 : 0 : return PyErr_SetFromErrno(PyExc_OSError);
13946 : : }
13947 : 0 : return PyLong_FromUnsignedLongLong(value);
13948 : : }
13949 : :
13950 : : /*[clinic input]
13951 : : os.eventfd_write
13952 : :
13953 : : fd: fildes
13954 : : value: unsigned_long_long
13955 : :
13956 : : Write eventfd value.
13957 : : [clinic start generated code]*/
13958 : :
13959 : : static PyObject *
13960 : 0 : os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
13961 : : /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
13962 : : {
13963 : : int result;
13964 : 0 : Py_BEGIN_ALLOW_THREADS
13965 : 0 : result = eventfd_write(fd, value);
13966 : 0 : Py_END_ALLOW_THREADS
13967 [ # # ]: 0 : if (result == -1) {
13968 : 0 : return PyErr_SetFromErrno(PyExc_OSError);
13969 : : }
13970 : 0 : Py_RETURN_NONE;
13971 : : }
13972 : : #endif /* HAVE_EVENTFD && EFD_CLOEXEC */
13973 : :
13974 : : /* Terminal size querying */
13975 : :
13976 : : PyDoc_STRVAR(TerminalSize_docstring,
13977 : : "A tuple of (columns, lines) for holding terminal window size");
13978 : :
13979 : : static PyStructSequence_Field TerminalSize_fields[] = {
13980 : : {"columns", "width of the terminal window in characters"},
13981 : : {"lines", "height of the terminal window in characters"},
13982 : : {NULL, NULL}
13983 : : };
13984 : :
13985 : : static PyStructSequence_Desc TerminalSize_desc = {
13986 : : "os.terminal_size",
13987 : : TerminalSize_docstring,
13988 : : TerminalSize_fields,
13989 : : 2,
13990 : : };
13991 : :
13992 : : #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
13993 : : /*[clinic input]
13994 : : os.get_terminal_size
13995 : :
13996 : : fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
13997 : : /
13998 : :
13999 : : Return the size of the terminal window as (columns, lines).
14000 : :
14001 : : The optional argument fd (default standard output) specifies
14002 : : which file descriptor should be queried.
14003 : :
14004 : : If the file descriptor is not connected to a terminal, an OSError
14005 : : is thrown.
14006 : :
14007 : : This function will only be defined if an implementation is
14008 : : available for this system.
14009 : :
14010 : : shutil.get_terminal_size is the high-level function which should
14011 : : normally be used, os.get_terminal_size is the low-level implementation.
14012 : : [clinic start generated code]*/
14013 : :
14014 : : static PyObject *
14015 : 10 : os_get_terminal_size_impl(PyObject *module, int fd)
14016 : : /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
14017 : : {
14018 : : int columns, lines;
14019 : : PyObject *termsize;
14020 : :
14021 : : /* Under some conditions stdout may not be connected and
14022 : : * fileno(stdout) may point to an invalid file descriptor. For example
14023 : : * GUI apps don't have valid standard streams by default.
14024 : : *
14025 : : * If this happens, and the optional fd argument is not present,
14026 : : * the ioctl below will fail returning EBADF. This is what we want.
14027 : : */
14028 : :
14029 : : #ifdef TERMSIZE_USE_IOCTL
14030 : : {
14031 : : struct winsize w;
14032 [ - + ]: 10 : if (ioctl(fd, TIOCGWINSZ, &w))
14033 : 0 : return PyErr_SetFromErrno(PyExc_OSError);
14034 : 10 : columns = w.ws_col;
14035 : 10 : lines = w.ws_row;
14036 : : }
14037 : : #endif /* TERMSIZE_USE_IOCTL */
14038 : :
14039 : : #ifdef TERMSIZE_USE_CONIO
14040 : : {
14041 : : HANDLE handle;
14042 : : CONSOLE_SCREEN_BUFFER_INFO csbi;
14043 : : handle = _Py_get_osfhandle(fd);
14044 : : if (handle == INVALID_HANDLE_VALUE)
14045 : : return NULL;
14046 : :
14047 : : if (!GetConsoleScreenBufferInfo(handle, &csbi))
14048 : : return PyErr_SetFromWindowsErr(0);
14049 : :
14050 : : columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
14051 : : lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
14052 : : }
14053 : : #endif /* TERMSIZE_USE_CONIO */
14054 : :
14055 : 10 : PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
14056 : 10 : termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
14057 [ - + ]: 10 : if (termsize == NULL)
14058 : 0 : return NULL;
14059 : 10 : PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
14060 : 10 : PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
14061 [ - + ]: 10 : if (PyErr_Occurred()) {
14062 : 0 : Py_DECREF(termsize);
14063 : 0 : return NULL;
14064 : : }
14065 : 10 : return termsize;
14066 : : }
14067 : : #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
14068 : :
14069 : :
14070 : : /*[clinic input]
14071 : : os.cpu_count
14072 : :
14073 : : Return the number of CPUs in the system; return None if indeterminable.
14074 : :
14075 : : This number is not equivalent to the number of CPUs the current process can
14076 : : use. The number of usable CPUs can be obtained with
14077 : : ``len(os.sched_getaffinity(0))``
14078 : : [clinic start generated code]*/
14079 : :
14080 : : static PyObject *
14081 : 0 : os_cpu_count_impl(PyObject *module)
14082 : : /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
14083 : : {
14084 : 0 : int ncpu = 0;
14085 : : #ifdef MS_WINDOWS
14086 : : #ifdef MS_WINDOWS_DESKTOP
14087 : : ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
14088 : : #endif
14089 : : #elif defined(__hpux)
14090 : : ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
14091 : : #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
14092 : 0 : ncpu = sysconf(_SC_NPROCESSORS_ONLN);
14093 : : #elif defined(__VXWORKS__)
14094 : : ncpu = _Py_popcount32(vxCpuEnabledGet());
14095 : : #elif defined(__DragonFly__) || \
14096 : : defined(__OpenBSD__) || \
14097 : : defined(__FreeBSD__) || \
14098 : : defined(__NetBSD__) || \
14099 : : defined(__APPLE__)
14100 : : int mib[2];
14101 : : size_t len = sizeof(ncpu);
14102 : : mib[0] = CTL_HW;
14103 : : mib[1] = HW_NCPU;
14104 : : if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
14105 : : ncpu = 0;
14106 : : #endif
14107 [ # # ]: 0 : if (ncpu >= 1)
14108 : 0 : return PyLong_FromLong(ncpu);
14109 : : else
14110 : 0 : Py_RETURN_NONE;
14111 : : }
14112 : :
14113 : :
14114 : : /*[clinic input]
14115 : : os.get_inheritable -> bool
14116 : :
14117 : : fd: int
14118 : : /
14119 : :
14120 : : Get the close-on-exe flag of the specified file descriptor.
14121 : : [clinic start generated code]*/
14122 : :
14123 : : static int
14124 : 0 : os_get_inheritable_impl(PyObject *module, int fd)
14125 : : /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
14126 : : {
14127 : : int return_value;
14128 : : _Py_BEGIN_SUPPRESS_IPH
14129 : 0 : return_value = _Py_get_inheritable(fd);
14130 : : _Py_END_SUPPRESS_IPH
14131 : 0 : return return_value;
14132 : : }
14133 : :
14134 : :
14135 : : /*[clinic input]
14136 : : os.set_inheritable
14137 : : fd: int
14138 : : inheritable: int
14139 : : /
14140 : :
14141 : : Set the inheritable flag of the specified file descriptor.
14142 : : [clinic start generated code]*/
14143 : :
14144 : : static PyObject *
14145 : 0 : os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
14146 : : /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
14147 : : {
14148 : : int result;
14149 : :
14150 : : _Py_BEGIN_SUPPRESS_IPH
14151 : 0 : result = _Py_set_inheritable(fd, inheritable, NULL);
14152 : : _Py_END_SUPPRESS_IPH
14153 [ # # ]: 0 : if (result < 0)
14154 : 0 : return NULL;
14155 : 0 : Py_RETURN_NONE;
14156 : : }
14157 : :
14158 : :
14159 : : #ifdef MS_WINDOWS
14160 : : #ifndef HANDLE_FLAG_INHERIT
14161 : : #define HANDLE_FLAG_INHERIT 0x00000001
14162 : : #endif
14163 : :
14164 : : /*[clinic input]
14165 : : os.get_handle_inheritable -> bool
14166 : : handle: intptr_t
14167 : : /
14168 : :
14169 : : Get the close-on-exe flag of the specified file descriptor.
14170 : : [clinic start generated code]*/
14171 : :
14172 : : static int
14173 : : os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
14174 : : /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
14175 : : {
14176 : : DWORD flags;
14177 : :
14178 : : if (!GetHandleInformation((HANDLE)handle, &flags)) {
14179 : : PyErr_SetFromWindowsErr(0);
14180 : : return -1;
14181 : : }
14182 : :
14183 : : return flags & HANDLE_FLAG_INHERIT;
14184 : : }
14185 : :
14186 : :
14187 : : /*[clinic input]
14188 : : os.set_handle_inheritable
14189 : : handle: intptr_t
14190 : : inheritable: bool
14191 : : /
14192 : :
14193 : : Set the inheritable flag of the specified handle.
14194 : : [clinic start generated code]*/
14195 : :
14196 : : static PyObject *
14197 : : os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
14198 : : int inheritable)
14199 : : /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
14200 : : {
14201 : : DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
14202 : : if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
14203 : : PyErr_SetFromWindowsErr(0);
14204 : : return NULL;
14205 : : }
14206 : : Py_RETURN_NONE;
14207 : : }
14208 : : #endif /* MS_WINDOWS */
14209 : :
14210 : : /*[clinic input]
14211 : : os.get_blocking -> bool
14212 : : fd: int
14213 : : /
14214 : :
14215 : : Get the blocking mode of the file descriptor.
14216 : :
14217 : : Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
14218 : : [clinic start generated code]*/
14219 : :
14220 : : static int
14221 : 0 : os_get_blocking_impl(PyObject *module, int fd)
14222 : : /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
14223 : : {
14224 : : int blocking;
14225 : :
14226 : : _Py_BEGIN_SUPPRESS_IPH
14227 : 0 : blocking = _Py_get_blocking(fd);
14228 : : _Py_END_SUPPRESS_IPH
14229 : 0 : return blocking;
14230 : : }
14231 : :
14232 : : /*[clinic input]
14233 : : os.set_blocking
14234 : : fd: int
14235 : : blocking: bool
14236 : : /
14237 : :
14238 : : Set the blocking mode of the specified file descriptor.
14239 : :
14240 : : Set the O_NONBLOCK flag if blocking is False,
14241 : : clear the O_NONBLOCK flag otherwise.
14242 : : [clinic start generated code]*/
14243 : :
14244 : : static PyObject *
14245 : 0 : os_set_blocking_impl(PyObject *module, int fd, int blocking)
14246 : : /*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
14247 : : {
14248 : : int result;
14249 : :
14250 : : _Py_BEGIN_SUPPRESS_IPH
14251 : 0 : result = _Py_set_blocking(fd, blocking);
14252 : : _Py_END_SUPPRESS_IPH
14253 [ # # ]: 0 : if (result < 0)
14254 : 0 : return NULL;
14255 : 0 : Py_RETURN_NONE;
14256 : : }
14257 : :
14258 : :
14259 : : /*[clinic input]
14260 : : class os.DirEntry "DirEntry *" "DirEntryType"
14261 : : [clinic start generated code]*/
14262 : : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
14263 : :
14264 : : typedef struct {
14265 : : PyObject_HEAD
14266 : : PyObject *name;
14267 : : PyObject *path;
14268 : : PyObject *stat;
14269 : : PyObject *lstat;
14270 : : #ifdef MS_WINDOWS
14271 : : struct _Py_stat_struct win32_lstat;
14272 : : uint64_t win32_file_index;
14273 : : int got_file_index;
14274 : : #else /* POSIX */
14275 : : #ifdef HAVE_DIRENT_D_TYPE
14276 : : unsigned char d_type;
14277 : : #endif
14278 : : ino_t d_ino;
14279 : : int dir_fd;
14280 : : #endif
14281 : : } DirEntry;
14282 : :
14283 : : static void
14284 : 1540 : DirEntry_dealloc(DirEntry *entry)
14285 : : {
14286 : 1540 : PyTypeObject *tp = Py_TYPE(entry);
14287 : 1540 : Py_XDECREF(entry->name);
14288 : 1540 : Py_XDECREF(entry->path);
14289 : 1540 : Py_XDECREF(entry->stat);
14290 : 1540 : Py_XDECREF(entry->lstat);
14291 : 1540 : freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
14292 : 1540 : free_func(entry);
14293 : 1540 : Py_DECREF(tp);
14294 : 1540 : }
14295 : :
14296 : : /* Forward reference */
14297 : : static int
14298 : : DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
14299 : : int follow_symlinks, unsigned short mode_bits);
14300 : :
14301 : : /*[clinic input]
14302 : : os.DirEntry.is_symlink -> bool
14303 : : defining_class: defining_class
14304 : : /
14305 : :
14306 : : Return True if the entry is a symbolic link; cached per entry.
14307 : : [clinic start generated code]*/
14308 : :
14309 : : static int
14310 : 0 : os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
14311 : : /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
14312 : : {
14313 : : #ifdef MS_WINDOWS
14314 : : return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
14315 : : #elif defined(HAVE_DIRENT_D_TYPE)
14316 : : /* POSIX */
14317 [ # # ]: 0 : if (self->d_type != DT_UNKNOWN)
14318 : 0 : return self->d_type == DT_LNK;
14319 : : else
14320 : 0 : return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
14321 : : #else
14322 : : /* POSIX without d_type */
14323 : : return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
14324 : : #endif
14325 : : }
14326 : :
14327 : : /*[clinic input]
14328 : : os.DirEntry.is_junction -> bool
14329 : : defining_class: defining_class
14330 : : /
14331 : :
14332 : : Return True if the entry is a junction; cached per entry.
14333 : : [clinic start generated code]*/
14334 : :
14335 : : static int
14336 : 0 : os_DirEntry_is_junction_impl(DirEntry *self, PyTypeObject *defining_class)
14337 : : /*[clinic end generated code: output=7061a07b0ef2cd1f input=475cd36fb7d4723f]*/
14338 : : {
14339 : : #ifdef MS_WINDOWS
14340 : : return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
14341 : : #else
14342 : 0 : return 0;
14343 : : #endif
14344 : : }
14345 : :
14346 : : static PyObject *
14347 : 0 : DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
14348 : : {
14349 : : int result;
14350 : : STRUCT_STAT st;
14351 : : PyObject *ub;
14352 : :
14353 : : #ifdef MS_WINDOWS
14354 : : if (!PyUnicode_FSDecoder(self->path, &ub))
14355 : : return NULL;
14356 : : wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
14357 : : Py_DECREF(ub);
14358 : : #else /* POSIX */
14359 [ # # ]: 0 : if (!PyUnicode_FSConverter(self->path, &ub))
14360 : 0 : return NULL;
14361 : 0 : const char *path = PyBytes_AS_STRING(ub);
14362 [ # # ]: 0 : if (self->dir_fd != DEFAULT_DIR_FD) {
14363 : : #ifdef HAVE_FSTATAT
14364 : : if (HAVE_FSTATAT_RUNTIME) {
14365 : 0 : Py_BEGIN_ALLOW_THREADS
14366 [ # # ]: 0 : result = fstatat(self->dir_fd, path, &st,
14367 : : follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
14368 : 0 : Py_END_ALLOW_THREADS
14369 : : } else
14370 : :
14371 : : #endif /* HAVE_FSTATAT */
14372 : : {
14373 : : Py_DECREF(ub);
14374 : : PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
14375 : : return NULL;
14376 : : }
14377 : : }
14378 : : else
14379 : : #endif
14380 : : {
14381 : 0 : Py_BEGIN_ALLOW_THREADS
14382 [ # # ]: 0 : if (follow_symlinks) {
14383 : 0 : result = STAT(path, &st);
14384 : : }
14385 : : else {
14386 : 0 : result = LSTAT(path, &st);
14387 : : }
14388 : 0 : Py_END_ALLOW_THREADS
14389 : : }
14390 : : #if defined(MS_WINDOWS)
14391 : : PyMem_Free(path);
14392 : : #else
14393 : 0 : Py_DECREF(ub);
14394 : : #endif
14395 : :
14396 [ # # ]: 0 : if (result != 0)
14397 : 0 : return path_object_error(self->path);
14398 : :
14399 : 0 : return _pystat_fromstructstat(module, &st);
14400 : : }
14401 : :
14402 : : static PyObject *
14403 : 0 : DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
14404 : : {
14405 [ # # ]: 0 : if (!self->lstat) {
14406 : 0 : PyObject *module = PyType_GetModule(defining_class);
14407 : : #ifdef MS_WINDOWS
14408 : : self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
14409 : : #else /* POSIX */
14410 : 0 : self->lstat = DirEntry_fetch_stat(module, self, 0);
14411 : : #endif
14412 : : }
14413 : 0 : return Py_XNewRef(self->lstat);
14414 : : }
14415 : :
14416 : : /*[clinic input]
14417 : : os.DirEntry.stat
14418 : : defining_class: defining_class
14419 : : /
14420 : : *
14421 : : follow_symlinks: bool = True
14422 : :
14423 : : Return stat_result object for the entry; cached per entry.
14424 : : [clinic start generated code]*/
14425 : :
14426 : : static PyObject *
14427 : 0 : os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
14428 : : int follow_symlinks)
14429 : : /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
14430 : : {
14431 [ # # ]: 0 : if (!follow_symlinks) {
14432 : 0 : return DirEntry_get_lstat(defining_class, self);
14433 : : }
14434 : :
14435 [ # # ]: 0 : if (!self->stat) {
14436 : 0 : int result = os_DirEntry_is_symlink_impl(self, defining_class);
14437 [ # # ]: 0 : if (result == -1) {
14438 : 0 : return NULL;
14439 : : }
14440 [ # # ]: 0 : if (result) {
14441 : 0 : PyObject *module = PyType_GetModule(defining_class);
14442 : 0 : self->stat = DirEntry_fetch_stat(module, self, 1);
14443 : : }
14444 : : else {
14445 : 0 : self->stat = DirEntry_get_lstat(defining_class, self);
14446 : : }
14447 : : }
14448 : :
14449 : 0 : return Py_XNewRef(self->stat);
14450 : : }
14451 : :
14452 : : /* Set exception and return -1 on error, 0 for False, 1 for True */
14453 : : static int
14454 : 1540 : DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
14455 : : int follow_symlinks, unsigned short mode_bits)
14456 : : {
14457 : 1540 : PyObject *stat = NULL;
14458 : 1540 : PyObject *st_mode = NULL;
14459 : : long mode;
14460 : : int result;
14461 : : #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
14462 : : int is_symlink;
14463 : : int need_stat;
14464 : : #endif
14465 : : #ifdef MS_WINDOWS
14466 : : unsigned long dir_bits;
14467 : : #endif
14468 : :
14469 : : #ifdef MS_WINDOWS
14470 : : is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
14471 : : need_stat = follow_symlinks && is_symlink;
14472 : : #elif defined(HAVE_DIRENT_D_TYPE)
14473 : 1540 : is_symlink = self->d_type == DT_LNK;
14474 [ + - + - : 1540 : need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
- + ]
14475 : : #endif
14476 : :
14477 : : #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
14478 [ - + ]: 1540 : if (need_stat) {
14479 : : #endif
14480 : 0 : stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
14481 [ # # ]: 0 : if (!stat) {
14482 [ # # ]: 0 : if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
14483 : : /* If file doesn't exist (anymore), then return False
14484 : : (i.e., say it's not a file/directory) */
14485 : 0 : PyErr_Clear();
14486 : 0 : return 0;
14487 : : }
14488 : 0 : goto error;
14489 : : }
14490 : 0 : _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
14491 : 0 : st_mode = PyObject_GetAttr(stat, state->st_mode);
14492 [ # # ]: 0 : if (!st_mode)
14493 : 0 : goto error;
14494 : :
14495 : 0 : mode = PyLong_AsLong(st_mode);
14496 [ # # # # ]: 0 : if (mode == -1 && PyErr_Occurred())
14497 : 0 : goto error;
14498 [ # # ]: 0 : Py_CLEAR(st_mode);
14499 [ # # ]: 0 : Py_CLEAR(stat);
14500 : 0 : result = (mode & S_IFMT) == mode_bits;
14501 : : #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
14502 : : }
14503 [ - + ]: 1540 : else if (is_symlink) {
14504 : : assert(mode_bits != S_IFLNK);
14505 : 0 : result = 0;
14506 : : }
14507 : : else {
14508 : : assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
14509 : : #ifdef MS_WINDOWS
14510 : : dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
14511 : : if (mode_bits == S_IFDIR)
14512 : : result = dir_bits != 0;
14513 : : else
14514 : : result = dir_bits == 0;
14515 : : #else /* POSIX */
14516 [ + - ]: 1540 : if (mode_bits == S_IFDIR)
14517 : 1540 : result = self->d_type == DT_DIR;
14518 : : else
14519 : 0 : result = self->d_type == DT_REG;
14520 : : #endif
14521 : : }
14522 : : #endif
14523 : :
14524 : 1540 : return result;
14525 : :
14526 : 0 : error:
14527 : 0 : Py_XDECREF(st_mode);
14528 : 0 : Py_XDECREF(stat);
14529 : 0 : return -1;
14530 : : }
14531 : :
14532 : : /*[clinic input]
14533 : : os.DirEntry.is_dir -> bool
14534 : : defining_class: defining_class
14535 : : /
14536 : : *
14537 : : follow_symlinks: bool = True
14538 : :
14539 : : Return True if the entry is a directory; cached per entry.
14540 : : [clinic start generated code]*/
14541 : :
14542 : : static int
14543 : 1540 : os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
14544 : : int follow_symlinks)
14545 : : /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
14546 : : {
14547 : 1540 : return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
14548 : : }
14549 : :
14550 : : /*[clinic input]
14551 : : os.DirEntry.is_file -> bool
14552 : : defining_class: defining_class
14553 : : /
14554 : : *
14555 : : follow_symlinks: bool = True
14556 : :
14557 : : Return True if the entry is a file; cached per entry.
14558 : : [clinic start generated code]*/
14559 : :
14560 : : static int
14561 : 0 : os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
14562 : : int follow_symlinks)
14563 : : /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
14564 : : {
14565 : 0 : return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
14566 : : }
14567 : :
14568 : : /*[clinic input]
14569 : : os.DirEntry.inode
14570 : :
14571 : : Return inode of the entry; cached per entry.
14572 : : [clinic start generated code]*/
14573 : :
14574 : : static PyObject *
14575 : 0 : os_DirEntry_inode_impl(DirEntry *self)
14576 : : /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
14577 : : {
14578 : : #ifdef MS_WINDOWS
14579 : : if (!self->got_file_index) {
14580 : : PyObject *unicode;
14581 : : STRUCT_STAT stat;
14582 : : int result;
14583 : :
14584 : : if (!PyUnicode_FSDecoder(self->path, &unicode))
14585 : : return NULL;
14586 : : wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
14587 : : Py_DECREF(unicode);
14588 : : result = LSTAT(path, &stat);
14589 : : PyMem_Free(path);
14590 : :
14591 : : if (result != 0)
14592 : : return path_object_error(self->path);
14593 : :
14594 : : self->win32_file_index = stat.st_ino;
14595 : : self->got_file_index = 1;
14596 : : }
14597 : : static_assert(sizeof(unsigned long long) >= sizeof(self->win32_file_index),
14598 : : "DirEntry.win32_file_index is larger than unsigned long long");
14599 : : return PyLong_FromUnsignedLongLong(self->win32_file_index);
14600 : : #else /* POSIX */
14601 : : static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
14602 : : "DirEntry.d_ino is larger than unsigned long long");
14603 : 0 : return PyLong_FromUnsignedLongLong(self->d_ino);
14604 : : #endif
14605 : : }
14606 : :
14607 : : static PyObject *
14608 : 0 : DirEntry_repr(DirEntry *self)
14609 : : {
14610 : 0 : return PyUnicode_FromFormat("<DirEntry %R>", self->name);
14611 : : }
14612 : :
14613 : : /*[clinic input]
14614 : : os.DirEntry.__fspath__
14615 : :
14616 : : Returns the path for the entry.
14617 : : [clinic start generated code]*/
14618 : :
14619 : : static PyObject *
14620 : 0 : os_DirEntry___fspath___impl(DirEntry *self)
14621 : : /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
14622 : : {
14623 : 0 : return Py_NewRef(self->path);
14624 : : }
14625 : :
14626 : : static PyMemberDef DirEntry_members[] = {
14627 : : {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
14628 : : "the entry's base filename, relative to scandir() \"path\" argument"},
14629 : : {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
14630 : : "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
14631 : : {NULL}
14632 : : };
14633 : :
14634 : : #include "clinic/posixmodule.c.h"
14635 : :
14636 : : static PyMethodDef DirEntry_methods[] = {
14637 : : OS_DIRENTRY_IS_DIR_METHODDEF
14638 : : OS_DIRENTRY_IS_FILE_METHODDEF
14639 : : OS_DIRENTRY_IS_SYMLINK_METHODDEF
14640 : : OS_DIRENTRY_IS_JUNCTION_METHODDEF
14641 : : OS_DIRENTRY_STAT_METHODDEF
14642 : : OS_DIRENTRY_INODE_METHODDEF
14643 : : OS_DIRENTRY___FSPATH___METHODDEF
14644 : : {"__class_getitem__", Py_GenericAlias,
14645 : : METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
14646 : : {NULL}
14647 : : };
14648 : :
14649 : : static PyType_Slot DirEntryType_slots[] = {
14650 : : {Py_tp_dealloc, DirEntry_dealloc},
14651 : : {Py_tp_repr, DirEntry_repr},
14652 : : {Py_tp_methods, DirEntry_methods},
14653 : : {Py_tp_members, DirEntry_members},
14654 : : {0, 0},
14655 : : };
14656 : :
14657 : : static PyType_Spec DirEntryType_spec = {
14658 : : MODNAME ".DirEntry",
14659 : : sizeof(DirEntry),
14660 : : 0,
14661 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
14662 : : DirEntryType_slots
14663 : : };
14664 : :
14665 : :
14666 : : #ifdef MS_WINDOWS
14667 : :
14668 : : static wchar_t *
14669 : : join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
14670 : : {
14671 : : Py_ssize_t path_len;
14672 : : Py_ssize_t size;
14673 : : wchar_t *result;
14674 : : wchar_t ch;
14675 : :
14676 : : if (!path_wide) { /* Default arg: "." */
14677 : : path_wide = L".";
14678 : : path_len = 1;
14679 : : }
14680 : : else {
14681 : : path_len = wcslen(path_wide);
14682 : : }
14683 : :
14684 : : /* The +1's are for the path separator and the NUL */
14685 : : size = path_len + 1 + wcslen(filename) + 1;
14686 : : result = PyMem_New(wchar_t, size);
14687 : : if (!result) {
14688 : : PyErr_NoMemory();
14689 : : return NULL;
14690 : : }
14691 : : wcscpy(result, path_wide);
14692 : : if (path_len > 0) {
14693 : : ch = result[path_len - 1];
14694 : : if (ch != SEP && ch != ALTSEP && ch != L':')
14695 : : result[path_len++] = SEP;
14696 : : wcscpy(result + path_len, filename);
14697 : : }
14698 : : return result;
14699 : : }
14700 : :
14701 : : static PyObject *
14702 : : DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
14703 : : {
14704 : : DirEntry *entry;
14705 : : BY_HANDLE_FILE_INFORMATION file_info;
14706 : : ULONG reparse_tag;
14707 : : wchar_t *joined_path;
14708 : :
14709 : : PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
14710 : : entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
14711 : : if (!entry)
14712 : : return NULL;
14713 : : entry->name = NULL;
14714 : : entry->path = NULL;
14715 : : entry->stat = NULL;
14716 : : entry->lstat = NULL;
14717 : : entry->got_file_index = 0;
14718 : :
14719 : : entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
14720 : : if (!entry->name)
14721 : : goto error;
14722 : : if (path->narrow) {
14723 : : Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
14724 : : if (!entry->name)
14725 : : goto error;
14726 : : }
14727 : :
14728 : : joined_path = join_path_filenameW(path->wide, dataW->cFileName);
14729 : : if (!joined_path)
14730 : : goto error;
14731 : :
14732 : : entry->path = PyUnicode_FromWideChar(joined_path, -1);
14733 : : PyMem_Free(joined_path);
14734 : : if (!entry->path)
14735 : : goto error;
14736 : : if (path->narrow) {
14737 : : Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
14738 : : if (!entry->path)
14739 : : goto error;
14740 : : }
14741 : :
14742 : : find_data_to_file_info(dataW, &file_info, &reparse_tag);
14743 : : _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
14744 : :
14745 : : return (PyObject *)entry;
14746 : :
14747 : : error:
14748 : : Py_DECREF(entry);
14749 : : return NULL;
14750 : : }
14751 : :
14752 : : #else /* POSIX */
14753 : :
14754 : : static char *
14755 : 1540 : join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
14756 : : {
14757 : : Py_ssize_t path_len;
14758 : : Py_ssize_t size;
14759 : : char *result;
14760 : :
14761 [ - + ]: 1540 : if (!path_narrow) { /* Default arg: "." */
14762 : 0 : path_narrow = ".";
14763 : 0 : path_len = 1;
14764 : : }
14765 : : else {
14766 : 1540 : path_len = strlen(path_narrow);
14767 : : }
14768 : :
14769 [ - + ]: 1540 : if (filename_len == -1)
14770 : 0 : filename_len = strlen(filename);
14771 : :
14772 : : /* The +1's are for the path separator and the NUL */
14773 : 1540 : size = path_len + 1 + filename_len + 1;
14774 [ + - ]: 1540 : result = PyMem_New(char, size);
14775 [ - + ]: 1540 : if (!result) {
14776 : 0 : PyErr_NoMemory();
14777 : 0 : return NULL;
14778 : : }
14779 : 1540 : strcpy(result, path_narrow);
14780 [ + - + - ]: 1540 : if (path_len > 0 && result[path_len - 1] != '/')
14781 : 1540 : result[path_len++] = '/';
14782 : 1540 : strcpy(result + path_len, filename);
14783 : 1540 : return result;
14784 : : }
14785 : :
14786 : : static PyObject *
14787 : 1540 : DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
14788 : : Py_ssize_t name_len, ino_t d_ino
14789 : : #ifdef HAVE_DIRENT_D_TYPE
14790 : : , unsigned char d_type
14791 : : #endif
14792 : : )
14793 : : {
14794 : : DirEntry *entry;
14795 : : char *joined_path;
14796 : :
14797 : 1540 : PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
14798 : 1540 : entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
14799 [ - + ]: 1540 : if (!entry)
14800 : 0 : return NULL;
14801 : 1540 : entry->name = NULL;
14802 : 1540 : entry->path = NULL;
14803 : 1540 : entry->stat = NULL;
14804 : 1540 : entry->lstat = NULL;
14805 : :
14806 [ - + ]: 1540 : if (path->fd != -1) {
14807 : 0 : entry->dir_fd = path->fd;
14808 : 0 : joined_path = NULL;
14809 : : }
14810 : : else {
14811 : 1540 : entry->dir_fd = DEFAULT_DIR_FD;
14812 : 1540 : joined_path = join_path_filename(path->narrow, name, name_len);
14813 [ - + ]: 1540 : if (!joined_path)
14814 : 0 : goto error;
14815 : : }
14816 : :
14817 [ + - + - ]: 1540 : if (!path->narrow || !PyBytes_Check(path->object)) {
14818 : 1540 : entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
14819 [ + - ]: 1540 : if (joined_path)
14820 : 1540 : entry->path = PyUnicode_DecodeFSDefault(joined_path);
14821 : : }
14822 : : else {
14823 : 0 : entry->name = PyBytes_FromStringAndSize(name, name_len);
14824 [ # # ]: 0 : if (joined_path)
14825 : 0 : entry->path = PyBytes_FromString(joined_path);
14826 : : }
14827 : 1540 : PyMem_Free(joined_path);
14828 [ - + ]: 1540 : if (!entry->name)
14829 : 0 : goto error;
14830 : :
14831 [ - + ]: 1540 : if (path->fd != -1) {
14832 : 0 : entry->path = Py_NewRef(entry->name);
14833 : : }
14834 [ - + ]: 1540 : else if (!entry->path)
14835 : 0 : goto error;
14836 : :
14837 : : #ifdef HAVE_DIRENT_D_TYPE
14838 : 1540 : entry->d_type = d_type;
14839 : : #endif
14840 : 1540 : entry->d_ino = d_ino;
14841 : :
14842 : 1540 : return (PyObject *)entry;
14843 : :
14844 : 0 : error:
14845 : 0 : Py_XDECREF(entry);
14846 : 0 : return NULL;
14847 : : }
14848 : :
14849 : : #endif
14850 : :
14851 : :
14852 : : typedef struct {
14853 : : PyObject_HEAD
14854 : : path_t path;
14855 : : #ifdef MS_WINDOWS
14856 : : HANDLE handle;
14857 : : WIN32_FIND_DATAW file_data;
14858 : : int first_time;
14859 : : #else /* POSIX */
14860 : : DIR *dirp;
14861 : : #endif
14862 : : #ifdef HAVE_FDOPENDIR
14863 : : int fd;
14864 : : #endif
14865 : : } ScandirIterator;
14866 : :
14867 : : #ifdef MS_WINDOWS
14868 : :
14869 : : static int
14870 : : ScandirIterator_is_closed(ScandirIterator *iterator)
14871 : : {
14872 : : return iterator->handle == INVALID_HANDLE_VALUE;
14873 : : }
14874 : :
14875 : : static void
14876 : : ScandirIterator_closedir(ScandirIterator *iterator)
14877 : : {
14878 : : HANDLE handle = iterator->handle;
14879 : :
14880 : : if (handle == INVALID_HANDLE_VALUE)
14881 : : return;
14882 : :
14883 : : iterator->handle = INVALID_HANDLE_VALUE;
14884 : : Py_BEGIN_ALLOW_THREADS
14885 : : FindClose(handle);
14886 : : Py_END_ALLOW_THREADS
14887 : : }
14888 : :
14889 : : static PyObject *
14890 : : ScandirIterator_iternext(ScandirIterator *iterator)
14891 : : {
14892 : : WIN32_FIND_DATAW *file_data = &iterator->file_data;
14893 : : BOOL success;
14894 : : PyObject *entry;
14895 : :
14896 : : /* Happens if the iterator is iterated twice, or closed explicitly */
14897 : : if (iterator->handle == INVALID_HANDLE_VALUE)
14898 : : return NULL;
14899 : :
14900 : : while (1) {
14901 : : if (!iterator->first_time) {
14902 : : Py_BEGIN_ALLOW_THREADS
14903 : : success = FindNextFileW(iterator->handle, file_data);
14904 : : Py_END_ALLOW_THREADS
14905 : : if (!success) {
14906 : : /* Error or no more files */
14907 : : if (GetLastError() != ERROR_NO_MORE_FILES)
14908 : : path_error(&iterator->path);
14909 : : break;
14910 : : }
14911 : : }
14912 : : iterator->first_time = 0;
14913 : :
14914 : : /* Skip over . and .. */
14915 : : if (wcscmp(file_data->cFileName, L".") != 0 &&
14916 : : wcscmp(file_data->cFileName, L"..") != 0)
14917 : : {
14918 : : PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14919 : : entry = DirEntry_from_find_data(module, &iterator->path, file_data);
14920 : : if (!entry)
14921 : : break;
14922 : : return entry;
14923 : : }
14924 : :
14925 : : /* Loop till we get a non-dot directory or finish iterating */
14926 : : }
14927 : :
14928 : : /* Error or no more files */
14929 : : ScandirIterator_closedir(iterator);
14930 : : return NULL;
14931 : : }
14932 : :
14933 : : #else /* POSIX */
14934 : :
14935 : : static int
14936 : 55 : ScandirIterator_is_closed(ScandirIterator *iterator)
14937 : : {
14938 : 55 : return !iterator->dirp;
14939 : : }
14940 : :
14941 : : static void
14942 : 110 : ScandirIterator_closedir(ScandirIterator *iterator)
14943 : : {
14944 : 110 : DIR *dirp = iterator->dirp;
14945 : :
14946 [ + + ]: 110 : if (!dirp)
14947 : 55 : return;
14948 : :
14949 : 55 : iterator->dirp = NULL;
14950 : 55 : Py_BEGIN_ALLOW_THREADS
14951 : : #ifdef HAVE_FDOPENDIR
14952 [ + + ]: 55 : if (iterator->path.fd != -1)
14953 : 1 : rewinddir(dirp);
14954 : : #endif
14955 : 55 : closedir(dirp);
14956 : 55 : Py_END_ALLOW_THREADS
14957 : 55 : return;
14958 : : }
14959 : :
14960 : : static PyObject *
14961 : 1595 : ScandirIterator_iternext(ScandirIterator *iterator)
14962 : : {
14963 : : struct dirent *direntp;
14964 : : Py_ssize_t name_len;
14965 : : int is_dot;
14966 : : PyObject *entry;
14967 : :
14968 : : /* Happens if the iterator is iterated twice, or closed explicitly */
14969 [ - + ]: 1595 : if (!iterator->dirp)
14970 : 0 : return NULL;
14971 : :
14972 : : while (1) {
14973 : 1705 : errno = 0;
14974 : 1705 : Py_BEGIN_ALLOW_THREADS
14975 : 1705 : direntp = readdir(iterator->dirp);
14976 : 1705 : Py_END_ALLOW_THREADS
14977 : :
14978 [ + + ]: 1705 : if (!direntp) {
14979 : : /* Error or no more files */
14980 [ - + ]: 55 : if (errno != 0)
14981 : 0 : path_error(&iterator->path);
14982 : 55 : break;
14983 : : }
14984 : :
14985 : : /* Skip over . and .. */
14986 : 1650 : name_len = NAMLEN(direntp);
14987 [ + + + + ]: 1705 : is_dot = direntp->d_name[0] == '.' &&
14988 [ + - + - ]: 55 : (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
14989 [ + + ]: 1650 : if (!is_dot) {
14990 : 1540 : PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14991 : 1540 : entry = DirEntry_from_posix_info(module,
14992 : 1540 : &iterator->path, direntp->d_name,
14993 : : name_len, direntp->d_ino
14994 : : #ifdef HAVE_DIRENT_D_TYPE
14995 : 1540 : , direntp->d_type
14996 : : #endif
14997 : : );
14998 [ - + ]: 1540 : if (!entry)
14999 : 0 : break;
15000 : 1540 : return entry;
15001 : : }
15002 : :
15003 : : /* Loop till we get a non-dot directory or finish iterating */
15004 : : }
15005 : :
15006 : : /* Error or no more files */
15007 : 55 : ScandirIterator_closedir(iterator);
15008 : 55 : return NULL;
15009 : : }
15010 : :
15011 : : #endif
15012 : :
15013 : : static PyObject *
15014 : 0 : ScandirIterator_close(ScandirIterator *self, PyObject *args)
15015 : : {
15016 : 0 : ScandirIterator_closedir(self);
15017 : 0 : Py_RETURN_NONE;
15018 : : }
15019 : :
15020 : : static PyObject *
15021 : 55 : ScandirIterator_enter(PyObject *self, PyObject *args)
15022 : : {
15023 : 55 : return Py_NewRef(self);
15024 : : }
15025 : :
15026 : : static PyObject *
15027 : 55 : ScandirIterator_exit(ScandirIterator *self, PyObject *args)
15028 : : {
15029 : 55 : ScandirIterator_closedir(self);
15030 : 55 : Py_RETURN_NONE;
15031 : : }
15032 : :
15033 : : static void
15034 : 55 : ScandirIterator_finalize(ScandirIterator *iterator)
15035 : : {
15036 : :
15037 : : /* Save the current exception, if any. */
15038 : 55 : PyObject *exc = PyErr_GetRaisedException();
15039 : :
15040 [ - + ]: 55 : if (!ScandirIterator_is_closed(iterator)) {
15041 : 0 : ScandirIterator_closedir(iterator);
15042 : :
15043 [ # # ]: 0 : if (PyErr_ResourceWarning((PyObject *)iterator, 1,
15044 : : "unclosed scandir iterator %R", iterator)) {
15045 : : /* Spurious errors can appear at shutdown */
15046 [ # # ]: 0 : if (PyErr_ExceptionMatches(PyExc_Warning)) {
15047 : 0 : PyErr_WriteUnraisable((PyObject *) iterator);
15048 : : }
15049 : : }
15050 : : }
15051 : :
15052 : 55 : path_cleanup(&iterator->path);
15053 : :
15054 : : /* Restore the saved exception. */
15055 : 55 : PyErr_SetRaisedException(exc);
15056 : 55 : }
15057 : :
15058 : : static void
15059 : 55 : ScandirIterator_dealloc(ScandirIterator *iterator)
15060 : : {
15061 : 55 : PyTypeObject *tp = Py_TYPE(iterator);
15062 [ - + ]: 55 : if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
15063 : 0 : return;
15064 : :
15065 : 55 : freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
15066 : 55 : free_func(iterator);
15067 : 55 : Py_DECREF(tp);
15068 : : }
15069 : :
15070 : : static PyMethodDef ScandirIterator_methods[] = {
15071 : : {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
15072 : : {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
15073 : : {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
15074 : : {NULL}
15075 : : };
15076 : :
15077 : : static PyType_Slot ScandirIteratorType_slots[] = {
15078 : : {Py_tp_dealloc, ScandirIterator_dealloc},
15079 : : {Py_tp_finalize, ScandirIterator_finalize},
15080 : : {Py_tp_iter, PyObject_SelfIter},
15081 : : {Py_tp_iternext, ScandirIterator_iternext},
15082 : : {Py_tp_methods, ScandirIterator_methods},
15083 : : {0, 0},
15084 : : };
15085 : :
15086 : : static PyType_Spec ScandirIteratorType_spec = {
15087 : : MODNAME ".ScandirIterator",
15088 : : sizeof(ScandirIterator),
15089 : : 0,
15090 : : // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
15091 : : // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
15092 : : (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
15093 : : | Py_TPFLAGS_DISALLOW_INSTANTIATION),
15094 : : ScandirIteratorType_slots
15095 : : };
15096 : :
15097 : : /*[clinic input]
15098 : : os.scandir
15099 : :
15100 : : path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
15101 : :
15102 : : Return an iterator of DirEntry objects for given path.
15103 : :
15104 : : path can be specified as either str, bytes, or a path-like object. If path
15105 : : is bytes, the names of yielded DirEntry objects will also be bytes; in
15106 : : all other circumstances they will be str.
15107 : :
15108 : : If path is None, uses the path='.'.
15109 : : [clinic start generated code]*/
15110 : :
15111 : : static PyObject *
15112 : 55 : os_scandir_impl(PyObject *module, path_t *path)
15113 : : /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
15114 : : {
15115 : : ScandirIterator *iterator;
15116 : : #ifdef MS_WINDOWS
15117 : : wchar_t *path_strW;
15118 : : #else
15119 : : const char *path_str;
15120 : : #ifdef HAVE_FDOPENDIR
15121 : 55 : int fd = -1;
15122 : : #endif
15123 : : #endif
15124 : :
15125 [ - + ]: 55 : if (PySys_Audit("os.scandir", "O",
15126 [ + - ]: 55 : path->object ? path->object : Py_None) < 0) {
15127 : 0 : return NULL;
15128 : : }
15129 : :
15130 : 55 : PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
15131 : 55 : iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
15132 [ - + ]: 55 : if (!iterator)
15133 : 0 : return NULL;
15134 : :
15135 : : #ifdef MS_WINDOWS
15136 : : iterator->handle = INVALID_HANDLE_VALUE;
15137 : : #else
15138 : 55 : iterator->dirp = NULL;
15139 : : #endif
15140 : :
15141 : : /* Move the ownership to iterator->path */
15142 : 55 : memcpy(&iterator->path, path, sizeof(path_t));
15143 : 55 : memset(path, 0, sizeof(path_t));
15144 : :
15145 : : #ifdef MS_WINDOWS
15146 : : iterator->first_time = 1;
15147 : :
15148 : : path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
15149 : : if (!path_strW)
15150 : : goto error;
15151 : :
15152 : : Py_BEGIN_ALLOW_THREADS
15153 : : iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
15154 : : Py_END_ALLOW_THREADS
15155 : :
15156 : : PyMem_Free(path_strW);
15157 : :
15158 : : if (iterator->handle == INVALID_HANDLE_VALUE) {
15159 : : path_error(&iterator->path);
15160 : : goto error;
15161 : : }
15162 : : #else /* POSIX */
15163 : 55 : errno = 0;
15164 : : #ifdef HAVE_FDOPENDIR
15165 [ + + ]: 55 : if (iterator->path.fd != -1) {
15166 : : if (HAVE_FDOPENDIR_RUNTIME) {
15167 : : /* closedir() closes the FD, so we duplicate it */
15168 : 1 : fd = _Py_dup(iterator->path.fd);
15169 [ - + ]: 1 : if (fd == -1)
15170 : 0 : goto error;
15171 : :
15172 : 1 : Py_BEGIN_ALLOW_THREADS
15173 : 1 : iterator->dirp = fdopendir(fd);
15174 : 1 : Py_END_ALLOW_THREADS
15175 : : } else {
15176 : : PyErr_SetString(PyExc_TypeError,
15177 : : "scandir: path should be string, bytes, os.PathLike or None, not int");
15178 : : return NULL;
15179 : : }
15180 : : }
15181 : : else
15182 : : #endif
15183 : : {
15184 [ + - ]: 54 : if (iterator->path.narrow)
15185 : 54 : path_str = iterator->path.narrow;
15186 : : else
15187 : 0 : path_str = ".";
15188 : :
15189 : 54 : Py_BEGIN_ALLOW_THREADS
15190 : 54 : iterator->dirp = opendir(path_str);
15191 : 54 : Py_END_ALLOW_THREADS
15192 : : }
15193 : :
15194 [ - + ]: 55 : if (!iterator->dirp) {
15195 : 0 : path_error(&iterator->path);
15196 : : #ifdef HAVE_FDOPENDIR
15197 [ # # ]: 0 : if (fd != -1) {
15198 : 0 : Py_BEGIN_ALLOW_THREADS
15199 : 0 : close(fd);
15200 : 0 : Py_END_ALLOW_THREADS
15201 : : }
15202 : : #endif
15203 : 0 : goto error;
15204 : : }
15205 : : #endif
15206 : :
15207 : 55 : return (PyObject *)iterator;
15208 : :
15209 : 0 : error:
15210 : 0 : Py_DECREF(iterator);
15211 : 0 : return NULL;
15212 : : }
15213 : :
15214 : : /*
15215 : : Return the file system path representation of the object.
15216 : :
15217 : : If the object is str or bytes, then allow it to pass through with
15218 : : an incremented refcount. If the object defines __fspath__(), then
15219 : : return the result of that method. All other types raise a TypeError.
15220 : : */
15221 : : PyObject *
15222 : 13009 : PyOS_FSPath(PyObject *path)
15223 : : {
15224 : : /* For error message reasons, this function is manually inlined in
15225 : : path_converter(). */
15226 : 13009 : PyObject *func = NULL;
15227 : 13009 : PyObject *path_repr = NULL;
15228 : :
15229 [ + + + + ]: 13009 : if (PyUnicode_Check(path) || PyBytes_Check(path)) {
15230 : 12928 : return Py_NewRef(path);
15231 : : }
15232 : :
15233 : 81 : func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
15234 [ - + ]: 81 : if (NULL == func) {
15235 : 0 : return PyErr_Format(PyExc_TypeError,
15236 : : "expected str, bytes or os.PathLike object, "
15237 : : "not %.200s",
15238 : : _PyType_Name(Py_TYPE(path)));
15239 : : }
15240 : :
15241 : 81 : path_repr = _PyObject_CallNoArgs(func);
15242 : 81 : Py_DECREF(func);
15243 [ - + ]: 81 : if (NULL == path_repr) {
15244 : 0 : return NULL;
15245 : : }
15246 : :
15247 [ - + - - ]: 81 : if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
15248 : 0 : PyErr_Format(PyExc_TypeError,
15249 : : "expected %.200s.__fspath__() to return str or bytes, "
15250 : : "not %.200s", _PyType_Name(Py_TYPE(path)),
15251 : : _PyType_Name(Py_TYPE(path_repr)));
15252 : 0 : Py_DECREF(path_repr);
15253 : 0 : return NULL;
15254 : : }
15255 : :
15256 : 81 : return path_repr;
15257 : : }
15258 : :
15259 : : /*[clinic input]
15260 : : os.fspath
15261 : :
15262 : : path: object
15263 : :
15264 : : Return the file system path representation of the object.
15265 : :
15266 : : If the object is str or bytes, then allow it to pass through as-is. If the
15267 : : object defines __fspath__(), then return the result of that method. All other
15268 : : types raise a TypeError.
15269 : : [clinic start generated code]*/
15270 : :
15271 : : static PyObject *
15272 : 6021 : os_fspath_impl(PyObject *module, PyObject *path)
15273 : : /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
15274 : : {
15275 : 6021 : return PyOS_FSPath(path);
15276 : : }
15277 : :
15278 : : #ifdef HAVE_GETRANDOM_SYSCALL
15279 : : /*[clinic input]
15280 : : os.getrandom
15281 : :
15282 : : size: Py_ssize_t
15283 : : flags: int=0
15284 : :
15285 : : Obtain a series of random bytes.
15286 : : [clinic start generated code]*/
15287 : :
15288 : : static PyObject *
15289 : 0 : os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
15290 : : /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
15291 : : {
15292 : : PyObject *bytes;
15293 : : Py_ssize_t n;
15294 : :
15295 [ # # ]: 0 : if (size < 0) {
15296 : 0 : errno = EINVAL;
15297 : 0 : return posix_error();
15298 : : }
15299 : :
15300 : 0 : bytes = PyBytes_FromStringAndSize(NULL, size);
15301 [ # # ]: 0 : if (bytes == NULL) {
15302 : 0 : PyErr_NoMemory();
15303 : 0 : return NULL;
15304 : : }
15305 : :
15306 : : while (1) {
15307 : 0 : n = syscall(SYS_getrandom,
15308 : : PyBytes_AS_STRING(bytes),
15309 : : PyBytes_GET_SIZE(bytes),
15310 : : flags);
15311 [ # # # # ]: 0 : if (n < 0 && errno == EINTR) {
15312 [ # # ]: 0 : if (PyErr_CheckSignals() < 0) {
15313 : 0 : goto error;
15314 : : }
15315 : :
15316 : : /* getrandom() was interrupted by a signal: retry */
15317 : 0 : continue;
15318 : : }
15319 : 0 : break;
15320 : : }
15321 : :
15322 [ # # ]: 0 : if (n < 0) {
15323 : 0 : PyErr_SetFromErrno(PyExc_OSError);
15324 : 0 : goto error;
15325 : : }
15326 : :
15327 [ # # ]: 0 : if (n != size) {
15328 : 0 : _PyBytes_Resize(&bytes, n);
15329 : : }
15330 : :
15331 : 0 : return bytes;
15332 : :
15333 : 0 : error:
15334 : 0 : Py_DECREF(bytes);
15335 : 0 : return NULL;
15336 : : }
15337 : : #endif /* HAVE_GETRANDOM_SYSCALL */
15338 : :
15339 : : #if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
15340 : :
15341 : : /* bpo-36085: Helper functions for managing DLL search directories
15342 : : * on win32
15343 : : */
15344 : :
15345 : : /*[clinic input]
15346 : : os._add_dll_directory
15347 : :
15348 : : path: path_t
15349 : :
15350 : : Add a path to the DLL search path.
15351 : :
15352 : : This search path is used when resolving dependencies for imported
15353 : : extension modules (the module itself is resolved through sys.path),
15354 : : and also by ctypes.
15355 : :
15356 : : Returns an opaque value that may be passed to os.remove_dll_directory
15357 : : to remove this directory from the search path.
15358 : : [clinic start generated code]*/
15359 : :
15360 : : static PyObject *
15361 : : os__add_dll_directory_impl(PyObject *module, path_t *path)
15362 : : /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
15363 : : {
15364 : : DLL_DIRECTORY_COOKIE cookie = 0;
15365 : : DWORD err = 0;
15366 : :
15367 : : if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
15368 : : return NULL;
15369 : : }
15370 : :
15371 : : Py_BEGIN_ALLOW_THREADS
15372 : : if (!(cookie = AddDllDirectory(path->wide))) {
15373 : : err = GetLastError();
15374 : : }
15375 : : Py_END_ALLOW_THREADS
15376 : :
15377 : : if (err) {
15378 : : return win32_error_object_err("add_dll_directory",
15379 : : path->object, err);
15380 : : }
15381 : :
15382 : : return PyCapsule_New(cookie, "DLL directory cookie", NULL);
15383 : : }
15384 : :
15385 : : /*[clinic input]
15386 : : os._remove_dll_directory
15387 : :
15388 : : cookie: object
15389 : :
15390 : : Removes a path from the DLL search path.
15391 : :
15392 : : The parameter is an opaque value that was returned from
15393 : : os.add_dll_directory. You can only remove directories that you added
15394 : : yourself.
15395 : : [clinic start generated code]*/
15396 : :
15397 : : static PyObject *
15398 : : os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
15399 : : /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
15400 : : {
15401 : : DLL_DIRECTORY_COOKIE cookieValue;
15402 : : DWORD err = 0;
15403 : :
15404 : : if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
15405 : : PyErr_SetString(PyExc_TypeError,
15406 : : "Provided cookie was not returned from os.add_dll_directory");
15407 : : return NULL;
15408 : : }
15409 : :
15410 : : cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
15411 : : cookie, "DLL directory cookie");
15412 : :
15413 : : Py_BEGIN_ALLOW_THREADS
15414 : : if (!RemoveDllDirectory(cookieValue)) {
15415 : : err = GetLastError();
15416 : : }
15417 : : Py_END_ALLOW_THREADS
15418 : :
15419 : : if (err) {
15420 : : return win32_error_object_err("remove_dll_directory",
15421 : : NULL, err);
15422 : : }
15423 : :
15424 : : if (PyCapsule_SetName(cookie, NULL)) {
15425 : : return NULL;
15426 : : }
15427 : :
15428 : : Py_RETURN_NONE;
15429 : : }
15430 : :
15431 : : #endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
15432 : :
15433 : :
15434 : : /* Only check if WIFEXITED is available: expect that it comes
15435 : : with WEXITSTATUS, WIFSIGNALED, etc.
15436 : :
15437 : : os.waitstatus_to_exitcode() is implemented in C and not in Python, so
15438 : : subprocess can safely call it during late Python finalization without
15439 : : risking that used os attributes were set to None by finalize_modules(). */
15440 : : #if defined(WIFEXITED) || defined(MS_WINDOWS)
15441 : : /*[clinic input]
15442 : : os.waitstatus_to_exitcode
15443 : :
15444 : : status as status_obj: object
15445 : :
15446 : : Convert a wait status to an exit code.
15447 : :
15448 : : On Unix:
15449 : :
15450 : : * If WIFEXITED(status) is true, return WEXITSTATUS(status).
15451 : : * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
15452 : : * Otherwise, raise a ValueError.
15453 : :
15454 : : On Windows, return status shifted right by 8 bits.
15455 : :
15456 : : On Unix, if the process is being traced or if waitpid() was called with
15457 : : WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
15458 : : This function must not be called if WIFSTOPPED(status) is true.
15459 : : [clinic start generated code]*/
15460 : :
15461 : : static PyObject *
15462 : 0 : os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
15463 : : /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
15464 : : {
15465 : : #ifndef MS_WINDOWS
15466 : 0 : int status = _PyLong_AsInt(status_obj);
15467 [ # # # # ]: 0 : if (status == -1 && PyErr_Occurred()) {
15468 : 0 : return NULL;
15469 : : }
15470 : :
15471 : : WAIT_TYPE wait_status;
15472 : 0 : WAIT_STATUS_INT(wait_status) = status;
15473 : : int exitcode;
15474 [ # # ]: 0 : if (WIFEXITED(wait_status)) {
15475 : 0 : exitcode = WEXITSTATUS(wait_status);
15476 : : /* Sanity check to provide warranty on the function behavior.
15477 : : It should not occur in practice */
15478 [ # # ]: 0 : if (exitcode < 0) {
15479 : 0 : PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
15480 : 0 : return NULL;
15481 : : }
15482 : : }
15483 [ # # ]: 0 : else if (WIFSIGNALED(wait_status)) {
15484 : 0 : int signum = WTERMSIG(wait_status);
15485 : : /* Sanity check to provide warranty on the function behavior.
15486 : : It should not occurs in practice */
15487 [ # # ]: 0 : if (signum <= 0) {
15488 : 0 : PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
15489 : 0 : return NULL;
15490 : : }
15491 : 0 : exitcode = -signum;
15492 [ # # ]: 0 : } else if (WIFSTOPPED(wait_status)) {
15493 : : /* Status only received if the process is being traced
15494 : : or if waitpid() was called with WUNTRACED option. */
15495 : 0 : int signum = WSTOPSIG(wait_status);
15496 : 0 : PyErr_Format(PyExc_ValueError,
15497 : : "process stopped by delivery of signal %i",
15498 : : signum);
15499 : 0 : return NULL;
15500 : : }
15501 : : else {
15502 : 0 : PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
15503 : 0 : return NULL;
15504 : : }
15505 : 0 : return PyLong_FromLong(exitcode);
15506 : : #else
15507 : : /* Windows implementation: see os.waitpid() implementation
15508 : : which uses _cwait(). */
15509 : : unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
15510 : : if (status == (unsigned long long)-1 && PyErr_Occurred()) {
15511 : : return NULL;
15512 : : }
15513 : :
15514 : : unsigned long long exitcode = (status >> 8);
15515 : : /* ExitProcess() accepts an UINT type:
15516 : : reject exit code which doesn't fit in an UINT */
15517 : : if (exitcode > UINT_MAX) {
15518 : : PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
15519 : : return NULL;
15520 : : }
15521 : : return PyLong_FromUnsignedLong((unsigned long)exitcode);
15522 : : #endif
15523 : : }
15524 : : #endif
15525 : :
15526 : :
15527 : : static PyMethodDef posix_methods[] = {
15528 : :
15529 : : OS_STAT_METHODDEF
15530 : : OS_ACCESS_METHODDEF
15531 : : OS_TTYNAME_METHODDEF
15532 : : OS_CHDIR_METHODDEF
15533 : : OS_CHFLAGS_METHODDEF
15534 : : OS_CHMOD_METHODDEF
15535 : : OS_FCHMOD_METHODDEF
15536 : : OS_LCHMOD_METHODDEF
15537 : : OS_CHOWN_METHODDEF
15538 : : OS_FCHOWN_METHODDEF
15539 : : OS_LCHOWN_METHODDEF
15540 : : OS_LCHFLAGS_METHODDEF
15541 : : OS_CHROOT_METHODDEF
15542 : : OS_CTERMID_METHODDEF
15543 : : OS_GETCWD_METHODDEF
15544 : : OS_GETCWDB_METHODDEF
15545 : : OS_LINK_METHODDEF
15546 : : OS_LISTDIR_METHODDEF
15547 : : OS_LISTDRIVES_METHODDEF
15548 : : OS_LISTMOUNTS_METHODDEF
15549 : : OS_LISTVOLUMES_METHODDEF
15550 : : OS_LSTAT_METHODDEF
15551 : : OS_MKDIR_METHODDEF
15552 : : OS_NICE_METHODDEF
15553 : : OS_GETPRIORITY_METHODDEF
15554 : : OS_SETPRIORITY_METHODDEF
15555 : : OS_POSIX_SPAWN_METHODDEF
15556 : : OS_POSIX_SPAWNP_METHODDEF
15557 : : OS_READLINK_METHODDEF
15558 : : OS_COPY_FILE_RANGE_METHODDEF
15559 : : OS_SPLICE_METHODDEF
15560 : : OS_RENAME_METHODDEF
15561 : : OS_REPLACE_METHODDEF
15562 : : OS_RMDIR_METHODDEF
15563 : : OS_SYMLINK_METHODDEF
15564 : : OS_SYSTEM_METHODDEF
15565 : : OS_UMASK_METHODDEF
15566 : : OS_UNAME_METHODDEF
15567 : : OS_UNLINK_METHODDEF
15568 : : OS_REMOVE_METHODDEF
15569 : : OS_UTIME_METHODDEF
15570 : : OS_TIMES_METHODDEF
15571 : : OS__EXIT_METHODDEF
15572 : : OS__FCOPYFILE_METHODDEF
15573 : : OS_EXECV_METHODDEF
15574 : : OS_EXECVE_METHODDEF
15575 : : OS_SPAWNV_METHODDEF
15576 : : OS_SPAWNVE_METHODDEF
15577 : : OS_FORK1_METHODDEF
15578 : : OS_FORK_METHODDEF
15579 : : OS_REGISTER_AT_FORK_METHODDEF
15580 : : OS_SCHED_GET_PRIORITY_MAX_METHODDEF
15581 : : OS_SCHED_GET_PRIORITY_MIN_METHODDEF
15582 : : OS_SCHED_GETPARAM_METHODDEF
15583 : : OS_SCHED_GETSCHEDULER_METHODDEF
15584 : : OS_SCHED_RR_GET_INTERVAL_METHODDEF
15585 : : OS_SCHED_SETPARAM_METHODDEF
15586 : : OS_SCHED_SETSCHEDULER_METHODDEF
15587 : : OS_SCHED_YIELD_METHODDEF
15588 : : OS_SCHED_SETAFFINITY_METHODDEF
15589 : : OS_SCHED_GETAFFINITY_METHODDEF
15590 : : OS_OPENPTY_METHODDEF
15591 : : OS_LOGIN_TTY_METHODDEF
15592 : : OS_FORKPTY_METHODDEF
15593 : : OS_GETEGID_METHODDEF
15594 : : OS_GETEUID_METHODDEF
15595 : : OS_GETGID_METHODDEF
15596 : : OS_GETGROUPLIST_METHODDEF
15597 : : OS_GETGROUPS_METHODDEF
15598 : : OS_GETPID_METHODDEF
15599 : : OS_GETPGRP_METHODDEF
15600 : : OS_GETPPID_METHODDEF
15601 : : OS_GETUID_METHODDEF
15602 : : OS_GETLOGIN_METHODDEF
15603 : : OS_KILL_METHODDEF
15604 : : OS_KILLPG_METHODDEF
15605 : : OS_PLOCK_METHODDEF
15606 : : OS_STARTFILE_METHODDEF
15607 : : OS_SETUID_METHODDEF
15608 : : OS_SETEUID_METHODDEF
15609 : : OS_SETREUID_METHODDEF
15610 : : OS_SETGID_METHODDEF
15611 : : OS_SETEGID_METHODDEF
15612 : : OS_SETREGID_METHODDEF
15613 : : OS_SETGROUPS_METHODDEF
15614 : : OS_INITGROUPS_METHODDEF
15615 : : OS_GETPGID_METHODDEF
15616 : : OS_SETPGRP_METHODDEF
15617 : : OS_WAIT_METHODDEF
15618 : : OS_WAIT3_METHODDEF
15619 : : OS_WAIT4_METHODDEF
15620 : : OS_WAITID_METHODDEF
15621 : : OS_WAITPID_METHODDEF
15622 : : OS_PIDFD_OPEN_METHODDEF
15623 : : OS_GETSID_METHODDEF
15624 : : OS_SETSID_METHODDEF
15625 : : OS_SETPGID_METHODDEF
15626 : : OS_TCGETPGRP_METHODDEF
15627 : : OS_TCSETPGRP_METHODDEF
15628 : : OS_OPEN_METHODDEF
15629 : : OS_CLOSE_METHODDEF
15630 : : OS_CLOSERANGE_METHODDEF
15631 : : OS_DEVICE_ENCODING_METHODDEF
15632 : : OS_DUP_METHODDEF
15633 : : OS_DUP2_METHODDEF
15634 : : OS_LOCKF_METHODDEF
15635 : : OS_LSEEK_METHODDEF
15636 : : OS_READ_METHODDEF
15637 : : OS_READV_METHODDEF
15638 : : OS_PREAD_METHODDEF
15639 : : OS_PREADV_METHODDEF
15640 : : OS_WRITE_METHODDEF
15641 : : OS_WRITEV_METHODDEF
15642 : : OS_PWRITE_METHODDEF
15643 : : OS_PWRITEV_METHODDEF
15644 : : OS_SENDFILE_METHODDEF
15645 : : OS_FSTAT_METHODDEF
15646 : : OS_ISATTY_METHODDEF
15647 : : OS_PIPE_METHODDEF
15648 : : OS_PIPE2_METHODDEF
15649 : : OS_MKFIFO_METHODDEF
15650 : : OS_MKNOD_METHODDEF
15651 : : OS_MAJOR_METHODDEF
15652 : : OS_MINOR_METHODDEF
15653 : : OS_MAKEDEV_METHODDEF
15654 : : OS_FTRUNCATE_METHODDEF
15655 : : OS_TRUNCATE_METHODDEF
15656 : : OS_POSIX_FALLOCATE_METHODDEF
15657 : : OS_POSIX_FADVISE_METHODDEF
15658 : : OS_PUTENV_METHODDEF
15659 : : OS_UNSETENV_METHODDEF
15660 : : OS_STRERROR_METHODDEF
15661 : : OS_FCHDIR_METHODDEF
15662 : : OS_FSYNC_METHODDEF
15663 : : OS_SYNC_METHODDEF
15664 : : OS_FDATASYNC_METHODDEF
15665 : : OS_WCOREDUMP_METHODDEF
15666 : : OS_WIFCONTINUED_METHODDEF
15667 : : OS_WIFSTOPPED_METHODDEF
15668 : : OS_WIFSIGNALED_METHODDEF
15669 : : OS_WIFEXITED_METHODDEF
15670 : : OS_WEXITSTATUS_METHODDEF
15671 : : OS_WTERMSIG_METHODDEF
15672 : : OS_WSTOPSIG_METHODDEF
15673 : : OS_FSTATVFS_METHODDEF
15674 : : OS_STATVFS_METHODDEF
15675 : : OS_CONFSTR_METHODDEF
15676 : : OS_SYSCONF_METHODDEF
15677 : : OS_FPATHCONF_METHODDEF
15678 : : OS_PATHCONF_METHODDEF
15679 : : OS_ABORT_METHODDEF
15680 : : OS__GETFULLPATHNAME_METHODDEF
15681 : : OS__GETDISKUSAGE_METHODDEF
15682 : : OS__GETFINALPATHNAME_METHODDEF
15683 : : OS__GETVOLUMEPATHNAME_METHODDEF
15684 : : OS__PATH_SPLITROOT_METHODDEF
15685 : : OS__PATH_NORMPATH_METHODDEF
15686 : : OS_GETLOADAVG_METHODDEF
15687 : : OS_URANDOM_METHODDEF
15688 : : OS_SETRESUID_METHODDEF
15689 : : OS_SETRESGID_METHODDEF
15690 : : OS_GETRESUID_METHODDEF
15691 : : OS_GETRESGID_METHODDEF
15692 : :
15693 : : OS_GETXATTR_METHODDEF
15694 : : OS_SETXATTR_METHODDEF
15695 : : OS_REMOVEXATTR_METHODDEF
15696 : : OS_LISTXATTR_METHODDEF
15697 : :
15698 : : OS_GET_TERMINAL_SIZE_METHODDEF
15699 : : OS_CPU_COUNT_METHODDEF
15700 : : OS_GET_INHERITABLE_METHODDEF
15701 : : OS_SET_INHERITABLE_METHODDEF
15702 : : OS_GET_HANDLE_INHERITABLE_METHODDEF
15703 : : OS_SET_HANDLE_INHERITABLE_METHODDEF
15704 : : OS_GET_BLOCKING_METHODDEF
15705 : : OS_SET_BLOCKING_METHODDEF
15706 : : OS_SCANDIR_METHODDEF
15707 : : OS_FSPATH_METHODDEF
15708 : : OS_GETRANDOM_METHODDEF
15709 : : OS_MEMFD_CREATE_METHODDEF
15710 : : OS_EVENTFD_METHODDEF
15711 : : OS_EVENTFD_READ_METHODDEF
15712 : : OS_EVENTFD_WRITE_METHODDEF
15713 : : OS__ADD_DLL_DIRECTORY_METHODDEF
15714 : : OS__REMOVE_DLL_DIRECTORY_METHODDEF
15715 : : OS_WAITSTATUS_TO_EXITCODE_METHODDEF
15716 : : OS_SETNS_METHODDEF
15717 : : OS_UNSHARE_METHODDEF
15718 : :
15719 : : OS__PATH_ISDIR_METHODDEF
15720 : : OS__PATH_ISFILE_METHODDEF
15721 : : OS__PATH_ISLINK_METHODDEF
15722 : : OS__PATH_EXISTS_METHODDEF
15723 : : {NULL, NULL} /* Sentinel */
15724 : : };
15725 : :
15726 : : static int
15727 : 26 : all_ins(PyObject *m)
15728 : : {
15729 : : #ifdef F_OK
15730 [ - + ]: 26 : if (PyModule_AddIntMacro(m, F_OK)) return -1;
15731 : : #endif
15732 : : #ifdef R_OK
15733 [ - + ]: 26 : if (PyModule_AddIntMacro(m, R_OK)) return -1;
15734 : : #endif
15735 : : #ifdef W_OK
15736 [ - + ]: 26 : if (PyModule_AddIntMacro(m, W_OK)) return -1;
15737 : : #endif
15738 : : #ifdef X_OK
15739 [ - + ]: 26 : if (PyModule_AddIntMacro(m, X_OK)) return -1;
15740 : : #endif
15741 : : #ifdef NGROUPS_MAX
15742 [ - + ]: 26 : if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
15743 : : #endif
15744 : : #ifdef TMP_MAX
15745 [ - + ]: 26 : if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
15746 : : #endif
15747 : : #ifdef WCONTINUED
15748 [ - + ]: 26 : if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
15749 : : #endif
15750 : : #ifdef WNOHANG
15751 [ - + ]: 26 : if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
15752 : : #endif
15753 : : #ifdef WUNTRACED
15754 [ - + ]: 26 : if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
15755 : : #endif
15756 : : #ifdef O_RDONLY
15757 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
15758 : : #endif
15759 : : #ifdef O_WRONLY
15760 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
15761 : : #endif
15762 : : #ifdef O_RDWR
15763 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
15764 : : #endif
15765 : : #ifdef O_NDELAY
15766 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
15767 : : #endif
15768 : : #ifdef O_NONBLOCK
15769 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
15770 : : #endif
15771 : : #ifdef O_APPEND
15772 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
15773 : : #endif
15774 : : #ifdef O_DSYNC
15775 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
15776 : : #endif
15777 : : #ifdef O_RSYNC
15778 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
15779 : : #endif
15780 : : #ifdef O_SYNC
15781 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
15782 : : #endif
15783 : : #ifdef O_NOCTTY
15784 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
15785 : : #endif
15786 : : #ifdef O_CREAT
15787 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
15788 : : #endif
15789 : : #ifdef O_EXCL
15790 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
15791 : : #endif
15792 : : #ifdef O_TRUNC
15793 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
15794 : : #endif
15795 : : #ifdef O_BINARY
15796 : : if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
15797 : : #endif
15798 : : #ifdef O_TEXT
15799 : : if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
15800 : : #endif
15801 : : #ifdef O_XATTR
15802 : : if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
15803 : : #endif
15804 : : #ifdef O_LARGEFILE
15805 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
15806 : : #endif
15807 : : #ifndef __GNU__
15808 : : #ifdef O_SHLOCK
15809 : : if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
15810 : : #endif
15811 : : #ifdef O_EXLOCK
15812 : : if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
15813 : : #endif
15814 : : #endif
15815 : : #ifdef O_EXEC
15816 : : if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
15817 : : #endif
15818 : : #ifdef O_SEARCH
15819 : : if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
15820 : : #endif
15821 : : #ifdef O_PATH
15822 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_PATH)) return -1;
15823 : : #endif
15824 : : #ifdef O_TTY_INIT
15825 : : if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
15826 : : #endif
15827 : : #ifdef O_TMPFILE
15828 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
15829 : : #endif
15830 : : #ifdef PRIO_PROCESS
15831 [ - + ]: 26 : if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
15832 : : #endif
15833 : : #ifdef PRIO_PGRP
15834 [ - + ]: 26 : if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
15835 : : #endif
15836 : : #ifdef PRIO_USER
15837 [ - + ]: 26 : if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
15838 : : #endif
15839 : : #ifdef O_CLOEXEC
15840 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
15841 : : #endif
15842 : : #ifdef O_ACCMODE
15843 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
15844 : : #endif
15845 : : #ifdef O_EVTONLY
15846 : : if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
15847 : : #endif
15848 : : #ifdef O_FSYNC
15849 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
15850 : : #endif
15851 : : #ifdef O_SYMLINK
15852 : : if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
15853 : : #endif
15854 : :
15855 : : #ifdef SEEK_HOLE
15856 [ - + ]: 26 : if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
15857 : : #endif
15858 : : #ifdef SEEK_DATA
15859 [ - + ]: 26 : if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
15860 : : #endif
15861 : :
15862 : : /* MS Windows */
15863 : : #ifdef O_NOINHERIT
15864 : : /* Don't inherit in child processes. */
15865 : : if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
15866 : : #endif
15867 : : #ifdef _O_SHORT_LIVED
15868 : : /* Optimize for short life (keep in memory). */
15869 : : /* MS forgot to define this one with a non-underscore form too. */
15870 : : if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
15871 : : #endif
15872 : : #ifdef O_TEMPORARY
15873 : : /* Automatically delete when last handle is closed. */
15874 : : if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
15875 : : #endif
15876 : : #ifdef O_RANDOM
15877 : : /* Optimize for random access. */
15878 : : if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
15879 : : #endif
15880 : : #ifdef O_SEQUENTIAL
15881 : : /* Optimize for sequential access. */
15882 : : if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
15883 : : #endif
15884 : :
15885 : : /* GNU extensions. */
15886 : : #ifdef O_ASYNC
15887 : : /* Send a SIGIO signal whenever input or output
15888 : : becomes available on file descriptor */
15889 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
15890 : : #endif
15891 : : #ifdef O_DIRECT
15892 : : /* Direct disk access. */
15893 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
15894 : : #endif
15895 : : #ifdef O_DIRECTORY
15896 : : /* Must be a directory. */
15897 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
15898 : : #endif
15899 : : #ifdef O_NOFOLLOW
15900 : : /* Do not follow links. */
15901 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
15902 : : #endif
15903 : : #ifdef O_NOFOLLOW_ANY
15904 : : if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
15905 : : #endif
15906 : : #ifdef O_NOLINKS
15907 : : /* Fails if link count of the named file is greater than 1 */
15908 : : if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
15909 : : #endif
15910 : : #ifdef O_NOATIME
15911 : : /* Do not update the access time. */
15912 [ - + ]: 26 : if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
15913 : : #endif
15914 : :
15915 : : /* These come from sysexits.h */
15916 : : #ifdef EX_OK
15917 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_OK)) return -1;
15918 : : #endif /* EX_OK */
15919 : : #ifdef EX_USAGE
15920 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
15921 : : #endif /* EX_USAGE */
15922 : : #ifdef EX_DATAERR
15923 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
15924 : : #endif /* EX_DATAERR */
15925 : : #ifdef EX_NOINPUT
15926 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
15927 : : #endif /* EX_NOINPUT */
15928 : : #ifdef EX_NOUSER
15929 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
15930 : : #endif /* EX_NOUSER */
15931 : : #ifdef EX_NOHOST
15932 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
15933 : : #endif /* EX_NOHOST */
15934 : : #ifdef EX_UNAVAILABLE
15935 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
15936 : : #endif /* EX_UNAVAILABLE */
15937 : : #ifdef EX_SOFTWARE
15938 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
15939 : : #endif /* EX_SOFTWARE */
15940 : : #ifdef EX_OSERR
15941 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
15942 : : #endif /* EX_OSERR */
15943 : : #ifdef EX_OSFILE
15944 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
15945 : : #endif /* EX_OSFILE */
15946 : : #ifdef EX_CANTCREAT
15947 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
15948 : : #endif /* EX_CANTCREAT */
15949 : : #ifdef EX_IOERR
15950 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
15951 : : #endif /* EX_IOERR */
15952 : : #ifdef EX_TEMPFAIL
15953 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
15954 : : #endif /* EX_TEMPFAIL */
15955 : : #ifdef EX_PROTOCOL
15956 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
15957 : : #endif /* EX_PROTOCOL */
15958 : : #ifdef EX_NOPERM
15959 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
15960 : : #endif /* EX_NOPERM */
15961 : : #ifdef EX_CONFIG
15962 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
15963 : : #endif /* EX_CONFIG */
15964 : : #ifdef EX_NOTFOUND
15965 : : if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
15966 : : #endif /* EX_NOTFOUND */
15967 : :
15968 : : /* statvfs */
15969 : : #ifdef ST_RDONLY
15970 [ - + ]: 26 : if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
15971 : : #endif /* ST_RDONLY */
15972 : : #ifdef ST_NOSUID
15973 [ - + ]: 26 : if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
15974 : : #endif /* ST_NOSUID */
15975 : :
15976 : : /* GNU extensions */
15977 : : #ifdef ST_NODEV
15978 [ - + ]: 26 : if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
15979 : : #endif /* ST_NODEV */
15980 : : #ifdef ST_NOEXEC
15981 [ - + ]: 26 : if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
15982 : : #endif /* ST_NOEXEC */
15983 : : #ifdef ST_SYNCHRONOUS
15984 [ - + ]: 26 : if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
15985 : : #endif /* ST_SYNCHRONOUS */
15986 : : #ifdef ST_MANDLOCK
15987 [ - + ]: 26 : if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
15988 : : #endif /* ST_MANDLOCK */
15989 : : #ifdef ST_WRITE
15990 [ - + ]: 26 : if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
15991 : : #endif /* ST_WRITE */
15992 : : #ifdef ST_APPEND
15993 [ - + ]: 26 : if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
15994 : : #endif /* ST_APPEND */
15995 : : #ifdef ST_NOATIME
15996 [ - + ]: 26 : if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
15997 : : #endif /* ST_NOATIME */
15998 : : #ifdef ST_NODIRATIME
15999 [ - + ]: 26 : if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
16000 : : #endif /* ST_NODIRATIME */
16001 : : #ifdef ST_RELATIME
16002 [ - + ]: 26 : if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
16003 : : #endif /* ST_RELATIME */
16004 : :
16005 : : /* FreeBSD sendfile() constants */
16006 : : #ifdef SF_NODISKIO
16007 : : if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
16008 : : #endif
16009 : : /* is obsolete since the 11.x release */
16010 : : #ifdef SF_MNOWAIT
16011 : : if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
16012 : : #endif
16013 : : #ifdef SF_SYNC
16014 : : if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
16015 : : #endif
16016 : : #ifdef SF_NOCACHE
16017 : : if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
16018 : : #endif
16019 : :
16020 : : /* constants for posix_fadvise */
16021 : : #ifdef POSIX_FADV_NORMAL
16022 [ - + ]: 26 : if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
16023 : : #endif
16024 : : #ifdef POSIX_FADV_SEQUENTIAL
16025 [ - + ]: 26 : if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
16026 : : #endif
16027 : : #ifdef POSIX_FADV_RANDOM
16028 [ - + ]: 26 : if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
16029 : : #endif
16030 : : #ifdef POSIX_FADV_NOREUSE
16031 [ - + ]: 26 : if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
16032 : : #endif
16033 : : #ifdef POSIX_FADV_WILLNEED
16034 [ - + ]: 26 : if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
16035 : : #endif
16036 : : #ifdef POSIX_FADV_DONTNEED
16037 [ - + ]: 26 : if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
16038 : : #endif
16039 : :
16040 : : /* constants for waitid */
16041 : : #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
16042 [ - + ]: 26 : if (PyModule_AddIntMacro(m, P_PID)) return -1;
16043 [ - + ]: 26 : if (PyModule_AddIntMacro(m, P_PGID)) return -1;
16044 [ - + ]: 26 : if (PyModule_AddIntMacro(m, P_ALL)) return -1;
16045 : : #ifdef P_PIDFD
16046 [ - + ]: 26 : if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
16047 : : #endif
16048 : : #ifdef PIDFD_NONBLOCK
16049 : : if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
16050 : : #endif
16051 : : #endif
16052 : : #ifdef WEXITED
16053 [ - + ]: 26 : if (PyModule_AddIntMacro(m, WEXITED)) return -1;
16054 : : #endif
16055 : : #ifdef WNOWAIT
16056 [ - + ]: 26 : if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
16057 : : #endif
16058 : : #ifdef WSTOPPED
16059 [ - + ]: 26 : if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
16060 : : #endif
16061 : : #ifdef CLD_EXITED
16062 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
16063 : : #endif
16064 : : #ifdef CLD_KILLED
16065 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
16066 : : #endif
16067 : : #ifdef CLD_DUMPED
16068 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
16069 : : #endif
16070 : : #ifdef CLD_TRAPPED
16071 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
16072 : : #endif
16073 : : #ifdef CLD_STOPPED
16074 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
16075 : : #endif
16076 : : #ifdef CLD_CONTINUED
16077 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
16078 : : #endif
16079 : :
16080 : : /* constants for lockf */
16081 : : #ifdef F_LOCK
16082 [ - + ]: 26 : if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
16083 : : #endif
16084 : : #ifdef F_TLOCK
16085 [ - + ]: 26 : if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
16086 : : #endif
16087 : : #ifdef F_ULOCK
16088 [ - + ]: 26 : if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
16089 : : #endif
16090 : : #ifdef F_TEST
16091 [ - + ]: 26 : if (PyModule_AddIntMacro(m, F_TEST)) return -1;
16092 : : #endif
16093 : :
16094 : : #ifdef RWF_DSYNC
16095 [ - + ]: 26 : if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
16096 : : #endif
16097 : : #ifdef RWF_HIPRI
16098 [ - + ]: 26 : if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
16099 : : #endif
16100 : : #ifdef RWF_SYNC
16101 [ - + ]: 26 : if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
16102 : : #endif
16103 : : #ifdef RWF_NOWAIT
16104 [ - + ]: 26 : if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
16105 : : #endif
16106 : : #ifdef RWF_APPEND
16107 [ - + ]: 26 : if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
16108 : : #endif
16109 : :
16110 : : /* constants for splice */
16111 : : #if defined(HAVE_SPLICE) && defined(__linux__)
16112 [ - + ]: 26 : if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
16113 [ - + ]: 26 : if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
16114 [ - + ]: 26 : if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
16115 : : #endif
16116 : :
16117 : : /* constants for posix_spawn */
16118 : : #ifdef HAVE_POSIX_SPAWN
16119 [ - + ]: 26 : if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
16120 [ - + ]: 26 : if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
16121 [ - + ]: 26 : if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
16122 : : #endif
16123 : :
16124 : : #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
16125 : : if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
16126 : : if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
16127 : : if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
16128 : : #endif
16129 : : #ifdef HAVE_SPAWNV
16130 : : if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
16131 : : if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
16132 : : #endif
16133 : :
16134 : : #ifdef HAVE_SCHED_H
16135 : : #ifdef SCHED_OTHER
16136 [ - + ]: 26 : if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
16137 : : #endif
16138 : : #ifdef SCHED_FIFO
16139 [ - + ]: 26 : if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
16140 : : #endif
16141 : : #ifdef SCHED_RR
16142 [ - + ]: 26 : if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
16143 : : #endif
16144 : : #ifdef SCHED_SPORADIC
16145 : : if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
16146 : : #endif
16147 : : #ifdef SCHED_BATCH
16148 [ - + ]: 26 : if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
16149 : : #endif
16150 : : #ifdef SCHED_IDLE
16151 [ - + ]: 26 : if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
16152 : : #endif
16153 : : #ifdef SCHED_RESET_ON_FORK
16154 [ - + ]: 26 : if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
16155 : : #endif
16156 : : #ifdef SCHED_SYS
16157 : : if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
16158 : : #endif
16159 : : #ifdef SCHED_IA
16160 : : if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
16161 : : #endif
16162 : : #ifdef SCHED_FSS
16163 : : if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
16164 : : #endif
16165 : : #ifdef SCHED_FX
16166 : : if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
16167 : : #endif
16168 : :
16169 : : /* constants for namespaces */
16170 : : #if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
16171 : : #ifdef CLONE_FS
16172 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
16173 : : #endif
16174 : : #ifdef CLONE_FILES
16175 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
16176 : : #endif
16177 : : #ifdef CLONE_NEWNS
16178 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
16179 : : #endif
16180 : : #ifdef CLONE_NEWCGROUP
16181 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
16182 : : #endif
16183 : : #ifdef CLONE_NEWUTS
16184 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
16185 : : #endif
16186 : : #ifdef CLONE_NEWIPC
16187 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
16188 : : #endif
16189 : : #ifdef CLONE_NEWUSER
16190 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
16191 : : #endif
16192 : : #ifdef CLONE_NEWPID
16193 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
16194 : : #endif
16195 : : #ifdef CLONE_NEWNET
16196 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
16197 : : #endif
16198 : : #ifdef CLONE_NEWTIME
16199 : : if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
16200 : : #endif
16201 : : #ifdef CLONE_SYSVSEM
16202 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
16203 : : #endif
16204 : : #ifdef CLONE_THREAD
16205 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
16206 : : #endif
16207 : : #ifdef CLONE_SIGHAND
16208 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
16209 : : #endif
16210 : : #ifdef CLONE_VM
16211 [ - + ]: 26 : if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
16212 : : #endif
16213 : : #endif
16214 : :
16215 : : #endif
16216 : :
16217 : : #ifdef USE_XATTRS
16218 [ - + ]: 26 : if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
16219 [ - + ]: 26 : if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
16220 [ - + ]: 26 : if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
16221 : : #endif
16222 : :
16223 : : #if HAVE_DECL_RTLD_LAZY
16224 [ - + ]: 26 : if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
16225 : : #endif
16226 : : #if HAVE_DECL_RTLD_NOW
16227 [ - + ]: 26 : if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
16228 : : #endif
16229 : : #if HAVE_DECL_RTLD_GLOBAL
16230 [ - + ]: 26 : if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
16231 : : #endif
16232 : : #if HAVE_DECL_RTLD_LOCAL
16233 [ - + ]: 26 : if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
16234 : : #endif
16235 : : #if HAVE_DECL_RTLD_NODELETE
16236 [ - + ]: 26 : if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
16237 : : #endif
16238 : : #if HAVE_DECL_RTLD_NOLOAD
16239 [ - + ]: 26 : if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
16240 : : #endif
16241 : : #if HAVE_DECL_RTLD_DEEPBIND
16242 [ - + ]: 26 : if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
16243 : : #endif
16244 : : #if HAVE_DECL_RTLD_MEMBER
16245 : : if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
16246 : : #endif
16247 : :
16248 : : #ifdef HAVE_GETRANDOM_SYSCALL
16249 [ - + ]: 26 : if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
16250 [ - + ]: 26 : if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
16251 : : #endif
16252 : : #ifdef HAVE_MEMFD_CREATE
16253 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
16254 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
16255 : : #ifdef MFD_HUGETLB
16256 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
16257 : : #endif
16258 : : #ifdef MFD_HUGE_SHIFT
16259 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
16260 : : #endif
16261 : : #ifdef MFD_HUGE_MASK
16262 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
16263 : : #endif
16264 : : #ifdef MFD_HUGE_64KB
16265 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
16266 : : #endif
16267 : : #ifdef MFD_HUGE_512KB
16268 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
16269 : : #endif
16270 : : #ifdef MFD_HUGE_1MB
16271 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
16272 : : #endif
16273 : : #ifdef MFD_HUGE_2MB
16274 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
16275 : : #endif
16276 : : #ifdef MFD_HUGE_8MB
16277 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
16278 : : #endif
16279 : : #ifdef MFD_HUGE_16MB
16280 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
16281 : : #endif
16282 : : #ifdef MFD_HUGE_32MB
16283 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
16284 : : #endif
16285 : : #ifdef MFD_HUGE_256MB
16286 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
16287 : : #endif
16288 : : #ifdef MFD_HUGE_512MB
16289 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
16290 : : #endif
16291 : : #ifdef MFD_HUGE_1GB
16292 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
16293 : : #endif
16294 : : #ifdef MFD_HUGE_2GB
16295 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
16296 : : #endif
16297 : : #ifdef MFD_HUGE_16GB
16298 [ - + ]: 26 : if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
16299 : : #endif
16300 : : #endif /* HAVE_MEMFD_CREATE */
16301 : :
16302 : : #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
16303 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
16304 : : #ifdef EFD_NONBLOCK
16305 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
16306 : : #endif
16307 : : #ifdef EFD_SEMAPHORE
16308 [ - + ]: 26 : if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
16309 : : #endif
16310 : : #endif /* HAVE_EVENTFD && EFD_CLOEXEC */
16311 : :
16312 : : #if defined(__APPLE__)
16313 : : if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
16314 : : if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
16315 : : if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
16316 : : if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
16317 : : #endif
16318 : :
16319 : : #ifdef MS_WINDOWS
16320 : : if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
16321 : : if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
16322 : : if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
16323 : : if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
16324 : : if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
16325 : : #endif
16326 : :
16327 : 26 : return 0;
16328 : : }
16329 : :
16330 : :
16331 : :
16332 : : #define PROBE(name, test) \
16333 : : static int name(void) \
16334 : : { \
16335 : : if (test) { \
16336 : : return 1; \
16337 : : } else { \
16338 : : return 0; \
16339 : : } \
16340 : : }
16341 : :
16342 : : #ifdef HAVE_FSTATAT
16343 : 26 : PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
16344 : : #endif
16345 : :
16346 : : #ifdef HAVE_FACCESSAT
16347 : 26 : PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
16348 : : #endif
16349 : :
16350 : : #ifdef HAVE_FCHMODAT
16351 : 26 : PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
16352 : : #endif
16353 : :
16354 : : #ifdef HAVE_FCHOWNAT
16355 : 26 : PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
16356 : : #endif
16357 : :
16358 : : #ifdef HAVE_LINKAT
16359 : 26 : PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
16360 : : #endif
16361 : :
16362 : : #ifdef HAVE_FDOPENDIR
16363 : 26 : PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
16364 : : #endif
16365 : :
16366 : : #ifdef HAVE_MKDIRAT
16367 : 26 : PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
16368 : : #endif
16369 : :
16370 : : #ifdef HAVE_MKFIFOAT
16371 : 26 : PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
16372 : : #endif
16373 : :
16374 : : #ifdef HAVE_MKNODAT
16375 : 26 : PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
16376 : : #endif
16377 : :
16378 : : #ifdef HAVE_RENAMEAT
16379 : 26 : PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
16380 : : #endif
16381 : :
16382 : : #ifdef HAVE_UNLINKAT
16383 : 26 : PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
16384 : : #endif
16385 : :
16386 : : #ifdef HAVE_OPENAT
16387 : 26 : PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
16388 : : #endif
16389 : :
16390 : : #ifdef HAVE_READLINKAT
16391 : 26 : PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
16392 : : #endif
16393 : :
16394 : : #ifdef HAVE_SYMLINKAT
16395 : 26 : PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
16396 : : #endif
16397 : :
16398 : : #ifdef HAVE_FUTIMENS
16399 : 26 : PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
16400 : : #endif
16401 : :
16402 : : #ifdef HAVE_UTIMENSAT
16403 : 26 : PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
16404 : : #endif
16405 : :
16406 : :
16407 : :
16408 : :
16409 : : static const struct have_function {
16410 : : const char * const label;
16411 : : int (*probe)(void);
16412 : : } have_functions[] = {
16413 : :
16414 : : #ifdef HAVE_EVENTFD
16415 : : {"HAVE_EVENTFD", NULL},
16416 : : #endif
16417 : :
16418 : : #ifdef HAVE_FACCESSAT
16419 : : { "HAVE_FACCESSAT", probe_faccessat },
16420 : : #endif
16421 : :
16422 : : #ifdef HAVE_FCHDIR
16423 : : { "HAVE_FCHDIR", NULL },
16424 : : #endif
16425 : :
16426 : : #ifdef HAVE_FCHMOD
16427 : : { "HAVE_FCHMOD", NULL },
16428 : : #endif
16429 : :
16430 : : #ifdef HAVE_FCHMODAT
16431 : : { "HAVE_FCHMODAT", probe_fchmodat },
16432 : : #endif
16433 : :
16434 : : #ifdef HAVE_FCHOWN
16435 : : { "HAVE_FCHOWN", NULL },
16436 : : #endif
16437 : :
16438 : : #ifdef HAVE_FCHOWNAT
16439 : : { "HAVE_FCHOWNAT", probe_fchownat },
16440 : : #endif
16441 : :
16442 : : #ifdef HAVE_FEXECVE
16443 : : { "HAVE_FEXECVE", NULL },
16444 : : #endif
16445 : :
16446 : : #ifdef HAVE_FDOPENDIR
16447 : : { "HAVE_FDOPENDIR", probe_fdopendir },
16448 : : #endif
16449 : :
16450 : : #ifdef HAVE_FPATHCONF
16451 : : { "HAVE_FPATHCONF", NULL },
16452 : : #endif
16453 : :
16454 : : #ifdef HAVE_FSTATAT
16455 : : { "HAVE_FSTATAT", probe_fstatat },
16456 : : #endif
16457 : :
16458 : : #ifdef HAVE_FSTATVFS
16459 : : { "HAVE_FSTATVFS", NULL },
16460 : : #endif
16461 : :
16462 : : #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
16463 : : { "HAVE_FTRUNCATE", NULL },
16464 : : #endif
16465 : :
16466 : : #ifdef HAVE_FUTIMENS
16467 : : { "HAVE_FUTIMENS", probe_futimens },
16468 : : #endif
16469 : :
16470 : : #ifdef HAVE_FUTIMES
16471 : : { "HAVE_FUTIMES", NULL },
16472 : : #endif
16473 : :
16474 : : #ifdef HAVE_FUTIMESAT
16475 : : { "HAVE_FUTIMESAT", NULL },
16476 : : #endif
16477 : :
16478 : : #ifdef HAVE_LINKAT
16479 : : { "HAVE_LINKAT", probe_linkat },
16480 : : #endif
16481 : :
16482 : : #ifdef HAVE_LCHFLAGS
16483 : : { "HAVE_LCHFLAGS", NULL },
16484 : : #endif
16485 : :
16486 : : #ifdef HAVE_LCHMOD
16487 : : { "HAVE_LCHMOD", NULL },
16488 : : #endif
16489 : :
16490 : : #ifdef HAVE_LCHOWN
16491 : : { "HAVE_LCHOWN", NULL },
16492 : : #endif
16493 : :
16494 : : #ifdef HAVE_LSTAT
16495 : : { "HAVE_LSTAT", NULL },
16496 : : #endif
16497 : :
16498 : : #ifdef HAVE_LUTIMES
16499 : : { "HAVE_LUTIMES", NULL },
16500 : : #endif
16501 : :
16502 : : #ifdef HAVE_MEMFD_CREATE
16503 : : { "HAVE_MEMFD_CREATE", NULL },
16504 : : #endif
16505 : :
16506 : : #ifdef HAVE_MKDIRAT
16507 : : { "HAVE_MKDIRAT", probe_mkdirat },
16508 : : #endif
16509 : :
16510 : : #ifdef HAVE_MKFIFOAT
16511 : : { "HAVE_MKFIFOAT", probe_mkfifoat },
16512 : : #endif
16513 : :
16514 : : #ifdef HAVE_MKNODAT
16515 : : { "HAVE_MKNODAT", probe_mknodat },
16516 : : #endif
16517 : :
16518 : : #ifdef HAVE_OPENAT
16519 : : { "HAVE_OPENAT", probe_openat },
16520 : : #endif
16521 : :
16522 : : #ifdef HAVE_READLINKAT
16523 : : { "HAVE_READLINKAT", probe_readlinkat },
16524 : : #endif
16525 : :
16526 : : #ifdef HAVE_RENAMEAT
16527 : : { "HAVE_RENAMEAT", probe_renameat },
16528 : : #endif
16529 : :
16530 : : #ifdef HAVE_SYMLINKAT
16531 : : { "HAVE_SYMLINKAT", probe_symlinkat },
16532 : : #endif
16533 : :
16534 : : #ifdef HAVE_UNLINKAT
16535 : : { "HAVE_UNLINKAT", probe_unlinkat },
16536 : : #endif
16537 : :
16538 : : #ifdef HAVE_UTIMENSAT
16539 : : { "HAVE_UTIMENSAT", probe_utimensat },
16540 : : #endif
16541 : :
16542 : : #ifdef MS_WINDOWS
16543 : : { "MS_WINDOWS", NULL },
16544 : : #endif
16545 : :
16546 : : { NULL, NULL }
16547 : : };
16548 : :
16549 : :
16550 : : static int
16551 : 26 : posixmodule_exec(PyObject *m)
16552 : : {
16553 : 26 : _posixstate *state = get_posix_state(m);
16554 : :
16555 : : #if defined(HAVE_PWRITEV)
16556 : : if (HAVE_PWRITEV_RUNTIME) {} else {
16557 : : PyObject* dct = PyModule_GetDict(m);
16558 : :
16559 : : if (dct == NULL) {
16560 : : return -1;
16561 : : }
16562 : :
16563 : : if (PyDict_DelItemString(dct, "pwritev") == -1) {
16564 : : PyErr_Clear();
16565 : : }
16566 : : if (PyDict_DelItemString(dct, "preadv") == -1) {
16567 : : PyErr_Clear();
16568 : : }
16569 : : }
16570 : : #endif
16571 : :
16572 : : /* Initialize environ dictionary */
16573 : 26 : PyObject *v = convertenviron();
16574 : 26 : Py_XINCREF(v);
16575 [ + - - + ]: 26 : if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
16576 : 0 : return -1;
16577 : 26 : Py_DECREF(v);
16578 : :
16579 [ - + ]: 26 : if (all_ins(m))
16580 : 0 : return -1;
16581 : :
16582 [ - + ]: 26 : if (setup_confname_tables(m))
16583 : 0 : return -1;
16584 : :
16585 : 26 : PyModule_AddObject(m, "error", Py_NewRef(PyExc_OSError));
16586 : :
16587 : : #if defined(HAVE_WAITID) && !defined(__APPLE__)
16588 : 26 : waitid_result_desc.name = MODNAME ".waitid_result";
16589 : 26 : PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
16590 [ - + ]: 26 : if (WaitidResultType == NULL) {
16591 : 0 : return -1;
16592 : : }
16593 : 26 : PyModule_AddObject(m, "waitid_result", Py_NewRef(WaitidResultType));
16594 : 26 : state->WaitidResultType = WaitidResultType;
16595 : : #endif
16596 : :
16597 : 26 : stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
16598 : 26 : stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
16599 : 26 : stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
16600 : 26 : stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
16601 : 26 : PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
16602 [ - + ]: 26 : if (StatResultType == NULL) {
16603 : 0 : return -1;
16604 : : }
16605 : 26 : PyModule_AddObject(m, "stat_result", Py_NewRef(StatResultType));
16606 : 26 : state->StatResultType = StatResultType;
16607 : 26 : state->statresult_new_orig = ((PyTypeObject *)StatResultType)->tp_new;
16608 : 26 : ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
16609 : :
16610 : 26 : statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
16611 : 26 : PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
16612 [ - + ]: 26 : if (StatVFSResultType == NULL) {
16613 : 0 : return -1;
16614 : : }
16615 : 26 : PyModule_AddObject(m, "statvfs_result", Py_NewRef(StatVFSResultType));
16616 : 26 : state->StatVFSResultType = StatVFSResultType;
16617 : :
16618 : : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
16619 : 26 : sched_param_desc.name = MODNAME ".sched_param";
16620 : 26 : PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
16621 [ - + ]: 26 : if (SchedParamType == NULL) {
16622 : 0 : return -1;
16623 : : }
16624 : 26 : PyModule_AddObject(m, "sched_param", Py_NewRef(SchedParamType));
16625 : 26 : state->SchedParamType = SchedParamType;
16626 : 26 : ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
16627 : : #endif
16628 : :
16629 : : /* initialize TerminalSize_info */
16630 : 26 : PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
16631 [ - + ]: 26 : if (TerminalSizeType == NULL) {
16632 : 0 : return -1;
16633 : : }
16634 : 26 : PyModule_AddObject(m, "terminal_size", Py_NewRef(TerminalSizeType));
16635 : 26 : state->TerminalSizeType = TerminalSizeType;
16636 : :
16637 : : /* initialize scandir types */
16638 : 26 : PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
16639 [ - + ]: 26 : if (ScandirIteratorType == NULL) {
16640 : 0 : return -1;
16641 : : }
16642 : 26 : state->ScandirIteratorType = ScandirIteratorType;
16643 : :
16644 : 26 : PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
16645 [ - + ]: 26 : if (DirEntryType == NULL) {
16646 : 0 : return -1;
16647 : : }
16648 : 26 : PyModule_AddObject(m, "DirEntry", Py_NewRef(DirEntryType));
16649 : 26 : state->DirEntryType = DirEntryType;
16650 : :
16651 : 26 : times_result_desc.name = MODNAME ".times_result";
16652 : 26 : PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(×_result_desc);
16653 [ - + ]: 26 : if (TimesResultType == NULL) {
16654 : 0 : return -1;
16655 : : }
16656 : 26 : PyModule_AddObject(m, "times_result", Py_NewRef(TimesResultType));
16657 : 26 : state->TimesResultType = TimesResultType;
16658 : :
16659 : 26 : PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
16660 [ - + ]: 26 : if (UnameResultType == NULL) {
16661 : 0 : return -1;
16662 : : }
16663 : : ;
16664 : 26 : PyModule_AddObject(m, "uname_result", Py_NewRef(UnameResultType));
16665 : 26 : state->UnameResultType = (PyObject *)UnameResultType;
16666 : :
16667 [ - + ]: 26 : if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
16668 : 0 : return -1;
16669 : : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
16670 : 26 : state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
16671 [ - + ]: 26 : if (state->struct_rusage == NULL)
16672 : 0 : return -1;
16673 : : #endif
16674 : 26 : state->st_mode = PyUnicode_InternFromString("st_mode");
16675 [ - + ]: 26 : if (state->st_mode == NULL)
16676 : 0 : return -1;
16677 : :
16678 : : /* suppress "function not used" warnings */
16679 : : {
16680 : : int ignored;
16681 : 26 : fd_specified("", -1);
16682 : 26 : follow_symlinks_specified("", 1);
16683 : 26 : dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
16684 : 26 : dir_fd_converter(Py_None, &ignored);
16685 : 26 : dir_fd_unavailable(Py_None, &ignored);
16686 : : }
16687 : :
16688 : : /*
16689 : : * provide list of locally available functions
16690 : : * so os.py can populate support_* lists
16691 : : */
16692 : 26 : PyObject *list = PyList_New(0);
16693 [ - + ]: 26 : if (!list) {
16694 : 0 : return -1;
16695 : : }
16696 [ + + ]: 806 : for (const struct have_function *trace = have_functions; trace->label; trace++) {
16697 : : PyObject *unicode;
16698 [ + + - + ]: 780 : if (trace->probe && !trace->probe()) continue;
16699 : 780 : unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
16700 [ - + ]: 780 : if (!unicode)
16701 : 0 : return -1;
16702 [ - + ]: 780 : if (PyList_Append(list, unicode))
16703 : 0 : return -1;
16704 : 780 : Py_DECREF(unicode);
16705 : : }
16706 : :
16707 : 26 : PyModule_AddObject(m, "_have_functions", list);
16708 : :
16709 : 26 : return 0;
16710 : : }
16711 : :
16712 : :
16713 : : static PyModuleDef_Slot posixmodile_slots[] = {
16714 : : {Py_mod_exec, posixmodule_exec},
16715 : : {0, NULL}
16716 : : };
16717 : :
16718 : : static struct PyModuleDef posixmodule = {
16719 : : PyModuleDef_HEAD_INIT,
16720 : : .m_name = MODNAME,
16721 : : .m_doc = posix__doc__,
16722 : : .m_size = sizeof(_posixstate),
16723 : : .m_methods = posix_methods,
16724 : : .m_slots = posixmodile_slots,
16725 : : .m_traverse = _posix_traverse,
16726 : : .m_clear = _posix_clear,
16727 : : .m_free = _posix_free,
16728 : : };
16729 : :
16730 : : PyMODINIT_FUNC
16731 : 26 : INITFUNC(void)
16732 : : {
16733 : 26 : return PyModuleDef_Init(&posixmodule);
16734 : : }
16735 : :
16736 : : #ifdef __cplusplus
16737 : : }
16738 : : #endif
|