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 3364 : run_at_forkers(PyObject *lst, int reverse)
525 : {
526 : Py_ssize_t i;
527 : PyObject *cpy;
528 :
529 3364 : if (lst != NULL) {
530 2614 : 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 2614 : cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
536 2614 : if (cpy == NULL)
537 0 : PyErr_WriteUnraisable(lst);
538 : else {
539 2614 : if (reverse)
540 1304 : PyList_Reverse(cpy);
541 6078 : for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
542 : PyObject *func, *res;
543 3464 : func = PyList_GET_ITEM(cpy, i);
544 3464 : res = _PyObject_CallNoArgs(func);
545 3464 : if (res == NULL)
546 0 : PyErr_WriteUnraisable(func);
547 : else
548 3464 : Py_DECREF(res);
549 : }
550 2614 : Py_DECREF(cpy);
551 : }
552 : }
553 3364 : }
554 :
555 : void
556 1682 : PyOS_BeforeFork(void)
557 : {
558 1682 : run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1);
559 :
560 1682 : _PyImport_AcquireLock();
561 1682 : }
562 :
563 : void
564 1674 : PyOS_AfterFork_Parent(void)
565 : {
566 1674 : if (_PyImport_ReleaseLock() <= 0)
567 0 : Py_FatalError("failed releasing import lock after fork");
568 :
569 1674 : run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0);
570 1674 : }
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 8 : 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 9300 : register_at_forker(PyObject **lst, PyObject *func)
618 : {
619 9300 : if (func == NULL) /* nothing to register? do nothing. */
620 4826 : return 0;
621 4474 : if (*lst == NULL) {
622 2482 : *lst = PyList_New(0);
623 2482 : if (*lst == NULL)
624 0 : return -1;
625 : }
626 4474 : 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 1308050 : _PyLong_FromUid(uid_t uid)
652 : {
653 1308050 : if (uid == (uid_t)-1)
654 1 : return PyLong_FromLong(-1);
655 1308050 : return PyLong_FromUnsignedLong(uid);
656 : }
657 :
658 : PyObject *
659 1308790 : _PyLong_FromGid(gid_t gid)
660 : {
661 1308790 : if (gid == (gid_t)-1)
662 0 : return PyLong_FromLong(-1);
663 1308790 : return PyLong_FromUnsignedLong(gid);
664 : }
665 :
666 : int
667 734 : _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 734 : index = _PyNumber_Index(obj);
676 734 : 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 718 : result = PyLong_AsLongAndOverflow(index, &overflow);
697 :
698 718 : if (!overflow) {
699 715 : uid = (uid_t)result;
700 :
701 715 : 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 696 : if (result < 0)
710 0 : goto underflow;
711 :
712 : /* Ensure the value wasn't truncated. */
713 696 : if (sizeof(uid_t) < sizeof(long) &&
714 696 : (long)uid != result)
715 5 : goto underflow;
716 691 : 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 710 : Py_DECREF(index);
754 710 : *p = uid;
755 710 : 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 737 : _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 737 : index = _PyNumber_Index(obj);
782 737 : 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 720 : result = PyLong_AsLongAndOverflow(index, &overflow);
803 :
804 720 : if (!overflow) {
805 718 : gid = (gid_t)result;
806 :
807 718 : 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 698 : if (result < 0) {
816 0 : goto underflow;
817 : }
818 :
819 : /* Ensure the value wasn't truncated. */
820 698 : if (sizeof(gid_t) < sizeof(long) &&
821 698 : (long)gid != result)
822 4 : goto underflow;
823 694 : 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 714 : Py_DECREF(index);
861 714 : *p = gid;
862 714 : 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 70713 : _fd_converter(PyObject *o, int *p)
911 : {
912 : int overflow;
913 : long long_value;
914 :
915 70713 : PyObject *index = _PyNumber_Index(o);
916 70713 : if (index == NULL) {
917 0 : return 0;
918 : }
919 :
920 70713 : assert(PyLong_Check(index));
921 70713 : long_value = PyLong_AsLongAndOverflow(index, &overflow);
922 70713 : Py_DECREF(index);
923 70713 : assert(!PyErr_Occurred());
924 70713 : 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 70712 : 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 70712 : *p = (int)long_value;
936 70712 : return 1;
937 : }
938 :
939 : static int
940 72148 : dir_fd_converter(PyObject *o, void *p)
941 : {
942 72148 : if (o == Py_None) {
943 18799 : *(int *)p = DEFAULT_DIR_FD;
944 18799 : return 1;
945 : }
946 53349 : else if (PyIndex_Check(o)) {
947 53347 : 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 5456960 : get_posix_state(PyObject *module)
981 : {
982 5456960 : void *state = _PyModule_GetState(module);
983 5456960 : assert(state != NULL);
984 5456960 : 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 1797190 : path_cleanup(path_t *path)
1100 : {
1101 1797190 : wchar_t *wide = (wchar_t *)path->wide;
1102 1797190 : path->wide = NULL;
1103 1797190 : PyMem_Free(wide);
1104 1797190 : Py_CLEAR(path->object);
1105 1797190 : Py_CLEAR(path->cleanup);
1106 1797190 : }
1107 :
1108 : static int
1109 1746760 : path_converter(PyObject *o, void *p)
1110 : {
1111 1746760 : path_t *path = (path_t *)p;
1112 1746760 : PyObject *bytes = NULL;
1113 1746760 : 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 1746760 : 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 1746760 : path->object = path->cleanup = NULL;
1135 : /* path->object owns a reference to the original object */
1136 1746760 : Py_INCREF(o);
1137 :
1138 1746760 : 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 1746760 : is_index = path->allow_fd && PyIndex_Check(o);
1152 1746760 : is_buffer = PyObject_CheckBuffer(o);
1153 1746760 : is_bytes = PyBytes_Check(o);
1154 1746760 : is_unicode = PyUnicode_Check(o);
1155 :
1156 1746760 : if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
1157 : /* Inline PyOS_FSPath() for better error messages. */
1158 : PyObject *func, *res;
1159 :
1160 32991 : func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1161 32991 : if (NULL == func) {
1162 12 : goto error_format;
1163 : }
1164 32979 : res = _PyObject_CallNoArgs(func);
1165 32979 : Py_DECREF(func);
1166 32979 : if (NULL == res) {
1167 0 : goto error_exit;
1168 : }
1169 32979 : else if (PyUnicode_Check(res)) {
1170 32967 : 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 32972 : Py_DECREF(o);
1186 32972 : o = res;
1187 : }
1188 :
1189 1746740 : 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 1711100 : if (!PyUnicode_FSConverter(o, &bytes)) {
1211 102 : goto error_exit;
1212 : }
1213 : #endif
1214 : }
1215 35648 : else if (is_bytes) {
1216 18237 : bytes = o;
1217 18237 : Py_INCREF(bytes);
1218 : }
1219 17411 : 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 17366 : else if (is_index) {
1241 17366 : if (!_fd_converter(o, &path->fd)) {
1242 0 : goto error_exit;
1243 : }
1244 17366 : path->wide = NULL;
1245 : #ifdef MS_WINDOWS
1246 : path->narrow = FALSE;
1247 : #else
1248 17366 : path->narrow = NULL;
1249 : #endif
1250 17366 : 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 1729280 : length = PyBytes_GET_SIZE(bytes);
1268 1729280 : narrow = PyBytes_AS_STRING(bytes);
1269 1729280 : 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 1729250 : path->wide = NULL;
1302 1729250 : path->narrow = narrow;
1303 1729250 : 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 18212 : Py_DECREF(bytes);
1307 : }
1308 : else {
1309 1711040 : path->cleanup = bytes;
1310 : }
1311 : #endif
1312 1729250 : path->fd = -1;
1313 :
1314 1746620 : success_exit:
1315 1746620 : path->length = length;
1316 1746620 : path->object = o;
1317 1746620 : 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 3130 : dir_fd_unavailable(PyObject *o, void *p)
1340 : {
1341 : int dir_fd;
1342 3130 : if (!dir_fd_converter(o, &dir_fd))
1343 0 : return 0;
1344 3130 : if (dir_fd != DEFAULT_DIR_FD) {
1345 0 : argument_unavailable_error(NULL, "dir_fd");
1346 0 : return 0;
1347 : }
1348 3130 : *(int *)p = dir_fd;
1349 3130 : return 1;
1350 : }
1351 :
1352 : static int
1353 3130 : fd_specified(const char *function_name, int fd)
1354 : {
1355 3130 : if (fd == -1)
1356 3130 : return 0;
1357 :
1358 0 : argument_unavailable_error(function_name, "fd");
1359 0 : return 1;
1360 : }
1361 :
1362 : static int
1363 3130 : follow_symlinks_specified(const char *function_name, int follow_symlinks)
1364 : {
1365 3130 : if (follow_symlinks)
1366 3130 : return 0;
1367 :
1368 0 : argument_unavailable_error(function_name, "follow_symlinks");
1369 0 : return 1;
1370 : }
1371 :
1372 : static int
1373 1499690 : path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1374 : {
1375 1499690 : 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 1499690 : return 0;
1386 : }
1387 :
1388 : static int
1389 1499720 : dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1390 : {
1391 1499720 : 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 1499720 : return 0;
1398 : }
1399 :
1400 : static int
1401 1511610 : fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1402 : int follow_symlinks)
1403 : {
1404 1511610 : 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 1511610 : return 0;
1411 : }
1412 :
1413 : static int
1414 3130 : dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1415 : int follow_symlinks)
1416 : {
1417 3130 : 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 3130 : 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 30718 : 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 30718 : *((Py_off_t *)addr) = PyLong_AsLong(arg);
1439 : #endif
1440 30718 : if (PyErr_Occurred())
1441 0 : return 0;
1442 30718 : 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 270 : _Py_Sigset_Converter(PyObject *obj, void *addr)
1460 : {
1461 270 : 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 270 : if (sigemptyset(mask) < (0)) {
1468 : /* Probably only if mask == NULL. */
1469 0 : PyErr_SetFromErrno(PyExc_OSError);
1470 0 : return 0;
1471 : }
1472 :
1473 270 : iterator = PyObject_GetIter(obj);
1474 270 : if (iterator == NULL) {
1475 4 : return 0;
1476 : }
1477 :
1478 1082 : while ((item = PyIter_Next(iterator)) != NULL) {
1479 827 : signum = PyLong_AsLongAndOverflow(item, &overflow);
1480 827 : Py_DECREF(item);
1481 827 : 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 816 : 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 255 : if (!PyErr_Occurred()) {
1506 255 : Py_DECREF(iterator);
1507 255 : 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 3130 : convertenviron(void)
1555 : {
1556 : PyObject *d;
1557 : #ifdef MS_WINDOWS
1558 : wchar_t **e;
1559 : #else
1560 : char **e;
1561 : #endif
1562 :
1563 3130 : d = PyDict_New();
1564 3130 : 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 3130 : e = environ;
1578 : #endif
1579 3130 : if (e == NULL)
1580 0 : return d;
1581 355656 : 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 352526 : const char *p = strchr(*e, '=');
1588 : #endif
1589 352526 : if (p == NULL)
1590 0 : continue;
1591 : #ifdef MS_WINDOWS
1592 : k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1593 : #else
1594 352526 : k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1595 : #endif
1596 352526 : 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 352526 : v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1604 : #endif
1605 352526 : if (v == NULL) {
1606 0 : Py_DECREF(k);
1607 0 : Py_DECREF(d);
1608 0 : return NULL;
1609 : }
1610 352526 : 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 352526 : Py_DECREF(k);
1617 352526 : Py_DECREF(v);
1618 : }
1619 3130 : return d;
1620 : }
1621 :
1622 : /* Set a POSIX-specific error from errno, and return NULL */
1623 :
1624 : static PyObject *
1625 1052640 : posix_error(void)
1626 : {
1627 1052640 : 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 253458 : posix_path_object_error(PyObject *path)
1670 : {
1671 253458 : return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1672 : }
1673 :
1674 : static PyObject *
1675 253453 : path_object_error(PyObject *path)
1676 : {
1677 : #ifdef MS_WINDOWS
1678 : return PyErr_SetExcFromWindowsErrWithFilenameObject(
1679 : PyExc_OSError, 0, path);
1680 : #else
1681 253453 : 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 251270 : path_error(path_t *path)
1698 : {
1699 251270 : 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 68 : statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2243 : {
2244 : PyStructSequence *result;
2245 : int i;
2246 :
2247 68 : result = (PyStructSequence*)structseq_new(type, args, kwds);
2248 68 : 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 264 : for (i = 7; i <= 9; i++) {
2254 198 : if (result->ob_item[i+3] == Py_None) {
2255 66 : Py_DECREF(Py_None);
2256 66 : Py_INCREF(result->ob_item[i]);
2257 66 : result->ob_item[i+3] = result->ob_item[i];
2258 : }
2259 : }
2260 66 : return (PyObject*)result;
2261 : }
2262 :
2263 : static int
2264 6158 : _posix_clear(PyObject *module)
2265 : {
2266 6158 : _posixstate *state = get_posix_state(module);
2267 6158 : Py_CLEAR(state->billion);
2268 6158 : Py_CLEAR(state->DirEntryType);
2269 6158 : Py_CLEAR(state->ScandirIteratorType);
2270 : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2271 6158 : Py_CLEAR(state->SchedParamType);
2272 : #endif
2273 6158 : Py_CLEAR(state->StatResultType);
2274 6158 : Py_CLEAR(state->StatVFSResultType);
2275 6158 : Py_CLEAR(state->TerminalSizeType);
2276 6158 : Py_CLEAR(state->TimesResultType);
2277 6158 : Py_CLEAR(state->UnameResultType);
2278 : #if defined(HAVE_WAITID) && !defined(__APPLE__)
2279 6158 : Py_CLEAR(state->WaitidResultType);
2280 : #endif
2281 : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2282 6158 : Py_CLEAR(state->struct_rusage);
2283 : #endif
2284 6158 : Py_CLEAR(state->st_mode);
2285 6158 : return 0;
2286 : }
2287 :
2288 : static int
2289 55736 : _posix_traverse(PyObject *module, visitproc visit, void *arg)
2290 : {
2291 55736 : _posixstate *state = get_posix_state(module);
2292 55736 : Py_VISIT(state->billion);
2293 55736 : Py_VISIT(state->DirEntryType);
2294 55736 : Py_VISIT(state->ScandirIteratorType);
2295 : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2296 55736 : Py_VISIT(state->SchedParamType);
2297 : #endif
2298 55736 : Py_VISIT(state->StatResultType);
2299 55736 : Py_VISIT(state->StatVFSResultType);
2300 55736 : Py_VISIT(state->TerminalSizeType);
2301 55736 : Py_VISIT(state->TimesResultType);
2302 55736 : Py_VISIT(state->UnameResultType);
2303 : #if defined(HAVE_WAITID) && !defined(__APPLE__)
2304 55736 : Py_VISIT(state->WaitidResultType);
2305 : #endif
2306 : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2307 55736 : Py_VISIT(state->struct_rusage);
2308 : #endif
2309 55736 : Py_VISIT(state->st_mode);
2310 55736 : return 0;
2311 : }
2312 :
2313 : static void
2314 3079 : _posix_free(void *module)
2315 : {
2316 3079 : _posix_clear((PyObject *)module);
2317 3079 : }
2318 :
2319 : static void
2320 3906860 : fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)
2321 : {
2322 3906860 : PyObject *s = _PyLong_FromTime_t(sec);
2323 3906860 : PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2324 3906860 : PyObject *s_in_ns = NULL;
2325 3906860 : PyObject *ns_total = NULL;
2326 3906860 : PyObject *float_s = NULL;
2327 :
2328 3906860 : if (!(s && ns_fractional))
2329 0 : goto exit;
2330 :
2331 3906860 : s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2332 3906860 : if (!s_in_ns)
2333 0 : goto exit;
2334 :
2335 3906860 : ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2336 3906860 : if (!ns_total)
2337 0 : goto exit;
2338 :
2339 3906860 : float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2340 3906860 : if (!float_s) {
2341 0 : goto exit;
2342 : }
2343 :
2344 3906860 : PyStructSequence_SET_ITEM(v, index, s);
2345 3906860 : PyStructSequence_SET_ITEM(v, index+3, float_s);
2346 3906860 : PyStructSequence_SET_ITEM(v, index+6, ns_total);
2347 3906860 : s = NULL;
2348 3906860 : float_s = NULL;
2349 3906860 : ns_total = NULL;
2350 3906860 : exit:
2351 3906860 : Py_XDECREF(s);
2352 3906860 : Py_XDECREF(ns_fractional);
2353 3906860 : Py_XDECREF(s_in_ns);
2354 3906860 : Py_XDECREF(ns_total);
2355 3906860 : Py_XDECREF(float_s);
2356 3906860 : }
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 1302280 : _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2362 : {
2363 : unsigned long ansec, mnsec, cnsec;
2364 1302280 : PyObject *StatResultType = get_posix_state(module)->StatResultType;
2365 1302280 : PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2366 1302280 : if (v == NULL)
2367 0 : return NULL;
2368 :
2369 1302280 : 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 1302280 : 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 1302280 : PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2377 : #endif
2378 1302280 : 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 1302280 : PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2384 1302280 : 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 1302280 : PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2389 :
2390 : #if defined(HAVE_STAT_TV_NSEC)
2391 1302280 : ansec = st->st_atim.tv_nsec;
2392 1302280 : mnsec = st->st_mtim.tv_nsec;
2393 1302280 : 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 1302280 : fill_time(module, v, 7, st->st_atime, ansec);
2406 1302280 : fill_time(module, v, 8, st->st_mtime, mnsec);
2407 1302280 : fill_time(module, v, 9, st->st_ctime, cnsec);
2408 :
2409 : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2410 1302280 : PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2411 : PyLong_FromLong((long)st->st_blksize));
2412 : #endif
2413 : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2414 1302280 : PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2415 : PyLong_FromLong((long)st->st_blocks));
2416 : #endif
2417 : #ifdef HAVE_STRUCT_STAT_ST_RDEV
2418 1302280 : 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 1302280 : if (PyErr_Occurred()) {
2458 0 : Py_DECREF(v);
2459 0 : return NULL;
2460 : }
2461 :
2462 1302280 : return v;
2463 : }
2464 :
2465 : /* POSIX methods */
2466 :
2467 :
2468 : static PyObject *
2469 1488140 : 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 1488140 : 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 2976270 : if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2485 2976270 : dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2486 1488140 : fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2487 0 : return NULL;
2488 :
2489 1488140 : Py_BEGIN_ALLOW_THREADS
2490 1488140 : 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 1484370 : if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2501 139672 : result = LSTAT(path->narrow, &st);
2502 : else
2503 : #endif /* HAVE_LSTAT */
2504 : #ifdef HAVE_FSTATAT
2505 1344700 : 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 1340850 : result = STAT(path->narrow, &st);
2516 : #endif /* MS_WINDOWS */
2517 1488140 : Py_END_ALLOW_THREADS
2518 :
2519 : #ifdef HAVE_FSTATAT
2520 1488130 : if (fstatat_unavailable) {
2521 0 : argument_unavailable_error("stat", "dir_fd");
2522 0 : return NULL;
2523 : }
2524 : #endif
2525 :
2526 1488130 : if (result != 0) {
2527 234504 : return path_error(path);
2528 : }
2529 :
2530 1253630 : 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 1348890 : 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 1348890 : 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 139247 : os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2880 : /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2881 : {
2882 139247 : int follow_symlinks = 0;
2883 139247 : 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 163 : 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 163 : 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 163 : Py_BEGIN_ALLOW_THREADS
2973 : #ifdef HAVE_FACCESSAT
2974 163 : if ((dir_fd != DEFAULT_DIR_FD) ||
2975 158 : 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 158 : result = access(path->narrow, mode);
2992 163 : Py_END_ALLOW_THREADS
2993 :
2994 : #ifdef HAVE_FACCESSAT
2995 163 : 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 163 : return_value = !result;
3012 : #endif
3013 :
3014 163 : 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 0 : 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 3177 : os_chdir_impl(PyObject *module, path_t *path)
3108 : /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3109 : {
3110 : int result;
3111 :
3112 3177 : if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3113 0 : return NULL;
3114 : }
3115 :
3116 3177 : 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 3177 : if (path->fd != -1)
3123 0 : result = fchdir(path->fd);
3124 : else
3125 : #endif
3126 3177 : result = chdir(path->narrow);
3127 : #endif
3128 3177 : Py_END_ALLOW_THREADS
3129 :
3130 3177 : if (result) {
3131 190 : return path_error(path);
3132 : }
3133 :
3134 2987 : 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 14214 : 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 14214 : int fchmodat_nofollow_unsupported = 0;
3208 14214 : 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 14214 : 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 14214 : Py_BEGIN_ALLOW_THREADS
3240 : #ifdef HAVE_FCHMOD
3241 14214 : 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 14214 : 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 14213 : 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 14214 : Py_END_ALLOW_THREADS
3295 :
3296 14214 : 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 14209 : 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 35707 : 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 35707 : const size_t chunk = 1024;
3786 :
3787 35707 : char *buf = NULL;
3788 35707 : char *cwd = NULL;
3789 35707 : size_t buflen = 0;
3790 :
3791 35707 : Py_BEGIN_ALLOW_THREADS
3792 : do {
3793 : char *newbuf;
3794 35713 : if (buflen <= PY_SSIZE_T_MAX - chunk) {
3795 35713 : buflen += chunk;
3796 35713 : newbuf = PyMem_RawRealloc(buf, buflen);
3797 : }
3798 : else {
3799 0 : newbuf = NULL;
3800 : }
3801 35713 : if (newbuf == NULL) {
3802 0 : PyMem_RawFree(buf);
3803 0 : buf = NULL;
3804 0 : break;
3805 : }
3806 35713 : buf = newbuf;
3807 :
3808 35713 : cwd = getcwd(buf, buflen);
3809 35713 : } while (cwd == NULL && errno == ERANGE);
3810 35707 : Py_END_ALLOW_THREADS
3811 :
3812 35707 : if (buf == NULL) {
3813 0 : return PyErr_NoMemory();
3814 : }
3815 35707 : if (cwd == NULL) {
3816 4 : PyMem_RawFree(buf);
3817 4 : return posix_error();
3818 : }
3819 :
3820 : PyObject *obj;
3821 35703 : if (use_bytes) {
3822 67 : obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3823 : }
3824 : else {
3825 35636 : obj = PyUnicode_DecodeFSDefault(buf);
3826 : }
3827 35703 : PyMem_RawFree(buf);
3828 :
3829 35703 : 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 35640 : os_getcwd_impl(PyObject *module)
3842 : /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3843 : {
3844 35640 : 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 37287 : _posix_listdir(path_t *path, PyObject *list)
4085 : {
4086 : PyObject *v;
4087 37287 : DIR *dirp = NULL;
4088 : struct dirent *ep;
4089 : int return_str; /* if false, return bytes */
4090 : #ifdef HAVE_FDOPENDIR
4091 37287 : int fd = -1;
4092 : #endif
4093 :
4094 37287 : errno = 0;
4095 : #ifdef HAVE_FDOPENDIR
4096 37287 : 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 37232 : if (path->narrow) {
4119 35138 : name = path->narrow;
4120 : /* only return bytes if they specified a bytes-like object */
4121 35138 : return_str = !PyObject_CheckBuffer(path->object);
4122 : }
4123 : else {
4124 2094 : name = ".";
4125 2094 : return_str = 1;
4126 : }
4127 :
4128 37232 : Py_BEGIN_ALLOW_THREADS
4129 37232 : dirp = opendir(name);
4130 37232 : Py_END_ALLOW_THREADS
4131 : }
4132 :
4133 37287 : if (dirp == NULL) {
4134 526 : list = path_error(path);
4135 : #ifdef HAVE_FDOPENDIR
4136 526 : if (fd != -1) {
4137 0 : Py_BEGIN_ALLOW_THREADS
4138 0 : close(fd);
4139 0 : Py_END_ALLOW_THREADS
4140 : }
4141 : #endif
4142 526 : goto exit;
4143 : }
4144 36761 : if ((list = PyList_New(0)) == NULL) {
4145 0 : goto exit;
4146 : }
4147 : for (;;) {
4148 2344280 : errno = 0;
4149 2344280 : Py_BEGIN_ALLOW_THREADS
4150 2344280 : ep = readdir(dirp);
4151 2344280 : Py_END_ALLOW_THREADS
4152 2344280 : if (ep == NULL) {
4153 36761 : if (errno == 0) {
4154 36761 : break;
4155 : } else {
4156 0 : Py_DECREF(list);
4157 0 : list = path_error(path);
4158 0 : goto exit;
4159 : }
4160 : }
4161 2307520 : if (ep->d_name[0] == '.' &&
4162 81006 : (NAMLEN(ep) == 1 ||
4163 44245 : (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4164 73522 : continue;
4165 2234000 : if (return_str)
4166 2233900 : v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4167 : else
4168 98 : v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4169 2234000 : if (v == NULL) {
4170 0 : Py_CLEAR(list);
4171 0 : break;
4172 : }
4173 2234000 : if (PyList_Append(list, v) != 0) {
4174 0 : Py_DECREF(v);
4175 0 : Py_CLEAR(list);
4176 0 : break;
4177 : }
4178 2234000 : Py_DECREF(v);
4179 : }
4180 :
4181 37287 : exit:
4182 37287 : if (dirp != NULL) {
4183 36761 : Py_BEGIN_ALLOW_THREADS
4184 : #ifdef HAVE_FDOPENDIR
4185 36761 : if (fd > -1)
4186 55 : rewinddir(dirp);
4187 : #endif
4188 36761 : closedir(dirp);
4189 36761 : Py_END_ALLOW_THREADS
4190 : }
4191 :
4192 37287 : 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 37287 : os_listdir_impl(PyObject *module, path_t *path)
4220 : /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4221 : {
4222 37287 : if (PySys_Audit("os.listdir", "O",
4223 37287 : 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 37287 : 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 152965 : os__path_normpath_impl(PyObject *module, PyObject *path)
4496 : /*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/
4497 : {
4498 152965 : 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 152965 : wchar_t *buffer = PyUnicode_AsWideCharString(path, &len);
4505 152965 : if (!buffer) {
4506 0 : return NULL;
4507 : }
4508 152965 : PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1);
4509 152965 : PyMem_Free(buffer);
4510 152965 : 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 17676 : 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 17676 : int mkdirat_unavailable = 0;
4543 : #endif
4544 :
4545 17676 : 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 17676 : Py_BEGIN_ALLOW_THREADS
4559 : #if HAVE_MKDIRAT
4560 17676 : 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 17675 : result = mkdir(path->narrow, mode);
4573 : #endif
4574 17676 : Py_END_ALLOW_THREADS
4575 :
4576 : #if HAVE_MKDIRAT
4577 17676 : if (mkdirat_unavailable) {
4578 0 : argument_unavailable_error(NULL, "dir_fd");
4579 0 : return NULL;
4580 : }
4581 : #endif
4582 :
4583 17676 : if (result < 0)
4584 7686 : return path_error(path);
4585 : #endif /* MS_WINDOWS */
4586 9990 : 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 8476 : internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4688 : {
4689 8476 : const char *function_name = is_replace ? "replace" : "rename";
4690 : int dir_fd_specified;
4691 :
4692 : #ifdef HAVE_RENAMEAT
4693 8476 : 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 8476 : 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 8476 : 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 8476 : 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 8476 : Py_BEGIN_ALLOW_THREADS
4734 : #ifdef HAVE_RENAMEAT
4735 8476 : 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 8475 : result = rename(src->narrow, dst->narrow);
4744 8476 : Py_END_ALLOW_THREADS
4745 :
4746 :
4747 : #ifdef HAVE_RENAMEAT
4748 8476 : 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 8476 : if (result)
4755 121 : return path_error2(src, dst);
4756 : #endif
4757 8355 : 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 931 : 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 931 : 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 7545 : 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 7545 : 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 10658 : 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 10658 : int unlinkat_unavailable = 0;
4831 : #endif
4832 :
4833 10658 : 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 10658 : 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 10658 : if (dir_fd != DEFAULT_DIR_FD) {
4845 : if (HAVE_UNLINKAT_RUNTIME) {
4846 5809 : result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4847 : } else {
4848 : unlinkat_unavailable = 1;
4849 : result = -1;
4850 : }
4851 : } else
4852 : #endif
4853 4849 : result = rmdir(path->narrow);
4854 : #endif
4855 10658 : Py_END_ALLOW_THREADS
4856 :
4857 : #ifdef HAVE_UNLINKAT
4858 10658 : if (unlinkat_unavailable) {
4859 0 : argument_unavailable_error("rmdir", "dir_fd");
4860 0 : return NULL;
4861 : }
4862 : #endif
4863 :
4864 10658 : if (result)
4865 409 : return path_error(path);
4866 :
4867 10249 : 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 5 : os_system_impl(PyObject *module, PyObject *command)
4909 : /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4910 : {
4911 : long result;
4912 5 : const char *bytes = PyBytes_AsString(command);
4913 :
4914 5 : if (PySys_Audit("os.system", "(O)", command) < 0) {
4915 0 : return -1;
4916 : }
4917 :
4918 5 : Py_BEGIN_ALLOW_THREADS
4919 5 : result = system(bytes);
4920 5 : Py_END_ALLOW_THREADS
4921 5 : 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 51699 : 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 51699 : int unlinkat_unavailable = 0;
5011 : #endif
5012 :
5013 51699 : 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 51699 : 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 51699 : if (dir_fd != DEFAULT_DIR_FD) {
5026 : if (HAVE_UNLINKAT_RUNTIME) {
5027 :
5028 33538 : result = unlinkat(dir_fd, path->narrow, 0);
5029 : } else {
5030 : unlinkat_unavailable = 1;
5031 : }
5032 : } else
5033 : #endif /* HAVE_UNLINKAT */
5034 18161 : result = unlink(path->narrow);
5035 : #endif
5036 : _Py_END_SUPPRESS_IPH
5037 51699 : Py_END_ALLOW_THREADS
5038 :
5039 : #ifdef HAVE_UNLINKAT
5040 51699 : if (unlinkat_unavailable) {
5041 0 : argument_unavailable_error(NULL, "dir_fd");
5042 0 : return NULL;
5043 : }
5044 : #endif
5045 :
5046 51699 : if (result)
5047 7413 : return path_error(path);
5048 :
5049 44286 : 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 1435 : os_remove_impl(PyObject *module, path_t *path, int dir_fd)
5066 : /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
5067 : {
5068 1435 : 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 289 : 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 289 : Py_BEGIN_ALLOW_THREADS
5116 289 : res = uname(&u);
5117 289 : Py_END_ALLOW_THREADS
5118 289 : if (res < 0)
5119 0 : return posix_error();
5120 :
5121 289 : PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
5122 289 : value = PyStructSequence_New((PyTypeObject *)UnameResultType);
5123 289 : 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 289 : SET(0, u.sysname);
5137 289 : SET(1, u.nodename);
5138 289 : SET(2, u.release);
5139 289 : SET(3, u.version);
5140 289 : SET(4, u.machine);
5141 :
5142 : #undef SET
5143 :
5144 289 : 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 11529 : 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 11529 : UTIME_TO_TIMESPEC;
5335 11529 : 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 22323 : split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5352 : {
5353 22323 : int result = 0;
5354 : PyObject *divmod;
5355 22323 : divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5356 22323 : if (!divmod)
5357 0 : goto exit;
5358 22323 : 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 22320 : *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5365 22320 : if ((*s == -1) && PyErr_Occurred())
5366 0 : goto exit;
5367 22320 : *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5368 22320 : if ((*ns == -1) && PyErr_Occurred())
5369 0 : goto exit;
5370 :
5371 22320 : result = 1;
5372 22323 : exit:
5373 22323 : Py_XDECREF(divmod);
5374 22323 : 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 11581 : 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 11581 : memset(&utime, 0, sizeof(utime_t));
5431 :
5432 11581 : 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 11577 : if (times != Py_None) {
5440 : time_t a_sec, m_sec;
5441 : long a_nsec, m_nsec;
5442 344 : 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 340 : utime.now = 0;
5449 340 : if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
5450 332 : &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
5451 332 : _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
5452 : &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
5453 13 : return NULL;
5454 : }
5455 327 : utime.atime_s = a_sec;
5456 327 : utime.atime_ns = a_nsec;
5457 327 : utime.mtime_s = m_sec;
5458 327 : utime.mtime_ns = m_nsec;
5459 : }
5460 11233 : else if (ns) {
5461 11166 : 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 11163 : utime.now = 0;
5467 11163 : if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
5468 11160 : &utime.atime_s, &utime.atime_ns) ||
5469 11160 : !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 67 : 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 23108 : if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
5485 23108 : dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
5486 11554 : 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 11554 : 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 11554 : Py_BEGIN_ALLOW_THREADS
5534 :
5535 : #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5536 11554 : 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 11544 : 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 11536 : if (path->fd != -1)
5550 7 : result = utime_fd(&utime, path->fd);
5551 : else
5552 : #endif
5553 :
5554 11529 : result = utime_default(&utime, path->narrow);
5555 :
5556 11554 : 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 11554 : 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 11505 : 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 210 : free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5605 : {
5606 : Py_ssize_t i;
5607 11103 : for (i = 0; i < count; i++)
5608 10893 : PyMem_Free(array[i]);
5609 210 : PyMem_Free(array);
5610 210 : }
5611 :
5612 : static int
5613 10893 : fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5614 : {
5615 : Py_ssize_t size;
5616 : PyObject *ub;
5617 10893 : 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 10893 : if (!PyUnicode_FSConverter(o, &ub))
5626 0 : return 0;
5627 10893 : size = PyBytes_GET_SIZE(ub);
5628 10893 : *out = PyMem_Malloc(size + 1);
5629 10893 : if (*out) {
5630 10893 : memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5631 10893 : result = 1;
5632 : } else
5633 0 : PyErr_NoMemory();
5634 : #endif
5635 10893 : Py_DECREF(ub);
5636 10893 : 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 0 : 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 10625 : for (pos = 0; pos < i; pos++) {
5671 10534 : key = PyList_GetItem(keys, pos);
5672 10534 : val = PyList_GetItem(vals, pos);
5673 10534 : 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 10534 : if (!PyUnicode_FSConverter(key, &key2))
5696 1 : goto error;
5697 10533 : if (!PyUnicode_FSConverter(val, &val2)) {
5698 1 : Py_DECREF(key2);
5699 1 : goto error;
5700 : }
5701 10532 : if (PyBytes_GET_SIZE(key2) == 0 ||
5702 10532 : 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 10531 : keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5710 : PyBytes_AS_STRING(val2));
5711 : #endif
5712 10531 : Py_DECREF(key2);
5713 10531 : Py_DECREF(val2);
5714 10531 : if (!keyval)
5715 0 : goto error;
5716 :
5717 10531 : if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5718 0 : Py_DECREF(keyval);
5719 0 : goto error;
5720 : }
5721 :
5722 10531 : 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 116 : parse_arglist(PyObject* argv, Py_ssize_t *argc)
5740 : {
5741 : int i;
5742 116 : EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5743 116 : if (argvlist == NULL) {
5744 0 : PyErr_NoMemory();
5745 0 : return NULL;
5746 : }
5747 478 : for (i = 0; i < *argc; i++) {
5748 362 : PyObject* item = PySequence_ITEM(argv, i);
5749 362 : if (item == NULL)
5750 0 : goto fail;
5751 362 : if (!fsconvert_strdup(item, &argvlist[i])) {
5752 0 : Py_DECREF(item);
5753 0 : goto fail;
5754 : }
5755 362 : Py_DECREF(item);
5756 : }
5757 116 : argvlist[*argc] = NULL;
5758 116 : 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 24 : 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 24 : 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 24 : argc = PySequence_Size(argv);
5797 24 : if (argc < 1) {
5798 3 : PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5799 3 : return NULL;
5800 : }
5801 :
5802 21 : argvlist = parse_arglist(argv, &argc);
5803 21 : if (argvlist == NULL) {
5804 0 : return NULL;
5805 : }
5806 21 : 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 19 : 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 19 : execv(path->narrow, argvlist);
5823 : #endif
5824 : _Py_END_SUPPRESS_IPH
5825 :
5826 : /* If we get here it's definitely an error */
5827 :
5828 19 : free_string_array(argvlist, argc);
5829 19 : 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 9315 : check_null_or_callable(PyObject *obj, const char* obj_name)
6666 : {
6667 9315 : 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 9307 : 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 3108 : 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 3108 : 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 6213 : if (check_null_or_callable(before, "before") ||
6705 6207 : check_null_or_callable(after_in_child, "after_in_child") ||
6706 3102 : check_null_or_callable(after_in_parent, "after_in_parent")) {
6707 8 : return NULL;
6708 : }
6709 3100 : interp = _PyInterpreterState_GET();
6710 :
6711 3100 : if (register_at_forker(&interp->before_forkers, before)) {
6712 0 : return NULL;
6713 : }
6714 3100 : if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6715 0 : return NULL;
6716 : }
6717 3100 : if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6718 0 : return NULL;
6719 : }
6720 3100 : 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 1669 : os_fork_impl(PyObject *module)
6771 : /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6772 : {
6773 : pid_t pid;
6774 1669 : PyInterpreterState *interp = _PyInterpreterState_GET();
6775 1669 : if (interp->config._isolated_interpreter) {
6776 2 : PyErr_SetString(PyExc_RuntimeError,
6777 : "fork not supported for isolated subinterpreters");
6778 2 : return NULL;
6779 : }
6780 1667 : if (PySys_Audit("os.fork", NULL) < 0) {
6781 0 : return NULL;
6782 : }
6783 1667 : PyOS_BeforeFork();
6784 1667 : pid = fork();
6785 1667 : 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 1659 : PyOS_AfterFork_Parent();
6791 : }
6792 1667 : if (pid == -1)
6793 0 : return posix_error();
6794 1667 : 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 0 : PyErr_NoMemory();
7107 0 : goto error;
7108 : }
7109 6 : CPU_ZERO_S(setsize, cpu_set);
7110 :
7111 9 : while ((item = PyIter_Next(iterator))) {
7112 : long cpu;
7113 5 : 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 5 : cpu = PyLong_AsLong(item);
7122 5 : Py_DECREF(item);
7123 5 : if (cpu < 0) {
7124 2 : if (!PyErr_Occurred())
7125 1 : PyErr_SetString(PyExc_ValueError, "negative CPU number");
7126 2 : goto error;
7127 : }
7128 3 : if (cpu > INT_MAX - 1) {
7129 0 : PyErr_SetString(PyExc_OverflowError, "CPU number too large");
7130 0 : goto error;
7131 : }
7132 3 : 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 0 : 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 3 : 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 0 : 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 9 : for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7220 6 : if (CPU_ISSET_S(cpu, setsize, mask)) {
7221 5 : PyObject *cpu_num = PyLong_FromLong(cpu);
7222 5 : --count;
7223 5 : if (cpu_num == NULL)
7224 0 : goto error;
7225 5 : if (PySet_Add(res, cpu_num)) {
7226 0 : Py_DECREF(cpu_num);
7227 0 : goto error;
7228 : }
7229 5 : 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 2273 : os_getegid_impl(PyObject *module)
7474 : /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
7475 : {
7476 2273 : 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 2504 : os_geteuid_impl(PyObject *module)
7490 : /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
7491 : {
7492 2504 : 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 2278 : os_getgid_impl(PyObject *module)
7506 : /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
7507 : {
7508 2278 : 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 288533 : os_getpid_impl(PyObject *module)
7522 : /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
7523 : {
7524 288533 : 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 0 : 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 0 : 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 4 : for (i = 0; i < ngroups; i++) {
7637 : #ifdef __APPLE__
7638 : PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7639 : #else
7640 3 : PyObject *o = _PyLong_FromGid(groups[i]);
7641 : #endif
7642 3 : if (o == NULL) {
7643 0 : Py_DECREF(list);
7644 0 : PyMem_Free(groups);
7645 0 : return NULL;
7646 : }
7647 3 : 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 0 : 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 24 : for (int i = 0; i < n; ++i) {
7695 18 : PyObject *group = _PyLong_FromGid(grouplist[i]);
7696 18 : if (group == NULL) {
7697 0 : goto error;
7698 : }
7699 18 : 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 2319 : os_getuid_impl(PyObject *module)
7942 : /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7943 : {
7944 2319 : 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 15912 : os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
7966 : /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
7967 : {
7968 15912 : if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
7969 0 : return NULL;
7970 : }
7971 : #ifndef MS_WINDOWS
7972 15912 : 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 15901 : if (PyErr_CheckSignals()) {
7980 95 : return NULL;
7981 : }
7982 :
7983 15806 : 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 25 : Py_BEGIN_ALLOW_THREADS
8351 25 : pid = wait3(&status, options, &ru);
8352 25 : Py_END_ALLOW_THREADS
8353 25 : } 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 18 : Py_BEGIN_ALLOW_THREADS
8388 18 : res = wait4(pid, &status, options, &ru);
8389 18 : Py_END_ALLOW_THREADS
8390 18 : } 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 81369 : 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 81369 : int async_err = 0;
8480 : WAIT_TYPE status;
8481 81369 : WAIT_STATUS_INT(status) = 0;
8482 :
8483 : do {
8484 81405 : Py_BEGIN_ALLOW_THREADS
8485 81405 : res = waitpid(pid, &status, options);
8486 81405 : Py_END_ALLOW_THREADS
8487 81405 : } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8488 81369 : if (res < 0)
8489 3639 : return (!async_err) ? posix_error() : NULL;
8490 :
8491 77730 : 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 15 : Py_BEGIN_ALLOW_THREADS
8556 15 : pid = wait(&status);
8557 15 : Py_END_ALLOW_THREADS
8558 15 : } 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 327 : 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 327 : int readlinkat_unavailable = 0;
8617 : #endif
8618 :
8619 327 : Py_BEGIN_ALLOW_THREADS
8620 : #ifdef HAVE_READLINKAT
8621 327 : 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 326 : length = readlink(path->narrow, buffer, MAXPATHLEN);
8630 327 : Py_END_ALLOW_THREADS
8631 :
8632 : #ifdef HAVE_READLINKAT
8633 327 : if (readlinkat_unavailable) {
8634 0 : argument_unavailable_error(NULL, "dir_fd");
8635 0 : return NULL;
8636 : }
8637 : #endif
8638 :
8639 327 : if (length < 0) {
8640 11 : return path_error(path);
8641 : }
8642 316 : buffer[length] = '\0';
8643 :
8644 316 : if (PyUnicode_Check(path->object))
8645 314 : 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 1309 : 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 1309 : int symlinkat_unavailable = 0;
8836 : #endif
8837 : #endif
8838 :
8839 1309 : 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 1309 : 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 1309 : Py_BEGIN_ALLOW_THREADS
8899 : #ifdef HAVE_SYMLINKAT
8900 1309 : 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 1308 : result = symlink(src->narrow, dst->narrow);
8909 1309 : Py_END_ALLOW_THREADS
8910 :
8911 : #ifdef HAVE_SYMLINKAT
8912 1309 : if (symlinkat_unavailable) {
8913 0 : argument_unavailable_error(NULL, "dir_fd");
8914 0 : return NULL;
8915 : }
8916 : #endif
8917 :
8918 1309 : if (result)
8919 0 : return path_error2(src, dst);
8920 : #endif
8921 :
8922 1309 : 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 32305 : 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 32305 : int async_err = 0;
9188 : #ifdef HAVE_OPENAT
9189 32305 : int openat_unavailable = 0;
9190 : #endif
9191 :
9192 : #ifdef O_CLOEXEC
9193 32305 : 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 32305 : flags |= O_CLOEXEC;
9202 : #endif
9203 :
9204 32305 : 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 32311 : Py_BEGIN_ALLOW_THREADS
9211 : #ifdef MS_WINDOWS
9212 : fd = _wopen(path->wide, flags, mode);
9213 : #else
9214 : #ifdef HAVE_OPENAT
9215 32311 : if (dir_fd != DEFAULT_DIR_FD) {
9216 : if (HAVE_OPENAT_RUNTIME) {
9217 10126 : 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 22185 : fd = open(path->narrow, flags, mode);
9226 : #endif /* !MS_WINDOWS */
9227 32311 : Py_END_ALLOW_THREADS
9228 32311 : } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9229 : _Py_END_SUPPRESS_IPH
9230 :
9231 : #ifdef HAVE_OPENAT
9232 32305 : if (openat_unavailable) {
9233 0 : argument_unavailable_error(NULL, "dir_fd");
9234 0 : return -1;
9235 : }
9236 : #endif
9237 :
9238 32305 : 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 31571 : if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
9246 0 : close(fd);
9247 0 : return -1;
9248 : }
9249 : #endif
9250 :
9251 31571 : 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 61929 : 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 61929 : Py_BEGIN_ALLOW_THREADS
9273 : _Py_BEGIN_SUPPRESS_IPH
9274 61929 : res = close(fd);
9275 : _Py_END_SUPPRESS_IPH
9276 61929 : Py_END_ALLOW_THREADS
9277 61929 : if (res < 0)
9278 25 : return posix_error();
9279 61904 : 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 1434 : os_dup_impl(PyObject *module, int fd)
9314 : /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
9315 : {
9316 1434 : 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 411 : os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
9331 : /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
9332 : {
9333 411 : 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 411 : 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 411 : 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 411 : if (inheritable || dup3_works == 0)
9397 : {
9398 : #endif
9399 410 : Py_BEGIN_ALLOW_THREADS
9400 410 : res = dup2(fd, fd2);
9401 410 : Py_END_ALLOW_THREADS
9402 410 : if (res < 0) {
9403 1 : posix_error();
9404 1 : return -1;
9405 : }
9406 :
9407 409 : 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 410 : 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 178712 : 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 178712 : if (length < 0) {
9521 0 : errno = EINVAL;
9522 0 : return posix_error();
9523 : }
9524 :
9525 178712 : length = Py_MIN(length, _PY_READ_MAX);
9526 :
9527 178712 : buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9528 178712 : if (buffer == NULL)
9529 0 : return NULL;
9530 :
9531 178712 : n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
9532 178710 : if (n == -1) {
9533 30 : Py_DECREF(buffer);
9534 30 : return NULL;
9535 : }
9536 :
9537 178680 : if (n != length)
9538 36880 : _PyBytes_Resize(&buffer, n);
9539 :
9540 178680 : 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 0 : 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 0 : 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 83228 : os_write_impl(PyObject *module, int fd, Py_buffer *data)
9823 : /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9824 : {
9825 83228 : 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 21997 : 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 21997 : 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 21997 : 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 21997 : 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 21997 : Py_BEGIN_ALLOW_THREADS
10042 21997 : 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 21997 : Py_END_ALLOW_THREADS
10051 21997 : } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10052 21997 : if (ret < 0)
10053 6 : return (!async_err) ? posix_error() : NULL;
10054 21991 : 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 1079470 : 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 1079470 : int async_err = 0;
10106 :
10107 : do {
10108 1079470 : Py_BEGIN_ALLOW_THREADS
10109 1079470 : res = FSTAT(fd, &st);
10110 1079470 : Py_END_ALLOW_THREADS
10111 1079470 : } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10112 1079470 : if (res != 0) {
10113 : #ifdef MS_WINDOWS
10114 : return PyErr_SetFromWindowsErr(0);
10115 : #else
10116 1048800 : return (!async_err) ? posix_error() : NULL;
10117 : #endif
10118 : }
10119 :
10120 30667 : 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 21079 : 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 21079 : Py_BEGIN_ALLOW_THREADS
10196 21079 : res = pipe2(fds, O_CLOEXEC);
10197 21079 : Py_END_ALLOW_THREADS
10198 :
10199 21079 : 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 21079 : if (res != 0)
10223 0 : return PyErr_SetFromErrno(PyExc_OSError);
10224 : #endif /* !MS_WINDOWS */
10225 21079 : 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 0 : } while (result != 0 && errno == EINTR &&
10625 10 : !(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 0 : } while (result != 0 && errno == EINTR &&
10677 3 : !(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 297 : 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 297 : int async_err = 0;
10757 :
10758 297 : if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10759 0 : return NULL;
10760 : }
10761 :
10762 : do {
10763 297 : Py_BEGIN_ALLOW_THREADS
10764 : _Py_BEGIN_SUPPRESS_IPH
10765 : #ifdef MS_WINDOWS
10766 : result = _chsize_s(fd, length);
10767 : #else
10768 297 : result = ftruncate(fd, length);
10769 : #endif
10770 : _Py_END_SUPPRESS_IPH
10771 297 : Py_END_ALLOW_THREADS
10772 4 : } while (result != 0 && errno == EINTR &&
10773 297 : !(async_err = PyErr_CheckSignals()));
10774 297 : if (result != 0)
10775 4 : return (!async_err) ? posix_error() : NULL;
10776 293 : 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 13698 : os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11022 : /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
11023 : {
11024 13698 : const char *name_string = PyBytes_AS_STRING(name);
11025 13698 : const char *value_string = PyBytes_AS_STRING(value);
11026 :
11027 13698 : if (strchr(name_string, '=') != NULL) {
11028 5 : PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11029 5 : return NULL;
11030 : }
11031 :
11032 13693 : if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11033 0 : return NULL;
11034 : }
11035 :
11036 13693 : if (setenv(name_string, value_string, 1)) {
11037 1 : return posix_error();
11038 : }
11039 13692 : 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 13313 : os_unsetenv_impl(PyObject *module, PyObject *name)
11073 : /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
11074 : {
11075 13313 : 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 13313 : int err = unsetenv(PyBytes_AS_STRING(name));
11082 13313 : if (err) {
11083 4 : return posix_error();
11084 : }
11085 : #endif
11086 :
11087 13309 : 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 2095 : os_strerror_impl(PyObject *module, int code)
11103 : /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
11104 : {
11105 2095 : char *message = strerror(code);
11106 2095 : if (message == NULL) {
11107 0 : PyErr_SetString(PyExc_ValueError,
11108 : "strerror() argument out of range");
11109 0 : return NULL;
11110 : }
11111 2095 : 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 4943 : os_WIFSTOPPED_impl(PyObject *module, int status)
11171 : /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
11172 : {
11173 : WAIT_TYPE wait_status;
11174 4943 : WAIT_STATUS_INT(wait_status) = status;
11175 4943 : 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 135 : _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
11291 135 : PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
11292 135 : PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
11293 135 : if (v == NULL)
11294 0 : return NULL;
11295 :
11296 : #if !defined(HAVE_LARGEFILE_SUPPORT)
11297 135 : PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11298 135 : PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11299 135 : PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
11300 135 : PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
11301 135 : PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
11302 135 : PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
11303 135 : PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
11304 135 : PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
11305 135 : PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11306 135 : 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 135 : PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
11331 : #endif
11332 135 : if (PyErr_Occurred()) {
11333 0 : Py_DECREF(v);
11334 0 : return NULL;
11335 : }
11336 :
11337 135 : 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 1 : } while (result != 0 && errno == EINTR &&
11364 2 : !(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 134 : 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 134 : Py_BEGIN_ALLOW_THREADS
11395 : #ifdef HAVE_FSTATVFS
11396 134 : if (path->fd != -1) {
11397 1 : result = fstatvfs(path->fd, &st);
11398 : }
11399 : else
11400 : #endif
11401 133 : result = statvfs(path->narrow, &st);
11402 134 : Py_END_ALLOW_THREADS
11403 :
11404 134 : if (result) {
11405 0 : return path_error(path);
11406 : }
11407 :
11408 134 : 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 2741 : conv_confname(PyObject *arg, int *valuep, struct constdef *table,
11483 : size_t tablesize)
11484 : {
11485 2741 : 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 2741 : size_t lo = 0;
11495 : size_t mid;
11496 2741 : size_t hi = tablesize;
11497 : int cmp;
11498 : const char *confname;
11499 2741 : if (!PyUnicode_Check(arg)) {
11500 0 : PyErr_SetString(PyExc_TypeError,
11501 : "configuration names must be strings or integers");
11502 0 : return 0;
11503 : }
11504 2741 : confname = PyUnicode_AsUTF8(arg);
11505 2741 : if (confname == NULL)
11506 0 : return 0;
11507 14505 : while (lo < hi) {
11508 14504 : mid = (lo + hi) / 2;
11509 14504 : cmp = strcmp(confname, table[mid].name);
11510 14504 : if (cmp < 0)
11511 8731 : hi = mid;
11512 5773 : else if (cmp > 0)
11513 3033 : lo = mid + 1;
11514 : else {
11515 2740 : *valuep = table[mid].value;
11516 2740 : 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 1227 : conv_confstr_confname(PyObject *arg, int *valuep)
11846 : {
11847 1227 : 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 1226 : os_confstr_impl(PyObject *module, int name)
11864 : /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11865 : {
11866 1226 : PyObject *result = NULL;
11867 : char buffer[255];
11868 : size_t len;
11869 :
11870 1226 : errno = 0;
11871 1226 : len = confstr(name, buffer, sizeof(buffer));
11872 1226 : 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 1226 : if (len >= sizeof(buffer)) {
11883 : size_t len2;
11884 0 : char *buf = PyMem_Malloc(len);
11885 0 : if (buf == NULL)
11886 0 : return PyErr_NoMemory();
11887 0 : len2 = confstr(name, buf, len);
11888 0 : assert(len == len2);
11889 0 : result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11890 0 : PyMem_Free(buf);
11891 : }
11892 : else
11893 1226 : result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11894 1226 : 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 1512 : conv_sysconf_confname(PyObject *arg, int *valuep)
12403 : {
12404 1512 : 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 1512 : os_sysconf_impl(PyObject *module, int name)
12420 : /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
12421 : {
12422 : long value;
12423 :
12424 1512 : errno = 0;
12425 1512 : value = sysconf(name);
12426 1512 : if (value == -1 && errno != 0)
12427 0 : posix_error();
12428 1512 : 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 1773480 : cmp_constdefs(const void *v1, const void *v2)
12445 : {
12446 1773480 : const struct constdef *c1 =
12447 : (const struct constdef *) v1;
12448 1773480 : const struct constdef *c2 =
12449 : (const struct constdef *) v2;
12450 :
12451 1773480 : return strcmp(c1->name, c2->name);
12452 : }
12453 :
12454 : static int
12455 9390 : setup_confname_table(struct constdef *table, size_t tablesize,
12456 : const char *tablename, PyObject *module)
12457 : {
12458 9390 : PyObject *d = NULL;
12459 : size_t i;
12460 :
12461 9390 : qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
12462 9390 : d = PyDict_New();
12463 9390 : if (d == NULL)
12464 0 : return -1;
12465 :
12466 575920 : for (i=0; i < tablesize; ++i) {
12467 566530 : PyObject *o = PyLong_FromLong(table[i].value);
12468 566530 : 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 566530 : Py_DECREF(o);
12474 : }
12475 9390 : return PyModule_AddObject(module, tablename, d);
12476 : }
12477 :
12478 : /* Return -1 on failure, 0 on success. */
12479 : static int
12480 3130 : setup_confname_tables(PyObject *module)
12481 : {
12482 : #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12483 3130 : 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 3130 : 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 3130 : 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 3130 : 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 707 : os_getloadavg_impl(PyObject *module)
12649 : /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
12650 : {
12651 : double loadavg[3];
12652 707 : if (getloadavg(loadavg, 3)!=3) {
12653 0 : PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
12654 0 : return NULL;
12655 : } else
12656 707 : 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 1 : os_device_encoding_impl(PyObject *module, int fd)
12673 : /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
12674 : {
12675 1 : 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 41 : 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 41 : PyObject *buffer = NULL;
12792 :
12793 41 : if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12794 0 : return NULL;
12795 :
12796 41 : if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12797 0 : return NULL;
12798 : }
12799 :
12800 41 : 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 47 : Py_ssize_t buffer_size = buffer_sizes[i];
12805 47 : if (!buffer_size) {
12806 0 : path_error(path);
12807 0 : return NULL;
12808 : }
12809 47 : buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12810 47 : if (!buffer)
12811 0 : return NULL;
12812 47 : ptr = PyBytes_AS_STRING(buffer);
12813 :
12814 47 : Py_BEGIN_ALLOW_THREADS;
12815 47 : if (path->fd >= 0)
12816 14 : result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12817 33 : else if (follow_symlinks)
12818 19 : result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12819 : else
12820 14 : result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12821 47 : Py_END_ALLOW_THREADS;
12822 :
12823 47 : 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 24 : if (result != buffer_size) {
12832 : /* Can only shrink. */
12833 24 : _PyBytes_Resize(&buffer, result);
12834 : }
12835 24 : break;
12836 : }
12837 :
12838 24 : 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 647 : 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 647 : if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12869 0 : return NULL;
12870 :
12871 647 : 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 647 : Py_BEGIN_ALLOW_THREADS;
12877 647 : if (path->fd > -1)
12878 216 : result = fsetxattr(path->fd, attribute->narrow,
12879 216 : value->buf, value->len, flags);
12880 431 : else if (follow_symlinks)
12881 219 : result = setxattr(path->narrow, attribute->narrow,
12882 219 : value->buf, value->len, flags);
12883 : else
12884 212 : result = lsetxattr(path->narrow, attribute->narrow,
12885 212 : value->buf, value->len, flags);
12886 647 : Py_END_ALLOW_THREADS;
12887 :
12888 647 : if (result) {
12889 19 : path_error(path);
12890 19 : return NULL;
12891 : }
12892 :
12893 628 : 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 11189 : 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 11189 : PyObject *result = NULL;
12967 : const char *name;
12968 11189 : char *buffer = NULL;
12969 :
12970 11189 : if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
12971 0 : goto exit;
12972 :
12973 11189 : if (PySys_Audit("os.listxattr", "(O)",
12974 11189 : path->object ? path->object : Py_None) < 0) {
12975 0 : return NULL;
12976 : }
12977 :
12978 11189 : name = path->narrow ? path->narrow : ".";
12979 :
12980 11189 : 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 11195 : Py_ssize_t buffer_size = buffer_sizes[i];
12985 11195 : if (!buffer_size) {
12986 : /* ERANGE */
12987 0 : path_error(path);
12988 0 : break;
12989 : }
12990 11195 : buffer = PyMem_Malloc(buffer_size);
12991 11195 : if (!buffer) {
12992 0 : PyErr_NoMemory();
12993 0 : break;
12994 : }
12995 :
12996 11195 : Py_BEGIN_ALLOW_THREADS;
12997 11195 : if (path->fd > -1)
12998 12 : length = flistxattr(path->fd, buffer, buffer_size);
12999 11183 : else if (follow_symlinks)
13000 11178 : length = listxattr(name, buffer, buffer_size);
13001 : else
13002 5 : length = llistxattr(name, buffer, buffer_size);
13003 11195 : Py_END_ALLOW_THREADS;
13004 :
13005 11195 : 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 11184 : result = PyList_New(0);
13016 11184 : if (!result) {
13017 0 : goto exit;
13018 : }
13019 :
13020 11184 : end = buffer + length;
13021 18576 : for (trace = start = buffer; trace != end; trace++) {
13022 7392 : if (!*trace) {
13023 : int error;
13024 624 : PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
13025 : trace - start);
13026 624 : if (!attribute) {
13027 0 : Py_DECREF(result);
13028 0 : result = NULL;
13029 0 : goto exit;
13030 : }
13031 624 : error = PyList_Append(result, attribute);
13032 624 : Py_DECREF(attribute);
13033 624 : if (error) {
13034 0 : Py_DECREF(result);
13035 0 : result = NULL;
13036 0 : goto exit;
13037 : }
13038 624 : start = trace + 1;
13039 : }
13040 : }
13041 11184 : break;
13042 : }
13043 11189 : exit:
13044 11189 : if (buffer)
13045 11189 : PyMem_Free(buffer);
13046 11189 : 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 168921 : 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 168921 : if (size < 0)
13068 1 : return PyErr_Format(PyExc_ValueError,
13069 : "negative argument not allowed");
13070 168920 : bytes = PyBytes_FromStringAndSize(NULL, size);
13071 168920 : if (bytes == NULL)
13072 0 : return NULL;
13073 :
13074 168920 : result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
13075 168920 : if (result == -1) {
13076 0 : Py_DECREF(bytes);
13077 0 : return NULL;
13078 : }
13079 168920 : 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 10553 : 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 10553 : if (ioctl(fd, TIOCGWINSZ, &w))
13239 10553 : return PyErr_SetFromErrno(PyExc_OSError);
13240 0 : columns = w.ws_col;
13241 0 : 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 0 : PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
13275 0 : termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
13276 0 : if (termsize == NULL)
13277 0 : return NULL;
13278 0 : PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
13279 0 : PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
13280 0 : if (PyErr_Occurred()) {
13281 0 : Py_DECREF(termsize);
13282 0 : return NULL;
13283 : }
13284 0 : 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 110 : os_cpu_count_impl(PyObject *module)
13301 : /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
13302 : {
13303 110 : 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 110 : 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 110 : if (ncpu >= 1)
13325 110 : 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 7 : 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 7 : blocking = _Py_get_blocking(fd);
13442 : _Py_END_SUPPRESS_IPH
13443 7 : 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 327 : 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 327 : result = _Py_set_blocking(fd, blocking);
13466 : _Py_END_SUPPRESS_IPH
13467 327 : if (result < 0)
13468 1 : return NULL;
13469 326 : 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 110745 : DirEntry_dealloc(DirEntry *entry)
13500 : {
13501 110745 : PyTypeObject *tp = Py_TYPE(entry);
13502 110745 : Py_XDECREF(entry->name);
13503 110745 : Py_XDECREF(entry->path);
13504 110745 : Py_XDECREF(entry->stat);
13505 110745 : Py_XDECREF(entry->lstat);
13506 110745 : freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13507 110745 : free_func(entry);
13508 110745 : Py_DECREF(tp);
13509 110745 : }
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 38764 : 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 38764 : if (self->d_type != DT_UNKNOWN)
13533 38764 : 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 20174 : 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 20174 : if (!PyUnicode_FSConverter(self->path, &ub))
13556 0 : return NULL;
13557 20174 : const char *path = PyBytes_AS_STRING(ub);
13558 20174 : if (self->dir_fd != DEFAULT_DIR_FD) {
13559 : #ifdef HAVE_FSTATAT
13560 : if (HAVE_FSTATAT_RUNTIME) {
13561 8257 : Py_BEGIN_ALLOW_THREADS
13562 8257 : result = fstatat(self->dir_fd, path, &st,
13563 : follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
13564 8257 : 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 11917 : Py_BEGIN_ALLOW_THREADS
13578 11917 : if (follow_symlinks) {
13579 794 : result = STAT(path, &st);
13580 : }
13581 : else {
13582 11123 : result = LSTAT(path, &st);
13583 : }
13584 11917 : Py_END_ALLOW_THREADS
13585 : }
13586 : #if defined(MS_WINDOWS)
13587 : PyMem_Free(path);
13588 : #else
13589 20174 : Py_DECREF(ub);
13590 : #endif
13591 :
13592 20174 : if (result != 0)
13593 2183 : return path_object_error(self->path);
13594 :
13595 17991 : return _pystat_fromstructstat(module, &st);
13596 : }
13597 :
13598 : static PyObject *
13599 17059 : DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
13600 : {
13601 17059 : if (!self->lstat) {
13602 17055 : PyObject *module = PyType_GetModule(defining_class);
13603 : #ifdef MS_WINDOWS
13604 : self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
13605 : #else /* POSIX */
13606 17055 : self->lstat = DirEntry_fetch_stat(module, self, 0);
13607 : #endif
13608 : }
13609 17059 : Py_XINCREF(self->lstat);
13610 17059 : 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 40818 : os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
13625 : int follow_symlinks)
13626 : /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
13627 : {
13628 40818 : if (!follow_symlinks) {
13629 5943 : return DirEntry_get_lstat(defining_class, self);
13630 : }
13631 :
13632 34875 : if (!self->stat) {
13633 14235 : int result = os_DirEntry_is_symlink_impl(self, defining_class);
13634 14235 : if (result == -1) {
13635 0 : return NULL;
13636 : }
13637 14235 : if (result) {
13638 3119 : PyObject *module = PyType_GetModule(defining_class);
13639 3119 : self->stat = DirEntry_fetch_stat(module, self, 1);
13640 : }
13641 : else {
13642 11116 : self->stat = DirEntry_get_lstat(defining_class, self);
13643 : }
13644 : }
13645 :
13646 34875 : Py_XINCREF(self->stat);
13647 34875 : return self->stat;
13648 : }
13649 :
13650 : /* Set exception and return -1 on error, 0 for False, 1 for True */
13651 : static int
13652 103445 : DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13653 : int follow_symlinks, unsigned short mode_bits)
13654 : {
13655 103445 : PyObject *stat = NULL;
13656 103445 : 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 103445 : is_symlink = self->d_type == DT_LNK;
13672 103445 : 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 103445 : if (need_stat) {
13677 : #endif
13678 3117 : stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
13679 3117 : 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 951 : _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
13689 951 : st_mode = PyObject_GetAttr(stat, state->st_mode);
13690 951 : if (!st_mode)
13691 0 : goto error;
13692 :
13693 951 : mode = PyLong_AsLong(st_mode);
13694 951 : if (mode == -1 && PyErr_Occurred())
13695 0 : goto error;
13696 951 : Py_CLEAR(st_mode);
13697 951 : Py_CLEAR(stat);
13698 951 : result = (mode & S_IFMT) == mode_bits;
13699 : #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13700 : }
13701 100328 : else if (is_symlink) {
13702 1199 : assert(mode_bits != S_IFLNK);
13703 1199 : result = 0;
13704 : }
13705 : else {
13706 99129 : 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 99129 : if (mode_bits == S_IFDIR)
13715 99122 : result = self->d_type == DT_DIR;
13716 : else
13717 7 : result = self->d_type == DT_REG;
13718 : #endif
13719 : }
13720 : #endif
13721 :
13722 101279 : 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 103432 : 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 103432 : 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 33273 : os_DirEntry___fspath___impl(DirEntry *self)
13819 : /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
13820 : {
13821 33273 : Py_INCREF(self->path);
13822 33273 : 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 62160 : 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 62160 : if (!path_narrow) { /* Default arg: "." */
13960 1 : path_narrow = ".";
13961 1 : path_len = 1;
13962 : }
13963 : else {
13964 62159 : path_len = strlen(path_narrow);
13965 : }
13966 :
13967 62160 : if (filename_len == -1)
13968 0 : filename_len = strlen(filename);
13969 :
13970 : /* The +1's are for the path separator and the NUL */
13971 62160 : size = path_len + 1 + filename_len + 1;
13972 62160 : result = PyMem_New(char, size);
13973 62160 : if (!result) {
13974 0 : PyErr_NoMemory();
13975 0 : return NULL;
13976 : }
13977 62160 : strcpy(result, path_narrow);
13978 62160 : if (path_len > 0 && result[path_len - 1] != '/')
13979 62070 : result[path_len++] = '/';
13980 62160 : strcpy(result + path_len, filename);
13981 62160 : return result;
13982 : }
13983 :
13984 : static PyObject *
13985 110745 : 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 110745 : PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13996 110745 : entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13997 110745 : if (!entry)
13998 0 : return NULL;
13999 110745 : entry->name = NULL;
14000 110745 : entry->path = NULL;
14001 110745 : entry->stat = NULL;
14002 110745 : entry->lstat = NULL;
14003 :
14004 110745 : if (path->fd != -1) {
14005 48585 : entry->dir_fd = path->fd;
14006 48585 : joined_path = NULL;
14007 : }
14008 : else {
14009 62160 : entry->dir_fd = DEFAULT_DIR_FD;
14010 62160 : joined_path = join_path_filename(path->narrow, name, name_len);
14011 62160 : if (!joined_path)
14012 0 : goto error;
14013 : }
14014 :
14015 110745 : if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
14016 102396 : entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
14017 102396 : if (joined_path)
14018 53811 : entry->path = PyUnicode_DecodeFSDefault(joined_path);
14019 : }
14020 : else {
14021 8349 : entry->name = PyBytes_FromStringAndSize(name, name_len);
14022 8349 : if (joined_path)
14023 8349 : entry->path = PyBytes_FromString(joined_path);
14024 : }
14025 110745 : PyMem_Free(joined_path);
14026 110745 : if (!entry->name)
14027 0 : goto error;
14028 :
14029 110745 : if (path->fd != -1) {
14030 48585 : entry->path = entry->name;
14031 48585 : Py_INCREF(entry->path);
14032 : }
14033 62160 : else if (!entry->path)
14034 0 : goto error;
14035 :
14036 : #ifdef HAVE_DIRENT_D_TYPE
14037 110745 : entry->d_type = d_type;
14038 : #endif
14039 110745 : entry->d_ino = d_ino;
14040 :
14041 110745 : 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 48335 : ScandirIterator_is_closed(ScandirIterator *iterator)
14136 : {
14137 48335 : return !iterator->dirp;
14138 : }
14139 :
14140 : static void
14141 92470 : ScandirIterator_closedir(ScandirIterator *iterator)
14142 : {
14143 92470 : DIR *dirp = iterator->dirp;
14144 :
14145 92470 : if (!dirp)
14146 44592 : return;
14147 :
14148 47878 : iterator->dirp = NULL;
14149 47878 : Py_BEGIN_ALLOW_THREADS
14150 : #ifdef HAVE_FDOPENDIR
14151 47878 : if (iterator->path.fd != -1)
14152 13280 : rewinddir(dirp);
14153 : #endif
14154 47878 : closedir(dirp);
14155 47878 : Py_END_ALLOW_THREADS
14156 47878 : return;
14157 : }
14158 :
14159 : static PyObject *
14160 158617 : 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 158617 : if (!iterator->dirp)
14169 1 : return NULL;
14170 :
14171 : while (1) {
14172 254368 : errno = 0;
14173 254368 : Py_BEGIN_ALLOW_THREADS
14174 254368 : direntp = readdir(iterator->dirp);
14175 254368 : Py_END_ALLOW_THREADS
14176 :
14177 254368 : if (!direntp) {
14178 : /* Error or no more files */
14179 47871 : if (errno != 0)
14180 0 : path_error(&iterator->path);
14181 47871 : break;
14182 : }
14183 :
14184 : /* Skip over . and .. */
14185 206497 : name_len = NAMLEN(direntp);
14186 255377 : is_dot = direntp->d_name[0] == '.' &&
14187 48880 : (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
14188 206497 : if (!is_dot) {
14189 110745 : PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14190 110745 : entry = DirEntry_from_posix_info(module,
14191 110745 : &iterator->path, direntp->d_name,
14192 : name_len, direntp->d_ino
14193 : #ifdef HAVE_DIRENT_D_TYPE
14194 110745 : , direntp->d_type
14195 : #endif
14196 : );
14197 110745 : if (!entry)
14198 0 : break;
14199 110745 : 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 47871 : ScandirIterator_closedir(iterator);
14207 47871 : 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 44593 : ScandirIterator_enter(PyObject *self, PyObject *args)
14221 : {
14222 44593 : Py_INCREF(self);
14223 44593 : return self;
14224 : }
14225 :
14226 : static PyObject *
14227 44593 : ScandirIterator_exit(ScandirIterator *self, PyObject *args)
14228 : {
14229 44593 : ScandirIterator_closedir(self);
14230 44593 : Py_RETURN_NONE;
14231 : }
14232 :
14233 : static void
14234 48335 : ScandirIterator_finalize(ScandirIterator *iterator)
14235 : {
14236 : PyObject *error_type, *error_value, *error_traceback;
14237 :
14238 : /* Save the current exception, if any. */
14239 48335 : PyErr_Fetch(&error_type, &error_value, &error_traceback);
14240 :
14241 48335 : 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 48335 : path_cleanup(&iterator->path);
14254 :
14255 : /* Restore the saved exception. */
14256 48335 : PyErr_Restore(error_type, error_value, error_traceback);
14257 48335 : }
14258 :
14259 : static void
14260 48335 : ScandirIterator_dealloc(ScandirIterator *iterator)
14261 : {
14262 48335 : PyTypeObject *tp = Py_TYPE(iterator);
14263 48335 : if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
14264 1 : return;
14265 :
14266 48334 : freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
14267 48334 : free_func(iterator);
14268 48334 : 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 48334 : 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 48334 : int fd = -1;
14323 : #endif
14324 : #endif
14325 :
14326 48334 : if (PySys_Audit("os.scandir", "O",
14327 48334 : path->object ? path->object : Py_None) < 0) {
14328 0 : return NULL;
14329 : }
14330 :
14331 48334 : PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
14332 48334 : iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
14333 48334 : if (!iterator)
14334 0 : return NULL;
14335 :
14336 : #ifdef MS_WINDOWS
14337 : iterator->handle = INVALID_HANDLE_VALUE;
14338 : #else
14339 48334 : iterator->dirp = NULL;
14340 : #endif
14341 :
14342 : /* Move the ownership to iterator->path */
14343 48334 : memcpy(&iterator->path, path, sizeof(path_t));
14344 48334 : 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 48334 : errno = 0;
14365 : #ifdef HAVE_FDOPENDIR
14366 48334 : if (iterator->path.fd != -1) {
14367 : if (HAVE_FDOPENDIR_RUNTIME) {
14368 : /* closedir() closes the FD, so we duplicate it */
14369 13284 : fd = _Py_dup(iterator->path.fd);
14370 13284 : if (fd == -1)
14371 0 : goto error;
14372 :
14373 13284 : Py_BEGIN_ALLOW_THREADS
14374 13284 : iterator->dirp = fdopendir(fd);
14375 13284 : 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 35050 : if (iterator->path.narrow)
14386 35049 : path_str = iterator->path.narrow;
14387 : else
14388 1 : path_str = ".";
14389 :
14390 35050 : Py_BEGIN_ALLOW_THREADS
14391 35050 : iterator->dirp = opendir(path_str);
14392 35050 : Py_END_ALLOW_THREADS
14393 : }
14394 :
14395 48334 : 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 47878 : 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 6097820 : PyOS_FSPath(PyObject *path)
14424 : {
14425 : /* For error message reasons, this function is manually inlined in
14426 : path_converter(). */
14427 6097820 : PyObject *func = NULL;
14428 6097820 : PyObject *path_repr = NULL;
14429 :
14430 6097820 : if (PyUnicode_Check(path) || PyBytes_Check(path)) {
14431 6072390 : Py_INCREF(path);
14432 6072390 : return path;
14433 : }
14434 :
14435 25427 : func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
14436 25427 : if (NULL == func) {
14437 90 : 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 25337 : path_repr = _PyObject_CallNoArgs(func);
14444 25337 : Py_DECREF(func);
14445 25337 : if (NULL == path_repr) {
14446 4 : return NULL;
14447 : }
14448 :
14449 25333 : 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 25328 : 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 3622600 : os_fspath_impl(PyObject *module, PyObject *path)
14475 : /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
14476 : {
14477 3622600 : 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 0 : 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 7294 : 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 7294 : int status = _PyLong_AsInt(status_obj);
14687 7294 : if (status == -1 && PyErr_Occurred()) {
14688 1 : return NULL;
14689 : }
14690 :
14691 : WAIT_TYPE wait_status;
14692 7293 : WAIT_STATUS_INT(wait_status) = status;
14693 : int exitcode;
14694 7293 : if (WIFEXITED(wait_status)) {
14695 6774 : exitcode = WEXITSTATUS(wait_status);
14696 : /* Sanity check to provide warranty on the function behavior.
14697 : It should not occur in practice */
14698 6774 : if (exitcode < 0) {
14699 0 : PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
14700 0 : return NULL;
14701 : }
14702 : }
14703 519 : else if (WIFSIGNALED(wait_status)) {
14704 519 : int signum = WTERMSIG(wait_status);
14705 : /* Sanity check to provide warranty on the function behavior.
14706 : It should not occurs in practice */
14707 519 : if (signum <= 0) {
14708 0 : PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
14709 0 : return NULL;
14710 : }
14711 519 : 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 7293 : 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 3130 : all_ins(PyObject *m)
14938 : {
14939 : #ifdef F_OK
14940 3130 : if (PyModule_AddIntMacro(m, F_OK)) return -1;
14941 : #endif
14942 : #ifdef R_OK
14943 3130 : if (PyModule_AddIntMacro(m, R_OK)) return -1;
14944 : #endif
14945 : #ifdef W_OK
14946 3130 : if (PyModule_AddIntMacro(m, W_OK)) return -1;
14947 : #endif
14948 : #ifdef X_OK
14949 3130 : if (PyModule_AddIntMacro(m, X_OK)) return -1;
14950 : #endif
14951 : #ifdef NGROUPS_MAX
14952 3130 : if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
14953 : #endif
14954 : #ifdef TMP_MAX
14955 3130 : if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
14956 : #endif
14957 : #ifdef WCONTINUED
14958 3130 : if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
14959 : #endif
14960 : #ifdef WNOHANG
14961 3130 : if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
14962 : #endif
14963 : #ifdef WUNTRACED
14964 3130 : if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
14965 : #endif
14966 : #ifdef O_RDONLY
14967 3130 : if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
14968 : #endif
14969 : #ifdef O_WRONLY
14970 3130 : if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
14971 : #endif
14972 : #ifdef O_RDWR
14973 3130 : if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
14974 : #endif
14975 : #ifdef O_NDELAY
14976 3130 : if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
14977 : #endif
14978 : #ifdef O_NONBLOCK
14979 3130 : if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
14980 : #endif
14981 : #ifdef O_APPEND
14982 3130 : if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
14983 : #endif
14984 : #ifdef O_DSYNC
14985 3130 : if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
14986 : #endif
14987 : #ifdef O_RSYNC
14988 3130 : if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
14989 : #endif
14990 : #ifdef O_SYNC
14991 3130 : if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
14992 : #endif
14993 : #ifdef O_NOCTTY
14994 3130 : if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
14995 : #endif
14996 : #ifdef O_CREAT
14997 3130 : if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
14998 : #endif
14999 : #ifdef O_EXCL
15000 3130 : if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
15001 : #endif
15002 : #ifdef O_TRUNC
15003 3130 : 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 3130 : 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 3130 : 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 3130 : if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
15039 : #endif
15040 : #ifdef PRIO_PROCESS
15041 3130 : if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
15042 : #endif
15043 : #ifdef PRIO_PGRP
15044 3130 : if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
15045 : #endif
15046 : #ifdef PRIO_USER
15047 3130 : if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
15048 : #endif
15049 : #ifdef O_CLOEXEC
15050 3130 : if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
15051 : #endif
15052 : #ifdef O_ACCMODE
15053 3130 : 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 3130 : 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 3130 : if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
15067 : #endif
15068 : #ifdef SEEK_DATA
15069 3130 : 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 3130 : if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
15100 : #endif
15101 : #ifdef O_DIRECT
15102 : /* Direct disk access. */
15103 3130 : if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
15104 : #endif
15105 : #ifdef O_DIRECTORY
15106 : /* Must be a directory. */
15107 3130 : if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
15108 : #endif
15109 : #ifdef O_NOFOLLOW
15110 : /* Do not follow links. */
15111 3130 : 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 3130 : if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
15123 : #endif
15124 :
15125 : /* These come from sysexits.h */
15126 : #ifdef EX_OK
15127 3130 : if (PyModule_AddIntMacro(m, EX_OK)) return -1;
15128 : #endif /* EX_OK */
15129 : #ifdef EX_USAGE
15130 3130 : if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
15131 : #endif /* EX_USAGE */
15132 : #ifdef EX_DATAERR
15133 3130 : if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
15134 : #endif /* EX_DATAERR */
15135 : #ifdef EX_NOINPUT
15136 3130 : if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
15137 : #endif /* EX_NOINPUT */
15138 : #ifdef EX_NOUSER
15139 3130 : if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
15140 : #endif /* EX_NOUSER */
15141 : #ifdef EX_NOHOST
15142 3130 : if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
15143 : #endif /* EX_NOHOST */
15144 : #ifdef EX_UNAVAILABLE
15145 3130 : if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
15146 : #endif /* EX_UNAVAILABLE */
15147 : #ifdef EX_SOFTWARE
15148 3130 : if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
15149 : #endif /* EX_SOFTWARE */
15150 : #ifdef EX_OSERR
15151 3130 : if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
15152 : #endif /* EX_OSERR */
15153 : #ifdef EX_OSFILE
15154 3130 : if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
15155 : #endif /* EX_OSFILE */
15156 : #ifdef EX_CANTCREAT
15157 3130 : if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
15158 : #endif /* EX_CANTCREAT */
15159 : #ifdef EX_IOERR
15160 3130 : if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
15161 : #endif /* EX_IOERR */
15162 : #ifdef EX_TEMPFAIL
15163 3130 : if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
15164 : #endif /* EX_TEMPFAIL */
15165 : #ifdef EX_PROTOCOL
15166 3130 : if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
15167 : #endif /* EX_PROTOCOL */
15168 : #ifdef EX_NOPERM
15169 3130 : if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
15170 : #endif /* EX_NOPERM */
15171 : #ifdef EX_CONFIG
15172 3130 : 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 3130 : if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
15181 : #endif /* ST_RDONLY */
15182 : #ifdef ST_NOSUID
15183 3130 : if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
15184 : #endif /* ST_NOSUID */
15185 :
15186 : /* GNU extensions */
15187 : #ifdef ST_NODEV
15188 3130 : if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
15189 : #endif /* ST_NODEV */
15190 : #ifdef ST_NOEXEC
15191 3130 : if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
15192 : #endif /* ST_NOEXEC */
15193 : #ifdef ST_SYNCHRONOUS
15194 3130 : if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
15195 : #endif /* ST_SYNCHRONOUS */
15196 : #ifdef ST_MANDLOCK
15197 3130 : if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
15198 : #endif /* ST_MANDLOCK */
15199 : #ifdef ST_WRITE
15200 3130 : if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
15201 : #endif /* ST_WRITE */
15202 : #ifdef ST_APPEND
15203 3130 : if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
15204 : #endif /* ST_APPEND */
15205 : #ifdef ST_NOATIME
15206 3130 : if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
15207 : #endif /* ST_NOATIME */
15208 : #ifdef ST_NODIRATIME
15209 3130 : if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
15210 : #endif /* ST_NODIRATIME */
15211 : #ifdef ST_RELATIME
15212 3130 : 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 3130 : if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
15233 : #endif
15234 : #ifdef POSIX_FADV_SEQUENTIAL
15235 3130 : if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
15236 : #endif
15237 : #ifdef POSIX_FADV_RANDOM
15238 3130 : if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
15239 : #endif
15240 : #ifdef POSIX_FADV_NOREUSE
15241 3130 : if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
15242 : #endif
15243 : #ifdef POSIX_FADV_WILLNEED
15244 3130 : if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
15245 : #endif
15246 : #ifdef POSIX_FADV_DONTNEED
15247 3130 : 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 3130 : if (PyModule_AddIntMacro(m, P_PID)) return -1;
15253 3130 : if (PyModule_AddIntMacro(m, P_PGID)) return -1;
15254 3130 : if (PyModule_AddIntMacro(m, P_ALL)) return -1;
15255 : #ifdef P_PIDFD
15256 3130 : 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 3130 : if (PyModule_AddIntMacro(m, WEXITED)) return -1;
15264 : #endif
15265 : #ifdef WNOWAIT
15266 3130 : if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
15267 : #endif
15268 : #ifdef WSTOPPED
15269 3130 : if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
15270 : #endif
15271 : #ifdef CLD_EXITED
15272 3130 : if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
15273 : #endif
15274 : #ifdef CLD_KILLED
15275 3130 : if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
15276 : #endif
15277 : #ifdef CLD_DUMPED
15278 3130 : if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
15279 : #endif
15280 : #ifdef CLD_TRAPPED
15281 3130 : if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
15282 : #endif
15283 : #ifdef CLD_STOPPED
15284 3130 : if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
15285 : #endif
15286 : #ifdef CLD_CONTINUED
15287 3130 : if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
15288 : #endif
15289 :
15290 : /* constants for lockf */
15291 : #ifdef F_LOCK
15292 3130 : if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
15293 : #endif
15294 : #ifdef F_TLOCK
15295 3130 : if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
15296 : #endif
15297 : #ifdef F_ULOCK
15298 3130 : if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
15299 : #endif
15300 : #ifdef F_TEST
15301 3130 : if (PyModule_AddIntMacro(m, F_TEST)) return -1;
15302 : #endif
15303 :
15304 : #ifdef RWF_DSYNC
15305 3130 : if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
15306 : #endif
15307 : #ifdef RWF_HIPRI
15308 3130 : if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
15309 : #endif
15310 : #ifdef RWF_SYNC
15311 3130 : if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
15312 : #endif
15313 : #ifdef RWF_NOWAIT
15314 3130 : if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
15315 : #endif
15316 : #ifdef RWF_APPEND
15317 3130 : 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 3130 : if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
15323 3130 : if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
15324 3130 : 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 3130 : if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
15330 3130 : if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
15331 3130 : 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 3130 : if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
15347 : #endif
15348 : #ifdef SCHED_FIFO
15349 3130 : if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
15350 : #endif
15351 : #ifdef SCHED_RR
15352 3130 : 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 3130 : if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
15359 : #endif
15360 : #ifdef SCHED_IDLE
15361 3130 : if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
15362 : #endif
15363 : #ifdef SCHED_RESET_ON_FORK
15364 3130 : 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 3130 : if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
15382 3130 : if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
15383 3130 : if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
15384 : #endif
15385 :
15386 : #if HAVE_DECL_RTLD_LAZY
15387 3130 : if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
15388 : #endif
15389 : #if HAVE_DECL_RTLD_NOW
15390 3130 : if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
15391 : #endif
15392 : #if HAVE_DECL_RTLD_GLOBAL
15393 3130 : if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
15394 : #endif
15395 : #if HAVE_DECL_RTLD_LOCAL
15396 3130 : if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
15397 : #endif
15398 : #if HAVE_DECL_RTLD_NODELETE
15399 3130 : if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
15400 : #endif
15401 : #if HAVE_DECL_RTLD_NOLOAD
15402 3130 : if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
15403 : #endif
15404 : #if HAVE_DECL_RTLD_DEEPBIND
15405 3130 : 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 3130 : if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
15413 3130 : if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
15414 : #endif
15415 : #ifdef HAVE_MEMFD_CREATE
15416 3130 : if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
15417 3130 : if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
15418 : #ifdef MFD_HUGETLB
15419 3130 : if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
15420 : #endif
15421 : #ifdef MFD_HUGE_SHIFT
15422 3130 : if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
15423 : #endif
15424 : #ifdef MFD_HUGE_MASK
15425 3130 : if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
15426 : #endif
15427 : #ifdef MFD_HUGE_64KB
15428 3130 : if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
15429 : #endif
15430 : #ifdef MFD_HUGE_512KB
15431 3130 : if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
15432 : #endif
15433 : #ifdef MFD_HUGE_1MB
15434 3130 : if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
15435 : #endif
15436 : #ifdef MFD_HUGE_2MB
15437 3130 : if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
15438 : #endif
15439 : #ifdef MFD_HUGE_8MB
15440 3130 : if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
15441 : #endif
15442 : #ifdef MFD_HUGE_16MB
15443 3130 : if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
15444 : #endif
15445 : #ifdef MFD_HUGE_32MB
15446 3130 : if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
15447 : #endif
15448 : #ifdef MFD_HUGE_256MB
15449 3130 : if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
15450 : #endif
15451 : #ifdef MFD_HUGE_512MB
15452 3130 : if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
15453 : #endif
15454 : #ifdef MFD_HUGE_1GB
15455 3130 : if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
15456 : #endif
15457 : #ifdef MFD_HUGE_2GB
15458 3130 : if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
15459 : #endif
15460 : #ifdef MFD_HUGE_16GB
15461 3130 : if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
15462 : #endif
15463 : #endif /* HAVE_MEMFD_CREATE */
15464 :
15465 : #ifdef HAVE_EVENTFD
15466 3130 : if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
15467 3130 : if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
15468 3130 : 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 3130 : 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 3130 : PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
15503 : #endif
15504 :
15505 : #ifdef HAVE_FACCESSAT
15506 3130 : PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
15507 : #endif
15508 :
15509 : #ifdef HAVE_FCHMODAT
15510 3130 : PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
15511 : #endif
15512 :
15513 : #ifdef HAVE_FCHOWNAT
15514 3130 : PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
15515 : #endif
15516 :
15517 : #ifdef HAVE_LINKAT
15518 3130 : PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
15519 : #endif
15520 :
15521 : #ifdef HAVE_FDOPENDIR
15522 3130 : PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
15523 : #endif
15524 :
15525 : #ifdef HAVE_MKDIRAT
15526 3130 : PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
15527 : #endif
15528 :
15529 : #ifdef HAVE_RENAMEAT
15530 3130 : PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
15531 : #endif
15532 :
15533 : #ifdef HAVE_UNLINKAT
15534 3130 : PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
15535 : #endif
15536 :
15537 : #ifdef HAVE_OPENAT
15538 3130 : PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
15539 : #endif
15540 :
15541 : #ifdef HAVE_READLINKAT
15542 3130 : PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
15543 : #endif
15544 :
15545 : #ifdef HAVE_SYMLINKAT
15546 3130 : PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
15547 : #endif
15548 :
15549 : #ifdef HAVE_FUTIMENS
15550 3130 : PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
15551 : #endif
15552 :
15553 : #ifdef HAVE_UTIMENSAT
15554 3130 : 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 3130 : posixmodule_exec(PyObject *m)
15703 : {
15704 3130 : _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 3130 : PyObject *v = convertenviron();
15725 3130 : Py_XINCREF(v);
15726 3130 : if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
15727 0 : return -1;
15728 3130 : Py_DECREF(v);
15729 :
15730 3130 : if (all_ins(m))
15731 0 : return -1;
15732 :
15733 3130 : if (setup_confname_tables(m))
15734 0 : return -1;
15735 :
15736 3130 : Py_INCREF(PyExc_OSError);
15737 3130 : PyModule_AddObject(m, "error", PyExc_OSError);
15738 :
15739 : #if defined(HAVE_WAITID) && !defined(__APPLE__)
15740 3130 : waitid_result_desc.name = MODNAME ".waitid_result";
15741 3130 : PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
15742 3130 : if (WaitidResultType == NULL) {
15743 0 : return -1;
15744 : }
15745 3130 : Py_INCREF(WaitidResultType);
15746 3130 : PyModule_AddObject(m, "waitid_result", WaitidResultType);
15747 3130 : state->WaitidResultType = WaitidResultType;
15748 : #endif
15749 :
15750 3130 : stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
15751 3130 : stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
15752 3130 : stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
15753 3130 : stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
15754 3130 : PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
15755 3130 : if (StatResultType == NULL) {
15756 0 : return -1;
15757 : }
15758 3130 : Py_INCREF(StatResultType);
15759 3130 : PyModule_AddObject(m, "stat_result", StatResultType);
15760 3130 : state->StatResultType = StatResultType;
15761 3130 : structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15762 3130 : ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
15763 :
15764 3130 : statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
15765 3130 : PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
15766 3130 : if (StatVFSResultType == NULL) {
15767 0 : return -1;
15768 : }
15769 3130 : Py_INCREF(StatVFSResultType);
15770 3130 : PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
15771 3130 : state->StatVFSResultType = StatVFSResultType;
15772 : #ifdef NEED_TICKS_PER_SECOND
15773 : # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15774 3130 : 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 3130 : sched_param_desc.name = MODNAME ".sched_param";
15784 3130 : PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
15785 3130 : if (SchedParamType == NULL) {
15786 0 : return -1;
15787 : }
15788 3130 : Py_INCREF(SchedParamType);
15789 3130 : PyModule_AddObject(m, "sched_param", SchedParamType);
15790 3130 : state->SchedParamType = SchedParamType;
15791 3130 : ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
15792 : #endif
15793 :
15794 : /* initialize TerminalSize_info */
15795 3130 : PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
15796 3130 : if (TerminalSizeType == NULL) {
15797 0 : return -1;
15798 : }
15799 3130 : Py_INCREF(TerminalSizeType);
15800 3130 : PyModule_AddObject(m, "terminal_size", TerminalSizeType);
15801 3130 : state->TerminalSizeType = TerminalSizeType;
15802 :
15803 : /* initialize scandir types */
15804 3130 : PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
15805 3130 : if (ScandirIteratorType == NULL) {
15806 0 : return -1;
15807 : }
15808 3130 : state->ScandirIteratorType = ScandirIteratorType;
15809 :
15810 3130 : PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
15811 3130 : if (DirEntryType == NULL) {
15812 0 : return -1;
15813 : }
15814 3130 : Py_INCREF(DirEntryType);
15815 3130 : PyModule_AddObject(m, "DirEntry", DirEntryType);
15816 3130 : state->DirEntryType = DirEntryType;
15817 :
15818 3130 : times_result_desc.name = MODNAME ".times_result";
15819 3130 : PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(×_result_desc);
15820 3130 : if (TimesResultType == NULL) {
15821 0 : return -1;
15822 : }
15823 3130 : Py_INCREF(TimesResultType);
15824 3130 : PyModule_AddObject(m, "times_result", TimesResultType);
15825 3130 : state->TimesResultType = TimesResultType;
15826 :
15827 3130 : PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
15828 3130 : if (UnameResultType == NULL) {
15829 0 : return -1;
15830 : }
15831 3130 : Py_INCREF(UnameResultType);
15832 3130 : PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
15833 3130 : state->UnameResultType = (PyObject *)UnameResultType;
15834 :
15835 3130 : if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
15836 0 : return -1;
15837 : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
15838 3130 : state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
15839 3130 : if (state->struct_rusage == NULL)
15840 0 : return -1;
15841 : #endif
15842 3130 : state->st_mode = PyUnicode_InternFromString("st_mode");
15843 3130 : if (state->st_mode == NULL)
15844 0 : return -1;
15845 :
15846 : /* suppress "function not used" warnings */
15847 : {
15848 : int ignored;
15849 3130 : fd_specified("", -1);
15850 3130 : follow_symlinks_specified("", 1);
15851 3130 : dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
15852 3130 : dir_fd_converter(Py_None, &ignored);
15853 3130 : 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 3130 : PyObject *list = PyList_New(0);
15861 3130 : if (!list) {
15862 0 : return -1;
15863 : }
15864 97030 : for (const struct have_function *trace = have_functions; trace->label; trace++) {
15865 : PyObject *unicode;
15866 93900 : if (trace->probe && !trace->probe()) continue;
15867 93900 : unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
15868 93900 : if (!unicode)
15869 0 : return -1;
15870 93900 : if (PyList_Append(list, unicode))
15871 0 : return -1;
15872 93900 : Py_DECREF(unicode);
15873 : }
15874 :
15875 3130 : PyModule_AddObject(m, "_have_functions", list);
15876 :
15877 3130 : 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 3130 : INITFUNC(void)
15900 : {
15901 3130 : return PyModuleDef_Init(&posixmodule);
15902 : }
15903 :
15904 : #ifdef __cplusplus
15905 : }
15906 : #endif
|