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 # include <lmcons.h> // UNLEN
20 # include "osdefs.h" // SEP
21 # define HAVE_SYMLINK
22 #endif
23
24 #ifdef __VXWORKS__
25 # include "pycore_bitutils.h" // _Py_popcount32()
26 #endif
27 #include "pycore_call.h" // _PyObject_CallNoArgs()
28 #include "pycore_ceval.h" // _PyEval_ReInitThreads()
29 #include "pycore_fileutils.h" // _Py_closerange()
30 #include "pycore_import.h" // _PyImport_ReInitLock()
31 #include "pycore_initconfig.h" // _PyStatus_EXCEPTION()
32 #include "pycore_moduleobject.h" // _PyModule_GetState()
33 #include "pycore_object.h" // _PyObject_LookupSpecial()
34 #include "pycore_pystate.h" // _PyInterpreterState_GET()
35 #include "pycore_signal.h" // Py_NSIG
36
37 #include "structmember.h" // PyMemberDef
38 #ifndef MS_WINDOWS
39 # include "posixmodule.h"
40 #else
41 # include "winreparse.h"
42 #endif
43
44 #if !defined(EX_OK) && defined(EXIT_SUCCESS)
45 # define EX_OK EXIT_SUCCESS
46 #endif
47
48 /* On android API level 21, 'AT_EACCESS' is not declared although
49 * HAVE_FACCESSAT is defined. */
50 #ifdef __ANDROID__
51 # undef HAVE_FACCESSAT
52 #endif
53
54 #include <stdio.h> // ctermid()
55 #include <stdlib.h> // system()
56
57 /*
58 * A number of APIs are available on macOS from a certain macOS version.
59 * To support building with a new SDK while deploying to older versions
60 * the availability test is split into two:
61 * - HAVE_<FUNCTION>: The configure check for compile time availability
62 * - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
63 *
64 * The latter is always true when not on macOS, or when using a compiler
65 * that does not support __has_builtin (older versions of Xcode).
66 *
67 * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
68 * if (HAVE_<FUNCTION>_RUNTIME) { ... }
69 *
70 * In mixing the test with other tests or using negations will result in compile
71 * errors.
72 */
73 #if defined(__APPLE__)
74
75 #if defined(__has_builtin)
76 #if __has_builtin(__builtin_available)
77 #define HAVE_BUILTIN_AVAILABLE 1
78 #endif
79 #endif
80
81 #ifdef HAVE_BUILTIN_AVAILABLE
82 # define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
83 # define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
84 # define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
85 # define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
86 # define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
87 # define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
88 # define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
89 # define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
90 # define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
91 # define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
92 # define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
93 # define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
94 # define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
95 # define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
96 # define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
97 # define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
98 # define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
99
100 # define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
101
102 #else /* Xcode 8 or earlier */
103
104 /* __builtin_available is not present in these compilers, but
105 * some of the symbols might be weak linked (10.10 SDK or later
106 * deploying on 10.9.
107 *
108 * Fall back to the older style of availability checking for
109 * symbols introduced in macOS 10.10.
110 */
111
112 # ifdef HAVE_FSTATAT
113 # define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
114 # endif
115
116 # ifdef HAVE_FACCESSAT
117 # define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
118 # endif
119
120 # ifdef HAVE_FCHMODAT
121 # define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
122 # endif
123
124 # ifdef HAVE_FCHOWNAT
125 # define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
126 # endif
127
128 # ifdef HAVE_LINKAT
129 # define HAVE_LINKAT_RUNTIME (linkat != NULL)
130 # endif
131
132 # ifdef HAVE_FDOPENDIR
133 # define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
134 # endif
135
136 # ifdef HAVE_MKDIRAT
137 # define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
138 # endif
139
140 # ifdef HAVE_RENAMEAT
141 # define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
142 # endif
143
144 # ifdef HAVE_UNLINKAT
145 # define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
146 # endif
147
148 # ifdef HAVE_OPENAT
149 # define HAVE_OPENAT_RUNTIME (openat != NULL)
150 # endif
151
152 # ifdef HAVE_READLINKAT
153 # define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
154 # endif
155
156 # ifdef HAVE_SYMLINKAT
157 # define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
158 # endif
159
160 # ifdef HAVE_UTIMENSAT
161 # define HAVE_UTIMENSAT_RUNTIME (utimensat != NULL)
162 # endif
163
164 # ifdef HAVE_FUTIMENS
165 # define HAVE_FUTIMENS_RUNTIME (futimens != NULL)
166 # endif
167
168 # ifdef HAVE_PWRITEV
169 # define HAVE_PWRITEV_RUNTIME (pwritev != NULL)
170 # endif
171
172 # ifdef HAVE_MKFIFOAT
173 # define HAVE_MKFIFOAT_RUNTIME (mkfifoat != NULL)
174 # endif
175
176 # ifdef HAVE_MKNODAT
177 # define HAVE_MKNODAT_RUNTIME (mknodat != NULL)
178 # endif
179
180 #endif
181
182 #ifdef HAVE_FUTIMESAT
183 /* Some of the logic for weak linking depends on this assertion */
184 # error "HAVE_FUTIMESAT unexpectedly defined"
185 #endif
186
187 #else
188 # define HAVE_FSTATAT_RUNTIME 1
189 # define HAVE_FACCESSAT_RUNTIME 1
190 # define HAVE_FCHMODAT_RUNTIME 1
191 # define HAVE_FCHOWNAT_RUNTIME 1
192 # define HAVE_LINKAT_RUNTIME 1
193 # define HAVE_FDOPENDIR_RUNTIME 1
194 # define HAVE_MKDIRAT_RUNTIME 1
195 # define HAVE_RENAMEAT_RUNTIME 1
196 # define HAVE_UNLINKAT_RUNTIME 1
197 # define HAVE_OPENAT_RUNTIME 1
198 # define HAVE_READLINKAT_RUNTIME 1
199 # define HAVE_SYMLINKAT_RUNTIME 1
200 # define HAVE_FUTIMENS_RUNTIME 1
201 # define HAVE_UTIMENSAT_RUNTIME 1
202 # define HAVE_PWRITEV_RUNTIME 1
203 # define HAVE_MKFIFOAT_RUNTIME 1
204 # define HAVE_MKNODAT_RUNTIME 1
205 #endif
206
207
208 #ifdef __cplusplus
209 extern "C" {
210 #endif
211
212 PyDoc_STRVAR(posix__doc__,
213 "This module provides access to operating system functionality that is\n\
214 standardized by the C Standard and the POSIX standard (a thinly\n\
215 disguised Unix interface). Refer to the library manual and\n\
216 corresponding Unix manual entries for more information on calls.");
217
218
219 #ifdef HAVE_SYS_UIO_H
220 # include <sys/uio.h>
221 #endif
222
223 #ifdef HAVE_SYS_SYSMACROS_H
224 /* GNU C Library: major(), minor(), makedev() */
225 # include <sys/sysmacros.h>
226 #endif
227
228 #ifdef HAVE_SYS_TYPES_H
229 # include <sys/types.h>
230 #endif /* HAVE_SYS_TYPES_H */
231
232 #ifdef HAVE_SYS_STAT_H
233 # include <sys/stat.h>
234 #endif /* HAVE_SYS_STAT_H */
235
236 #ifdef HAVE_SYS_WAIT_H
237 # include <sys/wait.h> // WNOHANG
238 #endif
239 #ifdef HAVE_LINUX_WAIT_H
240 # include <linux/wait.h> // P_PIDFD
241 #endif
242
243 #ifdef HAVE_SIGNAL_H
244 # include <signal.h>
245 #endif
246
247 #ifdef HAVE_FCNTL_H
248 # include <fcntl.h>
249 #endif
250
251 #ifdef HAVE_GRP_H
252 # include <grp.h>
253 #endif
254
255 #ifdef HAVE_SYSEXITS_H
256 # include <sysexits.h>
257 #endif
258
259 #ifdef HAVE_SYS_LOADAVG_H
260 # include <sys/loadavg.h>
261 #endif
262
263 #ifdef HAVE_SYS_SENDFILE_H
264 # include <sys/sendfile.h>
265 #endif
266
267 #if defined(__APPLE__)
268 # include <copyfile.h>
269 #endif
270
271 #ifdef HAVE_SCHED_H
272 # include <sched.h>
273 #endif
274
275 #ifdef HAVE_COPY_FILE_RANGE
276 # include <unistd.h>
277 #endif
278
279 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
280 # undef HAVE_SCHED_SETAFFINITY
281 #endif
282
283 #if defined(HAVE_SYS_XATTR_H) && defined(__linux__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
284 # define USE_XATTRS
285 # include <linux/limits.h> // Needed for XATTR_SIZE_MAX on musl libc.
286 #endif
287
288 #ifdef USE_XATTRS
289 # include <sys/xattr.h>
290 #endif
291
292 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
293 # ifdef HAVE_SYS_SOCKET_H
294 # include <sys/socket.h>
295 # endif
296 #endif
297
298 #ifdef HAVE_DLFCN_H
299 # include <dlfcn.h>
300 #endif
301
302 #ifdef __hpux
303 # include <sys/mpctl.h>
304 #endif
305
306 #if defined(__DragonFly__) || \
307 defined(__OpenBSD__) || \
308 defined(__FreeBSD__) || \
309 defined(__NetBSD__) || \
310 defined(__APPLE__)
311 # include <sys/sysctl.h>
312 #endif
313
314 #ifdef HAVE_LINUX_RANDOM_H
315 # include <linux/random.h>
316 #endif
317 #ifdef HAVE_GETRANDOM_SYSCALL
318 # include <sys/syscall.h>
319 #endif
320
321 #if defined(MS_WINDOWS)
322 # define TERMSIZE_USE_CONIO
323 #elif defined(HAVE_SYS_IOCTL_H)
324 # include <sys/ioctl.h>
325 # if defined(HAVE_TERMIOS_H)
326 # include <termios.h>
327 # endif
328 # if defined(TIOCGWINSZ)
329 # define TERMSIZE_USE_IOCTL
330 # endif
331 #endif /* MS_WINDOWS */
332
333 /* Various compilers have only certain posix functions */
334 /* XXX Gosh I wish these were all moved into pyconfig.h */
335 #if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */
336 # define HAVE_OPENDIR 1
337 # define HAVE_SYSTEM 1
338 # include <process.h>
339 #else
340 # ifdef _MSC_VER
341 /* Microsoft compiler */
342 # define HAVE_GETPPID 1
343 # define HAVE_GETLOGIN 1
344 # define HAVE_SPAWNV 1
345 # define HAVE_EXECV 1
346 # define HAVE_WSPAWNV 1
347 # define HAVE_WEXECV 1
348 # define HAVE_PIPE 1
349 # define HAVE_SYSTEM 1
350 # define HAVE_CWAIT 1
351 # define HAVE_FSYNC 1
352 # define fsync _commit
353 # endif /* _MSC_VER */
354 #endif /* ! __WATCOMC__ || __QNX__ */
355
356 /*[clinic input]
357 # one of the few times we lie about this name!
358 module os
359 [clinic start generated code]*/
360 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
361
362 #ifndef _MSC_VER
363
364 #if defined(__sgi)&&_COMPILER_VERSION>=700
365 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
366 (default) */
367 extern char *ctermid_r(char *);
368 #endif
369
370 #endif /* !_MSC_VER */
371
372 #if defined(__VXWORKS__)
373 # include <vxCpuLib.h>
374 # include <rtpLib.h>
375 # include <wait.h>
376 # include <taskLib.h>
377 # ifndef _P_WAIT
378 # define _P_WAIT 0
379 # define _P_NOWAIT 1
380 # define _P_NOWAITO 1
381 # endif
382 #endif /* __VXWORKS__ */
383
384 #ifdef HAVE_POSIX_SPAWN
385 # include <spawn.h>
386 #endif
387
388 #ifdef HAVE_UTIME_H
389 # include <utime.h>
390 #endif /* HAVE_UTIME_H */
391
392 #ifdef HAVE_SYS_UTIME_H
393 # include <sys/utime.h>
394 # define HAVE_UTIME_H /* pretend we do for the rest of this file */
395 #endif /* HAVE_SYS_UTIME_H */
396
397 #ifdef HAVE_SYS_TIMES_H
398 # include <sys/times.h>
399 #endif /* HAVE_SYS_TIMES_H */
400
401 #ifdef HAVE_SYS_PARAM_H
402 # include <sys/param.h>
403 #endif /* HAVE_SYS_PARAM_H */
404
405 #ifdef HAVE_SYS_UTSNAME_H
406 # include <sys/utsname.h>
407 #endif /* HAVE_SYS_UTSNAME_H */
408
409 #ifdef HAVE_DIRENT_H
410 # include <dirent.h>
411 # define NAMLEN(dirent) strlen((dirent)->d_name)
412 #else
413 # if defined(__WATCOMC__) && !defined(__QNX__)
414 # include <direct.h>
415 # define NAMLEN(dirent) strlen((dirent)->d_name)
416 # else
417 # define dirent direct
418 # define NAMLEN(dirent) (dirent)->d_namlen
419 # endif
420 # ifdef HAVE_SYS_NDIR_H
421 # include <sys/ndir.h>
422 # endif
423 # ifdef HAVE_SYS_DIR_H
424 # include <sys/dir.h>
425 # endif
426 # ifdef HAVE_NDIR_H
427 # include <ndir.h>
428 # endif
429 #endif
430
431 #ifdef _MSC_VER
432 # ifdef HAVE_DIRECT_H
433 # include <direct.h>
434 # endif
435 # ifdef HAVE_IO_H
436 # include <io.h>
437 # endif
438 # ifdef HAVE_PROCESS_H
439 # include <process.h>
440 # endif
441 # include <malloc.h>
442 #endif /* _MSC_VER */
443
444 #ifndef MAXPATHLEN
445 # if defined(PATH_MAX) && PATH_MAX > 1024
446 # define MAXPATHLEN PATH_MAX
447 # else
448 # define MAXPATHLEN 1024
449 # endif
450 #endif /* MAXPATHLEN */
451
452 #ifdef UNION_WAIT
453 /* Emulate some macros on systems that have a union instead of macros */
454 # ifndef WIFEXITED
455 # define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
456 # endif
457 # ifndef WEXITSTATUS
458 # define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
459 # endif
460 # ifndef WTERMSIG
461 # define WTERMSIG(u_wait) ((u_wait).w_termsig)
462 # endif
463 # define WAIT_TYPE union wait
464 # define WAIT_STATUS_INT(s) (s.w_status)
465 #else
466 /* !UNION_WAIT */
467 # define WAIT_TYPE int
468 # define WAIT_STATUS_INT(s) (s)
469 #endif /* UNION_WAIT */
470
471 /* Don't use the "_r" form if we don't need it (also, won't have a
472 prototype for it, at least on Solaris -- maybe others as well?). */
473 #if defined(HAVE_CTERMID_R)
474 # define USE_CTERMID_R
475 #endif
476
477 /* choose the appropriate stat and fstat functions and return structs */
478 #undef STAT
479 #undef FSTAT
480 #undef STRUCT_STAT
481 #ifdef MS_WINDOWS
482 # define STAT win32_stat
483 # define LSTAT win32_lstat
484 # define FSTAT _Py_fstat_noraise
485 # define STRUCT_STAT struct _Py_stat_struct
486 #else
487 # define STAT stat
488 # define LSTAT lstat
489 # define FSTAT fstat
490 # define STRUCT_STAT struct stat
491 #endif
492
493 #if defined(MAJOR_IN_MKDEV)
494 # include <sys/mkdev.h>
495 #else
496 # if defined(MAJOR_IN_SYSMACROS)
497 # include <sys/sysmacros.h>
498 # endif
499 # if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
500 # include <sys/mkdev.h>
501 # endif
502 #endif
503
504 #ifdef MS_WINDOWS
505 # define INITFUNC PyInit_nt
506 # define MODNAME "nt"
507 #else
508 # define INITFUNC PyInit_posix
509 # define MODNAME "posix"
510 #endif
511
512 #if defined(__sun)
513 /* Something to implement in autoconf, not present in autoconf 2.69 */
514 # define HAVE_STRUCT_STAT_ST_FSTYPE 1
515 #endif
516
517 /* memfd_create is either defined in sys/mman.h or sys/memfd.h
518 * linux/memfd.h defines additional flags
519 */
520 #ifdef HAVE_SYS_MMAN_H
521 # include <sys/mman.h>
522 #endif
523 #ifdef HAVE_SYS_MEMFD_H
524 # include <sys/memfd.h>
525 #endif
526 #ifdef HAVE_LINUX_MEMFD_H
527 # include <linux/memfd.h>
528 #endif
529
530 /* eventfd() */
531 #ifdef HAVE_SYS_EVENTFD_H
532 # include <sys/eventfd.h>
533 #endif
534
535 #ifdef _Py_MEMORY_SANITIZER
536 # include <sanitizer/msan_interface.h>
537 #endif
538
539 #ifdef HAVE_FORK
540 static void
run_at_forkers(PyObject * lst,int reverse)541 run_at_forkers(PyObject *lst, int reverse)
542 {
543 Py_ssize_t i;
544 PyObject *cpy;
545
546 if (lst != NULL) {
547 assert(PyList_CheckExact(lst));
548
549 /* Use a list copy in case register_at_fork() is called from
550 * one of the callbacks.
551 */
552 cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
553 if (cpy == NULL)
554 PyErr_WriteUnraisable(lst);
555 else {
556 if (reverse)
557 PyList_Reverse(cpy);
558 for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
559 PyObject *func, *res;
560 func = PyList_GET_ITEM(cpy, i);
561 res = _PyObject_CallNoArgs(func);
562 if (res == NULL)
563 PyErr_WriteUnraisable(func);
564 else
565 Py_DECREF(res);
566 }
567 Py_DECREF(cpy);
568 }
569 }
570 }
571
572 void
PyOS_BeforeFork(void)573 PyOS_BeforeFork(void)
574 {
575 run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1);
576
577 _PyImport_AcquireLock();
578 }
579
580 void
PyOS_AfterFork_Parent(void)581 PyOS_AfterFork_Parent(void)
582 {
583 if (_PyImport_ReleaseLock() <= 0)
584 Py_FatalError("failed releasing import lock after fork");
585
586 run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0);
587 }
588
589 void
PyOS_AfterFork_Child(void)590 PyOS_AfterFork_Child(void)
591 {
592 PyStatus status;
593 _PyRuntimeState *runtime = &_PyRuntime;
594
595 status = _PyGILState_Reinit(runtime);
596 if (_PyStatus_EXCEPTION(status)) {
597 goto fatal_error;
598 }
599
600 PyThreadState *tstate = _PyThreadState_GET();
601 _Py_EnsureTstateNotNULL(tstate);
602
603 #ifdef PY_HAVE_THREAD_NATIVE_ID
604 tstate->native_thread_id = PyThread_get_thread_native_id();
605 #endif
606
607 status = _PyEval_ReInitThreads(tstate);
608 if (_PyStatus_EXCEPTION(status)) {
609 goto fatal_error;
610 }
611
612 status = _PyImport_ReInitLock();
613 if (_PyStatus_EXCEPTION(status)) {
614 goto fatal_error;
615 }
616
617 _PySignal_AfterFork();
618
619 status = _PyRuntimeState_ReInitThreads(runtime);
620 if (_PyStatus_EXCEPTION(status)) {
621 goto fatal_error;
622 }
623
624 status = _PyInterpreterState_DeleteExceptMain(runtime);
625 if (_PyStatus_EXCEPTION(status)) {
626 goto fatal_error;
627 }
628 assert(_PyThreadState_GET() == tstate);
629
630 run_at_forkers(tstate->interp->after_forkers_child, 0);
631 return;
632
633 fatal_error:
634 Py_ExitStatusException(status);
635 }
636
637 static int
register_at_forker(PyObject ** lst,PyObject * func)638 register_at_forker(PyObject **lst, PyObject *func)
639 {
640 if (func == NULL) /* nothing to register? do nothing. */
641 return 0;
642 if (*lst == NULL) {
643 *lst = PyList_New(0);
644 if (*lst == NULL)
645 return -1;
646 }
647 return PyList_Append(*lst, func);
648 }
649 #endif /* HAVE_FORK */
650
651
652 /* Legacy wrapper */
653 void
PyOS_AfterFork(void)654 PyOS_AfterFork(void)
655 {
656 #ifdef HAVE_FORK
657 PyOS_AfterFork_Child();
658 #endif
659 }
660
661
662 #ifdef MS_WINDOWS
663 /* defined in fileutils.c */
664 void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
665 void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
666 ULONG, struct _Py_stat_struct *);
667 #endif
668
669
670 #ifndef MS_WINDOWS
671 PyObject *
_PyLong_FromUid(uid_t uid)672 _PyLong_FromUid(uid_t uid)
673 {
674 if (uid == (uid_t)-1)
675 return PyLong_FromLong(-1);
676 return PyLong_FromUnsignedLong(uid);
677 }
678
679 PyObject *
_PyLong_FromGid(gid_t gid)680 _PyLong_FromGid(gid_t gid)
681 {
682 if (gid == (gid_t)-1)
683 return PyLong_FromLong(-1);
684 return PyLong_FromUnsignedLong(gid);
685 }
686
687 int
_Py_Uid_Converter(PyObject * obj,uid_t * p)688 _Py_Uid_Converter(PyObject *obj, uid_t *p)
689 {
690 uid_t uid;
691 PyObject *index;
692 int overflow;
693 long result;
694 unsigned long uresult;
695
696 index = _PyNumber_Index(obj);
697 if (index == NULL) {
698 PyErr_Format(PyExc_TypeError,
699 "uid should be integer, not %.200s",
700 _PyType_Name(Py_TYPE(obj)));
701 return 0;
702 }
703
704 /*
705 * Handling uid_t is complicated for two reasons:
706 * * Although uid_t is (always?) unsigned, it still
707 * accepts -1.
708 * * We don't know its size in advance--it may be
709 * bigger than an int, or it may be smaller than
710 * a long.
711 *
712 * So a bit of defensive programming is in order.
713 * Start with interpreting the value passed
714 * in as a signed long and see if it works.
715 */
716
717 result = PyLong_AsLongAndOverflow(index, &overflow);
718
719 if (!overflow) {
720 uid = (uid_t)result;
721
722 if (result == -1) {
723 if (PyErr_Occurred())
724 goto fail;
725 /* It's a legitimate -1, we're done. */
726 goto success;
727 }
728
729 /* Any other negative number is disallowed. */
730 if (result < 0)
731 goto underflow;
732
733 /* Ensure the value wasn't truncated. */
734 if (sizeof(uid_t) < sizeof(long) &&
735 (long)uid != result)
736 goto underflow;
737 goto success;
738 }
739
740 if (overflow < 0)
741 goto underflow;
742
743 /*
744 * Okay, the value overflowed a signed long. If it
745 * fits in an *unsigned* long, it may still be okay,
746 * as uid_t may be unsigned long on this platform.
747 */
748 uresult = PyLong_AsUnsignedLong(index);
749 if (PyErr_Occurred()) {
750 if (PyErr_ExceptionMatches(PyExc_OverflowError))
751 goto overflow;
752 goto fail;
753 }
754
755 uid = (uid_t)uresult;
756
757 /*
758 * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
759 * but this value would get interpreted as (uid_t)-1 by chown
760 * and its siblings. That's not what the user meant! So we
761 * throw an overflow exception instead. (We already
762 * handled a real -1 with PyLong_AsLongAndOverflow() above.)
763 */
764 if (uid == (uid_t)-1)
765 goto overflow;
766
767 /* Ensure the value wasn't truncated. */
768 if (sizeof(uid_t) < sizeof(long) &&
769 (unsigned long)uid != uresult)
770 goto overflow;
771 /* fallthrough */
772
773 success:
774 Py_DECREF(index);
775 *p = uid;
776 return 1;
777
778 underflow:
779 PyErr_SetString(PyExc_OverflowError,
780 "uid is less than minimum");
781 goto fail;
782
783 overflow:
784 PyErr_SetString(PyExc_OverflowError,
785 "uid is greater than maximum");
786 /* fallthrough */
787
788 fail:
789 Py_DECREF(index);
790 return 0;
791 }
792
793 int
_Py_Gid_Converter(PyObject * obj,gid_t * p)794 _Py_Gid_Converter(PyObject *obj, gid_t *p)
795 {
796 gid_t gid;
797 PyObject *index;
798 int overflow;
799 long result;
800 unsigned long uresult;
801
802 index = _PyNumber_Index(obj);
803 if (index == NULL) {
804 PyErr_Format(PyExc_TypeError,
805 "gid should be integer, not %.200s",
806 _PyType_Name(Py_TYPE(obj)));
807 return 0;
808 }
809
810 /*
811 * Handling gid_t is complicated for two reasons:
812 * * Although gid_t is (always?) unsigned, it still
813 * accepts -1.
814 * * We don't know its size in advance--it may be
815 * bigger than an int, or it may be smaller than
816 * a long.
817 *
818 * So a bit of defensive programming is in order.
819 * Start with interpreting the value passed
820 * in as a signed long and see if it works.
821 */
822
823 result = PyLong_AsLongAndOverflow(index, &overflow);
824
825 if (!overflow) {
826 gid = (gid_t)result;
827
828 if (result == -1) {
829 if (PyErr_Occurred())
830 goto fail;
831 /* It's a legitimate -1, we're done. */
832 goto success;
833 }
834
835 /* Any other negative number is disallowed. */
836 if (result < 0) {
837 goto underflow;
838 }
839
840 /* Ensure the value wasn't truncated. */
841 if (sizeof(gid_t) < sizeof(long) &&
842 (long)gid != result)
843 goto underflow;
844 goto success;
845 }
846
847 if (overflow < 0)
848 goto underflow;
849
850 /*
851 * Okay, the value overflowed a signed long. If it
852 * fits in an *unsigned* long, it may still be okay,
853 * as gid_t may be unsigned long on this platform.
854 */
855 uresult = PyLong_AsUnsignedLong(index);
856 if (PyErr_Occurred()) {
857 if (PyErr_ExceptionMatches(PyExc_OverflowError))
858 goto overflow;
859 goto fail;
860 }
861
862 gid = (gid_t)uresult;
863
864 /*
865 * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
866 * but this value would get interpreted as (gid_t)-1 by chown
867 * and its siblings. That's not what the user meant! So we
868 * throw an overflow exception instead. (We already
869 * handled a real -1 with PyLong_AsLongAndOverflow() above.)
870 */
871 if (gid == (gid_t)-1)
872 goto overflow;
873
874 /* Ensure the value wasn't truncated. */
875 if (sizeof(gid_t) < sizeof(long) &&
876 (unsigned long)gid != uresult)
877 goto overflow;
878 /* fallthrough */
879
880 success:
881 Py_DECREF(index);
882 *p = gid;
883 return 1;
884
885 underflow:
886 PyErr_SetString(PyExc_OverflowError,
887 "gid is less than minimum");
888 goto fail;
889
890 overflow:
891 PyErr_SetString(PyExc_OverflowError,
892 "gid is greater than maximum");
893 /* fallthrough */
894
895 fail:
896 Py_DECREF(index);
897 return 0;
898 }
899 #endif /* MS_WINDOWS */
900
901
902 #define _PyLong_FromDev PyLong_FromLongLong
903
904
905 #if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
906 static int
_Py_Dev_Converter(PyObject * obj,void * p)907 _Py_Dev_Converter(PyObject *obj, void *p)
908 {
909 *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
910 if (PyErr_Occurred())
911 return 0;
912 return 1;
913 }
914 #endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
915
916
917 #ifdef AT_FDCWD
918 /*
919 * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
920 * without the int cast, the value gets interpreted as uint (4291925331),
921 * which doesn't play nicely with all the initializer lines in this file that
922 * look like this:
923 * int dir_fd = DEFAULT_DIR_FD;
924 */
925 #define DEFAULT_DIR_FD (int)AT_FDCWD
926 #else
927 #define DEFAULT_DIR_FD (-100)
928 #endif
929
930 static int
_fd_converter(PyObject * o,int * p)931 _fd_converter(PyObject *o, int *p)
932 {
933 int overflow;
934 long long_value;
935
936 PyObject *index = _PyNumber_Index(o);
937 if (index == NULL) {
938 return 0;
939 }
940
941 assert(PyLong_Check(index));
942 long_value = PyLong_AsLongAndOverflow(index, &overflow);
943 Py_DECREF(index);
944 assert(!PyErr_Occurred());
945 if (overflow > 0 || long_value > INT_MAX) {
946 PyErr_SetString(PyExc_OverflowError,
947 "fd is greater than maximum");
948 return 0;
949 }
950 if (overflow < 0 || long_value < INT_MIN) {
951 PyErr_SetString(PyExc_OverflowError,
952 "fd is less than minimum");
953 return 0;
954 }
955
956 *p = (int)long_value;
957 return 1;
958 }
959
960 static int
dir_fd_converter(PyObject * o,void * p)961 dir_fd_converter(PyObject *o, void *p)
962 {
963 if (o == Py_None) {
964 *(int *)p = DEFAULT_DIR_FD;
965 return 1;
966 }
967 else if (PyIndex_Check(o)) {
968 return _fd_converter(o, (int *)p);
969 }
970 else {
971 PyErr_Format(PyExc_TypeError,
972 "argument should be integer or None, not %.200s",
973 _PyType_Name(Py_TYPE(o)));
974 return 0;
975 }
976 }
977
978 typedef struct {
979 PyObject *billion;
980 PyObject *DirEntryType;
981 PyObject *ScandirIteratorType;
982 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
983 PyObject *SchedParamType;
984 #endif
985 PyObject *StatResultType;
986 PyObject *StatVFSResultType;
987 PyObject *TerminalSizeType;
988 PyObject *TimesResultType;
989 PyObject *UnameResultType;
990 #if defined(HAVE_WAITID) && !defined(__APPLE__)
991 PyObject *WaitidResultType;
992 #endif
993 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
994 PyObject *struct_rusage;
995 #endif
996 PyObject *st_mode;
997 } _posixstate;
998
999
1000 static inline _posixstate*
get_posix_state(PyObject * module)1001 get_posix_state(PyObject *module)
1002 {
1003 void *state = _PyModule_GetState(module);
1004 assert(state != NULL);
1005 return (_posixstate *)state;
1006 }
1007
1008 /*
1009 * A PyArg_ParseTuple "converter" function
1010 * that handles filesystem paths in the manner
1011 * preferred by the os module.
1012 *
1013 * path_converter accepts (Unicode) strings and their
1014 * subclasses, and bytes and their subclasses. What
1015 * it does with the argument depends on the platform:
1016 *
1017 * * On Windows, if we get a (Unicode) string we
1018 * extract the wchar_t * and return it; if we get
1019 * bytes we decode to wchar_t * and return that.
1020 *
1021 * * On all other platforms, strings are encoded
1022 * to bytes using PyUnicode_FSConverter, then we
1023 * extract the char * from the bytes object and
1024 * return that.
1025 *
1026 * path_converter also optionally accepts signed
1027 * integers (representing open file descriptors) instead
1028 * of path strings.
1029 *
1030 * Input fields:
1031 * path.nullable
1032 * If nonzero, the path is permitted to be None.
1033 * path.allow_fd
1034 * If nonzero, the path is permitted to be a file handle
1035 * (a signed int) instead of a string.
1036 * path.function_name
1037 * If non-NULL, path_converter will use that as the name
1038 * of the function in error messages.
1039 * (If path.function_name is NULL it omits the function name.)
1040 * path.argument_name
1041 * If non-NULL, path_converter will use that as the name
1042 * of the parameter in error messages.
1043 * (If path.argument_name is NULL it uses "path".)
1044 *
1045 * Output fields:
1046 * path.wide
1047 * Points to the path if it was expressed as Unicode
1048 * and was not encoded. (Only used on Windows.)
1049 * path.narrow
1050 * Points to the path if it was expressed as bytes,
1051 * or it was Unicode and was encoded to bytes. (On Windows,
1052 * is a non-zero integer if the path was expressed as bytes.
1053 * The type is deliberately incompatible to prevent misuse.)
1054 * path.fd
1055 * Contains a file descriptor if path.accept_fd was true
1056 * and the caller provided a signed integer instead of any
1057 * sort of string.
1058 *
1059 * WARNING: if your "path" parameter is optional, and is
1060 * unspecified, path_converter will never get called.
1061 * So if you set allow_fd, you *MUST* initialize path.fd = -1
1062 * yourself!
1063 * path.length
1064 * The length of the path in characters, if specified as
1065 * a string.
1066 * path.object
1067 * The original object passed in (if get a PathLike object,
1068 * the result of PyOS_FSPath() is treated as the original object).
1069 * Own a reference to the object.
1070 * path.cleanup
1071 * For internal use only. May point to a temporary object.
1072 * (Pay no attention to the man behind the curtain.)
1073 *
1074 * At most one of path.wide or path.narrow will be non-NULL.
1075 * If path was None and path.nullable was set,
1076 * or if path was an integer and path.allow_fd was set,
1077 * both path.wide and path.narrow will be NULL
1078 * and path.length will be 0.
1079 *
1080 * path_converter takes care to not write to the path_t
1081 * unless it's successful. However it must reset the
1082 * "cleanup" field each time it's called.
1083 *
1084 * Use as follows:
1085 * path_t path;
1086 * memset(&path, 0, sizeof(path));
1087 * PyArg_ParseTuple(args, "O&", path_converter, &path);
1088 * // ... use values from path ...
1089 * path_cleanup(&path);
1090 *
1091 * (Note that if PyArg_Parse fails you don't need to call
1092 * path_cleanup(). However it is safe to do so.)
1093 */
1094 typedef struct {
1095 const char *function_name;
1096 const char *argument_name;
1097 int nullable;
1098 int allow_fd;
1099 const wchar_t *wide;
1100 #ifdef MS_WINDOWS
1101 BOOL narrow;
1102 #else
1103 const char *narrow;
1104 #endif
1105 int fd;
1106 Py_ssize_t length;
1107 PyObject *object;
1108 PyObject *cleanup;
1109 } path_t;
1110
1111 #ifdef MS_WINDOWS
1112 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1113 {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
1114 #else
1115 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1116 {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
1117 #endif
1118
1119 static void
path_cleanup(path_t * path)1120 path_cleanup(path_t *path)
1121 {
1122 #if !USE_UNICODE_WCHAR_CACHE
1123 wchar_t *wide = (wchar_t *)path->wide;
1124 path->wide = NULL;
1125 PyMem_Free(wide);
1126 #endif /* USE_UNICODE_WCHAR_CACHE */
1127 Py_CLEAR(path->object);
1128 Py_CLEAR(path->cleanup);
1129 }
1130
1131 static int
path_converter(PyObject * o,void * p)1132 path_converter(PyObject *o, void *p)
1133 {
1134 path_t *path = (path_t *)p;
1135 PyObject *bytes = NULL;
1136 Py_ssize_t length = 0;
1137 int is_index, is_buffer, is_bytes, is_unicode;
1138 const char *narrow;
1139 #ifdef MS_WINDOWS
1140 PyObject *wo = NULL;
1141 wchar_t *wide = NULL;
1142 #endif
1143
1144 #define FORMAT_EXCEPTION(exc, fmt) \
1145 PyErr_Format(exc, "%s%s" fmt, \
1146 path->function_name ? path->function_name : "", \
1147 path->function_name ? ": " : "", \
1148 path->argument_name ? path->argument_name : "path")
1149
1150 /* Py_CLEANUP_SUPPORTED support */
1151 if (o == NULL) {
1152 path_cleanup(path);
1153 return 1;
1154 }
1155
1156 /* Ensure it's always safe to call path_cleanup(). */
1157 path->object = path->cleanup = NULL;
1158 /* path->object owns a reference to the original object */
1159 Py_INCREF(o);
1160
1161 if ((o == Py_None) && path->nullable) {
1162 path->wide = NULL;
1163 #ifdef MS_WINDOWS
1164 path->narrow = FALSE;
1165 #else
1166 path->narrow = NULL;
1167 #endif
1168 path->fd = -1;
1169 goto success_exit;
1170 }
1171
1172 /* Only call this here so that we don't treat the return value of
1173 os.fspath() as an fd or buffer. */
1174 is_index = path->allow_fd && PyIndex_Check(o);
1175 is_buffer = PyObject_CheckBuffer(o);
1176 is_bytes = PyBytes_Check(o);
1177 is_unicode = PyUnicode_Check(o);
1178
1179 if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
1180 /* Inline PyOS_FSPath() for better error messages. */
1181 PyObject *func, *res;
1182
1183 func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1184 if (NULL == func) {
1185 goto error_format;
1186 }
1187 res = _PyObject_CallNoArgs(func);
1188 Py_DECREF(func);
1189 if (NULL == res) {
1190 goto error_exit;
1191 }
1192 else if (PyUnicode_Check(res)) {
1193 is_unicode = 1;
1194 }
1195 else if (PyBytes_Check(res)) {
1196 is_bytes = 1;
1197 }
1198 else {
1199 PyErr_Format(PyExc_TypeError,
1200 "expected %.200s.__fspath__() to return str or bytes, "
1201 "not %.200s", _PyType_Name(Py_TYPE(o)),
1202 _PyType_Name(Py_TYPE(res)));
1203 Py_DECREF(res);
1204 goto error_exit;
1205 }
1206
1207 /* still owns a reference to the original object */
1208 Py_DECREF(o);
1209 o = res;
1210 }
1211
1212 if (is_unicode) {
1213 #ifdef MS_WINDOWS
1214 #if USE_UNICODE_WCHAR_CACHE
1215 _Py_COMP_DIAG_PUSH
1216 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1217 wide = PyUnicode_AsUnicodeAndSize(o, &length);
1218 _Py_COMP_DIAG_POP
1219 #else /* USE_UNICODE_WCHAR_CACHE */
1220 wide = PyUnicode_AsWideCharString(o, &length);
1221 #endif /* USE_UNICODE_WCHAR_CACHE */
1222 if (!wide) {
1223 goto error_exit;
1224 }
1225 if (length > 32767) {
1226 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1227 goto error_exit;
1228 }
1229 if (wcslen(wide) != length) {
1230 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1231 goto error_exit;
1232 }
1233
1234 path->wide = wide;
1235 path->narrow = FALSE;
1236 path->fd = -1;
1237 #if !USE_UNICODE_WCHAR_CACHE
1238 wide = NULL;
1239 #endif /* USE_UNICODE_WCHAR_CACHE */
1240 goto success_exit;
1241 #else
1242 if (!PyUnicode_FSConverter(o, &bytes)) {
1243 goto error_exit;
1244 }
1245 #endif
1246 }
1247 else if (is_bytes) {
1248 bytes = o;
1249 Py_INCREF(bytes);
1250 }
1251 else if (is_buffer) {
1252 /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1253 after removing support of non-bytes buffer objects. */
1254 if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
1255 "%s%s%s should be %s, not %.200s",
1256 path->function_name ? path->function_name : "",
1257 path->function_name ? ": " : "",
1258 path->argument_name ? path->argument_name : "path",
1259 path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1260 "integer or None" :
1261 path->allow_fd ? "string, bytes, os.PathLike or integer" :
1262 path->nullable ? "string, bytes, os.PathLike or None" :
1263 "string, bytes or os.PathLike",
1264 _PyType_Name(Py_TYPE(o)))) {
1265 goto error_exit;
1266 }
1267 bytes = PyBytes_FromObject(o);
1268 if (!bytes) {
1269 goto error_exit;
1270 }
1271 }
1272 else if (is_index) {
1273 if (!_fd_converter(o, &path->fd)) {
1274 goto error_exit;
1275 }
1276 path->wide = NULL;
1277 #ifdef MS_WINDOWS
1278 path->narrow = FALSE;
1279 #else
1280 path->narrow = NULL;
1281 #endif
1282 goto success_exit;
1283 }
1284 else {
1285 error_format:
1286 PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1287 path->function_name ? path->function_name : "",
1288 path->function_name ? ": " : "",
1289 path->argument_name ? path->argument_name : "path",
1290 path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1291 "integer or None" :
1292 path->allow_fd ? "string, bytes, os.PathLike or integer" :
1293 path->nullable ? "string, bytes, os.PathLike or None" :
1294 "string, bytes or os.PathLike",
1295 _PyType_Name(Py_TYPE(o)));
1296 goto error_exit;
1297 }
1298
1299 length = PyBytes_GET_SIZE(bytes);
1300 narrow = PyBytes_AS_STRING(bytes);
1301 if ((size_t)length != strlen(narrow)) {
1302 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1303 goto error_exit;
1304 }
1305
1306 #ifdef MS_WINDOWS
1307 wo = PyUnicode_DecodeFSDefaultAndSize(
1308 narrow,
1309 length
1310 );
1311 if (!wo) {
1312 goto error_exit;
1313 }
1314
1315 #if USE_UNICODE_WCHAR_CACHE
1316 _Py_COMP_DIAG_PUSH
1317 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1318 wide = PyUnicode_AsUnicodeAndSize(wo, &length);
1319 _Py_COMP_DIAG_POP
1320 #else /* USE_UNICODE_WCHAR_CACHE */
1321 wide = PyUnicode_AsWideCharString(wo, &length);
1322 Py_DECREF(wo);
1323 #endif /* USE_UNICODE_WCHAR_CACHE */
1324 if (!wide) {
1325 goto error_exit;
1326 }
1327 if (length > 32767) {
1328 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1329 goto error_exit;
1330 }
1331 if (wcslen(wide) != length) {
1332 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1333 goto error_exit;
1334 }
1335 path->wide = wide;
1336 path->narrow = TRUE;
1337 Py_DECREF(bytes);
1338 #if USE_UNICODE_WCHAR_CACHE
1339 path->cleanup = wo;
1340 #else /* USE_UNICODE_WCHAR_CACHE */
1341 wide = NULL;
1342 #endif /* USE_UNICODE_WCHAR_CACHE */
1343 #else
1344 path->wide = NULL;
1345 path->narrow = narrow;
1346 if (bytes == o) {
1347 /* Still a reference owned by path->object, don't have to
1348 worry about path->narrow is used after free. */
1349 Py_DECREF(bytes);
1350 }
1351 else {
1352 path->cleanup = bytes;
1353 }
1354 #endif
1355 path->fd = -1;
1356
1357 success_exit:
1358 path->length = length;
1359 path->object = o;
1360 return Py_CLEANUP_SUPPORTED;
1361
1362 error_exit:
1363 Py_XDECREF(o);
1364 Py_XDECREF(bytes);
1365 #ifdef MS_WINDOWS
1366 #if USE_UNICODE_WCHAR_CACHE
1367 Py_XDECREF(wo);
1368 #else /* USE_UNICODE_WCHAR_CACHE */
1369 PyMem_Free(wide);
1370 #endif /* USE_UNICODE_WCHAR_CACHE */
1371 #endif
1372 return 0;
1373 }
1374
1375 static void
argument_unavailable_error(const char * function_name,const char * argument_name)1376 argument_unavailable_error(const char *function_name, const char *argument_name)
1377 {
1378 PyErr_Format(PyExc_NotImplementedError,
1379 "%s%s%s unavailable on this platform",
1380 (function_name != NULL) ? function_name : "",
1381 (function_name != NULL) ? ": ": "",
1382 argument_name);
1383 }
1384
1385 static int
dir_fd_unavailable(PyObject * o,void * p)1386 dir_fd_unavailable(PyObject *o, void *p)
1387 {
1388 int dir_fd;
1389 if (!dir_fd_converter(o, &dir_fd))
1390 return 0;
1391 if (dir_fd != DEFAULT_DIR_FD) {
1392 argument_unavailable_error(NULL, "dir_fd");
1393 return 0;
1394 }
1395 *(int *)p = dir_fd;
1396 return 1;
1397 }
1398
1399 static int
fd_specified(const char * function_name,int fd)1400 fd_specified(const char *function_name, int fd)
1401 {
1402 if (fd == -1)
1403 return 0;
1404
1405 argument_unavailable_error(function_name, "fd");
1406 return 1;
1407 }
1408
1409 static int
follow_symlinks_specified(const char * function_name,int follow_symlinks)1410 follow_symlinks_specified(const char *function_name, int follow_symlinks)
1411 {
1412 if (follow_symlinks)
1413 return 0;
1414
1415 argument_unavailable_error(function_name, "follow_symlinks");
1416 return 1;
1417 }
1418
1419 static int
path_and_dir_fd_invalid(const char * function_name,path_t * path,int dir_fd)1420 path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1421 {
1422 if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1423 #ifndef MS_WINDOWS
1424 && !path->narrow
1425 #endif
1426 ) {
1427 PyErr_Format(PyExc_ValueError,
1428 "%s: can't specify dir_fd without matching path",
1429 function_name);
1430 return 1;
1431 }
1432 return 0;
1433 }
1434
1435 static int
dir_fd_and_fd_invalid(const char * function_name,int dir_fd,int fd)1436 dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1437 {
1438 if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1439 PyErr_Format(PyExc_ValueError,
1440 "%s: can't specify both dir_fd and fd",
1441 function_name);
1442 return 1;
1443 }
1444 return 0;
1445 }
1446
1447 static int
fd_and_follow_symlinks_invalid(const char * function_name,int fd,int follow_symlinks)1448 fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1449 int follow_symlinks)
1450 {
1451 if ((fd > 0) && (!follow_symlinks)) {
1452 PyErr_Format(PyExc_ValueError,
1453 "%s: cannot use fd and follow_symlinks together",
1454 function_name);
1455 return 1;
1456 }
1457 return 0;
1458 }
1459
1460 static int
dir_fd_and_follow_symlinks_invalid(const char * function_name,int dir_fd,int follow_symlinks)1461 dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1462 int follow_symlinks)
1463 {
1464 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1465 PyErr_Format(PyExc_ValueError,
1466 "%s: cannot use dir_fd and follow_symlinks together",
1467 function_name);
1468 return 1;
1469 }
1470 return 0;
1471 }
1472
1473 #ifdef MS_WINDOWS
1474 typedef long long Py_off_t;
1475 #else
1476 typedef off_t Py_off_t;
1477 #endif
1478
1479 static int
Py_off_t_converter(PyObject * arg,void * addr)1480 Py_off_t_converter(PyObject *arg, void *addr)
1481 {
1482 #ifdef HAVE_LARGEFILE_SUPPORT
1483 *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1484 #else
1485 *((Py_off_t *)addr) = PyLong_AsLong(arg);
1486 #endif
1487 if (PyErr_Occurred())
1488 return 0;
1489 return 1;
1490 }
1491
1492 static PyObject *
PyLong_FromPy_off_t(Py_off_t offset)1493 PyLong_FromPy_off_t(Py_off_t offset)
1494 {
1495 #ifdef HAVE_LARGEFILE_SUPPORT
1496 return PyLong_FromLongLong(offset);
1497 #else
1498 return PyLong_FromLong(offset);
1499 #endif
1500 }
1501
1502 #ifdef HAVE_SIGSET_T
1503 /* Convert an iterable of integers to a sigset.
1504 Return 1 on success, return 0 and raise an exception on error. */
1505 int
_Py_Sigset_Converter(PyObject * obj,void * addr)1506 _Py_Sigset_Converter(PyObject *obj, void *addr)
1507 {
1508 sigset_t *mask = (sigset_t *)addr;
1509 PyObject *iterator, *item;
1510 long signum;
1511 int overflow;
1512
1513 // The extra parens suppress the unreachable-code warning with clang on MacOS
1514 if (sigemptyset(mask) < (0)) {
1515 /* Probably only if mask == NULL. */
1516 PyErr_SetFromErrno(PyExc_OSError);
1517 return 0;
1518 }
1519
1520 iterator = PyObject_GetIter(obj);
1521 if (iterator == NULL) {
1522 return 0;
1523 }
1524
1525 while ((item = PyIter_Next(iterator)) != NULL) {
1526 signum = PyLong_AsLongAndOverflow(item, &overflow);
1527 Py_DECREF(item);
1528 if (signum <= 0 || signum >= Py_NSIG) {
1529 if (overflow || signum != -1 || !PyErr_Occurred()) {
1530 PyErr_Format(PyExc_ValueError,
1531 "signal number %ld out of range [1; %i]",
1532 signum, Py_NSIG - 1);
1533 }
1534 goto error;
1535 }
1536 if (sigaddset(mask, (int)signum)) {
1537 if (errno != EINVAL) {
1538 /* Probably impossible */
1539 PyErr_SetFromErrno(PyExc_OSError);
1540 goto error;
1541 }
1542 /* For backwards compatibility, allow idioms such as
1543 * `range(1, NSIG)` but warn about invalid signal numbers
1544 */
1545 const char msg[] =
1546 "invalid signal number %ld, please use valid_signals()";
1547 if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1548 goto error;
1549 }
1550 }
1551 }
1552 if (!PyErr_Occurred()) {
1553 Py_DECREF(iterator);
1554 return 1;
1555 }
1556
1557 error:
1558 Py_DECREF(iterator);
1559 return 0;
1560 }
1561 #endif /* HAVE_SIGSET_T */
1562
1563 #ifdef MS_WINDOWS
1564
1565 static int
win32_get_reparse_tag(HANDLE reparse_point_handle,ULONG * reparse_tag)1566 win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1567 {
1568 char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1569 _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1570 DWORD n_bytes_returned;
1571
1572 if (0 == DeviceIoControl(
1573 reparse_point_handle,
1574 FSCTL_GET_REPARSE_POINT,
1575 NULL, 0, /* in buffer */
1576 target_buffer, sizeof(target_buffer),
1577 &n_bytes_returned,
1578 NULL)) /* we're not using OVERLAPPED_IO */
1579 return FALSE;
1580
1581 if (reparse_tag)
1582 *reparse_tag = rdb->ReparseTag;
1583
1584 return TRUE;
1585 }
1586
1587 #endif /* MS_WINDOWS */
1588
1589 /* Return a dictionary corresponding to the POSIX environment table */
1590 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1591 /* On Darwin/MacOSX a shared library or framework has no access to
1592 ** environ directly, we must obtain it with _NSGetEnviron(). See also
1593 ** man environ(7).
1594 */
1595 #include <crt_externs.h>
1596 #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1597 extern char **environ;
1598 #endif /* !_MSC_VER */
1599
1600 static PyObject *
convertenviron(void)1601 convertenviron(void)
1602 {
1603 PyObject *d;
1604 #ifdef MS_WINDOWS
1605 wchar_t **e;
1606 #else
1607 char **e;
1608 #endif
1609
1610 d = PyDict_New();
1611 if (d == NULL)
1612 return NULL;
1613 #ifdef MS_WINDOWS
1614 /* _wenviron must be initialized in this way if the program is started
1615 through main() instead of wmain(). */
1616 _wgetenv(L"");
1617 e = _wenviron;
1618 #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1619 /* environ is not accessible as an extern in a shared object on OSX; use
1620 _NSGetEnviron to resolve it. The value changes if you add environment
1621 variables between calls to Py_Initialize, so don't cache the value. */
1622 e = *_NSGetEnviron();
1623 #else
1624 e = environ;
1625 #endif
1626 if (e == NULL)
1627 return d;
1628 for (; *e != NULL; e++) {
1629 PyObject *k;
1630 PyObject *v;
1631 #ifdef MS_WINDOWS
1632 const wchar_t *p = wcschr(*e, L'=');
1633 #else
1634 const char *p = strchr(*e, '=');
1635 #endif
1636 if (p == NULL)
1637 continue;
1638 #ifdef MS_WINDOWS
1639 k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1640 #else
1641 k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1642 #endif
1643 if (k == NULL) {
1644 Py_DECREF(d);
1645 return NULL;
1646 }
1647 #ifdef MS_WINDOWS
1648 v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1649 #else
1650 v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1651 #endif
1652 if (v == NULL) {
1653 Py_DECREF(k);
1654 Py_DECREF(d);
1655 return NULL;
1656 }
1657 if (PyDict_SetDefault(d, k, v) == NULL) {
1658 Py_DECREF(v);
1659 Py_DECREF(k);
1660 Py_DECREF(d);
1661 return NULL;
1662 }
1663 Py_DECREF(k);
1664 Py_DECREF(v);
1665 }
1666 return d;
1667 }
1668
1669 /* Set a POSIX-specific error from errno, and return NULL */
1670
1671 static PyObject *
posix_error(void)1672 posix_error(void)
1673 {
1674 return PyErr_SetFromErrno(PyExc_OSError);
1675 }
1676
1677 #ifdef MS_WINDOWS
1678 static PyObject *
win32_error(const char * function,const char * filename)1679 win32_error(const char* function, const char* filename)
1680 {
1681 /* XXX We should pass the function name along in the future.
1682 (winreg.c also wants to pass the function name.)
1683 This would however require an additional param to the
1684 Windows error object, which is non-trivial.
1685 */
1686 errno = GetLastError();
1687 if (filename)
1688 return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1689 else
1690 return PyErr_SetFromWindowsErr(errno);
1691 }
1692
1693 static PyObject *
win32_error_object_err(const char * function,PyObject * filename,DWORD err)1694 win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1695 {
1696 /* XXX - see win32_error for comments on 'function' */
1697 if (filename)
1698 return PyErr_SetExcFromWindowsErrWithFilenameObject(
1699 PyExc_OSError,
1700 err,
1701 filename);
1702 else
1703 return PyErr_SetFromWindowsErr(err);
1704 }
1705
1706 static PyObject *
win32_error_object(const char * function,PyObject * filename)1707 win32_error_object(const char* function, PyObject* filename)
1708 {
1709 errno = GetLastError();
1710 return win32_error_object_err(function, filename, errno);
1711 }
1712
1713 #endif /* MS_WINDOWS */
1714
1715 static PyObject *
posix_path_object_error(PyObject * path)1716 posix_path_object_error(PyObject *path)
1717 {
1718 return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1719 }
1720
1721 static PyObject *
path_object_error(PyObject * path)1722 path_object_error(PyObject *path)
1723 {
1724 #ifdef MS_WINDOWS
1725 return PyErr_SetExcFromWindowsErrWithFilenameObject(
1726 PyExc_OSError, 0, path);
1727 #else
1728 return posix_path_object_error(path);
1729 #endif
1730 }
1731
1732 static PyObject *
path_object_error2(PyObject * path,PyObject * path2)1733 path_object_error2(PyObject *path, PyObject *path2)
1734 {
1735 #ifdef MS_WINDOWS
1736 return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1737 PyExc_OSError, 0, path, path2);
1738 #else
1739 return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1740 #endif
1741 }
1742
1743 static PyObject *
path_error(path_t * path)1744 path_error(path_t *path)
1745 {
1746 return path_object_error(path->object);
1747 }
1748
1749 static PyObject *
posix_path_error(path_t * path)1750 posix_path_error(path_t *path)
1751 {
1752 return posix_path_object_error(path->object);
1753 }
1754
1755 static PyObject *
path_error2(path_t * path,path_t * path2)1756 path_error2(path_t *path, path_t *path2)
1757 {
1758 return path_object_error2(path->object, path2->object);
1759 }
1760
1761
1762 /* POSIX generic methods */
1763
1764 static PyObject *
posix_fildes_fd(int fd,int (* func)(int))1765 posix_fildes_fd(int fd, int (*func)(int))
1766 {
1767 int res;
1768 int async_err = 0;
1769
1770 do {
1771 Py_BEGIN_ALLOW_THREADS
1772 _Py_BEGIN_SUPPRESS_IPH
1773 res = (*func)(fd);
1774 _Py_END_SUPPRESS_IPH
1775 Py_END_ALLOW_THREADS
1776 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1777 if (res != 0)
1778 return (!async_err) ? posix_error() : NULL;
1779 Py_RETURN_NONE;
1780 }
1781
1782
1783 #ifdef MS_WINDOWS
1784 /* This is a reimplementation of the C library's chdir function,
1785 but one that produces Win32 errors instead of DOS error codes.
1786 chdir is essentially a wrapper around SetCurrentDirectory; however,
1787 it also needs to set "magic" environment variables indicating
1788 the per-drive current directory, which are of the form =<drive>: */
1789 static BOOL __stdcall
win32_wchdir(LPCWSTR path)1790 win32_wchdir(LPCWSTR path)
1791 {
1792 wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1793 int result;
1794 wchar_t env[4] = L"=x:";
1795
1796 if(!SetCurrentDirectoryW(path))
1797 return FALSE;
1798 result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1799 if (!result)
1800 return FALSE;
1801 if (result > Py_ARRAY_LENGTH(path_buf)) {
1802 new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1803 if (!new_path) {
1804 SetLastError(ERROR_OUTOFMEMORY);
1805 return FALSE;
1806 }
1807 result = GetCurrentDirectoryW(result, new_path);
1808 if (!result) {
1809 PyMem_RawFree(new_path);
1810 return FALSE;
1811 }
1812 }
1813 int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1814 wcsncmp(new_path, L"//", 2) == 0);
1815 if (!is_unc_like_path) {
1816 env[1] = new_path[0];
1817 result = SetEnvironmentVariableW(env, new_path);
1818 }
1819 if (new_path != path_buf)
1820 PyMem_RawFree(new_path);
1821 return result ? TRUE : FALSE;
1822 }
1823 #endif
1824
1825 #ifdef MS_WINDOWS
1826 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1827 - time stamps are restricted to second resolution
1828 - file modification times suffer from forth-and-back conversions between
1829 UTC and local time
1830 Therefore, we implement our own stat, based on the Win32 API directly.
1831 */
1832 #define HAVE_STAT_NSEC 1
1833 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1834 #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1835
1836 static void
find_data_to_file_info(WIN32_FIND_DATAW * pFileData,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1837 find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1838 BY_HANDLE_FILE_INFORMATION *info,
1839 ULONG *reparse_tag)
1840 {
1841 memset(info, 0, sizeof(*info));
1842 info->dwFileAttributes = pFileData->dwFileAttributes;
1843 info->ftCreationTime = pFileData->ftCreationTime;
1844 info->ftLastAccessTime = pFileData->ftLastAccessTime;
1845 info->ftLastWriteTime = pFileData->ftLastWriteTime;
1846 info->nFileSizeHigh = pFileData->nFileSizeHigh;
1847 info->nFileSizeLow = pFileData->nFileSizeLow;
1848 /* info->nNumberOfLinks = 1; */
1849 if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1850 *reparse_tag = pFileData->dwReserved0;
1851 else
1852 *reparse_tag = 0;
1853 }
1854
1855 static BOOL
attributes_from_dir(LPCWSTR pszFile,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1856 attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1857 {
1858 HANDLE hFindFile;
1859 WIN32_FIND_DATAW FileData;
1860 LPCWSTR filename = pszFile;
1861 size_t n = wcslen(pszFile);
1862 if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
1863 // cannot use PyMem_Malloc here because we do not hold the GIL
1864 filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
1865 wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
1866 while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
1867 ((LPWSTR)filename)[n] = L'\0';
1868 }
1869 if (!n || (n == 1 && filename[1] == L':')) {
1870 // Nothing left to query
1871 free((void *)filename);
1872 return FALSE;
1873 }
1874 }
1875 hFindFile = FindFirstFileW(filename, &FileData);
1876 if (pszFile != filename) {
1877 free((void *)filename);
1878 }
1879 if (hFindFile == INVALID_HANDLE_VALUE) {
1880 return FALSE;
1881 }
1882 FindClose(hFindFile);
1883 find_data_to_file_info(&FileData, info, reparse_tag);
1884 return TRUE;
1885 }
1886
1887 static int
win32_xstat_impl(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1888 win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1889 BOOL traverse)
1890 {
1891 HANDLE hFile;
1892 BY_HANDLE_FILE_INFORMATION fileInfo;
1893 FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1894 DWORD fileType, error;
1895 BOOL isUnhandledTag = FALSE;
1896 int retval = 0;
1897
1898 DWORD access = FILE_READ_ATTRIBUTES;
1899 DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1900 if (!traverse) {
1901 flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1902 }
1903
1904 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1905 if (hFile == INVALID_HANDLE_VALUE) {
1906 /* Either the path doesn't exist, or the caller lacks access. */
1907 error = GetLastError();
1908 switch (error) {
1909 case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */
1910 case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1911 /* Try reading the parent directory. */
1912 if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1913 /* Cannot read the parent directory. */
1914 switch (GetLastError()) {
1915 case ERROR_FILE_NOT_FOUND: /* File cannot be found */
1916 case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
1917 case ERROR_NOT_READY: /* Drive exists but unavailable */
1918 case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
1919 break;
1920 /* Restore the error from CreateFileW(). */
1921 default:
1922 SetLastError(error);
1923 }
1924
1925 return -1;
1926 }
1927 if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1928 if (traverse ||
1929 !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1930 /* The stat call has to traverse but cannot, so fail. */
1931 SetLastError(error);
1932 return -1;
1933 }
1934 }
1935 break;
1936
1937 case ERROR_INVALID_PARAMETER:
1938 /* \\.\con requires read or write access. */
1939 hFile = CreateFileW(path, access | GENERIC_READ,
1940 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1941 OPEN_EXISTING, flags, NULL);
1942 if (hFile == INVALID_HANDLE_VALUE) {
1943 SetLastError(error);
1944 return -1;
1945 }
1946 break;
1947
1948 case ERROR_CANT_ACCESS_FILE:
1949 /* bpo37834: open unhandled reparse points if traverse fails. */
1950 if (traverse) {
1951 traverse = FALSE;
1952 isUnhandledTag = TRUE;
1953 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1954 flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1955 }
1956 if (hFile == INVALID_HANDLE_VALUE) {
1957 SetLastError(error);
1958 return -1;
1959 }
1960 break;
1961
1962 default:
1963 return -1;
1964 }
1965 }
1966
1967 if (hFile != INVALID_HANDLE_VALUE) {
1968 /* Handle types other than files on disk. */
1969 fileType = GetFileType(hFile);
1970 if (fileType != FILE_TYPE_DISK) {
1971 if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1972 retval = -1;
1973 goto cleanup;
1974 }
1975 DWORD fileAttributes = GetFileAttributesW(path);
1976 memset(result, 0, sizeof(*result));
1977 if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1978 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1979 /* \\.\pipe\ or \\.\mailslot\ */
1980 result->st_mode = _S_IFDIR;
1981 } else if (fileType == FILE_TYPE_CHAR) {
1982 /* \\.\nul */
1983 result->st_mode = _S_IFCHR;
1984 } else if (fileType == FILE_TYPE_PIPE) {
1985 /* \\.\pipe\spam */
1986 result->st_mode = _S_IFIFO;
1987 }
1988 /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1989 goto cleanup;
1990 }
1991
1992 /* Query the reparse tag, and traverse a non-link. */
1993 if (!traverse) {
1994 if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
1995 &tagInfo, sizeof(tagInfo))) {
1996 /* Allow devices that do not support FileAttributeTagInfo. */
1997 switch (GetLastError()) {
1998 case ERROR_INVALID_PARAMETER:
1999 case ERROR_INVALID_FUNCTION:
2000 case ERROR_NOT_SUPPORTED:
2001 tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2002 tagInfo.ReparseTag = 0;
2003 break;
2004 default:
2005 retval = -1;
2006 goto cleanup;
2007 }
2008 } else if (tagInfo.FileAttributes &
2009 FILE_ATTRIBUTE_REPARSE_POINT) {
2010 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2011 if (isUnhandledTag) {
2012 /* Traversing previously failed for either this link
2013 or its target. */
2014 SetLastError(ERROR_CANT_ACCESS_FILE);
2015 retval = -1;
2016 goto cleanup;
2017 }
2018 /* Traverse a non-link, but not if traversing already failed
2019 for an unhandled tag. */
2020 } else if (!isUnhandledTag) {
2021 CloseHandle(hFile);
2022 return win32_xstat_impl(path, result, TRUE);
2023 }
2024 }
2025 }
2026
2027 if (!GetFileInformationByHandle(hFile, &fileInfo)) {
2028 switch (GetLastError()) {
2029 case ERROR_INVALID_PARAMETER:
2030 case ERROR_INVALID_FUNCTION:
2031 case ERROR_NOT_SUPPORTED:
2032 /* Volumes and physical disks are block devices, e.g.
2033 \\.\C: and \\.\PhysicalDrive0. */
2034 memset(result, 0, sizeof(*result));
2035 result->st_mode = 0x6000; /* S_IFBLK */
2036 goto cleanup;
2037 }
2038 retval = -1;
2039 goto cleanup;
2040 }
2041 }
2042
2043 _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
2044
2045 if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
2046 /* Fix the file execute permissions. This hack sets S_IEXEC if
2047 the filename has an extension that is commonly used by files
2048 that CreateProcessW can execute. A real implementation calls
2049 GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2050 AccessCheck to check for generic read, write, and execute
2051 access. */
2052 const wchar_t *fileExtension = wcsrchr(path, '.');
2053 if (fileExtension) {
2054 if (_wcsicmp(fileExtension, L".exe") == 0 ||
2055 _wcsicmp(fileExtension, L".bat") == 0 ||
2056 _wcsicmp(fileExtension, L".cmd") == 0 ||
2057 _wcsicmp(fileExtension, L".com") == 0) {
2058 result->st_mode |= 0111;
2059 }
2060 }
2061 }
2062
2063 cleanup:
2064 if (hFile != INVALID_HANDLE_VALUE) {
2065 /* Preserve last error if we are failing */
2066 error = retval ? GetLastError() : 0;
2067 if (!CloseHandle(hFile)) {
2068 retval = -1;
2069 } else if (retval) {
2070 /* Restore last error */
2071 SetLastError(error);
2072 }
2073 }
2074
2075 return retval;
2076 }
2077
2078 static int
win32_xstat(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)2079 win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2080 {
2081 /* Protocol violation: we explicitly clear errno, instead of
2082 setting it to a POSIX error. Callers should use GetLastError. */
2083 int code = win32_xstat_impl(path, result, traverse);
2084 errno = 0;
2085 return code;
2086 }
2087 /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2088
2089 In Posix, stat automatically traverses symlinks and returns the stat
2090 structure for the target. In Windows, the equivalent GetFileAttributes by
2091 default does not traverse symlinks and instead returns attributes for
2092 the symlink.
2093
2094 Instead, we will open the file (which *does* traverse symlinks by default)
2095 and GetFileInformationByHandle(). */
2096
2097 static int
win32_lstat(const wchar_t * path,struct _Py_stat_struct * result)2098 win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2099 {
2100 return win32_xstat(path, result, FALSE);
2101 }
2102
2103 static int
win32_stat(const wchar_t * path,struct _Py_stat_struct * result)2104 win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2105 {
2106 return win32_xstat(path, result, TRUE);
2107 }
2108
2109 #endif /* MS_WINDOWS */
2110
2111 PyDoc_STRVAR(stat_result__doc__,
2112 "stat_result: Result from stat, fstat, or lstat.\n\n\
2113 This object may be accessed either as a tuple of\n\
2114 (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2115 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2116 \n\
2117 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2118 or st_flags, they are available as attributes only.\n\
2119 \n\
2120 See os.stat for more information.");
2121
2122 static PyStructSequence_Field stat_result_fields[] = {
2123 {"st_mode", "protection bits"},
2124 {"st_ino", "inode"},
2125 {"st_dev", "device"},
2126 {"st_nlink", "number of hard links"},
2127 {"st_uid", "user ID of owner"},
2128 {"st_gid", "group ID of owner"},
2129 {"st_size", "total size, in bytes"},
2130 /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2131 {NULL, "integer time of last access"},
2132 {NULL, "integer time of last modification"},
2133 {NULL, "integer time of last change"},
2134 {"st_atime", "time of last access"},
2135 {"st_mtime", "time of last modification"},
2136 {"st_ctime", "time of last change"},
2137 {"st_atime_ns", "time of last access in nanoseconds"},
2138 {"st_mtime_ns", "time of last modification in nanoseconds"},
2139 {"st_ctime_ns", "time of last change in nanoseconds"},
2140 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2141 {"st_blksize", "blocksize for filesystem I/O"},
2142 #endif
2143 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2144 {"st_blocks", "number of blocks allocated"},
2145 #endif
2146 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2147 {"st_rdev", "device type (if inode device)"},
2148 #endif
2149 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2150 {"st_flags", "user defined flags for file"},
2151 #endif
2152 #ifdef HAVE_STRUCT_STAT_ST_GEN
2153 {"st_gen", "generation number"},
2154 #endif
2155 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2156 {"st_birthtime", "time of creation"},
2157 #endif
2158 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2159 {"st_file_attributes", "Windows file attribute bits"},
2160 #endif
2161 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2162 {"st_fstype", "Type of filesystem"},
2163 #endif
2164 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2165 {"st_reparse_tag", "Windows reparse tag"},
2166 #endif
2167 {0}
2168 };
2169
2170 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2171 #define ST_BLKSIZE_IDX 16
2172 #else
2173 #define ST_BLKSIZE_IDX 15
2174 #endif
2175
2176 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2177 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2178 #else
2179 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2180 #endif
2181
2182 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2183 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2184 #else
2185 #define ST_RDEV_IDX ST_BLOCKS_IDX
2186 #endif
2187
2188 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2189 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2190 #else
2191 #define ST_FLAGS_IDX ST_RDEV_IDX
2192 #endif
2193
2194 #ifdef HAVE_STRUCT_STAT_ST_GEN
2195 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
2196 #else
2197 #define ST_GEN_IDX ST_FLAGS_IDX
2198 #endif
2199
2200 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2201 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2202 #else
2203 #define ST_BIRTHTIME_IDX ST_GEN_IDX
2204 #endif
2205
2206 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2207 #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
2208 #else
2209 #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
2210 #endif
2211
2212 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2213 #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2214 #else
2215 #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2216 #endif
2217
2218 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2219 #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2220 #else
2221 #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2222 #endif
2223
2224 static PyStructSequence_Desc stat_result_desc = {
2225 "stat_result", /* name */
2226 stat_result__doc__, /* doc */
2227 stat_result_fields,
2228 10
2229 };
2230
2231 PyDoc_STRVAR(statvfs_result__doc__,
2232 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
2233 This object may be accessed either as a tuple of\n\
2234 (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2235 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2236 \n\
2237 See os.statvfs for more information.");
2238
2239 static PyStructSequence_Field statvfs_result_fields[] = {
2240 {"f_bsize", },
2241 {"f_frsize", },
2242 {"f_blocks", },
2243 {"f_bfree", },
2244 {"f_bavail", },
2245 {"f_files", },
2246 {"f_ffree", },
2247 {"f_favail", },
2248 {"f_flag", },
2249 {"f_namemax",},
2250 {"f_fsid", },
2251 {0}
2252 };
2253
2254 static PyStructSequence_Desc statvfs_result_desc = {
2255 "statvfs_result", /* name */
2256 statvfs_result__doc__, /* doc */
2257 statvfs_result_fields,
2258 10
2259 };
2260
2261 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2262 PyDoc_STRVAR(waitid_result__doc__,
2263 "waitid_result: Result from waitid.\n\n\
2264 This object may be accessed either as a tuple of\n\
2265 (si_pid, si_uid, si_signo, si_status, si_code),\n\
2266 or via the attributes si_pid, si_uid, and so on.\n\
2267 \n\
2268 See os.waitid for more information.");
2269
2270 static PyStructSequence_Field waitid_result_fields[] = {
2271 {"si_pid", },
2272 {"si_uid", },
2273 {"si_signo", },
2274 {"si_status", },
2275 {"si_code", },
2276 {0}
2277 };
2278
2279 static PyStructSequence_Desc waitid_result_desc = {
2280 "waitid_result", /* name */
2281 waitid_result__doc__, /* doc */
2282 waitid_result_fields,
2283 5
2284 };
2285 #endif
2286 static newfunc structseq_new;
2287
2288 static PyObject *
statresult_new(PyTypeObject * type,PyObject * args,PyObject * kwds)2289 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2290 {
2291 PyStructSequence *result;
2292 int i;
2293
2294 result = (PyStructSequence*)structseq_new(type, args, kwds);
2295 if (!result)
2296 return NULL;
2297 /* If we have been initialized from a tuple,
2298 st_?time might be set to None. Initialize it
2299 from the int slots. */
2300 for (i = 7; i <= 9; i++) {
2301 if (result->ob_item[i+3] == Py_None) {
2302 Py_DECREF(Py_None);
2303 Py_INCREF(result->ob_item[i]);
2304 result->ob_item[i+3] = result->ob_item[i];
2305 }
2306 }
2307 return (PyObject*)result;
2308 }
2309
2310 static int
_posix_clear(PyObject * module)2311 _posix_clear(PyObject *module)
2312 {
2313 _posixstate *state = get_posix_state(module);
2314 Py_CLEAR(state->billion);
2315 Py_CLEAR(state->DirEntryType);
2316 Py_CLEAR(state->ScandirIteratorType);
2317 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2318 Py_CLEAR(state->SchedParamType);
2319 #endif
2320 Py_CLEAR(state->StatResultType);
2321 Py_CLEAR(state->StatVFSResultType);
2322 Py_CLEAR(state->TerminalSizeType);
2323 Py_CLEAR(state->TimesResultType);
2324 Py_CLEAR(state->UnameResultType);
2325 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2326 Py_CLEAR(state->WaitidResultType);
2327 #endif
2328 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2329 Py_CLEAR(state->struct_rusage);
2330 #endif
2331 Py_CLEAR(state->st_mode);
2332 return 0;
2333 }
2334
2335 static int
_posix_traverse(PyObject * module,visitproc visit,void * arg)2336 _posix_traverse(PyObject *module, visitproc visit, void *arg)
2337 {
2338 _posixstate *state = get_posix_state(module);
2339 Py_VISIT(state->billion);
2340 Py_VISIT(state->DirEntryType);
2341 Py_VISIT(state->ScandirIteratorType);
2342 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2343 Py_VISIT(state->SchedParamType);
2344 #endif
2345 Py_VISIT(state->StatResultType);
2346 Py_VISIT(state->StatVFSResultType);
2347 Py_VISIT(state->TerminalSizeType);
2348 Py_VISIT(state->TimesResultType);
2349 Py_VISIT(state->UnameResultType);
2350 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2351 Py_VISIT(state->WaitidResultType);
2352 #endif
2353 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2354 Py_VISIT(state->struct_rusage);
2355 #endif
2356 Py_VISIT(state->st_mode);
2357 return 0;
2358 }
2359
2360 static void
_posix_free(void * module)2361 _posix_free(void *module)
2362 {
2363 _posix_clear((PyObject *)module);
2364 }
2365
2366 static void
fill_time(PyObject * module,PyObject * v,int index,time_t sec,unsigned long nsec)2367 fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)
2368 {
2369 PyObject *s = _PyLong_FromTime_t(sec);
2370 PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2371 PyObject *s_in_ns = NULL;
2372 PyObject *ns_total = NULL;
2373 PyObject *float_s = NULL;
2374
2375 if (!(s && ns_fractional))
2376 goto exit;
2377
2378 s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2379 if (!s_in_ns)
2380 goto exit;
2381
2382 ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2383 if (!ns_total)
2384 goto exit;
2385
2386 float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2387 if (!float_s) {
2388 goto exit;
2389 }
2390
2391 PyStructSequence_SET_ITEM(v, index, s);
2392 PyStructSequence_SET_ITEM(v, index+3, float_s);
2393 PyStructSequence_SET_ITEM(v, index+6, ns_total);
2394 s = NULL;
2395 float_s = NULL;
2396 ns_total = NULL;
2397 exit:
2398 Py_XDECREF(s);
2399 Py_XDECREF(ns_fractional);
2400 Py_XDECREF(s_in_ns);
2401 Py_XDECREF(ns_total);
2402 Py_XDECREF(float_s);
2403 }
2404
2405 /* pack a system stat C structure into the Python stat tuple
2406 (used by posix_stat() and posix_fstat()) */
2407 static PyObject*
_pystat_fromstructstat(PyObject * module,STRUCT_STAT * st)2408 _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2409 {
2410 unsigned long ansec, mnsec, cnsec;
2411 PyObject *StatResultType = get_posix_state(module)->StatResultType;
2412 PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2413 if (v == NULL)
2414 return NULL;
2415
2416 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2417 static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2418 "stat.st_ino is larger than unsigned long long");
2419 PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2420 #ifdef MS_WINDOWS
2421 PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
2422 #else
2423 PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2424 #endif
2425 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2426 #if defined(MS_WINDOWS)
2427 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2428 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2429 #else
2430 PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2431 PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2432 #endif
2433 static_assert(sizeof(long long) >= sizeof(st->st_size),
2434 "stat.st_size is larger than long long");
2435 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2436
2437 #if defined(HAVE_STAT_TV_NSEC)
2438 ansec = st->st_atim.tv_nsec;
2439 mnsec = st->st_mtim.tv_nsec;
2440 cnsec = st->st_ctim.tv_nsec;
2441 #elif defined(HAVE_STAT_TV_NSEC2)
2442 ansec = st->st_atimespec.tv_nsec;
2443 mnsec = st->st_mtimespec.tv_nsec;
2444 cnsec = st->st_ctimespec.tv_nsec;
2445 #elif defined(HAVE_STAT_NSEC)
2446 ansec = st->st_atime_nsec;
2447 mnsec = st->st_mtime_nsec;
2448 cnsec = st->st_ctime_nsec;
2449 #else
2450 ansec = mnsec = cnsec = 0;
2451 #endif
2452 fill_time(module, v, 7, st->st_atime, ansec);
2453 fill_time(module, v, 8, st->st_mtime, mnsec);
2454 fill_time(module, v, 9, st->st_ctime, cnsec);
2455
2456 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2457 PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2458 PyLong_FromLong((long)st->st_blksize));
2459 #endif
2460 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2461 PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2462 PyLong_FromLong((long)st->st_blocks));
2463 #endif
2464 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2465 PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2466 PyLong_FromLong((long)st->st_rdev));
2467 #endif
2468 #ifdef HAVE_STRUCT_STAT_ST_GEN
2469 PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2470 PyLong_FromLong((long)st->st_gen));
2471 #endif
2472 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2473 {
2474 PyObject *val;
2475 unsigned long bsec,bnsec;
2476 bsec = (long)st->st_birthtime;
2477 #ifdef HAVE_STAT_TV_NSEC2
2478 bnsec = st->st_birthtimespec.tv_nsec;
2479 #else
2480 bnsec = 0;
2481 #endif
2482 val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2483 PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2484 val);
2485 }
2486 #endif
2487 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2488 PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2489 PyLong_FromLong((long)st->st_flags));
2490 #endif
2491 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2492 PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2493 PyLong_FromUnsignedLong(st->st_file_attributes));
2494 #endif
2495 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2496 PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2497 PyUnicode_FromString(st->st_fstype));
2498 #endif
2499 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2500 PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2501 PyLong_FromUnsignedLong(st->st_reparse_tag));
2502 #endif
2503
2504 if (PyErr_Occurred()) {
2505 Py_DECREF(v);
2506 return NULL;
2507 }
2508
2509 return v;
2510 }
2511
2512 /* POSIX methods */
2513
2514
2515 static PyObject *
posix_do_stat(PyObject * module,const char * function_name,path_t * path,int dir_fd,int follow_symlinks)2516 posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2517 int dir_fd, int follow_symlinks)
2518 {
2519 STRUCT_STAT st;
2520 int result;
2521
2522 #ifdef HAVE_FSTATAT
2523 int fstatat_unavailable = 0;
2524 #endif
2525
2526 #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2527 if (follow_symlinks_specified(function_name, follow_symlinks))
2528 return NULL;
2529 #endif
2530
2531 if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2532 dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2533 fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2534 return NULL;
2535
2536 Py_BEGIN_ALLOW_THREADS
2537 if (path->fd != -1)
2538 result = FSTAT(path->fd, &st);
2539 #ifdef MS_WINDOWS
2540 else if (follow_symlinks)
2541 result = win32_stat(path->wide, &st);
2542 else
2543 result = win32_lstat(path->wide, &st);
2544 #else
2545 else
2546 #if defined(HAVE_LSTAT)
2547 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2548 result = LSTAT(path->narrow, &st);
2549 else
2550 #endif /* HAVE_LSTAT */
2551 #ifdef HAVE_FSTATAT
2552 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2553 if (HAVE_FSTATAT_RUNTIME) {
2554 result = fstatat(dir_fd, path->narrow, &st,
2555 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2556
2557 } else {
2558 fstatat_unavailable = 1;
2559 }
2560 } else
2561 #endif /* HAVE_FSTATAT */
2562 result = STAT(path->narrow, &st);
2563 #endif /* MS_WINDOWS */
2564 Py_END_ALLOW_THREADS
2565
2566 #ifdef HAVE_FSTATAT
2567 if (fstatat_unavailable) {
2568 argument_unavailable_error("stat", "dir_fd");
2569 return NULL;
2570 }
2571 #endif
2572
2573 if (result != 0) {
2574 return path_error(path);
2575 }
2576
2577 return _pystat_fromstructstat(module, &st);
2578 }
2579
2580 /*[python input]
2581
2582 for s in """
2583
2584 FACCESSAT
2585 FCHMODAT
2586 FCHOWNAT
2587 FSTATAT
2588 LINKAT
2589 MKDIRAT
2590 MKFIFOAT
2591 MKNODAT
2592 OPENAT
2593 READLINKAT
2594 SYMLINKAT
2595 UNLINKAT
2596
2597 """.strip().split():
2598 s = s.strip()
2599 print("""
2600 #ifdef HAVE_{s}
2601 #define {s}_DIR_FD_CONVERTER dir_fd_converter
2602 #else
2603 #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2604 #endif
2605 """.rstrip().format(s=s))
2606
2607 for s in """
2608
2609 FCHDIR
2610 FCHMOD
2611 FCHOWN
2612 FDOPENDIR
2613 FEXECVE
2614 FPATHCONF
2615 FSTATVFS
2616 FTRUNCATE
2617
2618 """.strip().split():
2619 s = s.strip()
2620 print("""
2621 #ifdef HAVE_{s}
2622 #define PATH_HAVE_{s} 1
2623 #else
2624 #define PATH_HAVE_{s} 0
2625 #endif
2626
2627 """.rstrip().format(s=s))
2628 [python start generated code]*/
2629
2630 #ifdef HAVE_FACCESSAT
2631 #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2632 #else
2633 #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2634 #endif
2635
2636 #ifdef HAVE_FCHMODAT
2637 #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2638 #else
2639 #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2640 #endif
2641
2642 #ifdef HAVE_FCHOWNAT
2643 #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2644 #else
2645 #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2646 #endif
2647
2648 #ifdef HAVE_FSTATAT
2649 #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2650 #else
2651 #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2652 #endif
2653
2654 #ifdef HAVE_LINKAT
2655 #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2656 #else
2657 #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2658 #endif
2659
2660 #ifdef HAVE_MKDIRAT
2661 #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2662 #else
2663 #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2664 #endif
2665
2666 #ifdef HAVE_MKFIFOAT
2667 #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2668 #else
2669 #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2670 #endif
2671
2672 #ifdef HAVE_MKNODAT
2673 #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2674 #else
2675 #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2676 #endif
2677
2678 #ifdef HAVE_OPENAT
2679 #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2680 #else
2681 #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2682 #endif
2683
2684 #ifdef HAVE_READLINKAT
2685 #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2686 #else
2687 #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2688 #endif
2689
2690 #ifdef HAVE_SYMLINKAT
2691 #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2692 #else
2693 #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2694 #endif
2695
2696 #ifdef HAVE_UNLINKAT
2697 #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2698 #else
2699 #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2700 #endif
2701
2702 #ifdef HAVE_FCHDIR
2703 #define PATH_HAVE_FCHDIR 1
2704 #else
2705 #define PATH_HAVE_FCHDIR 0
2706 #endif
2707
2708 #ifdef HAVE_FCHMOD
2709 #define PATH_HAVE_FCHMOD 1
2710 #else
2711 #define PATH_HAVE_FCHMOD 0
2712 #endif
2713
2714 #ifdef HAVE_FCHOWN
2715 #define PATH_HAVE_FCHOWN 1
2716 #else
2717 #define PATH_HAVE_FCHOWN 0
2718 #endif
2719
2720 #ifdef HAVE_FDOPENDIR
2721 #define PATH_HAVE_FDOPENDIR 1
2722 #else
2723 #define PATH_HAVE_FDOPENDIR 0
2724 #endif
2725
2726 #ifdef HAVE_FEXECVE
2727 #define PATH_HAVE_FEXECVE 1
2728 #else
2729 #define PATH_HAVE_FEXECVE 0
2730 #endif
2731
2732 #ifdef HAVE_FPATHCONF
2733 #define PATH_HAVE_FPATHCONF 1
2734 #else
2735 #define PATH_HAVE_FPATHCONF 0
2736 #endif
2737
2738 #ifdef HAVE_FSTATVFS
2739 #define PATH_HAVE_FSTATVFS 1
2740 #else
2741 #define PATH_HAVE_FSTATVFS 0
2742 #endif
2743
2744 #ifdef HAVE_FTRUNCATE
2745 #define PATH_HAVE_FTRUNCATE 1
2746 #else
2747 #define PATH_HAVE_FTRUNCATE 0
2748 #endif
2749 /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2750
2751 #ifdef MS_WINDOWS
2752 #undef PATH_HAVE_FTRUNCATE
2753 #define PATH_HAVE_FTRUNCATE 1
2754 #endif
2755
2756 /*[python input]
2757
2758 class path_t_converter(CConverter):
2759
2760 type = "path_t"
2761 impl_by_reference = True
2762 parse_by_reference = True
2763
2764 converter = 'path_converter'
2765
2766 def converter_init(self, *, allow_fd=False, nullable=False):
2767 # right now path_t doesn't support default values.
2768 # to support a default value, you'll need to override initialize().
2769 if self.default not in (unspecified, None):
2770 fail("Can't specify a default to the path_t converter!")
2771
2772 if self.c_default not in (None, 'Py_None'):
2773 raise RuntimeError("Can't specify a c_default to the path_t converter!")
2774
2775 self.nullable = nullable
2776 self.allow_fd = allow_fd
2777
2778 def pre_render(self):
2779 def strify(value):
2780 if isinstance(value, str):
2781 return value
2782 return str(int(bool(value)))
2783
2784 # add self.py_name here when merging with posixmodule conversion
2785 self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2786 self.function.name,
2787 self.name,
2788 strify(self.nullable),
2789 strify(self.allow_fd),
2790 )
2791
2792 def cleanup(self):
2793 return "path_cleanup(&" + self.name + ");\n"
2794
2795
2796 class dir_fd_converter(CConverter):
2797 type = 'int'
2798
2799 def converter_init(self, requires=None):
2800 if self.default in (unspecified, None):
2801 self.c_default = 'DEFAULT_DIR_FD'
2802 if isinstance(requires, str):
2803 self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2804 else:
2805 self.converter = 'dir_fd_converter'
2806
2807 class uid_t_converter(CConverter):
2808 type = "uid_t"
2809 converter = '_Py_Uid_Converter'
2810
2811 class gid_t_converter(CConverter):
2812 type = "gid_t"
2813 converter = '_Py_Gid_Converter'
2814
2815 class dev_t_converter(CConverter):
2816 type = 'dev_t'
2817 converter = '_Py_Dev_Converter'
2818
2819 class dev_t_return_converter(unsigned_long_return_converter):
2820 type = 'dev_t'
2821 conversion_fn = '_PyLong_FromDev'
2822 unsigned_cast = '(dev_t)'
2823
2824 class FSConverter_converter(CConverter):
2825 type = 'PyObject *'
2826 converter = 'PyUnicode_FSConverter'
2827 def converter_init(self):
2828 if self.default is not unspecified:
2829 fail("FSConverter_converter does not support default values")
2830 self.c_default = 'NULL'
2831
2832 def cleanup(self):
2833 return "Py_XDECREF(" + self.name + ");\n"
2834
2835 class pid_t_converter(CConverter):
2836 type = 'pid_t'
2837 format_unit = '" _Py_PARSE_PID "'
2838
2839 class idtype_t_converter(int_converter):
2840 type = 'idtype_t'
2841
2842 class id_t_converter(CConverter):
2843 type = 'id_t'
2844 format_unit = '" _Py_PARSE_PID "'
2845
2846 class intptr_t_converter(CConverter):
2847 type = 'intptr_t'
2848 format_unit = '" _Py_PARSE_INTPTR "'
2849
2850 class Py_off_t_converter(CConverter):
2851 type = 'Py_off_t'
2852 converter = 'Py_off_t_converter'
2853
2854 class Py_off_t_return_converter(long_return_converter):
2855 type = 'Py_off_t'
2856 conversion_fn = 'PyLong_FromPy_off_t'
2857
2858 class path_confname_converter(CConverter):
2859 type="int"
2860 converter="conv_path_confname"
2861
2862 class confstr_confname_converter(path_confname_converter):
2863 converter='conv_confstr_confname'
2864
2865 class sysconf_confname_converter(path_confname_converter):
2866 converter="conv_sysconf_confname"
2867
2868 [python start generated code]*/
2869 /*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/
2870
2871 /*[clinic input]
2872
2873 os.stat
2874
2875 path : path_t(allow_fd=True)
2876 Path to be examined; can be string, bytes, a path-like object or
2877 open-file-descriptor int.
2878
2879 *
2880
2881 dir_fd : dir_fd(requires='fstatat') = None
2882 If not None, it should be a file descriptor open to a directory,
2883 and path should be a relative string; path will then be relative to
2884 that directory.
2885
2886 follow_symlinks: bool = True
2887 If False, and the last element of the path is a symbolic link,
2888 stat will examine the symbolic link itself instead of the file
2889 the link points to.
2890
2891 Perform a stat system call on the given path.
2892
2893 dir_fd and follow_symlinks may not be implemented
2894 on your platform. If they are unavailable, using them will raise a
2895 NotImplementedError.
2896
2897 It's an error to use dir_fd or follow_symlinks when specifying path as
2898 an open file descriptor.
2899
2900 [clinic start generated code]*/
2901
2902 static PyObject *
os_stat_impl(PyObject * module,path_t * path,int dir_fd,int follow_symlinks)2903 os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2904 /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2905 {
2906 return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
2907 }
2908
2909
2910 /*[clinic input]
2911 os.lstat
2912
2913 path : path_t
2914
2915 *
2916
2917 dir_fd : dir_fd(requires='fstatat') = None
2918
2919 Perform a stat system call on the given path, without following symbolic links.
2920
2921 Like stat(), but do not follow symbolic links.
2922 Equivalent to stat(path, follow_symlinks=False).
2923 [clinic start generated code]*/
2924
2925 static PyObject *
os_lstat_impl(PyObject * module,path_t * path,int dir_fd)2926 os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2927 /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2928 {
2929 int follow_symlinks = 0;
2930 return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
2931 }
2932
2933
2934 /*[clinic input]
2935 os.access -> bool
2936
2937 path: path_t
2938 Path to be tested; can be string, bytes, or a path-like object.
2939
2940 mode: int
2941 Operating-system mode bitfield. Can be F_OK to test existence,
2942 or the inclusive-OR of R_OK, W_OK, and X_OK.
2943
2944 *
2945
2946 dir_fd : dir_fd(requires='faccessat') = None
2947 If not None, it should be a file descriptor open to a directory,
2948 and path should be relative; path will then be relative to that
2949 directory.
2950
2951 effective_ids: bool = False
2952 If True, access will use the effective uid/gid instead of
2953 the real uid/gid.
2954
2955 follow_symlinks: bool = True
2956 If False, and the last element of the path is a symbolic link,
2957 access will examine the symbolic link itself instead of the file
2958 the link points to.
2959
2960 Use the real uid/gid to test for access to a path.
2961
2962 {parameters}
2963 dir_fd, effective_ids, and follow_symlinks may not be implemented
2964 on your platform. If they are unavailable, using them will raise a
2965 NotImplementedError.
2966
2967 Note that most operations will use the effective uid/gid, therefore this
2968 routine can be used in a suid/sgid environment to test if the invoking user
2969 has the specified access to the path.
2970
2971 [clinic start generated code]*/
2972
2973 static int
os_access_impl(PyObject * module,path_t * path,int mode,int dir_fd,int effective_ids,int follow_symlinks)2974 os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2975 int effective_ids, int follow_symlinks)
2976 /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
2977 {
2978 int return_value;
2979
2980 #ifdef MS_WINDOWS
2981 DWORD attr;
2982 #else
2983 int result;
2984 #endif
2985
2986 #ifdef HAVE_FACCESSAT
2987 int faccessat_unavailable = 0;
2988 #endif
2989
2990 #ifndef HAVE_FACCESSAT
2991 if (follow_symlinks_specified("access", follow_symlinks))
2992 return -1;
2993
2994 if (effective_ids) {
2995 argument_unavailable_error("access", "effective_ids");
2996 return -1;
2997 }
2998 #endif
2999
3000 #ifdef MS_WINDOWS
3001 Py_BEGIN_ALLOW_THREADS
3002 attr = GetFileAttributesW(path->wide);
3003 Py_END_ALLOW_THREADS
3004
3005 /*
3006 * Access is possible if
3007 * * we didn't get a -1, and
3008 * * write access wasn't requested,
3009 * * or the file isn't read-only,
3010 * * or it's a directory.
3011 * (Directories cannot be read-only on Windows.)
3012 */
3013 return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3014 (!(mode & 2) ||
3015 !(attr & FILE_ATTRIBUTE_READONLY) ||
3016 (attr & FILE_ATTRIBUTE_DIRECTORY));
3017 #else
3018
3019 Py_BEGIN_ALLOW_THREADS
3020 #ifdef HAVE_FACCESSAT
3021 if ((dir_fd != DEFAULT_DIR_FD) ||
3022 effective_ids ||
3023 !follow_symlinks) {
3024
3025 if (HAVE_FACCESSAT_RUNTIME) {
3026 int flags = 0;
3027 if (!follow_symlinks)
3028 flags |= AT_SYMLINK_NOFOLLOW;
3029 if (effective_ids)
3030 flags |= AT_EACCESS;
3031 result = faccessat(dir_fd, path->narrow, mode, flags);
3032 } else {
3033 faccessat_unavailable = 1;
3034 }
3035 }
3036 else
3037 #endif
3038 result = access(path->narrow, mode);
3039 Py_END_ALLOW_THREADS
3040
3041 #ifdef HAVE_FACCESSAT
3042 if (faccessat_unavailable) {
3043 if (dir_fd != DEFAULT_DIR_FD) {
3044 argument_unavailable_error("access", "dir_fd");
3045 return -1;
3046 }
3047 if (follow_symlinks_specified("access", follow_symlinks))
3048 return -1;
3049
3050 if (effective_ids) {
3051 argument_unavailable_error("access", "effective_ids");
3052 return -1;
3053 }
3054 /* should be unreachable */
3055 return -1;
3056 }
3057 #endif
3058 return_value = !result;
3059 #endif
3060
3061 return return_value;
3062 }
3063
3064 #ifndef F_OK
3065 #define F_OK 0
3066 #endif
3067 #ifndef R_OK
3068 #define R_OK 4
3069 #endif
3070 #ifndef W_OK
3071 #define W_OK 2
3072 #endif
3073 #ifndef X_OK
3074 #define X_OK 1
3075 #endif
3076
3077
3078 #ifdef HAVE_TTYNAME
3079 /*[clinic input]
3080 os.ttyname
3081
3082 fd: int
3083 Integer file descriptor handle.
3084
3085 /
3086
3087 Return the name of the terminal device connected to 'fd'.
3088 [clinic start generated code]*/
3089
3090 static PyObject *
os_ttyname_impl(PyObject * module,int fd)3091 os_ttyname_impl(PyObject *module, int fd)
3092 /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3093 {
3094
3095 long size = sysconf(_SC_TTY_NAME_MAX);
3096 if (size == -1) {
3097 return posix_error();
3098 }
3099 char *buffer = (char *)PyMem_RawMalloc(size);
3100 if (buffer == NULL) {
3101 return PyErr_NoMemory();
3102 }
3103 int ret = ttyname_r(fd, buffer, size);
3104 if (ret != 0) {
3105 PyMem_RawFree(buffer);
3106 errno = ret;
3107 return posix_error();
3108 }
3109 PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3110 PyMem_RawFree(buffer);
3111 return res;
3112 }
3113 #endif
3114
3115 #ifdef HAVE_CTERMID
3116 /*[clinic input]
3117 os.ctermid
3118
3119 Return the name of the controlling terminal for this process.
3120 [clinic start generated code]*/
3121
3122 static PyObject *
os_ctermid_impl(PyObject * module)3123 os_ctermid_impl(PyObject *module)
3124 /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3125 {
3126 char *ret;
3127 char buffer[L_ctermid];
3128
3129 #ifdef USE_CTERMID_R
3130 ret = ctermid_r(buffer);
3131 #else
3132 ret = ctermid(buffer);
3133 #endif
3134 if (ret == NULL)
3135 return posix_error();
3136 return PyUnicode_DecodeFSDefault(buffer);
3137 }
3138 #endif /* HAVE_CTERMID */
3139
3140
3141 /*[clinic input]
3142 os.chdir
3143
3144 path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3145
3146 Change the current working directory to the specified path.
3147
3148 path may always be specified as a string.
3149 On some platforms, path may also be specified as an open file descriptor.
3150 If this functionality is unavailable, using it raises an exception.
3151 [clinic start generated code]*/
3152
3153 static PyObject *
os_chdir_impl(PyObject * module,path_t * path)3154 os_chdir_impl(PyObject *module, path_t *path)
3155 /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3156 {
3157 int result;
3158
3159 if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3160 return NULL;
3161 }
3162
3163 Py_BEGIN_ALLOW_THREADS
3164 #ifdef MS_WINDOWS
3165 /* on unix, success = 0, on windows, success = !0 */
3166 result = !win32_wchdir(path->wide);
3167 #else
3168 #ifdef HAVE_FCHDIR
3169 if (path->fd != -1)
3170 result = fchdir(path->fd);
3171 else
3172 #endif
3173 result = chdir(path->narrow);
3174 #endif
3175 Py_END_ALLOW_THREADS
3176
3177 if (result) {
3178 return path_error(path);
3179 }
3180
3181 Py_RETURN_NONE;
3182 }
3183
3184
3185 #ifdef HAVE_FCHDIR
3186 /*[clinic input]
3187 os.fchdir
3188
3189 fd: fildes
3190
3191 Change to the directory of the given file descriptor.
3192
3193 fd must be opened on a directory, not a file.
3194 Equivalent to os.chdir(fd).
3195
3196 [clinic start generated code]*/
3197
3198 static PyObject *
os_fchdir_impl(PyObject * module,int fd)3199 os_fchdir_impl(PyObject *module, int fd)
3200 /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3201 {
3202 if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3203 return NULL;
3204 }
3205 return posix_fildes_fd(fd, fchdir);
3206 }
3207 #endif /* HAVE_FCHDIR */
3208
3209
3210 /*[clinic input]
3211 os.chmod
3212
3213 path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3214 Path to be modified. May always be specified as a str, bytes, or a path-like object.
3215 On some platforms, path may also be specified as an open file descriptor.
3216 If this functionality is unavailable, using it raises an exception.
3217
3218 mode: int
3219 Operating-system mode bitfield.
3220
3221 *
3222
3223 dir_fd : dir_fd(requires='fchmodat') = None
3224 If not None, it should be a file descriptor open to a directory,
3225 and path should be relative; path will then be relative to that
3226 directory.
3227
3228 follow_symlinks: bool = True
3229 If False, and the last element of the path is a symbolic link,
3230 chmod will modify the symbolic link itself instead of the file
3231 the link points to.
3232
3233 Change the access permissions of a file.
3234
3235 It is an error to use dir_fd or follow_symlinks when specifying path as
3236 an open file descriptor.
3237 dir_fd and follow_symlinks may not be implemented on your platform.
3238 If they are unavailable, using them will raise a NotImplementedError.
3239
3240 [clinic start generated code]*/
3241
3242 static PyObject *
os_chmod_impl(PyObject * module,path_t * path,int mode,int dir_fd,int follow_symlinks)3243 os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3244 int follow_symlinks)
3245 /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
3246 {
3247 int result;
3248
3249 #ifdef MS_WINDOWS
3250 DWORD attr;
3251 #endif
3252
3253 #ifdef HAVE_FCHMODAT
3254 int fchmodat_nofollow_unsupported = 0;
3255 int fchmodat_unsupported = 0;
3256 #endif
3257
3258 #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
3259 if (follow_symlinks_specified("chmod", follow_symlinks))
3260 return NULL;
3261 #endif
3262
3263 if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3264 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3265 return NULL;
3266 }
3267
3268 #ifdef MS_WINDOWS
3269 Py_BEGIN_ALLOW_THREADS
3270 attr = GetFileAttributesW(path->wide);
3271 if (attr == INVALID_FILE_ATTRIBUTES)
3272 result = 0;
3273 else {
3274 if (mode & _S_IWRITE)
3275 attr &= ~FILE_ATTRIBUTE_READONLY;
3276 else
3277 attr |= FILE_ATTRIBUTE_READONLY;
3278 result = SetFileAttributesW(path->wide, attr);
3279 }
3280 Py_END_ALLOW_THREADS
3281
3282 if (!result) {
3283 return path_error(path);
3284 }
3285 #else /* MS_WINDOWS */
3286 Py_BEGIN_ALLOW_THREADS
3287 #ifdef HAVE_FCHMOD
3288 if (path->fd != -1)
3289 result = fchmod(path->fd, mode);
3290 else
3291 #endif /* HAVE_CHMOD */
3292 #ifdef HAVE_LCHMOD
3293 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3294 result = lchmod(path->narrow, mode);
3295 else
3296 #endif /* HAVE_LCHMOD */
3297 #ifdef HAVE_FCHMODAT
3298 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3299 if (HAVE_FCHMODAT_RUNTIME) {
3300 /*
3301 * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3302 * The documentation specifically shows how to use it,
3303 * and then says it isn't implemented yet.
3304 * (true on linux with glibc 2.15, and openindiana 3.x)
3305 *
3306 * Once it is supported, os.chmod will automatically
3307 * support dir_fd and follow_symlinks=False. (Hopefully.)
3308 * Until then, we need to be careful what exception we raise.
3309 */
3310 result = fchmodat(dir_fd, path->narrow, mode,
3311 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3312 /*
3313 * But wait! We can't throw the exception without allowing threads,
3314 * and we can't do that in this nested scope. (Macro trickery, sigh.)
3315 */
3316 fchmodat_nofollow_unsupported =
3317 result &&
3318 ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3319 !follow_symlinks;
3320 } else {
3321 fchmodat_unsupported = 1;
3322 fchmodat_nofollow_unsupported = 1;
3323
3324 result = -1;
3325 }
3326 }
3327 else
3328 #endif /* HAVE_FHCMODAT */
3329 {
3330 #ifdef HAVE_CHMOD
3331 result = chmod(path->narrow, mode);
3332 #elif defined(__wasi__)
3333 // WASI SDK 15.0 does not support chmod.
3334 // Ignore missing syscall for now.
3335 result = 0;
3336 #else
3337 result = -1;
3338 errno = ENOSYS;
3339 #endif
3340 }
3341 Py_END_ALLOW_THREADS
3342
3343 if (result) {
3344 #ifdef HAVE_FCHMODAT
3345 if (fchmodat_unsupported) {
3346 if (dir_fd != DEFAULT_DIR_FD) {
3347 argument_unavailable_error("chmod", "dir_fd");
3348 return NULL;
3349 }
3350 }
3351
3352 if (fchmodat_nofollow_unsupported) {
3353 if (dir_fd != DEFAULT_DIR_FD)
3354 dir_fd_and_follow_symlinks_invalid("chmod",
3355 dir_fd, follow_symlinks);
3356 else
3357 follow_symlinks_specified("chmod", follow_symlinks);
3358 return NULL;
3359 }
3360 else
3361 #endif /* HAVE_FCHMODAT */
3362 return path_error(path);
3363 }
3364 #endif /* MS_WINDOWS */
3365
3366 Py_RETURN_NONE;
3367 }
3368
3369
3370 #ifdef HAVE_FCHMOD
3371 /*[clinic input]
3372 os.fchmod
3373
3374 fd: int
3375 mode: int
3376
3377 Change the access permissions of the file given by file descriptor fd.
3378
3379 Equivalent to os.chmod(fd, mode).
3380 [clinic start generated code]*/
3381
3382 static PyObject *
os_fchmod_impl(PyObject * module,int fd,int mode)3383 os_fchmod_impl(PyObject *module, int fd, int mode)
3384 /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
3385 {
3386 int res;
3387 int async_err = 0;
3388
3389 if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3390 return NULL;
3391 }
3392
3393 do {
3394 Py_BEGIN_ALLOW_THREADS
3395 res = fchmod(fd, mode);
3396 Py_END_ALLOW_THREADS
3397 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3398 if (res != 0)
3399 return (!async_err) ? posix_error() : NULL;
3400
3401 Py_RETURN_NONE;
3402 }
3403 #endif /* HAVE_FCHMOD */
3404
3405
3406 #ifdef HAVE_LCHMOD
3407 /*[clinic input]
3408 os.lchmod
3409
3410 path: path_t
3411 mode: int
3412
3413 Change the access permissions of a file, without following symbolic links.
3414
3415 If path is a symlink, this affects the link itself rather than the target.
3416 Equivalent to chmod(path, mode, follow_symlinks=False)."
3417 [clinic start generated code]*/
3418
3419 static PyObject *
os_lchmod_impl(PyObject * module,path_t * path,int mode)3420 os_lchmod_impl(PyObject *module, path_t *path, int mode)
3421 /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3422 {
3423 int res;
3424 if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3425 return NULL;
3426 }
3427 Py_BEGIN_ALLOW_THREADS
3428 res = lchmod(path->narrow, mode);
3429 Py_END_ALLOW_THREADS
3430 if (res < 0) {
3431 path_error(path);
3432 return NULL;
3433 }
3434 Py_RETURN_NONE;
3435 }
3436 #endif /* HAVE_LCHMOD */
3437
3438
3439 #ifdef HAVE_CHFLAGS
3440 /*[clinic input]
3441 os.chflags
3442
3443 path: path_t
3444 flags: unsigned_long(bitwise=True)
3445 follow_symlinks: bool=True
3446
3447 Set file flags.
3448
3449 If follow_symlinks is False, and the last element of the path is a symbolic
3450 link, chflags will change flags on the symbolic link itself instead of the
3451 file the link points to.
3452 follow_symlinks may not be implemented on your platform. If it is
3453 unavailable, using it will raise a NotImplementedError.
3454
3455 [clinic start generated code]*/
3456
3457 static PyObject *
os_chflags_impl(PyObject * module,path_t * path,unsigned long flags,int follow_symlinks)3458 os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3459 int follow_symlinks)
3460 /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3461 {
3462 int result;
3463
3464 #ifndef HAVE_LCHFLAGS
3465 if (follow_symlinks_specified("chflags", follow_symlinks))
3466 return NULL;
3467 #endif
3468
3469 if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3470 return NULL;
3471 }
3472
3473 Py_BEGIN_ALLOW_THREADS
3474 #ifdef HAVE_LCHFLAGS
3475 if (!follow_symlinks)
3476 result = lchflags(path->narrow, flags);
3477 else
3478 #endif
3479 result = chflags(path->narrow, flags);
3480 Py_END_ALLOW_THREADS
3481
3482 if (result)
3483 return path_error(path);
3484
3485 Py_RETURN_NONE;
3486 }
3487 #endif /* HAVE_CHFLAGS */
3488
3489
3490 #ifdef HAVE_LCHFLAGS
3491 /*[clinic input]
3492 os.lchflags
3493
3494 path: path_t
3495 flags: unsigned_long(bitwise=True)
3496
3497 Set file flags.
3498
3499 This function will not follow symbolic links.
3500 Equivalent to chflags(path, flags, follow_symlinks=False).
3501 [clinic start generated code]*/
3502
3503 static PyObject *
os_lchflags_impl(PyObject * module,path_t * path,unsigned long flags)3504 os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3505 /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3506 {
3507 int res;
3508 if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3509 return NULL;
3510 }
3511 Py_BEGIN_ALLOW_THREADS
3512 res = lchflags(path->narrow, flags);
3513 Py_END_ALLOW_THREADS
3514 if (res < 0) {
3515 return path_error(path);
3516 }
3517 Py_RETURN_NONE;
3518 }
3519 #endif /* HAVE_LCHFLAGS */
3520
3521
3522 #ifdef HAVE_CHROOT
3523 /*[clinic input]
3524 os.chroot
3525 path: path_t
3526
3527 Change root directory to path.
3528
3529 [clinic start generated code]*/
3530
3531 static PyObject *
os_chroot_impl(PyObject * module,path_t * path)3532 os_chroot_impl(PyObject *module, path_t *path)
3533 /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3534 {
3535 int res;
3536 Py_BEGIN_ALLOW_THREADS
3537 res = chroot(path->narrow);
3538 Py_END_ALLOW_THREADS
3539 if (res < 0)
3540 return path_error(path);
3541 Py_RETURN_NONE;
3542 }
3543 #endif /* HAVE_CHROOT */
3544
3545
3546 #ifdef HAVE_FSYNC
3547 /*[clinic input]
3548 os.fsync
3549
3550 fd: fildes
3551
3552 Force write of fd to disk.
3553 [clinic start generated code]*/
3554
3555 static PyObject *
os_fsync_impl(PyObject * module,int fd)3556 os_fsync_impl(PyObject *module, int fd)
3557 /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3558 {
3559 return posix_fildes_fd(fd, fsync);
3560 }
3561 #endif /* HAVE_FSYNC */
3562
3563
3564 #ifdef HAVE_SYNC
3565 /*[clinic input]
3566 os.sync
3567
3568 Force write of everything to disk.
3569 [clinic start generated code]*/
3570
3571 static PyObject *
os_sync_impl(PyObject * module)3572 os_sync_impl(PyObject *module)
3573 /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3574 {
3575 Py_BEGIN_ALLOW_THREADS
3576 sync();
3577 Py_END_ALLOW_THREADS
3578 Py_RETURN_NONE;
3579 }
3580 #endif /* HAVE_SYNC */
3581
3582
3583 #ifdef HAVE_FDATASYNC
3584 #ifdef __hpux
3585 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3586 #endif
3587
3588 /*[clinic input]
3589 os.fdatasync
3590
3591 fd: fildes
3592
3593 Force write of fd to disk without forcing update of metadata.
3594 [clinic start generated code]*/
3595
3596 static PyObject *
os_fdatasync_impl(PyObject * module,int fd)3597 os_fdatasync_impl(PyObject *module, int fd)
3598 /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3599 {
3600 return posix_fildes_fd(fd, fdatasync);
3601 }
3602 #endif /* HAVE_FDATASYNC */
3603
3604
3605 #ifdef HAVE_CHOWN
3606 /*[clinic input]
3607 os.chown
3608
3609 path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3610 Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3611
3612 uid: uid_t
3613
3614 gid: gid_t
3615
3616 *
3617
3618 dir_fd : dir_fd(requires='fchownat') = None
3619 If not None, it should be a file descriptor open to a directory,
3620 and path should be relative; path will then be relative to that
3621 directory.
3622
3623 follow_symlinks: bool = True
3624 If False, and the last element of the path is a symbolic link,
3625 stat will examine the symbolic link itself instead of the file
3626 the link points to.
3627
3628 Change the owner and group id of path to the numeric uid and gid.\
3629
3630 path may always be specified as a string.
3631 On some platforms, path may also be specified as an open file descriptor.
3632 If this functionality is unavailable, using it raises an exception.
3633 If dir_fd is not None, it should be a file descriptor open to a directory,
3634 and path should be relative; path will then be relative to that directory.
3635 If follow_symlinks is False, and the last element of the path is a symbolic
3636 link, chown will modify the symbolic link itself instead of the file the
3637 link points to.
3638 It is an error to use dir_fd or follow_symlinks when specifying path as
3639 an open file descriptor.
3640 dir_fd and follow_symlinks may not be implemented on your platform.
3641 If they are unavailable, using them will raise a NotImplementedError.
3642
3643 [clinic start generated code]*/
3644
3645 static PyObject *
os_chown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid,int dir_fd,int follow_symlinks)3646 os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3647 int dir_fd, int follow_symlinks)
3648 /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3649 {
3650 int result;
3651
3652 #if defined(HAVE_FCHOWNAT)
3653 int fchownat_unsupported = 0;
3654 #endif
3655
3656 #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3657 if (follow_symlinks_specified("chown", follow_symlinks))
3658 return NULL;
3659 #endif
3660 if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3661 fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3662 return NULL;
3663
3664 if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3665 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3666 return NULL;
3667 }
3668
3669 Py_BEGIN_ALLOW_THREADS
3670 #ifdef HAVE_FCHOWN
3671 if (path->fd != -1)
3672 result = fchown(path->fd, uid, gid);
3673 else
3674 #endif
3675 #ifdef HAVE_LCHOWN
3676 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3677 result = lchown(path->narrow, uid, gid);
3678 else
3679 #endif
3680 #ifdef HAVE_FCHOWNAT
3681 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
3682 if (HAVE_FCHOWNAT_RUNTIME) {
3683 result = fchownat(dir_fd, path->narrow, uid, gid,
3684 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3685 } else {
3686 fchownat_unsupported = 1;
3687 }
3688 } else
3689 #endif
3690 result = chown(path->narrow, uid, gid);
3691 Py_END_ALLOW_THREADS
3692
3693 #ifdef HAVE_FCHOWNAT
3694 if (fchownat_unsupported) {
3695 /* This would be incorrect if the current platform
3696 * doesn't support lchown.
3697 */
3698 argument_unavailable_error(NULL, "dir_fd");
3699 return NULL;
3700 }
3701 #endif
3702
3703 if (result)
3704 return path_error(path);
3705
3706 Py_RETURN_NONE;
3707 }
3708 #endif /* HAVE_CHOWN */
3709
3710
3711 #ifdef HAVE_FCHOWN
3712 /*[clinic input]
3713 os.fchown
3714
3715 fd: int
3716 uid: uid_t
3717 gid: gid_t
3718
3719 Change the owner and group id of the file specified by file descriptor.
3720
3721 Equivalent to os.chown(fd, uid, gid).
3722
3723 [clinic start generated code]*/
3724
3725 static PyObject *
os_fchown_impl(PyObject * module,int fd,uid_t uid,gid_t gid)3726 os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3727 /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3728 {
3729 int res;
3730 int async_err = 0;
3731
3732 if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
3733 return NULL;
3734 }
3735
3736 do {
3737 Py_BEGIN_ALLOW_THREADS
3738 res = fchown(fd, uid, gid);
3739 Py_END_ALLOW_THREADS
3740 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3741 if (res != 0)
3742 return (!async_err) ? posix_error() : NULL;
3743
3744 Py_RETURN_NONE;
3745 }
3746 #endif /* HAVE_FCHOWN */
3747
3748
3749 #ifdef HAVE_LCHOWN
3750 /*[clinic input]
3751 os.lchown
3752
3753 path : path_t
3754 uid: uid_t
3755 gid: gid_t
3756
3757 Change the owner and group id of path to the numeric uid and gid.
3758
3759 This function will not follow symbolic links.
3760 Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3761 [clinic start generated code]*/
3762
3763 static PyObject *
os_lchown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid)3764 os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3765 /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3766 {
3767 int res;
3768 if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
3769 return NULL;
3770 }
3771 Py_BEGIN_ALLOW_THREADS
3772 res = lchown(path->narrow, uid, gid);
3773 Py_END_ALLOW_THREADS
3774 if (res < 0) {
3775 return path_error(path);
3776 }
3777 Py_RETURN_NONE;
3778 }
3779 #endif /* HAVE_LCHOWN */
3780
3781
3782 static PyObject *
posix_getcwd(int use_bytes)3783 posix_getcwd(int use_bytes)
3784 {
3785 #ifdef MS_WINDOWS
3786 wchar_t wbuf[MAXPATHLEN];
3787 wchar_t *wbuf2 = wbuf;
3788 DWORD len;
3789
3790 Py_BEGIN_ALLOW_THREADS
3791 len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3792 /* If the buffer is large enough, len does not include the
3793 terminating \0. If the buffer is too small, len includes
3794 the space needed for the terminator. */
3795 if (len >= Py_ARRAY_LENGTH(wbuf)) {
3796 if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3797 wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3798 }
3799 else {
3800 wbuf2 = NULL;
3801 }
3802 if (wbuf2) {
3803 len = GetCurrentDirectoryW(len, wbuf2);
3804 }
3805 }
3806 Py_END_ALLOW_THREADS
3807
3808 if (!wbuf2) {
3809 PyErr_NoMemory();
3810 return NULL;
3811 }
3812 if (!len) {
3813 if (wbuf2 != wbuf)
3814 PyMem_RawFree(wbuf2);
3815 return PyErr_SetFromWindowsErr(0);
3816 }
3817
3818 PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3819 if (wbuf2 != wbuf) {
3820 PyMem_RawFree(wbuf2);
3821 }
3822
3823 if (use_bytes) {
3824 if (resobj == NULL) {
3825 return NULL;
3826 }
3827 Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3828 }
3829
3830 return resobj;
3831 #else
3832 const size_t chunk = 1024;
3833
3834 char *buf = NULL;
3835 char *cwd = NULL;
3836 size_t buflen = 0;
3837
3838 Py_BEGIN_ALLOW_THREADS
3839 do {
3840 char *newbuf;
3841 if (buflen <= PY_SSIZE_T_MAX - chunk) {
3842 buflen += chunk;
3843 newbuf = PyMem_RawRealloc(buf, buflen);
3844 }
3845 else {
3846 newbuf = NULL;
3847 }
3848 if (newbuf == NULL) {
3849 PyMem_RawFree(buf);
3850 buf = NULL;
3851 break;
3852 }
3853 buf = newbuf;
3854
3855 cwd = getcwd(buf, buflen);
3856 } while (cwd == NULL && errno == ERANGE);
3857 Py_END_ALLOW_THREADS
3858
3859 if (buf == NULL) {
3860 return PyErr_NoMemory();
3861 }
3862 if (cwd == NULL) {
3863 PyMem_RawFree(buf);
3864 return posix_error();
3865 }
3866
3867 PyObject *obj;
3868 if (use_bytes) {
3869 obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3870 }
3871 else {
3872 obj = PyUnicode_DecodeFSDefault(buf);
3873 }
3874 PyMem_RawFree(buf);
3875
3876 return obj;
3877 #endif /* !MS_WINDOWS */
3878 }
3879
3880
3881 /*[clinic input]
3882 os.getcwd
3883
3884 Return a unicode string representing the current working directory.
3885 [clinic start generated code]*/
3886
3887 static PyObject *
os_getcwd_impl(PyObject * module)3888 os_getcwd_impl(PyObject *module)
3889 /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3890 {
3891 return posix_getcwd(0);
3892 }
3893
3894
3895 /*[clinic input]
3896 os.getcwdb
3897
3898 Return a bytes string representing the current working directory.
3899 [clinic start generated code]*/
3900
3901 static PyObject *
os_getcwdb_impl(PyObject * module)3902 os_getcwdb_impl(PyObject *module)
3903 /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3904 {
3905 return posix_getcwd(1);
3906 }
3907
3908
3909 #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3910 #define HAVE_LINK 1
3911 #endif
3912
3913 #ifdef HAVE_LINK
3914 /*[clinic input]
3915
3916 os.link
3917
3918 src : path_t
3919 dst : path_t
3920 *
3921 src_dir_fd : dir_fd = None
3922 dst_dir_fd : dir_fd = None
3923 follow_symlinks: bool = True
3924
3925 Create a hard link to a file.
3926
3927 If either src_dir_fd or dst_dir_fd is not None, it should be a file
3928 descriptor open to a directory, and the respective path string (src or dst)
3929 should be relative; the path will then be relative to that directory.
3930 If follow_symlinks is False, and the last element of src is a symbolic
3931 link, link will create a link to the symbolic link itself instead of the
3932 file the link points to.
3933 src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3934 platform. If they are unavailable, using them will raise a
3935 NotImplementedError.
3936 [clinic start generated code]*/
3937
3938 static PyObject *
os_link_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int follow_symlinks)3939 os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3940 int dst_dir_fd, int follow_symlinks)
3941 /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3942 {
3943 #ifdef MS_WINDOWS
3944 BOOL result = FALSE;
3945 #else
3946 int result;
3947 #endif
3948 #if defined(HAVE_LINKAT)
3949 int linkat_unavailable = 0;
3950 #endif
3951
3952 #ifndef HAVE_LINKAT
3953 if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3954 argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3955 return NULL;
3956 }
3957 #endif
3958
3959 #ifndef MS_WINDOWS
3960 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3961 PyErr_SetString(PyExc_NotImplementedError,
3962 "link: src and dst must be the same type");
3963 return NULL;
3964 }
3965 #endif
3966
3967 if (PySys_Audit("os.link", "OOii", src->object, dst->object,
3968 src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
3969 dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
3970 return NULL;
3971 }
3972
3973 #ifdef MS_WINDOWS
3974 Py_BEGIN_ALLOW_THREADS
3975 result = CreateHardLinkW(dst->wide, src->wide, NULL);
3976 Py_END_ALLOW_THREADS
3977
3978 if (!result)
3979 return path_error2(src, dst);
3980 #else
3981 Py_BEGIN_ALLOW_THREADS
3982 #ifdef HAVE_LINKAT
3983 if ((src_dir_fd != DEFAULT_DIR_FD) ||
3984 (dst_dir_fd != DEFAULT_DIR_FD) ||
3985 (!follow_symlinks)) {
3986
3987 if (HAVE_LINKAT_RUNTIME) {
3988
3989 result = linkat(src_dir_fd, src->narrow,
3990 dst_dir_fd, dst->narrow,
3991 follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3992
3993 }
3994 #ifdef __APPLE__
3995 else {
3996 if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
3997 /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
3998 result = link(src->narrow, dst->narrow);
3999 } else {
4000 linkat_unavailable = 1;
4001 }
4002 }
4003 #endif
4004 }
4005 else
4006 #endif /* HAVE_LINKAT */
4007 result = link(src->narrow, dst->narrow);
4008 Py_END_ALLOW_THREADS
4009
4010 #ifdef HAVE_LINKAT
4011 if (linkat_unavailable) {
4012 /* Either or both dir_fd arguments were specified */
4013 if (src_dir_fd != DEFAULT_DIR_FD) {
4014 argument_unavailable_error("link", "src_dir_fd");
4015 } else {
4016 argument_unavailable_error("link", "dst_dir_fd");
4017 }
4018 return NULL;
4019 }
4020 #endif
4021
4022 if (result)
4023 return path_error2(src, dst);
4024 #endif /* MS_WINDOWS */
4025
4026 Py_RETURN_NONE;
4027 }
4028 #endif
4029
4030
4031 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4032 static PyObject *
_listdir_windows_no_opendir(path_t * path,PyObject * list)4033 _listdir_windows_no_opendir(path_t *path, PyObject *list)
4034 {
4035 PyObject *v;
4036 HANDLE hFindFile = INVALID_HANDLE_VALUE;
4037 BOOL result;
4038 wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4039 /* only claim to have space for MAX_PATH */
4040 Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4041 wchar_t *wnamebuf = NULL;
4042
4043 WIN32_FIND_DATAW wFileData;
4044 const wchar_t *po_wchars;
4045
4046 if (!path->wide) { /* Default arg: "." */
4047 po_wchars = L".";
4048 len = 1;
4049 } else {
4050 po_wchars = path->wide;
4051 len = wcslen(path->wide);
4052 }
4053 /* The +5 is so we can append "\\*.*\0" */
4054 wnamebuf = PyMem_New(wchar_t, len + 5);
4055 if (!wnamebuf) {
4056 PyErr_NoMemory();
4057 goto exit;
4058 }
4059 wcscpy(wnamebuf, po_wchars);
4060 if (len > 0) {
4061 wchar_t wch = wnamebuf[len-1];
4062 if (wch != SEP && wch != ALTSEP && wch != L':')
4063 wnamebuf[len++] = SEP;
4064 wcscpy(wnamebuf + len, L"*.*");
4065 }
4066 if ((list = PyList_New(0)) == NULL) {
4067 goto exit;
4068 }
4069 Py_BEGIN_ALLOW_THREADS
4070 hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4071 Py_END_ALLOW_THREADS
4072 if (hFindFile == INVALID_HANDLE_VALUE) {
4073 int error = GetLastError();
4074 if (error == ERROR_FILE_NOT_FOUND)
4075 goto exit;
4076 Py_DECREF(list);
4077 list = path_error(path);
4078 goto exit;
4079 }
4080 do {
4081 /* Skip over . and .. */
4082 if (wcscmp(wFileData.cFileName, L".") != 0 &&
4083 wcscmp(wFileData.cFileName, L"..") != 0) {
4084 v = PyUnicode_FromWideChar(wFileData.cFileName,
4085 wcslen(wFileData.cFileName));
4086 if (path->narrow && v) {
4087 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4088 }
4089 if (v == NULL) {
4090 Py_DECREF(list);
4091 list = NULL;
4092 break;
4093 }
4094 if (PyList_Append(list, v) != 0) {
4095 Py_DECREF(v);
4096 Py_DECREF(list);
4097 list = NULL;
4098 break;
4099 }
4100 Py_DECREF(v);
4101 }
4102 Py_BEGIN_ALLOW_THREADS
4103 result = FindNextFileW(hFindFile, &wFileData);
4104 Py_END_ALLOW_THREADS
4105 /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4106 it got to the end of the directory. */
4107 if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4108 Py_DECREF(list);
4109 list = path_error(path);
4110 goto exit;
4111 }
4112 } while (result == TRUE);
4113
4114 exit:
4115 if (hFindFile != INVALID_HANDLE_VALUE) {
4116 if (FindClose(hFindFile) == FALSE) {
4117 if (list != NULL) {
4118 Py_DECREF(list);
4119 list = path_error(path);
4120 }
4121 }
4122 }
4123 PyMem_Free(wnamebuf);
4124
4125 return list;
4126 } /* end of _listdir_windows_no_opendir */
4127
4128 #else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4129
4130 static PyObject *
_posix_listdir(path_t * path,PyObject * list)4131 _posix_listdir(path_t *path, PyObject *list)
4132 {
4133 PyObject *v;
4134 DIR *dirp = NULL;
4135 struct dirent *ep;
4136 int return_str; /* if false, return bytes */
4137 #ifdef HAVE_FDOPENDIR
4138 int fd = -1;
4139 #endif
4140
4141 errno = 0;
4142 #ifdef HAVE_FDOPENDIR
4143 if (path->fd != -1) {
4144 if (HAVE_FDOPENDIR_RUNTIME) {
4145 /* closedir() closes the FD, so we duplicate it */
4146 fd = _Py_dup(path->fd);
4147 if (fd == -1)
4148 return NULL;
4149
4150 return_str = 1;
4151
4152 Py_BEGIN_ALLOW_THREADS
4153 dirp = fdopendir(fd);
4154 Py_END_ALLOW_THREADS
4155 } else {
4156 PyErr_SetString(PyExc_TypeError,
4157 "listdir: path should be string, bytes, os.PathLike or None, not int");
4158 return NULL;
4159 }
4160 }
4161 else
4162 #endif
4163 {
4164 const char *name;
4165 if (path->narrow) {
4166 name = path->narrow;
4167 /* only return bytes if they specified a bytes-like object */
4168 return_str = !PyObject_CheckBuffer(path->object);
4169 }
4170 else {
4171 name = ".";
4172 return_str = 1;
4173 }
4174
4175 Py_BEGIN_ALLOW_THREADS
4176 dirp = opendir(name);
4177 Py_END_ALLOW_THREADS
4178 }
4179
4180 if (dirp == NULL) {
4181 list = path_error(path);
4182 #ifdef HAVE_FDOPENDIR
4183 if (fd != -1) {
4184 Py_BEGIN_ALLOW_THREADS
4185 close(fd);
4186 Py_END_ALLOW_THREADS
4187 }
4188 #endif
4189 goto exit;
4190 }
4191 if ((list = PyList_New(0)) == NULL) {
4192 goto exit;
4193 }
4194 for (;;) {
4195 errno = 0;
4196 Py_BEGIN_ALLOW_THREADS
4197 ep = readdir(dirp);
4198 Py_END_ALLOW_THREADS
4199 if (ep == NULL) {
4200 if (errno == 0) {
4201 break;
4202 } else {
4203 Py_DECREF(list);
4204 list = path_error(path);
4205 goto exit;
4206 }
4207 }
4208 if (ep->d_name[0] == '.' &&
4209 (NAMLEN(ep) == 1 ||
4210 (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4211 continue;
4212 if (return_str)
4213 v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4214 else
4215 v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4216 if (v == NULL) {
4217 Py_CLEAR(list);
4218 break;
4219 }
4220 if (PyList_Append(list, v) != 0) {
4221 Py_DECREF(v);
4222 Py_CLEAR(list);
4223 break;
4224 }
4225 Py_DECREF(v);
4226 }
4227
4228 exit:
4229 if (dirp != NULL) {
4230 Py_BEGIN_ALLOW_THREADS
4231 #ifdef HAVE_FDOPENDIR
4232 if (fd > -1)
4233 rewinddir(dirp);
4234 #endif
4235 closedir(dirp);
4236 Py_END_ALLOW_THREADS
4237 }
4238
4239 return list;
4240 } /* end of _posix_listdir */
4241 #endif /* which OS */
4242
4243
4244 /*[clinic input]
4245 os.listdir
4246
4247 path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4248
4249 Return a list containing the names of the files in the directory.
4250
4251 path can be specified as either str, bytes, or a path-like object. If path is bytes,
4252 the filenames returned will also be bytes; in all other circumstances
4253 the filenames returned will be str.
4254 If path is None, uses the path='.'.
4255 On some platforms, path may also be specified as an open file descriptor;\
4256 the file descriptor must refer to a directory.
4257 If this functionality is unavailable, using it raises NotImplementedError.
4258
4259 The list is in arbitrary order. It does not include the special
4260 entries '.' and '..' even if they are present in the directory.
4261
4262
4263 [clinic start generated code]*/
4264
4265 static PyObject *
os_listdir_impl(PyObject * module,path_t * path)4266 os_listdir_impl(PyObject *module, path_t *path)
4267 /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4268 {
4269 if (PySys_Audit("os.listdir", "O",
4270 path->object ? path->object : Py_None) < 0) {
4271 return NULL;
4272 }
4273 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4274 return _listdir_windows_no_opendir(path, NULL);
4275 #else
4276 return _posix_listdir(path, NULL);
4277 #endif
4278 }
4279
4280 #ifdef MS_WINDOWS
4281 int
_PyOS_getfullpathname(const wchar_t * path,wchar_t ** abspath_p)4282 _PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
4283 {
4284 wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
4285 DWORD result;
4286
4287 result = GetFullPathNameW(path,
4288 Py_ARRAY_LENGTH(woutbuf), woutbuf,
4289 NULL);
4290 if (!result) {
4291 return -1;
4292 }
4293
4294 if (result >= Py_ARRAY_LENGTH(woutbuf)) {
4295 if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4296 woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
4297 }
4298 else {
4299 woutbufp = NULL;
4300 }
4301 if (!woutbufp) {
4302 *abspath_p = NULL;
4303 return 0;
4304 }
4305
4306 result = GetFullPathNameW(path, result, woutbufp, NULL);
4307 if (!result) {
4308 PyMem_RawFree(woutbufp);
4309 return -1;
4310 }
4311 }
4312
4313 if (woutbufp != woutbuf) {
4314 *abspath_p = woutbufp;
4315 return 0;
4316 }
4317
4318 *abspath_p = _PyMem_RawWcsdup(woutbufp);
4319 return 0;
4320 }
4321
4322
4323 /* A helper function for abspath on win32 */
4324 /*[clinic input]
4325 os._getfullpathname
4326
4327 path: path_t
4328 /
4329
4330 [clinic start generated code]*/
4331
4332 static PyObject *
os__getfullpathname_impl(PyObject * module,path_t * path)4333 os__getfullpathname_impl(PyObject *module, path_t *path)
4334 /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
4335 {
4336 wchar_t *abspath;
4337
4338 if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
4339 return win32_error_object("GetFullPathNameW", path->object);
4340 }
4341 if (abspath == NULL) {
4342 return PyErr_NoMemory();
4343 }
4344
4345 PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
4346 PyMem_RawFree(abspath);
4347 if (str == NULL) {
4348 return NULL;
4349 }
4350 if (path->narrow) {
4351 Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
4352 }
4353 return str;
4354 }
4355
4356
4357 /*[clinic input]
4358 os._getfinalpathname
4359
4360 path: path_t
4361 /
4362
4363 A helper function for samepath on windows.
4364 [clinic start generated code]*/
4365
4366 static PyObject *
os__getfinalpathname_impl(PyObject * module,path_t * path)4367 os__getfinalpathname_impl(PyObject *module, path_t *path)
4368 /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
4369 {
4370 HANDLE hFile;
4371 wchar_t buf[MAXPATHLEN], *target_path = buf;
4372 int buf_size = Py_ARRAY_LENGTH(buf);
4373 int result_length;
4374 PyObject *result;
4375
4376 Py_BEGIN_ALLOW_THREADS
4377 hFile = CreateFileW(
4378 path->wide,
4379 0, /* desired access */
4380 0, /* share mode */
4381 NULL, /* security attributes */
4382 OPEN_EXISTING,
4383 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
4384 FILE_FLAG_BACKUP_SEMANTICS,
4385 NULL);
4386 Py_END_ALLOW_THREADS
4387
4388 if (hFile == INVALID_HANDLE_VALUE) {
4389 return win32_error_object("CreateFileW", path->object);
4390 }
4391
4392 /* We have a good handle to the target, use it to determine the
4393 target path name. */
4394 while (1) {
4395 Py_BEGIN_ALLOW_THREADS
4396 result_length = GetFinalPathNameByHandleW(hFile, target_path,
4397 buf_size, VOLUME_NAME_DOS);
4398 Py_END_ALLOW_THREADS
4399
4400 if (!result_length) {
4401 result = win32_error_object("GetFinalPathNameByHandleW",
4402 path->object);
4403 goto cleanup;
4404 }
4405
4406 if (result_length < buf_size) {
4407 break;
4408 }
4409
4410 wchar_t *tmp;
4411 tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
4412 result_length * sizeof(*tmp));
4413 if (!tmp) {
4414 result = PyErr_NoMemory();
4415 goto cleanup;
4416 }
4417
4418 buf_size = result_length;
4419 target_path = tmp;
4420 }
4421
4422 result = PyUnicode_FromWideChar(target_path, result_length);
4423 if (result && path->narrow) {
4424 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4425 }
4426
4427 cleanup:
4428 if (target_path != buf) {
4429 PyMem_Free(target_path);
4430 }
4431 CloseHandle(hFile);
4432 return result;
4433 }
4434
4435
4436 /*[clinic input]
4437 os._getvolumepathname
4438
4439 path: path_t
4440
4441 A helper function for ismount on Win32.
4442 [clinic start generated code]*/
4443
4444 static PyObject *
os__getvolumepathname_impl(PyObject * module,path_t * path)4445 os__getvolumepathname_impl(PyObject *module, path_t *path)
4446 /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
4447 {
4448 PyObject *result;
4449 wchar_t *mountpath=NULL;
4450 size_t buflen;
4451 BOOL ret;
4452
4453 /* Volume path should be shorter than entire path */
4454 buflen = Py_MAX(path->length, MAX_PATH);
4455
4456 if (buflen > PY_DWORD_MAX) {
4457 PyErr_SetString(PyExc_OverflowError, "path too long");
4458 return NULL;
4459 }
4460
4461 mountpath = PyMem_New(wchar_t, buflen);
4462 if (mountpath == NULL)
4463 return PyErr_NoMemory();
4464
4465 Py_BEGIN_ALLOW_THREADS
4466 ret = GetVolumePathNameW(path->wide, mountpath,
4467 Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
4468 Py_END_ALLOW_THREADS
4469
4470 if (!ret) {
4471 result = win32_error_object("_getvolumepathname", path->object);
4472 goto exit;
4473 }
4474 result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
4475 if (path->narrow)
4476 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4477
4478 exit:
4479 PyMem_Free(mountpath);
4480 return result;
4481 }
4482
4483
4484 /*[clinic input]
4485 os._path_splitroot
4486
4487 path: path_t
4488
4489 Removes everything after the root on Win32.
4490 [clinic start generated code]*/
4491
4492 static PyObject *
os__path_splitroot_impl(PyObject * module,path_t * path)4493 os__path_splitroot_impl(PyObject *module, path_t *path)
4494 /*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/
4495 {
4496 wchar_t *buffer;
4497 wchar_t *end;
4498 PyObject *result = NULL;
4499 HRESULT ret;
4500
4501 buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
4502 if (!buffer) {
4503 return NULL;
4504 }
4505 wcscpy(buffer, path->wide);
4506 for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
4507 *p = L'\\';
4508 }
4509
4510 Py_BEGIN_ALLOW_THREADS
4511 ret = PathCchSkipRoot(buffer, &end);
4512 Py_END_ALLOW_THREADS
4513 if (FAILED(ret)) {
4514 result = Py_BuildValue("sO", "", path->object);
4515 } else if (end != buffer) {
4516 size_t rootLen = (size_t)(end - buffer);
4517 result = Py_BuildValue("NN",
4518 PyUnicode_FromWideChar(path->wide, rootLen),
4519 PyUnicode_FromWideChar(path->wide + rootLen, -1)
4520 );
4521 } else {
4522 result = Py_BuildValue("Os", path->object, "");
4523 }
4524 PyMem_Free(buffer);
4525
4526 return result;
4527 }
4528
4529
4530 #endif /* MS_WINDOWS */
4531
4532
4533 /*[clinic input]
4534 os._path_normpath
4535
4536 path: object
4537
4538 Basic path normalization.
4539 [clinic start generated code]*/
4540
4541 static PyObject *
os__path_normpath_impl(PyObject * module,PyObject * path)4542 os__path_normpath_impl(PyObject *module, PyObject *path)
4543 /*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/
4544 {
4545 if (!PyUnicode_Check(path)) {
4546 PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'",
4547 Py_TYPE(path)->tp_name);
4548 return NULL;
4549 }
4550 Py_ssize_t len;
4551 wchar_t *buffer = PyUnicode_AsWideCharString(path, &len);
4552 if (!buffer) {
4553 return NULL;
4554 }
4555 PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1);
4556 PyMem_Free(buffer);
4557 return result;
4558 }
4559
4560 /*[clinic input]
4561 os.mkdir
4562
4563 path : path_t
4564
4565 mode: int = 0o777
4566
4567 *
4568
4569 dir_fd : dir_fd(requires='mkdirat') = None
4570
4571 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4572
4573 Create a directory.
4574
4575 If dir_fd is not None, it should be a file descriptor open to a directory,
4576 and path should be relative; path will then be relative to that directory.
4577 dir_fd may not be implemented on your platform.
4578 If it is unavailable, using it will raise a NotImplementedError.
4579
4580 The mode argument is ignored on Windows. Where it is used, the current umask
4581 value is first masked out.
4582 [clinic start generated code]*/
4583
4584 static PyObject *
os_mkdir_impl(PyObject * module,path_t * path,int mode,int dir_fd)4585 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4586 /*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
4587 {
4588 int result;
4589 #ifdef HAVE_MKDIRAT
4590 int mkdirat_unavailable = 0;
4591 #endif
4592
4593 if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4594 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4595 return NULL;
4596 }
4597
4598 #ifdef MS_WINDOWS
4599 Py_BEGIN_ALLOW_THREADS
4600 result = CreateDirectoryW(path->wide, NULL);
4601 Py_END_ALLOW_THREADS
4602
4603 if (!result)
4604 return path_error(path);
4605 #else
4606 Py_BEGIN_ALLOW_THREADS
4607 #if HAVE_MKDIRAT
4608 if (dir_fd != DEFAULT_DIR_FD) {
4609 if (HAVE_MKDIRAT_RUNTIME) {
4610 result = mkdirat(dir_fd, path->narrow, mode);
4611
4612 } else {
4613 mkdirat_unavailable = 1;
4614 }
4615 } else
4616 #endif
4617 #if defined(__WATCOMC__) && !defined(__QNX__)
4618 result = mkdir(path->narrow);
4619 #else
4620 result = mkdir(path->narrow, mode);
4621 #endif
4622 Py_END_ALLOW_THREADS
4623
4624 #if HAVE_MKDIRAT
4625 if (mkdirat_unavailable) {
4626 argument_unavailable_error(NULL, "dir_fd");
4627 return NULL;
4628 }
4629 #endif
4630
4631 if (result < 0)
4632 return path_error(path);
4633 #endif /* MS_WINDOWS */
4634 Py_RETURN_NONE;
4635 }
4636
4637
4638 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4639 #if defined(HAVE_SYS_RESOURCE_H)
4640 #include <sys/resource.h>
4641 #endif
4642
4643
4644 #ifdef HAVE_NICE
4645 /*[clinic input]
4646 os.nice
4647
4648 increment: int
4649 /
4650
4651 Add increment to the priority of process and return the new priority.
4652 [clinic start generated code]*/
4653
4654 static PyObject *
os_nice_impl(PyObject * module,int increment)4655 os_nice_impl(PyObject *module, int increment)
4656 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4657 {
4658 int value;
4659
4660 /* There are two flavours of 'nice': one that returns the new
4661 priority (as required by almost all standards out there) and the
4662 Linux/FreeBSD one, which returns '0' on success and advices
4663 the use of getpriority() to get the new priority.
4664
4665 If we are of the nice family that returns the new priority, we
4666 need to clear errno before the call, and check if errno is filled
4667 before calling posix_error() on a returnvalue of -1, because the
4668 -1 may be the actual new priority! */
4669
4670 errno = 0;
4671 value = nice(increment);
4672 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4673 if (value == 0)
4674 value = getpriority(PRIO_PROCESS, 0);
4675 #endif
4676 if (value == -1 && errno != 0)
4677 /* either nice() or getpriority() returned an error */
4678 return posix_error();
4679 return PyLong_FromLong((long) value);
4680 }
4681 #endif /* HAVE_NICE */
4682
4683
4684 #ifdef HAVE_GETPRIORITY
4685 /*[clinic input]
4686 os.getpriority
4687
4688 which: int
4689 who: int
4690
4691 Return program scheduling priority.
4692 [clinic start generated code]*/
4693
4694 static PyObject *
os_getpriority_impl(PyObject * module,int which,int who)4695 os_getpriority_impl(PyObject *module, int which, int who)
4696 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4697 {
4698 int retval;
4699
4700 errno = 0;
4701 retval = getpriority(which, who);
4702 if (errno != 0)
4703 return posix_error();
4704 return PyLong_FromLong((long)retval);
4705 }
4706 #endif /* HAVE_GETPRIORITY */
4707
4708
4709 #ifdef HAVE_SETPRIORITY
4710 /*[clinic input]
4711 os.setpriority
4712
4713 which: int
4714 who: int
4715 priority: int
4716
4717 Set program scheduling priority.
4718 [clinic start generated code]*/
4719
4720 static PyObject *
os_setpriority_impl(PyObject * module,int which,int who,int priority)4721 os_setpriority_impl(PyObject *module, int which, int who, int priority)
4722 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4723 {
4724 int retval;
4725
4726 retval = setpriority(which, who, priority);
4727 if (retval == -1)
4728 return posix_error();
4729 Py_RETURN_NONE;
4730 }
4731 #endif /* HAVE_SETPRIORITY */
4732
4733
4734 static PyObject *
internal_rename(path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int is_replace)4735 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4736 {
4737 const char *function_name = is_replace ? "replace" : "rename";
4738 int dir_fd_specified;
4739
4740 #ifdef HAVE_RENAMEAT
4741 int renameat_unavailable = 0;
4742 #endif
4743
4744 #ifdef MS_WINDOWS
4745 BOOL result;
4746 int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4747 #else
4748 int result;
4749 #endif
4750
4751 dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4752 (dst_dir_fd != DEFAULT_DIR_FD);
4753 #ifndef HAVE_RENAMEAT
4754 if (dir_fd_specified) {
4755 argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4756 return NULL;
4757 }
4758 #endif
4759
4760 if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
4761 src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4762 dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4763 return NULL;
4764 }
4765
4766 #ifdef MS_WINDOWS
4767 Py_BEGIN_ALLOW_THREADS
4768 result = MoveFileExW(src->wide, dst->wide, flags);
4769 Py_END_ALLOW_THREADS
4770
4771 if (!result)
4772 return path_error2(src, dst);
4773
4774 #else
4775 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4776 PyErr_Format(PyExc_ValueError,
4777 "%s: src and dst must be the same type", function_name);
4778 return NULL;
4779 }
4780
4781 Py_BEGIN_ALLOW_THREADS
4782 #ifdef HAVE_RENAMEAT
4783 if (dir_fd_specified) {
4784 if (HAVE_RENAMEAT_RUNTIME) {
4785 result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4786 } else {
4787 renameat_unavailable = 1;
4788 }
4789 } else
4790 #endif
4791 result = rename(src->narrow, dst->narrow);
4792 Py_END_ALLOW_THREADS
4793
4794
4795 #ifdef HAVE_RENAMEAT
4796 if (renameat_unavailable) {
4797 argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4798 return NULL;
4799 }
4800 #endif
4801
4802 if (result)
4803 return path_error2(src, dst);
4804 #endif
4805 Py_RETURN_NONE;
4806 }
4807
4808
4809 /*[clinic input]
4810 os.rename
4811
4812 src : path_t
4813 dst : path_t
4814 *
4815 src_dir_fd : dir_fd = None
4816 dst_dir_fd : dir_fd = None
4817
4818 Rename a file or directory.
4819
4820 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4821 descriptor open to a directory, and the respective path string (src or dst)
4822 should be relative; the path will then be relative to that directory.
4823 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4824 If they are unavailable, using them will raise a NotImplementedError.
4825 [clinic start generated code]*/
4826
4827 static PyObject *
os_rename_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4828 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4829 int dst_dir_fd)
4830 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4831 {
4832 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4833 }
4834
4835
4836 /*[clinic input]
4837 os.replace = os.rename
4838
4839 Rename a file or directory, overwriting the destination.
4840
4841 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4842 descriptor open to a directory, and the respective path string (src or dst)
4843 should be relative; the path will then be relative to that directory.
4844 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4845 If they are unavailable, using them will raise a NotImplementedError.
4846 [clinic start generated code]*/
4847
4848 static PyObject *
os_replace_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4849 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4850 int dst_dir_fd)
4851 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4852 {
4853 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4854 }
4855
4856
4857 /*[clinic input]
4858 os.rmdir
4859
4860 path: path_t
4861 *
4862 dir_fd: dir_fd(requires='unlinkat') = None
4863
4864 Remove a directory.
4865
4866 If dir_fd is not None, it should be a file descriptor open to a directory,
4867 and path should be relative; path will then be relative to that directory.
4868 dir_fd may not be implemented on your platform.
4869 If it is unavailable, using it will raise a NotImplementedError.
4870 [clinic start generated code]*/
4871
4872 static PyObject *
os_rmdir_impl(PyObject * module,path_t * path,int dir_fd)4873 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4874 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4875 {
4876 int result;
4877 #ifdef HAVE_UNLINKAT
4878 int unlinkat_unavailable = 0;
4879 #endif
4880
4881 if (PySys_Audit("os.rmdir", "Oi", path->object,
4882 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4883 return NULL;
4884 }
4885
4886 Py_BEGIN_ALLOW_THREADS
4887 #ifdef MS_WINDOWS
4888 /* Windows, success=1, UNIX, success=0 */
4889 result = !RemoveDirectoryW(path->wide);
4890 #else
4891 #ifdef HAVE_UNLINKAT
4892 if (dir_fd != DEFAULT_DIR_FD) {
4893 if (HAVE_UNLINKAT_RUNTIME) {
4894 result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4895 } else {
4896 unlinkat_unavailable = 1;
4897 result = -1;
4898 }
4899 } else
4900 #endif
4901 result = rmdir(path->narrow);
4902 #endif
4903 Py_END_ALLOW_THREADS
4904
4905 #ifdef HAVE_UNLINKAT
4906 if (unlinkat_unavailable) {
4907 argument_unavailable_error("rmdir", "dir_fd");
4908 return NULL;
4909 }
4910 #endif
4911
4912 if (result)
4913 return path_error(path);
4914
4915 Py_RETURN_NONE;
4916 }
4917
4918
4919 #ifdef HAVE_SYSTEM
4920 #ifdef MS_WINDOWS
4921 /*[clinic input]
4922 os.system -> long
4923
4924 command: Py_UNICODE
4925
4926 Execute the command in a subshell.
4927 [clinic start generated code]*/
4928
4929 static long
os_system_impl(PyObject * module,const Py_UNICODE * command)4930 os_system_impl(PyObject *module, const Py_UNICODE *command)
4931 /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4932 {
4933 long result;
4934
4935 if (PySys_Audit("os.system", "(u)", command) < 0) {
4936 return -1;
4937 }
4938
4939 Py_BEGIN_ALLOW_THREADS
4940 _Py_BEGIN_SUPPRESS_IPH
4941 result = _wsystem(command);
4942 _Py_END_SUPPRESS_IPH
4943 Py_END_ALLOW_THREADS
4944 return result;
4945 }
4946 #else /* MS_WINDOWS */
4947 /*[clinic input]
4948 os.system -> long
4949
4950 command: FSConverter
4951
4952 Execute the command in a subshell.
4953 [clinic start generated code]*/
4954
4955 static long
os_system_impl(PyObject * module,PyObject * command)4956 os_system_impl(PyObject *module, PyObject *command)
4957 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4958 {
4959 long result;
4960 const char *bytes = PyBytes_AsString(command);
4961
4962 if (PySys_Audit("os.system", "(O)", command) < 0) {
4963 return -1;
4964 }
4965
4966 Py_BEGIN_ALLOW_THREADS
4967 result = system(bytes);
4968 Py_END_ALLOW_THREADS
4969 return result;
4970 }
4971 #endif
4972 #endif /* HAVE_SYSTEM */
4973
4974
4975 #ifdef HAVE_UMASK
4976 /*[clinic input]
4977 os.umask
4978
4979 mask: int
4980 /
4981
4982 Set the current numeric umask and return the previous umask.
4983 [clinic start generated code]*/
4984
4985 static PyObject *
os_umask_impl(PyObject * module,int mask)4986 os_umask_impl(PyObject *module, int mask)
4987 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4988 {
4989 int i = (int)umask(mask);
4990 if (i < 0)
4991 return posix_error();
4992 return PyLong_FromLong((long)i);
4993 }
4994 #endif
4995
4996 #ifdef MS_WINDOWS
4997
4998 /* override the default DeleteFileW behavior so that directory
4999 symlinks can be removed with this function, the same as with
5000 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)5001 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
5002 {
5003 WIN32_FILE_ATTRIBUTE_DATA info;
5004 WIN32_FIND_DATAW find_data;
5005 HANDLE find_data_handle;
5006 int is_directory = 0;
5007 int is_link = 0;
5008
5009 if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
5010 is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
5011
5012 /* Get WIN32_FIND_DATA structure for the path to determine if
5013 it is a symlink */
5014 if(is_directory &&
5015 info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
5016 find_data_handle = FindFirstFileW(lpFileName, &find_data);
5017
5018 if(find_data_handle != INVALID_HANDLE_VALUE) {
5019 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
5020 IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
5021 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
5022 find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
5023 FindClose(find_data_handle);
5024 }
5025 }
5026 }
5027
5028 if (is_directory && is_link)
5029 return RemoveDirectoryW(lpFileName);
5030
5031 return DeleteFileW(lpFileName);
5032 }
5033 #endif /* MS_WINDOWS */
5034
5035
5036 /*[clinic input]
5037 os.unlink
5038
5039 path: path_t
5040 *
5041 dir_fd: dir_fd(requires='unlinkat')=None
5042
5043 Remove a file (same as remove()).
5044
5045 If dir_fd is not None, it should be a file descriptor open to a directory,
5046 and path should be relative; path will then be relative to that directory.
5047 dir_fd may not be implemented on your platform.
5048 If it is unavailable, using it will raise a NotImplementedError.
5049
5050 [clinic start generated code]*/
5051
5052 static PyObject *
os_unlink_impl(PyObject * module,path_t * path,int dir_fd)5053 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
5054 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
5055 {
5056 int result;
5057 #ifdef HAVE_UNLINKAT
5058 int unlinkat_unavailable = 0;
5059 #endif
5060
5061 if (PySys_Audit("os.remove", "Oi", path->object,
5062 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5063 return NULL;
5064 }
5065
5066 Py_BEGIN_ALLOW_THREADS
5067 _Py_BEGIN_SUPPRESS_IPH
5068 #ifdef MS_WINDOWS
5069 /* Windows, success=1, UNIX, success=0 */
5070 result = !Py_DeleteFileW(path->wide);
5071 #else
5072 #ifdef HAVE_UNLINKAT
5073 if (dir_fd != DEFAULT_DIR_FD) {
5074 if (HAVE_UNLINKAT_RUNTIME) {
5075
5076 result = unlinkat(dir_fd, path->narrow, 0);
5077 } else {
5078 unlinkat_unavailable = 1;
5079 }
5080 } else
5081 #endif /* HAVE_UNLINKAT */
5082 result = unlink(path->narrow);
5083 #endif
5084 _Py_END_SUPPRESS_IPH
5085 Py_END_ALLOW_THREADS
5086
5087 #ifdef HAVE_UNLINKAT
5088 if (unlinkat_unavailable) {
5089 argument_unavailable_error(NULL, "dir_fd");
5090 return NULL;
5091 }
5092 #endif
5093
5094 if (result)
5095 return path_error(path);
5096
5097 Py_RETURN_NONE;
5098 }
5099
5100
5101 /*[clinic input]
5102 os.remove = os.unlink
5103
5104 Remove a file (same as unlink()).
5105
5106 If dir_fd is not None, it should be a file descriptor open to a directory,
5107 and path should be relative; path will then be relative to that directory.
5108 dir_fd may not be implemented on your platform.
5109 If it is unavailable, using it will raise a NotImplementedError.
5110 [clinic start generated code]*/
5111
5112 static PyObject *
os_remove_impl(PyObject * module,path_t * path,int dir_fd)5113 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
5114 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
5115 {
5116 return os_unlink_impl(module, path, dir_fd);
5117 }
5118
5119
5120 static PyStructSequence_Field uname_result_fields[] = {
5121 {"sysname", "operating system name"},
5122 {"nodename", "name of machine on network (implementation-defined)"},
5123 {"release", "operating system release"},
5124 {"version", "operating system version"},
5125 {"machine", "hardware identifier"},
5126 {NULL}
5127 };
5128
5129 PyDoc_STRVAR(uname_result__doc__,
5130 "uname_result: Result from os.uname().\n\n\
5131 This object may be accessed either as a tuple of\n\
5132 (sysname, nodename, release, version, machine),\n\
5133 or via the attributes sysname, nodename, release, version, and machine.\n\
5134 \n\
5135 See os.uname for more information.");
5136
5137 static PyStructSequence_Desc uname_result_desc = {
5138 MODNAME ".uname_result", /* name */
5139 uname_result__doc__, /* doc */
5140 uname_result_fields,
5141 5
5142 };
5143
5144 #ifdef HAVE_UNAME
5145 /*[clinic input]
5146 os.uname
5147
5148 Return an object identifying the current operating system.
5149
5150 The object behaves like a named tuple with the following fields:
5151 (sysname, nodename, release, version, machine)
5152
5153 [clinic start generated code]*/
5154
5155 static PyObject *
os_uname_impl(PyObject * module)5156 os_uname_impl(PyObject *module)
5157 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
5158 {
5159 struct utsname u;
5160 int res;
5161 PyObject *value;
5162
5163 Py_BEGIN_ALLOW_THREADS
5164 res = uname(&u);
5165 Py_END_ALLOW_THREADS
5166 if (res < 0)
5167 return posix_error();
5168
5169 PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
5170 value = PyStructSequence_New((PyTypeObject *)UnameResultType);
5171 if (value == NULL)
5172 return NULL;
5173
5174 #define SET(i, field) \
5175 { \
5176 PyObject *o = PyUnicode_DecodeFSDefault(field); \
5177 if (!o) { \
5178 Py_DECREF(value); \
5179 return NULL; \
5180 } \
5181 PyStructSequence_SET_ITEM(value, i, o); \
5182 } \
5183
5184 SET(0, u.sysname);
5185 SET(1, u.nodename);
5186 SET(2, u.release);
5187 SET(3, u.version);
5188 SET(4, u.machine);
5189
5190 #undef SET
5191
5192 return value;
5193 }
5194 #endif /* HAVE_UNAME */
5195
5196
5197
5198 typedef struct {
5199 int now;
5200 time_t atime_s;
5201 long atime_ns;
5202 time_t mtime_s;
5203 long mtime_ns;
5204 } utime_t;
5205
5206 /*
5207 * these macros assume that "ut" is a pointer to a utime_t
5208 * they also intentionally leak the declaration of a pointer named "time"
5209 */
5210 #define UTIME_TO_TIMESPEC \
5211 struct timespec ts[2]; \
5212 struct timespec *time; \
5213 if (ut->now) \
5214 time = NULL; \
5215 else { \
5216 ts[0].tv_sec = ut->atime_s; \
5217 ts[0].tv_nsec = ut->atime_ns; \
5218 ts[1].tv_sec = ut->mtime_s; \
5219 ts[1].tv_nsec = ut->mtime_ns; \
5220 time = ts; \
5221 } \
5222
5223 #define UTIME_TO_TIMEVAL \
5224 struct timeval tv[2]; \
5225 struct timeval *time; \
5226 if (ut->now) \
5227 time = NULL; \
5228 else { \
5229 tv[0].tv_sec = ut->atime_s; \
5230 tv[0].tv_usec = ut->atime_ns / 1000; \
5231 tv[1].tv_sec = ut->mtime_s; \
5232 tv[1].tv_usec = ut->mtime_ns / 1000; \
5233 time = tv; \
5234 } \
5235
5236 #define UTIME_TO_UTIMBUF \
5237 struct utimbuf u; \
5238 struct utimbuf *time; \
5239 if (ut->now) \
5240 time = NULL; \
5241 else { \
5242 u.actime = ut->atime_s; \
5243 u.modtime = ut->mtime_s; \
5244 time = &u; \
5245 }
5246
5247 #define UTIME_TO_TIME_T \
5248 time_t timet[2]; \
5249 time_t *time; \
5250 if (ut->now) \
5251 time = NULL; \
5252 else { \
5253 timet[0] = ut->atime_s; \
5254 timet[1] = ut->mtime_s; \
5255 time = timet; \
5256 } \
5257
5258
5259 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5260
5261 static int
utime_dir_fd(utime_t * ut,int dir_fd,const char * path,int follow_symlinks)5262 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
5263 {
5264 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5265 if (HAVE_UTIMENSAT_RUNTIME) {
5266 int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5267 UTIME_TO_TIMESPEC;
5268 return utimensat(dir_fd, path, time, flags);
5269 } else {
5270 errno = ENOSYS;
5271 return -1;
5272 }
5273 #elif defined(HAVE_UTIMENSAT)
5274 int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5275 UTIME_TO_TIMESPEC;
5276 return utimensat(dir_fd, path, time, flags);
5277 #elif defined(HAVE_FUTIMESAT)
5278 UTIME_TO_TIMEVAL;
5279 /*
5280 * follow_symlinks will never be false here;
5281 * we only allow !follow_symlinks and dir_fd together
5282 * if we have utimensat()
5283 */
5284 assert(follow_symlinks);
5285 return futimesat(dir_fd, path, time);
5286 #endif
5287 }
5288
5289 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
5290 #else
5291 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
5292 #endif
5293
5294 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5295
5296 static int
utime_fd(utime_t * ut,int fd)5297 utime_fd(utime_t *ut, int fd)
5298 {
5299 #ifdef HAVE_FUTIMENS
5300
5301 if (HAVE_FUTIMENS_RUNTIME) {
5302
5303 UTIME_TO_TIMESPEC;
5304 return futimens(fd, time);
5305
5306 } else
5307 #ifndef HAVE_FUTIMES
5308 {
5309 /* Not sure if this can happen */
5310 PyErr_SetString(
5311 PyExc_RuntimeError,
5312 "neither futimens nor futimes are supported"
5313 " on this system");
5314 return -1;
5315 }
5316 #endif
5317
5318 #endif
5319 #ifdef HAVE_FUTIMES
5320 {
5321 UTIME_TO_TIMEVAL;
5322 return futimes(fd, time);
5323 }
5324 #endif
5325 }
5326
5327 #define PATH_UTIME_HAVE_FD 1
5328 #else
5329 #define PATH_UTIME_HAVE_FD 0
5330 #endif
5331
5332 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
5333 # define UTIME_HAVE_NOFOLLOW_SYMLINKS
5334 #endif
5335
5336 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5337
5338 static int
utime_nofollow_symlinks(utime_t * ut,const char * path)5339 utime_nofollow_symlinks(utime_t *ut, const char *path)
5340 {
5341 #ifdef HAVE_UTIMENSAT
5342 if (HAVE_UTIMENSAT_RUNTIME) {
5343 UTIME_TO_TIMESPEC;
5344 return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
5345 } else
5346 #ifndef HAVE_LUTIMES
5347 {
5348 /* Not sure if this can happen */
5349 PyErr_SetString(
5350 PyExc_RuntimeError,
5351 "neither utimensat nor lutimes are supported"
5352 " on this system");
5353 return -1;
5354 }
5355 #endif
5356 #endif
5357
5358 #ifdef HAVE_LUTIMES
5359 {
5360 UTIME_TO_TIMEVAL;
5361 return lutimes(path, time);
5362 }
5363 #endif
5364 }
5365
5366 #endif
5367
5368 #ifndef MS_WINDOWS
5369
5370 static int
utime_default(utime_t * ut,const char * path)5371 utime_default(utime_t *ut, const char *path)
5372 {
5373 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5374 if (HAVE_UTIMENSAT_RUNTIME) {
5375 UTIME_TO_TIMESPEC;
5376 return utimensat(DEFAULT_DIR_FD, path, time, 0);
5377 } else {
5378 UTIME_TO_TIMEVAL;
5379 return utimes(path, time);
5380 }
5381 #elif defined(HAVE_UTIMENSAT)
5382 UTIME_TO_TIMESPEC;
5383 return utimensat(DEFAULT_DIR_FD, path, time, 0);
5384 #elif defined(HAVE_UTIMES)
5385 UTIME_TO_TIMEVAL;
5386 return utimes(path, time);
5387 #elif defined(HAVE_UTIME_H)
5388 UTIME_TO_UTIMBUF;
5389 return utime(path, time);
5390 #else
5391 UTIME_TO_TIME_T;
5392 return utime(path, time);
5393 #endif
5394 }
5395
5396 #endif
5397
5398 static int
split_py_long_to_s_and_ns(PyObject * module,PyObject * py_long,time_t * s,long * ns)5399 split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5400 {
5401 int result = 0;
5402 PyObject *divmod;
5403 divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5404 if (!divmod)
5405 goto exit;
5406 if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
5407 PyErr_Format(PyExc_TypeError,
5408 "%.200s.__divmod__() must return a 2-tuple, not %.200s",
5409 _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
5410 goto exit;
5411 }
5412 *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5413 if ((*s == -1) && PyErr_Occurred())
5414 goto exit;
5415 *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5416 if ((*ns == -1) && PyErr_Occurred())
5417 goto exit;
5418
5419 result = 1;
5420 exit:
5421 Py_XDECREF(divmod);
5422 return result;
5423 }
5424
5425
5426 /*[clinic input]
5427 os.utime
5428
5429 path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
5430 times: object = None
5431 *
5432 ns: object = NULL
5433 dir_fd: dir_fd(requires='futimensat') = None
5434 follow_symlinks: bool=True
5435
5436 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
5437
5438 Set the access and modified time of path.
5439
5440 path may always be specified as a string.
5441 On some platforms, path may also be specified as an open file descriptor.
5442 If this functionality is unavailable, using it raises an exception.
5443
5444 If times is not None, it must be a tuple (atime, mtime);
5445 atime and mtime should be expressed as float seconds since the epoch.
5446 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
5447 atime_ns and mtime_ns should be expressed as integer nanoseconds
5448 since the epoch.
5449 If times is None and ns is unspecified, utime uses the current time.
5450 Specifying tuples for both times and ns is an error.
5451
5452 If dir_fd is not None, it should be a file descriptor open to a directory,
5453 and path should be relative; path will then be relative to that directory.
5454 If follow_symlinks is False, and the last element of the path is a symbolic
5455 link, utime will modify the symbolic link itself instead of the file the
5456 link points to.
5457 It is an error to use dir_fd or follow_symlinks when specifying path
5458 as an open file descriptor.
5459 dir_fd and follow_symlinks may not be available on your platform.
5460 If they are unavailable, using them will raise a NotImplementedError.
5461
5462 [clinic start generated code]*/
5463
5464 static PyObject *
os_utime_impl(PyObject * module,path_t * path,PyObject * times,PyObject * ns,int dir_fd,int follow_symlinks)5465 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
5466 int dir_fd, int follow_symlinks)
5467 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
5468 {
5469 #ifdef MS_WINDOWS
5470 HANDLE hFile;
5471 FILETIME atime, mtime;
5472 #else
5473 int result;
5474 #endif
5475
5476 utime_t utime;
5477
5478 memset(&utime, 0, sizeof(utime_t));
5479
5480 if (times != Py_None && ns) {
5481 PyErr_SetString(PyExc_ValueError,
5482 "utime: you may specify either 'times'"
5483 " or 'ns' but not both");
5484 return NULL;
5485 }
5486
5487 if (times != Py_None) {
5488 time_t a_sec, m_sec;
5489 long a_nsec, m_nsec;
5490 if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
5491 PyErr_SetString(PyExc_TypeError,
5492 "utime: 'times' must be either"
5493 " a tuple of two ints or None");
5494 return NULL;
5495 }
5496 utime.now = 0;
5497 if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
5498 &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
5499 _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
5500 &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
5501 return NULL;
5502 }
5503 utime.atime_s = a_sec;
5504 utime.atime_ns = a_nsec;
5505 utime.mtime_s = m_sec;
5506 utime.mtime_ns = m_nsec;
5507 }
5508 else if (ns) {
5509 if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
5510 PyErr_SetString(PyExc_TypeError,
5511 "utime: 'ns' must be a tuple of two ints");
5512 return NULL;
5513 }
5514 utime.now = 0;
5515 if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
5516 &utime.atime_s, &utime.atime_ns) ||
5517 !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
5518 &utime.mtime_s, &utime.mtime_ns)) {
5519 return NULL;
5520 }
5521 }
5522 else {
5523 /* times and ns are both None/unspecified. use "now". */
5524 utime.now = 1;
5525 }
5526
5527 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
5528 if (follow_symlinks_specified("utime", follow_symlinks))
5529 return NULL;
5530 #endif
5531
5532 if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
5533 dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
5534 fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
5535 return NULL;
5536
5537 #if !defined(HAVE_UTIMENSAT)
5538 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
5539 PyErr_SetString(PyExc_ValueError,
5540 "utime: cannot use dir_fd and follow_symlinks "
5541 "together on this platform");
5542 return NULL;
5543 }
5544 #endif
5545
5546 if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
5547 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5548 return NULL;
5549 }
5550
5551 #ifdef MS_WINDOWS
5552 Py_BEGIN_ALLOW_THREADS
5553 hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
5554 NULL, OPEN_EXISTING,
5555 FILE_FLAG_BACKUP_SEMANTICS, NULL);
5556 Py_END_ALLOW_THREADS
5557 if (hFile == INVALID_HANDLE_VALUE) {
5558 path_error(path);
5559 return NULL;
5560 }
5561
5562 if (utime.now) {
5563 GetSystemTimeAsFileTime(&mtime);
5564 atime = mtime;
5565 }
5566 else {
5567 _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
5568 _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
5569 }
5570 if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
5571 /* Avoid putting the file name into the error here,
5572 as that may confuse the user into believing that
5573 something is wrong with the file, when it also
5574 could be the time stamp that gives a problem. */
5575 PyErr_SetFromWindowsErr(0);
5576 CloseHandle(hFile);
5577 return NULL;
5578 }
5579 CloseHandle(hFile);
5580 #else /* MS_WINDOWS */
5581 Py_BEGIN_ALLOW_THREADS
5582
5583 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5584 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
5585 result = utime_nofollow_symlinks(&utime, path->narrow);
5586 else
5587 #endif
5588
5589 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5590 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
5591 result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
5592
5593 } else
5594 #endif
5595
5596 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5597 if (path->fd != -1)
5598 result = utime_fd(&utime, path->fd);
5599 else
5600 #endif
5601
5602 result = utime_default(&utime, path->narrow);
5603
5604 Py_END_ALLOW_THREADS
5605
5606 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5607 /* See utime_dir_fd implementation */
5608 if (result == -1 && errno == ENOSYS) {
5609 argument_unavailable_error(NULL, "dir_fd");
5610 return NULL;
5611 }
5612 #endif
5613
5614 if (result < 0) {
5615 /* see previous comment about not putting filename in error here */
5616 posix_error();
5617 return NULL;
5618 }
5619
5620 #endif /* MS_WINDOWS */
5621
5622 Py_RETURN_NONE;
5623 }
5624
5625 /* Process operations */
5626
5627
5628 /*[clinic input]
5629 os._exit
5630
5631 status: int
5632
5633 Exit to the system with specified status, without normal exit processing.
5634 [clinic start generated code]*/
5635
5636 static PyObject *
os__exit_impl(PyObject * module,int status)5637 os__exit_impl(PyObject *module, int status)
5638 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5639 {
5640 _exit(status);
5641 return NULL; /* Make gcc -Wall happy */
5642 }
5643
5644 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5645 #define EXECV_CHAR wchar_t
5646 #else
5647 #define EXECV_CHAR char
5648 #endif
5649
5650 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5651 static void
free_string_array(EXECV_CHAR ** array,Py_ssize_t count)5652 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5653 {
5654 Py_ssize_t i;
5655 for (i = 0; i < count; i++)
5656 PyMem_Free(array[i]);
5657 PyMem_Free(array);
5658 }
5659
5660 static int
fsconvert_strdup(PyObject * o,EXECV_CHAR ** out)5661 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5662 {
5663 Py_ssize_t size;
5664 PyObject *ub;
5665 int result = 0;
5666 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5667 if (!PyUnicode_FSDecoder(o, &ub))
5668 return 0;
5669 *out = PyUnicode_AsWideCharString(ub, &size);
5670 if (*out)
5671 result = 1;
5672 #else
5673 if (!PyUnicode_FSConverter(o, &ub))
5674 return 0;
5675 size = PyBytes_GET_SIZE(ub);
5676 *out = PyMem_Malloc(size + 1);
5677 if (*out) {
5678 memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5679 result = 1;
5680 } else
5681 PyErr_NoMemory();
5682 #endif
5683 Py_DECREF(ub);
5684 return result;
5685 }
5686 #endif
5687
5688 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5689 static EXECV_CHAR**
parse_envlist(PyObject * env,Py_ssize_t * envc_ptr)5690 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5691 {
5692 Py_ssize_t i, pos, envc;
5693 PyObject *keys=NULL, *vals=NULL;
5694 PyObject *key, *val, *key2, *val2, *keyval;
5695 EXECV_CHAR **envlist;
5696
5697 i = PyMapping_Size(env);
5698 if (i < 0)
5699 return NULL;
5700 envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5701 if (envlist == NULL) {
5702 PyErr_NoMemory();
5703 return NULL;
5704 }
5705 envc = 0;
5706 keys = PyMapping_Keys(env);
5707 if (!keys)
5708 goto error;
5709 vals = PyMapping_Values(env);
5710 if (!vals)
5711 goto error;
5712 if (!PyList_Check(keys) || !PyList_Check(vals)) {
5713 PyErr_Format(PyExc_TypeError,
5714 "env.keys() or env.values() is not a list");
5715 goto error;
5716 }
5717
5718 for (pos = 0; pos < i; pos++) {
5719 key = PyList_GetItem(keys, pos);
5720 val = PyList_GetItem(vals, pos);
5721 if (!key || !val)
5722 goto error;
5723
5724 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5725 if (!PyUnicode_FSDecoder(key, &key2))
5726 goto error;
5727 if (!PyUnicode_FSDecoder(val, &val2)) {
5728 Py_DECREF(key2);
5729 goto error;
5730 }
5731 /* Search from index 1 because on Windows starting '=' is allowed for
5732 defining hidden environment variables. */
5733 if (PyUnicode_GET_LENGTH(key2) == 0 ||
5734 PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5735 {
5736 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5737 Py_DECREF(key2);
5738 Py_DECREF(val2);
5739 goto error;
5740 }
5741 keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5742 #else
5743 if (!PyUnicode_FSConverter(key, &key2))
5744 goto error;
5745 if (!PyUnicode_FSConverter(val, &val2)) {
5746 Py_DECREF(key2);
5747 goto error;
5748 }
5749 if (PyBytes_GET_SIZE(key2) == 0 ||
5750 strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5751 {
5752 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5753 Py_DECREF(key2);
5754 Py_DECREF(val2);
5755 goto error;
5756 }
5757 keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5758 PyBytes_AS_STRING(val2));
5759 #endif
5760 Py_DECREF(key2);
5761 Py_DECREF(val2);
5762 if (!keyval)
5763 goto error;
5764
5765 if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5766 Py_DECREF(keyval);
5767 goto error;
5768 }
5769
5770 Py_DECREF(keyval);
5771 }
5772 Py_DECREF(vals);
5773 Py_DECREF(keys);
5774
5775 envlist[envc] = 0;
5776 *envc_ptr = envc;
5777 return envlist;
5778
5779 error:
5780 Py_XDECREF(keys);
5781 Py_XDECREF(vals);
5782 free_string_array(envlist, envc);
5783 return NULL;
5784 }
5785
5786 static EXECV_CHAR**
parse_arglist(PyObject * argv,Py_ssize_t * argc)5787 parse_arglist(PyObject* argv, Py_ssize_t *argc)
5788 {
5789 int i;
5790 EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5791 if (argvlist == NULL) {
5792 PyErr_NoMemory();
5793 return NULL;
5794 }
5795 for (i = 0; i < *argc; i++) {
5796 PyObject* item = PySequence_ITEM(argv, i);
5797 if (item == NULL)
5798 goto fail;
5799 if (!fsconvert_strdup(item, &argvlist[i])) {
5800 Py_DECREF(item);
5801 goto fail;
5802 }
5803 Py_DECREF(item);
5804 }
5805 argvlist[*argc] = NULL;
5806 return argvlist;
5807 fail:
5808 *argc = i;
5809 free_string_array(argvlist, *argc);
5810 return NULL;
5811 }
5812
5813 #endif
5814
5815
5816 #ifdef HAVE_EXECV
5817 /*[clinic input]
5818 os.execv
5819
5820 path: path_t
5821 Path of executable file.
5822 argv: object
5823 Tuple or list of strings.
5824 /
5825
5826 Execute an executable path with arguments, replacing current process.
5827 [clinic start generated code]*/
5828
5829 static PyObject *
os_execv_impl(PyObject * module,path_t * path,PyObject * argv)5830 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5831 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5832 {
5833 EXECV_CHAR **argvlist;
5834 Py_ssize_t argc;
5835
5836 /* execv has two arguments: (path, argv), where
5837 argv is a list or tuple of strings. */
5838
5839 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5840 PyErr_SetString(PyExc_TypeError,
5841 "execv() arg 2 must be a tuple or list");
5842 return NULL;
5843 }
5844 argc = PySequence_Size(argv);
5845 if (argc < 1) {
5846 PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5847 return NULL;
5848 }
5849
5850 argvlist = parse_arglist(argv, &argc);
5851 if (argvlist == NULL) {
5852 return NULL;
5853 }
5854 if (!argvlist[0][0]) {
5855 PyErr_SetString(PyExc_ValueError,
5856 "execv() arg 2 first element cannot be empty");
5857 free_string_array(argvlist, argc);
5858 return NULL;
5859 }
5860
5861 if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5862 free_string_array(argvlist, argc);
5863 return NULL;
5864 }
5865
5866 _Py_BEGIN_SUPPRESS_IPH
5867 #ifdef HAVE_WEXECV
5868 _wexecv(path->wide, argvlist);
5869 #else
5870 execv(path->narrow, argvlist);
5871 #endif
5872 _Py_END_SUPPRESS_IPH
5873
5874 /* If we get here it's definitely an error */
5875
5876 free_string_array(argvlist, argc);
5877 return posix_error();
5878 }
5879
5880
5881 /*[clinic input]
5882 os.execve
5883
5884 path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5885 Path of executable file.
5886 argv: object
5887 Tuple or list of strings.
5888 env: object
5889 Dictionary of strings mapping to strings.
5890
5891 Execute an executable path with arguments, replacing current process.
5892 [clinic start generated code]*/
5893
5894 static PyObject *
os_execve_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env)5895 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5896 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5897 {
5898 EXECV_CHAR **argvlist = NULL;
5899 EXECV_CHAR **envlist;
5900 Py_ssize_t argc, envc;
5901
5902 /* execve has three arguments: (path, argv, env), where
5903 argv is a list or tuple of strings and env is a dictionary
5904 like posix.environ. */
5905
5906 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5907 PyErr_SetString(PyExc_TypeError,
5908 "execve: argv must be a tuple or list");
5909 goto fail_0;
5910 }
5911 argc = PySequence_Size(argv);
5912 if (argc < 1) {
5913 PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5914 return NULL;
5915 }
5916
5917 if (!PyMapping_Check(env)) {
5918 PyErr_SetString(PyExc_TypeError,
5919 "execve: environment must be a mapping object");
5920 goto fail_0;
5921 }
5922
5923 argvlist = parse_arglist(argv, &argc);
5924 if (argvlist == NULL) {
5925 goto fail_0;
5926 }
5927 if (!argvlist[0][0]) {
5928 PyErr_SetString(PyExc_ValueError,
5929 "execve: argv first element cannot be empty");
5930 goto fail_0;
5931 }
5932
5933 envlist = parse_envlist(env, &envc);
5934 if (envlist == NULL)
5935 goto fail_0;
5936
5937 if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5938 goto fail_1;
5939 }
5940
5941 _Py_BEGIN_SUPPRESS_IPH
5942 #ifdef HAVE_FEXECVE
5943 if (path->fd > -1)
5944 fexecve(path->fd, argvlist, envlist);
5945 else
5946 #endif
5947 #ifdef HAVE_WEXECV
5948 _wexecve(path->wide, argvlist, envlist);
5949 #else
5950 execve(path->narrow, argvlist, envlist);
5951 #endif
5952 _Py_END_SUPPRESS_IPH
5953
5954 /* If we get here it's definitely an error */
5955
5956 posix_path_error(path);
5957 fail_1:
5958 free_string_array(envlist, envc);
5959 fail_0:
5960 if (argvlist)
5961 free_string_array(argvlist, argc);
5962 return NULL;
5963 }
5964
5965 #endif /* HAVE_EXECV */
5966
5967 #ifdef HAVE_POSIX_SPAWN
5968
5969 enum posix_spawn_file_actions_identifier {
5970 POSIX_SPAWN_OPEN,
5971 POSIX_SPAWN_CLOSE,
5972 POSIX_SPAWN_DUP2
5973 };
5974
5975 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
5976 static int
5977 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
5978 #endif
5979
5980 static int
parse_posix_spawn_flags(PyObject * module,const char * func_name,PyObject * setpgroup,int resetids,int setsid,PyObject * setsigmask,PyObject * setsigdef,PyObject * scheduler,posix_spawnattr_t * attrp)5981 parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
5982 int resetids, int setsid, PyObject *setsigmask,
5983 PyObject *setsigdef, PyObject *scheduler,
5984 posix_spawnattr_t *attrp)
5985 {
5986 long all_flags = 0;
5987
5988 errno = posix_spawnattr_init(attrp);
5989 if (errno) {
5990 posix_error();
5991 return -1;
5992 }
5993
5994 if (setpgroup) {
5995 pid_t pgid = PyLong_AsPid(setpgroup);
5996 if (pgid == (pid_t)-1 && PyErr_Occurred()) {
5997 goto fail;
5998 }
5999 errno = posix_spawnattr_setpgroup(attrp, pgid);
6000 if (errno) {
6001 posix_error();
6002 goto fail;
6003 }
6004 all_flags |= POSIX_SPAWN_SETPGROUP;
6005 }
6006
6007 if (resetids) {
6008 all_flags |= POSIX_SPAWN_RESETIDS;
6009 }
6010
6011 if (setsid) {
6012 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
6013 if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
6014 #endif
6015 #ifdef POSIX_SPAWN_SETSID
6016 all_flags |= POSIX_SPAWN_SETSID;
6017 #elif defined(POSIX_SPAWN_SETSID_NP)
6018 all_flags |= POSIX_SPAWN_SETSID_NP;
6019 #else
6020 argument_unavailable_error(func_name, "setsid");
6021 return -1;
6022 #endif
6023
6024 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
6025 } else {
6026 argument_unavailable_error(func_name, "setsid");
6027 return -1;
6028 }
6029 #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
6030
6031 }
6032
6033 #ifdef HAVE_SIGSET_T
6034 if (setsigmask) {
6035 sigset_t set;
6036 if (!_Py_Sigset_Converter(setsigmask, &set)) {
6037 goto fail;
6038 }
6039 errno = posix_spawnattr_setsigmask(attrp, &set);
6040 if (errno) {
6041 posix_error();
6042 goto fail;
6043 }
6044 all_flags |= POSIX_SPAWN_SETSIGMASK;
6045 }
6046
6047 if (setsigdef) {
6048 sigset_t set;
6049 if (!_Py_Sigset_Converter(setsigdef, &set)) {
6050 goto fail;
6051 }
6052 errno = posix_spawnattr_setsigdefault(attrp, &set);
6053 if (errno) {
6054 posix_error();
6055 goto fail;
6056 }
6057 all_flags |= POSIX_SPAWN_SETSIGDEF;
6058 }
6059 #else
6060 if (setsigmask || setsigdef) {
6061 PyErr_SetString(PyExc_NotImplementedError,
6062 "sigset is not supported on this platform");
6063 goto fail;
6064 }
6065 #endif
6066
6067 if (scheduler) {
6068 #ifdef POSIX_SPAWN_SETSCHEDULER
6069 PyObject *py_schedpolicy;
6070 PyObject *schedparam_obj;
6071 struct sched_param schedparam;
6072
6073 if (!PyArg_ParseTuple(scheduler, "OO"
6074 ";A scheduler tuple must have two elements",
6075 &py_schedpolicy, &schedparam_obj)) {
6076 goto fail;
6077 }
6078 if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
6079 goto fail;
6080 }
6081 if (py_schedpolicy != Py_None) {
6082 int schedpolicy = _PyLong_AsInt(py_schedpolicy);
6083
6084 if (schedpolicy == -1 && PyErr_Occurred()) {
6085 goto fail;
6086 }
6087 errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
6088 if (errno) {
6089 posix_error();
6090 goto fail;
6091 }
6092 all_flags |= POSIX_SPAWN_SETSCHEDULER;
6093 }
6094 errno = posix_spawnattr_setschedparam(attrp, &schedparam);
6095 if (errno) {
6096 posix_error();
6097 goto fail;
6098 }
6099 all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
6100 #else
6101 PyErr_SetString(PyExc_NotImplementedError,
6102 "The scheduler option is not supported in this system.");
6103 goto fail;
6104 #endif
6105 }
6106
6107 errno = posix_spawnattr_setflags(attrp, all_flags);
6108 if (errno) {
6109 posix_error();
6110 goto fail;
6111 }
6112
6113 return 0;
6114
6115 fail:
6116 (void)posix_spawnattr_destroy(attrp);
6117 return -1;
6118 }
6119
6120 static int
parse_file_actions(PyObject * file_actions,posix_spawn_file_actions_t * file_actionsp,PyObject * temp_buffer)6121 parse_file_actions(PyObject *file_actions,
6122 posix_spawn_file_actions_t *file_actionsp,
6123 PyObject *temp_buffer)
6124 {
6125 PyObject *seq;
6126 PyObject *file_action = NULL;
6127 PyObject *tag_obj;
6128
6129 seq = PySequence_Fast(file_actions,
6130 "file_actions must be a sequence or None");
6131 if (seq == NULL) {
6132 return -1;
6133 }
6134
6135 errno = posix_spawn_file_actions_init(file_actionsp);
6136 if (errno) {
6137 posix_error();
6138 Py_DECREF(seq);
6139 return -1;
6140 }
6141
6142 for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
6143 file_action = PySequence_Fast_GET_ITEM(seq, i);
6144 Py_INCREF(file_action);
6145 if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
6146 PyErr_SetString(PyExc_TypeError,
6147 "Each file_actions element must be a non-empty tuple");
6148 goto fail;
6149 }
6150 long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
6151 if (tag == -1 && PyErr_Occurred()) {
6152 goto fail;
6153 }
6154
6155 /* Populate the file_actions object */
6156 switch (tag) {
6157 case POSIX_SPAWN_OPEN: {
6158 int fd, oflag;
6159 PyObject *path;
6160 unsigned long mode;
6161 if (!PyArg_ParseTuple(file_action, "OiO&ik"
6162 ";A open file_action tuple must have 5 elements",
6163 &tag_obj, &fd, PyUnicode_FSConverter, &path,
6164 &oflag, &mode))
6165 {
6166 goto fail;
6167 }
6168 if (PyList_Append(temp_buffer, path)) {
6169 Py_DECREF(path);
6170 goto fail;
6171 }
6172 errno = posix_spawn_file_actions_addopen(file_actionsp,
6173 fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
6174 Py_DECREF(path);
6175 if (errno) {
6176 posix_error();
6177 goto fail;
6178 }
6179 break;
6180 }
6181 case POSIX_SPAWN_CLOSE: {
6182 int fd;
6183 if (!PyArg_ParseTuple(file_action, "Oi"
6184 ";A close file_action tuple must have 2 elements",
6185 &tag_obj, &fd))
6186 {
6187 goto fail;
6188 }
6189 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
6190 if (errno) {
6191 posix_error();
6192 goto fail;
6193 }
6194 break;
6195 }
6196 case POSIX_SPAWN_DUP2: {
6197 int fd1, fd2;
6198 if (!PyArg_ParseTuple(file_action, "Oii"
6199 ";A dup2 file_action tuple must have 3 elements",
6200 &tag_obj, &fd1, &fd2))
6201 {
6202 goto fail;
6203 }
6204 errno = posix_spawn_file_actions_adddup2(file_actionsp,
6205 fd1, fd2);
6206 if (errno) {
6207 posix_error();
6208 goto fail;
6209 }
6210 break;
6211 }
6212 default: {
6213 PyErr_SetString(PyExc_TypeError,
6214 "Unknown file_actions identifier");
6215 goto fail;
6216 }
6217 }
6218 Py_DECREF(file_action);
6219 }
6220
6221 Py_DECREF(seq);
6222 return 0;
6223
6224 fail:
6225 Py_DECREF(seq);
6226 Py_DECREF(file_action);
6227 (void)posix_spawn_file_actions_destroy(file_actionsp);
6228 return -1;
6229 }
6230
6231
6232 static PyObject *
py_posix_spawn(int use_posix_spawnp,PyObject * module,path_t * path,PyObject * argv,PyObject * env,PyObject * file_actions,PyObject * setpgroup,int resetids,int setsid,PyObject * setsigmask,PyObject * setsigdef,PyObject * scheduler)6233 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
6234 PyObject *env, PyObject *file_actions,
6235 PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
6236 PyObject *setsigdef, PyObject *scheduler)
6237 {
6238 const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
6239 EXECV_CHAR **argvlist = NULL;
6240 EXECV_CHAR **envlist = NULL;
6241 posix_spawn_file_actions_t file_actions_buf;
6242 posix_spawn_file_actions_t *file_actionsp = NULL;
6243 posix_spawnattr_t attr;
6244 posix_spawnattr_t *attrp = NULL;
6245 Py_ssize_t argc, envc;
6246 PyObject *result = NULL;
6247 PyObject *temp_buffer = NULL;
6248 pid_t pid;
6249 int err_code;
6250
6251 /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
6252 argv is a list or tuple of strings and env is a dictionary
6253 like posix.environ. */
6254
6255 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6256 PyErr_Format(PyExc_TypeError,
6257 "%s: argv must be a tuple or list", func_name);
6258 goto exit;
6259 }
6260 argc = PySequence_Size(argv);
6261 if (argc < 1) {
6262 PyErr_Format(PyExc_ValueError,
6263 "%s: argv must not be empty", func_name);
6264 return NULL;
6265 }
6266
6267 if (!PyMapping_Check(env)) {
6268 PyErr_Format(PyExc_TypeError,
6269 "%s: environment must be a mapping object", func_name);
6270 goto exit;
6271 }
6272
6273 argvlist = parse_arglist(argv, &argc);
6274 if (argvlist == NULL) {
6275 goto exit;
6276 }
6277 if (!argvlist[0][0]) {
6278 PyErr_Format(PyExc_ValueError,
6279 "%s: argv first element cannot be empty", func_name);
6280 goto exit;
6281 }
6282
6283 envlist = parse_envlist(env, &envc);
6284 if (envlist == NULL) {
6285 goto exit;
6286 }
6287
6288 if (file_actions != NULL && file_actions != Py_None) {
6289 /* There is a bug in old versions of glibc that makes some of the
6290 * helper functions for manipulating file actions not copy the provided
6291 * buffers. The problem is that posix_spawn_file_actions_addopen does not
6292 * copy the value of path for some old versions of glibc (<2.20).
6293 * The use of temp_buffer here is a workaround that keeps the
6294 * python objects that own the buffers alive until posix_spawn gets called.
6295 * Check https://bugs.python.org/issue33630 and
6296 * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
6297 temp_buffer = PyList_New(0);
6298 if (!temp_buffer) {
6299 goto exit;
6300 }
6301 if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
6302 goto exit;
6303 }
6304 file_actionsp = &file_actions_buf;
6305 }
6306
6307 if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
6308 setsigmask, setsigdef, scheduler, &attr)) {
6309 goto exit;
6310 }
6311 attrp = &attr;
6312
6313 if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
6314 goto exit;
6315 }
6316
6317 _Py_BEGIN_SUPPRESS_IPH
6318 #ifdef HAVE_POSIX_SPAWNP
6319 if (use_posix_spawnp) {
6320 err_code = posix_spawnp(&pid, path->narrow,
6321 file_actionsp, attrp, argvlist, envlist);
6322 }
6323 else
6324 #endif /* HAVE_POSIX_SPAWNP */
6325 {
6326 err_code = posix_spawn(&pid, path->narrow,
6327 file_actionsp, attrp, argvlist, envlist);
6328 }
6329 _Py_END_SUPPRESS_IPH
6330
6331 if (err_code) {
6332 errno = err_code;
6333 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
6334 goto exit;
6335 }
6336 #ifdef _Py_MEMORY_SANITIZER
6337 __msan_unpoison(&pid, sizeof(pid));
6338 #endif
6339 result = PyLong_FromPid(pid);
6340
6341 exit:
6342 if (file_actionsp) {
6343 (void)posix_spawn_file_actions_destroy(file_actionsp);
6344 }
6345 if (attrp) {
6346 (void)posix_spawnattr_destroy(attrp);
6347 }
6348 if (envlist) {
6349 free_string_array(envlist, envc);
6350 }
6351 if (argvlist) {
6352 free_string_array(argvlist, argc);
6353 }
6354 Py_XDECREF(temp_buffer);
6355 return result;
6356 }
6357
6358
6359 /*[clinic input]
6360
6361 os.posix_spawn
6362 path: path_t
6363 Path of executable file.
6364 argv: object
6365 Tuple or list of strings.
6366 env: object
6367 Dictionary of strings mapping to strings.
6368 /
6369 *
6370 file_actions: object(c_default='NULL') = ()
6371 A sequence of file action tuples.
6372 setpgroup: object = NULL
6373 The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6374 resetids: bool(accept={int}) = False
6375 If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
6376 setsid: bool(accept={int}) = False
6377 If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6378 setsigmask: object(c_default='NULL') = ()
6379 The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6380 setsigdef: object(c_default='NULL') = ()
6381 The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6382 scheduler: object = NULL
6383 A tuple with the scheduler policy (optional) and parameters.
6384
6385 Execute the program specified by path in a new process.
6386 [clinic start generated code]*/
6387
6388 static PyObject *
os_posix_spawn_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env,PyObject * file_actions,PyObject * setpgroup,int resetids,int setsid,PyObject * setsigmask,PyObject * setsigdef,PyObject * scheduler)6389 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
6390 PyObject *env, PyObject *file_actions,
6391 PyObject *setpgroup, int resetids, int setsid,
6392 PyObject *setsigmask, PyObject *setsigdef,
6393 PyObject *scheduler)
6394 /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
6395 {
6396 return py_posix_spawn(0, module, path, argv, env, file_actions,
6397 setpgroup, resetids, setsid, setsigmask, setsigdef,
6398 scheduler);
6399 }
6400 #endif /* HAVE_POSIX_SPAWN */
6401
6402
6403
6404 #ifdef HAVE_POSIX_SPAWNP
6405 /*[clinic input]
6406
6407 os.posix_spawnp
6408 path: path_t
6409 Path of executable file.
6410 argv: object
6411 Tuple or list of strings.
6412 env: object
6413 Dictionary of strings mapping to strings.
6414 /
6415 *
6416 file_actions: object(c_default='NULL') = ()
6417 A sequence of file action tuples.
6418 setpgroup: object = NULL
6419 The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6420 resetids: bool(accept={int}) = False
6421 If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
6422 setsid: bool(accept={int}) = False
6423 If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6424 setsigmask: object(c_default='NULL') = ()
6425 The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6426 setsigdef: object(c_default='NULL') = ()
6427 The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6428 scheduler: object = NULL
6429 A tuple with the scheduler policy (optional) and parameters.
6430
6431 Execute the program specified by path in a new process.
6432 [clinic start generated code]*/
6433
6434 static PyObject *
os_posix_spawnp_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env,PyObject * file_actions,PyObject * setpgroup,int resetids,int setsid,PyObject * setsigmask,PyObject * setsigdef,PyObject * scheduler)6435 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
6436 PyObject *env, PyObject *file_actions,
6437 PyObject *setpgroup, int resetids, int setsid,
6438 PyObject *setsigmask, PyObject *setsigdef,
6439 PyObject *scheduler)
6440 /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
6441 {
6442 return py_posix_spawn(1, module, path, argv, env, file_actions,
6443 setpgroup, resetids, setsid, setsigmask, setsigdef,
6444 scheduler);
6445 }
6446 #endif /* HAVE_POSIX_SPAWNP */
6447
6448 #ifdef HAVE_RTPSPAWN
6449 static intptr_t
_rtp_spawn(int mode,const char * rtpFileName,const char * argv[],const char * envp[])6450 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
6451 const char *envp[])
6452 {
6453 RTP_ID rtpid;
6454 int status;
6455 pid_t res;
6456 int async_err = 0;
6457
6458 /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
6459 uStackSize=0 cannot be used, the default stack size is too small for
6460 Python. */
6461 if (envp) {
6462 rtpid = rtpSpawn(rtpFileName, argv, envp,
6463 100, 0x1000000, 0, VX_FP_TASK);
6464 }
6465 else {
6466 rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
6467 100, 0x1000000, 0, VX_FP_TASK);
6468 }
6469 if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
6470 do {
6471 res = waitpid((pid_t)rtpid, &status, 0);
6472 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6473
6474 if (res < 0)
6475 return RTP_ID_ERROR;
6476 return ((intptr_t)status);
6477 }
6478 return ((intptr_t)rtpid);
6479 }
6480 #endif
6481
6482 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
6483 /*[clinic input]
6484 os.spawnv
6485
6486 mode: int
6487 Mode of process creation.
6488 path: path_t
6489 Path of executable file.
6490 argv: object
6491 Tuple or list of strings.
6492 /
6493
6494 Execute the program specified by path in a new process.
6495 [clinic start generated code]*/
6496
6497 static PyObject *
os_spawnv_impl(PyObject * module,int mode,path_t * path,PyObject * argv)6498 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
6499 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
6500 {
6501 EXECV_CHAR **argvlist;
6502 int i;
6503 Py_ssize_t argc;
6504 intptr_t spawnval;
6505 PyObject *(*getitem)(PyObject *, Py_ssize_t);
6506
6507 /* spawnv has three arguments: (mode, path, argv), where
6508 argv is a list or tuple of strings. */
6509
6510 if (PyList_Check(argv)) {
6511 argc = PyList_Size(argv);
6512 getitem = PyList_GetItem;
6513 }
6514 else if (PyTuple_Check(argv)) {
6515 argc = PyTuple_Size(argv);
6516 getitem = PyTuple_GetItem;
6517 }
6518 else {
6519 PyErr_SetString(PyExc_TypeError,
6520 "spawnv() arg 2 must be a tuple or list");
6521 return NULL;
6522 }
6523 if (argc == 0) {
6524 PyErr_SetString(PyExc_ValueError,
6525 "spawnv() arg 2 cannot be empty");
6526 return NULL;
6527 }
6528
6529 argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6530 if (argvlist == NULL) {
6531 return PyErr_NoMemory();
6532 }
6533 for (i = 0; i < argc; i++) {
6534 if (!fsconvert_strdup((*getitem)(argv, i),
6535 &argvlist[i])) {
6536 free_string_array(argvlist, i);
6537 PyErr_SetString(
6538 PyExc_TypeError,
6539 "spawnv() arg 2 must contain only strings");
6540 return NULL;
6541 }
6542 if (i == 0 && !argvlist[0][0]) {
6543 free_string_array(argvlist, i + 1);
6544 PyErr_SetString(
6545 PyExc_ValueError,
6546 "spawnv() arg 2 first element cannot be empty");
6547 return NULL;
6548 }
6549 }
6550 argvlist[argc] = NULL;
6551
6552 #if !defined(HAVE_RTPSPAWN)
6553 if (mode == _OLD_P_OVERLAY)
6554 mode = _P_OVERLAY;
6555 #endif
6556
6557 if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
6558 Py_None) < 0) {
6559 free_string_array(argvlist, argc);
6560 return NULL;
6561 }
6562
6563 Py_BEGIN_ALLOW_THREADS
6564 _Py_BEGIN_SUPPRESS_IPH
6565 #ifdef HAVE_WSPAWNV
6566 spawnval = _wspawnv(mode, path->wide, argvlist);
6567 #elif defined(HAVE_RTPSPAWN)
6568 spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
6569 #else
6570 spawnval = _spawnv(mode, path->narrow, argvlist);
6571 #endif
6572 _Py_END_SUPPRESS_IPH
6573 Py_END_ALLOW_THREADS
6574
6575 free_string_array(argvlist, argc);
6576
6577 if (spawnval == -1)
6578 return posix_error();
6579 else
6580 return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6581 }
6582
6583 /*[clinic input]
6584 os.spawnve
6585
6586 mode: int
6587 Mode of process creation.
6588 path: path_t
6589 Path of executable file.
6590 argv: object
6591 Tuple or list of strings.
6592 env: object
6593 Dictionary of strings mapping to strings.
6594 /
6595
6596 Execute the program specified by path in a new process.
6597 [clinic start generated code]*/
6598
6599 static PyObject *
os_spawnve_impl(PyObject * module,int mode,path_t * path,PyObject * argv,PyObject * env)6600 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
6601 PyObject *env)
6602 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
6603 {
6604 EXECV_CHAR **argvlist;
6605 EXECV_CHAR **envlist;
6606 PyObject *res = NULL;
6607 Py_ssize_t argc, i, envc;
6608 intptr_t spawnval;
6609 PyObject *(*getitem)(PyObject *, Py_ssize_t);
6610 Py_ssize_t lastarg = 0;
6611
6612 /* spawnve has four arguments: (mode, path, argv, env), where
6613 argv is a list or tuple of strings and env is a dictionary
6614 like posix.environ. */
6615
6616 if (PyList_Check(argv)) {
6617 argc = PyList_Size(argv);
6618 getitem = PyList_GetItem;
6619 }
6620 else if (PyTuple_Check(argv)) {
6621 argc = PyTuple_Size(argv);
6622 getitem = PyTuple_GetItem;
6623 }
6624 else {
6625 PyErr_SetString(PyExc_TypeError,
6626 "spawnve() arg 2 must be a tuple or list");
6627 goto fail_0;
6628 }
6629 if (argc == 0) {
6630 PyErr_SetString(PyExc_ValueError,
6631 "spawnve() arg 2 cannot be empty");
6632 goto fail_0;
6633 }
6634 if (!PyMapping_Check(env)) {
6635 PyErr_SetString(PyExc_TypeError,
6636 "spawnve() arg 3 must be a mapping object");
6637 goto fail_0;
6638 }
6639
6640 argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6641 if (argvlist == NULL) {
6642 PyErr_NoMemory();
6643 goto fail_0;
6644 }
6645 for (i = 0; i < argc; i++) {
6646 if (!fsconvert_strdup((*getitem)(argv, i),
6647 &argvlist[i]))
6648 {
6649 lastarg = i;
6650 goto fail_1;
6651 }
6652 if (i == 0 && !argvlist[0][0]) {
6653 lastarg = i + 1;
6654 PyErr_SetString(
6655 PyExc_ValueError,
6656 "spawnv() arg 2 first element cannot be empty");
6657 goto fail_1;
6658 }
6659 }
6660 lastarg = argc;
6661 argvlist[argc] = NULL;
6662
6663 envlist = parse_envlist(env, &envc);
6664 if (envlist == NULL)
6665 goto fail_1;
6666
6667 #if !defined(HAVE_RTPSPAWN)
6668 if (mode == _OLD_P_OVERLAY)
6669 mode = _P_OVERLAY;
6670 #endif
6671
6672 if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6673 goto fail_2;
6674 }
6675
6676 Py_BEGIN_ALLOW_THREADS
6677 _Py_BEGIN_SUPPRESS_IPH
6678 #ifdef HAVE_WSPAWNV
6679 spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6680 #elif defined(HAVE_RTPSPAWN)
6681 spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6682 (const char **)envlist);
6683 #else
6684 spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6685 #endif
6686 _Py_END_SUPPRESS_IPH
6687 Py_END_ALLOW_THREADS
6688
6689 if (spawnval == -1)
6690 (void) posix_error();
6691 else
6692 res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6693
6694 fail_2:
6695 while (--envc >= 0) {
6696 PyMem_Free(envlist[envc]);
6697 }
6698 PyMem_Free(envlist);
6699 fail_1:
6700 free_string_array(argvlist, lastarg);
6701 fail_0:
6702 return res;
6703 }
6704
6705 #endif /* HAVE_SPAWNV */
6706
6707 #ifdef HAVE_FORK
6708
6709 /* Helper function to validate arguments.
6710 Returns 0 on success. non-zero on failure with a TypeError raised.
6711 If obj is non-NULL it must be callable. */
6712 static int
check_null_or_callable(PyObject * obj,const char * obj_name)6713 check_null_or_callable(PyObject *obj, const char* obj_name)
6714 {
6715 if (obj && !PyCallable_Check(obj)) {
6716 PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6717 obj_name, _PyType_Name(Py_TYPE(obj)));
6718 return -1;
6719 }
6720 return 0;
6721 }
6722
6723 /*[clinic input]
6724 os.register_at_fork
6725
6726 *
6727 before: object=NULL
6728 A callable to be called in the parent before the fork() syscall.
6729 after_in_child: object=NULL
6730 A callable to be called in the child after fork().
6731 after_in_parent: object=NULL
6732 A callable to be called in the parent after fork().
6733
6734 Register callables to be called when forking a new process.
6735
6736 'before' callbacks are called in reverse order.
6737 'after_in_child' and 'after_in_parent' callbacks are called in order.
6738
6739 [clinic start generated code]*/
6740
6741 static PyObject *
os_register_at_fork_impl(PyObject * module,PyObject * before,PyObject * after_in_child,PyObject * after_in_parent)6742 os_register_at_fork_impl(PyObject *module, PyObject *before,
6743 PyObject *after_in_child, PyObject *after_in_parent)
6744 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6745 {
6746 PyInterpreterState *interp;
6747
6748 if (!before && !after_in_child && !after_in_parent) {
6749 PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6750 return NULL;
6751 }
6752 if (check_null_or_callable(before, "before") ||
6753 check_null_or_callable(after_in_child, "after_in_child") ||
6754 check_null_or_callable(after_in_parent, "after_in_parent")) {
6755 return NULL;
6756 }
6757 interp = _PyInterpreterState_GET();
6758
6759 if (register_at_forker(&interp->before_forkers, before)) {
6760 return NULL;
6761 }
6762 if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6763 return NULL;
6764 }
6765 if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6766 return NULL;
6767 }
6768 Py_RETURN_NONE;
6769 }
6770 #endif /* HAVE_FORK */
6771
6772
6773 #ifdef HAVE_FORK1
6774 /*[clinic input]
6775 os.fork1
6776
6777 Fork a child process with a single multiplexed (i.e., not bound) thread.
6778
6779 Return 0 to child process and PID of child to parent process.
6780 [clinic start generated code]*/
6781
6782 static PyObject *
os_fork1_impl(PyObject * module)6783 os_fork1_impl(PyObject *module)
6784 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6785 {
6786 pid_t pid;
6787
6788 if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
6789 PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6790 return NULL;
6791 }
6792 PyOS_BeforeFork();
6793 pid = fork1();
6794 if (pid == 0) {
6795 /* child: this clobbers and resets the import lock. */
6796 PyOS_AfterFork_Child();
6797 } else {
6798 /* parent: release the import lock. */
6799 PyOS_AfterFork_Parent();
6800 }
6801 if (pid == -1)
6802 return posix_error();
6803 return PyLong_FromPid(pid);
6804 }
6805 #endif /* HAVE_FORK1 */
6806
6807
6808 #ifdef HAVE_FORK
6809 /*[clinic input]
6810 os.fork
6811
6812 Fork a child process.
6813
6814 Return 0 to child process and PID of child to parent process.
6815 [clinic start generated code]*/
6816
6817 static PyObject *
os_fork_impl(PyObject * module)6818 os_fork_impl(PyObject *module)
6819 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6820 {
6821 pid_t pid;
6822 PyInterpreterState *interp = _PyInterpreterState_GET();
6823 if (interp->config._isolated_interpreter) {
6824 PyErr_SetString(PyExc_RuntimeError,
6825 "fork not supported for isolated subinterpreters");
6826 return NULL;
6827 }
6828 if (PySys_Audit("os.fork", NULL) < 0) {
6829 return NULL;
6830 }
6831 PyOS_BeforeFork();
6832 pid = fork();
6833 if (pid == 0) {
6834 /* child: this clobbers and resets the import lock. */
6835 PyOS_AfterFork_Child();
6836 } else {
6837 /* parent: release the import lock. */
6838 PyOS_AfterFork_Parent();
6839 }
6840 if (pid == -1)
6841 return posix_error();
6842 return PyLong_FromPid(pid);
6843 }
6844 #endif /* HAVE_FORK */
6845
6846
6847 #ifdef HAVE_SCHED_H
6848 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6849 /*[clinic input]
6850 os.sched_get_priority_max
6851
6852 policy: int
6853
6854 Get the maximum scheduling priority for policy.
6855 [clinic start generated code]*/
6856
6857 static PyObject *
os_sched_get_priority_max_impl(PyObject * module,int policy)6858 os_sched_get_priority_max_impl(PyObject *module, int policy)
6859 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6860 {
6861 int max;
6862
6863 max = sched_get_priority_max(policy);
6864 if (max < 0)
6865 return posix_error();
6866 return PyLong_FromLong(max);
6867 }
6868
6869
6870 /*[clinic input]
6871 os.sched_get_priority_min
6872
6873 policy: int
6874
6875 Get the minimum scheduling priority for policy.
6876 [clinic start generated code]*/
6877
6878 static PyObject *
os_sched_get_priority_min_impl(PyObject * module,int policy)6879 os_sched_get_priority_min_impl(PyObject *module, int policy)
6880 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6881 {
6882 int min = sched_get_priority_min(policy);
6883 if (min < 0)
6884 return posix_error();
6885 return PyLong_FromLong(min);
6886 }
6887 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6888
6889
6890 #ifdef HAVE_SCHED_SETSCHEDULER
6891 /*[clinic input]
6892 os.sched_getscheduler
6893 pid: pid_t
6894 /
6895
6896 Get the scheduling policy for the process identified by pid.
6897
6898 Passing 0 for pid returns the scheduling policy for the calling process.
6899 [clinic start generated code]*/
6900
6901 static PyObject *
os_sched_getscheduler_impl(PyObject * module,pid_t pid)6902 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6903 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
6904 {
6905 int policy;
6906
6907 policy = sched_getscheduler(pid);
6908 if (policy < 0)
6909 return posix_error();
6910 return PyLong_FromLong(policy);
6911 }
6912 #endif /* HAVE_SCHED_SETSCHEDULER */
6913
6914
6915 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6916 /*[clinic input]
6917 class os.sched_param "PyObject *" "SchedParamType"
6918
6919 @classmethod
6920 os.sched_param.__new__
6921
6922 sched_priority: object
6923 A scheduling parameter.
6924
6925 Currently has only one field: sched_priority
6926 [clinic start generated code]*/
6927
6928 static PyObject *
os_sched_param_impl(PyTypeObject * type,PyObject * sched_priority)6929 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6930 /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
6931 {
6932 PyObject *res;
6933
6934 res = PyStructSequence_New(type);
6935 if (!res)
6936 return NULL;
6937 Py_INCREF(sched_priority);
6938 PyStructSequence_SET_ITEM(res, 0, sched_priority);
6939 return res;
6940 }
6941
6942 PyDoc_VAR(os_sched_param__doc__);
6943
6944 static PyStructSequence_Field sched_param_fields[] = {
6945 {"sched_priority", "the scheduling priority"},
6946 {0}
6947 };
6948
6949 static PyStructSequence_Desc sched_param_desc = {
6950 "sched_param", /* name */
6951 os_sched_param__doc__, /* doc */
6952 sched_param_fields,
6953 1
6954 };
6955
6956 static int
convert_sched_param(PyObject * module,PyObject * param,struct sched_param * res)6957 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
6958 {
6959 long priority;
6960
6961 if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
6962 PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
6963 return 0;
6964 }
6965 priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
6966 if (priority == -1 && PyErr_Occurred())
6967 return 0;
6968 if (priority > INT_MAX || priority < INT_MIN) {
6969 PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
6970 return 0;
6971 }
6972 res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
6973 return 1;
6974 }
6975 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
6976
6977
6978 #ifdef HAVE_SCHED_SETSCHEDULER
6979 /*[clinic input]
6980 os.sched_setscheduler
6981
6982 pid: pid_t
6983 policy: int
6984 param as param_obj: object
6985 /
6986
6987 Set the scheduling policy for the process identified by pid.
6988
6989 If pid is 0, the calling process is changed.
6990 param is an instance of sched_param.
6991 [clinic start generated code]*/
6992
6993 static PyObject *
os_sched_setscheduler_impl(PyObject * module,pid_t pid,int policy,PyObject * param_obj)6994 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
6995 PyObject *param_obj)
6996 /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
6997 {
6998 struct sched_param param;
6999 if (!convert_sched_param(module, param_obj, ¶m)) {
7000 return NULL;
7001 }
7002
7003 /*
7004 ** sched_setscheduler() returns 0 in Linux, but the previous
7005 ** scheduling policy under Solaris/Illumos, and others.
7006 ** On error, -1 is returned in all Operating Systems.
7007 */
7008 if (sched_setscheduler(pid, policy, ¶m) == -1)
7009 return posix_error();
7010 Py_RETURN_NONE;
7011 }
7012 #endif /* HAVE_SCHED_SETSCHEDULER*/
7013
7014
7015 #ifdef HAVE_SCHED_SETPARAM
7016 /*[clinic input]
7017 os.sched_getparam
7018 pid: pid_t
7019 /
7020
7021 Returns scheduling parameters for the process identified by pid.
7022
7023 If pid is 0, returns parameters for the calling process.
7024 Return value is an instance of sched_param.
7025 [clinic start generated code]*/
7026
7027 static PyObject *
os_sched_getparam_impl(PyObject * module,pid_t pid)7028 os_sched_getparam_impl(PyObject *module, pid_t pid)
7029 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
7030 {
7031 struct sched_param param;
7032 PyObject *result;
7033 PyObject *priority;
7034
7035 if (sched_getparam(pid, ¶m))
7036 return posix_error();
7037 PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
7038 result = PyStructSequence_New((PyTypeObject *)SchedParamType);
7039 if (!result)
7040 return NULL;
7041 priority = PyLong_FromLong(param.sched_priority);
7042 if (!priority) {
7043 Py_DECREF(result);
7044 return NULL;
7045 }
7046 PyStructSequence_SET_ITEM(result, 0, priority);
7047 return result;
7048 }
7049
7050
7051 /*[clinic input]
7052 os.sched_setparam
7053 pid: pid_t
7054 param as param_obj: object
7055 /
7056
7057 Set scheduling parameters for the process identified by pid.
7058
7059 If pid is 0, sets parameters for the calling process.
7060 param should be an instance of sched_param.
7061 [clinic start generated code]*/
7062
7063 static PyObject *
os_sched_setparam_impl(PyObject * module,pid_t pid,PyObject * param_obj)7064 os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
7065 /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
7066 {
7067 struct sched_param param;
7068 if (!convert_sched_param(module, param_obj, ¶m)) {
7069 return NULL;
7070 }
7071
7072 if (sched_setparam(pid, ¶m))
7073 return posix_error();
7074 Py_RETURN_NONE;
7075 }
7076 #endif /* HAVE_SCHED_SETPARAM */
7077
7078
7079 #ifdef HAVE_SCHED_RR_GET_INTERVAL
7080 /*[clinic input]
7081 os.sched_rr_get_interval -> double
7082 pid: pid_t
7083 /
7084
7085 Return the round-robin quantum for the process identified by pid, in seconds.
7086
7087 Value returned is a float.
7088 [clinic start generated code]*/
7089
7090 static double
os_sched_rr_get_interval_impl(PyObject * module,pid_t pid)7091 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
7092 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
7093 {
7094 struct timespec interval;
7095 if (sched_rr_get_interval(pid, &interval)) {
7096 posix_error();
7097 return -1.0;
7098 }
7099 #ifdef _Py_MEMORY_SANITIZER
7100 __msan_unpoison(&interval, sizeof(interval));
7101 #endif
7102 return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
7103 }
7104 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
7105
7106
7107 /*[clinic input]
7108 os.sched_yield
7109
7110 Voluntarily relinquish the CPU.
7111 [clinic start generated code]*/
7112
7113 static PyObject *
os_sched_yield_impl(PyObject * module)7114 os_sched_yield_impl(PyObject *module)
7115 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
7116 {
7117 int result;
7118 Py_BEGIN_ALLOW_THREADS
7119 result = sched_yield();
7120 Py_END_ALLOW_THREADS
7121 if (result < 0) {
7122 return posix_error();
7123 }
7124 Py_RETURN_NONE;
7125 }
7126
7127 #ifdef HAVE_SCHED_SETAFFINITY
7128 /* The minimum number of CPUs allocated in a cpu_set_t */
7129 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
7130
7131 /*[clinic input]
7132 os.sched_setaffinity
7133 pid: pid_t
7134 mask : object
7135 /
7136
7137 Set the CPU affinity of the process identified by pid to mask.
7138
7139 mask should be an iterable of integers identifying CPUs.
7140 [clinic start generated code]*/
7141
7142 static PyObject *
os_sched_setaffinity_impl(PyObject * module,pid_t pid,PyObject * mask)7143 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
7144 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
7145 {
7146 int ncpus;
7147 size_t setsize;
7148 cpu_set_t *cpu_set = NULL;
7149 PyObject *iterator = NULL, *item;
7150
7151 iterator = PyObject_GetIter(mask);
7152 if (iterator == NULL)
7153 return NULL;
7154
7155 ncpus = NCPUS_START;
7156 setsize = CPU_ALLOC_SIZE(ncpus);
7157 cpu_set = CPU_ALLOC(ncpus);
7158 if (cpu_set == NULL) {
7159 PyErr_NoMemory();
7160 goto error;
7161 }
7162 CPU_ZERO_S(setsize, cpu_set);
7163
7164 while ((item = PyIter_Next(iterator))) {
7165 long cpu;
7166 if (!PyLong_Check(item)) {
7167 PyErr_Format(PyExc_TypeError,
7168 "expected an iterator of ints, "
7169 "but iterator yielded %R",
7170 Py_TYPE(item));
7171 Py_DECREF(item);
7172 goto error;
7173 }
7174 cpu = PyLong_AsLong(item);
7175 Py_DECREF(item);
7176 if (cpu < 0) {
7177 if (!PyErr_Occurred())
7178 PyErr_SetString(PyExc_ValueError, "negative CPU number");
7179 goto error;
7180 }
7181 if (cpu > INT_MAX - 1) {
7182 PyErr_SetString(PyExc_OverflowError, "CPU number too large");
7183 goto error;
7184 }
7185 if (cpu >= ncpus) {
7186 /* Grow CPU mask to fit the CPU number */
7187 int newncpus = ncpus;
7188 cpu_set_t *newmask;
7189 size_t newsetsize;
7190 while (newncpus <= cpu) {
7191 if (newncpus > INT_MAX / 2)
7192 newncpus = cpu + 1;
7193 else
7194 newncpus = newncpus * 2;
7195 }
7196 newmask = CPU_ALLOC(newncpus);
7197 if (newmask == NULL) {
7198 PyErr_NoMemory();
7199 goto error;
7200 }
7201 newsetsize = CPU_ALLOC_SIZE(newncpus);
7202 CPU_ZERO_S(newsetsize, newmask);
7203 memcpy(newmask, cpu_set, setsize);
7204 CPU_FREE(cpu_set);
7205 setsize = newsetsize;
7206 cpu_set = newmask;
7207 ncpus = newncpus;
7208 }
7209 CPU_SET_S(cpu, setsize, cpu_set);
7210 }
7211 if (PyErr_Occurred()) {
7212 goto error;
7213 }
7214 Py_CLEAR(iterator);
7215
7216 if (sched_setaffinity(pid, setsize, cpu_set)) {
7217 posix_error();
7218 goto error;
7219 }
7220 CPU_FREE(cpu_set);
7221 Py_RETURN_NONE;
7222
7223 error:
7224 if (cpu_set)
7225 CPU_FREE(cpu_set);
7226 Py_XDECREF(iterator);
7227 return NULL;
7228 }
7229
7230
7231 /*[clinic input]
7232 os.sched_getaffinity
7233 pid: pid_t
7234 /
7235
7236 Return the affinity of the process identified by pid (or the current process if zero).
7237
7238 The affinity is returned as a set of CPU identifiers.
7239 [clinic start generated code]*/
7240
7241 static PyObject *
os_sched_getaffinity_impl(PyObject * module,pid_t pid)7242 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
7243 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
7244 {
7245 int cpu, ncpus, count;
7246 size_t setsize;
7247 cpu_set_t *mask = NULL;
7248 PyObject *res = NULL;
7249
7250 ncpus = NCPUS_START;
7251 while (1) {
7252 setsize = CPU_ALLOC_SIZE(ncpus);
7253 mask = CPU_ALLOC(ncpus);
7254 if (mask == NULL)
7255 return PyErr_NoMemory();
7256 if (sched_getaffinity(pid, setsize, mask) == 0)
7257 break;
7258 CPU_FREE(mask);
7259 if (errno != EINVAL)
7260 return posix_error();
7261 if (ncpus > INT_MAX / 2) {
7262 PyErr_SetString(PyExc_OverflowError, "could not allocate "
7263 "a large enough CPU set");
7264 return NULL;
7265 }
7266 ncpus = ncpus * 2;
7267 }
7268
7269 res = PySet_New(NULL);
7270 if (res == NULL)
7271 goto error;
7272 for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7273 if (CPU_ISSET_S(cpu, setsize, mask)) {
7274 PyObject *cpu_num = PyLong_FromLong(cpu);
7275 --count;
7276 if (cpu_num == NULL)
7277 goto error;
7278 if (PySet_Add(res, cpu_num)) {
7279 Py_DECREF(cpu_num);
7280 goto error;
7281 }
7282 Py_DECREF(cpu_num);
7283 }
7284 }
7285 CPU_FREE(mask);
7286 return res;
7287
7288 error:
7289 if (mask)
7290 CPU_FREE(mask);
7291 Py_XDECREF(res);
7292 return NULL;
7293 }
7294
7295 #endif /* HAVE_SCHED_SETAFFINITY */
7296
7297 #endif /* HAVE_SCHED_H */
7298
7299
7300 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
7301 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
7302 # define DEV_PTY_FILE "/dev/ptc"
7303 # define HAVE_DEV_PTMX
7304 #else
7305 # define DEV_PTY_FILE "/dev/ptmx"
7306 #endif
7307
7308 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
7309 #ifdef HAVE_PTY_H
7310 #include <pty.h>
7311 #ifdef HAVE_UTMP_H
7312 #include <utmp.h>
7313 #endif /* HAVE_UTMP_H */
7314 #elif defined(HAVE_LIBUTIL_H)
7315 #include <libutil.h>
7316 #elif defined(HAVE_UTIL_H)
7317 #include <util.h>
7318 #endif /* HAVE_PTY_H */
7319 #ifdef HAVE_STROPTS_H
7320 #include <stropts.h>
7321 #endif
7322 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
7323
7324
7325 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7326 /*[clinic input]
7327 os.openpty
7328
7329 Open a pseudo-terminal.
7330
7331 Return a tuple of (master_fd, slave_fd) containing open file descriptors
7332 for both the master and slave ends.
7333 [clinic start generated code]*/
7334
7335 static PyObject *
os_openpty_impl(PyObject * module)7336 os_openpty_impl(PyObject *module)
7337 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
7338 {
7339 int master_fd = -1, slave_fd = -1;
7340 #ifndef HAVE_OPENPTY
7341 char * slave_name;
7342 #endif
7343 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
7344 PyOS_sighandler_t sig_saved;
7345 #if defined(__sun) && defined(__SVR4)
7346 extern char *ptsname(int fildes);
7347 #endif
7348 #endif
7349
7350 #ifdef HAVE_OPENPTY
7351 if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
7352 goto posix_error;
7353
7354 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7355 goto error;
7356 if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
7357 goto error;
7358
7359 #elif defined(HAVE__GETPTY)
7360 slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
7361 if (slave_name == NULL)
7362 goto posix_error;
7363 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7364 goto error;
7365
7366 slave_fd = _Py_open(slave_name, O_RDWR);
7367 if (slave_fd < 0)
7368 goto error;
7369
7370 #else
7371 master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
7372 if (master_fd < 0)
7373 goto posix_error;
7374
7375 sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
7376
7377 /* change permission of slave */
7378 if (grantpt(master_fd) < 0) {
7379 PyOS_setsig(SIGCHLD, sig_saved);
7380 goto posix_error;
7381 }
7382
7383 /* unlock slave */
7384 if (unlockpt(master_fd) < 0) {
7385 PyOS_setsig(SIGCHLD, sig_saved);
7386 goto posix_error;
7387 }
7388
7389 PyOS_setsig(SIGCHLD, sig_saved);
7390
7391 slave_name = ptsname(master_fd); /* get name of slave */
7392 if (slave_name == NULL)
7393 goto posix_error;
7394
7395 slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
7396 if (slave_fd == -1)
7397 goto error;
7398
7399 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7400 goto posix_error;
7401
7402 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
7403 ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
7404 ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
7405 #ifndef __hpux
7406 ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
7407 #endif /* __hpux */
7408 #endif /* HAVE_CYGWIN */
7409 #endif /* HAVE_OPENPTY */
7410
7411 return Py_BuildValue("(ii)", master_fd, slave_fd);
7412
7413 posix_error:
7414 posix_error();
7415 error:
7416 if (master_fd != -1)
7417 close(master_fd);
7418 if (slave_fd != -1)
7419 close(slave_fd);
7420 return NULL;
7421 }
7422 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
7423
7424
7425 #if defined(HAVE_SETSID) && defined(TIOCSCTTY)
7426 #define HAVE_FALLBACK_LOGIN_TTY 1
7427 #endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
7428
7429 #if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
7430 /*[clinic input]
7431 os.login_tty
7432
7433 fd: fildes
7434 /
7435
7436 Prepare the tty of which fd is a file descriptor for a new login session.
7437
7438 Make the calling process a session leader; make the tty the
7439 controlling tty, the stdin, the stdout, and the stderr of the
7440 calling process; close fd.
7441 [clinic start generated code]*/
7442
7443 static PyObject *
os_login_tty_impl(PyObject * module,int fd)7444 os_login_tty_impl(PyObject *module, int fd)
7445 /*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
7446 {
7447 #ifdef HAVE_LOGIN_TTY
7448 if (login_tty(fd) == -1) {
7449 return posix_error();
7450 }
7451 #else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
7452 /* Establish a new session. */
7453 if (setsid() == -1) {
7454 return posix_error();
7455 }
7456
7457 /* The tty becomes the controlling terminal. */
7458 if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
7459 return posix_error();
7460 }
7461
7462 /* The tty becomes stdin/stdout/stderr */
7463 if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
7464 return posix_error();
7465 }
7466 if (fd > 2) {
7467 close(fd);
7468 }
7469 #endif /* HAVE_LOGIN_TTY */
7470 Py_RETURN_NONE;
7471 }
7472 #endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
7473
7474
7475 #ifdef HAVE_FORKPTY
7476 /*[clinic input]
7477 os.forkpty
7478
7479 Fork a new process with a new pseudo-terminal as controlling tty.
7480
7481 Returns a tuple of (pid, master_fd).
7482 Like fork(), return pid of 0 to the child process,
7483 and pid of child to the parent process.
7484 To both, return fd of newly opened pseudo-terminal.
7485 [clinic start generated code]*/
7486
7487 static PyObject *
os_forkpty_impl(PyObject * module)7488 os_forkpty_impl(PyObject *module)
7489 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
7490 {
7491 int master_fd = -1;
7492 pid_t pid;
7493
7494 if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
7495 PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
7496 return NULL;
7497 }
7498 if (PySys_Audit("os.forkpty", NULL) < 0) {
7499 return NULL;
7500 }
7501 PyOS_BeforeFork();
7502 pid = forkpty(&master_fd, NULL, NULL, NULL);
7503 if (pid == 0) {
7504 /* child: this clobbers and resets the import lock. */
7505 PyOS_AfterFork_Child();
7506 } else {
7507 /* parent: release the import lock. */
7508 PyOS_AfterFork_Parent();
7509 }
7510 if (pid == -1) {
7511 return posix_error();
7512 }
7513 return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
7514 }
7515 #endif /* HAVE_FORKPTY */
7516
7517
7518 #ifdef HAVE_GETEGID
7519 /*[clinic input]
7520 os.getegid
7521
7522 Return the current process's effective group id.
7523 [clinic start generated code]*/
7524
7525 static PyObject *
os_getegid_impl(PyObject * module)7526 os_getegid_impl(PyObject *module)
7527 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
7528 {
7529 return _PyLong_FromGid(getegid());
7530 }
7531 #endif /* HAVE_GETEGID */
7532
7533
7534 #ifdef HAVE_GETEUID
7535 /*[clinic input]
7536 os.geteuid
7537
7538 Return the current process's effective user id.
7539 [clinic start generated code]*/
7540
7541 static PyObject *
os_geteuid_impl(PyObject * module)7542 os_geteuid_impl(PyObject *module)
7543 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
7544 {
7545 return _PyLong_FromUid(geteuid());
7546 }
7547 #endif /* HAVE_GETEUID */
7548
7549
7550 #ifdef HAVE_GETGID
7551 /*[clinic input]
7552 os.getgid
7553
7554 Return the current process's group id.
7555 [clinic start generated code]*/
7556
7557 static PyObject *
os_getgid_impl(PyObject * module)7558 os_getgid_impl(PyObject *module)
7559 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
7560 {
7561 return _PyLong_FromGid(getgid());
7562 }
7563 #endif /* HAVE_GETGID */
7564
7565
7566 #ifdef HAVE_GETPID
7567 /*[clinic input]
7568 os.getpid
7569
7570 Return the current process id.
7571 [clinic start generated code]*/
7572
7573 static PyObject *
os_getpid_impl(PyObject * module)7574 os_getpid_impl(PyObject *module)
7575 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
7576 {
7577 return PyLong_FromPid(getpid());
7578 }
7579 #endif /* HAVE_GETPID */
7580
7581 #ifdef NGROUPS_MAX
7582 #define MAX_GROUPS NGROUPS_MAX
7583 #else
7584 /* defined to be 16 on Solaris7, so this should be a small number */
7585 #define MAX_GROUPS 64
7586 #endif
7587
7588 #ifdef HAVE_GETGROUPLIST
7589
7590 #ifdef __APPLE__
7591 /*[clinic input]
7592 os.getgrouplist
7593
7594 user: str
7595 username to lookup
7596 group as basegid: int
7597 base group id of the user
7598 /
7599
7600 Returns a list of groups to which a user belongs.
7601 [clinic start generated code]*/
7602
7603 static PyObject *
os_getgrouplist_impl(PyObject * module,const char * user,int basegid)7604 os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
7605 /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
7606 #else
7607 /*[clinic input]
7608 os.getgrouplist
7609
7610 user: str
7611 username to lookup
7612 group as basegid: gid_t
7613 base group id of the user
7614 /
7615
7616 Returns a list of groups to which a user belongs.
7617 [clinic start generated code]*/
7618
7619 static PyObject *
7620 os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
7621 /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
7622 #endif
7623 {
7624 int i, ngroups;
7625 PyObject *list;
7626 #ifdef __APPLE__
7627 int *groups;
7628 #else
7629 gid_t *groups;
7630 #endif
7631
7632 /*
7633 * NGROUPS_MAX is defined by POSIX.1 as the maximum
7634 * number of supplimental groups a users can belong to.
7635 * We have to increment it by one because
7636 * getgrouplist() returns both the supplemental groups
7637 * and the primary group, i.e. all of the groups the
7638 * user belongs to.
7639 */
7640 ngroups = 1 + MAX_GROUPS;
7641
7642 while (1) {
7643 #ifdef __APPLE__
7644 groups = PyMem_New(int, ngroups);
7645 #else
7646 groups = PyMem_New(gid_t, ngroups);
7647 #endif
7648 if (groups == NULL) {
7649 return PyErr_NoMemory();
7650 }
7651
7652 int old_ngroups = ngroups;
7653 if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
7654 /* Success */
7655 break;
7656 }
7657
7658 /* getgrouplist() fails if the group list is too small */
7659 PyMem_Free(groups);
7660
7661 if (ngroups > old_ngroups) {
7662 /* If the group list is too small, the glibc implementation of
7663 getgrouplist() sets ngroups to the total number of groups and
7664 returns -1. */
7665 }
7666 else {
7667 /* Double the group list size */
7668 if (ngroups > INT_MAX / 2) {
7669 return PyErr_NoMemory();
7670 }
7671 ngroups *= 2;
7672 }
7673
7674 /* Retry getgrouplist() with a larger group list */
7675 }
7676
7677 #ifdef _Py_MEMORY_SANITIZER
7678 /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
7679 __msan_unpoison(&ngroups, sizeof(ngroups));
7680 __msan_unpoison(groups, ngroups*sizeof(*groups));
7681 #endif
7682
7683 list = PyList_New(ngroups);
7684 if (list == NULL) {
7685 PyMem_Free(groups);
7686 return NULL;
7687 }
7688
7689 for (i = 0; i < ngroups; i++) {
7690 #ifdef __APPLE__
7691 PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7692 #else
7693 PyObject *o = _PyLong_FromGid(groups[i]);
7694 #endif
7695 if (o == NULL) {
7696 Py_DECREF(list);
7697 PyMem_Free(groups);
7698 return NULL;
7699 }
7700 PyList_SET_ITEM(list, i, o);
7701 }
7702
7703 PyMem_Free(groups);
7704
7705 return list;
7706 }
7707 #endif /* HAVE_GETGROUPLIST */
7708
7709
7710 #ifdef HAVE_GETGROUPS
7711 /*[clinic input]
7712 os.getgroups
7713
7714 Return list of supplemental group IDs for the process.
7715 [clinic start generated code]*/
7716
7717 static PyObject *
os_getgroups_impl(PyObject * module)7718 os_getgroups_impl(PyObject *module)
7719 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
7720 {
7721 // Call getgroups with length 0 to get the actual number of groups
7722 int n = getgroups(0, NULL);
7723 if (n < 0) {
7724 return posix_error();
7725 }
7726
7727 if (n == 0) {
7728 return PyList_New(0);
7729 }
7730
7731 gid_t *grouplist = PyMem_New(gid_t, n);
7732 if (grouplist == NULL) {
7733 return PyErr_NoMemory();
7734 }
7735
7736 n = getgroups(n, grouplist);
7737 if (n == -1) {
7738 PyMem_Free(grouplist);
7739 return posix_error();
7740 }
7741
7742 PyObject *result = PyList_New(n);
7743 if (result == NULL) {
7744 goto error;
7745 }
7746
7747 for (int i = 0; i < n; ++i) {
7748 PyObject *group = _PyLong_FromGid(grouplist[i]);
7749 if (group == NULL) {
7750 goto error;
7751 }
7752 PyList_SET_ITEM(result, i, group);
7753 }
7754 PyMem_Free(grouplist);
7755
7756 return result;
7757
7758 error:
7759 PyMem_Free(grouplist);
7760 Py_XDECREF(result);
7761 return NULL;
7762 }
7763 #endif /* HAVE_GETGROUPS */
7764
7765 #ifdef HAVE_INITGROUPS
7766 #ifdef __APPLE__
7767 /*[clinic input]
7768 os.initgroups
7769
7770 username as oname: FSConverter
7771 gid: int
7772 /
7773
7774 Initialize the group access list.
7775
7776 Call the system initgroups() to initialize the group access list with all of
7777 the groups of which the specified username is a member, plus the specified
7778 group id.
7779 [clinic start generated code]*/
7780
7781 static PyObject *
os_initgroups_impl(PyObject * module,PyObject * oname,int gid)7782 os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
7783 /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
7784 #else
7785 /*[clinic input]
7786 os.initgroups
7787
7788 username as oname: FSConverter
7789 gid: gid_t
7790 /
7791
7792 Initialize the group access list.
7793
7794 Call the system initgroups() to initialize the group access list with all of
7795 the groups of which the specified username is a member, plus the specified
7796 group id.
7797 [clinic start generated code]*/
7798
7799 static PyObject *
7800 os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
7801 /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
7802 #endif
7803 {
7804 const char *username = PyBytes_AS_STRING(oname);
7805
7806 if (initgroups(username, gid) == -1)
7807 return PyErr_SetFromErrno(PyExc_OSError);
7808
7809 Py_RETURN_NONE;
7810 }
7811 #endif /* HAVE_INITGROUPS */
7812
7813
7814 #ifdef HAVE_GETPGID
7815 /*[clinic input]
7816 os.getpgid
7817
7818 pid: pid_t
7819
7820 Call the system call getpgid(), and return the result.
7821 [clinic start generated code]*/
7822
7823 static PyObject *
os_getpgid_impl(PyObject * module,pid_t pid)7824 os_getpgid_impl(PyObject *module, pid_t pid)
7825 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7826 {
7827 pid_t pgid = getpgid(pid);
7828 if (pgid < 0)
7829 return posix_error();
7830 return PyLong_FromPid(pgid);
7831 }
7832 #endif /* HAVE_GETPGID */
7833
7834
7835 #ifdef HAVE_GETPGRP
7836 /*[clinic input]
7837 os.getpgrp
7838
7839 Return the current process group id.
7840 [clinic start generated code]*/
7841
7842 static PyObject *
os_getpgrp_impl(PyObject * module)7843 os_getpgrp_impl(PyObject *module)
7844 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7845 {
7846 #ifdef GETPGRP_HAVE_ARG
7847 return PyLong_FromPid(getpgrp(0));
7848 #else /* GETPGRP_HAVE_ARG */
7849 return PyLong_FromPid(getpgrp());
7850 #endif /* GETPGRP_HAVE_ARG */
7851 }
7852 #endif /* HAVE_GETPGRP */
7853
7854
7855 #ifdef HAVE_SETPGRP
7856 /*[clinic input]
7857 os.setpgrp
7858
7859 Make the current process the leader of its process group.
7860 [clinic start generated code]*/
7861
7862 static PyObject *
os_setpgrp_impl(PyObject * module)7863 os_setpgrp_impl(PyObject *module)
7864 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7865 {
7866 #ifdef SETPGRP_HAVE_ARG
7867 if (setpgrp(0, 0) < 0)
7868 #else /* SETPGRP_HAVE_ARG */
7869 if (setpgrp() < 0)
7870 #endif /* SETPGRP_HAVE_ARG */
7871 return posix_error();
7872 Py_RETURN_NONE;
7873 }
7874 #endif /* HAVE_SETPGRP */
7875
7876 #ifdef HAVE_GETPPID
7877
7878 #ifdef MS_WINDOWS
7879 #include <tlhelp32.h>
7880
7881 static PyObject*
win32_getppid()7882 win32_getppid()
7883 {
7884 HANDLE snapshot;
7885 pid_t mypid;
7886 PyObject* result = NULL;
7887 BOOL have_record;
7888 PROCESSENTRY32 pe;
7889
7890 mypid = getpid(); /* This function never fails */
7891
7892 snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7893 if (snapshot == INVALID_HANDLE_VALUE)
7894 return PyErr_SetFromWindowsErr(GetLastError());
7895
7896 pe.dwSize = sizeof(pe);
7897 have_record = Process32First(snapshot, &pe);
7898 while (have_record) {
7899 if (mypid == (pid_t)pe.th32ProcessID) {
7900 /* We could cache the ulong value in a static variable. */
7901 result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7902 break;
7903 }
7904
7905 have_record = Process32Next(snapshot, &pe);
7906 }
7907
7908 /* If our loop exits and our pid was not found (result will be NULL)
7909 * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7910 * error anyway, so let's raise it. */
7911 if (!result)
7912 result = PyErr_SetFromWindowsErr(GetLastError());
7913
7914 CloseHandle(snapshot);
7915
7916 return result;
7917 }
7918 #endif /*MS_WINDOWS*/
7919
7920
7921 /*[clinic input]
7922 os.getppid
7923
7924 Return the parent's process id.
7925
7926 If the parent process has already exited, Windows machines will still
7927 return its id; others systems will return the id of the 'init' process (1).
7928 [clinic start generated code]*/
7929
7930 static PyObject *
os_getppid_impl(PyObject * module)7931 os_getppid_impl(PyObject *module)
7932 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7933 {
7934 #ifdef MS_WINDOWS
7935 return win32_getppid();
7936 #else
7937 return PyLong_FromPid(getppid());
7938 #endif
7939 }
7940 #endif /* HAVE_GETPPID */
7941
7942
7943 #ifdef HAVE_GETLOGIN
7944 /*[clinic input]
7945 os.getlogin
7946
7947 Return the actual login name.
7948 [clinic start generated code]*/
7949
7950 static PyObject *
os_getlogin_impl(PyObject * module)7951 os_getlogin_impl(PyObject *module)
7952 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7953 {
7954 PyObject *result = NULL;
7955 #ifdef MS_WINDOWS
7956 wchar_t user_name[UNLEN + 1];
7957 DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7958
7959 if (GetUserNameW(user_name, &num_chars)) {
7960 /* num_chars is the number of unicode chars plus null terminator */
7961 result = PyUnicode_FromWideChar(user_name, num_chars - 1);
7962 }
7963 else
7964 result = PyErr_SetFromWindowsErr(GetLastError());
7965 #else
7966 char *name;
7967 int old_errno = errno;
7968
7969 errno = 0;
7970 name = getlogin();
7971 if (name == NULL) {
7972 if (errno)
7973 posix_error();
7974 else
7975 PyErr_SetString(PyExc_OSError, "unable to determine login name");
7976 }
7977 else
7978 result = PyUnicode_DecodeFSDefault(name);
7979 errno = old_errno;
7980 #endif
7981 return result;
7982 }
7983 #endif /* HAVE_GETLOGIN */
7984
7985
7986 #ifdef HAVE_GETUID
7987 /*[clinic input]
7988 os.getuid
7989
7990 Return the current process's user id.
7991 [clinic start generated code]*/
7992
7993 static PyObject *
os_getuid_impl(PyObject * module)7994 os_getuid_impl(PyObject *module)
7995 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7996 {
7997 return _PyLong_FromUid(getuid());
7998 }
7999 #endif /* HAVE_GETUID */
8000
8001
8002 #ifdef MS_WINDOWS
8003 #define HAVE_KILL
8004 #endif /* MS_WINDOWS */
8005
8006 #ifdef HAVE_KILL
8007 /*[clinic input]
8008 os.kill
8009
8010 pid: pid_t
8011 signal: Py_ssize_t
8012 /
8013
8014 Kill a process with a signal.
8015 [clinic start generated code]*/
8016
8017 static PyObject *
os_kill_impl(PyObject * module,pid_t pid,Py_ssize_t signal)8018 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
8019 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
8020 {
8021 if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
8022 return NULL;
8023 }
8024 #ifndef MS_WINDOWS
8025 if (kill(pid, (int)signal) == -1) {
8026 return posix_error();
8027 }
8028
8029 // Check immediately if the signal was sent to the current process.
8030 // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
8031 // is cheap.
8032 if (PyErr_CheckSignals()) {
8033 return NULL;
8034 }
8035
8036 Py_RETURN_NONE;
8037 #else /* !MS_WINDOWS */
8038 PyObject *result;
8039 DWORD sig = (DWORD)signal;
8040 DWORD err;
8041 HANDLE handle;
8042
8043 /* Console processes which share a common console can be sent CTRL+C or
8044 CTRL+BREAK events, provided they handle said events. */
8045 if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
8046 if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
8047 err = GetLastError();
8048 PyErr_SetFromWindowsErr(err);
8049 }
8050 else
8051 Py_RETURN_NONE;
8052 }
8053
8054 /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
8055 attempt to open and terminate the process. */
8056 handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
8057 if (handle == NULL) {
8058 err = GetLastError();
8059 return PyErr_SetFromWindowsErr(err);
8060 }
8061
8062 if (TerminateProcess(handle, sig) == 0) {
8063 err = GetLastError();
8064 result = PyErr_SetFromWindowsErr(err);
8065 } else {
8066 Py_INCREF(Py_None);
8067 result = Py_None;
8068 }
8069
8070 CloseHandle(handle);
8071 return result;
8072 #endif /* !MS_WINDOWS */
8073 }
8074 #endif /* HAVE_KILL */
8075
8076
8077 #ifdef HAVE_KILLPG
8078 /*[clinic input]
8079 os.killpg
8080
8081 pgid: pid_t
8082 signal: int
8083 /
8084
8085 Kill a process group with a signal.
8086 [clinic start generated code]*/
8087
8088 static PyObject *
os_killpg_impl(PyObject * module,pid_t pgid,int signal)8089 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
8090 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
8091 {
8092 if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
8093 return NULL;
8094 }
8095 /* XXX some man pages make the `pgid` parameter an int, others
8096 a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
8097 take the same type. Moreover, pid_t is always at least as wide as
8098 int (else compilation of this module fails), which is safe. */
8099 if (killpg(pgid, signal) == -1)
8100 return posix_error();
8101 Py_RETURN_NONE;
8102 }
8103 #endif /* HAVE_KILLPG */
8104
8105
8106 #ifdef HAVE_PLOCK
8107 #ifdef HAVE_SYS_LOCK_H
8108 #include <sys/lock.h>
8109 #endif
8110
8111 /*[clinic input]
8112 os.plock
8113 op: int
8114 /
8115
8116 Lock program segments into memory.");
8117 [clinic start generated code]*/
8118
8119 static PyObject *
os_plock_impl(PyObject * module,int op)8120 os_plock_impl(PyObject *module, int op)
8121 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
8122 {
8123 if (plock(op) == -1)
8124 return posix_error();
8125 Py_RETURN_NONE;
8126 }
8127 #endif /* HAVE_PLOCK */
8128
8129
8130 #ifdef HAVE_SETUID
8131 /*[clinic input]
8132 os.setuid
8133
8134 uid: uid_t
8135 /
8136
8137 Set the current process's user id.
8138 [clinic start generated code]*/
8139
8140 static PyObject *
os_setuid_impl(PyObject * module,uid_t uid)8141 os_setuid_impl(PyObject *module, uid_t uid)
8142 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
8143 {
8144 if (setuid(uid) < 0)
8145 return posix_error();
8146 Py_RETURN_NONE;
8147 }
8148 #endif /* HAVE_SETUID */
8149
8150
8151 #ifdef HAVE_SETEUID
8152 /*[clinic input]
8153 os.seteuid
8154
8155 euid: uid_t
8156 /
8157
8158 Set the current process's effective user id.
8159 [clinic start generated code]*/
8160
8161 static PyObject *
os_seteuid_impl(PyObject * module,uid_t euid)8162 os_seteuid_impl(PyObject *module, uid_t euid)
8163 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
8164 {
8165 if (seteuid(euid) < 0)
8166 return posix_error();
8167 Py_RETURN_NONE;
8168 }
8169 #endif /* HAVE_SETEUID */
8170
8171
8172 #ifdef HAVE_SETEGID
8173 /*[clinic input]
8174 os.setegid
8175
8176 egid: gid_t
8177 /
8178
8179 Set the current process's effective group id.
8180 [clinic start generated code]*/
8181
8182 static PyObject *
os_setegid_impl(PyObject * module,gid_t egid)8183 os_setegid_impl(PyObject *module, gid_t egid)
8184 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
8185 {
8186 if (setegid(egid) < 0)
8187 return posix_error();
8188 Py_RETURN_NONE;
8189 }
8190 #endif /* HAVE_SETEGID */
8191
8192
8193 #ifdef HAVE_SETREUID
8194 /*[clinic input]
8195 os.setreuid
8196
8197 ruid: uid_t
8198 euid: uid_t
8199 /
8200
8201 Set the current process's real and effective user ids.
8202 [clinic start generated code]*/
8203
8204 static PyObject *
os_setreuid_impl(PyObject * module,uid_t ruid,uid_t euid)8205 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
8206 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
8207 {
8208 if (setreuid(ruid, euid) < 0) {
8209 return posix_error();
8210 } else {
8211 Py_RETURN_NONE;
8212 }
8213 }
8214 #endif /* HAVE_SETREUID */
8215
8216
8217 #ifdef HAVE_SETREGID
8218 /*[clinic input]
8219 os.setregid
8220
8221 rgid: gid_t
8222 egid: gid_t
8223 /
8224
8225 Set the current process's real and effective group ids.
8226 [clinic start generated code]*/
8227
8228 static PyObject *
os_setregid_impl(PyObject * module,gid_t rgid,gid_t egid)8229 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
8230 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
8231 {
8232 if (setregid(rgid, egid) < 0)
8233 return posix_error();
8234 Py_RETURN_NONE;
8235 }
8236 #endif /* HAVE_SETREGID */
8237
8238
8239 #ifdef HAVE_SETGID
8240 /*[clinic input]
8241 os.setgid
8242 gid: gid_t
8243 /
8244
8245 Set the current process's group id.
8246 [clinic start generated code]*/
8247
8248 static PyObject *
os_setgid_impl(PyObject * module,gid_t gid)8249 os_setgid_impl(PyObject *module, gid_t gid)
8250 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
8251 {
8252 if (setgid(gid) < 0)
8253 return posix_error();
8254 Py_RETURN_NONE;
8255 }
8256 #endif /* HAVE_SETGID */
8257
8258
8259 #ifdef HAVE_SETGROUPS
8260 /*[clinic input]
8261 os.setgroups
8262
8263 groups: object
8264 /
8265
8266 Set the groups of the current process to list.
8267 [clinic start generated code]*/
8268
8269 static PyObject *
os_setgroups(PyObject * module,PyObject * groups)8270 os_setgroups(PyObject *module, PyObject *groups)
8271 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
8272 {
8273 if (!PySequence_Check(groups)) {
8274 PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
8275 return NULL;
8276 }
8277 Py_ssize_t len = PySequence_Size(groups);
8278 if (len < 0) {
8279 return NULL;
8280 }
8281 if (len > MAX_GROUPS) {
8282 PyErr_SetString(PyExc_ValueError, "too many groups");
8283 return NULL;
8284 }
8285
8286 gid_t *grouplist = PyMem_New(gid_t, len);
8287 for (Py_ssize_t i = 0; i < len; i++) {
8288 PyObject *elem;
8289 elem = PySequence_GetItem(groups, i);
8290 if (!elem) {
8291 PyMem_Free(grouplist);
8292 return NULL;
8293 }
8294 if (!PyLong_Check(elem)) {
8295 PyErr_SetString(PyExc_TypeError,
8296 "groups must be integers");
8297 Py_DECREF(elem);
8298 PyMem_Free(grouplist);
8299 return NULL;
8300 } else {
8301 if (!_Py_Gid_Converter(elem, &grouplist[i])) {
8302 Py_DECREF(elem);
8303 PyMem_Free(grouplist);
8304 return NULL;
8305 }
8306 }
8307 Py_DECREF(elem);
8308 }
8309
8310 if (setgroups(len, grouplist) < 0) {
8311 PyMem_Free(grouplist);
8312 return posix_error();
8313 }
8314 PyMem_Free(grouplist);
8315 Py_RETURN_NONE;
8316 }
8317 #endif /* HAVE_SETGROUPS */
8318
8319 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
8320 static PyObject *
wait_helper(PyObject * module,pid_t pid,int status,struct rusage * ru)8321 wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
8322 {
8323 PyObject *result;
8324 PyObject *struct_rusage;
8325
8326 if (pid == -1)
8327 return posix_error();
8328
8329 // If wait succeeded but no child was ready to report status, ru will not
8330 // have been populated.
8331 if (pid == 0) {
8332 memset(ru, 0, sizeof(*ru));
8333 }
8334
8335 PyObject *m = PyImport_ImportModule("resource");
8336 if (m == NULL)
8337 return NULL;
8338 struct_rusage = PyObject_GetAttr(m, get_posix_state(module)->struct_rusage);
8339 Py_DECREF(m);
8340 if (struct_rusage == NULL)
8341 return NULL;
8342
8343 /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
8344 result = PyStructSequence_New((PyTypeObject*) struct_rusage);
8345 Py_DECREF(struct_rusage);
8346 if (!result)
8347 return NULL;
8348
8349 #ifndef doubletime
8350 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
8351 #endif
8352
8353 PyStructSequence_SET_ITEM(result, 0,
8354 PyFloat_FromDouble(doubletime(ru->ru_utime)));
8355 PyStructSequence_SET_ITEM(result, 1,
8356 PyFloat_FromDouble(doubletime(ru->ru_stime)));
8357 #define SET_INT(result, index, value)\
8358 PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
8359 SET_INT(result, 2, ru->ru_maxrss);
8360 SET_INT(result, 3, ru->ru_ixrss);
8361 SET_INT(result, 4, ru->ru_idrss);
8362 SET_INT(result, 5, ru->ru_isrss);
8363 SET_INT(result, 6, ru->ru_minflt);
8364 SET_INT(result, 7, ru->ru_majflt);
8365 SET_INT(result, 8, ru->ru_nswap);
8366 SET_INT(result, 9, ru->ru_inblock);
8367 SET_INT(result, 10, ru->ru_oublock);
8368 SET_INT(result, 11, ru->ru_msgsnd);
8369 SET_INT(result, 12, ru->ru_msgrcv);
8370 SET_INT(result, 13, ru->ru_nsignals);
8371 SET_INT(result, 14, ru->ru_nvcsw);
8372 SET_INT(result, 15, ru->ru_nivcsw);
8373 #undef SET_INT
8374
8375 if (PyErr_Occurred()) {
8376 Py_DECREF(result);
8377 return NULL;
8378 }
8379
8380 return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
8381 }
8382 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
8383
8384
8385 #ifdef HAVE_WAIT3
8386 /*[clinic input]
8387 os.wait3
8388
8389 options: int
8390 Wait for completion of a child process.
8391
8392 Returns a tuple of information about the child process:
8393 (pid, status, rusage)
8394 [clinic start generated code]*/
8395
8396 static PyObject *
os_wait3_impl(PyObject * module,int options)8397 os_wait3_impl(PyObject *module, int options)
8398 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
8399 {
8400 pid_t pid;
8401 struct rusage ru;
8402 int async_err = 0;
8403 WAIT_TYPE status;
8404 WAIT_STATUS_INT(status) = 0;
8405
8406 do {
8407 Py_BEGIN_ALLOW_THREADS
8408 pid = wait3(&status, options, &ru);
8409 Py_END_ALLOW_THREADS
8410 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8411 if (pid < 0)
8412 return (!async_err) ? posix_error() : NULL;
8413
8414 return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
8415 }
8416 #endif /* HAVE_WAIT3 */
8417
8418
8419 #ifdef HAVE_WAIT4
8420 /*[clinic input]
8421
8422 os.wait4
8423
8424 pid: pid_t
8425 options: int
8426
8427 Wait for completion of a specific child process.
8428
8429 Returns a tuple of information about the child process:
8430 (pid, status, rusage)
8431 [clinic start generated code]*/
8432
8433 static PyObject *
os_wait4_impl(PyObject * module,pid_t pid,int options)8434 os_wait4_impl(PyObject *module, pid_t pid, int options)
8435 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
8436 {
8437 pid_t res;
8438 struct rusage ru;
8439 int async_err = 0;
8440 WAIT_TYPE status;
8441 WAIT_STATUS_INT(status) = 0;
8442
8443 do {
8444 Py_BEGIN_ALLOW_THREADS
8445 res = wait4(pid, &status, options, &ru);
8446 Py_END_ALLOW_THREADS
8447 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8448 if (res < 0)
8449 return (!async_err) ? posix_error() : NULL;
8450
8451 return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
8452 }
8453 #endif /* HAVE_WAIT4 */
8454
8455
8456 #if defined(HAVE_WAITID) && !defined(__APPLE__)
8457 /*[clinic input]
8458 os.waitid
8459
8460 idtype: idtype_t
8461 Must be one of be P_PID, P_PGID or P_ALL.
8462 id: id_t
8463 The id to wait on.
8464 options: int
8465 Constructed from the ORing of one or more of WEXITED, WSTOPPED
8466 or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
8467 /
8468
8469 Returns the result of waiting for a process or processes.
8470
8471 Returns either waitid_result or None if WNOHANG is specified and there are
8472 no children in a waitable state.
8473 [clinic start generated code]*/
8474
8475 static PyObject *
os_waitid_impl(PyObject * module,idtype_t idtype,id_t id,int options)8476 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
8477 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
8478 {
8479 PyObject *result;
8480 int res;
8481 int async_err = 0;
8482 siginfo_t si;
8483 si.si_pid = 0;
8484
8485 do {
8486 Py_BEGIN_ALLOW_THREADS
8487 res = waitid(idtype, id, &si, options);
8488 Py_END_ALLOW_THREADS
8489 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8490 if (res < 0)
8491 return (!async_err) ? posix_error() : NULL;
8492
8493 if (si.si_pid == 0)
8494 Py_RETURN_NONE;
8495
8496 PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
8497 result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
8498 if (!result)
8499 return NULL;
8500
8501 PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
8502 PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
8503 PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
8504 PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
8505 PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
8506 if (PyErr_Occurred()) {
8507 Py_DECREF(result);
8508 return NULL;
8509 }
8510
8511 return result;
8512 }
8513 #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
8514
8515
8516 #if defined(HAVE_WAITPID)
8517 /*[clinic input]
8518 os.waitpid
8519 pid: pid_t
8520 options: int
8521 /
8522
8523 Wait for completion of a given child process.
8524
8525 Returns a tuple of information regarding the child process:
8526 (pid, status)
8527
8528 The options argument is ignored on Windows.
8529 [clinic start generated code]*/
8530
8531 static PyObject *
os_waitpid_impl(PyObject * module,pid_t pid,int options)8532 os_waitpid_impl(PyObject *module, pid_t pid, int options)
8533 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
8534 {
8535 pid_t res;
8536 int async_err = 0;
8537 WAIT_TYPE status;
8538 WAIT_STATUS_INT(status) = 0;
8539
8540 do {
8541 Py_BEGIN_ALLOW_THREADS
8542 res = waitpid(pid, &status, options);
8543 Py_END_ALLOW_THREADS
8544 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8545 if (res < 0)
8546 return (!async_err) ? posix_error() : NULL;
8547
8548 return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
8549 }
8550 #elif defined(HAVE_CWAIT)
8551 /* MS C has a variant of waitpid() that's usable for most purposes. */
8552 /*[clinic input]
8553 os.waitpid
8554 pid: intptr_t
8555 options: int
8556 /
8557
8558 Wait for completion of a given process.
8559
8560 Returns a tuple of information regarding the process:
8561 (pid, status << 8)
8562
8563 The options argument is ignored on Windows.
8564 [clinic start generated code]*/
8565
8566 static PyObject *
os_waitpid_impl(PyObject * module,intptr_t pid,int options)8567 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
8568 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
8569 {
8570 int status;
8571 intptr_t res;
8572 int async_err = 0;
8573
8574 do {
8575 Py_BEGIN_ALLOW_THREADS
8576 _Py_BEGIN_SUPPRESS_IPH
8577 res = _cwait(&status, pid, options);
8578 _Py_END_SUPPRESS_IPH
8579 Py_END_ALLOW_THREADS
8580 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8581 if (res < 0)
8582 return (!async_err) ? posix_error() : NULL;
8583
8584 unsigned long long ustatus = (unsigned int)status;
8585
8586 /* shift the status left a byte so this is more like the POSIX waitpid */
8587 return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
8588 }
8589 #endif
8590
8591
8592 #ifdef HAVE_WAIT
8593 /*[clinic input]
8594 os.wait
8595
8596 Wait for completion of a child process.
8597
8598 Returns a tuple of information about the child process:
8599 (pid, status)
8600 [clinic start generated code]*/
8601
8602 static PyObject *
os_wait_impl(PyObject * module)8603 os_wait_impl(PyObject *module)
8604 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
8605 {
8606 pid_t pid;
8607 int async_err = 0;
8608 WAIT_TYPE status;
8609 WAIT_STATUS_INT(status) = 0;
8610
8611 do {
8612 Py_BEGIN_ALLOW_THREADS
8613 pid = wait(&status);
8614 Py_END_ALLOW_THREADS
8615 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8616 if (pid < 0)
8617 return (!async_err) ? posix_error() : NULL;
8618
8619 return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
8620 }
8621 #endif /* HAVE_WAIT */
8622
8623 #if defined(__linux__) && defined(__NR_pidfd_open)
8624 /*[clinic input]
8625 os.pidfd_open
8626 pid: pid_t
8627 flags: unsigned_int = 0
8628
8629 Return a file descriptor referring to the process *pid*.
8630
8631 The descriptor can be used to perform process management without races and
8632 signals.
8633 [clinic start generated code]*/
8634
8635 static PyObject *
os_pidfd_open_impl(PyObject * module,pid_t pid,unsigned int flags)8636 os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
8637 /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
8638 {
8639 int fd = syscall(__NR_pidfd_open, pid, flags);
8640 if (fd < 0) {
8641 return posix_error();
8642 }
8643 return PyLong_FromLong(fd);
8644 }
8645 #endif
8646
8647
8648 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
8649 /*[clinic input]
8650 os.readlink
8651
8652 path: path_t
8653 *
8654 dir_fd: dir_fd(requires='readlinkat') = None
8655
8656 Return a string representing the path to which the symbolic link points.
8657
8658 If dir_fd is not None, it should be a file descriptor open to a directory,
8659 and path should be relative; path will then be relative to that directory.
8660
8661 dir_fd may not be implemented on your platform. If it is unavailable,
8662 using it will raise a NotImplementedError.
8663 [clinic start generated code]*/
8664
8665 static PyObject *
os_readlink_impl(PyObject * module,path_t * path,int dir_fd)8666 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
8667 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
8668 {
8669 #if defined(HAVE_READLINK)
8670 char buffer[MAXPATHLEN+1];
8671 ssize_t length;
8672 #ifdef HAVE_READLINKAT
8673 int readlinkat_unavailable = 0;
8674 #endif
8675
8676 Py_BEGIN_ALLOW_THREADS
8677 #ifdef HAVE_READLINKAT
8678 if (dir_fd != DEFAULT_DIR_FD) {
8679 if (HAVE_READLINKAT_RUNTIME) {
8680 length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
8681 } else {
8682 readlinkat_unavailable = 1;
8683 }
8684 } else
8685 #endif
8686 length = readlink(path->narrow, buffer, MAXPATHLEN);
8687 Py_END_ALLOW_THREADS
8688
8689 #ifdef HAVE_READLINKAT
8690 if (readlinkat_unavailable) {
8691 argument_unavailable_error(NULL, "dir_fd");
8692 return NULL;
8693 }
8694 #endif
8695
8696 if (length < 0) {
8697 return path_error(path);
8698 }
8699 buffer[length] = '\0';
8700
8701 if (PyUnicode_Check(path->object))
8702 return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
8703 else
8704 return PyBytes_FromStringAndSize(buffer, length);
8705 #elif defined(MS_WINDOWS)
8706 DWORD n_bytes_returned;
8707 DWORD io_result = 0;
8708 HANDLE reparse_point_handle;
8709 char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
8710 _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
8711 PyObject *result = NULL;
8712
8713 /* First get a handle to the reparse point */
8714 Py_BEGIN_ALLOW_THREADS
8715 reparse_point_handle = CreateFileW(
8716 path->wide,
8717 0,
8718 0,
8719 0,
8720 OPEN_EXISTING,
8721 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
8722 0);
8723 if (reparse_point_handle != INVALID_HANDLE_VALUE) {
8724 /* New call DeviceIoControl to read the reparse point */
8725 io_result = DeviceIoControl(
8726 reparse_point_handle,
8727 FSCTL_GET_REPARSE_POINT,
8728 0, 0, /* in buffer */
8729 target_buffer, sizeof(target_buffer),
8730 &n_bytes_returned,
8731 0 /* we're not using OVERLAPPED_IO */
8732 );
8733 CloseHandle(reparse_point_handle);
8734 }
8735 Py_END_ALLOW_THREADS
8736
8737 if (io_result == 0) {
8738 return path_error(path);
8739 }
8740
8741 wchar_t *name = NULL;
8742 Py_ssize_t nameLen = 0;
8743 if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
8744 {
8745 name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
8746 rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
8747 nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8748 }
8749 else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
8750 {
8751 name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8752 rdb->MountPointReparseBuffer.SubstituteNameOffset);
8753 nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8754 }
8755 else
8756 {
8757 PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8758 }
8759 if (name) {
8760 if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8761 /* Our buffer is mutable, so this is okay */
8762 name[1] = L'\\';
8763 }
8764 result = PyUnicode_FromWideChar(name, nameLen);
8765 if (result && path->narrow) {
8766 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8767 }
8768 }
8769 return result;
8770 #endif
8771 }
8772 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8773
8774 #if defined(MS_WINDOWS)
8775
8776 /* Remove the last portion of the path - return 0 on success */
8777 static int
_dirnameW(WCHAR * path)8778 _dirnameW(WCHAR *path)
8779 {
8780 WCHAR *ptr;
8781 size_t length = wcsnlen_s(path, MAX_PATH);
8782 if (length == MAX_PATH) {
8783 return -1;
8784 }
8785
8786 /* walk the path from the end until a backslash is encountered */
8787 for(ptr = path + length; ptr != path; ptr--) {
8788 if (*ptr == L'\\' || *ptr == L'/') {
8789 break;
8790 }
8791 }
8792 *ptr = 0;
8793 return 0;
8794 }
8795
8796 #endif
8797
8798 #ifdef HAVE_SYMLINK
8799
8800 #if defined(MS_WINDOWS)
8801
8802 /* Is this path absolute? */
8803 static int
_is_absW(const WCHAR * path)8804 _is_absW(const WCHAR *path)
8805 {
8806 return path[0] == L'\\' || path[0] == L'/' ||
8807 (path[0] && path[1] == L':');
8808 }
8809
8810 /* join root and rest with a backslash - return 0 on success */
8811 static int
_joinW(WCHAR * dest_path,const WCHAR * root,const WCHAR * rest)8812 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8813 {
8814 if (_is_absW(rest)) {
8815 return wcscpy_s(dest_path, MAX_PATH, rest);
8816 }
8817
8818 if (wcscpy_s(dest_path, MAX_PATH, root)) {
8819 return -1;
8820 }
8821
8822 if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8823 return -1;
8824 }
8825
8826 return wcscat_s(dest_path, MAX_PATH, rest);
8827 }
8828
8829 /* Return True if the path at src relative to dest is a directory */
8830 static int
_check_dirW(LPCWSTR src,LPCWSTR dest)8831 _check_dirW(LPCWSTR src, LPCWSTR dest)
8832 {
8833 WIN32_FILE_ATTRIBUTE_DATA src_info;
8834 WCHAR dest_parent[MAX_PATH];
8835 WCHAR src_resolved[MAX_PATH] = L"";
8836
8837 /* dest_parent = os.path.dirname(dest) */
8838 if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8839 _dirnameW(dest_parent)) {
8840 return 0;
8841 }
8842 /* src_resolved = os.path.join(dest_parent, src) */
8843 if (_joinW(src_resolved, dest_parent, src)) {
8844 return 0;
8845 }
8846 return (
8847 GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8848 && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8849 );
8850 }
8851 #endif
8852
8853
8854 /*[clinic input]
8855 os.symlink
8856 src: path_t
8857 dst: path_t
8858 target_is_directory: bool = False
8859 *
8860 dir_fd: dir_fd(requires='symlinkat')=None
8861
8862 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8863
8864 Create a symbolic link pointing to src named dst.
8865
8866 target_is_directory is required on Windows if the target is to be
8867 interpreted as a directory. (On Windows, symlink requires
8868 Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8869 target_is_directory is ignored on non-Windows platforms.
8870
8871 If dir_fd is not None, it should be a file descriptor open to a directory,
8872 and path should be relative; path will then be relative to that directory.
8873 dir_fd may not be implemented on your platform.
8874 If it is unavailable, using it will raise a NotImplementedError.
8875
8876 [clinic start generated code]*/
8877
8878 static PyObject *
os_symlink_impl(PyObject * module,path_t * src,path_t * dst,int target_is_directory,int dir_fd)8879 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8880 int target_is_directory, int dir_fd)
8881 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8882 {
8883 #ifdef MS_WINDOWS
8884 DWORD result;
8885 DWORD flags = 0;
8886
8887 /* Assumed true, set to false if detected to not be available. */
8888 static int windows_has_symlink_unprivileged_flag = TRUE;
8889 #else
8890 int result;
8891 #ifdef HAVE_SYMLINKAT
8892 int symlinkat_unavailable = 0;
8893 #endif
8894 #endif
8895
8896 if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8897 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8898 return NULL;
8899 }
8900
8901 #ifdef MS_WINDOWS
8902
8903 if (windows_has_symlink_unprivileged_flag) {
8904 /* Allow non-admin symlinks if system allows it. */
8905 flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8906 }
8907
8908 Py_BEGIN_ALLOW_THREADS
8909 _Py_BEGIN_SUPPRESS_IPH
8910 /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8911 if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8912 flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8913 }
8914
8915 result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8916 _Py_END_SUPPRESS_IPH
8917 Py_END_ALLOW_THREADS
8918
8919 if (windows_has_symlink_unprivileged_flag && !result &&
8920 ERROR_INVALID_PARAMETER == GetLastError()) {
8921
8922 Py_BEGIN_ALLOW_THREADS
8923 _Py_BEGIN_SUPPRESS_IPH
8924 /* This error might be caused by
8925 SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8926 Try again, and update windows_has_symlink_unprivileged_flag if we
8927 are successful this time.
8928
8929 NOTE: There is a risk of a race condition here if there are other
8930 conditions than the flag causing ERROR_INVALID_PARAMETER, and
8931 another process (or thread) changes that condition in between our
8932 calls to CreateSymbolicLink.
8933 */
8934 flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8935 result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8936 _Py_END_SUPPRESS_IPH
8937 Py_END_ALLOW_THREADS
8938
8939 if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8940 windows_has_symlink_unprivileged_flag = FALSE;
8941 }
8942 }
8943
8944 if (!result)
8945 return path_error2(src, dst);
8946
8947 #else
8948
8949 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8950 PyErr_SetString(PyExc_ValueError,
8951 "symlink: src and dst must be the same type");
8952 return NULL;
8953 }
8954
8955 Py_BEGIN_ALLOW_THREADS
8956 #ifdef HAVE_SYMLINKAT
8957 if (dir_fd != DEFAULT_DIR_FD) {
8958 if (HAVE_SYMLINKAT_RUNTIME) {
8959 result = symlinkat(src->narrow, dir_fd, dst->narrow);
8960 } else {
8961 symlinkat_unavailable = 1;
8962 }
8963 } else
8964 #endif
8965 result = symlink(src->narrow, dst->narrow);
8966 Py_END_ALLOW_THREADS
8967
8968 #ifdef HAVE_SYMLINKAT
8969 if (symlinkat_unavailable) {
8970 argument_unavailable_error(NULL, "dir_fd");
8971 return NULL;
8972 }
8973 #endif
8974
8975 if (result)
8976 return path_error2(src, dst);
8977 #endif
8978
8979 Py_RETURN_NONE;
8980 }
8981 #endif /* HAVE_SYMLINK */
8982
8983
8984
8985
8986 static PyStructSequence_Field times_result_fields[] = {
8987 {"user", "user time"},
8988 {"system", "system time"},
8989 {"children_user", "user time of children"},
8990 {"children_system", "system time of children"},
8991 {"elapsed", "elapsed time since an arbitrary point in the past"},
8992 {NULL}
8993 };
8994
8995 PyDoc_STRVAR(times_result__doc__,
8996 "times_result: Result from os.times().\n\n\
8997 This object may be accessed either as a tuple of\n\
8998 (user, system, children_user, children_system, elapsed),\n\
8999 or via the attributes user, system, children_user, children_system,\n\
9000 and elapsed.\n\
9001 \n\
9002 See os.times for more information.");
9003
9004 static PyStructSequence_Desc times_result_desc = {
9005 "times_result", /* name */
9006 times_result__doc__, /* doc */
9007 times_result_fields,
9008 5
9009 };
9010
9011 #ifdef MS_WINDOWS
9012 #define HAVE_TIMES /* mandatory, for the method table */
9013 #endif
9014
9015 #ifdef HAVE_TIMES
9016
9017 static PyObject *
build_times_result(PyObject * module,double user,double system,double children_user,double children_system,double elapsed)9018 build_times_result(PyObject *module, double user, double system,
9019 double children_user, double children_system,
9020 double elapsed)
9021 {
9022 PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
9023 PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
9024 if (value == NULL)
9025 return NULL;
9026
9027 #define SET(i, field) \
9028 { \
9029 PyObject *o = PyFloat_FromDouble(field); \
9030 if (!o) { \
9031 Py_DECREF(value); \
9032 return NULL; \
9033 } \
9034 PyStructSequence_SET_ITEM(value, i, o); \
9035 } \
9036
9037 SET(0, user);
9038 SET(1, system);
9039 SET(2, children_user);
9040 SET(3, children_system);
9041 SET(4, elapsed);
9042
9043 #undef SET
9044
9045 return value;
9046 }
9047
9048
9049 #ifndef MS_WINDOWS
9050 #define NEED_TICKS_PER_SECOND
9051 static long ticks_per_second = -1;
9052 #endif /* MS_WINDOWS */
9053
9054 /*[clinic input]
9055 os.times
9056
9057 Return a collection containing process timing information.
9058
9059 The object returned behaves like a named tuple with these fields:
9060 (utime, stime, cutime, cstime, elapsed_time)
9061 All fields are floating point numbers.
9062 [clinic start generated code]*/
9063
9064 static PyObject *
os_times_impl(PyObject * module)9065 os_times_impl(PyObject *module)
9066 /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
9067 #ifdef MS_WINDOWS
9068 {
9069 FILETIME create, exit, kernel, user;
9070 HANDLE hProc;
9071 hProc = GetCurrentProcess();
9072 GetProcessTimes(hProc, &create, &exit, &kernel, &user);
9073 /* The fields of a FILETIME structure are the hi and lo part
9074 of a 64-bit value expressed in 100 nanosecond units.
9075 1e7 is one second in such units; 1e-7 the inverse.
9076 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
9077 */
9078 return build_times_result(module,
9079 (double)(user.dwHighDateTime*429.4967296 +
9080 user.dwLowDateTime*1e-7),
9081 (double)(kernel.dwHighDateTime*429.4967296 +
9082 kernel.dwLowDateTime*1e-7),
9083 (double)0,
9084 (double)0,
9085 (double)0);
9086 }
9087 #else /* MS_WINDOWS */
9088 {
9089
9090
9091 struct tms t;
9092 clock_t c;
9093 errno = 0;
9094 c = times(&t);
9095 if (c == (clock_t) -1)
9096 return posix_error();
9097 return build_times_result(module,
9098 (double)t.tms_utime / ticks_per_second,
9099 (double)t.tms_stime / ticks_per_second,
9100 (double)t.tms_cutime / ticks_per_second,
9101 (double)t.tms_cstime / ticks_per_second,
9102 (double)c / ticks_per_second);
9103 }
9104 #endif /* MS_WINDOWS */
9105 #endif /* HAVE_TIMES */
9106
9107
9108 #ifdef HAVE_GETSID
9109 /*[clinic input]
9110 os.getsid
9111
9112 pid: pid_t
9113 /
9114
9115 Call the system call getsid(pid) and return the result.
9116 [clinic start generated code]*/
9117
9118 static PyObject *
os_getsid_impl(PyObject * module,pid_t pid)9119 os_getsid_impl(PyObject *module, pid_t pid)
9120 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
9121 {
9122 int sid;
9123 sid = getsid(pid);
9124 if (sid < 0)
9125 return posix_error();
9126 return PyLong_FromLong((long)sid);
9127 }
9128 #endif /* HAVE_GETSID */
9129
9130
9131 #ifdef HAVE_SETSID
9132 /*[clinic input]
9133 os.setsid
9134
9135 Call the system call setsid().
9136 [clinic start generated code]*/
9137
9138 static PyObject *
os_setsid_impl(PyObject * module)9139 os_setsid_impl(PyObject *module)
9140 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
9141 {
9142 if (setsid() < 0)
9143 return posix_error();
9144 Py_RETURN_NONE;
9145 }
9146 #endif /* HAVE_SETSID */
9147
9148
9149 #ifdef HAVE_SETPGID
9150 /*[clinic input]
9151 os.setpgid
9152
9153 pid: pid_t
9154 pgrp: pid_t
9155 /
9156
9157 Call the system call setpgid(pid, pgrp).
9158 [clinic start generated code]*/
9159
9160 static PyObject *
os_setpgid_impl(PyObject * module,pid_t pid,pid_t pgrp)9161 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
9162 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
9163 {
9164 if (setpgid(pid, pgrp) < 0)
9165 return posix_error();
9166 Py_RETURN_NONE;
9167 }
9168 #endif /* HAVE_SETPGID */
9169
9170
9171 #ifdef HAVE_TCGETPGRP
9172 /*[clinic input]
9173 os.tcgetpgrp
9174
9175 fd: int
9176 /
9177
9178 Return the process group associated with the terminal specified by fd.
9179 [clinic start generated code]*/
9180
9181 static PyObject *
os_tcgetpgrp_impl(PyObject * module,int fd)9182 os_tcgetpgrp_impl(PyObject *module, int fd)
9183 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
9184 {
9185 pid_t pgid = tcgetpgrp(fd);
9186 if (pgid < 0)
9187 return posix_error();
9188 return PyLong_FromPid(pgid);
9189 }
9190 #endif /* HAVE_TCGETPGRP */
9191
9192
9193 #ifdef HAVE_TCSETPGRP
9194 /*[clinic input]
9195 os.tcsetpgrp
9196
9197 fd: int
9198 pgid: pid_t
9199 /
9200
9201 Set the process group associated with the terminal specified by fd.
9202 [clinic start generated code]*/
9203
9204 static PyObject *
os_tcsetpgrp_impl(PyObject * module,int fd,pid_t pgid)9205 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
9206 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
9207 {
9208 if (tcsetpgrp(fd, pgid) < 0)
9209 return posix_error();
9210 Py_RETURN_NONE;
9211 }
9212 #endif /* HAVE_TCSETPGRP */
9213
9214 /* Functions acting on file descriptors */
9215
9216 #ifdef O_CLOEXEC
9217 extern int _Py_open_cloexec_works;
9218 #endif
9219
9220
9221 /*[clinic input]
9222 os.open -> int
9223 path: path_t
9224 flags: int
9225 mode: int = 0o777
9226 *
9227 dir_fd: dir_fd(requires='openat') = None
9228
9229 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
9230
9231 Open a file for low level IO. Returns a file descriptor (integer).
9232
9233 If dir_fd is not None, it should be a file descriptor open to a directory,
9234 and path should be relative; path will then be relative to that directory.
9235 dir_fd may not be implemented on your platform.
9236 If it is unavailable, using it will raise a NotImplementedError.
9237 [clinic start generated code]*/
9238
9239 static int
os_open_impl(PyObject * module,path_t * path,int flags,int mode,int dir_fd)9240 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
9241 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
9242 {
9243 int fd;
9244 int async_err = 0;
9245 #ifdef HAVE_OPENAT
9246 int openat_unavailable = 0;
9247 #endif
9248
9249 #ifdef O_CLOEXEC
9250 int *atomic_flag_works = &_Py_open_cloexec_works;
9251 #elif !defined(MS_WINDOWS)
9252 int *atomic_flag_works = NULL;
9253 #endif
9254
9255 #ifdef MS_WINDOWS
9256 flags |= O_NOINHERIT;
9257 #elif defined(O_CLOEXEC)
9258 flags |= O_CLOEXEC;
9259 #endif
9260
9261 if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
9262 return -1;
9263 }
9264
9265 _Py_BEGIN_SUPPRESS_IPH
9266 do {
9267 Py_BEGIN_ALLOW_THREADS
9268 #ifdef MS_WINDOWS
9269 fd = _wopen(path->wide, flags, mode);
9270 #else
9271 #ifdef HAVE_OPENAT
9272 if (dir_fd != DEFAULT_DIR_FD) {
9273 if (HAVE_OPENAT_RUNTIME) {
9274 fd = openat(dir_fd, path->narrow, flags, mode);
9275
9276 } else {
9277 openat_unavailable = 1;
9278 fd = -1;
9279 }
9280 } else
9281 #endif /* HAVE_OPENAT */
9282 fd = open(path->narrow, flags, mode);
9283 #endif /* !MS_WINDOWS */
9284 Py_END_ALLOW_THREADS
9285 } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9286 _Py_END_SUPPRESS_IPH
9287
9288 #ifdef HAVE_OPENAT
9289 if (openat_unavailable) {
9290 argument_unavailable_error(NULL, "dir_fd");
9291 return -1;
9292 }
9293 #endif
9294
9295 if (fd < 0) {
9296 if (!async_err)
9297 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
9298 return -1;
9299 }
9300
9301 #ifndef MS_WINDOWS
9302 if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
9303 close(fd);
9304 return -1;
9305 }
9306 #endif
9307
9308 return fd;
9309 }
9310
9311
9312 /*[clinic input]
9313 os.close
9314
9315 fd: int
9316
9317 Close a file descriptor.
9318 [clinic start generated code]*/
9319
9320 static PyObject *
os_close_impl(PyObject * module,int fd)9321 os_close_impl(PyObject *module, int fd)
9322 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
9323 {
9324 int res;
9325 /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
9326 * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
9327 * for more details.
9328 */
9329 Py_BEGIN_ALLOW_THREADS
9330 _Py_BEGIN_SUPPRESS_IPH
9331 res = close(fd);
9332 _Py_END_SUPPRESS_IPH
9333 Py_END_ALLOW_THREADS
9334 if (res < 0)
9335 return posix_error();
9336 Py_RETURN_NONE;
9337 }
9338
9339 /*[clinic input]
9340 os.closerange
9341
9342 fd_low: int
9343 fd_high: int
9344 /
9345
9346 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
9347 [clinic start generated code]*/
9348
9349 static PyObject *
os_closerange_impl(PyObject * module,int fd_low,int fd_high)9350 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
9351 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
9352 {
9353 Py_BEGIN_ALLOW_THREADS
9354 _Py_closerange(fd_low, fd_high - 1);
9355 Py_END_ALLOW_THREADS
9356 Py_RETURN_NONE;
9357 }
9358
9359
9360 /*[clinic input]
9361 os.dup -> int
9362
9363 fd: int
9364 /
9365
9366 Return a duplicate of a file descriptor.
9367 [clinic start generated code]*/
9368
9369 static int
os_dup_impl(PyObject * module,int fd)9370 os_dup_impl(PyObject *module, int fd)
9371 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
9372 {
9373 return _Py_dup(fd);
9374 }
9375
9376 // dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
9377 // dup2.c provides working dup2() if and only if F_DUPFD is available.
9378 #if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
9379 /*[clinic input]
9380 os.dup2 -> int
9381 fd: int
9382 fd2: int
9383 inheritable: bool=True
9384
9385 Duplicate file descriptor.
9386 [clinic start generated code]*/
9387
9388 static int
os_dup2_impl(PyObject * module,int fd,int fd2,int inheritable)9389 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
9390 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
9391 {
9392 int res = 0;
9393 #if defined(HAVE_DUP3) && \
9394 !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
9395 /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
9396 static int dup3_works = -1;
9397 #endif
9398
9399 /* dup2() can fail with EINTR if the target FD is already open, because it
9400 * then has to be closed. See os_close_impl() for why we don't handle EINTR
9401 * upon close(), and therefore below.
9402 */
9403 #ifdef MS_WINDOWS
9404 Py_BEGIN_ALLOW_THREADS
9405 _Py_BEGIN_SUPPRESS_IPH
9406 res = dup2(fd, fd2);
9407 _Py_END_SUPPRESS_IPH
9408 Py_END_ALLOW_THREADS
9409 if (res < 0) {
9410 posix_error();
9411 return -1;
9412 }
9413 res = fd2; // msvcrt dup2 returns 0 on success.
9414
9415 /* Character files like console cannot be make non-inheritable */
9416 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9417 close(fd2);
9418 return -1;
9419 }
9420
9421 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
9422 Py_BEGIN_ALLOW_THREADS
9423 if (!inheritable)
9424 res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
9425 else
9426 res = dup2(fd, fd2);
9427 Py_END_ALLOW_THREADS
9428 if (res < 0) {
9429 posix_error();
9430 return -1;
9431 }
9432
9433 #else
9434
9435 #ifdef HAVE_DUP3
9436 if (!inheritable && dup3_works != 0) {
9437 Py_BEGIN_ALLOW_THREADS
9438 res = dup3(fd, fd2, O_CLOEXEC);
9439 Py_END_ALLOW_THREADS
9440 if (res < 0) {
9441 if (dup3_works == -1)
9442 dup3_works = (errno != ENOSYS);
9443 if (dup3_works) {
9444 posix_error();
9445 return -1;
9446 }
9447 }
9448 }
9449
9450 if (inheritable || dup3_works == 0)
9451 {
9452 #endif
9453 Py_BEGIN_ALLOW_THREADS
9454 res = dup2(fd, fd2);
9455 Py_END_ALLOW_THREADS
9456 if (res < 0) {
9457 posix_error();
9458 return -1;
9459 }
9460
9461 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9462 close(fd2);
9463 return -1;
9464 }
9465 #ifdef HAVE_DUP3
9466 }
9467 #endif
9468
9469 #endif
9470
9471 return res;
9472 }
9473 #endif
9474
9475
9476 #ifdef HAVE_LOCKF
9477 /*[clinic input]
9478 os.lockf
9479
9480 fd: int
9481 An open file descriptor.
9482 command: int
9483 One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
9484 length: Py_off_t
9485 The number of bytes to lock, starting at the current position.
9486 /
9487
9488 Apply, test or remove a POSIX lock on an open file descriptor.
9489
9490 [clinic start generated code]*/
9491
9492 static PyObject *
os_lockf_impl(PyObject * module,int fd,int command,Py_off_t length)9493 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
9494 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
9495 {
9496 int res;
9497
9498 if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
9499 return NULL;
9500 }
9501
9502 Py_BEGIN_ALLOW_THREADS
9503 res = lockf(fd, command, length);
9504 Py_END_ALLOW_THREADS
9505
9506 if (res < 0)
9507 return posix_error();
9508
9509 Py_RETURN_NONE;
9510 }
9511 #endif /* HAVE_LOCKF */
9512
9513
9514 /*[clinic input]
9515 os.lseek -> Py_off_t
9516
9517 fd: int
9518 position: Py_off_t
9519 how: int
9520 /
9521
9522 Set the position of a file descriptor. Return the new position.
9523
9524 Return the new cursor position in number of bytes
9525 relative to the beginning of the file.
9526 [clinic start generated code]*/
9527
9528 static Py_off_t
os_lseek_impl(PyObject * module,int fd,Py_off_t position,int how)9529 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
9530 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
9531 {
9532 Py_off_t result;
9533
9534 #ifdef SEEK_SET
9535 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
9536 switch (how) {
9537 case 0: how = SEEK_SET; break;
9538 case 1: how = SEEK_CUR; break;
9539 case 2: how = SEEK_END; break;
9540 }
9541 #endif /* SEEK_END */
9542
9543 Py_BEGIN_ALLOW_THREADS
9544 _Py_BEGIN_SUPPRESS_IPH
9545 #ifdef MS_WINDOWS
9546 result = _lseeki64(fd, position, how);
9547 #else
9548 result = lseek(fd, position, how);
9549 #endif
9550 _Py_END_SUPPRESS_IPH
9551 Py_END_ALLOW_THREADS
9552 if (result < 0)
9553 posix_error();
9554
9555 return result;
9556 }
9557
9558
9559 /*[clinic input]
9560 os.read
9561 fd: int
9562 length: Py_ssize_t
9563 /
9564
9565 Read from a file descriptor. Returns a bytes object.
9566 [clinic start generated code]*/
9567
9568 static PyObject *
os_read_impl(PyObject * module,int fd,Py_ssize_t length)9569 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
9570 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
9571 {
9572 Py_ssize_t n;
9573 PyObject *buffer;
9574
9575 if (length < 0) {
9576 errno = EINVAL;
9577 return posix_error();
9578 }
9579
9580 length = Py_MIN(length, _PY_READ_MAX);
9581
9582 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9583 if (buffer == NULL)
9584 return NULL;
9585
9586 n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
9587 if (n == -1) {
9588 Py_DECREF(buffer);
9589 return NULL;
9590 }
9591
9592 if (n != length)
9593 _PyBytes_Resize(&buffer, n);
9594
9595 return buffer;
9596 }
9597
9598 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
9599 || defined(__APPLE__))) \
9600 || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
9601 || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9602 static int
iov_setup(struct iovec ** iov,Py_buffer ** buf,PyObject * seq,Py_ssize_t cnt,int type)9603 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
9604 {
9605 Py_ssize_t i, j;
9606
9607 *iov = PyMem_New(struct iovec, cnt);
9608 if (*iov == NULL) {
9609 PyErr_NoMemory();
9610 return -1;
9611 }
9612
9613 *buf = PyMem_New(Py_buffer, cnt);
9614 if (*buf == NULL) {
9615 PyMem_Free(*iov);
9616 PyErr_NoMemory();
9617 return -1;
9618 }
9619
9620 for (i = 0; i < cnt; i++) {
9621 PyObject *item = PySequence_GetItem(seq, i);
9622 if (item == NULL)
9623 goto fail;
9624 if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
9625 Py_DECREF(item);
9626 goto fail;
9627 }
9628 Py_DECREF(item);
9629 (*iov)[i].iov_base = (*buf)[i].buf;
9630 (*iov)[i].iov_len = (*buf)[i].len;
9631 }
9632 return 0;
9633
9634 fail:
9635 PyMem_Free(*iov);
9636 for (j = 0; j < i; j++) {
9637 PyBuffer_Release(&(*buf)[j]);
9638 }
9639 PyMem_Free(*buf);
9640 return -1;
9641 }
9642
9643 static void
iov_cleanup(struct iovec * iov,Py_buffer * buf,int cnt)9644 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9645 {
9646 int i;
9647 PyMem_Free(iov);
9648 for (i = 0; i < cnt; i++) {
9649 PyBuffer_Release(&buf[i]);
9650 }
9651 PyMem_Free(buf);
9652 }
9653 #endif
9654
9655
9656 #ifdef HAVE_READV
9657 /*[clinic input]
9658 os.readv -> Py_ssize_t
9659
9660 fd: int
9661 buffers: object
9662 /
9663
9664 Read from a file descriptor fd into an iterable of buffers.
9665
9666 The buffers should be mutable buffers accepting bytes.
9667 readv will transfer data into each buffer until it is full
9668 and then move on to the next buffer in the sequence to hold
9669 the rest of the data.
9670
9671 readv returns the total number of bytes read,
9672 which may be less than the total capacity of all the buffers.
9673 [clinic start generated code]*/
9674
9675 static Py_ssize_t
os_readv_impl(PyObject * module,int fd,PyObject * buffers)9676 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9677 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9678 {
9679 Py_ssize_t cnt, n;
9680 int async_err = 0;
9681 struct iovec *iov;
9682 Py_buffer *buf;
9683
9684 if (!PySequence_Check(buffers)) {
9685 PyErr_SetString(PyExc_TypeError,
9686 "readv() arg 2 must be a sequence");
9687 return -1;
9688 }
9689
9690 cnt = PySequence_Size(buffers);
9691 if (cnt < 0)
9692 return -1;
9693
9694 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9695 return -1;
9696
9697 do {
9698 Py_BEGIN_ALLOW_THREADS
9699 n = readv(fd, iov, cnt);
9700 Py_END_ALLOW_THREADS
9701 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9702
9703 iov_cleanup(iov, buf, cnt);
9704 if (n < 0) {
9705 if (!async_err)
9706 posix_error();
9707 return -1;
9708 }
9709
9710 return n;
9711 }
9712 #endif /* HAVE_READV */
9713
9714
9715 #ifdef HAVE_PREAD
9716 /*[clinic input]
9717 os.pread
9718
9719 fd: int
9720 length: Py_ssize_t
9721 offset: Py_off_t
9722 /
9723
9724 Read a number of bytes from a file descriptor starting at a particular offset.
9725
9726 Read length bytes from file descriptor fd, starting at offset bytes from
9727 the beginning of the file. The file offset remains unchanged.
9728 [clinic start generated code]*/
9729
9730 static PyObject *
os_pread_impl(PyObject * module,int fd,Py_ssize_t length,Py_off_t offset)9731 os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
9732 /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
9733 {
9734 Py_ssize_t n;
9735 int async_err = 0;
9736 PyObject *buffer;
9737
9738 if (length < 0) {
9739 errno = EINVAL;
9740 return posix_error();
9741 }
9742 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9743 if (buffer == NULL)
9744 return NULL;
9745
9746 do {
9747 Py_BEGIN_ALLOW_THREADS
9748 _Py_BEGIN_SUPPRESS_IPH
9749 n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9750 _Py_END_SUPPRESS_IPH
9751 Py_END_ALLOW_THREADS
9752 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9753
9754 if (n < 0) {
9755 Py_DECREF(buffer);
9756 return (!async_err) ? posix_error() : NULL;
9757 }
9758 if (n != length)
9759 _PyBytes_Resize(&buffer, n);
9760 return buffer;
9761 }
9762 #endif /* HAVE_PREAD */
9763
9764 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9765 /*[clinic input]
9766 os.preadv -> Py_ssize_t
9767
9768 fd: int
9769 buffers: object
9770 offset: Py_off_t
9771 flags: int = 0
9772 /
9773
9774 Reads from a file descriptor into a number of mutable bytes-like objects.
9775
9776 Combines the functionality of readv() and pread(). As readv(), it will
9777 transfer data into each buffer until it is full and then move on to the next
9778 buffer in the sequence to hold the rest of the data. Its fourth argument,
9779 specifies the file offset at which the input operation is to be performed. It
9780 will return the total number of bytes read (which can be less than the total
9781 capacity of all the objects).
9782
9783 The flags argument contains a bitwise OR of zero or more of the following flags:
9784
9785 - RWF_HIPRI
9786 - RWF_NOWAIT
9787
9788 Using non-zero flags requires Linux 4.6 or newer.
9789 [clinic start generated code]*/
9790
9791 static Py_ssize_t
os_preadv_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9792 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9793 int flags)
9794 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9795 {
9796 Py_ssize_t cnt, n;
9797 int async_err = 0;
9798 struct iovec *iov;
9799 Py_buffer *buf;
9800
9801 if (!PySequence_Check(buffers)) {
9802 PyErr_SetString(PyExc_TypeError,
9803 "preadv2() arg 2 must be a sequence");
9804 return -1;
9805 }
9806
9807 cnt = PySequence_Size(buffers);
9808 if (cnt < 0) {
9809 return -1;
9810 }
9811
9812 #ifndef HAVE_PREADV2
9813 if(flags != 0) {
9814 argument_unavailable_error("preadv2", "flags");
9815 return -1;
9816 }
9817 #endif
9818
9819 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9820 return -1;
9821 }
9822 #ifdef HAVE_PREADV2
9823 do {
9824 Py_BEGIN_ALLOW_THREADS
9825 _Py_BEGIN_SUPPRESS_IPH
9826 n = preadv2(fd, iov, cnt, offset, flags);
9827 _Py_END_SUPPRESS_IPH
9828 Py_END_ALLOW_THREADS
9829 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9830 #else
9831 do {
9832 #if defined(__APPLE__) && defined(__clang__)
9833 /* This entire function will be removed from the module dict when the API
9834 * is not available.
9835 */
9836 #pragma clang diagnostic push
9837 #pragma clang diagnostic ignored "-Wunguarded-availability"
9838 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
9839 #endif
9840 Py_BEGIN_ALLOW_THREADS
9841 _Py_BEGIN_SUPPRESS_IPH
9842 n = preadv(fd, iov, cnt, offset);
9843 _Py_END_SUPPRESS_IPH
9844 Py_END_ALLOW_THREADS
9845 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9846
9847 #if defined(__APPLE__) && defined(__clang__)
9848 #pragma clang diagnostic pop
9849 #endif
9850
9851 #endif
9852
9853 iov_cleanup(iov, buf, cnt);
9854 if (n < 0) {
9855 if (!async_err) {
9856 posix_error();
9857 }
9858 return -1;
9859 }
9860
9861 return n;
9862 }
9863 #endif /* HAVE_PREADV */
9864
9865
9866 /*[clinic input]
9867 os.write -> Py_ssize_t
9868
9869 fd: int
9870 data: Py_buffer
9871 /
9872
9873 Write a bytes object to a file descriptor.
9874 [clinic start generated code]*/
9875
9876 static Py_ssize_t
os_write_impl(PyObject * module,int fd,Py_buffer * data)9877 os_write_impl(PyObject *module, int fd, Py_buffer *data)
9878 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9879 {
9880 return _Py_write(fd, data->buf, data->len);
9881 }
9882
9883 #ifdef HAVE_SENDFILE
9884 #ifdef __APPLE__
9885 /*[clinic input]
9886 os.sendfile
9887
9888 out_fd: int
9889 in_fd: int
9890 offset: Py_off_t
9891 count as sbytes: Py_off_t
9892 headers: object(c_default="NULL") = ()
9893 trailers: object(c_default="NULL") = ()
9894 flags: int = 0
9895
9896 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9897 [clinic start generated code]*/
9898
9899 static PyObject *
os_sendfile_impl(PyObject * module,int out_fd,int in_fd,Py_off_t offset,Py_off_t sbytes,PyObject * headers,PyObject * trailers,int flags)9900 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9901 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
9902 int flags)
9903 /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
9904 #elif defined(__FreeBSD__) || defined(__DragonFly__)
9905 /*[clinic input]
9906 os.sendfile
9907
9908 out_fd: int
9909 in_fd: int
9910 offset: Py_off_t
9911 count: Py_ssize_t
9912 headers: object(c_default="NULL") = ()
9913 trailers: object(c_default="NULL") = ()
9914 flags: int = 0
9915
9916 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9917 [clinic start generated code]*/
9918
9919 static PyObject *
9920 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9921 Py_ssize_t count, PyObject *headers, PyObject *trailers,
9922 int flags)
9923 /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
9924 #else
9925 /*[clinic input]
9926 os.sendfile
9927
9928 out_fd: int
9929 in_fd: int
9930 offset as offobj: object
9931 count: Py_ssize_t
9932
9933 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9934 [clinic start generated code]*/
9935
9936 static PyObject *
9937 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
9938 Py_ssize_t count)
9939 /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
9940 #endif
9941 {
9942 Py_ssize_t ret;
9943 int async_err = 0;
9944
9945 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9946 #ifndef __APPLE__
9947 off_t sbytes;
9948 #endif
9949 Py_buffer *hbuf, *tbuf;
9950 struct sf_hdtr sf;
9951
9952 sf.headers = NULL;
9953 sf.trailers = NULL;
9954
9955 if (headers != NULL) {
9956 if (!PySequence_Check(headers)) {
9957 PyErr_SetString(PyExc_TypeError,
9958 "sendfile() headers must be a sequence");
9959 return NULL;
9960 } else {
9961 Py_ssize_t i = PySequence_Size(headers);
9962 if (i < 0)
9963 return NULL;
9964 if (i > INT_MAX) {
9965 PyErr_SetString(PyExc_OverflowError,
9966 "sendfile() header is too large");
9967 return NULL;
9968 }
9969 if (i > 0) {
9970 sf.hdr_cnt = (int)i;
9971 if (iov_setup(&(sf.headers), &hbuf,
9972 headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9973 return NULL;
9974 #ifdef __APPLE__
9975 for (i = 0; i < sf.hdr_cnt; i++) {
9976 Py_ssize_t blen = sf.headers[i].iov_len;
9977 # define OFF_T_MAX 0x7fffffffffffffff
9978 if (sbytes >= OFF_T_MAX - blen) {
9979 PyErr_SetString(PyExc_OverflowError,
9980 "sendfile() header is too large");
9981 return NULL;
9982 }
9983 sbytes += blen;
9984 }
9985 #endif
9986 }
9987 }
9988 }
9989 if (trailers != NULL) {
9990 if (!PySequence_Check(trailers)) {
9991 PyErr_SetString(PyExc_TypeError,
9992 "sendfile() trailers must be a sequence");
9993 return NULL;
9994 } else {
9995 Py_ssize_t i = PySequence_Size(trailers);
9996 if (i < 0)
9997 return NULL;
9998 if (i > INT_MAX) {
9999 PyErr_SetString(PyExc_OverflowError,
10000 "sendfile() trailer is too large");
10001 return NULL;
10002 }
10003 if (i > 0) {
10004 sf.trl_cnt = (int)i;
10005 if (iov_setup(&(sf.trailers), &tbuf,
10006 trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
10007 return NULL;
10008 }
10009 }
10010 }
10011
10012 _Py_BEGIN_SUPPRESS_IPH
10013 do {
10014 Py_BEGIN_ALLOW_THREADS
10015 #ifdef __APPLE__
10016 ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
10017 #else
10018 ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
10019 #endif
10020 Py_END_ALLOW_THREADS
10021 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10022 _Py_END_SUPPRESS_IPH
10023
10024 if (sf.headers != NULL)
10025 iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
10026 if (sf.trailers != NULL)
10027 iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
10028
10029 if (ret < 0) {
10030 if ((errno == EAGAIN) || (errno == EBUSY)) {
10031 if (sbytes != 0) {
10032 // some data has been sent
10033 goto done;
10034 }
10035 else {
10036 // no data has been sent; upper application is supposed
10037 // to retry on EAGAIN or EBUSY
10038 return posix_error();
10039 }
10040 }
10041 return (!async_err) ? posix_error() : NULL;
10042 }
10043 goto done;
10044
10045 done:
10046 #if !defined(HAVE_LARGEFILE_SUPPORT)
10047 return Py_BuildValue("l", sbytes);
10048 #else
10049 return Py_BuildValue("L", sbytes);
10050 #endif
10051
10052 #else
10053 #ifdef __linux__
10054 if (offobj == Py_None) {
10055 do {
10056 Py_BEGIN_ALLOW_THREADS
10057 ret = sendfile(out_fd, in_fd, NULL, count);
10058 Py_END_ALLOW_THREADS
10059 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10060 if (ret < 0)
10061 return (!async_err) ? posix_error() : NULL;
10062 return Py_BuildValue("n", ret);
10063 }
10064 #endif
10065 off_t offset;
10066 if (!Py_off_t_converter(offobj, &offset))
10067 return NULL;
10068
10069 #if defined(__sun) && defined(__SVR4)
10070 // On Solaris, sendfile raises EINVAL rather than returning 0
10071 // when the offset is equal or bigger than the in_fd size.
10072 struct stat st;
10073
10074 do {
10075 Py_BEGIN_ALLOW_THREADS
10076 ret = fstat(in_fd, &st);
10077 Py_END_ALLOW_THREADS
10078 } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10079 if (ret < 0)
10080 return (!async_err) ? posix_error() : NULL;
10081
10082 if (offset >= st.st_size) {
10083 return Py_BuildValue("i", 0);
10084 }
10085
10086 // On illumos specifically sendfile() may perform a partial write but
10087 // return -1/an error (in one confirmed case the destination socket
10088 // had a 5 second timeout set and errno was EAGAIN) and it's on the client
10089 // code to check if the offset parameter was modified by sendfile().
10090 //
10091 // We need this variable to track said change.
10092 off_t original_offset = offset;
10093 #endif
10094
10095 do {
10096 Py_BEGIN_ALLOW_THREADS
10097 ret = sendfile(out_fd, in_fd, &offset, count);
10098 #if defined(__sun) && defined(__SVR4)
10099 // This handles illumos-specific sendfile() partial write behavior,
10100 // see a comment above for more details.
10101 if (ret < 0 && offset != original_offset) {
10102 ret = offset - original_offset;
10103 }
10104 #endif
10105 Py_END_ALLOW_THREADS
10106 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10107 if (ret < 0)
10108 return (!async_err) ? posix_error() : NULL;
10109 return Py_BuildValue("n", ret);
10110 #endif
10111 }
10112 #endif /* HAVE_SENDFILE */
10113
10114
10115 #if defined(__APPLE__)
10116 /*[clinic input]
10117 os._fcopyfile
10118
10119 in_fd: int
10120 out_fd: int
10121 flags: int
10122 /
10123
10124 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
10125 [clinic start generated code]*/
10126
10127 static PyObject *
os__fcopyfile_impl(PyObject * module,int in_fd,int out_fd,int flags)10128 os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
10129 /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
10130 {
10131 int ret;
10132
10133 Py_BEGIN_ALLOW_THREADS
10134 ret = fcopyfile(in_fd, out_fd, NULL, flags);
10135 Py_END_ALLOW_THREADS
10136 if (ret < 0)
10137 return posix_error();
10138 Py_RETURN_NONE;
10139 }
10140 #endif
10141
10142
10143 /*[clinic input]
10144 os.fstat
10145
10146 fd : int
10147
10148 Perform a stat system call on the given file descriptor.
10149
10150 Like stat(), but for an open file descriptor.
10151 Equivalent to os.stat(fd).
10152 [clinic start generated code]*/
10153
10154 static PyObject *
os_fstat_impl(PyObject * module,int fd)10155 os_fstat_impl(PyObject *module, int fd)
10156 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
10157 {
10158 STRUCT_STAT st;
10159 int res;
10160 int async_err = 0;
10161
10162 do {
10163 Py_BEGIN_ALLOW_THREADS
10164 res = FSTAT(fd, &st);
10165 Py_END_ALLOW_THREADS
10166 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10167 if (res != 0) {
10168 #ifdef MS_WINDOWS
10169 return PyErr_SetFromWindowsErr(0);
10170 #else
10171 return (!async_err) ? posix_error() : NULL;
10172 #endif
10173 }
10174
10175 return _pystat_fromstructstat(module, &st);
10176 }
10177
10178
10179 /*[clinic input]
10180 os.isatty -> bool
10181 fd: int
10182 /
10183
10184 Return True if the fd is connected to a terminal.
10185
10186 Return True if the file descriptor is an open file descriptor
10187 connected to the slave end of a terminal.
10188 [clinic start generated code]*/
10189
10190 static int
os_isatty_impl(PyObject * module,int fd)10191 os_isatty_impl(PyObject *module, int fd)
10192 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
10193 {
10194 int return_value;
10195 Py_BEGIN_ALLOW_THREADS
10196 _Py_BEGIN_SUPPRESS_IPH
10197 return_value = isatty(fd);
10198 _Py_END_SUPPRESS_IPH
10199 Py_END_ALLOW_THREADS
10200 return return_value;
10201 }
10202
10203
10204 #ifdef HAVE_PIPE
10205 /*[clinic input]
10206 os.pipe
10207
10208 Create a pipe.
10209
10210 Returns a tuple of two file descriptors:
10211 (read_fd, write_fd)
10212 [clinic start generated code]*/
10213
10214 static PyObject *
os_pipe_impl(PyObject * module)10215 os_pipe_impl(PyObject *module)
10216 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
10217 {
10218 int fds[2];
10219 #ifdef MS_WINDOWS
10220 HANDLE read, write;
10221 SECURITY_ATTRIBUTES attr;
10222 BOOL ok;
10223 #else
10224 int res;
10225 #endif
10226
10227 #ifdef MS_WINDOWS
10228 attr.nLength = sizeof(attr);
10229 attr.lpSecurityDescriptor = NULL;
10230 attr.bInheritHandle = FALSE;
10231
10232 Py_BEGIN_ALLOW_THREADS
10233 ok = CreatePipe(&read, &write, &attr, 0);
10234 if (ok) {
10235 fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY);
10236 fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY);
10237 if (fds[0] == -1 || fds[1] == -1) {
10238 CloseHandle(read);
10239 CloseHandle(write);
10240 ok = 0;
10241 }
10242 }
10243 Py_END_ALLOW_THREADS
10244
10245 if (!ok)
10246 return PyErr_SetFromWindowsErr(0);
10247 #else
10248
10249 #ifdef HAVE_PIPE2
10250 Py_BEGIN_ALLOW_THREADS
10251 res = pipe2(fds, O_CLOEXEC);
10252 Py_END_ALLOW_THREADS
10253
10254 if (res != 0 && errno == ENOSYS)
10255 {
10256 #endif
10257 Py_BEGIN_ALLOW_THREADS
10258 res = pipe(fds);
10259 Py_END_ALLOW_THREADS
10260
10261 if (res == 0) {
10262 if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
10263 close(fds[0]);
10264 close(fds[1]);
10265 return NULL;
10266 }
10267 if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
10268 close(fds[0]);
10269 close(fds[1]);
10270 return NULL;
10271 }
10272 }
10273 #ifdef HAVE_PIPE2
10274 }
10275 #endif
10276
10277 if (res != 0)
10278 return PyErr_SetFromErrno(PyExc_OSError);
10279 #endif /* !MS_WINDOWS */
10280 return Py_BuildValue("(ii)", fds[0], fds[1]);
10281 }
10282 #endif /* HAVE_PIPE */
10283
10284
10285 #ifdef HAVE_PIPE2
10286 /*[clinic input]
10287 os.pipe2
10288
10289 flags: int
10290 /
10291
10292 Create a pipe with flags set atomically.
10293
10294 Returns a tuple of two file descriptors:
10295 (read_fd, write_fd)
10296
10297 flags can be constructed by ORing together one or more of these values:
10298 O_NONBLOCK, O_CLOEXEC.
10299 [clinic start generated code]*/
10300
10301 static PyObject *
os_pipe2_impl(PyObject * module,int flags)10302 os_pipe2_impl(PyObject *module, int flags)
10303 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
10304 {
10305 int fds[2];
10306 int res;
10307
10308 res = pipe2(fds, flags);
10309 if (res != 0)
10310 return posix_error();
10311 return Py_BuildValue("(ii)", fds[0], fds[1]);
10312 }
10313 #endif /* HAVE_PIPE2 */
10314
10315
10316 #ifdef HAVE_WRITEV
10317 /*[clinic input]
10318 os.writev -> Py_ssize_t
10319 fd: int
10320 buffers: object
10321 /
10322
10323 Iterate over buffers, and write the contents of each to a file descriptor.
10324
10325 Returns the total number of bytes written.
10326 buffers must be a sequence of bytes-like objects.
10327 [clinic start generated code]*/
10328
10329 static Py_ssize_t
os_writev_impl(PyObject * module,int fd,PyObject * buffers)10330 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
10331 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
10332 {
10333 Py_ssize_t cnt;
10334 Py_ssize_t result;
10335 int async_err = 0;
10336 struct iovec *iov;
10337 Py_buffer *buf;
10338
10339 if (!PySequence_Check(buffers)) {
10340 PyErr_SetString(PyExc_TypeError,
10341 "writev() arg 2 must be a sequence");
10342 return -1;
10343 }
10344 cnt = PySequence_Size(buffers);
10345 if (cnt < 0)
10346 return -1;
10347
10348 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10349 return -1;
10350 }
10351
10352 do {
10353 Py_BEGIN_ALLOW_THREADS
10354 result = writev(fd, iov, cnt);
10355 Py_END_ALLOW_THREADS
10356 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10357
10358 iov_cleanup(iov, buf, cnt);
10359 if (result < 0 && !async_err)
10360 posix_error();
10361
10362 return result;
10363 }
10364 #endif /* HAVE_WRITEV */
10365
10366
10367 #ifdef HAVE_PWRITE
10368 /*[clinic input]
10369 os.pwrite -> Py_ssize_t
10370
10371 fd: int
10372 buffer: Py_buffer
10373 offset: Py_off_t
10374 /
10375
10376 Write bytes to a file descriptor starting at a particular offset.
10377
10378 Write buffer to fd, starting at offset bytes from the beginning of
10379 the file. Returns the number of bytes writte. Does not change the
10380 current file offset.
10381 [clinic start generated code]*/
10382
10383 static Py_ssize_t
os_pwrite_impl(PyObject * module,int fd,Py_buffer * buffer,Py_off_t offset)10384 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
10385 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
10386 {
10387 Py_ssize_t size;
10388 int async_err = 0;
10389
10390 do {
10391 Py_BEGIN_ALLOW_THREADS
10392 _Py_BEGIN_SUPPRESS_IPH
10393 size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
10394 _Py_END_SUPPRESS_IPH
10395 Py_END_ALLOW_THREADS
10396 } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10397
10398 if (size < 0 && !async_err)
10399 posix_error();
10400 return size;
10401 }
10402 #endif /* HAVE_PWRITE */
10403
10404 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
10405 /*[clinic input]
10406 os.pwritev -> Py_ssize_t
10407
10408 fd: int
10409 buffers: object
10410 offset: Py_off_t
10411 flags: int = 0
10412 /
10413
10414 Writes the contents of bytes-like objects to a file descriptor at a given offset.
10415
10416 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
10417 of bytes-like objects. Buffers are processed in array order. Entire contents of first
10418 buffer is written before proceeding to second, and so on. The operating system may
10419 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
10420 This function writes the contents of each object to the file descriptor and returns
10421 the total number of bytes written.
10422
10423 The flags argument contains a bitwise OR of zero or more of the following flags:
10424
10425 - RWF_DSYNC
10426 - RWF_SYNC
10427 - RWF_APPEND
10428
10429 Using non-zero flags requires Linux 4.7 or newer.
10430 [clinic start generated code]*/
10431
10432 static Py_ssize_t
os_pwritev_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)10433 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
10434 int flags)
10435 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
10436 {
10437 Py_ssize_t cnt;
10438 Py_ssize_t result;
10439 int async_err = 0;
10440 struct iovec *iov;
10441 Py_buffer *buf;
10442
10443 if (!PySequence_Check(buffers)) {
10444 PyErr_SetString(PyExc_TypeError,
10445 "pwritev() arg 2 must be a sequence");
10446 return -1;
10447 }
10448
10449 cnt = PySequence_Size(buffers);
10450 if (cnt < 0) {
10451 return -1;
10452 }
10453
10454 #ifndef HAVE_PWRITEV2
10455 if(flags != 0) {
10456 argument_unavailable_error("pwritev2", "flags");
10457 return -1;
10458 }
10459 #endif
10460
10461 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10462 return -1;
10463 }
10464 #ifdef HAVE_PWRITEV2
10465 do {
10466 Py_BEGIN_ALLOW_THREADS
10467 _Py_BEGIN_SUPPRESS_IPH
10468 result = pwritev2(fd, iov, cnt, offset, flags);
10469 _Py_END_SUPPRESS_IPH
10470 Py_END_ALLOW_THREADS
10471 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10472 #else
10473
10474 #if defined(__APPLE__) && defined(__clang__)
10475 /* This entire function will be removed from the module dict when the API
10476 * is not available.
10477 */
10478 #pragma clang diagnostic push
10479 #pragma clang diagnostic ignored "-Wunguarded-availability"
10480 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
10481 #endif
10482 do {
10483 Py_BEGIN_ALLOW_THREADS
10484 _Py_BEGIN_SUPPRESS_IPH
10485 result = pwritev(fd, iov, cnt, offset);
10486 _Py_END_SUPPRESS_IPH
10487 Py_END_ALLOW_THREADS
10488 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10489
10490 #if defined(__APPLE__) && defined(__clang__)
10491 #pragma clang diagnostic pop
10492 #endif
10493
10494 #endif
10495
10496 iov_cleanup(iov, buf, cnt);
10497 if (result < 0) {
10498 if (!async_err) {
10499 posix_error();
10500 }
10501 return -1;
10502 }
10503
10504 return result;
10505 }
10506 #endif /* HAVE_PWRITEV */
10507
10508 #ifdef HAVE_COPY_FILE_RANGE
10509 /*[clinic input]
10510
10511 os.copy_file_range
10512 src: int
10513 Source file descriptor.
10514 dst: int
10515 Destination file descriptor.
10516 count: Py_ssize_t
10517 Number of bytes to copy.
10518 offset_src: object = None
10519 Starting offset in src.
10520 offset_dst: object = None
10521 Starting offset in dst.
10522
10523 Copy count bytes from one file descriptor to another.
10524
10525 If offset_src is None, then src is read from the current position;
10526 respectively for offset_dst.
10527 [clinic start generated code]*/
10528
10529 static PyObject *
os_copy_file_range_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst)10530 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10531 PyObject *offset_src, PyObject *offset_dst)
10532 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
10533 {
10534 off_t offset_src_val, offset_dst_val;
10535 off_t *p_offset_src = NULL;
10536 off_t *p_offset_dst = NULL;
10537 Py_ssize_t ret;
10538 int async_err = 0;
10539 /* The flags argument is provided to allow
10540 * for future extensions and currently must be to 0. */
10541 int flags = 0;
10542
10543
10544 if (count < 0) {
10545 PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10546 return NULL;
10547 }
10548
10549 if (offset_src != Py_None) {
10550 if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10551 return NULL;
10552 }
10553 p_offset_src = &offset_src_val;
10554 }
10555
10556 if (offset_dst != Py_None) {
10557 if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10558 return NULL;
10559 }
10560 p_offset_dst = &offset_dst_val;
10561 }
10562
10563 do {
10564 Py_BEGIN_ALLOW_THREADS
10565 ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
10566 Py_END_ALLOW_THREADS
10567 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10568
10569 if (ret < 0) {
10570 return (!async_err) ? posix_error() : NULL;
10571 }
10572
10573 return PyLong_FromSsize_t(ret);
10574 }
10575 #endif /* HAVE_COPY_FILE_RANGE*/
10576
10577 #if (defined(HAVE_SPLICE) && !defined(_AIX))
10578 /*[clinic input]
10579
10580 os.splice
10581 src: int
10582 Source file descriptor.
10583 dst: int
10584 Destination file descriptor.
10585 count: Py_ssize_t
10586 Number of bytes to copy.
10587 offset_src: object = None
10588 Starting offset in src.
10589 offset_dst: object = None
10590 Starting offset in dst.
10591 flags: unsigned_int = 0
10592 Flags to modify the semantics of the call.
10593
10594 Transfer count bytes from one pipe to a descriptor or vice versa.
10595
10596 If offset_src is None, then src is read from the current position;
10597 respectively for offset_dst. The offset associated to the file
10598 descriptor that refers to a pipe must be None.
10599 [clinic start generated code]*/
10600
10601 static PyObject *
os_splice_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst,unsigned int flags)10602 os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10603 PyObject *offset_src, PyObject *offset_dst,
10604 unsigned int flags)
10605 /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
10606 {
10607 off_t offset_src_val, offset_dst_val;
10608 off_t *p_offset_src = NULL;
10609 off_t *p_offset_dst = NULL;
10610 Py_ssize_t ret;
10611 int async_err = 0;
10612
10613 if (count < 0) {
10614 PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10615 return NULL;
10616 }
10617
10618 if (offset_src != Py_None) {
10619 if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10620 return NULL;
10621 }
10622 p_offset_src = &offset_src_val;
10623 }
10624
10625 if (offset_dst != Py_None) {
10626 if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10627 return NULL;
10628 }
10629 p_offset_dst = &offset_dst_val;
10630 }
10631
10632 do {
10633 Py_BEGIN_ALLOW_THREADS
10634 ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
10635 Py_END_ALLOW_THREADS
10636 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10637
10638 if (ret < 0) {
10639 return (!async_err) ? posix_error() : NULL;
10640 }
10641
10642 return PyLong_FromSsize_t(ret);
10643 }
10644 #endif /* HAVE_SPLICE*/
10645
10646 #ifdef HAVE_MKFIFO
10647 /*[clinic input]
10648 os.mkfifo
10649
10650 path: path_t
10651 mode: int=0o666
10652 *
10653 dir_fd: dir_fd(requires='mkfifoat')=None
10654
10655 Create a "fifo" (a POSIX named pipe).
10656
10657 If dir_fd is not None, it should be a file descriptor open to a directory,
10658 and path should be relative; path will then be relative to that directory.
10659 dir_fd may not be implemented on your platform.
10660 If it is unavailable, using it will raise a NotImplementedError.
10661 [clinic start generated code]*/
10662
10663 static PyObject *
os_mkfifo_impl(PyObject * module,path_t * path,int mode,int dir_fd)10664 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
10665 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
10666 {
10667 int result;
10668 int async_err = 0;
10669 #ifdef HAVE_MKFIFOAT
10670 int mkfifoat_unavailable = 0;
10671 #endif
10672
10673 do {
10674 Py_BEGIN_ALLOW_THREADS
10675 #ifdef HAVE_MKFIFOAT
10676 if (dir_fd != DEFAULT_DIR_FD) {
10677 if (HAVE_MKFIFOAT_RUNTIME) {
10678 result = mkfifoat(dir_fd, path->narrow, mode);
10679
10680 } else {
10681 mkfifoat_unavailable = 1;
10682 result = 0;
10683 }
10684 } else
10685 #endif
10686 result = mkfifo(path->narrow, mode);
10687 Py_END_ALLOW_THREADS
10688 } while (result != 0 && errno == EINTR &&
10689 !(async_err = PyErr_CheckSignals()));
10690
10691 #ifdef HAVE_MKFIFOAT
10692 if (mkfifoat_unavailable) {
10693 argument_unavailable_error(NULL, "dir_fd");
10694 return NULL;
10695 }
10696 #endif
10697
10698 if (result != 0)
10699 return (!async_err) ? posix_error() : NULL;
10700
10701 Py_RETURN_NONE;
10702 }
10703 #endif /* HAVE_MKFIFO */
10704
10705
10706 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
10707 /*[clinic input]
10708 os.mknod
10709
10710 path: path_t
10711 mode: int=0o600
10712 device: dev_t=0
10713 *
10714 dir_fd: dir_fd(requires='mknodat')=None
10715
10716 Create a node in the file system.
10717
10718 Create a node in the file system (file, device special file or named pipe)
10719 at path. mode specifies both the permissions to use and the
10720 type of node to be created, being combined (bitwise OR) with one of
10721 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,
10722 device defines the newly created device special file (probably using
10723 os.makedev()). Otherwise device is ignored.
10724
10725 If dir_fd is not None, it should be a file descriptor open to a directory,
10726 and path should be relative; path will then be relative to that directory.
10727 dir_fd may not be implemented on your platform.
10728 If it is unavailable, using it will raise a NotImplementedError.
10729 [clinic start generated code]*/
10730
10731 static PyObject *
os_mknod_impl(PyObject * module,path_t * path,int mode,dev_t device,int dir_fd)10732 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
10733 int dir_fd)
10734 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
10735 {
10736 int result;
10737 int async_err = 0;
10738 #ifdef HAVE_MKNODAT
10739 int mknodat_unavailable = 0;
10740 #endif
10741
10742 do {
10743 Py_BEGIN_ALLOW_THREADS
10744 #ifdef HAVE_MKNODAT
10745 if (dir_fd != DEFAULT_DIR_FD) {
10746 if (HAVE_MKNODAT_RUNTIME) {
10747 result = mknodat(dir_fd, path->narrow, mode, device);
10748
10749 } else {
10750 mknodat_unavailable = 1;
10751 result = 0;
10752 }
10753 } else
10754 #endif
10755 result = mknod(path->narrow, mode, device);
10756 Py_END_ALLOW_THREADS
10757 } while (result != 0 && errno == EINTR &&
10758 !(async_err = PyErr_CheckSignals()));
10759 #ifdef HAVE_MKNODAT
10760 if (mknodat_unavailable) {
10761 argument_unavailable_error(NULL, "dir_fd");
10762 return NULL;
10763 }
10764 #endif
10765 if (result != 0)
10766 return (!async_err) ? posix_error() : NULL;
10767
10768 Py_RETURN_NONE;
10769 }
10770 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
10771
10772
10773 #ifdef HAVE_DEVICE_MACROS
10774 /*[clinic input]
10775 os.major -> unsigned_int
10776
10777 device: dev_t
10778 /
10779
10780 Extracts a device major number from a raw device number.
10781 [clinic start generated code]*/
10782
10783 static unsigned int
os_major_impl(PyObject * module,dev_t device)10784 os_major_impl(PyObject *module, dev_t device)
10785 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
10786 {
10787 return major(device);
10788 }
10789
10790
10791 /*[clinic input]
10792 os.minor -> unsigned_int
10793
10794 device: dev_t
10795 /
10796
10797 Extracts a device minor number from a raw device number.
10798 [clinic start generated code]*/
10799
10800 static unsigned int
os_minor_impl(PyObject * module,dev_t device)10801 os_minor_impl(PyObject *module, dev_t device)
10802 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10803 {
10804 return minor(device);
10805 }
10806
10807
10808 /*[clinic input]
10809 os.makedev -> dev_t
10810
10811 major: int
10812 minor: int
10813 /
10814
10815 Composes a raw device number from the major and minor device numbers.
10816 [clinic start generated code]*/
10817
10818 static dev_t
os_makedev_impl(PyObject * module,int major,int minor)10819 os_makedev_impl(PyObject *module, int major, int minor)
10820 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10821 {
10822 return makedev(major, minor);
10823 }
10824 #endif /* HAVE_DEVICE_MACROS */
10825
10826
10827 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10828 /*[clinic input]
10829 os.ftruncate
10830
10831 fd: int
10832 length: Py_off_t
10833 /
10834
10835 Truncate a file, specified by file descriptor, to a specific length.
10836 [clinic start generated code]*/
10837
10838 static PyObject *
os_ftruncate_impl(PyObject * module,int fd,Py_off_t length)10839 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10840 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10841 {
10842 int result;
10843 int async_err = 0;
10844
10845 if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10846 return NULL;
10847 }
10848
10849 do {
10850 Py_BEGIN_ALLOW_THREADS
10851 _Py_BEGIN_SUPPRESS_IPH
10852 #ifdef MS_WINDOWS
10853 result = _chsize_s(fd, length);
10854 #else
10855 result = ftruncate(fd, length);
10856 #endif
10857 _Py_END_SUPPRESS_IPH
10858 Py_END_ALLOW_THREADS
10859 } while (result != 0 && errno == EINTR &&
10860 !(async_err = PyErr_CheckSignals()));
10861 if (result != 0)
10862 return (!async_err) ? posix_error() : NULL;
10863 Py_RETURN_NONE;
10864 }
10865 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10866
10867
10868 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10869 /*[clinic input]
10870 os.truncate
10871 path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10872 length: Py_off_t
10873
10874 Truncate a file, specified by path, to a specific length.
10875
10876 On some platforms, path may also be specified as an open file descriptor.
10877 If this functionality is unavailable, using it raises an exception.
10878 [clinic start generated code]*/
10879
10880 static PyObject *
os_truncate_impl(PyObject * module,path_t * path,Py_off_t length)10881 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10882 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10883 {
10884 int result;
10885 #ifdef MS_WINDOWS
10886 int fd;
10887 #endif
10888
10889 if (path->fd != -1)
10890 return os_ftruncate_impl(module, path->fd, length);
10891
10892 if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10893 return NULL;
10894 }
10895
10896 Py_BEGIN_ALLOW_THREADS
10897 _Py_BEGIN_SUPPRESS_IPH
10898 #ifdef MS_WINDOWS
10899 fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10900 if (fd < 0)
10901 result = -1;
10902 else {
10903 result = _chsize_s(fd, length);
10904 close(fd);
10905 if (result < 0)
10906 errno = result;
10907 }
10908 #else
10909 result = truncate(path->narrow, length);
10910 #endif
10911 _Py_END_SUPPRESS_IPH
10912 Py_END_ALLOW_THREADS
10913 if (result < 0)
10914 return posix_path_error(path);
10915
10916 Py_RETURN_NONE;
10917 }
10918 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10919
10920
10921 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10922 and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10923 defined, which is the case in Python on AIX. AIX bug report:
10924 http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10925 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10926 # define POSIX_FADVISE_AIX_BUG
10927 #endif
10928
10929
10930 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10931 /*[clinic input]
10932 os.posix_fallocate
10933
10934 fd: int
10935 offset: Py_off_t
10936 length: Py_off_t
10937 /
10938
10939 Ensure a file has allocated at least a particular number of bytes on disk.
10940
10941 Ensure that the file specified by fd encompasses a range of bytes
10942 starting at offset bytes from the beginning and continuing for length bytes.
10943 [clinic start generated code]*/
10944
10945 static PyObject *
os_posix_fallocate_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length)10946 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10947 Py_off_t length)
10948 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10949 {
10950 int result;
10951 int async_err = 0;
10952
10953 do {
10954 Py_BEGIN_ALLOW_THREADS
10955 result = posix_fallocate(fd, offset, length);
10956 Py_END_ALLOW_THREADS
10957 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10958
10959 if (result == 0)
10960 Py_RETURN_NONE;
10961
10962 if (async_err)
10963 return NULL;
10964
10965 errno = result;
10966 return posix_error();
10967 }
10968 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
10969
10970
10971 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
10972 /*[clinic input]
10973 os.posix_fadvise
10974
10975 fd: int
10976 offset: Py_off_t
10977 length: Py_off_t
10978 advice: int
10979 /
10980
10981 Announce an intention to access data in a specific pattern.
10982
10983 Announce an intention to access data in a specific pattern, thus allowing
10984 the kernel to make optimizations.
10985 The advice applies to the region of the file specified by fd starting at
10986 offset and continuing for length bytes.
10987 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
10988 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
10989 POSIX_FADV_DONTNEED.
10990 [clinic start generated code]*/
10991
10992 static PyObject *
os_posix_fadvise_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length,int advice)10993 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
10994 Py_off_t length, int advice)
10995 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
10996 {
10997 int result;
10998 int async_err = 0;
10999
11000 do {
11001 Py_BEGIN_ALLOW_THREADS
11002 result = posix_fadvise(fd, offset, length, advice);
11003 Py_END_ALLOW_THREADS
11004 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
11005
11006 if (result == 0)
11007 Py_RETURN_NONE;
11008
11009 if (async_err)
11010 return NULL;
11011
11012 errno = result;
11013 return posix_error();
11014 }
11015 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
11016
11017
11018 #ifdef MS_WINDOWS
11019 static PyObject*
win32_putenv(PyObject * name,PyObject * value)11020 win32_putenv(PyObject *name, PyObject *value)
11021 {
11022 /* Search from index 1 because on Windows starting '=' is allowed for
11023 defining hidden environment variables. */
11024 if (PyUnicode_GET_LENGTH(name) == 0 ||
11025 PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
11026 {
11027 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11028 return NULL;
11029 }
11030 PyObject *unicode;
11031 if (value != NULL) {
11032 unicode = PyUnicode_FromFormat("%U=%U", name, value);
11033 }
11034 else {
11035 unicode = PyUnicode_FromFormat("%U=", name);
11036 }
11037 if (unicode == NULL) {
11038 return NULL;
11039 }
11040
11041 Py_ssize_t size;
11042 /* PyUnicode_AsWideCharString() rejects embedded null characters */
11043 wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
11044 Py_DECREF(unicode);
11045
11046 if (env == NULL) {
11047 return NULL;
11048 }
11049 if (size > _MAX_ENV) {
11050 PyErr_Format(PyExc_ValueError,
11051 "the environment variable is longer than %u characters",
11052 _MAX_ENV);
11053 PyMem_Free(env);
11054 return NULL;
11055 }
11056
11057 /* _wputenv() and SetEnvironmentVariableW() update the environment in the
11058 Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
11059 and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
11060
11061 Prefer _wputenv() to be compatible with C libraries using CRT
11062 variables and CRT functions using these variables (ex: getenv()). */
11063 int err = _wputenv(env);
11064 PyMem_Free(env);
11065
11066 if (err) {
11067 posix_error();
11068 return NULL;
11069 }
11070
11071 Py_RETURN_NONE;
11072 }
11073 #endif
11074
11075
11076 #ifdef MS_WINDOWS
11077 /*[clinic input]
11078 os.putenv
11079
11080 name: unicode
11081 value: unicode
11082 /
11083
11084 Change or add an environment variable.
11085 [clinic start generated code]*/
11086
11087 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)11088 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11089 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
11090 {
11091 if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11092 return NULL;
11093 }
11094 return win32_putenv(name, value);
11095 }
11096 #else
11097 /*[clinic input]
11098 os.putenv
11099
11100 name: FSConverter
11101 value: FSConverter
11102 /
11103
11104 Change or add an environment variable.
11105 [clinic start generated code]*/
11106
11107 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)11108 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11109 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
11110 {
11111 const char *name_string = PyBytes_AS_STRING(name);
11112 const char *value_string = PyBytes_AS_STRING(value);
11113
11114 if (strchr(name_string, '=') != NULL) {
11115 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11116 return NULL;
11117 }
11118
11119 if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11120 return NULL;
11121 }
11122
11123 if (setenv(name_string, value_string, 1)) {
11124 return posix_error();
11125 }
11126 Py_RETURN_NONE;
11127 }
11128 #endif /* !defined(MS_WINDOWS) */
11129
11130
11131 #ifdef MS_WINDOWS
11132 /*[clinic input]
11133 os.unsetenv
11134 name: unicode
11135 /
11136
11137 Delete an environment variable.
11138 [clinic start generated code]*/
11139
11140 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)11141 os_unsetenv_impl(PyObject *module, PyObject *name)
11142 /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
11143 {
11144 if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11145 return NULL;
11146 }
11147 return win32_putenv(name, NULL);
11148 }
11149 #else
11150 /*[clinic input]
11151 os.unsetenv
11152 name: FSConverter
11153 /
11154
11155 Delete an environment variable.
11156 [clinic start generated code]*/
11157
11158 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)11159 os_unsetenv_impl(PyObject *module, PyObject *name)
11160 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
11161 {
11162 if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11163 return NULL;
11164 }
11165 #ifdef HAVE_BROKEN_UNSETENV
11166 unsetenv(PyBytes_AS_STRING(name));
11167 #else
11168 int err = unsetenv(PyBytes_AS_STRING(name));
11169 if (err) {
11170 return posix_error();
11171 }
11172 #endif
11173
11174 Py_RETURN_NONE;
11175 }
11176 #endif /* !MS_WINDOWS */
11177
11178
11179 /*[clinic input]
11180 os.strerror
11181
11182 code: int
11183 /
11184
11185 Translate an error code to a message string.
11186 [clinic start generated code]*/
11187
11188 static PyObject *
os_strerror_impl(PyObject * module,int code)11189 os_strerror_impl(PyObject *module, int code)
11190 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
11191 {
11192 char *message = strerror(code);
11193 if (message == NULL) {
11194 PyErr_SetString(PyExc_ValueError,
11195 "strerror() argument out of range");
11196 return NULL;
11197 }
11198 return PyUnicode_DecodeLocale(message, "surrogateescape");
11199 }
11200
11201
11202 #ifdef HAVE_SYS_WAIT_H
11203 #ifdef WCOREDUMP
11204 /*[clinic input]
11205 os.WCOREDUMP -> bool
11206
11207 status: int
11208 /
11209
11210 Return True if the process returning status was dumped to a core file.
11211 [clinic start generated code]*/
11212
11213 static int
os_WCOREDUMP_impl(PyObject * module,int status)11214 os_WCOREDUMP_impl(PyObject *module, int status)
11215 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
11216 {
11217 WAIT_TYPE wait_status;
11218 WAIT_STATUS_INT(wait_status) = status;
11219 return WCOREDUMP(wait_status);
11220 }
11221 #endif /* WCOREDUMP */
11222
11223
11224 #ifdef WIFCONTINUED
11225 /*[clinic input]
11226 os.WIFCONTINUED -> bool
11227
11228 status: int
11229
11230 Return True if a particular process was continued from a job control stop.
11231
11232 Return True if the process returning status was continued from a
11233 job control stop.
11234 [clinic start generated code]*/
11235
11236 static int
os_WIFCONTINUED_impl(PyObject * module,int status)11237 os_WIFCONTINUED_impl(PyObject *module, int status)
11238 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
11239 {
11240 WAIT_TYPE wait_status;
11241 WAIT_STATUS_INT(wait_status) = status;
11242 return WIFCONTINUED(wait_status);
11243 }
11244 #endif /* WIFCONTINUED */
11245
11246
11247 #ifdef WIFSTOPPED
11248 /*[clinic input]
11249 os.WIFSTOPPED -> bool
11250
11251 status: int
11252
11253 Return True if the process returning status was stopped.
11254 [clinic start generated code]*/
11255
11256 static int
os_WIFSTOPPED_impl(PyObject * module,int status)11257 os_WIFSTOPPED_impl(PyObject *module, int status)
11258 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
11259 {
11260 WAIT_TYPE wait_status;
11261 WAIT_STATUS_INT(wait_status) = status;
11262 return WIFSTOPPED(wait_status);
11263 }
11264 #endif /* WIFSTOPPED */
11265
11266
11267 #ifdef WIFSIGNALED
11268 /*[clinic input]
11269 os.WIFSIGNALED -> bool
11270
11271 status: int
11272
11273 Return True if the process returning status was terminated by a signal.
11274 [clinic start generated code]*/
11275
11276 static int
os_WIFSIGNALED_impl(PyObject * module,int status)11277 os_WIFSIGNALED_impl(PyObject *module, int status)
11278 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
11279 {
11280 WAIT_TYPE wait_status;
11281 WAIT_STATUS_INT(wait_status) = status;
11282 return WIFSIGNALED(wait_status);
11283 }
11284 #endif /* WIFSIGNALED */
11285
11286
11287 #ifdef WIFEXITED
11288 /*[clinic input]
11289 os.WIFEXITED -> bool
11290
11291 status: int
11292
11293 Return True if the process returning status exited via the exit() system call.
11294 [clinic start generated code]*/
11295
11296 static int
os_WIFEXITED_impl(PyObject * module,int status)11297 os_WIFEXITED_impl(PyObject *module, int status)
11298 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
11299 {
11300 WAIT_TYPE wait_status;
11301 WAIT_STATUS_INT(wait_status) = status;
11302 return WIFEXITED(wait_status);
11303 }
11304 #endif /* WIFEXITED */
11305
11306
11307 #ifdef WEXITSTATUS
11308 /*[clinic input]
11309 os.WEXITSTATUS -> int
11310
11311 status: int
11312
11313 Return the process return code from status.
11314 [clinic start generated code]*/
11315
11316 static int
os_WEXITSTATUS_impl(PyObject * module,int status)11317 os_WEXITSTATUS_impl(PyObject *module, int status)
11318 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
11319 {
11320 WAIT_TYPE wait_status;
11321 WAIT_STATUS_INT(wait_status) = status;
11322 return WEXITSTATUS(wait_status);
11323 }
11324 #endif /* WEXITSTATUS */
11325
11326
11327 #ifdef WTERMSIG
11328 /*[clinic input]
11329 os.WTERMSIG -> int
11330
11331 status: int
11332
11333 Return the signal that terminated the process that provided the status value.
11334 [clinic start generated code]*/
11335
11336 static int
os_WTERMSIG_impl(PyObject * module,int status)11337 os_WTERMSIG_impl(PyObject *module, int status)
11338 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
11339 {
11340 WAIT_TYPE wait_status;
11341 WAIT_STATUS_INT(wait_status) = status;
11342 return WTERMSIG(wait_status);
11343 }
11344 #endif /* WTERMSIG */
11345
11346
11347 #ifdef WSTOPSIG
11348 /*[clinic input]
11349 os.WSTOPSIG -> int
11350
11351 status: int
11352
11353 Return the signal that stopped the process that provided the status value.
11354 [clinic start generated code]*/
11355
11356 static int
os_WSTOPSIG_impl(PyObject * module,int status)11357 os_WSTOPSIG_impl(PyObject *module, int status)
11358 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
11359 {
11360 WAIT_TYPE wait_status;
11361 WAIT_STATUS_INT(wait_status) = status;
11362 return WSTOPSIG(wait_status);
11363 }
11364 #endif /* WSTOPSIG */
11365 #endif /* HAVE_SYS_WAIT_H */
11366
11367
11368 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
11369 #ifdef _SCO_DS
11370 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
11371 needed definitions in sys/statvfs.h */
11372 #define _SVID3
11373 #endif
11374 #include <sys/statvfs.h>
11375
11376 static PyObject*
_pystatvfs_fromstructstatvfs(PyObject * module,struct statvfs st)11377 _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
11378 PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
11379 PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
11380 if (v == NULL)
11381 return NULL;
11382
11383 #if !defined(HAVE_LARGEFILE_SUPPORT)
11384 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11385 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11386 PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
11387 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
11388 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
11389 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
11390 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
11391 PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
11392 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11393 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11394 #else
11395 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11396 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11397 PyStructSequence_SET_ITEM(v, 2,
11398 PyLong_FromLongLong((long long) st.f_blocks));
11399 PyStructSequence_SET_ITEM(v, 3,
11400 PyLong_FromLongLong((long long) st.f_bfree));
11401 PyStructSequence_SET_ITEM(v, 4,
11402 PyLong_FromLongLong((long long) st.f_bavail));
11403 PyStructSequence_SET_ITEM(v, 5,
11404 PyLong_FromLongLong((long long) st.f_files));
11405 PyStructSequence_SET_ITEM(v, 6,
11406 PyLong_FromLongLong((long long) st.f_ffree));
11407 PyStructSequence_SET_ITEM(v, 7,
11408 PyLong_FromLongLong((long long) st.f_favail));
11409 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11410 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11411 #endif
11412 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
11413 * (issue #32390). */
11414 #if defined(_AIX) && defined(_ALL_SOURCE)
11415 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
11416 #else
11417 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
11418 #endif
11419 if (PyErr_Occurred()) {
11420 Py_DECREF(v);
11421 return NULL;
11422 }
11423
11424 return v;
11425 }
11426
11427
11428 /*[clinic input]
11429 os.fstatvfs
11430 fd: int
11431 /
11432
11433 Perform an fstatvfs system call on the given fd.
11434
11435 Equivalent to statvfs(fd).
11436 [clinic start generated code]*/
11437
11438 static PyObject *
os_fstatvfs_impl(PyObject * module,int fd)11439 os_fstatvfs_impl(PyObject *module, int fd)
11440 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
11441 {
11442 int result;
11443 int async_err = 0;
11444 struct statvfs st;
11445
11446 do {
11447 Py_BEGIN_ALLOW_THREADS
11448 result = fstatvfs(fd, &st);
11449 Py_END_ALLOW_THREADS
11450 } while (result != 0 && errno == EINTR &&
11451 !(async_err = PyErr_CheckSignals()));
11452 if (result != 0)
11453 return (!async_err) ? posix_error() : NULL;
11454
11455 return _pystatvfs_fromstructstatvfs(module, st);
11456 }
11457 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
11458
11459
11460 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
11461 #include <sys/statvfs.h>
11462 /*[clinic input]
11463 os.statvfs
11464
11465 path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
11466
11467 Perform a statvfs system call on the given path.
11468
11469 path may always be specified as a string.
11470 On some platforms, path may also be specified as an open file descriptor.
11471 If this functionality is unavailable, using it raises an exception.
11472 [clinic start generated code]*/
11473
11474 static PyObject *
os_statvfs_impl(PyObject * module,path_t * path)11475 os_statvfs_impl(PyObject *module, path_t *path)
11476 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
11477 {
11478 int result;
11479 struct statvfs st;
11480
11481 Py_BEGIN_ALLOW_THREADS
11482 #ifdef HAVE_FSTATVFS
11483 if (path->fd != -1) {
11484 result = fstatvfs(path->fd, &st);
11485 }
11486 else
11487 #endif
11488 result = statvfs(path->narrow, &st);
11489 Py_END_ALLOW_THREADS
11490
11491 if (result) {
11492 return path_error(path);
11493 }
11494
11495 return _pystatvfs_fromstructstatvfs(module, st);
11496 }
11497 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
11498
11499
11500 #ifdef MS_WINDOWS
11501 /*[clinic input]
11502 os._getdiskusage
11503
11504 path: path_t
11505
11506 Return disk usage statistics about the given path as a (total, free) tuple.
11507 [clinic start generated code]*/
11508
11509 static PyObject *
os__getdiskusage_impl(PyObject * module,path_t * path)11510 os__getdiskusage_impl(PyObject *module, path_t *path)
11511 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
11512 {
11513 BOOL retval;
11514 ULARGE_INTEGER _, total, free;
11515 DWORD err = 0;
11516
11517 Py_BEGIN_ALLOW_THREADS
11518 retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
11519 Py_END_ALLOW_THREADS
11520 if (retval == 0) {
11521 if (GetLastError() == ERROR_DIRECTORY) {
11522 wchar_t *dir_path = NULL;
11523
11524 dir_path = PyMem_New(wchar_t, path->length + 1);
11525 if (dir_path == NULL) {
11526 return PyErr_NoMemory();
11527 }
11528
11529 wcscpy_s(dir_path, path->length + 1, path->wide);
11530
11531 if (_dirnameW(dir_path) != -1) {
11532 Py_BEGIN_ALLOW_THREADS
11533 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
11534 Py_END_ALLOW_THREADS
11535 }
11536 /* Record the last error in case it's modified by PyMem_Free. */
11537 err = GetLastError();
11538 PyMem_Free(dir_path);
11539 if (retval) {
11540 goto success;
11541 }
11542 }
11543 return PyErr_SetFromWindowsErr(err);
11544 }
11545
11546 success:
11547 return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
11548 }
11549 #endif /* MS_WINDOWS */
11550
11551
11552 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
11553 * It maps strings representing configuration variable names to
11554 * integer values, allowing those functions to be called with the
11555 * magic names instead of polluting the module's namespace with tons of
11556 * rarely-used constants. There are three separate tables that use
11557 * these definitions.
11558 *
11559 * This code is always included, even if none of the interfaces that
11560 * need it are included. The #if hackery needed to avoid it would be
11561 * sufficiently pervasive that it's not worth the loss of readability.
11562 */
11563 struct constdef {
11564 const char *name;
11565 int value;
11566 };
11567
11568 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)11569 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
11570 size_t tablesize)
11571 {
11572 if (PyLong_Check(arg)) {
11573 int value = _PyLong_AsInt(arg);
11574 if (value == -1 && PyErr_Occurred())
11575 return 0;
11576 *valuep = value;
11577 return 1;
11578 }
11579 else {
11580 /* look up the value in the table using a binary search */
11581 size_t lo = 0;
11582 size_t mid;
11583 size_t hi = tablesize;
11584 int cmp;
11585 const char *confname;
11586 if (!PyUnicode_Check(arg)) {
11587 PyErr_SetString(PyExc_TypeError,
11588 "configuration names must be strings or integers");
11589 return 0;
11590 }
11591 confname = PyUnicode_AsUTF8(arg);
11592 if (confname == NULL)
11593 return 0;
11594 while (lo < hi) {
11595 mid = (lo + hi) / 2;
11596 cmp = strcmp(confname, table[mid].name);
11597 if (cmp < 0)
11598 hi = mid;
11599 else if (cmp > 0)
11600 lo = mid + 1;
11601 else {
11602 *valuep = table[mid].value;
11603 return 1;
11604 }
11605 }
11606 PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
11607 return 0;
11608 }
11609 }
11610
11611
11612 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11613 static struct constdef posix_constants_pathconf[] = {
11614 #ifdef _PC_ABI_AIO_XFER_MAX
11615 {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
11616 #endif
11617 #ifdef _PC_ABI_ASYNC_IO
11618 {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
11619 #endif
11620 #ifdef _PC_ASYNC_IO
11621 {"PC_ASYNC_IO", _PC_ASYNC_IO},
11622 #endif
11623 #ifdef _PC_CHOWN_RESTRICTED
11624 {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
11625 #endif
11626 #ifdef _PC_FILESIZEBITS
11627 {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
11628 #endif
11629 #ifdef _PC_LAST
11630 {"PC_LAST", _PC_LAST},
11631 #endif
11632 #ifdef _PC_LINK_MAX
11633 {"PC_LINK_MAX", _PC_LINK_MAX},
11634 #endif
11635 #ifdef _PC_MAX_CANON
11636 {"PC_MAX_CANON", _PC_MAX_CANON},
11637 #endif
11638 #ifdef _PC_MAX_INPUT
11639 {"PC_MAX_INPUT", _PC_MAX_INPUT},
11640 #endif
11641 #ifdef _PC_NAME_MAX
11642 {"PC_NAME_MAX", _PC_NAME_MAX},
11643 #endif
11644 #ifdef _PC_NO_TRUNC
11645 {"PC_NO_TRUNC", _PC_NO_TRUNC},
11646 #endif
11647 #ifdef _PC_PATH_MAX
11648 {"PC_PATH_MAX", _PC_PATH_MAX},
11649 #endif
11650 #ifdef _PC_PIPE_BUF
11651 {"PC_PIPE_BUF", _PC_PIPE_BUF},
11652 #endif
11653 #ifdef _PC_PRIO_IO
11654 {"PC_PRIO_IO", _PC_PRIO_IO},
11655 #endif
11656 #ifdef _PC_SOCK_MAXBUF
11657 {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
11658 #endif
11659 #ifdef _PC_SYNC_IO
11660 {"PC_SYNC_IO", _PC_SYNC_IO},
11661 #endif
11662 #ifdef _PC_VDISABLE
11663 {"PC_VDISABLE", _PC_VDISABLE},
11664 #endif
11665 #ifdef _PC_ACL_ENABLED
11666 {"PC_ACL_ENABLED", _PC_ACL_ENABLED},
11667 #endif
11668 #ifdef _PC_MIN_HOLE_SIZE
11669 {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE},
11670 #endif
11671 #ifdef _PC_ALLOC_SIZE_MIN
11672 {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN},
11673 #endif
11674 #ifdef _PC_REC_INCR_XFER_SIZE
11675 {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE},
11676 #endif
11677 #ifdef _PC_REC_MAX_XFER_SIZE
11678 {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE},
11679 #endif
11680 #ifdef _PC_REC_MIN_XFER_SIZE
11681 {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE},
11682 #endif
11683 #ifdef _PC_REC_XFER_ALIGN
11684 {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN},
11685 #endif
11686 #ifdef _PC_SYMLINK_MAX
11687 {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX},
11688 #endif
11689 #ifdef _PC_XATTR_ENABLED
11690 {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED},
11691 #endif
11692 #ifdef _PC_XATTR_EXISTS
11693 {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
11694 #endif
11695 #ifdef _PC_TIMESTAMP_RESOLUTION
11696 {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
11697 #endif
11698 };
11699
11700 static int
conv_path_confname(PyObject * arg,int * valuep)11701 conv_path_confname(PyObject *arg, int *valuep)
11702 {
11703 return conv_confname(arg, valuep, posix_constants_pathconf,
11704 sizeof(posix_constants_pathconf)
11705 / sizeof(struct constdef));
11706 }
11707 #endif
11708
11709
11710 #ifdef HAVE_FPATHCONF
11711 /*[clinic input]
11712 os.fpathconf -> long
11713
11714 fd: fildes
11715 name: path_confname
11716 /
11717
11718 Return the configuration limit name for the file descriptor fd.
11719
11720 If there is no limit, return -1.
11721 [clinic start generated code]*/
11722
11723 static long
os_fpathconf_impl(PyObject * module,int fd,int name)11724 os_fpathconf_impl(PyObject *module, int fd, int name)
11725 /*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
11726 {
11727 long limit;
11728
11729 errno = 0;
11730 limit = fpathconf(fd, name);
11731 if (limit == -1 && errno != 0)
11732 posix_error();
11733
11734 return limit;
11735 }
11736 #endif /* HAVE_FPATHCONF */
11737
11738
11739 #ifdef HAVE_PATHCONF
11740 /*[clinic input]
11741 os.pathconf -> long
11742 path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
11743 name: path_confname
11744
11745 Return the configuration limit name for the file or directory path.
11746
11747 If there is no limit, return -1.
11748 On some platforms, path may also be specified as an open file descriptor.
11749 If this functionality is unavailable, using it raises an exception.
11750 [clinic start generated code]*/
11751
11752 static long
os_pathconf_impl(PyObject * module,path_t * path,int name)11753 os_pathconf_impl(PyObject *module, path_t *path, int name)
11754 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
11755 {
11756 long limit;
11757
11758 errno = 0;
11759 #ifdef HAVE_FPATHCONF
11760 if (path->fd != -1)
11761 limit = fpathconf(path->fd, name);
11762 else
11763 #endif
11764 limit = pathconf(path->narrow, name);
11765 if (limit == -1 && errno != 0) {
11766 if (errno == EINVAL)
11767 /* could be a path or name problem */
11768 posix_error();
11769 else
11770 path_error(path);
11771 }
11772
11773 return limit;
11774 }
11775 #endif /* HAVE_PATHCONF */
11776
11777 #ifdef HAVE_CONFSTR
11778 static struct constdef posix_constants_confstr[] = {
11779 #ifdef _CS_ARCHITECTURE
11780 {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
11781 #endif
11782 #ifdef _CS_GNU_LIBC_VERSION
11783 {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION},
11784 #endif
11785 #ifdef _CS_GNU_LIBPTHREAD_VERSION
11786 {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION},
11787 #endif
11788 #ifdef _CS_HOSTNAME
11789 {"CS_HOSTNAME", _CS_HOSTNAME},
11790 #endif
11791 #ifdef _CS_HW_PROVIDER
11792 {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
11793 #endif
11794 #ifdef _CS_HW_SERIAL
11795 {"CS_HW_SERIAL", _CS_HW_SERIAL},
11796 #endif
11797 #ifdef _CS_INITTAB_NAME
11798 {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11799 #endif
11800 #ifdef _CS_LFS64_CFLAGS
11801 {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11802 #endif
11803 #ifdef _CS_LFS64_LDFLAGS
11804 {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
11805 #endif
11806 #ifdef _CS_LFS64_LIBS
11807 {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
11808 #endif
11809 #ifdef _CS_LFS64_LINTFLAGS
11810 {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
11811 #endif
11812 #ifdef _CS_LFS_CFLAGS
11813 {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
11814 #endif
11815 #ifdef _CS_LFS_LDFLAGS
11816 {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
11817 #endif
11818 #ifdef _CS_LFS_LIBS
11819 {"CS_LFS_LIBS", _CS_LFS_LIBS},
11820 #endif
11821 #ifdef _CS_LFS_LINTFLAGS
11822 {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
11823 #endif
11824 #ifdef _CS_MACHINE
11825 {"CS_MACHINE", _CS_MACHINE},
11826 #endif
11827 #ifdef _CS_PATH
11828 {"CS_PATH", _CS_PATH},
11829 #endif
11830 #ifdef _CS_RELEASE
11831 {"CS_RELEASE", _CS_RELEASE},
11832 #endif
11833 #ifdef _CS_SRPC_DOMAIN
11834 {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
11835 #endif
11836 #ifdef _CS_SYSNAME
11837 {"CS_SYSNAME", _CS_SYSNAME},
11838 #endif
11839 #ifdef _CS_VERSION
11840 {"CS_VERSION", _CS_VERSION},
11841 #endif
11842 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11843 {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
11844 #endif
11845 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11846 {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
11847 #endif
11848 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11849 {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
11850 #endif
11851 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11852 {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11853 #endif
11854 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11855 {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11856 #endif
11857 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11858 {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11859 #endif
11860 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11861 {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
11862 #endif
11863 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11864 {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11865 #endif
11866 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11867 {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
11868 #endif
11869 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11870 {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
11871 #endif
11872 #ifdef _CS_XBS5_LP64_OFF64_LIBS
11873 {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11874 #endif
11875 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11876 {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
11877 #endif
11878 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11879 {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11880 #endif
11881 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11882 {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11883 #endif
11884 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11885 {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
11886 #endif
11887 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11888 {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11889 #endif
11890 #ifdef _MIPS_CS_AVAIL_PROCESSORS
11891 {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
11892 #endif
11893 #ifdef _MIPS_CS_BASE
11894 {"MIPS_CS_BASE", _MIPS_CS_BASE},
11895 #endif
11896 #ifdef _MIPS_CS_HOSTID
11897 {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
11898 #endif
11899 #ifdef _MIPS_CS_HW_NAME
11900 {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11901 #endif
11902 #ifdef _MIPS_CS_NUM_PROCESSORS
11903 {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
11904 #endif
11905 #ifdef _MIPS_CS_OSREL_MAJ
11906 {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
11907 #endif
11908 #ifdef _MIPS_CS_OSREL_MIN
11909 {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
11910 #endif
11911 #ifdef _MIPS_CS_OSREL_PATCH
11912 {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
11913 #endif
11914 #ifdef _MIPS_CS_OS_NAME
11915 {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11916 #endif
11917 #ifdef _MIPS_CS_OS_PROVIDER
11918 {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
11919 #endif
11920 #ifdef _MIPS_CS_PROCESSORS
11921 {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
11922 #endif
11923 #ifdef _MIPS_CS_SERIAL
11924 {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
11925 #endif
11926 #ifdef _MIPS_CS_VENDOR
11927 {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
11928 #endif
11929 };
11930
11931 static int
conv_confstr_confname(PyObject * arg,int * valuep)11932 conv_confstr_confname(PyObject *arg, int *valuep)
11933 {
11934 return conv_confname(arg, valuep, posix_constants_confstr,
11935 sizeof(posix_constants_confstr)
11936 / sizeof(struct constdef));
11937 }
11938
11939
11940 /*[clinic input]
11941 os.confstr
11942
11943 name: confstr_confname
11944 /
11945
11946 Return a string-valued system configuration variable.
11947 [clinic start generated code]*/
11948
11949 static PyObject *
os_confstr_impl(PyObject * module,int name)11950 os_confstr_impl(PyObject *module, int name)
11951 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11952 {
11953 PyObject *result = NULL;
11954 char buffer[255];
11955 size_t len;
11956
11957 errno = 0;
11958 len = confstr(name, buffer, sizeof(buffer));
11959 if (len == 0) {
11960 if (errno) {
11961 posix_error();
11962 return NULL;
11963 }
11964 else {
11965 Py_RETURN_NONE;
11966 }
11967 }
11968
11969 if (len >= sizeof(buffer)) {
11970 size_t len2;
11971 char *buf = PyMem_Malloc(len);
11972 if (buf == NULL)
11973 return PyErr_NoMemory();
11974 len2 = confstr(name, buf, len);
11975 assert(len == len2);
11976 result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11977 PyMem_Free(buf);
11978 }
11979 else
11980 result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11981 return result;
11982 }
11983 #endif /* HAVE_CONFSTR */
11984
11985
11986 #ifdef HAVE_SYSCONF
11987 static struct constdef posix_constants_sysconf[] = {
11988 #ifdef _SC_2_CHAR_TERM
11989 {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
11990 #endif
11991 #ifdef _SC_2_C_BIND
11992 {"SC_2_C_BIND", _SC_2_C_BIND},
11993 #endif
11994 #ifdef _SC_2_C_DEV
11995 {"SC_2_C_DEV", _SC_2_C_DEV},
11996 #endif
11997 #ifdef _SC_2_C_VERSION
11998 {"SC_2_C_VERSION", _SC_2_C_VERSION},
11999 #endif
12000 #ifdef _SC_2_FORT_DEV
12001 {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
12002 #endif
12003 #ifdef _SC_2_FORT_RUN
12004 {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
12005 #endif
12006 #ifdef _SC_2_LOCALEDEF
12007 {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
12008 #endif
12009 #ifdef _SC_2_SW_DEV
12010 {"SC_2_SW_DEV", _SC_2_SW_DEV},
12011 #endif
12012 #ifdef _SC_2_UPE
12013 {"SC_2_UPE", _SC_2_UPE},
12014 #endif
12015 #ifdef _SC_2_VERSION
12016 {"SC_2_VERSION", _SC_2_VERSION},
12017 #endif
12018 #ifdef _SC_ABI_ASYNCHRONOUS_IO
12019 {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
12020 #endif
12021 #ifdef _SC_ACL
12022 {"SC_ACL", _SC_ACL},
12023 #endif
12024 #ifdef _SC_AIO_LISTIO_MAX
12025 {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
12026 #endif
12027 #ifdef _SC_AIO_MAX
12028 {"SC_AIO_MAX", _SC_AIO_MAX},
12029 #endif
12030 #ifdef _SC_AIO_PRIO_DELTA_MAX
12031 {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
12032 #endif
12033 #ifdef _SC_ARG_MAX
12034 {"SC_ARG_MAX", _SC_ARG_MAX},
12035 #endif
12036 #ifdef _SC_ASYNCHRONOUS_IO
12037 {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
12038 #endif
12039 #ifdef _SC_ATEXIT_MAX
12040 {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
12041 #endif
12042 #ifdef _SC_AUDIT
12043 {"SC_AUDIT", _SC_AUDIT},
12044 #endif
12045 #ifdef _SC_AVPHYS_PAGES
12046 {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
12047 #endif
12048 #ifdef _SC_BC_BASE_MAX
12049 {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
12050 #endif
12051 #ifdef _SC_BC_DIM_MAX
12052 {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
12053 #endif
12054 #ifdef _SC_BC_SCALE_MAX
12055 {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
12056 #endif
12057 #ifdef _SC_BC_STRING_MAX
12058 {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
12059 #endif
12060 #ifdef _SC_CAP
12061 {"SC_CAP", _SC_CAP},
12062 #endif
12063 #ifdef _SC_CHARCLASS_NAME_MAX
12064 {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
12065 #endif
12066 #ifdef _SC_CHAR_BIT
12067 {"SC_CHAR_BIT", _SC_CHAR_BIT},
12068 #endif
12069 #ifdef _SC_CHAR_MAX
12070 {"SC_CHAR_MAX", _SC_CHAR_MAX},
12071 #endif
12072 #ifdef _SC_CHAR_MIN
12073 {"SC_CHAR_MIN", _SC_CHAR_MIN},
12074 #endif
12075 #ifdef _SC_CHILD_MAX
12076 {"SC_CHILD_MAX", _SC_CHILD_MAX},
12077 #endif
12078 #ifdef _SC_CLK_TCK
12079 {"SC_CLK_TCK", _SC_CLK_TCK},
12080 #endif
12081 #ifdef _SC_COHER_BLKSZ
12082 {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
12083 #endif
12084 #ifdef _SC_COLL_WEIGHTS_MAX
12085 {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
12086 #endif
12087 #ifdef _SC_DCACHE_ASSOC
12088 {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
12089 #endif
12090 #ifdef _SC_DCACHE_BLKSZ
12091 {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
12092 #endif
12093 #ifdef _SC_DCACHE_LINESZ
12094 {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
12095 #endif
12096 #ifdef _SC_DCACHE_SZ
12097 {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
12098 #endif
12099 #ifdef _SC_DCACHE_TBLKSZ
12100 {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
12101 #endif
12102 #ifdef _SC_DELAYTIMER_MAX
12103 {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
12104 #endif
12105 #ifdef _SC_EQUIV_CLASS_MAX
12106 {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
12107 #endif
12108 #ifdef _SC_EXPR_NEST_MAX
12109 {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
12110 #endif
12111 #ifdef _SC_FSYNC
12112 {"SC_FSYNC", _SC_FSYNC},
12113 #endif
12114 #ifdef _SC_GETGR_R_SIZE_MAX
12115 {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
12116 #endif
12117 #ifdef _SC_GETPW_R_SIZE_MAX
12118 {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
12119 #endif
12120 #ifdef _SC_ICACHE_ASSOC
12121 {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
12122 #endif
12123 #ifdef _SC_ICACHE_BLKSZ
12124 {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
12125 #endif
12126 #ifdef _SC_ICACHE_LINESZ
12127 {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
12128 #endif
12129 #ifdef _SC_ICACHE_SZ
12130 {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
12131 #endif
12132 #ifdef _SC_INF
12133 {"SC_INF", _SC_INF},
12134 #endif
12135 #ifdef _SC_INT_MAX
12136 {"SC_INT_MAX", _SC_INT_MAX},
12137 #endif
12138 #ifdef _SC_INT_MIN
12139 {"SC_INT_MIN", _SC_INT_MIN},
12140 #endif
12141 #ifdef _SC_IOV_MAX
12142 {"SC_IOV_MAX", _SC_IOV_MAX},
12143 #endif
12144 #ifdef _SC_IP_SECOPTS
12145 {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
12146 #endif
12147 #ifdef _SC_JOB_CONTROL
12148 {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
12149 #endif
12150 #ifdef _SC_KERN_POINTERS
12151 {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
12152 #endif
12153 #ifdef _SC_KERN_SIM
12154 {"SC_KERN_SIM", _SC_KERN_SIM},
12155 #endif
12156 #ifdef _SC_LINE_MAX
12157 {"SC_LINE_MAX", _SC_LINE_MAX},
12158 #endif
12159 #ifdef _SC_LOGIN_NAME_MAX
12160 {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
12161 #endif
12162 #ifdef _SC_LOGNAME_MAX
12163 {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
12164 #endif
12165 #ifdef _SC_LONG_BIT
12166 {"SC_LONG_BIT", _SC_LONG_BIT},
12167 #endif
12168 #ifdef _SC_MAC
12169 {"SC_MAC", _SC_MAC},
12170 #endif
12171 #ifdef _SC_MAPPED_FILES
12172 {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
12173 #endif
12174 #ifdef _SC_MAXPID
12175 {"SC_MAXPID", _SC_MAXPID},
12176 #endif
12177 #ifdef _SC_MB_LEN_MAX
12178 {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
12179 #endif
12180 #ifdef _SC_MEMLOCK
12181 {"SC_MEMLOCK", _SC_MEMLOCK},
12182 #endif
12183 #ifdef _SC_MEMLOCK_RANGE
12184 {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
12185 #endif
12186 #ifdef _SC_MEMORY_PROTECTION
12187 {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
12188 #endif
12189 #ifdef _SC_MESSAGE_PASSING
12190 {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
12191 #endif
12192 #ifdef _SC_MMAP_FIXED_ALIGNMENT
12193 {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
12194 #endif
12195 #ifdef _SC_MQ_OPEN_MAX
12196 {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
12197 #endif
12198 #ifdef _SC_MQ_PRIO_MAX
12199 {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},
12200 #endif
12201 #ifdef _SC_NACLS_MAX
12202 {"SC_NACLS_MAX", _SC_NACLS_MAX},
12203 #endif
12204 #ifdef _SC_NGROUPS_MAX
12205 {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX},
12206 #endif
12207 #ifdef _SC_NL_ARGMAX
12208 {"SC_NL_ARGMAX", _SC_NL_ARGMAX},
12209 #endif
12210 #ifdef _SC_NL_LANGMAX
12211 {"SC_NL_LANGMAX", _SC_NL_LANGMAX},
12212 #endif
12213 #ifdef _SC_NL_MSGMAX
12214 {"SC_NL_MSGMAX", _SC_NL_MSGMAX},
12215 #endif
12216 #ifdef _SC_NL_NMAX
12217 {"SC_NL_NMAX", _SC_NL_NMAX},
12218 #endif
12219 #ifdef _SC_NL_SETMAX
12220 {"SC_NL_SETMAX", _SC_NL_SETMAX},
12221 #endif
12222 #ifdef _SC_NL_TEXTMAX
12223 {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX},
12224 #endif
12225 #ifdef _SC_NPROCESSORS_CONF
12226 {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
12227 #endif
12228 #ifdef _SC_NPROCESSORS_ONLN
12229 {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
12230 #endif
12231 #ifdef _SC_NPROC_CONF
12232 {"SC_NPROC_CONF", _SC_NPROC_CONF},
12233 #endif
12234 #ifdef _SC_NPROC_ONLN
12235 {"SC_NPROC_ONLN", _SC_NPROC_ONLN},
12236 #endif
12237 #ifdef _SC_NZERO
12238 {"SC_NZERO", _SC_NZERO},
12239 #endif
12240 #ifdef _SC_OPEN_MAX
12241 {"SC_OPEN_MAX", _SC_OPEN_MAX},
12242 #endif
12243 #ifdef _SC_PAGESIZE
12244 {"SC_PAGESIZE", _SC_PAGESIZE},
12245 #endif
12246 #ifdef _SC_PAGE_SIZE
12247 {"SC_PAGE_SIZE", _SC_PAGE_SIZE},
12248 #endif
12249 #ifdef _SC_AIX_REALMEM
12250 {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
12251 #endif
12252 #ifdef _SC_PASS_MAX
12253 {"SC_PASS_MAX", _SC_PASS_MAX},
12254 #endif
12255 #ifdef _SC_PHYS_PAGES
12256 {"SC_PHYS_PAGES", _SC_PHYS_PAGES},
12257 #endif
12258 #ifdef _SC_PII
12259 {"SC_PII", _SC_PII},
12260 #endif
12261 #ifdef _SC_PII_INTERNET
12262 {"SC_PII_INTERNET", _SC_PII_INTERNET},
12263 #endif
12264 #ifdef _SC_PII_INTERNET_DGRAM
12265 {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM},
12266 #endif
12267 #ifdef _SC_PII_INTERNET_STREAM
12268 {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM},
12269 #endif
12270 #ifdef _SC_PII_OSI
12271 {"SC_PII_OSI", _SC_PII_OSI},
12272 #endif
12273 #ifdef _SC_PII_OSI_CLTS
12274 {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
12275 #endif
12276 #ifdef _SC_PII_OSI_COTS
12277 {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
12278 #endif
12279 #ifdef _SC_PII_OSI_M
12280 {"SC_PII_OSI_M", _SC_PII_OSI_M},
12281 #endif
12282 #ifdef _SC_PII_SOCKET
12283 {"SC_PII_SOCKET", _SC_PII_SOCKET},
12284 #endif
12285 #ifdef _SC_PII_XTI
12286 {"SC_PII_XTI", _SC_PII_XTI},
12287 #endif
12288 #ifdef _SC_POLL
12289 {"SC_POLL", _SC_POLL},
12290 #endif
12291 #ifdef _SC_PRIORITIZED_IO
12292 {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO},
12293 #endif
12294 #ifdef _SC_PRIORITY_SCHEDULING
12295 {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING},
12296 #endif
12297 #ifdef _SC_REALTIME_SIGNALS
12298 {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS},
12299 #endif
12300 #ifdef _SC_RE_DUP_MAX
12301 {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX},
12302 #endif
12303 #ifdef _SC_RTSIG_MAX
12304 {"SC_RTSIG_MAX", _SC_RTSIG_MAX},
12305 #endif
12306 #ifdef _SC_SAVED_IDS
12307 {"SC_SAVED_IDS", _SC_SAVED_IDS},
12308 #endif
12309 #ifdef _SC_SCHAR_MAX
12310 {"SC_SCHAR_MAX", _SC_SCHAR_MAX},
12311 #endif
12312 #ifdef _SC_SCHAR_MIN
12313 {"SC_SCHAR_MIN", _SC_SCHAR_MIN},
12314 #endif
12315 #ifdef _SC_SELECT
12316 {"SC_SELECT", _SC_SELECT},
12317 #endif
12318 #ifdef _SC_SEMAPHORES
12319 {"SC_SEMAPHORES", _SC_SEMAPHORES},
12320 #endif
12321 #ifdef _SC_SEM_NSEMS_MAX
12322 {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX},
12323 #endif
12324 #ifdef _SC_SEM_VALUE_MAX
12325 {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX},
12326 #endif
12327 #ifdef _SC_SHARED_MEMORY_OBJECTS
12328 {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS},
12329 #endif
12330 #ifdef _SC_SHRT_MAX
12331 {"SC_SHRT_MAX", _SC_SHRT_MAX},
12332 #endif
12333 #ifdef _SC_SHRT_MIN
12334 {"SC_SHRT_MIN", _SC_SHRT_MIN},
12335 #endif
12336 #ifdef _SC_SIGQUEUE_MAX
12337 {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
12338 #endif
12339 #ifdef _SC_SIGRT_MAX
12340 {"SC_SIGRT_MAX", _SC_SIGRT_MAX},
12341 #endif
12342 #ifdef _SC_SIGRT_MIN
12343 {"SC_SIGRT_MIN", _SC_SIGRT_MIN},
12344 #endif
12345 #ifdef _SC_SOFTPOWER
12346 {"SC_SOFTPOWER", _SC_SOFTPOWER},
12347 #endif
12348 #ifdef _SC_SPLIT_CACHE
12349 {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE},
12350 #endif
12351 #ifdef _SC_SSIZE_MAX
12352 {"SC_SSIZE_MAX", _SC_SSIZE_MAX},
12353 #endif
12354 #ifdef _SC_STACK_PROT
12355 {"SC_STACK_PROT", _SC_STACK_PROT},
12356 #endif
12357 #ifdef _SC_STREAM_MAX
12358 {"SC_STREAM_MAX", _SC_STREAM_MAX},
12359 #endif
12360 #ifdef _SC_SYNCHRONIZED_IO
12361 {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO},
12362 #endif
12363 #ifdef _SC_THREADS
12364 {"SC_THREADS", _SC_THREADS},
12365 #endif
12366 #ifdef _SC_THREAD_ATTR_STACKADDR
12367 {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR},
12368 #endif
12369 #ifdef _SC_THREAD_ATTR_STACKSIZE
12370 {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE},
12371 #endif
12372 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
12373 {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
12374 #endif
12375 #ifdef _SC_THREAD_KEYS_MAX
12376 {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
12377 #endif
12378 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
12379 {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING},
12380 #endif
12381 #ifdef _SC_THREAD_PRIO_INHERIT
12382 {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT},
12383 #endif
12384 #ifdef _SC_THREAD_PRIO_PROTECT
12385 {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT},
12386 #endif
12387 #ifdef _SC_THREAD_PROCESS_SHARED
12388 {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED},
12389 #endif
12390 #ifdef _SC_THREAD_SAFE_FUNCTIONS
12391 {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS},
12392 #endif
12393 #ifdef _SC_THREAD_STACK_MIN
12394 {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
12395 #endif
12396 #ifdef _SC_THREAD_THREADS_MAX
12397 {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
12398 #endif
12399 #ifdef _SC_TIMERS
12400 {"SC_TIMERS", _SC_TIMERS},
12401 #endif
12402 #ifdef _SC_TIMER_MAX
12403 {"SC_TIMER_MAX", _SC_TIMER_MAX},
12404 #endif
12405 #ifdef _SC_TTY_NAME_MAX
12406 {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
12407 #endif
12408 #ifdef _SC_TZNAME_MAX
12409 {"SC_TZNAME_MAX", _SC_TZNAME_MAX},
12410 #endif
12411 #ifdef _SC_T_IOV_MAX
12412 {"SC_T_IOV_MAX", _SC_T_IOV_MAX},
12413 #endif
12414 #ifdef _SC_UCHAR_MAX
12415 {"SC_UCHAR_MAX", _SC_UCHAR_MAX},
12416 #endif
12417 #ifdef _SC_UINT_MAX
12418 {"SC_UINT_MAX", _SC_UINT_MAX},
12419 #endif
12420 #ifdef _SC_UIO_MAXIOV
12421 {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV},
12422 #endif
12423 #ifdef _SC_ULONG_MAX
12424 {"SC_ULONG_MAX", _SC_ULONG_MAX},
12425 #endif
12426 #ifdef _SC_USHRT_MAX
12427 {"SC_USHRT_MAX", _SC_USHRT_MAX},
12428 #endif
12429 #ifdef _SC_VERSION
12430 {"SC_VERSION", _SC_VERSION},
12431 #endif
12432 #ifdef _SC_WORD_BIT
12433 {"SC_WORD_BIT", _SC_WORD_BIT},
12434 #endif
12435 #ifdef _SC_XBS5_ILP32_OFF32
12436 {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32},
12437 #endif
12438 #ifdef _SC_XBS5_ILP32_OFFBIG
12439 {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG},
12440 #endif
12441 #ifdef _SC_XBS5_LP64_OFF64
12442 {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64},
12443 #endif
12444 #ifdef _SC_XBS5_LPBIG_OFFBIG
12445 {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG},
12446 #endif
12447 #ifdef _SC_XOPEN_CRYPT
12448 {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT},
12449 #endif
12450 #ifdef _SC_XOPEN_ENH_I18N
12451 {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N},
12452 #endif
12453 #ifdef _SC_XOPEN_LEGACY
12454 {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
12455 #endif
12456 #ifdef _SC_XOPEN_REALTIME
12457 {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME},
12458 #endif
12459 #ifdef _SC_XOPEN_REALTIME_THREADS
12460 {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS},
12461 #endif
12462 #ifdef _SC_XOPEN_SHM
12463 {"SC_XOPEN_SHM", _SC_XOPEN_SHM},
12464 #endif
12465 #ifdef _SC_XOPEN_UNIX
12466 {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX},
12467 #endif
12468 #ifdef _SC_XOPEN_VERSION
12469 {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION},
12470 #endif
12471 #ifdef _SC_XOPEN_XCU_VERSION
12472 {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION},
12473 #endif
12474 #ifdef _SC_XOPEN_XPG2
12475 {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2},
12476 #endif
12477 #ifdef _SC_XOPEN_XPG3
12478 {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3},
12479 #endif
12480 #ifdef _SC_XOPEN_XPG4
12481 {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4},
12482 #endif
12483 #ifdef _SC_MINSIGSTKSZ
12484 {"SC_MINSIGSTKSZ", _SC_MINSIGSTKSZ},
12485 #endif
12486 };
12487
12488 static int
conv_sysconf_confname(PyObject * arg,int * valuep)12489 conv_sysconf_confname(PyObject *arg, int *valuep)
12490 {
12491 return conv_confname(arg, valuep, posix_constants_sysconf,
12492 sizeof(posix_constants_sysconf)
12493 / sizeof(struct constdef));
12494 }
12495
12496
12497 /*[clinic input]
12498 os.sysconf -> long
12499 name: sysconf_confname
12500 /
12501
12502 Return an integer-valued system configuration variable.
12503 [clinic start generated code]*/
12504
12505 static long
os_sysconf_impl(PyObject * module,int name)12506 os_sysconf_impl(PyObject *module, int name)
12507 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
12508 {
12509 long value;
12510
12511 errno = 0;
12512 value = sysconf(name);
12513 if (value == -1 && errno != 0)
12514 posix_error();
12515 return value;
12516 }
12517 #endif /* HAVE_SYSCONF */
12518
12519
12520 /* This code is used to ensure that the tables of configuration value names
12521 * are in sorted order as required by conv_confname(), and also to build
12522 * the exported dictionaries that are used to publish information about the
12523 * names available on the host platform.
12524 *
12525 * Sorting the table at runtime ensures that the table is properly ordered
12526 * when used, even for platforms we're not able to test on. It also makes
12527 * it easier to add additional entries to the tables.
12528 */
12529
12530 static int
cmp_constdefs(const void * v1,const void * v2)12531 cmp_constdefs(const void *v1, const void *v2)
12532 {
12533 const struct constdef *c1 =
12534 (const struct constdef *) v1;
12535 const struct constdef *c2 =
12536 (const struct constdef *) v2;
12537
12538 return strcmp(c1->name, c2->name);
12539 }
12540
12541 static int
setup_confname_table(struct constdef * table,size_t tablesize,const char * tablename,PyObject * module)12542 setup_confname_table(struct constdef *table, size_t tablesize,
12543 const char *tablename, PyObject *module)
12544 {
12545 PyObject *d = NULL;
12546 size_t i;
12547
12548 qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
12549 d = PyDict_New();
12550 if (d == NULL)
12551 return -1;
12552
12553 for (i=0; i < tablesize; ++i) {
12554 PyObject *o = PyLong_FromLong(table[i].value);
12555 if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
12556 Py_XDECREF(o);
12557 Py_DECREF(d);
12558 return -1;
12559 }
12560 Py_DECREF(o);
12561 }
12562 return PyModule_AddObject(module, tablename, d);
12563 }
12564
12565 /* Return -1 on failure, 0 on success. */
12566 static int
setup_confname_tables(PyObject * module)12567 setup_confname_tables(PyObject *module)
12568 {
12569 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12570 if (setup_confname_table(posix_constants_pathconf,
12571 sizeof(posix_constants_pathconf)
12572 / sizeof(struct constdef),
12573 "pathconf_names", module))
12574 return -1;
12575 #endif
12576 #ifdef HAVE_CONFSTR
12577 if (setup_confname_table(posix_constants_confstr,
12578 sizeof(posix_constants_confstr)
12579 / sizeof(struct constdef),
12580 "confstr_names", module))
12581 return -1;
12582 #endif
12583 #ifdef HAVE_SYSCONF
12584 if (setup_confname_table(posix_constants_sysconf,
12585 sizeof(posix_constants_sysconf)
12586 / sizeof(struct constdef),
12587 "sysconf_names", module))
12588 return -1;
12589 #endif
12590 return 0;
12591 }
12592
12593
12594 /*[clinic input]
12595 os.abort
12596
12597 Abort the interpreter immediately.
12598
12599 This function 'dumps core' or otherwise fails in the hardest way possible
12600 on the hosting operating system. This function never returns.
12601 [clinic start generated code]*/
12602
12603 static PyObject *
os_abort_impl(PyObject * module)12604 os_abort_impl(PyObject *module)
12605 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
12606 {
12607 abort();
12608 /*NOTREACHED*/
12609 #ifndef __clang__
12610 /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
12611 GCC emits a warning without "return NULL;" (compiler bug?), but Clang
12612 is smarter and emits a warning on the return. */
12613 Py_FatalError("abort() called from Python code didn't abort!");
12614 return NULL;
12615 #endif
12616 }
12617
12618 #ifdef MS_WINDOWS
12619 /* Grab ShellExecute dynamically from shell32 */
12620 static int has_ShellExecute = -1;
12621 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
12622 LPCWSTR, INT);
12623 static int
check_ShellExecute()12624 check_ShellExecute()
12625 {
12626 HINSTANCE hShell32;
12627
12628 /* only recheck */
12629 if (-1 == has_ShellExecute) {
12630 Py_BEGIN_ALLOW_THREADS
12631 /* Security note: this call is not vulnerable to "DLL hijacking".
12632 SHELL32 is part of "KnownDLLs" and so Windows always load
12633 the system SHELL32.DLL, even if there is another SHELL32.DLL
12634 in the DLL search path. */
12635 hShell32 = LoadLibraryW(L"SHELL32");
12636 if (hShell32) {
12637 *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
12638 "ShellExecuteW");
12639 has_ShellExecute = Py_ShellExecuteW != NULL;
12640 } else {
12641 has_ShellExecute = 0;
12642 }
12643 Py_END_ALLOW_THREADS
12644 }
12645 return has_ShellExecute;
12646 }
12647
12648
12649 /*[clinic input]
12650 os.startfile
12651 filepath: path_t
12652 operation: Py_UNICODE = NULL
12653 arguments: Py_UNICODE = NULL
12654 cwd: path_t(nullable=True) = None
12655 show_cmd: int = 1
12656
12657 Start a file with its associated application.
12658
12659 When "operation" is not specified or "open", this acts like
12660 double-clicking the file in Explorer, or giving the file name as an
12661 argument to the DOS "start" command: the file is opened with whatever
12662 application (if any) its extension is associated.
12663 When another "operation" is given, it specifies what should be done with
12664 the file. A typical operation is "print".
12665
12666 "arguments" is passed to the application, but should be omitted if the
12667 file is a document.
12668
12669 "cwd" is the working directory for the operation. If "filepath" is
12670 relative, it will be resolved against this directory. This argument
12671 should usually be an absolute path.
12672
12673 "show_cmd" can be used to override the recommended visibility option.
12674 See the Windows ShellExecute documentation for values.
12675
12676 startfile returns as soon as the associated application is launched.
12677 There is no option to wait for the application to close, and no way
12678 to retrieve the application's exit status.
12679
12680 The filepath is relative to the current directory. If you want to use
12681 an absolute path, make sure the first character is not a slash ("/");
12682 the underlying Win32 ShellExecute function doesn't work if it is.
12683 [clinic start generated code]*/
12684
12685 static PyObject *
os_startfile_impl(PyObject * module,path_t * filepath,const Py_UNICODE * operation,const Py_UNICODE * arguments,path_t * cwd,int show_cmd)12686 os_startfile_impl(PyObject *module, path_t *filepath,
12687 const Py_UNICODE *operation, const Py_UNICODE *arguments,
12688 path_t *cwd, int show_cmd)
12689 /*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/
12690 {
12691 HINSTANCE rc;
12692
12693 if(!check_ShellExecute()) {
12694 /* If the OS doesn't have ShellExecute, return a
12695 NotImplementedError. */
12696 return PyErr_Format(PyExc_NotImplementedError,
12697 "startfile not available on this platform");
12698 }
12699
12700 if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
12701 return NULL;
12702 }
12703 if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
12704 arguments, cwd->object ? cwd->object : Py_None,
12705 show_cmd) < 0) {
12706 return NULL;
12707 }
12708
12709 Py_BEGIN_ALLOW_THREADS
12710 rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
12711 arguments, cwd->wide, show_cmd);
12712 Py_END_ALLOW_THREADS
12713
12714 if (rc <= (HINSTANCE)32) {
12715 win32_error_object("startfile", filepath->object);
12716 return NULL;
12717 }
12718 Py_RETURN_NONE;
12719 }
12720 #endif /* MS_WINDOWS */
12721
12722
12723 #ifdef HAVE_GETLOADAVG
12724 /*[clinic input]
12725 os.getloadavg
12726
12727 Return average recent system load information.
12728
12729 Return the number of processes in the system run queue averaged over
12730 the last 1, 5, and 15 minutes as a tuple of three floats.
12731 Raises OSError if the load average was unobtainable.
12732 [clinic start generated code]*/
12733
12734 static PyObject *
os_getloadavg_impl(PyObject * module)12735 os_getloadavg_impl(PyObject *module)
12736 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
12737 {
12738 double loadavg[3];
12739 if (getloadavg(loadavg, 3)!=3) {
12740 PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
12741 return NULL;
12742 } else
12743 return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
12744 }
12745 #endif /* HAVE_GETLOADAVG */
12746
12747
12748 /*[clinic input]
12749 os.device_encoding
12750 fd: int
12751
12752 Return a string describing the encoding of a terminal's file descriptor.
12753
12754 The file descriptor must be attached to a terminal.
12755 If the device is not a terminal, return None.
12756 [clinic start generated code]*/
12757
12758 static PyObject *
os_device_encoding_impl(PyObject * module,int fd)12759 os_device_encoding_impl(PyObject *module, int fd)
12760 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
12761 {
12762 return _Py_device_encoding(fd);
12763 }
12764
12765
12766 #ifdef HAVE_SETRESUID
12767 /*[clinic input]
12768 os.setresuid
12769
12770 ruid: uid_t
12771 euid: uid_t
12772 suid: uid_t
12773 /
12774
12775 Set the current process's real, effective, and saved user ids.
12776 [clinic start generated code]*/
12777
12778 static PyObject *
os_setresuid_impl(PyObject * module,uid_t ruid,uid_t euid,uid_t suid)12779 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
12780 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
12781 {
12782 if (setresuid(ruid, euid, suid) < 0)
12783 return posix_error();
12784 Py_RETURN_NONE;
12785 }
12786 #endif /* HAVE_SETRESUID */
12787
12788
12789 #ifdef HAVE_SETRESGID
12790 /*[clinic input]
12791 os.setresgid
12792
12793 rgid: gid_t
12794 egid: gid_t
12795 sgid: gid_t
12796 /
12797
12798 Set the current process's real, effective, and saved group ids.
12799 [clinic start generated code]*/
12800
12801 static PyObject *
os_setresgid_impl(PyObject * module,gid_t rgid,gid_t egid,gid_t sgid)12802 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
12803 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
12804 {
12805 if (setresgid(rgid, egid, sgid) < 0)
12806 return posix_error();
12807 Py_RETURN_NONE;
12808 }
12809 #endif /* HAVE_SETRESGID */
12810
12811
12812 #ifdef HAVE_GETRESUID
12813 /*[clinic input]
12814 os.getresuid
12815
12816 Return a tuple of the current process's real, effective, and saved user ids.
12817 [clinic start generated code]*/
12818
12819 static PyObject *
os_getresuid_impl(PyObject * module)12820 os_getresuid_impl(PyObject *module)
12821 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12822 {
12823 uid_t ruid, euid, suid;
12824 if (getresuid(&ruid, &euid, &suid) < 0)
12825 return posix_error();
12826 return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12827 _PyLong_FromUid(euid),
12828 _PyLong_FromUid(suid));
12829 }
12830 #endif /* HAVE_GETRESUID */
12831
12832
12833 #ifdef HAVE_GETRESGID
12834 /*[clinic input]
12835 os.getresgid
12836
12837 Return a tuple of the current process's real, effective, and saved group ids.
12838 [clinic start generated code]*/
12839
12840 static PyObject *
os_getresgid_impl(PyObject * module)12841 os_getresgid_impl(PyObject *module)
12842 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12843 {
12844 gid_t rgid, egid, sgid;
12845 if (getresgid(&rgid, &egid, &sgid) < 0)
12846 return posix_error();
12847 return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12848 _PyLong_FromGid(egid),
12849 _PyLong_FromGid(sgid));
12850 }
12851 #endif /* HAVE_GETRESGID */
12852
12853
12854 #ifdef USE_XATTRS
12855 /*[clinic input]
12856 os.getxattr
12857
12858 path: path_t(allow_fd=True)
12859 attribute: path_t
12860 *
12861 follow_symlinks: bool = True
12862
12863 Return the value of extended attribute attribute on path.
12864
12865 path may be either a string, a path-like object, or an open file descriptor.
12866 If follow_symlinks is False, and the last element of the path is a symbolic
12867 link, getxattr will examine the symbolic link itself instead of the file
12868 the link points to.
12869
12870 [clinic start generated code]*/
12871
12872 static PyObject *
os_getxattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12873 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12874 int follow_symlinks)
12875 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12876 {
12877 Py_ssize_t i;
12878 PyObject *buffer = NULL;
12879
12880 if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12881 return NULL;
12882
12883 if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12884 return NULL;
12885 }
12886
12887 for (i = 0; ; i++) {
12888 void *ptr;
12889 ssize_t result;
12890 static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12891 Py_ssize_t buffer_size = buffer_sizes[i];
12892 if (!buffer_size) {
12893 path_error(path);
12894 return NULL;
12895 }
12896 buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12897 if (!buffer)
12898 return NULL;
12899 ptr = PyBytes_AS_STRING(buffer);
12900
12901 Py_BEGIN_ALLOW_THREADS;
12902 if (path->fd >= 0)
12903 result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12904 else if (follow_symlinks)
12905 result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12906 else
12907 result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12908 Py_END_ALLOW_THREADS;
12909
12910 if (result < 0) {
12911 Py_DECREF(buffer);
12912 if (errno == ERANGE)
12913 continue;
12914 path_error(path);
12915 return NULL;
12916 }
12917
12918 if (result != buffer_size) {
12919 /* Can only shrink. */
12920 _PyBytes_Resize(&buffer, result);
12921 }
12922 break;
12923 }
12924
12925 return buffer;
12926 }
12927
12928
12929 /*[clinic input]
12930 os.setxattr
12931
12932 path: path_t(allow_fd=True)
12933 attribute: path_t
12934 value: Py_buffer
12935 flags: int = 0
12936 *
12937 follow_symlinks: bool = True
12938
12939 Set extended attribute attribute on path to value.
12940
12941 path may be either a string, a path-like object, or an open file descriptor.
12942 If follow_symlinks is False, and the last element of the path is a symbolic
12943 link, setxattr will modify the symbolic link itself instead of the file
12944 the link points to.
12945
12946 [clinic start generated code]*/
12947
12948 static PyObject *
os_setxattr_impl(PyObject * module,path_t * path,path_t * attribute,Py_buffer * value,int flags,int follow_symlinks)12949 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12950 Py_buffer *value, int flags, int follow_symlinks)
12951 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12952 {
12953 ssize_t result;
12954
12955 if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12956 return NULL;
12957
12958 if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12959 value->buf, value->len, flags) < 0) {
12960 return NULL;
12961 }
12962
12963 Py_BEGIN_ALLOW_THREADS;
12964 if (path->fd > -1)
12965 result = fsetxattr(path->fd, attribute->narrow,
12966 value->buf, value->len, flags);
12967 else if (follow_symlinks)
12968 result = setxattr(path->narrow, attribute->narrow,
12969 value->buf, value->len, flags);
12970 else
12971 result = lsetxattr(path->narrow, attribute->narrow,
12972 value->buf, value->len, flags);
12973 Py_END_ALLOW_THREADS;
12974
12975 if (result) {
12976 path_error(path);
12977 return NULL;
12978 }
12979
12980 Py_RETURN_NONE;
12981 }
12982
12983
12984 /*[clinic input]
12985 os.removexattr
12986
12987 path: path_t(allow_fd=True)
12988 attribute: path_t
12989 *
12990 follow_symlinks: bool = True
12991
12992 Remove extended attribute attribute on path.
12993
12994 path may be either a string, a path-like object, or an open file descriptor.
12995 If follow_symlinks is False, and the last element of the path is a symbolic
12996 link, removexattr will modify the symbolic link itself instead of the file
12997 the link points to.
12998
12999 [clinic start generated code]*/
13000
13001 static PyObject *
os_removexattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)13002 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
13003 int follow_symlinks)
13004 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
13005 {
13006 ssize_t result;
13007
13008 if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
13009 return NULL;
13010
13011 if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
13012 return NULL;
13013 }
13014
13015 Py_BEGIN_ALLOW_THREADS;
13016 if (path->fd > -1)
13017 result = fremovexattr(path->fd, attribute->narrow);
13018 else if (follow_symlinks)
13019 result = removexattr(path->narrow, attribute->narrow);
13020 else
13021 result = lremovexattr(path->narrow, attribute->narrow);
13022 Py_END_ALLOW_THREADS;
13023
13024 if (result) {
13025 return path_error(path);
13026 }
13027
13028 Py_RETURN_NONE;
13029 }
13030
13031
13032 /*[clinic input]
13033 os.listxattr
13034
13035 path: path_t(allow_fd=True, nullable=True) = None
13036 *
13037 follow_symlinks: bool = True
13038
13039 Return a list of extended attributes on path.
13040
13041 path may be either None, a string, a path-like object, or an open file descriptor.
13042 if path is None, listxattr will examine the current directory.
13043 If follow_symlinks is False, and the last element of the path is a symbolic
13044 link, listxattr will examine the symbolic link itself instead of the file
13045 the link points to.
13046 [clinic start generated code]*/
13047
13048 static PyObject *
os_listxattr_impl(PyObject * module,path_t * path,int follow_symlinks)13049 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
13050 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
13051 {
13052 Py_ssize_t i;
13053 PyObject *result = NULL;
13054 const char *name;
13055 char *buffer = NULL;
13056
13057 if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
13058 goto exit;
13059
13060 if (PySys_Audit("os.listxattr", "(O)",
13061 path->object ? path->object : Py_None) < 0) {
13062 return NULL;
13063 }
13064
13065 name = path->narrow ? path->narrow : ".";
13066
13067 for (i = 0; ; i++) {
13068 const char *start, *trace, *end;
13069 ssize_t length;
13070 static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
13071 Py_ssize_t buffer_size = buffer_sizes[i];
13072 if (!buffer_size) {
13073 /* ERANGE */
13074 path_error(path);
13075 break;
13076 }
13077 buffer = PyMem_Malloc(buffer_size);
13078 if (!buffer) {
13079 PyErr_NoMemory();
13080 break;
13081 }
13082
13083 Py_BEGIN_ALLOW_THREADS;
13084 if (path->fd > -1)
13085 length = flistxattr(path->fd, buffer, buffer_size);
13086 else if (follow_symlinks)
13087 length = listxattr(name, buffer, buffer_size);
13088 else
13089 length = llistxattr(name, buffer, buffer_size);
13090 Py_END_ALLOW_THREADS;
13091
13092 if (length < 0) {
13093 if (errno == ERANGE) {
13094 PyMem_Free(buffer);
13095 buffer = NULL;
13096 continue;
13097 }
13098 path_error(path);
13099 break;
13100 }
13101
13102 result = PyList_New(0);
13103 if (!result) {
13104 goto exit;
13105 }
13106
13107 end = buffer + length;
13108 for (trace = start = buffer; trace != end; trace++) {
13109 if (!*trace) {
13110 int error;
13111 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
13112 trace - start);
13113 if (!attribute) {
13114 Py_DECREF(result);
13115 result = NULL;
13116 goto exit;
13117 }
13118 error = PyList_Append(result, attribute);
13119 Py_DECREF(attribute);
13120 if (error) {
13121 Py_DECREF(result);
13122 result = NULL;
13123 goto exit;
13124 }
13125 start = trace + 1;
13126 }
13127 }
13128 break;
13129 }
13130 exit:
13131 if (buffer)
13132 PyMem_Free(buffer);
13133 return result;
13134 }
13135 #endif /* USE_XATTRS */
13136
13137
13138 /*[clinic input]
13139 os.urandom
13140
13141 size: Py_ssize_t
13142 /
13143
13144 Return a bytes object containing random bytes suitable for cryptographic use.
13145 [clinic start generated code]*/
13146
13147 static PyObject *
os_urandom_impl(PyObject * module,Py_ssize_t size)13148 os_urandom_impl(PyObject *module, Py_ssize_t size)
13149 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
13150 {
13151 PyObject *bytes;
13152 int result;
13153
13154 if (size < 0)
13155 return PyErr_Format(PyExc_ValueError,
13156 "negative argument not allowed");
13157 bytes = PyBytes_FromStringAndSize(NULL, size);
13158 if (bytes == NULL)
13159 return NULL;
13160
13161 result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
13162 if (result == -1) {
13163 Py_DECREF(bytes);
13164 return NULL;
13165 }
13166 return bytes;
13167 }
13168
13169 #ifdef HAVE_MEMFD_CREATE
13170 /*[clinic input]
13171 os.memfd_create
13172
13173 name: FSConverter
13174 flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
13175
13176 [clinic start generated code]*/
13177
13178 static PyObject *
os_memfd_create_impl(PyObject * module,PyObject * name,unsigned int flags)13179 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
13180 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
13181 {
13182 int fd;
13183 const char *bytes = PyBytes_AS_STRING(name);
13184 Py_BEGIN_ALLOW_THREADS
13185 fd = memfd_create(bytes, flags);
13186 Py_END_ALLOW_THREADS
13187 if (fd == -1) {
13188 return PyErr_SetFromErrno(PyExc_OSError);
13189 }
13190 return PyLong_FromLong(fd);
13191 }
13192 #endif
13193
13194 #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
13195 /*[clinic input]
13196 os.eventfd
13197
13198 initval: unsigned_int
13199 flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
13200
13201 Creates and returns an event notification file descriptor.
13202 [clinic start generated code]*/
13203
13204 static PyObject *
os_eventfd_impl(PyObject * module,unsigned int initval,int flags)13205 os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
13206 /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
13207
13208 {
13209 /* initval is limited to uint32_t, internal counter is uint64_t */
13210 int fd;
13211 Py_BEGIN_ALLOW_THREADS
13212 fd = eventfd(initval, flags);
13213 Py_END_ALLOW_THREADS
13214 if (fd == -1) {
13215 return PyErr_SetFromErrno(PyExc_OSError);
13216 }
13217 return PyLong_FromLong(fd);
13218 }
13219
13220 /*[clinic input]
13221 os.eventfd_read
13222
13223 fd: fildes
13224
13225 Read eventfd value
13226 [clinic start generated code]*/
13227
13228 static PyObject *
os_eventfd_read_impl(PyObject * module,int fd)13229 os_eventfd_read_impl(PyObject *module, int fd)
13230 /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
13231 {
13232 eventfd_t value;
13233 int result;
13234 Py_BEGIN_ALLOW_THREADS
13235 result = eventfd_read(fd, &value);
13236 Py_END_ALLOW_THREADS
13237 if (result == -1) {
13238 return PyErr_SetFromErrno(PyExc_OSError);
13239 }
13240 return PyLong_FromUnsignedLongLong(value);
13241 }
13242
13243 /*[clinic input]
13244 os.eventfd_write
13245
13246 fd: fildes
13247 value: unsigned_long_long
13248
13249 Write eventfd value.
13250 [clinic start generated code]*/
13251
13252 static PyObject *
os_eventfd_write_impl(PyObject * module,int fd,unsigned long long value)13253 os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
13254 /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
13255 {
13256 int result;
13257 Py_BEGIN_ALLOW_THREADS
13258 result = eventfd_write(fd, value);
13259 Py_END_ALLOW_THREADS
13260 if (result == -1) {
13261 return PyErr_SetFromErrno(PyExc_OSError);
13262 }
13263 Py_RETURN_NONE;
13264 }
13265 #endif /* HAVE_EVENTFD && EFD_CLOEXEC */
13266
13267 /* Terminal size querying */
13268
13269 PyDoc_STRVAR(TerminalSize_docstring,
13270 "A tuple of (columns, lines) for holding terminal window size");
13271
13272 static PyStructSequence_Field TerminalSize_fields[] = {
13273 {"columns", "width of the terminal window in characters"},
13274 {"lines", "height of the terminal window in characters"},
13275 {NULL, NULL}
13276 };
13277
13278 static PyStructSequence_Desc TerminalSize_desc = {
13279 "os.terminal_size",
13280 TerminalSize_docstring,
13281 TerminalSize_fields,
13282 2,
13283 };
13284
13285 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
13286 /*[clinic input]
13287 os.get_terminal_size
13288
13289 fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
13290 /
13291
13292 Return the size of the terminal window as (columns, lines).
13293
13294 The optional argument fd (default standard output) specifies
13295 which file descriptor should be queried.
13296
13297 If the file descriptor is not connected to a terminal, an OSError
13298 is thrown.
13299
13300 This function will only be defined if an implementation is
13301 available for this system.
13302
13303 shutil.get_terminal_size is the high-level function which should
13304 normally be used, os.get_terminal_size is the low-level implementation.
13305 [clinic start generated code]*/
13306
13307 static PyObject *
os_get_terminal_size_impl(PyObject * module,int fd)13308 os_get_terminal_size_impl(PyObject *module, int fd)
13309 /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
13310 {
13311 int columns, lines;
13312 PyObject *termsize;
13313
13314 /* Under some conditions stdout may not be connected and
13315 * fileno(stdout) may point to an invalid file descriptor. For example
13316 * GUI apps don't have valid standard streams by default.
13317 *
13318 * If this happens, and the optional fd argument is not present,
13319 * the ioctl below will fail returning EBADF. This is what we want.
13320 */
13321
13322 #ifdef TERMSIZE_USE_IOCTL
13323 {
13324 struct winsize w;
13325 if (ioctl(fd, TIOCGWINSZ, &w))
13326 return PyErr_SetFromErrno(PyExc_OSError);
13327 columns = w.ws_col;
13328 lines = w.ws_row;
13329 }
13330 #endif /* TERMSIZE_USE_IOCTL */
13331
13332 #ifdef TERMSIZE_USE_CONIO
13333 {
13334 DWORD nhandle;
13335 HANDLE handle;
13336 CONSOLE_SCREEN_BUFFER_INFO csbi;
13337 switch (fd) {
13338 case 0: nhandle = STD_INPUT_HANDLE;
13339 break;
13340 case 1: nhandle = STD_OUTPUT_HANDLE;
13341 break;
13342 case 2: nhandle = STD_ERROR_HANDLE;
13343 break;
13344 default:
13345 return PyErr_Format(PyExc_ValueError, "bad file descriptor");
13346 }
13347 handle = GetStdHandle(nhandle);
13348 if (handle == NULL)
13349 return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
13350 if (handle == INVALID_HANDLE_VALUE)
13351 return PyErr_SetFromWindowsErr(0);
13352
13353 if (!GetConsoleScreenBufferInfo(handle, &csbi))
13354 return PyErr_SetFromWindowsErr(0);
13355
13356 columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
13357 lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
13358 }
13359 #endif /* TERMSIZE_USE_CONIO */
13360
13361 PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
13362 termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
13363 if (termsize == NULL)
13364 return NULL;
13365 PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
13366 PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
13367 if (PyErr_Occurred()) {
13368 Py_DECREF(termsize);
13369 return NULL;
13370 }
13371 return termsize;
13372 }
13373 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
13374
13375
13376 /*[clinic input]
13377 os.cpu_count
13378
13379 Return the number of CPUs in the system; return None if indeterminable.
13380
13381 This number is not equivalent to the number of CPUs the current process can
13382 use. The number of usable CPUs can be obtained with
13383 ``len(os.sched_getaffinity(0))``
13384 [clinic start generated code]*/
13385
13386 static PyObject *
os_cpu_count_impl(PyObject * module)13387 os_cpu_count_impl(PyObject *module)
13388 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
13389 {
13390 int ncpu = 0;
13391 #ifdef MS_WINDOWS
13392 ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
13393 #elif defined(__hpux)
13394 ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
13395 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
13396 ncpu = sysconf(_SC_NPROCESSORS_ONLN);
13397 #elif defined(__VXWORKS__)
13398 ncpu = _Py_popcount32(vxCpuEnabledGet());
13399 #elif defined(__DragonFly__) || \
13400 defined(__OpenBSD__) || \
13401 defined(__FreeBSD__) || \
13402 defined(__NetBSD__) || \
13403 defined(__APPLE__)
13404 int mib[2];
13405 size_t len = sizeof(ncpu);
13406 mib[0] = CTL_HW;
13407 mib[1] = HW_NCPU;
13408 if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
13409 ncpu = 0;
13410 #endif
13411 if (ncpu >= 1)
13412 return PyLong_FromLong(ncpu);
13413 else
13414 Py_RETURN_NONE;
13415 }
13416
13417
13418 /*[clinic input]
13419 os.get_inheritable -> bool
13420
13421 fd: int
13422 /
13423
13424 Get the close-on-exe flag of the specified file descriptor.
13425 [clinic start generated code]*/
13426
13427 static int
os_get_inheritable_impl(PyObject * module,int fd)13428 os_get_inheritable_impl(PyObject *module, int fd)
13429 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
13430 {
13431 int return_value;
13432 _Py_BEGIN_SUPPRESS_IPH
13433 return_value = _Py_get_inheritable(fd);
13434 _Py_END_SUPPRESS_IPH
13435 return return_value;
13436 }
13437
13438
13439 /*[clinic input]
13440 os.set_inheritable
13441 fd: int
13442 inheritable: int
13443 /
13444
13445 Set the inheritable flag of the specified file descriptor.
13446 [clinic start generated code]*/
13447
13448 static PyObject *
os_set_inheritable_impl(PyObject * module,int fd,int inheritable)13449 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
13450 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
13451 {
13452 int result;
13453
13454 _Py_BEGIN_SUPPRESS_IPH
13455 result = _Py_set_inheritable(fd, inheritable, NULL);
13456 _Py_END_SUPPRESS_IPH
13457 if (result < 0)
13458 return NULL;
13459 Py_RETURN_NONE;
13460 }
13461
13462
13463 #ifdef MS_WINDOWS
13464 /*[clinic input]
13465 os.get_handle_inheritable -> bool
13466 handle: intptr_t
13467 /
13468
13469 Get the close-on-exe flag of the specified file descriptor.
13470 [clinic start generated code]*/
13471
13472 static int
os_get_handle_inheritable_impl(PyObject * module,intptr_t handle)13473 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
13474 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
13475 {
13476 DWORD flags;
13477
13478 if (!GetHandleInformation((HANDLE)handle, &flags)) {
13479 PyErr_SetFromWindowsErr(0);
13480 return -1;
13481 }
13482
13483 return flags & HANDLE_FLAG_INHERIT;
13484 }
13485
13486
13487 /*[clinic input]
13488 os.set_handle_inheritable
13489 handle: intptr_t
13490 inheritable: bool
13491 /
13492
13493 Set the inheritable flag of the specified handle.
13494 [clinic start generated code]*/
13495
13496 static PyObject *
os_set_handle_inheritable_impl(PyObject * module,intptr_t handle,int inheritable)13497 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
13498 int inheritable)
13499 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
13500 {
13501 DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
13502 if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
13503 PyErr_SetFromWindowsErr(0);
13504 return NULL;
13505 }
13506 Py_RETURN_NONE;
13507 }
13508 #endif /* MS_WINDOWS */
13509
13510 #ifndef MS_WINDOWS
13511 /*[clinic input]
13512 os.get_blocking -> bool
13513 fd: int
13514 /
13515
13516 Get the blocking mode of the file descriptor.
13517
13518 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
13519 [clinic start generated code]*/
13520
13521 static int
os_get_blocking_impl(PyObject * module,int fd)13522 os_get_blocking_impl(PyObject *module, int fd)
13523 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
13524 {
13525 int blocking;
13526
13527 _Py_BEGIN_SUPPRESS_IPH
13528 blocking = _Py_get_blocking(fd);
13529 _Py_END_SUPPRESS_IPH
13530 return blocking;
13531 }
13532
13533 /*[clinic input]
13534 os.set_blocking
13535 fd: int
13536 blocking: bool(accept={int})
13537 /
13538
13539 Set the blocking mode of the specified file descriptor.
13540
13541 Set the O_NONBLOCK flag if blocking is False,
13542 clear the O_NONBLOCK flag otherwise.
13543 [clinic start generated code]*/
13544
13545 static PyObject *
os_set_blocking_impl(PyObject * module,int fd,int blocking)13546 os_set_blocking_impl(PyObject *module, int fd, int blocking)
13547 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
13548 {
13549 int result;
13550
13551 _Py_BEGIN_SUPPRESS_IPH
13552 result = _Py_set_blocking(fd, blocking);
13553 _Py_END_SUPPRESS_IPH
13554 if (result < 0)
13555 return NULL;
13556 Py_RETURN_NONE;
13557 }
13558 #endif /* !MS_WINDOWS */
13559
13560
13561 /*[clinic input]
13562 class os.DirEntry "DirEntry *" "DirEntryType"
13563 [clinic start generated code]*/
13564 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
13565
13566 typedef struct {
13567 PyObject_HEAD
13568 PyObject *name;
13569 PyObject *path;
13570 PyObject *stat;
13571 PyObject *lstat;
13572 #ifdef MS_WINDOWS
13573 struct _Py_stat_struct win32_lstat;
13574 uint64_t win32_file_index;
13575 int got_file_index;
13576 #else /* POSIX */
13577 #ifdef HAVE_DIRENT_D_TYPE
13578 unsigned char d_type;
13579 #endif
13580 ino_t d_ino;
13581 int dir_fd;
13582 #endif
13583 } DirEntry;
13584
13585 static void
DirEntry_dealloc(DirEntry * entry)13586 DirEntry_dealloc(DirEntry *entry)
13587 {
13588 PyTypeObject *tp = Py_TYPE(entry);
13589 Py_XDECREF(entry->name);
13590 Py_XDECREF(entry->path);
13591 Py_XDECREF(entry->stat);
13592 Py_XDECREF(entry->lstat);
13593 freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13594 free_func(entry);
13595 Py_DECREF(tp);
13596 }
13597
13598 /* Forward reference */
13599 static int
13600 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13601 int follow_symlinks, unsigned short mode_bits);
13602
13603 /*[clinic input]
13604 os.DirEntry.is_symlink -> bool
13605 defining_class: defining_class
13606 /
13607
13608 Return True if the entry is a symbolic link; cached per entry.
13609 [clinic start generated code]*/
13610
13611 static int
os_DirEntry_is_symlink_impl(DirEntry * self,PyTypeObject * defining_class)13612 os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
13613 /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
13614 {
13615 #ifdef MS_WINDOWS
13616 return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13617 #elif defined(HAVE_DIRENT_D_TYPE)
13618 /* POSIX */
13619 if (self->d_type != DT_UNKNOWN)
13620 return self->d_type == DT_LNK;
13621 else
13622 return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13623 #else
13624 /* POSIX without d_type */
13625 return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13626 #endif
13627 }
13628
13629 static PyObject *
DirEntry_fetch_stat(PyObject * module,DirEntry * self,int follow_symlinks)13630 DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
13631 {
13632 int result;
13633 STRUCT_STAT st;
13634 PyObject *ub;
13635
13636 #ifdef MS_WINDOWS
13637 if (!PyUnicode_FSDecoder(self->path, &ub))
13638 return NULL;
13639 #if USE_UNICODE_WCHAR_CACHE
13640 _Py_COMP_DIAG_PUSH
13641 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13642 const wchar_t *path = PyUnicode_AsUnicode(ub);
13643 _Py_COMP_DIAG_POP
13644 #else /* USE_UNICODE_WCHAR_CACHE */
13645 wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
13646 Py_DECREF(ub);
13647 #endif /* USE_UNICODE_WCHAR_CACHE */
13648 #else /* POSIX */
13649 if (!PyUnicode_FSConverter(self->path, &ub))
13650 return NULL;
13651 const char *path = PyBytes_AS_STRING(ub);
13652 if (self->dir_fd != DEFAULT_DIR_FD) {
13653 #ifdef HAVE_FSTATAT
13654 if (HAVE_FSTATAT_RUNTIME) {
13655 Py_BEGIN_ALLOW_THREADS
13656 result = fstatat(self->dir_fd, path, &st,
13657 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
13658 Py_END_ALLOW_THREADS
13659 } else
13660
13661 #endif /* HAVE_FSTATAT */
13662 {
13663 Py_DECREF(ub);
13664 PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
13665 return NULL;
13666 }
13667 }
13668 else
13669 #endif
13670 {
13671 Py_BEGIN_ALLOW_THREADS
13672 if (follow_symlinks) {
13673 result = STAT(path, &st);
13674 }
13675 else {
13676 result = LSTAT(path, &st);
13677 }
13678 Py_END_ALLOW_THREADS
13679 }
13680 #if defined(MS_WINDOWS) && !USE_UNICODE_WCHAR_CACHE
13681 PyMem_Free(path);
13682 #else /* USE_UNICODE_WCHAR_CACHE */
13683 Py_DECREF(ub);
13684 #endif /* USE_UNICODE_WCHAR_CACHE */
13685
13686 if (result != 0)
13687 return path_object_error(self->path);
13688
13689 return _pystat_fromstructstat(module, &st);
13690 }
13691
13692 static PyObject *
DirEntry_get_lstat(PyTypeObject * defining_class,DirEntry * self)13693 DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
13694 {
13695 if (!self->lstat) {
13696 PyObject *module = PyType_GetModule(defining_class);
13697 #ifdef MS_WINDOWS
13698 self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
13699 #else /* POSIX */
13700 self->lstat = DirEntry_fetch_stat(module, self, 0);
13701 #endif
13702 }
13703 Py_XINCREF(self->lstat);
13704 return self->lstat;
13705 }
13706
13707 /*[clinic input]
13708 os.DirEntry.stat
13709 defining_class: defining_class
13710 /
13711 *
13712 follow_symlinks: bool = True
13713
13714 Return stat_result object for the entry; cached per entry.
13715 [clinic start generated code]*/
13716
13717 static PyObject *
os_DirEntry_stat_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13718 os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
13719 int follow_symlinks)
13720 /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
13721 {
13722 if (!follow_symlinks) {
13723 return DirEntry_get_lstat(defining_class, self);
13724 }
13725
13726 if (!self->stat) {
13727 int result = os_DirEntry_is_symlink_impl(self, defining_class);
13728 if (result == -1) {
13729 return NULL;
13730 }
13731 if (result) {
13732 PyObject *module = PyType_GetModule(defining_class);
13733 self->stat = DirEntry_fetch_stat(module, self, 1);
13734 }
13735 else {
13736 self->stat = DirEntry_get_lstat(defining_class, self);
13737 }
13738 }
13739
13740 Py_XINCREF(self->stat);
13741 return self->stat;
13742 }
13743
13744 /* Set exception and return -1 on error, 0 for False, 1 for True */
13745 static int
DirEntry_test_mode(PyTypeObject * defining_class,DirEntry * self,int follow_symlinks,unsigned short mode_bits)13746 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13747 int follow_symlinks, unsigned short mode_bits)
13748 {
13749 PyObject *stat = NULL;
13750 PyObject *st_mode = NULL;
13751 long mode;
13752 int result;
13753 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13754 int is_symlink;
13755 int need_stat;
13756 #endif
13757 #ifdef MS_WINDOWS
13758 unsigned long dir_bits;
13759 #endif
13760
13761 #ifdef MS_WINDOWS
13762 is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13763 need_stat = follow_symlinks && is_symlink;
13764 #elif defined(HAVE_DIRENT_D_TYPE)
13765 is_symlink = self->d_type == DT_LNK;
13766 need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
13767 #endif
13768
13769 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13770 if (need_stat) {
13771 #endif
13772 stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
13773 if (!stat) {
13774 if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
13775 /* If file doesn't exist (anymore), then return False
13776 (i.e., say it's not a file/directory) */
13777 PyErr_Clear();
13778 return 0;
13779 }
13780 goto error;
13781 }
13782 _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
13783 st_mode = PyObject_GetAttr(stat, state->st_mode);
13784 if (!st_mode)
13785 goto error;
13786
13787 mode = PyLong_AsLong(st_mode);
13788 if (mode == -1 && PyErr_Occurred())
13789 goto error;
13790 Py_CLEAR(st_mode);
13791 Py_CLEAR(stat);
13792 result = (mode & S_IFMT) == mode_bits;
13793 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13794 }
13795 else if (is_symlink) {
13796 assert(mode_bits != S_IFLNK);
13797 result = 0;
13798 }
13799 else {
13800 assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
13801 #ifdef MS_WINDOWS
13802 dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
13803 if (mode_bits == S_IFDIR)
13804 result = dir_bits != 0;
13805 else
13806 result = dir_bits == 0;
13807 #else /* POSIX */
13808 if (mode_bits == S_IFDIR)
13809 result = self->d_type == DT_DIR;
13810 else
13811 result = self->d_type == DT_REG;
13812 #endif
13813 }
13814 #endif
13815
13816 return result;
13817
13818 error:
13819 Py_XDECREF(st_mode);
13820 Py_XDECREF(stat);
13821 return -1;
13822 }
13823
13824 /*[clinic input]
13825 os.DirEntry.is_dir -> bool
13826 defining_class: defining_class
13827 /
13828 *
13829 follow_symlinks: bool = True
13830
13831 Return True if the entry is a directory; cached per entry.
13832 [clinic start generated code]*/
13833
13834 static int
os_DirEntry_is_dir_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13835 os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
13836 int follow_symlinks)
13837 /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
13838 {
13839 return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
13840 }
13841
13842 /*[clinic input]
13843 os.DirEntry.is_file -> bool
13844 defining_class: defining_class
13845 /
13846 *
13847 follow_symlinks: bool = True
13848
13849 Return True if the entry is a file; cached per entry.
13850 [clinic start generated code]*/
13851
13852 static int
os_DirEntry_is_file_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13853 os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
13854 int follow_symlinks)
13855 /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
13856 {
13857 return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
13858 }
13859
13860 /*[clinic input]
13861 os.DirEntry.inode
13862
13863 Return inode of the entry; cached per entry.
13864 [clinic start generated code]*/
13865
13866 static PyObject *
os_DirEntry_inode_impl(DirEntry * self)13867 os_DirEntry_inode_impl(DirEntry *self)
13868 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
13869 {
13870 #ifdef MS_WINDOWS
13871 if (!self->got_file_index) {
13872 PyObject *unicode;
13873 STRUCT_STAT stat;
13874 int result;
13875
13876 if (!PyUnicode_FSDecoder(self->path, &unicode))
13877 return NULL;
13878 #if USE_UNICODE_WCHAR_CACHE
13879 _Py_COMP_DIAG_PUSH
13880 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13881 const wchar_t *path = PyUnicode_AsUnicode(unicode);
13882 result = LSTAT(path, &stat);
13883 Py_DECREF(unicode);
13884 _Py_COMP_DIAG_POP
13885 #else /* USE_UNICODE_WCHAR_CACHE */
13886 wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
13887 Py_DECREF(unicode);
13888 result = LSTAT(path, &stat);
13889 PyMem_Free(path);
13890 #endif /* USE_UNICODE_WCHAR_CACHE */
13891
13892 if (result != 0)
13893 return path_object_error(self->path);
13894
13895 self->win32_file_index = stat.st_ino;
13896 self->got_file_index = 1;
13897 }
13898 static_assert(sizeof(unsigned long long) >= sizeof(self->win32_file_index),
13899 "DirEntry.win32_file_index is larger than unsigned long long");
13900 return PyLong_FromUnsignedLongLong(self->win32_file_index);
13901 #else /* POSIX */
13902 static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
13903 "DirEntry.d_ino is larger than unsigned long long");
13904 return PyLong_FromUnsignedLongLong(self->d_ino);
13905 #endif
13906 }
13907
13908 static PyObject *
DirEntry_repr(DirEntry * self)13909 DirEntry_repr(DirEntry *self)
13910 {
13911 return PyUnicode_FromFormat("<DirEntry %R>", self->name);
13912 }
13913
13914 /*[clinic input]
13915 os.DirEntry.__fspath__
13916
13917 Returns the path for the entry.
13918 [clinic start generated code]*/
13919
13920 static PyObject *
os_DirEntry___fspath___impl(DirEntry * self)13921 os_DirEntry___fspath___impl(DirEntry *self)
13922 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
13923 {
13924 Py_INCREF(self->path);
13925 return self->path;
13926 }
13927
13928 static PyMemberDef DirEntry_members[] = {
13929 {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
13930 "the entry's base filename, relative to scandir() \"path\" argument"},
13931 {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
13932 "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
13933 {NULL}
13934 };
13935
13936 #include "clinic/posixmodule.c.h"
13937
13938 static PyMethodDef DirEntry_methods[] = {
13939 OS_DIRENTRY_IS_DIR_METHODDEF
13940 OS_DIRENTRY_IS_FILE_METHODDEF
13941 OS_DIRENTRY_IS_SYMLINK_METHODDEF
13942 OS_DIRENTRY_STAT_METHODDEF
13943 OS_DIRENTRY_INODE_METHODDEF
13944 OS_DIRENTRY___FSPATH___METHODDEF
13945 {"__class_getitem__", Py_GenericAlias,
13946 METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
13947 {NULL}
13948 };
13949
13950 static PyType_Slot DirEntryType_slots[] = {
13951 {Py_tp_dealloc, DirEntry_dealloc},
13952 {Py_tp_repr, DirEntry_repr},
13953 {Py_tp_methods, DirEntry_methods},
13954 {Py_tp_members, DirEntry_members},
13955 {0, 0},
13956 };
13957
13958 static PyType_Spec DirEntryType_spec = {
13959 MODNAME ".DirEntry",
13960 sizeof(DirEntry),
13961 0,
13962 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
13963 DirEntryType_slots
13964 };
13965
13966
13967 #ifdef MS_WINDOWS
13968
13969 static wchar_t *
join_path_filenameW(const wchar_t * path_wide,const wchar_t * filename)13970 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
13971 {
13972 Py_ssize_t path_len;
13973 Py_ssize_t size;
13974 wchar_t *result;
13975 wchar_t ch;
13976
13977 if (!path_wide) { /* Default arg: "." */
13978 path_wide = L".";
13979 path_len = 1;
13980 }
13981 else {
13982 path_len = wcslen(path_wide);
13983 }
13984
13985 /* The +1's are for the path separator and the NUL */
13986 size = path_len + 1 + wcslen(filename) + 1;
13987 result = PyMem_New(wchar_t, size);
13988 if (!result) {
13989 PyErr_NoMemory();
13990 return NULL;
13991 }
13992 wcscpy(result, path_wide);
13993 if (path_len > 0) {
13994 ch = result[path_len - 1];
13995 if (ch != SEP && ch != ALTSEP && ch != L':')
13996 result[path_len++] = SEP;
13997 wcscpy(result + path_len, filename);
13998 }
13999 return result;
14000 }
14001
14002 static PyObject *
DirEntry_from_find_data(PyObject * module,path_t * path,WIN32_FIND_DATAW * dataW)14003 DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
14004 {
14005 DirEntry *entry;
14006 BY_HANDLE_FILE_INFORMATION file_info;
14007 ULONG reparse_tag;
14008 wchar_t *joined_path;
14009
14010 PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
14011 entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
14012 if (!entry)
14013 return NULL;
14014 entry->name = NULL;
14015 entry->path = NULL;
14016 entry->stat = NULL;
14017 entry->lstat = NULL;
14018 entry->got_file_index = 0;
14019
14020 entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
14021 if (!entry->name)
14022 goto error;
14023 if (path->narrow) {
14024 Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
14025 if (!entry->name)
14026 goto error;
14027 }
14028
14029 joined_path = join_path_filenameW(path->wide, dataW->cFileName);
14030 if (!joined_path)
14031 goto error;
14032
14033 entry->path = PyUnicode_FromWideChar(joined_path, -1);
14034 PyMem_Free(joined_path);
14035 if (!entry->path)
14036 goto error;
14037 if (path->narrow) {
14038 Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
14039 if (!entry->path)
14040 goto error;
14041 }
14042
14043 find_data_to_file_info(dataW, &file_info, &reparse_tag);
14044 _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
14045
14046 return (PyObject *)entry;
14047
14048 error:
14049 Py_DECREF(entry);
14050 return NULL;
14051 }
14052
14053 #else /* POSIX */
14054
14055 static char *
join_path_filename(const char * path_narrow,const char * filename,Py_ssize_t filename_len)14056 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
14057 {
14058 Py_ssize_t path_len;
14059 Py_ssize_t size;
14060 char *result;
14061
14062 if (!path_narrow) { /* Default arg: "." */
14063 path_narrow = ".";
14064 path_len = 1;
14065 }
14066 else {
14067 path_len = strlen(path_narrow);
14068 }
14069
14070 if (filename_len == -1)
14071 filename_len = strlen(filename);
14072
14073 /* The +1's are for the path separator and the NUL */
14074 size = path_len + 1 + filename_len + 1;
14075 result = PyMem_New(char, size);
14076 if (!result) {
14077 PyErr_NoMemory();
14078 return NULL;
14079 }
14080 strcpy(result, path_narrow);
14081 if (path_len > 0 && result[path_len - 1] != '/')
14082 result[path_len++] = '/';
14083 strcpy(result + path_len, filename);
14084 return result;
14085 }
14086
14087 static PyObject *
DirEntry_from_posix_info(PyObject * module,path_t * path,const char * name,Py_ssize_t name_len,ino_t d_ino,unsigned char d_type)14088 DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
14089 Py_ssize_t name_len, ino_t d_ino
14090 #ifdef HAVE_DIRENT_D_TYPE
14091 , unsigned char d_type
14092 #endif
14093 )
14094 {
14095 DirEntry *entry;
14096 char *joined_path;
14097
14098 PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
14099 entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
14100 if (!entry)
14101 return NULL;
14102 entry->name = NULL;
14103 entry->path = NULL;
14104 entry->stat = NULL;
14105 entry->lstat = NULL;
14106
14107 if (path->fd != -1) {
14108 entry->dir_fd = path->fd;
14109 joined_path = NULL;
14110 }
14111 else {
14112 entry->dir_fd = DEFAULT_DIR_FD;
14113 joined_path = join_path_filename(path->narrow, name, name_len);
14114 if (!joined_path)
14115 goto error;
14116 }
14117
14118 if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
14119 entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
14120 if (joined_path)
14121 entry->path = PyUnicode_DecodeFSDefault(joined_path);
14122 }
14123 else {
14124 entry->name = PyBytes_FromStringAndSize(name, name_len);
14125 if (joined_path)
14126 entry->path = PyBytes_FromString(joined_path);
14127 }
14128 PyMem_Free(joined_path);
14129 if (!entry->name)
14130 goto error;
14131
14132 if (path->fd != -1) {
14133 entry->path = entry->name;
14134 Py_INCREF(entry->path);
14135 }
14136 else if (!entry->path)
14137 goto error;
14138
14139 #ifdef HAVE_DIRENT_D_TYPE
14140 entry->d_type = d_type;
14141 #endif
14142 entry->d_ino = d_ino;
14143
14144 return (PyObject *)entry;
14145
14146 error:
14147 Py_XDECREF(entry);
14148 return NULL;
14149 }
14150
14151 #endif
14152
14153
14154 typedef struct {
14155 PyObject_HEAD
14156 path_t path;
14157 #ifdef MS_WINDOWS
14158 HANDLE handle;
14159 WIN32_FIND_DATAW file_data;
14160 int first_time;
14161 #else /* POSIX */
14162 DIR *dirp;
14163 #endif
14164 #ifdef HAVE_FDOPENDIR
14165 int fd;
14166 #endif
14167 } ScandirIterator;
14168
14169 #ifdef MS_WINDOWS
14170
14171 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14172 ScandirIterator_is_closed(ScandirIterator *iterator)
14173 {
14174 return iterator->handle == INVALID_HANDLE_VALUE;
14175 }
14176
14177 static void
ScandirIterator_closedir(ScandirIterator * iterator)14178 ScandirIterator_closedir(ScandirIterator *iterator)
14179 {
14180 HANDLE handle = iterator->handle;
14181
14182 if (handle == INVALID_HANDLE_VALUE)
14183 return;
14184
14185 iterator->handle = INVALID_HANDLE_VALUE;
14186 Py_BEGIN_ALLOW_THREADS
14187 FindClose(handle);
14188 Py_END_ALLOW_THREADS
14189 }
14190
14191 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14192 ScandirIterator_iternext(ScandirIterator *iterator)
14193 {
14194 WIN32_FIND_DATAW *file_data = &iterator->file_data;
14195 BOOL success;
14196 PyObject *entry;
14197
14198 /* Happens if the iterator is iterated twice, or closed explicitly */
14199 if (iterator->handle == INVALID_HANDLE_VALUE)
14200 return NULL;
14201
14202 while (1) {
14203 if (!iterator->first_time) {
14204 Py_BEGIN_ALLOW_THREADS
14205 success = FindNextFileW(iterator->handle, file_data);
14206 Py_END_ALLOW_THREADS
14207 if (!success) {
14208 /* Error or no more files */
14209 if (GetLastError() != ERROR_NO_MORE_FILES)
14210 path_error(&iterator->path);
14211 break;
14212 }
14213 }
14214 iterator->first_time = 0;
14215
14216 /* Skip over . and .. */
14217 if (wcscmp(file_data->cFileName, L".") != 0 &&
14218 wcscmp(file_data->cFileName, L"..") != 0)
14219 {
14220 PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14221 entry = DirEntry_from_find_data(module, &iterator->path, file_data);
14222 if (!entry)
14223 break;
14224 return entry;
14225 }
14226
14227 /* Loop till we get a non-dot directory or finish iterating */
14228 }
14229
14230 /* Error or no more files */
14231 ScandirIterator_closedir(iterator);
14232 return NULL;
14233 }
14234
14235 #else /* POSIX */
14236
14237 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14238 ScandirIterator_is_closed(ScandirIterator *iterator)
14239 {
14240 return !iterator->dirp;
14241 }
14242
14243 static void
ScandirIterator_closedir(ScandirIterator * iterator)14244 ScandirIterator_closedir(ScandirIterator *iterator)
14245 {
14246 DIR *dirp = iterator->dirp;
14247
14248 if (!dirp)
14249 return;
14250
14251 iterator->dirp = NULL;
14252 Py_BEGIN_ALLOW_THREADS
14253 #ifdef HAVE_FDOPENDIR
14254 if (iterator->path.fd != -1)
14255 rewinddir(dirp);
14256 #endif
14257 closedir(dirp);
14258 Py_END_ALLOW_THREADS
14259 return;
14260 }
14261
14262 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14263 ScandirIterator_iternext(ScandirIterator *iterator)
14264 {
14265 struct dirent *direntp;
14266 Py_ssize_t name_len;
14267 int is_dot;
14268 PyObject *entry;
14269
14270 /* Happens if the iterator is iterated twice, or closed explicitly */
14271 if (!iterator->dirp)
14272 return NULL;
14273
14274 while (1) {
14275 errno = 0;
14276 Py_BEGIN_ALLOW_THREADS
14277 direntp = readdir(iterator->dirp);
14278 Py_END_ALLOW_THREADS
14279
14280 if (!direntp) {
14281 /* Error or no more files */
14282 if (errno != 0)
14283 path_error(&iterator->path);
14284 break;
14285 }
14286
14287 /* Skip over . and .. */
14288 name_len = NAMLEN(direntp);
14289 is_dot = direntp->d_name[0] == '.' &&
14290 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
14291 if (!is_dot) {
14292 PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14293 entry = DirEntry_from_posix_info(module,
14294 &iterator->path, direntp->d_name,
14295 name_len, direntp->d_ino
14296 #ifdef HAVE_DIRENT_D_TYPE
14297 , direntp->d_type
14298 #endif
14299 );
14300 if (!entry)
14301 break;
14302 return entry;
14303 }
14304
14305 /* Loop till we get a non-dot directory or finish iterating */
14306 }
14307
14308 /* Error or no more files */
14309 ScandirIterator_closedir(iterator);
14310 return NULL;
14311 }
14312
14313 #endif
14314
14315 static PyObject *
ScandirIterator_close(ScandirIterator * self,PyObject * args)14316 ScandirIterator_close(ScandirIterator *self, PyObject *args)
14317 {
14318 ScandirIterator_closedir(self);
14319 Py_RETURN_NONE;
14320 }
14321
14322 static PyObject *
ScandirIterator_enter(PyObject * self,PyObject * args)14323 ScandirIterator_enter(PyObject *self, PyObject *args)
14324 {
14325 Py_INCREF(self);
14326 return self;
14327 }
14328
14329 static PyObject *
ScandirIterator_exit(ScandirIterator * self,PyObject * args)14330 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
14331 {
14332 ScandirIterator_closedir(self);
14333 Py_RETURN_NONE;
14334 }
14335
14336 static void
ScandirIterator_finalize(ScandirIterator * iterator)14337 ScandirIterator_finalize(ScandirIterator *iterator)
14338 {
14339 PyObject *error_type, *error_value, *error_traceback;
14340
14341 /* Save the current exception, if any. */
14342 PyErr_Fetch(&error_type, &error_value, &error_traceback);
14343
14344 if (!ScandirIterator_is_closed(iterator)) {
14345 ScandirIterator_closedir(iterator);
14346
14347 if (PyErr_ResourceWarning((PyObject *)iterator, 1,
14348 "unclosed scandir iterator %R", iterator)) {
14349 /* Spurious errors can appear at shutdown */
14350 if (PyErr_ExceptionMatches(PyExc_Warning)) {
14351 PyErr_WriteUnraisable((PyObject *) iterator);
14352 }
14353 }
14354 }
14355
14356 path_cleanup(&iterator->path);
14357
14358 /* Restore the saved exception. */
14359 PyErr_Restore(error_type, error_value, error_traceback);
14360 }
14361
14362 static void
ScandirIterator_dealloc(ScandirIterator * iterator)14363 ScandirIterator_dealloc(ScandirIterator *iterator)
14364 {
14365 PyTypeObject *tp = Py_TYPE(iterator);
14366 if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
14367 return;
14368
14369 freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
14370 free_func(iterator);
14371 Py_DECREF(tp);
14372 }
14373
14374 static PyMethodDef ScandirIterator_methods[] = {
14375 {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
14376 {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
14377 {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
14378 {NULL}
14379 };
14380
14381 static PyType_Slot ScandirIteratorType_slots[] = {
14382 {Py_tp_dealloc, ScandirIterator_dealloc},
14383 {Py_tp_finalize, ScandirIterator_finalize},
14384 {Py_tp_iter, PyObject_SelfIter},
14385 {Py_tp_iternext, ScandirIterator_iternext},
14386 {Py_tp_methods, ScandirIterator_methods},
14387 {0, 0},
14388 };
14389
14390 static PyType_Spec ScandirIteratorType_spec = {
14391 MODNAME ".ScandirIterator",
14392 sizeof(ScandirIterator),
14393 0,
14394 // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
14395 // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
14396 (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
14397 | Py_TPFLAGS_DISALLOW_INSTANTIATION),
14398 ScandirIteratorType_slots
14399 };
14400
14401 /*[clinic input]
14402 os.scandir
14403
14404 path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
14405
14406 Return an iterator of DirEntry objects for given path.
14407
14408 path can be specified as either str, bytes, or a path-like object. If path
14409 is bytes, the names of yielded DirEntry objects will also be bytes; in
14410 all other circumstances they will be str.
14411
14412 If path is None, uses the path='.'.
14413 [clinic start generated code]*/
14414
14415 static PyObject *
os_scandir_impl(PyObject * module,path_t * path)14416 os_scandir_impl(PyObject *module, path_t *path)
14417 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
14418 {
14419 ScandirIterator *iterator;
14420 #ifdef MS_WINDOWS
14421 wchar_t *path_strW;
14422 #else
14423 const char *path_str;
14424 #ifdef HAVE_FDOPENDIR
14425 int fd = -1;
14426 #endif
14427 #endif
14428
14429 if (PySys_Audit("os.scandir", "O",
14430 path->object ? path->object : Py_None) < 0) {
14431 return NULL;
14432 }
14433
14434 PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
14435 iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
14436 if (!iterator)
14437 return NULL;
14438
14439 #ifdef MS_WINDOWS
14440 iterator->handle = INVALID_HANDLE_VALUE;
14441 #else
14442 iterator->dirp = NULL;
14443 #endif
14444
14445 /* Move the ownership to iterator->path */
14446 memcpy(&iterator->path, path, sizeof(path_t));
14447 memset(path, 0, sizeof(path_t));
14448
14449 #ifdef MS_WINDOWS
14450 iterator->first_time = 1;
14451
14452 path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
14453 if (!path_strW)
14454 goto error;
14455
14456 Py_BEGIN_ALLOW_THREADS
14457 iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
14458 Py_END_ALLOW_THREADS
14459
14460 PyMem_Free(path_strW);
14461
14462 if (iterator->handle == INVALID_HANDLE_VALUE) {
14463 path_error(&iterator->path);
14464 goto error;
14465 }
14466 #else /* POSIX */
14467 errno = 0;
14468 #ifdef HAVE_FDOPENDIR
14469 if (iterator->path.fd != -1) {
14470 if (HAVE_FDOPENDIR_RUNTIME) {
14471 /* closedir() closes the FD, so we duplicate it */
14472 fd = _Py_dup(iterator->path.fd);
14473 if (fd == -1)
14474 goto error;
14475
14476 Py_BEGIN_ALLOW_THREADS
14477 iterator->dirp = fdopendir(fd);
14478 Py_END_ALLOW_THREADS
14479 } else {
14480 PyErr_SetString(PyExc_TypeError,
14481 "scandir: path should be string, bytes, os.PathLike or None, not int");
14482 return NULL;
14483 }
14484 }
14485 else
14486 #endif
14487 {
14488 if (iterator->path.narrow)
14489 path_str = iterator->path.narrow;
14490 else
14491 path_str = ".";
14492
14493 Py_BEGIN_ALLOW_THREADS
14494 iterator->dirp = opendir(path_str);
14495 Py_END_ALLOW_THREADS
14496 }
14497
14498 if (!iterator->dirp) {
14499 path_error(&iterator->path);
14500 #ifdef HAVE_FDOPENDIR
14501 if (fd != -1) {
14502 Py_BEGIN_ALLOW_THREADS
14503 close(fd);
14504 Py_END_ALLOW_THREADS
14505 }
14506 #endif
14507 goto error;
14508 }
14509 #endif
14510
14511 return (PyObject *)iterator;
14512
14513 error:
14514 Py_DECREF(iterator);
14515 return NULL;
14516 }
14517
14518 /*
14519 Return the file system path representation of the object.
14520
14521 If the object is str or bytes, then allow it to pass through with
14522 an incremented refcount. If the object defines __fspath__(), then
14523 return the result of that method. All other types raise a TypeError.
14524 */
14525 PyObject *
PyOS_FSPath(PyObject * path)14526 PyOS_FSPath(PyObject *path)
14527 {
14528 /* For error message reasons, this function is manually inlined in
14529 path_converter(). */
14530 PyObject *func = NULL;
14531 PyObject *path_repr = NULL;
14532
14533 if (PyUnicode_Check(path) || PyBytes_Check(path)) {
14534 Py_INCREF(path);
14535 return path;
14536 }
14537
14538 func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
14539 if (NULL == func) {
14540 return PyErr_Format(PyExc_TypeError,
14541 "expected str, bytes or os.PathLike object, "
14542 "not %.200s",
14543 _PyType_Name(Py_TYPE(path)));
14544 }
14545
14546 path_repr = _PyObject_CallNoArgs(func);
14547 Py_DECREF(func);
14548 if (NULL == path_repr) {
14549 return NULL;
14550 }
14551
14552 if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
14553 PyErr_Format(PyExc_TypeError,
14554 "expected %.200s.__fspath__() to return str or bytes, "
14555 "not %.200s", _PyType_Name(Py_TYPE(path)),
14556 _PyType_Name(Py_TYPE(path_repr)));
14557 Py_DECREF(path_repr);
14558 return NULL;
14559 }
14560
14561 return path_repr;
14562 }
14563
14564 /*[clinic input]
14565 os.fspath
14566
14567 path: object
14568
14569 Return the file system path representation of the object.
14570
14571 If the object is str or bytes, then allow it to pass through as-is. If the
14572 object defines __fspath__(), then return the result of that method. All other
14573 types raise a TypeError.
14574 [clinic start generated code]*/
14575
14576 static PyObject *
os_fspath_impl(PyObject * module,PyObject * path)14577 os_fspath_impl(PyObject *module, PyObject *path)
14578 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
14579 {
14580 return PyOS_FSPath(path);
14581 }
14582
14583 #ifdef HAVE_GETRANDOM_SYSCALL
14584 /*[clinic input]
14585 os.getrandom
14586
14587 size: Py_ssize_t
14588 flags: int=0
14589
14590 Obtain a series of random bytes.
14591 [clinic start generated code]*/
14592
14593 static PyObject *
os_getrandom_impl(PyObject * module,Py_ssize_t size,int flags)14594 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
14595 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
14596 {
14597 PyObject *bytes;
14598 Py_ssize_t n;
14599
14600 if (size < 0) {
14601 errno = EINVAL;
14602 return posix_error();
14603 }
14604
14605 bytes = PyBytes_FromStringAndSize(NULL, size);
14606 if (bytes == NULL) {
14607 PyErr_NoMemory();
14608 return NULL;
14609 }
14610
14611 while (1) {
14612 n = syscall(SYS_getrandom,
14613 PyBytes_AS_STRING(bytes),
14614 PyBytes_GET_SIZE(bytes),
14615 flags);
14616 if (n < 0 && errno == EINTR) {
14617 if (PyErr_CheckSignals() < 0) {
14618 goto error;
14619 }
14620
14621 /* getrandom() was interrupted by a signal: retry */
14622 continue;
14623 }
14624 break;
14625 }
14626
14627 if (n < 0) {
14628 PyErr_SetFromErrno(PyExc_OSError);
14629 goto error;
14630 }
14631
14632 if (n != size) {
14633 _PyBytes_Resize(&bytes, n);
14634 }
14635
14636 return bytes;
14637
14638 error:
14639 Py_DECREF(bytes);
14640 return NULL;
14641 }
14642 #endif /* HAVE_GETRANDOM_SYSCALL */
14643
14644 #ifdef MS_WINDOWS
14645 /* bpo-36085: Helper functions for managing DLL search directories
14646 * on win32
14647 */
14648
14649 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
14650 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
14651
14652 /*[clinic input]
14653 os._add_dll_directory
14654
14655 path: path_t
14656
14657 Add a path to the DLL search path.
14658
14659 This search path is used when resolving dependencies for imported
14660 extension modules (the module itself is resolved through sys.path),
14661 and also by ctypes.
14662
14663 Returns an opaque value that may be passed to os.remove_dll_directory
14664 to remove this directory from the search path.
14665 [clinic start generated code]*/
14666
14667 static PyObject *
os__add_dll_directory_impl(PyObject * module,path_t * path)14668 os__add_dll_directory_impl(PyObject *module, path_t *path)
14669 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
14670 {
14671 HMODULE hKernel32;
14672 PAddDllDirectory AddDllDirectory;
14673 DLL_DIRECTORY_COOKIE cookie = 0;
14674 DWORD err = 0;
14675
14676 if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
14677 return NULL;
14678 }
14679
14680 /* For Windows 7, we have to load this. As this will be a fairly
14681 infrequent operation, just do it each time. Kernel32 is always
14682 loaded. */
14683 Py_BEGIN_ALLOW_THREADS
14684 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14685 !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
14686 hKernel32, "AddDllDirectory")) ||
14687 !(cookie = (*AddDllDirectory)(path->wide))) {
14688 err = GetLastError();
14689 }
14690 Py_END_ALLOW_THREADS
14691
14692 if (err) {
14693 return win32_error_object_err("add_dll_directory",
14694 path->object, err);
14695 }
14696
14697 return PyCapsule_New(cookie, "DLL directory cookie", NULL);
14698 }
14699
14700 /*[clinic input]
14701 os._remove_dll_directory
14702
14703 cookie: object
14704
14705 Removes a path from the DLL search path.
14706
14707 The parameter is an opaque value that was returned from
14708 os.add_dll_directory. You can only remove directories that you added
14709 yourself.
14710 [clinic start generated code]*/
14711
14712 static PyObject *
os__remove_dll_directory_impl(PyObject * module,PyObject * cookie)14713 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
14714 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
14715 {
14716 HMODULE hKernel32;
14717 PRemoveDllDirectory RemoveDllDirectory;
14718 DLL_DIRECTORY_COOKIE cookieValue;
14719 DWORD err = 0;
14720
14721 if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
14722 PyErr_SetString(PyExc_TypeError,
14723 "Provided cookie was not returned from os.add_dll_directory");
14724 return NULL;
14725 }
14726
14727 cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
14728 cookie, "DLL directory cookie");
14729
14730 /* For Windows 7, we have to load this. As this will be a fairly
14731 infrequent operation, just do it each time. Kernel32 is always
14732 loaded. */
14733 Py_BEGIN_ALLOW_THREADS
14734 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14735 !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
14736 hKernel32, "RemoveDllDirectory")) ||
14737 !(*RemoveDllDirectory)(cookieValue)) {
14738 err = GetLastError();
14739 }
14740 Py_END_ALLOW_THREADS
14741
14742 if (err) {
14743 return win32_error_object_err("remove_dll_directory",
14744 NULL, err);
14745 }
14746
14747 if (PyCapsule_SetName(cookie, NULL)) {
14748 return NULL;
14749 }
14750
14751 Py_RETURN_NONE;
14752 }
14753
14754 #endif
14755
14756
14757 /* Only check if WIFEXITED is available: expect that it comes
14758 with WEXITSTATUS, WIFSIGNALED, etc.
14759
14760 os.waitstatus_to_exitcode() is implemented in C and not in Python, so
14761 subprocess can safely call it during late Python finalization without
14762 risking that used os attributes were set to None by finalize_modules(). */
14763 #if defined(WIFEXITED) || defined(MS_WINDOWS)
14764 /*[clinic input]
14765 os.waitstatus_to_exitcode
14766
14767 status as status_obj: object
14768
14769 Convert a wait status to an exit code.
14770
14771 On Unix:
14772
14773 * If WIFEXITED(status) is true, return WEXITSTATUS(status).
14774 * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
14775 * Otherwise, raise a ValueError.
14776
14777 On Windows, return status shifted right by 8 bits.
14778
14779 On Unix, if the process is being traced or if waitpid() was called with
14780 WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
14781 This function must not be called if WIFSTOPPED(status) is true.
14782 [clinic start generated code]*/
14783
14784 static PyObject *
os_waitstatus_to_exitcode_impl(PyObject * module,PyObject * status_obj)14785 os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
14786 /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
14787 {
14788 #ifndef MS_WINDOWS
14789 int status = _PyLong_AsInt(status_obj);
14790 if (status == -1 && PyErr_Occurred()) {
14791 return NULL;
14792 }
14793
14794 WAIT_TYPE wait_status;
14795 WAIT_STATUS_INT(wait_status) = status;
14796 int exitcode;
14797 if (WIFEXITED(wait_status)) {
14798 exitcode = WEXITSTATUS(wait_status);
14799 /* Sanity check to provide warranty on the function behavior.
14800 It should not occur in practice */
14801 if (exitcode < 0) {
14802 PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
14803 return NULL;
14804 }
14805 }
14806 else if (WIFSIGNALED(wait_status)) {
14807 int signum = WTERMSIG(wait_status);
14808 /* Sanity check to provide warranty on the function behavior.
14809 It should not occurs in practice */
14810 if (signum <= 0) {
14811 PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
14812 return NULL;
14813 }
14814 exitcode = -signum;
14815 } else if (WIFSTOPPED(wait_status)) {
14816 /* Status only received if the process is being traced
14817 or if waitpid() was called with WUNTRACED option. */
14818 int signum = WSTOPSIG(wait_status);
14819 PyErr_Format(PyExc_ValueError,
14820 "process stopped by delivery of signal %i",
14821 signum);
14822 return NULL;
14823 }
14824 else {
14825 PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
14826 return NULL;
14827 }
14828 return PyLong_FromLong(exitcode);
14829 #else
14830 /* Windows implementation: see os.waitpid() implementation
14831 which uses _cwait(). */
14832 unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
14833 if (status == (unsigned long long)-1 && PyErr_Occurred()) {
14834 return NULL;
14835 }
14836
14837 unsigned long long exitcode = (status >> 8);
14838 /* ExitProcess() accepts an UINT type:
14839 reject exit code which doesn't fit in an UINT */
14840 if (exitcode > UINT_MAX) {
14841 PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
14842 return NULL;
14843 }
14844 return PyLong_FromUnsignedLong((unsigned long)exitcode);
14845 #endif
14846 }
14847 #endif
14848
14849
14850 static PyMethodDef posix_methods[] = {
14851
14852 OS_STAT_METHODDEF
14853 OS_ACCESS_METHODDEF
14854 OS_TTYNAME_METHODDEF
14855 OS_CHDIR_METHODDEF
14856 OS_CHFLAGS_METHODDEF
14857 OS_CHMOD_METHODDEF
14858 OS_FCHMOD_METHODDEF
14859 OS_LCHMOD_METHODDEF
14860 OS_CHOWN_METHODDEF
14861 OS_FCHOWN_METHODDEF
14862 OS_LCHOWN_METHODDEF
14863 OS_LCHFLAGS_METHODDEF
14864 OS_CHROOT_METHODDEF
14865 OS_CTERMID_METHODDEF
14866 OS_GETCWD_METHODDEF
14867 OS_GETCWDB_METHODDEF
14868 OS_LINK_METHODDEF
14869 OS_LISTDIR_METHODDEF
14870 OS_LSTAT_METHODDEF
14871 OS_MKDIR_METHODDEF
14872 OS_NICE_METHODDEF
14873 OS_GETPRIORITY_METHODDEF
14874 OS_SETPRIORITY_METHODDEF
14875 OS_POSIX_SPAWN_METHODDEF
14876 OS_POSIX_SPAWNP_METHODDEF
14877 OS_READLINK_METHODDEF
14878 OS_COPY_FILE_RANGE_METHODDEF
14879 OS_SPLICE_METHODDEF
14880 OS_RENAME_METHODDEF
14881 OS_REPLACE_METHODDEF
14882 OS_RMDIR_METHODDEF
14883 OS_SYMLINK_METHODDEF
14884 OS_SYSTEM_METHODDEF
14885 OS_UMASK_METHODDEF
14886 OS_UNAME_METHODDEF
14887 OS_UNLINK_METHODDEF
14888 OS_REMOVE_METHODDEF
14889 OS_UTIME_METHODDEF
14890 OS_TIMES_METHODDEF
14891 OS__EXIT_METHODDEF
14892 OS__FCOPYFILE_METHODDEF
14893 OS_EXECV_METHODDEF
14894 OS_EXECVE_METHODDEF
14895 OS_SPAWNV_METHODDEF
14896 OS_SPAWNVE_METHODDEF
14897 OS_FORK1_METHODDEF
14898 OS_FORK_METHODDEF
14899 OS_REGISTER_AT_FORK_METHODDEF
14900 OS_SCHED_GET_PRIORITY_MAX_METHODDEF
14901 OS_SCHED_GET_PRIORITY_MIN_METHODDEF
14902 OS_SCHED_GETPARAM_METHODDEF
14903 OS_SCHED_GETSCHEDULER_METHODDEF
14904 OS_SCHED_RR_GET_INTERVAL_METHODDEF
14905 OS_SCHED_SETPARAM_METHODDEF
14906 OS_SCHED_SETSCHEDULER_METHODDEF
14907 OS_SCHED_YIELD_METHODDEF
14908 OS_SCHED_SETAFFINITY_METHODDEF
14909 OS_SCHED_GETAFFINITY_METHODDEF
14910 OS_OPENPTY_METHODDEF
14911 OS_LOGIN_TTY_METHODDEF
14912 OS_FORKPTY_METHODDEF
14913 OS_GETEGID_METHODDEF
14914 OS_GETEUID_METHODDEF
14915 OS_GETGID_METHODDEF
14916 OS_GETGROUPLIST_METHODDEF
14917 OS_GETGROUPS_METHODDEF
14918 OS_GETPID_METHODDEF
14919 OS_GETPGRP_METHODDEF
14920 OS_GETPPID_METHODDEF
14921 OS_GETUID_METHODDEF
14922 OS_GETLOGIN_METHODDEF
14923 OS_KILL_METHODDEF
14924 OS_KILLPG_METHODDEF
14925 OS_PLOCK_METHODDEF
14926 OS_STARTFILE_METHODDEF
14927 OS_SETUID_METHODDEF
14928 OS_SETEUID_METHODDEF
14929 OS_SETREUID_METHODDEF
14930 OS_SETGID_METHODDEF
14931 OS_SETEGID_METHODDEF
14932 OS_SETREGID_METHODDEF
14933 OS_SETGROUPS_METHODDEF
14934 OS_INITGROUPS_METHODDEF
14935 OS_GETPGID_METHODDEF
14936 OS_SETPGRP_METHODDEF
14937 OS_WAIT_METHODDEF
14938 OS_WAIT3_METHODDEF
14939 OS_WAIT4_METHODDEF
14940 OS_WAITID_METHODDEF
14941 OS_WAITPID_METHODDEF
14942 OS_PIDFD_OPEN_METHODDEF
14943 OS_GETSID_METHODDEF
14944 OS_SETSID_METHODDEF
14945 OS_SETPGID_METHODDEF
14946 OS_TCGETPGRP_METHODDEF
14947 OS_TCSETPGRP_METHODDEF
14948 OS_OPEN_METHODDEF
14949 OS_CLOSE_METHODDEF
14950 OS_CLOSERANGE_METHODDEF
14951 OS_DEVICE_ENCODING_METHODDEF
14952 OS_DUP_METHODDEF
14953 OS_DUP2_METHODDEF
14954 OS_LOCKF_METHODDEF
14955 OS_LSEEK_METHODDEF
14956 OS_READ_METHODDEF
14957 OS_READV_METHODDEF
14958 OS_PREAD_METHODDEF
14959 OS_PREADV_METHODDEF
14960 OS_WRITE_METHODDEF
14961 OS_WRITEV_METHODDEF
14962 OS_PWRITE_METHODDEF
14963 OS_PWRITEV_METHODDEF
14964 OS_SENDFILE_METHODDEF
14965 OS_FSTAT_METHODDEF
14966 OS_ISATTY_METHODDEF
14967 OS_PIPE_METHODDEF
14968 OS_PIPE2_METHODDEF
14969 OS_MKFIFO_METHODDEF
14970 OS_MKNOD_METHODDEF
14971 OS_MAJOR_METHODDEF
14972 OS_MINOR_METHODDEF
14973 OS_MAKEDEV_METHODDEF
14974 OS_FTRUNCATE_METHODDEF
14975 OS_TRUNCATE_METHODDEF
14976 OS_POSIX_FALLOCATE_METHODDEF
14977 OS_POSIX_FADVISE_METHODDEF
14978 OS_PUTENV_METHODDEF
14979 OS_UNSETENV_METHODDEF
14980 OS_STRERROR_METHODDEF
14981 OS_FCHDIR_METHODDEF
14982 OS_FSYNC_METHODDEF
14983 OS_SYNC_METHODDEF
14984 OS_FDATASYNC_METHODDEF
14985 OS_WCOREDUMP_METHODDEF
14986 OS_WIFCONTINUED_METHODDEF
14987 OS_WIFSTOPPED_METHODDEF
14988 OS_WIFSIGNALED_METHODDEF
14989 OS_WIFEXITED_METHODDEF
14990 OS_WEXITSTATUS_METHODDEF
14991 OS_WTERMSIG_METHODDEF
14992 OS_WSTOPSIG_METHODDEF
14993 OS_FSTATVFS_METHODDEF
14994 OS_STATVFS_METHODDEF
14995 OS_CONFSTR_METHODDEF
14996 OS_SYSCONF_METHODDEF
14997 OS_FPATHCONF_METHODDEF
14998 OS_PATHCONF_METHODDEF
14999 OS_ABORT_METHODDEF
15000 OS__GETFULLPATHNAME_METHODDEF
15001 OS__GETDISKUSAGE_METHODDEF
15002 OS__GETFINALPATHNAME_METHODDEF
15003 OS__GETVOLUMEPATHNAME_METHODDEF
15004 OS__PATH_SPLITROOT_METHODDEF
15005 OS__PATH_NORMPATH_METHODDEF
15006 OS_GETLOADAVG_METHODDEF
15007 OS_URANDOM_METHODDEF
15008 OS_SETRESUID_METHODDEF
15009 OS_SETRESGID_METHODDEF
15010 OS_GETRESUID_METHODDEF
15011 OS_GETRESGID_METHODDEF
15012
15013 OS_GETXATTR_METHODDEF
15014 OS_SETXATTR_METHODDEF
15015 OS_REMOVEXATTR_METHODDEF
15016 OS_LISTXATTR_METHODDEF
15017
15018 OS_GET_TERMINAL_SIZE_METHODDEF
15019 OS_CPU_COUNT_METHODDEF
15020 OS_GET_INHERITABLE_METHODDEF
15021 OS_SET_INHERITABLE_METHODDEF
15022 OS_GET_HANDLE_INHERITABLE_METHODDEF
15023 OS_SET_HANDLE_INHERITABLE_METHODDEF
15024 OS_GET_BLOCKING_METHODDEF
15025 OS_SET_BLOCKING_METHODDEF
15026 OS_SCANDIR_METHODDEF
15027 OS_FSPATH_METHODDEF
15028 OS_GETRANDOM_METHODDEF
15029 OS_MEMFD_CREATE_METHODDEF
15030 OS_EVENTFD_METHODDEF
15031 OS_EVENTFD_READ_METHODDEF
15032 OS_EVENTFD_WRITE_METHODDEF
15033 OS__ADD_DLL_DIRECTORY_METHODDEF
15034 OS__REMOVE_DLL_DIRECTORY_METHODDEF
15035 OS_WAITSTATUS_TO_EXITCODE_METHODDEF
15036 {NULL, NULL} /* Sentinel */
15037 };
15038
15039 static int
all_ins(PyObject * m)15040 all_ins(PyObject *m)
15041 {
15042 #ifdef F_OK
15043 if (PyModule_AddIntMacro(m, F_OK)) return -1;
15044 #endif
15045 #ifdef R_OK
15046 if (PyModule_AddIntMacro(m, R_OK)) return -1;
15047 #endif
15048 #ifdef W_OK
15049 if (PyModule_AddIntMacro(m, W_OK)) return -1;
15050 #endif
15051 #ifdef X_OK
15052 if (PyModule_AddIntMacro(m, X_OK)) return -1;
15053 #endif
15054 #ifdef NGROUPS_MAX
15055 if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
15056 #endif
15057 #ifdef TMP_MAX
15058 if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
15059 #endif
15060 #ifdef WCONTINUED
15061 if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
15062 #endif
15063 #ifdef WNOHANG
15064 if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
15065 #endif
15066 #ifdef WUNTRACED
15067 if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
15068 #endif
15069 #ifdef O_RDONLY
15070 if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
15071 #endif
15072 #ifdef O_WRONLY
15073 if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
15074 #endif
15075 #ifdef O_RDWR
15076 if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
15077 #endif
15078 #ifdef O_NDELAY
15079 if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
15080 #endif
15081 #ifdef O_NONBLOCK
15082 if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
15083 #endif
15084 #ifdef O_APPEND
15085 if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
15086 #endif
15087 #ifdef O_DSYNC
15088 if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
15089 #endif
15090 #ifdef O_RSYNC
15091 if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
15092 #endif
15093 #ifdef O_SYNC
15094 if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
15095 #endif
15096 #ifdef O_NOCTTY
15097 if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
15098 #endif
15099 #ifdef O_CREAT
15100 if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
15101 #endif
15102 #ifdef O_EXCL
15103 if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
15104 #endif
15105 #ifdef O_TRUNC
15106 if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
15107 #endif
15108 #ifdef O_BINARY
15109 if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
15110 #endif
15111 #ifdef O_TEXT
15112 if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
15113 #endif
15114 #ifdef O_XATTR
15115 if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
15116 #endif
15117 #ifdef O_LARGEFILE
15118 if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
15119 #endif
15120 #ifndef __GNU__
15121 #ifdef O_SHLOCK
15122 if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
15123 #endif
15124 #ifdef O_EXLOCK
15125 if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
15126 #endif
15127 #endif
15128 #ifdef O_EXEC
15129 if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
15130 #endif
15131 #ifdef O_SEARCH
15132 if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
15133 #endif
15134 #ifdef O_PATH
15135 if (PyModule_AddIntMacro(m, O_PATH)) return -1;
15136 #endif
15137 #ifdef O_TTY_INIT
15138 if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
15139 #endif
15140 #ifdef O_TMPFILE
15141 if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
15142 #endif
15143 #ifdef PRIO_PROCESS
15144 if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
15145 #endif
15146 #ifdef PRIO_PGRP
15147 if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
15148 #endif
15149 #ifdef PRIO_USER
15150 if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
15151 #endif
15152 #ifdef O_CLOEXEC
15153 if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
15154 #endif
15155 #ifdef O_ACCMODE
15156 if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
15157 #endif
15158 #ifdef O_EVTONLY
15159 if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
15160 #endif
15161 #ifdef O_FSYNC
15162 if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
15163 #endif
15164 #ifdef O_SYMLINK
15165 if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
15166 #endif
15167
15168 #ifdef SEEK_HOLE
15169 if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
15170 #endif
15171 #ifdef SEEK_DATA
15172 if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
15173 #endif
15174
15175 /* MS Windows */
15176 #ifdef O_NOINHERIT
15177 /* Don't inherit in child processes. */
15178 if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
15179 #endif
15180 #ifdef _O_SHORT_LIVED
15181 /* Optimize for short life (keep in memory). */
15182 /* MS forgot to define this one with a non-underscore form too. */
15183 if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
15184 #endif
15185 #ifdef O_TEMPORARY
15186 /* Automatically delete when last handle is closed. */
15187 if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
15188 #endif
15189 #ifdef O_RANDOM
15190 /* Optimize for random access. */
15191 if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
15192 #endif
15193 #ifdef O_SEQUENTIAL
15194 /* Optimize for sequential access. */
15195 if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
15196 #endif
15197
15198 /* GNU extensions. */
15199 #ifdef O_ASYNC
15200 /* Send a SIGIO signal whenever input or output
15201 becomes available on file descriptor */
15202 if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
15203 #endif
15204 #ifdef O_DIRECT
15205 /* Direct disk access. */
15206 if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
15207 #endif
15208 #ifdef O_DIRECTORY
15209 /* Must be a directory. */
15210 if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
15211 #endif
15212 #ifdef O_NOFOLLOW
15213 /* Do not follow links. */
15214 if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
15215 #endif
15216 #ifdef O_NOFOLLOW_ANY
15217 if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
15218 #endif
15219 #ifdef O_NOLINKS
15220 /* Fails if link count of the named file is greater than 1 */
15221 if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
15222 #endif
15223 #ifdef O_NOATIME
15224 /* Do not update the access time. */
15225 if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
15226 #endif
15227
15228 /* These come from sysexits.h */
15229 #ifdef EX_OK
15230 if (PyModule_AddIntMacro(m, EX_OK)) return -1;
15231 #endif /* EX_OK */
15232 #ifdef EX_USAGE
15233 if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
15234 #endif /* EX_USAGE */
15235 #ifdef EX_DATAERR
15236 if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
15237 #endif /* EX_DATAERR */
15238 #ifdef EX_NOINPUT
15239 if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
15240 #endif /* EX_NOINPUT */
15241 #ifdef EX_NOUSER
15242 if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
15243 #endif /* EX_NOUSER */
15244 #ifdef EX_NOHOST
15245 if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
15246 #endif /* EX_NOHOST */
15247 #ifdef EX_UNAVAILABLE
15248 if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
15249 #endif /* EX_UNAVAILABLE */
15250 #ifdef EX_SOFTWARE
15251 if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
15252 #endif /* EX_SOFTWARE */
15253 #ifdef EX_OSERR
15254 if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
15255 #endif /* EX_OSERR */
15256 #ifdef EX_OSFILE
15257 if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
15258 #endif /* EX_OSFILE */
15259 #ifdef EX_CANTCREAT
15260 if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
15261 #endif /* EX_CANTCREAT */
15262 #ifdef EX_IOERR
15263 if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
15264 #endif /* EX_IOERR */
15265 #ifdef EX_TEMPFAIL
15266 if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
15267 #endif /* EX_TEMPFAIL */
15268 #ifdef EX_PROTOCOL
15269 if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
15270 #endif /* EX_PROTOCOL */
15271 #ifdef EX_NOPERM
15272 if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
15273 #endif /* EX_NOPERM */
15274 #ifdef EX_CONFIG
15275 if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
15276 #endif /* EX_CONFIG */
15277 #ifdef EX_NOTFOUND
15278 if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
15279 #endif /* EX_NOTFOUND */
15280
15281 /* statvfs */
15282 #ifdef ST_RDONLY
15283 if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
15284 #endif /* ST_RDONLY */
15285 #ifdef ST_NOSUID
15286 if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
15287 #endif /* ST_NOSUID */
15288
15289 /* GNU extensions */
15290 #ifdef ST_NODEV
15291 if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
15292 #endif /* ST_NODEV */
15293 #ifdef ST_NOEXEC
15294 if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
15295 #endif /* ST_NOEXEC */
15296 #ifdef ST_SYNCHRONOUS
15297 if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
15298 #endif /* ST_SYNCHRONOUS */
15299 #ifdef ST_MANDLOCK
15300 if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
15301 #endif /* ST_MANDLOCK */
15302 #ifdef ST_WRITE
15303 if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
15304 #endif /* ST_WRITE */
15305 #ifdef ST_APPEND
15306 if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
15307 #endif /* ST_APPEND */
15308 #ifdef ST_NOATIME
15309 if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
15310 #endif /* ST_NOATIME */
15311 #ifdef ST_NODIRATIME
15312 if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
15313 #endif /* ST_NODIRATIME */
15314 #ifdef ST_RELATIME
15315 if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
15316 #endif /* ST_RELATIME */
15317
15318 /* FreeBSD sendfile() constants */
15319 #ifdef SF_NODISKIO
15320 if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
15321 #endif
15322 /* is obsolete since the 11.x release */
15323 #ifdef SF_MNOWAIT
15324 if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
15325 #endif
15326 #ifdef SF_SYNC
15327 if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
15328 #endif
15329 #ifdef SF_NOCACHE
15330 if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
15331 #endif
15332
15333 /* constants for posix_fadvise */
15334 #ifdef POSIX_FADV_NORMAL
15335 if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
15336 #endif
15337 #ifdef POSIX_FADV_SEQUENTIAL
15338 if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
15339 #endif
15340 #ifdef POSIX_FADV_RANDOM
15341 if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
15342 #endif
15343 #ifdef POSIX_FADV_NOREUSE
15344 if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
15345 #endif
15346 #ifdef POSIX_FADV_WILLNEED
15347 if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
15348 #endif
15349 #ifdef POSIX_FADV_DONTNEED
15350 if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
15351 #endif
15352
15353 /* constants for waitid */
15354 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
15355 if (PyModule_AddIntMacro(m, P_PID)) return -1;
15356 if (PyModule_AddIntMacro(m, P_PGID)) return -1;
15357 if (PyModule_AddIntMacro(m, P_ALL)) return -1;
15358 #ifdef P_PIDFD
15359 if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
15360 #endif
15361 #endif
15362 #ifdef WEXITED
15363 if (PyModule_AddIntMacro(m, WEXITED)) return -1;
15364 #endif
15365 #ifdef WNOWAIT
15366 if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
15367 #endif
15368 #ifdef WSTOPPED
15369 if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
15370 #endif
15371 #ifdef CLD_EXITED
15372 if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
15373 #endif
15374 #ifdef CLD_KILLED
15375 if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
15376 #endif
15377 #ifdef CLD_DUMPED
15378 if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
15379 #endif
15380 #ifdef CLD_TRAPPED
15381 if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
15382 #endif
15383 #ifdef CLD_STOPPED
15384 if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
15385 #endif
15386 #ifdef CLD_CONTINUED
15387 if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
15388 #endif
15389
15390 /* constants for lockf */
15391 #ifdef F_LOCK
15392 if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
15393 #endif
15394 #ifdef F_TLOCK
15395 if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
15396 #endif
15397 #ifdef F_ULOCK
15398 if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
15399 #endif
15400 #ifdef F_TEST
15401 if (PyModule_AddIntMacro(m, F_TEST)) return -1;
15402 #endif
15403
15404 #ifdef RWF_DSYNC
15405 if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
15406 #endif
15407 #ifdef RWF_HIPRI
15408 if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
15409 #endif
15410 #ifdef RWF_SYNC
15411 if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
15412 #endif
15413 #ifdef RWF_NOWAIT
15414 if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
15415 #endif
15416 #ifdef RWF_APPEND
15417 if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
15418 #endif
15419
15420 /* constants for splice */
15421 #if defined(HAVE_SPLICE) && defined(__linux__)
15422 if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
15423 if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
15424 if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
15425 #endif
15426
15427 /* constants for posix_spawn */
15428 #ifdef HAVE_POSIX_SPAWN
15429 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
15430 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
15431 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
15432 #endif
15433
15434 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
15435 if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
15436 if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
15437 if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
15438 #endif
15439 #ifdef HAVE_SPAWNV
15440 if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
15441 if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
15442 #endif
15443
15444 #ifdef HAVE_SCHED_H
15445 #ifdef SCHED_OTHER
15446 if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
15447 #endif
15448 #ifdef SCHED_FIFO
15449 if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
15450 #endif
15451 #ifdef SCHED_RR
15452 if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
15453 #endif
15454 #ifdef SCHED_SPORADIC
15455 if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
15456 #endif
15457 #ifdef SCHED_BATCH
15458 if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
15459 #endif
15460 #ifdef SCHED_IDLE
15461 if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
15462 #endif
15463 #ifdef SCHED_RESET_ON_FORK
15464 if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
15465 #endif
15466 #ifdef SCHED_SYS
15467 if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
15468 #endif
15469 #ifdef SCHED_IA
15470 if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
15471 #endif
15472 #ifdef SCHED_FSS
15473 if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
15474 #endif
15475 #ifdef SCHED_FX
15476 if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
15477 #endif
15478 #endif
15479
15480 #ifdef USE_XATTRS
15481 if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
15482 if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
15483 if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
15484 #endif
15485
15486 #if HAVE_DECL_RTLD_LAZY
15487 if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
15488 #endif
15489 #if HAVE_DECL_RTLD_NOW
15490 if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
15491 #endif
15492 #if HAVE_DECL_RTLD_GLOBAL
15493 if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
15494 #endif
15495 #if HAVE_DECL_RTLD_LOCAL
15496 if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
15497 #endif
15498 #if HAVE_DECL_RTLD_NODELETE
15499 if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
15500 #endif
15501 #if HAVE_DECL_RTLD_NOLOAD
15502 if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
15503 #endif
15504 #if HAVE_DECL_RTLD_DEEPBIND
15505 if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
15506 #endif
15507 #if HAVE_DECL_RTLD_MEMBER
15508 if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
15509 #endif
15510
15511 #ifdef HAVE_GETRANDOM_SYSCALL
15512 if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
15513 if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
15514 #endif
15515 #ifdef HAVE_MEMFD_CREATE
15516 if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
15517 if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
15518 #ifdef MFD_HUGETLB
15519 if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
15520 #endif
15521 #ifdef MFD_HUGE_SHIFT
15522 if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
15523 #endif
15524 #ifdef MFD_HUGE_MASK
15525 if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
15526 #endif
15527 #ifdef MFD_HUGE_64KB
15528 if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
15529 #endif
15530 #ifdef MFD_HUGE_512KB
15531 if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
15532 #endif
15533 #ifdef MFD_HUGE_1MB
15534 if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
15535 #endif
15536 #ifdef MFD_HUGE_2MB
15537 if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
15538 #endif
15539 #ifdef MFD_HUGE_8MB
15540 if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
15541 #endif
15542 #ifdef MFD_HUGE_16MB
15543 if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
15544 #endif
15545 #ifdef MFD_HUGE_32MB
15546 if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
15547 #endif
15548 #ifdef MFD_HUGE_256MB
15549 if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
15550 #endif
15551 #ifdef MFD_HUGE_512MB
15552 if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
15553 #endif
15554 #ifdef MFD_HUGE_1GB
15555 if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
15556 #endif
15557 #ifdef MFD_HUGE_2GB
15558 if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
15559 #endif
15560 #ifdef MFD_HUGE_16GB
15561 if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
15562 #endif
15563 #endif /* HAVE_MEMFD_CREATE */
15564
15565 #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15566 if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
15567 #ifdef EFD_NONBLOCK
15568 if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
15569 #endif
15570 #ifdef EFD_SEMAPHORE
15571 if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
15572 #endif
15573 #endif /* HAVE_EVENTFD && EFD_CLOEXEC */
15574
15575 #if defined(__APPLE__)
15576 if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
15577 if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
15578 if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
15579 if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
15580 #endif
15581
15582 #ifdef MS_WINDOWS
15583 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
15584 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
15585 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
15586 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
15587 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
15588 #endif
15589
15590 return 0;
15591 }
15592
15593
15594
15595 #define PROBE(name, test) \
15596 static int name(void) \
15597 { \
15598 if (test) { \
15599 return 1; \
15600 } else { \
15601 return 0; \
15602 } \
15603 }
15604
15605 #ifdef HAVE_FSTATAT
15606 PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
15607 #endif
15608
15609 #ifdef HAVE_FACCESSAT
15610 PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
15611 #endif
15612
15613 #ifdef HAVE_FCHMODAT
15614 PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
15615 #endif
15616
15617 #ifdef HAVE_FCHOWNAT
15618 PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
15619 #endif
15620
15621 #ifdef HAVE_LINKAT
15622 PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
15623 #endif
15624
15625 #ifdef HAVE_FDOPENDIR
15626 PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
15627 #endif
15628
15629 #ifdef HAVE_MKDIRAT
15630 PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
15631 #endif
15632
15633 #ifdef HAVE_MKFIFOAT
15634 PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
15635 #endif
15636
15637 #ifdef HAVE_MKNODAT
15638 PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
15639 #endif
15640
15641 #ifdef HAVE_RENAMEAT
15642 PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
15643 #endif
15644
15645 #ifdef HAVE_UNLINKAT
15646 PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
15647 #endif
15648
15649 #ifdef HAVE_OPENAT
15650 PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
15651 #endif
15652
15653 #ifdef HAVE_READLINKAT
15654 PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
15655 #endif
15656
15657 #ifdef HAVE_SYMLINKAT
15658 PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
15659 #endif
15660
15661 #ifdef HAVE_FUTIMENS
15662 PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
15663 #endif
15664
15665 #ifdef HAVE_UTIMENSAT
15666 PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
15667 #endif
15668
15669
15670
15671
15672 static const struct have_function {
15673 const char * const label;
15674 int (*probe)(void);
15675 } have_functions[] = {
15676
15677 #ifdef HAVE_EVENTFD
15678 {"HAVE_EVENTFD", NULL},
15679 #endif
15680
15681 #ifdef HAVE_FACCESSAT
15682 { "HAVE_FACCESSAT", probe_faccessat },
15683 #endif
15684
15685 #ifdef HAVE_FCHDIR
15686 { "HAVE_FCHDIR", NULL },
15687 #endif
15688
15689 #ifdef HAVE_FCHMOD
15690 { "HAVE_FCHMOD", NULL },
15691 #endif
15692
15693 #ifdef HAVE_FCHMODAT
15694 { "HAVE_FCHMODAT", probe_fchmodat },
15695 #endif
15696
15697 #ifdef HAVE_FCHOWN
15698 { "HAVE_FCHOWN", NULL },
15699 #endif
15700
15701 #ifdef HAVE_FCHOWNAT
15702 { "HAVE_FCHOWNAT", probe_fchownat },
15703 #endif
15704
15705 #ifdef HAVE_FEXECVE
15706 { "HAVE_FEXECVE", NULL },
15707 #endif
15708
15709 #ifdef HAVE_FDOPENDIR
15710 { "HAVE_FDOPENDIR", probe_fdopendir },
15711 #endif
15712
15713 #ifdef HAVE_FPATHCONF
15714 { "HAVE_FPATHCONF", NULL },
15715 #endif
15716
15717 #ifdef HAVE_FSTATAT
15718 { "HAVE_FSTATAT", probe_fstatat },
15719 #endif
15720
15721 #ifdef HAVE_FSTATVFS
15722 { "HAVE_FSTATVFS", NULL },
15723 #endif
15724
15725 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
15726 { "HAVE_FTRUNCATE", NULL },
15727 #endif
15728
15729 #ifdef HAVE_FUTIMENS
15730 { "HAVE_FUTIMENS", probe_futimens },
15731 #endif
15732
15733 #ifdef HAVE_FUTIMES
15734 { "HAVE_FUTIMES", NULL },
15735 #endif
15736
15737 #ifdef HAVE_FUTIMESAT
15738 { "HAVE_FUTIMESAT", NULL },
15739 #endif
15740
15741 #ifdef HAVE_LINKAT
15742 { "HAVE_LINKAT", probe_linkat },
15743 #endif
15744
15745 #ifdef HAVE_LCHFLAGS
15746 { "HAVE_LCHFLAGS", NULL },
15747 #endif
15748
15749 #ifdef HAVE_LCHMOD
15750 { "HAVE_LCHMOD", NULL },
15751 #endif
15752
15753 #ifdef HAVE_LCHOWN
15754 { "HAVE_LCHOWN", NULL },
15755 #endif
15756
15757 #ifdef HAVE_LSTAT
15758 { "HAVE_LSTAT", NULL },
15759 #endif
15760
15761 #ifdef HAVE_LUTIMES
15762 { "HAVE_LUTIMES", NULL },
15763 #endif
15764
15765 #ifdef HAVE_MEMFD_CREATE
15766 { "HAVE_MEMFD_CREATE", NULL },
15767 #endif
15768
15769 #ifdef HAVE_MKDIRAT
15770 { "HAVE_MKDIRAT", probe_mkdirat },
15771 #endif
15772
15773 #ifdef HAVE_MKFIFOAT
15774 { "HAVE_MKFIFOAT", probe_mkfifoat },
15775 #endif
15776
15777 #ifdef HAVE_MKNODAT
15778 { "HAVE_MKNODAT", probe_mknodat },
15779 #endif
15780
15781 #ifdef HAVE_OPENAT
15782 { "HAVE_OPENAT", probe_openat },
15783 #endif
15784
15785 #ifdef HAVE_READLINKAT
15786 { "HAVE_READLINKAT", probe_readlinkat },
15787 #endif
15788
15789 #ifdef HAVE_RENAMEAT
15790 { "HAVE_RENAMEAT", probe_renameat },
15791 #endif
15792
15793 #ifdef HAVE_SYMLINKAT
15794 { "HAVE_SYMLINKAT", probe_symlinkat },
15795 #endif
15796
15797 #ifdef HAVE_UNLINKAT
15798 { "HAVE_UNLINKAT", probe_unlinkat },
15799 #endif
15800
15801 #ifdef HAVE_UTIMENSAT
15802 { "HAVE_UTIMENSAT", probe_utimensat },
15803 #endif
15804
15805 #ifdef MS_WINDOWS
15806 { "MS_WINDOWS", NULL },
15807 #endif
15808
15809 { NULL, NULL }
15810 };
15811
15812
15813 static int
posixmodule_exec(PyObject * m)15814 posixmodule_exec(PyObject *m)
15815 {
15816 _posixstate *state = get_posix_state(m);
15817
15818 #if defined(HAVE_PWRITEV)
15819 if (HAVE_PWRITEV_RUNTIME) {} else {
15820 PyObject* dct = PyModule_GetDict(m);
15821
15822 if (dct == NULL) {
15823 return -1;
15824 }
15825
15826 if (PyDict_DelItemString(dct, "pwritev") == -1) {
15827 PyErr_Clear();
15828 }
15829 if (PyDict_DelItemString(dct, "preadv") == -1) {
15830 PyErr_Clear();
15831 }
15832 }
15833 #endif
15834
15835 /* Initialize environ dictionary */
15836 PyObject *v = convertenviron();
15837 Py_XINCREF(v);
15838 if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
15839 return -1;
15840 Py_DECREF(v);
15841
15842 if (all_ins(m))
15843 return -1;
15844
15845 if (setup_confname_tables(m))
15846 return -1;
15847
15848 Py_INCREF(PyExc_OSError);
15849 PyModule_AddObject(m, "error", PyExc_OSError);
15850
15851 #if defined(HAVE_WAITID) && !defined(__APPLE__)
15852 waitid_result_desc.name = MODNAME ".waitid_result";
15853 PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
15854 if (WaitidResultType == NULL) {
15855 return -1;
15856 }
15857 Py_INCREF(WaitidResultType);
15858 PyModule_AddObject(m, "waitid_result", WaitidResultType);
15859 state->WaitidResultType = WaitidResultType;
15860 #endif
15861
15862 stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
15863 stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
15864 stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
15865 stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
15866 PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
15867 if (StatResultType == NULL) {
15868 return -1;
15869 }
15870 Py_INCREF(StatResultType);
15871 PyModule_AddObject(m, "stat_result", StatResultType);
15872 state->StatResultType = StatResultType;
15873 structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15874 ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
15875
15876 statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
15877 PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
15878 if (StatVFSResultType == NULL) {
15879 return -1;
15880 }
15881 Py_INCREF(StatVFSResultType);
15882 PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
15883 state->StatVFSResultType = StatVFSResultType;
15884 #ifdef NEED_TICKS_PER_SECOND
15885 # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15886 ticks_per_second = sysconf(_SC_CLK_TCK);
15887 # elif defined(HZ)
15888 ticks_per_second = HZ;
15889 # else
15890 ticks_per_second = 60; /* magic fallback value; may be bogus */
15891 # endif
15892 #endif
15893
15894 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
15895 sched_param_desc.name = MODNAME ".sched_param";
15896 PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
15897 if (SchedParamType == NULL) {
15898 return -1;
15899 }
15900 Py_INCREF(SchedParamType);
15901 PyModule_AddObject(m, "sched_param", SchedParamType);
15902 state->SchedParamType = SchedParamType;
15903 ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
15904 #endif
15905
15906 /* initialize TerminalSize_info */
15907 PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
15908 if (TerminalSizeType == NULL) {
15909 return -1;
15910 }
15911 Py_INCREF(TerminalSizeType);
15912 PyModule_AddObject(m, "terminal_size", TerminalSizeType);
15913 state->TerminalSizeType = TerminalSizeType;
15914
15915 /* initialize scandir types */
15916 PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
15917 if (ScandirIteratorType == NULL) {
15918 return -1;
15919 }
15920 state->ScandirIteratorType = ScandirIteratorType;
15921
15922 PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
15923 if (DirEntryType == NULL) {
15924 return -1;
15925 }
15926 Py_INCREF(DirEntryType);
15927 PyModule_AddObject(m, "DirEntry", DirEntryType);
15928 state->DirEntryType = DirEntryType;
15929
15930 times_result_desc.name = MODNAME ".times_result";
15931 PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(×_result_desc);
15932 if (TimesResultType == NULL) {
15933 return -1;
15934 }
15935 Py_INCREF(TimesResultType);
15936 PyModule_AddObject(m, "times_result", TimesResultType);
15937 state->TimesResultType = TimesResultType;
15938
15939 PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
15940 if (UnameResultType == NULL) {
15941 return -1;
15942 }
15943 Py_INCREF(UnameResultType);
15944 PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
15945 state->UnameResultType = (PyObject *)UnameResultType;
15946
15947 if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
15948 return -1;
15949 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
15950 state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
15951 if (state->struct_rusage == NULL)
15952 return -1;
15953 #endif
15954 state->st_mode = PyUnicode_InternFromString("st_mode");
15955 if (state->st_mode == NULL)
15956 return -1;
15957
15958 /* suppress "function not used" warnings */
15959 {
15960 int ignored;
15961 fd_specified("", -1);
15962 follow_symlinks_specified("", 1);
15963 dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
15964 dir_fd_converter(Py_None, &ignored);
15965 dir_fd_unavailable(Py_None, &ignored);
15966 }
15967
15968 /*
15969 * provide list of locally available functions
15970 * so os.py can populate support_* lists
15971 */
15972 PyObject *list = PyList_New(0);
15973 if (!list) {
15974 return -1;
15975 }
15976 for (const struct have_function *trace = have_functions; trace->label; trace++) {
15977 PyObject *unicode;
15978 if (trace->probe && !trace->probe()) continue;
15979 unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
15980 if (!unicode)
15981 return -1;
15982 if (PyList_Append(list, unicode))
15983 return -1;
15984 Py_DECREF(unicode);
15985 }
15986
15987 PyModule_AddObject(m, "_have_functions", list);
15988
15989 return 0;
15990 }
15991
15992
15993 static PyModuleDef_Slot posixmodile_slots[] = {
15994 {Py_mod_exec, posixmodule_exec},
15995 {0, NULL}
15996 };
15997
15998 static struct PyModuleDef posixmodule = {
15999 PyModuleDef_HEAD_INIT,
16000 .m_name = MODNAME,
16001 .m_doc = posix__doc__,
16002 .m_size = sizeof(_posixstate),
16003 .m_methods = posix_methods,
16004 .m_slots = posixmodile_slots,
16005 .m_traverse = _posix_traverse,
16006 .m_clear = _posix_clear,
16007 .m_free = _posix_free,
16008 };
16009
16010 PyMODINIT_FUNC
INITFUNC(void)16011 INITFUNC(void)
16012 {
16013 return PyModuleDef_Init(&posixmodule);
16014 }
16015
16016 #ifdef __cplusplus
16017 }
16018 #endif
16019