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 : : // Include <windows.h> before pycore internal headers. FSCTL_GET_REPARSE_POINT
14 : : // is not exported by <windows.h> if the WIN32_LEAN_AND_MEAN macro is defined,
15 : : // whereas pycore_condvar.h defines the WIN32_LEAN_AND_MEAN macro.
16 : : #ifdef MS_WINDOWS
17 : : # include <windows.h>
18 : : # include <pathcch.h>
19 : : #endif
20 : :
21 : : #ifdef __VXWORKS__
22 : : # include "pycore_bitutils.h" // _Py_popcount32()
23 : : #endif
24 : : #include "pycore_call.h" // _PyObject_CallNoArgs()
25 : : #include "pycore_ceval.h" // _PyEval_ReInitThreads()
26 : : #include "pycore_fileutils.h" // _Py_closerange()
27 : : #include "pycore_import.h" // _PyImport_ReInitLock()
28 : : #include "pycore_initconfig.h" // _PyStatus_EXCEPTION()
29 : : #include "pycore_moduleobject.h" // _PyModule_GetState()
30 : : #include "pycore_object.h" // _PyObject_LookupSpecial()
31 : : #include "pycore_pystate.h" // _PyInterpreterState_GET()
32 : : #include "pycore_signal.h" // Py_NSIG
33 : :
34 : : #include "structmember.h" // PyMemberDef
35 : : #ifndef MS_WINDOWS
36 : : # include "posixmodule.h"
37 : : #else
38 : : # include "winreparse.h"
39 : : #endif
40 : :
41 : : #if !defined(EX_OK) && defined(EXIT_SUCCESS)
42 : : # define EX_OK EXIT_SUCCESS
43 : : #endif
44 : :
45 : : /* On android API level 21, 'AT_EACCESS' is not declared although
46 : : * HAVE_FACCESSAT is defined. */
47 : : #ifdef __ANDROID__
48 : : # undef HAVE_FACCESSAT
49 : : #endif
50 : :
51 : : #include <stdio.h> // ctermid()
52 : : #include <stdlib.h> // system()
53 : :
54 : : /*
55 : : * A number of APIs are available on macOS from a certain macOS version.
56 : : * To support building with a new SDK while deploying to older versions
57 : : * the availability test is split into two:
58 : : * - HAVE_<FUNCTION>: The configure check for compile time availability
59 : : * - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
60 : : *
61 : : * The latter is always true when not on macOS, or when using a compiler
62 : : * that does not support __has_builtin (older versions of Xcode).
63 : : *
64 : : * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
65 : : * if (HAVE_<FUNCTION>_RUNTIME) { ... }
66 : : *
67 : : * In mixing the test with other tests or using negations will result in compile
68 : : * errors.
69 : : */
70 : : #if defined(__APPLE__)
71 : :
72 : : #if defined(__has_builtin)
73 : : #if __has_builtin(__builtin_available)
74 : : #define HAVE_BUILTIN_AVAILABLE 1
75 : : #endif
76 : : #endif
77 : :
78 : : #ifdef HAVE_BUILTIN_AVAILABLE
79 : : # define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
80 : : # define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
81 : : # define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
82 : : # define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
83 : : # define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
84 : : # define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
85 : : # define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
86 : : # define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
87 : : # define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
88 : : # define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
89 : : # define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
90 : : # define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
91 : : # define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
92 : : # define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
93 : : # define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
94 : :
95 : : # define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
96 : :
97 : : #else /* Xcode 8 or earlier */
98 : :
99 : : /* __builtin_available is not present in these compilers, but
100 : : * some of the symbols might be weak linked (10.10 SDK or later
101 : : * deploying on 10.9.
102 : : *
103 : : * Fall back to the older style of availability checking for
104 : : * symbols introduced in macOS 10.10.
105 : : */
106 : :
107 : : # ifdef HAVE_FSTATAT
108 : : # define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
109 : : # endif
110 : :
111 : : # ifdef HAVE_FACCESSAT
112 : : # define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
113 : : # endif
114 : :
115 : : # ifdef HAVE_FCHMODAT
116 : : # define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
117 : : # endif
118 : :
119 : : # ifdef HAVE_FCHOWNAT
120 : : # define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
121 : : # endif
122 : :
123 : : # ifdef HAVE_LINKAT
124 : : # define HAVE_LINKAT_RUNTIME (linkat != NULL)
125 : : # endif
126 : :
127 : : # ifdef HAVE_FDOPENDIR
128 : : # define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
129 : : # endif
130 : :
131 : : # ifdef HAVE_MKDIRAT
132 : : # define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
133 : : # endif
134 : :
135 : : # ifdef HAVE_RENAMEAT
136 : : # define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
137 : : # endif
138 : :
139 : : # ifdef HAVE_UNLINKAT
140 : : # define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
141 : : # endif
142 : :
143 : : # ifdef HAVE_OPENAT
144 : : # define HAVE_OPENAT_RUNTIME (openat != NULL)
145 : : # endif
146 : :
147 : : # ifdef HAVE_READLINKAT
148 : : # define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
149 : : # endif
150 : :
151 : : # ifdef HAVE_SYMLINKAT
152 : : # define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
153 : : # endif
154 : :
155 : : #endif
156 : :
157 : : #ifdef HAVE_FUTIMESAT
158 : : /* Some of the logic for weak linking depends on this assertion */
159 : : # error "HAVE_FUTIMESAT unexpectedly defined"
160 : : #endif
161 : :
162 : : #else
163 : : # define HAVE_FSTATAT_RUNTIME 1
164 : : # define HAVE_FACCESSAT_RUNTIME 1
165 : : # define HAVE_FCHMODAT_RUNTIME 1
166 : : # define HAVE_FCHOWNAT_RUNTIME 1
167 : : # define HAVE_LINKAT_RUNTIME 1
168 : : # define HAVE_FDOPENDIR_RUNTIME 1
169 : : # define HAVE_MKDIRAT_RUNTIME 1
170 : : # define HAVE_RENAMEAT_RUNTIME 1
171 : : # define HAVE_UNLINKAT_RUNTIME 1
172 : : # define HAVE_OPENAT_RUNTIME 1
173 : : # define HAVE_READLINKAT_RUNTIME 1
174 : : # define HAVE_SYMLINKAT_RUNTIME 1
175 : : # define HAVE_FUTIMENS_RUNTIME 1
176 : : # define HAVE_UTIMENSAT_RUNTIME 1
177 : : # define HAVE_PWRITEV_RUNTIME 1
178 : : #endif
179 : :
180 : :
181 : : #ifdef __cplusplus
182 : : extern "C" {
183 : : #endif
184 : :
185 : : PyDoc_STRVAR(posix__doc__,
186 : : "This module provides access to operating system functionality that is\n\
187 : : standardized by the C Standard and the POSIX standard (a thinly\n\
188 : : disguised Unix interface). Refer to the library manual and\n\
189 : : corresponding Unix manual entries for more information on calls.");
190 : :
191 : :
192 : : #ifdef HAVE_SYS_UIO_H
193 : : # include <sys/uio.h>
194 : : #endif
195 : :
196 : : #ifdef HAVE_SYS_SYSMACROS_H
197 : : /* GNU C Library: major(), minor(), makedev() */
198 : : # include <sys/sysmacros.h>
199 : : #endif
200 : :
201 : : #ifdef HAVE_SYS_TYPES_H
202 : : # include <sys/types.h>
203 : : #endif /* HAVE_SYS_TYPES_H */
204 : :
205 : : #ifdef HAVE_SYS_STAT_H
206 : : # include <sys/stat.h>
207 : : #endif /* HAVE_SYS_STAT_H */
208 : :
209 : : #ifdef HAVE_SYS_WAIT_H
210 : : # include <sys/wait.h> // WNOHANG
211 : : #endif
212 : : #ifdef HAVE_LINUX_WAIT_H
213 : : # include <linux/wait.h> // P_PIDFD
214 : : #endif
215 : :
216 : : #ifdef HAVE_SIGNAL_H
217 : : # include <signal.h>
218 : : #endif
219 : :
220 : : #ifdef HAVE_FCNTL_H
221 : : # include <fcntl.h>
222 : : #endif
223 : :
224 : : #ifdef HAVE_GRP_H
225 : : # include <grp.h>
226 : : #endif
227 : :
228 : : #ifdef HAVE_SYSEXITS_H
229 : : # include <sysexits.h>
230 : : #endif
231 : :
232 : : #ifdef HAVE_SYS_LOADAVG_H
233 : : # include <sys/loadavg.h>
234 : : #endif
235 : :
236 : : #ifdef HAVE_SYS_SENDFILE_H
237 : : # include <sys/sendfile.h>
238 : : #endif
239 : :
240 : : #if defined(__APPLE__)
241 : : # include <copyfile.h>
242 : : #endif
243 : :
244 : : #ifdef HAVE_SCHED_H
245 : : # include <sched.h>
246 : : #endif
247 : :
248 : : #ifdef HAVE_COPY_FILE_RANGE
249 : : # include <unistd.h>
250 : : #endif
251 : :
252 : : #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
253 : : # undef HAVE_SCHED_SETAFFINITY
254 : : #endif
255 : :
256 : : #if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
257 : : # define USE_XATTRS
258 : : #endif
259 : :
260 : : #ifdef USE_XATTRS
261 : : # include <sys/xattr.h>
262 : : #endif
263 : :
264 : : #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
265 : : # ifdef HAVE_SYS_SOCKET_H
266 : : # include <sys/socket.h>
267 : : # endif
268 : : #endif
269 : :
270 : : #ifdef HAVE_DLFCN_H
271 : : # include <dlfcn.h>
272 : : #endif
273 : :
274 : : #ifdef __hpux
275 : : # include <sys/mpctl.h>
276 : : #endif
277 : :
278 : : #if defined(__DragonFly__) || \
279 : : defined(__OpenBSD__) || \
280 : : defined(__FreeBSD__) || \
281 : : defined(__NetBSD__) || \
282 : : defined(__APPLE__)
283 : : # include <sys/sysctl.h>
284 : : #endif
285 : :
286 : : #ifdef HAVE_LINUX_RANDOM_H
287 : : # include <linux/random.h>
288 : : #endif
289 : : #ifdef HAVE_GETRANDOM_SYSCALL
290 : : # include <sys/syscall.h>
291 : : #endif
292 : :
293 : : #if defined(MS_WINDOWS)
294 : : # define TERMSIZE_USE_CONIO
295 : : #elif defined(HAVE_SYS_IOCTL_H)
296 : : # include <sys/ioctl.h>
297 : : # if defined(HAVE_TERMIOS_H)
298 : : # include <termios.h>
299 : : # endif
300 : : # if defined(TIOCGWINSZ)
301 : : # define TERMSIZE_USE_IOCTL
302 : : # endif
303 : : #endif /* MS_WINDOWS */
304 : :
305 : : /* Various compilers have only certain posix functions */
306 : : /* XXX Gosh I wish these were all moved into pyconfig.h */
307 : : #if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */
308 : : # define HAVE_OPENDIR 1
309 : : # define HAVE_SYSTEM 1
310 : : # include <process.h>
311 : : #else
312 : : # ifdef _MSC_VER
313 : : /* Microsoft compiler */
314 : : # define HAVE_GETPPID 1
315 : : # define HAVE_GETLOGIN 1
316 : : # define HAVE_SPAWNV 1
317 : : # define HAVE_EXECV 1
318 : : # define HAVE_WSPAWNV 1
319 : : # define HAVE_WEXECV 1
320 : : # define HAVE_PIPE 1
321 : : # define HAVE_SYSTEM 1
322 : : # define HAVE_CWAIT 1
323 : : # define HAVE_FSYNC 1
324 : : # define fsync _commit
325 : : # endif /* _MSC_VER */
326 : : #endif /* ! __WATCOMC__ || __QNX__ */
327 : :
328 : : /*[clinic input]
329 : : # one of the few times we lie about this name!
330 : : module os
331 : : [clinic start generated code]*/
332 : : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
333 : :
334 : : #ifndef _MSC_VER
335 : :
336 : : #if defined(__sgi)&&_COMPILER_VERSION>=700
337 : : /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
338 : : (default) */
339 : : extern char *ctermid_r(char *);
340 : : #endif
341 : :
342 : : #endif /* !_MSC_VER */
343 : :
344 : : #if defined(__VXWORKS__)
345 : : # include <vxCpuLib.h>
346 : : # include <rtpLib.h>
347 : : # include <wait.h>
348 : : # include <taskLib.h>
349 : : # ifndef _P_WAIT
350 : : # define _P_WAIT 0
351 : : # define _P_NOWAIT 1
352 : : # define _P_NOWAITO 1
353 : : # endif
354 : : #endif /* __VXWORKS__ */
355 : :
356 : : #ifdef HAVE_POSIX_SPAWN
357 : : # include <spawn.h>
358 : : #endif
359 : :
360 : : #ifdef HAVE_UTIME_H
361 : : # include <utime.h>
362 : : #endif /* HAVE_UTIME_H */
363 : :
364 : : #ifdef HAVE_SYS_UTIME_H
365 : : # include <sys/utime.h>
366 : : # define HAVE_UTIME_H /* pretend we do for the rest of this file */
367 : : #endif /* HAVE_SYS_UTIME_H */
368 : :
369 : : #ifdef HAVE_SYS_TIMES_H
370 : : # include <sys/times.h>
371 : : #endif /* HAVE_SYS_TIMES_H */
372 : :
373 : : #ifdef HAVE_SYS_PARAM_H
374 : : # include <sys/param.h>
375 : : #endif /* HAVE_SYS_PARAM_H */
376 : :
377 : : #ifdef HAVE_SYS_UTSNAME_H
378 : : # include <sys/utsname.h>
379 : : #endif /* HAVE_SYS_UTSNAME_H */
380 : :
381 : : #ifdef HAVE_DIRENT_H
382 : : # include <dirent.h>
383 : : # define NAMLEN(dirent) strlen((dirent)->d_name)
384 : : #else
385 : : # if defined(__WATCOMC__) && !defined(__QNX__)
386 : : # include <direct.h>
387 : : # define NAMLEN(dirent) strlen((dirent)->d_name)
388 : : # else
389 : : # define dirent direct
390 : : # define NAMLEN(dirent) (dirent)->d_namlen
391 : : # endif
392 : : # ifdef HAVE_SYS_NDIR_H
393 : : # include <sys/ndir.h>
394 : : # endif
395 : : # ifdef HAVE_SYS_DIR_H
396 : : # include <sys/dir.h>
397 : : # endif
398 : : # ifdef HAVE_NDIR_H
399 : : # include <ndir.h>
400 : : # endif
401 : : #endif
402 : :
403 : : #ifdef _MSC_VER
404 : : # ifdef HAVE_DIRECT_H
405 : : # include <direct.h>
406 : : # endif
407 : : # ifdef HAVE_IO_H
408 : : # include <io.h>
409 : : # endif
410 : : # ifdef HAVE_PROCESS_H
411 : : # include <process.h>
412 : : # endif
413 : : # ifndef IO_REPARSE_TAG_SYMLINK
414 : : # define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
415 : : # endif
416 : : # ifndef IO_REPARSE_TAG_MOUNT_POINT
417 : : # define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
418 : : # endif
419 : : # include "osdefs.h" // SEP
420 : : # include <malloc.h>
421 : : # include <windows.h>
422 : : # include <shellapi.h> // ShellExecute()
423 : : # include <lmcons.h> // UNLEN
424 : : # define HAVE_SYMLINK
425 : : #endif /* _MSC_VER */
426 : :
427 : : #ifndef MAXPATHLEN
428 : : # if defined(PATH_MAX) && PATH_MAX > 1024
429 : : # define MAXPATHLEN PATH_MAX
430 : : # else
431 : : # define MAXPATHLEN 1024
432 : : # endif
433 : : #endif /* MAXPATHLEN */
434 : :
435 : : #ifdef UNION_WAIT
436 : : /* Emulate some macros on systems that have a union instead of macros */
437 : : # ifndef WIFEXITED
438 : : # define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
439 : : # endif
440 : : # ifndef WEXITSTATUS
441 : : # define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
442 : : # endif
443 : : # ifndef WTERMSIG
444 : : # define WTERMSIG(u_wait) ((u_wait).w_termsig)
445 : : # endif
446 : : # define WAIT_TYPE union wait
447 : : # define WAIT_STATUS_INT(s) (s.w_status)
448 : : #else
449 : : /* !UNION_WAIT */
450 : : # define WAIT_TYPE int
451 : : # define WAIT_STATUS_INT(s) (s)
452 : : #endif /* UNION_WAIT */
453 : :
454 : : /* Don't use the "_r" form if we don't need it (also, won't have a
455 : : prototype for it, at least on Solaris -- maybe others as well?). */
456 : : #if defined(HAVE_CTERMID_R)
457 : : # define USE_CTERMID_R
458 : : #endif
459 : :
460 : : /* choose the appropriate stat and fstat functions and return structs */
461 : : #undef STAT
462 : : #undef FSTAT
463 : : #undef STRUCT_STAT
464 : : #ifdef MS_WINDOWS
465 : : # define STAT win32_stat
466 : : # define LSTAT win32_lstat
467 : : # define FSTAT _Py_fstat_noraise
468 : : # define STRUCT_STAT struct _Py_stat_struct
469 : : #else
470 : : # define STAT stat
471 : : # define LSTAT lstat
472 : : # define FSTAT fstat
473 : : # define STRUCT_STAT struct stat
474 : : #endif
475 : :
476 : : #if defined(MAJOR_IN_MKDEV)
477 : : # include <sys/mkdev.h>
478 : : #else
479 : : # if defined(MAJOR_IN_SYSMACROS)
480 : : # include <sys/sysmacros.h>
481 : : # endif
482 : : # if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
483 : : # include <sys/mkdev.h>
484 : : # endif
485 : : #endif
486 : :
487 : : #ifdef MS_WINDOWS
488 : : # define INITFUNC PyInit_nt
489 : : # define MODNAME "nt"
490 : : #else
491 : : # define INITFUNC PyInit_posix
492 : : # define MODNAME "posix"
493 : : #endif
494 : :
495 : : #if defined(__sun)
496 : : /* Something to implement in autoconf, not present in autoconf 2.69 */
497 : : # define HAVE_STRUCT_STAT_ST_FSTYPE 1
498 : : #endif
499 : :
500 : : /* memfd_create is either defined in sys/mman.h or sys/memfd.h
501 : : * linux/memfd.h defines additional flags
502 : : */
503 : : #ifdef HAVE_SYS_MMAN_H
504 : : # include <sys/mman.h>
505 : : #endif
506 : : #ifdef HAVE_SYS_MEMFD_H
507 : : # include <sys/memfd.h>
508 : : #endif
509 : : #ifdef HAVE_LINUX_MEMFD_H
510 : : # include <linux/memfd.h>
511 : : #endif
512 : :
513 : : /* eventfd() */
514 : : #ifdef HAVE_SYS_EVENTFD_H
515 : : # include <sys/eventfd.h>
516 : : #endif
517 : :
518 : : #ifdef _Py_MEMORY_SANITIZER
519 : : # include <sanitizer/msan_interface.h>
520 : : #endif
521 : :
522 : : #ifdef HAVE_FORK
523 : : static void
524 : 3036 : run_at_forkers(PyObject *lst, int reverse)
525 : : {
526 : : Py_ssize_t i;
527 : : PyObject *cpy;
528 : :
529 [ + + ]: 3036 : if (lst != NULL) {
530 : : assert(PyList_CheckExact(lst));
531 : :
532 : : /* Use a list copy in case register_at_fork() is called from
533 : : * one of the callbacks.
534 : : */
535 : 2296 : cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
536 [ - + ]: 2296 : if (cpy == NULL)
537 : 0 : PyErr_WriteUnraisable(lst);
538 : : else {
539 [ + + ]: 2296 : if (reverse)
540 : 1145 : PyList_Reverse(cpy);
541 [ + + ]: 5102 : for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
542 : : PyObject *func, *res;
543 : 2806 : func = PyList_GET_ITEM(cpy, i);
544 : 2806 : res = _PyObject_CallNoArgs(func);
545 [ - + ]: 2806 : if (res == NULL)
546 : 0 : PyErr_WriteUnraisable(func);
547 : : else
548 : 2806 : Py_DECREF(res);
549 : : }
550 : 2296 : Py_DECREF(cpy);
551 : : }
552 : : }
553 : 3036 : }
554 : :
555 : : void
556 : 1518 : PyOS_BeforeFork(void)
557 : : {
558 : 1518 : run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1);
559 : :
560 : 1518 : _PyImport_AcquireLock();
561 : 1518 : }
562 : :
563 : : void
564 : 1510 : PyOS_AfterFork_Parent(void)
565 : : {
566 [ - + ]: 1510 : if (_PyImport_ReleaseLock() <= 0)
567 : : Py_FatalError("failed releasing import lock after fork");
568 : :
569 : 1510 : run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0);
570 : 1510 : }
571 : :
572 : : void
573 : 8 : PyOS_AfterFork_Child(void)
574 : : {
575 : : PyStatus status;
576 : 8 : _PyRuntimeState *runtime = &_PyRuntime;
577 : :
578 : 8 : status = _PyGILState_Reinit(runtime);
579 [ - + ]: 8 : if (_PyStatus_EXCEPTION(status)) {
580 : 0 : goto fatal_error;
581 : : }
582 : :
583 : 8 : PyThreadState *tstate = _PyThreadState_GET();
584 : 8 : _Py_EnsureTstateNotNULL(tstate);
585 : :
586 : 8 : status = _PyEval_ReInitThreads(tstate);
587 [ - + ]: 8 : if (_PyStatus_EXCEPTION(status)) {
588 : 0 : goto fatal_error;
589 : : }
590 : :
591 : 8 : status = _PyImport_ReInitLock();
592 [ - + ]: 8 : if (_PyStatus_EXCEPTION(status)) {
593 : 0 : goto fatal_error;
594 : : }
595 : :
596 : 8 : _PySignal_AfterFork();
597 : :
598 : 8 : status = _PyRuntimeState_ReInitThreads(runtime);
599 [ - + ]: 8 : if (_PyStatus_EXCEPTION(status)) {
600 : 0 : goto fatal_error;
601 : : }
602 : :
603 : 8 : status = _PyInterpreterState_DeleteExceptMain(runtime);
604 [ - + ]: 8 : if (_PyStatus_EXCEPTION(status)) {
605 : 0 : goto fatal_error;
606 : : }
607 : : assert(_PyThreadState_GET() == tstate);
608 : :
609 : 8 : run_at_forkers(tstate->interp->after_forkers_child, 0);
610 : 8 : return;
611 : :
612 : 0 : fatal_error:
613 : 0 : Py_ExitStatusException(status);
614 : : }
615 : :
616 : : static int
617 : 9270 : register_at_forker(PyObject **lst, PyObject *func)
618 : : {
619 [ + + ]: 9270 : if (func == NULL) /* nothing to register? do nothing. */
620 : 4812 : return 0;
621 [ + + ]: 4458 : if (*lst == NULL) {
622 : 2477 : *lst = PyList_New(0);
623 [ - + ]: 2477 : if (*lst == NULL)
624 : 0 : return -1;
625 : : }
626 : 4458 : return PyList_Append(*lst, func);
627 : : }
628 : : #endif /* HAVE_FORK */
629 : :
630 : :
631 : : /* Legacy wrapper */
632 : : void
633 : 0 : PyOS_AfterFork(void)
634 : : {
635 : : #ifdef HAVE_FORK
636 : 0 : PyOS_AfterFork_Child();
637 : : #endif
638 : 0 : }
639 : :
640 : :
641 : : #ifdef MS_WINDOWS
642 : : /* defined in fileutils.c */
643 : : void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
644 : : void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
645 : : ULONG, struct _Py_stat_struct *);
646 : : #endif
647 : :
648 : :
649 : : #ifndef MS_WINDOWS
650 : : PyObject *
651 : 1220264 : _PyLong_FromUid(uid_t uid)
652 : : {
653 [ + + ]: 1220264 : if (uid == (uid_t)-1)
654 : 1 : return PyLong_FromLong(-1);
655 : 1220263 : return PyLong_FromUnsignedLong(uid);
656 : : }
657 : :
658 : : PyObject *
659 : 1221241 : _PyLong_FromGid(gid_t gid)
660 : : {
661 [ - + ]: 1221241 : if (gid == (gid_t)-1)
662 : 0 : return PyLong_FromLong(-1);
663 : 1221241 : return PyLong_FromUnsignedLong(gid);
664 : : }
665 : :
666 : : int
667 : 754 : _Py_Uid_Converter(PyObject *obj, uid_t *p)
668 : : {
669 : : uid_t uid;
670 : : PyObject *index;
671 : : int overflow;
672 : : long result;
673 : : unsigned long uresult;
674 : :
675 : 754 : index = _PyNumber_Index(obj);
676 [ + + ]: 754 : if (index == NULL) {
677 : 16 : PyErr_Format(PyExc_TypeError,
678 : : "uid should be integer, not %.200s",
679 : : _PyType_Name(Py_TYPE(obj)));
680 : 16 : return 0;
681 : : }
682 : :
683 : : /*
684 : : * Handling uid_t is complicated for two reasons:
685 : : * * Although uid_t is (always?) unsigned, it still
686 : : * accepts -1.
687 : : * * We don't know its size in advance--it may be
688 : : * bigger than an int, or it may be smaller than
689 : : * a long.
690 : : *
691 : : * So a bit of defensive programming is in order.
692 : : * Start with interpreting the value passed
693 : : * in as a signed long and see if it works.
694 : : */
695 : :
696 : 738 : result = PyLong_AsLongAndOverflow(index, &overflow);
697 : :
698 [ + + ]: 738 : if (!overflow) {
699 : 735 : uid = (uid_t)result;
700 : :
701 [ + + ]: 735 : if (result == -1) {
702 [ - + ]: 19 : if (PyErr_Occurred())
703 : 0 : goto fail;
704 : : /* It's a legitimate -1, we're done. */
705 : 19 : goto success;
706 : : }
707 : :
708 : : /* Any other negative number is disallowed. */
709 [ - + ]: 716 : if (result < 0)
710 : 0 : goto underflow;
711 : :
712 : : /* Ensure the value wasn't truncated. */
713 : 716 : if (sizeof(uid_t) < sizeof(long) &&
714 [ + + ]: 716 : (long)uid != result)
715 : 5 : goto underflow;
716 : 711 : goto success;
717 : : }
718 : :
719 [ + + ]: 3 : if (overflow < 0)
720 : 1 : goto underflow;
721 : :
722 : : /*
723 : : * Okay, the value overflowed a signed long. If it
724 : : * fits in an *unsigned* long, it may still be okay,
725 : : * as uid_t may be unsigned long on this platform.
726 : : */
727 : 2 : uresult = PyLong_AsUnsignedLong(index);
728 [ + - ]: 2 : if (PyErr_Occurred()) {
729 [ + - ]: 2 : if (PyErr_ExceptionMatches(PyExc_OverflowError))
730 : 2 : goto overflow;
731 : 0 : goto fail;
732 : : }
733 : :
734 : 0 : uid = (uid_t)uresult;
735 : :
736 : : /*
737 : : * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
738 : : * but this value would get interpreted as (uid_t)-1 by chown
739 : : * and its siblings. That's not what the user meant! So we
740 : : * throw an overflow exception instead. (We already
741 : : * handled a real -1 with PyLong_AsLongAndOverflow() above.)
742 : : */
743 [ # # ]: 0 : if (uid == (uid_t)-1)
744 : 0 : goto overflow;
745 : :
746 : : /* Ensure the value wasn't truncated. */
747 : 0 : if (sizeof(uid_t) < sizeof(long) &&
748 [ # # ]: 0 : (unsigned long)uid != uresult)
749 : 0 : goto overflow;
750 : : /* fallthrough */
751 : :
752 : 0 : success:
753 : 730 : Py_DECREF(index);
754 : 730 : *p = uid;
755 : 730 : return 1;
756 : :
757 : 6 : underflow:
758 : 6 : PyErr_SetString(PyExc_OverflowError,
759 : : "uid is less than minimum");
760 : 6 : goto fail;
761 : :
762 : 2 : overflow:
763 : 2 : PyErr_SetString(PyExc_OverflowError,
764 : : "uid is greater than maximum");
765 : : /* fallthrough */
766 : :
767 : 8 : fail:
768 : 8 : Py_DECREF(index);
769 : 8 : return 0;
770 : : }
771 : :
772 : : int
773 : 769 : _Py_Gid_Converter(PyObject *obj, gid_t *p)
774 : : {
775 : : gid_t gid;
776 : : PyObject *index;
777 : : int overflow;
778 : : long result;
779 : : unsigned long uresult;
780 : :
781 : 769 : index = _PyNumber_Index(obj);
782 [ + + ]: 769 : if (index == NULL) {
783 : 17 : PyErr_Format(PyExc_TypeError,
784 : : "gid should be integer, not %.200s",
785 : : _PyType_Name(Py_TYPE(obj)));
786 : 17 : return 0;
787 : : }
788 : :
789 : : /*
790 : : * Handling gid_t is complicated for two reasons:
791 : : * * Although gid_t is (always?) unsigned, it still
792 : : * accepts -1.
793 : : * * We don't know its size in advance--it may be
794 : : * bigger than an int, or it may be smaller than
795 : : * a long.
796 : : *
797 : : * So a bit of defensive programming is in order.
798 : : * Start with interpreting the value passed
799 : : * in as a signed long and see if it works.
800 : : */
801 : :
802 : 752 : result = PyLong_AsLongAndOverflow(index, &overflow);
803 : :
804 [ + + ]: 752 : if (!overflow) {
805 : 750 : gid = (gid_t)result;
806 : :
807 [ + + ]: 750 : if (result == -1) {
808 [ - + ]: 20 : if (PyErr_Occurred())
809 : 0 : goto fail;
810 : : /* It's a legitimate -1, we're done. */
811 : 20 : goto success;
812 : : }
813 : :
814 : : /* Any other negative number is disallowed. */
815 [ - + ]: 730 : if (result < 0) {
816 : 0 : goto underflow;
817 : : }
818 : :
819 : : /* Ensure the value wasn't truncated. */
820 : 730 : if (sizeof(gid_t) < sizeof(long) &&
821 [ + + ]: 730 : (long)gid != result)
822 : 4 : goto underflow;
823 : 726 : goto success;
824 : : }
825 : :
826 [ - + ]: 2 : if (overflow < 0)
827 : 0 : goto underflow;
828 : :
829 : : /*
830 : : * Okay, the value overflowed a signed long. If it
831 : : * fits in an *unsigned* long, it may still be okay,
832 : : * as gid_t may be unsigned long on this platform.
833 : : */
834 : 2 : uresult = PyLong_AsUnsignedLong(index);
835 [ + - ]: 2 : if (PyErr_Occurred()) {
836 [ + - ]: 2 : if (PyErr_ExceptionMatches(PyExc_OverflowError))
837 : 2 : goto overflow;
838 : 0 : goto fail;
839 : : }
840 : :
841 : 0 : gid = (gid_t)uresult;
842 : :
843 : : /*
844 : : * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
845 : : * but this value would get interpreted as (gid_t)-1 by chown
846 : : * and its siblings. That's not what the user meant! So we
847 : : * throw an overflow exception instead. (We already
848 : : * handled a real -1 with PyLong_AsLongAndOverflow() above.)
849 : : */
850 [ # # ]: 0 : if (gid == (gid_t)-1)
851 : 0 : goto overflow;
852 : :
853 : : /* Ensure the value wasn't truncated. */
854 : 0 : if (sizeof(gid_t) < sizeof(long) &&
855 [ # # ]: 0 : (unsigned long)gid != uresult)
856 : 0 : goto overflow;
857 : : /* fallthrough */
858 : :
859 : 0 : success:
860 : 746 : Py_DECREF(index);
861 : 746 : *p = gid;
862 : 746 : return 1;
863 : :
864 : 4 : underflow:
865 : 4 : PyErr_SetString(PyExc_OverflowError,
866 : : "gid is less than minimum");
867 : 4 : goto fail;
868 : :
869 : 2 : overflow:
870 : 2 : PyErr_SetString(PyExc_OverflowError,
871 : : "gid is greater than maximum");
872 : : /* fallthrough */
873 : :
874 : 6 : fail:
875 : 6 : Py_DECREF(index);
876 : 6 : return 0;
877 : : }
878 : : #endif /* MS_WINDOWS */
879 : :
880 : :
881 : : #define _PyLong_FromDev PyLong_FromLongLong
882 : :
883 : :
884 : : #if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
885 : : static int
886 : 11 : _Py_Dev_Converter(PyObject *obj, void *p)
887 : : {
888 : 11 : *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
889 [ + + ]: 11 : if (PyErr_Occurred())
890 : 4 : return 0;
891 : 7 : return 1;
892 : : }
893 : : #endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
894 : :
895 : :
896 : : #ifdef AT_FDCWD
897 : : /*
898 : : * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
899 : : * without the int cast, the value gets interpreted as uint (4291925331),
900 : : * which doesn't play nicely with all the initializer lines in this file that
901 : : * look like this:
902 : : * int dir_fd = DEFAULT_DIR_FD;
903 : : */
904 : : #define DEFAULT_DIR_FD (int)AT_FDCWD
905 : : #else
906 : : #define DEFAULT_DIR_FD (-100)
907 : : #endif
908 : :
909 : : static int
910 : 80183 : _fd_converter(PyObject *o, int *p)
911 : : {
912 : : int overflow;
913 : : long long_value;
914 : :
915 : 80183 : PyObject *index = _PyNumber_Index(o);
916 [ - + ]: 80183 : if (index == NULL) {
917 : 0 : return 0;
918 : : }
919 : :
920 : : assert(PyLong_Check(index));
921 : 80183 : long_value = PyLong_AsLongAndOverflow(index, &overflow);
922 : 80183 : Py_DECREF(index);
923 : : assert(!PyErr_Occurred());
924 [ + + - + ]: 80183 : if (overflow > 0 || long_value > INT_MAX) {
925 : 1 : PyErr_SetString(PyExc_OverflowError,
926 : : "fd is greater than maximum");
927 : 1 : return 0;
928 : : }
929 [ + - - + ]: 80182 : if (overflow < 0 || long_value < INT_MIN) {
930 : 0 : PyErr_SetString(PyExc_OverflowError,
931 : : "fd is less than minimum");
932 : 0 : return 0;
933 : : }
934 : :
935 : 80182 : *p = (int)long_value;
936 : 80182 : return 1;
937 : : }
938 : :
939 : : static int
940 : 80675 : dir_fd_converter(PyObject *o, void *p)
941 : : {
942 [ + + ]: 80675 : if (o == Py_None) {
943 : 18525 : *(int *)p = DEFAULT_DIR_FD;
944 : 18525 : return 1;
945 : : }
946 [ + + ]: 62150 : else if (PyIndex_Check(o)) {
947 : 62148 : return _fd_converter(o, (int *)p);
948 : : }
949 : : else {
950 : 2 : PyErr_Format(PyExc_TypeError,
951 : : "argument should be integer or None, not %.200s",
952 : : _PyType_Name(Py_TYPE(o)));
953 : 2 : return 0;
954 : : }
955 : : }
956 : :
957 : : typedef struct {
958 : : PyObject *billion;
959 : : PyObject *DirEntryType;
960 : : PyObject *ScandirIteratorType;
961 : : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
962 : : PyObject *SchedParamType;
963 : : #endif
964 : : PyObject *StatResultType;
965 : : PyObject *StatVFSResultType;
966 : : PyObject *TerminalSizeType;
967 : : PyObject *TimesResultType;
968 : : PyObject *UnameResultType;
969 : : #if defined(HAVE_WAITID) && !defined(__APPLE__)
970 : : PyObject *WaitidResultType;
971 : : #endif
972 : : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
973 : : PyObject *struct_rusage;
974 : : #endif
975 : : PyObject *st_mode;
976 : : } _posixstate;
977 : :
978 : :
979 : : static inline _posixstate*
980 : 5145036 : get_posix_state(PyObject *module)
981 : : {
982 : 5145036 : void *state = _PyModule_GetState(module);
983 : : assert(state != NULL);
984 : 5145036 : return (_posixstate *)state;
985 : : }
986 : :
987 : : /*
988 : : * A PyArg_ParseTuple "converter" function
989 : : * that handles filesystem paths in the manner
990 : : * preferred by the os module.
991 : : *
992 : : * path_converter accepts (Unicode) strings and their
993 : : * subclasses, and bytes and their subclasses. What
994 : : * it does with the argument depends on the platform:
995 : : *
996 : : * * On Windows, if we get a (Unicode) string we
997 : : * extract the wchar_t * and return it; if we get
998 : : * bytes we decode to wchar_t * and return that.
999 : : *
1000 : : * * On all other platforms, strings are encoded
1001 : : * to bytes using PyUnicode_FSConverter, then we
1002 : : * extract the char * from the bytes object and
1003 : : * return that.
1004 : : *
1005 : : * path_converter also optionally accepts signed
1006 : : * integers (representing open file descriptors) instead
1007 : : * of path strings.
1008 : : *
1009 : : * Input fields:
1010 : : * path.nullable
1011 : : * If nonzero, the path is permitted to be None.
1012 : : * path.allow_fd
1013 : : * If nonzero, the path is permitted to be a file handle
1014 : : * (a signed int) instead of a string.
1015 : : * path.function_name
1016 : : * If non-NULL, path_converter will use that as the name
1017 : : * of the function in error messages.
1018 : : * (If path.function_name is NULL it omits the function name.)
1019 : : * path.argument_name
1020 : : * If non-NULL, path_converter will use that as the name
1021 : : * of the parameter in error messages.
1022 : : * (If path.argument_name is NULL it uses "path".)
1023 : : *
1024 : : * Output fields:
1025 : : * path.wide
1026 : : * Points to the path if it was expressed as Unicode
1027 : : * and was not encoded. (Only used on Windows.)
1028 : : * path.narrow
1029 : : * Points to the path if it was expressed as bytes,
1030 : : * or it was Unicode and was encoded to bytes. (On Windows,
1031 : : * is a non-zero integer if the path was expressed as bytes.
1032 : : * The type is deliberately incompatible to prevent misuse.)
1033 : : * path.fd
1034 : : * Contains a file descriptor if path.accept_fd was true
1035 : : * and the caller provided a signed integer instead of any
1036 : : * sort of string.
1037 : : *
1038 : : * WARNING: if your "path" parameter is optional, and is
1039 : : * unspecified, path_converter will never get called.
1040 : : * So if you set allow_fd, you *MUST* initialize path.fd = -1
1041 : : * yourself!
1042 : : * path.length
1043 : : * The length of the path in characters, if specified as
1044 : : * a string.
1045 : : * path.object
1046 : : * The original object passed in (if get a PathLike object,
1047 : : * the result of PyOS_FSPath() is treated as the original object).
1048 : : * Own a reference to the object.
1049 : : * path.cleanup
1050 : : * For internal use only. May point to a temporary object.
1051 : : * (Pay no attention to the man behind the curtain.)
1052 : : *
1053 : : * At most one of path.wide or path.narrow will be non-NULL.
1054 : : * If path was None and path.nullable was set,
1055 : : * or if path was an integer and path.allow_fd was set,
1056 : : * both path.wide and path.narrow will be NULL
1057 : : * and path.length will be 0.
1058 : : *
1059 : : * path_converter takes care to not write to the path_t
1060 : : * unless it's successful. However it must reset the
1061 : : * "cleanup" field each time it's called.
1062 : : *
1063 : : * Use as follows:
1064 : : * path_t path;
1065 : : * memset(&path, 0, sizeof(path));
1066 : : * PyArg_ParseTuple(args, "O&", path_converter, &path);
1067 : : * // ... use values from path ...
1068 : : * path_cleanup(&path);
1069 : : *
1070 : : * (Note that if PyArg_Parse fails you don't need to call
1071 : : * path_cleanup(). However it is safe to do so.)
1072 : : */
1073 : : typedef struct {
1074 : : const char *function_name;
1075 : : const char *argument_name;
1076 : : int nullable;
1077 : : int allow_fd;
1078 : : const wchar_t *wide;
1079 : : #ifdef MS_WINDOWS
1080 : : BOOL narrow;
1081 : : #else
1082 : : const char *narrow;
1083 : : #endif
1084 : : int fd;
1085 : : Py_ssize_t length;
1086 : : PyObject *object;
1087 : : PyObject *cleanup;
1088 : : } path_t;
1089 : :
1090 : : #ifdef MS_WINDOWS
1091 : : #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1092 : : {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
1093 : : #else
1094 : : #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1095 : : {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
1096 : : #endif
1097 : :
1098 : : static void
1099 : 1828677 : path_cleanup(path_t *path)
1100 : : {
1101 : 1828677 : wchar_t *wide = (wchar_t *)path->wide;
1102 : 1828677 : path->wide = NULL;
1103 : 1828677 : PyMem_Free(wide);
1104 [ + + ]: 1828677 : Py_CLEAR(path->object);
1105 [ + + ]: 1828677 : Py_CLEAR(path->cleanup);
1106 : 1828677 : }
1107 : :
1108 : : static int
1109 : 1776787 : path_converter(PyObject *o, void *p)
1110 : : {
1111 : 1776787 : path_t *path = (path_t *)p;
1112 : 1776787 : PyObject *bytes = NULL;
1113 : 1776787 : Py_ssize_t length = 0;
1114 : : int is_index, is_buffer, is_bytes, is_unicode;
1115 : : const char *narrow;
1116 : : #ifdef MS_WINDOWS
1117 : : PyObject *wo = NULL;
1118 : : wchar_t *wide = NULL;
1119 : : #endif
1120 : :
1121 : : #define FORMAT_EXCEPTION(exc, fmt) \
1122 : : PyErr_Format(exc, "%s%s" fmt, \
1123 : : path->function_name ? path->function_name : "", \
1124 : : path->function_name ? ": " : "", \
1125 : : path->argument_name ? path->argument_name : "path")
1126 : :
1127 : : /* Py_CLEANUP_SUPPORTED support */
1128 [ - + ]: 1776787 : if (o == NULL) {
1129 : 0 : path_cleanup(path);
1130 : 0 : return 1;
1131 : : }
1132 : :
1133 : : /* Ensure it's always safe to call path_cleanup(). */
1134 : 1776787 : path->object = path->cleanup = NULL;
1135 : : /* path->object owns a reference to the original object */
1136 : 1776787 : Py_INCREF(o);
1137 : :
1138 [ + + - + ]: 1776787 : if ((o == Py_None) && path->nullable) {
1139 : 0 : path->wide = NULL;
1140 : : #ifdef MS_WINDOWS
1141 : : path->narrow = FALSE;
1142 : : #else
1143 : 0 : path->narrow = NULL;
1144 : : #endif
1145 : 0 : path->fd = -1;
1146 : 0 : goto success_exit;
1147 : : }
1148 : :
1149 : : /* Only call this here so that we don't treat the return value of
1150 : : os.fspath() as an fd or buffer. */
1151 [ + + + + ]: 1776787 : is_index = path->allow_fd && PyIndex_Check(o);
1152 : 1776787 : is_buffer = PyObject_CheckBuffer(o);
1153 : 1776787 : is_bytes = PyBytes_Check(o);
1154 : 1776787 : is_unicode = PyUnicode_Check(o);
1155 : :
1156 [ + + + + : 1776787 : if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
+ + + - ]
1157 : : /* Inline PyOS_FSPath() for better error messages. */
1158 : : PyObject *func, *res;
1159 : :
1160 : 66418 : func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1161 [ + + ]: 66418 : if (NULL == func) {
1162 : 12 : goto error_format;
1163 : : }
1164 : 66406 : res = _PyObject_CallNoArgs(func);
1165 : 66406 : Py_DECREF(func);
1166 [ - + ]: 66406 : if (NULL == res) {
1167 : 0 : goto error_exit;
1168 : : }
1169 [ + + ]: 66406 : else if (PyUnicode_Check(res)) {
1170 : 66394 : is_unicode = 1;
1171 : : }
1172 [ + + ]: 12 : else if (PyBytes_Check(res)) {
1173 : 5 : is_bytes = 1;
1174 : : }
1175 : : else {
1176 : 7 : PyErr_Format(PyExc_TypeError,
1177 : : "expected %.200s.__fspath__() to return str or bytes, "
1178 : : "not %.200s", _PyType_Name(Py_TYPE(o)),
1179 : : _PyType_Name(Py_TYPE(res)));
1180 : 7 : Py_DECREF(res);
1181 : 7 : goto error_exit;
1182 : : }
1183 : :
1184 : : /* still owns a reference to the original object */
1185 : 66399 : Py_DECREF(o);
1186 : 66399 : o = res;
1187 : : }
1188 : :
1189 [ + + ]: 1776768 : if (is_unicode) {
1190 : : #ifdef MS_WINDOWS
1191 : : wide = PyUnicode_AsWideCharString(o, &length);
1192 : : if (!wide) {
1193 : : goto error_exit;
1194 : : }
1195 : : if (length > 32767) {
1196 : : FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1197 : : goto error_exit;
1198 : : }
1199 : : if (wcslen(wide) != length) {
1200 : : FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1201 : : goto error_exit;
1202 : : }
1203 : :
1204 : : path->wide = wide;
1205 : : path->narrow = FALSE;
1206 : : path->fd = -1;
1207 : : wide = NULL;
1208 : : goto success_exit;
1209 : : #else
1210 [ + + ]: 1740405 : if (!PyUnicode_FSConverter(o, &bytes)) {
1211 : 102 : goto error_exit;
1212 : : }
1213 : : #endif
1214 : : }
1215 [ + + ]: 36363 : else if (is_bytes) {
1216 : 18283 : bytes = o;
1217 : 18283 : Py_INCREF(bytes);
1218 : : }
1219 [ + + ]: 18080 : else if (is_buffer) {
1220 : : /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1221 : : after removing support of non-bytes buffer objects. */
1222 [ - + ]: 225 : if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
1223 : : "%s%s%s should be %s, not %.200s",
1224 [ + - ]: 45 : path->function_name ? path->function_name : "",
1225 [ + - ]: 45 : path->function_name ? ": " : "",
1226 [ + - ]: 45 : path->argument_name ? path->argument_name : "path",
1227 [ + + + + ]: 45 : path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1228 : : "integer or None" :
1229 [ + + ]: 57 : path->allow_fd ? "string, bytes, os.PathLike or integer" :
1230 [ - + ]: 20 : path->nullable ? "string, bytes, os.PathLike or None" :
1231 : : "string, bytes or os.PathLike",
1232 : : _PyType_Name(Py_TYPE(o)))) {
1233 : 0 : goto error_exit;
1234 : : }
1235 : 45 : bytes = PyBytes_FromObject(o);
1236 [ - + ]: 45 : if (!bytes) {
1237 : 0 : goto error_exit;
1238 : : }
1239 : : }
1240 [ + - ]: 18035 : else if (is_index) {
1241 [ - + ]: 18035 : if (!_fd_converter(o, &path->fd)) {
1242 : 0 : goto error_exit;
1243 : : }
1244 : 18035 : path->wide = NULL;
1245 : : #ifdef MS_WINDOWS
1246 : : path->narrow = FALSE;
1247 : : #else
1248 : 18035 : path->narrow = NULL;
1249 : : #endif
1250 : 18035 : goto success_exit;
1251 : : }
1252 : : else {
1253 : 0 : error_format:
1254 : 60 : PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1255 [ + - ]: 12 : path->function_name ? path->function_name : "",
1256 [ + - ]: 12 : path->function_name ? ": " : "",
1257 [ + - ]: 12 : path->argument_name ? path->argument_name : "path",
1258 [ + + + + ]: 12 : path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1259 : : "integer or None" :
1260 [ + + ]: 14 : path->allow_fd ? "string, bytes, os.PathLike or integer" :
1261 [ - + ]: 5 : path->nullable ? "string, bytes, os.PathLike or None" :
1262 : : "string, bytes or os.PathLike",
1263 : : _PyType_Name(Py_TYPE(o)));
1264 : 12 : goto error_exit;
1265 : : }
1266 : :
1267 : 1758631 : length = PyBytes_GET_SIZE(bytes);
1268 : 1758631 : narrow = PyBytes_AS_STRING(bytes);
1269 [ + + ]: 1758631 : if ((size_t)length != strlen(narrow)) {
1270 [ + - + - : 25 : FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
+ - ]
1271 : 25 : goto error_exit;
1272 : : }
1273 : :
1274 : : #ifdef MS_WINDOWS
1275 : : wo = PyUnicode_DecodeFSDefaultAndSize(
1276 : : narrow,
1277 : : length
1278 : : );
1279 : : if (!wo) {
1280 : : goto error_exit;
1281 : : }
1282 : :
1283 : : wide = PyUnicode_AsWideCharString(wo, &length);
1284 : : Py_DECREF(wo);
1285 : : if (!wide) {
1286 : : goto error_exit;
1287 : : }
1288 : : if (length > 32767) {
1289 : : FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1290 : : goto error_exit;
1291 : : }
1292 : : if (wcslen(wide) != length) {
1293 : : FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1294 : : goto error_exit;
1295 : : }
1296 : : path->wide = wide;
1297 : : path->narrow = TRUE;
1298 : : Py_DECREF(bytes);
1299 : : wide = NULL;
1300 : : #else
1301 : 1758606 : path->wide = NULL;
1302 : 1758606 : path->narrow = narrow;
1303 [ + + ]: 1758606 : if (bytes == o) {
1304 : : /* Still a reference owned by path->object, don't have to
1305 : : worry about path->narrow is used after free. */
1306 : 18258 : Py_DECREF(bytes);
1307 : : }
1308 : : else {
1309 : 1740348 : path->cleanup = bytes;
1310 : : }
1311 : : #endif
1312 : 1758606 : path->fd = -1;
1313 : :
1314 : 1776641 : success_exit:
1315 : 1776641 : path->length = length;
1316 : 1776641 : path->object = o;
1317 : 1776641 : return Py_CLEANUP_SUPPORTED;
1318 : :
1319 : 146 : error_exit:
1320 : 146 : Py_XDECREF(o);
1321 : 146 : Py_XDECREF(bytes);
1322 : : #ifdef MS_WINDOWS
1323 : : PyMem_Free(wide);
1324 : : #endif
1325 : 146 : return 0;
1326 : : }
1327 : :
1328 : : static void
1329 : 0 : argument_unavailable_error(const char *function_name, const char *argument_name)
1330 : : {
1331 [ # # # # ]: 0 : PyErr_Format(PyExc_NotImplementedError,
1332 : : "%s%s%s unavailable on this platform",
1333 : : (function_name != NULL) ? function_name : "",
1334 : : (function_name != NULL) ? ": ": "",
1335 : : argument_name);
1336 : 0 : }
1337 : :
1338 : : static int
1339 : 3135 : dir_fd_unavailable(PyObject *o, void *p)
1340 : : {
1341 : : int dir_fd;
1342 [ - + ]: 3135 : if (!dir_fd_converter(o, &dir_fd))
1343 : 0 : return 0;
1344 [ - + ]: 3135 : if (dir_fd != DEFAULT_DIR_FD) {
1345 : 0 : argument_unavailable_error(NULL, "dir_fd");
1346 : 0 : return 0;
1347 : : }
1348 : 3135 : *(int *)p = dir_fd;
1349 : 3135 : return 1;
1350 : : }
1351 : :
1352 : : static int
1353 : 3135 : fd_specified(const char *function_name, int fd)
1354 : : {
1355 [ + - ]: 3135 : if (fd == -1)
1356 : 3135 : return 0;
1357 : :
1358 : 0 : argument_unavailable_error(function_name, "fd");
1359 : 0 : return 1;
1360 : : }
1361 : :
1362 : : static int
1363 : 3135 : follow_symlinks_specified(const char *function_name, int follow_symlinks)
1364 : : {
1365 [ + - ]: 3135 : if (follow_symlinks)
1366 : 3135 : return 0;
1367 : :
1368 : 0 : argument_unavailable_error(function_name, "follow_symlinks");
1369 : 0 : return 1;
1370 : : }
1371 : :
1372 : : static int
1373 : 1409707 : path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1374 : : {
1375 [ + - + + ]: 1409707 : if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1376 : : #ifndef MS_WINDOWS
1377 [ - + ]: 3856 : && !path->narrow
1378 : : #endif
1379 : : ) {
1380 : 0 : PyErr_Format(PyExc_ValueError,
1381 : : "%s: can't specify dir_fd without matching path",
1382 : : function_name);
1383 : 0 : return 1;
1384 : : }
1385 : 1409707 : return 0;
1386 : : }
1387 : :
1388 : : static int
1389 : 1409735 : dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1390 : : {
1391 [ + + - + ]: 1409735 : if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1392 : 0 : PyErr_Format(PyExc_ValueError,
1393 : : "%s: can't specify both dir_fd and fd",
1394 : : function_name);
1395 : 0 : return 1;
1396 : : }
1397 : 1409735 : return 0;
1398 : : }
1399 : :
1400 : : static int
1401 : 1476344 : fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1402 : : int follow_symlinks)
1403 : : {
1404 [ + + - + ]: 1476344 : if ((fd > 0) && (!follow_symlinks)) {
1405 : 0 : PyErr_Format(PyExc_ValueError,
1406 : : "%s: cannot use fd and follow_symlinks together",
1407 : : function_name);
1408 : 0 : return 1;
1409 : : }
1410 : 1476344 : return 0;
1411 : : }
1412 : :
1413 : : static int
1414 : 3135 : dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1415 : : int follow_symlinks)
1416 : : {
1417 [ - + - - ]: 3135 : if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1418 : 0 : PyErr_Format(PyExc_ValueError,
1419 : : "%s: cannot use dir_fd and follow_symlinks together",
1420 : : function_name);
1421 : 0 : return 1;
1422 : : }
1423 : 3135 : return 0;
1424 : : }
1425 : :
1426 : : #ifdef MS_WINDOWS
1427 : : typedef long long Py_off_t;
1428 : : #else
1429 : : typedef off_t Py_off_t;
1430 : : #endif
1431 : :
1432 : : static int
1433 : 49893 : Py_off_t_converter(PyObject *arg, void *addr)
1434 : : {
1435 : : #ifdef HAVE_LARGEFILE_SUPPORT
1436 : : *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1437 : : #else
1438 : 49893 : *((Py_off_t *)addr) = PyLong_AsLong(arg);
1439 : : #endif
1440 [ - + ]: 49893 : if (PyErr_Occurred())
1441 : 0 : return 0;
1442 : 49893 : return 1;
1443 : : }
1444 : :
1445 : : static PyObject *
1446 : 8362 : PyLong_FromPy_off_t(Py_off_t offset)
1447 : : {
1448 : : #ifdef HAVE_LARGEFILE_SUPPORT
1449 : : return PyLong_FromLongLong(offset);
1450 : : #else
1451 : 8362 : return PyLong_FromLong(offset);
1452 : : #endif
1453 : : }
1454 : :
1455 : : #ifdef HAVE_SIGSET_T
1456 : : /* Convert an iterable of integers to a sigset.
1457 : : Return 1 on success, return 0 and raise an exception on error. */
1458 : : int
1459 : 267 : _Py_Sigset_Converter(PyObject *obj, void *addr)
1460 : : {
1461 : 267 : sigset_t *mask = (sigset_t *)addr;
1462 : : PyObject *iterator, *item;
1463 : : long signum;
1464 : : int overflow;
1465 : :
1466 : : // The extra parens suppress the unreachable-code warning with clang on MacOS
1467 [ - + ]: 267 : if (sigemptyset(mask) < (0)) {
1468 : : /* Probably only if mask == NULL. */
1469 : 0 : PyErr_SetFromErrno(PyExc_OSError);
1470 : 0 : return 0;
1471 : : }
1472 : :
1473 : 267 : iterator = PyObject_GetIter(obj);
1474 [ + + ]: 267 : if (iterator == NULL) {
1475 : 4 : return 0;
1476 : : }
1477 : :
1478 [ + + ]: 1336 : while ((item = PyIter_Next(iterator)) != NULL) {
1479 : 821 : signum = PyLong_AsLongAndOverflow(item, &overflow);
1480 : 821 : Py_DECREF(item);
1481 [ + + + + ]: 821 : if (signum <= 0 || signum >= Py_NSIG) {
1482 [ + + + + : 11 : if (overflow || signum != -1 || !PyErr_Occurred()) {
- + ]
1483 : 7 : PyErr_Format(PyExc_ValueError,
1484 : : "signal number %ld out of range [1; %i]",
1485 : : signum, Py_NSIG - 1);
1486 : : }
1487 : 11 : goto error;
1488 : : }
1489 [ - + ]: 810 : if (sigaddset(mask, (int)signum)) {
1490 [ # # ]: 0 : if (errno != EINVAL) {
1491 : : /* Probably impossible */
1492 : 0 : PyErr_SetFromErrno(PyExc_OSError);
1493 : 0 : goto error;
1494 : : }
1495 : : /* For backwards compatibility, allow idioms such as
1496 : : * `range(1, NSIG)` but warn about invalid signal numbers
1497 : : */
1498 : 0 : const char msg[] =
1499 : : "invalid signal number %ld, please use valid_signals()";
1500 [ # # ]: 0 : if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1501 : 0 : goto error;
1502 : : }
1503 : : }
1504 : : }
1505 [ + - ]: 252 : if (!PyErr_Occurred()) {
1506 : 252 : Py_DECREF(iterator);
1507 : 252 : return 1;
1508 : : }
1509 : :
1510 : 0 : error:
1511 : 11 : Py_DECREF(iterator);
1512 : 11 : return 0;
1513 : : }
1514 : : #endif /* HAVE_SIGSET_T */
1515 : :
1516 : : #ifdef MS_WINDOWS
1517 : :
1518 : : static int
1519 : : win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1520 : : {
1521 : : char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1522 : : _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1523 : : DWORD n_bytes_returned;
1524 : :
1525 : : if (0 == DeviceIoControl(
1526 : : reparse_point_handle,
1527 : : FSCTL_GET_REPARSE_POINT,
1528 : : NULL, 0, /* in buffer */
1529 : : target_buffer, sizeof(target_buffer),
1530 : : &n_bytes_returned,
1531 : : NULL)) /* we're not using OVERLAPPED_IO */
1532 : : return FALSE;
1533 : :
1534 : : if (reparse_tag)
1535 : : *reparse_tag = rdb->ReparseTag;
1536 : :
1537 : : return TRUE;
1538 : : }
1539 : :
1540 : : #endif /* MS_WINDOWS */
1541 : :
1542 : : /* Return a dictionary corresponding to the POSIX environment table */
1543 : : #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1544 : : /* On Darwin/MacOSX a shared library or framework has no access to
1545 : : ** environ directly, we must obtain it with _NSGetEnviron(). See also
1546 : : ** man environ(7).
1547 : : */
1548 : : #include <crt_externs.h>
1549 : : #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1550 : : extern char **environ;
1551 : : #endif /* !_MSC_VER */
1552 : :
1553 : : static PyObject *
1554 : 3135 : convertenviron(void)
1555 : : {
1556 : : PyObject *d;
1557 : : #ifdef MS_WINDOWS
1558 : : wchar_t **e;
1559 : : #else
1560 : : char **e;
1561 : : #endif
1562 : :
1563 : 3135 : d = PyDict_New();
1564 [ - + ]: 3135 : if (d == NULL)
1565 : 0 : return NULL;
1566 : : #ifdef MS_WINDOWS
1567 : : /* _wenviron must be initialized in this way if the program is started
1568 : : through main() instead of wmain(). */
1569 : : _wgetenv(L"");
1570 : : e = _wenviron;
1571 : : #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1572 : : /* environ is not accessible as an extern in a shared object on OSX; use
1573 : : _NSGetEnviron to resolve it. The value changes if you add environment
1574 : : variables between calls to Py_Initialize, so don't cache the value. */
1575 : : e = *_NSGetEnviron();
1576 : : #else
1577 : 3135 : e = environ;
1578 : : #endif
1579 [ - + ]: 3135 : if (e == NULL)
1580 : 0 : return d;
1581 [ + + ]: 336386 : for (; *e != NULL; e++) {
1582 : : PyObject *k;
1583 : : PyObject *v;
1584 : : #ifdef MS_WINDOWS
1585 : : const wchar_t *p = wcschr(*e, L'=');
1586 : : #else
1587 : 333251 : const char *p = strchr(*e, '=');
1588 : : #endif
1589 [ - + ]: 333251 : if (p == NULL)
1590 : 0 : continue;
1591 : : #ifdef MS_WINDOWS
1592 : : k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1593 : : #else
1594 : 333251 : k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1595 : : #endif
1596 [ - + ]: 333251 : if (k == NULL) {
1597 : 0 : Py_DECREF(d);
1598 : 0 : return NULL;
1599 : : }
1600 : : #ifdef MS_WINDOWS
1601 : : v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1602 : : #else
1603 : 333251 : v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1604 : : #endif
1605 [ - + ]: 333251 : if (v == NULL) {
1606 : 0 : Py_DECREF(k);
1607 : 0 : Py_DECREF(d);
1608 : 0 : return NULL;
1609 : : }
1610 [ - + ]: 333251 : if (PyDict_SetDefault(d, k, v) == NULL) {
1611 : 0 : Py_DECREF(v);
1612 : 0 : Py_DECREF(k);
1613 : 0 : Py_DECREF(d);
1614 : 0 : return NULL;
1615 : : }
1616 : 333251 : Py_DECREF(k);
1617 : 333251 : Py_DECREF(v);
1618 : : }
1619 : 3135 : return d;
1620 : : }
1621 : :
1622 : : /* Set a POSIX-specific error from errno, and return NULL */
1623 : :
1624 : : static PyObject *
1625 : 20428 : posix_error(void)
1626 : : {
1627 : 20428 : return PyErr_SetFromErrno(PyExc_OSError);
1628 : : }
1629 : :
1630 : : #ifdef MS_WINDOWS
1631 : : static PyObject *
1632 : : win32_error(const char* function, const char* filename)
1633 : : {
1634 : : /* XXX We should pass the function name along in the future.
1635 : : (winreg.c also wants to pass the function name.)
1636 : : This would however require an additional param to the
1637 : : Windows error object, which is non-trivial.
1638 : : */
1639 : : errno = GetLastError();
1640 : : if (filename)
1641 : : return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1642 : : else
1643 : : return PyErr_SetFromWindowsErr(errno);
1644 : : }
1645 : :
1646 : : static PyObject *
1647 : : win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1648 : : {
1649 : : /* XXX - see win32_error for comments on 'function' */
1650 : : if (filename)
1651 : : return PyErr_SetExcFromWindowsErrWithFilenameObject(
1652 : : PyExc_OSError,
1653 : : err,
1654 : : filename);
1655 : : else
1656 : : return PyErr_SetFromWindowsErr(err);
1657 : : }
1658 : :
1659 : : static PyObject *
1660 : : win32_error_object(const char* function, PyObject* filename)
1661 : : {
1662 : : errno = GetLastError();
1663 : : return win32_error_object_err(function, filename, errno);
1664 : : }
1665 : :
1666 : : #endif /* MS_WINDOWS */
1667 : :
1668 : : static PyObject *
1669 : 263123 : posix_path_object_error(PyObject *path)
1670 : : {
1671 : 263123 : return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1672 : : }
1673 : :
1674 : : static PyObject *
1675 : 263118 : path_object_error(PyObject *path)
1676 : : {
1677 : : #ifdef MS_WINDOWS
1678 : : return PyErr_SetExcFromWindowsErrWithFilenameObject(
1679 : : PyExc_OSError, 0, path);
1680 : : #else
1681 : 263118 : return posix_path_object_error(path);
1682 : : #endif
1683 : : }
1684 : :
1685 : : static PyObject *
1686 : 127 : path_object_error2(PyObject *path, PyObject *path2)
1687 : : {
1688 : : #ifdef MS_WINDOWS
1689 : : return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1690 : : PyExc_OSError, 0, path, path2);
1691 : : #else
1692 : 127 : return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1693 : : #endif
1694 : : }
1695 : :
1696 : : static PyObject *
1697 : 260945 : path_error(path_t *path)
1698 : : {
1699 : 260945 : return path_object_error(path->object);
1700 : : }
1701 : :
1702 : : static PyObject *
1703 : 5 : posix_path_error(path_t *path)
1704 : : {
1705 : 5 : return posix_path_object_error(path->object);
1706 : : }
1707 : :
1708 : : static PyObject *
1709 : 127 : path_error2(path_t *path, path_t *path2)
1710 : : {
1711 : 127 : return path_object_error2(path->object, path2->object);
1712 : : }
1713 : :
1714 : :
1715 : : /* POSIX generic methods */
1716 : :
1717 : : static PyObject *
1718 : 561 : posix_fildes_fd(int fd, int (*func)(int))
1719 : : {
1720 : : int res;
1721 : 561 : int async_err = 0;
1722 : :
1723 : : do {
1724 : 561 : Py_BEGIN_ALLOW_THREADS
1725 : : _Py_BEGIN_SUPPRESS_IPH
1726 : 561 : res = (*func)(fd);
1727 : : _Py_END_SUPPRESS_IPH
1728 : 561 : Py_END_ALLOW_THREADS
1729 [ + + - + : 561 : } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
1730 [ + + ]: 561 : if (res != 0)
1731 [ + - ]: 3 : return (!async_err) ? posix_error() : NULL;
1732 : 558 : Py_RETURN_NONE;
1733 : : }
1734 : :
1735 : :
1736 : : #ifdef MS_WINDOWS
1737 : : /* This is a reimplementation of the C library's chdir function,
1738 : : but one that produces Win32 errors instead of DOS error codes.
1739 : : chdir is essentially a wrapper around SetCurrentDirectory; however,
1740 : : it also needs to set "magic" environment variables indicating
1741 : : the per-drive current directory, which are of the form =<drive>: */
1742 : : static BOOL __stdcall
1743 : : win32_wchdir(LPCWSTR path)
1744 : : {
1745 : : wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1746 : : int result;
1747 : : wchar_t env[4] = L"=x:";
1748 : :
1749 : : if(!SetCurrentDirectoryW(path))
1750 : : return FALSE;
1751 : : result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1752 : : if (!result)
1753 : : return FALSE;
1754 : : if (result > Py_ARRAY_LENGTH(path_buf)) {
1755 : : new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1756 : : if (!new_path) {
1757 : : SetLastError(ERROR_OUTOFMEMORY);
1758 : : return FALSE;
1759 : : }
1760 : : result = GetCurrentDirectoryW(result, new_path);
1761 : : if (!result) {
1762 : : PyMem_RawFree(new_path);
1763 : : return FALSE;
1764 : : }
1765 : : }
1766 : : int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1767 : : wcsncmp(new_path, L"//", 2) == 0);
1768 : : if (!is_unc_like_path) {
1769 : : env[1] = new_path[0];
1770 : : result = SetEnvironmentVariableW(env, new_path);
1771 : : }
1772 : : if (new_path != path_buf)
1773 : : PyMem_RawFree(new_path);
1774 : : return result ? TRUE : FALSE;
1775 : : }
1776 : : #endif
1777 : :
1778 : : #ifdef MS_WINDOWS
1779 : : /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1780 : : - time stamps are restricted to second resolution
1781 : : - file modification times suffer from forth-and-back conversions between
1782 : : UTC and local time
1783 : : Therefore, we implement our own stat, based on the Win32 API directly.
1784 : : */
1785 : : #define HAVE_STAT_NSEC 1
1786 : : #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1787 : : #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1788 : :
1789 : : static void
1790 : : find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1791 : : BY_HANDLE_FILE_INFORMATION *info,
1792 : : ULONG *reparse_tag)
1793 : : {
1794 : : memset(info, 0, sizeof(*info));
1795 : : info->dwFileAttributes = pFileData->dwFileAttributes;
1796 : : info->ftCreationTime = pFileData->ftCreationTime;
1797 : : info->ftLastAccessTime = pFileData->ftLastAccessTime;
1798 : : info->ftLastWriteTime = pFileData->ftLastWriteTime;
1799 : : info->nFileSizeHigh = pFileData->nFileSizeHigh;
1800 : : info->nFileSizeLow = pFileData->nFileSizeLow;
1801 : : /* info->nNumberOfLinks = 1; */
1802 : : if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1803 : : *reparse_tag = pFileData->dwReserved0;
1804 : : else
1805 : : *reparse_tag = 0;
1806 : : }
1807 : :
1808 : : static BOOL
1809 : : attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1810 : : {
1811 : : HANDLE hFindFile;
1812 : : WIN32_FIND_DATAW FileData;
1813 : : LPCWSTR filename = pszFile;
1814 : : size_t n = wcslen(pszFile);
1815 : : if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
1816 : : // cannot use PyMem_Malloc here because we do not hold the GIL
1817 : : filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
1818 : : wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
1819 : : while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
1820 : : ((LPWSTR)filename)[n] = L'\0';
1821 : : }
1822 : : if (!n || (n == 1 && filename[1] == L':')) {
1823 : : // Nothing left to query
1824 : : free((void *)filename);
1825 : : return FALSE;
1826 : : }
1827 : : }
1828 : : hFindFile = FindFirstFileW(filename, &FileData);
1829 : : if (pszFile != filename) {
1830 : : free((void *)filename);
1831 : : }
1832 : : if (hFindFile == INVALID_HANDLE_VALUE) {
1833 : : return FALSE;
1834 : : }
1835 : : FindClose(hFindFile);
1836 : : find_data_to_file_info(&FileData, info, reparse_tag);
1837 : : return TRUE;
1838 : : }
1839 : :
1840 : : static int
1841 : : win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1842 : : BOOL traverse)
1843 : : {
1844 : : HANDLE hFile;
1845 : : BY_HANDLE_FILE_INFORMATION fileInfo;
1846 : : FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1847 : : DWORD fileType, error;
1848 : : BOOL isUnhandledTag = FALSE;
1849 : : int retval = 0;
1850 : :
1851 : : DWORD access = FILE_READ_ATTRIBUTES;
1852 : : DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1853 : : if (!traverse) {
1854 : : flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1855 : : }
1856 : :
1857 : : hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1858 : : if (hFile == INVALID_HANDLE_VALUE) {
1859 : : /* Either the path doesn't exist, or the caller lacks access. */
1860 : : error = GetLastError();
1861 : : switch (error) {
1862 : : case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */
1863 : : case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1864 : : /* Try reading the parent directory. */
1865 : : if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1866 : : /* Cannot read the parent directory. */
1867 : : switch (GetLastError()) {
1868 : : case ERROR_FILE_NOT_FOUND: /* File cannot be found */
1869 : : case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
1870 : : case ERROR_NOT_READY: /* Drive exists but unavailable */
1871 : : case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
1872 : : break;
1873 : : /* Restore the error from CreateFileW(). */
1874 : : default:
1875 : : SetLastError(error);
1876 : : }
1877 : :
1878 : : return -1;
1879 : : }
1880 : : if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1881 : : if (traverse ||
1882 : : !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1883 : : /* The stat call has to traverse but cannot, so fail. */
1884 : : SetLastError(error);
1885 : : return -1;
1886 : : }
1887 : : }
1888 : : break;
1889 : :
1890 : : case ERROR_INVALID_PARAMETER:
1891 : : /* \\.\con requires read or write access. */
1892 : : hFile = CreateFileW(path, access | GENERIC_READ,
1893 : : FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1894 : : OPEN_EXISTING, flags, NULL);
1895 : : if (hFile == INVALID_HANDLE_VALUE) {
1896 : : SetLastError(error);
1897 : : return -1;
1898 : : }
1899 : : break;
1900 : :
1901 : : case ERROR_CANT_ACCESS_FILE:
1902 : : /* bpo37834: open unhandled reparse points if traverse fails. */
1903 : : if (traverse) {
1904 : : traverse = FALSE;
1905 : : isUnhandledTag = TRUE;
1906 : : hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1907 : : flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1908 : : }
1909 : : if (hFile == INVALID_HANDLE_VALUE) {
1910 : : SetLastError(error);
1911 : : return -1;
1912 : : }
1913 : : break;
1914 : :
1915 : : default:
1916 : : return -1;
1917 : : }
1918 : : }
1919 : :
1920 : : if (hFile != INVALID_HANDLE_VALUE) {
1921 : : /* Handle types other than files on disk. */
1922 : : fileType = GetFileType(hFile);
1923 : : if (fileType != FILE_TYPE_DISK) {
1924 : : if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1925 : : retval = -1;
1926 : : goto cleanup;
1927 : : }
1928 : : DWORD fileAttributes = GetFileAttributesW(path);
1929 : : memset(result, 0, sizeof(*result));
1930 : : if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1931 : : fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1932 : : /* \\.\pipe\ or \\.\mailslot\ */
1933 : : result->st_mode = _S_IFDIR;
1934 : : } else if (fileType == FILE_TYPE_CHAR) {
1935 : : /* \\.\nul */
1936 : : result->st_mode = _S_IFCHR;
1937 : : } else if (fileType == FILE_TYPE_PIPE) {
1938 : : /* \\.\pipe\spam */
1939 : : result->st_mode = _S_IFIFO;
1940 : : }
1941 : : /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1942 : : goto cleanup;
1943 : : }
1944 : :
1945 : : /* Query the reparse tag, and traverse a non-link. */
1946 : : if (!traverse) {
1947 : : if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
1948 : : &tagInfo, sizeof(tagInfo))) {
1949 : : /* Allow devices that do not support FileAttributeTagInfo. */
1950 : : switch (GetLastError()) {
1951 : : case ERROR_INVALID_PARAMETER:
1952 : : case ERROR_INVALID_FUNCTION:
1953 : : case ERROR_NOT_SUPPORTED:
1954 : : tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1955 : : tagInfo.ReparseTag = 0;
1956 : : break;
1957 : : default:
1958 : : retval = -1;
1959 : : goto cleanup;
1960 : : }
1961 : : } else if (tagInfo.FileAttributes &
1962 : : FILE_ATTRIBUTE_REPARSE_POINT) {
1963 : : if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1964 : : if (isUnhandledTag) {
1965 : : /* Traversing previously failed for either this link
1966 : : or its target. */
1967 : : SetLastError(ERROR_CANT_ACCESS_FILE);
1968 : : retval = -1;
1969 : : goto cleanup;
1970 : : }
1971 : : /* Traverse a non-link, but not if traversing already failed
1972 : : for an unhandled tag. */
1973 : : } else if (!isUnhandledTag) {
1974 : : CloseHandle(hFile);
1975 : : return win32_xstat_impl(path, result, TRUE);
1976 : : }
1977 : : }
1978 : : }
1979 : :
1980 : : if (!GetFileInformationByHandle(hFile, &fileInfo)) {
1981 : : switch (GetLastError()) {
1982 : : case ERROR_INVALID_PARAMETER:
1983 : : case ERROR_INVALID_FUNCTION:
1984 : : case ERROR_NOT_SUPPORTED:
1985 : : /* Volumes and physical disks are block devices, e.g.
1986 : : \\.\C: and \\.\PhysicalDrive0. */
1987 : : memset(result, 0, sizeof(*result));
1988 : : result->st_mode = 0x6000; /* S_IFBLK */
1989 : : goto cleanup;
1990 : : }
1991 : : retval = -1;
1992 : : goto cleanup;
1993 : : }
1994 : : }
1995 : :
1996 : : _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
1997 : :
1998 : : if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
1999 : : /* Fix the file execute permissions. This hack sets S_IEXEC if
2000 : : the filename has an extension that is commonly used by files
2001 : : that CreateProcessW can execute. A real implementation calls
2002 : : GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2003 : : AccessCheck to check for generic read, write, and execute
2004 : : access. */
2005 : : const wchar_t *fileExtension = wcsrchr(path, '.');
2006 : : if (fileExtension) {
2007 : : if (_wcsicmp(fileExtension, L".exe") == 0 ||
2008 : : _wcsicmp(fileExtension, L".bat") == 0 ||
2009 : : _wcsicmp(fileExtension, L".cmd") == 0 ||
2010 : : _wcsicmp(fileExtension, L".com") == 0) {
2011 : : result->st_mode |= 0111;
2012 : : }
2013 : : }
2014 : : }
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(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2033 : : {
2034 : : /* Protocol violation: we explicitly clear errno, instead of
2035 : : setting it to a POSIX error. Callers should use GetLastError. */
2036 : : int code = win32_xstat_impl(path, result, traverse);
2037 : : errno = 0;
2038 : : return code;
2039 : : }
2040 : : /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2041 : :
2042 : : In Posix, stat automatically traverses symlinks and returns the stat
2043 : : structure for the target. In Windows, the equivalent GetFileAttributes by
2044 : : default does not traverse symlinks and instead returns attributes for
2045 : : the symlink.
2046 : :
2047 : : Instead, we will open the file (which *does* traverse symlinks by default)
2048 : : and GetFileInformationByHandle(). */
2049 : :
2050 : : static int
2051 : : win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2052 : : {
2053 : : return win32_xstat(path, result, FALSE);
2054 : : }
2055 : :
2056 : : static int
2057 : : win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2058 : : {
2059 : : return win32_xstat(path, result, TRUE);
2060 : : }
2061 : :
2062 : : #endif /* MS_WINDOWS */
2063 : :
2064 : : PyDoc_STRVAR(stat_result__doc__,
2065 : : "stat_result: Result from stat, fstat, or lstat.\n\n\
2066 : : This object may be accessed either as a tuple of\n\
2067 : : (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2068 : : or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2069 : : \n\
2070 : : Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2071 : : or st_flags, they are available as attributes only.\n\
2072 : : \n\
2073 : : See os.stat for more information.");
2074 : :
2075 : : static PyStructSequence_Field stat_result_fields[] = {
2076 : : {"st_mode", "protection bits"},
2077 : : {"st_ino", "inode"},
2078 : : {"st_dev", "device"},
2079 : : {"st_nlink", "number of hard links"},
2080 : : {"st_uid", "user ID of owner"},
2081 : : {"st_gid", "group ID of owner"},
2082 : : {"st_size", "total size, in bytes"},
2083 : : /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2084 : : {NULL, "integer time of last access"},
2085 : : {NULL, "integer time of last modification"},
2086 : : {NULL, "integer time of last change"},
2087 : : {"st_atime", "time of last access"},
2088 : : {"st_mtime", "time of last modification"},
2089 : : {"st_ctime", "time of last change"},
2090 : : {"st_atime_ns", "time of last access in nanoseconds"},
2091 : : {"st_mtime_ns", "time of last modification in nanoseconds"},
2092 : : {"st_ctime_ns", "time of last change in nanoseconds"},
2093 : : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2094 : : {"st_blksize", "blocksize for filesystem I/O"},
2095 : : #endif
2096 : : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2097 : : {"st_blocks", "number of blocks allocated"},
2098 : : #endif
2099 : : #ifdef HAVE_STRUCT_STAT_ST_RDEV
2100 : : {"st_rdev", "device type (if inode device)"},
2101 : : #endif
2102 : : #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2103 : : {"st_flags", "user defined flags for file"},
2104 : : #endif
2105 : : #ifdef HAVE_STRUCT_STAT_ST_GEN
2106 : : {"st_gen", "generation number"},
2107 : : #endif
2108 : : #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2109 : : {"st_birthtime", "time of creation"},
2110 : : #endif
2111 : : #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2112 : : {"st_file_attributes", "Windows file attribute bits"},
2113 : : #endif
2114 : : #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2115 : : {"st_fstype", "Type of filesystem"},
2116 : : #endif
2117 : : #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2118 : : {"st_reparse_tag", "Windows reparse tag"},
2119 : : #endif
2120 : : {0}
2121 : : };
2122 : :
2123 : : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2124 : : #define ST_BLKSIZE_IDX 16
2125 : : #else
2126 : : #define ST_BLKSIZE_IDX 15
2127 : : #endif
2128 : :
2129 : : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2130 : : #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2131 : : #else
2132 : : #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2133 : : #endif
2134 : :
2135 : : #ifdef HAVE_STRUCT_STAT_ST_RDEV
2136 : : #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2137 : : #else
2138 : : #define ST_RDEV_IDX ST_BLOCKS_IDX
2139 : : #endif
2140 : :
2141 : : #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2142 : : #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2143 : : #else
2144 : : #define ST_FLAGS_IDX ST_RDEV_IDX
2145 : : #endif
2146 : :
2147 : : #ifdef HAVE_STRUCT_STAT_ST_GEN
2148 : : #define ST_GEN_IDX (ST_FLAGS_IDX+1)
2149 : : #else
2150 : : #define ST_GEN_IDX ST_FLAGS_IDX
2151 : : #endif
2152 : :
2153 : : #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2154 : : #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2155 : : #else
2156 : : #define ST_BIRTHTIME_IDX ST_GEN_IDX
2157 : : #endif
2158 : :
2159 : : #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2160 : : #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
2161 : : #else
2162 : : #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
2163 : : #endif
2164 : :
2165 : : #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2166 : : #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2167 : : #else
2168 : : #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2169 : : #endif
2170 : :
2171 : : #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2172 : : #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2173 : : #else
2174 : : #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2175 : : #endif
2176 : :
2177 : : static PyStructSequence_Desc stat_result_desc = {
2178 : : "stat_result", /* name */
2179 : : stat_result__doc__, /* doc */
2180 : : stat_result_fields,
2181 : : 10
2182 : : };
2183 : :
2184 : : PyDoc_STRVAR(statvfs_result__doc__,
2185 : : "statvfs_result: Result from statvfs or fstatvfs.\n\n\
2186 : : This object may be accessed either as a tuple of\n\
2187 : : (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2188 : : or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2189 : : \n\
2190 : : See os.statvfs for more information.");
2191 : :
2192 : : static PyStructSequence_Field statvfs_result_fields[] = {
2193 : : {"f_bsize", },
2194 : : {"f_frsize", },
2195 : : {"f_blocks", },
2196 : : {"f_bfree", },
2197 : : {"f_bavail", },
2198 : : {"f_files", },
2199 : : {"f_ffree", },
2200 : : {"f_favail", },
2201 : : {"f_flag", },
2202 : : {"f_namemax",},
2203 : : {"f_fsid", },
2204 : : {0}
2205 : : };
2206 : :
2207 : : static PyStructSequence_Desc statvfs_result_desc = {
2208 : : "statvfs_result", /* name */
2209 : : statvfs_result__doc__, /* doc */
2210 : : statvfs_result_fields,
2211 : : 10
2212 : : };
2213 : :
2214 : : #if defined(HAVE_WAITID) && !defined(__APPLE__)
2215 : : PyDoc_STRVAR(waitid_result__doc__,
2216 : : "waitid_result: Result from waitid.\n\n\
2217 : : This object may be accessed either as a tuple of\n\
2218 : : (si_pid, si_uid, si_signo, si_status, si_code),\n\
2219 : : or via the attributes si_pid, si_uid, and so on.\n\
2220 : : \n\
2221 : : See os.waitid for more information.");
2222 : :
2223 : : static PyStructSequence_Field waitid_result_fields[] = {
2224 : : {"si_pid", },
2225 : : {"si_uid", },
2226 : : {"si_signo", },
2227 : : {"si_status", },
2228 : : {"si_code", },
2229 : : {0}
2230 : : };
2231 : :
2232 : : static PyStructSequence_Desc waitid_result_desc = {
2233 : : "waitid_result", /* name */
2234 : : waitid_result__doc__, /* doc */
2235 : : waitid_result_fields,
2236 : : 5
2237 : : };
2238 : : #endif
2239 : : static newfunc structseq_new;
2240 : :
2241 : : static PyObject *
2242 : 72 : statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2243 : : {
2244 : : PyStructSequence *result;
2245 : : int i;
2246 : :
2247 : 72 : result = (PyStructSequence*)structseq_new(type, args, kwds);
2248 [ + + ]: 72 : if (!result)
2249 : 2 : return NULL;
2250 : : /* If we have been initialized from a tuple,
2251 : : st_?time might be set to None. Initialize it
2252 : : from the int slots. */
2253 [ + + ]: 280 : for (i = 7; i <= 9; i++) {
2254 [ + + ]: 210 : if (result->ob_item[i+3] == Py_None) {
2255 : 78 : Py_DECREF(Py_None);
2256 : 78 : Py_INCREF(result->ob_item[i]);
2257 : 78 : result->ob_item[i+3] = result->ob_item[i];
2258 : : }
2259 : : }
2260 : 70 : return (PyObject*)result;
2261 : : }
2262 : :
2263 : : static int
2264 : 6162 : _posix_clear(PyObject *module)
2265 : : {
2266 : 6162 : _posixstate *state = get_posix_state(module);
2267 [ + + ]: 6162 : Py_CLEAR(state->billion);
2268 [ + + ]: 6162 : Py_CLEAR(state->DirEntryType);
2269 [ + + ]: 6162 : Py_CLEAR(state->ScandirIteratorType);
2270 : : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2271 [ + + ]: 6162 : Py_CLEAR(state->SchedParamType);
2272 : : #endif
2273 [ + + ]: 6162 : Py_CLEAR(state->StatResultType);
2274 [ + + ]: 6162 : Py_CLEAR(state->StatVFSResultType);
2275 [ + + ]: 6162 : Py_CLEAR(state->TerminalSizeType);
2276 [ + + ]: 6162 : Py_CLEAR(state->TimesResultType);
2277 [ + + ]: 6162 : Py_CLEAR(state->UnameResultType);
2278 : : #if defined(HAVE_WAITID) && !defined(__APPLE__)
2279 [ + + ]: 6162 : Py_CLEAR(state->WaitidResultType);
2280 : : #endif
2281 : : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2282 [ + + ]: 6162 : Py_CLEAR(state->struct_rusage);
2283 : : #endif
2284 [ + + ]: 6162 : Py_CLEAR(state->st_mode);
2285 : 6162 : return 0;
2286 : : }
2287 : :
2288 : : static int
2289 : 53458 : _posix_traverse(PyObject *module, visitproc visit, void *arg)
2290 : : {
2291 : 53458 : _posixstate *state = get_posix_state(module);
2292 [ + + - + ]: 53458 : Py_VISIT(state->billion);
2293 [ + + - + ]: 53458 : Py_VISIT(state->DirEntryType);
2294 [ + + - + ]: 53458 : Py_VISIT(state->ScandirIteratorType);
2295 : : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2296 [ + + - + ]: 53458 : Py_VISIT(state->SchedParamType);
2297 : : #endif
2298 [ + - - + ]: 53458 : Py_VISIT(state->StatResultType);
2299 [ + - - + ]: 53458 : Py_VISIT(state->StatVFSResultType);
2300 [ + + - + ]: 53458 : Py_VISIT(state->TerminalSizeType);
2301 [ + + - + ]: 53458 : Py_VISIT(state->TimesResultType);
2302 [ + + - + ]: 53458 : Py_VISIT(state->UnameResultType);
2303 : : #if defined(HAVE_WAITID) && !defined(__APPLE__)
2304 [ + - - + ]: 53458 : Py_VISIT(state->WaitidResultType);
2305 : : #endif
2306 : : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2307 [ + + - + ]: 53458 : Py_VISIT(state->struct_rusage);
2308 : : #endif
2309 [ + + - + ]: 53458 : Py_VISIT(state->st_mode);
2310 : 53458 : return 0;
2311 : : }
2312 : :
2313 : : static void
2314 : 3081 : _posix_free(void *module)
2315 : : {
2316 : 3081 : _posix_clear((PyObject *)module);
2317 : 3081 : }
2318 : :
2319 : : static void
2320 : 3642831 : fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)
2321 : : {
2322 : 3642831 : PyObject *s = _PyLong_FromTime_t(sec);
2323 : 3642831 : PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2324 : 3642831 : PyObject *s_in_ns = NULL;
2325 : 3642831 : PyObject *ns_total = NULL;
2326 : 3642831 : PyObject *float_s = NULL;
2327 : :
2328 [ + - - + ]: 3642831 : if (!(s && ns_fractional))
2329 : 0 : goto exit;
2330 : :
2331 : 3642831 : s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2332 [ - + ]: 3642831 : if (!s_in_ns)
2333 : 0 : goto exit;
2334 : :
2335 : 3642831 : ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2336 [ - + ]: 3642831 : if (!ns_total)
2337 : 0 : goto exit;
2338 : :
2339 : 3642831 : float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2340 [ - + ]: 3642831 : if (!float_s) {
2341 : 0 : goto exit;
2342 : : }
2343 : :
2344 : 3642831 : PyStructSequence_SET_ITEM(v, index, s);
2345 : 3642831 : PyStructSequence_SET_ITEM(v, index+3, float_s);
2346 : 3642831 : PyStructSequence_SET_ITEM(v, index+6, ns_total);
2347 : 3642831 : s = NULL;
2348 : 3642831 : float_s = NULL;
2349 : 3642831 : ns_total = NULL;
2350 : 3642831 : exit:
2351 : 3642831 : Py_XDECREF(s);
2352 : 3642831 : Py_XDECREF(ns_fractional);
2353 : 3642831 : Py_XDECREF(s_in_ns);
2354 : 3642831 : Py_XDECREF(ns_total);
2355 : 3642831 : Py_XDECREF(float_s);
2356 : 3642831 : }
2357 : :
2358 : : /* pack a system stat C structure into the Python stat tuple
2359 : : (used by posix_stat() and posix_fstat()) */
2360 : : static PyObject*
2361 : 1214277 : _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2362 : : {
2363 : : unsigned long ansec, mnsec, cnsec;
2364 : 1214277 : PyObject *StatResultType = get_posix_state(module)->StatResultType;
2365 : 1214277 : PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2366 [ - + ]: 1214277 : if (v == NULL)
2367 : 0 : return NULL;
2368 : :
2369 : 1214277 : PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2370 : : static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2371 : : "stat.st_ino is larger than unsigned long long");
2372 : 1214277 : PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2373 : : #ifdef MS_WINDOWS
2374 : : PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
2375 : : #else
2376 : 1214277 : PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2377 : : #endif
2378 : 1214277 : PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2379 : : #if defined(MS_WINDOWS)
2380 : : PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2381 : : PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2382 : : #else
2383 : 1214277 : PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2384 : 1214277 : PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2385 : : #endif
2386 : : static_assert(sizeof(long long) >= sizeof(st->st_size),
2387 : : "stat.st_size is larger than long long");
2388 : 1214277 : PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2389 : :
2390 : : #if defined(HAVE_STAT_TV_NSEC)
2391 : 1214277 : ansec = st->st_atim.tv_nsec;
2392 : 1214277 : mnsec = st->st_mtim.tv_nsec;
2393 : 1214277 : cnsec = st->st_ctim.tv_nsec;
2394 : : #elif defined(HAVE_STAT_TV_NSEC2)
2395 : : ansec = st->st_atimespec.tv_nsec;
2396 : : mnsec = st->st_mtimespec.tv_nsec;
2397 : : cnsec = st->st_ctimespec.tv_nsec;
2398 : : #elif defined(HAVE_STAT_NSEC)
2399 : : ansec = st->st_atime_nsec;
2400 : : mnsec = st->st_mtime_nsec;
2401 : : cnsec = st->st_ctime_nsec;
2402 : : #else
2403 : : ansec = mnsec = cnsec = 0;
2404 : : #endif
2405 : 1214277 : fill_time(module, v, 7, st->st_atime, ansec);
2406 : 1214277 : fill_time(module, v, 8, st->st_mtime, mnsec);
2407 : 1214277 : fill_time(module, v, 9, st->st_ctime, cnsec);
2408 : :
2409 : : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2410 : 1214277 : PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2411 : : PyLong_FromLong((long)st->st_blksize));
2412 : : #endif
2413 : : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2414 : 1214277 : PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2415 : : PyLong_FromLong((long)st->st_blocks));
2416 : : #endif
2417 : : #ifdef HAVE_STRUCT_STAT_ST_RDEV
2418 : 1214277 : PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2419 : : PyLong_FromLong((long)st->st_rdev));
2420 : : #endif
2421 : : #ifdef HAVE_STRUCT_STAT_ST_GEN
2422 : : PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2423 : : PyLong_FromLong((long)st->st_gen));
2424 : : #endif
2425 : : #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2426 : : {
2427 : : PyObject *val;
2428 : : unsigned long bsec,bnsec;
2429 : : bsec = (long)st->st_birthtime;
2430 : : #ifdef HAVE_STAT_TV_NSEC2
2431 : : bnsec = st->st_birthtimespec.tv_nsec;
2432 : : #else
2433 : : bnsec = 0;
2434 : : #endif
2435 : : val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2436 : : PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2437 : : val);
2438 : : }
2439 : : #endif
2440 : : #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2441 : : PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2442 : : PyLong_FromLong((long)st->st_flags));
2443 : : #endif
2444 : : #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2445 : : PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2446 : : PyLong_FromUnsignedLong(st->st_file_attributes));
2447 : : #endif
2448 : : #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2449 : : PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2450 : : PyUnicode_FromString(st->st_fstype));
2451 : : #endif
2452 : : #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2453 : : PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2454 : : PyLong_FromUnsignedLong(st->st_reparse_tag));
2455 : : #endif
2456 : :
2457 [ - + ]: 1214277 : if (PyErr_Occurred()) {
2458 : 0 : Py_DECREF(v);
2459 : 0 : return NULL;
2460 : : }
2461 : :
2462 : 1214277 : return v;
2463 : : }
2464 : :
2465 : : /* POSIX methods */
2466 : :
2467 : :
2468 : : static PyObject *
2469 : 1387337 : posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2470 : : int dir_fd, int follow_symlinks)
2471 : : {
2472 : : STRUCT_STAT st;
2473 : : int result;
2474 : :
2475 : : #ifdef HAVE_FSTATAT
2476 : 1387337 : int fstatat_unavailable = 0;
2477 : : #endif
2478 : :
2479 : : #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2480 : : if (follow_symlinks_specified(function_name, follow_symlinks))
2481 : : return NULL;
2482 : : #endif
2483 : :
2484 [ + - + - ]: 2774674 : if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2485 [ - + ]: 2774674 : dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2486 : 1387337 : fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2487 : 0 : return NULL;
2488 : :
2489 : 1387337 : Py_BEGIN_ALLOW_THREADS
2490 [ + + ]: 1387337 : if (path->fd != -1)
2491 : 3769 : result = FSTAT(path->fd, &st);
2492 : : #ifdef MS_WINDOWS
2493 : : else if (follow_symlinks)
2494 : : result = win32_stat(path->wide, &st);
2495 : : else
2496 : : result = win32_lstat(path->wide, &st);
2497 : : #else
2498 : : else
2499 : : #if defined(HAVE_LSTAT)
2500 [ + + + + ]: 1383568 : if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2501 : 152463 : result = LSTAT(path->narrow, &st);
2502 : : else
2503 : : #endif /* HAVE_LSTAT */
2504 : : #ifdef HAVE_FSTATAT
2505 [ + + - + ]: 1231105 : if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2506 : 3848 : if (HAVE_FSTATAT_RUNTIME) {
2507 [ + + ]: 3848 : result = fstatat(dir_fd, path->narrow, &st,
2508 : : follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2509 : :
2510 : : } else {
2511 : : fstatat_unavailable = 1;
2512 : : }
2513 : : } else
2514 : : #endif /* HAVE_FSTATAT */
2515 : 1227257 : result = STAT(path->narrow, &st);
2516 : : #endif /* MS_WINDOWS */
2517 : 1387337 : Py_END_ALLOW_THREADS
2518 : :
2519 : : #ifdef HAVE_FSTATAT
2520 [ - + ]: 1387334 : if (fstatat_unavailable) {
2521 : 0 : argument_unavailable_error("stat", "dir_fd");
2522 : 0 : return NULL;
2523 : : }
2524 : : #endif
2525 : :
2526 [ + + ]: 1387334 : if (result != 0) {
2527 : 243997 : return path_error(path);
2528 : : }
2529 : :
2530 : 1143337 : return _pystat_fromstructstat(module, &st);
2531 : : }
2532 : :
2533 : : /*[python input]
2534 : :
2535 : : for s in """
2536 : :
2537 : : FACCESSAT
2538 : : FCHMODAT
2539 : : FCHOWNAT
2540 : : FSTATAT
2541 : : LINKAT
2542 : : MKDIRAT
2543 : : MKFIFOAT
2544 : : MKNODAT
2545 : : OPENAT
2546 : : READLINKAT
2547 : : SYMLINKAT
2548 : : UNLINKAT
2549 : :
2550 : : """.strip().split():
2551 : : s = s.strip()
2552 : : print("""
2553 : : #ifdef HAVE_{s}
2554 : : #define {s}_DIR_FD_CONVERTER dir_fd_converter
2555 : : #else
2556 : : #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2557 : : #endif
2558 : : """.rstrip().format(s=s))
2559 : :
2560 : : for s in """
2561 : :
2562 : : FCHDIR
2563 : : FCHMOD
2564 : : FCHOWN
2565 : : FDOPENDIR
2566 : : FEXECVE
2567 : : FPATHCONF
2568 : : FSTATVFS
2569 : : FTRUNCATE
2570 : :
2571 : : """.strip().split():
2572 : : s = s.strip()
2573 : : print("""
2574 : : #ifdef HAVE_{s}
2575 : : #define PATH_HAVE_{s} 1
2576 : : #else
2577 : : #define PATH_HAVE_{s} 0
2578 : : #endif
2579 : :
2580 : : """.rstrip().format(s=s))
2581 : : [python start generated code]*/
2582 : :
2583 : : #ifdef HAVE_FACCESSAT
2584 : : #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2585 : : #else
2586 : : #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2587 : : #endif
2588 : :
2589 : : #ifdef HAVE_FCHMODAT
2590 : : #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2591 : : #else
2592 : : #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2593 : : #endif
2594 : :
2595 : : #ifdef HAVE_FCHOWNAT
2596 : : #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2597 : : #else
2598 : : #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2599 : : #endif
2600 : :
2601 : : #ifdef HAVE_FSTATAT
2602 : : #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2603 : : #else
2604 : : #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2605 : : #endif
2606 : :
2607 : : #ifdef HAVE_LINKAT
2608 : : #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2609 : : #else
2610 : : #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2611 : : #endif
2612 : :
2613 : : #ifdef HAVE_MKDIRAT
2614 : : #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2615 : : #else
2616 : : #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2617 : : #endif
2618 : :
2619 : : #ifdef HAVE_MKFIFOAT
2620 : : #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2621 : : #else
2622 : : #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2623 : : #endif
2624 : :
2625 : : #ifdef HAVE_MKNODAT
2626 : : #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2627 : : #else
2628 : : #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2629 : : #endif
2630 : :
2631 : : #ifdef HAVE_OPENAT
2632 : : #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2633 : : #else
2634 : : #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2635 : : #endif
2636 : :
2637 : : #ifdef HAVE_READLINKAT
2638 : : #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2639 : : #else
2640 : : #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2641 : : #endif
2642 : :
2643 : : #ifdef HAVE_SYMLINKAT
2644 : : #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2645 : : #else
2646 : : #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2647 : : #endif
2648 : :
2649 : : #ifdef HAVE_UNLINKAT
2650 : : #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2651 : : #else
2652 : : #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2653 : : #endif
2654 : :
2655 : : #ifdef HAVE_FCHDIR
2656 : : #define PATH_HAVE_FCHDIR 1
2657 : : #else
2658 : : #define PATH_HAVE_FCHDIR 0
2659 : : #endif
2660 : :
2661 : : #ifdef HAVE_FCHMOD
2662 : : #define PATH_HAVE_FCHMOD 1
2663 : : #else
2664 : : #define PATH_HAVE_FCHMOD 0
2665 : : #endif
2666 : :
2667 : : #ifdef HAVE_FCHOWN
2668 : : #define PATH_HAVE_FCHOWN 1
2669 : : #else
2670 : : #define PATH_HAVE_FCHOWN 0
2671 : : #endif
2672 : :
2673 : : #ifdef HAVE_FDOPENDIR
2674 : : #define PATH_HAVE_FDOPENDIR 1
2675 : : #else
2676 : : #define PATH_HAVE_FDOPENDIR 0
2677 : : #endif
2678 : :
2679 : : #ifdef HAVE_FEXECVE
2680 : : #define PATH_HAVE_FEXECVE 1
2681 : : #else
2682 : : #define PATH_HAVE_FEXECVE 0
2683 : : #endif
2684 : :
2685 : : #ifdef HAVE_FPATHCONF
2686 : : #define PATH_HAVE_FPATHCONF 1
2687 : : #else
2688 : : #define PATH_HAVE_FPATHCONF 0
2689 : : #endif
2690 : :
2691 : : #ifdef HAVE_FSTATVFS
2692 : : #define PATH_HAVE_FSTATVFS 1
2693 : : #else
2694 : : #define PATH_HAVE_FSTATVFS 0
2695 : : #endif
2696 : :
2697 : : #ifdef HAVE_FTRUNCATE
2698 : : #define PATH_HAVE_FTRUNCATE 1
2699 : : #else
2700 : : #define PATH_HAVE_FTRUNCATE 0
2701 : : #endif
2702 : : /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2703 : :
2704 : : #ifdef MS_WINDOWS
2705 : : #undef PATH_HAVE_FTRUNCATE
2706 : : #define PATH_HAVE_FTRUNCATE 1
2707 : : #endif
2708 : :
2709 : : /*[python input]
2710 : :
2711 : : class path_t_converter(CConverter):
2712 : :
2713 : : type = "path_t"
2714 : : impl_by_reference = True
2715 : : parse_by_reference = True
2716 : :
2717 : : converter = 'path_converter'
2718 : :
2719 : : def converter_init(self, *, allow_fd=False, nullable=False):
2720 : : # right now path_t doesn't support default values.
2721 : : # to support a default value, you'll need to override initialize().
2722 : : if self.default not in (unspecified, None):
2723 : : fail("Can't specify a default to the path_t converter!")
2724 : :
2725 : : if self.c_default not in (None, 'Py_None'):
2726 : : raise RuntimeError("Can't specify a c_default to the path_t converter!")
2727 : :
2728 : : self.nullable = nullable
2729 : : self.allow_fd = allow_fd
2730 : :
2731 : : def pre_render(self):
2732 : : def strify(value):
2733 : : if isinstance(value, str):
2734 : : return value
2735 : : return str(int(bool(value)))
2736 : :
2737 : : # add self.py_name here when merging with posixmodule conversion
2738 : : self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2739 : : self.function.name,
2740 : : self.name,
2741 : : strify(self.nullable),
2742 : : strify(self.allow_fd),
2743 : : )
2744 : :
2745 : : def cleanup(self):
2746 : : return "path_cleanup(&" + self.name + ");\n"
2747 : :
2748 : :
2749 : : class dir_fd_converter(CConverter):
2750 : : type = 'int'
2751 : :
2752 : : def converter_init(self, requires=None):
2753 : : if self.default in (unspecified, None):
2754 : : self.c_default = 'DEFAULT_DIR_FD'
2755 : : if isinstance(requires, str):
2756 : : self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2757 : : else:
2758 : : self.converter = 'dir_fd_converter'
2759 : :
2760 : : class uid_t_converter(CConverter):
2761 : : type = "uid_t"
2762 : : converter = '_Py_Uid_Converter'
2763 : :
2764 : : class gid_t_converter(CConverter):
2765 : : type = "gid_t"
2766 : : converter = '_Py_Gid_Converter'
2767 : :
2768 : : class dev_t_converter(CConverter):
2769 : : type = 'dev_t'
2770 : : converter = '_Py_Dev_Converter'
2771 : :
2772 : : class dev_t_return_converter(unsigned_long_return_converter):
2773 : : type = 'dev_t'
2774 : : conversion_fn = '_PyLong_FromDev'
2775 : : unsigned_cast = '(dev_t)'
2776 : :
2777 : : class FSConverter_converter(CConverter):
2778 : : type = 'PyObject *'
2779 : : converter = 'PyUnicode_FSConverter'
2780 : : def converter_init(self):
2781 : : if self.default is not unspecified:
2782 : : fail("FSConverter_converter does not support default values")
2783 : : self.c_default = 'NULL'
2784 : :
2785 : : def cleanup(self):
2786 : : return "Py_XDECREF(" + self.name + ");\n"
2787 : :
2788 : : class pid_t_converter(CConverter):
2789 : : type = 'pid_t'
2790 : : format_unit = '" _Py_PARSE_PID "'
2791 : :
2792 : : class idtype_t_converter(int_converter):
2793 : : type = 'idtype_t'
2794 : :
2795 : : class id_t_converter(CConverter):
2796 : : type = 'id_t'
2797 : : format_unit = '" _Py_PARSE_PID "'
2798 : :
2799 : : class intptr_t_converter(CConverter):
2800 : : type = 'intptr_t'
2801 : : format_unit = '" _Py_PARSE_INTPTR "'
2802 : :
2803 : : class Py_off_t_converter(CConverter):
2804 : : type = 'Py_off_t'
2805 : : converter = 'Py_off_t_converter'
2806 : :
2807 : : class Py_off_t_return_converter(long_return_converter):
2808 : : type = 'Py_off_t'
2809 : : conversion_fn = 'PyLong_FromPy_off_t'
2810 : :
2811 : : class path_confname_converter(CConverter):
2812 : : type="int"
2813 : : converter="conv_path_confname"
2814 : :
2815 : : class confstr_confname_converter(path_confname_converter):
2816 : : converter='conv_confstr_confname'
2817 : :
2818 : : class sysconf_confname_converter(path_confname_converter):
2819 : : converter="conv_sysconf_confname"
2820 : :
2821 : : [python start generated code]*/
2822 : : /*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/
2823 : :
2824 : : /*[clinic input]
2825 : :
2826 : : os.stat
2827 : :
2828 : : path : path_t(allow_fd=True)
2829 : : Path to be examined; can be string, bytes, a path-like object or
2830 : : open-file-descriptor int.
2831 : :
2832 : : *
2833 : :
2834 : : dir_fd : dir_fd(requires='fstatat') = None
2835 : : If not None, it should be a file descriptor open to a directory,
2836 : : and path should be a relative string; path will then be relative to
2837 : : that directory.
2838 : :
2839 : : follow_symlinks: bool = True
2840 : : If False, and the last element of the path is a symbolic link,
2841 : : stat will examine the symbolic link itself instead of the file
2842 : : the link points to.
2843 : :
2844 : : Perform a stat system call on the given path.
2845 : :
2846 : : dir_fd and follow_symlinks may not be implemented
2847 : : on your platform. If they are unavailable, using them will raise a
2848 : : NotImplementedError.
2849 : :
2850 : : It's an error to use dir_fd or follow_symlinks when specifying path as
2851 : : an open file descriptor.
2852 : :
2853 : : [clinic start generated code]*/
2854 : :
2855 : : static PyObject *
2856 : 1235299 : os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2857 : : /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2858 : : {
2859 : 1235299 : return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
2860 : : }
2861 : :
2862 : :
2863 : : /*[clinic input]
2864 : : os.lstat
2865 : :
2866 : : path : path_t
2867 : :
2868 : : *
2869 : :
2870 : : dir_fd : dir_fd(requires='fstatat') = None
2871 : :
2872 : : Perform a stat system call on the given path, without following symbolic links.
2873 : :
2874 : : Like stat(), but do not follow symbolic links.
2875 : : Equivalent to stat(path, follow_symlinks=False).
2876 : : [clinic start generated code]*/
2877 : :
2878 : : static PyObject *
2879 : 152038 : os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2880 : : /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2881 : : {
2882 : 152038 : int follow_symlinks = 0;
2883 : 152038 : return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
2884 : : }
2885 : :
2886 : :
2887 : : /*[clinic input]
2888 : : os.access -> bool
2889 : :
2890 : : path: path_t
2891 : : Path to be tested; can be string, bytes, or a path-like object.
2892 : :
2893 : : mode: int
2894 : : Operating-system mode bitfield. Can be F_OK to test existence,
2895 : : or the inclusive-OR of R_OK, W_OK, and X_OK.
2896 : :
2897 : : *
2898 : :
2899 : : dir_fd : dir_fd(requires='faccessat') = None
2900 : : If not None, it should be a file descriptor open to a directory,
2901 : : and path should be relative; path will then be relative to that
2902 : : directory.
2903 : :
2904 : : effective_ids: bool = False
2905 : : If True, access will use the effective uid/gid instead of
2906 : : the real uid/gid.
2907 : :
2908 : : follow_symlinks: bool = True
2909 : : If False, and the last element of the path is a symbolic link,
2910 : : access will examine the symbolic link itself instead of the file
2911 : : the link points to.
2912 : :
2913 : : Use the real uid/gid to test for access to a path.
2914 : :
2915 : : {parameters}
2916 : : dir_fd, effective_ids, and follow_symlinks may not be implemented
2917 : : on your platform. If they are unavailable, using them will raise a
2918 : : NotImplementedError.
2919 : :
2920 : : Note that most operations will use the effective uid/gid, therefore this
2921 : : routine can be used in a suid/sgid environment to test if the invoking user
2922 : : has the specified access to the path.
2923 : :
2924 : : [clinic start generated code]*/
2925 : :
2926 : : static int
2927 : 162 : os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2928 : : int effective_ids, int follow_symlinks)
2929 : : /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
2930 : : {
2931 : : int return_value;
2932 : :
2933 : : #ifdef MS_WINDOWS
2934 : : DWORD attr;
2935 : : #else
2936 : : int result;
2937 : : #endif
2938 : :
2939 : : #ifdef HAVE_FACCESSAT
2940 : 162 : int faccessat_unavailable = 0;
2941 : : #endif
2942 : :
2943 : : #ifndef HAVE_FACCESSAT
2944 : : if (follow_symlinks_specified("access", follow_symlinks))
2945 : : return -1;
2946 : :
2947 : : if (effective_ids) {
2948 : : argument_unavailable_error("access", "effective_ids");
2949 : : return -1;
2950 : : }
2951 : : #endif
2952 : :
2953 : : #ifdef MS_WINDOWS
2954 : : Py_BEGIN_ALLOW_THREADS
2955 : : attr = GetFileAttributesW(path->wide);
2956 : : Py_END_ALLOW_THREADS
2957 : :
2958 : : /*
2959 : : * Access is possible if
2960 : : * * we didn't get a -1, and
2961 : : * * write access wasn't requested,
2962 : : * * or the file isn't read-only,
2963 : : * * or it's a directory.
2964 : : * (Directories cannot be read-only on Windows.)
2965 : : */
2966 : : return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
2967 : : (!(mode & 2) ||
2968 : : !(attr & FILE_ATTRIBUTE_READONLY) ||
2969 : : (attr & FILE_ATTRIBUTE_DIRECTORY));
2970 : : #else
2971 : :
2972 : 162 : Py_BEGIN_ALLOW_THREADS
2973 : : #ifdef HAVE_FACCESSAT
2974 [ + + + + ]: 162 : if ((dir_fd != DEFAULT_DIR_FD) ||
2975 [ - + ]: 157 : effective_ids ||
2976 : : !follow_symlinks) {
2977 : :
2978 : 5 : if (HAVE_FACCESSAT_RUNTIME) {
2979 : 5 : int flags = 0;
2980 [ - + ]: 5 : if (!follow_symlinks)
2981 : 0 : flags |= AT_SYMLINK_NOFOLLOW;
2982 [ + + ]: 5 : if (effective_ids)
2983 : 4 : flags |= AT_EACCESS;
2984 : 5 : result = faccessat(dir_fd, path->narrow, mode, flags);
2985 : : } else {
2986 : : faccessat_unavailable = 1;
2987 : : }
2988 : : }
2989 : : else
2990 : : #endif
2991 : 157 : result = access(path->narrow, mode);
2992 : 162 : Py_END_ALLOW_THREADS
2993 : :
2994 : : #ifdef HAVE_FACCESSAT
2995 [ - + ]: 162 : if (faccessat_unavailable) {
2996 [ # # ]: 0 : if (dir_fd != DEFAULT_DIR_FD) {
2997 : 0 : argument_unavailable_error("access", "dir_fd");
2998 : 0 : return -1;
2999 : : }
3000 [ # # ]: 0 : if (follow_symlinks_specified("access", follow_symlinks))
3001 : 0 : return -1;
3002 : :
3003 [ # # ]: 0 : if (effective_ids) {
3004 : 0 : argument_unavailable_error("access", "effective_ids");
3005 : 0 : return -1;
3006 : : }
3007 : : /* should be unreachable */
3008 : 0 : return -1;
3009 : : }
3010 : : #endif
3011 : 162 : return_value = !result;
3012 : : #endif
3013 : :
3014 : 162 : return return_value;
3015 : : }
3016 : :
3017 : : #ifndef F_OK
3018 : : #define F_OK 0
3019 : : #endif
3020 : : #ifndef R_OK
3021 : : #define R_OK 4
3022 : : #endif
3023 : : #ifndef W_OK
3024 : : #define W_OK 2
3025 : : #endif
3026 : : #ifndef X_OK
3027 : : #define X_OK 1
3028 : : #endif
3029 : :
3030 : :
3031 : : #ifdef HAVE_TTYNAME
3032 : : /*[clinic input]
3033 : : os.ttyname
3034 : :
3035 : : fd: int
3036 : : Integer file descriptor handle.
3037 : :
3038 : : /
3039 : :
3040 : : Return the name of the terminal device connected to 'fd'.
3041 : : [clinic start generated code]*/
3042 : :
3043 : : static PyObject *
3044 : 1 : os_ttyname_impl(PyObject *module, int fd)
3045 : : /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3046 : : {
3047 : :
3048 : 1 : long size = sysconf(_SC_TTY_NAME_MAX);
3049 [ - + ]: 1 : if (size == -1) {
3050 : 0 : return posix_error();
3051 : : }
3052 : 1 : char *buffer = (char *)PyMem_RawMalloc(size);
3053 [ - + ]: 1 : if (buffer == NULL) {
3054 : : return PyErr_NoMemory();
3055 : : }
3056 : 1 : int ret = ttyname_r(fd, buffer, size);
3057 [ + - ]: 1 : if (ret != 0) {
3058 : 1 : PyMem_RawFree(buffer);
3059 : 1 : errno = ret;
3060 : 1 : return posix_error();
3061 : : }
3062 : 0 : PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3063 : 0 : PyMem_RawFree(buffer);
3064 : 0 : return res;
3065 : : }
3066 : : #endif
3067 : :
3068 : : #ifdef HAVE_CTERMID
3069 : : /*[clinic input]
3070 : : os.ctermid
3071 : :
3072 : : Return the name of the controlling terminal for this process.
3073 : : [clinic start generated code]*/
3074 : :
3075 : : static PyObject *
3076 : 1 : os_ctermid_impl(PyObject *module)
3077 : : /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3078 : : {
3079 : : char *ret;
3080 : : char buffer[L_ctermid];
3081 : :
3082 : : #ifdef USE_CTERMID_R
3083 : : ret = ctermid_r(buffer);
3084 : : #else
3085 : 1 : ret = ctermid(buffer);
3086 : : #endif
3087 [ - + ]: 1 : if (ret == NULL)
3088 : 0 : return posix_error();
3089 : 1 : return PyUnicode_DecodeFSDefault(buffer);
3090 : : }
3091 : : #endif /* HAVE_CTERMID */
3092 : :
3093 : :
3094 : : /*[clinic input]
3095 : : os.chdir
3096 : :
3097 : : path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3098 : :
3099 : : Change the current working directory to the specified path.
3100 : :
3101 : : path may always be specified as a string.
3102 : : On some platforms, path may also be specified as an open file descriptor.
3103 : : If this functionality is unavailable, using it raises an exception.
3104 : : [clinic start generated code]*/
3105 : :
3106 : : static PyObject *
3107 : 3021 : os_chdir_impl(PyObject *module, path_t *path)
3108 : : /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3109 : : {
3110 : : int result;
3111 : :
3112 [ - + ]: 3021 : if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3113 : 0 : return NULL;
3114 : : }
3115 : :
3116 : 3021 : Py_BEGIN_ALLOW_THREADS
3117 : : #ifdef MS_WINDOWS
3118 : : /* on unix, success = 0, on windows, success = !0 */
3119 : : result = !win32_wchdir(path->wide);
3120 : : #else
3121 : : #ifdef HAVE_FCHDIR
3122 [ - + ]: 3021 : if (path->fd != -1)
3123 : 0 : result = fchdir(path->fd);
3124 : : else
3125 : : #endif
3126 : 3021 : result = chdir(path->narrow);
3127 : : #endif
3128 : 3021 : Py_END_ALLOW_THREADS
3129 : :
3130 [ + + ]: 3021 : if (result) {
3131 : 190 : return path_error(path);
3132 : : }
3133 : :
3134 : 2831 : Py_RETURN_NONE;
3135 : : }
3136 : :
3137 : :
3138 : : #ifdef HAVE_FCHDIR
3139 : : /*[clinic input]
3140 : : os.fchdir
3141 : :
3142 : : fd: fildes
3143 : :
3144 : : Change to the directory of the given file descriptor.
3145 : :
3146 : : fd must be opened on a directory, not a file.
3147 : : Equivalent to os.chdir(fd).
3148 : :
3149 : : [clinic start generated code]*/
3150 : :
3151 : : static PyObject *
3152 : 1 : os_fchdir_impl(PyObject *module, int fd)
3153 : : /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3154 : : {
3155 [ - + ]: 1 : if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3156 : 0 : return NULL;
3157 : : }
3158 : 1 : return posix_fildes_fd(fd, fchdir);
3159 : : }
3160 : : #endif /* HAVE_FCHDIR */
3161 : :
3162 : :
3163 : : /*[clinic input]
3164 : : os.chmod
3165 : :
3166 : : path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3167 : : Path to be modified. May always be specified as a str, bytes, or a path-like object.
3168 : : On some platforms, path may also be specified as an open file descriptor.
3169 : : If this functionality is unavailable, using it raises an exception.
3170 : :
3171 : : mode: int
3172 : : Operating-system mode bitfield.
3173 : :
3174 : : *
3175 : :
3176 : : dir_fd : dir_fd(requires='fchmodat') = None
3177 : : If not None, it should be a file descriptor open to a directory,
3178 : : and path should be relative; path will then be relative to that
3179 : : directory.
3180 : :
3181 : : follow_symlinks: bool = True
3182 : : If False, and the last element of the path is a symbolic link,
3183 : : chmod will modify the symbolic link itself instead of the file
3184 : : the link points to.
3185 : :
3186 : : Change the access permissions of a file.
3187 : :
3188 : : It is an error to use dir_fd or follow_symlinks when specifying path as
3189 : : an open file descriptor.
3190 : : dir_fd and follow_symlinks may not be implemented on your platform.
3191 : : If they are unavailable, using them will raise a NotImplementedError.
3192 : :
3193 : : [clinic start generated code]*/
3194 : :
3195 : : static PyObject *
3196 : 25088 : os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3197 : : int follow_symlinks)
3198 : : /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
3199 : : {
3200 : : int result;
3201 : :
3202 : : #ifdef MS_WINDOWS
3203 : : DWORD attr;
3204 : : #endif
3205 : :
3206 : : #ifdef HAVE_FCHMODAT
3207 : 25088 : int fchmodat_nofollow_unsupported = 0;
3208 : 25088 : int fchmodat_unsupported = 0;
3209 : : #endif
3210 : :
3211 : : #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
3212 : : if (follow_symlinks_specified("chmod", follow_symlinks))
3213 : : return NULL;
3214 : : #endif
3215 : :
3216 [ + + - + ]: 25088 : if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3217 : : dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3218 : 0 : return NULL;
3219 : : }
3220 : :
3221 : : #ifdef MS_WINDOWS
3222 : : Py_BEGIN_ALLOW_THREADS
3223 : : attr = GetFileAttributesW(path->wide);
3224 : : if (attr == INVALID_FILE_ATTRIBUTES)
3225 : : result = 0;
3226 : : else {
3227 : : if (mode & _S_IWRITE)
3228 : : attr &= ~FILE_ATTRIBUTE_READONLY;
3229 : : else
3230 : : attr |= FILE_ATTRIBUTE_READONLY;
3231 : : result = SetFileAttributesW(path->wide, attr);
3232 : : }
3233 : : Py_END_ALLOW_THREADS
3234 : :
3235 : : if (!result) {
3236 : : return path_error(path);
3237 : : }
3238 : : #else /* MS_WINDOWS */
3239 : 25088 : Py_BEGIN_ALLOW_THREADS
3240 : : #ifdef HAVE_FCHMOD
3241 [ - + ]: 25088 : if (path->fd != -1)
3242 : 0 : result = fchmod(path->fd, mode);
3243 : : else
3244 : : #endif /* HAVE_CHMOD */
3245 : : #ifdef HAVE_LCHMOD
3246 : : if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3247 : : result = lchmod(path->narrow, mode);
3248 : : else
3249 : : #endif /* HAVE_LCHMOD */
3250 : : #ifdef HAVE_FCHMODAT
3251 [ + + - + ]: 25088 : if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3252 : 1 : if (HAVE_FCHMODAT_RUNTIME) {
3253 : : /*
3254 : : * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3255 : : * The documentation specifically shows how to use it,
3256 : : * and then says it isn't implemented yet.
3257 : : * (true on linux with glibc 2.15, and openindiana 3.x)
3258 : : *
3259 : : * Once it is supported, os.chmod will automatically
3260 : : * support dir_fd and follow_symlinks=False. (Hopefully.)
3261 : : * Until then, we need to be careful what exception we raise.
3262 : : */
3263 [ + - ]: 1 : result = fchmodat(dir_fd, path->narrow, mode,
3264 : : follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3265 : : /*
3266 : : * But wait! We can't throw the exception without allowing threads,
3267 : : * and we can't do that in this nested scope. (Macro trickery, sigh.)
3268 : : */
3269 : 1 : fchmodat_nofollow_unsupported =
3270 : 0 : result &&
3271 [ - + - - : 1 : ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
- - - - ]
3272 : : !follow_symlinks;
3273 : : } else {
3274 : : fchmodat_unsupported = 1;
3275 : : fchmodat_nofollow_unsupported = 1;
3276 : :
3277 : : result = -1;
3278 : : }
3279 : : }
3280 : : else
3281 : : #endif /* HAVE_FHCMODAT */
3282 : : {
3283 : : #ifdef HAVE_CHMOD
3284 : 25087 : result = chmod(path->narrow, mode);
3285 : : #elif defined(__wasi__)
3286 : : // WASI SDK 15.0 does not support chmod.
3287 : : // Ignore missing syscall for now.
3288 : : result = 0;
3289 : : #else
3290 : : result = -1;
3291 : : errno = ENOSYS;
3292 : : #endif
3293 : : }
3294 : 25088 : Py_END_ALLOW_THREADS
3295 : :
3296 [ + + ]: 25088 : if (result) {
3297 : : #ifdef HAVE_FCHMODAT
3298 [ - + ]: 5 : if (fchmodat_unsupported) {
3299 [ # # ]: 0 : if (dir_fd != DEFAULT_DIR_FD) {
3300 : 0 : argument_unavailable_error("chmod", "dir_fd");
3301 : 0 : return NULL;
3302 : : }
3303 : : }
3304 : :
3305 [ - + ]: 5 : if (fchmodat_nofollow_unsupported) {
3306 [ # # ]: 0 : if (dir_fd != DEFAULT_DIR_FD)
3307 : 0 : dir_fd_and_follow_symlinks_invalid("chmod",
3308 : : dir_fd, follow_symlinks);
3309 : : else
3310 : 0 : follow_symlinks_specified("chmod", follow_symlinks);
3311 : 0 : return NULL;
3312 : : }
3313 : : else
3314 : : #endif /* HAVE_FCHMODAT */
3315 : 5 : return path_error(path);
3316 : : }
3317 : : #endif /* MS_WINDOWS */
3318 : :
3319 : 25083 : Py_RETURN_NONE;
3320 : : }
3321 : :
3322 : :
3323 : : #ifdef HAVE_FCHMOD
3324 : : /*[clinic input]
3325 : : os.fchmod
3326 : :
3327 : : fd: int
3328 : : mode: int
3329 : :
3330 : : Change the access permissions of the file given by file descriptor fd.
3331 : :
3332 : : Equivalent to os.chmod(fd, mode).
3333 : : [clinic start generated code]*/
3334 : :
3335 : : static PyObject *
3336 : 1 : os_fchmod_impl(PyObject *module, int fd, int mode)
3337 : : /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
3338 : : {
3339 : : int res;
3340 : 1 : int async_err = 0;
3341 : :
3342 [ - + ]: 1 : if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3343 : 0 : return NULL;
3344 : : }
3345 : :
3346 : : do {
3347 : 1 : Py_BEGIN_ALLOW_THREADS
3348 : 1 : res = fchmod(fd, mode);
3349 : 1 : Py_END_ALLOW_THREADS
3350 [ + - - + : 1 : } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
3351 [ + - ]: 1 : if (res != 0)
3352 [ + - ]: 1 : return (!async_err) ? posix_error() : NULL;
3353 : :
3354 : 0 : Py_RETURN_NONE;
3355 : : }
3356 : : #endif /* HAVE_FCHMOD */
3357 : :
3358 : :
3359 : : #ifdef HAVE_LCHMOD
3360 : : /*[clinic input]
3361 : : os.lchmod
3362 : :
3363 : : path: path_t
3364 : : mode: int
3365 : :
3366 : : Change the access permissions of a file, without following symbolic links.
3367 : :
3368 : : If path is a symlink, this affects the link itself rather than the target.
3369 : : Equivalent to chmod(path, mode, follow_symlinks=False)."
3370 : : [clinic start generated code]*/
3371 : :
3372 : : static PyObject *
3373 : : os_lchmod_impl(PyObject *module, path_t *path, int mode)
3374 : : /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3375 : : {
3376 : : int res;
3377 : : if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3378 : : return NULL;
3379 : : }
3380 : : Py_BEGIN_ALLOW_THREADS
3381 : : res = lchmod(path->narrow, mode);
3382 : : Py_END_ALLOW_THREADS
3383 : : if (res < 0) {
3384 : : path_error(path);
3385 : : return NULL;
3386 : : }
3387 : : Py_RETURN_NONE;
3388 : : }
3389 : : #endif /* HAVE_LCHMOD */
3390 : :
3391 : :
3392 : : #ifdef HAVE_CHFLAGS
3393 : : /*[clinic input]
3394 : : os.chflags
3395 : :
3396 : : path: path_t
3397 : : flags: unsigned_long(bitwise=True)
3398 : : follow_symlinks: bool=True
3399 : :
3400 : : Set file flags.
3401 : :
3402 : : If follow_symlinks is False, and the last element of the path is a symbolic
3403 : : link, chflags will change flags on the symbolic link itself instead of the
3404 : : file the link points to.
3405 : : follow_symlinks may not be implemented on your platform. If it is
3406 : : unavailable, using it will raise a NotImplementedError.
3407 : :
3408 : : [clinic start generated code]*/
3409 : :
3410 : : static PyObject *
3411 : : os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3412 : : int follow_symlinks)
3413 : : /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3414 : : {
3415 : : int result;
3416 : :
3417 : : #ifndef HAVE_LCHFLAGS
3418 : : if (follow_symlinks_specified("chflags", follow_symlinks))
3419 : : return NULL;
3420 : : #endif
3421 : :
3422 : : if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3423 : : return NULL;
3424 : : }
3425 : :
3426 : : Py_BEGIN_ALLOW_THREADS
3427 : : #ifdef HAVE_LCHFLAGS
3428 : : if (!follow_symlinks)
3429 : : result = lchflags(path->narrow, flags);
3430 : : else
3431 : : #endif
3432 : : result = chflags(path->narrow, flags);
3433 : : Py_END_ALLOW_THREADS
3434 : :
3435 : : if (result)
3436 : : return path_error(path);
3437 : :
3438 : : Py_RETURN_NONE;
3439 : : }
3440 : : #endif /* HAVE_CHFLAGS */
3441 : :
3442 : :
3443 : : #ifdef HAVE_LCHFLAGS
3444 : : /*[clinic input]
3445 : : os.lchflags
3446 : :
3447 : : path: path_t
3448 : : flags: unsigned_long(bitwise=True)
3449 : :
3450 : : Set file flags.
3451 : :
3452 : : This function will not follow symbolic links.
3453 : : Equivalent to chflags(path, flags, follow_symlinks=False).
3454 : : [clinic start generated code]*/
3455 : :
3456 : : static PyObject *
3457 : : os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3458 : : /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3459 : : {
3460 : : int res;
3461 : : if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3462 : : return NULL;
3463 : : }
3464 : : Py_BEGIN_ALLOW_THREADS
3465 : : res = lchflags(path->narrow, flags);
3466 : : Py_END_ALLOW_THREADS
3467 : : if (res < 0) {
3468 : : return path_error(path);
3469 : : }
3470 : : Py_RETURN_NONE;
3471 : : }
3472 : : #endif /* HAVE_LCHFLAGS */
3473 : :
3474 : :
3475 : : #ifdef HAVE_CHROOT
3476 : : /*[clinic input]
3477 : : os.chroot
3478 : : path: path_t
3479 : :
3480 : : Change root directory to path.
3481 : :
3482 : : [clinic start generated code]*/
3483 : :
3484 : : static PyObject *
3485 : 5 : os_chroot_impl(PyObject *module, path_t *path)
3486 : : /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3487 : : {
3488 : : int res;
3489 : 5 : Py_BEGIN_ALLOW_THREADS
3490 : 5 : res = chroot(path->narrow);
3491 : 5 : Py_END_ALLOW_THREADS
3492 [ + - ]: 5 : if (res < 0)
3493 : 5 : return path_error(path);
3494 : 0 : Py_RETURN_NONE;
3495 : : }
3496 : : #endif /* HAVE_CHROOT */
3497 : :
3498 : :
3499 : : #ifdef HAVE_FSYNC
3500 : : /*[clinic input]
3501 : : os.fsync
3502 : :
3503 : : fd: fildes
3504 : :
3505 : : Force write of fd to disk.
3506 : : [clinic start generated code]*/
3507 : :
3508 : : static PyObject *
3509 : 559 : os_fsync_impl(PyObject *module, int fd)
3510 : : /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3511 : : {
3512 : 559 : return posix_fildes_fd(fd, fsync);
3513 : : }
3514 : : #endif /* HAVE_FSYNC */
3515 : :
3516 : :
3517 : : #ifdef HAVE_SYNC
3518 : : /*[clinic input]
3519 : : os.sync
3520 : :
3521 : : Force write of everything to disk.
3522 : : [clinic start generated code]*/
3523 : :
3524 : : static PyObject *
3525 : 1 : os_sync_impl(PyObject *module)
3526 : : /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3527 : : {
3528 : 1 : Py_BEGIN_ALLOW_THREADS
3529 : 1 : sync();
3530 : 1 : Py_END_ALLOW_THREADS
3531 : 1 : Py_RETURN_NONE;
3532 : : }
3533 : : #endif /* HAVE_SYNC */
3534 : :
3535 : :
3536 : : #ifdef HAVE_FDATASYNC
3537 : : #ifdef __hpux
3538 : : extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3539 : : #endif
3540 : :
3541 : : /*[clinic input]
3542 : : os.fdatasync
3543 : :
3544 : : fd: fildes
3545 : :
3546 : : Force write of fd to disk without forcing update of metadata.
3547 : : [clinic start generated code]*/
3548 : :
3549 : : static PyObject *
3550 : 1 : os_fdatasync_impl(PyObject *module, int fd)
3551 : : /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3552 : : {
3553 : 1 : return posix_fildes_fd(fd, fdatasync);
3554 : : }
3555 : : #endif /* HAVE_FDATASYNC */
3556 : :
3557 : :
3558 : : #ifdef HAVE_CHOWN
3559 : : /*[clinic input]
3560 : : os.chown
3561 : :
3562 : : path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3563 : : Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3564 : :
3565 : : uid: uid_t
3566 : :
3567 : : gid: gid_t
3568 : :
3569 : : *
3570 : :
3571 : : dir_fd : dir_fd(requires='fchownat') = None
3572 : : If not None, it should be a file descriptor open to a directory,
3573 : : and path should be relative; path will then be relative to that
3574 : : directory.
3575 : :
3576 : : follow_symlinks: bool = True
3577 : : If False, and the last element of the path is a symbolic link,
3578 : : stat will examine the symbolic link itself instead of the file
3579 : : the link points to.
3580 : :
3581 : : Change the owner and group id of path to the numeric uid and gid.\
3582 : :
3583 : : path may always be specified as a string.
3584 : : On some platforms, path may also be specified as an open file descriptor.
3585 : : If this functionality is unavailable, using it raises an exception.
3586 : : If dir_fd is not None, it should be a file descriptor open to a directory,
3587 : : and path should be relative; path will then be relative to that directory.
3588 : : If follow_symlinks is False, and the last element of the path is a symbolic
3589 : : link, chown will modify the symbolic link itself instead of the file the
3590 : : link points to.
3591 : : It is an error to use dir_fd or follow_symlinks when specifying path as
3592 : : an open file descriptor.
3593 : : dir_fd and follow_symlinks may not be implemented on your platform.
3594 : : If they are unavailable, using them will raise a NotImplementedError.
3595 : :
3596 : : [clinic start generated code]*/
3597 : :
3598 : : static PyObject *
3599 : 28 : os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3600 : : int dir_fd, int follow_symlinks)
3601 : : /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3602 : : {
3603 : : int result;
3604 : :
3605 : : #if defined(HAVE_FCHOWNAT)
3606 : 28 : int fchownat_unsupported = 0;
3607 : : #endif
3608 : :
3609 : : #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3610 : : if (follow_symlinks_specified("chown", follow_symlinks))
3611 : : return NULL;
3612 : : #endif
3613 [ + - - + ]: 56 : if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3614 : 28 : fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3615 : 0 : return NULL;
3616 : :
3617 [ + + - + ]: 28 : if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3618 : : dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3619 : 0 : return NULL;
3620 : : }
3621 : :
3622 : 28 : Py_BEGIN_ALLOW_THREADS
3623 : : #ifdef HAVE_FCHOWN
3624 [ - + ]: 28 : if (path->fd != -1)
3625 : 0 : result = fchown(path->fd, uid, gid);
3626 : : else
3627 : : #endif
3628 : : #ifdef HAVE_LCHOWN
3629 [ - + - - ]: 28 : if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3630 : 0 : result = lchown(path->narrow, uid, gid);
3631 : : else
3632 : : #endif
3633 : : #ifdef HAVE_FCHOWNAT
3634 [ + + - + ]: 28 : if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
3635 : 1 : if (HAVE_FCHOWNAT_RUNTIME) {
3636 [ + - ]: 1 : result = fchownat(dir_fd, path->narrow, uid, gid,
3637 : : follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3638 : : } else {
3639 : : fchownat_unsupported = 1;
3640 : : }
3641 : : } else
3642 : : #endif
3643 : 27 : result = chown(path->narrow, uid, gid);
3644 : 28 : Py_END_ALLOW_THREADS
3645 : :
3646 : : #ifdef HAVE_FCHOWNAT
3647 [ - + ]: 28 : if (fchownat_unsupported) {
3648 : : /* This would be incorrect if the current platform
3649 : : * doesn't support lchown.
3650 : : */
3651 : 0 : argument_unavailable_error(NULL, "dir_fd");
3652 : 0 : return NULL;
3653 : : }
3654 : : #endif
3655 : :
3656 [ + + ]: 28 : if (result)
3657 : 10 : return path_error(path);
3658 : :
3659 : 18 : Py_RETURN_NONE;
3660 : : }
3661 : : #endif /* HAVE_CHOWN */
3662 : :
3663 : :
3664 : : #ifdef HAVE_FCHOWN
3665 : : /*[clinic input]
3666 : : os.fchown
3667 : :
3668 : : fd: int
3669 : : uid: uid_t
3670 : : gid: gid_t
3671 : :
3672 : : Change the owner and group id of the file specified by file descriptor.
3673 : :
3674 : : Equivalent to os.chown(fd, uid, gid).
3675 : :
3676 : : [clinic start generated code]*/
3677 : :
3678 : : static PyObject *
3679 : 7 : os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3680 : : /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3681 : : {
3682 : : int res;
3683 : 7 : int async_err = 0;
3684 : :
3685 [ - + ]: 7 : if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
3686 : 0 : return NULL;
3687 : : }
3688 : :
3689 : : do {
3690 : 7 : Py_BEGIN_ALLOW_THREADS
3691 : 7 : res = fchown(fd, uid, gid);
3692 : 7 : Py_END_ALLOW_THREADS
3693 [ + + - + : 7 : } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
3694 [ + + ]: 7 : if (res != 0)
3695 [ + - ]: 4 : return (!async_err) ? posix_error() : NULL;
3696 : :
3697 : 3 : Py_RETURN_NONE;
3698 : : }
3699 : : #endif /* HAVE_FCHOWN */
3700 : :
3701 : :
3702 : : #ifdef HAVE_LCHOWN
3703 : : /*[clinic input]
3704 : : os.lchown
3705 : :
3706 : : path : path_t
3707 : : uid: uid_t
3708 : : gid: gid_t
3709 : :
3710 : : Change the owner and group id of path to the numeric uid and gid.
3711 : :
3712 : : This function will not follow symbolic links.
3713 : : Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3714 : : [clinic start generated code]*/
3715 : :
3716 : : static PyObject *
3717 : 11 : os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3718 : : /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3719 : : {
3720 : : int res;
3721 [ - + ]: 11 : if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
3722 : 0 : return NULL;
3723 : : }
3724 : 11 : Py_BEGIN_ALLOW_THREADS
3725 : 11 : res = lchown(path->narrow, uid, gid);
3726 : 11 : Py_END_ALLOW_THREADS
3727 [ + + ]: 11 : if (res < 0) {
3728 : 8 : return path_error(path);
3729 : : }
3730 : 3 : Py_RETURN_NONE;
3731 : : }
3732 : : #endif /* HAVE_LCHOWN */
3733 : :
3734 : :
3735 : : static PyObject *
3736 : 34983 : posix_getcwd(int use_bytes)
3737 : : {
3738 : : #ifdef MS_WINDOWS
3739 : : wchar_t wbuf[MAXPATHLEN];
3740 : : wchar_t *wbuf2 = wbuf;
3741 : : DWORD len;
3742 : :
3743 : : Py_BEGIN_ALLOW_THREADS
3744 : : len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3745 : : /* If the buffer is large enough, len does not include the
3746 : : terminating \0. If the buffer is too small, len includes
3747 : : the space needed for the terminator. */
3748 : : if (len >= Py_ARRAY_LENGTH(wbuf)) {
3749 : : if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3750 : : wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3751 : : }
3752 : : else {
3753 : : wbuf2 = NULL;
3754 : : }
3755 : : if (wbuf2) {
3756 : : len = GetCurrentDirectoryW(len, wbuf2);
3757 : : }
3758 : : }
3759 : : Py_END_ALLOW_THREADS
3760 : :
3761 : : if (!wbuf2) {
3762 : : PyErr_NoMemory();
3763 : : return NULL;
3764 : : }
3765 : : if (!len) {
3766 : : if (wbuf2 != wbuf)
3767 : : PyMem_RawFree(wbuf2);
3768 : : return PyErr_SetFromWindowsErr(0);
3769 : : }
3770 : :
3771 : : PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3772 : : if (wbuf2 != wbuf) {
3773 : : PyMem_RawFree(wbuf2);
3774 : : }
3775 : :
3776 : : if (use_bytes) {
3777 : : if (resobj == NULL) {
3778 : : return NULL;
3779 : : }
3780 : : Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3781 : : }
3782 : :
3783 : : return resobj;
3784 : : #else
3785 : 34983 : const size_t chunk = 1024;
3786 : :
3787 : 34983 : char *buf = NULL;
3788 : 34983 : char *cwd = NULL;
3789 : 34983 : size_t buflen = 0;
3790 : :
3791 : 34983 : Py_BEGIN_ALLOW_THREADS
3792 : : do {
3793 : : char *newbuf;
3794 [ + - ]: 34989 : if (buflen <= PY_SSIZE_T_MAX - chunk) {
3795 : 34989 : buflen += chunk;
3796 : 34989 : newbuf = PyMem_RawRealloc(buf, buflen);
3797 : : }
3798 : : else {
3799 : 0 : newbuf = NULL;
3800 : : }
3801 [ - + ]: 34989 : if (newbuf == NULL) {
3802 : 0 : PyMem_RawFree(buf);
3803 : 0 : buf = NULL;
3804 : 0 : break;
3805 : : }
3806 : 34989 : buf = newbuf;
3807 : :
3808 : 34989 : cwd = getcwd(buf, buflen);
3809 [ + + + + ]: 34989 : } while (cwd == NULL && errno == ERANGE);
3810 : 34983 : Py_END_ALLOW_THREADS
3811 : :
3812 [ - + ]: 34983 : if (buf == NULL) {
3813 : : return PyErr_NoMemory();
3814 : : }
3815 [ + + ]: 34983 : if (cwd == NULL) {
3816 : 4 : PyMem_RawFree(buf);
3817 : 4 : return posix_error();
3818 : : }
3819 : :
3820 : : PyObject *obj;
3821 [ + + ]: 34979 : if (use_bytes) {
3822 : 67 : obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3823 : : }
3824 : : else {
3825 : 34912 : obj = PyUnicode_DecodeFSDefault(buf);
3826 : : }
3827 : 34979 : PyMem_RawFree(buf);
3828 : :
3829 : 34979 : return obj;
3830 : : #endif /* !MS_WINDOWS */
3831 : : }
3832 : :
3833 : :
3834 : : /*[clinic input]
3835 : : os.getcwd
3836 : :
3837 : : Return a unicode string representing the current working directory.
3838 : : [clinic start generated code]*/
3839 : :
3840 : : static PyObject *
3841 : 34916 : os_getcwd_impl(PyObject *module)
3842 : : /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3843 : : {
3844 : 34916 : return posix_getcwd(0);
3845 : : }
3846 : :
3847 : :
3848 : : /*[clinic input]
3849 : : os.getcwdb
3850 : :
3851 : : Return a bytes string representing the current working directory.
3852 : : [clinic start generated code]*/
3853 : :
3854 : : static PyObject *
3855 : 67 : os_getcwdb_impl(PyObject *module)
3856 : : /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3857 : : {
3858 : 67 : return posix_getcwd(1);
3859 : : }
3860 : :
3861 : :
3862 : : #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3863 : : #define HAVE_LINK 1
3864 : : #endif
3865 : :
3866 : : #ifdef HAVE_LINK
3867 : : /*[clinic input]
3868 : :
3869 : : os.link
3870 : :
3871 : : src : path_t
3872 : : dst : path_t
3873 : : *
3874 : : src_dir_fd : dir_fd = None
3875 : : dst_dir_fd : dir_fd = None
3876 : : follow_symlinks: bool = True
3877 : :
3878 : : Create a hard link to a file.
3879 : :
3880 : : If either src_dir_fd or dst_dir_fd is not None, it should be a file
3881 : : descriptor open to a directory, and the respective path string (src or dst)
3882 : : should be relative; the path will then be relative to that directory.
3883 : : If follow_symlinks is False, and the last element of src is a symbolic
3884 : : link, link will create a link to the symbolic link itself instead of the
3885 : : file the link points to.
3886 : : src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3887 : : platform. If they are unavailable, using them will raise a
3888 : : NotImplementedError.
3889 : : [clinic start generated code]*/
3890 : :
3891 : : static PyObject *
3892 : 322 : os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3893 : : int dst_dir_fd, int follow_symlinks)
3894 : : /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3895 : : {
3896 : : #ifdef MS_WINDOWS
3897 : : BOOL result = FALSE;
3898 : : #else
3899 : : int result;
3900 : : #endif
3901 : : #if defined(HAVE_LINKAT)
3902 : 322 : int linkat_unavailable = 0;
3903 : : #endif
3904 : :
3905 : : #ifndef HAVE_LINKAT
3906 : : if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3907 : : argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3908 : : return NULL;
3909 : : }
3910 : : #endif
3911 : :
3912 : : #ifndef MS_WINDOWS
3913 [ + - + - : 322 : if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
- + - - ]
3914 : 0 : PyErr_SetString(PyExc_NotImplementedError,
3915 : : "link: src and dst must be the same type");
3916 : 0 : return NULL;
3917 : : }
3918 : : #endif
3919 : :
3920 [ + + + + : 322 : if (PySys_Audit("os.link", "OOii", src->object, dst->object,
- + ]
3921 : : src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
3922 : : dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
3923 : 0 : return NULL;
3924 : : }
3925 : :
3926 : : #ifdef MS_WINDOWS
3927 : : Py_BEGIN_ALLOW_THREADS
3928 : : result = CreateHardLinkW(dst->wide, src->wide, NULL);
3929 : : Py_END_ALLOW_THREADS
3930 : :
3931 : : if (!result)
3932 : : return path_error2(src, dst);
3933 : : #else
3934 : 322 : Py_BEGIN_ALLOW_THREADS
3935 : : #ifdef HAVE_LINKAT
3936 [ + + + - ]: 322 : if ((src_dir_fd != DEFAULT_DIR_FD) ||
3937 [ - + ]: 321 : (dst_dir_fd != DEFAULT_DIR_FD) ||
3938 : : (!follow_symlinks)) {
3939 : :
3940 : 1 : if (HAVE_LINKAT_RUNTIME) {
3941 : :
3942 [ + - ]: 1 : result = linkat(src_dir_fd, src->narrow,
3943 : : dst_dir_fd, dst->narrow,
3944 : : follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3945 : :
3946 : : }
3947 : : #ifdef __APPLE__
3948 : : else {
3949 : : if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
3950 : : /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
3951 : : result = link(src->narrow, dst->narrow);
3952 : : } else {
3953 : : linkat_unavailable = 1;
3954 : : }
3955 : : }
3956 : : #endif
3957 : : }
3958 : : else
3959 : : #endif /* HAVE_LINKAT */
3960 : 321 : result = link(src->narrow, dst->narrow);
3961 : 322 : Py_END_ALLOW_THREADS
3962 : :
3963 : : #ifdef HAVE_LINKAT
3964 [ - + ]: 322 : if (linkat_unavailable) {
3965 : : /* Either or both dir_fd arguments were specified */
3966 [ # # ]: 0 : if (src_dir_fd != DEFAULT_DIR_FD) {
3967 : 0 : argument_unavailable_error("link", "src_dir_fd");
3968 : : } else {
3969 : 0 : argument_unavailable_error("link", "dst_dir_fd");
3970 : : }
3971 : 0 : return NULL;
3972 : : }
3973 : : #endif
3974 : :
3975 [ + + ]: 322 : if (result)
3976 : 6 : return path_error2(src, dst);
3977 : : #endif /* MS_WINDOWS */
3978 : :
3979 : 316 : Py_RETURN_NONE;
3980 : : }
3981 : : #endif
3982 : :
3983 : :
3984 : : #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3985 : : static PyObject *
3986 : : _listdir_windows_no_opendir(path_t *path, PyObject *list)
3987 : : {
3988 : : PyObject *v;
3989 : : HANDLE hFindFile = INVALID_HANDLE_VALUE;
3990 : : BOOL result;
3991 : : wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
3992 : : /* only claim to have space for MAX_PATH */
3993 : : Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
3994 : : wchar_t *wnamebuf = NULL;
3995 : :
3996 : : WIN32_FIND_DATAW wFileData;
3997 : : const wchar_t *po_wchars;
3998 : :
3999 : : if (!path->wide) { /* Default arg: "." */
4000 : : po_wchars = L".";
4001 : : len = 1;
4002 : : } else {
4003 : : po_wchars = path->wide;
4004 : : len = wcslen(path->wide);
4005 : : }
4006 : : /* The +5 is so we can append "\\*.*\0" */
4007 : : wnamebuf = PyMem_New(wchar_t, len + 5);
4008 : : if (!wnamebuf) {
4009 : : PyErr_NoMemory();
4010 : : goto exit;
4011 : : }
4012 : : wcscpy(wnamebuf, po_wchars);
4013 : : if (len > 0) {
4014 : : wchar_t wch = wnamebuf[len-1];
4015 : : if (wch != SEP && wch != ALTSEP && wch != L':')
4016 : : wnamebuf[len++] = SEP;
4017 : : wcscpy(wnamebuf + len, L"*.*");
4018 : : }
4019 : : if ((list = PyList_New(0)) == NULL) {
4020 : : goto exit;
4021 : : }
4022 : : Py_BEGIN_ALLOW_THREADS
4023 : : hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4024 : : Py_END_ALLOW_THREADS
4025 : : if (hFindFile == INVALID_HANDLE_VALUE) {
4026 : : int error = GetLastError();
4027 : : if (error == ERROR_FILE_NOT_FOUND)
4028 : : goto exit;
4029 : : Py_DECREF(list);
4030 : : list = path_error(path);
4031 : : goto exit;
4032 : : }
4033 : : do {
4034 : : /* Skip over . and .. */
4035 : : if (wcscmp(wFileData.cFileName, L".") != 0 &&
4036 : : wcscmp(wFileData.cFileName, L"..") != 0) {
4037 : : v = PyUnicode_FromWideChar(wFileData.cFileName,
4038 : : wcslen(wFileData.cFileName));
4039 : : if (path->narrow && v) {
4040 : : Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4041 : : }
4042 : : if (v == NULL) {
4043 : : Py_DECREF(list);
4044 : : list = NULL;
4045 : : break;
4046 : : }
4047 : : if (PyList_Append(list, v) != 0) {
4048 : : Py_DECREF(v);
4049 : : Py_DECREF(list);
4050 : : list = NULL;
4051 : : break;
4052 : : }
4053 : : Py_DECREF(v);
4054 : : }
4055 : : Py_BEGIN_ALLOW_THREADS
4056 : : result = FindNextFileW(hFindFile, &wFileData);
4057 : : Py_END_ALLOW_THREADS
4058 : : /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4059 : : it got to the end of the directory. */
4060 : : if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4061 : : Py_DECREF(list);
4062 : : list = path_error(path);
4063 : : goto exit;
4064 : : }
4065 : : } while (result == TRUE);
4066 : :
4067 : : exit:
4068 : : if (hFindFile != INVALID_HANDLE_VALUE) {
4069 : : if (FindClose(hFindFile) == FALSE) {
4070 : : if (list != NULL) {
4071 : : Py_DECREF(list);
4072 : : list = path_error(path);
4073 : : }
4074 : : }
4075 : : }
4076 : : PyMem_Free(wnamebuf);
4077 : :
4078 : : return list;
4079 : : } /* end of _listdir_windows_no_opendir */
4080 : :
4081 : : #else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4082 : :
4083 : : static PyObject *
4084 : 36661 : _posix_listdir(path_t *path, PyObject *list)
4085 : : {
4086 : : PyObject *v;
4087 : 36661 : DIR *dirp = NULL;
4088 : : struct dirent *ep;
4089 : : int return_str; /* if false, return bytes */
4090 : : #ifdef HAVE_FDOPENDIR
4091 : 36661 : int fd = -1;
4092 : : #endif
4093 : :
4094 : 36661 : errno = 0;
4095 : : #ifdef HAVE_FDOPENDIR
4096 [ + + ]: 36661 : if (path->fd != -1) {
4097 : : if (HAVE_FDOPENDIR_RUNTIME) {
4098 : : /* closedir() closes the FD, so we duplicate it */
4099 : 55 : fd = _Py_dup(path->fd);
4100 [ - + ]: 55 : if (fd == -1)
4101 : 0 : return NULL;
4102 : :
4103 : 55 : return_str = 1;
4104 : :
4105 : 55 : Py_BEGIN_ALLOW_THREADS
4106 : 55 : dirp = fdopendir(fd);
4107 : 55 : Py_END_ALLOW_THREADS
4108 : : } else {
4109 : : PyErr_SetString(PyExc_TypeError,
4110 : : "listdir: path should be string, bytes, os.PathLike or None, not int");
4111 : : return NULL;
4112 : : }
4113 : : }
4114 : : else
4115 : : #endif
4116 : : {
4117 : : const char *name;
4118 [ + + ]: 36606 : if (path->narrow) {
4119 : 34528 : name = path->narrow;
4120 : : /* only return bytes if they specified a bytes-like object */
4121 : 34528 : return_str = !PyObject_CheckBuffer(path->object);
4122 : : }
4123 : : else {
4124 : 2078 : name = ".";
4125 : 2078 : return_str = 1;
4126 : : }
4127 : :
4128 : 36606 : Py_BEGIN_ALLOW_THREADS
4129 : 36606 : dirp = opendir(name);
4130 : 36606 : Py_END_ALLOW_THREADS
4131 : : }
4132 : :
4133 [ + + ]: 36661 : if (dirp == NULL) {
4134 : 527 : list = path_error(path);
4135 : : #ifdef HAVE_FDOPENDIR
4136 [ - + ]: 527 : if (fd != -1) {
4137 : 0 : Py_BEGIN_ALLOW_THREADS
4138 : 0 : close(fd);
4139 : 0 : Py_END_ALLOW_THREADS
4140 : : }
4141 : : #endif
4142 : 527 : goto exit;
4143 : : }
4144 [ - + ]: 36134 : if ((list = PyList_New(0)) == NULL) {
4145 : 0 : goto exit;
4146 : : }
4147 : : for (;;) {
4148 : 2306356 : errno = 0;
4149 : 2306356 : Py_BEGIN_ALLOW_THREADS
4150 : 2306356 : ep = readdir(dirp);
4151 : 2306356 : Py_END_ALLOW_THREADS
4152 [ + + ]: 2306356 : if (ep == NULL) {
4153 [ + - ]: 36134 : if (errno == 0) {
4154 : 36134 : break;
4155 : : } else {
4156 : 0 : Py_DECREF(list);
4157 : 0 : list = path_error(path);
4158 : 0 : goto exit;
4159 : : }
4160 : : }
4161 [ + + ]: 2270222 : if (ep->d_name[0] == '.' &&
4162 [ + + ]: 72771 : (NAMLEN(ep) == 1 ||
4163 [ + + + - ]: 36637 : (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4164 : 72268 : continue;
4165 [ + + ]: 2197954 : if (return_str)
4166 : 2197856 : v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4167 : : else
4168 : 98 : v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4169 [ - + ]: 2197954 : if (v == NULL) {
4170 [ # # ]: 0 : Py_CLEAR(list);
4171 : 0 : break;
4172 : : }
4173 [ - + ]: 2197954 : if (PyList_Append(list, v) != 0) {
4174 : 0 : Py_DECREF(v);
4175 [ # # ]: 0 : Py_CLEAR(list);
4176 : 0 : break;
4177 : : }
4178 : 2197954 : Py_DECREF(v);
4179 : : }
4180 : :
4181 : 36661 : exit:
4182 [ + + ]: 36661 : if (dirp != NULL) {
4183 : 36134 : Py_BEGIN_ALLOW_THREADS
4184 : : #ifdef HAVE_FDOPENDIR
4185 [ + + ]: 36134 : if (fd > -1)
4186 : 55 : rewinddir(dirp);
4187 : : #endif
4188 : 36134 : closedir(dirp);
4189 : 36134 : Py_END_ALLOW_THREADS
4190 : : }
4191 : :
4192 : 36661 : return list;
4193 : : } /* end of _posix_listdir */
4194 : : #endif /* which OS */
4195 : :
4196 : :
4197 : : /*[clinic input]
4198 : : os.listdir
4199 : :
4200 : : path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4201 : :
4202 : : Return a list containing the names of the files in the directory.
4203 : :
4204 : : path can be specified as either str, bytes, or a path-like object. If path is bytes,
4205 : : the filenames returned will also be bytes; in all other circumstances
4206 : : the filenames returned will be str.
4207 : : If path is None, uses the path='.'.
4208 : : On some platforms, path may also be specified as an open file descriptor;\
4209 : : the file descriptor must refer to a directory.
4210 : : If this functionality is unavailable, using it raises NotImplementedError.
4211 : :
4212 : : The list is in arbitrary order. It does not include the special
4213 : : entries '.' and '..' even if they are present in the directory.
4214 : :
4215 : :
4216 : : [clinic start generated code]*/
4217 : :
4218 : : static PyObject *
4219 : 36661 : os_listdir_impl(PyObject *module, path_t *path)
4220 : : /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4221 : : {
4222 [ - + ]: 36661 : if (PySys_Audit("os.listdir", "O",
4223 [ + + ]: 36661 : path->object ? path->object : Py_None) < 0) {
4224 : 0 : return NULL;
4225 : : }
4226 : : #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4227 : : return _listdir_windows_no_opendir(path, NULL);
4228 : : #else
4229 : 36661 : return _posix_listdir(path, NULL);
4230 : : #endif
4231 : : }
4232 : :
4233 : : #ifdef MS_WINDOWS
4234 : : int
4235 : : _PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
4236 : : {
4237 : : wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
4238 : : DWORD result;
4239 : :
4240 : : result = GetFullPathNameW(path,
4241 : : Py_ARRAY_LENGTH(woutbuf), woutbuf,
4242 : : NULL);
4243 : : if (!result) {
4244 : : return -1;
4245 : : }
4246 : :
4247 : : if (result >= Py_ARRAY_LENGTH(woutbuf)) {
4248 : : if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4249 : : woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
4250 : : }
4251 : : else {
4252 : : woutbufp = NULL;
4253 : : }
4254 : : if (!woutbufp) {
4255 : : *abspath_p = NULL;
4256 : : return 0;
4257 : : }
4258 : :
4259 : : result = GetFullPathNameW(path, result, woutbufp, NULL);
4260 : : if (!result) {
4261 : : PyMem_RawFree(woutbufp);
4262 : : return -1;
4263 : : }
4264 : : }
4265 : :
4266 : : if (woutbufp != woutbuf) {
4267 : : *abspath_p = woutbufp;
4268 : : return 0;
4269 : : }
4270 : :
4271 : : *abspath_p = _PyMem_RawWcsdup(woutbufp);
4272 : : return 0;
4273 : : }
4274 : :
4275 : :
4276 : : /* A helper function for abspath on win32 */
4277 : : /*[clinic input]
4278 : : os._getfullpathname
4279 : :
4280 : : path: path_t
4281 : : /
4282 : :
4283 : : [clinic start generated code]*/
4284 : :
4285 : : static PyObject *
4286 : : os__getfullpathname_impl(PyObject *module, path_t *path)
4287 : : /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
4288 : : {
4289 : : wchar_t *abspath;
4290 : :
4291 : : if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
4292 : : return win32_error_object("GetFullPathNameW", path->object);
4293 : : }
4294 : : if (abspath == NULL) {
4295 : : return PyErr_NoMemory();
4296 : : }
4297 : :
4298 : : PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
4299 : : PyMem_RawFree(abspath);
4300 : : if (str == NULL) {
4301 : : return NULL;
4302 : : }
4303 : : if (path->narrow) {
4304 : : Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
4305 : : }
4306 : : return str;
4307 : : }
4308 : :
4309 : :
4310 : : /*[clinic input]
4311 : : os._getfinalpathname
4312 : :
4313 : : path: path_t
4314 : : /
4315 : :
4316 : : A helper function for samepath on windows.
4317 : : [clinic start generated code]*/
4318 : :
4319 : : static PyObject *
4320 : : os__getfinalpathname_impl(PyObject *module, path_t *path)
4321 : : /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
4322 : : {
4323 : : HANDLE hFile;
4324 : : wchar_t buf[MAXPATHLEN], *target_path = buf;
4325 : : int buf_size = Py_ARRAY_LENGTH(buf);
4326 : : int result_length;
4327 : : PyObject *result;
4328 : :
4329 : : Py_BEGIN_ALLOW_THREADS
4330 : : hFile = CreateFileW(
4331 : : path->wide,
4332 : : 0, /* desired access */
4333 : : 0, /* share mode */
4334 : : NULL, /* security attributes */
4335 : : OPEN_EXISTING,
4336 : : /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
4337 : : FILE_FLAG_BACKUP_SEMANTICS,
4338 : : NULL);
4339 : : Py_END_ALLOW_THREADS
4340 : :
4341 : : if (hFile == INVALID_HANDLE_VALUE) {
4342 : : return win32_error_object("CreateFileW", path->object);
4343 : : }
4344 : :
4345 : : /* We have a good handle to the target, use it to determine the
4346 : : target path name. */
4347 : : while (1) {
4348 : : Py_BEGIN_ALLOW_THREADS
4349 : : result_length = GetFinalPathNameByHandleW(hFile, target_path,
4350 : : buf_size, VOLUME_NAME_DOS);
4351 : : Py_END_ALLOW_THREADS
4352 : :
4353 : : if (!result_length) {
4354 : : result = win32_error_object("GetFinalPathNameByHandleW",
4355 : : path->object);
4356 : : goto cleanup;
4357 : : }
4358 : :
4359 : : if (result_length < buf_size) {
4360 : : break;
4361 : : }
4362 : :
4363 : : wchar_t *tmp;
4364 : : tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
4365 : : result_length * sizeof(*tmp));
4366 : : if (!tmp) {
4367 : : result = PyErr_NoMemory();
4368 : : goto cleanup;
4369 : : }
4370 : :
4371 : : buf_size = result_length;
4372 : : target_path = tmp;
4373 : : }
4374 : :
4375 : : result = PyUnicode_FromWideChar(target_path, result_length);
4376 : : if (result && path->narrow) {
4377 : : Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4378 : : }
4379 : :
4380 : : cleanup:
4381 : : if (target_path != buf) {
4382 : : PyMem_Free(target_path);
4383 : : }
4384 : : CloseHandle(hFile);
4385 : : return result;
4386 : : }
4387 : :
4388 : :
4389 : : /*[clinic input]
4390 : : os._getvolumepathname
4391 : :
4392 : : path: path_t
4393 : :
4394 : : A helper function for ismount on Win32.
4395 : : [clinic start generated code]*/
4396 : :
4397 : : static PyObject *
4398 : : os__getvolumepathname_impl(PyObject *module, path_t *path)
4399 : : /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
4400 : : {
4401 : : PyObject *result;
4402 : : wchar_t *mountpath=NULL;
4403 : : size_t buflen;
4404 : : BOOL ret;
4405 : :
4406 : : /* Volume path should be shorter than entire path */
4407 : : buflen = Py_MAX(path->length, MAX_PATH);
4408 : :
4409 : : if (buflen > PY_DWORD_MAX) {
4410 : : PyErr_SetString(PyExc_OverflowError, "path too long");
4411 : : return NULL;
4412 : : }
4413 : :
4414 : : mountpath = PyMem_New(wchar_t, buflen);
4415 : : if (mountpath == NULL)
4416 : : return PyErr_NoMemory();
4417 : :
4418 : : Py_BEGIN_ALLOW_THREADS
4419 : : ret = GetVolumePathNameW(path->wide, mountpath,
4420 : : Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
4421 : : Py_END_ALLOW_THREADS
4422 : :
4423 : : if (!ret) {
4424 : : result = win32_error_object("_getvolumepathname", path->object);
4425 : : goto exit;
4426 : : }
4427 : : result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
4428 : : if (path->narrow)
4429 : : Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4430 : :
4431 : : exit:
4432 : : PyMem_Free(mountpath);
4433 : : return result;
4434 : : }
4435 : :
4436 : :
4437 : : /*[clinic input]
4438 : : os._path_splitroot
4439 : :
4440 : : path: path_t
4441 : :
4442 : : Removes everything after the root on Win32.
4443 : : [clinic start generated code]*/
4444 : :
4445 : : static PyObject *
4446 : : os__path_splitroot_impl(PyObject *module, path_t *path)
4447 : : /*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/
4448 : : {
4449 : : wchar_t *buffer;
4450 : : wchar_t *end;
4451 : : PyObject *result = NULL;
4452 : : HRESULT ret;
4453 : :
4454 : : buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
4455 : : if (!buffer) {
4456 : : return NULL;
4457 : : }
4458 : : wcscpy(buffer, path->wide);
4459 : : for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
4460 : : *p = L'\\';
4461 : : }
4462 : :
4463 : : Py_BEGIN_ALLOW_THREADS
4464 : : ret = PathCchSkipRoot(buffer, &end);
4465 : : Py_END_ALLOW_THREADS
4466 : : if (FAILED(ret)) {
4467 : : result = Py_BuildValue("sO", "", path->object);
4468 : : } else if (end != buffer) {
4469 : : size_t rootLen = (size_t)(end - buffer);
4470 : : result = Py_BuildValue("NN",
4471 : : PyUnicode_FromWideChar(path->wide, rootLen),
4472 : : PyUnicode_FromWideChar(path->wide + rootLen, -1)
4473 : : );
4474 : : } else {
4475 : : result = Py_BuildValue("Os", path->object, "");
4476 : : }
4477 : : PyMem_Free(buffer);
4478 : :
4479 : : return result;
4480 : : }
4481 : :
4482 : :
4483 : : #endif /* MS_WINDOWS */
4484 : :
4485 : :
4486 : : /*[clinic input]
4487 : : os._path_normpath
4488 : :
4489 : : path: object
4490 : :
4491 : : Basic path normalization.
4492 : : [clinic start generated code]*/
4493 : :
4494 : : static PyObject *
4495 : 152511 : os__path_normpath_impl(PyObject *module, PyObject *path)
4496 : : /*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/
4497 : : {
4498 [ - + ]: 152511 : if (!PyUnicode_Check(path)) {
4499 : 0 : PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'",
4500 : 0 : Py_TYPE(path)->tp_name);
4501 : 0 : return NULL;
4502 : : }
4503 : : Py_ssize_t len;
4504 : 152511 : wchar_t *buffer = PyUnicode_AsWideCharString(path, &len);
4505 [ - + ]: 152511 : if (!buffer) {
4506 : 0 : return NULL;
4507 : : }
4508 : 152511 : PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1);
4509 : 152511 : PyMem_Free(buffer);
4510 : 152511 : return result;
4511 : : }
4512 : :
4513 : : /*[clinic input]
4514 : : os.mkdir
4515 : :
4516 : : path : path_t
4517 : :
4518 : : mode: int = 0o777
4519 : :
4520 : : *
4521 : :
4522 : : dir_fd : dir_fd(requires='mkdirat') = None
4523 : :
4524 : : # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4525 : :
4526 : : Create a directory.
4527 : :
4528 : : If dir_fd is not None, it should be a file descriptor open to a directory,
4529 : : and path should be relative; path will then be relative to that directory.
4530 : : dir_fd may not be implemented on your platform.
4531 : : If it is unavailable, using it will raise a NotImplementedError.
4532 : :
4533 : : The mode argument is ignored on Windows.
4534 : : [clinic start generated code]*/
4535 : :
4536 : : static PyObject *
4537 : 18463 : os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4538 : : /*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/
4539 : : {
4540 : : int result;
4541 : : #ifdef HAVE_MKDIRAT
4542 : 18463 : int mkdirat_unavailable = 0;
4543 : : #endif
4544 : :
4545 [ + + - + ]: 18463 : if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4546 : : dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4547 : 0 : return NULL;
4548 : : }
4549 : :
4550 : : #ifdef MS_WINDOWS
4551 : : Py_BEGIN_ALLOW_THREADS
4552 : : result = CreateDirectoryW(path->wide, NULL);
4553 : : Py_END_ALLOW_THREADS
4554 : :
4555 : : if (!result)
4556 : : return path_error(path);
4557 : : #else
4558 : 18463 : Py_BEGIN_ALLOW_THREADS
4559 : : #if HAVE_MKDIRAT
4560 [ + + ]: 18463 : if (dir_fd != DEFAULT_DIR_FD) {
4561 : : if (HAVE_MKDIRAT_RUNTIME) {
4562 : 1 : result = mkdirat(dir_fd, path->narrow, mode);
4563 : :
4564 : : } else {
4565 : : mkdirat_unavailable = 1;
4566 : : }
4567 : : } else
4568 : : #endif
4569 : : #if defined(__WATCOMC__) && !defined(__QNX__)
4570 : : result = mkdir(path->narrow);
4571 : : #else
4572 : 18462 : result = mkdir(path->narrow, mode);
4573 : : #endif
4574 : 18463 : Py_END_ALLOW_THREADS
4575 : :
4576 : : #if HAVE_MKDIRAT
4577 [ - + ]: 18463 : if (mkdirat_unavailable) {
4578 : 0 : argument_unavailable_error(NULL, "dir_fd");
4579 : 0 : return NULL;
4580 : : }
4581 : : #endif
4582 : :
4583 [ + + ]: 18463 : if (result < 0)
4584 : 7838 : return path_error(path);
4585 : : #endif /* MS_WINDOWS */
4586 : 10625 : Py_RETURN_NONE;
4587 : : }
4588 : :
4589 : :
4590 : : /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4591 : : #if defined(HAVE_SYS_RESOURCE_H)
4592 : : #include <sys/resource.h>
4593 : : #endif
4594 : :
4595 : :
4596 : : #ifdef HAVE_NICE
4597 : : /*[clinic input]
4598 : : os.nice
4599 : :
4600 : : increment: int
4601 : : /
4602 : :
4603 : : Add increment to the priority of process and return the new priority.
4604 : : [clinic start generated code]*/
4605 : :
4606 : : static PyObject *
4607 : 0 : os_nice_impl(PyObject *module, int increment)
4608 : : /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4609 : : {
4610 : : int value;
4611 : :
4612 : : /* There are two flavours of 'nice': one that returns the new
4613 : : priority (as required by almost all standards out there) and the
4614 : : Linux/FreeBSD one, which returns '0' on success and advices
4615 : : the use of getpriority() to get the new priority.
4616 : :
4617 : : If we are of the nice family that returns the new priority, we
4618 : : need to clear errno before the call, and check if errno is filled
4619 : : before calling posix_error() on a returnvalue of -1, because the
4620 : : -1 may be the actual new priority! */
4621 : :
4622 : 0 : errno = 0;
4623 : 0 : value = nice(increment);
4624 : : #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4625 : : if (value == 0)
4626 : : value = getpriority(PRIO_PROCESS, 0);
4627 : : #endif
4628 [ # # # # ]: 0 : if (value == -1 && errno != 0)
4629 : : /* either nice() or getpriority() returned an error */
4630 : 0 : return posix_error();
4631 : 0 : return PyLong_FromLong((long) value);
4632 : : }
4633 : : #endif /* HAVE_NICE */
4634 : :
4635 : :
4636 : : #ifdef HAVE_GETPRIORITY
4637 : : /*[clinic input]
4638 : : os.getpriority
4639 : :
4640 : : which: int
4641 : : who: int
4642 : :
4643 : : Return program scheduling priority.
4644 : : [clinic start generated code]*/
4645 : :
4646 : : static PyObject *
4647 : 2 : os_getpriority_impl(PyObject *module, int which, int who)
4648 : : /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4649 : : {
4650 : : int retval;
4651 : :
4652 : 2 : errno = 0;
4653 : 2 : retval = getpriority(which, who);
4654 [ - + ]: 2 : if (errno != 0)
4655 : 0 : return posix_error();
4656 : 2 : return PyLong_FromLong((long)retval);
4657 : : }
4658 : : #endif /* HAVE_GETPRIORITY */
4659 : :
4660 : :
4661 : : #ifdef HAVE_SETPRIORITY
4662 : : /*[clinic input]
4663 : : os.setpriority
4664 : :
4665 : : which: int
4666 : : who: int
4667 : : priority: int
4668 : :
4669 : : Set program scheduling priority.
4670 : : [clinic start generated code]*/
4671 : :
4672 : : static PyObject *
4673 : 2 : os_setpriority_impl(PyObject *module, int which, int who, int priority)
4674 : : /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4675 : : {
4676 : : int retval;
4677 : :
4678 : 2 : retval = setpriority(which, who, priority);
4679 [ + + ]: 2 : if (retval == -1)
4680 : 1 : return posix_error();
4681 : 1 : Py_RETURN_NONE;
4682 : : }
4683 : : #endif /* HAVE_SETPRIORITY */
4684 : :
4685 : :
4686 : : static PyObject *
4687 : 8411 : internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4688 : : {
4689 [ + + ]: 8411 : const char *function_name = is_replace ? "replace" : "rename";
4690 : : int dir_fd_specified;
4691 : :
4692 : : #ifdef HAVE_RENAMEAT
4693 : 8411 : int renameat_unavailable = 0;
4694 : : #endif
4695 : :
4696 : : #ifdef MS_WINDOWS
4697 : : BOOL result;
4698 : : int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4699 : : #else
4700 : : int result;
4701 : : #endif
4702 : :
4703 [ + + - + ]: 8411 : dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4704 : : (dst_dir_fd != DEFAULT_DIR_FD);
4705 : : #ifndef HAVE_RENAMEAT
4706 : : if (dir_fd_specified) {
4707 : : argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4708 : : return NULL;
4709 : : }
4710 : : #endif
4711 : :
4712 [ + + + + : 8411 : if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
- + ]
4713 : : src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4714 : : dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4715 : 0 : return NULL;
4716 : : }
4717 : :
4718 : : #ifdef MS_WINDOWS
4719 : : Py_BEGIN_ALLOW_THREADS
4720 : : result = MoveFileExW(src->wide, dst->wide, flags);
4721 : : Py_END_ALLOW_THREADS
4722 : :
4723 : : if (!result)
4724 : : return path_error2(src, dst);
4725 : :
4726 : : #else
4727 [ + - + - : 8411 : if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
- + - - ]
4728 : 0 : PyErr_Format(PyExc_ValueError,
4729 : : "%s: src and dst must be the same type", function_name);
4730 : 0 : return NULL;
4731 : : }
4732 : :
4733 : 8411 : Py_BEGIN_ALLOW_THREADS
4734 : : #ifdef HAVE_RENAMEAT
4735 [ + + ]: 8411 : if (dir_fd_specified) {
4736 : : if (HAVE_RENAMEAT_RUNTIME) {
4737 : 1 : result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4738 : : } else {
4739 : : renameat_unavailable = 1;
4740 : : }
4741 : : } else
4742 : : #endif
4743 : 8410 : result = rename(src->narrow, dst->narrow);
4744 : 8411 : Py_END_ALLOW_THREADS
4745 : :
4746 : :
4747 : : #ifdef HAVE_RENAMEAT
4748 [ - + ]: 8411 : if (renameat_unavailable) {
4749 : 0 : argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4750 : 0 : return NULL;
4751 : : }
4752 : : #endif
4753 : :
4754 [ + + ]: 8411 : if (result)
4755 : 121 : return path_error2(src, dst);
4756 : : #endif
4757 : 8290 : Py_RETURN_NONE;
4758 : : }
4759 : :
4760 : :
4761 : : /*[clinic input]
4762 : : os.rename
4763 : :
4764 : : src : path_t
4765 : : dst : path_t
4766 : : *
4767 : : src_dir_fd : dir_fd = None
4768 : : dst_dir_fd : dir_fd = None
4769 : :
4770 : : Rename a file or directory.
4771 : :
4772 : : If either src_dir_fd or dst_dir_fd is not None, it should be a file
4773 : : descriptor open to a directory, and the respective path string (src or dst)
4774 : : should be relative; the path will then be relative to that directory.
4775 : : src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4776 : : If they are unavailable, using them will raise a NotImplementedError.
4777 : : [clinic start generated code]*/
4778 : :
4779 : : static PyObject *
4780 : 941 : os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4781 : : int dst_dir_fd)
4782 : : /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4783 : : {
4784 : 941 : return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4785 : : }
4786 : :
4787 : :
4788 : : /*[clinic input]
4789 : : os.replace = os.rename
4790 : :
4791 : : Rename a file or directory, overwriting the destination.
4792 : :
4793 : : If either src_dir_fd or dst_dir_fd is not None, it should be a file
4794 : : descriptor open to a directory, and the respective path string (src or dst)
4795 : : should be relative; the path will then be relative to that directory.
4796 : : src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4797 : : If they are unavailable, using them will raise a NotImplementedError.
4798 : : [clinic start generated code]*/
4799 : :
4800 : : static PyObject *
4801 : 7470 : os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4802 : : int dst_dir_fd)
4803 : : /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4804 : : {
4805 : 7470 : return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4806 : : }
4807 : :
4808 : :
4809 : : /*[clinic input]
4810 : : os.rmdir
4811 : :
4812 : : path: path_t
4813 : : *
4814 : : dir_fd: dir_fd(requires='unlinkat') = None
4815 : :
4816 : : Remove a directory.
4817 : :
4818 : : If dir_fd is not None, it should be a file descriptor open to a directory,
4819 : : and path should be relative; path will then be relative to that directory.
4820 : : dir_fd may not be implemented on your platform.
4821 : : If it is unavailable, using it will raise a NotImplementedError.
4822 : : [clinic start generated code]*/
4823 : :
4824 : : static PyObject *
4825 : 11337 : os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4826 : : /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4827 : : {
4828 : : int result;
4829 : : #ifdef HAVE_UNLINKAT
4830 : 11337 : int unlinkat_unavailable = 0;
4831 : : #endif
4832 : :
4833 [ + + - + ]: 11337 : if (PySys_Audit("os.rmdir", "Oi", path->object,
4834 : : dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4835 : 0 : return NULL;
4836 : : }
4837 : :
4838 : 11337 : Py_BEGIN_ALLOW_THREADS
4839 : : #ifdef MS_WINDOWS
4840 : : /* Windows, success=1, UNIX, success=0 */
4841 : : result = !RemoveDirectoryW(path->wide);
4842 : : #else
4843 : : #ifdef HAVE_UNLINKAT
4844 [ + + ]: 11337 : if (dir_fd != DEFAULT_DIR_FD) {
4845 : : if (HAVE_UNLINKAT_RUNTIME) {
4846 : 6577 : result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4847 : : } else {
4848 : : unlinkat_unavailable = 1;
4849 : : result = -1;
4850 : : }
4851 : : } else
4852 : : #endif
4853 : 4760 : result = rmdir(path->narrow);
4854 : : #endif
4855 : 11337 : Py_END_ALLOW_THREADS
4856 : :
4857 : : #ifdef HAVE_UNLINKAT
4858 [ - + ]: 11337 : if (unlinkat_unavailable) {
4859 : 0 : argument_unavailable_error("rmdir", "dir_fd");
4860 : 0 : return NULL;
4861 : : }
4862 : : #endif
4863 : :
4864 [ + + ]: 11337 : if (result)
4865 : 402 : return path_error(path);
4866 : :
4867 : 10935 : Py_RETURN_NONE;
4868 : : }
4869 : :
4870 : :
4871 : : #ifdef HAVE_SYSTEM
4872 : : #ifdef MS_WINDOWS
4873 : : /*[clinic input]
4874 : : os.system -> long
4875 : :
4876 : : command: Py_UNICODE
4877 : :
4878 : : Execute the command in a subshell.
4879 : : [clinic start generated code]*/
4880 : :
4881 : : static long
4882 : : os_system_impl(PyObject *module, const Py_UNICODE *command)
4883 : : /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4884 : : {
4885 : : long result;
4886 : :
4887 : : if (PySys_Audit("os.system", "(u)", command) < 0) {
4888 : : return -1;
4889 : : }
4890 : :
4891 : : Py_BEGIN_ALLOW_THREADS
4892 : : _Py_BEGIN_SUPPRESS_IPH
4893 : : result = _wsystem(command);
4894 : : _Py_END_SUPPRESS_IPH
4895 : : Py_END_ALLOW_THREADS
4896 : : return result;
4897 : : }
4898 : : #else /* MS_WINDOWS */
4899 : : /*[clinic input]
4900 : : os.system -> long
4901 : :
4902 : : command: FSConverter
4903 : :
4904 : : Execute the command in a subshell.
4905 : : [clinic start generated code]*/
4906 : :
4907 : : static long
4908 : 4 : os_system_impl(PyObject *module, PyObject *command)
4909 : : /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4910 : : {
4911 : : long result;
4912 : 4 : const char *bytes = PyBytes_AsString(command);
4913 : :
4914 [ - + ]: 4 : if (PySys_Audit("os.system", "(O)", command) < 0) {
4915 : 0 : return -1;
4916 : : }
4917 : :
4918 : 4 : Py_BEGIN_ALLOW_THREADS
4919 : 4 : result = system(bytes);
4920 : 4 : Py_END_ALLOW_THREADS
4921 : 4 : return result;
4922 : : }
4923 : : #endif
4924 : : #endif /* HAVE_SYSTEM */
4925 : :
4926 : :
4927 : : #ifdef HAVE_UMASK
4928 : : /*[clinic input]
4929 : : os.umask
4930 : :
4931 : : mask: int
4932 : : /
4933 : :
4934 : : Set the current numeric umask and return the previous umask.
4935 : : [clinic start generated code]*/
4936 : :
4937 : : static PyObject *
4938 : 502 : os_umask_impl(PyObject *module, int mask)
4939 : : /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4940 : : {
4941 : 502 : int i = (int)umask(mask);
4942 [ - + ]: 502 : if (i < 0)
4943 : 0 : return posix_error();
4944 : 502 : return PyLong_FromLong((long)i);
4945 : : }
4946 : : #endif
4947 : :
4948 : : #ifdef MS_WINDOWS
4949 : :
4950 : : /* override the default DeleteFileW behavior so that directory
4951 : : symlinks can be removed with this function, the same as with
4952 : : Unix symlinks */
4953 : : BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
4954 : : {
4955 : : WIN32_FILE_ATTRIBUTE_DATA info;
4956 : : WIN32_FIND_DATAW find_data;
4957 : : HANDLE find_data_handle;
4958 : : int is_directory = 0;
4959 : : int is_link = 0;
4960 : :
4961 : : if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
4962 : : is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4963 : :
4964 : : /* Get WIN32_FIND_DATA structure for the path to determine if
4965 : : it is a symlink */
4966 : : if(is_directory &&
4967 : : info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
4968 : : find_data_handle = FindFirstFileW(lpFileName, &find_data);
4969 : :
4970 : : if(find_data_handle != INVALID_HANDLE_VALUE) {
4971 : : /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
4972 : : IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
4973 : : is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
4974 : : find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
4975 : : FindClose(find_data_handle);
4976 : : }
4977 : : }
4978 : : }
4979 : :
4980 : : if (is_directory && is_link)
4981 : : return RemoveDirectoryW(lpFileName);
4982 : :
4983 : : return DeleteFileW(lpFileName);
4984 : : }
4985 : : #endif /* MS_WINDOWS */
4986 : :
4987 : :
4988 : : /*[clinic input]
4989 : : os.unlink
4990 : :
4991 : : path: path_t
4992 : : *
4993 : : dir_fd: dir_fd(requires='unlinkat')=None
4994 : :
4995 : : Remove a file (same as remove()).
4996 : :
4997 : : If dir_fd is not None, it should be a file descriptor open to a directory,
4998 : : and path should be relative; path will then be relative to that directory.
4999 : : dir_fd may not be implemented on your platform.
5000 : : If it is unavailable, using it will raise a NotImplementedError.
5001 : :
5002 : : [clinic start generated code]*/
5003 : :
5004 : : static PyObject *
5005 : 58992 : os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
5006 : : /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
5007 : : {
5008 : : int result;
5009 : : #ifdef HAVE_UNLINKAT
5010 : 58992 : int unlinkat_unavailable = 0;
5011 : : #endif
5012 : :
5013 [ + + - + ]: 58992 : if (PySys_Audit("os.remove", "Oi", path->object,
5014 : : dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5015 : 0 : return NULL;
5016 : : }
5017 : :
5018 : 58992 : Py_BEGIN_ALLOW_THREADS
5019 : : _Py_BEGIN_SUPPRESS_IPH
5020 : : #ifdef MS_WINDOWS
5021 : : /* Windows, success=1, UNIX, success=0 */
5022 : : result = !Py_DeleteFileW(path->wide);
5023 : : #else
5024 : : #ifdef HAVE_UNLINKAT
5025 [ + + ]: 58992 : if (dir_fd != DEFAULT_DIR_FD) {
5026 : : if (HAVE_UNLINKAT_RUNTIME) {
5027 : :
5028 : 40809 : result = unlinkat(dir_fd, path->narrow, 0);
5029 : : } else {
5030 : : unlinkat_unavailable = 1;
5031 : : }
5032 : : } else
5033 : : #endif /* HAVE_UNLINKAT */
5034 : 18183 : result = unlink(path->narrow);
5035 : : #endif
5036 : : _Py_END_SUPPRESS_IPH
5037 : 58992 : Py_END_ALLOW_THREADS
5038 : :
5039 : : #ifdef HAVE_UNLINKAT
5040 [ - + ]: 58992 : if (unlinkat_unavailable) {
5041 : 0 : argument_unavailable_error(NULL, "dir_fd");
5042 : 0 : return NULL;
5043 : : }
5044 : : #endif
5045 : :
5046 [ + + ]: 58992 : if (result)
5047 : 7449 : return path_error(path);
5048 : :
5049 : 51543 : Py_RETURN_NONE;
5050 : : }
5051 : :
5052 : :
5053 : : /*[clinic input]
5054 : : os.remove = os.unlink
5055 : :
5056 : : Remove a file (same as unlink()).
5057 : :
5058 : : If dir_fd is not None, it should be a file descriptor open to a directory,
5059 : : and path should be relative; path will then be relative to that directory.
5060 : : dir_fd may not be implemented on your platform.
5061 : : If it is unavailable, using it will raise a NotImplementedError.
5062 : : [clinic start generated code]*/
5063 : :
5064 : : static PyObject *
5065 : 1453 : os_remove_impl(PyObject *module, path_t *path, int dir_fd)
5066 : : /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
5067 : : {
5068 : 1453 : return os_unlink_impl(module, path, dir_fd);
5069 : : }
5070 : :
5071 : :
5072 : : static PyStructSequence_Field uname_result_fields[] = {
5073 : : {"sysname", "operating system name"},
5074 : : {"nodename", "name of machine on network (implementation-defined)"},
5075 : : {"release", "operating system release"},
5076 : : {"version", "operating system version"},
5077 : : {"machine", "hardware identifier"},
5078 : : {NULL}
5079 : : };
5080 : :
5081 : : PyDoc_STRVAR(uname_result__doc__,
5082 : : "uname_result: Result from os.uname().\n\n\
5083 : : This object may be accessed either as a tuple of\n\
5084 : : (sysname, nodename, release, version, machine),\n\
5085 : : or via the attributes sysname, nodename, release, version, and machine.\n\
5086 : : \n\
5087 : : See os.uname for more information.");
5088 : :
5089 : : static PyStructSequence_Desc uname_result_desc = {
5090 : : MODNAME ".uname_result", /* name */
5091 : : uname_result__doc__, /* doc */
5092 : : uname_result_fields,
5093 : : 5
5094 : : };
5095 : :
5096 : : #ifdef HAVE_UNAME
5097 : : /*[clinic input]
5098 : : os.uname
5099 : :
5100 : : Return an object identifying the current operating system.
5101 : :
5102 : : The object behaves like a named tuple with the following fields:
5103 : : (sysname, nodename, release, version, machine)
5104 : :
5105 : : [clinic start generated code]*/
5106 : :
5107 : : static PyObject *
5108 : 254 : os_uname_impl(PyObject *module)
5109 : : /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
5110 : : {
5111 : : struct utsname u;
5112 : : int res;
5113 : : PyObject *value;
5114 : :
5115 : 254 : Py_BEGIN_ALLOW_THREADS
5116 : 254 : res = uname(&u);
5117 : 254 : Py_END_ALLOW_THREADS
5118 [ - + ]: 254 : if (res < 0)
5119 : 0 : return posix_error();
5120 : :
5121 : 254 : PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
5122 : 254 : value = PyStructSequence_New((PyTypeObject *)UnameResultType);
5123 [ - + ]: 254 : if (value == NULL)
5124 : 0 : return NULL;
5125 : :
5126 : : #define SET(i, field) \
5127 : : { \
5128 : : PyObject *o = PyUnicode_DecodeFSDefault(field); \
5129 : : if (!o) { \
5130 : : Py_DECREF(value); \
5131 : : return NULL; \
5132 : : } \
5133 : : PyStructSequence_SET_ITEM(value, i, o); \
5134 : : } \
5135 : :
5136 [ - + ]: 254 : SET(0, u.sysname);
5137 [ - + ]: 254 : SET(1, u.nodename);
5138 [ - + ]: 254 : SET(2, u.release);
5139 [ - + ]: 254 : SET(3, u.version);
5140 [ - + ]: 254 : SET(4, u.machine);
5141 : :
5142 : : #undef SET
5143 : :
5144 : 254 : return value;
5145 : : }
5146 : : #endif /* HAVE_UNAME */
5147 : :
5148 : :
5149 : :
5150 : : typedef struct {
5151 : : int now;
5152 : : time_t atime_s;
5153 : : long atime_ns;
5154 : : time_t mtime_s;
5155 : : long mtime_ns;
5156 : : } utime_t;
5157 : :
5158 : : /*
5159 : : * these macros assume that "ut" is a pointer to a utime_t
5160 : : * they also intentionally leak the declaration of a pointer named "time"
5161 : : */
5162 : : #define UTIME_TO_TIMESPEC \
5163 : : struct timespec ts[2]; \
5164 : : struct timespec *time; \
5165 : : if (ut->now) \
5166 : : time = NULL; \
5167 : : else { \
5168 : : ts[0].tv_sec = ut->atime_s; \
5169 : : ts[0].tv_nsec = ut->atime_ns; \
5170 : : ts[1].tv_sec = ut->mtime_s; \
5171 : : ts[1].tv_nsec = ut->mtime_ns; \
5172 : : time = ts; \
5173 : : } \
5174 : :
5175 : : #define UTIME_TO_TIMEVAL \
5176 : : struct timeval tv[2]; \
5177 : : struct timeval *time; \
5178 : : if (ut->now) \
5179 : : time = NULL; \
5180 : : else { \
5181 : : tv[0].tv_sec = ut->atime_s; \
5182 : : tv[0].tv_usec = ut->atime_ns / 1000; \
5183 : : tv[1].tv_sec = ut->mtime_s; \
5184 : : tv[1].tv_usec = ut->mtime_ns / 1000; \
5185 : : time = tv; \
5186 : : } \
5187 : :
5188 : : #define UTIME_TO_UTIMBUF \
5189 : : struct utimbuf u; \
5190 : : struct utimbuf *time; \
5191 : : if (ut->now) \
5192 : : time = NULL; \
5193 : : else { \
5194 : : u.actime = ut->atime_s; \
5195 : : u.modtime = ut->mtime_s; \
5196 : : time = &u; \
5197 : : }
5198 : :
5199 : : #define UTIME_TO_TIME_T \
5200 : : time_t timet[2]; \
5201 : : time_t *time; \
5202 : : if (ut->now) \
5203 : : time = NULL; \
5204 : : else { \
5205 : : timet[0] = ut->atime_s; \
5206 : : timet[1] = ut->mtime_s; \
5207 : : time = timet; \
5208 : : } \
5209 : :
5210 : :
5211 : : #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5212 : :
5213 : : static int
5214 : 8 : utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
5215 : : {
5216 : : #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5217 : : if (HAVE_UTIMENSAT_RUNTIME) {
5218 : : int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5219 : : UTIME_TO_TIMESPEC;
5220 : : return utimensat(dir_fd, path, time, flags);
5221 : : } else {
5222 : : errno = ENOSYS;
5223 : : return -1;
5224 : : }
5225 : : #elif defined(HAVE_UTIMENSAT)
5226 [ + + ]: 8 : int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5227 [ + + ]: 8 : UTIME_TO_TIMESPEC;
5228 : 8 : return utimensat(dir_fd, path, time, flags);
5229 : : #elif defined(HAVE_FUTIMESAT)
5230 : : UTIME_TO_TIMEVAL;
5231 : : /*
5232 : : * follow_symlinks will never be false here;
5233 : : * we only allow !follow_symlinks and dir_fd together
5234 : : * if we have utimensat()
5235 : : */
5236 : : assert(follow_symlinks);
5237 : : return futimesat(dir_fd, path, time);
5238 : : #endif
5239 : : }
5240 : :
5241 : : #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
5242 : : #else
5243 : : #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
5244 : : #endif
5245 : :
5246 : : #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5247 : :
5248 : : static int
5249 : 7 : utime_fd(utime_t *ut, int fd)
5250 : : {
5251 : : #ifdef HAVE_FUTIMENS
5252 : :
5253 : : if (HAVE_FUTIMENS_RUNTIME) {
5254 : :
5255 [ + + ]: 7 : UTIME_TO_TIMESPEC;
5256 : 7 : return futimens(fd, time);
5257 : :
5258 : : } else
5259 : : #ifndef HAVE_FUTIMES
5260 : : {
5261 : : /* Not sure if this can happen */
5262 : : PyErr_SetString(
5263 : : PyExc_RuntimeError,
5264 : : "neither futimens nor futimes are supported"
5265 : : " on this system");
5266 : : return -1;
5267 : : }
5268 : : #endif
5269 : :
5270 : : #endif
5271 : : #ifdef HAVE_FUTIMES
5272 : : {
5273 : : UTIME_TO_TIMEVAL;
5274 : : return futimes(fd, time);
5275 : : }
5276 : : #endif
5277 : : }
5278 : :
5279 : : #define PATH_UTIME_HAVE_FD 1
5280 : : #else
5281 : : #define PATH_UTIME_HAVE_FD 0
5282 : : #endif
5283 : :
5284 : : #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
5285 : : # define UTIME_HAVE_NOFOLLOW_SYMLINKS
5286 : : #endif
5287 : :
5288 : : #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5289 : :
5290 : : static int
5291 : 10 : utime_nofollow_symlinks(utime_t *ut, const char *path)
5292 : : {
5293 : : #ifdef HAVE_UTIMENSAT
5294 : : if (HAVE_UTIMENSAT_RUNTIME) {
5295 [ + + ]: 10 : UTIME_TO_TIMESPEC;
5296 : 10 : return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
5297 : : } else
5298 : : #ifndef HAVE_LUTIMES
5299 : : {
5300 : : /* Not sure if this can happen */
5301 : : PyErr_SetString(
5302 : : PyExc_RuntimeError,
5303 : : "neither utimensat nor lutimes are supported"
5304 : : " on this system");
5305 : : return -1;
5306 : : }
5307 : : #endif
5308 : : #endif
5309 : :
5310 : : #ifdef HAVE_LUTIMES
5311 : : {
5312 : : UTIME_TO_TIMEVAL;
5313 : : return lutimes(path, time);
5314 : : }
5315 : : #endif
5316 : : }
5317 : :
5318 : : #endif
5319 : :
5320 : : #ifndef MS_WINDOWS
5321 : :
5322 : : static int
5323 : 22345 : utime_default(utime_t *ut, const char *path)
5324 : : {
5325 : : #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5326 : : if (HAVE_UTIMENSAT_RUNTIME) {
5327 : : UTIME_TO_TIMESPEC;
5328 : : return utimensat(DEFAULT_DIR_FD, path, time, 0);
5329 : : } else {
5330 : : UTIME_TO_TIMEVAL;
5331 : : return utimes(path, time);
5332 : : }
5333 : : #elif defined(HAVE_UTIMENSAT)
5334 [ + + ]: 22345 : UTIME_TO_TIMESPEC;
5335 : 22345 : return utimensat(DEFAULT_DIR_FD, path, time, 0);
5336 : : #elif defined(HAVE_UTIMES)
5337 : : UTIME_TO_TIMEVAL;
5338 : : return utimes(path, time);
5339 : : #elif defined(HAVE_UTIME_H)
5340 : : UTIME_TO_UTIMBUF;
5341 : : return utime(path, time);
5342 : : #else
5343 : : UTIME_TO_TIME_T;
5344 : : return utime(path, time);
5345 : : #endif
5346 : : }
5347 : :
5348 : : #endif
5349 : :
5350 : : static int
5351 : 43929 : split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5352 : : {
5353 : 43929 : int result = 0;
5354 : : PyObject *divmod;
5355 : 43929 : divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5356 [ - + ]: 43929 : if (!divmod)
5357 : 0 : goto exit;
5358 [ + + + + ]: 43929 : if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
5359 : 3 : PyErr_Format(PyExc_TypeError,
5360 : : "%.200s.__divmod__() must return a 2-tuple, not %.200s",
5361 : : _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
5362 : 3 : goto exit;
5363 : : }
5364 : 43926 : *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5365 [ - + - - ]: 43926 : if ((*s == -1) && PyErr_Occurred())
5366 : 0 : goto exit;
5367 : 43926 : *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5368 [ - + - - ]: 43926 : if ((*ns == -1) && PyErr_Occurred())
5369 : 0 : goto exit;
5370 : :
5371 : 43926 : result = 1;
5372 : 43929 : exit:
5373 : 43929 : Py_XDECREF(divmod);
5374 : 43929 : return result;
5375 : : }
5376 : :
5377 : :
5378 : : /*[clinic input]
5379 : : os.utime
5380 : :
5381 : : path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
5382 : : times: object = None
5383 : : *
5384 : : ns: object = NULL
5385 : : dir_fd: dir_fd(requires='futimensat') = None
5386 : : follow_symlinks: bool=True
5387 : :
5388 : : # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
5389 : :
5390 : : Set the access and modified time of path.
5391 : :
5392 : : path may always be specified as a string.
5393 : : On some platforms, path may also be specified as an open file descriptor.
5394 : : If this functionality is unavailable, using it raises an exception.
5395 : :
5396 : : If times is not None, it must be a tuple (atime, mtime);
5397 : : atime and mtime should be expressed as float seconds since the epoch.
5398 : : If ns is specified, it must be a tuple (atime_ns, mtime_ns);
5399 : : atime_ns and mtime_ns should be expressed as integer nanoseconds
5400 : : since the epoch.
5401 : : If times is None and ns is unspecified, utime uses the current time.
5402 : : Specifying tuples for both times and ns is an error.
5403 : :
5404 : : If dir_fd is not None, it should be a file descriptor open to a directory,
5405 : : and path should be relative; path will then be relative to that directory.
5406 : : If follow_symlinks is False, and the last element of the path is a symbolic
5407 : : link, utime will modify the symbolic link itself instead of the file the
5408 : : link points to.
5409 : : It is an error to use dir_fd or follow_symlinks when specifying path
5410 : : as an open file descriptor.
5411 : : dir_fd and follow_symlinks may not be available on your platform.
5412 : : If they are unavailable, using them will raise a NotImplementedError.
5413 : :
5414 : : [clinic start generated code]*/
5415 : :
5416 : : static PyObject *
5417 : 22397 : os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
5418 : : int dir_fd, int follow_symlinks)
5419 : : /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
5420 : : {
5421 : : #ifdef MS_WINDOWS
5422 : : HANDLE hFile;
5423 : : FILETIME atime, mtime;
5424 : : #else
5425 : : int result;
5426 : : #endif
5427 : :
5428 : : utime_t utime;
5429 : :
5430 : 22397 : memset(&utime, 0, sizeof(utime_t));
5431 : :
5432 [ + + + + ]: 22397 : if (times != Py_None && ns) {
5433 : 4 : PyErr_SetString(PyExc_ValueError,
5434 : : "utime: you may specify either 'times'"
5435 : : " or 'ns' but not both");
5436 : 4 : return NULL;
5437 : : }
5438 : :
5439 [ + + ]: 22393 : if (times != Py_None) {
5440 : : time_t a_sec, m_sec;
5441 : : long a_nsec, m_nsec;
5442 [ + + + + ]: 355 : if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
5443 : 4 : PyErr_SetString(PyExc_TypeError,
5444 : : "utime: 'times' must be either"
5445 : : " a tuple of two ints or None");
5446 : 17 : return NULL;
5447 : : }
5448 : 351 : utime.now = 0;
5449 [ + + ]: 351 : if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
5450 [ + + ]: 343 : &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
5451 : 343 : _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
5452 : : &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
5453 : 13 : return NULL;
5454 : : }
5455 : 338 : utime.atime_s = a_sec;
5456 : 338 : utime.atime_ns = a_nsec;
5457 : 338 : utime.mtime_s = m_sec;
5458 : 338 : utime.mtime_ns = m_nsec;
5459 : : }
5460 [ + + ]: 22038 : else if (ns) {
5461 [ + + + + ]: 21969 : if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
5462 : 3 : PyErr_SetString(PyExc_TypeError,
5463 : : "utime: 'ns' must be a tuple of two ints");
5464 : 3 : return NULL;
5465 : : }
5466 : 21966 : utime.now = 0;
5467 [ + + ]: 21966 : if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
5468 [ - + ]: 21963 : &utime.atime_s, &utime.atime_ns) ||
5469 : 21963 : !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
5470 : : &utime.mtime_s, &utime.mtime_ns)) {
5471 : 3 : return NULL;
5472 : : }
5473 : : }
5474 : : else {
5475 : : /* times and ns are both None/unspecified. use "now". */
5476 : 69 : utime.now = 1;
5477 : : }
5478 : :
5479 : : #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
5480 : : if (follow_symlinks_specified("utime", follow_symlinks))
5481 : : return NULL;
5482 : : #endif
5483 : :
5484 [ + - + - ]: 44740 : if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
5485 [ - + ]: 44740 : dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
5486 : 22370 : fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
5487 : 0 : return NULL;
5488 : :
5489 : : #if !defined(HAVE_UTIMENSAT)
5490 : : if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
5491 : : PyErr_SetString(PyExc_ValueError,
5492 : : "utime: cannot use dir_fd and follow_symlinks "
5493 : : "together on this platform");
5494 : : return NULL;
5495 : : }
5496 : : #endif
5497 : :
5498 [ + + + + : 22370 : if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
- + ]
5499 : : dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5500 : 0 : return NULL;
5501 : : }
5502 : :
5503 : : #ifdef MS_WINDOWS
5504 : : Py_BEGIN_ALLOW_THREADS
5505 : : hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
5506 : : NULL, OPEN_EXISTING,
5507 : : FILE_FLAG_BACKUP_SEMANTICS, NULL);
5508 : : Py_END_ALLOW_THREADS
5509 : : if (hFile == INVALID_HANDLE_VALUE) {
5510 : : path_error(path);
5511 : : return NULL;
5512 : : }
5513 : :
5514 : : if (utime.now) {
5515 : : GetSystemTimeAsFileTime(&mtime);
5516 : : atime = mtime;
5517 : : }
5518 : : else {
5519 : : _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
5520 : : _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
5521 : : }
5522 : : if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
5523 : : /* Avoid putting the file name into the error here,
5524 : : as that may confuse the user into believing that
5525 : : something is wrong with the file, when it also
5526 : : could be the time stamp that gives a problem. */
5527 : : PyErr_SetFromWindowsErr(0);
5528 : : CloseHandle(hFile);
5529 : : return NULL;
5530 : : }
5531 : : CloseHandle(hFile);
5532 : : #else /* MS_WINDOWS */
5533 : 22370 : Py_BEGIN_ALLOW_THREADS
5534 : :
5535 : : #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5536 [ + + + + ]: 22370 : if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
5537 : 10 : result = utime_nofollow_symlinks(&utime, path->narrow);
5538 : : else
5539 : : #endif
5540 : :
5541 : : #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5542 [ + + - + ]: 22360 : if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
5543 : 8 : result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
5544 : :
5545 : : } else
5546 : : #endif
5547 : :
5548 : : #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5549 [ + + ]: 22352 : if (path->fd != -1)
5550 : 7 : result = utime_fd(&utime, path->fd);
5551 : : else
5552 : : #endif
5553 : :
5554 : 22345 : result = utime_default(&utime, path->narrow);
5555 : :
5556 : 22370 : Py_END_ALLOW_THREADS
5557 : :
5558 : : #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5559 : : /* See utime_dir_fd implementation */
5560 : : if (result == -1 && errno == ENOSYS) {
5561 : : argument_unavailable_error(NULL, "dir_fd");
5562 : : return NULL;
5563 : : }
5564 : : #endif
5565 : :
5566 [ + + ]: 22370 : if (result < 0) {
5567 : : /* see previous comment about not putting filename in error here */
5568 : 49 : posix_error();
5569 : 49 : return NULL;
5570 : : }
5571 : :
5572 : : #endif /* MS_WINDOWS */
5573 : :
5574 : 22321 : Py_RETURN_NONE;
5575 : : }
5576 : :
5577 : : /* Process operations */
5578 : :
5579 : :
5580 : : /*[clinic input]
5581 : : os._exit
5582 : :
5583 : : status: int
5584 : :
5585 : : Exit to the system with specified status, without normal exit processing.
5586 : : [clinic start generated code]*/
5587 : :
5588 : : static PyObject *
5589 : 0 : os__exit_impl(PyObject *module, int status)
5590 : : /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5591 : : {
5592 : 0 : _exit(status);
5593 : : return NULL; /* Make gcc -Wall happy */
5594 : : }
5595 : :
5596 : : #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5597 : : #define EXECV_CHAR wchar_t
5598 : : #else
5599 : : #define EXECV_CHAR char
5600 : : #endif
5601 : :
5602 : : #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5603 : : static void
5604 : 199 : free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5605 : : {
5606 : : Py_ssize_t i;
5607 [ + + ]: 10516 : for (i = 0; i < count; i++)
5608 : 10317 : PyMem_Free(array[i]);
5609 : 199 : PyMem_Free(array);
5610 : 199 : }
5611 : :
5612 : : static int
5613 : 10317 : fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5614 : : {
5615 : : Py_ssize_t size;
5616 : : PyObject *ub;
5617 : 10317 : int result = 0;
5618 : : #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5619 : : if (!PyUnicode_FSDecoder(o, &ub))
5620 : : return 0;
5621 : : *out = PyUnicode_AsWideCharString(ub, &size);
5622 : : if (*out)
5623 : : result = 1;
5624 : : #else
5625 [ - + ]: 10317 : if (!PyUnicode_FSConverter(o, &ub))
5626 : 0 : return 0;
5627 : 10317 : size = PyBytes_GET_SIZE(ub);
5628 : 10317 : *out = PyMem_Malloc(size + 1);
5629 [ + - ]: 10317 : if (*out) {
5630 : 10317 : memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5631 : 10317 : result = 1;
5632 : : } else
5633 : : PyErr_NoMemory();
5634 : : #endif
5635 : 10317 : Py_DECREF(ub);
5636 : 10317 : return result;
5637 : : }
5638 : : #endif
5639 : :
5640 : : #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5641 : : static EXECV_CHAR**
5642 : 94 : parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5643 : : {
5644 : : Py_ssize_t i, pos, envc;
5645 : 94 : PyObject *keys=NULL, *vals=NULL;
5646 : : PyObject *key, *val, *key2, *val2, *keyval;
5647 : : EXECV_CHAR **envlist;
5648 : :
5649 : 94 : i = PyMapping_Size(env);
5650 [ - + ]: 94 : if (i < 0)
5651 : 0 : return NULL;
5652 [ + - ]: 94 : envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5653 [ - + ]: 94 : if (envlist == NULL) {
5654 : : PyErr_NoMemory();
5655 : 0 : return NULL;
5656 : : }
5657 : 94 : envc = 0;
5658 : 94 : keys = PyMapping_Keys(env);
5659 [ - + ]: 94 : if (!keys)
5660 : 0 : goto error;
5661 : 94 : vals = PyMapping_Values(env);
5662 [ - + ]: 94 : if (!vals)
5663 : 0 : goto error;
5664 [ + - - + ]: 94 : if (!PyList_Check(keys) || !PyList_Check(vals)) {
5665 : 0 : PyErr_Format(PyExc_TypeError,
5666 : : "env.keys() or env.values() is not a list");
5667 : 0 : goto error;
5668 : : }
5669 : :
5670 [ + + ]: 10060 : for (pos = 0; pos < i; pos++) {
5671 : 9969 : key = PyList_GetItem(keys, pos);
5672 : 9969 : val = PyList_GetItem(vals, pos);
5673 [ + - - + ]: 9969 : if (!key || !val)
5674 : 0 : goto error;
5675 : :
5676 : : #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5677 : : if (!PyUnicode_FSDecoder(key, &key2))
5678 : : goto error;
5679 : : if (!PyUnicode_FSDecoder(val, &val2)) {
5680 : : Py_DECREF(key2);
5681 : : goto error;
5682 : : }
5683 : : /* Search from index 1 because on Windows starting '=' is allowed for
5684 : : defining hidden environment variables. */
5685 : : if (PyUnicode_GET_LENGTH(key2) == 0 ||
5686 : : PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5687 : : {
5688 : : PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5689 : : Py_DECREF(key2);
5690 : : Py_DECREF(val2);
5691 : : goto error;
5692 : : }
5693 : : keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5694 : : #else
5695 [ + + ]: 9969 : if (!PyUnicode_FSConverter(key, &key2))
5696 : 1 : goto error;
5697 [ + + ]: 9968 : if (!PyUnicode_FSConverter(val, &val2)) {
5698 : 1 : Py_DECREF(key2);
5699 : 1 : goto error;
5700 : : }
5701 [ + - ]: 9967 : if (PyBytes_GET_SIZE(key2) == 0 ||
5702 [ + + ]: 9967 : strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5703 : : {
5704 : 1 : PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5705 : 1 : Py_DECREF(key2);
5706 : 1 : Py_DECREF(val2);
5707 : 1 : goto error;
5708 : : }
5709 : 9966 : keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5710 : : PyBytes_AS_STRING(val2));
5711 : : #endif
5712 : 9966 : Py_DECREF(key2);
5713 : 9966 : Py_DECREF(val2);
5714 [ - + ]: 9966 : if (!keyval)
5715 : 0 : goto error;
5716 : :
5717 [ - + ]: 9966 : if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5718 : 0 : Py_DECREF(keyval);
5719 : 0 : goto error;
5720 : : }
5721 : :
5722 : 9966 : Py_DECREF(keyval);
5723 : : }
5724 : 91 : Py_DECREF(vals);
5725 : 91 : Py_DECREF(keys);
5726 : :
5727 : 91 : envlist[envc] = 0;
5728 : 91 : *envc_ptr = envc;
5729 : 91 : return envlist;
5730 : :
5731 : 3 : error:
5732 : 3 : Py_XDECREF(keys);
5733 : 3 : Py_XDECREF(vals);
5734 : 3 : free_string_array(envlist, envc);
5735 : 3 : return NULL;
5736 : : }
5737 : :
5738 : : static EXECV_CHAR**
5739 : 105 : parse_arglist(PyObject* argv, Py_ssize_t *argc)
5740 : : {
5741 : : int i;
5742 [ + - ]: 105 : EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5743 [ - + ]: 105 : if (argvlist == NULL) {
5744 : : PyErr_NoMemory();
5745 : 0 : return NULL;
5746 : : }
5747 [ + + ]: 456 : for (i = 0; i < *argc; i++) {
5748 : 351 : PyObject* item = PySequence_ITEM(argv, i);
5749 [ - + ]: 351 : if (item == NULL)
5750 : 0 : goto fail;
5751 [ - + ]: 351 : if (!fsconvert_strdup(item, &argvlist[i])) {
5752 : 0 : Py_DECREF(item);
5753 : 0 : goto fail;
5754 : : }
5755 : 351 : Py_DECREF(item);
5756 : : }
5757 : 105 : argvlist[*argc] = NULL;
5758 : 105 : return argvlist;
5759 : 0 : fail:
5760 : 0 : *argc = i;
5761 : 0 : free_string_array(argvlist, *argc);
5762 : 0 : return NULL;
5763 : : }
5764 : :
5765 : : #endif
5766 : :
5767 : :
5768 : : #ifdef HAVE_EXECV
5769 : : /*[clinic input]
5770 : : os.execv
5771 : :
5772 : : path: path_t
5773 : : Path of executable file.
5774 : : argv: object
5775 : : Tuple or list of strings.
5776 : : /
5777 : :
5778 : : Execute an executable path with arguments, replacing current process.
5779 : : [clinic start generated code]*/
5780 : :
5781 : : static PyObject *
5782 : 13 : os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5783 : : /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5784 : : {
5785 : : EXECV_CHAR **argvlist;
5786 : : Py_ssize_t argc;
5787 : :
5788 : : /* execv has two arguments: (path, argv), where
5789 : : argv is a list or tuple of strings. */
5790 : :
5791 [ + + - + ]: 13 : if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5792 : 0 : PyErr_SetString(PyExc_TypeError,
5793 : : "execv() arg 2 must be a tuple or list");
5794 : 0 : return NULL;
5795 : : }
5796 : 13 : argc = PySequence_Size(argv);
5797 [ + + ]: 13 : if (argc < 1) {
5798 : 3 : PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5799 : 3 : return NULL;
5800 : : }
5801 : :
5802 : 10 : argvlist = parse_arglist(argv, &argc);
5803 [ - + ]: 10 : if (argvlist == NULL) {
5804 : 0 : return NULL;
5805 : : }
5806 [ + + ]: 10 : if (!argvlist[0][0]) {
5807 : 2 : PyErr_SetString(PyExc_ValueError,
5808 : : "execv() arg 2 first element cannot be empty");
5809 : 2 : free_string_array(argvlist, argc);
5810 : 2 : return NULL;
5811 : : }
5812 : :
5813 [ - + ]: 8 : if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5814 : 0 : free_string_array(argvlist, argc);
5815 : 0 : return NULL;
5816 : : }
5817 : :
5818 : : _Py_BEGIN_SUPPRESS_IPH
5819 : : #ifdef HAVE_WEXECV
5820 : : _wexecv(path->wide, argvlist);
5821 : : #else
5822 : 8 : execv(path->narrow, argvlist);
5823 : : #endif
5824 : : _Py_END_SUPPRESS_IPH
5825 : :
5826 : : /* If we get here it's definitely an error */
5827 : :
5828 : 8 : free_string_array(argvlist, argc);
5829 : 8 : return posix_error();
5830 : : }
5831 : :
5832 : :
5833 : : /*[clinic input]
5834 : : os.execve
5835 : :
5836 : : path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5837 : : Path of executable file.
5838 : : argv: object
5839 : : Tuple or list of strings.
5840 : : env: object
5841 : : Dictionary of strings mapping to strings.
5842 : :
5843 : : Execute an executable path with arguments, replacing current process.
5844 : : [clinic start generated code]*/
5845 : :
5846 : : static PyObject *
5847 : 5 : os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5848 : : /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5849 : : {
5850 : 5 : EXECV_CHAR **argvlist = NULL;
5851 : : EXECV_CHAR **envlist;
5852 : : Py_ssize_t argc, envc;
5853 : :
5854 : : /* execve has three arguments: (path, argv, env), where
5855 : : argv is a list or tuple of strings and env is a dictionary
5856 : : like posix.environ. */
5857 : :
5858 [ - + - - ]: 5 : if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5859 : 0 : PyErr_SetString(PyExc_TypeError,
5860 : : "execve: argv must be a tuple or list");
5861 : 0 : goto fail_0;
5862 : : }
5863 : 5 : argc = PySequence_Size(argv);
5864 [ + + ]: 5 : if (argc < 1) {
5865 : 1 : PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5866 : 1 : return NULL;
5867 : : }
5868 : :
5869 [ - + ]: 4 : if (!PyMapping_Check(env)) {
5870 : 0 : PyErr_SetString(PyExc_TypeError,
5871 : : "execve: environment must be a mapping object");
5872 : 0 : goto fail_0;
5873 : : }
5874 : :
5875 : 4 : argvlist = parse_arglist(argv, &argc);
5876 [ - + ]: 4 : if (argvlist == NULL) {
5877 : 0 : goto fail_0;
5878 : : }
5879 [ + + ]: 4 : if (!argvlist[0][0]) {
5880 : 1 : PyErr_SetString(PyExc_ValueError,
5881 : : "execve: argv first element cannot be empty");
5882 : 1 : goto fail_0;
5883 : : }
5884 : :
5885 : 3 : envlist = parse_envlist(env, &envc);
5886 [ + - ]: 3 : if (envlist == NULL)
5887 : 3 : goto fail_0;
5888 : :
5889 [ # # ]: 0 : if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5890 : 0 : goto fail_1;
5891 : : }
5892 : :
5893 : : _Py_BEGIN_SUPPRESS_IPH
5894 : : #ifdef HAVE_FEXECVE
5895 [ # # ]: 0 : if (path->fd > -1)
5896 : 0 : fexecve(path->fd, argvlist, envlist);
5897 : : else
5898 : : #endif
5899 : : #ifdef HAVE_WEXECV
5900 : : _wexecve(path->wide, argvlist, envlist);
5901 : : #else
5902 : 0 : execve(path->narrow, argvlist, envlist);
5903 : : #endif
5904 : : _Py_END_SUPPRESS_IPH
5905 : :
5906 : : /* If we get here it's definitely an error */
5907 : :
5908 : 0 : posix_path_error(path);
5909 : 0 : fail_1:
5910 : 0 : free_string_array(envlist, envc);
5911 : 4 : fail_0:
5912 [ + - ]: 4 : if (argvlist)
5913 : 4 : free_string_array(argvlist, argc);
5914 : 4 : return NULL;
5915 : : }
5916 : :
5917 : : #endif /* HAVE_EXECV */
5918 : :
5919 : : #ifdef HAVE_POSIX_SPAWN
5920 : :
5921 : : enum posix_spawn_file_actions_identifier {
5922 : : POSIX_SPAWN_OPEN,
5923 : : POSIX_SPAWN_CLOSE,
5924 : : POSIX_SPAWN_DUP2
5925 : : };
5926 : :
5927 : : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
5928 : : static int
5929 : : convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
5930 : : #endif
5931 : :
5932 : : static int
5933 : 75 : parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
5934 : : int resetids, int setsid, PyObject *setsigmask,
5935 : : PyObject *setsigdef, PyObject *scheduler,
5936 : : posix_spawnattr_t *attrp)
5937 : : {
5938 : 75 : long all_flags = 0;
5939 : :
5940 : 75 : errno = posix_spawnattr_init(attrp);
5941 [ - + ]: 75 : if (errno) {
5942 : 0 : posix_error();
5943 : 0 : return -1;
5944 : : }
5945 : :
5946 [ + + ]: 75 : if (setpgroup) {
5947 : 4 : pid_t pgid = PyLong_AsPid(setpgroup);
5948 [ + + + - ]: 4 : if (pgid == (pid_t)-1 && PyErr_Occurred()) {
5949 : 2 : goto fail;
5950 : : }
5951 : 2 : errno = posix_spawnattr_setpgroup(attrp, pgid);
5952 [ - + ]: 2 : if (errno) {
5953 : 0 : posix_error();
5954 : 0 : goto fail;
5955 : : }
5956 : 2 : all_flags |= POSIX_SPAWN_SETPGROUP;
5957 : : }
5958 : :
5959 [ + + ]: 73 : if (resetids) {
5960 : 2 : all_flags |= POSIX_SPAWN_RESETIDS;
5961 : : }
5962 : :
5963 [ + + ]: 73 : if (setsid) {
5964 : : #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5965 : : if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
5966 : : #endif
5967 : : #ifdef POSIX_SPAWN_SETSID
5968 : 2 : all_flags |= POSIX_SPAWN_SETSID;
5969 : : #elif defined(POSIX_SPAWN_SETSID_NP)
5970 : : all_flags |= POSIX_SPAWN_SETSID_NP;
5971 : : #else
5972 : : argument_unavailable_error(func_name, "setsid");
5973 : : return -1;
5974 : : #endif
5975 : :
5976 : : #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5977 : : } else {
5978 : : argument_unavailable_error(func_name, "setsid");
5979 : : return -1;
5980 : : }
5981 : : #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
5982 : :
5983 : : }
5984 : :
5985 : : #ifdef HAVE_SIGSET_T
5986 [ + + ]: 73 : if (setsigmask) {
5987 : : sigset_t set;
5988 [ + + ]: 8 : if (!_Py_Sigset_Converter(setsigmask, &set)) {
5989 : 6 : goto fail;
5990 : : }
5991 : 2 : errno = posix_spawnattr_setsigmask(attrp, &set);
5992 [ - + ]: 2 : if (errno) {
5993 : 0 : posix_error();
5994 : 0 : goto fail;
5995 : : }
5996 : 2 : all_flags |= POSIX_SPAWN_SETSIGMASK;
5997 : : }
5998 : :
5999 [ + + ]: 67 : if (setsigdef) {
6000 : : sigset_t set;
6001 [ + + ]: 34 : if (!_Py_Sigset_Converter(setsigdef, &set)) {
6002 : 6 : goto fail;
6003 : : }
6004 : 28 : errno = posix_spawnattr_setsigdefault(attrp, &set);
6005 [ - + ]: 28 : if (errno) {
6006 : 0 : posix_error();
6007 : 0 : goto fail;
6008 : : }
6009 : 28 : all_flags |= POSIX_SPAWN_SETSIGDEF;
6010 : : }
6011 : : #else
6012 : : if (setsigmask || setsigdef) {
6013 : : PyErr_SetString(PyExc_NotImplementedError,
6014 : : "sigset is not supported on this platform");
6015 : : goto fail;
6016 : : }
6017 : : #endif
6018 : :
6019 [ + + ]: 61 : if (scheduler) {
6020 : : #ifdef POSIX_SPAWN_SETSCHEDULER
6021 : : PyObject *py_schedpolicy;
6022 : : PyObject *schedparam_obj;
6023 : : struct sched_param schedparam;
6024 : :
6025 [ - + ]: 4 : if (!PyArg_ParseTuple(scheduler, "OO"
6026 : : ";A scheduler tuple must have two elements",
6027 : : &py_schedpolicy, &schedparam_obj)) {
6028 : 0 : goto fail;
6029 : : }
6030 [ - + ]: 4 : if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
6031 : 0 : goto fail;
6032 : : }
6033 [ + + ]: 4 : if (py_schedpolicy != Py_None) {
6034 : 2 : int schedpolicy = _PyLong_AsInt(py_schedpolicy);
6035 : :
6036 [ - + - - ]: 2 : if (schedpolicy == -1 && PyErr_Occurred()) {
6037 : 0 : goto fail;
6038 : : }
6039 : 2 : errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
6040 [ - + ]: 2 : if (errno) {
6041 : 0 : posix_error();
6042 : 0 : goto fail;
6043 : : }
6044 : 2 : all_flags |= POSIX_SPAWN_SETSCHEDULER;
6045 : : }
6046 : 4 : errno = posix_spawnattr_setschedparam(attrp, &schedparam);
6047 [ - + ]: 4 : if (errno) {
6048 : 0 : posix_error();
6049 : 0 : goto fail;
6050 : : }
6051 : 4 : all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
6052 : : #else
6053 : : PyErr_SetString(PyExc_NotImplementedError,
6054 : : "The scheduler option is not supported in this system.");
6055 : : goto fail;
6056 : : #endif
6057 : : }
6058 : :
6059 : 61 : errno = posix_spawnattr_setflags(attrp, all_flags);
6060 [ - + ]: 61 : if (errno) {
6061 : 0 : posix_error();
6062 : 0 : goto fail;
6063 : : }
6064 : :
6065 : 61 : return 0;
6066 : :
6067 : 14 : fail:
6068 : 14 : (void)posix_spawnattr_destroy(attrp);
6069 : 14 : return -1;
6070 : : }
6071 : :
6072 : : static int
6073 : 51 : parse_file_actions(PyObject *file_actions,
6074 : : posix_spawn_file_actions_t *file_actionsp,
6075 : : PyObject *temp_buffer)
6076 : : {
6077 : : PyObject *seq;
6078 : 51 : PyObject *file_action = NULL;
6079 : : PyObject *tag_obj;
6080 : :
6081 : 51 : seq = PySequence_Fast(file_actions,
6082 : : "file_actions must be a sequence or None");
6083 [ - + ]: 51 : if (seq == NULL) {
6084 : 0 : return -1;
6085 : : }
6086 : :
6087 : 51 : errno = posix_spawn_file_actions_init(file_actionsp);
6088 [ - + ]: 51 : if (errno) {
6089 : 0 : posix_error();
6090 : 0 : Py_DECREF(seq);
6091 : 0 : return -1;
6092 : : }
6093 : :
6094 [ + - + + ]: 172 : for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
6095 [ + - ]: 137 : file_action = PySequence_Fast_GET_ITEM(seq, i);
6096 : 137 : Py_INCREF(file_action);
6097 [ + + + + ]: 137 : if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
6098 : 4 : PyErr_SetString(PyExc_TypeError,
6099 : : "Each file_actions element must be a non-empty tuple");
6100 : 4 : goto fail;
6101 : : }
6102 : 133 : long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
6103 [ + + + - ]: 133 : if (tag == -1 && PyErr_Occurred()) {
6104 : 2 : goto fail;
6105 : : }
6106 : :
6107 : : /* Populate the file_actions object */
6108 [ + + + + ]: 131 : switch (tag) {
6109 : 6 : case POSIX_SPAWN_OPEN: {
6110 : : int fd, oflag;
6111 : : PyObject *path;
6112 : : unsigned long mode;
6113 [ + + ]: 6 : if (!PyArg_ParseTuple(file_action, "OiO&ik"
6114 : : ";A open file_action tuple must have 5 elements",
6115 : : &tag_obj, &fd, PyUnicode_FSConverter, &path,
6116 : : &oflag, &mode))
6117 : : {
6118 : 2 : goto fail;
6119 : : }
6120 [ - + ]: 4 : if (PyList_Append(temp_buffer, path)) {
6121 : 0 : Py_DECREF(path);
6122 : 0 : goto fail;
6123 : : }
6124 : 4 : errno = posix_spawn_file_actions_addopen(file_actionsp,
6125 : 4 : fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
6126 : 4 : Py_DECREF(path);
6127 [ - + ]: 4 : if (errno) {
6128 : 0 : posix_error();
6129 : 0 : goto fail;
6130 : : }
6131 : 4 : break;
6132 : : }
6133 : 50 : case POSIX_SPAWN_CLOSE: {
6134 : : int fd;
6135 [ + + ]: 50 : if (!PyArg_ParseTuple(file_action, "Oi"
6136 : : ";A close file_action tuple must have 2 elements",
6137 : : &tag_obj, &fd))
6138 : : {
6139 : 6 : goto fail;
6140 : : }
6141 : 44 : errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
6142 [ - + ]: 44 : if (errno) {
6143 : 0 : posix_error();
6144 : 0 : goto fail;
6145 : : }
6146 : 44 : break;
6147 : : }
6148 : 73 : case POSIX_SPAWN_DUP2: {
6149 : : int fd1, fd2;
6150 [ - + ]: 73 : if (!PyArg_ParseTuple(file_action, "Oii"
6151 : : ";A dup2 file_action tuple must have 3 elements",
6152 : : &tag_obj, &fd1, &fd2))
6153 : : {
6154 : 0 : goto fail;
6155 : : }
6156 : 73 : errno = posix_spawn_file_actions_adddup2(file_actionsp,
6157 : : fd1, fd2);
6158 [ - + ]: 73 : if (errno) {
6159 : 0 : posix_error();
6160 : 0 : goto fail;
6161 : : }
6162 : 73 : break;
6163 : : }
6164 : 2 : default: {
6165 : 2 : PyErr_SetString(PyExc_TypeError,
6166 : : "Unknown file_actions identifier");
6167 : 2 : goto fail;
6168 : : }
6169 : : }
6170 : 121 : Py_DECREF(file_action);
6171 : : }
6172 : :
6173 : 35 : Py_DECREF(seq);
6174 : 35 : return 0;
6175 : :
6176 : 16 : fail:
6177 : 16 : Py_DECREF(seq);
6178 : 16 : Py_DECREF(file_action);
6179 : 16 : (void)posix_spawn_file_actions_destroy(file_actionsp);
6180 : 16 : return -1;
6181 : : }
6182 : :
6183 : :
6184 : : static PyObject *
6185 : 91 : py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
6186 : : PyObject *env, PyObject *file_actions,
6187 : : PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
6188 : : PyObject *setsigdef, PyObject *scheduler)
6189 : : {
6190 [ + + ]: 91 : const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
6191 : 91 : EXECV_CHAR **argvlist = NULL;
6192 : 91 : EXECV_CHAR **envlist = NULL;
6193 : : posix_spawn_file_actions_t file_actions_buf;
6194 : 91 : posix_spawn_file_actions_t *file_actionsp = NULL;
6195 : : posix_spawnattr_t attr;
6196 : 91 : posix_spawnattr_t *attrp = NULL;
6197 : : Py_ssize_t argc, envc;
6198 : 91 : PyObject *result = NULL;
6199 : 91 : PyObject *temp_buffer = NULL;
6200 : : pid_t pid;
6201 : : int err_code;
6202 : :
6203 : : /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
6204 : : argv is a list or tuple of strings and env is a dictionary
6205 : : like posix.environ. */
6206 : :
6207 [ + + - + ]: 91 : if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6208 : 0 : PyErr_Format(PyExc_TypeError,
6209 : : "%s: argv must be a tuple or list", func_name);
6210 : 0 : goto exit;
6211 : : }
6212 : 91 : argc = PySequence_Size(argv);
6213 [ - + ]: 91 : if (argc < 1) {
6214 : 0 : PyErr_Format(PyExc_ValueError,
6215 : : "%s: argv must not be empty", func_name);
6216 : 0 : return NULL;
6217 : : }
6218 : :
6219 [ - + ]: 91 : if (!PyMapping_Check(env)) {
6220 : 0 : PyErr_Format(PyExc_TypeError,
6221 : : "%s: environment must be a mapping object", func_name);
6222 : 0 : goto exit;
6223 : : }
6224 : :
6225 : 91 : argvlist = parse_arglist(argv, &argc);
6226 [ - + ]: 91 : if (argvlist == NULL) {
6227 : 0 : goto exit;
6228 : : }
6229 [ - + ]: 91 : if (!argvlist[0][0]) {
6230 : 0 : PyErr_Format(PyExc_ValueError,
6231 : : "%s: argv first element cannot be empty", func_name);
6232 : 0 : goto exit;
6233 : : }
6234 : :
6235 : 91 : envlist = parse_envlist(env, &envc);
6236 [ - + ]: 91 : if (envlist == NULL) {
6237 : 0 : goto exit;
6238 : : }
6239 : :
6240 [ + + + + ]: 91 : if (file_actions != NULL && file_actions != Py_None) {
6241 : : /* There is a bug in old versions of glibc that makes some of the
6242 : : * helper functions for manipulating file actions not copy the provided
6243 : : * buffers. The problem is that posix_spawn_file_actions_addopen does not
6244 : : * copy the value of path for some old versions of glibc (<2.20).
6245 : : * The use of temp_buffer here is a workaround that keeps the
6246 : : * python objects that own the buffers alive until posix_spawn gets called.
6247 : : * Check https://bugs.python.org/issue33630 and
6248 : : * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
6249 : 51 : temp_buffer = PyList_New(0);
6250 [ - + ]: 51 : if (!temp_buffer) {
6251 : 0 : goto exit;
6252 : : }
6253 [ + + ]: 51 : if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
6254 : 16 : goto exit;
6255 : : }
6256 : 35 : file_actionsp = &file_actions_buf;
6257 : : }
6258 : :
6259 [ + + ]: 75 : if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
6260 : : setsigmask, setsigdef, scheduler, &attr)) {
6261 : 14 : goto exit;
6262 : : }
6263 : 61 : attrp = &attr;
6264 : :
6265 [ - + ]: 61 : if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
6266 : 0 : goto exit;
6267 : : }
6268 : :
6269 : : _Py_BEGIN_SUPPRESS_IPH
6270 : : #ifdef HAVE_POSIX_SPAWNP
6271 [ + + ]: 61 : if (use_posix_spawnp) {
6272 : 18 : err_code = posix_spawnp(&pid, path->narrow,
6273 : : file_actionsp, attrp, argvlist, envlist);
6274 : : }
6275 : : else
6276 : : #endif /* HAVE_POSIX_SPAWNP */
6277 : : {
6278 : 43 : err_code = posix_spawn(&pid, path->narrow,
6279 : : file_actionsp, attrp, argvlist, envlist);
6280 : : }
6281 : : _Py_END_SUPPRESS_IPH
6282 : :
6283 [ + + ]: 61 : if (err_code) {
6284 : 2 : errno = err_code;
6285 : 2 : PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
6286 : 2 : goto exit;
6287 : : }
6288 : : #ifdef _Py_MEMORY_SANITIZER
6289 : : __msan_unpoison(&pid, sizeof(pid));
6290 : : #endif
6291 : 59 : result = PyLong_FromPid(pid);
6292 : :
6293 : 91 : exit:
6294 [ + + ]: 91 : if (file_actionsp) {
6295 : 35 : (void)posix_spawn_file_actions_destroy(file_actionsp);
6296 : : }
6297 [ + + ]: 91 : if (attrp) {
6298 : 61 : (void)posix_spawnattr_destroy(attrp);
6299 : : }
6300 [ + - ]: 91 : if (envlist) {
6301 : 91 : free_string_array(envlist, envc);
6302 : : }
6303 [ + - ]: 91 : if (argvlist) {
6304 : 91 : free_string_array(argvlist, argc);
6305 : : }
6306 : 91 : Py_XDECREF(temp_buffer);
6307 : 91 : return result;
6308 : : }
6309 : :
6310 : :
6311 : : /*[clinic input]
6312 : :
6313 : : os.posix_spawn
6314 : : path: path_t
6315 : : Path of executable file.
6316 : : argv: object
6317 : : Tuple or list of strings.
6318 : : env: object
6319 : : Dictionary of strings mapping to strings.
6320 : : /
6321 : : *
6322 : : file_actions: object(c_default='NULL') = ()
6323 : : A sequence of file action tuples.
6324 : : setpgroup: object = NULL
6325 : : The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6326 : : resetids: bool(accept={int}) = False
6327 : : If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
6328 : : setsid: bool(accept={int}) = False
6329 : : If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6330 : : setsigmask: object(c_default='NULL') = ()
6331 : : The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6332 : : setsigdef: object(c_default='NULL') = ()
6333 : : The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6334 : : scheduler: object = NULL
6335 : : A tuple with the scheduler policy (optional) and parameters.
6336 : :
6337 : : Execute the program specified by path in a new process.
6338 : : [clinic start generated code]*/
6339 : :
6340 : : static PyObject *
6341 : 58 : os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
6342 : : PyObject *env, PyObject *file_actions,
6343 : : PyObject *setpgroup, int resetids, int setsid,
6344 : : PyObject *setsigmask, PyObject *setsigdef,
6345 : : PyObject *scheduler)
6346 : : /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
6347 : : {
6348 : 58 : return py_posix_spawn(0, module, path, argv, env, file_actions,
6349 : : setpgroup, resetids, setsid, setsigmask, setsigdef,
6350 : : scheduler);
6351 : : }
6352 : : #endif /* HAVE_POSIX_SPAWN */
6353 : :
6354 : :
6355 : :
6356 : : #ifdef HAVE_POSIX_SPAWNP
6357 : : /*[clinic input]
6358 : :
6359 : : os.posix_spawnp
6360 : : path: path_t
6361 : : Path of executable file.
6362 : : argv: object
6363 : : Tuple or list of strings.
6364 : : env: object
6365 : : Dictionary of strings mapping to strings.
6366 : : /
6367 : : *
6368 : : file_actions: object(c_default='NULL') = ()
6369 : : A sequence of file action tuples.
6370 : : setpgroup: object = NULL
6371 : : The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6372 : : resetids: bool(accept={int}) = False
6373 : : If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
6374 : : setsid: bool(accept={int}) = False
6375 : : If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6376 : : setsigmask: object(c_default='NULL') = ()
6377 : : The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6378 : : setsigdef: object(c_default='NULL') = ()
6379 : : The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6380 : : scheduler: object = NULL
6381 : : A tuple with the scheduler policy (optional) and parameters.
6382 : :
6383 : : Execute the program specified by path in a new process.
6384 : : [clinic start generated code]*/
6385 : :
6386 : : static PyObject *
6387 : 33 : os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
6388 : : PyObject *env, PyObject *file_actions,
6389 : : PyObject *setpgroup, int resetids, int setsid,
6390 : : PyObject *setsigmask, PyObject *setsigdef,
6391 : : PyObject *scheduler)
6392 : : /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
6393 : : {
6394 : 33 : return py_posix_spawn(1, module, path, argv, env, file_actions,
6395 : : setpgroup, resetids, setsid, setsigmask, setsigdef,
6396 : : scheduler);
6397 : : }
6398 : : #endif /* HAVE_POSIX_SPAWNP */
6399 : :
6400 : : #ifdef HAVE_RTPSPAWN
6401 : : static intptr_t
6402 : : _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
6403 : : const char *envp[])
6404 : : {
6405 : : RTP_ID rtpid;
6406 : : int status;
6407 : : pid_t res;
6408 : : int async_err = 0;
6409 : :
6410 : : /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
6411 : : uStackSize=0 cannot be used, the default stack size is too small for
6412 : : Python. */
6413 : : if (envp) {
6414 : : rtpid = rtpSpawn(rtpFileName, argv, envp,
6415 : : 100, 0x1000000, 0, VX_FP_TASK);
6416 : : }
6417 : : else {
6418 : : rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
6419 : : 100, 0x1000000, 0, VX_FP_TASK);
6420 : : }
6421 : : if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
6422 : : do {
6423 : : res = waitpid((pid_t)rtpid, &status, 0);
6424 : : } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6425 : :
6426 : : if (res < 0)
6427 : : return RTP_ID_ERROR;
6428 : : return ((intptr_t)status);
6429 : : }
6430 : : return ((intptr_t)rtpid);
6431 : : }
6432 : : #endif
6433 : :
6434 : : #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
6435 : : /*[clinic input]
6436 : : os.spawnv
6437 : :
6438 : : mode: int
6439 : : Mode of process creation.
6440 : : path: path_t
6441 : : Path of executable file.
6442 : : argv: object
6443 : : Tuple or list of strings.
6444 : : /
6445 : :
6446 : : Execute the program specified by path in a new process.
6447 : : [clinic start generated code]*/
6448 : :
6449 : : static PyObject *
6450 : : os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
6451 : : /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
6452 : : {
6453 : : EXECV_CHAR **argvlist;
6454 : : int i;
6455 : : Py_ssize_t argc;
6456 : : intptr_t spawnval;
6457 : : PyObject *(*getitem)(PyObject *, Py_ssize_t);
6458 : :
6459 : : /* spawnv has three arguments: (mode, path, argv), where
6460 : : argv is a list or tuple of strings. */
6461 : :
6462 : : if (PyList_Check(argv)) {
6463 : : argc = PyList_Size(argv);
6464 : : getitem = PyList_GetItem;
6465 : : }
6466 : : else if (PyTuple_Check(argv)) {
6467 : : argc = PyTuple_Size(argv);
6468 : : getitem = PyTuple_GetItem;
6469 : : }
6470 : : else {
6471 : : PyErr_SetString(PyExc_TypeError,
6472 : : "spawnv() arg 2 must be a tuple or list");
6473 : : return NULL;
6474 : : }
6475 : : if (argc == 0) {
6476 : : PyErr_SetString(PyExc_ValueError,
6477 : : "spawnv() arg 2 cannot be empty");
6478 : : return NULL;
6479 : : }
6480 : :
6481 : : argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6482 : : if (argvlist == NULL) {
6483 : : return PyErr_NoMemory();
6484 : : }
6485 : : for (i = 0; i < argc; i++) {
6486 : : if (!fsconvert_strdup((*getitem)(argv, i),
6487 : : &argvlist[i])) {
6488 : : free_string_array(argvlist, i);
6489 : : PyErr_SetString(
6490 : : PyExc_TypeError,
6491 : : "spawnv() arg 2 must contain only strings");
6492 : : return NULL;
6493 : : }
6494 : : if (i == 0 && !argvlist[0][0]) {
6495 : : free_string_array(argvlist, i + 1);
6496 : : PyErr_SetString(
6497 : : PyExc_ValueError,
6498 : : "spawnv() arg 2 first element cannot be empty");
6499 : : return NULL;
6500 : : }
6501 : : }
6502 : : argvlist[argc] = NULL;
6503 : :
6504 : : #if !defined(HAVE_RTPSPAWN)
6505 : : if (mode == _OLD_P_OVERLAY)
6506 : : mode = _P_OVERLAY;
6507 : : #endif
6508 : :
6509 : : if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
6510 : : Py_None) < 0) {
6511 : : free_string_array(argvlist, argc);
6512 : : return NULL;
6513 : : }
6514 : :
6515 : : Py_BEGIN_ALLOW_THREADS
6516 : : _Py_BEGIN_SUPPRESS_IPH
6517 : : #ifdef HAVE_WSPAWNV
6518 : : spawnval = _wspawnv(mode, path->wide, argvlist);
6519 : : #elif defined(HAVE_RTPSPAWN)
6520 : : spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
6521 : : #else
6522 : : spawnval = _spawnv(mode, path->narrow, argvlist);
6523 : : #endif
6524 : : _Py_END_SUPPRESS_IPH
6525 : : Py_END_ALLOW_THREADS
6526 : :
6527 : : free_string_array(argvlist, argc);
6528 : :
6529 : : if (spawnval == -1)
6530 : : return posix_error();
6531 : : else
6532 : : return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6533 : : }
6534 : :
6535 : : /*[clinic input]
6536 : : os.spawnve
6537 : :
6538 : : mode: int
6539 : : Mode of process creation.
6540 : : path: path_t
6541 : : Path of executable file.
6542 : : argv: object
6543 : : Tuple or list of strings.
6544 : : env: object
6545 : : Dictionary of strings mapping to strings.
6546 : : /
6547 : :
6548 : : Execute the program specified by path in a new process.
6549 : : [clinic start generated code]*/
6550 : :
6551 : : static PyObject *
6552 : : os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
6553 : : PyObject *env)
6554 : : /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
6555 : : {
6556 : : EXECV_CHAR **argvlist;
6557 : : EXECV_CHAR **envlist;
6558 : : PyObject *res = NULL;
6559 : : Py_ssize_t argc, i, envc;
6560 : : intptr_t spawnval;
6561 : : PyObject *(*getitem)(PyObject *, Py_ssize_t);
6562 : : Py_ssize_t lastarg = 0;
6563 : :
6564 : : /* spawnve has four arguments: (mode, path, argv, env), where
6565 : : argv is a list or tuple of strings and env is a dictionary
6566 : : like posix.environ. */
6567 : :
6568 : : if (PyList_Check(argv)) {
6569 : : argc = PyList_Size(argv);
6570 : : getitem = PyList_GetItem;
6571 : : }
6572 : : else if (PyTuple_Check(argv)) {
6573 : : argc = PyTuple_Size(argv);
6574 : : getitem = PyTuple_GetItem;
6575 : : }
6576 : : else {
6577 : : PyErr_SetString(PyExc_TypeError,
6578 : : "spawnve() arg 2 must be a tuple or list");
6579 : : goto fail_0;
6580 : : }
6581 : : if (argc == 0) {
6582 : : PyErr_SetString(PyExc_ValueError,
6583 : : "spawnve() arg 2 cannot be empty");
6584 : : goto fail_0;
6585 : : }
6586 : : if (!PyMapping_Check(env)) {
6587 : : PyErr_SetString(PyExc_TypeError,
6588 : : "spawnve() arg 3 must be a mapping object");
6589 : : goto fail_0;
6590 : : }
6591 : :
6592 : : argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6593 : : if (argvlist == NULL) {
6594 : : PyErr_NoMemory();
6595 : : goto fail_0;
6596 : : }
6597 : : for (i = 0; i < argc; i++) {
6598 : : if (!fsconvert_strdup((*getitem)(argv, i),
6599 : : &argvlist[i]))
6600 : : {
6601 : : lastarg = i;
6602 : : goto fail_1;
6603 : : }
6604 : : if (i == 0 && !argvlist[0][0]) {
6605 : : lastarg = i + 1;
6606 : : PyErr_SetString(
6607 : : PyExc_ValueError,
6608 : : "spawnv() arg 2 first element cannot be empty");
6609 : : goto fail_1;
6610 : : }
6611 : : }
6612 : : lastarg = argc;
6613 : : argvlist[argc] = NULL;
6614 : :
6615 : : envlist = parse_envlist(env, &envc);
6616 : : if (envlist == NULL)
6617 : : goto fail_1;
6618 : :
6619 : : #if !defined(HAVE_RTPSPAWN)
6620 : : if (mode == _OLD_P_OVERLAY)
6621 : : mode = _P_OVERLAY;
6622 : : #endif
6623 : :
6624 : : if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6625 : : goto fail_2;
6626 : : }
6627 : :
6628 : : Py_BEGIN_ALLOW_THREADS
6629 : : _Py_BEGIN_SUPPRESS_IPH
6630 : : #ifdef HAVE_WSPAWNV
6631 : : spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6632 : : #elif defined(HAVE_RTPSPAWN)
6633 : : spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6634 : : (const char **)envlist);
6635 : : #else
6636 : : spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6637 : : #endif
6638 : : _Py_END_SUPPRESS_IPH
6639 : : Py_END_ALLOW_THREADS
6640 : :
6641 : : if (spawnval == -1)
6642 : : (void) posix_error();
6643 : : else
6644 : : res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6645 : :
6646 : : fail_2:
6647 : : while (--envc >= 0) {
6648 : : PyMem_Free(envlist[envc]);
6649 : : }
6650 : : PyMem_Free(envlist);
6651 : : fail_1:
6652 : : free_string_array(argvlist, lastarg);
6653 : : fail_0:
6654 : : return res;
6655 : : }
6656 : :
6657 : : #endif /* HAVE_SPAWNV */
6658 : :
6659 : : #ifdef HAVE_FORK
6660 : :
6661 : : /* Helper function to validate arguments.
6662 : : Returns 0 on success. non-zero on failure with a TypeError raised.
6663 : : If obj is non-NULL it must be callable. */
6664 : : static int
6665 : 9285 : check_null_or_callable(PyObject *obj, const char* obj_name)
6666 : : {
6667 [ + + + + ]: 9285 : if (obj && !PyCallable_Check(obj)) {
6668 : 8 : PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6669 : : obj_name, _PyType_Name(Py_TYPE(obj)));
6670 : 8 : return -1;
6671 : : }
6672 : 9277 : return 0;
6673 : : }
6674 : :
6675 : : /*[clinic input]
6676 : : os.register_at_fork
6677 : :
6678 : : *
6679 : : before: object=NULL
6680 : : A callable to be called in the parent before the fork() syscall.
6681 : : after_in_child: object=NULL
6682 : : A callable to be called in the child after fork().
6683 : : after_in_parent: object=NULL
6684 : : A callable to be called in the parent after fork().
6685 : :
6686 : : Register callables to be called when forking a new process.
6687 : :
6688 : : 'before' callbacks are called in reverse order.
6689 : : 'after_in_child' and 'after_in_parent' callbacks are called in order.
6690 : :
6691 : : [clinic start generated code]*/
6692 : :
6693 : : static PyObject *
6694 : 3098 : os_register_at_fork_impl(PyObject *module, PyObject *before,
6695 : : PyObject *after_in_child, PyObject *after_in_parent)
6696 : : /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6697 : : {
6698 : : PyInterpreterState *interp;
6699 : :
6700 [ + + + + : 3098 : if (!before && !after_in_child && !after_in_parent) {
- + ]
6701 : 0 : PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6702 : 0 : return NULL;
6703 : : }
6704 [ + + + + ]: 6193 : if (check_null_or_callable(before, "before") ||
6705 [ + + ]: 6187 : check_null_or_callable(after_in_child, "after_in_child") ||
6706 : 3092 : check_null_or_callable(after_in_parent, "after_in_parent")) {
6707 : 8 : return NULL;
6708 : : }
6709 : 3090 : interp = _PyInterpreterState_GET();
6710 : :
6711 [ - + ]: 3090 : if (register_at_forker(&interp->before_forkers, before)) {
6712 : 0 : return NULL;
6713 : : }
6714 [ - + ]: 3090 : if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6715 : 0 : return NULL;
6716 : : }
6717 [ - + ]: 3090 : if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6718 : 0 : return NULL;
6719 : : }
6720 : 3090 : Py_RETURN_NONE;
6721 : : }
6722 : : #endif /* HAVE_FORK */
6723 : :
6724 : :
6725 : : #ifdef HAVE_FORK1
6726 : : /*[clinic input]
6727 : : os.fork1
6728 : :
6729 : : Fork a child process with a single multiplexed (i.e., not bound) thread.
6730 : :
6731 : : Return 0 to child process and PID of child to parent process.
6732 : : [clinic start generated code]*/
6733 : :
6734 : : static PyObject *
6735 : : os_fork1_impl(PyObject *module)
6736 : : /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6737 : : {
6738 : : pid_t pid;
6739 : :
6740 : : if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
6741 : : PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6742 : : return NULL;
6743 : : }
6744 : : PyOS_BeforeFork();
6745 : : pid = fork1();
6746 : : if (pid == 0) {
6747 : : /* child: this clobbers and resets the import lock. */
6748 : : PyOS_AfterFork_Child();
6749 : : } else {
6750 : : /* parent: release the import lock. */
6751 : : PyOS_AfterFork_Parent();
6752 : : }
6753 : : if (pid == -1)
6754 : : return posix_error();
6755 : : return PyLong_FromPid(pid);
6756 : : }
6757 : : #endif /* HAVE_FORK1 */
6758 : :
6759 : :
6760 : : #ifdef HAVE_FORK
6761 : : /*[clinic input]
6762 : : os.fork
6763 : :
6764 : : Fork a child process.
6765 : :
6766 : : Return 0 to child process and PID of child to parent process.
6767 : : [clinic start generated code]*/
6768 : :
6769 : : static PyObject *
6770 : 1505 : os_fork_impl(PyObject *module)
6771 : : /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6772 : : {
6773 : : pid_t pid;
6774 : 1505 : PyInterpreterState *interp = _PyInterpreterState_GET();
6775 [ + + ]: 1505 : if (interp->config._isolated_interpreter) {
6776 : 2 : PyErr_SetString(PyExc_RuntimeError,
6777 : : "fork not supported for isolated subinterpreters");
6778 : 2 : return NULL;
6779 : : }
6780 [ - + ]: 1503 : if (PySys_Audit("os.fork", NULL) < 0) {
6781 : 0 : return NULL;
6782 : : }
6783 : 1503 : PyOS_BeforeFork();
6784 : 1503 : pid = fork();
6785 [ + + ]: 1503 : if (pid == 0) {
6786 : : /* child: this clobbers and resets the import lock. */
6787 : 8 : PyOS_AfterFork_Child();
6788 : : } else {
6789 : : /* parent: release the import lock. */
6790 : 1495 : PyOS_AfterFork_Parent();
6791 : : }
6792 [ - + ]: 1503 : if (pid == -1)
6793 : 0 : return posix_error();
6794 : 1503 : return PyLong_FromPid(pid);
6795 : : }
6796 : : #endif /* HAVE_FORK */
6797 : :
6798 : :
6799 : : #ifdef HAVE_SCHED_H
6800 : : #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6801 : : /*[clinic input]
6802 : : os.sched_get_priority_max
6803 : :
6804 : : policy: int
6805 : :
6806 : : Get the maximum scheduling priority for policy.
6807 : : [clinic start generated code]*/
6808 : :
6809 : : static PyObject *
6810 : 2 : os_sched_get_priority_max_impl(PyObject *module, int policy)
6811 : : /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6812 : : {
6813 : : int max;
6814 : :
6815 : 2 : max = sched_get_priority_max(policy);
6816 [ + + ]: 2 : if (max < 0)
6817 : 1 : return posix_error();
6818 : 1 : return PyLong_FromLong(max);
6819 : : }
6820 : :
6821 : :
6822 : : /*[clinic input]
6823 : : os.sched_get_priority_min
6824 : :
6825 : : policy: int
6826 : :
6827 : : Get the minimum scheduling priority for policy.
6828 : : [clinic start generated code]*/
6829 : :
6830 : : static PyObject *
6831 : 6 : os_sched_get_priority_min_impl(PyObject *module, int policy)
6832 : : /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6833 : : {
6834 : 6 : int min = sched_get_priority_min(policy);
6835 [ + + ]: 6 : if (min < 0)
6836 : 1 : return posix_error();
6837 : 5 : return PyLong_FromLong(min);
6838 : : }
6839 : : #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6840 : :
6841 : :
6842 : : #ifdef HAVE_SCHED_SETSCHEDULER
6843 : : /*[clinic input]
6844 : : os.sched_getscheduler
6845 : : pid: pid_t
6846 : : /
6847 : :
6848 : : Get the scheduling policy for the process identified by pid.
6849 : :
6850 : : Passing 0 for pid returns the scheduling policy for the calling process.
6851 : : [clinic start generated code]*/
6852 : :
6853 : : static PyObject *
6854 : 12 : os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6855 : : /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
6856 : : {
6857 : : int policy;
6858 : :
6859 : 12 : policy = sched_getscheduler(pid);
6860 [ + + ]: 12 : if (policy < 0)
6861 : 1 : return posix_error();
6862 : 11 : return PyLong_FromLong(policy);
6863 : : }
6864 : : #endif /* HAVE_SCHED_SETSCHEDULER */
6865 : :
6866 : :
6867 : : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6868 : : /*[clinic input]
6869 : : class os.sched_param "PyObject *" "SchedParamType"
6870 : :
6871 : : @classmethod
6872 : : os.sched_param.__new__
6873 : :
6874 : : sched_priority: object
6875 : : A scheduling parameter.
6876 : :
6877 : : Currently has only one field: sched_priority
6878 : : [clinic start generated code]*/
6879 : :
6880 : : static PyObject *
6881 : 7 : os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6882 : : /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
6883 : : {
6884 : : PyObject *res;
6885 : :
6886 : 7 : res = PyStructSequence_New(type);
6887 [ - + ]: 7 : if (!res)
6888 : 0 : return NULL;
6889 : 7 : Py_INCREF(sched_priority);
6890 : 7 : PyStructSequence_SET_ITEM(res, 0, sched_priority);
6891 : 7 : return res;
6892 : : }
6893 : :
6894 : : PyDoc_VAR(os_sched_param__doc__);
6895 : :
6896 : : static PyStructSequence_Field sched_param_fields[] = {
6897 : : {"sched_priority", "the scheduling priority"},
6898 : : {0}
6899 : : };
6900 : :
6901 : : static PyStructSequence_Desc sched_param_desc = {
6902 : : "sched_param", /* name */
6903 : : os_sched_param__doc__, /* doc */
6904 : : sched_param_fields,
6905 : : 1
6906 : : };
6907 : :
6908 : : static int
6909 : 13 : convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
6910 : : {
6911 : : long priority;
6912 : :
6913 [ + + ]: 13 : if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
6914 : 2 : PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
6915 : 2 : return 0;
6916 : : }
6917 : 11 : priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
6918 [ + + + - ]: 11 : if (priority == -1 && PyErr_Occurred())
6919 : 1 : return 0;
6920 [ + + + + ]: 10 : if (priority > INT_MAX || priority < INT_MIN) {
6921 : 2 : PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
6922 : 2 : return 0;
6923 : : }
6924 : 8 : res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
6925 : 8 : return 1;
6926 : : }
6927 : : #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
6928 : :
6929 : :
6930 : : #ifdef HAVE_SCHED_SETSCHEDULER
6931 : : /*[clinic input]
6932 : : os.sched_setscheduler
6933 : :
6934 : : pid: pid_t
6935 : : policy: int
6936 : : param as param_obj: object
6937 : : /
6938 : :
6939 : : Set the scheduling policy for the process identified by pid.
6940 : :
6941 : : If pid is 0, the calling process is changed.
6942 : : param is an instance of sched_param.
6943 : : [clinic start generated code]*/
6944 : :
6945 : : static PyObject *
6946 : 3 : os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
6947 : : PyObject *param_obj)
6948 : : /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
6949 : : {
6950 : : struct sched_param param;
6951 [ + + ]: 3 : if (!convert_sched_param(module, param_obj, ¶m)) {
6952 : 1 : return NULL;
6953 : : }
6954 : :
6955 : : /*
6956 : : ** sched_setscheduler() returns 0 in Linux, but the previous
6957 : : ** scheduling policy under Solaris/Illumos, and others.
6958 : : ** On error, -1 is returned in all Operating Systems.
6959 : : */
6960 [ + + ]: 2 : if (sched_setscheduler(pid, policy, ¶m) == -1)
6961 : 1 : return posix_error();
6962 : 1 : Py_RETURN_NONE;
6963 : : }
6964 : : #endif /* HAVE_SCHED_SETSCHEDULER*/
6965 : :
6966 : :
6967 : : #ifdef HAVE_SCHED_SETPARAM
6968 : : /*[clinic input]
6969 : : os.sched_getparam
6970 : : pid: pid_t
6971 : : /
6972 : :
6973 : : Returns scheduling parameters for the process identified by pid.
6974 : :
6975 : : If pid is 0, returns parameters for the calling process.
6976 : : Return value is an instance of sched_param.
6977 : : [clinic start generated code]*/
6978 : :
6979 : : static PyObject *
6980 : 6 : os_sched_getparam_impl(PyObject *module, pid_t pid)
6981 : : /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
6982 : : {
6983 : : struct sched_param param;
6984 : : PyObject *result;
6985 : : PyObject *priority;
6986 : :
6987 [ + + ]: 6 : if (sched_getparam(pid, ¶m))
6988 : 1 : return posix_error();
6989 : 5 : PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
6990 : 5 : result = PyStructSequence_New((PyTypeObject *)SchedParamType);
6991 [ - + ]: 5 : if (!result)
6992 : 0 : return NULL;
6993 : 5 : priority = PyLong_FromLong(param.sched_priority);
6994 [ - + ]: 5 : if (!priority) {
6995 : 0 : Py_DECREF(result);
6996 : 0 : return NULL;
6997 : : }
6998 : 5 : PyStructSequence_SET_ITEM(result, 0, priority);
6999 : 5 : return result;
7000 : : }
7001 : :
7002 : :
7003 : : /*[clinic input]
7004 : : os.sched_setparam
7005 : : pid: pid_t
7006 : : param as param_obj: object
7007 : : /
7008 : :
7009 : : Set scheduling parameters for the process identified by pid.
7010 : :
7011 : : If pid is 0, sets parameters for the calling process.
7012 : : param should be an instance of sched_param.
7013 : : [clinic start generated code]*/
7014 : :
7015 : : static PyObject *
7016 : 6 : os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
7017 : : /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
7018 : : {
7019 : : struct sched_param param;
7020 [ + + ]: 6 : if (!convert_sched_param(module, param_obj, ¶m)) {
7021 : 4 : return NULL;
7022 : : }
7023 : :
7024 [ + + ]: 2 : if (sched_setparam(pid, ¶m))
7025 : 1 : return posix_error();
7026 : 1 : Py_RETURN_NONE;
7027 : : }
7028 : : #endif /* HAVE_SCHED_SETPARAM */
7029 : :
7030 : :
7031 : : #ifdef HAVE_SCHED_RR_GET_INTERVAL
7032 : : /*[clinic input]
7033 : : os.sched_rr_get_interval -> double
7034 : : pid: pid_t
7035 : : /
7036 : :
7037 : : Return the round-robin quantum for the process identified by pid, in seconds.
7038 : :
7039 : : Value returned is a float.
7040 : : [clinic start generated code]*/
7041 : :
7042 : : static double
7043 : 1 : os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
7044 : : /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
7045 : : {
7046 : : struct timespec interval;
7047 [ - + ]: 1 : if (sched_rr_get_interval(pid, &interval)) {
7048 : 0 : posix_error();
7049 : 0 : return -1.0;
7050 : : }
7051 : : #ifdef _Py_MEMORY_SANITIZER
7052 : : __msan_unpoison(&interval, sizeof(interval));
7053 : : #endif
7054 : 1 : return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
7055 : : }
7056 : : #endif /* HAVE_SCHED_RR_GET_INTERVAL */
7057 : :
7058 : :
7059 : : /*[clinic input]
7060 : : os.sched_yield
7061 : :
7062 : : Voluntarily relinquish the CPU.
7063 : : [clinic start generated code]*/
7064 : :
7065 : : static PyObject *
7066 : 1 : os_sched_yield_impl(PyObject *module)
7067 : : /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
7068 : : {
7069 [ - + ]: 1 : if (sched_yield())
7070 : 0 : return posix_error();
7071 : 1 : Py_RETURN_NONE;
7072 : : }
7073 : :
7074 : : #ifdef HAVE_SCHED_SETAFFINITY
7075 : : /* The minimum number of CPUs allocated in a cpu_set_t */
7076 : : static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
7077 : :
7078 : : /*[clinic input]
7079 : : os.sched_setaffinity
7080 : : pid: pid_t
7081 : : mask : object
7082 : : /
7083 : :
7084 : : Set the CPU affinity of the process identified by pid to mask.
7085 : :
7086 : : mask should be an iterable of integers identifying CPUs.
7087 : : [clinic start generated code]*/
7088 : :
7089 : : static PyObject *
7090 : 6 : os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
7091 : : /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
7092 : : {
7093 : : int ncpus;
7094 : : size_t setsize;
7095 : 6 : cpu_set_t *cpu_set = NULL;
7096 : 6 : PyObject *iterator = NULL, *item;
7097 : :
7098 : 6 : iterator = PyObject_GetIter(mask);
7099 [ - + ]: 6 : if (iterator == NULL)
7100 : 0 : return NULL;
7101 : :
7102 : 6 : ncpus = NCPUS_START;
7103 : 6 : setsize = CPU_ALLOC_SIZE(ncpus);
7104 : 6 : cpu_set = CPU_ALLOC(ncpus);
7105 [ - + ]: 6 : if (cpu_set == NULL) {
7106 : : PyErr_NoMemory();
7107 : 0 : goto error;
7108 : : }
7109 : 6 : CPU_ZERO_S(setsize, cpu_set);
7110 : :
7111 [ + + ]: 21 : while ((item = PyIter_Next(iterator))) {
7112 : : long cpu;
7113 [ - + ]: 17 : if (!PyLong_Check(item)) {
7114 : 0 : PyErr_Format(PyExc_TypeError,
7115 : : "expected an iterator of ints, "
7116 : : "but iterator yielded %R",
7117 : : Py_TYPE(item));
7118 : 0 : Py_DECREF(item);
7119 : 0 : goto error;
7120 : : }
7121 : 17 : cpu = PyLong_AsLong(item);
7122 : 17 : Py_DECREF(item);
7123 [ + + ]: 17 : if (cpu < 0) {
7124 [ + + ]: 2 : if (!PyErr_Occurred())
7125 : 1 : PyErr_SetString(PyExc_ValueError, "negative CPU number");
7126 : 2 : goto error;
7127 : : }
7128 [ - + ]: 15 : if (cpu > INT_MAX - 1) {
7129 : 0 : PyErr_SetString(PyExc_OverflowError, "CPU number too large");
7130 : 0 : goto error;
7131 : : }
7132 [ - + ]: 15 : if (cpu >= ncpus) {
7133 : : /* Grow CPU mask to fit the CPU number */
7134 : 0 : int newncpus = ncpus;
7135 : : cpu_set_t *newmask;
7136 : : size_t newsetsize;
7137 [ # # ]: 0 : while (newncpus <= cpu) {
7138 [ # # ]: 0 : if (newncpus > INT_MAX / 2)
7139 : 0 : newncpus = cpu + 1;
7140 : : else
7141 : 0 : newncpus = newncpus * 2;
7142 : : }
7143 : 0 : newmask = CPU_ALLOC(newncpus);
7144 [ # # ]: 0 : if (newmask == NULL) {
7145 : : PyErr_NoMemory();
7146 : 0 : goto error;
7147 : : }
7148 : 0 : newsetsize = CPU_ALLOC_SIZE(newncpus);
7149 : 0 : CPU_ZERO_S(newsetsize, newmask);
7150 : 0 : memcpy(newmask, cpu_set, setsize);
7151 : 0 : CPU_FREE(cpu_set);
7152 : 0 : setsize = newsetsize;
7153 : 0 : cpu_set = newmask;
7154 : 0 : ncpus = newncpus;
7155 : : }
7156 [ + - ]: 15 : CPU_SET_S(cpu, setsize, cpu_set);
7157 : : }
7158 [ + + ]: 4 : if (PyErr_Occurred()) {
7159 : 1 : goto error;
7160 : : }
7161 [ + - ]: 3 : Py_CLEAR(iterator);
7162 : :
7163 [ + + ]: 3 : if (sched_setaffinity(pid, setsize, cpu_set)) {
7164 : 2 : posix_error();
7165 : 2 : goto error;
7166 : : }
7167 : 1 : CPU_FREE(cpu_set);
7168 : 1 : Py_RETURN_NONE;
7169 : :
7170 : 5 : error:
7171 [ + - ]: 5 : if (cpu_set)
7172 : 5 : CPU_FREE(cpu_set);
7173 : 5 : Py_XDECREF(iterator);
7174 : 5 : return NULL;
7175 : : }
7176 : :
7177 : :
7178 : : /*[clinic input]
7179 : : os.sched_getaffinity
7180 : : pid: pid_t
7181 : : /
7182 : :
7183 : : Return the affinity of the process identified by pid (or the current process if zero).
7184 : :
7185 : : The affinity is returned as a set of CPU identifiers.
7186 : : [clinic start generated code]*/
7187 : :
7188 : : static PyObject *
7189 : 4 : os_sched_getaffinity_impl(PyObject *module, pid_t pid)
7190 : : /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
7191 : : {
7192 : : int cpu, ncpus, count;
7193 : : size_t setsize;
7194 : 4 : cpu_set_t *mask = NULL;
7195 : 4 : PyObject *res = NULL;
7196 : :
7197 : 4 : ncpus = NCPUS_START;
7198 : : while (1) {
7199 : 4 : setsize = CPU_ALLOC_SIZE(ncpus);
7200 : 4 : mask = CPU_ALLOC(ncpus);
7201 [ - + ]: 4 : if (mask == NULL)
7202 : : return PyErr_NoMemory();
7203 [ + + ]: 4 : if (sched_getaffinity(pid, setsize, mask) == 0)
7204 : 3 : break;
7205 : 1 : CPU_FREE(mask);
7206 [ + - ]: 1 : if (errno != EINVAL)
7207 : 1 : return posix_error();
7208 [ # # ]: 0 : if (ncpus > INT_MAX / 2) {
7209 : 0 : PyErr_SetString(PyExc_OverflowError, "could not allocate "
7210 : : "a large enough CPU set");
7211 : 0 : return NULL;
7212 : : }
7213 : 0 : ncpus = ncpus * 2;
7214 : : }
7215 : :
7216 : 3 : res = PySet_New(NULL);
7217 [ - + ]: 3 : if (res == NULL)
7218 : 0 : goto error;
7219 [ + + ]: 27 : for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7220 [ + - + + : 24 : if (CPU_ISSET_S(cpu, setsize, mask)) {
+ + ]
7221 : 23 : PyObject *cpu_num = PyLong_FromLong(cpu);
7222 : 23 : --count;
7223 [ - + ]: 23 : if (cpu_num == NULL)
7224 : 0 : goto error;
7225 [ - + ]: 23 : if (PySet_Add(res, cpu_num)) {
7226 : 0 : Py_DECREF(cpu_num);
7227 : 0 : goto error;
7228 : : }
7229 : 23 : Py_DECREF(cpu_num);
7230 : : }
7231 : : }
7232 : 3 : CPU_FREE(mask);
7233 : 3 : return res;
7234 : :
7235 : 0 : error:
7236 [ # # ]: 0 : if (mask)
7237 : 0 : CPU_FREE(mask);
7238 : 0 : Py_XDECREF(res);
7239 : 0 : return NULL;
7240 : : }
7241 : :
7242 : : #endif /* HAVE_SCHED_SETAFFINITY */
7243 : :
7244 : : #endif /* HAVE_SCHED_H */
7245 : :
7246 : :
7247 : : /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
7248 : : #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
7249 : : # define DEV_PTY_FILE "/dev/ptc"
7250 : : # define HAVE_DEV_PTMX
7251 : : #else
7252 : : # define DEV_PTY_FILE "/dev/ptmx"
7253 : : #endif
7254 : :
7255 : : #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
7256 : : #ifdef HAVE_PTY_H
7257 : : #include <pty.h>
7258 : : #ifdef HAVE_UTMP_H
7259 : : #include <utmp.h>
7260 : : #endif /* HAVE_UTMP_H */
7261 : : #elif defined(HAVE_LIBUTIL_H)
7262 : : #include <libutil.h>
7263 : : #elif defined(HAVE_UTIL_H)
7264 : : #include <util.h>
7265 : : #endif /* HAVE_PTY_H */
7266 : : #ifdef HAVE_STROPTS_H
7267 : : #include <stropts.h>
7268 : : #endif
7269 : : #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
7270 : :
7271 : :
7272 : : #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7273 : : /*[clinic input]
7274 : : os.openpty
7275 : :
7276 : : Open a pseudo-terminal.
7277 : :
7278 : : Return a tuple of (master_fd, slave_fd) containing open file descriptors
7279 : : for both the master and slave ends.
7280 : : [clinic start generated code]*/
7281 : :
7282 : : static PyObject *
7283 : 17 : os_openpty_impl(PyObject *module)
7284 : : /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
7285 : : {
7286 : 17 : int master_fd = -1, slave_fd = -1;
7287 : : #ifndef HAVE_OPENPTY
7288 : : char * slave_name;
7289 : : #endif
7290 : : #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
7291 : : PyOS_sighandler_t sig_saved;
7292 : : #if defined(__sun) && defined(__SVR4)
7293 : : extern char *ptsname(int fildes);
7294 : : #endif
7295 : : #endif
7296 : :
7297 : : #ifdef HAVE_OPENPTY
7298 [ - + ]: 17 : if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
7299 : 0 : goto posix_error;
7300 : :
7301 [ - + ]: 17 : if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7302 : 0 : goto error;
7303 [ - + ]: 17 : if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
7304 : 0 : goto error;
7305 : :
7306 : : #elif defined(HAVE__GETPTY)
7307 : : slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
7308 : : if (slave_name == NULL)
7309 : : goto posix_error;
7310 : : if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7311 : : goto error;
7312 : :
7313 : : slave_fd = _Py_open(slave_name, O_RDWR);
7314 : : if (slave_fd < 0)
7315 : : goto error;
7316 : :
7317 : : #else
7318 : : master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
7319 : : if (master_fd < 0)
7320 : : goto posix_error;
7321 : :
7322 : : sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
7323 : :
7324 : : /* change permission of slave */
7325 : : if (grantpt(master_fd) < 0) {
7326 : : PyOS_setsig(SIGCHLD, sig_saved);
7327 : : goto posix_error;
7328 : : }
7329 : :
7330 : : /* unlock slave */
7331 : : if (unlockpt(master_fd) < 0) {
7332 : : PyOS_setsig(SIGCHLD, sig_saved);
7333 : : goto posix_error;
7334 : : }
7335 : :
7336 : : PyOS_setsig(SIGCHLD, sig_saved);
7337 : :
7338 : : slave_name = ptsname(master_fd); /* get name of slave */
7339 : : if (slave_name == NULL)
7340 : : goto posix_error;
7341 : :
7342 : : slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
7343 : : if (slave_fd == -1)
7344 : : goto error;
7345 : :
7346 : : if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7347 : : goto posix_error;
7348 : :
7349 : : #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
7350 : : ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
7351 : : ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
7352 : : #ifndef __hpux
7353 : : ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
7354 : : #endif /* __hpux */
7355 : : #endif /* HAVE_CYGWIN */
7356 : : #endif /* HAVE_OPENPTY */
7357 : :
7358 : 17 : return Py_BuildValue("(ii)", master_fd, slave_fd);
7359 : :
7360 : 0 : posix_error:
7361 : 0 : posix_error();
7362 : 0 : error:
7363 [ # # ]: 0 : if (master_fd != -1)
7364 : 0 : close(master_fd);
7365 [ # # ]: 0 : if (slave_fd != -1)
7366 : 0 : close(slave_fd);
7367 : 0 : return NULL;
7368 : : }
7369 : : #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
7370 : :
7371 : :
7372 : : #if defined(HAVE_SETSID) && defined(TIOCSCTTY)
7373 : : #define HAVE_FALLBACK_LOGIN_TTY 1
7374 : : #endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
7375 : :
7376 : : #if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
7377 : : /*[clinic input]
7378 : : os.login_tty
7379 : :
7380 : : fd: fildes
7381 : : /
7382 : :
7383 : : Prepare the tty of which fd is a file descriptor for a new login session.
7384 : :
7385 : : Make the calling process a session leader; make the tty the
7386 : : controlling tty, the stdin, the stdout, and the stderr of the
7387 : : calling process; close fd.
7388 : : [clinic start generated code]*/
7389 : :
7390 : : static PyObject *
7391 : 0 : os_login_tty_impl(PyObject *module, int fd)
7392 : : /*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
7393 : : {
7394 : : #ifdef HAVE_LOGIN_TTY
7395 [ # # ]: 0 : if (login_tty(fd) == -1) {
7396 : 0 : return posix_error();
7397 : : }
7398 : : #else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
7399 : : /* Establish a new session. */
7400 : : if (setsid() == -1) {
7401 : : return posix_error();
7402 : : }
7403 : :
7404 : : /* The tty becomes the controlling terminal. */
7405 : : if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
7406 : : return posix_error();
7407 : : }
7408 : :
7409 : : /* The tty becomes stdin/stdout/stderr */
7410 : : if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
7411 : : return posix_error();
7412 : : }
7413 : : if (fd > 2) {
7414 : : close(fd);
7415 : : }
7416 : : #endif /* HAVE_LOGIN_TTY */
7417 : 0 : Py_RETURN_NONE;
7418 : : }
7419 : : #endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
7420 : :
7421 : :
7422 : : #ifdef HAVE_FORKPTY
7423 : : /*[clinic input]
7424 : : os.forkpty
7425 : :
7426 : : Fork a new process with a new pseudo-terminal as controlling tty.
7427 : :
7428 : : Returns a tuple of (pid, master_fd).
7429 : : Like fork(), return pid of 0 to the child process,
7430 : : and pid of child to the parent process.
7431 : : To both, return fd of newly opened pseudo-terminal.
7432 : : [clinic start generated code]*/
7433 : :
7434 : : static PyObject *
7435 : 3 : os_forkpty_impl(PyObject *module)
7436 : : /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
7437 : : {
7438 : 3 : int master_fd = -1;
7439 : : pid_t pid;
7440 : :
7441 [ - + ]: 3 : if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
7442 : 0 : PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
7443 : 0 : return NULL;
7444 : : }
7445 [ - + ]: 3 : if (PySys_Audit("os.forkpty", NULL) < 0) {
7446 : 0 : return NULL;
7447 : : }
7448 : 3 : PyOS_BeforeFork();
7449 : 3 : pid = forkpty(&master_fd, NULL, NULL, NULL);
7450 [ - + ]: 3 : if (pid == 0) {
7451 : : /* child: this clobbers and resets the import lock. */
7452 : 0 : PyOS_AfterFork_Child();
7453 : : } else {
7454 : : /* parent: release the import lock. */
7455 : 3 : PyOS_AfterFork_Parent();
7456 : : }
7457 [ - + ]: 3 : if (pid == -1) {
7458 : 0 : return posix_error();
7459 : : }
7460 : 3 : return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
7461 : : }
7462 : : #endif /* HAVE_FORKPTY */
7463 : :
7464 : :
7465 : : #ifdef HAVE_GETEGID
7466 : : /*[clinic input]
7467 : : os.getegid
7468 : :
7469 : : Return the current process's effective group id.
7470 : : [clinic start generated code]*/
7471 : :
7472 : : static PyObject *
7473 : 2303 : os_getegid_impl(PyObject *module)
7474 : : /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
7475 : : {
7476 : 2303 : return _PyLong_FromGid(getegid());
7477 : : }
7478 : : #endif /* HAVE_GETEGID */
7479 : :
7480 : :
7481 : : #ifdef HAVE_GETEUID
7482 : : /*[clinic input]
7483 : : os.geteuid
7484 : :
7485 : : Return the current process's effective user id.
7486 : : [clinic start generated code]*/
7487 : :
7488 : : static PyObject *
7489 : 2534 : os_geteuid_impl(PyObject *module)
7490 : : /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
7491 : : {
7492 : 2534 : return _PyLong_FromUid(geteuid());
7493 : : }
7494 : : #endif /* HAVE_GETEUID */
7495 : :
7496 : :
7497 : : #ifdef HAVE_GETGID
7498 : : /*[clinic input]
7499 : : os.getgid
7500 : :
7501 : : Return the current process's group id.
7502 : : [clinic start generated code]*/
7503 : :
7504 : : static PyObject *
7505 : 2308 : os_getgid_impl(PyObject *module)
7506 : : /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
7507 : : {
7508 : 2308 : return _PyLong_FromGid(getgid());
7509 : : }
7510 : : #endif /* HAVE_GETGID */
7511 : :
7512 : :
7513 : : #ifdef HAVE_GETPID
7514 : : /*[clinic input]
7515 : : os.getpid
7516 : :
7517 : : Return the current process id.
7518 : : [clinic start generated code]*/
7519 : :
7520 : : static PyObject *
7521 : 414604 : os_getpid_impl(PyObject *module)
7522 : : /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
7523 : : {
7524 : 414604 : return PyLong_FromPid(getpid());
7525 : : }
7526 : : #endif /* HAVE_GETPID */
7527 : :
7528 : : #ifdef NGROUPS_MAX
7529 : : #define MAX_GROUPS NGROUPS_MAX
7530 : : #else
7531 : : /* defined to be 16 on Solaris7, so this should be a small number */
7532 : : #define MAX_GROUPS 64
7533 : : #endif
7534 : :
7535 : : #ifdef HAVE_GETGROUPLIST
7536 : :
7537 : : #ifdef __APPLE__
7538 : : /*[clinic input]
7539 : : os.getgrouplist
7540 : :
7541 : : user: str
7542 : : username to lookup
7543 : : group as basegid: int
7544 : : base group id of the user
7545 : : /
7546 : :
7547 : : Returns a list of groups to which a user belongs.
7548 : : [clinic start generated code]*/
7549 : :
7550 : : static PyObject *
7551 : : os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
7552 : : /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
7553 : : #else
7554 : : /*[clinic input]
7555 : : os.getgrouplist
7556 : :
7557 : : user: str
7558 : : username to lookup
7559 : : group as basegid: gid_t
7560 : : base group id of the user
7561 : : /
7562 : :
7563 : : Returns a list of groups to which a user belongs.
7564 : : [clinic start generated code]*/
7565 : :
7566 : : static PyObject *
7567 : 1 : os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
7568 : : /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
7569 : : #endif
7570 : : {
7571 : : int i, ngroups;
7572 : : PyObject *list;
7573 : : #ifdef __APPLE__
7574 : : int *groups;
7575 : : #else
7576 : : gid_t *groups;
7577 : : #endif
7578 : :
7579 : : /*
7580 : : * NGROUPS_MAX is defined by POSIX.1 as the maximum
7581 : : * number of supplimental groups a users can belong to.
7582 : : * We have to increment it by one because
7583 : : * getgrouplist() returns both the supplemental groups
7584 : : * and the primary group, i.e. all of the groups the
7585 : : * user belongs to.
7586 : : */
7587 : 1 : ngroups = 1 + MAX_GROUPS;
7588 : :
7589 : 0 : while (1) {
7590 : : #ifdef __APPLE__
7591 : : groups = PyMem_New(int, ngroups);
7592 : : #else
7593 [ + - ]: 1 : groups = PyMem_New(gid_t, ngroups);
7594 : : #endif
7595 [ - + ]: 1 : if (groups == NULL) {
7596 : : return PyErr_NoMemory();
7597 : : }
7598 : :
7599 : 1 : int old_ngroups = ngroups;
7600 [ + - ]: 1 : if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
7601 : : /* Success */
7602 : 1 : break;
7603 : : }
7604 : :
7605 : : /* getgrouplist() fails if the group list is too small */
7606 : 0 : PyMem_Free(groups);
7607 : :
7608 [ # # ]: 0 : if (ngroups > old_ngroups) {
7609 : : /* If the group list is too small, the glibc implementation of
7610 : : getgrouplist() sets ngroups to the total number of groups and
7611 : : returns -1. */
7612 : : }
7613 : : else {
7614 : : /* Double the group list size */
7615 [ # # ]: 0 : if (ngroups > INT_MAX / 2) {
7616 : : return PyErr_NoMemory();
7617 : : }
7618 : 0 : ngroups *= 2;
7619 : : }
7620 : :
7621 : : /* Retry getgrouplist() with a larger group list */
7622 : : }
7623 : :
7624 : : #ifdef _Py_MEMORY_SANITIZER
7625 : : /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
7626 : : __msan_unpoison(&ngroups, sizeof(ngroups));
7627 : : __msan_unpoison(groups, ngroups*sizeof(*groups));
7628 : : #endif
7629 : :
7630 : 1 : list = PyList_New(ngroups);
7631 [ - + ]: 1 : if (list == NULL) {
7632 : 0 : PyMem_Free(groups);
7633 : 0 : return NULL;
7634 : : }
7635 : :
7636 [ + + ]: 11 : for (i = 0; i < ngroups; i++) {
7637 : : #ifdef __APPLE__
7638 : : PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7639 : : #else
7640 : 10 : PyObject *o = _PyLong_FromGid(groups[i]);
7641 : : #endif
7642 [ - + ]: 10 : if (o == NULL) {
7643 : 0 : Py_DECREF(list);
7644 : 0 : PyMem_Free(groups);
7645 : 0 : return NULL;
7646 : : }
7647 : 10 : PyList_SET_ITEM(list, i, o);
7648 : : }
7649 : :
7650 : 1 : PyMem_Free(groups);
7651 : :
7652 : 1 : return list;
7653 : : }
7654 : : #endif /* HAVE_GETGROUPLIST */
7655 : :
7656 : :
7657 : : #ifdef HAVE_GETGROUPS
7658 : : /*[clinic input]
7659 : : os.getgroups
7660 : :
7661 : : Return list of supplemental group IDs for the process.
7662 : : [clinic start generated code]*/
7663 : :
7664 : : static PyObject *
7665 : 6 : os_getgroups_impl(PyObject *module)
7666 : : /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
7667 : : {
7668 : : // Call getgroups with length 0 to get the actual number of groups
7669 : 6 : int n = getgroups(0, NULL);
7670 [ - + ]: 6 : if (n < 0) {
7671 : 0 : return posix_error();
7672 : : }
7673 : :
7674 [ - + ]: 6 : if (n == 0) {
7675 : 0 : return PyList_New(0);
7676 : : }
7677 : :
7678 [ + - ]: 6 : gid_t *grouplist = PyMem_New(gid_t, n);
7679 [ - + ]: 6 : if (grouplist == NULL) {
7680 : : return PyErr_NoMemory();
7681 : : }
7682 : :
7683 : 6 : n = getgroups(n, grouplist);
7684 [ - + ]: 6 : if (n == -1) {
7685 : 0 : PyMem_Free(grouplist);
7686 : 0 : return posix_error();
7687 : : }
7688 : :
7689 : 6 : PyObject *result = PyList_New(n);
7690 [ - + ]: 6 : if (result == NULL) {
7691 : 0 : goto error;
7692 : : }
7693 : :
7694 [ + + ]: 66 : for (int i = 0; i < n; ++i) {
7695 : 60 : PyObject *group = _PyLong_FromGid(grouplist[i]);
7696 [ - + ]: 60 : if (group == NULL) {
7697 : 0 : goto error;
7698 : : }
7699 : 60 : PyList_SET_ITEM(result, i, group);
7700 : : }
7701 : 6 : PyMem_Free(grouplist);
7702 : :
7703 : 6 : return result;
7704 : :
7705 : 0 : error:
7706 : 0 : PyMem_Free(grouplist);
7707 : 0 : Py_XDECREF(result);
7708 : 0 : return NULL;
7709 : : }
7710 : : #endif /* HAVE_GETGROUPS */
7711 : :
7712 : : #ifdef HAVE_INITGROUPS
7713 : : #ifdef __APPLE__
7714 : : /*[clinic input]
7715 : : os.initgroups
7716 : :
7717 : : username as oname: FSConverter
7718 : : gid: int
7719 : : /
7720 : :
7721 : : Initialize the group access list.
7722 : :
7723 : : Call the system initgroups() to initialize the group access list with all of
7724 : : the groups of which the specified username is a member, plus the specified
7725 : : group id.
7726 : : [clinic start generated code]*/
7727 : :
7728 : : static PyObject *
7729 : : os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
7730 : : /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
7731 : : #else
7732 : : /*[clinic input]
7733 : : os.initgroups
7734 : :
7735 : : username as oname: FSConverter
7736 : : gid: gid_t
7737 : : /
7738 : :
7739 : : Initialize the group access list.
7740 : :
7741 : : Call the system initgroups() to initialize the group access list with all of
7742 : : the groups of which the specified username is a member, plus the specified
7743 : : group id.
7744 : : [clinic start generated code]*/
7745 : :
7746 : : static PyObject *
7747 : 1 : os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
7748 : : /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
7749 : : #endif
7750 : : {
7751 : 1 : const char *username = PyBytes_AS_STRING(oname);
7752 : :
7753 [ + - ]: 1 : if (initgroups(username, gid) == -1)
7754 : 1 : return PyErr_SetFromErrno(PyExc_OSError);
7755 : :
7756 : 0 : Py_RETURN_NONE;
7757 : : }
7758 : : #endif /* HAVE_INITGROUPS */
7759 : :
7760 : :
7761 : : #ifdef HAVE_GETPGID
7762 : : /*[clinic input]
7763 : : os.getpgid
7764 : :
7765 : : pid: pid_t
7766 : :
7767 : : Call the system call getpgid(), and return the result.
7768 : : [clinic start generated code]*/
7769 : :
7770 : : static PyObject *
7771 : 2 : os_getpgid_impl(PyObject *module, pid_t pid)
7772 : : /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7773 : : {
7774 : 2 : pid_t pgid = getpgid(pid);
7775 [ - + ]: 2 : if (pgid < 0)
7776 : 0 : return posix_error();
7777 : 2 : return PyLong_FromPid(pgid);
7778 : : }
7779 : : #endif /* HAVE_GETPGID */
7780 : :
7781 : :
7782 : : #ifdef HAVE_GETPGRP
7783 : : /*[clinic input]
7784 : : os.getpgrp
7785 : :
7786 : : Return the current process group id.
7787 : : [clinic start generated code]*/
7788 : :
7789 : : static PyObject *
7790 : 3 : os_getpgrp_impl(PyObject *module)
7791 : : /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7792 : : {
7793 : : #ifdef GETPGRP_HAVE_ARG
7794 : : return PyLong_FromPid(getpgrp(0));
7795 : : #else /* GETPGRP_HAVE_ARG */
7796 : 3 : return PyLong_FromPid(getpgrp());
7797 : : #endif /* GETPGRP_HAVE_ARG */
7798 : : }
7799 : : #endif /* HAVE_GETPGRP */
7800 : :
7801 : :
7802 : : #ifdef HAVE_SETPGRP
7803 : : /*[clinic input]
7804 : : os.setpgrp
7805 : :
7806 : : Make the current process the leader of its process group.
7807 : : [clinic start generated code]*/
7808 : :
7809 : : static PyObject *
7810 : 0 : os_setpgrp_impl(PyObject *module)
7811 : : /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7812 : : {
7813 : : #ifdef SETPGRP_HAVE_ARG
7814 : : if (setpgrp(0, 0) < 0)
7815 : : #else /* SETPGRP_HAVE_ARG */
7816 [ # # ]: 0 : if (setpgrp() < 0)
7817 : : #endif /* SETPGRP_HAVE_ARG */
7818 : 0 : return posix_error();
7819 : 0 : Py_RETURN_NONE;
7820 : : }
7821 : : #endif /* HAVE_SETPGRP */
7822 : :
7823 : : #ifdef HAVE_GETPPID
7824 : :
7825 : : #ifdef MS_WINDOWS
7826 : : #include <tlhelp32.h>
7827 : :
7828 : : static PyObject*
7829 : : win32_getppid()
7830 : : {
7831 : : HANDLE snapshot;
7832 : : pid_t mypid;
7833 : : PyObject* result = NULL;
7834 : : BOOL have_record;
7835 : : PROCESSENTRY32 pe;
7836 : :
7837 : : mypid = getpid(); /* This function never fails */
7838 : :
7839 : : snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7840 : : if (snapshot == INVALID_HANDLE_VALUE)
7841 : : return PyErr_SetFromWindowsErr(GetLastError());
7842 : :
7843 : : pe.dwSize = sizeof(pe);
7844 : : have_record = Process32First(snapshot, &pe);
7845 : : while (have_record) {
7846 : : if (mypid == (pid_t)pe.th32ProcessID) {
7847 : : /* We could cache the ulong value in a static variable. */
7848 : : result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7849 : : break;
7850 : : }
7851 : :
7852 : : have_record = Process32Next(snapshot, &pe);
7853 : : }
7854 : :
7855 : : /* If our loop exits and our pid was not found (result will be NULL)
7856 : : * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7857 : : * error anyway, so let's raise it. */
7858 : : if (!result)
7859 : : result = PyErr_SetFromWindowsErr(GetLastError());
7860 : :
7861 : : CloseHandle(snapshot);
7862 : :
7863 : : return result;
7864 : : }
7865 : : #endif /*MS_WINDOWS*/
7866 : :
7867 : :
7868 : : /*[clinic input]
7869 : : os.getppid
7870 : :
7871 : : Return the parent's process id.
7872 : :
7873 : : If the parent process has already exited, Windows machines will still
7874 : : return its id; others systems will return the id of the 'init' process (1).
7875 : : [clinic start generated code]*/
7876 : :
7877 : : static PyObject *
7878 : 7 : os_getppid_impl(PyObject *module)
7879 : : /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7880 : : {
7881 : : #ifdef MS_WINDOWS
7882 : : return win32_getppid();
7883 : : #else
7884 : 7 : return PyLong_FromPid(getppid());
7885 : : #endif
7886 : : }
7887 : : #endif /* HAVE_GETPPID */
7888 : :
7889 : :
7890 : : #ifdef HAVE_GETLOGIN
7891 : : /*[clinic input]
7892 : : os.getlogin
7893 : :
7894 : : Return the actual login name.
7895 : : [clinic start generated code]*/
7896 : :
7897 : : static PyObject *
7898 : 0 : os_getlogin_impl(PyObject *module)
7899 : : /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7900 : : {
7901 : 0 : PyObject *result = NULL;
7902 : : #ifdef MS_WINDOWS
7903 : : wchar_t user_name[UNLEN + 1];
7904 : : DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7905 : :
7906 : : if (GetUserNameW(user_name, &num_chars)) {
7907 : : /* num_chars is the number of unicode chars plus null terminator */
7908 : : result = PyUnicode_FromWideChar(user_name, num_chars - 1);
7909 : : }
7910 : : else
7911 : : result = PyErr_SetFromWindowsErr(GetLastError());
7912 : : #else
7913 : : char *name;
7914 : 0 : int old_errno = errno;
7915 : :
7916 : 0 : errno = 0;
7917 : 0 : name = getlogin();
7918 [ # # ]: 0 : if (name == NULL) {
7919 [ # # ]: 0 : if (errno)
7920 : 0 : posix_error();
7921 : : else
7922 : 0 : PyErr_SetString(PyExc_OSError, "unable to determine login name");
7923 : : }
7924 : : else
7925 : 0 : result = PyUnicode_DecodeFSDefault(name);
7926 : 0 : errno = old_errno;
7927 : : #endif
7928 : 0 : return result;
7929 : : }
7930 : : #endif /* HAVE_GETLOGIN */
7931 : :
7932 : :
7933 : : #ifdef HAVE_GETUID
7934 : : /*[clinic input]
7935 : : os.getuid
7936 : :
7937 : : Return the current process's user id.
7938 : : [clinic start generated code]*/
7939 : :
7940 : : static PyObject *
7941 : 2349 : os_getuid_impl(PyObject *module)
7942 : : /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7943 : : {
7944 : 2349 : return _PyLong_FromUid(getuid());
7945 : : }
7946 : : #endif /* HAVE_GETUID */
7947 : :
7948 : :
7949 : : #ifdef MS_WINDOWS
7950 : : #define HAVE_KILL
7951 : : #endif /* MS_WINDOWS */
7952 : :
7953 : : #ifdef HAVE_KILL
7954 : : /*[clinic input]
7955 : : os.kill
7956 : :
7957 : : pid: pid_t
7958 : : signal: Py_ssize_t
7959 : : /
7960 : :
7961 : : Kill a process with a signal.
7962 : : [clinic start generated code]*/
7963 : :
7964 : : static PyObject *
7965 : 15928 : os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
7966 : : /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
7967 : : {
7968 [ - + ]: 15928 : if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
7969 : 0 : return NULL;
7970 : : }
7971 : : #ifndef MS_WINDOWS
7972 [ + + ]: 15928 : if (kill(pid, (int)signal) == -1) {
7973 : 11 : return posix_error();
7974 : : }
7975 : :
7976 : : // Check immediately if the signal was sent to the current process.
7977 : : // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
7978 : : // is cheap.
7979 [ + + ]: 15917 : if (PyErr_CheckSignals()) {
7980 : 95 : return NULL;
7981 : : }
7982 : :
7983 : 15822 : Py_RETURN_NONE;
7984 : : #else /* !MS_WINDOWS */
7985 : : PyObject *result;
7986 : : DWORD sig = (DWORD)signal;
7987 : : DWORD err;
7988 : : HANDLE handle;
7989 : :
7990 : : /* Console processes which share a common console can be sent CTRL+C or
7991 : : CTRL+BREAK events, provided they handle said events. */
7992 : : if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
7993 : : if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
7994 : : err = GetLastError();
7995 : : PyErr_SetFromWindowsErr(err);
7996 : : }
7997 : : else
7998 : : Py_RETURN_NONE;
7999 : : }
8000 : :
8001 : : /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
8002 : : attempt to open and terminate the process. */
8003 : : handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
8004 : : if (handle == NULL) {
8005 : : err = GetLastError();
8006 : : return PyErr_SetFromWindowsErr(err);
8007 : : }
8008 : :
8009 : : if (TerminateProcess(handle, sig) == 0) {
8010 : : err = GetLastError();
8011 : : result = PyErr_SetFromWindowsErr(err);
8012 : : } else {
8013 : : Py_INCREF(Py_None);
8014 : : result = Py_None;
8015 : : }
8016 : :
8017 : : CloseHandle(handle);
8018 : : return result;
8019 : : #endif /* !MS_WINDOWS */
8020 : : }
8021 : : #endif /* HAVE_KILL */
8022 : :
8023 : :
8024 : : #ifdef HAVE_KILLPG
8025 : : /*[clinic input]
8026 : : os.killpg
8027 : :
8028 : : pgid: pid_t
8029 : : signal: int
8030 : : /
8031 : :
8032 : : Kill a process group with a signal.
8033 : : [clinic start generated code]*/
8034 : :
8035 : : static PyObject *
8036 : 1 : os_killpg_impl(PyObject *module, pid_t pgid, int signal)
8037 : : /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
8038 : : {
8039 [ - + ]: 1 : if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
8040 : 0 : return NULL;
8041 : : }
8042 : : /* XXX some man pages make the `pgid` parameter an int, others
8043 : : a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
8044 : : take the same type. Moreover, pid_t is always at least as wide as
8045 : : int (else compilation of this module fails), which is safe. */
8046 [ - + ]: 1 : if (killpg(pgid, signal) == -1)
8047 : 0 : return posix_error();
8048 : 1 : Py_RETURN_NONE;
8049 : : }
8050 : : #endif /* HAVE_KILLPG */
8051 : :
8052 : :
8053 : : #ifdef HAVE_PLOCK
8054 : : #ifdef HAVE_SYS_LOCK_H
8055 : : #include <sys/lock.h>
8056 : : #endif
8057 : :
8058 : : /*[clinic input]
8059 : : os.plock
8060 : : op: int
8061 : : /
8062 : :
8063 : : Lock program segments into memory.");
8064 : : [clinic start generated code]*/
8065 : :
8066 : : static PyObject *
8067 : : os_plock_impl(PyObject *module, int op)
8068 : : /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
8069 : : {
8070 : : if (plock(op) == -1)
8071 : : return posix_error();
8072 : : Py_RETURN_NONE;
8073 : : }
8074 : : #endif /* HAVE_PLOCK */
8075 : :
8076 : :
8077 : : #ifdef HAVE_SETUID
8078 : : /*[clinic input]
8079 : : os.setuid
8080 : :
8081 : : uid: uid_t
8082 : : /
8083 : :
8084 : : Set the current process's user id.
8085 : : [clinic start generated code]*/
8086 : :
8087 : : static PyObject *
8088 : 1 : os_setuid_impl(PyObject *module, uid_t uid)
8089 : : /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
8090 : : {
8091 [ + - ]: 1 : if (setuid(uid) < 0)
8092 : 1 : return posix_error();
8093 : 0 : Py_RETURN_NONE;
8094 : : }
8095 : : #endif /* HAVE_SETUID */
8096 : :
8097 : :
8098 : : #ifdef HAVE_SETEUID
8099 : : /*[clinic input]
8100 : : os.seteuid
8101 : :
8102 : : euid: uid_t
8103 : : /
8104 : :
8105 : : Set the current process's effective user id.
8106 : : [clinic start generated code]*/
8107 : :
8108 : : static PyObject *
8109 : 1 : os_seteuid_impl(PyObject *module, uid_t euid)
8110 : : /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
8111 : : {
8112 [ + - ]: 1 : if (seteuid(euid) < 0)
8113 : 1 : return posix_error();
8114 : 0 : Py_RETURN_NONE;
8115 : : }
8116 : : #endif /* HAVE_SETEUID */
8117 : :
8118 : :
8119 : : #ifdef HAVE_SETEGID
8120 : : /*[clinic input]
8121 : : os.setegid
8122 : :
8123 : : egid: gid_t
8124 : : /
8125 : :
8126 : : Set the current process's effective group id.
8127 : : [clinic start generated code]*/
8128 : :
8129 : : static PyObject *
8130 : 1 : os_setegid_impl(PyObject *module, gid_t egid)
8131 : : /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
8132 : : {
8133 [ + - ]: 1 : if (setegid(egid) < 0)
8134 : 1 : return posix_error();
8135 : 0 : Py_RETURN_NONE;
8136 : : }
8137 : : #endif /* HAVE_SETEGID */
8138 : :
8139 : :
8140 : : #ifdef HAVE_SETREUID
8141 : : /*[clinic input]
8142 : : os.setreuid
8143 : :
8144 : : ruid: uid_t
8145 : : euid: uid_t
8146 : : /
8147 : :
8148 : : Set the current process's real and effective user ids.
8149 : : [clinic start generated code]*/
8150 : :
8151 : : static PyObject *
8152 : 2 : os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
8153 : : /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
8154 : : {
8155 [ + + ]: 2 : if (setreuid(ruid, euid) < 0) {
8156 : 1 : return posix_error();
8157 : : } else {
8158 : 1 : Py_RETURN_NONE;
8159 : : }
8160 : : }
8161 : : #endif /* HAVE_SETREUID */
8162 : :
8163 : :
8164 : : #ifdef HAVE_SETREGID
8165 : : /*[clinic input]
8166 : : os.setregid
8167 : :
8168 : : rgid: gid_t
8169 : : egid: gid_t
8170 : : /
8171 : :
8172 : : Set the current process's real and effective group ids.
8173 : : [clinic start generated code]*/
8174 : :
8175 : : static PyObject *
8176 : 2 : os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
8177 : : /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
8178 : : {
8179 [ + + ]: 2 : if (setregid(rgid, egid) < 0)
8180 : 1 : return posix_error();
8181 : 1 : Py_RETURN_NONE;
8182 : : }
8183 : : #endif /* HAVE_SETREGID */
8184 : :
8185 : :
8186 : : #ifdef HAVE_SETGID
8187 : : /*[clinic input]
8188 : : os.setgid
8189 : : gid: gid_t
8190 : : /
8191 : :
8192 : : Set the current process's group id.
8193 : : [clinic start generated code]*/
8194 : :
8195 : : static PyObject *
8196 : 1 : os_setgid_impl(PyObject *module, gid_t gid)
8197 : : /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
8198 : : {
8199 [ + - ]: 1 : if (setgid(gid) < 0)
8200 : 1 : return posix_error();
8201 : 0 : Py_RETURN_NONE;
8202 : : }
8203 : : #endif /* HAVE_SETGID */
8204 : :
8205 : :
8206 : : #ifdef HAVE_SETGROUPS
8207 : : /*[clinic input]
8208 : : os.setgroups
8209 : :
8210 : : groups: object
8211 : : /
8212 : :
8213 : : Set the groups of the current process to list.
8214 : : [clinic start generated code]*/
8215 : :
8216 : : static PyObject *
8217 : 0 : os_setgroups(PyObject *module, PyObject *groups)
8218 : : /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
8219 : : {
8220 [ # # ]: 0 : if (!PySequence_Check(groups)) {
8221 : 0 : PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
8222 : 0 : return NULL;
8223 : : }
8224 : 0 : Py_ssize_t len = PySequence_Size(groups);
8225 [ # # ]: 0 : if (len < 0) {
8226 : 0 : return NULL;
8227 : : }
8228 [ # # ]: 0 : if (len > MAX_GROUPS) {
8229 : 0 : PyErr_SetString(PyExc_ValueError, "too many groups");
8230 : 0 : return NULL;
8231 : : }
8232 : :
8233 [ # # ]: 0 : gid_t *grouplist = PyMem_New(gid_t, len);
8234 [ # # ]: 0 : for (Py_ssize_t i = 0; i < len; i++) {
8235 : : PyObject *elem;
8236 : 0 : elem = PySequence_GetItem(groups, i);
8237 [ # # ]: 0 : if (!elem) {
8238 : 0 : PyMem_Free(grouplist);
8239 : 0 : return NULL;
8240 : : }
8241 [ # # ]: 0 : if (!PyLong_Check(elem)) {
8242 : 0 : PyErr_SetString(PyExc_TypeError,
8243 : : "groups must be integers");
8244 : 0 : Py_DECREF(elem);
8245 : 0 : PyMem_Free(grouplist);
8246 : 0 : return NULL;
8247 : : } else {
8248 [ # # ]: 0 : if (!_Py_Gid_Converter(elem, &grouplist[i])) {
8249 : 0 : Py_DECREF(elem);
8250 : 0 : PyMem_Free(grouplist);
8251 : 0 : return NULL;
8252 : : }
8253 : : }
8254 : 0 : Py_DECREF(elem);
8255 : : }
8256 : :
8257 [ # # ]: 0 : if (setgroups(len, grouplist) < 0) {
8258 : 0 : PyMem_Free(grouplist);
8259 : 0 : return posix_error();
8260 : : }
8261 : 0 : PyMem_Free(grouplist);
8262 : 0 : Py_RETURN_NONE;
8263 : : }
8264 : : #endif /* HAVE_SETGROUPS */
8265 : :
8266 : : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
8267 : : static PyObject *
8268 : 23 : wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
8269 : : {
8270 : : PyObject *result;
8271 : : PyObject *struct_rusage;
8272 : :
8273 [ - + ]: 23 : if (pid == -1)
8274 : 0 : return posix_error();
8275 : :
8276 : : // If wait succeeded but no child was ready to report status, ru will not
8277 : : // have been populated.
8278 [ + + ]: 23 : if (pid == 0) {
8279 : 17 : memset(ru, 0, sizeof(*ru));
8280 : : }
8281 : :
8282 : 23 : struct_rusage = _PyImport_GetModuleAttrString("resource", "struct_rusage");
8283 [ - + ]: 23 : if (struct_rusage == NULL)
8284 : 0 : return NULL;
8285 : :
8286 : : /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
8287 : 23 : result = PyStructSequence_New((PyTypeObject*) struct_rusage);
8288 : 23 : Py_DECREF(struct_rusage);
8289 [ - + ]: 23 : if (!result)
8290 : 0 : return NULL;
8291 : :
8292 : : #ifndef doubletime
8293 : : #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
8294 : : #endif
8295 : :
8296 : 23 : PyStructSequence_SET_ITEM(result, 0,
8297 : : PyFloat_FromDouble(doubletime(ru->ru_utime)));
8298 : 23 : PyStructSequence_SET_ITEM(result, 1,
8299 : : PyFloat_FromDouble(doubletime(ru->ru_stime)));
8300 : : #define SET_INT(result, index, value)\
8301 : : PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
8302 : 23 : SET_INT(result, 2, ru->ru_maxrss);
8303 : 23 : SET_INT(result, 3, ru->ru_ixrss);
8304 : 23 : SET_INT(result, 4, ru->ru_idrss);
8305 : 23 : SET_INT(result, 5, ru->ru_isrss);
8306 : 23 : SET_INT(result, 6, ru->ru_minflt);
8307 : 23 : SET_INT(result, 7, ru->ru_majflt);
8308 : 23 : SET_INT(result, 8, ru->ru_nswap);
8309 : 23 : SET_INT(result, 9, ru->ru_inblock);
8310 : 23 : SET_INT(result, 10, ru->ru_oublock);
8311 : 23 : SET_INT(result, 11, ru->ru_msgsnd);
8312 : 23 : SET_INT(result, 12, ru->ru_msgrcv);
8313 : 23 : SET_INT(result, 13, ru->ru_nsignals);
8314 : 23 : SET_INT(result, 14, ru->ru_nvcsw);
8315 : 23 : SET_INT(result, 15, ru->ru_nivcsw);
8316 : : #undef SET_INT
8317 : :
8318 [ - + ]: 23 : if (PyErr_Occurred()) {
8319 : 0 : Py_DECREF(result);
8320 : 0 : return NULL;
8321 : : }
8322 : :
8323 : 23 : return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
8324 : : }
8325 : : #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
8326 : :
8327 : :
8328 : : #ifdef HAVE_WAIT3
8329 : : /*[clinic input]
8330 : : os.wait3
8331 : :
8332 : : options: int
8333 : : Wait for completion of a child process.
8334 : :
8335 : : Returns a tuple of information about the child process:
8336 : : (pid, status, rusage)
8337 : : [clinic start generated code]*/
8338 : :
8339 : : static PyObject *
8340 : 13 : os_wait3_impl(PyObject *module, int options)
8341 : : /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
8342 : : {
8343 : : pid_t pid;
8344 : : struct rusage ru;
8345 : 13 : int async_err = 0;
8346 : : WAIT_TYPE status;
8347 : 13 : WAIT_STATUS_INT(status) = 0;
8348 : :
8349 : : do {
8350 : 22 : Py_BEGIN_ALLOW_THREADS
8351 : 22 : pid = wait3(&status, options, &ru);
8352 : 22 : Py_END_ALLOW_THREADS
8353 [ + + + - : 22 : } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ - ]
8354 [ - + ]: 13 : if (pid < 0)
8355 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
8356 : :
8357 : 13 : return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
8358 : : }
8359 : : #endif /* HAVE_WAIT3 */
8360 : :
8361 : :
8362 : : #ifdef HAVE_WAIT4
8363 : : /*[clinic input]
8364 : :
8365 : : os.wait4
8366 : :
8367 : : pid: pid_t
8368 : : options: int
8369 : :
8370 : : Wait for completion of a specific child process.
8371 : :
8372 : : Returns a tuple of information about the child process:
8373 : : (pid, status, rusage)
8374 : : [clinic start generated code]*/
8375 : :
8376 : : static PyObject *
8377 : 10 : os_wait4_impl(PyObject *module, pid_t pid, int options)
8378 : : /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
8379 : : {
8380 : : pid_t res;
8381 : : struct rusage ru;
8382 : 10 : int async_err = 0;
8383 : : WAIT_TYPE status;
8384 : 10 : WAIT_STATUS_INT(status) = 0;
8385 : :
8386 : : do {
8387 : 16 : Py_BEGIN_ALLOW_THREADS
8388 : 16 : res = wait4(pid, &status, options, &ru);
8389 : 16 : Py_END_ALLOW_THREADS
8390 [ + + + - : 16 : } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ - ]
8391 [ - + ]: 10 : if (res < 0)
8392 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
8393 : :
8394 : 10 : return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
8395 : : }
8396 : : #endif /* HAVE_WAIT4 */
8397 : :
8398 : :
8399 : : #if defined(HAVE_WAITID) && !defined(__APPLE__)
8400 : : /*[clinic input]
8401 : : os.waitid
8402 : :
8403 : : idtype: idtype_t
8404 : : Must be one of be P_PID, P_PGID or P_ALL.
8405 : : id: id_t
8406 : : The id to wait on.
8407 : : options: int
8408 : : Constructed from the ORing of one or more of WEXITED, WSTOPPED
8409 : : or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
8410 : : /
8411 : :
8412 : : Returns the result of waiting for a process or processes.
8413 : :
8414 : : Returns either waitid_result or None if WNOHANG is specified and there are
8415 : : no children in a waitable state.
8416 : : [clinic start generated code]*/
8417 : :
8418 : : static PyObject *
8419 : 1 : os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
8420 : : /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
8421 : : {
8422 : : PyObject *result;
8423 : : int res;
8424 : 1 : int async_err = 0;
8425 : : siginfo_t si;
8426 : 1 : si.si_pid = 0;
8427 : :
8428 : : do {
8429 : 1 : Py_BEGIN_ALLOW_THREADS
8430 : 1 : res = waitid(idtype, id, &si, options);
8431 : 1 : Py_END_ALLOW_THREADS
8432 [ - + - - : 1 : } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
8433 [ - + ]: 1 : if (res < 0)
8434 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
8435 : :
8436 [ - + ]: 1 : if (si.si_pid == 0)
8437 : 0 : Py_RETURN_NONE;
8438 : :
8439 : 1 : PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
8440 : 1 : result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
8441 [ - + ]: 1 : if (!result)
8442 : 0 : return NULL;
8443 : :
8444 : 1 : PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
8445 : 1 : PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
8446 : 1 : PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
8447 : 1 : PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
8448 : 1 : PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
8449 [ - + ]: 1 : if (PyErr_Occurred()) {
8450 : 0 : Py_DECREF(result);
8451 : 0 : return NULL;
8452 : : }
8453 : :
8454 : 1 : return result;
8455 : : }
8456 : : #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
8457 : :
8458 : :
8459 : : #if defined(HAVE_WAITPID)
8460 : : /*[clinic input]
8461 : : os.waitpid
8462 : : pid: pid_t
8463 : : options: int
8464 : : /
8465 : :
8466 : : Wait for completion of a given child process.
8467 : :
8468 : : Returns a tuple of information regarding the child process:
8469 : : (pid, status)
8470 : :
8471 : : The options argument is ignored on Windows.
8472 : : [clinic start generated code]*/
8473 : :
8474 : : static PyObject *
8475 : 44251 : os_waitpid_impl(PyObject *module, pid_t pid, int options)
8476 : : /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
8477 : : {
8478 : : pid_t res;
8479 : 44251 : int async_err = 0;
8480 : : WAIT_TYPE status;
8481 : 44251 : WAIT_STATUS_INT(status) = 0;
8482 : :
8483 : : do {
8484 : 44280 : Py_BEGIN_ALLOW_THREADS
8485 : 44280 : res = waitpid(pid, &status, options);
8486 : 44280 : Py_END_ALLOW_THREADS
8487 [ + + + + : 44280 : } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ + ]
8488 [ + + ]: 44251 : if (res < 0)
8489 [ + + ]: 3632 : return (!async_err) ? posix_error() : NULL;
8490 : :
8491 : 40619 : return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
8492 : : }
8493 : : #elif defined(HAVE_CWAIT)
8494 : : /* MS C has a variant of waitpid() that's usable for most purposes. */
8495 : : /*[clinic input]
8496 : : os.waitpid
8497 : : pid: intptr_t
8498 : : options: int
8499 : : /
8500 : :
8501 : : Wait for completion of a given process.
8502 : :
8503 : : Returns a tuple of information regarding the process:
8504 : : (pid, status << 8)
8505 : :
8506 : : The options argument is ignored on Windows.
8507 : : [clinic start generated code]*/
8508 : :
8509 : : static PyObject *
8510 : : os_waitpid_impl(PyObject *module, intptr_t pid, int options)
8511 : : /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
8512 : : {
8513 : : int status;
8514 : : intptr_t res;
8515 : : int async_err = 0;
8516 : :
8517 : : do {
8518 : : Py_BEGIN_ALLOW_THREADS
8519 : : _Py_BEGIN_SUPPRESS_IPH
8520 : : res = _cwait(&status, pid, options);
8521 : : _Py_END_SUPPRESS_IPH
8522 : : Py_END_ALLOW_THREADS
8523 : : } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8524 : : if (res < 0)
8525 : : return (!async_err) ? posix_error() : NULL;
8526 : :
8527 : : unsigned long long ustatus = (unsigned int)status;
8528 : :
8529 : : /* shift the status left a byte so this is more like the POSIX waitpid */
8530 : : return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
8531 : : }
8532 : : #endif
8533 : :
8534 : :
8535 : : #ifdef HAVE_WAIT
8536 : : /*[clinic input]
8537 : : os.wait
8538 : :
8539 : : Wait for completion of a child process.
8540 : :
8541 : : Returns a tuple of information about the child process:
8542 : : (pid, status)
8543 : : [clinic start generated code]*/
8544 : :
8545 : : static PyObject *
8546 : 4 : os_wait_impl(PyObject *module)
8547 : : /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
8548 : : {
8549 : : pid_t pid;
8550 : 4 : int async_err = 0;
8551 : : WAIT_TYPE status;
8552 : 4 : WAIT_STATUS_INT(status) = 0;
8553 : :
8554 : : do {
8555 : 12 : Py_BEGIN_ALLOW_THREADS
8556 : 12 : pid = wait(&status);
8557 : 12 : Py_END_ALLOW_THREADS
8558 [ + + + - : 12 : } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ - ]
8559 [ - + ]: 4 : if (pid < 0)
8560 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
8561 : :
8562 : 4 : return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
8563 : : }
8564 : : #endif /* HAVE_WAIT */
8565 : :
8566 : : #if defined(__linux__) && defined(__NR_pidfd_open)
8567 : : /*[clinic input]
8568 : : os.pidfd_open
8569 : : pid: pid_t
8570 : : flags: unsigned_int = 0
8571 : :
8572 : : Return a file descriptor referring to the process *pid*.
8573 : :
8574 : : The descriptor can be used to perform process management without races and
8575 : : signals.
8576 : : [clinic start generated code]*/
8577 : :
8578 : : static PyObject *
8579 : 26 : os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
8580 : : /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
8581 : : {
8582 : 26 : int fd = syscall(__NR_pidfd_open, pid, flags);
8583 [ + + ]: 26 : if (fd < 0) {
8584 : 1 : return posix_error();
8585 : : }
8586 : 25 : return PyLong_FromLong(fd);
8587 : : }
8588 : : #endif
8589 : :
8590 : :
8591 : : #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
8592 : : /*[clinic input]
8593 : : os.readlink
8594 : :
8595 : : path: path_t
8596 : : *
8597 : : dir_fd: dir_fd(requires='readlinkat') = None
8598 : :
8599 : : Return a string representing the path to which the symbolic link points.
8600 : :
8601 : : If dir_fd is not None, it should be a file descriptor open to a directory,
8602 : : and path should be relative; path will then be relative to that directory.
8603 : :
8604 : : dir_fd may not be implemented on your platform. If it is unavailable,
8605 : : using it will raise a NotImplementedError.
8606 : : [clinic start generated code]*/
8607 : :
8608 : : static PyObject *
8609 : 885 : os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
8610 : : /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
8611 : : {
8612 : : #if defined(HAVE_READLINK)
8613 : : char buffer[MAXPATHLEN+1];
8614 : : ssize_t length;
8615 : : #ifdef HAVE_READLINKAT
8616 : 885 : int readlinkat_unavailable = 0;
8617 : : #endif
8618 : :
8619 : 885 : Py_BEGIN_ALLOW_THREADS
8620 : : #ifdef HAVE_READLINKAT
8621 [ + + ]: 885 : if (dir_fd != DEFAULT_DIR_FD) {
8622 : : if (HAVE_READLINKAT_RUNTIME) {
8623 : 1 : length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
8624 : : } else {
8625 : : readlinkat_unavailable = 1;
8626 : : }
8627 : : } else
8628 : : #endif
8629 : 884 : length = readlink(path->narrow, buffer, MAXPATHLEN);
8630 : 885 : Py_END_ALLOW_THREADS
8631 : :
8632 : : #ifdef HAVE_READLINKAT
8633 [ - + ]: 885 : if (readlinkat_unavailable) {
8634 : 0 : argument_unavailable_error(NULL, "dir_fd");
8635 : 0 : return NULL;
8636 : : }
8637 : : #endif
8638 : :
8639 [ + + ]: 885 : if (length < 0) {
8640 : 11 : return path_error(path);
8641 : : }
8642 : 874 : buffer[length] = '\0';
8643 : :
8644 [ + + ]: 874 : if (PyUnicode_Check(path->object))
8645 : 872 : return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
8646 : : else
8647 : 2 : return PyBytes_FromStringAndSize(buffer, length);
8648 : : #elif defined(MS_WINDOWS)
8649 : : DWORD n_bytes_returned;
8650 : : DWORD io_result = 0;
8651 : : HANDLE reparse_point_handle;
8652 : : char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
8653 : : _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
8654 : : PyObject *result = NULL;
8655 : :
8656 : : /* First get a handle to the reparse point */
8657 : : Py_BEGIN_ALLOW_THREADS
8658 : : reparse_point_handle = CreateFileW(
8659 : : path->wide,
8660 : : 0,
8661 : : 0,
8662 : : 0,
8663 : : OPEN_EXISTING,
8664 : : FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
8665 : : 0);
8666 : : if (reparse_point_handle != INVALID_HANDLE_VALUE) {
8667 : : /* New call DeviceIoControl to read the reparse point */
8668 : : io_result = DeviceIoControl(
8669 : : reparse_point_handle,
8670 : : FSCTL_GET_REPARSE_POINT,
8671 : : 0, 0, /* in buffer */
8672 : : target_buffer, sizeof(target_buffer),
8673 : : &n_bytes_returned,
8674 : : 0 /* we're not using OVERLAPPED_IO */
8675 : : );
8676 : : CloseHandle(reparse_point_handle);
8677 : : }
8678 : : Py_END_ALLOW_THREADS
8679 : :
8680 : : if (io_result == 0) {
8681 : : return path_error(path);
8682 : : }
8683 : :
8684 : : wchar_t *name = NULL;
8685 : : Py_ssize_t nameLen = 0;
8686 : : if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
8687 : : {
8688 : : name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
8689 : : rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
8690 : : nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8691 : : }
8692 : : else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
8693 : : {
8694 : : name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8695 : : rdb->MountPointReparseBuffer.SubstituteNameOffset);
8696 : : nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8697 : : }
8698 : : else
8699 : : {
8700 : : PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8701 : : }
8702 : : if (name) {
8703 : : if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8704 : : /* Our buffer is mutable, so this is okay */
8705 : : name[1] = L'\\';
8706 : : }
8707 : : result = PyUnicode_FromWideChar(name, nameLen);
8708 : : if (result && path->narrow) {
8709 : : Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8710 : : }
8711 : : }
8712 : : return result;
8713 : : #endif
8714 : : }
8715 : : #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8716 : :
8717 : : #if defined(MS_WINDOWS)
8718 : :
8719 : : /* Remove the last portion of the path - return 0 on success */
8720 : : static int
8721 : : _dirnameW(WCHAR *path)
8722 : : {
8723 : : WCHAR *ptr;
8724 : : size_t length = wcsnlen_s(path, MAX_PATH);
8725 : : if (length == MAX_PATH) {
8726 : : return -1;
8727 : : }
8728 : :
8729 : : /* walk the path from the end until a backslash is encountered */
8730 : : for(ptr = path + length; ptr != path; ptr--) {
8731 : : if (*ptr == L'\\' || *ptr == L'/') {
8732 : : break;
8733 : : }
8734 : : }
8735 : : *ptr = 0;
8736 : : return 0;
8737 : : }
8738 : :
8739 : : #endif
8740 : :
8741 : : #ifdef HAVE_SYMLINK
8742 : :
8743 : : #if defined(MS_WINDOWS)
8744 : :
8745 : : /* Is this path absolute? */
8746 : : static int
8747 : : _is_absW(const WCHAR *path)
8748 : : {
8749 : : return path[0] == L'\\' || path[0] == L'/' ||
8750 : : (path[0] && path[1] == L':');
8751 : : }
8752 : :
8753 : : /* join root and rest with a backslash - return 0 on success */
8754 : : static int
8755 : : _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8756 : : {
8757 : : if (_is_absW(rest)) {
8758 : : return wcscpy_s(dest_path, MAX_PATH, rest);
8759 : : }
8760 : :
8761 : : if (wcscpy_s(dest_path, MAX_PATH, root)) {
8762 : : return -1;
8763 : : }
8764 : :
8765 : : if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8766 : : return -1;
8767 : : }
8768 : :
8769 : : return wcscat_s(dest_path, MAX_PATH, rest);
8770 : : }
8771 : :
8772 : : /* Return True if the path at src relative to dest is a directory */
8773 : : static int
8774 : : _check_dirW(LPCWSTR src, LPCWSTR dest)
8775 : : {
8776 : : WIN32_FILE_ATTRIBUTE_DATA src_info;
8777 : : WCHAR dest_parent[MAX_PATH];
8778 : : WCHAR src_resolved[MAX_PATH] = L"";
8779 : :
8780 : : /* dest_parent = os.path.dirname(dest) */
8781 : : if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8782 : : _dirnameW(dest_parent)) {
8783 : : return 0;
8784 : : }
8785 : : /* src_resolved = os.path.join(dest_parent, src) */
8786 : : if (_joinW(src_resolved, dest_parent, src)) {
8787 : : return 0;
8788 : : }
8789 : : return (
8790 : : GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8791 : : && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8792 : : );
8793 : : }
8794 : : #endif
8795 : :
8796 : :
8797 : : /*[clinic input]
8798 : : os.symlink
8799 : : src: path_t
8800 : : dst: path_t
8801 : : target_is_directory: bool = False
8802 : : *
8803 : : dir_fd: dir_fd(requires='symlinkat')=None
8804 : :
8805 : : # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8806 : :
8807 : : Create a symbolic link pointing to src named dst.
8808 : :
8809 : : target_is_directory is required on Windows if the target is to be
8810 : : interpreted as a directory. (On Windows, symlink requires
8811 : : Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8812 : : target_is_directory is ignored on non-Windows platforms.
8813 : :
8814 : : If dir_fd is not None, it should be a file descriptor open to a directory,
8815 : : and path should be relative; path will then be relative to that directory.
8816 : : dir_fd may not be implemented on your platform.
8817 : : If it is unavailable, using it will raise a NotImplementedError.
8818 : :
8819 : : [clinic start generated code]*/
8820 : :
8821 : : static PyObject *
8822 : 1308 : os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8823 : : int target_is_directory, int dir_fd)
8824 : : /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8825 : : {
8826 : : #ifdef MS_WINDOWS
8827 : : DWORD result;
8828 : : DWORD flags = 0;
8829 : :
8830 : : /* Assumed true, set to false if detected to not be available. */
8831 : : static int windows_has_symlink_unprivileged_flag = TRUE;
8832 : : #else
8833 : : int result;
8834 : : #ifdef HAVE_SYMLINKAT
8835 : 1308 : int symlinkat_unavailable = 0;
8836 : : #endif
8837 : : #endif
8838 : :
8839 [ + + - + ]: 1308 : if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8840 : : dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8841 : 0 : return NULL;
8842 : : }
8843 : :
8844 : : #ifdef MS_WINDOWS
8845 : :
8846 : : if (windows_has_symlink_unprivileged_flag) {
8847 : : /* Allow non-admin symlinks if system allows it. */
8848 : : flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8849 : : }
8850 : :
8851 : : Py_BEGIN_ALLOW_THREADS
8852 : : _Py_BEGIN_SUPPRESS_IPH
8853 : : /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8854 : : if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8855 : : flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8856 : : }
8857 : :
8858 : : result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8859 : : _Py_END_SUPPRESS_IPH
8860 : : Py_END_ALLOW_THREADS
8861 : :
8862 : : if (windows_has_symlink_unprivileged_flag && !result &&
8863 : : ERROR_INVALID_PARAMETER == GetLastError()) {
8864 : :
8865 : : Py_BEGIN_ALLOW_THREADS
8866 : : _Py_BEGIN_SUPPRESS_IPH
8867 : : /* This error might be caused by
8868 : : SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8869 : : Try again, and update windows_has_symlink_unprivileged_flag if we
8870 : : are successful this time.
8871 : :
8872 : : NOTE: There is a risk of a race condition here if there are other
8873 : : conditions than the flag causing ERROR_INVALID_PARAMETER, and
8874 : : another process (or thread) changes that condition in between our
8875 : : calls to CreateSymbolicLink.
8876 : : */
8877 : : flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8878 : : result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8879 : : _Py_END_SUPPRESS_IPH
8880 : : Py_END_ALLOW_THREADS
8881 : :
8882 : : if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8883 : : windows_has_symlink_unprivileged_flag = FALSE;
8884 : : }
8885 : : }
8886 : :
8887 : : if (!result)
8888 : : return path_error2(src, dst);
8889 : :
8890 : : #else
8891 : :
8892 [ + - + - : 1308 : if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
- + - - ]
8893 : 0 : PyErr_SetString(PyExc_ValueError,
8894 : : "symlink: src and dst must be the same type");
8895 : 0 : return NULL;
8896 : : }
8897 : :
8898 : 1308 : Py_BEGIN_ALLOW_THREADS
8899 : : #ifdef HAVE_SYMLINKAT
8900 [ + + ]: 1308 : if (dir_fd != DEFAULT_DIR_FD) {
8901 : : if (HAVE_SYMLINKAT_RUNTIME) {
8902 : 1 : result = symlinkat(src->narrow, dir_fd, dst->narrow);
8903 : : } else {
8904 : : symlinkat_unavailable = 1;
8905 : : }
8906 : : } else
8907 : : #endif
8908 : 1307 : result = symlink(src->narrow, dst->narrow);
8909 : 1308 : Py_END_ALLOW_THREADS
8910 : :
8911 : : #ifdef HAVE_SYMLINKAT
8912 [ - + ]: 1308 : if (symlinkat_unavailable) {
8913 : 0 : argument_unavailable_error(NULL, "dir_fd");
8914 : 0 : return NULL;
8915 : : }
8916 : : #endif
8917 : :
8918 [ - + ]: 1308 : if (result)
8919 : 0 : return path_error2(src, dst);
8920 : : #endif
8921 : :
8922 : 1308 : Py_RETURN_NONE;
8923 : : }
8924 : : #endif /* HAVE_SYMLINK */
8925 : :
8926 : :
8927 : :
8928 : :
8929 : : static PyStructSequence_Field times_result_fields[] = {
8930 : : {"user", "user time"},
8931 : : {"system", "system time"},
8932 : : {"children_user", "user time of children"},
8933 : : {"children_system", "system time of children"},
8934 : : {"elapsed", "elapsed time since an arbitrary point in the past"},
8935 : : {NULL}
8936 : : };
8937 : :
8938 : : PyDoc_STRVAR(times_result__doc__,
8939 : : "times_result: Result from os.times().\n\n\
8940 : : This object may be accessed either as a tuple of\n\
8941 : : (user, system, children_user, children_system, elapsed),\n\
8942 : : or via the attributes user, system, children_user, children_system,\n\
8943 : : and elapsed.\n\
8944 : : \n\
8945 : : See os.times for more information.");
8946 : :
8947 : : static PyStructSequence_Desc times_result_desc = {
8948 : : "times_result", /* name */
8949 : : times_result__doc__, /* doc */
8950 : : times_result_fields,
8951 : : 5
8952 : : };
8953 : :
8954 : : #ifdef MS_WINDOWS
8955 : : #define HAVE_TIMES /* mandatory, for the method table */
8956 : : #endif
8957 : :
8958 : : #ifdef HAVE_TIMES
8959 : :
8960 : : static PyObject *
8961 : 2 : build_times_result(PyObject *module, double user, double system,
8962 : : double children_user, double children_system,
8963 : : double elapsed)
8964 : : {
8965 : 2 : PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
8966 : 2 : PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
8967 [ - + ]: 2 : if (value == NULL)
8968 : 0 : return NULL;
8969 : :
8970 : : #define SET(i, field) \
8971 : : { \
8972 : : PyObject *o = PyFloat_FromDouble(field); \
8973 : : if (!o) { \
8974 : : Py_DECREF(value); \
8975 : : return NULL; \
8976 : : } \
8977 : : PyStructSequence_SET_ITEM(value, i, o); \
8978 : : } \
8979 : :
8980 [ - + ]: 2 : SET(0, user);
8981 [ - + ]: 2 : SET(1, system);
8982 [ - + ]: 2 : SET(2, children_user);
8983 [ - + ]: 2 : SET(3, children_system);
8984 [ - + ]: 2 : SET(4, elapsed);
8985 : :
8986 : : #undef SET
8987 : :
8988 : 2 : return value;
8989 : : }
8990 : :
8991 : :
8992 : : #ifndef MS_WINDOWS
8993 : : #define NEED_TICKS_PER_SECOND
8994 : : static long ticks_per_second = -1;
8995 : : #endif /* MS_WINDOWS */
8996 : :
8997 : : /*[clinic input]
8998 : : os.times
8999 : :
9000 : : Return a collection containing process timing information.
9001 : :
9002 : : The object returned behaves like a named tuple with these fields:
9003 : : (utime, stime, cutime, cstime, elapsed_time)
9004 : : All fields are floating point numbers.
9005 : : [clinic start generated code]*/
9006 : :
9007 : : static PyObject *
9008 : 2 : os_times_impl(PyObject *module)
9009 : : /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
9010 : : #ifdef MS_WINDOWS
9011 : : {
9012 : : FILETIME create, exit, kernel, user;
9013 : : HANDLE hProc;
9014 : : hProc = GetCurrentProcess();
9015 : : GetProcessTimes(hProc, &create, &exit, &kernel, &user);
9016 : : /* The fields of a FILETIME structure are the hi and lo part
9017 : : of a 64-bit value expressed in 100 nanosecond units.
9018 : : 1e7 is one second in such units; 1e-7 the inverse.
9019 : : 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
9020 : : */
9021 : : return build_times_result(module,
9022 : : (double)(user.dwHighDateTime*429.4967296 +
9023 : : user.dwLowDateTime*1e-7),
9024 : : (double)(kernel.dwHighDateTime*429.4967296 +
9025 : : kernel.dwLowDateTime*1e-7),
9026 : : (double)0,
9027 : : (double)0,
9028 : : (double)0);
9029 : : }
9030 : : #else /* MS_WINDOWS */
9031 : : {
9032 : :
9033 : :
9034 : : struct tms t;
9035 : : clock_t c;
9036 : 2 : errno = 0;
9037 : 2 : c = times(&t);
9038 [ - + ]: 2 : if (c == (clock_t) -1)
9039 : 0 : return posix_error();
9040 : 2 : return build_times_result(module,
9041 : 2 : (double)t.tms_utime / ticks_per_second,
9042 : 2 : (double)t.tms_stime / ticks_per_second,
9043 : 2 : (double)t.tms_cutime / ticks_per_second,
9044 : 2 : (double)t.tms_cstime / ticks_per_second,
9045 : 2 : (double)c / ticks_per_second);
9046 : : }
9047 : : #endif /* MS_WINDOWS */
9048 : : #endif /* HAVE_TIMES */
9049 : :
9050 : :
9051 : : #ifdef HAVE_GETSID
9052 : : /*[clinic input]
9053 : : os.getsid
9054 : :
9055 : : pid: pid_t
9056 : : /
9057 : :
9058 : : Call the system call getsid(pid) and return the result.
9059 : : [clinic start generated code]*/
9060 : :
9061 : : static PyObject *
9062 : 6 : os_getsid_impl(PyObject *module, pid_t pid)
9063 : : /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
9064 : : {
9065 : : int sid;
9066 : 6 : sid = getsid(pid);
9067 [ - + ]: 6 : if (sid < 0)
9068 : 0 : return posix_error();
9069 : 6 : return PyLong_FromLong((long)sid);
9070 : : }
9071 : : #endif /* HAVE_GETSID */
9072 : :
9073 : :
9074 : : #ifdef HAVE_SETSID
9075 : : /*[clinic input]
9076 : : os.setsid
9077 : :
9078 : : Call the system call setsid().
9079 : : [clinic start generated code]*/
9080 : :
9081 : : static PyObject *
9082 : 0 : os_setsid_impl(PyObject *module)
9083 : : /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
9084 : : {
9085 [ # # ]: 0 : if (setsid() < 0)
9086 : 0 : return posix_error();
9087 : 0 : Py_RETURN_NONE;
9088 : : }
9089 : : #endif /* HAVE_SETSID */
9090 : :
9091 : :
9092 : : #ifdef HAVE_SETPGID
9093 : : /*[clinic input]
9094 : : os.setpgid
9095 : :
9096 : : pid: pid_t
9097 : : pgrp: pid_t
9098 : : /
9099 : :
9100 : : Call the system call setpgid(pid, pgrp).
9101 : : [clinic start generated code]*/
9102 : :
9103 : : static PyObject *
9104 : 0 : os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
9105 : : /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
9106 : : {
9107 [ # # ]: 0 : if (setpgid(pid, pgrp) < 0)
9108 : 0 : return posix_error();
9109 : 0 : Py_RETURN_NONE;
9110 : : }
9111 : : #endif /* HAVE_SETPGID */
9112 : :
9113 : :
9114 : : #ifdef HAVE_TCGETPGRP
9115 : : /*[clinic input]
9116 : : os.tcgetpgrp
9117 : :
9118 : : fd: int
9119 : : /
9120 : :
9121 : : Return the process group associated with the terminal specified by fd.
9122 : : [clinic start generated code]*/
9123 : :
9124 : : static PyObject *
9125 : 1 : os_tcgetpgrp_impl(PyObject *module, int fd)
9126 : : /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
9127 : : {
9128 : 1 : pid_t pgid = tcgetpgrp(fd);
9129 [ + - ]: 1 : if (pgid < 0)
9130 : 1 : return posix_error();
9131 : 0 : return PyLong_FromPid(pgid);
9132 : : }
9133 : : #endif /* HAVE_TCGETPGRP */
9134 : :
9135 : :
9136 : : #ifdef HAVE_TCSETPGRP
9137 : : /*[clinic input]
9138 : : os.tcsetpgrp
9139 : :
9140 : : fd: int
9141 : : pgid: pid_t
9142 : : /
9143 : :
9144 : : Set the process group associated with the terminal specified by fd.
9145 : : [clinic start generated code]*/
9146 : :
9147 : : static PyObject *
9148 : 1 : os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
9149 : : /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
9150 : : {
9151 [ + - ]: 1 : if (tcsetpgrp(fd, pgid) < 0)
9152 : 1 : return posix_error();
9153 : 0 : Py_RETURN_NONE;
9154 : : }
9155 : : #endif /* HAVE_TCSETPGRP */
9156 : :
9157 : : /* Functions acting on file descriptors */
9158 : :
9159 : : #ifdef O_CLOEXEC
9160 : : extern int _Py_open_cloexec_works;
9161 : : #endif
9162 : :
9163 : :
9164 : : /*[clinic input]
9165 : : os.open -> int
9166 : : path: path_t
9167 : : flags: int
9168 : : mode: int = 0o777
9169 : : *
9170 : : dir_fd: dir_fd(requires='openat') = None
9171 : :
9172 : : # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
9173 : :
9174 : : Open a file for low level IO. Returns a file descriptor (integer).
9175 : :
9176 : : If dir_fd is not None, it should be a file descriptor open to a directory,
9177 : : and path should be relative; path will then be relative to that directory.
9178 : : dir_fd may not be implemented on your platform.
9179 : : If it is unavailable, using it will raise a NotImplementedError.
9180 : : [clinic start generated code]*/
9181 : :
9182 : : static int
9183 : 32935 : os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
9184 : : /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
9185 : : {
9186 : : int fd;
9187 : 32935 : int async_err = 0;
9188 : : #ifdef HAVE_OPENAT
9189 : 32935 : int openat_unavailable = 0;
9190 : : #endif
9191 : :
9192 : : #ifdef O_CLOEXEC
9193 : 32935 : int *atomic_flag_works = &_Py_open_cloexec_works;
9194 : : #elif !defined(MS_WINDOWS)
9195 : : int *atomic_flag_works = NULL;
9196 : : #endif
9197 : :
9198 : : #ifdef MS_WINDOWS
9199 : : flags |= O_NOINHERIT;
9200 : : #elif defined(O_CLOEXEC)
9201 : 32935 : flags |= O_CLOEXEC;
9202 : : #endif
9203 : :
9204 [ - + ]: 32935 : if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
9205 : 0 : return -1;
9206 : : }
9207 : :
9208 : : _Py_BEGIN_SUPPRESS_IPH
9209 : : do {
9210 : 32938 : Py_BEGIN_ALLOW_THREADS
9211 : : #ifdef MS_WINDOWS
9212 : : fd = _wopen(path->wide, flags, mode);
9213 : : #else
9214 : : #ifdef HAVE_OPENAT
9215 [ + + ]: 32938 : if (dir_fd != DEFAULT_DIR_FD) {
9216 : : if (HAVE_OPENAT_RUNTIME) {
9217 : 10888 : fd = openat(dir_fd, path->narrow, flags, mode);
9218 : :
9219 : : } else {
9220 : : openat_unavailable = 1;
9221 : : fd = -1;
9222 : : }
9223 : : } else
9224 : : #endif /* HAVE_OPENAT */
9225 : 22050 : fd = open(path->narrow, flags, mode);
9226 : : #endif /* !MS_WINDOWS */
9227 : 32938 : Py_END_ALLOW_THREADS
9228 [ + + + + : 32938 : } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ - ]
9229 : : _Py_END_SUPPRESS_IPH
9230 : :
9231 : : #ifdef HAVE_OPENAT
9232 [ - + ]: 32935 : if (openat_unavailable) {
9233 : 0 : argument_unavailable_error(NULL, "dir_fd");
9234 : 0 : return -1;
9235 : : }
9236 : : #endif
9237 : :
9238 [ + + ]: 32935 : if (fd < 0) {
9239 [ + - ]: 734 : if (!async_err)
9240 : 734 : PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
9241 : 734 : return -1;
9242 : : }
9243 : :
9244 : : #ifndef MS_WINDOWS
9245 [ - + ]: 32201 : if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
9246 : 0 : close(fd);
9247 : 0 : return -1;
9248 : : }
9249 : : #endif
9250 : :
9251 : 32201 : return fd;
9252 : : }
9253 : :
9254 : :
9255 : : /*[clinic input]
9256 : : os.close
9257 : :
9258 : : fd: int
9259 : :
9260 : : Close a file descriptor.
9261 : : [clinic start generated code]*/
9262 : :
9263 : : static PyObject *
9264 : 62409 : os_close_impl(PyObject *module, int fd)
9265 : : /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
9266 : : {
9267 : : int res;
9268 : : /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
9269 : : * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
9270 : : * for more details.
9271 : : */
9272 : 62409 : Py_BEGIN_ALLOW_THREADS
9273 : : _Py_BEGIN_SUPPRESS_IPH
9274 : 62409 : res = close(fd);
9275 : : _Py_END_SUPPRESS_IPH
9276 : 62409 : Py_END_ALLOW_THREADS
9277 [ + + ]: 62407 : if (res < 0)
9278 : 25 : return posix_error();
9279 : 62382 : Py_RETURN_NONE;
9280 : : }
9281 : :
9282 : : /*[clinic input]
9283 : : os.closerange
9284 : :
9285 : : fd_low: int
9286 : : fd_high: int
9287 : : /
9288 : :
9289 : : Closes all file descriptors in [fd_low, fd_high), ignoring errors.
9290 : : [clinic start generated code]*/
9291 : :
9292 : : static PyObject *
9293 : 2 : os_closerange_impl(PyObject *module, int fd_low, int fd_high)
9294 : : /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
9295 : : {
9296 : 2 : Py_BEGIN_ALLOW_THREADS
9297 : 2 : _Py_closerange(fd_low, fd_high - 1);
9298 : 2 : Py_END_ALLOW_THREADS
9299 : 2 : Py_RETURN_NONE;
9300 : : }
9301 : :
9302 : :
9303 : : /*[clinic input]
9304 : : os.dup -> int
9305 : :
9306 : : fd: int
9307 : : /
9308 : :
9309 : : Return a duplicate of a file descriptor.
9310 : : [clinic start generated code]*/
9311 : :
9312 : : static int
9313 : 1489 : os_dup_impl(PyObject *module, int fd)
9314 : : /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
9315 : : {
9316 : 1489 : return _Py_dup(fd);
9317 : : }
9318 : :
9319 : :
9320 : : /*[clinic input]
9321 : : os.dup2 -> int
9322 : : fd: int
9323 : : fd2: int
9324 : : inheritable: bool=True
9325 : :
9326 : : Duplicate file descriptor.
9327 : : [clinic start generated code]*/
9328 : :
9329 : : static int
9330 : 535 : os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
9331 : : /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
9332 : : {
9333 : 535 : int res = 0;
9334 : : #if defined(HAVE_DUP3) && \
9335 : : !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
9336 : : /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
9337 : : static int dup3_works = -1;
9338 : : #endif
9339 : :
9340 [ + - - + ]: 535 : if (fd < 0 || fd2 < 0) {
9341 : 0 : posix_error();
9342 : 0 : return -1;
9343 : : }
9344 : :
9345 : : /* dup2() can fail with EINTR if the target FD is already open, because it
9346 : : * then has to be closed. See os_close_impl() for why we don't handle EINTR
9347 : : * upon close(), and therefore below.
9348 : : */
9349 : : #ifdef MS_WINDOWS
9350 : : Py_BEGIN_ALLOW_THREADS
9351 : : _Py_BEGIN_SUPPRESS_IPH
9352 : : res = dup2(fd, fd2);
9353 : : _Py_END_SUPPRESS_IPH
9354 : : Py_END_ALLOW_THREADS
9355 : : if (res < 0) {
9356 : : posix_error();
9357 : : return -1;
9358 : : }
9359 : : res = fd2; // msvcrt dup2 returns 0 on success.
9360 : :
9361 : : /* Character files like console cannot be make non-inheritable */
9362 : : if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9363 : : close(fd2);
9364 : : return -1;
9365 : : }
9366 : :
9367 : : #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
9368 : : Py_BEGIN_ALLOW_THREADS
9369 : : if (!inheritable)
9370 : : res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
9371 : : else
9372 : : res = dup2(fd, fd2);
9373 : : Py_END_ALLOW_THREADS
9374 : : if (res < 0) {
9375 : : posix_error();
9376 : : return -1;
9377 : : }
9378 : :
9379 : : #else
9380 : :
9381 : : #ifdef HAVE_DUP3
9382 [ + + + - ]: 535 : if (!inheritable && dup3_works != 0) {
9383 : 1 : Py_BEGIN_ALLOW_THREADS
9384 : 1 : res = dup3(fd, fd2, O_CLOEXEC);
9385 : 1 : Py_END_ALLOW_THREADS
9386 [ - + ]: 1 : if (res < 0) {
9387 [ # # ]: 0 : if (dup3_works == -1)
9388 : 0 : dup3_works = (errno != ENOSYS);
9389 [ # # ]: 0 : if (dup3_works) {
9390 : 0 : posix_error();
9391 : 0 : return -1;
9392 : : }
9393 : : }
9394 : : }
9395 : :
9396 [ + + - + ]: 535 : if (inheritable || dup3_works == 0)
9397 : : {
9398 : : #endif
9399 : 534 : Py_BEGIN_ALLOW_THREADS
9400 : 534 : res = dup2(fd, fd2);
9401 : 534 : Py_END_ALLOW_THREADS
9402 [ + + ]: 534 : if (res < 0) {
9403 : 1 : posix_error();
9404 : 1 : return -1;
9405 : : }
9406 : :
9407 [ - + - - ]: 533 : if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9408 : 0 : close(fd2);
9409 : 0 : return -1;
9410 : : }
9411 : : #ifdef HAVE_DUP3
9412 : : }
9413 : : #endif
9414 : :
9415 : : #endif
9416 : :
9417 : 534 : return res;
9418 : : }
9419 : :
9420 : :
9421 : : #ifdef HAVE_LOCKF
9422 : : /*[clinic input]
9423 : : os.lockf
9424 : :
9425 : : fd: int
9426 : : An open file descriptor.
9427 : : command: int
9428 : : One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
9429 : : length: Py_off_t
9430 : : The number of bytes to lock, starting at the current position.
9431 : : /
9432 : :
9433 : : Apply, test or remove a POSIX lock on an open file descriptor.
9434 : :
9435 : : [clinic start generated code]*/
9436 : :
9437 : : static PyObject *
9438 : 2 : os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
9439 : : /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
9440 : : {
9441 : : int res;
9442 : :
9443 [ - + ]: 2 : if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
9444 : 0 : return NULL;
9445 : : }
9446 : :
9447 : 2 : Py_BEGIN_ALLOW_THREADS
9448 : 2 : res = lockf(fd, command, length);
9449 : 2 : Py_END_ALLOW_THREADS
9450 : :
9451 [ - + ]: 2 : if (res < 0)
9452 : 0 : return posix_error();
9453 : :
9454 : 2 : Py_RETURN_NONE;
9455 : : }
9456 : : #endif /* HAVE_LOCKF */
9457 : :
9458 : :
9459 : : /*[clinic input]
9460 : : os.lseek -> Py_off_t
9461 : :
9462 : : fd: int
9463 : : position: Py_off_t
9464 : : how: int
9465 : : /
9466 : :
9467 : : Set the position of a file descriptor. Return the new position.
9468 : :
9469 : : Return the new cursor position in number of bytes
9470 : : relative to the beginning of the file.
9471 : : [clinic start generated code]*/
9472 : :
9473 : : static Py_off_t
9474 : 8399 : os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
9475 : : /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
9476 : : {
9477 : : Py_off_t result;
9478 : :
9479 : : #ifdef SEEK_SET
9480 : : /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
9481 [ + + + + ]: 8399 : switch (how) {
9482 : 2044 : case 0: how = SEEK_SET; break;
9483 : 6258 : case 1: how = SEEK_CUR; break;
9484 : 85 : case 2: how = SEEK_END; break;
9485 : : }
9486 : : #endif /* SEEK_END */
9487 : :
9488 : 8399 : Py_BEGIN_ALLOW_THREADS
9489 : : _Py_BEGIN_SUPPRESS_IPH
9490 : : #ifdef MS_WINDOWS
9491 : : result = _lseeki64(fd, position, how);
9492 : : #else
9493 : 8399 : result = lseek(fd, position, how);
9494 : : #endif
9495 : : _Py_END_SUPPRESS_IPH
9496 : 8399 : Py_END_ALLOW_THREADS
9497 [ + + ]: 8399 : if (result < 0)
9498 : 37 : posix_error();
9499 : :
9500 : 8399 : return result;
9501 : : }
9502 : :
9503 : :
9504 : : /*[clinic input]
9505 : : os.read
9506 : : fd: int
9507 : : length: Py_ssize_t
9508 : : /
9509 : :
9510 : : Read from a file descriptor. Returns a bytes object.
9511 : : [clinic start generated code]*/
9512 : :
9513 : : static PyObject *
9514 : 180343 : os_read_impl(PyObject *module, int fd, Py_ssize_t length)
9515 : : /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
9516 : : {
9517 : : Py_ssize_t n;
9518 : : PyObject *buffer;
9519 : :
9520 [ - + ]: 180343 : if (length < 0) {
9521 : 0 : errno = EINVAL;
9522 : 0 : return posix_error();
9523 : : }
9524 : :
9525 : 180343 : length = Py_MIN(length, _PY_READ_MAX);
9526 : :
9527 : 180343 : buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9528 [ - + ]: 180343 : if (buffer == NULL)
9529 : 0 : return NULL;
9530 : :
9531 : 180343 : n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
9532 [ + + ]: 180341 : if (n == -1) {
9533 : 29 : Py_DECREF(buffer);
9534 : 29 : return NULL;
9535 : : }
9536 : :
9537 [ + + ]: 180312 : if (n != length)
9538 : 37769 : _PyBytes_Resize(&buffer, n);
9539 : :
9540 : 180312 : return buffer;
9541 : : }
9542 : :
9543 : : #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
9544 : : || defined(__APPLE__))) \
9545 : : || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
9546 : : || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9547 : : static int
9548 : 9 : iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
9549 : : {
9550 : : Py_ssize_t i, j;
9551 : :
9552 [ + - ]: 9 : *iov = PyMem_New(struct iovec, cnt);
9553 [ - + ]: 9 : if (*iov == NULL) {
9554 : : PyErr_NoMemory();
9555 : 0 : return -1;
9556 : : }
9557 : :
9558 [ + - ]: 9 : *buf = PyMem_New(Py_buffer, cnt);
9559 [ - + ]: 9 : if (*buf == NULL) {
9560 : 0 : PyMem_Free(*iov);
9561 : : PyErr_NoMemory();
9562 : 0 : return -1;
9563 : : }
9564 : :
9565 [ + + ]: 26 : for (i = 0; i < cnt; i++) {
9566 : 17 : PyObject *item = PySequence_GetItem(seq, i);
9567 [ - + ]: 17 : if (item == NULL)
9568 : 0 : goto fail;
9569 [ - + ]: 17 : if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
9570 : 0 : Py_DECREF(item);
9571 : 0 : goto fail;
9572 : : }
9573 : 17 : Py_DECREF(item);
9574 : 17 : (*iov)[i].iov_base = (*buf)[i].buf;
9575 : 17 : (*iov)[i].iov_len = (*buf)[i].len;
9576 : : }
9577 : 9 : return 0;
9578 : :
9579 : 0 : fail:
9580 : 0 : PyMem_Free(*iov);
9581 [ # # ]: 0 : for (j = 0; j < i; j++) {
9582 : 0 : PyBuffer_Release(&(*buf)[j]);
9583 : : }
9584 : 0 : PyMem_Free(*buf);
9585 : 0 : return -1;
9586 : : }
9587 : :
9588 : : static void
9589 : 9 : iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9590 : : {
9591 : : int i;
9592 : 9 : PyMem_Free(iov);
9593 [ + + ]: 26 : for (i = 0; i < cnt; i++) {
9594 : 17 : PyBuffer_Release(&buf[i]);
9595 : : }
9596 : 9 : PyMem_Free(buf);
9597 : 9 : }
9598 : : #endif
9599 : :
9600 : :
9601 : : #ifdef HAVE_READV
9602 : : /*[clinic input]
9603 : : os.readv -> Py_ssize_t
9604 : :
9605 : : fd: int
9606 : : buffers: object
9607 : : /
9608 : :
9609 : : Read from a file descriptor fd into an iterable of buffers.
9610 : :
9611 : : The buffers should be mutable buffers accepting bytes.
9612 : : readv will transfer data into each buffer until it is full
9613 : : and then move on to the next buffer in the sequence to hold
9614 : : the rest of the data.
9615 : :
9616 : : readv returns the total number of bytes read,
9617 : : which may be less than the total capacity of all the buffers.
9618 : : [clinic start generated code]*/
9619 : :
9620 : : static Py_ssize_t
9621 : 3 : os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9622 : : /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9623 : : {
9624 : : Py_ssize_t cnt, n;
9625 : 3 : int async_err = 0;
9626 : : struct iovec *iov;
9627 : : Py_buffer *buf;
9628 : :
9629 [ - + ]: 3 : if (!PySequence_Check(buffers)) {
9630 : 0 : PyErr_SetString(PyExc_TypeError,
9631 : : "readv() arg 2 must be a sequence");
9632 : 0 : return -1;
9633 : : }
9634 : :
9635 : 3 : cnt = PySequence_Size(buffers);
9636 [ - + ]: 3 : if (cnt < 0)
9637 : 0 : return -1;
9638 : :
9639 [ - + ]: 3 : if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9640 : 0 : return -1;
9641 : :
9642 : : do {
9643 : 3 : Py_BEGIN_ALLOW_THREADS
9644 : 3 : n = readv(fd, iov, cnt);
9645 : 3 : Py_END_ALLOW_THREADS
9646 [ + + - + : 3 : } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
9647 : :
9648 : 3 : iov_cleanup(iov, buf, cnt);
9649 [ + + ]: 3 : if (n < 0) {
9650 [ + - ]: 1 : if (!async_err)
9651 : 1 : posix_error();
9652 : 1 : return -1;
9653 : : }
9654 : :
9655 : 2 : return n;
9656 : : }
9657 : : #endif /* HAVE_READV */
9658 : :
9659 : :
9660 : : #ifdef HAVE_PREAD
9661 : : /*[clinic input]
9662 : : os.pread
9663 : :
9664 : : fd: int
9665 : : length: Py_ssize_t
9666 : : offset: Py_off_t
9667 : : /
9668 : :
9669 : : Read a number of bytes from a file descriptor starting at a particular offset.
9670 : :
9671 : : Read length bytes from file descriptor fd, starting at offset bytes from
9672 : : the beginning of the file. The file offset remains unchanged.
9673 : : [clinic start generated code]*/
9674 : :
9675 : : static PyObject *
9676 : 1 : os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
9677 : : /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
9678 : : {
9679 : : Py_ssize_t n;
9680 : 1 : int async_err = 0;
9681 : : PyObject *buffer;
9682 : :
9683 [ - + ]: 1 : if (length < 0) {
9684 : 0 : errno = EINVAL;
9685 : 0 : return posix_error();
9686 : : }
9687 : 1 : buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9688 [ - + ]: 1 : if (buffer == NULL)
9689 : 0 : return NULL;
9690 : :
9691 : : do {
9692 : 1 : Py_BEGIN_ALLOW_THREADS
9693 : : _Py_BEGIN_SUPPRESS_IPH
9694 : 1 : n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9695 : : _Py_END_SUPPRESS_IPH
9696 : 1 : Py_END_ALLOW_THREADS
9697 [ - + - - : 1 : } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
9698 : :
9699 [ - + ]: 1 : if (n < 0) {
9700 : 0 : Py_DECREF(buffer);
9701 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
9702 : : }
9703 [ - + ]: 1 : if (n != length)
9704 : 0 : _PyBytes_Resize(&buffer, n);
9705 : 1 : return buffer;
9706 : : }
9707 : : #endif /* HAVE_PREAD */
9708 : :
9709 : : #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9710 : : /*[clinic input]
9711 : : os.preadv -> Py_ssize_t
9712 : :
9713 : : fd: int
9714 : : buffers: object
9715 : : offset: Py_off_t
9716 : : flags: int = 0
9717 : : /
9718 : :
9719 : : Reads from a file descriptor into a number of mutable bytes-like objects.
9720 : :
9721 : : Combines the functionality of readv() and pread(). As readv(), it will
9722 : : transfer data into each buffer until it is full and then move on to the next
9723 : : buffer in the sequence to hold the rest of the data. Its fourth argument,
9724 : : specifies the file offset at which the input operation is to be performed. It
9725 : : will return the total number of bytes read (which can be less than the total
9726 : : capacity of all the objects).
9727 : :
9728 : : The flags argument contains a bitwise OR of zero or more of the following flags:
9729 : :
9730 : : - RWF_HIPRI
9731 : : - RWF_NOWAIT
9732 : :
9733 : : Using non-zero flags requires Linux 4.6 or newer.
9734 : : [clinic start generated code]*/
9735 : :
9736 : : static Py_ssize_t
9737 : 2 : os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9738 : : int flags)
9739 : : /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9740 : : {
9741 : : Py_ssize_t cnt, n;
9742 : 2 : int async_err = 0;
9743 : : struct iovec *iov;
9744 : : Py_buffer *buf;
9745 : :
9746 [ - + ]: 2 : if (!PySequence_Check(buffers)) {
9747 : 0 : PyErr_SetString(PyExc_TypeError,
9748 : : "preadv2() arg 2 must be a sequence");
9749 : 0 : return -1;
9750 : : }
9751 : :
9752 : 2 : cnt = PySequence_Size(buffers);
9753 [ - + ]: 2 : if (cnt < 0) {
9754 : 0 : return -1;
9755 : : }
9756 : :
9757 : : #ifndef HAVE_PREADV2
9758 : : if(flags != 0) {
9759 : : argument_unavailable_error("preadv2", "flags");
9760 : : return -1;
9761 : : }
9762 : : #endif
9763 : :
9764 [ - + ]: 2 : if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9765 : 0 : return -1;
9766 : : }
9767 : : #ifdef HAVE_PREADV2
9768 : : do {
9769 : 2 : Py_BEGIN_ALLOW_THREADS
9770 : : _Py_BEGIN_SUPPRESS_IPH
9771 : 2 : n = preadv2(fd, iov, cnt, offset, flags);
9772 : : _Py_END_SUPPRESS_IPH
9773 : 2 : Py_END_ALLOW_THREADS
9774 [ - + - - : 2 : } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
9775 : : #else
9776 : : do {
9777 : : #ifdef __APPLE__
9778 : : /* This entire function will be removed from the module dict when the API
9779 : : * is not available.
9780 : : */
9781 : : #pragma clang diagnostic push
9782 : : #pragma clang diagnostic ignored "-Wunguarded-availability"
9783 : : #pragma clang diagnostic ignored "-Wunguarded-availability-new"
9784 : : #endif
9785 : : Py_BEGIN_ALLOW_THREADS
9786 : : _Py_BEGIN_SUPPRESS_IPH
9787 : : n = preadv(fd, iov, cnt, offset);
9788 : : _Py_END_SUPPRESS_IPH
9789 : : Py_END_ALLOW_THREADS
9790 : : } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9791 : :
9792 : : #ifdef __APPLE__
9793 : : #pragma clang diagnostic pop
9794 : : #endif
9795 : :
9796 : : #endif
9797 : :
9798 : 2 : iov_cleanup(iov, buf, cnt);
9799 [ - + ]: 2 : if (n < 0) {
9800 [ # # ]: 0 : if (!async_err) {
9801 : 0 : posix_error();
9802 : : }
9803 : 0 : return -1;
9804 : : }
9805 : :
9806 : 2 : return n;
9807 : : }
9808 : : #endif /* HAVE_PREADV */
9809 : :
9810 : :
9811 : : /*[clinic input]
9812 : : os.write -> Py_ssize_t
9813 : :
9814 : : fd: int
9815 : : data: Py_buffer
9816 : : /
9817 : :
9818 : : Write a bytes object to a file descriptor.
9819 : : [clinic start generated code]*/
9820 : :
9821 : : static Py_ssize_t
9822 : 82911 : os_write_impl(PyObject *module, int fd, Py_buffer *data)
9823 : : /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9824 : : {
9825 : 82911 : return _Py_write(fd, data->buf, data->len);
9826 : : }
9827 : :
9828 : : #ifdef HAVE_SENDFILE
9829 : : #ifdef __APPLE__
9830 : : /*[clinic input]
9831 : : os.sendfile
9832 : :
9833 : : out_fd: int
9834 : : in_fd: int
9835 : : offset: Py_off_t
9836 : : count as sbytes: Py_off_t
9837 : : headers: object(c_default="NULL") = ()
9838 : : trailers: object(c_default="NULL") = ()
9839 : : flags: int = 0
9840 : :
9841 : : Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9842 : : [clinic start generated code]*/
9843 : :
9844 : : static PyObject *
9845 : : os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9846 : : Py_off_t sbytes, PyObject *headers, PyObject *trailers,
9847 : : int flags)
9848 : : /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
9849 : : #elif defined(__FreeBSD__) || defined(__DragonFly__)
9850 : : /*[clinic input]
9851 : : os.sendfile
9852 : :
9853 : : out_fd: int
9854 : : in_fd: int
9855 : : offset: Py_off_t
9856 : : count: Py_ssize_t
9857 : : headers: object(c_default="NULL") = ()
9858 : : trailers: object(c_default="NULL") = ()
9859 : : flags: int = 0
9860 : :
9861 : : Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9862 : : [clinic start generated code]*/
9863 : :
9864 : : static PyObject *
9865 : : os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9866 : : Py_ssize_t count, PyObject *headers, PyObject *trailers,
9867 : : int flags)
9868 : : /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
9869 : : #else
9870 : : /*[clinic input]
9871 : : os.sendfile
9872 : :
9873 : : out_fd: int
9874 : : in_fd: int
9875 : : offset as offobj: object
9876 : : count: Py_ssize_t
9877 : :
9878 : : Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9879 : : [clinic start generated code]*/
9880 : :
9881 : : static PyObject *
9882 : 41183 : os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
9883 : : Py_ssize_t count)
9884 : : /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
9885 : : #endif
9886 : : {
9887 : : Py_ssize_t ret;
9888 : 41183 : int async_err = 0;
9889 : :
9890 : : #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9891 : : #ifndef __APPLE__
9892 : : off_t sbytes;
9893 : : #endif
9894 : : Py_buffer *hbuf, *tbuf;
9895 : : struct sf_hdtr sf;
9896 : :
9897 : : sf.headers = NULL;
9898 : : sf.trailers = NULL;
9899 : :
9900 : : if (headers != NULL) {
9901 : : if (!PySequence_Check(headers)) {
9902 : : PyErr_SetString(PyExc_TypeError,
9903 : : "sendfile() headers must be a sequence");
9904 : : return NULL;
9905 : : } else {
9906 : : Py_ssize_t i = PySequence_Size(headers);
9907 : : if (i < 0)
9908 : : return NULL;
9909 : : if (i > INT_MAX) {
9910 : : PyErr_SetString(PyExc_OverflowError,
9911 : : "sendfile() header is too large");
9912 : : return NULL;
9913 : : }
9914 : : if (i > 0) {
9915 : : sf.hdr_cnt = (int)i;
9916 : : if (iov_setup(&(sf.headers), &hbuf,
9917 : : headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9918 : : return NULL;
9919 : : #ifdef __APPLE__
9920 : : for (i = 0; i < sf.hdr_cnt; i++) {
9921 : : Py_ssize_t blen = sf.headers[i].iov_len;
9922 : : # define OFF_T_MAX 0x7fffffffffffffff
9923 : : if (sbytes >= OFF_T_MAX - blen) {
9924 : : PyErr_SetString(PyExc_OverflowError,
9925 : : "sendfile() header is too large");
9926 : : return NULL;
9927 : : }
9928 : : sbytes += blen;
9929 : : }
9930 : : #endif
9931 : : }
9932 : : }
9933 : : }
9934 : : if (trailers != NULL) {
9935 : : if (!PySequence_Check(trailers)) {
9936 : : PyErr_SetString(PyExc_TypeError,
9937 : : "sendfile() trailers must be a sequence");
9938 : : return NULL;
9939 : : } else {
9940 : : Py_ssize_t i = PySequence_Size(trailers);
9941 : : if (i < 0)
9942 : : return NULL;
9943 : : if (i > INT_MAX) {
9944 : : PyErr_SetString(PyExc_OverflowError,
9945 : : "sendfile() trailer is too large");
9946 : : return NULL;
9947 : : }
9948 : : if (i > 0) {
9949 : : sf.trl_cnt = (int)i;
9950 : : if (iov_setup(&(sf.trailers), &tbuf,
9951 : : trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
9952 : : return NULL;
9953 : : }
9954 : : }
9955 : : }
9956 : :
9957 : : _Py_BEGIN_SUPPRESS_IPH
9958 : : do {
9959 : : Py_BEGIN_ALLOW_THREADS
9960 : : #ifdef __APPLE__
9961 : : ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
9962 : : #else
9963 : : ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
9964 : : #endif
9965 : : Py_END_ALLOW_THREADS
9966 : : } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9967 : : _Py_END_SUPPRESS_IPH
9968 : :
9969 : : if (sf.headers != NULL)
9970 : : iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
9971 : : if (sf.trailers != NULL)
9972 : : iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
9973 : :
9974 : : if (ret < 0) {
9975 : : if ((errno == EAGAIN) || (errno == EBUSY)) {
9976 : : if (sbytes != 0) {
9977 : : // some data has been sent
9978 : : goto done;
9979 : : }
9980 : : else {
9981 : : // no data has been sent; upper application is supposed
9982 : : // to retry on EAGAIN or EBUSY
9983 : : return posix_error();
9984 : : }
9985 : : }
9986 : : return (!async_err) ? posix_error() : NULL;
9987 : : }
9988 : : goto done;
9989 : :
9990 : : done:
9991 : : #if !defined(HAVE_LARGEFILE_SUPPORT)
9992 : : return Py_BuildValue("l", sbytes);
9993 : : #else
9994 : : return Py_BuildValue("L", sbytes);
9995 : : #endif
9996 : :
9997 : : #else
9998 : : #ifdef __linux__
9999 [ - + ]: 41183 : if (offobj == Py_None) {
10000 : : do {
10001 : 0 : Py_BEGIN_ALLOW_THREADS
10002 : 0 : ret = sendfile(out_fd, in_fd, NULL, count);
10003 : 0 : Py_END_ALLOW_THREADS
10004 [ # # # # : 0 : } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
# # ]
10005 [ # # ]: 0 : if (ret < 0)
10006 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
10007 : 0 : return Py_BuildValue("n", ret);
10008 : : }
10009 : : #endif
10010 : : off_t offset;
10011 [ - + ]: 41183 : if (!Py_off_t_converter(offobj, &offset))
10012 : 0 : return NULL;
10013 : :
10014 : : #if defined(__sun) && defined(__SVR4)
10015 : : // On Solaris, sendfile raises EINVAL rather than returning 0
10016 : : // when the offset is equal or bigger than the in_fd size.
10017 : : struct stat st;
10018 : :
10019 : : do {
10020 : : Py_BEGIN_ALLOW_THREADS
10021 : : ret = fstat(in_fd, &st);
10022 : : Py_END_ALLOW_THREADS
10023 : : } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10024 : : if (ret < 0)
10025 : : return (!async_err) ? posix_error() : NULL;
10026 : :
10027 : : if (offset >= st.st_size) {
10028 : : return Py_BuildValue("i", 0);
10029 : : }
10030 : :
10031 : : // On illumos specifically sendfile() may perform a partial write but
10032 : : // return -1/an error (in one confirmed case the destination socket
10033 : : // had a 5 second timeout set and errno was EAGAIN) and it's on the client
10034 : : // code to check if the offset parameter was modified by sendfile().
10035 : : //
10036 : : // We need this variable to track said change.
10037 : : off_t original_offset = offset;
10038 : : #endif
10039 : :
10040 : : do {
10041 : 41183 : Py_BEGIN_ALLOW_THREADS
10042 : 41183 : ret = sendfile(out_fd, in_fd, &offset, count);
10043 : : #if defined(__sun) && defined(__SVR4)
10044 : : // This handles illumos-specific sendfile() partial write behavior,
10045 : : // see a comment above for more details.
10046 : : if (ret < 0 && offset != original_offset) {
10047 : : ret = offset - original_offset;
10048 : : }
10049 : : #endif
10050 : 41183 : Py_END_ALLOW_THREADS
10051 [ + + - + : 41183 : } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
10052 [ + + ]: 41183 : if (ret < 0)
10053 [ + - ]: 6 : return (!async_err) ? posix_error() : NULL;
10054 : 41177 : return Py_BuildValue("n", ret);
10055 : : #endif
10056 : : }
10057 : : #endif /* HAVE_SENDFILE */
10058 : :
10059 : :
10060 : : #if defined(__APPLE__)
10061 : : /*[clinic input]
10062 : : os._fcopyfile
10063 : :
10064 : : in_fd: int
10065 : : out_fd: int
10066 : : flags: int
10067 : : /
10068 : :
10069 : : Efficiently copy content or metadata of 2 regular file descriptors (macOS).
10070 : : [clinic start generated code]*/
10071 : :
10072 : : static PyObject *
10073 : : os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
10074 : : /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
10075 : : {
10076 : : int ret;
10077 : :
10078 : : Py_BEGIN_ALLOW_THREADS
10079 : : ret = fcopyfile(in_fd, out_fd, NULL, flags);
10080 : : Py_END_ALLOW_THREADS
10081 : : if (ret < 0)
10082 : : return posix_error();
10083 : : Py_RETURN_NONE;
10084 : : }
10085 : : #endif
10086 : :
10087 : :
10088 : : /*[clinic input]
10089 : : os.fstat
10090 : :
10091 : : fd : int
10092 : :
10093 : : Perform a stat system call on the given file descriptor.
10094 : :
10095 : : Like stat(), but for an open file descriptor.
10096 : : Equivalent to os.stat(fd).
10097 : : [clinic start generated code]*/
10098 : :
10099 : : static PyObject *
10100 : 57989 : os_fstat_impl(PyObject *module, int fd)
10101 : : /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
10102 : : {
10103 : : STRUCT_STAT st;
10104 : : int res;
10105 : 57989 : int async_err = 0;
10106 : :
10107 : : do {
10108 : 57989 : Py_BEGIN_ALLOW_THREADS
10109 : 57989 : res = FSTAT(fd, &st);
10110 : 57989 : Py_END_ALLOW_THREADS
10111 [ + + - + : 57989 : } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
10112 [ + + ]: 57989 : if (res != 0) {
10113 : : #ifdef MS_WINDOWS
10114 : : return PyErr_SetFromWindowsErr(0);
10115 : : #else
10116 [ + - ]: 16611 : return (!async_err) ? posix_error() : NULL;
10117 : : #endif
10118 : : }
10119 : :
10120 : 41378 : return _pystat_fromstructstat(module, &st);
10121 : : }
10122 : :
10123 : :
10124 : : /*[clinic input]
10125 : : os.isatty -> bool
10126 : : fd: int
10127 : : /
10128 : :
10129 : : Return True if the fd is connected to a terminal.
10130 : :
10131 : : Return True if the file descriptor is an open file descriptor
10132 : : connected to the slave end of a terminal.
10133 : : [clinic start generated code]*/
10134 : :
10135 : : static int
10136 : 3604 : os_isatty_impl(PyObject *module, int fd)
10137 : : /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
10138 : : {
10139 : : int return_value;
10140 : 3604 : Py_BEGIN_ALLOW_THREADS
10141 : : _Py_BEGIN_SUPPRESS_IPH
10142 : 3604 : return_value = isatty(fd);
10143 : : _Py_END_SUPPRESS_IPH
10144 : 3604 : Py_END_ALLOW_THREADS
10145 : 3604 : return return_value;
10146 : : }
10147 : :
10148 : :
10149 : : #ifdef HAVE_PIPE
10150 : : /*[clinic input]
10151 : : os.pipe
10152 : :
10153 : : Create a pipe.
10154 : :
10155 : : Returns a tuple of two file descriptors:
10156 : : (read_fd, write_fd)
10157 : : [clinic start generated code]*/
10158 : :
10159 : : static PyObject *
10160 : 20972 : os_pipe_impl(PyObject *module)
10161 : : /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
10162 : : {
10163 : : int fds[2];
10164 : : #ifdef MS_WINDOWS
10165 : : HANDLE read, write;
10166 : : SECURITY_ATTRIBUTES attr;
10167 : : BOOL ok;
10168 : : #else
10169 : : int res;
10170 : : #endif
10171 : :
10172 : : #ifdef MS_WINDOWS
10173 : : attr.nLength = sizeof(attr);
10174 : : attr.lpSecurityDescriptor = NULL;
10175 : : attr.bInheritHandle = FALSE;
10176 : :
10177 : : Py_BEGIN_ALLOW_THREADS
10178 : : ok = CreatePipe(&read, &write, &attr, 0);
10179 : : if (ok) {
10180 : : fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY);
10181 : : fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY);
10182 : : if (fds[0] == -1 || fds[1] == -1) {
10183 : : CloseHandle(read);
10184 : : CloseHandle(write);
10185 : : ok = 0;
10186 : : }
10187 : : }
10188 : : Py_END_ALLOW_THREADS
10189 : :
10190 : : if (!ok)
10191 : : return PyErr_SetFromWindowsErr(0);
10192 : : #else
10193 : :
10194 : : #ifdef HAVE_PIPE2
10195 : 20972 : Py_BEGIN_ALLOW_THREADS
10196 : 20972 : res = pipe2(fds, O_CLOEXEC);
10197 : 20972 : Py_END_ALLOW_THREADS
10198 : :
10199 [ - + - - ]: 20972 : if (res != 0 && errno == ENOSYS)
10200 : : {
10201 : : #endif
10202 : 0 : Py_BEGIN_ALLOW_THREADS
10203 : 0 : res = pipe(fds);
10204 : 0 : Py_END_ALLOW_THREADS
10205 : :
10206 [ # # ]: 0 : if (res == 0) {
10207 [ # # ]: 0 : if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
10208 : 0 : close(fds[0]);
10209 : 0 : close(fds[1]);
10210 : 0 : return NULL;
10211 : : }
10212 [ # # ]: 0 : if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
10213 : 0 : close(fds[0]);
10214 : 0 : close(fds[1]);
10215 : 0 : return NULL;
10216 : : }
10217 : : }
10218 : : #ifdef HAVE_PIPE2
10219 : : }
10220 : : #endif
10221 : :
10222 [ - + ]: 20972 : if (res != 0)
10223 : 0 : return PyErr_SetFromErrno(PyExc_OSError);
10224 : : #endif /* !MS_WINDOWS */
10225 : 20972 : return Py_BuildValue("(ii)", fds[0], fds[1]);
10226 : : }
10227 : : #endif /* HAVE_PIPE */
10228 : :
10229 : :
10230 : : #ifdef HAVE_PIPE2
10231 : : /*[clinic input]
10232 : : os.pipe2
10233 : :
10234 : : flags: int
10235 : : /
10236 : :
10237 : : Create a pipe with flags set atomically.
10238 : :
10239 : : Returns a tuple of two file descriptors:
10240 : : (read_fd, write_fd)
10241 : :
10242 : : flags can be constructed by ORing together one or more of these values:
10243 : : O_NONBLOCK, O_CLOEXEC.
10244 : : [clinic start generated code]*/
10245 : :
10246 : : static PyObject *
10247 : 2 : os_pipe2_impl(PyObject *module, int flags)
10248 : : /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
10249 : : {
10250 : : int fds[2];
10251 : : int res;
10252 : :
10253 : 2 : res = pipe2(fds, flags);
10254 [ - + ]: 2 : if (res != 0)
10255 : 0 : return posix_error();
10256 : 2 : return Py_BuildValue("(ii)", fds[0], fds[1]);
10257 : : }
10258 : : #endif /* HAVE_PIPE2 */
10259 : :
10260 : :
10261 : : #ifdef HAVE_WRITEV
10262 : : /*[clinic input]
10263 : : os.writev -> Py_ssize_t
10264 : : fd: int
10265 : : buffers: object
10266 : : /
10267 : :
10268 : : Iterate over buffers, and write the contents of each to a file descriptor.
10269 : :
10270 : : Returns the total number of bytes written.
10271 : : buffers must be a sequence of bytes-like objects.
10272 : : [clinic start generated code]*/
10273 : :
10274 : : static Py_ssize_t
10275 : 3 : os_writev_impl(PyObject *module, int fd, PyObject *buffers)
10276 : : /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
10277 : : {
10278 : : Py_ssize_t cnt;
10279 : : Py_ssize_t result;
10280 : 3 : int async_err = 0;
10281 : : struct iovec *iov;
10282 : : Py_buffer *buf;
10283 : :
10284 [ - + ]: 3 : if (!PySequence_Check(buffers)) {
10285 : 0 : PyErr_SetString(PyExc_TypeError,
10286 : : "writev() arg 2 must be a sequence");
10287 : 0 : return -1;
10288 : : }
10289 : 3 : cnt = PySequence_Size(buffers);
10290 [ - + ]: 3 : if (cnt < 0)
10291 : 0 : return -1;
10292 : :
10293 [ - + ]: 3 : if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10294 : 0 : return -1;
10295 : : }
10296 : :
10297 : : do {
10298 : 3 : Py_BEGIN_ALLOW_THREADS
10299 : 3 : result = writev(fd, iov, cnt);
10300 : 3 : Py_END_ALLOW_THREADS
10301 [ + + - + : 3 : } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
10302 : :
10303 : 3 : iov_cleanup(iov, buf, cnt);
10304 [ + + + - ]: 3 : if (result < 0 && !async_err)
10305 : 1 : posix_error();
10306 : :
10307 : 3 : return result;
10308 : : }
10309 : : #endif /* HAVE_WRITEV */
10310 : :
10311 : :
10312 : : #ifdef HAVE_PWRITE
10313 : : /*[clinic input]
10314 : : os.pwrite -> Py_ssize_t
10315 : :
10316 : : fd: int
10317 : : buffer: Py_buffer
10318 : : offset: Py_off_t
10319 : : /
10320 : :
10321 : : Write bytes to a file descriptor starting at a particular offset.
10322 : :
10323 : : Write buffer to fd, starting at offset bytes from the beginning of
10324 : : the file. Returns the number of bytes writte. Does not change the
10325 : : current file offset.
10326 : : [clinic start generated code]*/
10327 : :
10328 : : static Py_ssize_t
10329 : 1 : os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
10330 : : /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
10331 : : {
10332 : : Py_ssize_t size;
10333 : 1 : int async_err = 0;
10334 : :
10335 : : do {
10336 : 1 : Py_BEGIN_ALLOW_THREADS
10337 : : _Py_BEGIN_SUPPRESS_IPH
10338 : 1 : size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
10339 : : _Py_END_SUPPRESS_IPH
10340 : 1 : Py_END_ALLOW_THREADS
10341 [ - + - - : 1 : } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
10342 : :
10343 [ - + - - ]: 1 : if (size < 0 && !async_err)
10344 : 0 : posix_error();
10345 : 1 : return size;
10346 : : }
10347 : : #endif /* HAVE_PWRITE */
10348 : :
10349 : : #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
10350 : : /*[clinic input]
10351 : : os.pwritev -> Py_ssize_t
10352 : :
10353 : : fd: int
10354 : : buffers: object
10355 : : offset: Py_off_t
10356 : : flags: int = 0
10357 : : /
10358 : :
10359 : : Writes the contents of bytes-like objects to a file descriptor at a given offset.
10360 : :
10361 : : Combines the functionality of writev() and pwrite(). All buffers must be a sequence
10362 : : of bytes-like objects. Buffers are processed in array order. Entire contents of first
10363 : : buffer is written before proceeding to second, and so on. The operating system may
10364 : : set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
10365 : : This function writes the contents of each object to the file descriptor and returns
10366 : : the total number of bytes written.
10367 : :
10368 : : The flags argument contains a bitwise OR of zero or more of the following flags:
10369 : :
10370 : : - RWF_DSYNC
10371 : : - RWF_SYNC
10372 : : - RWF_APPEND
10373 : :
10374 : : Using non-zero flags requires Linux 4.7 or newer.
10375 : : [clinic start generated code]*/
10376 : :
10377 : : static Py_ssize_t
10378 : 1 : os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
10379 : : int flags)
10380 : : /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
10381 : : {
10382 : : Py_ssize_t cnt;
10383 : : Py_ssize_t result;
10384 : 1 : int async_err = 0;
10385 : : struct iovec *iov;
10386 : : Py_buffer *buf;
10387 : :
10388 [ - + ]: 1 : if (!PySequence_Check(buffers)) {
10389 : 0 : PyErr_SetString(PyExc_TypeError,
10390 : : "pwritev() arg 2 must be a sequence");
10391 : 0 : return -1;
10392 : : }
10393 : :
10394 : 1 : cnt = PySequence_Size(buffers);
10395 [ - + ]: 1 : if (cnt < 0) {
10396 : 0 : return -1;
10397 : : }
10398 : :
10399 : : #ifndef HAVE_PWRITEV2
10400 : : if(flags != 0) {
10401 : : argument_unavailable_error("pwritev2", "flags");
10402 : : return -1;
10403 : : }
10404 : : #endif
10405 : :
10406 [ - + ]: 1 : if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10407 : 0 : return -1;
10408 : : }
10409 : : #ifdef HAVE_PWRITEV2
10410 : : do {
10411 : 1 : Py_BEGIN_ALLOW_THREADS
10412 : : _Py_BEGIN_SUPPRESS_IPH
10413 : 1 : result = pwritev2(fd, iov, cnt, offset, flags);
10414 : : _Py_END_SUPPRESS_IPH
10415 : 1 : Py_END_ALLOW_THREADS
10416 [ - + - - : 1 : } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
10417 : : #else
10418 : :
10419 : : #ifdef __APPLE__
10420 : : /* This entire function will be removed from the module dict when the API
10421 : : * is not available.
10422 : : */
10423 : : #pragma clang diagnostic push
10424 : : #pragma clang diagnostic ignored "-Wunguarded-availability"
10425 : : #pragma clang diagnostic ignored "-Wunguarded-availability-new"
10426 : : #endif
10427 : : do {
10428 : : Py_BEGIN_ALLOW_THREADS
10429 : : _Py_BEGIN_SUPPRESS_IPH
10430 : : result = pwritev(fd, iov, cnt, offset);
10431 : : _Py_END_SUPPRESS_IPH
10432 : : Py_END_ALLOW_THREADS
10433 : : } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10434 : :
10435 : : #ifdef __APPLE__
10436 : : #pragma clang diagnostic pop
10437 : : #endif
10438 : :
10439 : : #endif
10440 : :
10441 : 1 : iov_cleanup(iov, buf, cnt);
10442 [ - + ]: 1 : if (result < 0) {
10443 [ # # ]: 0 : if (!async_err) {
10444 : 0 : posix_error();
10445 : : }
10446 : 0 : return -1;
10447 : : }
10448 : :
10449 : 1 : return result;
10450 : : }
10451 : : #endif /* HAVE_PWRITEV */
10452 : :
10453 : : #ifdef HAVE_COPY_FILE_RANGE
10454 : : /*[clinic input]
10455 : :
10456 : : os.copy_file_range
10457 : : src: int
10458 : : Source file descriptor.
10459 : : dst: int
10460 : : Destination file descriptor.
10461 : : count: Py_ssize_t
10462 : : Number of bytes to copy.
10463 : : offset_src: object = None
10464 : : Starting offset in src.
10465 : : offset_dst: object = None
10466 : : Starting offset in dst.
10467 : :
10468 : : Copy count bytes from one file descriptor to another.
10469 : :
10470 : : If offset_src is None, then src is read from the current position;
10471 : : respectively for offset_dst.
10472 : : [clinic start generated code]*/
10473 : :
10474 : : static PyObject *
10475 : 3 : os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10476 : : PyObject *offset_src, PyObject *offset_dst)
10477 : : /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
10478 : : {
10479 : : off_t offset_src_val, offset_dst_val;
10480 : 3 : off_t *p_offset_src = NULL;
10481 : 3 : off_t *p_offset_dst = NULL;
10482 : : Py_ssize_t ret;
10483 : 3 : int async_err = 0;
10484 : : /* The flags argument is provided to allow
10485 : : * for future extensions and currently must be to 0. */
10486 : 3 : int flags = 0;
10487 : :
10488 : :
10489 [ + + ]: 3 : if (count < 0) {
10490 : 1 : PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10491 : 1 : return NULL;
10492 : : }
10493 : :
10494 [ + + ]: 2 : if (offset_src != Py_None) {
10495 [ - + ]: 1 : if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10496 : 0 : return NULL;
10497 : : }
10498 : 1 : p_offset_src = &offset_src_val;
10499 : : }
10500 : :
10501 [ + + ]: 2 : if (offset_dst != Py_None) {
10502 [ - + ]: 1 : if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10503 : 0 : return NULL;
10504 : : }
10505 : 1 : p_offset_dst = &offset_dst_val;
10506 : : }
10507 : :
10508 : : do {
10509 : 2 : Py_BEGIN_ALLOW_THREADS
10510 : 2 : ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
10511 : 2 : Py_END_ALLOW_THREADS
10512 [ - + - - : 2 : } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
10513 : :
10514 [ - + ]: 2 : if (ret < 0) {
10515 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
10516 : : }
10517 : :
10518 : 2 : return PyLong_FromSsize_t(ret);
10519 : : }
10520 : : #endif /* HAVE_COPY_FILE_RANGE*/
10521 : :
10522 : : #if (defined(HAVE_SPLICE) && !defined(_AIX))
10523 : : /*[clinic input]
10524 : :
10525 : : os.splice
10526 : : src: int
10527 : : Source file descriptor.
10528 : : dst: int
10529 : : Destination file descriptor.
10530 : : count: Py_ssize_t
10531 : : Number of bytes to copy.
10532 : : offset_src: object = None
10533 : : Starting offset in src.
10534 : : offset_dst: object = None
10535 : : Starting offset in dst.
10536 : : flags: unsigned_int = 0
10537 : : Flags to modify the semantics of the call.
10538 : :
10539 : : Transfer count bytes from one pipe to a descriptor or vice versa.
10540 : :
10541 : : If offset_src is None, then src is read from the current position;
10542 : : respectively for offset_dst. The offset associated to the file
10543 : : descriptor that refers to a pipe must be None.
10544 : : [clinic start generated code]*/
10545 : :
10546 : : static PyObject *
10547 : 4 : os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10548 : : PyObject *offset_src, PyObject *offset_dst,
10549 : : unsigned int flags)
10550 : : /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
10551 : : {
10552 : : off_t offset_src_val, offset_dst_val;
10553 : 4 : off_t *p_offset_src = NULL;
10554 : 4 : off_t *p_offset_dst = NULL;
10555 : : Py_ssize_t ret;
10556 : 4 : int async_err = 0;
10557 : :
10558 [ + + ]: 4 : if (count < 0) {
10559 : 1 : PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10560 : 1 : return NULL;
10561 : : }
10562 : :
10563 [ + + ]: 3 : if (offset_src != Py_None) {
10564 [ - + ]: 1 : if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10565 : 0 : return NULL;
10566 : : }
10567 : 1 : p_offset_src = &offset_src_val;
10568 : : }
10569 : :
10570 [ + + ]: 3 : if (offset_dst != Py_None) {
10571 [ - + ]: 1 : if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10572 : 0 : return NULL;
10573 : : }
10574 : 1 : p_offset_dst = &offset_dst_val;
10575 : : }
10576 : :
10577 : : do {
10578 : 3 : Py_BEGIN_ALLOW_THREADS
10579 : 3 : ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
10580 : 3 : Py_END_ALLOW_THREADS
10581 [ - + - - : 3 : } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- - ]
10582 : :
10583 [ - + ]: 3 : if (ret < 0) {
10584 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
10585 : : }
10586 : :
10587 : 3 : return PyLong_FromSsize_t(ret);
10588 : : }
10589 : : #endif /* HAVE_SPLICE*/
10590 : :
10591 : : #ifdef HAVE_MKFIFO
10592 : : /*[clinic input]
10593 : : os.mkfifo
10594 : :
10595 : : path: path_t
10596 : : mode: int=0o666
10597 : : *
10598 : : dir_fd: dir_fd(requires='mkfifoat')=None
10599 : :
10600 : : Create a "fifo" (a POSIX named pipe).
10601 : :
10602 : : If dir_fd is not None, it should be a file descriptor open to a directory,
10603 : : and path should be relative; path will then be relative to that directory.
10604 : : dir_fd may not be implemented on your platform.
10605 : : If it is unavailable, using it will raise a NotImplementedError.
10606 : : [clinic start generated code]*/
10607 : :
10608 : : static PyObject *
10609 : 10 : os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
10610 : : /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
10611 : : {
10612 : : int result;
10613 : 10 : int async_err = 0;
10614 : :
10615 : : do {
10616 : 10 : Py_BEGIN_ALLOW_THREADS
10617 : : #ifdef HAVE_MKFIFOAT
10618 [ + + ]: 10 : if (dir_fd != DEFAULT_DIR_FD)
10619 : 1 : result = mkfifoat(dir_fd, path->narrow, mode);
10620 : : else
10621 : : #endif
10622 : 9 : result = mkfifo(path->narrow, mode);
10623 : 10 : Py_END_ALLOW_THREADS
10624 [ - + - - : 10 : } while (result != 0 && errno == EINTR &&
- - ]
10625 : 0 : !(async_err = PyErr_CheckSignals()));
10626 [ - + ]: 10 : if (result != 0)
10627 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
10628 : :
10629 : 10 : Py_RETURN_NONE;
10630 : : }
10631 : : #endif /* HAVE_MKFIFO */
10632 : :
10633 : :
10634 : : #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
10635 : : /*[clinic input]
10636 : : os.mknod
10637 : :
10638 : : path: path_t
10639 : : mode: int=0o600
10640 : : device: dev_t=0
10641 : : *
10642 : : dir_fd: dir_fd(requires='mknodat')=None
10643 : :
10644 : : Create a node in the file system.
10645 : :
10646 : : Create a node in the file system (file, device special file or named pipe)
10647 : : at path. mode specifies both the permissions to use and the
10648 : : type of node to be created, being combined (bitwise OR) with one of
10649 : : S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,
10650 : : device defines the newly created device special file (probably using
10651 : : os.makedev()). Otherwise device is ignored.
10652 : :
10653 : : If dir_fd is not None, it should be a file descriptor open to a directory,
10654 : : and path should be relative; path will then be relative to that directory.
10655 : : dir_fd may not be implemented on your platform.
10656 : : If it is unavailable, using it will raise a NotImplementedError.
10657 : : [clinic start generated code]*/
10658 : :
10659 : : static PyObject *
10660 : 3 : os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
10661 : : int dir_fd)
10662 : : /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
10663 : : {
10664 : : int result;
10665 : 3 : int async_err = 0;
10666 : :
10667 : : do {
10668 : 3 : Py_BEGIN_ALLOW_THREADS
10669 : : #ifdef HAVE_MKNODAT
10670 [ + + ]: 3 : if (dir_fd != DEFAULT_DIR_FD)
10671 : 1 : result = mknodat(dir_fd, path->narrow, mode, device);
10672 : : else
10673 : : #endif
10674 : 2 : result = mknod(path->narrow, mode, device);
10675 : 3 : Py_END_ALLOW_THREADS
10676 [ - + - - : 3 : } while (result != 0 && errno == EINTR &&
- - ]
10677 : 0 : !(async_err = PyErr_CheckSignals()));
10678 [ - + ]: 3 : if (result != 0)
10679 [ # # ]: 0 : return (!async_err) ? posix_error() : NULL;
10680 : :
10681 : 3 : Py_RETURN_NONE;
10682 : : }
10683 : : #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
10684 : :
10685 : :
10686 : : #ifdef HAVE_DEVICE_MACROS
10687 : : /*[clinic input]
10688 : : os.major -> unsigned_int
10689 : :
10690 : : device: dev_t
10691 : : /
10692 : :
10693 : : Extracts a device major number from a raw device number.
10694 : : [clinic start generated code]*/
10695 : :
10696 : : static unsigned int
10697 : 2 : os_major_impl(PyObject *module, dev_t device)
10698 : : /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
10699 : : {
10700 : 2 : return major(device);
10701 : : }
10702 : :
10703 : :
10704 : : /*[clinic input]
10705 : : os.minor -> unsigned_int
10706 : :
10707 : : device: dev_t
10708 : : /
10709 : :
10710 : : Extracts a device minor number from a raw device number.
10711 : : [clinic start generated code]*/
10712 : :
10713 : : static unsigned int
10714 : 2 : os_minor_impl(PyObject *module, dev_t device)
10715 : : /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10716 : : {
10717 : 2 : return minor(device);
10718 : : }
10719 : :
10720 : :
10721 : : /*[clinic input]
10722 : : os.makedev -> dev_t
10723 : :
10724 : : major: int
10725 : : minor: int
10726 : : /
10727 : :
10728 : : Composes a raw device number from the major and minor device numbers.
10729 : : [clinic start generated code]*/
10730 : :
10731 : : static dev_t
10732 : 1 : os_makedev_impl(PyObject *module, int major, int minor)
10733 : : /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10734 : : {
10735 : 1 : return makedev(major, minor);
10736 : : }
10737 : : #endif /* HAVE_DEVICE_MACROS */
10738 : :
10739 : :
10740 : : #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10741 : : /*[clinic input]
10742 : : os.ftruncate
10743 : :
10744 : : fd: int
10745 : : length: Py_off_t
10746 : : /
10747 : :
10748 : : Truncate a file, specified by file descriptor, to a specific length.
10749 : : [clinic start generated code]*/
10750 : :
10751 : : static PyObject *
10752 : 286 : os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10753 : : /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10754 : : {
10755 : : int result;
10756 : 286 : int async_err = 0;
10757 : :
10758 [ - + ]: 286 : if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10759 : 0 : return NULL;
10760 : : }
10761 : :
10762 : : do {
10763 : 286 : Py_BEGIN_ALLOW_THREADS
10764 : : _Py_BEGIN_SUPPRESS_IPH
10765 : : #ifdef MS_WINDOWS
10766 : : result = _chsize_s(fd, length);
10767 : : #else
10768 : 286 : result = ftruncate(fd, length);
10769 : : #endif
10770 : : _Py_END_SUPPRESS_IPH
10771 : 286 : Py_END_ALLOW_THREADS
10772 [ + + - + : 286 : } while (result != 0 && errno == EINTR &&
- - ]
10773 : 0 : !(async_err = PyErr_CheckSignals()));
10774 [ + + ]: 286 : if (result != 0)
10775 [ + - ]: 4 : return (!async_err) ? posix_error() : NULL;
10776 : 282 : Py_RETURN_NONE;
10777 : : }
10778 : : #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10779 : :
10780 : :
10781 : : #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10782 : : /*[clinic input]
10783 : : os.truncate
10784 : : path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10785 : : length: Py_off_t
10786 : :
10787 : : Truncate a file, specified by path, to a specific length.
10788 : :
10789 : : On some platforms, path may also be specified as an open file descriptor.
10790 : : If this functionality is unavailable, using it raises an exception.
10791 : : [clinic start generated code]*/
10792 : :
10793 : : static PyObject *
10794 : 7 : os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10795 : : /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10796 : : {
10797 : : int result;
10798 : : #ifdef MS_WINDOWS
10799 : : int fd;
10800 : : #endif
10801 : :
10802 [ + + ]: 7 : if (path->fd != -1)
10803 : 1 : return os_ftruncate_impl(module, path->fd, length);
10804 : :
10805 [ - + ]: 6 : if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10806 : 0 : return NULL;
10807 : : }
10808 : :
10809 : 6 : Py_BEGIN_ALLOW_THREADS
10810 : : _Py_BEGIN_SUPPRESS_IPH
10811 : : #ifdef MS_WINDOWS
10812 : : fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10813 : : if (fd < 0)
10814 : : result = -1;
10815 : : else {
10816 : : result = _chsize_s(fd, length);
10817 : : close(fd);
10818 : : if (result < 0)
10819 : : errno = result;
10820 : : }
10821 : : #else
10822 : 6 : result = truncate(path->narrow, length);
10823 : : #endif
10824 : : _Py_END_SUPPRESS_IPH
10825 : 6 : Py_END_ALLOW_THREADS
10826 [ + + ]: 6 : if (result < 0)
10827 : 5 : return posix_path_error(path);
10828 : :
10829 : 1 : Py_RETURN_NONE;
10830 : : }
10831 : : #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10832 : :
10833 : :
10834 : : /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10835 : : and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10836 : : defined, which is the case in Python on AIX. AIX bug report:
10837 : : http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10838 : : #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10839 : : # define POSIX_FADVISE_AIX_BUG
10840 : : #endif
10841 : :
10842 : :
10843 : : #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10844 : : /*[clinic input]
10845 : : os.posix_fallocate
10846 : :
10847 : : fd: int
10848 : : offset: Py_off_t
10849 : : length: Py_off_t
10850 : : /
10851 : :
10852 : : Ensure a file has allocated at least a particular number of bytes on disk.
10853 : :
10854 : : Ensure that the file specified by fd encompasses a range of bytes
10855 : : starting at offset bytes from the beginning and continuing for length bytes.
10856 : : [clinic start generated code]*/
10857 : :
10858 : : static PyObject *
10859 : 2 : os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10860 : : Py_off_t length)
10861 : : /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10862 : : {
10863 : : int result;
10864 : 2 : int async_err = 0;
10865 : :
10866 : : do {
10867 : 2 : Py_BEGIN_ALLOW_THREADS
10868 : 2 : result = posix_fallocate(fd, offset, length);
10869 : 2 : Py_END_ALLOW_THREADS
10870 [ - + - - ]: 2 : } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10871 : :
10872 [ + + ]: 2 : if (result == 0)
10873 : 1 : Py_RETURN_NONE;
10874 : :
10875 [ - + ]: 1 : if (async_err)
10876 : 0 : return NULL;
10877 : :
10878 : 1 : errno = result;
10879 : 1 : return posix_error();
10880 : : }
10881 : : #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
10882 : :
10883 : :
10884 : : #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
10885 : : /*[clinic input]
10886 : : os.posix_fadvise
10887 : :
10888 : : fd: int
10889 : : offset: Py_off_t
10890 : : length: Py_off_t
10891 : : advice: int
10892 : : /
10893 : :
10894 : : Announce an intention to access data in a specific pattern.
10895 : :
10896 : : Announce an intention to access data in a specific pattern, thus allowing
10897 : : the kernel to make optimizations.
10898 : : The advice applies to the region of the file specified by fd starting at
10899 : : offset and continuing for length bytes.
10900 : : advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
10901 : : POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
10902 : : POSIX_FADV_DONTNEED.
10903 : : [clinic start generated code]*/
10904 : :
10905 : : static PyObject *
10906 : 2 : os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
10907 : : Py_off_t length, int advice)
10908 : : /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
10909 : : {
10910 : : int result;
10911 : 2 : int async_err = 0;
10912 : :
10913 : : do {
10914 : 2 : Py_BEGIN_ALLOW_THREADS
10915 : 2 : result = posix_fadvise(fd, offset, length, advice);
10916 : 2 : Py_END_ALLOW_THREADS
10917 [ - + - - ]: 2 : } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10918 : :
10919 [ + + ]: 2 : if (result == 0)
10920 : 1 : Py_RETURN_NONE;
10921 : :
10922 [ - + ]: 1 : if (async_err)
10923 : 0 : return NULL;
10924 : :
10925 : 1 : errno = result;
10926 : 1 : return posix_error();
10927 : : }
10928 : : #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
10929 : :
10930 : :
10931 : : #ifdef MS_WINDOWS
10932 : : static PyObject*
10933 : : win32_putenv(PyObject *name, PyObject *value)
10934 : : {
10935 : : /* Search from index 1 because on Windows starting '=' is allowed for
10936 : : defining hidden environment variables. */
10937 : : if (PyUnicode_GET_LENGTH(name) == 0 ||
10938 : : PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
10939 : : {
10940 : : PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10941 : : return NULL;
10942 : : }
10943 : : PyObject *unicode;
10944 : : if (value != NULL) {
10945 : : unicode = PyUnicode_FromFormat("%U=%U", name, value);
10946 : : }
10947 : : else {
10948 : : unicode = PyUnicode_FromFormat("%U=", name);
10949 : : }
10950 : : if (unicode == NULL) {
10951 : : return NULL;
10952 : : }
10953 : :
10954 : : Py_ssize_t size;
10955 : : /* PyUnicode_AsWideCharString() rejects embedded null characters */
10956 : : wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
10957 : : Py_DECREF(unicode);
10958 : :
10959 : : if (env == NULL) {
10960 : : return NULL;
10961 : : }
10962 : : if (size > _MAX_ENV) {
10963 : : PyErr_Format(PyExc_ValueError,
10964 : : "the environment variable is longer than %u characters",
10965 : : _MAX_ENV);
10966 : : PyMem_Free(env);
10967 : : return NULL;
10968 : : }
10969 : :
10970 : : /* _wputenv() and SetEnvironmentVariableW() update the environment in the
10971 : : Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
10972 : : and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
10973 : :
10974 : : Prefer _wputenv() to be compatible with C libraries using CRT
10975 : : variables and CRT functions using these variables (ex: getenv()). */
10976 : : int err = _wputenv(env);
10977 : : PyMem_Free(env);
10978 : :
10979 : : if (err) {
10980 : : posix_error();
10981 : : return NULL;
10982 : : }
10983 : :
10984 : : Py_RETURN_NONE;
10985 : : }
10986 : : #endif
10987 : :
10988 : :
10989 : : #ifdef MS_WINDOWS
10990 : : /*[clinic input]
10991 : : os.putenv
10992 : :
10993 : : name: unicode
10994 : : value: unicode
10995 : : /
10996 : :
10997 : : Change or add an environment variable.
10998 : : [clinic start generated code]*/
10999 : :
11000 : : static PyObject *
11001 : : os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11002 : : /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
11003 : : {
11004 : : if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11005 : : return NULL;
11006 : : }
11007 : : return win32_putenv(name, value);
11008 : : }
11009 : : #else
11010 : : /*[clinic input]
11011 : : os.putenv
11012 : :
11013 : : name: FSConverter
11014 : : value: FSConverter
11015 : : /
11016 : :
11017 : : Change or add an environment variable.
11018 : : [clinic start generated code]*/
11019 : :
11020 : : static PyObject *
11021 : 13153 : os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11022 : : /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
11023 : : {
11024 : 13153 : const char *name_string = PyBytes_AS_STRING(name);
11025 : 13153 : const char *value_string = PyBytes_AS_STRING(value);
11026 : :
11027 [ + + ]: 13153 : if (strchr(name_string, '=') != NULL) {
11028 : 5 : PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11029 : 5 : return NULL;
11030 : : }
11031 : :
11032 [ - + ]: 13148 : if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11033 : 0 : return NULL;
11034 : : }
11035 : :
11036 [ + + ]: 13148 : if (setenv(name_string, value_string, 1)) {
11037 : 1 : return posix_error();
11038 : : }
11039 : 13147 : Py_RETURN_NONE;
11040 : : }
11041 : : #endif /* !defined(MS_WINDOWS) */
11042 : :
11043 : :
11044 : : #ifdef MS_WINDOWS
11045 : : /*[clinic input]
11046 : : os.unsetenv
11047 : : name: unicode
11048 : : /
11049 : :
11050 : : Delete an environment variable.
11051 : : [clinic start generated code]*/
11052 : :
11053 : : static PyObject *
11054 : : os_unsetenv_impl(PyObject *module, PyObject *name)
11055 : : /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
11056 : : {
11057 : : if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11058 : : return NULL;
11059 : : }
11060 : : return win32_putenv(name, NULL);
11061 : : }
11062 : : #else
11063 : : /*[clinic input]
11064 : : os.unsetenv
11065 : : name: FSConverter
11066 : : /
11067 : :
11068 : : Delete an environment variable.
11069 : : [clinic start generated code]*/
11070 : :
11071 : : static PyObject *
11072 : 12663 : os_unsetenv_impl(PyObject *module, PyObject *name)
11073 : : /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
11074 : : {
11075 [ - + ]: 12663 : if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11076 : 0 : return NULL;
11077 : : }
11078 : : #ifdef HAVE_BROKEN_UNSETENV
11079 : : unsetenv(PyBytes_AS_STRING(name));
11080 : : #else
11081 : 12663 : int err = unsetenv(PyBytes_AS_STRING(name));
11082 [ + + ]: 12663 : if (err) {
11083 : 4 : return posix_error();
11084 : : }
11085 : : #endif
11086 : :
11087 : 12659 : Py_RETURN_NONE;
11088 : : }
11089 : : #endif /* !MS_WINDOWS */
11090 : :
11091 : :
11092 : : /*[clinic input]
11093 : : os.strerror
11094 : :
11095 : : code: int
11096 : : /
11097 : :
11098 : : Translate an error code to a message string.
11099 : : [clinic start generated code]*/
11100 : :
11101 : : static PyObject *
11102 : 2091 : os_strerror_impl(PyObject *module, int code)
11103 : : /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
11104 : : {
11105 : 2091 : char *message = strerror(code);
11106 [ - + ]: 2091 : if (message == NULL) {
11107 : 0 : PyErr_SetString(PyExc_ValueError,
11108 : : "strerror() argument out of range");
11109 : 0 : return NULL;
11110 : : }
11111 : 2091 : return PyUnicode_DecodeLocale(message, "surrogateescape");
11112 : : }
11113 : :
11114 : :
11115 : : #ifdef HAVE_SYS_WAIT_H
11116 : : #ifdef WCOREDUMP
11117 : : /*[clinic input]
11118 : : os.WCOREDUMP -> bool
11119 : :
11120 : : status: int
11121 : : /
11122 : :
11123 : : Return True if the process returning status was dumped to a core file.
11124 : : [clinic start generated code]*/
11125 : :
11126 : : static int
11127 : 0 : os_WCOREDUMP_impl(PyObject *module, int status)
11128 : : /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
11129 : : {
11130 : : WAIT_TYPE wait_status;
11131 : 0 : WAIT_STATUS_INT(wait_status) = status;
11132 : 0 : return WCOREDUMP(wait_status);
11133 : : }
11134 : : #endif /* WCOREDUMP */
11135 : :
11136 : :
11137 : : #ifdef WIFCONTINUED
11138 : : /*[clinic input]
11139 : : os.WIFCONTINUED -> bool
11140 : :
11141 : : status: int
11142 : :
11143 : : Return True if a particular process was continued from a job control stop.
11144 : :
11145 : : Return True if the process returning status was continued from a
11146 : : job control stop.
11147 : : [clinic start generated code]*/
11148 : :
11149 : : static int
11150 : 0 : os_WIFCONTINUED_impl(PyObject *module, int status)
11151 : : /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
11152 : : {
11153 : : WAIT_TYPE wait_status;
11154 : 0 : WAIT_STATUS_INT(wait_status) = status;
11155 : 0 : return WIFCONTINUED(wait_status);
11156 : : }
11157 : : #endif /* WIFCONTINUED */
11158 : :
11159 : :
11160 : : #ifdef WIFSTOPPED
11161 : : /*[clinic input]
11162 : : os.WIFSTOPPED -> bool
11163 : :
11164 : : status: int
11165 : :
11166 : : Return True if the process returning status was stopped.
11167 : : [clinic start generated code]*/
11168 : :
11169 : : static int
11170 : 4875 : os_WIFSTOPPED_impl(PyObject *module, int status)
11171 : : /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
11172 : : {
11173 : : WAIT_TYPE wait_status;
11174 : 4875 : WAIT_STATUS_INT(wait_status) = status;
11175 : 4875 : return WIFSTOPPED(wait_status);
11176 : : }
11177 : : #endif /* WIFSTOPPED */
11178 : :
11179 : :
11180 : : #ifdef WIFSIGNALED
11181 : : /*[clinic input]
11182 : : os.WIFSIGNALED -> bool
11183 : :
11184 : : status: int
11185 : :
11186 : : Return True if the process returning status was terminated by a signal.
11187 : : [clinic start generated code]*/
11188 : :
11189 : : static int
11190 : 0 : os_WIFSIGNALED_impl(PyObject *module, int status)
11191 : : /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
11192 : : {
11193 : : WAIT_TYPE wait_status;
11194 : 0 : WAIT_STATUS_INT(wait_status) = status;
11195 : 0 : return WIFSIGNALED(wait_status);
11196 : : }
11197 : : #endif /* WIFSIGNALED */
11198 : :
11199 : :
11200 : : #ifdef WIFEXITED
11201 : : /*[clinic input]
11202 : : os.WIFEXITED -> bool
11203 : :
11204 : : status: int
11205 : :
11206 : : Return True if the process returning status exited via the exit() system call.
11207 : : [clinic start generated code]*/
11208 : :
11209 : : static int
11210 : 0 : os_WIFEXITED_impl(PyObject *module, int status)
11211 : : /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
11212 : : {
11213 : : WAIT_TYPE wait_status;
11214 : 0 : WAIT_STATUS_INT(wait_status) = status;
11215 : 0 : return WIFEXITED(wait_status);
11216 : : }
11217 : : #endif /* WIFEXITED */
11218 : :
11219 : :
11220 : : #ifdef WEXITSTATUS
11221 : : /*[clinic input]
11222 : : os.WEXITSTATUS -> int
11223 : :
11224 : : status: int
11225 : :
11226 : : Return the process return code from status.
11227 : : [clinic start generated code]*/
11228 : :
11229 : : static int
11230 : 0 : os_WEXITSTATUS_impl(PyObject *module, int status)
11231 : : /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
11232 : : {
11233 : : WAIT_TYPE wait_status;
11234 : 0 : WAIT_STATUS_INT(wait_status) = status;
11235 : 0 : return WEXITSTATUS(wait_status);
11236 : : }
11237 : : #endif /* WEXITSTATUS */
11238 : :
11239 : :
11240 : : #ifdef WTERMSIG
11241 : : /*[clinic input]
11242 : : os.WTERMSIG -> int
11243 : :
11244 : : status: int
11245 : :
11246 : : Return the signal that terminated the process that provided the status value.
11247 : : [clinic start generated code]*/
11248 : :
11249 : : static int
11250 : 0 : os_WTERMSIG_impl(PyObject *module, int status)
11251 : : /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
11252 : : {
11253 : : WAIT_TYPE wait_status;
11254 : 0 : WAIT_STATUS_INT(wait_status) = status;
11255 : 0 : return WTERMSIG(wait_status);
11256 : : }
11257 : : #endif /* WTERMSIG */
11258 : :
11259 : :
11260 : : #ifdef WSTOPSIG
11261 : : /*[clinic input]
11262 : : os.WSTOPSIG -> int
11263 : :
11264 : : status: int
11265 : :
11266 : : Return the signal that stopped the process that provided the status value.
11267 : : [clinic start generated code]*/
11268 : :
11269 : : static int
11270 : 1 : os_WSTOPSIG_impl(PyObject *module, int status)
11271 : : /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
11272 : : {
11273 : : WAIT_TYPE wait_status;
11274 : 1 : WAIT_STATUS_INT(wait_status) = status;
11275 : 1 : return WSTOPSIG(wait_status);
11276 : : }
11277 : : #endif /* WSTOPSIG */
11278 : : #endif /* HAVE_SYS_WAIT_H */
11279 : :
11280 : :
11281 : : #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
11282 : : #ifdef _SCO_DS
11283 : : /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
11284 : : needed definitions in sys/statvfs.h */
11285 : : #define _SVID3
11286 : : #endif
11287 : : #include <sys/statvfs.h>
11288 : :
11289 : : static PyObject*
11290 : 124 : _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
11291 : 124 : PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
11292 : 124 : PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
11293 [ - + ]: 124 : if (v == NULL)
11294 : 0 : return NULL;
11295 : :
11296 : : #if !defined(HAVE_LARGEFILE_SUPPORT)
11297 : 124 : PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11298 : 124 : PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11299 : 124 : PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
11300 : 124 : PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
11301 : 124 : PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
11302 : 124 : PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
11303 : 124 : PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
11304 : 124 : PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
11305 : 124 : PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11306 : 124 : PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11307 : : #else
11308 : : PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11309 : : PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11310 : : PyStructSequence_SET_ITEM(v, 2,
11311 : : PyLong_FromLongLong((long long) st.f_blocks));
11312 : : PyStructSequence_SET_ITEM(v, 3,
11313 : : PyLong_FromLongLong((long long) st.f_bfree));
11314 : : PyStructSequence_SET_ITEM(v, 4,
11315 : : PyLong_FromLongLong((long long) st.f_bavail));
11316 : : PyStructSequence_SET_ITEM(v, 5,
11317 : : PyLong_FromLongLong((long long) st.f_files));
11318 : : PyStructSequence_SET_ITEM(v, 6,
11319 : : PyLong_FromLongLong((long long) st.f_ffree));
11320 : : PyStructSequence_SET_ITEM(v, 7,
11321 : : PyLong_FromLongLong((long long) st.f_favail));
11322 : : PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11323 : : PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11324 : : #endif
11325 : : /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
11326 : : * (issue #32390). */
11327 : : #if defined(_AIX) && defined(_ALL_SOURCE)
11328 : : PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
11329 : : #else
11330 : 124 : PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
11331 : : #endif
11332 [ - + ]: 124 : if (PyErr_Occurred()) {
11333 : 0 : Py_DECREF(v);
11334 : 0 : return NULL;
11335 : : }
11336 : :
11337 : 124 : return v;
11338 : : }
11339 : :
11340 : :
11341 : : /*[clinic input]
11342 : : os.fstatvfs
11343 : : fd: int
11344 : : /
11345 : :
11346 : : Perform an fstatvfs system call on the given fd.
11347 : :
11348 : : Equivalent to statvfs(fd).
11349 : : [clinic start generated code]*/
11350 : :
11351 : : static PyObject *
11352 : 2 : os_fstatvfs_impl(PyObject *module, int fd)
11353 : : /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
11354 : : {
11355 : : int result;
11356 : 2 : int async_err = 0;
11357 : : struct statvfs st;
11358 : :
11359 : : do {
11360 : 2 : Py_BEGIN_ALLOW_THREADS
11361 : 2 : result = fstatvfs(fd, &st);
11362 : 2 : Py_END_ALLOW_THREADS
11363 [ + + - + : 2 : } while (result != 0 && errno == EINTR &&
- - ]
11364 : 0 : !(async_err = PyErr_CheckSignals()));
11365 [ + + ]: 2 : if (result != 0)
11366 [ + - ]: 1 : return (!async_err) ? posix_error() : NULL;
11367 : :
11368 : 1 : return _pystatvfs_fromstructstatvfs(module, st);
11369 : : }
11370 : : #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
11371 : :
11372 : :
11373 : : #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
11374 : : #include <sys/statvfs.h>
11375 : : /*[clinic input]
11376 : : os.statvfs
11377 : :
11378 : : path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
11379 : :
11380 : : Perform a statvfs system call on the given path.
11381 : :
11382 : : path may always be specified as a string.
11383 : : On some platforms, path may also be specified as an open file descriptor.
11384 : : If this functionality is unavailable, using it raises an exception.
11385 : : [clinic start generated code]*/
11386 : :
11387 : : static PyObject *
11388 : 123 : os_statvfs_impl(PyObject *module, path_t *path)
11389 : : /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
11390 : : {
11391 : : int result;
11392 : : struct statvfs st;
11393 : :
11394 : 123 : Py_BEGIN_ALLOW_THREADS
11395 : : #ifdef HAVE_FSTATVFS
11396 [ + + ]: 123 : if (path->fd != -1) {
11397 : 1 : result = fstatvfs(path->fd, &st);
11398 : : }
11399 : : else
11400 : : #endif
11401 : 122 : result = statvfs(path->narrow, &st);
11402 : 123 : Py_END_ALLOW_THREADS
11403 : :
11404 [ - + ]: 123 : if (result) {
11405 : 0 : return path_error(path);
11406 : : }
11407 : :
11408 : 123 : return _pystatvfs_fromstructstatvfs(module, st);
11409 : : }
11410 : : #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
11411 : :
11412 : :
11413 : : #ifdef MS_WINDOWS
11414 : : /*[clinic input]
11415 : : os._getdiskusage
11416 : :
11417 : : path: path_t
11418 : :
11419 : : Return disk usage statistics about the given path as a (total, free) tuple.
11420 : : [clinic start generated code]*/
11421 : :
11422 : : static PyObject *
11423 : : os__getdiskusage_impl(PyObject *module, path_t *path)
11424 : : /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
11425 : : {
11426 : : BOOL retval;
11427 : : ULARGE_INTEGER _, total, free;
11428 : : DWORD err = 0;
11429 : :
11430 : : Py_BEGIN_ALLOW_THREADS
11431 : : retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
11432 : : Py_END_ALLOW_THREADS
11433 : : if (retval == 0) {
11434 : : if (GetLastError() == ERROR_DIRECTORY) {
11435 : : wchar_t *dir_path = NULL;
11436 : :
11437 : : dir_path = PyMem_New(wchar_t, path->length + 1);
11438 : : if (dir_path == NULL) {
11439 : : return PyErr_NoMemory();
11440 : : }
11441 : :
11442 : : wcscpy_s(dir_path, path->length + 1, path->wide);
11443 : :
11444 : : if (_dirnameW(dir_path) != -1) {
11445 : : Py_BEGIN_ALLOW_THREADS
11446 : : retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
11447 : : Py_END_ALLOW_THREADS
11448 : : }
11449 : : /* Record the last error in case it's modified by PyMem_Free. */
11450 : : err = GetLastError();
11451 : : PyMem_Free(dir_path);
11452 : : if (retval) {
11453 : : goto success;
11454 : : }
11455 : : }
11456 : : return PyErr_SetFromWindowsErr(err);
11457 : : }
11458 : :
11459 : : success:
11460 : : return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
11461 : : }
11462 : : #endif /* MS_WINDOWS */
11463 : :
11464 : :
11465 : : /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
11466 : : * It maps strings representing configuration variable names to
11467 : : * integer values, allowing those functions to be called with the
11468 : : * magic names instead of polluting the module's namespace with tons of
11469 : : * rarely-used constants. There are three separate tables that use
11470 : : * these definitions.
11471 : : *
11472 : : * This code is always included, even if none of the interfaces that
11473 : : * need it are included. The #if hackery needed to avoid it would be
11474 : : * sufficiently pervasive that it's not worth the loss of readability.
11475 : : */
11476 : : struct constdef {
11477 : : const char *name;
11478 : : int value;
11479 : : };
11480 : :
11481 : : static int
11482 : 2723 : conv_confname(PyObject *arg, int *valuep, struct constdef *table,
11483 : : size_t tablesize)
11484 : : {
11485 [ - + ]: 2723 : if (PyLong_Check(arg)) {
11486 : 0 : int value = _PyLong_AsInt(arg);
11487 [ # # # # ]: 0 : if (value == -1 && PyErr_Occurred())
11488 : 0 : return 0;
11489 : 0 : *valuep = value;
11490 : 0 : return 1;
11491 : : }
11492 : : else {
11493 : : /* look up the value in the table using a binary search */
11494 : 2723 : size_t lo = 0;
11495 : : size_t mid;
11496 : 2723 : size_t hi = tablesize;
11497 : : int cmp;
11498 : : const char *confname;
11499 [ - + ]: 2723 : if (!PyUnicode_Check(arg)) {
11500 : 0 : PyErr_SetString(PyExc_TypeError,
11501 : : "configuration names must be strings or integers");
11502 : 0 : return 0;
11503 : : }
11504 : 2723 : confname = PyUnicode_AsUTF8(arg);
11505 [ - + ]: 2723 : if (confname == NULL)
11506 : 0 : return 0;
11507 [ + + ]: 16599 : while (lo < hi) {
11508 : 16598 : mid = (lo + hi) / 2;
11509 : 16598 : cmp = strcmp(confname, table[mid].name);
11510 [ + + ]: 16598 : if (cmp < 0)
11511 : 9947 : hi = mid;
11512 [ + + ]: 6651 : else if (cmp > 0)
11513 : 3929 : lo = mid + 1;
11514 : : else {
11515 : 2722 : *valuep = table[mid].value;
11516 : 2722 : return 1;
11517 : : }
11518 : : }
11519 : 1 : PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
11520 : 1 : return 0;
11521 : : }
11522 : : }
11523 : :
11524 : :
11525 : : #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11526 : : static struct constdef posix_constants_pathconf[] = {
11527 : : #ifdef _PC_ABI_AIO_XFER_MAX
11528 : : {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
11529 : : #endif
11530 : : #ifdef _PC_ABI_ASYNC_IO
11531 : : {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
11532 : : #endif
11533 : : #ifdef _PC_ASYNC_IO
11534 : : {"PC_ASYNC_IO", _PC_ASYNC_IO},
11535 : : #endif
11536 : : #ifdef _PC_CHOWN_RESTRICTED
11537 : : {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
11538 : : #endif
11539 : : #ifdef _PC_FILESIZEBITS
11540 : : {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
11541 : : #endif
11542 : : #ifdef _PC_LAST
11543 : : {"PC_LAST", _PC_LAST},
11544 : : #endif
11545 : : #ifdef _PC_LINK_MAX
11546 : : {"PC_LINK_MAX", _PC_LINK_MAX},
11547 : : #endif
11548 : : #ifdef _PC_MAX_CANON
11549 : : {"PC_MAX_CANON", _PC_MAX_CANON},
11550 : : #endif
11551 : : #ifdef _PC_MAX_INPUT
11552 : : {"PC_MAX_INPUT", _PC_MAX_INPUT},
11553 : : #endif
11554 : : #ifdef _PC_NAME_MAX
11555 : : {"PC_NAME_MAX", _PC_NAME_MAX},
11556 : : #endif
11557 : : #ifdef _PC_NO_TRUNC
11558 : : {"PC_NO_TRUNC", _PC_NO_TRUNC},
11559 : : #endif
11560 : : #ifdef _PC_PATH_MAX
11561 : : {"PC_PATH_MAX", _PC_PATH_MAX},
11562 : : #endif
11563 : : #ifdef _PC_PIPE_BUF
11564 : : {"PC_PIPE_BUF", _PC_PIPE_BUF},
11565 : : #endif
11566 : : #ifdef _PC_PRIO_IO
11567 : : {"PC_PRIO_IO", _PC_PRIO_IO},
11568 : : #endif
11569 : : #ifdef _PC_SOCK_MAXBUF
11570 : : {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
11571 : : #endif
11572 : : #ifdef _PC_SYNC_IO
11573 : : {"PC_SYNC_IO", _PC_SYNC_IO},
11574 : : #endif
11575 : : #ifdef _PC_VDISABLE
11576 : : {"PC_VDISABLE", _PC_VDISABLE},
11577 : : #endif
11578 : : #ifdef _PC_ACL_ENABLED
11579 : : {"PC_ACL_ENABLED", _PC_ACL_ENABLED},
11580 : : #endif
11581 : : #ifdef _PC_MIN_HOLE_SIZE
11582 : : {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE},
11583 : : #endif
11584 : : #ifdef _PC_ALLOC_SIZE_MIN
11585 : : {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN},
11586 : : #endif
11587 : : #ifdef _PC_REC_INCR_XFER_SIZE
11588 : : {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE},
11589 : : #endif
11590 : : #ifdef _PC_REC_MAX_XFER_SIZE
11591 : : {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE},
11592 : : #endif
11593 : : #ifdef _PC_REC_MIN_XFER_SIZE
11594 : : {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE},
11595 : : #endif
11596 : : #ifdef _PC_REC_XFER_ALIGN
11597 : : {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN},
11598 : : #endif
11599 : : #ifdef _PC_SYMLINK_MAX
11600 : : {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX},
11601 : : #endif
11602 : : #ifdef _PC_XATTR_ENABLED
11603 : : {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED},
11604 : : #endif
11605 : : #ifdef _PC_XATTR_EXISTS
11606 : : {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
11607 : : #endif
11608 : : #ifdef _PC_TIMESTAMP_RESOLUTION
11609 : : {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
11610 : : #endif
11611 : : };
11612 : :
11613 : : static int
11614 : 2 : conv_path_confname(PyObject *arg, int *valuep)
11615 : : {
11616 : 2 : return conv_confname(arg, valuep, posix_constants_pathconf,
11617 : : sizeof(posix_constants_pathconf)
11618 : : / sizeof(struct constdef));
11619 : : }
11620 : : #endif
11621 : :
11622 : :
11623 : : #ifdef HAVE_FPATHCONF
11624 : : /*[clinic input]
11625 : : os.fpathconf -> long
11626 : :
11627 : : fd: fildes
11628 : : name: path_confname
11629 : : /
11630 : :
11631 : : Return the configuration limit name for the file descriptor fd.
11632 : :
11633 : : If there is no limit, return -1.
11634 : : [clinic start generated code]*/
11635 : :
11636 : : static long
11637 : 1 : os_fpathconf_impl(PyObject *module, int fd, int name)
11638 : : /*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
11639 : : {
11640 : : long limit;
11641 : :
11642 : 1 : errno = 0;
11643 : 1 : limit = fpathconf(fd, name);
11644 [ + - + - ]: 1 : if (limit == -1 && errno != 0)
11645 : 1 : posix_error();
11646 : :
11647 : 1 : return limit;
11648 : : }
11649 : : #endif /* HAVE_FPATHCONF */
11650 : :
11651 : :
11652 : : #ifdef HAVE_PATHCONF
11653 : : /*[clinic input]
11654 : : os.pathconf -> long
11655 : : path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
11656 : : name: path_confname
11657 : :
11658 : : Return the configuration limit name for the file or directory path.
11659 : :
11660 : : If there is no limit, return -1.
11661 : : On some platforms, path may also be specified as an open file descriptor.
11662 : : If this functionality is unavailable, using it raises an exception.
11663 : : [clinic start generated code]*/
11664 : :
11665 : : static long
11666 : 1 : os_pathconf_impl(PyObject *module, path_t *path, int name)
11667 : : /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
11668 : : {
11669 : : long limit;
11670 : :
11671 : 1 : errno = 0;
11672 : : #ifdef HAVE_FPATHCONF
11673 [ + - ]: 1 : if (path->fd != -1)
11674 : 1 : limit = fpathconf(path->fd, name);
11675 : : else
11676 : : #endif
11677 : 0 : limit = pathconf(path->narrow, name);
11678 [ + - + - ]: 1 : if (limit == -1 && errno != 0) {
11679 [ - + ]: 1 : if (errno == EINVAL)
11680 : : /* could be a path or name problem */
11681 : 0 : posix_error();
11682 : : else
11683 : 1 : path_error(path);
11684 : : }
11685 : :
11686 : 1 : return limit;
11687 : : }
11688 : : #endif /* HAVE_PATHCONF */
11689 : :
11690 : : #ifdef HAVE_CONFSTR
11691 : : static struct constdef posix_constants_confstr[] = {
11692 : : #ifdef _CS_ARCHITECTURE
11693 : : {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
11694 : : #endif
11695 : : #ifdef _CS_GNU_LIBC_VERSION
11696 : : {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION},
11697 : : #endif
11698 : : #ifdef _CS_GNU_LIBPTHREAD_VERSION
11699 : : {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION},
11700 : : #endif
11701 : : #ifdef _CS_HOSTNAME
11702 : : {"CS_HOSTNAME", _CS_HOSTNAME},
11703 : : #endif
11704 : : #ifdef _CS_HW_PROVIDER
11705 : : {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
11706 : : #endif
11707 : : #ifdef _CS_HW_SERIAL
11708 : : {"CS_HW_SERIAL", _CS_HW_SERIAL},
11709 : : #endif
11710 : : #ifdef _CS_INITTAB_NAME
11711 : : {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11712 : : #endif
11713 : : #ifdef _CS_LFS64_CFLAGS
11714 : : {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11715 : : #endif
11716 : : #ifdef _CS_LFS64_LDFLAGS
11717 : : {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
11718 : : #endif
11719 : : #ifdef _CS_LFS64_LIBS
11720 : : {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
11721 : : #endif
11722 : : #ifdef _CS_LFS64_LINTFLAGS
11723 : : {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
11724 : : #endif
11725 : : #ifdef _CS_LFS_CFLAGS
11726 : : {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
11727 : : #endif
11728 : : #ifdef _CS_LFS_LDFLAGS
11729 : : {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
11730 : : #endif
11731 : : #ifdef _CS_LFS_LIBS
11732 : : {"CS_LFS_LIBS", _CS_LFS_LIBS},
11733 : : #endif
11734 : : #ifdef _CS_LFS_LINTFLAGS
11735 : : {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
11736 : : #endif
11737 : : #ifdef _CS_MACHINE
11738 : : {"CS_MACHINE", _CS_MACHINE},
11739 : : #endif
11740 : : #ifdef _CS_PATH
11741 : : {"CS_PATH", _CS_PATH},
11742 : : #endif
11743 : : #ifdef _CS_RELEASE
11744 : : {"CS_RELEASE", _CS_RELEASE},
11745 : : #endif
11746 : : #ifdef _CS_SRPC_DOMAIN
11747 : : {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
11748 : : #endif
11749 : : #ifdef _CS_SYSNAME
11750 : : {"CS_SYSNAME", _CS_SYSNAME},
11751 : : #endif
11752 : : #ifdef _CS_VERSION
11753 : : {"CS_VERSION", _CS_VERSION},
11754 : : #endif
11755 : : #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11756 : : {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
11757 : : #endif
11758 : : #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11759 : : {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
11760 : : #endif
11761 : : #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11762 : : {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
11763 : : #endif
11764 : : #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11765 : : {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11766 : : #endif
11767 : : #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11768 : : {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11769 : : #endif
11770 : : #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11771 : : {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11772 : : #endif
11773 : : #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11774 : : {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
11775 : : #endif
11776 : : #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11777 : : {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11778 : : #endif
11779 : : #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11780 : : {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
11781 : : #endif
11782 : : #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11783 : : {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
11784 : : #endif
11785 : : #ifdef _CS_XBS5_LP64_OFF64_LIBS
11786 : : {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11787 : : #endif
11788 : : #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11789 : : {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
11790 : : #endif
11791 : : #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11792 : : {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11793 : : #endif
11794 : : #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11795 : : {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11796 : : #endif
11797 : : #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11798 : : {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
11799 : : #endif
11800 : : #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11801 : : {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11802 : : #endif
11803 : : #ifdef _MIPS_CS_AVAIL_PROCESSORS
11804 : : {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
11805 : : #endif
11806 : : #ifdef _MIPS_CS_BASE
11807 : : {"MIPS_CS_BASE", _MIPS_CS_BASE},
11808 : : #endif
11809 : : #ifdef _MIPS_CS_HOSTID
11810 : : {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
11811 : : #endif
11812 : : #ifdef _MIPS_CS_HW_NAME
11813 : : {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11814 : : #endif
11815 : : #ifdef _MIPS_CS_NUM_PROCESSORS
11816 : : {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
11817 : : #endif
11818 : : #ifdef _MIPS_CS_OSREL_MAJ
11819 : : {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
11820 : : #endif
11821 : : #ifdef _MIPS_CS_OSREL_MIN
11822 : : {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
11823 : : #endif
11824 : : #ifdef _MIPS_CS_OSREL_PATCH
11825 : : {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
11826 : : #endif
11827 : : #ifdef _MIPS_CS_OS_NAME
11828 : : {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11829 : : #endif
11830 : : #ifdef _MIPS_CS_OS_PROVIDER
11831 : : {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
11832 : : #endif
11833 : : #ifdef _MIPS_CS_PROCESSORS
11834 : : {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
11835 : : #endif
11836 : : #ifdef _MIPS_CS_SERIAL
11837 : : {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
11838 : : #endif
11839 : : #ifdef _MIPS_CS_VENDOR
11840 : : {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
11841 : : #endif
11842 : : };
11843 : :
11844 : : static int
11845 : 1225 : conv_confstr_confname(PyObject *arg, int *valuep)
11846 : : {
11847 : 1225 : return conv_confname(arg, valuep, posix_constants_confstr,
11848 : : sizeof(posix_constants_confstr)
11849 : : / sizeof(struct constdef));
11850 : : }
11851 : :
11852 : :
11853 : : /*[clinic input]
11854 : : os.confstr
11855 : :
11856 : : name: confstr_confname
11857 : : /
11858 : :
11859 : : Return a string-valued system configuration variable.
11860 : : [clinic start generated code]*/
11861 : :
11862 : : static PyObject *
11863 : 1224 : os_confstr_impl(PyObject *module, int name)
11864 : : /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11865 : : {
11866 : 1224 : PyObject *result = NULL;
11867 : : char buffer[255];
11868 : : size_t len;
11869 : :
11870 : 1224 : errno = 0;
11871 : 1224 : len = confstr(name, buffer, sizeof(buffer));
11872 [ - + ]: 1224 : if (len == 0) {
11873 [ # # ]: 0 : if (errno) {
11874 : 0 : posix_error();
11875 : 0 : return NULL;
11876 : : }
11877 : : else {
11878 : 0 : Py_RETURN_NONE;
11879 : : }
11880 : : }
11881 : :
11882 [ - + ]: 1224 : if (len >= sizeof(buffer)) {
11883 : : size_t len2;
11884 : 0 : char *buf = PyMem_Malloc(len);
11885 [ # # ]: 0 : if (buf == NULL)
11886 : : return PyErr_NoMemory();
11887 : 0 : len2 = confstr(name, buf, len);
11888 : : assert(len == len2);
11889 : 0 : result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11890 : 0 : PyMem_Free(buf);
11891 : : }
11892 : : else
11893 : 1224 : result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11894 : 1224 : return result;
11895 : : }
11896 : : #endif /* HAVE_CONFSTR */
11897 : :
11898 : :
11899 : : #ifdef HAVE_SYSCONF
11900 : : static struct constdef posix_constants_sysconf[] = {
11901 : : #ifdef _SC_2_CHAR_TERM
11902 : : {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
11903 : : #endif
11904 : : #ifdef _SC_2_C_BIND
11905 : : {"SC_2_C_BIND", _SC_2_C_BIND},
11906 : : #endif
11907 : : #ifdef _SC_2_C_DEV
11908 : : {"SC_2_C_DEV", _SC_2_C_DEV},
11909 : : #endif
11910 : : #ifdef _SC_2_C_VERSION
11911 : : {"SC_2_C_VERSION", _SC_2_C_VERSION},
11912 : : #endif
11913 : : #ifdef _SC_2_FORT_DEV
11914 : : {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
11915 : : #endif
11916 : : #ifdef _SC_2_FORT_RUN
11917 : : {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
11918 : : #endif
11919 : : #ifdef _SC_2_LOCALEDEF
11920 : : {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
11921 : : #endif
11922 : : #ifdef _SC_2_SW_DEV
11923 : : {"SC_2_SW_DEV", _SC_2_SW_DEV},
11924 : : #endif
11925 : : #ifdef _SC_2_UPE
11926 : : {"SC_2_UPE", _SC_2_UPE},
11927 : : #endif
11928 : : #ifdef _SC_2_VERSION
11929 : : {"SC_2_VERSION", _SC_2_VERSION},
11930 : : #endif
11931 : : #ifdef _SC_ABI_ASYNCHRONOUS_IO
11932 : : {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
11933 : : #endif
11934 : : #ifdef _SC_ACL
11935 : : {"SC_ACL", _SC_ACL},
11936 : : #endif
11937 : : #ifdef _SC_AIO_LISTIO_MAX
11938 : : {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
11939 : : #endif
11940 : : #ifdef _SC_AIO_MAX
11941 : : {"SC_AIO_MAX", _SC_AIO_MAX},
11942 : : #endif
11943 : : #ifdef _SC_AIO_PRIO_DELTA_MAX
11944 : : {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
11945 : : #endif
11946 : : #ifdef _SC_ARG_MAX
11947 : : {"SC_ARG_MAX", _SC_ARG_MAX},
11948 : : #endif
11949 : : #ifdef _SC_ASYNCHRONOUS_IO
11950 : : {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
11951 : : #endif
11952 : : #ifdef _SC_ATEXIT_MAX
11953 : : {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
11954 : : #endif
11955 : : #ifdef _SC_AUDIT
11956 : : {"SC_AUDIT", _SC_AUDIT},
11957 : : #endif
11958 : : #ifdef _SC_AVPHYS_PAGES
11959 : : {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
11960 : : #endif
11961 : : #ifdef _SC_BC_BASE_MAX
11962 : : {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
11963 : : #endif
11964 : : #ifdef _SC_BC_DIM_MAX
11965 : : {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
11966 : : #endif
11967 : : #ifdef _SC_BC_SCALE_MAX
11968 : : {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
11969 : : #endif
11970 : : #ifdef _SC_BC_STRING_MAX
11971 : : {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
11972 : : #endif
11973 : : #ifdef _SC_CAP
11974 : : {"SC_CAP", _SC_CAP},
11975 : : #endif
11976 : : #ifdef _SC_CHARCLASS_NAME_MAX
11977 : : {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
11978 : : #endif
11979 : : #ifdef _SC_CHAR_BIT
11980 : : {"SC_CHAR_BIT", _SC_CHAR_BIT},
11981 : : #endif
11982 : : #ifdef _SC_CHAR_MAX
11983 : : {"SC_CHAR_MAX", _SC_CHAR_MAX},
11984 : : #endif
11985 : : #ifdef _SC_CHAR_MIN
11986 : : {"SC_CHAR_MIN", _SC_CHAR_MIN},
11987 : : #endif
11988 : : #ifdef _SC_CHILD_MAX
11989 : : {"SC_CHILD_MAX", _SC_CHILD_MAX},
11990 : : #endif
11991 : : #ifdef _SC_CLK_TCK
11992 : : {"SC_CLK_TCK", _SC_CLK_TCK},
11993 : : #endif
11994 : : #ifdef _SC_COHER_BLKSZ
11995 : : {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
11996 : : #endif
11997 : : #ifdef _SC_COLL_WEIGHTS_MAX
11998 : : {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
11999 : : #endif
12000 : : #ifdef _SC_DCACHE_ASSOC
12001 : : {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
12002 : : #endif
12003 : : #ifdef _SC_DCACHE_BLKSZ
12004 : : {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
12005 : : #endif
12006 : : #ifdef _SC_DCACHE_LINESZ
12007 : : {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
12008 : : #endif
12009 : : #ifdef _SC_DCACHE_SZ
12010 : : {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
12011 : : #endif
12012 : : #ifdef _SC_DCACHE_TBLKSZ
12013 : : {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
12014 : : #endif
12015 : : #ifdef _SC_DELAYTIMER_MAX
12016 : : {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
12017 : : #endif
12018 : : #ifdef _SC_EQUIV_CLASS_MAX
12019 : : {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
12020 : : #endif
12021 : : #ifdef _SC_EXPR_NEST_MAX
12022 : : {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
12023 : : #endif
12024 : : #ifdef _SC_FSYNC
12025 : : {"SC_FSYNC", _SC_FSYNC},
12026 : : #endif
12027 : : #ifdef _SC_GETGR_R_SIZE_MAX
12028 : : {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
12029 : : #endif
12030 : : #ifdef _SC_GETPW_R_SIZE_MAX
12031 : : {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
12032 : : #endif
12033 : : #ifdef _SC_ICACHE_ASSOC
12034 : : {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
12035 : : #endif
12036 : : #ifdef _SC_ICACHE_BLKSZ
12037 : : {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
12038 : : #endif
12039 : : #ifdef _SC_ICACHE_LINESZ
12040 : : {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
12041 : : #endif
12042 : : #ifdef _SC_ICACHE_SZ
12043 : : {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
12044 : : #endif
12045 : : #ifdef _SC_INF
12046 : : {"SC_INF", _SC_INF},
12047 : : #endif
12048 : : #ifdef _SC_INT_MAX
12049 : : {"SC_INT_MAX", _SC_INT_MAX},
12050 : : #endif
12051 : : #ifdef _SC_INT_MIN
12052 : : {"SC_INT_MIN", _SC_INT_MIN},
12053 : : #endif
12054 : : #ifdef _SC_IOV_MAX
12055 : : {"SC_IOV_MAX", _SC_IOV_MAX},
12056 : : #endif
12057 : : #ifdef _SC_IP_SECOPTS
12058 : : {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
12059 : : #endif
12060 : : #ifdef _SC_JOB_CONTROL
12061 : : {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
12062 : : #endif
12063 : : #ifdef _SC_KERN_POINTERS
12064 : : {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
12065 : : #endif
12066 : : #ifdef _SC_KERN_SIM
12067 : : {"SC_KERN_SIM", _SC_KERN_SIM},
12068 : : #endif
12069 : : #ifdef _SC_LINE_MAX
12070 : : {"SC_LINE_MAX", _SC_LINE_MAX},
12071 : : #endif
12072 : : #ifdef _SC_LOGIN_NAME_MAX
12073 : : {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
12074 : : #endif
12075 : : #ifdef _SC_LOGNAME_MAX
12076 : : {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
12077 : : #endif
12078 : : #ifdef _SC_LONG_BIT
12079 : : {"SC_LONG_BIT", _SC_LONG_BIT},
12080 : : #endif
12081 : : #ifdef _SC_MAC
12082 : : {"SC_MAC", _SC_MAC},
12083 : : #endif
12084 : : #ifdef _SC_MAPPED_FILES
12085 : : {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
12086 : : #endif
12087 : : #ifdef _SC_MAXPID
12088 : : {"SC_MAXPID", _SC_MAXPID},
12089 : : #endif
12090 : : #ifdef _SC_MB_LEN_MAX
12091 : : {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
12092 : : #endif
12093 : : #ifdef _SC_MEMLOCK
12094 : : {"SC_MEMLOCK", _SC_MEMLOCK},
12095 : : #endif
12096 : : #ifdef _SC_MEMLOCK_RANGE
12097 : : {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
12098 : : #endif
12099 : : #ifdef _SC_MEMORY_PROTECTION
12100 : : {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
12101 : : #endif
12102 : : #ifdef _SC_MESSAGE_PASSING
12103 : : {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
12104 : : #endif
12105 : : #ifdef _SC_MMAP_FIXED_ALIGNMENT
12106 : : {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
12107 : : #endif
12108 : : #ifdef _SC_MQ_OPEN_MAX
12109 : : {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
12110 : : #endif
12111 : : #ifdef _SC_MQ_PRIO_MAX
12112 : : {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},
12113 : : #endif
12114 : : #ifdef _SC_NACLS_MAX
12115 : : {"SC_NACLS_MAX", _SC_NACLS_MAX},
12116 : : #endif
12117 : : #ifdef _SC_NGROUPS_MAX
12118 : : {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX},
12119 : : #endif
12120 : : #ifdef _SC_NL_ARGMAX
12121 : : {"SC_NL_ARGMAX", _SC_NL_ARGMAX},
12122 : : #endif
12123 : : #ifdef _SC_NL_LANGMAX
12124 : : {"SC_NL_LANGMAX", _SC_NL_LANGMAX},
12125 : : #endif
12126 : : #ifdef _SC_NL_MSGMAX
12127 : : {"SC_NL_MSGMAX", _SC_NL_MSGMAX},
12128 : : #endif
12129 : : #ifdef _SC_NL_NMAX
12130 : : {"SC_NL_NMAX", _SC_NL_NMAX},
12131 : : #endif
12132 : : #ifdef _SC_NL_SETMAX
12133 : : {"SC_NL_SETMAX", _SC_NL_SETMAX},
12134 : : #endif
12135 : : #ifdef _SC_NL_TEXTMAX
12136 : : {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX},
12137 : : #endif
12138 : : #ifdef _SC_NPROCESSORS_CONF
12139 : : {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
12140 : : #endif
12141 : : #ifdef _SC_NPROCESSORS_ONLN
12142 : : {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
12143 : : #endif
12144 : : #ifdef _SC_NPROC_CONF
12145 : : {"SC_NPROC_CONF", _SC_NPROC_CONF},
12146 : : #endif
12147 : : #ifdef _SC_NPROC_ONLN
12148 : : {"SC_NPROC_ONLN", _SC_NPROC_ONLN},
12149 : : #endif
12150 : : #ifdef _SC_NZERO
12151 : : {"SC_NZERO", _SC_NZERO},
12152 : : #endif
12153 : : #ifdef _SC_OPEN_MAX
12154 : : {"SC_OPEN_MAX", _SC_OPEN_MAX},
12155 : : #endif
12156 : : #ifdef _SC_PAGESIZE
12157 : : {"SC_PAGESIZE", _SC_PAGESIZE},
12158 : : #endif
12159 : : #ifdef _SC_PAGE_SIZE
12160 : : {"SC_PAGE_SIZE", _SC_PAGE_SIZE},
12161 : : #endif
12162 : : #ifdef _SC_AIX_REALMEM
12163 : : {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
12164 : : #endif
12165 : : #ifdef _SC_PASS_MAX
12166 : : {"SC_PASS_MAX", _SC_PASS_MAX},
12167 : : #endif
12168 : : #ifdef _SC_PHYS_PAGES
12169 : : {"SC_PHYS_PAGES", _SC_PHYS_PAGES},
12170 : : #endif
12171 : : #ifdef _SC_PII
12172 : : {"SC_PII", _SC_PII},
12173 : : #endif
12174 : : #ifdef _SC_PII_INTERNET
12175 : : {"SC_PII_INTERNET", _SC_PII_INTERNET},
12176 : : #endif
12177 : : #ifdef _SC_PII_INTERNET_DGRAM
12178 : : {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM},
12179 : : #endif
12180 : : #ifdef _SC_PII_INTERNET_STREAM
12181 : : {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM},
12182 : : #endif
12183 : : #ifdef _SC_PII_OSI
12184 : : {"SC_PII_OSI", _SC_PII_OSI},
12185 : : #endif
12186 : : #ifdef _SC_PII_OSI_CLTS
12187 : : {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
12188 : : #endif
12189 : : #ifdef _SC_PII_OSI_COTS
12190 : : {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
12191 : : #endif
12192 : : #ifdef _SC_PII_OSI_M
12193 : : {"SC_PII_OSI_M", _SC_PII_OSI_M},
12194 : : #endif
12195 : : #ifdef _SC_PII_SOCKET
12196 : : {"SC_PII_SOCKET", _SC_PII_SOCKET},
12197 : : #endif
12198 : : #ifdef _SC_PII_XTI
12199 : : {"SC_PII_XTI", _SC_PII_XTI},
12200 : : #endif
12201 : : #ifdef _SC_POLL
12202 : : {"SC_POLL", _SC_POLL},
12203 : : #endif
12204 : : #ifdef _SC_PRIORITIZED_IO
12205 : : {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO},
12206 : : #endif
12207 : : #ifdef _SC_PRIORITY_SCHEDULING
12208 : : {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING},
12209 : : #endif
12210 : : #ifdef _SC_REALTIME_SIGNALS
12211 : : {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS},
12212 : : #endif
12213 : : #ifdef _SC_RE_DUP_MAX
12214 : : {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX},
12215 : : #endif
12216 : : #ifdef _SC_RTSIG_MAX
12217 : : {"SC_RTSIG_MAX", _SC_RTSIG_MAX},
12218 : : #endif
12219 : : #ifdef _SC_SAVED_IDS
12220 : : {"SC_SAVED_IDS", _SC_SAVED_IDS},
12221 : : #endif
12222 : : #ifdef _SC_SCHAR_MAX
12223 : : {"SC_SCHAR_MAX", _SC_SCHAR_MAX},
12224 : : #endif
12225 : : #ifdef _SC_SCHAR_MIN
12226 : : {"SC_SCHAR_MIN", _SC_SCHAR_MIN},
12227 : : #endif
12228 : : #ifdef _SC_SELECT
12229 : : {"SC_SELECT", _SC_SELECT},
12230 : : #endif
12231 : : #ifdef _SC_SEMAPHORES
12232 : : {"SC_SEMAPHORES", _SC_SEMAPHORES},
12233 : : #endif
12234 : : #ifdef _SC_SEM_NSEMS_MAX
12235 : : {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX},
12236 : : #endif
12237 : : #ifdef _SC_SEM_VALUE_MAX
12238 : : {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX},
12239 : : #endif
12240 : : #ifdef _SC_SHARED_MEMORY_OBJECTS
12241 : : {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS},
12242 : : #endif
12243 : : #ifdef _SC_SHRT_MAX
12244 : : {"SC_SHRT_MAX", _SC_SHRT_MAX},
12245 : : #endif
12246 : : #ifdef _SC_SHRT_MIN
12247 : : {"SC_SHRT_MIN", _SC_SHRT_MIN},
12248 : : #endif
12249 : : #ifdef _SC_SIGQUEUE_MAX
12250 : : {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
12251 : : #endif
12252 : : #ifdef _SC_SIGRT_MAX
12253 : : {"SC_SIGRT_MAX", _SC_SIGRT_MAX},
12254 : : #endif
12255 : : #ifdef _SC_SIGRT_MIN
12256 : : {"SC_SIGRT_MIN", _SC_SIGRT_MIN},
12257 : : #endif
12258 : : #ifdef _SC_SOFTPOWER
12259 : : {"SC_SOFTPOWER", _SC_SOFTPOWER},
12260 : : #endif
12261 : : #ifdef _SC_SPLIT_CACHE
12262 : : {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE},
12263 : : #endif
12264 : : #ifdef _SC_SSIZE_MAX
12265 : : {"SC_SSIZE_MAX", _SC_SSIZE_MAX},
12266 : : #endif
12267 : : #ifdef _SC_STACK_PROT
12268 : : {"SC_STACK_PROT", _SC_STACK_PROT},
12269 : : #endif
12270 : : #ifdef _SC_STREAM_MAX
12271 : : {"SC_STREAM_MAX", _SC_STREAM_MAX},
12272 : : #endif
12273 : : #ifdef _SC_SYNCHRONIZED_IO
12274 : : {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO},
12275 : : #endif
12276 : : #ifdef _SC_THREADS
12277 : : {"SC_THREADS", _SC_THREADS},
12278 : : #endif
12279 : : #ifdef _SC_THREAD_ATTR_STACKADDR
12280 : : {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR},
12281 : : #endif
12282 : : #ifdef _SC_THREAD_ATTR_STACKSIZE
12283 : : {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE},
12284 : : #endif
12285 : : #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
12286 : : {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
12287 : : #endif
12288 : : #ifdef _SC_THREAD_KEYS_MAX
12289 : : {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
12290 : : #endif
12291 : : #ifdef _SC_THREAD_PRIORITY_SCHEDULING
12292 : : {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING},
12293 : : #endif
12294 : : #ifdef _SC_THREAD_PRIO_INHERIT
12295 : : {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT},
12296 : : #endif
12297 : : #ifdef _SC_THREAD_PRIO_PROTECT
12298 : : {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT},
12299 : : #endif
12300 : : #ifdef _SC_THREAD_PROCESS_SHARED
12301 : : {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED},
12302 : : #endif
12303 : : #ifdef _SC_THREAD_SAFE_FUNCTIONS
12304 : : {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS},
12305 : : #endif
12306 : : #ifdef _SC_THREAD_STACK_MIN
12307 : : {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
12308 : : #endif
12309 : : #ifdef _SC_THREAD_THREADS_MAX
12310 : : {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
12311 : : #endif
12312 : : #ifdef _SC_TIMERS
12313 : : {"SC_TIMERS", _SC_TIMERS},
12314 : : #endif
12315 : : #ifdef _SC_TIMER_MAX
12316 : : {"SC_TIMER_MAX", _SC_TIMER_MAX},
12317 : : #endif
12318 : : #ifdef _SC_TTY_NAME_MAX
12319 : : {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
12320 : : #endif
12321 : : #ifdef _SC_TZNAME_MAX
12322 : : {"SC_TZNAME_MAX", _SC_TZNAME_MAX},
12323 : : #endif
12324 : : #ifdef _SC_T_IOV_MAX
12325 : : {"SC_T_IOV_MAX", _SC_T_IOV_MAX},
12326 : : #endif
12327 : : #ifdef _SC_UCHAR_MAX
12328 : : {"SC_UCHAR_MAX", _SC_UCHAR_MAX},
12329 : : #endif
12330 : : #ifdef _SC_UINT_MAX
12331 : : {"SC_UINT_MAX", _SC_UINT_MAX},
12332 : : #endif
12333 : : #ifdef _SC_UIO_MAXIOV
12334 : : {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV},
12335 : : #endif
12336 : : #ifdef _SC_ULONG_MAX
12337 : : {"SC_ULONG_MAX", _SC_ULONG_MAX},
12338 : : #endif
12339 : : #ifdef _SC_USHRT_MAX
12340 : : {"SC_USHRT_MAX", _SC_USHRT_MAX},
12341 : : #endif
12342 : : #ifdef _SC_VERSION
12343 : : {"SC_VERSION", _SC_VERSION},
12344 : : #endif
12345 : : #ifdef _SC_WORD_BIT
12346 : : {"SC_WORD_BIT", _SC_WORD_BIT},
12347 : : #endif
12348 : : #ifdef _SC_XBS5_ILP32_OFF32
12349 : : {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32},
12350 : : #endif
12351 : : #ifdef _SC_XBS5_ILP32_OFFBIG
12352 : : {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG},
12353 : : #endif
12354 : : #ifdef _SC_XBS5_LP64_OFF64
12355 : : {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64},
12356 : : #endif
12357 : : #ifdef _SC_XBS5_LPBIG_OFFBIG
12358 : : {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG},
12359 : : #endif
12360 : : #ifdef _SC_XOPEN_CRYPT
12361 : : {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT},
12362 : : #endif
12363 : : #ifdef _SC_XOPEN_ENH_I18N
12364 : : {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N},
12365 : : #endif
12366 : : #ifdef _SC_XOPEN_LEGACY
12367 : : {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
12368 : : #endif
12369 : : #ifdef _SC_XOPEN_REALTIME
12370 : : {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME},
12371 : : #endif
12372 : : #ifdef _SC_XOPEN_REALTIME_THREADS
12373 : : {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS},
12374 : : #endif
12375 : : #ifdef _SC_XOPEN_SHM
12376 : : {"SC_XOPEN_SHM", _SC_XOPEN_SHM},
12377 : : #endif
12378 : : #ifdef _SC_XOPEN_UNIX
12379 : : {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX},
12380 : : #endif
12381 : : #ifdef _SC_XOPEN_VERSION
12382 : : {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION},
12383 : : #endif
12384 : : #ifdef _SC_XOPEN_XCU_VERSION
12385 : : {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION},
12386 : : #endif
12387 : : #ifdef _SC_XOPEN_XPG2
12388 : : {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2},
12389 : : #endif
12390 : : #ifdef _SC_XOPEN_XPG3
12391 : : {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3},
12392 : : #endif
12393 : : #ifdef _SC_XOPEN_XPG4
12394 : : {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4},
12395 : : #endif
12396 : : #ifdef _SC_MINSIGSTKSZ
12397 : : {"SC_MINSIGSTKSZ", _SC_MINSIGSTKSZ},
12398 : : #endif
12399 : : };
12400 : :
12401 : : static int
12402 : 1496 : conv_sysconf_confname(PyObject *arg, int *valuep)
12403 : : {
12404 : 1496 : return conv_confname(arg, valuep, posix_constants_sysconf,
12405 : : sizeof(posix_constants_sysconf)
12406 : : / sizeof(struct constdef));
12407 : : }
12408 : :
12409 : :
12410 : : /*[clinic input]
12411 : : os.sysconf -> long
12412 : : name: sysconf_confname
12413 : : /
12414 : :
12415 : : Return an integer-valued system configuration variable.
12416 : : [clinic start generated code]*/
12417 : :
12418 : : static long
12419 : 1496 : os_sysconf_impl(PyObject *module, int name)
12420 : : /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
12421 : : {
12422 : : long value;
12423 : :
12424 : 1496 : errno = 0;
12425 : 1496 : value = sysconf(name);
12426 [ + + - + ]: 1496 : if (value == -1 && errno != 0)
12427 : 0 : posix_error();
12428 : 1496 : return value;
12429 : : }
12430 : : #endif /* HAVE_SYSCONF */
12431 : :
12432 : :
12433 : : /* This code is used to ensure that the tables of configuration value names
12434 : : * are in sorted order as required by conv_confname(), and also to build
12435 : : * the exported dictionaries that are used to publish information about the
12436 : : * names available on the host platform.
12437 : : *
12438 : : * Sorting the table at runtime ensures that the table is properly ordered
12439 : : * when used, even for platforms we're not able to test on. It also makes
12440 : : * it easier to add additional entries to the tables.
12441 : : */
12442 : :
12443 : : static int
12444 : 1806217 : cmp_constdefs(const void *v1, const void *v2)
12445 : : {
12446 : 1806217 : const struct constdef *c1 =
12447 : : (const struct constdef *) v1;
12448 : 1806217 : const struct constdef *c2 =
12449 : : (const struct constdef *) v2;
12450 : :
12451 : 1806217 : return strcmp(c1->name, c2->name);
12452 : : }
12453 : :
12454 : : static int
12455 : 9405 : setup_confname_table(struct constdef *table, size_t tablesize,
12456 : : const char *tablename, PyObject *module)
12457 : : {
12458 : 9405 : PyObject *d = NULL;
12459 : : size_t i;
12460 : :
12461 : 9405 : qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
12462 : 9405 : d = PyDict_New();
12463 [ - + ]: 9405 : if (d == NULL)
12464 : 0 : return -1;
12465 : :
12466 [ + + ]: 579975 : for (i=0; i < tablesize; ++i) {
12467 : 570570 : PyObject *o = PyLong_FromLong(table[i].value);
12468 [ + - - + ]: 570570 : if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
12469 : 0 : Py_XDECREF(o);
12470 : 0 : Py_DECREF(d);
12471 : 0 : return -1;
12472 : : }
12473 : 570570 : Py_DECREF(o);
12474 : : }
12475 : 9405 : return PyModule_AddObject(module, tablename, d);
12476 : : }
12477 : :
12478 : : /* Return -1 on failure, 0 on success. */
12479 : : static int
12480 : 3135 : setup_confname_tables(PyObject *module)
12481 : : {
12482 : : #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12483 [ - + ]: 3135 : if (setup_confname_table(posix_constants_pathconf,
12484 : : sizeof(posix_constants_pathconf)
12485 : : / sizeof(struct constdef),
12486 : : "pathconf_names", module))
12487 : 0 : return -1;
12488 : : #endif
12489 : : #ifdef HAVE_CONFSTR
12490 [ - + ]: 3135 : if (setup_confname_table(posix_constants_confstr,
12491 : : sizeof(posix_constants_confstr)
12492 : : / sizeof(struct constdef),
12493 : : "confstr_names", module))
12494 : 0 : return -1;
12495 : : #endif
12496 : : #ifdef HAVE_SYSCONF
12497 [ - + ]: 3135 : if (setup_confname_table(posix_constants_sysconf,
12498 : : sizeof(posix_constants_sysconf)
12499 : : / sizeof(struct constdef),
12500 : : "sysconf_names", module))
12501 : 0 : return -1;
12502 : : #endif
12503 : 3135 : return 0;
12504 : : }
12505 : :
12506 : :
12507 : : /*[clinic input]
12508 : : os.abort
12509 : :
12510 : : Abort the interpreter immediately.
12511 : :
12512 : : This function 'dumps core' or otherwise fails in the hardest way possible
12513 : : on the hosting operating system. This function never returns.
12514 : : [clinic start generated code]*/
12515 : :
12516 : : static PyObject *
12517 : 0 : os_abort_impl(PyObject *module)
12518 : : /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
12519 : : {
12520 : 0 : abort();
12521 : : /*NOTREACHED*/
12522 : : #ifndef __clang__
12523 : : /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
12524 : : GCC emits a warning without "return NULL;" (compiler bug?), but Clang
12525 : : is smarter and emits a warning on the return. */
12526 : : Py_FatalError("abort() called from Python code didn't abort!");
12527 : : return NULL;
12528 : : #endif
12529 : : }
12530 : :
12531 : : #ifdef MS_WINDOWS
12532 : : /* Grab ShellExecute dynamically from shell32 */
12533 : : static int has_ShellExecute = -1;
12534 : : static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
12535 : : LPCWSTR, INT);
12536 : : static int
12537 : : check_ShellExecute()
12538 : : {
12539 : : HINSTANCE hShell32;
12540 : :
12541 : : /* only recheck */
12542 : : if (-1 == has_ShellExecute) {
12543 : : Py_BEGIN_ALLOW_THREADS
12544 : : /* Security note: this call is not vulnerable to "DLL hijacking".
12545 : : SHELL32 is part of "KnownDLLs" and so Windows always load
12546 : : the system SHELL32.DLL, even if there is another SHELL32.DLL
12547 : : in the DLL search path. */
12548 : : hShell32 = LoadLibraryW(L"SHELL32");
12549 : : if (hShell32) {
12550 : : *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
12551 : : "ShellExecuteW");
12552 : : has_ShellExecute = Py_ShellExecuteW != NULL;
12553 : : } else {
12554 : : has_ShellExecute = 0;
12555 : : }
12556 : : Py_END_ALLOW_THREADS
12557 : : }
12558 : : return has_ShellExecute;
12559 : : }
12560 : :
12561 : :
12562 : : /*[clinic input]
12563 : : os.startfile
12564 : : filepath: path_t
12565 : : operation: Py_UNICODE = NULL
12566 : : arguments: Py_UNICODE = NULL
12567 : : cwd: path_t(nullable=True) = None
12568 : : show_cmd: int = 1
12569 : :
12570 : : Start a file with its associated application.
12571 : :
12572 : : When "operation" is not specified or "open", this acts like
12573 : : double-clicking the file in Explorer, or giving the file name as an
12574 : : argument to the DOS "start" command: the file is opened with whatever
12575 : : application (if any) its extension is associated.
12576 : : When another "operation" is given, it specifies what should be done with
12577 : : the file. A typical operation is "print".
12578 : :
12579 : : "arguments" is passed to the application, but should be omitted if the
12580 : : file is a document.
12581 : :
12582 : : "cwd" is the working directory for the operation. If "filepath" is
12583 : : relative, it will be resolved against this directory. This argument
12584 : : should usually be an absolute path.
12585 : :
12586 : : "show_cmd" can be used to override the recommended visibility option.
12587 : : See the Windows ShellExecute documentation for values.
12588 : :
12589 : : startfile returns as soon as the associated application is launched.
12590 : : There is no option to wait for the application to close, and no way
12591 : : to retrieve the application's exit status.
12592 : :
12593 : : The filepath is relative to the current directory. If you want to use
12594 : : an absolute path, make sure the first character is not a slash ("/");
12595 : : the underlying Win32 ShellExecute function doesn't work if it is.
12596 : : [clinic start generated code]*/
12597 : :
12598 : : static PyObject *
12599 : : os_startfile_impl(PyObject *module, path_t *filepath,
12600 : : const Py_UNICODE *operation, const Py_UNICODE *arguments,
12601 : : path_t *cwd, int show_cmd)
12602 : : /*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/
12603 : : {
12604 : : HINSTANCE rc;
12605 : :
12606 : : if(!check_ShellExecute()) {
12607 : : /* If the OS doesn't have ShellExecute, return a
12608 : : NotImplementedError. */
12609 : : return PyErr_Format(PyExc_NotImplementedError,
12610 : : "startfile not available on this platform");
12611 : : }
12612 : :
12613 : : if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
12614 : : return NULL;
12615 : : }
12616 : : if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
12617 : : arguments, cwd->object ? cwd->object : Py_None,
12618 : : show_cmd) < 0) {
12619 : : return NULL;
12620 : : }
12621 : :
12622 : : Py_BEGIN_ALLOW_THREADS
12623 : : rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
12624 : : arguments, cwd->wide, show_cmd);
12625 : : Py_END_ALLOW_THREADS
12626 : :
12627 : : if (rc <= (HINSTANCE)32) {
12628 : : win32_error_object("startfile", filepath->object);
12629 : : return NULL;
12630 : : }
12631 : : Py_RETURN_NONE;
12632 : : }
12633 : : #endif /* MS_WINDOWS */
12634 : :
12635 : :
12636 : : #ifdef HAVE_GETLOADAVG
12637 : : /*[clinic input]
12638 : : os.getloadavg
12639 : :
12640 : : Return average recent system load information.
12641 : :
12642 : : Return the number of processes in the system run queue averaged over
12643 : : the last 1, 5, and 15 minutes as a tuple of three floats.
12644 : : Raises OSError if the load average was unobtainable.
12645 : : [clinic start generated code]*/
12646 : :
12647 : : static PyObject *
12648 : 588 : os_getloadavg_impl(PyObject *module)
12649 : : /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
12650 : : {
12651 : : double loadavg[3];
12652 [ - + ]: 588 : if (getloadavg(loadavg, 3)!=3) {
12653 : 0 : PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
12654 : 0 : return NULL;
12655 : : } else
12656 : 588 : return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
12657 : : }
12658 : : #endif /* HAVE_GETLOADAVG */
12659 : :
12660 : :
12661 : : /*[clinic input]
12662 : : os.device_encoding
12663 : : fd: int
12664 : :
12665 : : Return a string describing the encoding of a terminal's file descriptor.
12666 : :
12667 : : The file descriptor must be attached to a terminal.
12668 : : If the device is not a terminal, return None.
12669 : : [clinic start generated code]*/
12670 : :
12671 : : static PyObject *
12672 : 2 : os_device_encoding_impl(PyObject *module, int fd)
12673 : : /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
12674 : : {
12675 : 2 : return _Py_device_encoding(fd);
12676 : : }
12677 : :
12678 : :
12679 : : #ifdef HAVE_SETRESUID
12680 : : /*[clinic input]
12681 : : os.setresuid
12682 : :
12683 : : ruid: uid_t
12684 : : euid: uid_t
12685 : : suid: uid_t
12686 : : /
12687 : :
12688 : : Set the current process's real, effective, and saved user ids.
12689 : : [clinic start generated code]*/
12690 : :
12691 : : static PyObject *
12692 : 3 : os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
12693 : : /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
12694 : : {
12695 [ + + ]: 3 : if (setresuid(ruid, euid, suid) < 0)
12696 : 1 : return posix_error();
12697 : 2 : Py_RETURN_NONE;
12698 : : }
12699 : : #endif /* HAVE_SETRESUID */
12700 : :
12701 : :
12702 : : #ifdef HAVE_SETRESGID
12703 : : /*[clinic input]
12704 : : os.setresgid
12705 : :
12706 : : rgid: gid_t
12707 : : egid: gid_t
12708 : : sgid: gid_t
12709 : : /
12710 : :
12711 : : Set the current process's real, effective, and saved group ids.
12712 : : [clinic start generated code]*/
12713 : :
12714 : : static PyObject *
12715 : 3 : os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
12716 : : /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
12717 : : {
12718 [ + + ]: 3 : if (setresgid(rgid, egid, sgid) < 0)
12719 : 1 : return posix_error();
12720 : 2 : Py_RETURN_NONE;
12721 : : }
12722 : : #endif /* HAVE_SETRESGID */
12723 : :
12724 : :
12725 : : #ifdef HAVE_GETRESUID
12726 : : /*[clinic input]
12727 : : os.getresuid
12728 : :
12729 : : Return a tuple of the current process's real, effective, and saved user ids.
12730 : : [clinic start generated code]*/
12731 : :
12732 : : static PyObject *
12733 : 3 : os_getresuid_impl(PyObject *module)
12734 : : /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12735 : : {
12736 : : uid_t ruid, euid, suid;
12737 [ - + ]: 3 : if (getresuid(&ruid, &euid, &suid) < 0)
12738 : 0 : return posix_error();
12739 : 3 : return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12740 : : _PyLong_FromUid(euid),
12741 : : _PyLong_FromUid(suid));
12742 : : }
12743 : : #endif /* HAVE_GETRESUID */
12744 : :
12745 : :
12746 : : #ifdef HAVE_GETRESGID
12747 : : /*[clinic input]
12748 : : os.getresgid
12749 : :
12750 : : Return a tuple of the current process's real, effective, and saved group ids.
12751 : : [clinic start generated code]*/
12752 : :
12753 : : static PyObject *
12754 : 3 : os_getresgid_impl(PyObject *module)
12755 : : /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12756 : : {
12757 : : gid_t rgid, egid, sgid;
12758 [ - + ]: 3 : if (getresgid(&rgid, &egid, &sgid) < 0)
12759 : 0 : return posix_error();
12760 : 3 : return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12761 : : _PyLong_FromGid(egid),
12762 : : _PyLong_FromGid(sgid));
12763 : : }
12764 : : #endif /* HAVE_GETRESGID */
12765 : :
12766 : :
12767 : : #ifdef USE_XATTRS
12768 : : /*[clinic input]
12769 : : os.getxattr
12770 : :
12771 : : path: path_t(allow_fd=True)
12772 : : attribute: path_t
12773 : : *
12774 : : follow_symlinks: bool = True
12775 : :
12776 : : Return the value of extended attribute attribute on path.
12777 : :
12778 : : path may be either a string, a path-like object, or an open file descriptor.
12779 : : If follow_symlinks is False, and the last element of the path is a symbolic
12780 : : link, getxattr will examine the symbolic link itself instead of the file
12781 : : the link points to.
12782 : :
12783 : : [clinic start generated code]*/
12784 : :
12785 : : static PyObject *
12786 : 21998 : os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12787 : : int follow_symlinks)
12788 : : /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12789 : : {
12790 : : Py_ssize_t i;
12791 : 21998 : PyObject *buffer = NULL;
12792 : :
12793 [ - + ]: 21998 : if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12794 : 0 : return NULL;
12795 : :
12796 [ - + ]: 21998 : if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12797 : 0 : return NULL;
12798 : : }
12799 : :
12800 : 22004 : for (i = 0; ; i++) {
12801 : : void *ptr;
12802 : : ssize_t result;
12803 : : static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12804 : 22004 : Py_ssize_t buffer_size = buffer_sizes[i];
12805 [ - + ]: 22004 : if (!buffer_size) {
12806 : 0 : path_error(path);
12807 : 0 : return NULL;
12808 : : }
12809 : 22004 : buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12810 [ - + ]: 22004 : if (!buffer)
12811 : 0 : return NULL;
12812 : 22004 : ptr = PyBytes_AS_STRING(buffer);
12813 : :
12814 : 22004 : Py_BEGIN_ALLOW_THREADS;
12815 [ + + ]: 22004 : if (path->fd >= 0)
12816 : 14 : result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12817 [ + + ]: 21990 : else if (follow_symlinks)
12818 : 21971 : result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12819 : : else
12820 : 19 : result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12821 : 22004 : Py_END_ALLOW_THREADS;
12822 : :
12823 [ + + ]: 22004 : if (result < 0) {
12824 : 23 : Py_DECREF(buffer);
12825 [ + + ]: 23 : if (errno == ERANGE)
12826 : 6 : continue;
12827 : 17 : path_error(path);
12828 : 17 : return NULL;
12829 : : }
12830 : :
12831 [ + - ]: 21981 : if (result != buffer_size) {
12832 : : /* Can only shrink. */
12833 : 21981 : _PyBytes_Resize(&buffer, result);
12834 : : }
12835 : 21981 : break;
12836 : : }
12837 : :
12838 : 21981 : return buffer;
12839 : : }
12840 : :
12841 : :
12842 : : /*[clinic input]
12843 : : os.setxattr
12844 : :
12845 : : path: path_t(allow_fd=True)
12846 : : attribute: path_t
12847 : : value: Py_buffer
12848 : : flags: int = 0
12849 : : *
12850 : : follow_symlinks: bool = True
12851 : :
12852 : : Set extended attribute attribute on path to value.
12853 : :
12854 : : path may be either a string, a path-like object, or an open file descriptor.
12855 : : If follow_symlinks is False, and the last element of the path is a symbolic
12856 : : link, setxattr will modify the symbolic link itself instead of the file
12857 : : the link points to.
12858 : :
12859 : : [clinic start generated code]*/
12860 : :
12861 : : static PyObject *
12862 : 22602 : os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12863 : : Py_buffer *value, int flags, int follow_symlinks)
12864 : : /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12865 : : {
12866 : : ssize_t result;
12867 : :
12868 [ - + ]: 22602 : if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12869 : 0 : return NULL;
12870 : :
12871 [ - + ]: 22602 : if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12872 : : value->buf, value->len, flags) < 0) {
12873 : 0 : return NULL;
12874 : : }
12875 : :
12876 : 22602 : Py_BEGIN_ALLOW_THREADS;
12877 [ + + ]: 22602 : if (path->fd > -1)
12878 : 216 : result = fsetxattr(path->fd, attribute->narrow,
12879 : 216 : value->buf, value->len, flags);
12880 [ + + ]: 22386 : else if (follow_symlinks)
12881 : 22169 : result = setxattr(path->narrow, attribute->narrow,
12882 : 22169 : value->buf, value->len, flags);
12883 : : else
12884 : 217 : result = lsetxattr(path->narrow, attribute->narrow,
12885 : 217 : value->buf, value->len, flags);
12886 : 22602 : Py_END_ALLOW_THREADS;
12887 : :
12888 [ + + ]: 22602 : if (result) {
12889 : 19 : path_error(path);
12890 : 19 : return NULL;
12891 : : }
12892 : :
12893 : 22583 : Py_RETURN_NONE;
12894 : : }
12895 : :
12896 : :
12897 : : /*[clinic input]
12898 : : os.removexattr
12899 : :
12900 : : path: path_t(allow_fd=True)
12901 : : attribute: path_t
12902 : : *
12903 : : follow_symlinks: bool = True
12904 : :
12905 : : Remove extended attribute attribute on path.
12906 : :
12907 : : path may be either a string, a path-like object, or an open file descriptor.
12908 : : If follow_symlinks is False, and the last element of the path is a symbolic
12909 : : link, removexattr will modify the symbolic link itself instead of the file
12910 : : the link points to.
12911 : :
12912 : : [clinic start generated code]*/
12913 : :
12914 : : static PyObject *
12915 : 17 : os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
12916 : : int follow_symlinks)
12917 : : /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
12918 : : {
12919 : : ssize_t result;
12920 : :
12921 [ - + ]: 17 : if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
12922 : 0 : return NULL;
12923 : :
12924 [ - + ]: 17 : if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
12925 : 0 : return NULL;
12926 : : }
12927 : :
12928 : 17 : Py_BEGIN_ALLOW_THREADS;
12929 [ + + ]: 17 : if (path->fd > -1)
12930 : 4 : result = fremovexattr(path->fd, attribute->narrow);
12931 [ + + ]: 13 : else if (follow_symlinks)
12932 : 9 : result = removexattr(path->narrow, attribute->narrow);
12933 : : else
12934 : 4 : result = lremovexattr(path->narrow, attribute->narrow);
12935 : 17 : Py_END_ALLOW_THREADS;
12936 : :
12937 [ + + ]: 17 : if (result) {
12938 : 5 : return path_error(path);
12939 : : }
12940 : :
12941 : 12 : Py_RETURN_NONE;
12942 : : }
12943 : :
12944 : :
12945 : : /*[clinic input]
12946 : : os.listxattr
12947 : :
12948 : : path: path_t(allow_fd=True, nullable=True) = None
12949 : : *
12950 : : follow_symlinks: bool = True
12951 : :
12952 : : Return a list of extended attributes on path.
12953 : :
12954 : : path may be either None, a string, a path-like object, or an open file descriptor.
12955 : : if path is None, listxattr will examine the current directory.
12956 : : If follow_symlinks is False, and the last element of the path is a symbolic
12957 : : link, listxattr will examine the symbolic link itself instead of the file
12958 : : the link points to.
12959 : : [clinic start generated code]*/
12960 : :
12961 : : static PyObject *
12962 : 21992 : os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
12963 : : /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
12964 : : {
12965 : : Py_ssize_t i;
12966 : 21992 : PyObject *result = NULL;
12967 : : const char *name;
12968 : 21992 : char *buffer = NULL;
12969 : :
12970 [ - + ]: 21992 : if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
12971 : 0 : goto exit;
12972 : :
12973 [ - + ]: 21992 : if (PySys_Audit("os.listxattr", "(O)",
12974 [ + - ]: 21992 : path->object ? path->object : Py_None) < 0) {
12975 : 0 : return NULL;
12976 : : }
12977 : :
12978 [ + + ]: 21992 : name = path->narrow ? path->narrow : ".";
12979 : :
12980 : 21998 : for (i = 0; ; i++) {
12981 : : const char *start, *trace, *end;
12982 : : ssize_t length;
12983 : : static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
12984 : 21998 : Py_ssize_t buffer_size = buffer_sizes[i];
12985 [ - + ]: 21998 : if (!buffer_size) {
12986 : : /* ERANGE */
12987 : 0 : path_error(path);
12988 : 0 : break;
12989 : : }
12990 : 21998 : buffer = PyMem_Malloc(buffer_size);
12991 [ - + ]: 21998 : if (!buffer) {
12992 : : PyErr_NoMemory();
12993 : 0 : break;
12994 : : }
12995 : :
12996 : 21998 : Py_BEGIN_ALLOW_THREADS;
12997 [ + + ]: 21998 : if (path->fd > -1)
12998 : 12 : length = flistxattr(path->fd, buffer, buffer_size);
12999 [ + + ]: 21986 : else if (follow_symlinks)
13000 : 21981 : length = listxattr(name, buffer, buffer_size);
13001 : : else
13002 : 5 : length = llistxattr(name, buffer, buffer_size);
13003 : 21998 : Py_END_ALLOW_THREADS;
13004 : :
13005 [ + + ]: 21998 : if (length < 0) {
13006 [ + + ]: 11 : if (errno == ERANGE) {
13007 : 6 : PyMem_Free(buffer);
13008 : 6 : buffer = NULL;
13009 : 6 : continue;
13010 : : }
13011 : 5 : path_error(path);
13012 : 5 : break;
13013 : : }
13014 : :
13015 : 21987 : result = PyList_New(0);
13016 [ - + ]: 21987 : if (!result) {
13017 : 0 : goto exit;
13018 : : }
13019 : :
13020 : 21987 : end = buffer + length;
13021 [ + + ]: 403158 : for (trace = start = buffer; trace != end; trace++) {
13022 [ + + ]: 381171 : if (!*trace) {
13023 : : int error;
13024 : 22611 : PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
13025 : : trace - start);
13026 [ - + ]: 22611 : if (!attribute) {
13027 : 0 : Py_DECREF(result);
13028 : 0 : result = NULL;
13029 : 0 : goto exit;
13030 : : }
13031 : 22611 : error = PyList_Append(result, attribute);
13032 : 22611 : Py_DECREF(attribute);
13033 [ - + ]: 22611 : if (error) {
13034 : 0 : Py_DECREF(result);
13035 : 0 : result = NULL;
13036 : 0 : goto exit;
13037 : : }
13038 : 22611 : start = trace + 1;
13039 : : }
13040 : : }
13041 : 21987 : break;
13042 : : }
13043 : 21992 : exit:
13044 [ + - ]: 21992 : if (buffer)
13045 : 21992 : PyMem_Free(buffer);
13046 : 21992 : return result;
13047 : : }
13048 : : #endif /* USE_XATTRS */
13049 : :
13050 : :
13051 : : /*[clinic input]
13052 : : os.urandom
13053 : :
13054 : : size: Py_ssize_t
13055 : : /
13056 : :
13057 : : Return a bytes object containing random bytes suitable for cryptographic use.
13058 : : [clinic start generated code]*/
13059 : :
13060 : : static PyObject *
13061 : 168900 : os_urandom_impl(PyObject *module, Py_ssize_t size)
13062 : : /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
13063 : : {
13064 : : PyObject *bytes;
13065 : : int result;
13066 : :
13067 [ + + ]: 168900 : if (size < 0)
13068 : 1 : return PyErr_Format(PyExc_ValueError,
13069 : : "negative argument not allowed");
13070 : 168899 : bytes = PyBytes_FromStringAndSize(NULL, size);
13071 [ - + ]: 168899 : if (bytes == NULL)
13072 : 0 : return NULL;
13073 : :
13074 : 168899 : result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
13075 [ - + ]: 168899 : if (result == -1) {
13076 : 0 : Py_DECREF(bytes);
13077 : 0 : return NULL;
13078 : : }
13079 : 168899 : return bytes;
13080 : : }
13081 : :
13082 : : #ifdef HAVE_MEMFD_CREATE
13083 : : /*[clinic input]
13084 : : os.memfd_create
13085 : :
13086 : : name: FSConverter
13087 : : flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
13088 : :
13089 : : [clinic start generated code]*/
13090 : :
13091 : : static PyObject *
13092 : 2 : os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
13093 : : /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
13094 : : {
13095 : : int fd;
13096 : 2 : const char *bytes = PyBytes_AS_STRING(name);
13097 : 2 : Py_BEGIN_ALLOW_THREADS
13098 : 2 : fd = memfd_create(bytes, flags);
13099 : 2 : Py_END_ALLOW_THREADS
13100 [ - + ]: 2 : if (fd == -1) {
13101 : 0 : return PyErr_SetFromErrno(PyExc_OSError);
13102 : : }
13103 : 2 : return PyLong_FromLong(fd);
13104 : : }
13105 : : #endif
13106 : :
13107 : : #ifdef HAVE_EVENTFD
13108 : : /*[clinic input]
13109 : : os.eventfd
13110 : :
13111 : : initval: unsigned_int
13112 : : flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
13113 : :
13114 : : Creates and returns an event notification file descriptor.
13115 : : [clinic start generated code]*/
13116 : :
13117 : : static PyObject *
13118 : 3 : os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
13119 : : /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
13120 : :
13121 : : {
13122 : : /* initval is limited to uint32_t, internal counter is uint64_t */
13123 : : int fd;
13124 : 3 : Py_BEGIN_ALLOW_THREADS
13125 : 3 : fd = eventfd(initval, flags);
13126 : 3 : Py_END_ALLOW_THREADS
13127 [ - + ]: 3 : if (fd == -1) {
13128 : 0 : return PyErr_SetFromErrno(PyExc_OSError);
13129 : : }
13130 : 3 : return PyLong_FromLong(fd);
13131 : : }
13132 : :
13133 : : /*[clinic input]
13134 : : os.eventfd_read
13135 : :
13136 : : fd: fildes
13137 : :
13138 : : Read eventfd value
13139 : : [clinic start generated code]*/
13140 : :
13141 : : static PyObject *
13142 : 8 : os_eventfd_read_impl(PyObject *module, int fd)
13143 : : /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
13144 : : {
13145 : : eventfd_t value;
13146 : : int result;
13147 : 8 : Py_BEGIN_ALLOW_THREADS
13148 : 8 : result = eventfd_read(fd, &value);
13149 : 8 : Py_END_ALLOW_THREADS
13150 [ + + ]: 8 : if (result == -1) {
13151 : 2 : return PyErr_SetFromErrno(PyExc_OSError);
13152 : : }
13153 : 6 : return PyLong_FromUnsignedLongLong(value);
13154 : : }
13155 : :
13156 : : /*[clinic input]
13157 : : os.eventfd_write
13158 : :
13159 : : fd: fildes
13160 : : value: unsigned_long_long
13161 : :
13162 : : Write eventfd value.
13163 : : [clinic start generated code]*/
13164 : :
13165 : : static PyObject *
13166 : 5 : os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
13167 : : /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
13168 : : {
13169 : : int result;
13170 : 5 : Py_BEGIN_ALLOW_THREADS
13171 : 5 : result = eventfd_write(fd, value);
13172 : 5 : Py_END_ALLOW_THREADS
13173 [ - + ]: 5 : if (result == -1) {
13174 : 0 : return PyErr_SetFromErrno(PyExc_OSError);
13175 : : }
13176 : 5 : Py_RETURN_NONE;
13177 : : }
13178 : : #endif /* HAVE_EVENTFD */
13179 : :
13180 : : /* Terminal size querying */
13181 : :
13182 : : PyDoc_STRVAR(TerminalSize_docstring,
13183 : : "A tuple of (columns, lines) for holding terminal window size");
13184 : :
13185 : : static PyStructSequence_Field TerminalSize_fields[] = {
13186 : : {"columns", "width of the terminal window in characters"},
13187 : : {"lines", "height of the terminal window in characters"},
13188 : : {NULL, NULL}
13189 : : };
13190 : :
13191 : : static PyStructSequence_Desc TerminalSize_desc = {
13192 : : "os.terminal_size",
13193 : : TerminalSize_docstring,
13194 : : TerminalSize_fields,
13195 : : 2,
13196 : : };
13197 : :
13198 : : #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
13199 : : /*[clinic input]
13200 : : os.get_terminal_size
13201 : :
13202 : : fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
13203 : : /
13204 : :
13205 : : Return the size of the terminal window as (columns, lines).
13206 : :
13207 : : The optional argument fd (default standard output) specifies
13208 : : which file descriptor should be queried.
13209 : :
13210 : : If the file descriptor is not connected to a terminal, an OSError
13211 : : is thrown.
13212 : :
13213 : : This function will only be defined if an implementation is
13214 : : available for this system.
13215 : :
13216 : : shutil.get_terminal_size is the high-level function which should
13217 : : normally be used, os.get_terminal_size is the low-level implementation.
13218 : : [clinic start generated code]*/
13219 : :
13220 : : static PyObject *
13221 : 10822 : os_get_terminal_size_impl(PyObject *module, int fd)
13222 : : /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
13223 : : {
13224 : : int columns, lines;
13225 : : PyObject *termsize;
13226 : :
13227 : : /* Under some conditions stdout may not be connected and
13228 : : * fileno(stdout) may point to an invalid file descriptor. For example
13229 : : * GUI apps don't have valid standard streams by default.
13230 : : *
13231 : : * If this happens, and the optional fd argument is not present,
13232 : : * the ioctl below will fail returning EBADF. This is what we want.
13233 : : */
13234 : :
13235 : : #ifdef TERMSIZE_USE_IOCTL
13236 : : {
13237 : : struct winsize w;
13238 [ + + ]: 10822 : if (ioctl(fd, TIOCGWINSZ, &w))
13239 : 10711 : return PyErr_SetFromErrno(PyExc_OSError);
13240 : 111 : columns = w.ws_col;
13241 : 111 : lines = w.ws_row;
13242 : : }
13243 : : #endif /* TERMSIZE_USE_IOCTL */
13244 : :
13245 : : #ifdef TERMSIZE_USE_CONIO
13246 : : {
13247 : : DWORD nhandle;
13248 : : HANDLE handle;
13249 : : CONSOLE_SCREEN_BUFFER_INFO csbi;
13250 : : switch (fd) {
13251 : : case 0: nhandle = STD_INPUT_HANDLE;
13252 : : break;
13253 : : case 1: nhandle = STD_OUTPUT_HANDLE;
13254 : : break;
13255 : : case 2: nhandle = STD_ERROR_HANDLE;
13256 : : break;
13257 : : default:
13258 : : return PyErr_Format(PyExc_ValueError, "bad file descriptor");
13259 : : }
13260 : : handle = GetStdHandle(nhandle);
13261 : : if (handle == NULL)
13262 : : return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
13263 : : if (handle == INVALID_HANDLE_VALUE)
13264 : : return PyErr_SetFromWindowsErr(0);
13265 : :
13266 : : if (!GetConsoleScreenBufferInfo(handle, &csbi))
13267 : : return PyErr_SetFromWindowsErr(0);
13268 : :
13269 : : columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
13270 : : lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
13271 : : }
13272 : : #endif /* TERMSIZE_USE_CONIO */
13273 : :
13274 : 111 : PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
13275 : 111 : termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
13276 [ - + ]: 111 : if (termsize == NULL)
13277 : 0 : return NULL;
13278 : 111 : PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
13279 : 111 : PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
13280 [ - + ]: 111 : if (PyErr_Occurred()) {
13281 : 0 : Py_DECREF(termsize);
13282 : 0 : return NULL;
13283 : : }
13284 : 111 : return termsize;
13285 : : }
13286 : : #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
13287 : :
13288 : :
13289 : : /*[clinic input]
13290 : : os.cpu_count
13291 : :
13292 : : Return the number of CPUs in the system; return None if indeterminable.
13293 : :
13294 : : This number is not equivalent to the number of CPUs the current process can
13295 : : use. The number of usable CPUs can be obtained with
13296 : : ``len(os.sched_getaffinity(0))``
13297 : : [clinic start generated code]*/
13298 : :
13299 : : static PyObject *
13300 : 104 : os_cpu_count_impl(PyObject *module)
13301 : : /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
13302 : : {
13303 : 104 : int ncpu = 0;
13304 : : #ifdef MS_WINDOWS
13305 : : ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
13306 : : #elif defined(__hpux)
13307 : : ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
13308 : : #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
13309 : 104 : ncpu = sysconf(_SC_NPROCESSORS_ONLN);
13310 : : #elif defined(__VXWORKS__)
13311 : : ncpu = _Py_popcount32(vxCpuEnabledGet());
13312 : : #elif defined(__DragonFly__) || \
13313 : : defined(__OpenBSD__) || \
13314 : : defined(__FreeBSD__) || \
13315 : : defined(__NetBSD__) || \
13316 : : defined(__APPLE__)
13317 : : int mib[2];
13318 : : size_t len = sizeof(ncpu);
13319 : : mib[0] = CTL_HW;
13320 : : mib[1] = HW_NCPU;
13321 : : if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
13322 : : ncpu = 0;
13323 : : #endif
13324 [ + - ]: 104 : if (ncpu >= 1)
13325 : 104 : return PyLong_FromLong(ncpu);
13326 : : else
13327 : 0 : Py_RETURN_NONE;
13328 : : }
13329 : :
13330 : :
13331 : : /*[clinic input]
13332 : : os.get_inheritable -> bool
13333 : :
13334 : : fd: int
13335 : : /
13336 : :
13337 : : Get the close-on-exe flag of the specified file descriptor.
13338 : : [clinic start generated code]*/
13339 : :
13340 : : static int
13341 : 130 : os_get_inheritable_impl(PyObject *module, int fd)
13342 : : /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
13343 : : {
13344 : : int return_value;
13345 : : _Py_BEGIN_SUPPRESS_IPH
13346 : 130 : return_value = _Py_get_inheritable(fd);
13347 : : _Py_END_SUPPRESS_IPH
13348 : 130 : return return_value;
13349 : : }
13350 : :
13351 : :
13352 : : /*[clinic input]
13353 : : os.set_inheritable
13354 : : fd: int
13355 : : inheritable: int
13356 : : /
13357 : :
13358 : : Set the inheritable flag of the specified file descriptor.
13359 : : [clinic start generated code]*/
13360 : :
13361 : : static PyObject *
13362 : 61 : os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
13363 : : /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
13364 : : {
13365 : : int result;
13366 : :
13367 : : _Py_BEGIN_SUPPRESS_IPH
13368 : 61 : result = _Py_set_inheritable(fd, inheritable, NULL);
13369 : : _Py_END_SUPPRESS_IPH
13370 [ + + ]: 61 : if (result < 0)
13371 : 3 : return NULL;
13372 : 58 : Py_RETURN_NONE;
13373 : : }
13374 : :
13375 : :
13376 : : #ifdef MS_WINDOWS
13377 : : /*[clinic input]
13378 : : os.get_handle_inheritable -> bool
13379 : : handle: intptr_t
13380 : : /
13381 : :
13382 : : Get the close-on-exe flag of the specified file descriptor.
13383 : : [clinic start generated code]*/
13384 : :
13385 : : static int
13386 : : os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
13387 : : /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
13388 : : {
13389 : : DWORD flags;
13390 : :
13391 : : if (!GetHandleInformation((HANDLE)handle, &flags)) {
13392 : : PyErr_SetFromWindowsErr(0);
13393 : : return -1;
13394 : : }
13395 : :
13396 : : return flags & HANDLE_FLAG_INHERIT;
13397 : : }
13398 : :
13399 : :
13400 : : /*[clinic input]
13401 : : os.set_handle_inheritable
13402 : : handle: intptr_t
13403 : : inheritable: bool
13404 : : /
13405 : :
13406 : : Set the inheritable flag of the specified handle.
13407 : : [clinic start generated code]*/
13408 : :
13409 : : static PyObject *
13410 : : os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
13411 : : int inheritable)
13412 : : /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
13413 : : {
13414 : : DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
13415 : : if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
13416 : : PyErr_SetFromWindowsErr(0);
13417 : : return NULL;
13418 : : }
13419 : : Py_RETURN_NONE;
13420 : : }
13421 : : #endif /* MS_WINDOWS */
13422 : :
13423 : : #ifndef MS_WINDOWS
13424 : : /*[clinic input]
13425 : : os.get_blocking -> bool
13426 : : fd: int
13427 : : /
13428 : :
13429 : : Get the blocking mode of the file descriptor.
13430 : :
13431 : : Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
13432 : : [clinic start generated code]*/
13433 : :
13434 : : static int
13435 : 6 : os_get_blocking_impl(PyObject *module, int fd)
13436 : : /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
13437 : : {
13438 : : int blocking;
13439 : :
13440 : : _Py_BEGIN_SUPPRESS_IPH
13441 : 6 : blocking = _Py_get_blocking(fd);
13442 : : _Py_END_SUPPRESS_IPH
13443 : 6 : return blocking;
13444 : : }
13445 : :
13446 : : /*[clinic input]
13447 : : os.set_blocking
13448 : : fd: int
13449 : : blocking: bool(accept={int})
13450 : : /
13451 : :
13452 : : Set the blocking mode of the specified file descriptor.
13453 : :
13454 : : Set the O_NONBLOCK flag if blocking is False,
13455 : : clear the O_NONBLOCK flag otherwise.
13456 : : [clinic start generated code]*/
13457 : :
13458 : : static PyObject *
13459 : 323 : os_set_blocking_impl(PyObject *module, int fd, int blocking)
13460 : : /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
13461 : : {
13462 : : int result;
13463 : :
13464 : : _Py_BEGIN_SUPPRESS_IPH
13465 : 323 : result = _Py_set_blocking(fd, blocking);
13466 : : _Py_END_SUPPRESS_IPH
13467 [ + + ]: 323 : if (result < 0)
13468 : 1 : return NULL;
13469 : 322 : Py_RETURN_NONE;
13470 : : }
13471 : : #endif /* !MS_WINDOWS */
13472 : :
13473 : :
13474 : : /*[clinic input]
13475 : : class os.DirEntry "DirEntry *" "DirEntryType"
13476 : : [clinic start generated code]*/
13477 : : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
13478 : :
13479 : : typedef struct {
13480 : : PyObject_HEAD
13481 : : PyObject *name;
13482 : : PyObject *path;
13483 : : PyObject *stat;
13484 : : PyObject *lstat;
13485 : : #ifdef MS_WINDOWS
13486 : : struct _Py_stat_struct win32_lstat;
13487 : : uint64_t win32_file_index;
13488 : : int got_file_index;
13489 : : #else /* POSIX */
13490 : : #ifdef HAVE_DIRENT_D_TYPE
13491 : : unsigned char d_type;
13492 : : #endif
13493 : : ino_t d_ino;
13494 : : int dir_fd;
13495 : : #endif
13496 : : } DirEntry;
13497 : :
13498 : : static void
13499 : 129650 : DirEntry_dealloc(DirEntry *entry)
13500 : : {
13501 : 129650 : PyTypeObject *tp = Py_TYPE(entry);
13502 : 129650 : Py_XDECREF(entry->name);
13503 : 129650 : Py_XDECREF(entry->path);
13504 : 129650 : Py_XDECREF(entry->stat);
13505 : 129650 : Py_XDECREF(entry->lstat);
13506 : 129650 : freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13507 : 129650 : free_func(entry);
13508 : 129650 : Py_DECREF(tp);
13509 : 129650 : }
13510 : :
13511 : : /* Forward reference */
13512 : : static int
13513 : : DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13514 : : int follow_symlinks, unsigned short mode_bits);
13515 : :
13516 : : /*[clinic input]
13517 : : os.DirEntry.is_symlink -> bool
13518 : : defining_class: defining_class
13519 : : /
13520 : :
13521 : : Return True if the entry is a symbolic link; cached per entry.
13522 : : [clinic start generated code]*/
13523 : :
13524 : : static int
13525 : 60370 : os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
13526 : : /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
13527 : : {
13528 : : #ifdef MS_WINDOWS
13529 : : return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13530 : : #elif defined(HAVE_DIRENT_D_TYPE)
13531 : : /* POSIX */
13532 [ + - ]: 60370 : if (self->d_type != DT_UNKNOWN)
13533 : 60370 : return self->d_type == DT_LNK;
13534 : : else
13535 : 0 : return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13536 : : #else
13537 : : /* POSIX without d_type */
13538 : : return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13539 : : #endif
13540 : : }
13541 : :
13542 : : static PyObject *
13543 : 31735 : DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
13544 : : {
13545 : : int result;
13546 : : STRUCT_STAT st;
13547 : : PyObject *ub;
13548 : :
13549 : : #ifdef MS_WINDOWS
13550 : : if (!PyUnicode_FSDecoder(self->path, &ub))
13551 : : return NULL;
13552 : : wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
13553 : : Py_DECREF(ub);
13554 : : #else /* POSIX */
13555 [ - + ]: 31735 : if (!PyUnicode_FSConverter(self->path, &ub))
13556 : 0 : return NULL;
13557 : 31735 : const char *path = PyBytes_AS_STRING(ub);
13558 [ + + ]: 31735 : if (self->dir_fd != DEFAULT_DIR_FD) {
13559 : : #ifdef HAVE_FSTATAT
13560 : : if (HAVE_FSTATAT_RUNTIME) {
13561 : 9015 : Py_BEGIN_ALLOW_THREADS
13562 [ + + ]: 9015 : result = fstatat(self->dir_fd, path, &st,
13563 : : follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
13564 : 9015 : Py_END_ALLOW_THREADS
13565 : : } else
13566 : :
13567 : : #endif /* HAVE_FSTATAT */
13568 : : {
13569 : : Py_DECREF(ub);
13570 : : PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
13571 : : return NULL;
13572 : : }
13573 : : }
13574 : : else
13575 : : #endif
13576 : : {
13577 : 22720 : Py_BEGIN_ALLOW_THREADS
13578 [ + + ]: 22720 : if (follow_symlinks) {
13579 : 1114 : result = STAT(path, &st);
13580 : : }
13581 : : else {
13582 : 21606 : result = LSTAT(path, &st);
13583 : : }
13584 : 22720 : Py_END_ALLOW_THREADS
13585 : : }
13586 : : #if defined(MS_WINDOWS)
13587 : : PyMem_Free(path);
13588 : : #else
13589 : 31735 : Py_DECREF(ub);
13590 : : #endif
13591 : :
13592 [ + + ]: 31735 : if (result != 0)
13593 : 2173 : return path_object_error(self->path);
13594 : :
13595 : 29562 : return _pystat_fromstructstat(module, &st);
13596 : : }
13597 : :
13598 : : static PyObject *
13599 : 28300 : DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
13600 : : {
13601 [ + + ]: 28300 : if (!self->lstat) {
13602 : 28296 : PyObject *module = PyType_GetModule(defining_class);
13603 : : #ifdef MS_WINDOWS
13604 : : self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
13605 : : #else /* POSIX */
13606 : 28296 : self->lstat = DirEntry_fetch_stat(module, self, 0);
13607 : : #endif
13608 : : }
13609 : 28300 : Py_XINCREF(self->lstat);
13610 : 28300 : return self->lstat;
13611 : : }
13612 : :
13613 : : /*[clinic input]
13614 : : os.DirEntry.stat
13615 : : defining_class: defining_class
13616 : : /
13617 : : *
13618 : : follow_symlinks: bool = True
13619 : :
13620 : : Return stat_result object for the entry; cached per entry.
13621 : : [clinic start generated code]*/
13622 : :
13623 : : static PyObject *
13624 : 72843 : os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
13625 : : int follow_symlinks)
13626 : : /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
13627 : : {
13628 [ + + ]: 72843 : if (!follow_symlinks) {
13629 : 6701 : return DirEntry_get_lstat(defining_class, self);
13630 : : }
13631 : :
13632 [ + + ]: 66142 : if (!self->stat) {
13633 : 25038 : int result = os_DirEntry_is_symlink_impl(self, defining_class);
13634 [ - + ]: 25038 : if (result == -1) {
13635 : 0 : return NULL;
13636 : : }
13637 [ + + ]: 25038 : if (result) {
13638 : 3439 : PyObject *module = PyType_GetModule(defining_class);
13639 : 3439 : self->stat = DirEntry_fetch_stat(module, self, 1);
13640 : : }
13641 : : else {
13642 : 21599 : self->stat = DirEntry_get_lstat(defining_class, self);
13643 : : }
13644 : : }
13645 : :
13646 : 66142 : Py_XINCREF(self->stat);
13647 : 66142 : return self->stat;
13648 : : }
13649 : :
13650 : : /* Set exception and return -1 on error, 0 for False, 1 for True */
13651 : : static int
13652 : 122509 : DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13653 : : int follow_symlinks, unsigned short mode_bits)
13654 : : {
13655 : 122509 : PyObject *stat = NULL;
13656 : 122509 : PyObject *st_mode = NULL;
13657 : : long mode;
13658 : : int result;
13659 : : #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13660 : : int is_symlink;
13661 : : int need_stat;
13662 : : #endif
13663 : : #ifdef MS_WINDOWS
13664 : : unsigned long dir_bits;
13665 : : #endif
13666 : :
13667 : : #ifdef MS_WINDOWS
13668 : : is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13669 : : need_stat = follow_symlinks && is_symlink;
13670 : : #elif defined(HAVE_DIRENT_D_TYPE)
13671 : 122509 : is_symlink = self->d_type == DT_LNK;
13672 [ + - + + : 122509 : need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
+ + ]
13673 : : #endif
13674 : :
13675 : : #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13676 [ + + ]: 122509 : if (need_stat) {
13677 : : #endif
13678 : 3437 : stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
13679 [ + + ]: 3437 : if (!stat) {
13680 [ + + ]: 2166 : if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
13681 : : /* If file doesn't exist (anymore), then return False
13682 : : (i.e., say it's not a file/directory) */
13683 : 982 : PyErr_Clear();
13684 : 982 : return 0;
13685 : : }
13686 : 1184 : goto error;
13687 : : }
13688 : 1271 : _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
13689 : 1271 : st_mode = PyObject_GetAttr(stat, state->st_mode);
13690 [ - + ]: 1271 : if (!st_mode)
13691 : 0 : goto error;
13692 : :
13693 : 1271 : mode = PyLong_AsLong(st_mode);
13694 [ - + - - ]: 1271 : if (mode == -1 && PyErr_Occurred())
13695 : 0 : goto error;
13696 [ + - ]: 1271 : Py_CLEAR(st_mode);
13697 [ + - ]: 1271 : Py_CLEAR(stat);
13698 : 1271 : result = (mode & S_IFMT) == mode_bits;
13699 : : #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13700 : : }
13701 [ + + ]: 119072 : else if (is_symlink) {
13702 : : assert(mode_bits != S_IFLNK);
13703 : 1277 : result = 0;
13704 : : }
13705 : : else {
13706 : : assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
13707 : : #ifdef MS_WINDOWS
13708 : : dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
13709 : : if (mode_bits == S_IFDIR)
13710 : : result = dir_bits != 0;
13711 : : else
13712 : : result = dir_bits == 0;
13713 : : #else /* POSIX */
13714 [ + + ]: 117795 : if (mode_bits == S_IFDIR)
13715 : 117788 : result = self->d_type == DT_DIR;
13716 : : else
13717 : 7 : result = self->d_type == DT_REG;
13718 : : #endif
13719 : : }
13720 : : #endif
13721 : :
13722 : 120343 : return result;
13723 : :
13724 : 1184 : error:
13725 : 1184 : Py_XDECREF(st_mode);
13726 : 1184 : Py_XDECREF(stat);
13727 : 1184 : return -1;
13728 : : }
13729 : :
13730 : : /*[clinic input]
13731 : : os.DirEntry.is_dir -> bool
13732 : : defining_class: defining_class
13733 : : /
13734 : : *
13735 : : follow_symlinks: bool = True
13736 : :
13737 : : Return True if the entry is a directory; cached per entry.
13738 : : [clinic start generated code]*/
13739 : :
13740 : : static int
13741 : 122496 : os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
13742 : : int follow_symlinks)
13743 : : /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
13744 : : {
13745 : 122496 : return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
13746 : : }
13747 : :
13748 : : /*[clinic input]
13749 : : os.DirEntry.is_file -> bool
13750 : : defining_class: defining_class
13751 : : /
13752 : : *
13753 : : follow_symlinks: bool = True
13754 : :
13755 : : Return True if the entry is a file; cached per entry.
13756 : : [clinic start generated code]*/
13757 : :
13758 : : static int
13759 : 13 : os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
13760 : : int follow_symlinks)
13761 : : /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
13762 : : {
13763 : 13 : return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
13764 : : }
13765 : :
13766 : : /*[clinic input]
13767 : : os.DirEntry.inode
13768 : :
13769 : : Return inode of the entry; cached per entry.
13770 : : [clinic start generated code]*/
13771 : :
13772 : : static PyObject *
13773 : 8 : os_DirEntry_inode_impl(DirEntry *self)
13774 : : /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
13775 : : {
13776 : : #ifdef MS_WINDOWS
13777 : : if (!self->got_file_index) {
13778 : : PyObject *unicode;
13779 : : STRUCT_STAT stat;
13780 : : int result;
13781 : :
13782 : : if (!PyUnicode_FSDecoder(self->path, &unicode))
13783 : : return NULL;
13784 : : wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
13785 : : Py_DECREF(unicode);
13786 : : result = LSTAT(path, &stat);
13787 : : PyMem_Free(path);
13788 : :
13789 : : if (result != 0)
13790 : : return path_object_error(self->path);
13791 : :
13792 : : self->win32_file_index = stat.st_ino;
13793 : : self->got_file_index = 1;
13794 : : }
13795 : : static_assert(sizeof(unsigned long long) >= sizeof(self->win32_file_index),
13796 : : "DirEntry.win32_file_index is larger than unsigned long long");
13797 : : return PyLong_FromUnsignedLongLong(self->win32_file_index);
13798 : : #else /* POSIX */
13799 : : static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
13800 : : "DirEntry.d_ino is larger than unsigned long long");
13801 : 8 : return PyLong_FromUnsignedLongLong(self->d_ino);
13802 : : #endif
13803 : : }
13804 : :
13805 : : static PyObject *
13806 : 1 : DirEntry_repr(DirEntry *self)
13807 : : {
13808 : 1 : return PyUnicode_FromFormat("<DirEntry %R>", self->name);
13809 : : }
13810 : :
13811 : : /*[clinic input]
13812 : : os.DirEntry.__fspath__
13813 : :
13814 : : Returns the path for the entry.
13815 : : [clinic start generated code]*/
13816 : :
13817 : : static PyObject *
13818 : 87597 : os_DirEntry___fspath___impl(DirEntry *self)
13819 : : /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
13820 : : {
13821 : 87597 : Py_INCREF(self->path);
13822 : 87597 : return self->path;
13823 : : }
13824 : :
13825 : : static PyMemberDef DirEntry_members[] = {
13826 : : {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
13827 : : "the entry's base filename, relative to scandir() \"path\" argument"},
13828 : : {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
13829 : : "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
13830 : : {NULL}
13831 : : };
13832 : :
13833 : : #include "clinic/posixmodule.c.h"
13834 : :
13835 : : static PyMethodDef DirEntry_methods[] = {
13836 : : OS_DIRENTRY_IS_DIR_METHODDEF
13837 : : OS_DIRENTRY_IS_FILE_METHODDEF
13838 : : OS_DIRENTRY_IS_SYMLINK_METHODDEF
13839 : : OS_DIRENTRY_STAT_METHODDEF
13840 : : OS_DIRENTRY_INODE_METHODDEF
13841 : : OS_DIRENTRY___FSPATH___METHODDEF
13842 : : {"__class_getitem__", Py_GenericAlias,
13843 : : METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
13844 : : {NULL}
13845 : : };
13846 : :
13847 : : static PyType_Slot DirEntryType_slots[] = {
13848 : : {Py_tp_dealloc, DirEntry_dealloc},
13849 : : {Py_tp_repr, DirEntry_repr},
13850 : : {Py_tp_methods, DirEntry_methods},
13851 : : {Py_tp_members, DirEntry_members},
13852 : : {0, 0},
13853 : : };
13854 : :
13855 : : static PyType_Spec DirEntryType_spec = {
13856 : : MODNAME ".DirEntry",
13857 : : sizeof(DirEntry),
13858 : : 0,
13859 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
13860 : : DirEntryType_slots
13861 : : };
13862 : :
13863 : :
13864 : : #ifdef MS_WINDOWS
13865 : :
13866 : : static wchar_t *
13867 : : join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
13868 : : {
13869 : : Py_ssize_t path_len;
13870 : : Py_ssize_t size;
13871 : : wchar_t *result;
13872 : : wchar_t ch;
13873 : :
13874 : : if (!path_wide) { /* Default arg: "." */
13875 : : path_wide = L".";
13876 : : path_len = 1;
13877 : : }
13878 : : else {
13879 : : path_len = wcslen(path_wide);
13880 : : }
13881 : :
13882 : : /* The +1's are for the path separator and the NUL */
13883 : : size = path_len + 1 + wcslen(filename) + 1;
13884 : : result = PyMem_New(wchar_t, size);
13885 : : if (!result) {
13886 : : PyErr_NoMemory();
13887 : : return NULL;
13888 : : }
13889 : : wcscpy(result, path_wide);
13890 : : if (path_len > 0) {
13891 : : ch = result[path_len - 1];
13892 : : if (ch != SEP && ch != ALTSEP && ch != L':')
13893 : : result[path_len++] = SEP;
13894 : : wcscpy(result + path_len, filename);
13895 : : }
13896 : : return result;
13897 : : }
13898 : :
13899 : : static PyObject *
13900 : : DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
13901 : : {
13902 : : DirEntry *entry;
13903 : : BY_HANDLE_FILE_INFORMATION file_info;
13904 : : ULONG reparse_tag;
13905 : : wchar_t *joined_path;
13906 : :
13907 : : PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13908 : : entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13909 : : if (!entry)
13910 : : return NULL;
13911 : : entry->name = NULL;
13912 : : entry->path = NULL;
13913 : : entry->stat = NULL;
13914 : : entry->lstat = NULL;
13915 : : entry->got_file_index = 0;
13916 : :
13917 : : entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
13918 : : if (!entry->name)
13919 : : goto error;
13920 : : if (path->narrow) {
13921 : : Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
13922 : : if (!entry->name)
13923 : : goto error;
13924 : : }
13925 : :
13926 : : joined_path = join_path_filenameW(path->wide, dataW->cFileName);
13927 : : if (!joined_path)
13928 : : goto error;
13929 : :
13930 : : entry->path = PyUnicode_FromWideChar(joined_path, -1);
13931 : : PyMem_Free(joined_path);
13932 : : if (!entry->path)
13933 : : goto error;
13934 : : if (path->narrow) {
13935 : : Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
13936 : : if (!entry->path)
13937 : : goto error;
13938 : : }
13939 : :
13940 : : find_data_to_file_info(dataW, &file_info, &reparse_tag);
13941 : : _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
13942 : :
13943 : : return (PyObject *)entry;
13944 : :
13945 : : error:
13946 : : Py_DECREF(entry);
13947 : : return NULL;
13948 : : }
13949 : :
13950 : : #else /* POSIX */
13951 : :
13952 : : static char *
13953 : 73040 : join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
13954 : : {
13955 : : Py_ssize_t path_len;
13956 : : Py_ssize_t size;
13957 : : char *result;
13958 : :
13959 [ + + ]: 73040 : if (!path_narrow) { /* Default arg: "." */
13960 : 1 : path_narrow = ".";
13961 : 1 : path_len = 1;
13962 : : }
13963 : : else {
13964 : 73039 : path_len = strlen(path_narrow);
13965 : : }
13966 : :
13967 [ - + ]: 73040 : if (filename_len == -1)
13968 : 0 : filename_len = strlen(filename);
13969 : :
13970 : : /* The +1's are for the path separator and the NUL */
13971 : 73040 : size = path_len + 1 + filename_len + 1;
13972 [ + - ]: 73040 : result = PyMem_New(char, size);
13973 [ - + ]: 73040 : if (!result) {
13974 : : PyErr_NoMemory();
13975 : 0 : return NULL;
13976 : : }
13977 : 73040 : strcpy(result, path_narrow);
13978 [ + - + + ]: 73040 : if (path_len > 0 && result[path_len - 1] != '/')
13979 : 72950 : result[path_len++] = '/';
13980 : 73040 : strcpy(result + path_len, filename);
13981 : 73040 : return result;
13982 : : }
13983 : :
13984 : : static PyObject *
13985 : 129650 : DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
13986 : : Py_ssize_t name_len, ino_t d_ino
13987 : : #ifdef HAVE_DIRENT_D_TYPE
13988 : : , unsigned char d_type
13989 : : #endif
13990 : : )
13991 : : {
13992 : : DirEntry *entry;
13993 : : char *joined_path;
13994 : :
13995 : 129650 : PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13996 : 129650 : entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13997 [ - + ]: 129650 : if (!entry)
13998 : 0 : return NULL;
13999 : 129650 : entry->name = NULL;
14000 : 129650 : entry->path = NULL;
14001 : 129650 : entry->stat = NULL;
14002 : 129650 : entry->lstat = NULL;
14003 : :
14004 [ + + ]: 129650 : if (path->fd != -1) {
14005 : 56610 : entry->dir_fd = path->fd;
14006 : 56610 : joined_path = NULL;
14007 : : }
14008 : : else {
14009 : 73040 : entry->dir_fd = DEFAULT_DIR_FD;
14010 : 73040 : joined_path = join_path_filename(path->narrow, name, name_len);
14011 [ - + ]: 73040 : if (!joined_path)
14012 : 0 : goto error;
14013 : : }
14014 : :
14015 [ + + + + ]: 129650 : if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
14016 : 121303 : entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
14017 [ + + ]: 121303 : if (joined_path)
14018 : 64693 : entry->path = PyUnicode_DecodeFSDefault(joined_path);
14019 : : }
14020 : : else {
14021 : 8347 : entry->name = PyBytes_FromStringAndSize(name, name_len);
14022 [ + - ]: 8347 : if (joined_path)
14023 : 8347 : entry->path = PyBytes_FromString(joined_path);
14024 : : }
14025 : 129650 : PyMem_Free(joined_path);
14026 [ - + ]: 129650 : if (!entry->name)
14027 : 0 : goto error;
14028 : :
14029 [ + + ]: 129650 : if (path->fd != -1) {
14030 : 56610 : entry->path = entry->name;
14031 : 56610 : Py_INCREF(entry->path);
14032 : : }
14033 [ - + ]: 73040 : else if (!entry->path)
14034 : 0 : goto error;
14035 : :
14036 : : #ifdef HAVE_DIRENT_D_TYPE
14037 : 129650 : entry->d_type = d_type;
14038 : : #endif
14039 : 129650 : entry->d_ino = d_ino;
14040 : :
14041 : 129650 : return (PyObject *)entry;
14042 : :
14043 : 0 : error:
14044 : 0 : Py_XDECREF(entry);
14045 : 0 : return NULL;
14046 : : }
14047 : :
14048 : : #endif
14049 : :
14050 : :
14051 : : typedef struct {
14052 : : PyObject_HEAD
14053 : : path_t path;
14054 : : #ifdef MS_WINDOWS
14055 : : HANDLE handle;
14056 : : WIN32_FIND_DATAW file_data;
14057 : : int first_time;
14058 : : #else /* POSIX */
14059 : : DIR *dirp;
14060 : : #endif
14061 : : #ifdef HAVE_FDOPENDIR
14062 : : int fd;
14063 : : #endif
14064 : : } ScandirIterator;
14065 : :
14066 : : #ifdef MS_WINDOWS
14067 : :
14068 : : static int
14069 : : ScandirIterator_is_closed(ScandirIterator *iterator)
14070 : : {
14071 : : return iterator->handle == INVALID_HANDLE_VALUE;
14072 : : }
14073 : :
14074 : : static void
14075 : : ScandirIterator_closedir(ScandirIterator *iterator)
14076 : : {
14077 : : HANDLE handle = iterator->handle;
14078 : :
14079 : : if (handle == INVALID_HANDLE_VALUE)
14080 : : return;
14081 : :
14082 : : iterator->handle = INVALID_HANDLE_VALUE;
14083 : : Py_BEGIN_ALLOW_THREADS
14084 : : FindClose(handle);
14085 : : Py_END_ALLOW_THREADS
14086 : : }
14087 : :
14088 : : static PyObject *
14089 : : ScandirIterator_iternext(ScandirIterator *iterator)
14090 : : {
14091 : : WIN32_FIND_DATAW *file_data = &iterator->file_data;
14092 : : BOOL success;
14093 : : PyObject *entry;
14094 : :
14095 : : /* Happens if the iterator is iterated twice, or closed explicitly */
14096 : : if (iterator->handle == INVALID_HANDLE_VALUE)
14097 : : return NULL;
14098 : :
14099 : : while (1) {
14100 : : if (!iterator->first_time) {
14101 : : Py_BEGIN_ALLOW_THREADS
14102 : : success = FindNextFileW(iterator->handle, file_data);
14103 : : Py_END_ALLOW_THREADS
14104 : : if (!success) {
14105 : : /* Error or no more files */
14106 : : if (GetLastError() != ERROR_NO_MORE_FILES)
14107 : : path_error(&iterator->path);
14108 : : break;
14109 : : }
14110 : : }
14111 : : iterator->first_time = 0;
14112 : :
14113 : : /* Skip over . and .. */
14114 : : if (wcscmp(file_data->cFileName, L".") != 0 &&
14115 : : wcscmp(file_data->cFileName, L"..") != 0)
14116 : : {
14117 : : PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14118 : : entry = DirEntry_from_find_data(module, &iterator->path, file_data);
14119 : : if (!entry)
14120 : : break;
14121 : : return entry;
14122 : : }
14123 : :
14124 : : /* Loop till we get a non-dot directory or finish iterating */
14125 : : }
14126 : :
14127 : : /* Error or no more files */
14128 : : ScandirIterator_closedir(iterator);
14129 : : return NULL;
14130 : : }
14131 : :
14132 : : #else /* POSIX */
14133 : :
14134 : : static int
14135 : 49814 : ScandirIterator_is_closed(ScandirIterator *iterator)
14136 : : {
14137 : 49814 : return !iterator->dirp;
14138 : : }
14139 : :
14140 : : static void
14141 : 95432 : ScandirIterator_closedir(ScandirIterator *iterator)
14142 : : {
14143 : 95432 : DIR *dirp = iterator->dirp;
14144 : :
14145 [ + + ]: 95432 : if (!dirp)
14146 : 46075 : return;
14147 : :
14148 : 49357 : iterator->dirp = NULL;
14149 : 49357 : Py_BEGIN_ALLOW_THREADS
14150 : : #ifdef HAVE_FDOPENDIR
14151 [ + + ]: 49357 : if (iterator->path.fd != -1)
14152 : 13949 : rewinddir(dirp);
14153 : : #endif
14154 : 49357 : closedir(dirp);
14155 : 49357 : Py_END_ALLOW_THREADS
14156 : 49357 : return;
14157 : : }
14158 : :
14159 : : static PyObject *
14160 : 179001 : ScandirIterator_iternext(ScandirIterator *iterator)
14161 : : {
14162 : : struct dirent *direntp;
14163 : : Py_ssize_t name_len;
14164 : : int is_dot;
14165 : : PyObject *entry;
14166 : :
14167 : : /* Happens if the iterator is iterated twice, or closed explicitly */
14168 [ + + ]: 179001 : if (!iterator->dirp)
14169 : 1 : return NULL;
14170 : :
14171 : : while (1) {
14172 : 277705 : errno = 0;
14173 : 277705 : Py_BEGIN_ALLOW_THREADS
14174 : 277705 : direntp = readdir(iterator->dirp);
14175 : 277705 : Py_END_ALLOW_THREADS
14176 : :
14177 [ + + ]: 277705 : if (!direntp) {
14178 : : /* Error or no more files */
14179 [ - + ]: 49350 : if (errno != 0)
14180 : 0 : path_error(&iterator->path);
14181 : 49350 : break;
14182 : : }
14183 : :
14184 : : /* Skip over . and .. */
14185 : 228355 : name_len = NAMLEN(direntp);
14186 [ + + + + ]: 278714 : is_dot = direntp->d_name[0] == '.' &&
14187 [ + + + + ]: 50359 : (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
14188 [ + + ]: 228355 : if (!is_dot) {
14189 : 129650 : PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14190 : 129650 : entry = DirEntry_from_posix_info(module,
14191 : 129650 : &iterator->path, direntp->d_name,
14192 : : name_len, direntp->d_ino
14193 : : #ifdef HAVE_DIRENT_D_TYPE
14194 : 129650 : , direntp->d_type
14195 : : #endif
14196 : : );
14197 [ - + ]: 129650 : if (!entry)
14198 : 0 : break;
14199 : 129650 : return entry;
14200 : : }
14201 : :
14202 : : /* Loop till we get a non-dot directory or finish iterating */
14203 : : }
14204 : :
14205 : : /* Error or no more files */
14206 : 49350 : ScandirIterator_closedir(iterator);
14207 : 49350 : return NULL;
14208 : : }
14209 : :
14210 : : #endif
14211 : :
14212 : : static PyObject *
14213 : 5 : ScandirIterator_close(ScandirIterator *self, PyObject *args)
14214 : : {
14215 : 5 : ScandirIterator_closedir(self);
14216 : 5 : Py_RETURN_NONE;
14217 : : }
14218 : :
14219 : : static PyObject *
14220 : 46076 : ScandirIterator_enter(PyObject *self, PyObject *args)
14221 : : {
14222 : 46076 : Py_INCREF(self);
14223 : 46076 : return self;
14224 : : }
14225 : :
14226 : : static PyObject *
14227 : 46076 : ScandirIterator_exit(ScandirIterator *self, PyObject *args)
14228 : : {
14229 : 46076 : ScandirIterator_closedir(self);
14230 : 46076 : Py_RETURN_NONE;
14231 : : }
14232 : :
14233 : : static void
14234 : 49814 : ScandirIterator_finalize(ScandirIterator *iterator)
14235 : : {
14236 : : PyObject *error_type, *error_value, *error_traceback;
14237 : :
14238 : : /* Save the current exception, if any. */
14239 : 49814 : PyErr_Fetch(&error_type, &error_value, &error_traceback);
14240 : :
14241 [ + + ]: 49814 : if (!ScandirIterator_is_closed(iterator)) {
14242 : 1 : ScandirIterator_closedir(iterator);
14243 : :
14244 [ - + ]: 1 : if (PyErr_ResourceWarning((PyObject *)iterator, 1,
14245 : : "unclosed scandir iterator %R", iterator)) {
14246 : : /* Spurious errors can appear at shutdown */
14247 [ # # ]: 0 : if (PyErr_ExceptionMatches(PyExc_Warning)) {
14248 : 0 : PyErr_WriteUnraisable((PyObject *) iterator);
14249 : : }
14250 : : }
14251 : : }
14252 : :
14253 : 49814 : path_cleanup(&iterator->path);
14254 : :
14255 : : /* Restore the saved exception. */
14256 : 49814 : PyErr_Restore(error_type, error_value, error_traceback);
14257 : 49814 : }
14258 : :
14259 : : static void
14260 : 49814 : ScandirIterator_dealloc(ScandirIterator *iterator)
14261 : : {
14262 : 49814 : PyTypeObject *tp = Py_TYPE(iterator);
14263 [ + + ]: 49814 : if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
14264 : 1 : return;
14265 : :
14266 : 49813 : freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
14267 : 49813 : free_func(iterator);
14268 : 49813 : Py_DECREF(tp);
14269 : : }
14270 : :
14271 : : static PyMethodDef ScandirIterator_methods[] = {
14272 : : {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
14273 : : {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
14274 : : {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
14275 : : {NULL}
14276 : : };
14277 : :
14278 : : static PyType_Slot ScandirIteratorType_slots[] = {
14279 : : {Py_tp_dealloc, ScandirIterator_dealloc},
14280 : : {Py_tp_finalize, ScandirIterator_finalize},
14281 : : {Py_tp_iter, PyObject_SelfIter},
14282 : : {Py_tp_iternext, ScandirIterator_iternext},
14283 : : {Py_tp_methods, ScandirIterator_methods},
14284 : : {0, 0},
14285 : : };
14286 : :
14287 : : static PyType_Spec ScandirIteratorType_spec = {
14288 : : MODNAME ".ScandirIterator",
14289 : : sizeof(ScandirIterator),
14290 : : 0,
14291 : : // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
14292 : : // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
14293 : : (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
14294 : : | Py_TPFLAGS_DISALLOW_INSTANTIATION),
14295 : : ScandirIteratorType_slots
14296 : : };
14297 : :
14298 : : /*[clinic input]
14299 : : os.scandir
14300 : :
14301 : : path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
14302 : :
14303 : : Return an iterator of DirEntry objects for given path.
14304 : :
14305 : : path can be specified as either str, bytes, or a path-like object. If path
14306 : : is bytes, the names of yielded DirEntry objects will also be bytes; in
14307 : : all other circumstances they will be str.
14308 : :
14309 : : If path is None, uses the path='.'.
14310 : : [clinic start generated code]*/
14311 : :
14312 : : static PyObject *
14313 : 49813 : os_scandir_impl(PyObject *module, path_t *path)
14314 : : /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
14315 : : {
14316 : : ScandirIterator *iterator;
14317 : : #ifdef MS_WINDOWS
14318 : : wchar_t *path_strW;
14319 : : #else
14320 : : const char *path_str;
14321 : : #ifdef HAVE_FDOPENDIR
14322 : 49813 : int fd = -1;
14323 : : #endif
14324 : : #endif
14325 : :
14326 [ - + ]: 49813 : if (PySys_Audit("os.scandir", "O",
14327 [ + + ]: 49813 : path->object ? path->object : Py_None) < 0) {
14328 : 0 : return NULL;
14329 : : }
14330 : :
14331 : 49813 : PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
14332 : 49813 : iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
14333 [ - + ]: 49813 : if (!iterator)
14334 : 0 : return NULL;
14335 : :
14336 : : #ifdef MS_WINDOWS
14337 : : iterator->handle = INVALID_HANDLE_VALUE;
14338 : : #else
14339 : 49813 : iterator->dirp = NULL;
14340 : : #endif
14341 : :
14342 : : /* Move the ownership to iterator->path */
14343 : 49813 : memcpy(&iterator->path, path, sizeof(path_t));
14344 : 49813 : memset(path, 0, sizeof(path_t));
14345 : :
14346 : : #ifdef MS_WINDOWS
14347 : : iterator->first_time = 1;
14348 : :
14349 : : path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
14350 : : if (!path_strW)
14351 : : goto error;
14352 : :
14353 : : Py_BEGIN_ALLOW_THREADS
14354 : : iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
14355 : : Py_END_ALLOW_THREADS
14356 : :
14357 : : PyMem_Free(path_strW);
14358 : :
14359 : : if (iterator->handle == INVALID_HANDLE_VALUE) {
14360 : : path_error(&iterator->path);
14361 : : goto error;
14362 : : }
14363 : : #else /* POSIX */
14364 : 49813 : errno = 0;
14365 : : #ifdef HAVE_FDOPENDIR
14366 [ + + ]: 49813 : if (iterator->path.fd != -1) {
14367 : : if (HAVE_FDOPENDIR_RUNTIME) {
14368 : : /* closedir() closes the FD, so we duplicate it */
14369 : 13953 : fd = _Py_dup(iterator->path.fd);
14370 [ - + ]: 13953 : if (fd == -1)
14371 : 0 : goto error;
14372 : :
14373 : 13953 : Py_BEGIN_ALLOW_THREADS
14374 : 13953 : iterator->dirp = fdopendir(fd);
14375 : 13953 : Py_END_ALLOW_THREADS
14376 : : } else {
14377 : : PyErr_SetString(PyExc_TypeError,
14378 : : "scandir: path should be string, bytes, os.PathLike or None, not int");
14379 : : return NULL;
14380 : : }
14381 : : }
14382 : : else
14383 : : #endif
14384 : : {
14385 [ + + ]: 35860 : if (iterator->path.narrow)
14386 : 35859 : path_str = iterator->path.narrow;
14387 : : else
14388 : 1 : path_str = ".";
14389 : :
14390 : 35860 : Py_BEGIN_ALLOW_THREADS
14391 : 35860 : iterator->dirp = opendir(path_str);
14392 : 35860 : Py_END_ALLOW_THREADS
14393 : : }
14394 : :
14395 [ + + ]: 49813 : if (!iterator->dirp) {
14396 : 456 : path_error(&iterator->path);
14397 : : #ifdef HAVE_FDOPENDIR
14398 [ + + ]: 456 : if (fd != -1) {
14399 : 4 : Py_BEGIN_ALLOW_THREADS
14400 : 4 : close(fd);
14401 : 4 : Py_END_ALLOW_THREADS
14402 : : }
14403 : : #endif
14404 : 456 : goto error;
14405 : : }
14406 : : #endif
14407 : :
14408 : 49357 : return (PyObject *)iterator;
14409 : :
14410 : 456 : error:
14411 : 456 : Py_DECREF(iterator);
14412 : 456 : return NULL;
14413 : : }
14414 : :
14415 : : /*
14416 : : Return the file system path representation of the object.
14417 : :
14418 : : If the object is str or bytes, then allow it to pass through with
14419 : : an incremented refcount. If the object defines __fspath__(), then
14420 : : return the result of that method. All other types raise a TypeError.
14421 : : */
14422 : : PyObject *
14423 : 5965682 : PyOS_FSPath(PyObject *path)
14424 : : {
14425 : : /* For error message reasons, this function is manually inlined in
14426 : : path_converter(). */
14427 : 5965682 : PyObject *func = NULL;
14428 : 5965682 : PyObject *path_repr = NULL;
14429 : :
14430 [ + + + + ]: 5965682 : if (PyUnicode_Check(path) || PyBytes_Check(path)) {
14431 : 5919330 : Py_INCREF(path);
14432 : 5919330 : return path;
14433 : : }
14434 : :
14435 : 46352 : func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
14436 [ + + ]: 46352 : if (NULL == func) {
14437 : 84 : return PyErr_Format(PyExc_TypeError,
14438 : : "expected str, bytes or os.PathLike object, "
14439 : : "not %.200s",
14440 : : _PyType_Name(Py_TYPE(path)));
14441 : : }
14442 : :
14443 : 46268 : path_repr = _PyObject_CallNoArgs(func);
14444 : 46268 : Py_DECREF(func);
14445 [ + + ]: 46268 : if (NULL == path_repr) {
14446 : 4 : return NULL;
14447 : : }
14448 : :
14449 [ + + + + ]: 46264 : if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
14450 : 5 : PyErr_Format(PyExc_TypeError,
14451 : : "expected %.200s.__fspath__() to return str or bytes, "
14452 : : "not %.200s", _PyType_Name(Py_TYPE(path)),
14453 : : _PyType_Name(Py_TYPE(path_repr)));
14454 : 5 : Py_DECREF(path_repr);
14455 : 5 : return NULL;
14456 : : }
14457 : :
14458 : 46259 : return path_repr;
14459 : : }
14460 : :
14461 : : /*[clinic input]
14462 : : os.fspath
14463 : :
14464 : : path: object
14465 : :
14466 : : Return the file system path representation of the object.
14467 : :
14468 : : If the object is str or bytes, then allow it to pass through as-is. If the
14469 : : object defines __fspath__(), then return the result of that method. All other
14470 : : types raise a TypeError.
14471 : : [clinic start generated code]*/
14472 : :
14473 : : static PyObject *
14474 : 3492585 : os_fspath_impl(PyObject *module, PyObject *path)
14475 : : /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
14476 : : {
14477 : 3492585 : return PyOS_FSPath(path);
14478 : : }
14479 : :
14480 : : #ifdef HAVE_GETRANDOM_SYSCALL
14481 : : /*[clinic input]
14482 : : os.getrandom
14483 : :
14484 : : size: Py_ssize_t
14485 : : flags: int=0
14486 : :
14487 : : Obtain a series of random bytes.
14488 : : [clinic start generated code]*/
14489 : :
14490 : : static PyObject *
14491 : 6 : os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
14492 : : /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
14493 : : {
14494 : : PyObject *bytes;
14495 : : Py_ssize_t n;
14496 : :
14497 [ - + ]: 6 : if (size < 0) {
14498 : 0 : errno = EINVAL;
14499 : 0 : return posix_error();
14500 : : }
14501 : :
14502 : 6 : bytes = PyBytes_FromStringAndSize(NULL, size);
14503 [ - + ]: 6 : if (bytes == NULL) {
14504 : : PyErr_NoMemory();
14505 : 0 : return NULL;
14506 : : }
14507 : :
14508 : : while (1) {
14509 : 6 : n = syscall(SYS_getrandom,
14510 : : PyBytes_AS_STRING(bytes),
14511 : : PyBytes_GET_SIZE(bytes),
14512 : : flags);
14513 [ - + - - ]: 6 : if (n < 0 && errno == EINTR) {
14514 [ # # ]: 0 : if (PyErr_CheckSignals() < 0) {
14515 : 0 : goto error;
14516 : : }
14517 : :
14518 : : /* getrandom() was interrupted by a signal: retry */
14519 : 0 : continue;
14520 : : }
14521 : 6 : break;
14522 : : }
14523 : :
14524 [ - + ]: 6 : if (n < 0) {
14525 : 0 : PyErr_SetFromErrno(PyExc_OSError);
14526 : 0 : goto error;
14527 : : }
14528 : :
14529 [ - + ]: 6 : if (n != size) {
14530 : 0 : _PyBytes_Resize(&bytes, n);
14531 : : }
14532 : :
14533 : 6 : return bytes;
14534 : :
14535 : 0 : error:
14536 : 0 : Py_DECREF(bytes);
14537 : 0 : return NULL;
14538 : : }
14539 : : #endif /* HAVE_GETRANDOM_SYSCALL */
14540 : :
14541 : : #ifdef MS_WINDOWS
14542 : : /* bpo-36085: Helper functions for managing DLL search directories
14543 : : * on win32
14544 : : */
14545 : :
14546 : : typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
14547 : : typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
14548 : :
14549 : : /*[clinic input]
14550 : : os._add_dll_directory
14551 : :
14552 : : path: path_t
14553 : :
14554 : : Add a path to the DLL search path.
14555 : :
14556 : : This search path is used when resolving dependencies for imported
14557 : : extension modules (the module itself is resolved through sys.path),
14558 : : and also by ctypes.
14559 : :
14560 : : Returns an opaque value that may be passed to os.remove_dll_directory
14561 : : to remove this directory from the search path.
14562 : : [clinic start generated code]*/
14563 : :
14564 : : static PyObject *
14565 : : os__add_dll_directory_impl(PyObject *module, path_t *path)
14566 : : /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
14567 : : {
14568 : : HMODULE hKernel32;
14569 : : PAddDllDirectory AddDllDirectory;
14570 : : DLL_DIRECTORY_COOKIE cookie = 0;
14571 : : DWORD err = 0;
14572 : :
14573 : : if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
14574 : : return NULL;
14575 : : }
14576 : :
14577 : : /* For Windows 7, we have to load this. As this will be a fairly
14578 : : infrequent operation, just do it each time. Kernel32 is always
14579 : : loaded. */
14580 : : Py_BEGIN_ALLOW_THREADS
14581 : : if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14582 : : !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
14583 : : hKernel32, "AddDllDirectory")) ||
14584 : : !(cookie = (*AddDllDirectory)(path->wide))) {
14585 : : err = GetLastError();
14586 : : }
14587 : : Py_END_ALLOW_THREADS
14588 : :
14589 : : if (err) {
14590 : : return win32_error_object_err("add_dll_directory",
14591 : : path->object, err);
14592 : : }
14593 : :
14594 : : return PyCapsule_New(cookie, "DLL directory cookie", NULL);
14595 : : }
14596 : :
14597 : : /*[clinic input]
14598 : : os._remove_dll_directory
14599 : :
14600 : : cookie: object
14601 : :
14602 : : Removes a path from the DLL search path.
14603 : :
14604 : : The parameter is an opaque value that was returned from
14605 : : os.add_dll_directory. You can only remove directories that you added
14606 : : yourself.
14607 : : [clinic start generated code]*/
14608 : :
14609 : : static PyObject *
14610 : : os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
14611 : : /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
14612 : : {
14613 : : HMODULE hKernel32;
14614 : : PRemoveDllDirectory RemoveDllDirectory;
14615 : : DLL_DIRECTORY_COOKIE cookieValue;
14616 : : DWORD err = 0;
14617 : :
14618 : : if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
14619 : : PyErr_SetString(PyExc_TypeError,
14620 : : "Provided cookie was not returned from os.add_dll_directory");
14621 : : return NULL;
14622 : : }
14623 : :
14624 : : cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
14625 : : cookie, "DLL directory cookie");
14626 : :
14627 : : /* For Windows 7, we have to load this. As this will be a fairly
14628 : : infrequent operation, just do it each time. Kernel32 is always
14629 : : loaded. */
14630 : : Py_BEGIN_ALLOW_THREADS
14631 : : if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14632 : : !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
14633 : : hKernel32, "RemoveDllDirectory")) ||
14634 : : !(*RemoveDllDirectory)(cookieValue)) {
14635 : : err = GetLastError();
14636 : : }
14637 : : Py_END_ALLOW_THREADS
14638 : :
14639 : : if (err) {
14640 : : return win32_error_object_err("remove_dll_directory",
14641 : : NULL, err);
14642 : : }
14643 : :
14644 : : if (PyCapsule_SetName(cookie, NULL)) {
14645 : : return NULL;
14646 : : }
14647 : :
14648 : : Py_RETURN_NONE;
14649 : : }
14650 : :
14651 : : #endif
14652 : :
14653 : :
14654 : : /* Only check if WIFEXITED is available: expect that it comes
14655 : : with WEXITSTATUS, WIFSIGNALED, etc.
14656 : :
14657 : : os.waitstatus_to_exitcode() is implemented in C and not in Python, so
14658 : : subprocess can safely call it during late Python finalization without
14659 : : risking that used os attributes were set to None by finalize_modules(). */
14660 : : #if defined(WIFEXITED) || defined(MS_WINDOWS)
14661 : : /*[clinic input]
14662 : : os.waitstatus_to_exitcode
14663 : :
14664 : : status as status_obj: object
14665 : :
14666 : : Convert a wait status to an exit code.
14667 : :
14668 : : On Unix:
14669 : :
14670 : : * If WIFEXITED(status) is true, return WEXITSTATUS(status).
14671 : : * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
14672 : : * Otherwise, raise a ValueError.
14673 : :
14674 : : On Windows, return status shifted right by 8 bits.
14675 : :
14676 : : On Unix, if the process is being traced or if waitpid() was called with
14677 : : WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
14678 : : This function must not be called if WIFSTOPPED(status) is true.
14679 : : [clinic start generated code]*/
14680 : :
14681 : : static PyObject *
14682 : 7056 : os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
14683 : : /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
14684 : : {
14685 : : #ifndef MS_WINDOWS
14686 : 7056 : int status = _PyLong_AsInt(status_obj);
14687 [ + + + - ]: 7056 : if (status == -1 && PyErr_Occurred()) {
14688 : 1 : return NULL;
14689 : : }
14690 : :
14691 : : WAIT_TYPE wait_status;
14692 : 7055 : WAIT_STATUS_INT(wait_status) = status;
14693 : : int exitcode;
14694 [ + + ]: 7055 : if (WIFEXITED(wait_status)) {
14695 : 6533 : exitcode = WEXITSTATUS(wait_status);
14696 : : /* Sanity check to provide warranty on the function behavior.
14697 : : It should not occur in practice */
14698 [ - + ]: 6533 : if (exitcode < 0) {
14699 : 0 : PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
14700 : 0 : return NULL;
14701 : : }
14702 : : }
14703 [ + - ]: 522 : else if (WIFSIGNALED(wait_status)) {
14704 : 522 : int signum = WTERMSIG(wait_status);
14705 : : /* Sanity check to provide warranty on the function behavior.
14706 : : It should not occurs in practice */
14707 [ - + ]: 522 : if (signum <= 0) {
14708 : 0 : PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
14709 : 0 : return NULL;
14710 : : }
14711 : 522 : exitcode = -signum;
14712 [ # # ]: 0 : } else if (WIFSTOPPED(wait_status)) {
14713 : : /* Status only received if the process is being traced
14714 : : or if waitpid() was called with WUNTRACED option. */
14715 : 0 : int signum = WSTOPSIG(wait_status);
14716 : 0 : PyErr_Format(PyExc_ValueError,
14717 : : "process stopped by delivery of signal %i",
14718 : : signum);
14719 : 0 : return NULL;
14720 : : }
14721 : : else {
14722 : 0 : PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
14723 : 0 : return NULL;
14724 : : }
14725 : 7055 : return PyLong_FromLong(exitcode);
14726 : : #else
14727 : : /* Windows implementation: see os.waitpid() implementation
14728 : : which uses _cwait(). */
14729 : : unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
14730 : : if (status == (unsigned long long)-1 && PyErr_Occurred()) {
14731 : : return NULL;
14732 : : }
14733 : :
14734 : : unsigned long long exitcode = (status >> 8);
14735 : : /* ExitProcess() accepts an UINT type:
14736 : : reject exit code which doesn't fit in an UINT */
14737 : : if (exitcode > UINT_MAX) {
14738 : : PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
14739 : : return NULL;
14740 : : }
14741 : : return PyLong_FromUnsignedLong((unsigned long)exitcode);
14742 : : #endif
14743 : : }
14744 : : #endif
14745 : :
14746 : :
14747 : : static PyMethodDef posix_methods[] = {
14748 : :
14749 : : OS_STAT_METHODDEF
14750 : : OS_ACCESS_METHODDEF
14751 : : OS_TTYNAME_METHODDEF
14752 : : OS_CHDIR_METHODDEF
14753 : : OS_CHFLAGS_METHODDEF
14754 : : OS_CHMOD_METHODDEF
14755 : : OS_FCHMOD_METHODDEF
14756 : : OS_LCHMOD_METHODDEF
14757 : : OS_CHOWN_METHODDEF
14758 : : OS_FCHOWN_METHODDEF
14759 : : OS_LCHOWN_METHODDEF
14760 : : OS_LCHFLAGS_METHODDEF
14761 : : OS_CHROOT_METHODDEF
14762 : : OS_CTERMID_METHODDEF
14763 : : OS_GETCWD_METHODDEF
14764 : : OS_GETCWDB_METHODDEF
14765 : : OS_LINK_METHODDEF
14766 : : OS_LISTDIR_METHODDEF
14767 : : OS_LSTAT_METHODDEF
14768 : : OS_MKDIR_METHODDEF
14769 : : OS_NICE_METHODDEF
14770 : : OS_GETPRIORITY_METHODDEF
14771 : : OS_SETPRIORITY_METHODDEF
14772 : : OS_POSIX_SPAWN_METHODDEF
14773 : : OS_POSIX_SPAWNP_METHODDEF
14774 : : OS_READLINK_METHODDEF
14775 : : OS_COPY_FILE_RANGE_METHODDEF
14776 : : OS_SPLICE_METHODDEF
14777 : : OS_RENAME_METHODDEF
14778 : : OS_REPLACE_METHODDEF
14779 : : OS_RMDIR_METHODDEF
14780 : : OS_SYMLINK_METHODDEF
14781 : : OS_SYSTEM_METHODDEF
14782 : : OS_UMASK_METHODDEF
14783 : : OS_UNAME_METHODDEF
14784 : : OS_UNLINK_METHODDEF
14785 : : OS_REMOVE_METHODDEF
14786 : : OS_UTIME_METHODDEF
14787 : : OS_TIMES_METHODDEF
14788 : : OS__EXIT_METHODDEF
14789 : : OS__FCOPYFILE_METHODDEF
14790 : : OS_EXECV_METHODDEF
14791 : : OS_EXECVE_METHODDEF
14792 : : OS_SPAWNV_METHODDEF
14793 : : OS_SPAWNVE_METHODDEF
14794 : : OS_FORK1_METHODDEF
14795 : : OS_FORK_METHODDEF
14796 : : OS_REGISTER_AT_FORK_METHODDEF
14797 : : OS_SCHED_GET_PRIORITY_MAX_METHODDEF
14798 : : OS_SCHED_GET_PRIORITY_MIN_METHODDEF
14799 : : OS_SCHED_GETPARAM_METHODDEF
14800 : : OS_SCHED_GETSCHEDULER_METHODDEF
14801 : : OS_SCHED_RR_GET_INTERVAL_METHODDEF
14802 : : OS_SCHED_SETPARAM_METHODDEF
14803 : : OS_SCHED_SETSCHEDULER_METHODDEF
14804 : : OS_SCHED_YIELD_METHODDEF
14805 : : OS_SCHED_SETAFFINITY_METHODDEF
14806 : : OS_SCHED_GETAFFINITY_METHODDEF
14807 : : OS_OPENPTY_METHODDEF
14808 : : OS_LOGIN_TTY_METHODDEF
14809 : : OS_FORKPTY_METHODDEF
14810 : : OS_GETEGID_METHODDEF
14811 : : OS_GETEUID_METHODDEF
14812 : : OS_GETGID_METHODDEF
14813 : : OS_GETGROUPLIST_METHODDEF
14814 : : OS_GETGROUPS_METHODDEF
14815 : : OS_GETPID_METHODDEF
14816 : : OS_GETPGRP_METHODDEF
14817 : : OS_GETPPID_METHODDEF
14818 : : OS_GETUID_METHODDEF
14819 : : OS_GETLOGIN_METHODDEF
14820 : : OS_KILL_METHODDEF
14821 : : OS_KILLPG_METHODDEF
14822 : : OS_PLOCK_METHODDEF
14823 : : OS_STARTFILE_METHODDEF
14824 : : OS_SETUID_METHODDEF
14825 : : OS_SETEUID_METHODDEF
14826 : : OS_SETREUID_METHODDEF
14827 : : OS_SETGID_METHODDEF
14828 : : OS_SETEGID_METHODDEF
14829 : : OS_SETREGID_METHODDEF
14830 : : OS_SETGROUPS_METHODDEF
14831 : : OS_INITGROUPS_METHODDEF
14832 : : OS_GETPGID_METHODDEF
14833 : : OS_SETPGRP_METHODDEF
14834 : : OS_WAIT_METHODDEF
14835 : : OS_WAIT3_METHODDEF
14836 : : OS_WAIT4_METHODDEF
14837 : : OS_WAITID_METHODDEF
14838 : : OS_WAITPID_METHODDEF
14839 : : OS_PIDFD_OPEN_METHODDEF
14840 : : OS_GETSID_METHODDEF
14841 : : OS_SETSID_METHODDEF
14842 : : OS_SETPGID_METHODDEF
14843 : : OS_TCGETPGRP_METHODDEF
14844 : : OS_TCSETPGRP_METHODDEF
14845 : : OS_OPEN_METHODDEF
14846 : : OS_CLOSE_METHODDEF
14847 : : OS_CLOSERANGE_METHODDEF
14848 : : OS_DEVICE_ENCODING_METHODDEF
14849 : : OS_DUP_METHODDEF
14850 : : OS_DUP2_METHODDEF
14851 : : OS_LOCKF_METHODDEF
14852 : : OS_LSEEK_METHODDEF
14853 : : OS_READ_METHODDEF
14854 : : OS_READV_METHODDEF
14855 : : OS_PREAD_METHODDEF
14856 : : OS_PREADV_METHODDEF
14857 : : OS_WRITE_METHODDEF
14858 : : OS_WRITEV_METHODDEF
14859 : : OS_PWRITE_METHODDEF
14860 : : OS_PWRITEV_METHODDEF
14861 : : OS_SENDFILE_METHODDEF
14862 : : OS_FSTAT_METHODDEF
14863 : : OS_ISATTY_METHODDEF
14864 : : OS_PIPE_METHODDEF
14865 : : OS_PIPE2_METHODDEF
14866 : : OS_MKFIFO_METHODDEF
14867 : : OS_MKNOD_METHODDEF
14868 : : OS_MAJOR_METHODDEF
14869 : : OS_MINOR_METHODDEF
14870 : : OS_MAKEDEV_METHODDEF
14871 : : OS_FTRUNCATE_METHODDEF
14872 : : OS_TRUNCATE_METHODDEF
14873 : : OS_POSIX_FALLOCATE_METHODDEF
14874 : : OS_POSIX_FADVISE_METHODDEF
14875 : : OS_PUTENV_METHODDEF
14876 : : OS_UNSETENV_METHODDEF
14877 : : OS_STRERROR_METHODDEF
14878 : : OS_FCHDIR_METHODDEF
14879 : : OS_FSYNC_METHODDEF
14880 : : OS_SYNC_METHODDEF
14881 : : OS_FDATASYNC_METHODDEF
14882 : : OS_WCOREDUMP_METHODDEF
14883 : : OS_WIFCONTINUED_METHODDEF
14884 : : OS_WIFSTOPPED_METHODDEF
14885 : : OS_WIFSIGNALED_METHODDEF
14886 : : OS_WIFEXITED_METHODDEF
14887 : : OS_WEXITSTATUS_METHODDEF
14888 : : OS_WTERMSIG_METHODDEF
14889 : : OS_WSTOPSIG_METHODDEF
14890 : : OS_FSTATVFS_METHODDEF
14891 : : OS_STATVFS_METHODDEF
14892 : : OS_CONFSTR_METHODDEF
14893 : : OS_SYSCONF_METHODDEF
14894 : : OS_FPATHCONF_METHODDEF
14895 : : OS_PATHCONF_METHODDEF
14896 : : OS_ABORT_METHODDEF
14897 : : OS__GETFULLPATHNAME_METHODDEF
14898 : : OS__GETDISKUSAGE_METHODDEF
14899 : : OS__GETFINALPATHNAME_METHODDEF
14900 : : OS__GETVOLUMEPATHNAME_METHODDEF
14901 : : OS__PATH_SPLITROOT_METHODDEF
14902 : : OS__PATH_NORMPATH_METHODDEF
14903 : : OS_GETLOADAVG_METHODDEF
14904 : : OS_URANDOM_METHODDEF
14905 : : OS_SETRESUID_METHODDEF
14906 : : OS_SETRESGID_METHODDEF
14907 : : OS_GETRESUID_METHODDEF
14908 : : OS_GETRESGID_METHODDEF
14909 : :
14910 : : OS_GETXATTR_METHODDEF
14911 : : OS_SETXATTR_METHODDEF
14912 : : OS_REMOVEXATTR_METHODDEF
14913 : : OS_LISTXATTR_METHODDEF
14914 : :
14915 : : OS_GET_TERMINAL_SIZE_METHODDEF
14916 : : OS_CPU_COUNT_METHODDEF
14917 : : OS_GET_INHERITABLE_METHODDEF
14918 : : OS_SET_INHERITABLE_METHODDEF
14919 : : OS_GET_HANDLE_INHERITABLE_METHODDEF
14920 : : OS_SET_HANDLE_INHERITABLE_METHODDEF
14921 : : OS_GET_BLOCKING_METHODDEF
14922 : : OS_SET_BLOCKING_METHODDEF
14923 : : OS_SCANDIR_METHODDEF
14924 : : OS_FSPATH_METHODDEF
14925 : : OS_GETRANDOM_METHODDEF
14926 : : OS_MEMFD_CREATE_METHODDEF
14927 : : OS_EVENTFD_METHODDEF
14928 : : OS_EVENTFD_READ_METHODDEF
14929 : : OS_EVENTFD_WRITE_METHODDEF
14930 : : OS__ADD_DLL_DIRECTORY_METHODDEF
14931 : : OS__REMOVE_DLL_DIRECTORY_METHODDEF
14932 : : OS_WAITSTATUS_TO_EXITCODE_METHODDEF
14933 : : {NULL, NULL} /* Sentinel */
14934 : : };
14935 : :
14936 : : static int
14937 : 3135 : all_ins(PyObject *m)
14938 : : {
14939 : : #ifdef F_OK
14940 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, F_OK)) return -1;
14941 : : #endif
14942 : : #ifdef R_OK
14943 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, R_OK)) return -1;
14944 : : #endif
14945 : : #ifdef W_OK
14946 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, W_OK)) return -1;
14947 : : #endif
14948 : : #ifdef X_OK
14949 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, X_OK)) return -1;
14950 : : #endif
14951 : : #ifdef NGROUPS_MAX
14952 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
14953 : : #endif
14954 : : #ifdef TMP_MAX
14955 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
14956 : : #endif
14957 : : #ifdef WCONTINUED
14958 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
14959 : : #endif
14960 : : #ifdef WNOHANG
14961 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
14962 : : #endif
14963 : : #ifdef WUNTRACED
14964 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
14965 : : #endif
14966 : : #ifdef O_RDONLY
14967 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
14968 : : #endif
14969 : : #ifdef O_WRONLY
14970 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
14971 : : #endif
14972 : : #ifdef O_RDWR
14973 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
14974 : : #endif
14975 : : #ifdef O_NDELAY
14976 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
14977 : : #endif
14978 : : #ifdef O_NONBLOCK
14979 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
14980 : : #endif
14981 : : #ifdef O_APPEND
14982 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
14983 : : #endif
14984 : : #ifdef O_DSYNC
14985 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
14986 : : #endif
14987 : : #ifdef O_RSYNC
14988 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
14989 : : #endif
14990 : : #ifdef O_SYNC
14991 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
14992 : : #endif
14993 : : #ifdef O_NOCTTY
14994 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
14995 : : #endif
14996 : : #ifdef O_CREAT
14997 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
14998 : : #endif
14999 : : #ifdef O_EXCL
15000 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
15001 : : #endif
15002 : : #ifdef O_TRUNC
15003 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
15004 : : #endif
15005 : : #ifdef O_BINARY
15006 : : if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
15007 : : #endif
15008 : : #ifdef O_TEXT
15009 : : if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
15010 : : #endif
15011 : : #ifdef O_XATTR
15012 : : if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
15013 : : #endif
15014 : : #ifdef O_LARGEFILE
15015 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
15016 : : #endif
15017 : : #ifndef __GNU__
15018 : : #ifdef O_SHLOCK
15019 : : if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
15020 : : #endif
15021 : : #ifdef O_EXLOCK
15022 : : if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
15023 : : #endif
15024 : : #endif
15025 : : #ifdef O_EXEC
15026 : : if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
15027 : : #endif
15028 : : #ifdef O_SEARCH
15029 : : if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
15030 : : #endif
15031 : : #ifdef O_PATH
15032 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_PATH)) return -1;
15033 : : #endif
15034 : : #ifdef O_TTY_INIT
15035 : : if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
15036 : : #endif
15037 : : #ifdef O_TMPFILE
15038 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
15039 : : #endif
15040 : : #ifdef PRIO_PROCESS
15041 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
15042 : : #endif
15043 : : #ifdef PRIO_PGRP
15044 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
15045 : : #endif
15046 : : #ifdef PRIO_USER
15047 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
15048 : : #endif
15049 : : #ifdef O_CLOEXEC
15050 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
15051 : : #endif
15052 : : #ifdef O_ACCMODE
15053 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
15054 : : #endif
15055 : : #ifdef O_EVTONLY
15056 : : if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
15057 : : #endif
15058 : : #ifdef O_FSYNC
15059 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
15060 : : #endif
15061 : : #ifdef O_SYMLINK
15062 : : if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
15063 : : #endif
15064 : :
15065 : : #ifdef SEEK_HOLE
15066 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
15067 : : #endif
15068 : : #ifdef SEEK_DATA
15069 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
15070 : : #endif
15071 : :
15072 : : /* MS Windows */
15073 : : #ifdef O_NOINHERIT
15074 : : /* Don't inherit in child processes. */
15075 : : if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
15076 : : #endif
15077 : : #ifdef _O_SHORT_LIVED
15078 : : /* Optimize for short life (keep in memory). */
15079 : : /* MS forgot to define this one with a non-underscore form too. */
15080 : : if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
15081 : : #endif
15082 : : #ifdef O_TEMPORARY
15083 : : /* Automatically delete when last handle is closed. */
15084 : : if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
15085 : : #endif
15086 : : #ifdef O_RANDOM
15087 : : /* Optimize for random access. */
15088 : : if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
15089 : : #endif
15090 : : #ifdef O_SEQUENTIAL
15091 : : /* Optimize for sequential access. */
15092 : : if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
15093 : : #endif
15094 : :
15095 : : /* GNU extensions. */
15096 : : #ifdef O_ASYNC
15097 : : /* Send a SIGIO signal whenever input or output
15098 : : becomes available on file descriptor */
15099 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
15100 : : #endif
15101 : : #ifdef O_DIRECT
15102 : : /* Direct disk access. */
15103 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
15104 : : #endif
15105 : : #ifdef O_DIRECTORY
15106 : : /* Must be a directory. */
15107 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
15108 : : #endif
15109 : : #ifdef O_NOFOLLOW
15110 : : /* Do not follow links. */
15111 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
15112 : : #endif
15113 : : #ifdef O_NOFOLLOW_ANY
15114 : : if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
15115 : : #endif
15116 : : #ifdef O_NOLINKS
15117 : : /* Fails if link count of the named file is greater than 1 */
15118 : : if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
15119 : : #endif
15120 : : #ifdef O_NOATIME
15121 : : /* Do not update the access time. */
15122 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
15123 : : #endif
15124 : :
15125 : : /* These come from sysexits.h */
15126 : : #ifdef EX_OK
15127 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_OK)) return -1;
15128 : : #endif /* EX_OK */
15129 : : #ifdef EX_USAGE
15130 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
15131 : : #endif /* EX_USAGE */
15132 : : #ifdef EX_DATAERR
15133 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
15134 : : #endif /* EX_DATAERR */
15135 : : #ifdef EX_NOINPUT
15136 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
15137 : : #endif /* EX_NOINPUT */
15138 : : #ifdef EX_NOUSER
15139 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
15140 : : #endif /* EX_NOUSER */
15141 : : #ifdef EX_NOHOST
15142 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
15143 : : #endif /* EX_NOHOST */
15144 : : #ifdef EX_UNAVAILABLE
15145 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
15146 : : #endif /* EX_UNAVAILABLE */
15147 : : #ifdef EX_SOFTWARE
15148 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
15149 : : #endif /* EX_SOFTWARE */
15150 : : #ifdef EX_OSERR
15151 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
15152 : : #endif /* EX_OSERR */
15153 : : #ifdef EX_OSFILE
15154 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
15155 : : #endif /* EX_OSFILE */
15156 : : #ifdef EX_CANTCREAT
15157 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
15158 : : #endif /* EX_CANTCREAT */
15159 : : #ifdef EX_IOERR
15160 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
15161 : : #endif /* EX_IOERR */
15162 : : #ifdef EX_TEMPFAIL
15163 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
15164 : : #endif /* EX_TEMPFAIL */
15165 : : #ifdef EX_PROTOCOL
15166 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
15167 : : #endif /* EX_PROTOCOL */
15168 : : #ifdef EX_NOPERM
15169 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
15170 : : #endif /* EX_NOPERM */
15171 : : #ifdef EX_CONFIG
15172 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
15173 : : #endif /* EX_CONFIG */
15174 : : #ifdef EX_NOTFOUND
15175 : : if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
15176 : : #endif /* EX_NOTFOUND */
15177 : :
15178 : : /* statvfs */
15179 : : #ifdef ST_RDONLY
15180 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
15181 : : #endif /* ST_RDONLY */
15182 : : #ifdef ST_NOSUID
15183 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
15184 : : #endif /* ST_NOSUID */
15185 : :
15186 : : /* GNU extensions */
15187 : : #ifdef ST_NODEV
15188 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
15189 : : #endif /* ST_NODEV */
15190 : : #ifdef ST_NOEXEC
15191 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
15192 : : #endif /* ST_NOEXEC */
15193 : : #ifdef ST_SYNCHRONOUS
15194 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
15195 : : #endif /* ST_SYNCHRONOUS */
15196 : : #ifdef ST_MANDLOCK
15197 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
15198 : : #endif /* ST_MANDLOCK */
15199 : : #ifdef ST_WRITE
15200 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
15201 : : #endif /* ST_WRITE */
15202 : : #ifdef ST_APPEND
15203 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
15204 : : #endif /* ST_APPEND */
15205 : : #ifdef ST_NOATIME
15206 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
15207 : : #endif /* ST_NOATIME */
15208 : : #ifdef ST_NODIRATIME
15209 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
15210 : : #endif /* ST_NODIRATIME */
15211 : : #ifdef ST_RELATIME
15212 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
15213 : : #endif /* ST_RELATIME */
15214 : :
15215 : : /* FreeBSD sendfile() constants */
15216 : : #ifdef SF_NODISKIO
15217 : : if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
15218 : : #endif
15219 : : /* is obsolete since the 11.x release */
15220 : : #ifdef SF_MNOWAIT
15221 : : if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
15222 : : #endif
15223 : : #ifdef SF_SYNC
15224 : : if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
15225 : : #endif
15226 : : #ifdef SF_NOCACHE
15227 : : if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
15228 : : #endif
15229 : :
15230 : : /* constants for posix_fadvise */
15231 : : #ifdef POSIX_FADV_NORMAL
15232 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
15233 : : #endif
15234 : : #ifdef POSIX_FADV_SEQUENTIAL
15235 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
15236 : : #endif
15237 : : #ifdef POSIX_FADV_RANDOM
15238 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
15239 : : #endif
15240 : : #ifdef POSIX_FADV_NOREUSE
15241 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
15242 : : #endif
15243 : : #ifdef POSIX_FADV_WILLNEED
15244 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
15245 : : #endif
15246 : : #ifdef POSIX_FADV_DONTNEED
15247 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
15248 : : #endif
15249 : :
15250 : : /* constants for waitid */
15251 : : #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
15252 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, P_PID)) return -1;
15253 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, P_PGID)) return -1;
15254 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, P_ALL)) return -1;
15255 : : #ifdef P_PIDFD
15256 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
15257 : : #endif
15258 : : #ifdef PIDFD_NONBLOCK
15259 : : if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
15260 : : #endif
15261 : : #endif
15262 : : #ifdef WEXITED
15263 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, WEXITED)) return -1;
15264 : : #endif
15265 : : #ifdef WNOWAIT
15266 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
15267 : : #endif
15268 : : #ifdef WSTOPPED
15269 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
15270 : : #endif
15271 : : #ifdef CLD_EXITED
15272 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
15273 : : #endif
15274 : : #ifdef CLD_KILLED
15275 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
15276 : : #endif
15277 : : #ifdef CLD_DUMPED
15278 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
15279 : : #endif
15280 : : #ifdef CLD_TRAPPED
15281 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
15282 : : #endif
15283 : : #ifdef CLD_STOPPED
15284 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
15285 : : #endif
15286 : : #ifdef CLD_CONTINUED
15287 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
15288 : : #endif
15289 : :
15290 : : /* constants for lockf */
15291 : : #ifdef F_LOCK
15292 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
15293 : : #endif
15294 : : #ifdef F_TLOCK
15295 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
15296 : : #endif
15297 : : #ifdef F_ULOCK
15298 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
15299 : : #endif
15300 : : #ifdef F_TEST
15301 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, F_TEST)) return -1;
15302 : : #endif
15303 : :
15304 : : #ifdef RWF_DSYNC
15305 [ - + ]: 3135 : if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
15306 : : #endif
15307 : : #ifdef RWF_HIPRI
15308 [ - + ]: 3135 : if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
15309 : : #endif
15310 : : #ifdef RWF_SYNC
15311 [ - + ]: 3135 : if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
15312 : : #endif
15313 : : #ifdef RWF_NOWAIT
15314 [ - + ]: 3135 : if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
15315 : : #endif
15316 : : #ifdef RWF_APPEND
15317 [ - + ]: 3135 : if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
15318 : : #endif
15319 : :
15320 : : /* constants for splice */
15321 : : #if defined(HAVE_SPLICE) && defined(__linux__)
15322 [ - + ]: 3135 : if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
15323 [ - + ]: 3135 : if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
15324 [ - + ]: 3135 : if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
15325 : : #endif
15326 : :
15327 : : /* constants for posix_spawn */
15328 : : #ifdef HAVE_POSIX_SPAWN
15329 [ - + ]: 3135 : if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
15330 [ - + ]: 3135 : if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
15331 [ - + ]: 3135 : if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
15332 : : #endif
15333 : :
15334 : : #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
15335 : : if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
15336 : : if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
15337 : : if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
15338 : : #endif
15339 : : #ifdef HAVE_SPAWNV
15340 : : if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
15341 : : if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
15342 : : #endif
15343 : :
15344 : : #ifdef HAVE_SCHED_H
15345 : : #ifdef SCHED_OTHER
15346 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
15347 : : #endif
15348 : : #ifdef SCHED_FIFO
15349 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
15350 : : #endif
15351 : : #ifdef SCHED_RR
15352 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
15353 : : #endif
15354 : : #ifdef SCHED_SPORADIC
15355 : : if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
15356 : : #endif
15357 : : #ifdef SCHED_BATCH
15358 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
15359 : : #endif
15360 : : #ifdef SCHED_IDLE
15361 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
15362 : : #endif
15363 : : #ifdef SCHED_RESET_ON_FORK
15364 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
15365 : : #endif
15366 : : #ifdef SCHED_SYS
15367 : : if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
15368 : : #endif
15369 : : #ifdef SCHED_IA
15370 : : if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
15371 : : #endif
15372 : : #ifdef SCHED_FSS
15373 : : if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
15374 : : #endif
15375 : : #ifdef SCHED_FX
15376 : : if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
15377 : : #endif
15378 : : #endif
15379 : :
15380 : : #ifdef USE_XATTRS
15381 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
15382 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
15383 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
15384 : : #endif
15385 : :
15386 : : #if HAVE_DECL_RTLD_LAZY
15387 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
15388 : : #endif
15389 : : #if HAVE_DECL_RTLD_NOW
15390 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
15391 : : #endif
15392 : : #if HAVE_DECL_RTLD_GLOBAL
15393 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
15394 : : #endif
15395 : : #if HAVE_DECL_RTLD_LOCAL
15396 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
15397 : : #endif
15398 : : #if HAVE_DECL_RTLD_NODELETE
15399 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
15400 : : #endif
15401 : : #if HAVE_DECL_RTLD_NOLOAD
15402 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
15403 : : #endif
15404 : : #if HAVE_DECL_RTLD_DEEPBIND
15405 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
15406 : : #endif
15407 : : #if HAVE_DECL_RTLD_MEMBER
15408 : : if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
15409 : : #endif
15410 : :
15411 : : #ifdef HAVE_GETRANDOM_SYSCALL
15412 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
15413 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
15414 : : #endif
15415 : : #ifdef HAVE_MEMFD_CREATE
15416 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
15417 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
15418 : : #ifdef MFD_HUGETLB
15419 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
15420 : : #endif
15421 : : #ifdef MFD_HUGE_SHIFT
15422 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
15423 : : #endif
15424 : : #ifdef MFD_HUGE_MASK
15425 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
15426 : : #endif
15427 : : #ifdef MFD_HUGE_64KB
15428 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
15429 : : #endif
15430 : : #ifdef MFD_HUGE_512KB
15431 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
15432 : : #endif
15433 : : #ifdef MFD_HUGE_1MB
15434 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
15435 : : #endif
15436 : : #ifdef MFD_HUGE_2MB
15437 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
15438 : : #endif
15439 : : #ifdef MFD_HUGE_8MB
15440 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
15441 : : #endif
15442 : : #ifdef MFD_HUGE_16MB
15443 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
15444 : : #endif
15445 : : #ifdef MFD_HUGE_32MB
15446 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
15447 : : #endif
15448 : : #ifdef MFD_HUGE_256MB
15449 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
15450 : : #endif
15451 : : #ifdef MFD_HUGE_512MB
15452 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
15453 : : #endif
15454 : : #ifdef MFD_HUGE_1GB
15455 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
15456 : : #endif
15457 : : #ifdef MFD_HUGE_2GB
15458 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
15459 : : #endif
15460 : : #ifdef MFD_HUGE_16GB
15461 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
15462 : : #endif
15463 : : #endif /* HAVE_MEMFD_CREATE */
15464 : :
15465 : : #ifdef HAVE_EVENTFD
15466 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
15467 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
15468 [ - + ]: 3135 : if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
15469 : : #endif
15470 : :
15471 : : #if defined(__APPLE__)
15472 : : if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
15473 : : if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
15474 : : if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
15475 : : if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
15476 : : #endif
15477 : :
15478 : : #ifdef MS_WINDOWS
15479 : : if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
15480 : : if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
15481 : : if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
15482 : : if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
15483 : : if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
15484 : : #endif
15485 : :
15486 : 3135 : return 0;
15487 : : }
15488 : :
15489 : :
15490 : :
15491 : : #define PROBE(name, test) \
15492 : : static int name(void) \
15493 : : { \
15494 : : if (test) { \
15495 : : return 1; \
15496 : : } else { \
15497 : : return 0; \
15498 : : } \
15499 : : }
15500 : :
15501 : : #ifdef HAVE_FSTATAT
15502 : 3135 : PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
15503 : : #endif
15504 : :
15505 : : #ifdef HAVE_FACCESSAT
15506 : 3135 : PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
15507 : : #endif
15508 : :
15509 : : #ifdef HAVE_FCHMODAT
15510 : 3135 : PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
15511 : : #endif
15512 : :
15513 : : #ifdef HAVE_FCHOWNAT
15514 : 3135 : PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
15515 : : #endif
15516 : :
15517 : : #ifdef HAVE_LINKAT
15518 : 3135 : PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
15519 : : #endif
15520 : :
15521 : : #ifdef HAVE_FDOPENDIR
15522 : 3135 : PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
15523 : : #endif
15524 : :
15525 : : #ifdef HAVE_MKDIRAT
15526 : 3135 : PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
15527 : : #endif
15528 : :
15529 : : #ifdef HAVE_RENAMEAT
15530 : 3135 : PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
15531 : : #endif
15532 : :
15533 : : #ifdef HAVE_UNLINKAT
15534 : 3135 : PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
15535 : : #endif
15536 : :
15537 : : #ifdef HAVE_OPENAT
15538 : 3135 : PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
15539 : : #endif
15540 : :
15541 : : #ifdef HAVE_READLINKAT
15542 : 3135 : PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
15543 : : #endif
15544 : :
15545 : : #ifdef HAVE_SYMLINKAT
15546 : 3135 : PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
15547 : : #endif
15548 : :
15549 : : #ifdef HAVE_FUTIMENS
15550 : 3135 : PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
15551 : : #endif
15552 : :
15553 : : #ifdef HAVE_UTIMENSAT
15554 : 3135 : PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
15555 : : #endif
15556 : :
15557 : :
15558 : :
15559 : :
15560 : : static const struct have_function {
15561 : : const char * const label;
15562 : : int (*probe)(void);
15563 : : } have_functions[] = {
15564 : :
15565 : : #ifdef HAVE_EVENTFD
15566 : : {"HAVE_EVENTFD", NULL},
15567 : : #endif
15568 : :
15569 : : #ifdef HAVE_FACCESSAT
15570 : : { "HAVE_FACCESSAT", probe_faccessat },
15571 : : #endif
15572 : :
15573 : : #ifdef HAVE_FCHDIR
15574 : : { "HAVE_FCHDIR", NULL },
15575 : : #endif
15576 : :
15577 : : #ifdef HAVE_FCHMOD
15578 : : { "HAVE_FCHMOD", NULL },
15579 : : #endif
15580 : :
15581 : : #ifdef HAVE_FCHMODAT
15582 : : { "HAVE_FCHMODAT", probe_fchmodat },
15583 : : #endif
15584 : :
15585 : : #ifdef HAVE_FCHOWN
15586 : : { "HAVE_FCHOWN", NULL },
15587 : : #endif
15588 : :
15589 : : #ifdef HAVE_FCHOWNAT
15590 : : { "HAVE_FCHOWNAT", probe_fchownat },
15591 : : #endif
15592 : :
15593 : : #ifdef HAVE_FEXECVE
15594 : : { "HAVE_FEXECVE", NULL },
15595 : : #endif
15596 : :
15597 : : #ifdef HAVE_FDOPENDIR
15598 : : { "HAVE_FDOPENDIR", probe_fdopendir },
15599 : : #endif
15600 : :
15601 : : #ifdef HAVE_FPATHCONF
15602 : : { "HAVE_FPATHCONF", NULL },
15603 : : #endif
15604 : :
15605 : : #ifdef HAVE_FSTATAT
15606 : : { "HAVE_FSTATAT", probe_fstatat },
15607 : : #endif
15608 : :
15609 : : #ifdef HAVE_FSTATVFS
15610 : : { "HAVE_FSTATVFS", NULL },
15611 : : #endif
15612 : :
15613 : : #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
15614 : : { "HAVE_FTRUNCATE", NULL },
15615 : : #endif
15616 : :
15617 : : #ifdef HAVE_FUTIMENS
15618 : : { "HAVE_FUTIMENS", probe_futimens },
15619 : : #endif
15620 : :
15621 : : #ifdef HAVE_FUTIMES
15622 : : { "HAVE_FUTIMES", NULL },
15623 : : #endif
15624 : :
15625 : : #ifdef HAVE_FUTIMESAT
15626 : : { "HAVE_FUTIMESAT", NULL },
15627 : : #endif
15628 : :
15629 : : #ifdef HAVE_LINKAT
15630 : : { "HAVE_LINKAT", probe_linkat },
15631 : : #endif
15632 : :
15633 : : #ifdef HAVE_LCHFLAGS
15634 : : { "HAVE_LCHFLAGS", NULL },
15635 : : #endif
15636 : :
15637 : : #ifdef HAVE_LCHMOD
15638 : : { "HAVE_LCHMOD", NULL },
15639 : : #endif
15640 : :
15641 : : #ifdef HAVE_LCHOWN
15642 : : { "HAVE_LCHOWN", NULL },
15643 : : #endif
15644 : :
15645 : : #ifdef HAVE_LSTAT
15646 : : { "HAVE_LSTAT", NULL },
15647 : : #endif
15648 : :
15649 : : #ifdef HAVE_LUTIMES
15650 : : { "HAVE_LUTIMES", NULL },
15651 : : #endif
15652 : :
15653 : : #ifdef HAVE_MEMFD_CREATE
15654 : : { "HAVE_MEMFD_CREATE", NULL },
15655 : : #endif
15656 : :
15657 : : #ifdef HAVE_MKDIRAT
15658 : : { "HAVE_MKDIRAT", probe_mkdirat },
15659 : : #endif
15660 : :
15661 : : #ifdef HAVE_MKFIFOAT
15662 : : { "HAVE_MKFIFOAT", NULL },
15663 : : #endif
15664 : :
15665 : : #ifdef HAVE_MKNODAT
15666 : : { "HAVE_MKNODAT", NULL },
15667 : : #endif
15668 : :
15669 : : #ifdef HAVE_OPENAT
15670 : : { "HAVE_OPENAT", probe_openat },
15671 : : #endif
15672 : :
15673 : : #ifdef HAVE_READLINKAT
15674 : : { "HAVE_READLINKAT", probe_readlinkat },
15675 : : #endif
15676 : :
15677 : : #ifdef HAVE_RENAMEAT
15678 : : { "HAVE_RENAMEAT", probe_renameat },
15679 : : #endif
15680 : :
15681 : : #ifdef HAVE_SYMLINKAT
15682 : : { "HAVE_SYMLINKAT", probe_symlinkat },
15683 : : #endif
15684 : :
15685 : : #ifdef HAVE_UNLINKAT
15686 : : { "HAVE_UNLINKAT", probe_unlinkat },
15687 : : #endif
15688 : :
15689 : : #ifdef HAVE_UTIMENSAT
15690 : : { "HAVE_UTIMENSAT", probe_utimensat },
15691 : : #endif
15692 : :
15693 : : #ifdef MS_WINDOWS
15694 : : { "MS_WINDOWS", NULL },
15695 : : #endif
15696 : :
15697 : : { NULL, NULL }
15698 : : };
15699 : :
15700 : :
15701 : : static int
15702 : 3135 : posixmodule_exec(PyObject *m)
15703 : : {
15704 : 3135 : _posixstate *state = get_posix_state(m);
15705 : :
15706 : : #if defined(HAVE_PWRITEV)
15707 : : if (HAVE_PWRITEV_RUNTIME) {} else {
15708 : : PyObject* dct = PyModule_GetDict(m);
15709 : :
15710 : : if (dct == NULL) {
15711 : : return -1;
15712 : : }
15713 : :
15714 : : if (PyDict_DelItemString(dct, "pwritev") == -1) {
15715 : : PyErr_Clear();
15716 : : }
15717 : : if (PyDict_DelItemString(dct, "preadv") == -1) {
15718 : : PyErr_Clear();
15719 : : }
15720 : : }
15721 : : #endif
15722 : :
15723 : : /* Initialize environ dictionary */
15724 : 3135 : PyObject *v = convertenviron();
15725 : 3135 : Py_XINCREF(v);
15726 [ + - - + ]: 3135 : if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
15727 : 0 : return -1;
15728 : 3135 : Py_DECREF(v);
15729 : :
15730 [ - + ]: 3135 : if (all_ins(m))
15731 : 0 : return -1;
15732 : :
15733 [ - + ]: 3135 : if (setup_confname_tables(m))
15734 : 0 : return -1;
15735 : :
15736 : 3135 : Py_INCREF(PyExc_OSError);
15737 : 3135 : PyModule_AddObject(m, "error", PyExc_OSError);
15738 : :
15739 : : #if defined(HAVE_WAITID) && !defined(__APPLE__)
15740 : 3135 : waitid_result_desc.name = MODNAME ".waitid_result";
15741 : 3135 : PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
15742 [ - + ]: 3135 : if (WaitidResultType == NULL) {
15743 : 0 : return -1;
15744 : : }
15745 : 3135 : Py_INCREF(WaitidResultType);
15746 : 3135 : PyModule_AddObject(m, "waitid_result", WaitidResultType);
15747 : 3135 : state->WaitidResultType = WaitidResultType;
15748 : : #endif
15749 : :
15750 : 3135 : stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
15751 : 3135 : stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
15752 : 3135 : stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
15753 : 3135 : stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
15754 : 3135 : PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
15755 [ - + ]: 3135 : if (StatResultType == NULL) {
15756 : 0 : return -1;
15757 : : }
15758 : 3135 : Py_INCREF(StatResultType);
15759 : 3135 : PyModule_AddObject(m, "stat_result", StatResultType);
15760 : 3135 : state->StatResultType = StatResultType;
15761 : 3135 : structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15762 : 3135 : ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
15763 : :
15764 : 3135 : statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
15765 : 3135 : PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
15766 [ - + ]: 3135 : if (StatVFSResultType == NULL) {
15767 : 0 : return -1;
15768 : : }
15769 : 3135 : Py_INCREF(StatVFSResultType);
15770 : 3135 : PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
15771 : 3135 : state->StatVFSResultType = StatVFSResultType;
15772 : : #ifdef NEED_TICKS_PER_SECOND
15773 : : # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15774 : 3135 : ticks_per_second = sysconf(_SC_CLK_TCK);
15775 : : # elif defined(HZ)
15776 : : ticks_per_second = HZ;
15777 : : # else
15778 : : ticks_per_second = 60; /* magic fallback value; may be bogus */
15779 : : # endif
15780 : : #endif
15781 : :
15782 : : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
15783 : 3135 : sched_param_desc.name = MODNAME ".sched_param";
15784 : 3135 : PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
15785 [ - + ]: 3135 : if (SchedParamType == NULL) {
15786 : 0 : return -1;
15787 : : }
15788 : 3135 : Py_INCREF(SchedParamType);
15789 : 3135 : PyModule_AddObject(m, "sched_param", SchedParamType);
15790 : 3135 : state->SchedParamType = SchedParamType;
15791 : 3135 : ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
15792 : : #endif
15793 : :
15794 : : /* initialize TerminalSize_info */
15795 : 3135 : PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
15796 [ - + ]: 3135 : if (TerminalSizeType == NULL) {
15797 : 0 : return -1;
15798 : : }
15799 : 3135 : Py_INCREF(TerminalSizeType);
15800 : 3135 : PyModule_AddObject(m, "terminal_size", TerminalSizeType);
15801 : 3135 : state->TerminalSizeType = TerminalSizeType;
15802 : :
15803 : : /* initialize scandir types */
15804 : 3135 : PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
15805 [ - + ]: 3135 : if (ScandirIteratorType == NULL) {
15806 : 0 : return -1;
15807 : : }
15808 : 3135 : state->ScandirIteratorType = ScandirIteratorType;
15809 : :
15810 : 3135 : PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
15811 [ - + ]: 3135 : if (DirEntryType == NULL) {
15812 : 0 : return -1;
15813 : : }
15814 : 3135 : Py_INCREF(DirEntryType);
15815 : 3135 : PyModule_AddObject(m, "DirEntry", DirEntryType);
15816 : 3135 : state->DirEntryType = DirEntryType;
15817 : :
15818 : 3135 : times_result_desc.name = MODNAME ".times_result";
15819 : 3135 : PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(×_result_desc);
15820 [ - + ]: 3135 : if (TimesResultType == NULL) {
15821 : 0 : return -1;
15822 : : }
15823 : 3135 : Py_INCREF(TimesResultType);
15824 : 3135 : PyModule_AddObject(m, "times_result", TimesResultType);
15825 : 3135 : state->TimesResultType = TimesResultType;
15826 : :
15827 : 3135 : PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
15828 [ - + ]: 3135 : if (UnameResultType == NULL) {
15829 : 0 : return -1;
15830 : : }
15831 : 3135 : Py_INCREF(UnameResultType);
15832 : 3135 : PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
15833 : 3135 : state->UnameResultType = (PyObject *)UnameResultType;
15834 : :
15835 [ - + ]: 3135 : if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
15836 : 0 : return -1;
15837 : : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
15838 : 3135 : state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
15839 [ - + ]: 3135 : if (state->struct_rusage == NULL)
15840 : 0 : return -1;
15841 : : #endif
15842 : 3135 : state->st_mode = PyUnicode_InternFromString("st_mode");
15843 [ - + ]: 3135 : if (state->st_mode == NULL)
15844 : 0 : return -1;
15845 : :
15846 : : /* suppress "function not used" warnings */
15847 : : {
15848 : : int ignored;
15849 : 3135 : fd_specified("", -1);
15850 : 3135 : follow_symlinks_specified("", 1);
15851 : 3135 : dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
15852 : 3135 : dir_fd_converter(Py_None, &ignored);
15853 : 3135 : dir_fd_unavailable(Py_None, &ignored);
15854 : : }
15855 : :
15856 : : /*
15857 : : * provide list of locally available functions
15858 : : * so os.py can populate support_* lists
15859 : : */
15860 : 3135 : PyObject *list = PyList_New(0);
15861 [ - + ]: 3135 : if (!list) {
15862 : 0 : return -1;
15863 : : }
15864 [ + + ]: 97185 : for (const struct have_function *trace = have_functions; trace->label; trace++) {
15865 : : PyObject *unicode;
15866 [ + + - + ]: 94050 : if (trace->probe && !trace->probe()) continue;
15867 : 94050 : unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
15868 [ - + ]: 94050 : if (!unicode)
15869 : 0 : return -1;
15870 [ - + ]: 94050 : if (PyList_Append(list, unicode))
15871 : 0 : return -1;
15872 : 94050 : Py_DECREF(unicode);
15873 : : }
15874 : :
15875 : 3135 : PyModule_AddObject(m, "_have_functions", list);
15876 : :
15877 : 3135 : return 0;
15878 : : }
15879 : :
15880 : :
15881 : : static PyModuleDef_Slot posixmodile_slots[] = {
15882 : : {Py_mod_exec, posixmodule_exec},
15883 : : {0, NULL}
15884 : : };
15885 : :
15886 : : static struct PyModuleDef posixmodule = {
15887 : : PyModuleDef_HEAD_INIT,
15888 : : .m_name = MODNAME,
15889 : : .m_doc = posix__doc__,
15890 : : .m_size = sizeof(_posixstate),
15891 : : .m_methods = posix_methods,
15892 : : .m_slots = posixmodile_slots,
15893 : : .m_traverse = _posix_traverse,
15894 : : .m_clear = _posix_clear,
15895 : : .m_free = _posix_free,
15896 : : };
15897 : :
15898 : : PyMODINIT_FUNC
15899 : 3135 : INITFUNC(void)
15900 : : {
15901 : 3135 : return PyModuleDef_Init(&posixmodule);
15902 : : }
15903 : :
15904 : : #ifdef __cplusplus
15905 : : }
15906 : : #endif
|