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 Py_ssize_t norm_len;
4556 wchar_t *norm_path = _Py_normpath_and_size(buffer, len, &norm_len);
4557 PyObject *result = PyUnicode_FromWideChar(norm_path, norm_len);
4558 PyMem_Free(buffer);
4559 return result;
4560 }
4561
4562 /*[clinic input]
4563 os.mkdir
4564
4565 path : path_t
4566
4567 mode: int = 0o777
4568
4569 *
4570
4571 dir_fd : dir_fd(requires='mkdirat') = None
4572
4573 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4574
4575 Create a directory.
4576
4577 If dir_fd is not None, it should be a file descriptor open to a directory,
4578 and path should be relative; path will then be relative to that directory.
4579 dir_fd may not be implemented on your platform.
4580 If it is unavailable, using it will raise a NotImplementedError.
4581
4582 The mode argument is ignored on Windows. Where it is used, the current umask
4583 value is first masked out.
4584 [clinic start generated code]*/
4585
4586 static PyObject *
os_mkdir_impl(PyObject * module,path_t * path,int mode,int dir_fd)4587 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4588 /*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
4589 {
4590 int result;
4591 #ifdef HAVE_MKDIRAT
4592 int mkdirat_unavailable = 0;
4593 #endif
4594
4595 if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4596 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4597 return NULL;
4598 }
4599
4600 #ifdef MS_WINDOWS
4601 Py_BEGIN_ALLOW_THREADS
4602 result = CreateDirectoryW(path->wide, NULL);
4603 Py_END_ALLOW_THREADS
4604
4605 if (!result)
4606 return path_error(path);
4607 #else
4608 Py_BEGIN_ALLOW_THREADS
4609 #if HAVE_MKDIRAT
4610 if (dir_fd != DEFAULT_DIR_FD) {
4611 if (HAVE_MKDIRAT_RUNTIME) {
4612 result = mkdirat(dir_fd, path->narrow, mode);
4613
4614 } else {
4615 mkdirat_unavailable = 1;
4616 }
4617 } else
4618 #endif
4619 #if defined(__WATCOMC__) && !defined(__QNX__)
4620 result = mkdir(path->narrow);
4621 #else
4622 result = mkdir(path->narrow, mode);
4623 #endif
4624 Py_END_ALLOW_THREADS
4625
4626 #if HAVE_MKDIRAT
4627 if (mkdirat_unavailable) {
4628 argument_unavailable_error(NULL, "dir_fd");
4629 return NULL;
4630 }
4631 #endif
4632
4633 if (result < 0)
4634 return path_error(path);
4635 #endif /* MS_WINDOWS */
4636 Py_RETURN_NONE;
4637 }
4638
4639
4640 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4641 #if defined(HAVE_SYS_RESOURCE_H)
4642 #include <sys/resource.h>
4643 #endif
4644
4645
4646 #ifdef HAVE_NICE
4647 /*[clinic input]
4648 os.nice
4649
4650 increment: int
4651 /
4652
4653 Add increment to the priority of process and return the new priority.
4654 [clinic start generated code]*/
4655
4656 static PyObject *
os_nice_impl(PyObject * module,int increment)4657 os_nice_impl(PyObject *module, int increment)
4658 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4659 {
4660 int value;
4661
4662 /* There are two flavours of 'nice': one that returns the new
4663 priority (as required by almost all standards out there) and the
4664 Linux/FreeBSD one, which returns '0' on success and advices
4665 the use of getpriority() to get the new priority.
4666
4667 If we are of the nice family that returns the new priority, we
4668 need to clear errno before the call, and check if errno is filled
4669 before calling posix_error() on a returnvalue of -1, because the
4670 -1 may be the actual new priority! */
4671
4672 errno = 0;
4673 value = nice(increment);
4674 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4675 if (value == 0)
4676 value = getpriority(PRIO_PROCESS, 0);
4677 #endif
4678 if (value == -1 && errno != 0)
4679 /* either nice() or getpriority() returned an error */
4680 return posix_error();
4681 return PyLong_FromLong((long) value);
4682 }
4683 #endif /* HAVE_NICE */
4684
4685
4686 #ifdef HAVE_GETPRIORITY
4687 /*[clinic input]
4688 os.getpriority
4689
4690 which: int
4691 who: int
4692
4693 Return program scheduling priority.
4694 [clinic start generated code]*/
4695
4696 static PyObject *
os_getpriority_impl(PyObject * module,int which,int who)4697 os_getpriority_impl(PyObject *module, int which, int who)
4698 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4699 {
4700 int retval;
4701
4702 errno = 0;
4703 retval = getpriority(which, who);
4704 if (errno != 0)
4705 return posix_error();
4706 return PyLong_FromLong((long)retval);
4707 }
4708 #endif /* HAVE_GETPRIORITY */
4709
4710
4711 #ifdef HAVE_SETPRIORITY
4712 /*[clinic input]
4713 os.setpriority
4714
4715 which: int
4716 who: int
4717 priority: int
4718
4719 Set program scheduling priority.
4720 [clinic start generated code]*/
4721
4722 static PyObject *
os_setpriority_impl(PyObject * module,int which,int who,int priority)4723 os_setpriority_impl(PyObject *module, int which, int who, int priority)
4724 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4725 {
4726 int retval;
4727
4728 retval = setpriority(which, who, priority);
4729 if (retval == -1)
4730 return posix_error();
4731 Py_RETURN_NONE;
4732 }
4733 #endif /* HAVE_SETPRIORITY */
4734
4735
4736 static PyObject *
internal_rename(path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int is_replace)4737 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4738 {
4739 const char *function_name = is_replace ? "replace" : "rename";
4740 int dir_fd_specified;
4741
4742 #ifdef HAVE_RENAMEAT
4743 int renameat_unavailable = 0;
4744 #endif
4745
4746 #ifdef MS_WINDOWS
4747 BOOL result;
4748 int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4749 #else
4750 int result;
4751 #endif
4752
4753 dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4754 (dst_dir_fd != DEFAULT_DIR_FD);
4755 #ifndef HAVE_RENAMEAT
4756 if (dir_fd_specified) {
4757 argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4758 return NULL;
4759 }
4760 #endif
4761
4762 if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
4763 src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4764 dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4765 return NULL;
4766 }
4767
4768 #ifdef MS_WINDOWS
4769 Py_BEGIN_ALLOW_THREADS
4770 result = MoveFileExW(src->wide, dst->wide, flags);
4771 Py_END_ALLOW_THREADS
4772
4773 if (!result)
4774 return path_error2(src, dst);
4775
4776 #else
4777 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4778 PyErr_Format(PyExc_ValueError,
4779 "%s: src and dst must be the same type", function_name);
4780 return NULL;
4781 }
4782
4783 Py_BEGIN_ALLOW_THREADS
4784 #ifdef HAVE_RENAMEAT
4785 if (dir_fd_specified) {
4786 if (HAVE_RENAMEAT_RUNTIME) {
4787 result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4788 } else {
4789 renameat_unavailable = 1;
4790 }
4791 } else
4792 #endif
4793 result = rename(src->narrow, dst->narrow);
4794 Py_END_ALLOW_THREADS
4795
4796
4797 #ifdef HAVE_RENAMEAT
4798 if (renameat_unavailable) {
4799 argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4800 return NULL;
4801 }
4802 #endif
4803
4804 if (result)
4805 return path_error2(src, dst);
4806 #endif
4807 Py_RETURN_NONE;
4808 }
4809
4810
4811 /*[clinic input]
4812 os.rename
4813
4814 src : path_t
4815 dst : path_t
4816 *
4817 src_dir_fd : dir_fd = None
4818 dst_dir_fd : dir_fd = None
4819
4820 Rename a file or directory.
4821
4822 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4823 descriptor open to a directory, and the respective path string (src or dst)
4824 should be relative; the path will then be relative to that directory.
4825 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4826 If they are unavailable, using them will raise a NotImplementedError.
4827 [clinic start generated code]*/
4828
4829 static PyObject *
os_rename_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4830 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4831 int dst_dir_fd)
4832 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4833 {
4834 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4835 }
4836
4837
4838 /*[clinic input]
4839 os.replace = os.rename
4840
4841 Rename a file or directory, overwriting the destination.
4842
4843 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4844 descriptor open to a directory, and the respective path string (src or dst)
4845 should be relative; the path will then be relative to that directory.
4846 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4847 If they are unavailable, using them will raise a NotImplementedError.
4848 [clinic start generated code]*/
4849
4850 static PyObject *
os_replace_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4851 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4852 int dst_dir_fd)
4853 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4854 {
4855 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4856 }
4857
4858
4859 /*[clinic input]
4860 os.rmdir
4861
4862 path: path_t
4863 *
4864 dir_fd: dir_fd(requires='unlinkat') = None
4865
4866 Remove a directory.
4867
4868 If dir_fd is not None, it should be a file descriptor open to a directory,
4869 and path should be relative; path will then be relative to that directory.
4870 dir_fd may not be implemented on your platform.
4871 If it is unavailable, using it will raise a NotImplementedError.
4872 [clinic start generated code]*/
4873
4874 static PyObject *
os_rmdir_impl(PyObject * module,path_t * path,int dir_fd)4875 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4876 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4877 {
4878 int result;
4879 #ifdef HAVE_UNLINKAT
4880 int unlinkat_unavailable = 0;
4881 #endif
4882
4883 if (PySys_Audit("os.rmdir", "Oi", path->object,
4884 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4885 return NULL;
4886 }
4887
4888 Py_BEGIN_ALLOW_THREADS
4889 #ifdef MS_WINDOWS
4890 /* Windows, success=1, UNIX, success=0 */
4891 result = !RemoveDirectoryW(path->wide);
4892 #else
4893 #ifdef HAVE_UNLINKAT
4894 if (dir_fd != DEFAULT_DIR_FD) {
4895 if (HAVE_UNLINKAT_RUNTIME) {
4896 result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4897 } else {
4898 unlinkat_unavailable = 1;
4899 result = -1;
4900 }
4901 } else
4902 #endif
4903 result = rmdir(path->narrow);
4904 #endif
4905 Py_END_ALLOW_THREADS
4906
4907 #ifdef HAVE_UNLINKAT
4908 if (unlinkat_unavailable) {
4909 argument_unavailable_error("rmdir", "dir_fd");
4910 return NULL;
4911 }
4912 #endif
4913
4914 if (result)
4915 return path_error(path);
4916
4917 Py_RETURN_NONE;
4918 }
4919
4920
4921 #ifdef HAVE_SYSTEM
4922 #ifdef MS_WINDOWS
4923 /*[clinic input]
4924 os.system -> long
4925
4926 command: Py_UNICODE
4927
4928 Execute the command in a subshell.
4929 [clinic start generated code]*/
4930
4931 static long
os_system_impl(PyObject * module,const Py_UNICODE * command)4932 os_system_impl(PyObject *module, const Py_UNICODE *command)
4933 /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4934 {
4935 long result;
4936
4937 if (PySys_Audit("os.system", "(u)", command) < 0) {
4938 return -1;
4939 }
4940
4941 Py_BEGIN_ALLOW_THREADS
4942 _Py_BEGIN_SUPPRESS_IPH
4943 result = _wsystem(command);
4944 _Py_END_SUPPRESS_IPH
4945 Py_END_ALLOW_THREADS
4946 return result;
4947 }
4948 #else /* MS_WINDOWS */
4949 /*[clinic input]
4950 os.system -> long
4951
4952 command: FSConverter
4953
4954 Execute the command in a subshell.
4955 [clinic start generated code]*/
4956
4957 static long
os_system_impl(PyObject * module,PyObject * command)4958 os_system_impl(PyObject *module, PyObject *command)
4959 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4960 {
4961 long result;
4962 const char *bytes = PyBytes_AsString(command);
4963
4964 if (PySys_Audit("os.system", "(O)", command) < 0) {
4965 return -1;
4966 }
4967
4968 Py_BEGIN_ALLOW_THREADS
4969 result = system(bytes);
4970 Py_END_ALLOW_THREADS
4971 return result;
4972 }
4973 #endif
4974 #endif /* HAVE_SYSTEM */
4975
4976
4977 #ifdef HAVE_UMASK
4978 /*[clinic input]
4979 os.umask
4980
4981 mask: int
4982 /
4983
4984 Set the current numeric umask and return the previous umask.
4985 [clinic start generated code]*/
4986
4987 static PyObject *
os_umask_impl(PyObject * module,int mask)4988 os_umask_impl(PyObject *module, int mask)
4989 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4990 {
4991 int i = (int)umask(mask);
4992 if (i < 0)
4993 return posix_error();
4994 return PyLong_FromLong((long)i);
4995 }
4996 #endif
4997
4998 #ifdef MS_WINDOWS
4999
5000 /* override the default DeleteFileW behavior so that directory
5001 symlinks can be removed with this function, the same as with
5002 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)5003 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
5004 {
5005 WIN32_FILE_ATTRIBUTE_DATA info;
5006 WIN32_FIND_DATAW find_data;
5007 HANDLE find_data_handle;
5008 int is_directory = 0;
5009 int is_link = 0;
5010
5011 if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
5012 is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
5013
5014 /* Get WIN32_FIND_DATA structure for the path to determine if
5015 it is a symlink */
5016 if(is_directory &&
5017 info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
5018 find_data_handle = FindFirstFileW(lpFileName, &find_data);
5019
5020 if(find_data_handle != INVALID_HANDLE_VALUE) {
5021 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
5022 IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
5023 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
5024 find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
5025 FindClose(find_data_handle);
5026 }
5027 }
5028 }
5029
5030 if (is_directory && is_link)
5031 return RemoveDirectoryW(lpFileName);
5032
5033 return DeleteFileW(lpFileName);
5034 }
5035 #endif /* MS_WINDOWS */
5036
5037
5038 /*[clinic input]
5039 os.unlink
5040
5041 path: path_t
5042 *
5043 dir_fd: dir_fd(requires='unlinkat')=None
5044
5045 Remove a file (same as remove()).
5046
5047 If dir_fd is not None, it should be a file descriptor open to a directory,
5048 and path should be relative; path will then be relative to that directory.
5049 dir_fd may not be implemented on your platform.
5050 If it is unavailable, using it will raise a NotImplementedError.
5051
5052 [clinic start generated code]*/
5053
5054 static PyObject *
os_unlink_impl(PyObject * module,path_t * path,int dir_fd)5055 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
5056 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
5057 {
5058 int result;
5059 #ifdef HAVE_UNLINKAT
5060 int unlinkat_unavailable = 0;
5061 #endif
5062
5063 if (PySys_Audit("os.remove", "Oi", path->object,
5064 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5065 return NULL;
5066 }
5067
5068 Py_BEGIN_ALLOW_THREADS
5069 _Py_BEGIN_SUPPRESS_IPH
5070 #ifdef MS_WINDOWS
5071 /* Windows, success=1, UNIX, success=0 */
5072 result = !Py_DeleteFileW(path->wide);
5073 #else
5074 #ifdef HAVE_UNLINKAT
5075 if (dir_fd != DEFAULT_DIR_FD) {
5076 if (HAVE_UNLINKAT_RUNTIME) {
5077
5078 result = unlinkat(dir_fd, path->narrow, 0);
5079 } else {
5080 unlinkat_unavailable = 1;
5081 }
5082 } else
5083 #endif /* HAVE_UNLINKAT */
5084 result = unlink(path->narrow);
5085 #endif
5086 _Py_END_SUPPRESS_IPH
5087 Py_END_ALLOW_THREADS
5088
5089 #ifdef HAVE_UNLINKAT
5090 if (unlinkat_unavailable) {
5091 argument_unavailable_error(NULL, "dir_fd");
5092 return NULL;
5093 }
5094 #endif
5095
5096 if (result)
5097 return path_error(path);
5098
5099 Py_RETURN_NONE;
5100 }
5101
5102
5103 /*[clinic input]
5104 os.remove = os.unlink
5105
5106 Remove a file (same as unlink()).
5107
5108 If dir_fd is not None, it should be a file descriptor open to a directory,
5109 and path should be relative; path will then be relative to that directory.
5110 dir_fd may not be implemented on your platform.
5111 If it is unavailable, using it will raise a NotImplementedError.
5112 [clinic start generated code]*/
5113
5114 static PyObject *
os_remove_impl(PyObject * module,path_t * path,int dir_fd)5115 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
5116 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
5117 {
5118 return os_unlink_impl(module, path, dir_fd);
5119 }
5120
5121
5122 static PyStructSequence_Field uname_result_fields[] = {
5123 {"sysname", "operating system name"},
5124 {"nodename", "name of machine on network (implementation-defined)"},
5125 {"release", "operating system release"},
5126 {"version", "operating system version"},
5127 {"machine", "hardware identifier"},
5128 {NULL}
5129 };
5130
5131 PyDoc_STRVAR(uname_result__doc__,
5132 "uname_result: Result from os.uname().\n\n\
5133 This object may be accessed either as a tuple of\n\
5134 (sysname, nodename, release, version, machine),\n\
5135 or via the attributes sysname, nodename, release, version, and machine.\n\
5136 \n\
5137 See os.uname for more information.");
5138
5139 static PyStructSequence_Desc uname_result_desc = {
5140 MODNAME ".uname_result", /* name */
5141 uname_result__doc__, /* doc */
5142 uname_result_fields,
5143 5
5144 };
5145
5146 #ifdef HAVE_UNAME
5147 /*[clinic input]
5148 os.uname
5149
5150 Return an object identifying the current operating system.
5151
5152 The object behaves like a named tuple with the following fields:
5153 (sysname, nodename, release, version, machine)
5154
5155 [clinic start generated code]*/
5156
5157 static PyObject *
os_uname_impl(PyObject * module)5158 os_uname_impl(PyObject *module)
5159 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
5160 {
5161 struct utsname u;
5162 int res;
5163 PyObject *value;
5164
5165 Py_BEGIN_ALLOW_THREADS
5166 res = uname(&u);
5167 Py_END_ALLOW_THREADS
5168 if (res < 0)
5169 return posix_error();
5170
5171 PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
5172 value = PyStructSequence_New((PyTypeObject *)UnameResultType);
5173 if (value == NULL)
5174 return NULL;
5175
5176 #define SET(i, field) \
5177 { \
5178 PyObject *o = PyUnicode_DecodeFSDefault(field); \
5179 if (!o) { \
5180 Py_DECREF(value); \
5181 return NULL; \
5182 } \
5183 PyStructSequence_SET_ITEM(value, i, o); \
5184 } \
5185
5186 SET(0, u.sysname);
5187 SET(1, u.nodename);
5188 SET(2, u.release);
5189 SET(3, u.version);
5190 SET(4, u.machine);
5191
5192 #undef SET
5193
5194 return value;
5195 }
5196 #endif /* HAVE_UNAME */
5197
5198
5199
5200 typedef struct {
5201 int now;
5202 time_t atime_s;
5203 long atime_ns;
5204 time_t mtime_s;
5205 long mtime_ns;
5206 } utime_t;
5207
5208 /*
5209 * these macros assume that "ut" is a pointer to a utime_t
5210 * they also intentionally leak the declaration of a pointer named "time"
5211 */
5212 #define UTIME_TO_TIMESPEC \
5213 struct timespec ts[2]; \
5214 struct timespec *time; \
5215 if (ut->now) \
5216 time = NULL; \
5217 else { \
5218 ts[0].tv_sec = ut->atime_s; \
5219 ts[0].tv_nsec = ut->atime_ns; \
5220 ts[1].tv_sec = ut->mtime_s; \
5221 ts[1].tv_nsec = ut->mtime_ns; \
5222 time = ts; \
5223 } \
5224
5225 #define UTIME_TO_TIMEVAL \
5226 struct timeval tv[2]; \
5227 struct timeval *time; \
5228 if (ut->now) \
5229 time = NULL; \
5230 else { \
5231 tv[0].tv_sec = ut->atime_s; \
5232 tv[0].tv_usec = ut->atime_ns / 1000; \
5233 tv[1].tv_sec = ut->mtime_s; \
5234 tv[1].tv_usec = ut->mtime_ns / 1000; \
5235 time = tv; \
5236 } \
5237
5238 #define UTIME_TO_UTIMBUF \
5239 struct utimbuf u; \
5240 struct utimbuf *time; \
5241 if (ut->now) \
5242 time = NULL; \
5243 else { \
5244 u.actime = ut->atime_s; \
5245 u.modtime = ut->mtime_s; \
5246 time = &u; \
5247 }
5248
5249 #define UTIME_TO_TIME_T \
5250 time_t timet[2]; \
5251 time_t *time; \
5252 if (ut->now) \
5253 time = NULL; \
5254 else { \
5255 timet[0] = ut->atime_s; \
5256 timet[1] = ut->mtime_s; \
5257 time = timet; \
5258 } \
5259
5260
5261 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5262
5263 static int
utime_dir_fd(utime_t * ut,int dir_fd,const char * path,int follow_symlinks)5264 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
5265 {
5266 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5267 if (HAVE_UTIMENSAT_RUNTIME) {
5268 int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5269 UTIME_TO_TIMESPEC;
5270 return utimensat(dir_fd, path, time, flags);
5271 } else {
5272 errno = ENOSYS;
5273 return -1;
5274 }
5275 #elif defined(HAVE_UTIMENSAT)
5276 int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5277 UTIME_TO_TIMESPEC;
5278 return utimensat(dir_fd, path, time, flags);
5279 #elif defined(HAVE_FUTIMESAT)
5280 UTIME_TO_TIMEVAL;
5281 /*
5282 * follow_symlinks will never be false here;
5283 * we only allow !follow_symlinks and dir_fd together
5284 * if we have utimensat()
5285 */
5286 assert(follow_symlinks);
5287 return futimesat(dir_fd, path, time);
5288 #endif
5289 }
5290
5291 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
5292 #else
5293 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
5294 #endif
5295
5296 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5297
5298 static int
utime_fd(utime_t * ut,int fd)5299 utime_fd(utime_t *ut, int fd)
5300 {
5301 #ifdef HAVE_FUTIMENS
5302
5303 if (HAVE_FUTIMENS_RUNTIME) {
5304
5305 UTIME_TO_TIMESPEC;
5306 return futimens(fd, time);
5307
5308 } else
5309 #ifndef HAVE_FUTIMES
5310 {
5311 /* Not sure if this can happen */
5312 PyErr_SetString(
5313 PyExc_RuntimeError,
5314 "neither futimens nor futimes are supported"
5315 " on this system");
5316 return -1;
5317 }
5318 #endif
5319
5320 #endif
5321 #ifdef HAVE_FUTIMES
5322 {
5323 UTIME_TO_TIMEVAL;
5324 return futimes(fd, time);
5325 }
5326 #endif
5327 }
5328
5329 #define PATH_UTIME_HAVE_FD 1
5330 #else
5331 #define PATH_UTIME_HAVE_FD 0
5332 #endif
5333
5334 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
5335 # define UTIME_HAVE_NOFOLLOW_SYMLINKS
5336 #endif
5337
5338 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5339
5340 static int
utime_nofollow_symlinks(utime_t * ut,const char * path)5341 utime_nofollow_symlinks(utime_t *ut, const char *path)
5342 {
5343 #ifdef HAVE_UTIMENSAT
5344 if (HAVE_UTIMENSAT_RUNTIME) {
5345 UTIME_TO_TIMESPEC;
5346 return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
5347 } else
5348 #ifndef HAVE_LUTIMES
5349 {
5350 /* Not sure if this can happen */
5351 PyErr_SetString(
5352 PyExc_RuntimeError,
5353 "neither utimensat nor lutimes are supported"
5354 " on this system");
5355 return -1;
5356 }
5357 #endif
5358 #endif
5359
5360 #ifdef HAVE_LUTIMES
5361 {
5362 UTIME_TO_TIMEVAL;
5363 return lutimes(path, time);
5364 }
5365 #endif
5366 }
5367
5368 #endif
5369
5370 #ifndef MS_WINDOWS
5371
5372 static int
utime_default(utime_t * ut,const char * path)5373 utime_default(utime_t *ut, const char *path)
5374 {
5375 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5376 if (HAVE_UTIMENSAT_RUNTIME) {
5377 UTIME_TO_TIMESPEC;
5378 return utimensat(DEFAULT_DIR_FD, path, time, 0);
5379 } else {
5380 UTIME_TO_TIMEVAL;
5381 return utimes(path, time);
5382 }
5383 #elif defined(HAVE_UTIMENSAT)
5384 UTIME_TO_TIMESPEC;
5385 return utimensat(DEFAULT_DIR_FD, path, time, 0);
5386 #elif defined(HAVE_UTIMES)
5387 UTIME_TO_TIMEVAL;
5388 return utimes(path, time);
5389 #elif defined(HAVE_UTIME_H)
5390 UTIME_TO_UTIMBUF;
5391 return utime(path, time);
5392 #else
5393 UTIME_TO_TIME_T;
5394 return utime(path, time);
5395 #endif
5396 }
5397
5398 #endif
5399
5400 static int
split_py_long_to_s_and_ns(PyObject * module,PyObject * py_long,time_t * s,long * ns)5401 split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5402 {
5403 int result = 0;
5404 PyObject *divmod;
5405 divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5406 if (!divmod)
5407 goto exit;
5408 if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
5409 PyErr_Format(PyExc_TypeError,
5410 "%.200s.__divmod__() must return a 2-tuple, not %.200s",
5411 _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
5412 goto exit;
5413 }
5414 *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5415 if ((*s == -1) && PyErr_Occurred())
5416 goto exit;
5417 *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5418 if ((*ns == -1) && PyErr_Occurred())
5419 goto exit;
5420
5421 result = 1;
5422 exit:
5423 Py_XDECREF(divmod);
5424 return result;
5425 }
5426
5427
5428 /*[clinic input]
5429 os.utime
5430
5431 path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
5432 times: object = None
5433 *
5434 ns: object = NULL
5435 dir_fd: dir_fd(requires='futimensat') = None
5436 follow_symlinks: bool=True
5437
5438 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
5439
5440 Set the access and modified time of path.
5441
5442 path may always be specified as a string.
5443 On some platforms, path may also be specified as an open file descriptor.
5444 If this functionality is unavailable, using it raises an exception.
5445
5446 If times is not None, it must be a tuple (atime, mtime);
5447 atime and mtime should be expressed as float seconds since the epoch.
5448 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
5449 atime_ns and mtime_ns should be expressed as integer nanoseconds
5450 since the epoch.
5451 If times is None and ns is unspecified, utime uses the current time.
5452 Specifying tuples for both times and ns is an error.
5453
5454 If dir_fd is not None, it should be a file descriptor open to a directory,
5455 and path should be relative; path will then be relative to that directory.
5456 If follow_symlinks is False, and the last element of the path is a symbolic
5457 link, utime will modify the symbolic link itself instead of the file the
5458 link points to.
5459 It is an error to use dir_fd or follow_symlinks when specifying path
5460 as an open file descriptor.
5461 dir_fd and follow_symlinks may not be available on your platform.
5462 If they are unavailable, using them will raise a NotImplementedError.
5463
5464 [clinic start generated code]*/
5465
5466 static PyObject *
os_utime_impl(PyObject * module,path_t * path,PyObject * times,PyObject * ns,int dir_fd,int follow_symlinks)5467 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
5468 int dir_fd, int follow_symlinks)
5469 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
5470 {
5471 #ifdef MS_WINDOWS
5472 HANDLE hFile;
5473 FILETIME atime, mtime;
5474 #else
5475 int result;
5476 #endif
5477
5478 utime_t utime;
5479
5480 memset(&utime, 0, sizeof(utime_t));
5481
5482 if (times != Py_None && ns) {
5483 PyErr_SetString(PyExc_ValueError,
5484 "utime: you may specify either 'times'"
5485 " or 'ns' but not both");
5486 return NULL;
5487 }
5488
5489 if (times != Py_None) {
5490 time_t a_sec, m_sec;
5491 long a_nsec, m_nsec;
5492 if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
5493 PyErr_SetString(PyExc_TypeError,
5494 "utime: 'times' must be either"
5495 " a tuple of two ints or None");
5496 return NULL;
5497 }
5498 utime.now = 0;
5499 if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
5500 &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
5501 _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
5502 &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
5503 return NULL;
5504 }
5505 utime.atime_s = a_sec;
5506 utime.atime_ns = a_nsec;
5507 utime.mtime_s = m_sec;
5508 utime.mtime_ns = m_nsec;
5509 }
5510 else if (ns) {
5511 if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
5512 PyErr_SetString(PyExc_TypeError,
5513 "utime: 'ns' must be a tuple of two ints");
5514 return NULL;
5515 }
5516 utime.now = 0;
5517 if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
5518 &utime.atime_s, &utime.atime_ns) ||
5519 !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
5520 &utime.mtime_s, &utime.mtime_ns)) {
5521 return NULL;
5522 }
5523 }
5524 else {
5525 /* times and ns are both None/unspecified. use "now". */
5526 utime.now = 1;
5527 }
5528
5529 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
5530 if (follow_symlinks_specified("utime", follow_symlinks))
5531 return NULL;
5532 #endif
5533
5534 if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
5535 dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
5536 fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
5537 return NULL;
5538
5539 #if !defined(HAVE_UTIMENSAT)
5540 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
5541 PyErr_SetString(PyExc_ValueError,
5542 "utime: cannot use dir_fd and follow_symlinks "
5543 "together on this platform");
5544 return NULL;
5545 }
5546 #endif
5547
5548 if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
5549 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5550 return NULL;
5551 }
5552
5553 #ifdef MS_WINDOWS
5554 Py_BEGIN_ALLOW_THREADS
5555 hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
5556 NULL, OPEN_EXISTING,
5557 FILE_FLAG_BACKUP_SEMANTICS, NULL);
5558 Py_END_ALLOW_THREADS
5559 if (hFile == INVALID_HANDLE_VALUE) {
5560 path_error(path);
5561 return NULL;
5562 }
5563
5564 if (utime.now) {
5565 GetSystemTimeAsFileTime(&mtime);
5566 atime = mtime;
5567 }
5568 else {
5569 _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
5570 _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
5571 }
5572 if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
5573 /* Avoid putting the file name into the error here,
5574 as that may confuse the user into believing that
5575 something is wrong with the file, when it also
5576 could be the time stamp that gives a problem. */
5577 PyErr_SetFromWindowsErr(0);
5578 CloseHandle(hFile);
5579 return NULL;
5580 }
5581 CloseHandle(hFile);
5582 #else /* MS_WINDOWS */
5583 Py_BEGIN_ALLOW_THREADS
5584
5585 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5586 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
5587 result = utime_nofollow_symlinks(&utime, path->narrow);
5588 else
5589 #endif
5590
5591 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5592 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
5593 result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
5594
5595 } else
5596 #endif
5597
5598 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5599 if (path->fd != -1)
5600 result = utime_fd(&utime, path->fd);
5601 else
5602 #endif
5603
5604 result = utime_default(&utime, path->narrow);
5605
5606 Py_END_ALLOW_THREADS
5607
5608 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5609 /* See utime_dir_fd implementation */
5610 if (result == -1 && errno == ENOSYS) {
5611 argument_unavailable_error(NULL, "dir_fd");
5612 return NULL;
5613 }
5614 #endif
5615
5616 if (result < 0) {
5617 /* see previous comment about not putting filename in error here */
5618 posix_error();
5619 return NULL;
5620 }
5621
5622 #endif /* MS_WINDOWS */
5623
5624 Py_RETURN_NONE;
5625 }
5626
5627 /* Process operations */
5628
5629
5630 /*[clinic input]
5631 os._exit
5632
5633 status: int
5634
5635 Exit to the system with specified status, without normal exit processing.
5636 [clinic start generated code]*/
5637
5638 static PyObject *
os__exit_impl(PyObject * module,int status)5639 os__exit_impl(PyObject *module, int status)
5640 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5641 {
5642 _exit(status);
5643 return NULL; /* Make gcc -Wall happy */
5644 }
5645
5646 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5647 #define EXECV_CHAR wchar_t
5648 #else
5649 #define EXECV_CHAR char
5650 #endif
5651
5652 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5653 static void
free_string_array(EXECV_CHAR ** array,Py_ssize_t count)5654 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5655 {
5656 Py_ssize_t i;
5657 for (i = 0; i < count; i++)
5658 PyMem_Free(array[i]);
5659 PyMem_Free(array);
5660 }
5661
5662 static int
fsconvert_strdup(PyObject * o,EXECV_CHAR ** out)5663 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5664 {
5665 Py_ssize_t size;
5666 PyObject *ub;
5667 int result = 0;
5668 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5669 if (!PyUnicode_FSDecoder(o, &ub))
5670 return 0;
5671 *out = PyUnicode_AsWideCharString(ub, &size);
5672 if (*out)
5673 result = 1;
5674 #else
5675 if (!PyUnicode_FSConverter(o, &ub))
5676 return 0;
5677 size = PyBytes_GET_SIZE(ub);
5678 *out = PyMem_Malloc(size + 1);
5679 if (*out) {
5680 memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5681 result = 1;
5682 } else
5683 PyErr_NoMemory();
5684 #endif
5685 Py_DECREF(ub);
5686 return result;
5687 }
5688 #endif
5689
5690 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5691 static EXECV_CHAR**
parse_envlist(PyObject * env,Py_ssize_t * envc_ptr)5692 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5693 {
5694 Py_ssize_t i, pos, envc;
5695 PyObject *keys=NULL, *vals=NULL;
5696 PyObject *key, *val, *key2, *val2, *keyval;
5697 EXECV_CHAR **envlist;
5698
5699 i = PyMapping_Size(env);
5700 if (i < 0)
5701 return NULL;
5702 envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5703 if (envlist == NULL) {
5704 PyErr_NoMemory();
5705 return NULL;
5706 }
5707 envc = 0;
5708 keys = PyMapping_Keys(env);
5709 if (!keys)
5710 goto error;
5711 vals = PyMapping_Values(env);
5712 if (!vals)
5713 goto error;
5714 if (!PyList_Check(keys) || !PyList_Check(vals)) {
5715 PyErr_Format(PyExc_TypeError,
5716 "env.keys() or env.values() is not a list");
5717 goto error;
5718 }
5719
5720 for (pos = 0; pos < i; pos++) {
5721 key = PyList_GetItem(keys, pos);
5722 val = PyList_GetItem(vals, pos);
5723 if (!key || !val)
5724 goto error;
5725
5726 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5727 if (!PyUnicode_FSDecoder(key, &key2))
5728 goto error;
5729 if (!PyUnicode_FSDecoder(val, &val2)) {
5730 Py_DECREF(key2);
5731 goto error;
5732 }
5733 /* Search from index 1 because on Windows starting '=' is allowed for
5734 defining hidden environment variables. */
5735 if (PyUnicode_GET_LENGTH(key2) == 0 ||
5736 PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5737 {
5738 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5739 Py_DECREF(key2);
5740 Py_DECREF(val2);
5741 goto error;
5742 }
5743 keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5744 #else
5745 if (!PyUnicode_FSConverter(key, &key2))
5746 goto error;
5747 if (!PyUnicode_FSConverter(val, &val2)) {
5748 Py_DECREF(key2);
5749 goto error;
5750 }
5751 if (PyBytes_GET_SIZE(key2) == 0 ||
5752 strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5753 {
5754 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5755 Py_DECREF(key2);
5756 Py_DECREF(val2);
5757 goto error;
5758 }
5759 keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5760 PyBytes_AS_STRING(val2));
5761 #endif
5762 Py_DECREF(key2);
5763 Py_DECREF(val2);
5764 if (!keyval)
5765 goto error;
5766
5767 if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5768 Py_DECREF(keyval);
5769 goto error;
5770 }
5771
5772 Py_DECREF(keyval);
5773 }
5774 Py_DECREF(vals);
5775 Py_DECREF(keys);
5776
5777 envlist[envc] = 0;
5778 *envc_ptr = envc;
5779 return envlist;
5780
5781 error:
5782 Py_XDECREF(keys);
5783 Py_XDECREF(vals);
5784 free_string_array(envlist, envc);
5785 return NULL;
5786 }
5787
5788 static EXECV_CHAR**
parse_arglist(PyObject * argv,Py_ssize_t * argc)5789 parse_arglist(PyObject* argv, Py_ssize_t *argc)
5790 {
5791 int i;
5792 EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5793 if (argvlist == NULL) {
5794 PyErr_NoMemory();
5795 return NULL;
5796 }
5797 for (i = 0; i < *argc; i++) {
5798 PyObject* item = PySequence_ITEM(argv, i);
5799 if (item == NULL)
5800 goto fail;
5801 if (!fsconvert_strdup(item, &argvlist[i])) {
5802 Py_DECREF(item);
5803 goto fail;
5804 }
5805 Py_DECREF(item);
5806 }
5807 argvlist[*argc] = NULL;
5808 return argvlist;
5809 fail:
5810 *argc = i;
5811 free_string_array(argvlist, *argc);
5812 return NULL;
5813 }
5814
5815 #endif
5816
5817
5818 #ifdef HAVE_EXECV
5819 /*[clinic input]
5820 os.execv
5821
5822 path: path_t
5823 Path of executable file.
5824 argv: object
5825 Tuple or list of strings.
5826 /
5827
5828 Execute an executable path with arguments, replacing current process.
5829 [clinic start generated code]*/
5830
5831 static PyObject *
os_execv_impl(PyObject * module,path_t * path,PyObject * argv)5832 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5833 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5834 {
5835 EXECV_CHAR **argvlist;
5836 Py_ssize_t argc;
5837
5838 /* execv has two arguments: (path, argv), where
5839 argv is a list or tuple of strings. */
5840
5841 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5842 PyErr_SetString(PyExc_TypeError,
5843 "execv() arg 2 must be a tuple or list");
5844 return NULL;
5845 }
5846 argc = PySequence_Size(argv);
5847 if (argc < 1) {
5848 PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5849 return NULL;
5850 }
5851
5852 argvlist = parse_arglist(argv, &argc);
5853 if (argvlist == NULL) {
5854 return NULL;
5855 }
5856 if (!argvlist[0][0]) {
5857 PyErr_SetString(PyExc_ValueError,
5858 "execv() arg 2 first element cannot be empty");
5859 free_string_array(argvlist, argc);
5860 return NULL;
5861 }
5862
5863 if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5864 free_string_array(argvlist, argc);
5865 return NULL;
5866 }
5867
5868 _Py_BEGIN_SUPPRESS_IPH
5869 #ifdef HAVE_WEXECV
5870 _wexecv(path->wide, argvlist);
5871 #else
5872 execv(path->narrow, argvlist);
5873 #endif
5874 _Py_END_SUPPRESS_IPH
5875
5876 /* If we get here it's definitely an error */
5877
5878 free_string_array(argvlist, argc);
5879 return posix_error();
5880 }
5881
5882
5883 /*[clinic input]
5884 os.execve
5885
5886 path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5887 Path of executable file.
5888 argv: object
5889 Tuple or list of strings.
5890 env: object
5891 Dictionary of strings mapping to strings.
5892
5893 Execute an executable path with arguments, replacing current process.
5894 [clinic start generated code]*/
5895
5896 static PyObject *
os_execve_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env)5897 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5898 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5899 {
5900 EXECV_CHAR **argvlist = NULL;
5901 EXECV_CHAR **envlist;
5902 Py_ssize_t argc, envc;
5903
5904 /* execve has three arguments: (path, argv, env), where
5905 argv is a list or tuple of strings and env is a dictionary
5906 like posix.environ. */
5907
5908 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5909 PyErr_SetString(PyExc_TypeError,
5910 "execve: argv must be a tuple or list");
5911 goto fail_0;
5912 }
5913 argc = PySequence_Size(argv);
5914 if (argc < 1) {
5915 PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5916 return NULL;
5917 }
5918
5919 if (!PyMapping_Check(env)) {
5920 PyErr_SetString(PyExc_TypeError,
5921 "execve: environment must be a mapping object");
5922 goto fail_0;
5923 }
5924
5925 argvlist = parse_arglist(argv, &argc);
5926 if (argvlist == NULL) {
5927 goto fail_0;
5928 }
5929 if (!argvlist[0][0]) {
5930 PyErr_SetString(PyExc_ValueError,
5931 "execve: argv first element cannot be empty");
5932 goto fail_0;
5933 }
5934
5935 envlist = parse_envlist(env, &envc);
5936 if (envlist == NULL)
5937 goto fail_0;
5938
5939 if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5940 goto fail_1;
5941 }
5942
5943 _Py_BEGIN_SUPPRESS_IPH
5944 #ifdef HAVE_FEXECVE
5945 if (path->fd > -1)
5946 fexecve(path->fd, argvlist, envlist);
5947 else
5948 #endif
5949 #ifdef HAVE_WEXECV
5950 _wexecve(path->wide, argvlist, envlist);
5951 #else
5952 execve(path->narrow, argvlist, envlist);
5953 #endif
5954 _Py_END_SUPPRESS_IPH
5955
5956 /* If we get here it's definitely an error */
5957
5958 posix_path_error(path);
5959 fail_1:
5960 free_string_array(envlist, envc);
5961 fail_0:
5962 if (argvlist)
5963 free_string_array(argvlist, argc);
5964 return NULL;
5965 }
5966
5967 #endif /* HAVE_EXECV */
5968
5969 #ifdef HAVE_POSIX_SPAWN
5970
5971 enum posix_spawn_file_actions_identifier {
5972 POSIX_SPAWN_OPEN,
5973 POSIX_SPAWN_CLOSE,
5974 POSIX_SPAWN_DUP2
5975 };
5976
5977 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
5978 static int
5979 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
5980 #endif
5981
5982 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)5983 parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
5984 int resetids, int setsid, PyObject *setsigmask,
5985 PyObject *setsigdef, PyObject *scheduler,
5986 posix_spawnattr_t *attrp)
5987 {
5988 long all_flags = 0;
5989
5990 errno = posix_spawnattr_init(attrp);
5991 if (errno) {
5992 posix_error();
5993 return -1;
5994 }
5995
5996 if (setpgroup) {
5997 pid_t pgid = PyLong_AsPid(setpgroup);
5998 if (pgid == (pid_t)-1 && PyErr_Occurred()) {
5999 goto fail;
6000 }
6001 errno = posix_spawnattr_setpgroup(attrp, pgid);
6002 if (errno) {
6003 posix_error();
6004 goto fail;
6005 }
6006 all_flags |= POSIX_SPAWN_SETPGROUP;
6007 }
6008
6009 if (resetids) {
6010 all_flags |= POSIX_SPAWN_RESETIDS;
6011 }
6012
6013 if (setsid) {
6014 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
6015 if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
6016 #endif
6017 #ifdef POSIX_SPAWN_SETSID
6018 all_flags |= POSIX_SPAWN_SETSID;
6019 #elif defined(POSIX_SPAWN_SETSID_NP)
6020 all_flags |= POSIX_SPAWN_SETSID_NP;
6021 #else
6022 argument_unavailable_error(func_name, "setsid");
6023 return -1;
6024 #endif
6025
6026 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
6027 } else {
6028 argument_unavailable_error(func_name, "setsid");
6029 return -1;
6030 }
6031 #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
6032
6033 }
6034
6035 #ifdef HAVE_SIGSET_T
6036 if (setsigmask) {
6037 sigset_t set;
6038 if (!_Py_Sigset_Converter(setsigmask, &set)) {
6039 goto fail;
6040 }
6041 errno = posix_spawnattr_setsigmask(attrp, &set);
6042 if (errno) {
6043 posix_error();
6044 goto fail;
6045 }
6046 all_flags |= POSIX_SPAWN_SETSIGMASK;
6047 }
6048
6049 if (setsigdef) {
6050 sigset_t set;
6051 if (!_Py_Sigset_Converter(setsigdef, &set)) {
6052 goto fail;
6053 }
6054 errno = posix_spawnattr_setsigdefault(attrp, &set);
6055 if (errno) {
6056 posix_error();
6057 goto fail;
6058 }
6059 all_flags |= POSIX_SPAWN_SETSIGDEF;
6060 }
6061 #else
6062 if (setsigmask || setsigdef) {
6063 PyErr_SetString(PyExc_NotImplementedError,
6064 "sigset is not supported on this platform");
6065 goto fail;
6066 }
6067 #endif
6068
6069 if (scheduler) {
6070 #ifdef POSIX_SPAWN_SETSCHEDULER
6071 PyObject *py_schedpolicy;
6072 PyObject *schedparam_obj;
6073 struct sched_param schedparam;
6074
6075 if (!PyArg_ParseTuple(scheduler, "OO"
6076 ";A scheduler tuple must have two elements",
6077 &py_schedpolicy, &schedparam_obj)) {
6078 goto fail;
6079 }
6080 if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
6081 goto fail;
6082 }
6083 if (py_schedpolicy != Py_None) {
6084 int schedpolicy = _PyLong_AsInt(py_schedpolicy);
6085
6086 if (schedpolicy == -1 && PyErr_Occurred()) {
6087 goto fail;
6088 }
6089 errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
6090 if (errno) {
6091 posix_error();
6092 goto fail;
6093 }
6094 all_flags |= POSIX_SPAWN_SETSCHEDULER;
6095 }
6096 errno = posix_spawnattr_setschedparam(attrp, &schedparam);
6097 if (errno) {
6098 posix_error();
6099 goto fail;
6100 }
6101 all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
6102 #else
6103 PyErr_SetString(PyExc_NotImplementedError,
6104 "The scheduler option is not supported in this system.");
6105 goto fail;
6106 #endif
6107 }
6108
6109 errno = posix_spawnattr_setflags(attrp, all_flags);
6110 if (errno) {
6111 posix_error();
6112 goto fail;
6113 }
6114
6115 return 0;
6116
6117 fail:
6118 (void)posix_spawnattr_destroy(attrp);
6119 return -1;
6120 }
6121
6122 static int
parse_file_actions(PyObject * file_actions,posix_spawn_file_actions_t * file_actionsp,PyObject * temp_buffer)6123 parse_file_actions(PyObject *file_actions,
6124 posix_spawn_file_actions_t *file_actionsp,
6125 PyObject *temp_buffer)
6126 {
6127 PyObject *seq;
6128 PyObject *file_action = NULL;
6129 PyObject *tag_obj;
6130
6131 seq = PySequence_Fast(file_actions,
6132 "file_actions must be a sequence or None");
6133 if (seq == NULL) {
6134 return -1;
6135 }
6136
6137 errno = posix_spawn_file_actions_init(file_actionsp);
6138 if (errno) {
6139 posix_error();
6140 Py_DECREF(seq);
6141 return -1;
6142 }
6143
6144 for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
6145 file_action = PySequence_Fast_GET_ITEM(seq, i);
6146 Py_INCREF(file_action);
6147 if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
6148 PyErr_SetString(PyExc_TypeError,
6149 "Each file_actions element must be a non-empty tuple");
6150 goto fail;
6151 }
6152 long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
6153 if (tag == -1 && PyErr_Occurred()) {
6154 goto fail;
6155 }
6156
6157 /* Populate the file_actions object */
6158 switch (tag) {
6159 case POSIX_SPAWN_OPEN: {
6160 int fd, oflag;
6161 PyObject *path;
6162 unsigned long mode;
6163 if (!PyArg_ParseTuple(file_action, "OiO&ik"
6164 ";A open file_action tuple must have 5 elements",
6165 &tag_obj, &fd, PyUnicode_FSConverter, &path,
6166 &oflag, &mode))
6167 {
6168 goto fail;
6169 }
6170 if (PyList_Append(temp_buffer, path)) {
6171 Py_DECREF(path);
6172 goto fail;
6173 }
6174 errno = posix_spawn_file_actions_addopen(file_actionsp,
6175 fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
6176 Py_DECREF(path);
6177 if (errno) {
6178 posix_error();
6179 goto fail;
6180 }
6181 break;
6182 }
6183 case POSIX_SPAWN_CLOSE: {
6184 int fd;
6185 if (!PyArg_ParseTuple(file_action, "Oi"
6186 ";A close file_action tuple must have 2 elements",
6187 &tag_obj, &fd))
6188 {
6189 goto fail;
6190 }
6191 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
6192 if (errno) {
6193 posix_error();
6194 goto fail;
6195 }
6196 break;
6197 }
6198 case POSIX_SPAWN_DUP2: {
6199 int fd1, fd2;
6200 if (!PyArg_ParseTuple(file_action, "Oii"
6201 ";A dup2 file_action tuple must have 3 elements",
6202 &tag_obj, &fd1, &fd2))
6203 {
6204 goto fail;
6205 }
6206 errno = posix_spawn_file_actions_adddup2(file_actionsp,
6207 fd1, fd2);
6208 if (errno) {
6209 posix_error();
6210 goto fail;
6211 }
6212 break;
6213 }
6214 default: {
6215 PyErr_SetString(PyExc_TypeError,
6216 "Unknown file_actions identifier");
6217 goto fail;
6218 }
6219 }
6220 Py_DECREF(file_action);
6221 }
6222
6223 Py_DECREF(seq);
6224 return 0;
6225
6226 fail:
6227 Py_DECREF(seq);
6228 Py_DECREF(file_action);
6229 (void)posix_spawn_file_actions_destroy(file_actionsp);
6230 return -1;
6231 }
6232
6233
6234 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)6235 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
6236 PyObject *env, PyObject *file_actions,
6237 PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
6238 PyObject *setsigdef, PyObject *scheduler)
6239 {
6240 const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
6241 EXECV_CHAR **argvlist = NULL;
6242 EXECV_CHAR **envlist = NULL;
6243 posix_spawn_file_actions_t file_actions_buf;
6244 posix_spawn_file_actions_t *file_actionsp = NULL;
6245 posix_spawnattr_t attr;
6246 posix_spawnattr_t *attrp = NULL;
6247 Py_ssize_t argc, envc;
6248 PyObject *result = NULL;
6249 PyObject *temp_buffer = NULL;
6250 pid_t pid;
6251 int err_code;
6252
6253 /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
6254 argv is a list or tuple of strings and env is a dictionary
6255 like posix.environ. */
6256
6257 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6258 PyErr_Format(PyExc_TypeError,
6259 "%s: argv must be a tuple or list", func_name);
6260 goto exit;
6261 }
6262 argc = PySequence_Size(argv);
6263 if (argc < 1) {
6264 PyErr_Format(PyExc_ValueError,
6265 "%s: argv must not be empty", func_name);
6266 return NULL;
6267 }
6268
6269 if (!PyMapping_Check(env)) {
6270 PyErr_Format(PyExc_TypeError,
6271 "%s: environment must be a mapping object", func_name);
6272 goto exit;
6273 }
6274
6275 argvlist = parse_arglist(argv, &argc);
6276 if (argvlist == NULL) {
6277 goto exit;
6278 }
6279 if (!argvlist[0][0]) {
6280 PyErr_Format(PyExc_ValueError,
6281 "%s: argv first element cannot be empty", func_name);
6282 goto exit;
6283 }
6284
6285 envlist = parse_envlist(env, &envc);
6286 if (envlist == NULL) {
6287 goto exit;
6288 }
6289
6290 if (file_actions != NULL && file_actions != Py_None) {
6291 /* There is a bug in old versions of glibc that makes some of the
6292 * helper functions for manipulating file actions not copy the provided
6293 * buffers. The problem is that posix_spawn_file_actions_addopen does not
6294 * copy the value of path for some old versions of glibc (<2.20).
6295 * The use of temp_buffer here is a workaround that keeps the
6296 * python objects that own the buffers alive until posix_spawn gets called.
6297 * Check https://bugs.python.org/issue33630 and
6298 * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
6299 temp_buffer = PyList_New(0);
6300 if (!temp_buffer) {
6301 goto exit;
6302 }
6303 if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
6304 goto exit;
6305 }
6306 file_actionsp = &file_actions_buf;
6307 }
6308
6309 if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
6310 setsigmask, setsigdef, scheduler, &attr)) {
6311 goto exit;
6312 }
6313 attrp = &attr;
6314
6315 if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
6316 goto exit;
6317 }
6318
6319 _Py_BEGIN_SUPPRESS_IPH
6320 #ifdef HAVE_POSIX_SPAWNP
6321 if (use_posix_spawnp) {
6322 err_code = posix_spawnp(&pid, path->narrow,
6323 file_actionsp, attrp, argvlist, envlist);
6324 }
6325 else
6326 #endif /* HAVE_POSIX_SPAWNP */
6327 {
6328 err_code = posix_spawn(&pid, path->narrow,
6329 file_actionsp, attrp, argvlist, envlist);
6330 }
6331 _Py_END_SUPPRESS_IPH
6332
6333 if (err_code) {
6334 errno = err_code;
6335 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
6336 goto exit;
6337 }
6338 #ifdef _Py_MEMORY_SANITIZER
6339 __msan_unpoison(&pid, sizeof(pid));
6340 #endif
6341 result = PyLong_FromPid(pid);
6342
6343 exit:
6344 if (file_actionsp) {
6345 (void)posix_spawn_file_actions_destroy(file_actionsp);
6346 }
6347 if (attrp) {
6348 (void)posix_spawnattr_destroy(attrp);
6349 }
6350 if (envlist) {
6351 free_string_array(envlist, envc);
6352 }
6353 if (argvlist) {
6354 free_string_array(argvlist, argc);
6355 }
6356 Py_XDECREF(temp_buffer);
6357 return result;
6358 }
6359
6360
6361 /*[clinic input]
6362
6363 os.posix_spawn
6364 path: path_t
6365 Path of executable file.
6366 argv: object
6367 Tuple or list of strings.
6368 env: object
6369 Dictionary of strings mapping to strings.
6370 /
6371 *
6372 file_actions: object(c_default='NULL') = ()
6373 A sequence of file action tuples.
6374 setpgroup: object = NULL
6375 The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6376 resetids: bool(accept={int}) = False
6377 If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
6378 setsid: bool(accept={int}) = False
6379 If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6380 setsigmask: object(c_default='NULL') = ()
6381 The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6382 setsigdef: object(c_default='NULL') = ()
6383 The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6384 scheduler: object = NULL
6385 A tuple with the scheduler policy (optional) and parameters.
6386
6387 Execute the program specified by path in a new process.
6388 [clinic start generated code]*/
6389
6390 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)6391 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
6392 PyObject *env, PyObject *file_actions,
6393 PyObject *setpgroup, int resetids, int setsid,
6394 PyObject *setsigmask, PyObject *setsigdef,
6395 PyObject *scheduler)
6396 /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
6397 {
6398 return py_posix_spawn(0, module, path, argv, env, file_actions,
6399 setpgroup, resetids, setsid, setsigmask, setsigdef,
6400 scheduler);
6401 }
6402 #endif /* HAVE_POSIX_SPAWN */
6403
6404
6405
6406 #ifdef HAVE_POSIX_SPAWNP
6407 /*[clinic input]
6408
6409 os.posix_spawnp
6410 path: path_t
6411 Path of executable file.
6412 argv: object
6413 Tuple or list of strings.
6414 env: object
6415 Dictionary of strings mapping to strings.
6416 /
6417 *
6418 file_actions: object(c_default='NULL') = ()
6419 A sequence of file action tuples.
6420 setpgroup: object = NULL
6421 The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6422 resetids: bool(accept={int}) = False
6423 If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
6424 setsid: bool(accept={int}) = False
6425 If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6426 setsigmask: object(c_default='NULL') = ()
6427 The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6428 setsigdef: object(c_default='NULL') = ()
6429 The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6430 scheduler: object = NULL
6431 A tuple with the scheduler policy (optional) and parameters.
6432
6433 Execute the program specified by path in a new process.
6434 [clinic start generated code]*/
6435
6436 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)6437 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
6438 PyObject *env, PyObject *file_actions,
6439 PyObject *setpgroup, int resetids, int setsid,
6440 PyObject *setsigmask, PyObject *setsigdef,
6441 PyObject *scheduler)
6442 /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
6443 {
6444 return py_posix_spawn(1, module, path, argv, env, file_actions,
6445 setpgroup, resetids, setsid, setsigmask, setsigdef,
6446 scheduler);
6447 }
6448 #endif /* HAVE_POSIX_SPAWNP */
6449
6450 #ifdef HAVE_RTPSPAWN
6451 static intptr_t
_rtp_spawn(int mode,const char * rtpFileName,const char * argv[],const char * envp[])6452 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
6453 const char *envp[])
6454 {
6455 RTP_ID rtpid;
6456 int status;
6457 pid_t res;
6458 int async_err = 0;
6459
6460 /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
6461 uStackSize=0 cannot be used, the default stack size is too small for
6462 Python. */
6463 if (envp) {
6464 rtpid = rtpSpawn(rtpFileName, argv, envp,
6465 100, 0x1000000, 0, VX_FP_TASK);
6466 }
6467 else {
6468 rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
6469 100, 0x1000000, 0, VX_FP_TASK);
6470 }
6471 if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
6472 do {
6473 res = waitpid((pid_t)rtpid, &status, 0);
6474 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6475
6476 if (res < 0)
6477 return RTP_ID_ERROR;
6478 return ((intptr_t)status);
6479 }
6480 return ((intptr_t)rtpid);
6481 }
6482 #endif
6483
6484 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
6485 /*[clinic input]
6486 os.spawnv
6487
6488 mode: int
6489 Mode of process creation.
6490 path: path_t
6491 Path of executable file.
6492 argv: object
6493 Tuple or list of strings.
6494 /
6495
6496 Execute the program specified by path in a new process.
6497 [clinic start generated code]*/
6498
6499 static PyObject *
os_spawnv_impl(PyObject * module,int mode,path_t * path,PyObject * argv)6500 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
6501 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
6502 {
6503 EXECV_CHAR **argvlist;
6504 int i;
6505 Py_ssize_t argc;
6506 intptr_t spawnval;
6507 PyObject *(*getitem)(PyObject *, Py_ssize_t);
6508
6509 /* spawnv has three arguments: (mode, path, argv), where
6510 argv is a list or tuple of strings. */
6511
6512 if (PyList_Check(argv)) {
6513 argc = PyList_Size(argv);
6514 getitem = PyList_GetItem;
6515 }
6516 else if (PyTuple_Check(argv)) {
6517 argc = PyTuple_Size(argv);
6518 getitem = PyTuple_GetItem;
6519 }
6520 else {
6521 PyErr_SetString(PyExc_TypeError,
6522 "spawnv() arg 2 must be a tuple or list");
6523 return NULL;
6524 }
6525 if (argc == 0) {
6526 PyErr_SetString(PyExc_ValueError,
6527 "spawnv() arg 2 cannot be empty");
6528 return NULL;
6529 }
6530
6531 argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6532 if (argvlist == NULL) {
6533 return PyErr_NoMemory();
6534 }
6535 for (i = 0; i < argc; i++) {
6536 if (!fsconvert_strdup((*getitem)(argv, i),
6537 &argvlist[i])) {
6538 free_string_array(argvlist, i);
6539 PyErr_SetString(
6540 PyExc_TypeError,
6541 "spawnv() arg 2 must contain only strings");
6542 return NULL;
6543 }
6544 if (i == 0 && !argvlist[0][0]) {
6545 free_string_array(argvlist, i + 1);
6546 PyErr_SetString(
6547 PyExc_ValueError,
6548 "spawnv() arg 2 first element cannot be empty");
6549 return NULL;
6550 }
6551 }
6552 argvlist[argc] = NULL;
6553
6554 #if !defined(HAVE_RTPSPAWN)
6555 if (mode == _OLD_P_OVERLAY)
6556 mode = _P_OVERLAY;
6557 #endif
6558
6559 if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
6560 Py_None) < 0) {
6561 free_string_array(argvlist, argc);
6562 return NULL;
6563 }
6564
6565 Py_BEGIN_ALLOW_THREADS
6566 _Py_BEGIN_SUPPRESS_IPH
6567 #ifdef HAVE_WSPAWNV
6568 spawnval = _wspawnv(mode, path->wide, argvlist);
6569 #elif defined(HAVE_RTPSPAWN)
6570 spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
6571 #else
6572 spawnval = _spawnv(mode, path->narrow, argvlist);
6573 #endif
6574 _Py_END_SUPPRESS_IPH
6575 Py_END_ALLOW_THREADS
6576
6577 free_string_array(argvlist, argc);
6578
6579 if (spawnval == -1)
6580 return posix_error();
6581 else
6582 return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6583 }
6584
6585 /*[clinic input]
6586 os.spawnve
6587
6588 mode: int
6589 Mode of process creation.
6590 path: path_t
6591 Path of executable file.
6592 argv: object
6593 Tuple or list of strings.
6594 env: object
6595 Dictionary of strings mapping to strings.
6596 /
6597
6598 Execute the program specified by path in a new process.
6599 [clinic start generated code]*/
6600
6601 static PyObject *
os_spawnve_impl(PyObject * module,int mode,path_t * path,PyObject * argv,PyObject * env)6602 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
6603 PyObject *env)
6604 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
6605 {
6606 EXECV_CHAR **argvlist;
6607 EXECV_CHAR **envlist;
6608 PyObject *res = NULL;
6609 Py_ssize_t argc, i, envc;
6610 intptr_t spawnval;
6611 PyObject *(*getitem)(PyObject *, Py_ssize_t);
6612 Py_ssize_t lastarg = 0;
6613
6614 /* spawnve has four arguments: (mode, path, argv, env), where
6615 argv is a list or tuple of strings and env is a dictionary
6616 like posix.environ. */
6617
6618 if (PyList_Check(argv)) {
6619 argc = PyList_Size(argv);
6620 getitem = PyList_GetItem;
6621 }
6622 else if (PyTuple_Check(argv)) {
6623 argc = PyTuple_Size(argv);
6624 getitem = PyTuple_GetItem;
6625 }
6626 else {
6627 PyErr_SetString(PyExc_TypeError,
6628 "spawnve() arg 2 must be a tuple or list");
6629 goto fail_0;
6630 }
6631 if (argc == 0) {
6632 PyErr_SetString(PyExc_ValueError,
6633 "spawnve() arg 2 cannot be empty");
6634 goto fail_0;
6635 }
6636 if (!PyMapping_Check(env)) {
6637 PyErr_SetString(PyExc_TypeError,
6638 "spawnve() arg 3 must be a mapping object");
6639 goto fail_0;
6640 }
6641
6642 argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6643 if (argvlist == NULL) {
6644 PyErr_NoMemory();
6645 goto fail_0;
6646 }
6647 for (i = 0; i < argc; i++) {
6648 if (!fsconvert_strdup((*getitem)(argv, i),
6649 &argvlist[i]))
6650 {
6651 lastarg = i;
6652 goto fail_1;
6653 }
6654 if (i == 0 && !argvlist[0][0]) {
6655 lastarg = i + 1;
6656 PyErr_SetString(
6657 PyExc_ValueError,
6658 "spawnv() arg 2 first element cannot be empty");
6659 goto fail_1;
6660 }
6661 }
6662 lastarg = argc;
6663 argvlist[argc] = NULL;
6664
6665 envlist = parse_envlist(env, &envc);
6666 if (envlist == NULL)
6667 goto fail_1;
6668
6669 #if !defined(HAVE_RTPSPAWN)
6670 if (mode == _OLD_P_OVERLAY)
6671 mode = _P_OVERLAY;
6672 #endif
6673
6674 if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6675 goto fail_2;
6676 }
6677
6678 Py_BEGIN_ALLOW_THREADS
6679 _Py_BEGIN_SUPPRESS_IPH
6680 #ifdef HAVE_WSPAWNV
6681 spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6682 #elif defined(HAVE_RTPSPAWN)
6683 spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6684 (const char **)envlist);
6685 #else
6686 spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6687 #endif
6688 _Py_END_SUPPRESS_IPH
6689 Py_END_ALLOW_THREADS
6690
6691 if (spawnval == -1)
6692 (void) posix_error();
6693 else
6694 res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6695
6696 fail_2:
6697 while (--envc >= 0) {
6698 PyMem_Free(envlist[envc]);
6699 }
6700 PyMem_Free(envlist);
6701 fail_1:
6702 free_string_array(argvlist, lastarg);
6703 fail_0:
6704 return res;
6705 }
6706
6707 #endif /* HAVE_SPAWNV */
6708
6709 #ifdef HAVE_FORK
6710
6711 /* Helper function to validate arguments.
6712 Returns 0 on success. non-zero on failure with a TypeError raised.
6713 If obj is non-NULL it must be callable. */
6714 static int
check_null_or_callable(PyObject * obj,const char * obj_name)6715 check_null_or_callable(PyObject *obj, const char* obj_name)
6716 {
6717 if (obj && !PyCallable_Check(obj)) {
6718 PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6719 obj_name, _PyType_Name(Py_TYPE(obj)));
6720 return -1;
6721 }
6722 return 0;
6723 }
6724
6725 /*[clinic input]
6726 os.register_at_fork
6727
6728 *
6729 before: object=NULL
6730 A callable to be called in the parent before the fork() syscall.
6731 after_in_child: object=NULL
6732 A callable to be called in the child after fork().
6733 after_in_parent: object=NULL
6734 A callable to be called in the parent after fork().
6735
6736 Register callables to be called when forking a new process.
6737
6738 'before' callbacks are called in reverse order.
6739 'after_in_child' and 'after_in_parent' callbacks are called in order.
6740
6741 [clinic start generated code]*/
6742
6743 static PyObject *
os_register_at_fork_impl(PyObject * module,PyObject * before,PyObject * after_in_child,PyObject * after_in_parent)6744 os_register_at_fork_impl(PyObject *module, PyObject *before,
6745 PyObject *after_in_child, PyObject *after_in_parent)
6746 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6747 {
6748 PyInterpreterState *interp;
6749
6750 if (!before && !after_in_child && !after_in_parent) {
6751 PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6752 return NULL;
6753 }
6754 if (check_null_or_callable(before, "before") ||
6755 check_null_or_callable(after_in_child, "after_in_child") ||
6756 check_null_or_callable(after_in_parent, "after_in_parent")) {
6757 return NULL;
6758 }
6759 interp = _PyInterpreterState_GET();
6760
6761 if (register_at_forker(&interp->before_forkers, before)) {
6762 return NULL;
6763 }
6764 if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6765 return NULL;
6766 }
6767 if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6768 return NULL;
6769 }
6770 Py_RETURN_NONE;
6771 }
6772 #endif /* HAVE_FORK */
6773
6774
6775 #ifdef HAVE_FORK1
6776 /*[clinic input]
6777 os.fork1
6778
6779 Fork a child process with a single multiplexed (i.e., not bound) thread.
6780
6781 Return 0 to child process and PID of child to parent process.
6782 [clinic start generated code]*/
6783
6784 static PyObject *
os_fork1_impl(PyObject * module)6785 os_fork1_impl(PyObject *module)
6786 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6787 {
6788 pid_t pid;
6789
6790 if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
6791 PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6792 return NULL;
6793 }
6794 PyOS_BeforeFork();
6795 pid = fork1();
6796 if (pid == 0) {
6797 /* child: this clobbers and resets the import lock. */
6798 PyOS_AfterFork_Child();
6799 } else {
6800 /* parent: release the import lock. */
6801 PyOS_AfterFork_Parent();
6802 }
6803 if (pid == -1)
6804 return posix_error();
6805 return PyLong_FromPid(pid);
6806 }
6807 #endif /* HAVE_FORK1 */
6808
6809
6810 #ifdef HAVE_FORK
6811 /*[clinic input]
6812 os.fork
6813
6814 Fork a child process.
6815
6816 Return 0 to child process and PID of child to parent process.
6817 [clinic start generated code]*/
6818
6819 static PyObject *
os_fork_impl(PyObject * module)6820 os_fork_impl(PyObject *module)
6821 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6822 {
6823 pid_t pid;
6824 PyInterpreterState *interp = _PyInterpreterState_GET();
6825 if (interp->config._isolated_interpreter) {
6826 PyErr_SetString(PyExc_RuntimeError,
6827 "fork not supported for isolated subinterpreters");
6828 return NULL;
6829 }
6830 if (PySys_Audit("os.fork", NULL) < 0) {
6831 return NULL;
6832 }
6833 PyOS_BeforeFork();
6834 pid = fork();
6835 if (pid == 0) {
6836 /* child: this clobbers and resets the import lock. */
6837 PyOS_AfterFork_Child();
6838 } else {
6839 /* parent: release the import lock. */
6840 PyOS_AfterFork_Parent();
6841 }
6842 if (pid == -1)
6843 return posix_error();
6844 return PyLong_FromPid(pid);
6845 }
6846 #endif /* HAVE_FORK */
6847
6848
6849 #ifdef HAVE_SCHED_H
6850 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6851 /*[clinic input]
6852 os.sched_get_priority_max
6853
6854 policy: int
6855
6856 Get the maximum scheduling priority for policy.
6857 [clinic start generated code]*/
6858
6859 static PyObject *
os_sched_get_priority_max_impl(PyObject * module,int policy)6860 os_sched_get_priority_max_impl(PyObject *module, int policy)
6861 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6862 {
6863 int max;
6864
6865 max = sched_get_priority_max(policy);
6866 if (max < 0)
6867 return posix_error();
6868 return PyLong_FromLong(max);
6869 }
6870
6871
6872 /*[clinic input]
6873 os.sched_get_priority_min
6874
6875 policy: int
6876
6877 Get the minimum scheduling priority for policy.
6878 [clinic start generated code]*/
6879
6880 static PyObject *
os_sched_get_priority_min_impl(PyObject * module,int policy)6881 os_sched_get_priority_min_impl(PyObject *module, int policy)
6882 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6883 {
6884 int min = sched_get_priority_min(policy);
6885 if (min < 0)
6886 return posix_error();
6887 return PyLong_FromLong(min);
6888 }
6889 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6890
6891
6892 #ifdef HAVE_SCHED_SETSCHEDULER
6893 /*[clinic input]
6894 os.sched_getscheduler
6895 pid: pid_t
6896 /
6897
6898 Get the scheduling policy for the process identified by pid.
6899
6900 Passing 0 for pid returns the scheduling policy for the calling process.
6901 [clinic start generated code]*/
6902
6903 static PyObject *
os_sched_getscheduler_impl(PyObject * module,pid_t pid)6904 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6905 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
6906 {
6907 int policy;
6908
6909 policy = sched_getscheduler(pid);
6910 if (policy < 0)
6911 return posix_error();
6912 return PyLong_FromLong(policy);
6913 }
6914 #endif /* HAVE_SCHED_SETSCHEDULER */
6915
6916
6917 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6918 /*[clinic input]
6919 class os.sched_param "PyObject *" "SchedParamType"
6920
6921 @classmethod
6922 os.sched_param.__new__
6923
6924 sched_priority: object
6925 A scheduling parameter.
6926
6927 Currently has only one field: sched_priority
6928 [clinic start generated code]*/
6929
6930 static PyObject *
os_sched_param_impl(PyTypeObject * type,PyObject * sched_priority)6931 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6932 /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
6933 {
6934 PyObject *res;
6935
6936 res = PyStructSequence_New(type);
6937 if (!res)
6938 return NULL;
6939 Py_INCREF(sched_priority);
6940 PyStructSequence_SET_ITEM(res, 0, sched_priority);
6941 return res;
6942 }
6943
6944 PyDoc_VAR(os_sched_param__doc__);
6945
6946 static PyStructSequence_Field sched_param_fields[] = {
6947 {"sched_priority", "the scheduling priority"},
6948 {0}
6949 };
6950
6951 static PyStructSequence_Desc sched_param_desc = {
6952 "sched_param", /* name */
6953 os_sched_param__doc__, /* doc */
6954 sched_param_fields,
6955 1
6956 };
6957
6958 static int
convert_sched_param(PyObject * module,PyObject * param,struct sched_param * res)6959 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
6960 {
6961 long priority;
6962
6963 if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
6964 PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
6965 return 0;
6966 }
6967 priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
6968 if (priority == -1 && PyErr_Occurred())
6969 return 0;
6970 if (priority > INT_MAX || priority < INT_MIN) {
6971 PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
6972 return 0;
6973 }
6974 res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
6975 return 1;
6976 }
6977 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
6978
6979
6980 #ifdef HAVE_SCHED_SETSCHEDULER
6981 /*[clinic input]
6982 os.sched_setscheduler
6983
6984 pid: pid_t
6985 policy: int
6986 param as param_obj: object
6987 /
6988
6989 Set the scheduling policy for the process identified by pid.
6990
6991 If pid is 0, the calling process is changed.
6992 param is an instance of sched_param.
6993 [clinic start generated code]*/
6994
6995 static PyObject *
os_sched_setscheduler_impl(PyObject * module,pid_t pid,int policy,PyObject * param_obj)6996 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
6997 PyObject *param_obj)
6998 /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
6999 {
7000 struct sched_param param;
7001 if (!convert_sched_param(module, param_obj, ¶m)) {
7002 return NULL;
7003 }
7004
7005 /*
7006 ** sched_setscheduler() returns 0 in Linux, but the previous
7007 ** scheduling policy under Solaris/Illumos, and others.
7008 ** On error, -1 is returned in all Operating Systems.
7009 */
7010 if (sched_setscheduler(pid, policy, ¶m) == -1)
7011 return posix_error();
7012 Py_RETURN_NONE;
7013 }
7014 #endif /* HAVE_SCHED_SETSCHEDULER*/
7015
7016
7017 #ifdef HAVE_SCHED_SETPARAM
7018 /*[clinic input]
7019 os.sched_getparam
7020 pid: pid_t
7021 /
7022
7023 Returns scheduling parameters for the process identified by pid.
7024
7025 If pid is 0, returns parameters for the calling process.
7026 Return value is an instance of sched_param.
7027 [clinic start generated code]*/
7028
7029 static PyObject *
os_sched_getparam_impl(PyObject * module,pid_t pid)7030 os_sched_getparam_impl(PyObject *module, pid_t pid)
7031 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
7032 {
7033 struct sched_param param;
7034 PyObject *result;
7035 PyObject *priority;
7036
7037 if (sched_getparam(pid, ¶m))
7038 return posix_error();
7039 PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
7040 result = PyStructSequence_New((PyTypeObject *)SchedParamType);
7041 if (!result)
7042 return NULL;
7043 priority = PyLong_FromLong(param.sched_priority);
7044 if (!priority) {
7045 Py_DECREF(result);
7046 return NULL;
7047 }
7048 PyStructSequence_SET_ITEM(result, 0, priority);
7049 return result;
7050 }
7051
7052
7053 /*[clinic input]
7054 os.sched_setparam
7055 pid: pid_t
7056 param as param_obj: object
7057 /
7058
7059 Set scheduling parameters for the process identified by pid.
7060
7061 If pid is 0, sets parameters for the calling process.
7062 param should be an instance of sched_param.
7063 [clinic start generated code]*/
7064
7065 static PyObject *
os_sched_setparam_impl(PyObject * module,pid_t pid,PyObject * param_obj)7066 os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
7067 /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
7068 {
7069 struct sched_param param;
7070 if (!convert_sched_param(module, param_obj, ¶m)) {
7071 return NULL;
7072 }
7073
7074 if (sched_setparam(pid, ¶m))
7075 return posix_error();
7076 Py_RETURN_NONE;
7077 }
7078 #endif /* HAVE_SCHED_SETPARAM */
7079
7080
7081 #ifdef HAVE_SCHED_RR_GET_INTERVAL
7082 /*[clinic input]
7083 os.sched_rr_get_interval -> double
7084 pid: pid_t
7085 /
7086
7087 Return the round-robin quantum for the process identified by pid, in seconds.
7088
7089 Value returned is a float.
7090 [clinic start generated code]*/
7091
7092 static double
os_sched_rr_get_interval_impl(PyObject * module,pid_t pid)7093 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
7094 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
7095 {
7096 struct timespec interval;
7097 if (sched_rr_get_interval(pid, &interval)) {
7098 posix_error();
7099 return -1.0;
7100 }
7101 #ifdef _Py_MEMORY_SANITIZER
7102 __msan_unpoison(&interval, sizeof(interval));
7103 #endif
7104 return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
7105 }
7106 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
7107
7108
7109 /*[clinic input]
7110 os.sched_yield
7111
7112 Voluntarily relinquish the CPU.
7113 [clinic start generated code]*/
7114
7115 static PyObject *
os_sched_yield_impl(PyObject * module)7116 os_sched_yield_impl(PyObject *module)
7117 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
7118 {
7119 int result;
7120 Py_BEGIN_ALLOW_THREADS
7121 result = sched_yield();
7122 Py_END_ALLOW_THREADS
7123 if (result < 0) {
7124 return posix_error();
7125 }
7126 Py_RETURN_NONE;
7127 }
7128
7129 #ifdef HAVE_SCHED_SETAFFINITY
7130 /* The minimum number of CPUs allocated in a cpu_set_t */
7131 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
7132
7133 /*[clinic input]
7134 os.sched_setaffinity
7135 pid: pid_t
7136 mask : object
7137 /
7138
7139 Set the CPU affinity of the process identified by pid to mask.
7140
7141 mask should be an iterable of integers identifying CPUs.
7142 [clinic start generated code]*/
7143
7144 static PyObject *
os_sched_setaffinity_impl(PyObject * module,pid_t pid,PyObject * mask)7145 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
7146 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
7147 {
7148 int ncpus;
7149 size_t setsize;
7150 cpu_set_t *cpu_set = NULL;
7151 PyObject *iterator = NULL, *item;
7152
7153 iterator = PyObject_GetIter(mask);
7154 if (iterator == NULL)
7155 return NULL;
7156
7157 ncpus = NCPUS_START;
7158 setsize = CPU_ALLOC_SIZE(ncpus);
7159 cpu_set = CPU_ALLOC(ncpus);
7160 if (cpu_set == NULL) {
7161 PyErr_NoMemory();
7162 goto error;
7163 }
7164 CPU_ZERO_S(setsize, cpu_set);
7165
7166 while ((item = PyIter_Next(iterator))) {
7167 long cpu;
7168 if (!PyLong_Check(item)) {
7169 PyErr_Format(PyExc_TypeError,
7170 "expected an iterator of ints, "
7171 "but iterator yielded %R",
7172 Py_TYPE(item));
7173 Py_DECREF(item);
7174 goto error;
7175 }
7176 cpu = PyLong_AsLong(item);
7177 Py_DECREF(item);
7178 if (cpu < 0) {
7179 if (!PyErr_Occurred())
7180 PyErr_SetString(PyExc_ValueError, "negative CPU number");
7181 goto error;
7182 }
7183 if (cpu > INT_MAX - 1) {
7184 PyErr_SetString(PyExc_OverflowError, "CPU number too large");
7185 goto error;
7186 }
7187 if (cpu >= ncpus) {
7188 /* Grow CPU mask to fit the CPU number */
7189 int newncpus = ncpus;
7190 cpu_set_t *newmask;
7191 size_t newsetsize;
7192 while (newncpus <= cpu) {
7193 if (newncpus > INT_MAX / 2)
7194 newncpus = cpu + 1;
7195 else
7196 newncpus = newncpus * 2;
7197 }
7198 newmask = CPU_ALLOC(newncpus);
7199 if (newmask == NULL) {
7200 PyErr_NoMemory();
7201 goto error;
7202 }
7203 newsetsize = CPU_ALLOC_SIZE(newncpus);
7204 CPU_ZERO_S(newsetsize, newmask);
7205 memcpy(newmask, cpu_set, setsize);
7206 CPU_FREE(cpu_set);
7207 setsize = newsetsize;
7208 cpu_set = newmask;
7209 ncpus = newncpus;
7210 }
7211 CPU_SET_S(cpu, setsize, cpu_set);
7212 }
7213 if (PyErr_Occurred()) {
7214 goto error;
7215 }
7216 Py_CLEAR(iterator);
7217
7218 if (sched_setaffinity(pid, setsize, cpu_set)) {
7219 posix_error();
7220 goto error;
7221 }
7222 CPU_FREE(cpu_set);
7223 Py_RETURN_NONE;
7224
7225 error:
7226 if (cpu_set)
7227 CPU_FREE(cpu_set);
7228 Py_XDECREF(iterator);
7229 return NULL;
7230 }
7231
7232
7233 /*[clinic input]
7234 os.sched_getaffinity
7235 pid: pid_t
7236 /
7237
7238 Return the affinity of the process identified by pid (or the current process if zero).
7239
7240 The affinity is returned as a set of CPU identifiers.
7241 [clinic start generated code]*/
7242
7243 static PyObject *
os_sched_getaffinity_impl(PyObject * module,pid_t pid)7244 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
7245 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
7246 {
7247 int cpu, ncpus, count;
7248 size_t setsize;
7249 cpu_set_t *mask = NULL;
7250 PyObject *res = NULL;
7251
7252 ncpus = NCPUS_START;
7253 while (1) {
7254 setsize = CPU_ALLOC_SIZE(ncpus);
7255 mask = CPU_ALLOC(ncpus);
7256 if (mask == NULL)
7257 return PyErr_NoMemory();
7258 if (sched_getaffinity(pid, setsize, mask) == 0)
7259 break;
7260 CPU_FREE(mask);
7261 if (errno != EINVAL)
7262 return posix_error();
7263 if (ncpus > INT_MAX / 2) {
7264 PyErr_SetString(PyExc_OverflowError, "could not allocate "
7265 "a large enough CPU set");
7266 return NULL;
7267 }
7268 ncpus = ncpus * 2;
7269 }
7270
7271 res = PySet_New(NULL);
7272 if (res == NULL)
7273 goto error;
7274 for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7275 if (CPU_ISSET_S(cpu, setsize, mask)) {
7276 PyObject *cpu_num = PyLong_FromLong(cpu);
7277 --count;
7278 if (cpu_num == NULL)
7279 goto error;
7280 if (PySet_Add(res, cpu_num)) {
7281 Py_DECREF(cpu_num);
7282 goto error;
7283 }
7284 Py_DECREF(cpu_num);
7285 }
7286 }
7287 CPU_FREE(mask);
7288 return res;
7289
7290 error:
7291 if (mask)
7292 CPU_FREE(mask);
7293 Py_XDECREF(res);
7294 return NULL;
7295 }
7296
7297 #endif /* HAVE_SCHED_SETAFFINITY */
7298
7299 #endif /* HAVE_SCHED_H */
7300
7301
7302 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
7303 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
7304 # define DEV_PTY_FILE "/dev/ptc"
7305 # define HAVE_DEV_PTMX
7306 #else
7307 # define DEV_PTY_FILE "/dev/ptmx"
7308 #endif
7309
7310 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
7311 #ifdef HAVE_PTY_H
7312 #include <pty.h>
7313 #ifdef HAVE_UTMP_H
7314 #include <utmp.h>
7315 #endif /* HAVE_UTMP_H */
7316 #elif defined(HAVE_LIBUTIL_H)
7317 #include <libutil.h>
7318 #elif defined(HAVE_UTIL_H)
7319 #include <util.h>
7320 #endif /* HAVE_PTY_H */
7321 #ifdef HAVE_STROPTS_H
7322 #include <stropts.h>
7323 #endif
7324 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
7325
7326
7327 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7328 /*[clinic input]
7329 os.openpty
7330
7331 Open a pseudo-terminal.
7332
7333 Return a tuple of (master_fd, slave_fd) containing open file descriptors
7334 for both the master and slave ends.
7335 [clinic start generated code]*/
7336
7337 static PyObject *
os_openpty_impl(PyObject * module)7338 os_openpty_impl(PyObject *module)
7339 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
7340 {
7341 int master_fd = -1, slave_fd = -1;
7342 #ifndef HAVE_OPENPTY
7343 char * slave_name;
7344 #endif
7345 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
7346 PyOS_sighandler_t sig_saved;
7347 #if defined(__sun) && defined(__SVR4)
7348 extern char *ptsname(int fildes);
7349 #endif
7350 #endif
7351
7352 #ifdef HAVE_OPENPTY
7353 if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
7354 goto posix_error;
7355
7356 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7357 goto error;
7358 if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
7359 goto error;
7360
7361 #elif defined(HAVE__GETPTY)
7362 slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
7363 if (slave_name == NULL)
7364 goto posix_error;
7365 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7366 goto error;
7367
7368 slave_fd = _Py_open(slave_name, O_RDWR);
7369 if (slave_fd < 0)
7370 goto error;
7371
7372 #else
7373 master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
7374 if (master_fd < 0)
7375 goto posix_error;
7376
7377 sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
7378
7379 /* change permission of slave */
7380 if (grantpt(master_fd) < 0) {
7381 PyOS_setsig(SIGCHLD, sig_saved);
7382 goto posix_error;
7383 }
7384
7385 /* unlock slave */
7386 if (unlockpt(master_fd) < 0) {
7387 PyOS_setsig(SIGCHLD, sig_saved);
7388 goto posix_error;
7389 }
7390
7391 PyOS_setsig(SIGCHLD, sig_saved);
7392
7393 slave_name = ptsname(master_fd); /* get name of slave */
7394 if (slave_name == NULL)
7395 goto posix_error;
7396
7397 slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
7398 if (slave_fd == -1)
7399 goto error;
7400
7401 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7402 goto posix_error;
7403
7404 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
7405 ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
7406 ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
7407 #ifndef __hpux
7408 ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
7409 #endif /* __hpux */
7410 #endif /* HAVE_CYGWIN */
7411 #endif /* HAVE_OPENPTY */
7412
7413 return Py_BuildValue("(ii)", master_fd, slave_fd);
7414
7415 posix_error:
7416 posix_error();
7417 error:
7418 if (master_fd != -1)
7419 close(master_fd);
7420 if (slave_fd != -1)
7421 close(slave_fd);
7422 return NULL;
7423 }
7424 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
7425
7426
7427 #if defined(HAVE_SETSID) && defined(TIOCSCTTY)
7428 #define HAVE_FALLBACK_LOGIN_TTY 1
7429 #endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
7430
7431 #if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
7432 /*[clinic input]
7433 os.login_tty
7434
7435 fd: fildes
7436 /
7437
7438 Prepare the tty of which fd is a file descriptor for a new login session.
7439
7440 Make the calling process a session leader; make the tty the
7441 controlling tty, the stdin, the stdout, and the stderr of the
7442 calling process; close fd.
7443 [clinic start generated code]*/
7444
7445 static PyObject *
os_login_tty_impl(PyObject * module,int fd)7446 os_login_tty_impl(PyObject *module, int fd)
7447 /*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
7448 {
7449 #ifdef HAVE_LOGIN_TTY
7450 if (login_tty(fd) == -1) {
7451 return posix_error();
7452 }
7453 #else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
7454 /* Establish a new session. */
7455 if (setsid() == -1) {
7456 return posix_error();
7457 }
7458
7459 /* The tty becomes the controlling terminal. */
7460 if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
7461 return posix_error();
7462 }
7463
7464 /* The tty becomes stdin/stdout/stderr */
7465 if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
7466 return posix_error();
7467 }
7468 if (fd > 2) {
7469 close(fd);
7470 }
7471 #endif /* HAVE_LOGIN_TTY */
7472 Py_RETURN_NONE;
7473 }
7474 #endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
7475
7476
7477 #ifdef HAVE_FORKPTY
7478 /*[clinic input]
7479 os.forkpty
7480
7481 Fork a new process with a new pseudo-terminal as controlling tty.
7482
7483 Returns a tuple of (pid, master_fd).
7484 Like fork(), return pid of 0 to the child process,
7485 and pid of child to the parent process.
7486 To both, return fd of newly opened pseudo-terminal.
7487 [clinic start generated code]*/
7488
7489 static PyObject *
os_forkpty_impl(PyObject * module)7490 os_forkpty_impl(PyObject *module)
7491 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
7492 {
7493 int master_fd = -1;
7494 pid_t pid;
7495
7496 if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
7497 PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
7498 return NULL;
7499 }
7500 if (PySys_Audit("os.forkpty", NULL) < 0) {
7501 return NULL;
7502 }
7503 PyOS_BeforeFork();
7504 pid = forkpty(&master_fd, NULL, NULL, NULL);
7505 if (pid == 0) {
7506 /* child: this clobbers and resets the import lock. */
7507 PyOS_AfterFork_Child();
7508 } else {
7509 /* parent: release the import lock. */
7510 PyOS_AfterFork_Parent();
7511 }
7512 if (pid == -1) {
7513 return posix_error();
7514 }
7515 return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
7516 }
7517 #endif /* HAVE_FORKPTY */
7518
7519
7520 #ifdef HAVE_GETEGID
7521 /*[clinic input]
7522 os.getegid
7523
7524 Return the current process's effective group id.
7525 [clinic start generated code]*/
7526
7527 static PyObject *
os_getegid_impl(PyObject * module)7528 os_getegid_impl(PyObject *module)
7529 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
7530 {
7531 return _PyLong_FromGid(getegid());
7532 }
7533 #endif /* HAVE_GETEGID */
7534
7535
7536 #ifdef HAVE_GETEUID
7537 /*[clinic input]
7538 os.geteuid
7539
7540 Return the current process's effective user id.
7541 [clinic start generated code]*/
7542
7543 static PyObject *
os_geteuid_impl(PyObject * module)7544 os_geteuid_impl(PyObject *module)
7545 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
7546 {
7547 return _PyLong_FromUid(geteuid());
7548 }
7549 #endif /* HAVE_GETEUID */
7550
7551
7552 #ifdef HAVE_GETGID
7553 /*[clinic input]
7554 os.getgid
7555
7556 Return the current process's group id.
7557 [clinic start generated code]*/
7558
7559 static PyObject *
os_getgid_impl(PyObject * module)7560 os_getgid_impl(PyObject *module)
7561 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
7562 {
7563 return _PyLong_FromGid(getgid());
7564 }
7565 #endif /* HAVE_GETGID */
7566
7567
7568 #ifdef HAVE_GETPID
7569 /*[clinic input]
7570 os.getpid
7571
7572 Return the current process id.
7573 [clinic start generated code]*/
7574
7575 static PyObject *
os_getpid_impl(PyObject * module)7576 os_getpid_impl(PyObject *module)
7577 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
7578 {
7579 return PyLong_FromPid(getpid());
7580 }
7581 #endif /* HAVE_GETPID */
7582
7583 #ifdef NGROUPS_MAX
7584 #define MAX_GROUPS NGROUPS_MAX
7585 #else
7586 /* defined to be 16 on Solaris7, so this should be a small number */
7587 #define MAX_GROUPS 64
7588 #endif
7589
7590 #ifdef HAVE_GETGROUPLIST
7591
7592 #ifdef __APPLE__
7593 /*[clinic input]
7594 os.getgrouplist
7595
7596 user: str
7597 username to lookup
7598 group as basegid: int
7599 base group id of the user
7600 /
7601
7602 Returns a list of groups to which a user belongs.
7603 [clinic start generated code]*/
7604
7605 static PyObject *
os_getgrouplist_impl(PyObject * module,const char * user,int basegid)7606 os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
7607 /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
7608 #else
7609 /*[clinic input]
7610 os.getgrouplist
7611
7612 user: str
7613 username to lookup
7614 group as basegid: gid_t
7615 base group id of the user
7616 /
7617
7618 Returns a list of groups to which a user belongs.
7619 [clinic start generated code]*/
7620
7621 static PyObject *
7622 os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
7623 /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
7624 #endif
7625 {
7626 int i, ngroups;
7627 PyObject *list;
7628 #ifdef __APPLE__
7629 int *groups;
7630 #else
7631 gid_t *groups;
7632 #endif
7633
7634 /*
7635 * NGROUPS_MAX is defined by POSIX.1 as the maximum
7636 * number of supplimental groups a users can belong to.
7637 * We have to increment it by one because
7638 * getgrouplist() returns both the supplemental groups
7639 * and the primary group, i.e. all of the groups the
7640 * user belongs to.
7641 */
7642 ngroups = 1 + MAX_GROUPS;
7643
7644 while (1) {
7645 #ifdef __APPLE__
7646 groups = PyMem_New(int, ngroups);
7647 #else
7648 groups = PyMem_New(gid_t, ngroups);
7649 #endif
7650 if (groups == NULL) {
7651 return PyErr_NoMemory();
7652 }
7653
7654 int old_ngroups = ngroups;
7655 if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
7656 /* Success */
7657 break;
7658 }
7659
7660 /* getgrouplist() fails if the group list is too small */
7661 PyMem_Free(groups);
7662
7663 if (ngroups > old_ngroups) {
7664 /* If the group list is too small, the glibc implementation of
7665 getgrouplist() sets ngroups to the total number of groups and
7666 returns -1. */
7667 }
7668 else {
7669 /* Double the group list size */
7670 if (ngroups > INT_MAX / 2) {
7671 return PyErr_NoMemory();
7672 }
7673 ngroups *= 2;
7674 }
7675
7676 /* Retry getgrouplist() with a larger group list */
7677 }
7678
7679 #ifdef _Py_MEMORY_SANITIZER
7680 /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
7681 __msan_unpoison(&ngroups, sizeof(ngroups));
7682 __msan_unpoison(groups, ngroups*sizeof(*groups));
7683 #endif
7684
7685 list = PyList_New(ngroups);
7686 if (list == NULL) {
7687 PyMem_Free(groups);
7688 return NULL;
7689 }
7690
7691 for (i = 0; i < ngroups; i++) {
7692 #ifdef __APPLE__
7693 PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7694 #else
7695 PyObject *o = _PyLong_FromGid(groups[i]);
7696 #endif
7697 if (o == NULL) {
7698 Py_DECREF(list);
7699 PyMem_Free(groups);
7700 return NULL;
7701 }
7702 PyList_SET_ITEM(list, i, o);
7703 }
7704
7705 PyMem_Free(groups);
7706
7707 return list;
7708 }
7709 #endif /* HAVE_GETGROUPLIST */
7710
7711
7712 #ifdef HAVE_GETGROUPS
7713 /*[clinic input]
7714 os.getgroups
7715
7716 Return list of supplemental group IDs for the process.
7717 [clinic start generated code]*/
7718
7719 static PyObject *
os_getgroups_impl(PyObject * module)7720 os_getgroups_impl(PyObject *module)
7721 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
7722 {
7723 // Call getgroups with length 0 to get the actual number of groups
7724 int n = getgroups(0, NULL);
7725 if (n < 0) {
7726 return posix_error();
7727 }
7728
7729 if (n == 0) {
7730 return PyList_New(0);
7731 }
7732
7733 gid_t *grouplist = PyMem_New(gid_t, n);
7734 if (grouplist == NULL) {
7735 return PyErr_NoMemory();
7736 }
7737
7738 n = getgroups(n, grouplist);
7739 if (n == -1) {
7740 PyMem_Free(grouplist);
7741 return posix_error();
7742 }
7743
7744 PyObject *result = PyList_New(n);
7745 if (result == NULL) {
7746 goto error;
7747 }
7748
7749 for (int i = 0; i < n; ++i) {
7750 PyObject *group = _PyLong_FromGid(grouplist[i]);
7751 if (group == NULL) {
7752 goto error;
7753 }
7754 PyList_SET_ITEM(result, i, group);
7755 }
7756 PyMem_Free(grouplist);
7757
7758 return result;
7759
7760 error:
7761 PyMem_Free(grouplist);
7762 Py_XDECREF(result);
7763 return NULL;
7764 }
7765 #endif /* HAVE_GETGROUPS */
7766
7767 #ifdef HAVE_INITGROUPS
7768 #ifdef __APPLE__
7769 /*[clinic input]
7770 os.initgroups
7771
7772 username as oname: FSConverter
7773 gid: int
7774 /
7775
7776 Initialize the group access list.
7777
7778 Call the system initgroups() to initialize the group access list with all of
7779 the groups of which the specified username is a member, plus the specified
7780 group id.
7781 [clinic start generated code]*/
7782
7783 static PyObject *
os_initgroups_impl(PyObject * module,PyObject * oname,int gid)7784 os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
7785 /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
7786 #else
7787 /*[clinic input]
7788 os.initgroups
7789
7790 username as oname: FSConverter
7791 gid: gid_t
7792 /
7793
7794 Initialize the group access list.
7795
7796 Call the system initgroups() to initialize the group access list with all of
7797 the groups of which the specified username is a member, plus the specified
7798 group id.
7799 [clinic start generated code]*/
7800
7801 static PyObject *
7802 os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
7803 /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
7804 #endif
7805 {
7806 const char *username = PyBytes_AS_STRING(oname);
7807
7808 if (initgroups(username, gid) == -1)
7809 return PyErr_SetFromErrno(PyExc_OSError);
7810
7811 Py_RETURN_NONE;
7812 }
7813 #endif /* HAVE_INITGROUPS */
7814
7815
7816 #ifdef HAVE_GETPGID
7817 /*[clinic input]
7818 os.getpgid
7819
7820 pid: pid_t
7821
7822 Call the system call getpgid(), and return the result.
7823 [clinic start generated code]*/
7824
7825 static PyObject *
os_getpgid_impl(PyObject * module,pid_t pid)7826 os_getpgid_impl(PyObject *module, pid_t pid)
7827 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7828 {
7829 pid_t pgid = getpgid(pid);
7830 if (pgid < 0)
7831 return posix_error();
7832 return PyLong_FromPid(pgid);
7833 }
7834 #endif /* HAVE_GETPGID */
7835
7836
7837 #ifdef HAVE_GETPGRP
7838 /*[clinic input]
7839 os.getpgrp
7840
7841 Return the current process group id.
7842 [clinic start generated code]*/
7843
7844 static PyObject *
os_getpgrp_impl(PyObject * module)7845 os_getpgrp_impl(PyObject *module)
7846 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7847 {
7848 #ifdef GETPGRP_HAVE_ARG
7849 return PyLong_FromPid(getpgrp(0));
7850 #else /* GETPGRP_HAVE_ARG */
7851 return PyLong_FromPid(getpgrp());
7852 #endif /* GETPGRP_HAVE_ARG */
7853 }
7854 #endif /* HAVE_GETPGRP */
7855
7856
7857 #ifdef HAVE_SETPGRP
7858 /*[clinic input]
7859 os.setpgrp
7860
7861 Make the current process the leader of its process group.
7862 [clinic start generated code]*/
7863
7864 static PyObject *
os_setpgrp_impl(PyObject * module)7865 os_setpgrp_impl(PyObject *module)
7866 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7867 {
7868 #ifdef SETPGRP_HAVE_ARG
7869 if (setpgrp(0, 0) < 0)
7870 #else /* SETPGRP_HAVE_ARG */
7871 if (setpgrp() < 0)
7872 #endif /* SETPGRP_HAVE_ARG */
7873 return posix_error();
7874 Py_RETURN_NONE;
7875 }
7876 #endif /* HAVE_SETPGRP */
7877
7878 #ifdef HAVE_GETPPID
7879
7880 #ifdef MS_WINDOWS
7881 #include <tlhelp32.h>
7882
7883 static PyObject*
win32_getppid()7884 win32_getppid()
7885 {
7886 HANDLE snapshot;
7887 pid_t mypid;
7888 PyObject* result = NULL;
7889 BOOL have_record;
7890 PROCESSENTRY32 pe;
7891
7892 mypid = getpid(); /* This function never fails */
7893
7894 snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7895 if (snapshot == INVALID_HANDLE_VALUE)
7896 return PyErr_SetFromWindowsErr(GetLastError());
7897
7898 pe.dwSize = sizeof(pe);
7899 have_record = Process32First(snapshot, &pe);
7900 while (have_record) {
7901 if (mypid == (pid_t)pe.th32ProcessID) {
7902 /* We could cache the ulong value in a static variable. */
7903 result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7904 break;
7905 }
7906
7907 have_record = Process32Next(snapshot, &pe);
7908 }
7909
7910 /* If our loop exits and our pid was not found (result will be NULL)
7911 * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7912 * error anyway, so let's raise it. */
7913 if (!result)
7914 result = PyErr_SetFromWindowsErr(GetLastError());
7915
7916 CloseHandle(snapshot);
7917
7918 return result;
7919 }
7920 #endif /*MS_WINDOWS*/
7921
7922
7923 /*[clinic input]
7924 os.getppid
7925
7926 Return the parent's process id.
7927
7928 If the parent process has already exited, Windows machines will still
7929 return its id; others systems will return the id of the 'init' process (1).
7930 [clinic start generated code]*/
7931
7932 static PyObject *
os_getppid_impl(PyObject * module)7933 os_getppid_impl(PyObject *module)
7934 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7935 {
7936 #ifdef MS_WINDOWS
7937 return win32_getppid();
7938 #else
7939 return PyLong_FromPid(getppid());
7940 #endif
7941 }
7942 #endif /* HAVE_GETPPID */
7943
7944
7945 #ifdef HAVE_GETLOGIN
7946 /*[clinic input]
7947 os.getlogin
7948
7949 Return the actual login name.
7950 [clinic start generated code]*/
7951
7952 static PyObject *
os_getlogin_impl(PyObject * module)7953 os_getlogin_impl(PyObject *module)
7954 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7955 {
7956 PyObject *result = NULL;
7957 #ifdef MS_WINDOWS
7958 wchar_t user_name[UNLEN + 1];
7959 DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7960
7961 if (GetUserNameW(user_name, &num_chars)) {
7962 /* num_chars is the number of unicode chars plus null terminator */
7963 result = PyUnicode_FromWideChar(user_name, num_chars - 1);
7964 }
7965 else
7966 result = PyErr_SetFromWindowsErr(GetLastError());
7967 #else
7968 char *name;
7969 int old_errno = errno;
7970
7971 errno = 0;
7972 name = getlogin();
7973 if (name == NULL) {
7974 if (errno)
7975 posix_error();
7976 else
7977 PyErr_SetString(PyExc_OSError, "unable to determine login name");
7978 }
7979 else
7980 result = PyUnicode_DecodeFSDefault(name);
7981 errno = old_errno;
7982 #endif
7983 return result;
7984 }
7985 #endif /* HAVE_GETLOGIN */
7986
7987
7988 #ifdef HAVE_GETUID
7989 /*[clinic input]
7990 os.getuid
7991
7992 Return the current process's user id.
7993 [clinic start generated code]*/
7994
7995 static PyObject *
os_getuid_impl(PyObject * module)7996 os_getuid_impl(PyObject *module)
7997 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7998 {
7999 return _PyLong_FromUid(getuid());
8000 }
8001 #endif /* HAVE_GETUID */
8002
8003
8004 #ifdef MS_WINDOWS
8005 #define HAVE_KILL
8006 #endif /* MS_WINDOWS */
8007
8008 #ifdef HAVE_KILL
8009 /*[clinic input]
8010 os.kill
8011
8012 pid: pid_t
8013 signal: Py_ssize_t
8014 /
8015
8016 Kill a process with a signal.
8017 [clinic start generated code]*/
8018
8019 static PyObject *
os_kill_impl(PyObject * module,pid_t pid,Py_ssize_t signal)8020 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
8021 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
8022 {
8023 if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
8024 return NULL;
8025 }
8026 #ifndef MS_WINDOWS
8027 if (kill(pid, (int)signal) == -1) {
8028 return posix_error();
8029 }
8030
8031 // Check immediately if the signal was sent to the current process.
8032 // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
8033 // is cheap.
8034 if (PyErr_CheckSignals()) {
8035 return NULL;
8036 }
8037
8038 Py_RETURN_NONE;
8039 #else /* !MS_WINDOWS */
8040 PyObject *result;
8041 DWORD sig = (DWORD)signal;
8042 DWORD err;
8043 HANDLE handle;
8044
8045 /* Console processes which share a common console can be sent CTRL+C or
8046 CTRL+BREAK events, provided they handle said events. */
8047 if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
8048 if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
8049 err = GetLastError();
8050 PyErr_SetFromWindowsErr(err);
8051 }
8052 else
8053 Py_RETURN_NONE;
8054 }
8055
8056 /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
8057 attempt to open and terminate the process. */
8058 handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
8059 if (handle == NULL) {
8060 err = GetLastError();
8061 return PyErr_SetFromWindowsErr(err);
8062 }
8063
8064 if (TerminateProcess(handle, sig) == 0) {
8065 err = GetLastError();
8066 result = PyErr_SetFromWindowsErr(err);
8067 } else {
8068 Py_INCREF(Py_None);
8069 result = Py_None;
8070 }
8071
8072 CloseHandle(handle);
8073 return result;
8074 #endif /* !MS_WINDOWS */
8075 }
8076 #endif /* HAVE_KILL */
8077
8078
8079 #ifdef HAVE_KILLPG
8080 /*[clinic input]
8081 os.killpg
8082
8083 pgid: pid_t
8084 signal: int
8085 /
8086
8087 Kill a process group with a signal.
8088 [clinic start generated code]*/
8089
8090 static PyObject *
os_killpg_impl(PyObject * module,pid_t pgid,int signal)8091 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
8092 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
8093 {
8094 if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
8095 return NULL;
8096 }
8097 /* XXX some man pages make the `pgid` parameter an int, others
8098 a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
8099 take the same type. Moreover, pid_t is always at least as wide as
8100 int (else compilation of this module fails), which is safe. */
8101 if (killpg(pgid, signal) == -1)
8102 return posix_error();
8103 Py_RETURN_NONE;
8104 }
8105 #endif /* HAVE_KILLPG */
8106
8107
8108 #ifdef HAVE_PLOCK
8109 #ifdef HAVE_SYS_LOCK_H
8110 #include <sys/lock.h>
8111 #endif
8112
8113 /*[clinic input]
8114 os.plock
8115 op: int
8116 /
8117
8118 Lock program segments into memory.");
8119 [clinic start generated code]*/
8120
8121 static PyObject *
os_plock_impl(PyObject * module,int op)8122 os_plock_impl(PyObject *module, int op)
8123 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
8124 {
8125 if (plock(op) == -1)
8126 return posix_error();
8127 Py_RETURN_NONE;
8128 }
8129 #endif /* HAVE_PLOCK */
8130
8131
8132 #ifdef HAVE_SETUID
8133 /*[clinic input]
8134 os.setuid
8135
8136 uid: uid_t
8137 /
8138
8139 Set the current process's user id.
8140 [clinic start generated code]*/
8141
8142 static PyObject *
os_setuid_impl(PyObject * module,uid_t uid)8143 os_setuid_impl(PyObject *module, uid_t uid)
8144 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
8145 {
8146 if (setuid(uid) < 0)
8147 return posix_error();
8148 Py_RETURN_NONE;
8149 }
8150 #endif /* HAVE_SETUID */
8151
8152
8153 #ifdef HAVE_SETEUID
8154 /*[clinic input]
8155 os.seteuid
8156
8157 euid: uid_t
8158 /
8159
8160 Set the current process's effective user id.
8161 [clinic start generated code]*/
8162
8163 static PyObject *
os_seteuid_impl(PyObject * module,uid_t euid)8164 os_seteuid_impl(PyObject *module, uid_t euid)
8165 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
8166 {
8167 if (seteuid(euid) < 0)
8168 return posix_error();
8169 Py_RETURN_NONE;
8170 }
8171 #endif /* HAVE_SETEUID */
8172
8173
8174 #ifdef HAVE_SETEGID
8175 /*[clinic input]
8176 os.setegid
8177
8178 egid: gid_t
8179 /
8180
8181 Set the current process's effective group id.
8182 [clinic start generated code]*/
8183
8184 static PyObject *
os_setegid_impl(PyObject * module,gid_t egid)8185 os_setegid_impl(PyObject *module, gid_t egid)
8186 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
8187 {
8188 if (setegid(egid) < 0)
8189 return posix_error();
8190 Py_RETURN_NONE;
8191 }
8192 #endif /* HAVE_SETEGID */
8193
8194
8195 #ifdef HAVE_SETREUID
8196 /*[clinic input]
8197 os.setreuid
8198
8199 ruid: uid_t
8200 euid: uid_t
8201 /
8202
8203 Set the current process's real and effective user ids.
8204 [clinic start generated code]*/
8205
8206 static PyObject *
os_setreuid_impl(PyObject * module,uid_t ruid,uid_t euid)8207 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
8208 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
8209 {
8210 if (setreuid(ruid, euid) < 0) {
8211 return posix_error();
8212 } else {
8213 Py_RETURN_NONE;
8214 }
8215 }
8216 #endif /* HAVE_SETREUID */
8217
8218
8219 #ifdef HAVE_SETREGID
8220 /*[clinic input]
8221 os.setregid
8222
8223 rgid: gid_t
8224 egid: gid_t
8225 /
8226
8227 Set the current process's real and effective group ids.
8228 [clinic start generated code]*/
8229
8230 static PyObject *
os_setregid_impl(PyObject * module,gid_t rgid,gid_t egid)8231 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
8232 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
8233 {
8234 if (setregid(rgid, egid) < 0)
8235 return posix_error();
8236 Py_RETURN_NONE;
8237 }
8238 #endif /* HAVE_SETREGID */
8239
8240
8241 #ifdef HAVE_SETGID
8242 /*[clinic input]
8243 os.setgid
8244 gid: gid_t
8245 /
8246
8247 Set the current process's group id.
8248 [clinic start generated code]*/
8249
8250 static PyObject *
os_setgid_impl(PyObject * module,gid_t gid)8251 os_setgid_impl(PyObject *module, gid_t gid)
8252 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
8253 {
8254 if (setgid(gid) < 0)
8255 return posix_error();
8256 Py_RETURN_NONE;
8257 }
8258 #endif /* HAVE_SETGID */
8259
8260
8261 #ifdef HAVE_SETGROUPS
8262 /*[clinic input]
8263 os.setgroups
8264
8265 groups: object
8266 /
8267
8268 Set the groups of the current process to list.
8269 [clinic start generated code]*/
8270
8271 static PyObject *
os_setgroups(PyObject * module,PyObject * groups)8272 os_setgroups(PyObject *module, PyObject *groups)
8273 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
8274 {
8275 if (!PySequence_Check(groups)) {
8276 PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
8277 return NULL;
8278 }
8279 Py_ssize_t len = PySequence_Size(groups);
8280 if (len < 0) {
8281 return NULL;
8282 }
8283 if (len > MAX_GROUPS) {
8284 PyErr_SetString(PyExc_ValueError, "too many groups");
8285 return NULL;
8286 }
8287
8288 gid_t *grouplist = PyMem_New(gid_t, len);
8289 for (Py_ssize_t i = 0; i < len; i++) {
8290 PyObject *elem;
8291 elem = PySequence_GetItem(groups, i);
8292 if (!elem) {
8293 PyMem_Free(grouplist);
8294 return NULL;
8295 }
8296 if (!PyLong_Check(elem)) {
8297 PyErr_SetString(PyExc_TypeError,
8298 "groups must be integers");
8299 Py_DECREF(elem);
8300 PyMem_Free(grouplist);
8301 return NULL;
8302 } else {
8303 if (!_Py_Gid_Converter(elem, &grouplist[i])) {
8304 Py_DECREF(elem);
8305 PyMem_Free(grouplist);
8306 return NULL;
8307 }
8308 }
8309 Py_DECREF(elem);
8310 }
8311
8312 if (setgroups(len, grouplist) < 0) {
8313 PyMem_Free(grouplist);
8314 return posix_error();
8315 }
8316 PyMem_Free(grouplist);
8317 Py_RETURN_NONE;
8318 }
8319 #endif /* HAVE_SETGROUPS */
8320
8321 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
8322 static PyObject *
wait_helper(PyObject * module,pid_t pid,int status,struct rusage * ru)8323 wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
8324 {
8325 PyObject *result;
8326 PyObject *struct_rusage;
8327
8328 if (pid == -1)
8329 return posix_error();
8330
8331 // If wait succeeded but no child was ready to report status, ru will not
8332 // have been populated.
8333 if (pid == 0) {
8334 memset(ru, 0, sizeof(*ru));
8335 }
8336
8337 PyObject *m = PyImport_ImportModule("resource");
8338 if (m == NULL)
8339 return NULL;
8340 struct_rusage = PyObject_GetAttr(m, get_posix_state(module)->struct_rusage);
8341 Py_DECREF(m);
8342 if (struct_rusage == NULL)
8343 return NULL;
8344
8345 /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
8346 result = PyStructSequence_New((PyTypeObject*) struct_rusage);
8347 Py_DECREF(struct_rusage);
8348 if (!result)
8349 return NULL;
8350
8351 #ifndef doubletime
8352 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
8353 #endif
8354
8355 PyStructSequence_SET_ITEM(result, 0,
8356 PyFloat_FromDouble(doubletime(ru->ru_utime)));
8357 PyStructSequence_SET_ITEM(result, 1,
8358 PyFloat_FromDouble(doubletime(ru->ru_stime)));
8359 #define SET_INT(result, index, value)\
8360 PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
8361 SET_INT(result, 2, ru->ru_maxrss);
8362 SET_INT(result, 3, ru->ru_ixrss);
8363 SET_INT(result, 4, ru->ru_idrss);
8364 SET_INT(result, 5, ru->ru_isrss);
8365 SET_INT(result, 6, ru->ru_minflt);
8366 SET_INT(result, 7, ru->ru_majflt);
8367 SET_INT(result, 8, ru->ru_nswap);
8368 SET_INT(result, 9, ru->ru_inblock);
8369 SET_INT(result, 10, ru->ru_oublock);
8370 SET_INT(result, 11, ru->ru_msgsnd);
8371 SET_INT(result, 12, ru->ru_msgrcv);
8372 SET_INT(result, 13, ru->ru_nsignals);
8373 SET_INT(result, 14, ru->ru_nvcsw);
8374 SET_INT(result, 15, ru->ru_nivcsw);
8375 #undef SET_INT
8376
8377 if (PyErr_Occurred()) {
8378 Py_DECREF(result);
8379 return NULL;
8380 }
8381
8382 return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
8383 }
8384 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
8385
8386
8387 #ifdef HAVE_WAIT3
8388 /*[clinic input]
8389 os.wait3
8390
8391 options: int
8392 Wait for completion of a child process.
8393
8394 Returns a tuple of information about the child process:
8395 (pid, status, rusage)
8396 [clinic start generated code]*/
8397
8398 static PyObject *
os_wait3_impl(PyObject * module,int options)8399 os_wait3_impl(PyObject *module, int options)
8400 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
8401 {
8402 pid_t pid;
8403 struct rusage ru;
8404 int async_err = 0;
8405 WAIT_TYPE status;
8406 WAIT_STATUS_INT(status) = 0;
8407
8408 do {
8409 Py_BEGIN_ALLOW_THREADS
8410 pid = wait3(&status, options, &ru);
8411 Py_END_ALLOW_THREADS
8412 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8413 if (pid < 0)
8414 return (!async_err) ? posix_error() : NULL;
8415
8416 return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
8417 }
8418 #endif /* HAVE_WAIT3 */
8419
8420
8421 #ifdef HAVE_WAIT4
8422 /*[clinic input]
8423
8424 os.wait4
8425
8426 pid: pid_t
8427 options: int
8428
8429 Wait for completion of a specific child process.
8430
8431 Returns a tuple of information about the child process:
8432 (pid, status, rusage)
8433 [clinic start generated code]*/
8434
8435 static PyObject *
os_wait4_impl(PyObject * module,pid_t pid,int options)8436 os_wait4_impl(PyObject *module, pid_t pid, int options)
8437 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
8438 {
8439 pid_t res;
8440 struct rusage ru;
8441 int async_err = 0;
8442 WAIT_TYPE status;
8443 WAIT_STATUS_INT(status) = 0;
8444
8445 do {
8446 Py_BEGIN_ALLOW_THREADS
8447 res = wait4(pid, &status, options, &ru);
8448 Py_END_ALLOW_THREADS
8449 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8450 if (res < 0)
8451 return (!async_err) ? posix_error() : NULL;
8452
8453 return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
8454 }
8455 #endif /* HAVE_WAIT4 */
8456
8457
8458 #if defined(HAVE_WAITID) && !defined(__APPLE__)
8459 /*[clinic input]
8460 os.waitid
8461
8462 idtype: idtype_t
8463 Must be one of be P_PID, P_PGID or P_ALL.
8464 id: id_t
8465 The id to wait on.
8466 options: int
8467 Constructed from the ORing of one or more of WEXITED, WSTOPPED
8468 or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
8469 /
8470
8471 Returns the result of waiting for a process or processes.
8472
8473 Returns either waitid_result or None if WNOHANG is specified and there are
8474 no children in a waitable state.
8475 [clinic start generated code]*/
8476
8477 static PyObject *
os_waitid_impl(PyObject * module,idtype_t idtype,id_t id,int options)8478 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
8479 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
8480 {
8481 PyObject *result;
8482 int res;
8483 int async_err = 0;
8484 siginfo_t si;
8485 si.si_pid = 0;
8486
8487 do {
8488 Py_BEGIN_ALLOW_THREADS
8489 res = waitid(idtype, id, &si, options);
8490 Py_END_ALLOW_THREADS
8491 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8492 if (res < 0)
8493 return (!async_err) ? posix_error() : NULL;
8494
8495 if (si.si_pid == 0)
8496 Py_RETURN_NONE;
8497
8498 PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
8499 result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
8500 if (!result)
8501 return NULL;
8502
8503 PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
8504 PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
8505 PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
8506 PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
8507 PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
8508 if (PyErr_Occurred()) {
8509 Py_DECREF(result);
8510 return NULL;
8511 }
8512
8513 return result;
8514 }
8515 #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
8516
8517
8518 #if defined(HAVE_WAITPID)
8519 /*[clinic input]
8520 os.waitpid
8521 pid: pid_t
8522 options: int
8523 /
8524
8525 Wait for completion of a given child process.
8526
8527 Returns a tuple of information regarding the child process:
8528 (pid, status)
8529
8530 The options argument is ignored on Windows.
8531 [clinic start generated code]*/
8532
8533 static PyObject *
os_waitpid_impl(PyObject * module,pid_t pid,int options)8534 os_waitpid_impl(PyObject *module, pid_t pid, int options)
8535 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
8536 {
8537 pid_t res;
8538 int async_err = 0;
8539 WAIT_TYPE status;
8540 WAIT_STATUS_INT(status) = 0;
8541
8542 do {
8543 Py_BEGIN_ALLOW_THREADS
8544 res = waitpid(pid, &status, options);
8545 Py_END_ALLOW_THREADS
8546 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8547 if (res < 0)
8548 return (!async_err) ? posix_error() : NULL;
8549
8550 return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
8551 }
8552 #elif defined(HAVE_CWAIT)
8553 /* MS C has a variant of waitpid() that's usable for most purposes. */
8554 /*[clinic input]
8555 os.waitpid
8556 pid: intptr_t
8557 options: int
8558 /
8559
8560 Wait for completion of a given process.
8561
8562 Returns a tuple of information regarding the process:
8563 (pid, status << 8)
8564
8565 The options argument is ignored on Windows.
8566 [clinic start generated code]*/
8567
8568 static PyObject *
os_waitpid_impl(PyObject * module,intptr_t pid,int options)8569 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
8570 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
8571 {
8572 int status;
8573 intptr_t res;
8574 int async_err = 0;
8575
8576 do {
8577 Py_BEGIN_ALLOW_THREADS
8578 _Py_BEGIN_SUPPRESS_IPH
8579 res = _cwait(&status, pid, options);
8580 _Py_END_SUPPRESS_IPH
8581 Py_END_ALLOW_THREADS
8582 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8583 if (res < 0)
8584 return (!async_err) ? posix_error() : NULL;
8585
8586 unsigned long long ustatus = (unsigned int)status;
8587
8588 /* shift the status left a byte so this is more like the POSIX waitpid */
8589 return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
8590 }
8591 #endif
8592
8593
8594 #ifdef HAVE_WAIT
8595 /*[clinic input]
8596 os.wait
8597
8598 Wait for completion of a child process.
8599
8600 Returns a tuple of information about the child process:
8601 (pid, status)
8602 [clinic start generated code]*/
8603
8604 static PyObject *
os_wait_impl(PyObject * module)8605 os_wait_impl(PyObject *module)
8606 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
8607 {
8608 pid_t pid;
8609 int async_err = 0;
8610 WAIT_TYPE status;
8611 WAIT_STATUS_INT(status) = 0;
8612
8613 do {
8614 Py_BEGIN_ALLOW_THREADS
8615 pid = wait(&status);
8616 Py_END_ALLOW_THREADS
8617 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8618 if (pid < 0)
8619 return (!async_err) ? posix_error() : NULL;
8620
8621 return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
8622 }
8623 #endif /* HAVE_WAIT */
8624
8625 #if defined(__linux__) && defined(__NR_pidfd_open)
8626 /*[clinic input]
8627 os.pidfd_open
8628 pid: pid_t
8629 flags: unsigned_int = 0
8630
8631 Return a file descriptor referring to the process *pid*.
8632
8633 The descriptor can be used to perform process management without races and
8634 signals.
8635 [clinic start generated code]*/
8636
8637 static PyObject *
os_pidfd_open_impl(PyObject * module,pid_t pid,unsigned int flags)8638 os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
8639 /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
8640 {
8641 int fd = syscall(__NR_pidfd_open, pid, flags);
8642 if (fd < 0) {
8643 return posix_error();
8644 }
8645 return PyLong_FromLong(fd);
8646 }
8647 #endif
8648
8649
8650 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
8651 /*[clinic input]
8652 os.readlink
8653
8654 path: path_t
8655 *
8656 dir_fd: dir_fd(requires='readlinkat') = None
8657
8658 Return a string representing the path to which the symbolic link points.
8659
8660 If dir_fd is not None, it should be a file descriptor open to a directory,
8661 and path should be relative; path will then be relative to that directory.
8662
8663 dir_fd may not be implemented on your platform. If it is unavailable,
8664 using it will raise a NotImplementedError.
8665 [clinic start generated code]*/
8666
8667 static PyObject *
os_readlink_impl(PyObject * module,path_t * path,int dir_fd)8668 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
8669 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
8670 {
8671 #if defined(HAVE_READLINK)
8672 char buffer[MAXPATHLEN+1];
8673 ssize_t length;
8674 #ifdef HAVE_READLINKAT
8675 int readlinkat_unavailable = 0;
8676 #endif
8677
8678 Py_BEGIN_ALLOW_THREADS
8679 #ifdef HAVE_READLINKAT
8680 if (dir_fd != DEFAULT_DIR_FD) {
8681 if (HAVE_READLINKAT_RUNTIME) {
8682 length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
8683 } else {
8684 readlinkat_unavailable = 1;
8685 }
8686 } else
8687 #endif
8688 length = readlink(path->narrow, buffer, MAXPATHLEN);
8689 Py_END_ALLOW_THREADS
8690
8691 #ifdef HAVE_READLINKAT
8692 if (readlinkat_unavailable) {
8693 argument_unavailable_error(NULL, "dir_fd");
8694 return NULL;
8695 }
8696 #endif
8697
8698 if (length < 0) {
8699 return path_error(path);
8700 }
8701 buffer[length] = '\0';
8702
8703 if (PyUnicode_Check(path->object))
8704 return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
8705 else
8706 return PyBytes_FromStringAndSize(buffer, length);
8707 #elif defined(MS_WINDOWS)
8708 DWORD n_bytes_returned;
8709 DWORD io_result = 0;
8710 HANDLE reparse_point_handle;
8711 char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
8712 _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
8713 PyObject *result = NULL;
8714
8715 /* First get a handle to the reparse point */
8716 Py_BEGIN_ALLOW_THREADS
8717 reparse_point_handle = CreateFileW(
8718 path->wide,
8719 0,
8720 0,
8721 0,
8722 OPEN_EXISTING,
8723 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
8724 0);
8725 if (reparse_point_handle != INVALID_HANDLE_VALUE) {
8726 /* New call DeviceIoControl to read the reparse point */
8727 io_result = DeviceIoControl(
8728 reparse_point_handle,
8729 FSCTL_GET_REPARSE_POINT,
8730 0, 0, /* in buffer */
8731 target_buffer, sizeof(target_buffer),
8732 &n_bytes_returned,
8733 0 /* we're not using OVERLAPPED_IO */
8734 );
8735 CloseHandle(reparse_point_handle);
8736 }
8737 Py_END_ALLOW_THREADS
8738
8739 if (io_result == 0) {
8740 return path_error(path);
8741 }
8742
8743 wchar_t *name = NULL;
8744 Py_ssize_t nameLen = 0;
8745 if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
8746 {
8747 name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
8748 rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
8749 nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8750 }
8751 else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
8752 {
8753 name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8754 rdb->MountPointReparseBuffer.SubstituteNameOffset);
8755 nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8756 }
8757 else
8758 {
8759 PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8760 }
8761 if (name) {
8762 if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8763 /* Our buffer is mutable, so this is okay */
8764 name[1] = L'\\';
8765 }
8766 result = PyUnicode_FromWideChar(name, nameLen);
8767 if (result && path->narrow) {
8768 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8769 }
8770 }
8771 return result;
8772 #endif
8773 }
8774 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8775
8776 #if defined(MS_WINDOWS)
8777
8778 /* Remove the last portion of the path - return 0 on success */
8779 static int
_dirnameW(WCHAR * path)8780 _dirnameW(WCHAR *path)
8781 {
8782 WCHAR *ptr;
8783 size_t length = wcsnlen_s(path, MAX_PATH);
8784 if (length == MAX_PATH) {
8785 return -1;
8786 }
8787
8788 /* walk the path from the end until a backslash is encountered */
8789 for(ptr = path + length; ptr != path; ptr--) {
8790 if (*ptr == L'\\' || *ptr == L'/') {
8791 break;
8792 }
8793 }
8794 *ptr = 0;
8795 return 0;
8796 }
8797
8798 #endif
8799
8800 #ifdef HAVE_SYMLINK
8801
8802 #if defined(MS_WINDOWS)
8803
8804 /* Is this path absolute? */
8805 static int
_is_absW(const WCHAR * path)8806 _is_absW(const WCHAR *path)
8807 {
8808 return path[0] == L'\\' || path[0] == L'/' ||
8809 (path[0] && path[1] == L':');
8810 }
8811
8812 /* join root and rest with a backslash - return 0 on success */
8813 static int
_joinW(WCHAR * dest_path,const WCHAR * root,const WCHAR * rest)8814 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8815 {
8816 if (_is_absW(rest)) {
8817 return wcscpy_s(dest_path, MAX_PATH, rest);
8818 }
8819
8820 if (wcscpy_s(dest_path, MAX_PATH, root)) {
8821 return -1;
8822 }
8823
8824 if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8825 return -1;
8826 }
8827
8828 return wcscat_s(dest_path, MAX_PATH, rest);
8829 }
8830
8831 /* Return True if the path at src relative to dest is a directory */
8832 static int
_check_dirW(LPCWSTR src,LPCWSTR dest)8833 _check_dirW(LPCWSTR src, LPCWSTR dest)
8834 {
8835 WIN32_FILE_ATTRIBUTE_DATA src_info;
8836 WCHAR dest_parent[MAX_PATH];
8837 WCHAR src_resolved[MAX_PATH] = L"";
8838
8839 /* dest_parent = os.path.dirname(dest) */
8840 if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8841 _dirnameW(dest_parent)) {
8842 return 0;
8843 }
8844 /* src_resolved = os.path.join(dest_parent, src) */
8845 if (_joinW(src_resolved, dest_parent, src)) {
8846 return 0;
8847 }
8848 return (
8849 GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8850 && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8851 );
8852 }
8853 #endif
8854
8855
8856 /*[clinic input]
8857 os.symlink
8858 src: path_t
8859 dst: path_t
8860 target_is_directory: bool = False
8861 *
8862 dir_fd: dir_fd(requires='symlinkat')=None
8863
8864 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8865
8866 Create a symbolic link pointing to src named dst.
8867
8868 target_is_directory is required on Windows if the target is to be
8869 interpreted as a directory. (On Windows, symlink requires
8870 Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8871 target_is_directory is ignored on non-Windows platforms.
8872
8873 If dir_fd is not None, it should be a file descriptor open to a directory,
8874 and path should be relative; path will then be relative to that directory.
8875 dir_fd may not be implemented on your platform.
8876 If it is unavailable, using it will raise a NotImplementedError.
8877
8878 [clinic start generated code]*/
8879
8880 static PyObject *
os_symlink_impl(PyObject * module,path_t * src,path_t * dst,int target_is_directory,int dir_fd)8881 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8882 int target_is_directory, int dir_fd)
8883 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8884 {
8885 #ifdef MS_WINDOWS
8886 DWORD result;
8887 DWORD flags = 0;
8888
8889 /* Assumed true, set to false if detected to not be available. */
8890 static int windows_has_symlink_unprivileged_flag = TRUE;
8891 #else
8892 int result;
8893 #ifdef HAVE_SYMLINKAT
8894 int symlinkat_unavailable = 0;
8895 #endif
8896 #endif
8897
8898 if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8899 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8900 return NULL;
8901 }
8902
8903 #ifdef MS_WINDOWS
8904
8905 if (windows_has_symlink_unprivileged_flag) {
8906 /* Allow non-admin symlinks if system allows it. */
8907 flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8908 }
8909
8910 Py_BEGIN_ALLOW_THREADS
8911 _Py_BEGIN_SUPPRESS_IPH
8912 /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8913 if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8914 flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8915 }
8916
8917 result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8918 _Py_END_SUPPRESS_IPH
8919 Py_END_ALLOW_THREADS
8920
8921 if (windows_has_symlink_unprivileged_flag && !result &&
8922 ERROR_INVALID_PARAMETER == GetLastError()) {
8923
8924 Py_BEGIN_ALLOW_THREADS
8925 _Py_BEGIN_SUPPRESS_IPH
8926 /* This error might be caused by
8927 SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8928 Try again, and update windows_has_symlink_unprivileged_flag if we
8929 are successful this time.
8930
8931 NOTE: There is a risk of a race condition here if there are other
8932 conditions than the flag causing ERROR_INVALID_PARAMETER, and
8933 another process (or thread) changes that condition in between our
8934 calls to CreateSymbolicLink.
8935 */
8936 flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8937 result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8938 _Py_END_SUPPRESS_IPH
8939 Py_END_ALLOW_THREADS
8940
8941 if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8942 windows_has_symlink_unprivileged_flag = FALSE;
8943 }
8944 }
8945
8946 if (!result)
8947 return path_error2(src, dst);
8948
8949 #else
8950
8951 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8952 PyErr_SetString(PyExc_ValueError,
8953 "symlink: src and dst must be the same type");
8954 return NULL;
8955 }
8956
8957 Py_BEGIN_ALLOW_THREADS
8958 #ifdef HAVE_SYMLINKAT
8959 if (dir_fd != DEFAULT_DIR_FD) {
8960 if (HAVE_SYMLINKAT_RUNTIME) {
8961 result = symlinkat(src->narrow, dir_fd, dst->narrow);
8962 } else {
8963 symlinkat_unavailable = 1;
8964 }
8965 } else
8966 #endif
8967 result = symlink(src->narrow, dst->narrow);
8968 Py_END_ALLOW_THREADS
8969
8970 #ifdef HAVE_SYMLINKAT
8971 if (symlinkat_unavailable) {
8972 argument_unavailable_error(NULL, "dir_fd");
8973 return NULL;
8974 }
8975 #endif
8976
8977 if (result)
8978 return path_error2(src, dst);
8979 #endif
8980
8981 Py_RETURN_NONE;
8982 }
8983 #endif /* HAVE_SYMLINK */
8984
8985
8986
8987
8988 static PyStructSequence_Field times_result_fields[] = {
8989 {"user", "user time"},
8990 {"system", "system time"},
8991 {"children_user", "user time of children"},
8992 {"children_system", "system time of children"},
8993 {"elapsed", "elapsed time since an arbitrary point in the past"},
8994 {NULL}
8995 };
8996
8997 PyDoc_STRVAR(times_result__doc__,
8998 "times_result: Result from os.times().\n\n\
8999 This object may be accessed either as a tuple of\n\
9000 (user, system, children_user, children_system, elapsed),\n\
9001 or via the attributes user, system, children_user, children_system,\n\
9002 and elapsed.\n\
9003 \n\
9004 See os.times for more information.");
9005
9006 static PyStructSequence_Desc times_result_desc = {
9007 "times_result", /* name */
9008 times_result__doc__, /* doc */
9009 times_result_fields,
9010 5
9011 };
9012
9013 #ifdef MS_WINDOWS
9014 #define HAVE_TIMES /* mandatory, for the method table */
9015 #endif
9016
9017 #ifdef HAVE_TIMES
9018
9019 static PyObject *
build_times_result(PyObject * module,double user,double system,double children_user,double children_system,double elapsed)9020 build_times_result(PyObject *module, double user, double system,
9021 double children_user, double children_system,
9022 double elapsed)
9023 {
9024 PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
9025 PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
9026 if (value == NULL)
9027 return NULL;
9028
9029 #define SET(i, field) \
9030 { \
9031 PyObject *o = PyFloat_FromDouble(field); \
9032 if (!o) { \
9033 Py_DECREF(value); \
9034 return NULL; \
9035 } \
9036 PyStructSequence_SET_ITEM(value, i, o); \
9037 } \
9038
9039 SET(0, user);
9040 SET(1, system);
9041 SET(2, children_user);
9042 SET(3, children_system);
9043 SET(4, elapsed);
9044
9045 #undef SET
9046
9047 return value;
9048 }
9049
9050
9051 #ifndef MS_WINDOWS
9052 #define NEED_TICKS_PER_SECOND
9053 static long ticks_per_second = -1;
9054 #endif /* MS_WINDOWS */
9055
9056 /*[clinic input]
9057 os.times
9058
9059 Return a collection containing process timing information.
9060
9061 The object returned behaves like a named tuple with these fields:
9062 (utime, stime, cutime, cstime, elapsed_time)
9063 All fields are floating point numbers.
9064 [clinic start generated code]*/
9065
9066 static PyObject *
os_times_impl(PyObject * module)9067 os_times_impl(PyObject *module)
9068 /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
9069 #ifdef MS_WINDOWS
9070 {
9071 FILETIME create, exit, kernel, user;
9072 HANDLE hProc;
9073 hProc = GetCurrentProcess();
9074 GetProcessTimes(hProc, &create, &exit, &kernel, &user);
9075 /* The fields of a FILETIME structure are the hi and lo part
9076 of a 64-bit value expressed in 100 nanosecond units.
9077 1e7 is one second in such units; 1e-7 the inverse.
9078 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
9079 */
9080 return build_times_result(module,
9081 (double)(user.dwHighDateTime*429.4967296 +
9082 user.dwLowDateTime*1e-7),
9083 (double)(kernel.dwHighDateTime*429.4967296 +
9084 kernel.dwLowDateTime*1e-7),
9085 (double)0,
9086 (double)0,
9087 (double)0);
9088 }
9089 #else /* MS_WINDOWS */
9090 {
9091
9092
9093 struct tms t;
9094 clock_t c;
9095 errno = 0;
9096 c = times(&t);
9097 if (c == (clock_t) -1)
9098 return posix_error();
9099 return build_times_result(module,
9100 (double)t.tms_utime / ticks_per_second,
9101 (double)t.tms_stime / ticks_per_second,
9102 (double)t.tms_cutime / ticks_per_second,
9103 (double)t.tms_cstime / ticks_per_second,
9104 (double)c / ticks_per_second);
9105 }
9106 #endif /* MS_WINDOWS */
9107 #endif /* HAVE_TIMES */
9108
9109
9110 #ifdef HAVE_GETSID
9111 /*[clinic input]
9112 os.getsid
9113
9114 pid: pid_t
9115 /
9116
9117 Call the system call getsid(pid) and return the result.
9118 [clinic start generated code]*/
9119
9120 static PyObject *
os_getsid_impl(PyObject * module,pid_t pid)9121 os_getsid_impl(PyObject *module, pid_t pid)
9122 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
9123 {
9124 int sid;
9125 sid = getsid(pid);
9126 if (sid < 0)
9127 return posix_error();
9128 return PyLong_FromLong((long)sid);
9129 }
9130 #endif /* HAVE_GETSID */
9131
9132
9133 #ifdef HAVE_SETSID
9134 /*[clinic input]
9135 os.setsid
9136
9137 Call the system call setsid().
9138 [clinic start generated code]*/
9139
9140 static PyObject *
os_setsid_impl(PyObject * module)9141 os_setsid_impl(PyObject *module)
9142 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
9143 {
9144 if (setsid() < 0)
9145 return posix_error();
9146 Py_RETURN_NONE;
9147 }
9148 #endif /* HAVE_SETSID */
9149
9150
9151 #ifdef HAVE_SETPGID
9152 /*[clinic input]
9153 os.setpgid
9154
9155 pid: pid_t
9156 pgrp: pid_t
9157 /
9158
9159 Call the system call setpgid(pid, pgrp).
9160 [clinic start generated code]*/
9161
9162 static PyObject *
os_setpgid_impl(PyObject * module,pid_t pid,pid_t pgrp)9163 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
9164 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
9165 {
9166 if (setpgid(pid, pgrp) < 0)
9167 return posix_error();
9168 Py_RETURN_NONE;
9169 }
9170 #endif /* HAVE_SETPGID */
9171
9172
9173 #ifdef HAVE_TCGETPGRP
9174 /*[clinic input]
9175 os.tcgetpgrp
9176
9177 fd: int
9178 /
9179
9180 Return the process group associated with the terminal specified by fd.
9181 [clinic start generated code]*/
9182
9183 static PyObject *
os_tcgetpgrp_impl(PyObject * module,int fd)9184 os_tcgetpgrp_impl(PyObject *module, int fd)
9185 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
9186 {
9187 pid_t pgid = tcgetpgrp(fd);
9188 if (pgid < 0)
9189 return posix_error();
9190 return PyLong_FromPid(pgid);
9191 }
9192 #endif /* HAVE_TCGETPGRP */
9193
9194
9195 #ifdef HAVE_TCSETPGRP
9196 /*[clinic input]
9197 os.tcsetpgrp
9198
9199 fd: int
9200 pgid: pid_t
9201 /
9202
9203 Set the process group associated with the terminal specified by fd.
9204 [clinic start generated code]*/
9205
9206 static PyObject *
os_tcsetpgrp_impl(PyObject * module,int fd,pid_t pgid)9207 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
9208 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
9209 {
9210 if (tcsetpgrp(fd, pgid) < 0)
9211 return posix_error();
9212 Py_RETURN_NONE;
9213 }
9214 #endif /* HAVE_TCSETPGRP */
9215
9216 /* Functions acting on file descriptors */
9217
9218 #ifdef O_CLOEXEC
9219 extern int _Py_open_cloexec_works;
9220 #endif
9221
9222
9223 /*[clinic input]
9224 os.open -> int
9225 path: path_t
9226 flags: int
9227 mode: int = 0o777
9228 *
9229 dir_fd: dir_fd(requires='openat') = None
9230
9231 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
9232
9233 Open a file for low level IO. Returns a file descriptor (integer).
9234
9235 If dir_fd is not None, it should be a file descriptor open to a directory,
9236 and path should be relative; path will then be relative to that directory.
9237 dir_fd may not be implemented on your platform.
9238 If it is unavailable, using it will raise a NotImplementedError.
9239 [clinic start generated code]*/
9240
9241 static int
os_open_impl(PyObject * module,path_t * path,int flags,int mode,int dir_fd)9242 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
9243 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
9244 {
9245 int fd;
9246 int async_err = 0;
9247 #ifdef HAVE_OPENAT
9248 int openat_unavailable = 0;
9249 #endif
9250
9251 #ifdef O_CLOEXEC
9252 int *atomic_flag_works = &_Py_open_cloexec_works;
9253 #elif !defined(MS_WINDOWS)
9254 int *atomic_flag_works = NULL;
9255 #endif
9256
9257 #ifdef MS_WINDOWS
9258 flags |= O_NOINHERIT;
9259 #elif defined(O_CLOEXEC)
9260 flags |= O_CLOEXEC;
9261 #endif
9262
9263 if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
9264 return -1;
9265 }
9266
9267 _Py_BEGIN_SUPPRESS_IPH
9268 do {
9269 Py_BEGIN_ALLOW_THREADS
9270 #ifdef MS_WINDOWS
9271 fd = _wopen(path->wide, flags, mode);
9272 #else
9273 #ifdef HAVE_OPENAT
9274 if (dir_fd != DEFAULT_DIR_FD) {
9275 if (HAVE_OPENAT_RUNTIME) {
9276 fd = openat(dir_fd, path->narrow, flags, mode);
9277
9278 } else {
9279 openat_unavailable = 1;
9280 fd = -1;
9281 }
9282 } else
9283 #endif /* HAVE_OPENAT */
9284 fd = open(path->narrow, flags, mode);
9285 #endif /* !MS_WINDOWS */
9286 Py_END_ALLOW_THREADS
9287 } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9288 _Py_END_SUPPRESS_IPH
9289
9290 #ifdef HAVE_OPENAT
9291 if (openat_unavailable) {
9292 argument_unavailable_error(NULL, "dir_fd");
9293 return -1;
9294 }
9295 #endif
9296
9297 if (fd < 0) {
9298 if (!async_err)
9299 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
9300 return -1;
9301 }
9302
9303 #ifndef MS_WINDOWS
9304 if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
9305 close(fd);
9306 return -1;
9307 }
9308 #endif
9309
9310 return fd;
9311 }
9312
9313
9314 /*[clinic input]
9315 os.close
9316
9317 fd: int
9318
9319 Close a file descriptor.
9320 [clinic start generated code]*/
9321
9322 static PyObject *
os_close_impl(PyObject * module,int fd)9323 os_close_impl(PyObject *module, int fd)
9324 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
9325 {
9326 int res;
9327 /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
9328 * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
9329 * for more details.
9330 */
9331 Py_BEGIN_ALLOW_THREADS
9332 _Py_BEGIN_SUPPRESS_IPH
9333 res = close(fd);
9334 _Py_END_SUPPRESS_IPH
9335 Py_END_ALLOW_THREADS
9336 if (res < 0)
9337 return posix_error();
9338 Py_RETURN_NONE;
9339 }
9340
9341 /*[clinic input]
9342 os.closerange
9343
9344 fd_low: int
9345 fd_high: int
9346 /
9347
9348 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
9349 [clinic start generated code]*/
9350
9351 static PyObject *
os_closerange_impl(PyObject * module,int fd_low,int fd_high)9352 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
9353 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
9354 {
9355 Py_BEGIN_ALLOW_THREADS
9356 _Py_closerange(fd_low, fd_high - 1);
9357 Py_END_ALLOW_THREADS
9358 Py_RETURN_NONE;
9359 }
9360
9361
9362 /*[clinic input]
9363 os.dup -> int
9364
9365 fd: int
9366 /
9367
9368 Return a duplicate of a file descriptor.
9369 [clinic start generated code]*/
9370
9371 static int
os_dup_impl(PyObject * module,int fd)9372 os_dup_impl(PyObject *module, int fd)
9373 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
9374 {
9375 return _Py_dup(fd);
9376 }
9377
9378 // dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
9379 // dup2.c provides working dup2() if and only if F_DUPFD is available.
9380 #if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
9381 /*[clinic input]
9382 os.dup2 -> int
9383 fd: int
9384 fd2: int
9385 inheritable: bool=True
9386
9387 Duplicate file descriptor.
9388 [clinic start generated code]*/
9389
9390 static int
os_dup2_impl(PyObject * module,int fd,int fd2,int inheritable)9391 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
9392 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
9393 {
9394 int res = 0;
9395 #if defined(HAVE_DUP3) && \
9396 !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
9397 /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
9398 static int dup3_works = -1;
9399 #endif
9400
9401 /* dup2() can fail with EINTR if the target FD is already open, because it
9402 * then has to be closed. See os_close_impl() for why we don't handle EINTR
9403 * upon close(), and therefore below.
9404 */
9405 #ifdef MS_WINDOWS
9406 Py_BEGIN_ALLOW_THREADS
9407 _Py_BEGIN_SUPPRESS_IPH
9408 res = dup2(fd, fd2);
9409 _Py_END_SUPPRESS_IPH
9410 Py_END_ALLOW_THREADS
9411 if (res < 0) {
9412 posix_error();
9413 return -1;
9414 }
9415 res = fd2; // msvcrt dup2 returns 0 on success.
9416
9417 /* Character files like console cannot be make non-inheritable */
9418 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9419 close(fd2);
9420 return -1;
9421 }
9422
9423 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
9424 Py_BEGIN_ALLOW_THREADS
9425 if (!inheritable)
9426 res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
9427 else
9428 res = dup2(fd, fd2);
9429 Py_END_ALLOW_THREADS
9430 if (res < 0) {
9431 posix_error();
9432 return -1;
9433 }
9434
9435 #else
9436
9437 #ifdef HAVE_DUP3
9438 if (!inheritable && dup3_works != 0) {
9439 Py_BEGIN_ALLOW_THREADS
9440 res = dup3(fd, fd2, O_CLOEXEC);
9441 Py_END_ALLOW_THREADS
9442 if (res < 0) {
9443 if (dup3_works == -1)
9444 dup3_works = (errno != ENOSYS);
9445 if (dup3_works) {
9446 posix_error();
9447 return -1;
9448 }
9449 }
9450 }
9451
9452 if (inheritable || dup3_works == 0)
9453 {
9454 #endif
9455 Py_BEGIN_ALLOW_THREADS
9456 res = dup2(fd, fd2);
9457 Py_END_ALLOW_THREADS
9458 if (res < 0) {
9459 posix_error();
9460 return -1;
9461 }
9462
9463 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9464 close(fd2);
9465 return -1;
9466 }
9467 #ifdef HAVE_DUP3
9468 }
9469 #endif
9470
9471 #endif
9472
9473 return res;
9474 }
9475 #endif
9476
9477
9478 #ifdef HAVE_LOCKF
9479 /*[clinic input]
9480 os.lockf
9481
9482 fd: int
9483 An open file descriptor.
9484 command: int
9485 One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
9486 length: Py_off_t
9487 The number of bytes to lock, starting at the current position.
9488 /
9489
9490 Apply, test or remove a POSIX lock on an open file descriptor.
9491
9492 [clinic start generated code]*/
9493
9494 static PyObject *
os_lockf_impl(PyObject * module,int fd,int command,Py_off_t length)9495 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
9496 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
9497 {
9498 int res;
9499
9500 if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
9501 return NULL;
9502 }
9503
9504 Py_BEGIN_ALLOW_THREADS
9505 res = lockf(fd, command, length);
9506 Py_END_ALLOW_THREADS
9507
9508 if (res < 0)
9509 return posix_error();
9510
9511 Py_RETURN_NONE;
9512 }
9513 #endif /* HAVE_LOCKF */
9514
9515
9516 /*[clinic input]
9517 os.lseek -> Py_off_t
9518
9519 fd: int
9520 position: Py_off_t
9521 how: int
9522 /
9523
9524 Set the position of a file descriptor. Return the new position.
9525
9526 Return the new cursor position in number of bytes
9527 relative to the beginning of the file.
9528 [clinic start generated code]*/
9529
9530 static Py_off_t
os_lseek_impl(PyObject * module,int fd,Py_off_t position,int how)9531 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
9532 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
9533 {
9534 Py_off_t result;
9535
9536 #ifdef SEEK_SET
9537 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
9538 switch (how) {
9539 case 0: how = SEEK_SET; break;
9540 case 1: how = SEEK_CUR; break;
9541 case 2: how = SEEK_END; break;
9542 }
9543 #endif /* SEEK_END */
9544
9545 Py_BEGIN_ALLOW_THREADS
9546 _Py_BEGIN_SUPPRESS_IPH
9547 #ifdef MS_WINDOWS
9548 result = _lseeki64(fd, position, how);
9549 #else
9550 result = lseek(fd, position, how);
9551 #endif
9552 _Py_END_SUPPRESS_IPH
9553 Py_END_ALLOW_THREADS
9554 if (result < 0)
9555 posix_error();
9556
9557 return result;
9558 }
9559
9560
9561 /*[clinic input]
9562 os.read
9563 fd: int
9564 length: Py_ssize_t
9565 /
9566
9567 Read from a file descriptor. Returns a bytes object.
9568 [clinic start generated code]*/
9569
9570 static PyObject *
os_read_impl(PyObject * module,int fd,Py_ssize_t length)9571 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
9572 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
9573 {
9574 Py_ssize_t n;
9575 PyObject *buffer;
9576
9577 if (length < 0) {
9578 errno = EINVAL;
9579 return posix_error();
9580 }
9581
9582 length = Py_MIN(length, _PY_READ_MAX);
9583
9584 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9585 if (buffer == NULL)
9586 return NULL;
9587
9588 n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
9589 if (n == -1) {
9590 Py_DECREF(buffer);
9591 return NULL;
9592 }
9593
9594 if (n != length)
9595 _PyBytes_Resize(&buffer, n);
9596
9597 return buffer;
9598 }
9599
9600 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
9601 || defined(__APPLE__))) \
9602 || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
9603 || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9604 static int
iov_setup(struct iovec ** iov,Py_buffer ** buf,PyObject * seq,Py_ssize_t cnt,int type)9605 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
9606 {
9607 Py_ssize_t i, j;
9608
9609 *iov = PyMem_New(struct iovec, cnt);
9610 if (*iov == NULL) {
9611 PyErr_NoMemory();
9612 return -1;
9613 }
9614
9615 *buf = PyMem_New(Py_buffer, cnt);
9616 if (*buf == NULL) {
9617 PyMem_Free(*iov);
9618 PyErr_NoMemory();
9619 return -1;
9620 }
9621
9622 for (i = 0; i < cnt; i++) {
9623 PyObject *item = PySequence_GetItem(seq, i);
9624 if (item == NULL)
9625 goto fail;
9626 if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
9627 Py_DECREF(item);
9628 goto fail;
9629 }
9630 Py_DECREF(item);
9631 (*iov)[i].iov_base = (*buf)[i].buf;
9632 (*iov)[i].iov_len = (*buf)[i].len;
9633 }
9634 return 0;
9635
9636 fail:
9637 PyMem_Free(*iov);
9638 for (j = 0; j < i; j++) {
9639 PyBuffer_Release(&(*buf)[j]);
9640 }
9641 PyMem_Free(*buf);
9642 return -1;
9643 }
9644
9645 static void
iov_cleanup(struct iovec * iov,Py_buffer * buf,int cnt)9646 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9647 {
9648 int i;
9649 PyMem_Free(iov);
9650 for (i = 0; i < cnt; i++) {
9651 PyBuffer_Release(&buf[i]);
9652 }
9653 PyMem_Free(buf);
9654 }
9655 #endif
9656
9657
9658 #ifdef HAVE_READV
9659 /*[clinic input]
9660 os.readv -> Py_ssize_t
9661
9662 fd: int
9663 buffers: object
9664 /
9665
9666 Read from a file descriptor fd into an iterable of buffers.
9667
9668 The buffers should be mutable buffers accepting bytes.
9669 readv will transfer data into each buffer until it is full
9670 and then move on to the next buffer in the sequence to hold
9671 the rest of the data.
9672
9673 readv returns the total number of bytes read,
9674 which may be less than the total capacity of all the buffers.
9675 [clinic start generated code]*/
9676
9677 static Py_ssize_t
os_readv_impl(PyObject * module,int fd,PyObject * buffers)9678 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9679 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9680 {
9681 Py_ssize_t cnt, n;
9682 int async_err = 0;
9683 struct iovec *iov;
9684 Py_buffer *buf;
9685
9686 if (!PySequence_Check(buffers)) {
9687 PyErr_SetString(PyExc_TypeError,
9688 "readv() arg 2 must be a sequence");
9689 return -1;
9690 }
9691
9692 cnt = PySequence_Size(buffers);
9693 if (cnt < 0)
9694 return -1;
9695
9696 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9697 return -1;
9698
9699 do {
9700 Py_BEGIN_ALLOW_THREADS
9701 n = readv(fd, iov, cnt);
9702 Py_END_ALLOW_THREADS
9703 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9704
9705 iov_cleanup(iov, buf, cnt);
9706 if (n < 0) {
9707 if (!async_err)
9708 posix_error();
9709 return -1;
9710 }
9711
9712 return n;
9713 }
9714 #endif /* HAVE_READV */
9715
9716
9717 #ifdef HAVE_PREAD
9718 /*[clinic input]
9719 os.pread
9720
9721 fd: int
9722 length: Py_ssize_t
9723 offset: Py_off_t
9724 /
9725
9726 Read a number of bytes from a file descriptor starting at a particular offset.
9727
9728 Read length bytes from file descriptor fd, starting at offset bytes from
9729 the beginning of the file. The file offset remains unchanged.
9730 [clinic start generated code]*/
9731
9732 static PyObject *
os_pread_impl(PyObject * module,int fd,Py_ssize_t length,Py_off_t offset)9733 os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
9734 /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
9735 {
9736 Py_ssize_t n;
9737 int async_err = 0;
9738 PyObject *buffer;
9739
9740 if (length < 0) {
9741 errno = EINVAL;
9742 return posix_error();
9743 }
9744 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9745 if (buffer == NULL)
9746 return NULL;
9747
9748 do {
9749 Py_BEGIN_ALLOW_THREADS
9750 _Py_BEGIN_SUPPRESS_IPH
9751 n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9752 _Py_END_SUPPRESS_IPH
9753 Py_END_ALLOW_THREADS
9754 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9755
9756 if (n < 0) {
9757 Py_DECREF(buffer);
9758 return (!async_err) ? posix_error() : NULL;
9759 }
9760 if (n != length)
9761 _PyBytes_Resize(&buffer, n);
9762 return buffer;
9763 }
9764 #endif /* HAVE_PREAD */
9765
9766 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9767 /*[clinic input]
9768 os.preadv -> Py_ssize_t
9769
9770 fd: int
9771 buffers: object
9772 offset: Py_off_t
9773 flags: int = 0
9774 /
9775
9776 Reads from a file descriptor into a number of mutable bytes-like objects.
9777
9778 Combines the functionality of readv() and pread(). As readv(), it will
9779 transfer data into each buffer until it is full and then move on to the next
9780 buffer in the sequence to hold the rest of the data. Its fourth argument,
9781 specifies the file offset at which the input operation is to be performed. It
9782 will return the total number of bytes read (which can be less than the total
9783 capacity of all the objects).
9784
9785 The flags argument contains a bitwise OR of zero or more of the following flags:
9786
9787 - RWF_HIPRI
9788 - RWF_NOWAIT
9789
9790 Using non-zero flags requires Linux 4.6 or newer.
9791 [clinic start generated code]*/
9792
9793 static Py_ssize_t
os_preadv_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9794 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9795 int flags)
9796 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9797 {
9798 Py_ssize_t cnt, n;
9799 int async_err = 0;
9800 struct iovec *iov;
9801 Py_buffer *buf;
9802
9803 if (!PySequence_Check(buffers)) {
9804 PyErr_SetString(PyExc_TypeError,
9805 "preadv2() arg 2 must be a sequence");
9806 return -1;
9807 }
9808
9809 cnt = PySequence_Size(buffers);
9810 if (cnt < 0) {
9811 return -1;
9812 }
9813
9814 #ifndef HAVE_PREADV2
9815 if(flags != 0) {
9816 argument_unavailable_error("preadv2", "flags");
9817 return -1;
9818 }
9819 #endif
9820
9821 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9822 return -1;
9823 }
9824 #ifdef HAVE_PREADV2
9825 do {
9826 Py_BEGIN_ALLOW_THREADS
9827 _Py_BEGIN_SUPPRESS_IPH
9828 n = preadv2(fd, iov, cnt, offset, flags);
9829 _Py_END_SUPPRESS_IPH
9830 Py_END_ALLOW_THREADS
9831 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9832 #else
9833 do {
9834 #if defined(__APPLE__) && defined(__clang__)
9835 /* This entire function will be removed from the module dict when the API
9836 * is not available.
9837 */
9838 #pragma clang diagnostic push
9839 #pragma clang diagnostic ignored "-Wunguarded-availability"
9840 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
9841 #endif
9842 Py_BEGIN_ALLOW_THREADS
9843 _Py_BEGIN_SUPPRESS_IPH
9844 n = preadv(fd, iov, cnt, offset);
9845 _Py_END_SUPPRESS_IPH
9846 Py_END_ALLOW_THREADS
9847 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9848
9849 #if defined(__APPLE__) && defined(__clang__)
9850 #pragma clang diagnostic pop
9851 #endif
9852
9853 #endif
9854
9855 iov_cleanup(iov, buf, cnt);
9856 if (n < 0) {
9857 if (!async_err) {
9858 posix_error();
9859 }
9860 return -1;
9861 }
9862
9863 return n;
9864 }
9865 #endif /* HAVE_PREADV */
9866
9867
9868 /*[clinic input]
9869 os.write -> Py_ssize_t
9870
9871 fd: int
9872 data: Py_buffer
9873 /
9874
9875 Write a bytes object to a file descriptor.
9876 [clinic start generated code]*/
9877
9878 static Py_ssize_t
os_write_impl(PyObject * module,int fd,Py_buffer * data)9879 os_write_impl(PyObject *module, int fd, Py_buffer *data)
9880 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9881 {
9882 return _Py_write(fd, data->buf, data->len);
9883 }
9884
9885 #ifdef HAVE_SENDFILE
9886 #ifdef __APPLE__
9887 /*[clinic input]
9888 os.sendfile
9889
9890 out_fd: int
9891 in_fd: int
9892 offset: Py_off_t
9893 count as sbytes: Py_off_t
9894 headers: object(c_default="NULL") = ()
9895 trailers: object(c_default="NULL") = ()
9896 flags: int = 0
9897
9898 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9899 [clinic start generated code]*/
9900
9901 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)9902 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9903 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
9904 int flags)
9905 /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
9906 #elif defined(__FreeBSD__) || defined(__DragonFly__)
9907 /*[clinic input]
9908 os.sendfile
9909
9910 out_fd: int
9911 in_fd: int
9912 offset: Py_off_t
9913 count: Py_ssize_t
9914 headers: object(c_default="NULL") = ()
9915 trailers: object(c_default="NULL") = ()
9916 flags: int = 0
9917
9918 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9919 [clinic start generated code]*/
9920
9921 static PyObject *
9922 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9923 Py_ssize_t count, PyObject *headers, PyObject *trailers,
9924 int flags)
9925 /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
9926 #else
9927 /*[clinic input]
9928 os.sendfile
9929
9930 out_fd: int
9931 in_fd: int
9932 offset as offobj: object
9933 count: Py_ssize_t
9934
9935 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9936 [clinic start generated code]*/
9937
9938 static PyObject *
9939 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
9940 Py_ssize_t count)
9941 /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
9942 #endif
9943 {
9944 Py_ssize_t ret;
9945 int async_err = 0;
9946
9947 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9948 #ifndef __APPLE__
9949 off_t sbytes;
9950 #endif
9951 Py_buffer *hbuf, *tbuf;
9952 struct sf_hdtr sf;
9953
9954 sf.headers = NULL;
9955 sf.trailers = NULL;
9956
9957 if (headers != NULL) {
9958 if (!PySequence_Check(headers)) {
9959 PyErr_SetString(PyExc_TypeError,
9960 "sendfile() headers must be a sequence");
9961 return NULL;
9962 } else {
9963 Py_ssize_t i = PySequence_Size(headers);
9964 if (i < 0)
9965 return NULL;
9966 if (i > INT_MAX) {
9967 PyErr_SetString(PyExc_OverflowError,
9968 "sendfile() header is too large");
9969 return NULL;
9970 }
9971 if (i > 0) {
9972 sf.hdr_cnt = (int)i;
9973 if (iov_setup(&(sf.headers), &hbuf,
9974 headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9975 return NULL;
9976 #ifdef __APPLE__
9977 for (i = 0; i < sf.hdr_cnt; i++) {
9978 Py_ssize_t blen = sf.headers[i].iov_len;
9979 # define OFF_T_MAX 0x7fffffffffffffff
9980 if (sbytes >= OFF_T_MAX - blen) {
9981 PyErr_SetString(PyExc_OverflowError,
9982 "sendfile() header is too large");
9983 return NULL;
9984 }
9985 sbytes += blen;
9986 }
9987 #endif
9988 }
9989 }
9990 }
9991 if (trailers != NULL) {
9992 if (!PySequence_Check(trailers)) {
9993 PyErr_SetString(PyExc_TypeError,
9994 "sendfile() trailers must be a sequence");
9995 return NULL;
9996 } else {
9997 Py_ssize_t i = PySequence_Size(trailers);
9998 if (i < 0)
9999 return NULL;
10000 if (i > INT_MAX) {
10001 PyErr_SetString(PyExc_OverflowError,
10002 "sendfile() trailer is too large");
10003 return NULL;
10004 }
10005 if (i > 0) {
10006 sf.trl_cnt = (int)i;
10007 if (iov_setup(&(sf.trailers), &tbuf,
10008 trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
10009 return NULL;
10010 }
10011 }
10012 }
10013
10014 _Py_BEGIN_SUPPRESS_IPH
10015 do {
10016 Py_BEGIN_ALLOW_THREADS
10017 #ifdef __APPLE__
10018 ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
10019 #else
10020 ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
10021 #endif
10022 Py_END_ALLOW_THREADS
10023 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10024 _Py_END_SUPPRESS_IPH
10025
10026 if (sf.headers != NULL)
10027 iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
10028 if (sf.trailers != NULL)
10029 iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
10030
10031 if (ret < 0) {
10032 if ((errno == EAGAIN) || (errno == EBUSY)) {
10033 if (sbytes != 0) {
10034 // some data has been sent
10035 goto done;
10036 }
10037 else {
10038 // no data has been sent; upper application is supposed
10039 // to retry on EAGAIN or EBUSY
10040 return posix_error();
10041 }
10042 }
10043 return (!async_err) ? posix_error() : NULL;
10044 }
10045 goto done;
10046
10047 done:
10048 #if !defined(HAVE_LARGEFILE_SUPPORT)
10049 return Py_BuildValue("l", sbytes);
10050 #else
10051 return Py_BuildValue("L", sbytes);
10052 #endif
10053
10054 #else
10055 #ifdef __linux__
10056 if (offobj == Py_None) {
10057 do {
10058 Py_BEGIN_ALLOW_THREADS
10059 ret = sendfile(out_fd, in_fd, NULL, count);
10060 Py_END_ALLOW_THREADS
10061 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10062 if (ret < 0)
10063 return (!async_err) ? posix_error() : NULL;
10064 return Py_BuildValue("n", ret);
10065 }
10066 #endif
10067 off_t offset;
10068 if (!Py_off_t_converter(offobj, &offset))
10069 return NULL;
10070
10071 #if defined(__sun) && defined(__SVR4)
10072 // On Solaris, sendfile raises EINVAL rather than returning 0
10073 // when the offset is equal or bigger than the in_fd size.
10074 struct stat st;
10075
10076 do {
10077 Py_BEGIN_ALLOW_THREADS
10078 ret = fstat(in_fd, &st);
10079 Py_END_ALLOW_THREADS
10080 } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10081 if (ret < 0)
10082 return (!async_err) ? posix_error() : NULL;
10083
10084 if (offset >= st.st_size) {
10085 return Py_BuildValue("i", 0);
10086 }
10087
10088 // On illumos specifically sendfile() may perform a partial write but
10089 // return -1/an error (in one confirmed case the destination socket
10090 // had a 5 second timeout set and errno was EAGAIN) and it's on the client
10091 // code to check if the offset parameter was modified by sendfile().
10092 //
10093 // We need this variable to track said change.
10094 off_t original_offset = offset;
10095 #endif
10096
10097 do {
10098 Py_BEGIN_ALLOW_THREADS
10099 ret = sendfile(out_fd, in_fd, &offset, count);
10100 #if defined(__sun) && defined(__SVR4)
10101 // This handles illumos-specific sendfile() partial write behavior,
10102 // see a comment above for more details.
10103 if (ret < 0 && offset != original_offset) {
10104 ret = offset - original_offset;
10105 }
10106 #endif
10107 Py_END_ALLOW_THREADS
10108 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10109 if (ret < 0)
10110 return (!async_err) ? posix_error() : NULL;
10111 return Py_BuildValue("n", ret);
10112 #endif
10113 }
10114 #endif /* HAVE_SENDFILE */
10115
10116
10117 #if defined(__APPLE__)
10118 /*[clinic input]
10119 os._fcopyfile
10120
10121 in_fd: int
10122 out_fd: int
10123 flags: int
10124 /
10125
10126 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
10127 [clinic start generated code]*/
10128
10129 static PyObject *
os__fcopyfile_impl(PyObject * module,int in_fd,int out_fd,int flags)10130 os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
10131 /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
10132 {
10133 int ret;
10134
10135 Py_BEGIN_ALLOW_THREADS
10136 ret = fcopyfile(in_fd, out_fd, NULL, flags);
10137 Py_END_ALLOW_THREADS
10138 if (ret < 0)
10139 return posix_error();
10140 Py_RETURN_NONE;
10141 }
10142 #endif
10143
10144
10145 /*[clinic input]
10146 os.fstat
10147
10148 fd : int
10149
10150 Perform a stat system call on the given file descriptor.
10151
10152 Like stat(), but for an open file descriptor.
10153 Equivalent to os.stat(fd).
10154 [clinic start generated code]*/
10155
10156 static PyObject *
os_fstat_impl(PyObject * module,int fd)10157 os_fstat_impl(PyObject *module, int fd)
10158 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
10159 {
10160 STRUCT_STAT st;
10161 int res;
10162 int async_err = 0;
10163
10164 do {
10165 Py_BEGIN_ALLOW_THREADS
10166 res = FSTAT(fd, &st);
10167 Py_END_ALLOW_THREADS
10168 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10169 if (res != 0) {
10170 #ifdef MS_WINDOWS
10171 return PyErr_SetFromWindowsErr(0);
10172 #else
10173 return (!async_err) ? posix_error() : NULL;
10174 #endif
10175 }
10176
10177 return _pystat_fromstructstat(module, &st);
10178 }
10179
10180
10181 /*[clinic input]
10182 os.isatty -> bool
10183 fd: int
10184 /
10185
10186 Return True if the fd is connected to a terminal.
10187
10188 Return True if the file descriptor is an open file descriptor
10189 connected to the slave end of a terminal.
10190 [clinic start generated code]*/
10191
10192 static int
os_isatty_impl(PyObject * module,int fd)10193 os_isatty_impl(PyObject *module, int fd)
10194 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
10195 {
10196 int return_value;
10197 Py_BEGIN_ALLOW_THREADS
10198 _Py_BEGIN_SUPPRESS_IPH
10199 return_value = isatty(fd);
10200 _Py_END_SUPPRESS_IPH
10201 Py_END_ALLOW_THREADS
10202 return return_value;
10203 }
10204
10205
10206 #ifdef HAVE_PIPE
10207 /*[clinic input]
10208 os.pipe
10209
10210 Create a pipe.
10211
10212 Returns a tuple of two file descriptors:
10213 (read_fd, write_fd)
10214 [clinic start generated code]*/
10215
10216 static PyObject *
os_pipe_impl(PyObject * module)10217 os_pipe_impl(PyObject *module)
10218 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
10219 {
10220 int fds[2];
10221 #ifdef MS_WINDOWS
10222 HANDLE read, write;
10223 SECURITY_ATTRIBUTES attr;
10224 BOOL ok;
10225 #else
10226 int res;
10227 #endif
10228
10229 #ifdef MS_WINDOWS
10230 attr.nLength = sizeof(attr);
10231 attr.lpSecurityDescriptor = NULL;
10232 attr.bInheritHandle = FALSE;
10233
10234 Py_BEGIN_ALLOW_THREADS
10235 ok = CreatePipe(&read, &write, &attr, 0);
10236 if (ok) {
10237 fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY);
10238 fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY);
10239 if (fds[0] == -1 || fds[1] == -1) {
10240 CloseHandle(read);
10241 CloseHandle(write);
10242 ok = 0;
10243 }
10244 }
10245 Py_END_ALLOW_THREADS
10246
10247 if (!ok)
10248 return PyErr_SetFromWindowsErr(0);
10249 #else
10250
10251 #ifdef HAVE_PIPE2
10252 Py_BEGIN_ALLOW_THREADS
10253 res = pipe2(fds, O_CLOEXEC);
10254 Py_END_ALLOW_THREADS
10255
10256 if (res != 0 && errno == ENOSYS)
10257 {
10258 #endif
10259 Py_BEGIN_ALLOW_THREADS
10260 res = pipe(fds);
10261 Py_END_ALLOW_THREADS
10262
10263 if (res == 0) {
10264 if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
10265 close(fds[0]);
10266 close(fds[1]);
10267 return NULL;
10268 }
10269 if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
10270 close(fds[0]);
10271 close(fds[1]);
10272 return NULL;
10273 }
10274 }
10275 #ifdef HAVE_PIPE2
10276 }
10277 #endif
10278
10279 if (res != 0)
10280 return PyErr_SetFromErrno(PyExc_OSError);
10281 #endif /* !MS_WINDOWS */
10282 return Py_BuildValue("(ii)", fds[0], fds[1]);
10283 }
10284 #endif /* HAVE_PIPE */
10285
10286
10287 #ifdef HAVE_PIPE2
10288 /*[clinic input]
10289 os.pipe2
10290
10291 flags: int
10292 /
10293
10294 Create a pipe with flags set atomically.
10295
10296 Returns a tuple of two file descriptors:
10297 (read_fd, write_fd)
10298
10299 flags can be constructed by ORing together one or more of these values:
10300 O_NONBLOCK, O_CLOEXEC.
10301 [clinic start generated code]*/
10302
10303 static PyObject *
os_pipe2_impl(PyObject * module,int flags)10304 os_pipe2_impl(PyObject *module, int flags)
10305 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
10306 {
10307 int fds[2];
10308 int res;
10309
10310 res = pipe2(fds, flags);
10311 if (res != 0)
10312 return posix_error();
10313 return Py_BuildValue("(ii)", fds[0], fds[1]);
10314 }
10315 #endif /* HAVE_PIPE2 */
10316
10317
10318 #ifdef HAVE_WRITEV
10319 /*[clinic input]
10320 os.writev -> Py_ssize_t
10321 fd: int
10322 buffers: object
10323 /
10324
10325 Iterate over buffers, and write the contents of each to a file descriptor.
10326
10327 Returns the total number of bytes written.
10328 buffers must be a sequence of bytes-like objects.
10329 [clinic start generated code]*/
10330
10331 static Py_ssize_t
os_writev_impl(PyObject * module,int fd,PyObject * buffers)10332 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
10333 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
10334 {
10335 Py_ssize_t cnt;
10336 Py_ssize_t result;
10337 int async_err = 0;
10338 struct iovec *iov;
10339 Py_buffer *buf;
10340
10341 if (!PySequence_Check(buffers)) {
10342 PyErr_SetString(PyExc_TypeError,
10343 "writev() arg 2 must be a sequence");
10344 return -1;
10345 }
10346 cnt = PySequence_Size(buffers);
10347 if (cnt < 0)
10348 return -1;
10349
10350 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10351 return -1;
10352 }
10353
10354 do {
10355 Py_BEGIN_ALLOW_THREADS
10356 result = writev(fd, iov, cnt);
10357 Py_END_ALLOW_THREADS
10358 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10359
10360 iov_cleanup(iov, buf, cnt);
10361 if (result < 0 && !async_err)
10362 posix_error();
10363
10364 return result;
10365 }
10366 #endif /* HAVE_WRITEV */
10367
10368
10369 #ifdef HAVE_PWRITE
10370 /*[clinic input]
10371 os.pwrite -> Py_ssize_t
10372
10373 fd: int
10374 buffer: Py_buffer
10375 offset: Py_off_t
10376 /
10377
10378 Write bytes to a file descriptor starting at a particular offset.
10379
10380 Write buffer to fd, starting at offset bytes from the beginning of
10381 the file. Returns the number of bytes writte. Does not change the
10382 current file offset.
10383 [clinic start generated code]*/
10384
10385 static Py_ssize_t
os_pwrite_impl(PyObject * module,int fd,Py_buffer * buffer,Py_off_t offset)10386 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
10387 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
10388 {
10389 Py_ssize_t size;
10390 int async_err = 0;
10391
10392 do {
10393 Py_BEGIN_ALLOW_THREADS
10394 _Py_BEGIN_SUPPRESS_IPH
10395 size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
10396 _Py_END_SUPPRESS_IPH
10397 Py_END_ALLOW_THREADS
10398 } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10399
10400 if (size < 0 && !async_err)
10401 posix_error();
10402 return size;
10403 }
10404 #endif /* HAVE_PWRITE */
10405
10406 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
10407 /*[clinic input]
10408 os.pwritev -> Py_ssize_t
10409
10410 fd: int
10411 buffers: object
10412 offset: Py_off_t
10413 flags: int = 0
10414 /
10415
10416 Writes the contents of bytes-like objects to a file descriptor at a given offset.
10417
10418 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
10419 of bytes-like objects. Buffers are processed in array order. Entire contents of first
10420 buffer is written before proceeding to second, and so on. The operating system may
10421 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
10422 This function writes the contents of each object to the file descriptor and returns
10423 the total number of bytes written.
10424
10425 The flags argument contains a bitwise OR of zero or more of the following flags:
10426
10427 - RWF_DSYNC
10428 - RWF_SYNC
10429 - RWF_APPEND
10430
10431 Using non-zero flags requires Linux 4.7 or newer.
10432 [clinic start generated code]*/
10433
10434 static Py_ssize_t
os_pwritev_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)10435 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
10436 int flags)
10437 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
10438 {
10439 Py_ssize_t cnt;
10440 Py_ssize_t result;
10441 int async_err = 0;
10442 struct iovec *iov;
10443 Py_buffer *buf;
10444
10445 if (!PySequence_Check(buffers)) {
10446 PyErr_SetString(PyExc_TypeError,
10447 "pwritev() arg 2 must be a sequence");
10448 return -1;
10449 }
10450
10451 cnt = PySequence_Size(buffers);
10452 if (cnt < 0) {
10453 return -1;
10454 }
10455
10456 #ifndef HAVE_PWRITEV2
10457 if(flags != 0) {
10458 argument_unavailable_error("pwritev2", "flags");
10459 return -1;
10460 }
10461 #endif
10462
10463 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10464 return -1;
10465 }
10466 #ifdef HAVE_PWRITEV2
10467 do {
10468 Py_BEGIN_ALLOW_THREADS
10469 _Py_BEGIN_SUPPRESS_IPH
10470 result = pwritev2(fd, iov, cnt, offset, flags);
10471 _Py_END_SUPPRESS_IPH
10472 Py_END_ALLOW_THREADS
10473 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10474 #else
10475
10476 #if defined(__APPLE__) && defined(__clang__)
10477 /* This entire function will be removed from the module dict when the API
10478 * is not available.
10479 */
10480 #pragma clang diagnostic push
10481 #pragma clang diagnostic ignored "-Wunguarded-availability"
10482 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
10483 #endif
10484 do {
10485 Py_BEGIN_ALLOW_THREADS
10486 _Py_BEGIN_SUPPRESS_IPH
10487 result = pwritev(fd, iov, cnt, offset);
10488 _Py_END_SUPPRESS_IPH
10489 Py_END_ALLOW_THREADS
10490 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10491
10492 #if defined(__APPLE__) && defined(__clang__)
10493 #pragma clang diagnostic pop
10494 #endif
10495
10496 #endif
10497
10498 iov_cleanup(iov, buf, cnt);
10499 if (result < 0) {
10500 if (!async_err) {
10501 posix_error();
10502 }
10503 return -1;
10504 }
10505
10506 return result;
10507 }
10508 #endif /* HAVE_PWRITEV */
10509
10510 #ifdef HAVE_COPY_FILE_RANGE
10511 /*[clinic input]
10512
10513 os.copy_file_range
10514 src: int
10515 Source file descriptor.
10516 dst: int
10517 Destination file descriptor.
10518 count: Py_ssize_t
10519 Number of bytes to copy.
10520 offset_src: object = None
10521 Starting offset in src.
10522 offset_dst: object = None
10523 Starting offset in dst.
10524
10525 Copy count bytes from one file descriptor to another.
10526
10527 If offset_src is None, then src is read from the current position;
10528 respectively for offset_dst.
10529 [clinic start generated code]*/
10530
10531 static PyObject *
os_copy_file_range_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst)10532 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10533 PyObject *offset_src, PyObject *offset_dst)
10534 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
10535 {
10536 off_t offset_src_val, offset_dst_val;
10537 off_t *p_offset_src = NULL;
10538 off_t *p_offset_dst = NULL;
10539 Py_ssize_t ret;
10540 int async_err = 0;
10541 /* The flags argument is provided to allow
10542 * for future extensions and currently must be to 0. */
10543 int flags = 0;
10544
10545
10546 if (count < 0) {
10547 PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10548 return NULL;
10549 }
10550
10551 if (offset_src != Py_None) {
10552 if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10553 return NULL;
10554 }
10555 p_offset_src = &offset_src_val;
10556 }
10557
10558 if (offset_dst != Py_None) {
10559 if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10560 return NULL;
10561 }
10562 p_offset_dst = &offset_dst_val;
10563 }
10564
10565 do {
10566 Py_BEGIN_ALLOW_THREADS
10567 ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
10568 Py_END_ALLOW_THREADS
10569 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10570
10571 if (ret < 0) {
10572 return (!async_err) ? posix_error() : NULL;
10573 }
10574
10575 return PyLong_FromSsize_t(ret);
10576 }
10577 #endif /* HAVE_COPY_FILE_RANGE*/
10578
10579 #if (defined(HAVE_SPLICE) && !defined(_AIX))
10580 /*[clinic input]
10581
10582 os.splice
10583 src: int
10584 Source file descriptor.
10585 dst: int
10586 Destination file descriptor.
10587 count: Py_ssize_t
10588 Number of bytes to copy.
10589 offset_src: object = None
10590 Starting offset in src.
10591 offset_dst: object = None
10592 Starting offset in dst.
10593 flags: unsigned_int = 0
10594 Flags to modify the semantics of the call.
10595
10596 Transfer count bytes from one pipe to a descriptor or vice versa.
10597
10598 If offset_src is None, then src is read from the current position;
10599 respectively for offset_dst. The offset associated to the file
10600 descriptor that refers to a pipe must be None.
10601 [clinic start generated code]*/
10602
10603 static PyObject *
os_splice_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst,unsigned int flags)10604 os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10605 PyObject *offset_src, PyObject *offset_dst,
10606 unsigned int flags)
10607 /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
10608 {
10609 off_t offset_src_val, offset_dst_val;
10610 off_t *p_offset_src = NULL;
10611 off_t *p_offset_dst = NULL;
10612 Py_ssize_t ret;
10613 int async_err = 0;
10614
10615 if (count < 0) {
10616 PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10617 return NULL;
10618 }
10619
10620 if (offset_src != Py_None) {
10621 if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10622 return NULL;
10623 }
10624 p_offset_src = &offset_src_val;
10625 }
10626
10627 if (offset_dst != Py_None) {
10628 if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10629 return NULL;
10630 }
10631 p_offset_dst = &offset_dst_val;
10632 }
10633
10634 do {
10635 Py_BEGIN_ALLOW_THREADS
10636 ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
10637 Py_END_ALLOW_THREADS
10638 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10639
10640 if (ret < 0) {
10641 return (!async_err) ? posix_error() : NULL;
10642 }
10643
10644 return PyLong_FromSsize_t(ret);
10645 }
10646 #endif /* HAVE_SPLICE*/
10647
10648 #ifdef HAVE_MKFIFO
10649 /*[clinic input]
10650 os.mkfifo
10651
10652 path: path_t
10653 mode: int=0o666
10654 *
10655 dir_fd: dir_fd(requires='mkfifoat')=None
10656
10657 Create a "fifo" (a POSIX named pipe).
10658
10659 If dir_fd is not None, it should be a file descriptor open to a directory,
10660 and path should be relative; path will then be relative to that directory.
10661 dir_fd may not be implemented on your platform.
10662 If it is unavailable, using it will raise a NotImplementedError.
10663 [clinic start generated code]*/
10664
10665 static PyObject *
os_mkfifo_impl(PyObject * module,path_t * path,int mode,int dir_fd)10666 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
10667 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
10668 {
10669 int result;
10670 int async_err = 0;
10671 #ifdef HAVE_MKFIFOAT
10672 int mkfifoat_unavailable = 0;
10673 #endif
10674
10675 do {
10676 Py_BEGIN_ALLOW_THREADS
10677 #ifdef HAVE_MKFIFOAT
10678 if (dir_fd != DEFAULT_DIR_FD) {
10679 if (HAVE_MKFIFOAT_RUNTIME) {
10680 result = mkfifoat(dir_fd, path->narrow, mode);
10681
10682 } else {
10683 mkfifoat_unavailable = 1;
10684 result = 0;
10685 }
10686 } else
10687 #endif
10688 result = mkfifo(path->narrow, mode);
10689 Py_END_ALLOW_THREADS
10690 } while (result != 0 && errno == EINTR &&
10691 !(async_err = PyErr_CheckSignals()));
10692
10693 #ifdef HAVE_MKFIFOAT
10694 if (mkfifoat_unavailable) {
10695 argument_unavailable_error(NULL, "dir_fd");
10696 return NULL;
10697 }
10698 #endif
10699
10700 if (result != 0)
10701 return (!async_err) ? posix_error() : NULL;
10702
10703 Py_RETURN_NONE;
10704 }
10705 #endif /* HAVE_MKFIFO */
10706
10707
10708 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
10709 /*[clinic input]
10710 os.mknod
10711
10712 path: path_t
10713 mode: int=0o600
10714 device: dev_t=0
10715 *
10716 dir_fd: dir_fd(requires='mknodat')=None
10717
10718 Create a node in the file system.
10719
10720 Create a node in the file system (file, device special file or named pipe)
10721 at path. mode specifies both the permissions to use and the
10722 type of node to be created, being combined (bitwise OR) with one of
10723 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,
10724 device defines the newly created device special file (probably using
10725 os.makedev()). Otherwise device is ignored.
10726
10727 If dir_fd is not None, it should be a file descriptor open to a directory,
10728 and path should be relative; path will then be relative to that directory.
10729 dir_fd may not be implemented on your platform.
10730 If it is unavailable, using it will raise a NotImplementedError.
10731 [clinic start generated code]*/
10732
10733 static PyObject *
os_mknod_impl(PyObject * module,path_t * path,int mode,dev_t device,int dir_fd)10734 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
10735 int dir_fd)
10736 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
10737 {
10738 int result;
10739 int async_err = 0;
10740 #ifdef HAVE_MKNODAT
10741 int mknodat_unavailable = 0;
10742 #endif
10743
10744 do {
10745 Py_BEGIN_ALLOW_THREADS
10746 #ifdef HAVE_MKNODAT
10747 if (dir_fd != DEFAULT_DIR_FD) {
10748 if (HAVE_MKNODAT_RUNTIME) {
10749 result = mknodat(dir_fd, path->narrow, mode, device);
10750
10751 } else {
10752 mknodat_unavailable = 1;
10753 result = 0;
10754 }
10755 } else
10756 #endif
10757 result = mknod(path->narrow, mode, device);
10758 Py_END_ALLOW_THREADS
10759 } while (result != 0 && errno == EINTR &&
10760 !(async_err = PyErr_CheckSignals()));
10761 #ifdef HAVE_MKNODAT
10762 if (mknodat_unavailable) {
10763 argument_unavailable_error(NULL, "dir_fd");
10764 return NULL;
10765 }
10766 #endif
10767 if (result != 0)
10768 return (!async_err) ? posix_error() : NULL;
10769
10770 Py_RETURN_NONE;
10771 }
10772 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
10773
10774
10775 #ifdef HAVE_DEVICE_MACROS
10776 /*[clinic input]
10777 os.major -> unsigned_int
10778
10779 device: dev_t
10780 /
10781
10782 Extracts a device major number from a raw device number.
10783 [clinic start generated code]*/
10784
10785 static unsigned int
os_major_impl(PyObject * module,dev_t device)10786 os_major_impl(PyObject *module, dev_t device)
10787 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
10788 {
10789 return major(device);
10790 }
10791
10792
10793 /*[clinic input]
10794 os.minor -> unsigned_int
10795
10796 device: dev_t
10797 /
10798
10799 Extracts a device minor number from a raw device number.
10800 [clinic start generated code]*/
10801
10802 static unsigned int
os_minor_impl(PyObject * module,dev_t device)10803 os_minor_impl(PyObject *module, dev_t device)
10804 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10805 {
10806 return minor(device);
10807 }
10808
10809
10810 /*[clinic input]
10811 os.makedev -> dev_t
10812
10813 major: int
10814 minor: int
10815 /
10816
10817 Composes a raw device number from the major and minor device numbers.
10818 [clinic start generated code]*/
10819
10820 static dev_t
os_makedev_impl(PyObject * module,int major,int minor)10821 os_makedev_impl(PyObject *module, int major, int minor)
10822 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10823 {
10824 return makedev(major, minor);
10825 }
10826 #endif /* HAVE_DEVICE_MACROS */
10827
10828
10829 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10830 /*[clinic input]
10831 os.ftruncate
10832
10833 fd: int
10834 length: Py_off_t
10835 /
10836
10837 Truncate a file, specified by file descriptor, to a specific length.
10838 [clinic start generated code]*/
10839
10840 static PyObject *
os_ftruncate_impl(PyObject * module,int fd,Py_off_t length)10841 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10842 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10843 {
10844 int result;
10845 int async_err = 0;
10846
10847 if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10848 return NULL;
10849 }
10850
10851 do {
10852 Py_BEGIN_ALLOW_THREADS
10853 _Py_BEGIN_SUPPRESS_IPH
10854 #ifdef MS_WINDOWS
10855 result = _chsize_s(fd, length);
10856 #else
10857 result = ftruncate(fd, length);
10858 #endif
10859 _Py_END_SUPPRESS_IPH
10860 Py_END_ALLOW_THREADS
10861 } while (result != 0 && errno == EINTR &&
10862 !(async_err = PyErr_CheckSignals()));
10863 if (result != 0)
10864 return (!async_err) ? posix_error() : NULL;
10865 Py_RETURN_NONE;
10866 }
10867 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10868
10869
10870 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10871 /*[clinic input]
10872 os.truncate
10873 path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10874 length: Py_off_t
10875
10876 Truncate a file, specified by path, to a specific length.
10877
10878 On some platforms, path may also be specified as an open file descriptor.
10879 If this functionality is unavailable, using it raises an exception.
10880 [clinic start generated code]*/
10881
10882 static PyObject *
os_truncate_impl(PyObject * module,path_t * path,Py_off_t length)10883 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10884 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10885 {
10886 int result;
10887 #ifdef MS_WINDOWS
10888 int fd;
10889 #endif
10890
10891 if (path->fd != -1)
10892 return os_ftruncate_impl(module, path->fd, length);
10893
10894 if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10895 return NULL;
10896 }
10897
10898 Py_BEGIN_ALLOW_THREADS
10899 _Py_BEGIN_SUPPRESS_IPH
10900 #ifdef MS_WINDOWS
10901 fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10902 if (fd < 0)
10903 result = -1;
10904 else {
10905 result = _chsize_s(fd, length);
10906 close(fd);
10907 if (result < 0)
10908 errno = result;
10909 }
10910 #else
10911 result = truncate(path->narrow, length);
10912 #endif
10913 _Py_END_SUPPRESS_IPH
10914 Py_END_ALLOW_THREADS
10915 if (result < 0)
10916 return posix_path_error(path);
10917
10918 Py_RETURN_NONE;
10919 }
10920 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10921
10922
10923 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10924 and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10925 defined, which is the case in Python on AIX. AIX bug report:
10926 http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10927 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10928 # define POSIX_FADVISE_AIX_BUG
10929 #endif
10930
10931
10932 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10933 /*[clinic input]
10934 os.posix_fallocate
10935
10936 fd: int
10937 offset: Py_off_t
10938 length: Py_off_t
10939 /
10940
10941 Ensure a file has allocated at least a particular number of bytes on disk.
10942
10943 Ensure that the file specified by fd encompasses a range of bytes
10944 starting at offset bytes from the beginning and continuing for length bytes.
10945 [clinic start generated code]*/
10946
10947 static PyObject *
os_posix_fallocate_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length)10948 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10949 Py_off_t length)
10950 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10951 {
10952 int result;
10953 int async_err = 0;
10954
10955 do {
10956 Py_BEGIN_ALLOW_THREADS
10957 result = posix_fallocate(fd, offset, length);
10958 Py_END_ALLOW_THREADS
10959 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10960
10961 if (result == 0)
10962 Py_RETURN_NONE;
10963
10964 if (async_err)
10965 return NULL;
10966
10967 errno = result;
10968 return posix_error();
10969 }
10970 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
10971
10972
10973 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
10974 /*[clinic input]
10975 os.posix_fadvise
10976
10977 fd: int
10978 offset: Py_off_t
10979 length: Py_off_t
10980 advice: int
10981 /
10982
10983 Announce an intention to access data in a specific pattern.
10984
10985 Announce an intention to access data in a specific pattern, thus allowing
10986 the kernel to make optimizations.
10987 The advice applies to the region of the file specified by fd starting at
10988 offset and continuing for length bytes.
10989 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
10990 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
10991 POSIX_FADV_DONTNEED.
10992 [clinic start generated code]*/
10993
10994 static PyObject *
os_posix_fadvise_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length,int advice)10995 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
10996 Py_off_t length, int advice)
10997 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
10998 {
10999 int result;
11000 int async_err = 0;
11001
11002 do {
11003 Py_BEGIN_ALLOW_THREADS
11004 result = posix_fadvise(fd, offset, length, advice);
11005 Py_END_ALLOW_THREADS
11006 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
11007
11008 if (result == 0)
11009 Py_RETURN_NONE;
11010
11011 if (async_err)
11012 return NULL;
11013
11014 errno = result;
11015 return posix_error();
11016 }
11017 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
11018
11019
11020 #ifdef MS_WINDOWS
11021 static PyObject*
win32_putenv(PyObject * name,PyObject * value)11022 win32_putenv(PyObject *name, PyObject *value)
11023 {
11024 /* Search from index 1 because on Windows starting '=' is allowed for
11025 defining hidden environment variables. */
11026 if (PyUnicode_GET_LENGTH(name) == 0 ||
11027 PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
11028 {
11029 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11030 return NULL;
11031 }
11032 PyObject *unicode;
11033 if (value != NULL) {
11034 unicode = PyUnicode_FromFormat("%U=%U", name, value);
11035 }
11036 else {
11037 unicode = PyUnicode_FromFormat("%U=", name);
11038 }
11039 if (unicode == NULL) {
11040 return NULL;
11041 }
11042
11043 Py_ssize_t size;
11044 /* PyUnicode_AsWideCharString() rejects embedded null characters */
11045 wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
11046 Py_DECREF(unicode);
11047
11048 if (env == NULL) {
11049 return NULL;
11050 }
11051 if (size > _MAX_ENV) {
11052 PyErr_Format(PyExc_ValueError,
11053 "the environment variable is longer than %u characters",
11054 _MAX_ENV);
11055 PyMem_Free(env);
11056 return NULL;
11057 }
11058
11059 /* _wputenv() and SetEnvironmentVariableW() update the environment in the
11060 Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
11061 and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
11062
11063 Prefer _wputenv() to be compatible with C libraries using CRT
11064 variables and CRT functions using these variables (ex: getenv()). */
11065 int err = _wputenv(env);
11066 PyMem_Free(env);
11067
11068 if (err) {
11069 posix_error();
11070 return NULL;
11071 }
11072
11073 Py_RETURN_NONE;
11074 }
11075 #endif
11076
11077
11078 #ifdef MS_WINDOWS
11079 /*[clinic input]
11080 os.putenv
11081
11082 name: unicode
11083 value: unicode
11084 /
11085
11086 Change or add an environment variable.
11087 [clinic start generated code]*/
11088
11089 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)11090 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11091 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
11092 {
11093 if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11094 return NULL;
11095 }
11096 return win32_putenv(name, value);
11097 }
11098 #else
11099 /*[clinic input]
11100 os.putenv
11101
11102 name: FSConverter
11103 value: FSConverter
11104 /
11105
11106 Change or add an environment variable.
11107 [clinic start generated code]*/
11108
11109 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)11110 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11111 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
11112 {
11113 const char *name_string = PyBytes_AS_STRING(name);
11114 const char *value_string = PyBytes_AS_STRING(value);
11115
11116 if (strchr(name_string, '=') != NULL) {
11117 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11118 return NULL;
11119 }
11120
11121 if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11122 return NULL;
11123 }
11124
11125 if (setenv(name_string, value_string, 1)) {
11126 return posix_error();
11127 }
11128 Py_RETURN_NONE;
11129 }
11130 #endif /* !defined(MS_WINDOWS) */
11131
11132
11133 #ifdef MS_WINDOWS
11134 /*[clinic input]
11135 os.unsetenv
11136 name: unicode
11137 /
11138
11139 Delete an environment variable.
11140 [clinic start generated code]*/
11141
11142 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)11143 os_unsetenv_impl(PyObject *module, PyObject *name)
11144 /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
11145 {
11146 if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11147 return NULL;
11148 }
11149 return win32_putenv(name, NULL);
11150 }
11151 #else
11152 /*[clinic input]
11153 os.unsetenv
11154 name: FSConverter
11155 /
11156
11157 Delete an environment variable.
11158 [clinic start generated code]*/
11159
11160 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)11161 os_unsetenv_impl(PyObject *module, PyObject *name)
11162 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
11163 {
11164 if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11165 return NULL;
11166 }
11167 #ifdef HAVE_BROKEN_UNSETENV
11168 unsetenv(PyBytes_AS_STRING(name));
11169 #else
11170 int err = unsetenv(PyBytes_AS_STRING(name));
11171 if (err) {
11172 return posix_error();
11173 }
11174 #endif
11175
11176 Py_RETURN_NONE;
11177 }
11178 #endif /* !MS_WINDOWS */
11179
11180
11181 /*[clinic input]
11182 os.strerror
11183
11184 code: int
11185 /
11186
11187 Translate an error code to a message string.
11188 [clinic start generated code]*/
11189
11190 static PyObject *
os_strerror_impl(PyObject * module,int code)11191 os_strerror_impl(PyObject *module, int code)
11192 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
11193 {
11194 char *message = strerror(code);
11195 if (message == NULL) {
11196 PyErr_SetString(PyExc_ValueError,
11197 "strerror() argument out of range");
11198 return NULL;
11199 }
11200 return PyUnicode_DecodeLocale(message, "surrogateescape");
11201 }
11202
11203
11204 #ifdef HAVE_SYS_WAIT_H
11205 #ifdef WCOREDUMP
11206 /*[clinic input]
11207 os.WCOREDUMP -> bool
11208
11209 status: int
11210 /
11211
11212 Return True if the process returning status was dumped to a core file.
11213 [clinic start generated code]*/
11214
11215 static int
os_WCOREDUMP_impl(PyObject * module,int status)11216 os_WCOREDUMP_impl(PyObject *module, int status)
11217 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
11218 {
11219 WAIT_TYPE wait_status;
11220 WAIT_STATUS_INT(wait_status) = status;
11221 return WCOREDUMP(wait_status);
11222 }
11223 #endif /* WCOREDUMP */
11224
11225
11226 #ifdef WIFCONTINUED
11227 /*[clinic input]
11228 os.WIFCONTINUED -> bool
11229
11230 status: int
11231
11232 Return True if a particular process was continued from a job control stop.
11233
11234 Return True if the process returning status was continued from a
11235 job control stop.
11236 [clinic start generated code]*/
11237
11238 static int
os_WIFCONTINUED_impl(PyObject * module,int status)11239 os_WIFCONTINUED_impl(PyObject *module, int status)
11240 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
11241 {
11242 WAIT_TYPE wait_status;
11243 WAIT_STATUS_INT(wait_status) = status;
11244 return WIFCONTINUED(wait_status);
11245 }
11246 #endif /* WIFCONTINUED */
11247
11248
11249 #ifdef WIFSTOPPED
11250 /*[clinic input]
11251 os.WIFSTOPPED -> bool
11252
11253 status: int
11254
11255 Return True if the process returning status was stopped.
11256 [clinic start generated code]*/
11257
11258 static int
os_WIFSTOPPED_impl(PyObject * module,int status)11259 os_WIFSTOPPED_impl(PyObject *module, int status)
11260 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
11261 {
11262 WAIT_TYPE wait_status;
11263 WAIT_STATUS_INT(wait_status) = status;
11264 return WIFSTOPPED(wait_status);
11265 }
11266 #endif /* WIFSTOPPED */
11267
11268
11269 #ifdef WIFSIGNALED
11270 /*[clinic input]
11271 os.WIFSIGNALED -> bool
11272
11273 status: int
11274
11275 Return True if the process returning status was terminated by a signal.
11276 [clinic start generated code]*/
11277
11278 static int
os_WIFSIGNALED_impl(PyObject * module,int status)11279 os_WIFSIGNALED_impl(PyObject *module, int status)
11280 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
11281 {
11282 WAIT_TYPE wait_status;
11283 WAIT_STATUS_INT(wait_status) = status;
11284 return WIFSIGNALED(wait_status);
11285 }
11286 #endif /* WIFSIGNALED */
11287
11288
11289 #ifdef WIFEXITED
11290 /*[clinic input]
11291 os.WIFEXITED -> bool
11292
11293 status: int
11294
11295 Return True if the process returning status exited via the exit() system call.
11296 [clinic start generated code]*/
11297
11298 static int
os_WIFEXITED_impl(PyObject * module,int status)11299 os_WIFEXITED_impl(PyObject *module, int status)
11300 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
11301 {
11302 WAIT_TYPE wait_status;
11303 WAIT_STATUS_INT(wait_status) = status;
11304 return WIFEXITED(wait_status);
11305 }
11306 #endif /* WIFEXITED */
11307
11308
11309 #ifdef WEXITSTATUS
11310 /*[clinic input]
11311 os.WEXITSTATUS -> int
11312
11313 status: int
11314
11315 Return the process return code from status.
11316 [clinic start generated code]*/
11317
11318 static int
os_WEXITSTATUS_impl(PyObject * module,int status)11319 os_WEXITSTATUS_impl(PyObject *module, int status)
11320 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
11321 {
11322 WAIT_TYPE wait_status;
11323 WAIT_STATUS_INT(wait_status) = status;
11324 return WEXITSTATUS(wait_status);
11325 }
11326 #endif /* WEXITSTATUS */
11327
11328
11329 #ifdef WTERMSIG
11330 /*[clinic input]
11331 os.WTERMSIG -> int
11332
11333 status: int
11334
11335 Return the signal that terminated the process that provided the status value.
11336 [clinic start generated code]*/
11337
11338 static int
os_WTERMSIG_impl(PyObject * module,int status)11339 os_WTERMSIG_impl(PyObject *module, int status)
11340 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
11341 {
11342 WAIT_TYPE wait_status;
11343 WAIT_STATUS_INT(wait_status) = status;
11344 return WTERMSIG(wait_status);
11345 }
11346 #endif /* WTERMSIG */
11347
11348
11349 #ifdef WSTOPSIG
11350 /*[clinic input]
11351 os.WSTOPSIG -> int
11352
11353 status: int
11354
11355 Return the signal that stopped the process that provided the status value.
11356 [clinic start generated code]*/
11357
11358 static int
os_WSTOPSIG_impl(PyObject * module,int status)11359 os_WSTOPSIG_impl(PyObject *module, int status)
11360 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
11361 {
11362 WAIT_TYPE wait_status;
11363 WAIT_STATUS_INT(wait_status) = status;
11364 return WSTOPSIG(wait_status);
11365 }
11366 #endif /* WSTOPSIG */
11367 #endif /* HAVE_SYS_WAIT_H */
11368
11369
11370 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
11371 #ifdef _SCO_DS
11372 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
11373 needed definitions in sys/statvfs.h */
11374 #define _SVID3
11375 #endif
11376 #include <sys/statvfs.h>
11377
11378 static PyObject*
_pystatvfs_fromstructstatvfs(PyObject * module,struct statvfs st)11379 _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
11380 PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
11381 PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
11382 if (v == NULL)
11383 return NULL;
11384
11385 #if !defined(HAVE_LARGEFILE_SUPPORT)
11386 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11387 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11388 PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
11389 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
11390 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
11391 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
11392 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
11393 PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
11394 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11395 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11396 #else
11397 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11398 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11399 PyStructSequence_SET_ITEM(v, 2,
11400 PyLong_FromLongLong((long long) st.f_blocks));
11401 PyStructSequence_SET_ITEM(v, 3,
11402 PyLong_FromLongLong((long long) st.f_bfree));
11403 PyStructSequence_SET_ITEM(v, 4,
11404 PyLong_FromLongLong((long long) st.f_bavail));
11405 PyStructSequence_SET_ITEM(v, 5,
11406 PyLong_FromLongLong((long long) st.f_files));
11407 PyStructSequence_SET_ITEM(v, 6,
11408 PyLong_FromLongLong((long long) st.f_ffree));
11409 PyStructSequence_SET_ITEM(v, 7,
11410 PyLong_FromLongLong((long long) st.f_favail));
11411 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11412 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11413 #endif
11414 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
11415 * (issue #32390). */
11416 #if defined(_AIX) && defined(_ALL_SOURCE)
11417 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
11418 #else
11419 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
11420 #endif
11421 if (PyErr_Occurred()) {
11422 Py_DECREF(v);
11423 return NULL;
11424 }
11425
11426 return v;
11427 }
11428
11429
11430 /*[clinic input]
11431 os.fstatvfs
11432 fd: int
11433 /
11434
11435 Perform an fstatvfs system call on the given fd.
11436
11437 Equivalent to statvfs(fd).
11438 [clinic start generated code]*/
11439
11440 static PyObject *
os_fstatvfs_impl(PyObject * module,int fd)11441 os_fstatvfs_impl(PyObject *module, int fd)
11442 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
11443 {
11444 int result;
11445 int async_err = 0;
11446 struct statvfs st;
11447
11448 do {
11449 Py_BEGIN_ALLOW_THREADS
11450 result = fstatvfs(fd, &st);
11451 Py_END_ALLOW_THREADS
11452 } while (result != 0 && errno == EINTR &&
11453 !(async_err = PyErr_CheckSignals()));
11454 if (result != 0)
11455 return (!async_err) ? posix_error() : NULL;
11456
11457 return _pystatvfs_fromstructstatvfs(module, st);
11458 }
11459 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
11460
11461
11462 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
11463 #include <sys/statvfs.h>
11464 /*[clinic input]
11465 os.statvfs
11466
11467 path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
11468
11469 Perform a statvfs system call on the given path.
11470
11471 path may always be specified as a string.
11472 On some platforms, path may also be specified as an open file descriptor.
11473 If this functionality is unavailable, using it raises an exception.
11474 [clinic start generated code]*/
11475
11476 static PyObject *
os_statvfs_impl(PyObject * module,path_t * path)11477 os_statvfs_impl(PyObject *module, path_t *path)
11478 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
11479 {
11480 int result;
11481 struct statvfs st;
11482
11483 Py_BEGIN_ALLOW_THREADS
11484 #ifdef HAVE_FSTATVFS
11485 if (path->fd != -1) {
11486 result = fstatvfs(path->fd, &st);
11487 }
11488 else
11489 #endif
11490 result = statvfs(path->narrow, &st);
11491 Py_END_ALLOW_THREADS
11492
11493 if (result) {
11494 return path_error(path);
11495 }
11496
11497 return _pystatvfs_fromstructstatvfs(module, st);
11498 }
11499 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
11500
11501
11502 #ifdef MS_WINDOWS
11503 /*[clinic input]
11504 os._getdiskusage
11505
11506 path: path_t
11507
11508 Return disk usage statistics about the given path as a (total, free) tuple.
11509 [clinic start generated code]*/
11510
11511 static PyObject *
os__getdiskusage_impl(PyObject * module,path_t * path)11512 os__getdiskusage_impl(PyObject *module, path_t *path)
11513 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
11514 {
11515 BOOL retval;
11516 ULARGE_INTEGER _, total, free;
11517 DWORD err = 0;
11518
11519 Py_BEGIN_ALLOW_THREADS
11520 retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
11521 Py_END_ALLOW_THREADS
11522 if (retval == 0) {
11523 if (GetLastError() == ERROR_DIRECTORY) {
11524 wchar_t *dir_path = NULL;
11525
11526 dir_path = PyMem_New(wchar_t, path->length + 1);
11527 if (dir_path == NULL) {
11528 return PyErr_NoMemory();
11529 }
11530
11531 wcscpy_s(dir_path, path->length + 1, path->wide);
11532
11533 if (_dirnameW(dir_path) != -1) {
11534 Py_BEGIN_ALLOW_THREADS
11535 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
11536 Py_END_ALLOW_THREADS
11537 }
11538 /* Record the last error in case it's modified by PyMem_Free. */
11539 err = GetLastError();
11540 PyMem_Free(dir_path);
11541 if (retval) {
11542 goto success;
11543 }
11544 }
11545 return PyErr_SetFromWindowsErr(err);
11546 }
11547
11548 success:
11549 return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
11550 }
11551 #endif /* MS_WINDOWS */
11552
11553
11554 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
11555 * It maps strings representing configuration variable names to
11556 * integer values, allowing those functions to be called with the
11557 * magic names instead of polluting the module's namespace with tons of
11558 * rarely-used constants. There are three separate tables that use
11559 * these definitions.
11560 *
11561 * This code is always included, even if none of the interfaces that
11562 * need it are included. The #if hackery needed to avoid it would be
11563 * sufficiently pervasive that it's not worth the loss of readability.
11564 */
11565 struct constdef {
11566 const char *name;
11567 int value;
11568 };
11569
11570 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)11571 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
11572 size_t tablesize)
11573 {
11574 if (PyLong_Check(arg)) {
11575 int value = _PyLong_AsInt(arg);
11576 if (value == -1 && PyErr_Occurred())
11577 return 0;
11578 *valuep = value;
11579 return 1;
11580 }
11581 else {
11582 /* look up the value in the table using a binary search */
11583 size_t lo = 0;
11584 size_t mid;
11585 size_t hi = tablesize;
11586 int cmp;
11587 const char *confname;
11588 if (!PyUnicode_Check(arg)) {
11589 PyErr_SetString(PyExc_TypeError,
11590 "configuration names must be strings or integers");
11591 return 0;
11592 }
11593 confname = PyUnicode_AsUTF8(arg);
11594 if (confname == NULL)
11595 return 0;
11596 while (lo < hi) {
11597 mid = (lo + hi) / 2;
11598 cmp = strcmp(confname, table[mid].name);
11599 if (cmp < 0)
11600 hi = mid;
11601 else if (cmp > 0)
11602 lo = mid + 1;
11603 else {
11604 *valuep = table[mid].value;
11605 return 1;
11606 }
11607 }
11608 PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
11609 return 0;
11610 }
11611 }
11612
11613
11614 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11615 static struct constdef posix_constants_pathconf[] = {
11616 #ifdef _PC_ABI_AIO_XFER_MAX
11617 {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
11618 #endif
11619 #ifdef _PC_ABI_ASYNC_IO
11620 {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
11621 #endif
11622 #ifdef _PC_ASYNC_IO
11623 {"PC_ASYNC_IO", _PC_ASYNC_IO},
11624 #endif
11625 #ifdef _PC_CHOWN_RESTRICTED
11626 {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
11627 #endif
11628 #ifdef _PC_FILESIZEBITS
11629 {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
11630 #endif
11631 #ifdef _PC_LAST
11632 {"PC_LAST", _PC_LAST},
11633 #endif
11634 #ifdef _PC_LINK_MAX
11635 {"PC_LINK_MAX", _PC_LINK_MAX},
11636 #endif
11637 #ifdef _PC_MAX_CANON
11638 {"PC_MAX_CANON", _PC_MAX_CANON},
11639 #endif
11640 #ifdef _PC_MAX_INPUT
11641 {"PC_MAX_INPUT", _PC_MAX_INPUT},
11642 #endif
11643 #ifdef _PC_NAME_MAX
11644 {"PC_NAME_MAX", _PC_NAME_MAX},
11645 #endif
11646 #ifdef _PC_NO_TRUNC
11647 {"PC_NO_TRUNC", _PC_NO_TRUNC},
11648 #endif
11649 #ifdef _PC_PATH_MAX
11650 {"PC_PATH_MAX", _PC_PATH_MAX},
11651 #endif
11652 #ifdef _PC_PIPE_BUF
11653 {"PC_PIPE_BUF", _PC_PIPE_BUF},
11654 #endif
11655 #ifdef _PC_PRIO_IO
11656 {"PC_PRIO_IO", _PC_PRIO_IO},
11657 #endif
11658 #ifdef _PC_SOCK_MAXBUF
11659 {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
11660 #endif
11661 #ifdef _PC_SYNC_IO
11662 {"PC_SYNC_IO", _PC_SYNC_IO},
11663 #endif
11664 #ifdef _PC_VDISABLE
11665 {"PC_VDISABLE", _PC_VDISABLE},
11666 #endif
11667 #ifdef _PC_ACL_ENABLED
11668 {"PC_ACL_ENABLED", _PC_ACL_ENABLED},
11669 #endif
11670 #ifdef _PC_MIN_HOLE_SIZE
11671 {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE},
11672 #endif
11673 #ifdef _PC_ALLOC_SIZE_MIN
11674 {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN},
11675 #endif
11676 #ifdef _PC_REC_INCR_XFER_SIZE
11677 {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE},
11678 #endif
11679 #ifdef _PC_REC_MAX_XFER_SIZE
11680 {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE},
11681 #endif
11682 #ifdef _PC_REC_MIN_XFER_SIZE
11683 {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE},
11684 #endif
11685 #ifdef _PC_REC_XFER_ALIGN
11686 {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN},
11687 #endif
11688 #ifdef _PC_SYMLINK_MAX
11689 {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX},
11690 #endif
11691 #ifdef _PC_XATTR_ENABLED
11692 {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED},
11693 #endif
11694 #ifdef _PC_XATTR_EXISTS
11695 {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
11696 #endif
11697 #ifdef _PC_TIMESTAMP_RESOLUTION
11698 {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
11699 #endif
11700 };
11701
11702 static int
conv_path_confname(PyObject * arg,int * valuep)11703 conv_path_confname(PyObject *arg, int *valuep)
11704 {
11705 return conv_confname(arg, valuep, posix_constants_pathconf,
11706 sizeof(posix_constants_pathconf)
11707 / sizeof(struct constdef));
11708 }
11709 #endif
11710
11711
11712 #ifdef HAVE_FPATHCONF
11713 /*[clinic input]
11714 os.fpathconf -> long
11715
11716 fd: fildes
11717 name: path_confname
11718 /
11719
11720 Return the configuration limit name for the file descriptor fd.
11721
11722 If there is no limit, return -1.
11723 [clinic start generated code]*/
11724
11725 static long
os_fpathconf_impl(PyObject * module,int fd,int name)11726 os_fpathconf_impl(PyObject *module, int fd, int name)
11727 /*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
11728 {
11729 long limit;
11730
11731 errno = 0;
11732 limit = fpathconf(fd, name);
11733 if (limit == -1 && errno != 0)
11734 posix_error();
11735
11736 return limit;
11737 }
11738 #endif /* HAVE_FPATHCONF */
11739
11740
11741 #ifdef HAVE_PATHCONF
11742 /*[clinic input]
11743 os.pathconf -> long
11744 path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
11745 name: path_confname
11746
11747 Return the configuration limit name for the file or directory path.
11748
11749 If there is no limit, return -1.
11750 On some platforms, path may also be specified as an open file descriptor.
11751 If this functionality is unavailable, using it raises an exception.
11752 [clinic start generated code]*/
11753
11754 static long
os_pathconf_impl(PyObject * module,path_t * path,int name)11755 os_pathconf_impl(PyObject *module, path_t *path, int name)
11756 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
11757 {
11758 long limit;
11759
11760 errno = 0;
11761 #ifdef HAVE_FPATHCONF
11762 if (path->fd != -1)
11763 limit = fpathconf(path->fd, name);
11764 else
11765 #endif
11766 limit = pathconf(path->narrow, name);
11767 if (limit == -1 && errno != 0) {
11768 if (errno == EINVAL)
11769 /* could be a path or name problem */
11770 posix_error();
11771 else
11772 path_error(path);
11773 }
11774
11775 return limit;
11776 }
11777 #endif /* HAVE_PATHCONF */
11778
11779 #ifdef HAVE_CONFSTR
11780 static struct constdef posix_constants_confstr[] = {
11781 #ifdef _CS_ARCHITECTURE
11782 {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
11783 #endif
11784 #ifdef _CS_GNU_LIBC_VERSION
11785 {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION},
11786 #endif
11787 #ifdef _CS_GNU_LIBPTHREAD_VERSION
11788 {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION},
11789 #endif
11790 #ifdef _CS_HOSTNAME
11791 {"CS_HOSTNAME", _CS_HOSTNAME},
11792 #endif
11793 #ifdef _CS_HW_PROVIDER
11794 {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
11795 #endif
11796 #ifdef _CS_HW_SERIAL
11797 {"CS_HW_SERIAL", _CS_HW_SERIAL},
11798 #endif
11799 #ifdef _CS_INITTAB_NAME
11800 {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11801 #endif
11802 #ifdef _CS_LFS64_CFLAGS
11803 {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11804 #endif
11805 #ifdef _CS_LFS64_LDFLAGS
11806 {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
11807 #endif
11808 #ifdef _CS_LFS64_LIBS
11809 {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
11810 #endif
11811 #ifdef _CS_LFS64_LINTFLAGS
11812 {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
11813 #endif
11814 #ifdef _CS_LFS_CFLAGS
11815 {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
11816 #endif
11817 #ifdef _CS_LFS_LDFLAGS
11818 {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
11819 #endif
11820 #ifdef _CS_LFS_LIBS
11821 {"CS_LFS_LIBS", _CS_LFS_LIBS},
11822 #endif
11823 #ifdef _CS_LFS_LINTFLAGS
11824 {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
11825 #endif
11826 #ifdef _CS_MACHINE
11827 {"CS_MACHINE", _CS_MACHINE},
11828 #endif
11829 #ifdef _CS_PATH
11830 {"CS_PATH", _CS_PATH},
11831 #endif
11832 #ifdef _CS_RELEASE
11833 {"CS_RELEASE", _CS_RELEASE},
11834 #endif
11835 #ifdef _CS_SRPC_DOMAIN
11836 {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
11837 #endif
11838 #ifdef _CS_SYSNAME
11839 {"CS_SYSNAME", _CS_SYSNAME},
11840 #endif
11841 #ifdef _CS_VERSION
11842 {"CS_VERSION", _CS_VERSION},
11843 #endif
11844 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11845 {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
11846 #endif
11847 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11848 {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
11849 #endif
11850 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11851 {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
11852 #endif
11853 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11854 {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11855 #endif
11856 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11857 {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11858 #endif
11859 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11860 {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11861 #endif
11862 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11863 {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
11864 #endif
11865 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11866 {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11867 #endif
11868 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11869 {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
11870 #endif
11871 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11872 {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
11873 #endif
11874 #ifdef _CS_XBS5_LP64_OFF64_LIBS
11875 {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11876 #endif
11877 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11878 {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
11879 #endif
11880 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11881 {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11882 #endif
11883 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11884 {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11885 #endif
11886 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11887 {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
11888 #endif
11889 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11890 {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11891 #endif
11892 #ifdef _MIPS_CS_AVAIL_PROCESSORS
11893 {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
11894 #endif
11895 #ifdef _MIPS_CS_BASE
11896 {"MIPS_CS_BASE", _MIPS_CS_BASE},
11897 #endif
11898 #ifdef _MIPS_CS_HOSTID
11899 {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
11900 #endif
11901 #ifdef _MIPS_CS_HW_NAME
11902 {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11903 #endif
11904 #ifdef _MIPS_CS_NUM_PROCESSORS
11905 {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
11906 #endif
11907 #ifdef _MIPS_CS_OSREL_MAJ
11908 {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
11909 #endif
11910 #ifdef _MIPS_CS_OSREL_MIN
11911 {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
11912 #endif
11913 #ifdef _MIPS_CS_OSREL_PATCH
11914 {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
11915 #endif
11916 #ifdef _MIPS_CS_OS_NAME
11917 {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11918 #endif
11919 #ifdef _MIPS_CS_OS_PROVIDER
11920 {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
11921 #endif
11922 #ifdef _MIPS_CS_PROCESSORS
11923 {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
11924 #endif
11925 #ifdef _MIPS_CS_SERIAL
11926 {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
11927 #endif
11928 #ifdef _MIPS_CS_VENDOR
11929 {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
11930 #endif
11931 };
11932
11933 static int
conv_confstr_confname(PyObject * arg,int * valuep)11934 conv_confstr_confname(PyObject *arg, int *valuep)
11935 {
11936 return conv_confname(arg, valuep, posix_constants_confstr,
11937 sizeof(posix_constants_confstr)
11938 / sizeof(struct constdef));
11939 }
11940
11941
11942 /*[clinic input]
11943 os.confstr
11944
11945 name: confstr_confname
11946 /
11947
11948 Return a string-valued system configuration variable.
11949 [clinic start generated code]*/
11950
11951 static PyObject *
os_confstr_impl(PyObject * module,int name)11952 os_confstr_impl(PyObject *module, int name)
11953 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11954 {
11955 PyObject *result = NULL;
11956 char buffer[255];
11957 size_t len;
11958
11959 errno = 0;
11960 len = confstr(name, buffer, sizeof(buffer));
11961 if (len == 0) {
11962 if (errno) {
11963 posix_error();
11964 return NULL;
11965 }
11966 else {
11967 Py_RETURN_NONE;
11968 }
11969 }
11970
11971 if (len >= sizeof(buffer)) {
11972 size_t len2;
11973 char *buf = PyMem_Malloc(len);
11974 if (buf == NULL)
11975 return PyErr_NoMemory();
11976 len2 = confstr(name, buf, len);
11977 assert(len == len2);
11978 result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11979 PyMem_Free(buf);
11980 }
11981 else
11982 result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11983 return result;
11984 }
11985 #endif /* HAVE_CONFSTR */
11986
11987
11988 #ifdef HAVE_SYSCONF
11989 static struct constdef posix_constants_sysconf[] = {
11990 #ifdef _SC_2_CHAR_TERM
11991 {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
11992 #endif
11993 #ifdef _SC_2_C_BIND
11994 {"SC_2_C_BIND", _SC_2_C_BIND},
11995 #endif
11996 #ifdef _SC_2_C_DEV
11997 {"SC_2_C_DEV", _SC_2_C_DEV},
11998 #endif
11999 #ifdef _SC_2_C_VERSION
12000 {"SC_2_C_VERSION", _SC_2_C_VERSION},
12001 #endif
12002 #ifdef _SC_2_FORT_DEV
12003 {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
12004 #endif
12005 #ifdef _SC_2_FORT_RUN
12006 {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
12007 #endif
12008 #ifdef _SC_2_LOCALEDEF
12009 {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
12010 #endif
12011 #ifdef _SC_2_SW_DEV
12012 {"SC_2_SW_DEV", _SC_2_SW_DEV},
12013 #endif
12014 #ifdef _SC_2_UPE
12015 {"SC_2_UPE", _SC_2_UPE},
12016 #endif
12017 #ifdef _SC_2_VERSION
12018 {"SC_2_VERSION", _SC_2_VERSION},
12019 #endif
12020 #ifdef _SC_ABI_ASYNCHRONOUS_IO
12021 {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
12022 #endif
12023 #ifdef _SC_ACL
12024 {"SC_ACL", _SC_ACL},
12025 #endif
12026 #ifdef _SC_AIO_LISTIO_MAX
12027 {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
12028 #endif
12029 #ifdef _SC_AIO_MAX
12030 {"SC_AIO_MAX", _SC_AIO_MAX},
12031 #endif
12032 #ifdef _SC_AIO_PRIO_DELTA_MAX
12033 {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
12034 #endif
12035 #ifdef _SC_ARG_MAX
12036 {"SC_ARG_MAX", _SC_ARG_MAX},
12037 #endif
12038 #ifdef _SC_ASYNCHRONOUS_IO
12039 {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
12040 #endif
12041 #ifdef _SC_ATEXIT_MAX
12042 {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
12043 #endif
12044 #ifdef _SC_AUDIT
12045 {"SC_AUDIT", _SC_AUDIT},
12046 #endif
12047 #ifdef _SC_AVPHYS_PAGES
12048 {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
12049 #endif
12050 #ifdef _SC_BC_BASE_MAX
12051 {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
12052 #endif
12053 #ifdef _SC_BC_DIM_MAX
12054 {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
12055 #endif
12056 #ifdef _SC_BC_SCALE_MAX
12057 {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
12058 #endif
12059 #ifdef _SC_BC_STRING_MAX
12060 {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
12061 #endif
12062 #ifdef _SC_CAP
12063 {"SC_CAP", _SC_CAP},
12064 #endif
12065 #ifdef _SC_CHARCLASS_NAME_MAX
12066 {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
12067 #endif
12068 #ifdef _SC_CHAR_BIT
12069 {"SC_CHAR_BIT", _SC_CHAR_BIT},
12070 #endif
12071 #ifdef _SC_CHAR_MAX
12072 {"SC_CHAR_MAX", _SC_CHAR_MAX},
12073 #endif
12074 #ifdef _SC_CHAR_MIN
12075 {"SC_CHAR_MIN", _SC_CHAR_MIN},
12076 #endif
12077 #ifdef _SC_CHILD_MAX
12078 {"SC_CHILD_MAX", _SC_CHILD_MAX},
12079 #endif
12080 #ifdef _SC_CLK_TCK
12081 {"SC_CLK_TCK", _SC_CLK_TCK},
12082 #endif
12083 #ifdef _SC_COHER_BLKSZ
12084 {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
12085 #endif
12086 #ifdef _SC_COLL_WEIGHTS_MAX
12087 {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
12088 #endif
12089 #ifdef _SC_DCACHE_ASSOC
12090 {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
12091 #endif
12092 #ifdef _SC_DCACHE_BLKSZ
12093 {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
12094 #endif
12095 #ifdef _SC_DCACHE_LINESZ
12096 {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
12097 #endif
12098 #ifdef _SC_DCACHE_SZ
12099 {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
12100 #endif
12101 #ifdef _SC_DCACHE_TBLKSZ
12102 {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
12103 #endif
12104 #ifdef _SC_DELAYTIMER_MAX
12105 {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
12106 #endif
12107 #ifdef _SC_EQUIV_CLASS_MAX
12108 {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
12109 #endif
12110 #ifdef _SC_EXPR_NEST_MAX
12111 {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
12112 #endif
12113 #ifdef _SC_FSYNC
12114 {"SC_FSYNC", _SC_FSYNC},
12115 #endif
12116 #ifdef _SC_GETGR_R_SIZE_MAX
12117 {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
12118 #endif
12119 #ifdef _SC_GETPW_R_SIZE_MAX
12120 {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
12121 #endif
12122 #ifdef _SC_ICACHE_ASSOC
12123 {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
12124 #endif
12125 #ifdef _SC_ICACHE_BLKSZ
12126 {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
12127 #endif
12128 #ifdef _SC_ICACHE_LINESZ
12129 {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
12130 #endif
12131 #ifdef _SC_ICACHE_SZ
12132 {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
12133 #endif
12134 #ifdef _SC_INF
12135 {"SC_INF", _SC_INF},
12136 #endif
12137 #ifdef _SC_INT_MAX
12138 {"SC_INT_MAX", _SC_INT_MAX},
12139 #endif
12140 #ifdef _SC_INT_MIN
12141 {"SC_INT_MIN", _SC_INT_MIN},
12142 #endif
12143 #ifdef _SC_IOV_MAX
12144 {"SC_IOV_MAX", _SC_IOV_MAX},
12145 #endif
12146 #ifdef _SC_IP_SECOPTS
12147 {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
12148 #endif
12149 #ifdef _SC_JOB_CONTROL
12150 {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
12151 #endif
12152 #ifdef _SC_KERN_POINTERS
12153 {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
12154 #endif
12155 #ifdef _SC_KERN_SIM
12156 {"SC_KERN_SIM", _SC_KERN_SIM},
12157 #endif
12158 #ifdef _SC_LINE_MAX
12159 {"SC_LINE_MAX", _SC_LINE_MAX},
12160 #endif
12161 #ifdef _SC_LOGIN_NAME_MAX
12162 {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
12163 #endif
12164 #ifdef _SC_LOGNAME_MAX
12165 {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
12166 #endif
12167 #ifdef _SC_LONG_BIT
12168 {"SC_LONG_BIT", _SC_LONG_BIT},
12169 #endif
12170 #ifdef _SC_MAC
12171 {"SC_MAC", _SC_MAC},
12172 #endif
12173 #ifdef _SC_MAPPED_FILES
12174 {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
12175 #endif
12176 #ifdef _SC_MAXPID
12177 {"SC_MAXPID", _SC_MAXPID},
12178 #endif
12179 #ifdef _SC_MB_LEN_MAX
12180 {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
12181 #endif
12182 #ifdef _SC_MEMLOCK
12183 {"SC_MEMLOCK", _SC_MEMLOCK},
12184 #endif
12185 #ifdef _SC_MEMLOCK_RANGE
12186 {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
12187 #endif
12188 #ifdef _SC_MEMORY_PROTECTION
12189 {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
12190 #endif
12191 #ifdef _SC_MESSAGE_PASSING
12192 {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
12193 #endif
12194 #ifdef _SC_MMAP_FIXED_ALIGNMENT
12195 {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
12196 #endif
12197 #ifdef _SC_MQ_OPEN_MAX
12198 {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
12199 #endif
12200 #ifdef _SC_MQ_PRIO_MAX
12201 {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},
12202 #endif
12203 #ifdef _SC_NACLS_MAX
12204 {"SC_NACLS_MAX", _SC_NACLS_MAX},
12205 #endif
12206 #ifdef _SC_NGROUPS_MAX
12207 {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX},
12208 #endif
12209 #ifdef _SC_NL_ARGMAX
12210 {"SC_NL_ARGMAX", _SC_NL_ARGMAX},
12211 #endif
12212 #ifdef _SC_NL_LANGMAX
12213 {"SC_NL_LANGMAX", _SC_NL_LANGMAX},
12214 #endif
12215 #ifdef _SC_NL_MSGMAX
12216 {"SC_NL_MSGMAX", _SC_NL_MSGMAX},
12217 #endif
12218 #ifdef _SC_NL_NMAX
12219 {"SC_NL_NMAX", _SC_NL_NMAX},
12220 #endif
12221 #ifdef _SC_NL_SETMAX
12222 {"SC_NL_SETMAX", _SC_NL_SETMAX},
12223 #endif
12224 #ifdef _SC_NL_TEXTMAX
12225 {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX},
12226 #endif
12227 #ifdef _SC_NPROCESSORS_CONF
12228 {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
12229 #endif
12230 #ifdef _SC_NPROCESSORS_ONLN
12231 {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
12232 #endif
12233 #ifdef _SC_NPROC_CONF
12234 {"SC_NPROC_CONF", _SC_NPROC_CONF},
12235 #endif
12236 #ifdef _SC_NPROC_ONLN
12237 {"SC_NPROC_ONLN", _SC_NPROC_ONLN},
12238 #endif
12239 #ifdef _SC_NZERO
12240 {"SC_NZERO", _SC_NZERO},
12241 #endif
12242 #ifdef _SC_OPEN_MAX
12243 {"SC_OPEN_MAX", _SC_OPEN_MAX},
12244 #endif
12245 #ifdef _SC_PAGESIZE
12246 {"SC_PAGESIZE", _SC_PAGESIZE},
12247 #endif
12248 #ifdef _SC_PAGE_SIZE
12249 {"SC_PAGE_SIZE", _SC_PAGE_SIZE},
12250 #endif
12251 #ifdef _SC_AIX_REALMEM
12252 {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
12253 #endif
12254 #ifdef _SC_PASS_MAX
12255 {"SC_PASS_MAX", _SC_PASS_MAX},
12256 #endif
12257 #ifdef _SC_PHYS_PAGES
12258 {"SC_PHYS_PAGES", _SC_PHYS_PAGES},
12259 #endif
12260 #ifdef _SC_PII
12261 {"SC_PII", _SC_PII},
12262 #endif
12263 #ifdef _SC_PII_INTERNET
12264 {"SC_PII_INTERNET", _SC_PII_INTERNET},
12265 #endif
12266 #ifdef _SC_PII_INTERNET_DGRAM
12267 {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM},
12268 #endif
12269 #ifdef _SC_PII_INTERNET_STREAM
12270 {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM},
12271 #endif
12272 #ifdef _SC_PII_OSI
12273 {"SC_PII_OSI", _SC_PII_OSI},
12274 #endif
12275 #ifdef _SC_PII_OSI_CLTS
12276 {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
12277 #endif
12278 #ifdef _SC_PII_OSI_COTS
12279 {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
12280 #endif
12281 #ifdef _SC_PII_OSI_M
12282 {"SC_PII_OSI_M", _SC_PII_OSI_M},
12283 #endif
12284 #ifdef _SC_PII_SOCKET
12285 {"SC_PII_SOCKET", _SC_PII_SOCKET},
12286 #endif
12287 #ifdef _SC_PII_XTI
12288 {"SC_PII_XTI", _SC_PII_XTI},
12289 #endif
12290 #ifdef _SC_POLL
12291 {"SC_POLL", _SC_POLL},
12292 #endif
12293 #ifdef _SC_PRIORITIZED_IO
12294 {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO},
12295 #endif
12296 #ifdef _SC_PRIORITY_SCHEDULING
12297 {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING},
12298 #endif
12299 #ifdef _SC_REALTIME_SIGNALS
12300 {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS},
12301 #endif
12302 #ifdef _SC_RE_DUP_MAX
12303 {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX},
12304 #endif
12305 #ifdef _SC_RTSIG_MAX
12306 {"SC_RTSIG_MAX", _SC_RTSIG_MAX},
12307 #endif
12308 #ifdef _SC_SAVED_IDS
12309 {"SC_SAVED_IDS", _SC_SAVED_IDS},
12310 #endif
12311 #ifdef _SC_SCHAR_MAX
12312 {"SC_SCHAR_MAX", _SC_SCHAR_MAX},
12313 #endif
12314 #ifdef _SC_SCHAR_MIN
12315 {"SC_SCHAR_MIN", _SC_SCHAR_MIN},
12316 #endif
12317 #ifdef _SC_SELECT
12318 {"SC_SELECT", _SC_SELECT},
12319 #endif
12320 #ifdef _SC_SEMAPHORES
12321 {"SC_SEMAPHORES", _SC_SEMAPHORES},
12322 #endif
12323 #ifdef _SC_SEM_NSEMS_MAX
12324 {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX},
12325 #endif
12326 #ifdef _SC_SEM_VALUE_MAX
12327 {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX},
12328 #endif
12329 #ifdef _SC_SHARED_MEMORY_OBJECTS
12330 {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS},
12331 #endif
12332 #ifdef _SC_SHRT_MAX
12333 {"SC_SHRT_MAX", _SC_SHRT_MAX},
12334 #endif
12335 #ifdef _SC_SHRT_MIN
12336 {"SC_SHRT_MIN", _SC_SHRT_MIN},
12337 #endif
12338 #ifdef _SC_SIGQUEUE_MAX
12339 {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
12340 #endif
12341 #ifdef _SC_SIGRT_MAX
12342 {"SC_SIGRT_MAX", _SC_SIGRT_MAX},
12343 #endif
12344 #ifdef _SC_SIGRT_MIN
12345 {"SC_SIGRT_MIN", _SC_SIGRT_MIN},
12346 #endif
12347 #ifdef _SC_SOFTPOWER
12348 {"SC_SOFTPOWER", _SC_SOFTPOWER},
12349 #endif
12350 #ifdef _SC_SPLIT_CACHE
12351 {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE},
12352 #endif
12353 #ifdef _SC_SSIZE_MAX
12354 {"SC_SSIZE_MAX", _SC_SSIZE_MAX},
12355 #endif
12356 #ifdef _SC_STACK_PROT
12357 {"SC_STACK_PROT", _SC_STACK_PROT},
12358 #endif
12359 #ifdef _SC_STREAM_MAX
12360 {"SC_STREAM_MAX", _SC_STREAM_MAX},
12361 #endif
12362 #ifdef _SC_SYNCHRONIZED_IO
12363 {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO},
12364 #endif
12365 #ifdef _SC_THREADS
12366 {"SC_THREADS", _SC_THREADS},
12367 #endif
12368 #ifdef _SC_THREAD_ATTR_STACKADDR
12369 {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR},
12370 #endif
12371 #ifdef _SC_THREAD_ATTR_STACKSIZE
12372 {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE},
12373 #endif
12374 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
12375 {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
12376 #endif
12377 #ifdef _SC_THREAD_KEYS_MAX
12378 {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
12379 #endif
12380 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
12381 {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING},
12382 #endif
12383 #ifdef _SC_THREAD_PRIO_INHERIT
12384 {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT},
12385 #endif
12386 #ifdef _SC_THREAD_PRIO_PROTECT
12387 {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT},
12388 #endif
12389 #ifdef _SC_THREAD_PROCESS_SHARED
12390 {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED},
12391 #endif
12392 #ifdef _SC_THREAD_SAFE_FUNCTIONS
12393 {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS},
12394 #endif
12395 #ifdef _SC_THREAD_STACK_MIN
12396 {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
12397 #endif
12398 #ifdef _SC_THREAD_THREADS_MAX
12399 {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
12400 #endif
12401 #ifdef _SC_TIMERS
12402 {"SC_TIMERS", _SC_TIMERS},
12403 #endif
12404 #ifdef _SC_TIMER_MAX
12405 {"SC_TIMER_MAX", _SC_TIMER_MAX},
12406 #endif
12407 #ifdef _SC_TTY_NAME_MAX
12408 {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
12409 #endif
12410 #ifdef _SC_TZNAME_MAX
12411 {"SC_TZNAME_MAX", _SC_TZNAME_MAX},
12412 #endif
12413 #ifdef _SC_T_IOV_MAX
12414 {"SC_T_IOV_MAX", _SC_T_IOV_MAX},
12415 #endif
12416 #ifdef _SC_UCHAR_MAX
12417 {"SC_UCHAR_MAX", _SC_UCHAR_MAX},
12418 #endif
12419 #ifdef _SC_UINT_MAX
12420 {"SC_UINT_MAX", _SC_UINT_MAX},
12421 #endif
12422 #ifdef _SC_UIO_MAXIOV
12423 {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV},
12424 #endif
12425 #ifdef _SC_ULONG_MAX
12426 {"SC_ULONG_MAX", _SC_ULONG_MAX},
12427 #endif
12428 #ifdef _SC_USHRT_MAX
12429 {"SC_USHRT_MAX", _SC_USHRT_MAX},
12430 #endif
12431 #ifdef _SC_VERSION
12432 {"SC_VERSION", _SC_VERSION},
12433 #endif
12434 #ifdef _SC_WORD_BIT
12435 {"SC_WORD_BIT", _SC_WORD_BIT},
12436 #endif
12437 #ifdef _SC_XBS5_ILP32_OFF32
12438 {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32},
12439 #endif
12440 #ifdef _SC_XBS5_ILP32_OFFBIG
12441 {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG},
12442 #endif
12443 #ifdef _SC_XBS5_LP64_OFF64
12444 {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64},
12445 #endif
12446 #ifdef _SC_XBS5_LPBIG_OFFBIG
12447 {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG},
12448 #endif
12449 #ifdef _SC_XOPEN_CRYPT
12450 {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT},
12451 #endif
12452 #ifdef _SC_XOPEN_ENH_I18N
12453 {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N},
12454 #endif
12455 #ifdef _SC_XOPEN_LEGACY
12456 {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
12457 #endif
12458 #ifdef _SC_XOPEN_REALTIME
12459 {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME},
12460 #endif
12461 #ifdef _SC_XOPEN_REALTIME_THREADS
12462 {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS},
12463 #endif
12464 #ifdef _SC_XOPEN_SHM
12465 {"SC_XOPEN_SHM", _SC_XOPEN_SHM},
12466 #endif
12467 #ifdef _SC_XOPEN_UNIX
12468 {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX},
12469 #endif
12470 #ifdef _SC_XOPEN_VERSION
12471 {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION},
12472 #endif
12473 #ifdef _SC_XOPEN_XCU_VERSION
12474 {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION},
12475 #endif
12476 #ifdef _SC_XOPEN_XPG2
12477 {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2},
12478 #endif
12479 #ifdef _SC_XOPEN_XPG3
12480 {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3},
12481 #endif
12482 #ifdef _SC_XOPEN_XPG4
12483 {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4},
12484 #endif
12485 #ifdef _SC_MINSIGSTKSZ
12486 {"SC_MINSIGSTKSZ", _SC_MINSIGSTKSZ},
12487 #endif
12488 };
12489
12490 static int
conv_sysconf_confname(PyObject * arg,int * valuep)12491 conv_sysconf_confname(PyObject *arg, int *valuep)
12492 {
12493 return conv_confname(arg, valuep, posix_constants_sysconf,
12494 sizeof(posix_constants_sysconf)
12495 / sizeof(struct constdef));
12496 }
12497
12498
12499 /*[clinic input]
12500 os.sysconf -> long
12501 name: sysconf_confname
12502 /
12503
12504 Return an integer-valued system configuration variable.
12505 [clinic start generated code]*/
12506
12507 static long
os_sysconf_impl(PyObject * module,int name)12508 os_sysconf_impl(PyObject *module, int name)
12509 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
12510 {
12511 long value;
12512
12513 errno = 0;
12514 value = sysconf(name);
12515 if (value == -1 && errno != 0)
12516 posix_error();
12517 return value;
12518 }
12519 #endif /* HAVE_SYSCONF */
12520
12521
12522 /* This code is used to ensure that the tables of configuration value names
12523 * are in sorted order as required by conv_confname(), and also to build
12524 * the exported dictionaries that are used to publish information about the
12525 * names available on the host platform.
12526 *
12527 * Sorting the table at runtime ensures that the table is properly ordered
12528 * when used, even for platforms we're not able to test on. It also makes
12529 * it easier to add additional entries to the tables.
12530 */
12531
12532 static int
cmp_constdefs(const void * v1,const void * v2)12533 cmp_constdefs(const void *v1, const void *v2)
12534 {
12535 const struct constdef *c1 =
12536 (const struct constdef *) v1;
12537 const struct constdef *c2 =
12538 (const struct constdef *) v2;
12539
12540 return strcmp(c1->name, c2->name);
12541 }
12542
12543 static int
setup_confname_table(struct constdef * table,size_t tablesize,const char * tablename,PyObject * module)12544 setup_confname_table(struct constdef *table, size_t tablesize,
12545 const char *tablename, PyObject *module)
12546 {
12547 PyObject *d = NULL;
12548 size_t i;
12549
12550 qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
12551 d = PyDict_New();
12552 if (d == NULL)
12553 return -1;
12554
12555 for (i=0; i < tablesize; ++i) {
12556 PyObject *o = PyLong_FromLong(table[i].value);
12557 if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
12558 Py_XDECREF(o);
12559 Py_DECREF(d);
12560 return -1;
12561 }
12562 Py_DECREF(o);
12563 }
12564 return PyModule_AddObject(module, tablename, d);
12565 }
12566
12567 /* Return -1 on failure, 0 on success. */
12568 static int
setup_confname_tables(PyObject * module)12569 setup_confname_tables(PyObject *module)
12570 {
12571 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12572 if (setup_confname_table(posix_constants_pathconf,
12573 sizeof(posix_constants_pathconf)
12574 / sizeof(struct constdef),
12575 "pathconf_names", module))
12576 return -1;
12577 #endif
12578 #ifdef HAVE_CONFSTR
12579 if (setup_confname_table(posix_constants_confstr,
12580 sizeof(posix_constants_confstr)
12581 / sizeof(struct constdef),
12582 "confstr_names", module))
12583 return -1;
12584 #endif
12585 #ifdef HAVE_SYSCONF
12586 if (setup_confname_table(posix_constants_sysconf,
12587 sizeof(posix_constants_sysconf)
12588 / sizeof(struct constdef),
12589 "sysconf_names", module))
12590 return -1;
12591 #endif
12592 return 0;
12593 }
12594
12595
12596 /*[clinic input]
12597 os.abort
12598
12599 Abort the interpreter immediately.
12600
12601 This function 'dumps core' or otherwise fails in the hardest way possible
12602 on the hosting operating system. This function never returns.
12603 [clinic start generated code]*/
12604
12605 static PyObject *
os_abort_impl(PyObject * module)12606 os_abort_impl(PyObject *module)
12607 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
12608 {
12609 abort();
12610 /*NOTREACHED*/
12611 #ifndef __clang__
12612 /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
12613 GCC emits a warning without "return NULL;" (compiler bug?), but Clang
12614 is smarter and emits a warning on the return. */
12615 Py_FatalError("abort() called from Python code didn't abort!");
12616 return NULL;
12617 #endif
12618 }
12619
12620 #ifdef MS_WINDOWS
12621 /* Grab ShellExecute dynamically from shell32 */
12622 static int has_ShellExecute = -1;
12623 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
12624 LPCWSTR, INT);
12625 static int
check_ShellExecute()12626 check_ShellExecute()
12627 {
12628 HINSTANCE hShell32;
12629
12630 /* only recheck */
12631 if (-1 == has_ShellExecute) {
12632 Py_BEGIN_ALLOW_THREADS
12633 /* Security note: this call is not vulnerable to "DLL hijacking".
12634 SHELL32 is part of "KnownDLLs" and so Windows always load
12635 the system SHELL32.DLL, even if there is another SHELL32.DLL
12636 in the DLL search path. */
12637 hShell32 = LoadLibraryW(L"SHELL32");
12638 if (hShell32) {
12639 *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
12640 "ShellExecuteW");
12641 has_ShellExecute = Py_ShellExecuteW != NULL;
12642 } else {
12643 has_ShellExecute = 0;
12644 }
12645 Py_END_ALLOW_THREADS
12646 }
12647 return has_ShellExecute;
12648 }
12649
12650
12651 /*[clinic input]
12652 os.startfile
12653 filepath: path_t
12654 operation: Py_UNICODE = NULL
12655 arguments: Py_UNICODE = NULL
12656 cwd: path_t(nullable=True) = None
12657 show_cmd: int = 1
12658
12659 Start a file with its associated application.
12660
12661 When "operation" is not specified or "open", this acts like
12662 double-clicking the file in Explorer, or giving the file name as an
12663 argument to the DOS "start" command: the file is opened with whatever
12664 application (if any) its extension is associated.
12665 When another "operation" is given, it specifies what should be done with
12666 the file. A typical operation is "print".
12667
12668 "arguments" is passed to the application, but should be omitted if the
12669 file is a document.
12670
12671 "cwd" is the working directory for the operation. If "filepath" is
12672 relative, it will be resolved against this directory. This argument
12673 should usually be an absolute path.
12674
12675 "show_cmd" can be used to override the recommended visibility option.
12676 See the Windows ShellExecute documentation for values.
12677
12678 startfile returns as soon as the associated application is launched.
12679 There is no option to wait for the application to close, and no way
12680 to retrieve the application's exit status.
12681
12682 The filepath is relative to the current directory. If you want to use
12683 an absolute path, make sure the first character is not a slash ("/");
12684 the underlying Win32 ShellExecute function doesn't work if it is.
12685 [clinic start generated code]*/
12686
12687 static PyObject *
os_startfile_impl(PyObject * module,path_t * filepath,const Py_UNICODE * operation,const Py_UNICODE * arguments,path_t * cwd,int show_cmd)12688 os_startfile_impl(PyObject *module, path_t *filepath,
12689 const Py_UNICODE *operation, const Py_UNICODE *arguments,
12690 path_t *cwd, int show_cmd)
12691 /*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/
12692 {
12693 HINSTANCE rc;
12694
12695 if(!check_ShellExecute()) {
12696 /* If the OS doesn't have ShellExecute, return a
12697 NotImplementedError. */
12698 return PyErr_Format(PyExc_NotImplementedError,
12699 "startfile not available on this platform");
12700 }
12701
12702 if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
12703 return NULL;
12704 }
12705 if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
12706 arguments, cwd->object ? cwd->object : Py_None,
12707 show_cmd) < 0) {
12708 return NULL;
12709 }
12710
12711 Py_BEGIN_ALLOW_THREADS
12712 rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
12713 arguments, cwd->wide, show_cmd);
12714 Py_END_ALLOW_THREADS
12715
12716 if (rc <= (HINSTANCE)32) {
12717 win32_error_object("startfile", filepath->object);
12718 return NULL;
12719 }
12720 Py_RETURN_NONE;
12721 }
12722 #endif /* MS_WINDOWS */
12723
12724
12725 #ifdef HAVE_GETLOADAVG
12726 /*[clinic input]
12727 os.getloadavg
12728
12729 Return average recent system load information.
12730
12731 Return the number of processes in the system run queue averaged over
12732 the last 1, 5, and 15 minutes as a tuple of three floats.
12733 Raises OSError if the load average was unobtainable.
12734 [clinic start generated code]*/
12735
12736 static PyObject *
os_getloadavg_impl(PyObject * module)12737 os_getloadavg_impl(PyObject *module)
12738 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
12739 {
12740 double loadavg[3];
12741 if (getloadavg(loadavg, 3)!=3) {
12742 PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
12743 return NULL;
12744 } else
12745 return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
12746 }
12747 #endif /* HAVE_GETLOADAVG */
12748
12749
12750 /*[clinic input]
12751 os.device_encoding
12752 fd: int
12753
12754 Return a string describing the encoding of a terminal's file descriptor.
12755
12756 The file descriptor must be attached to a terminal.
12757 If the device is not a terminal, return None.
12758 [clinic start generated code]*/
12759
12760 static PyObject *
os_device_encoding_impl(PyObject * module,int fd)12761 os_device_encoding_impl(PyObject *module, int fd)
12762 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
12763 {
12764 return _Py_device_encoding(fd);
12765 }
12766
12767
12768 #ifdef HAVE_SETRESUID
12769 /*[clinic input]
12770 os.setresuid
12771
12772 ruid: uid_t
12773 euid: uid_t
12774 suid: uid_t
12775 /
12776
12777 Set the current process's real, effective, and saved user ids.
12778 [clinic start generated code]*/
12779
12780 static PyObject *
os_setresuid_impl(PyObject * module,uid_t ruid,uid_t euid,uid_t suid)12781 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
12782 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
12783 {
12784 if (setresuid(ruid, euid, suid) < 0)
12785 return posix_error();
12786 Py_RETURN_NONE;
12787 }
12788 #endif /* HAVE_SETRESUID */
12789
12790
12791 #ifdef HAVE_SETRESGID
12792 /*[clinic input]
12793 os.setresgid
12794
12795 rgid: gid_t
12796 egid: gid_t
12797 sgid: gid_t
12798 /
12799
12800 Set the current process's real, effective, and saved group ids.
12801 [clinic start generated code]*/
12802
12803 static PyObject *
os_setresgid_impl(PyObject * module,gid_t rgid,gid_t egid,gid_t sgid)12804 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
12805 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
12806 {
12807 if (setresgid(rgid, egid, sgid) < 0)
12808 return posix_error();
12809 Py_RETURN_NONE;
12810 }
12811 #endif /* HAVE_SETRESGID */
12812
12813
12814 #ifdef HAVE_GETRESUID
12815 /*[clinic input]
12816 os.getresuid
12817
12818 Return a tuple of the current process's real, effective, and saved user ids.
12819 [clinic start generated code]*/
12820
12821 static PyObject *
os_getresuid_impl(PyObject * module)12822 os_getresuid_impl(PyObject *module)
12823 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12824 {
12825 uid_t ruid, euid, suid;
12826 if (getresuid(&ruid, &euid, &suid) < 0)
12827 return posix_error();
12828 return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12829 _PyLong_FromUid(euid),
12830 _PyLong_FromUid(suid));
12831 }
12832 #endif /* HAVE_GETRESUID */
12833
12834
12835 #ifdef HAVE_GETRESGID
12836 /*[clinic input]
12837 os.getresgid
12838
12839 Return a tuple of the current process's real, effective, and saved group ids.
12840 [clinic start generated code]*/
12841
12842 static PyObject *
os_getresgid_impl(PyObject * module)12843 os_getresgid_impl(PyObject *module)
12844 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12845 {
12846 gid_t rgid, egid, sgid;
12847 if (getresgid(&rgid, &egid, &sgid) < 0)
12848 return posix_error();
12849 return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12850 _PyLong_FromGid(egid),
12851 _PyLong_FromGid(sgid));
12852 }
12853 #endif /* HAVE_GETRESGID */
12854
12855
12856 #ifdef USE_XATTRS
12857 /*[clinic input]
12858 os.getxattr
12859
12860 path: path_t(allow_fd=True)
12861 attribute: path_t
12862 *
12863 follow_symlinks: bool = True
12864
12865 Return the value of extended attribute attribute on path.
12866
12867 path may be either a string, a path-like object, or an open file descriptor.
12868 If follow_symlinks is False, and the last element of the path is a symbolic
12869 link, getxattr will examine the symbolic link itself instead of the file
12870 the link points to.
12871
12872 [clinic start generated code]*/
12873
12874 static PyObject *
os_getxattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12875 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12876 int follow_symlinks)
12877 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12878 {
12879 Py_ssize_t i;
12880 PyObject *buffer = NULL;
12881
12882 if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12883 return NULL;
12884
12885 if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12886 return NULL;
12887 }
12888
12889 for (i = 0; ; i++) {
12890 void *ptr;
12891 ssize_t result;
12892 static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12893 Py_ssize_t buffer_size = buffer_sizes[i];
12894 if (!buffer_size) {
12895 path_error(path);
12896 return NULL;
12897 }
12898 buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12899 if (!buffer)
12900 return NULL;
12901 ptr = PyBytes_AS_STRING(buffer);
12902
12903 Py_BEGIN_ALLOW_THREADS;
12904 if (path->fd >= 0)
12905 result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12906 else if (follow_symlinks)
12907 result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12908 else
12909 result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12910 Py_END_ALLOW_THREADS;
12911
12912 if (result < 0) {
12913 Py_DECREF(buffer);
12914 if (errno == ERANGE)
12915 continue;
12916 path_error(path);
12917 return NULL;
12918 }
12919
12920 if (result != buffer_size) {
12921 /* Can only shrink. */
12922 _PyBytes_Resize(&buffer, result);
12923 }
12924 break;
12925 }
12926
12927 return buffer;
12928 }
12929
12930
12931 /*[clinic input]
12932 os.setxattr
12933
12934 path: path_t(allow_fd=True)
12935 attribute: path_t
12936 value: Py_buffer
12937 flags: int = 0
12938 *
12939 follow_symlinks: bool = True
12940
12941 Set extended attribute attribute on path to value.
12942
12943 path may be either a string, a path-like object, or an open file descriptor.
12944 If follow_symlinks is False, and the last element of the path is a symbolic
12945 link, setxattr will modify the symbolic link itself instead of the file
12946 the link points to.
12947
12948 [clinic start generated code]*/
12949
12950 static PyObject *
os_setxattr_impl(PyObject * module,path_t * path,path_t * attribute,Py_buffer * value,int flags,int follow_symlinks)12951 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12952 Py_buffer *value, int flags, int follow_symlinks)
12953 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12954 {
12955 ssize_t result;
12956
12957 if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12958 return NULL;
12959
12960 if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12961 value->buf, value->len, flags) < 0) {
12962 return NULL;
12963 }
12964
12965 Py_BEGIN_ALLOW_THREADS;
12966 if (path->fd > -1)
12967 result = fsetxattr(path->fd, attribute->narrow,
12968 value->buf, value->len, flags);
12969 else if (follow_symlinks)
12970 result = setxattr(path->narrow, attribute->narrow,
12971 value->buf, value->len, flags);
12972 else
12973 result = lsetxattr(path->narrow, attribute->narrow,
12974 value->buf, value->len, flags);
12975 Py_END_ALLOW_THREADS;
12976
12977 if (result) {
12978 path_error(path);
12979 return NULL;
12980 }
12981
12982 Py_RETURN_NONE;
12983 }
12984
12985
12986 /*[clinic input]
12987 os.removexattr
12988
12989 path: path_t(allow_fd=True)
12990 attribute: path_t
12991 *
12992 follow_symlinks: bool = True
12993
12994 Remove extended attribute attribute on path.
12995
12996 path may be either a string, a path-like object, or an open file descriptor.
12997 If follow_symlinks is False, and the last element of the path is a symbolic
12998 link, removexattr will modify the symbolic link itself instead of the file
12999 the link points to.
13000
13001 [clinic start generated code]*/
13002
13003 static PyObject *
os_removexattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)13004 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
13005 int follow_symlinks)
13006 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
13007 {
13008 ssize_t result;
13009
13010 if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
13011 return NULL;
13012
13013 if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
13014 return NULL;
13015 }
13016
13017 Py_BEGIN_ALLOW_THREADS;
13018 if (path->fd > -1)
13019 result = fremovexattr(path->fd, attribute->narrow);
13020 else if (follow_symlinks)
13021 result = removexattr(path->narrow, attribute->narrow);
13022 else
13023 result = lremovexattr(path->narrow, attribute->narrow);
13024 Py_END_ALLOW_THREADS;
13025
13026 if (result) {
13027 return path_error(path);
13028 }
13029
13030 Py_RETURN_NONE;
13031 }
13032
13033
13034 /*[clinic input]
13035 os.listxattr
13036
13037 path: path_t(allow_fd=True, nullable=True) = None
13038 *
13039 follow_symlinks: bool = True
13040
13041 Return a list of extended attributes on path.
13042
13043 path may be either None, a string, a path-like object, or an open file descriptor.
13044 if path is None, listxattr will examine the current directory.
13045 If follow_symlinks is False, and the last element of the path is a symbolic
13046 link, listxattr will examine the symbolic link itself instead of the file
13047 the link points to.
13048 [clinic start generated code]*/
13049
13050 static PyObject *
os_listxattr_impl(PyObject * module,path_t * path,int follow_symlinks)13051 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
13052 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
13053 {
13054 Py_ssize_t i;
13055 PyObject *result = NULL;
13056 const char *name;
13057 char *buffer = NULL;
13058
13059 if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
13060 goto exit;
13061
13062 if (PySys_Audit("os.listxattr", "(O)",
13063 path->object ? path->object : Py_None) < 0) {
13064 return NULL;
13065 }
13066
13067 name = path->narrow ? path->narrow : ".";
13068
13069 for (i = 0; ; i++) {
13070 const char *start, *trace, *end;
13071 ssize_t length;
13072 static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
13073 Py_ssize_t buffer_size = buffer_sizes[i];
13074 if (!buffer_size) {
13075 /* ERANGE */
13076 path_error(path);
13077 break;
13078 }
13079 buffer = PyMem_Malloc(buffer_size);
13080 if (!buffer) {
13081 PyErr_NoMemory();
13082 break;
13083 }
13084
13085 Py_BEGIN_ALLOW_THREADS;
13086 if (path->fd > -1)
13087 length = flistxattr(path->fd, buffer, buffer_size);
13088 else if (follow_symlinks)
13089 length = listxattr(name, buffer, buffer_size);
13090 else
13091 length = llistxattr(name, buffer, buffer_size);
13092 Py_END_ALLOW_THREADS;
13093
13094 if (length < 0) {
13095 if (errno == ERANGE) {
13096 PyMem_Free(buffer);
13097 buffer = NULL;
13098 continue;
13099 }
13100 path_error(path);
13101 break;
13102 }
13103
13104 result = PyList_New(0);
13105 if (!result) {
13106 goto exit;
13107 }
13108
13109 end = buffer + length;
13110 for (trace = start = buffer; trace != end; trace++) {
13111 if (!*trace) {
13112 int error;
13113 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
13114 trace - start);
13115 if (!attribute) {
13116 Py_DECREF(result);
13117 result = NULL;
13118 goto exit;
13119 }
13120 error = PyList_Append(result, attribute);
13121 Py_DECREF(attribute);
13122 if (error) {
13123 Py_DECREF(result);
13124 result = NULL;
13125 goto exit;
13126 }
13127 start = trace + 1;
13128 }
13129 }
13130 break;
13131 }
13132 exit:
13133 if (buffer)
13134 PyMem_Free(buffer);
13135 return result;
13136 }
13137 #endif /* USE_XATTRS */
13138
13139
13140 /*[clinic input]
13141 os.urandom
13142
13143 size: Py_ssize_t
13144 /
13145
13146 Return a bytes object containing random bytes suitable for cryptographic use.
13147 [clinic start generated code]*/
13148
13149 static PyObject *
os_urandom_impl(PyObject * module,Py_ssize_t size)13150 os_urandom_impl(PyObject *module, Py_ssize_t size)
13151 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
13152 {
13153 PyObject *bytes;
13154 int result;
13155
13156 if (size < 0)
13157 return PyErr_Format(PyExc_ValueError,
13158 "negative argument not allowed");
13159 bytes = PyBytes_FromStringAndSize(NULL, size);
13160 if (bytes == NULL)
13161 return NULL;
13162
13163 result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
13164 if (result == -1) {
13165 Py_DECREF(bytes);
13166 return NULL;
13167 }
13168 return bytes;
13169 }
13170
13171 #ifdef HAVE_MEMFD_CREATE
13172 /*[clinic input]
13173 os.memfd_create
13174
13175 name: FSConverter
13176 flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
13177
13178 [clinic start generated code]*/
13179
13180 static PyObject *
os_memfd_create_impl(PyObject * module,PyObject * name,unsigned int flags)13181 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
13182 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
13183 {
13184 int fd;
13185 const char *bytes = PyBytes_AS_STRING(name);
13186 Py_BEGIN_ALLOW_THREADS
13187 fd = memfd_create(bytes, flags);
13188 Py_END_ALLOW_THREADS
13189 if (fd == -1) {
13190 return PyErr_SetFromErrno(PyExc_OSError);
13191 }
13192 return PyLong_FromLong(fd);
13193 }
13194 #endif
13195
13196 #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
13197 /*[clinic input]
13198 os.eventfd
13199
13200 initval: unsigned_int
13201 flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
13202
13203 Creates and returns an event notification file descriptor.
13204 [clinic start generated code]*/
13205
13206 static PyObject *
os_eventfd_impl(PyObject * module,unsigned int initval,int flags)13207 os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
13208 /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
13209
13210 {
13211 /* initval is limited to uint32_t, internal counter is uint64_t */
13212 int fd;
13213 Py_BEGIN_ALLOW_THREADS
13214 fd = eventfd(initval, flags);
13215 Py_END_ALLOW_THREADS
13216 if (fd == -1) {
13217 return PyErr_SetFromErrno(PyExc_OSError);
13218 }
13219 return PyLong_FromLong(fd);
13220 }
13221
13222 /*[clinic input]
13223 os.eventfd_read
13224
13225 fd: fildes
13226
13227 Read eventfd value
13228 [clinic start generated code]*/
13229
13230 static PyObject *
os_eventfd_read_impl(PyObject * module,int fd)13231 os_eventfd_read_impl(PyObject *module, int fd)
13232 /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
13233 {
13234 eventfd_t value;
13235 int result;
13236 Py_BEGIN_ALLOW_THREADS
13237 result = eventfd_read(fd, &value);
13238 Py_END_ALLOW_THREADS
13239 if (result == -1) {
13240 return PyErr_SetFromErrno(PyExc_OSError);
13241 }
13242 return PyLong_FromUnsignedLongLong(value);
13243 }
13244
13245 /*[clinic input]
13246 os.eventfd_write
13247
13248 fd: fildes
13249 value: unsigned_long_long
13250
13251 Write eventfd value.
13252 [clinic start generated code]*/
13253
13254 static PyObject *
os_eventfd_write_impl(PyObject * module,int fd,unsigned long long value)13255 os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
13256 /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
13257 {
13258 int result;
13259 Py_BEGIN_ALLOW_THREADS
13260 result = eventfd_write(fd, value);
13261 Py_END_ALLOW_THREADS
13262 if (result == -1) {
13263 return PyErr_SetFromErrno(PyExc_OSError);
13264 }
13265 Py_RETURN_NONE;
13266 }
13267 #endif /* HAVE_EVENTFD && EFD_CLOEXEC */
13268
13269 /* Terminal size querying */
13270
13271 PyDoc_STRVAR(TerminalSize_docstring,
13272 "A tuple of (columns, lines) for holding terminal window size");
13273
13274 static PyStructSequence_Field TerminalSize_fields[] = {
13275 {"columns", "width of the terminal window in characters"},
13276 {"lines", "height of the terminal window in characters"},
13277 {NULL, NULL}
13278 };
13279
13280 static PyStructSequence_Desc TerminalSize_desc = {
13281 "os.terminal_size",
13282 TerminalSize_docstring,
13283 TerminalSize_fields,
13284 2,
13285 };
13286
13287 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
13288 /*[clinic input]
13289 os.get_terminal_size
13290
13291 fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
13292 /
13293
13294 Return the size of the terminal window as (columns, lines).
13295
13296 The optional argument fd (default standard output) specifies
13297 which file descriptor should be queried.
13298
13299 If the file descriptor is not connected to a terminal, an OSError
13300 is thrown.
13301
13302 This function will only be defined if an implementation is
13303 available for this system.
13304
13305 shutil.get_terminal_size is the high-level function which should
13306 normally be used, os.get_terminal_size is the low-level implementation.
13307 [clinic start generated code]*/
13308
13309 static PyObject *
os_get_terminal_size_impl(PyObject * module,int fd)13310 os_get_terminal_size_impl(PyObject *module, int fd)
13311 /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
13312 {
13313 int columns, lines;
13314 PyObject *termsize;
13315
13316 /* Under some conditions stdout may not be connected and
13317 * fileno(stdout) may point to an invalid file descriptor. For example
13318 * GUI apps don't have valid standard streams by default.
13319 *
13320 * If this happens, and the optional fd argument is not present,
13321 * the ioctl below will fail returning EBADF. This is what we want.
13322 */
13323
13324 #ifdef TERMSIZE_USE_IOCTL
13325 {
13326 struct winsize w;
13327 if (ioctl(fd, TIOCGWINSZ, &w))
13328 return PyErr_SetFromErrno(PyExc_OSError);
13329 columns = w.ws_col;
13330 lines = w.ws_row;
13331 }
13332 #endif /* TERMSIZE_USE_IOCTL */
13333
13334 #ifdef TERMSIZE_USE_CONIO
13335 {
13336 DWORD nhandle;
13337 HANDLE handle;
13338 CONSOLE_SCREEN_BUFFER_INFO csbi;
13339 switch (fd) {
13340 case 0: nhandle = STD_INPUT_HANDLE;
13341 break;
13342 case 1: nhandle = STD_OUTPUT_HANDLE;
13343 break;
13344 case 2: nhandle = STD_ERROR_HANDLE;
13345 break;
13346 default:
13347 return PyErr_Format(PyExc_ValueError, "bad file descriptor");
13348 }
13349 handle = GetStdHandle(nhandle);
13350 if (handle == NULL)
13351 return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
13352 if (handle == INVALID_HANDLE_VALUE)
13353 return PyErr_SetFromWindowsErr(0);
13354
13355 if (!GetConsoleScreenBufferInfo(handle, &csbi))
13356 return PyErr_SetFromWindowsErr(0);
13357
13358 columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
13359 lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
13360 }
13361 #endif /* TERMSIZE_USE_CONIO */
13362
13363 PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
13364 termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
13365 if (termsize == NULL)
13366 return NULL;
13367 PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
13368 PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
13369 if (PyErr_Occurred()) {
13370 Py_DECREF(termsize);
13371 return NULL;
13372 }
13373 return termsize;
13374 }
13375 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
13376
13377
13378 /*[clinic input]
13379 os.cpu_count
13380
13381 Return the number of CPUs in the system; return None if indeterminable.
13382
13383 This number is not equivalent to the number of CPUs the current process can
13384 use. The number of usable CPUs can be obtained with
13385 ``len(os.sched_getaffinity(0))``
13386 [clinic start generated code]*/
13387
13388 static PyObject *
os_cpu_count_impl(PyObject * module)13389 os_cpu_count_impl(PyObject *module)
13390 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
13391 {
13392 int ncpu = 0;
13393 #ifdef MS_WINDOWS
13394 ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
13395 #elif defined(__hpux)
13396 ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
13397 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
13398 ncpu = sysconf(_SC_NPROCESSORS_ONLN);
13399 #elif defined(__VXWORKS__)
13400 ncpu = _Py_popcount32(vxCpuEnabledGet());
13401 #elif defined(__DragonFly__) || \
13402 defined(__OpenBSD__) || \
13403 defined(__FreeBSD__) || \
13404 defined(__NetBSD__) || \
13405 defined(__APPLE__)
13406 int mib[2];
13407 size_t len = sizeof(ncpu);
13408 mib[0] = CTL_HW;
13409 mib[1] = HW_NCPU;
13410 if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
13411 ncpu = 0;
13412 #endif
13413 if (ncpu >= 1)
13414 return PyLong_FromLong(ncpu);
13415 else
13416 Py_RETURN_NONE;
13417 }
13418
13419
13420 /*[clinic input]
13421 os.get_inheritable -> bool
13422
13423 fd: int
13424 /
13425
13426 Get the close-on-exe flag of the specified file descriptor.
13427 [clinic start generated code]*/
13428
13429 static int
os_get_inheritable_impl(PyObject * module,int fd)13430 os_get_inheritable_impl(PyObject *module, int fd)
13431 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
13432 {
13433 int return_value;
13434 _Py_BEGIN_SUPPRESS_IPH
13435 return_value = _Py_get_inheritable(fd);
13436 _Py_END_SUPPRESS_IPH
13437 return return_value;
13438 }
13439
13440
13441 /*[clinic input]
13442 os.set_inheritable
13443 fd: int
13444 inheritable: int
13445 /
13446
13447 Set the inheritable flag of the specified file descriptor.
13448 [clinic start generated code]*/
13449
13450 static PyObject *
os_set_inheritable_impl(PyObject * module,int fd,int inheritable)13451 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
13452 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
13453 {
13454 int result;
13455
13456 _Py_BEGIN_SUPPRESS_IPH
13457 result = _Py_set_inheritable(fd, inheritable, NULL);
13458 _Py_END_SUPPRESS_IPH
13459 if (result < 0)
13460 return NULL;
13461 Py_RETURN_NONE;
13462 }
13463
13464
13465 #ifdef MS_WINDOWS
13466 /*[clinic input]
13467 os.get_handle_inheritable -> bool
13468 handle: intptr_t
13469 /
13470
13471 Get the close-on-exe flag of the specified file descriptor.
13472 [clinic start generated code]*/
13473
13474 static int
os_get_handle_inheritable_impl(PyObject * module,intptr_t handle)13475 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
13476 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
13477 {
13478 DWORD flags;
13479
13480 if (!GetHandleInformation((HANDLE)handle, &flags)) {
13481 PyErr_SetFromWindowsErr(0);
13482 return -1;
13483 }
13484
13485 return flags & HANDLE_FLAG_INHERIT;
13486 }
13487
13488
13489 /*[clinic input]
13490 os.set_handle_inheritable
13491 handle: intptr_t
13492 inheritable: bool
13493 /
13494
13495 Set the inheritable flag of the specified handle.
13496 [clinic start generated code]*/
13497
13498 static PyObject *
os_set_handle_inheritable_impl(PyObject * module,intptr_t handle,int inheritable)13499 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
13500 int inheritable)
13501 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
13502 {
13503 DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
13504 if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
13505 PyErr_SetFromWindowsErr(0);
13506 return NULL;
13507 }
13508 Py_RETURN_NONE;
13509 }
13510 #endif /* MS_WINDOWS */
13511
13512 #ifndef MS_WINDOWS
13513 /*[clinic input]
13514 os.get_blocking -> bool
13515 fd: int
13516 /
13517
13518 Get the blocking mode of the file descriptor.
13519
13520 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
13521 [clinic start generated code]*/
13522
13523 static int
os_get_blocking_impl(PyObject * module,int fd)13524 os_get_blocking_impl(PyObject *module, int fd)
13525 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
13526 {
13527 int blocking;
13528
13529 _Py_BEGIN_SUPPRESS_IPH
13530 blocking = _Py_get_blocking(fd);
13531 _Py_END_SUPPRESS_IPH
13532 return blocking;
13533 }
13534
13535 /*[clinic input]
13536 os.set_blocking
13537 fd: int
13538 blocking: bool(accept={int})
13539 /
13540
13541 Set the blocking mode of the specified file descriptor.
13542
13543 Set the O_NONBLOCK flag if blocking is False,
13544 clear the O_NONBLOCK flag otherwise.
13545 [clinic start generated code]*/
13546
13547 static PyObject *
os_set_blocking_impl(PyObject * module,int fd,int blocking)13548 os_set_blocking_impl(PyObject *module, int fd, int blocking)
13549 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
13550 {
13551 int result;
13552
13553 _Py_BEGIN_SUPPRESS_IPH
13554 result = _Py_set_blocking(fd, blocking);
13555 _Py_END_SUPPRESS_IPH
13556 if (result < 0)
13557 return NULL;
13558 Py_RETURN_NONE;
13559 }
13560 #endif /* !MS_WINDOWS */
13561
13562
13563 /*[clinic input]
13564 class os.DirEntry "DirEntry *" "DirEntryType"
13565 [clinic start generated code]*/
13566 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
13567
13568 typedef struct {
13569 PyObject_HEAD
13570 PyObject *name;
13571 PyObject *path;
13572 PyObject *stat;
13573 PyObject *lstat;
13574 #ifdef MS_WINDOWS
13575 struct _Py_stat_struct win32_lstat;
13576 uint64_t win32_file_index;
13577 int got_file_index;
13578 #else /* POSIX */
13579 #ifdef HAVE_DIRENT_D_TYPE
13580 unsigned char d_type;
13581 #endif
13582 ino_t d_ino;
13583 int dir_fd;
13584 #endif
13585 } DirEntry;
13586
13587 static void
DirEntry_dealloc(DirEntry * entry)13588 DirEntry_dealloc(DirEntry *entry)
13589 {
13590 PyTypeObject *tp = Py_TYPE(entry);
13591 Py_XDECREF(entry->name);
13592 Py_XDECREF(entry->path);
13593 Py_XDECREF(entry->stat);
13594 Py_XDECREF(entry->lstat);
13595 freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13596 free_func(entry);
13597 Py_DECREF(tp);
13598 }
13599
13600 /* Forward reference */
13601 static int
13602 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13603 int follow_symlinks, unsigned short mode_bits);
13604
13605 /*[clinic input]
13606 os.DirEntry.is_symlink -> bool
13607 defining_class: defining_class
13608 /
13609
13610 Return True if the entry is a symbolic link; cached per entry.
13611 [clinic start generated code]*/
13612
13613 static int
os_DirEntry_is_symlink_impl(DirEntry * self,PyTypeObject * defining_class)13614 os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
13615 /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
13616 {
13617 #ifdef MS_WINDOWS
13618 return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13619 #elif defined(HAVE_DIRENT_D_TYPE)
13620 /* POSIX */
13621 if (self->d_type != DT_UNKNOWN)
13622 return self->d_type == DT_LNK;
13623 else
13624 return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13625 #else
13626 /* POSIX without d_type */
13627 return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13628 #endif
13629 }
13630
13631 static PyObject *
DirEntry_fetch_stat(PyObject * module,DirEntry * self,int follow_symlinks)13632 DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
13633 {
13634 int result;
13635 STRUCT_STAT st;
13636 PyObject *ub;
13637
13638 #ifdef MS_WINDOWS
13639 if (!PyUnicode_FSDecoder(self->path, &ub))
13640 return NULL;
13641 #if USE_UNICODE_WCHAR_CACHE
13642 _Py_COMP_DIAG_PUSH
13643 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13644 const wchar_t *path = PyUnicode_AsUnicode(ub);
13645 _Py_COMP_DIAG_POP
13646 #else /* USE_UNICODE_WCHAR_CACHE */
13647 wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
13648 Py_DECREF(ub);
13649 #endif /* USE_UNICODE_WCHAR_CACHE */
13650 #else /* POSIX */
13651 if (!PyUnicode_FSConverter(self->path, &ub))
13652 return NULL;
13653 const char *path = PyBytes_AS_STRING(ub);
13654 if (self->dir_fd != DEFAULT_DIR_FD) {
13655 #ifdef HAVE_FSTATAT
13656 if (HAVE_FSTATAT_RUNTIME) {
13657 Py_BEGIN_ALLOW_THREADS
13658 result = fstatat(self->dir_fd, path, &st,
13659 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
13660 Py_END_ALLOW_THREADS
13661 } else
13662
13663 #endif /* HAVE_FSTATAT */
13664 {
13665 Py_DECREF(ub);
13666 PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
13667 return NULL;
13668 }
13669 }
13670 else
13671 #endif
13672 {
13673 Py_BEGIN_ALLOW_THREADS
13674 if (follow_symlinks) {
13675 result = STAT(path, &st);
13676 }
13677 else {
13678 result = LSTAT(path, &st);
13679 }
13680 Py_END_ALLOW_THREADS
13681 }
13682 #if defined(MS_WINDOWS) && !USE_UNICODE_WCHAR_CACHE
13683 PyMem_Free(path);
13684 #else /* USE_UNICODE_WCHAR_CACHE */
13685 Py_DECREF(ub);
13686 #endif /* USE_UNICODE_WCHAR_CACHE */
13687
13688 if (result != 0)
13689 return path_object_error(self->path);
13690
13691 return _pystat_fromstructstat(module, &st);
13692 }
13693
13694 static PyObject *
DirEntry_get_lstat(PyTypeObject * defining_class,DirEntry * self)13695 DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
13696 {
13697 if (!self->lstat) {
13698 PyObject *module = PyType_GetModule(defining_class);
13699 #ifdef MS_WINDOWS
13700 self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
13701 #else /* POSIX */
13702 self->lstat = DirEntry_fetch_stat(module, self, 0);
13703 #endif
13704 }
13705 Py_XINCREF(self->lstat);
13706 return self->lstat;
13707 }
13708
13709 /*[clinic input]
13710 os.DirEntry.stat
13711 defining_class: defining_class
13712 /
13713 *
13714 follow_symlinks: bool = True
13715
13716 Return stat_result object for the entry; cached per entry.
13717 [clinic start generated code]*/
13718
13719 static PyObject *
os_DirEntry_stat_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13720 os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
13721 int follow_symlinks)
13722 /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
13723 {
13724 if (!follow_symlinks) {
13725 return DirEntry_get_lstat(defining_class, self);
13726 }
13727
13728 if (!self->stat) {
13729 int result = os_DirEntry_is_symlink_impl(self, defining_class);
13730 if (result == -1) {
13731 return NULL;
13732 }
13733 if (result) {
13734 PyObject *module = PyType_GetModule(defining_class);
13735 self->stat = DirEntry_fetch_stat(module, self, 1);
13736 }
13737 else {
13738 self->stat = DirEntry_get_lstat(defining_class, self);
13739 }
13740 }
13741
13742 Py_XINCREF(self->stat);
13743 return self->stat;
13744 }
13745
13746 /* Set exception and return -1 on error, 0 for False, 1 for True */
13747 static int
DirEntry_test_mode(PyTypeObject * defining_class,DirEntry * self,int follow_symlinks,unsigned short mode_bits)13748 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13749 int follow_symlinks, unsigned short mode_bits)
13750 {
13751 PyObject *stat = NULL;
13752 PyObject *st_mode = NULL;
13753 long mode;
13754 int result;
13755 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13756 int is_symlink;
13757 int need_stat;
13758 #endif
13759 #ifdef MS_WINDOWS
13760 unsigned long dir_bits;
13761 #endif
13762
13763 #ifdef MS_WINDOWS
13764 is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13765 need_stat = follow_symlinks && is_symlink;
13766 #elif defined(HAVE_DIRENT_D_TYPE)
13767 is_symlink = self->d_type == DT_LNK;
13768 need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
13769 #endif
13770
13771 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13772 if (need_stat) {
13773 #endif
13774 stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
13775 if (!stat) {
13776 if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
13777 /* If file doesn't exist (anymore), then return False
13778 (i.e., say it's not a file/directory) */
13779 PyErr_Clear();
13780 return 0;
13781 }
13782 goto error;
13783 }
13784 _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
13785 st_mode = PyObject_GetAttr(stat, state->st_mode);
13786 if (!st_mode)
13787 goto error;
13788
13789 mode = PyLong_AsLong(st_mode);
13790 if (mode == -1 && PyErr_Occurred())
13791 goto error;
13792 Py_CLEAR(st_mode);
13793 Py_CLEAR(stat);
13794 result = (mode & S_IFMT) == mode_bits;
13795 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13796 }
13797 else if (is_symlink) {
13798 assert(mode_bits != S_IFLNK);
13799 result = 0;
13800 }
13801 else {
13802 assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
13803 #ifdef MS_WINDOWS
13804 dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
13805 if (mode_bits == S_IFDIR)
13806 result = dir_bits != 0;
13807 else
13808 result = dir_bits == 0;
13809 #else /* POSIX */
13810 if (mode_bits == S_IFDIR)
13811 result = self->d_type == DT_DIR;
13812 else
13813 result = self->d_type == DT_REG;
13814 #endif
13815 }
13816 #endif
13817
13818 return result;
13819
13820 error:
13821 Py_XDECREF(st_mode);
13822 Py_XDECREF(stat);
13823 return -1;
13824 }
13825
13826 /*[clinic input]
13827 os.DirEntry.is_dir -> bool
13828 defining_class: defining_class
13829 /
13830 *
13831 follow_symlinks: bool = True
13832
13833 Return True if the entry is a directory; cached per entry.
13834 [clinic start generated code]*/
13835
13836 static int
os_DirEntry_is_dir_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13837 os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
13838 int follow_symlinks)
13839 /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
13840 {
13841 return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
13842 }
13843
13844 /*[clinic input]
13845 os.DirEntry.is_file -> bool
13846 defining_class: defining_class
13847 /
13848 *
13849 follow_symlinks: bool = True
13850
13851 Return True if the entry is a file; cached per entry.
13852 [clinic start generated code]*/
13853
13854 static int
os_DirEntry_is_file_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13855 os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
13856 int follow_symlinks)
13857 /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
13858 {
13859 return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
13860 }
13861
13862 /*[clinic input]
13863 os.DirEntry.inode
13864
13865 Return inode of the entry; cached per entry.
13866 [clinic start generated code]*/
13867
13868 static PyObject *
os_DirEntry_inode_impl(DirEntry * self)13869 os_DirEntry_inode_impl(DirEntry *self)
13870 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
13871 {
13872 #ifdef MS_WINDOWS
13873 if (!self->got_file_index) {
13874 PyObject *unicode;
13875 STRUCT_STAT stat;
13876 int result;
13877
13878 if (!PyUnicode_FSDecoder(self->path, &unicode))
13879 return NULL;
13880 #if USE_UNICODE_WCHAR_CACHE
13881 _Py_COMP_DIAG_PUSH
13882 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13883 const wchar_t *path = PyUnicode_AsUnicode(unicode);
13884 result = LSTAT(path, &stat);
13885 Py_DECREF(unicode);
13886 _Py_COMP_DIAG_POP
13887 #else /* USE_UNICODE_WCHAR_CACHE */
13888 wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
13889 Py_DECREF(unicode);
13890 result = LSTAT(path, &stat);
13891 PyMem_Free(path);
13892 #endif /* USE_UNICODE_WCHAR_CACHE */
13893
13894 if (result != 0)
13895 return path_object_error(self->path);
13896
13897 self->win32_file_index = stat.st_ino;
13898 self->got_file_index = 1;
13899 }
13900 static_assert(sizeof(unsigned long long) >= sizeof(self->win32_file_index),
13901 "DirEntry.win32_file_index is larger than unsigned long long");
13902 return PyLong_FromUnsignedLongLong(self->win32_file_index);
13903 #else /* POSIX */
13904 static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
13905 "DirEntry.d_ino is larger than unsigned long long");
13906 return PyLong_FromUnsignedLongLong(self->d_ino);
13907 #endif
13908 }
13909
13910 static PyObject *
DirEntry_repr(DirEntry * self)13911 DirEntry_repr(DirEntry *self)
13912 {
13913 return PyUnicode_FromFormat("<DirEntry %R>", self->name);
13914 }
13915
13916 /*[clinic input]
13917 os.DirEntry.__fspath__
13918
13919 Returns the path for the entry.
13920 [clinic start generated code]*/
13921
13922 static PyObject *
os_DirEntry___fspath___impl(DirEntry * self)13923 os_DirEntry___fspath___impl(DirEntry *self)
13924 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
13925 {
13926 Py_INCREF(self->path);
13927 return self->path;
13928 }
13929
13930 static PyMemberDef DirEntry_members[] = {
13931 {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
13932 "the entry's base filename, relative to scandir() \"path\" argument"},
13933 {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
13934 "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
13935 {NULL}
13936 };
13937
13938 #include "clinic/posixmodule.c.h"
13939
13940 static PyMethodDef DirEntry_methods[] = {
13941 OS_DIRENTRY_IS_DIR_METHODDEF
13942 OS_DIRENTRY_IS_FILE_METHODDEF
13943 OS_DIRENTRY_IS_SYMLINK_METHODDEF
13944 OS_DIRENTRY_STAT_METHODDEF
13945 OS_DIRENTRY_INODE_METHODDEF
13946 OS_DIRENTRY___FSPATH___METHODDEF
13947 {"__class_getitem__", Py_GenericAlias,
13948 METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
13949 {NULL}
13950 };
13951
13952 static PyType_Slot DirEntryType_slots[] = {
13953 {Py_tp_dealloc, DirEntry_dealloc},
13954 {Py_tp_repr, DirEntry_repr},
13955 {Py_tp_methods, DirEntry_methods},
13956 {Py_tp_members, DirEntry_members},
13957 {0, 0},
13958 };
13959
13960 static PyType_Spec DirEntryType_spec = {
13961 MODNAME ".DirEntry",
13962 sizeof(DirEntry),
13963 0,
13964 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
13965 DirEntryType_slots
13966 };
13967
13968
13969 #ifdef MS_WINDOWS
13970
13971 static wchar_t *
join_path_filenameW(const wchar_t * path_wide,const wchar_t * filename)13972 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
13973 {
13974 Py_ssize_t path_len;
13975 Py_ssize_t size;
13976 wchar_t *result;
13977 wchar_t ch;
13978
13979 if (!path_wide) { /* Default arg: "." */
13980 path_wide = L".";
13981 path_len = 1;
13982 }
13983 else {
13984 path_len = wcslen(path_wide);
13985 }
13986
13987 /* The +1's are for the path separator and the NUL */
13988 size = path_len + 1 + wcslen(filename) + 1;
13989 result = PyMem_New(wchar_t, size);
13990 if (!result) {
13991 PyErr_NoMemory();
13992 return NULL;
13993 }
13994 wcscpy(result, path_wide);
13995 if (path_len > 0) {
13996 ch = result[path_len - 1];
13997 if (ch != SEP && ch != ALTSEP && ch != L':')
13998 result[path_len++] = SEP;
13999 wcscpy(result + path_len, filename);
14000 }
14001 return result;
14002 }
14003
14004 static PyObject *
DirEntry_from_find_data(PyObject * module,path_t * path,WIN32_FIND_DATAW * dataW)14005 DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
14006 {
14007 DirEntry *entry;
14008 BY_HANDLE_FILE_INFORMATION file_info;
14009 ULONG reparse_tag;
14010 wchar_t *joined_path;
14011
14012 PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
14013 entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
14014 if (!entry)
14015 return NULL;
14016 entry->name = NULL;
14017 entry->path = NULL;
14018 entry->stat = NULL;
14019 entry->lstat = NULL;
14020 entry->got_file_index = 0;
14021
14022 entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
14023 if (!entry->name)
14024 goto error;
14025 if (path->narrow) {
14026 Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
14027 if (!entry->name)
14028 goto error;
14029 }
14030
14031 joined_path = join_path_filenameW(path->wide, dataW->cFileName);
14032 if (!joined_path)
14033 goto error;
14034
14035 entry->path = PyUnicode_FromWideChar(joined_path, -1);
14036 PyMem_Free(joined_path);
14037 if (!entry->path)
14038 goto error;
14039 if (path->narrow) {
14040 Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
14041 if (!entry->path)
14042 goto error;
14043 }
14044
14045 find_data_to_file_info(dataW, &file_info, &reparse_tag);
14046 _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
14047
14048 return (PyObject *)entry;
14049
14050 error:
14051 Py_DECREF(entry);
14052 return NULL;
14053 }
14054
14055 #else /* POSIX */
14056
14057 static char *
join_path_filename(const char * path_narrow,const char * filename,Py_ssize_t filename_len)14058 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
14059 {
14060 Py_ssize_t path_len;
14061 Py_ssize_t size;
14062 char *result;
14063
14064 if (!path_narrow) { /* Default arg: "." */
14065 path_narrow = ".";
14066 path_len = 1;
14067 }
14068 else {
14069 path_len = strlen(path_narrow);
14070 }
14071
14072 if (filename_len == -1)
14073 filename_len = strlen(filename);
14074
14075 /* The +1's are for the path separator and the NUL */
14076 size = path_len + 1 + filename_len + 1;
14077 result = PyMem_New(char, size);
14078 if (!result) {
14079 PyErr_NoMemory();
14080 return NULL;
14081 }
14082 strcpy(result, path_narrow);
14083 if (path_len > 0 && result[path_len - 1] != '/')
14084 result[path_len++] = '/';
14085 strcpy(result + path_len, filename);
14086 return result;
14087 }
14088
14089 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)14090 DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
14091 Py_ssize_t name_len, ino_t d_ino
14092 #ifdef HAVE_DIRENT_D_TYPE
14093 , unsigned char d_type
14094 #endif
14095 )
14096 {
14097 DirEntry *entry;
14098 char *joined_path;
14099
14100 PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
14101 entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
14102 if (!entry)
14103 return NULL;
14104 entry->name = NULL;
14105 entry->path = NULL;
14106 entry->stat = NULL;
14107 entry->lstat = NULL;
14108
14109 if (path->fd != -1) {
14110 entry->dir_fd = path->fd;
14111 joined_path = NULL;
14112 }
14113 else {
14114 entry->dir_fd = DEFAULT_DIR_FD;
14115 joined_path = join_path_filename(path->narrow, name, name_len);
14116 if (!joined_path)
14117 goto error;
14118 }
14119
14120 if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
14121 entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
14122 if (joined_path)
14123 entry->path = PyUnicode_DecodeFSDefault(joined_path);
14124 }
14125 else {
14126 entry->name = PyBytes_FromStringAndSize(name, name_len);
14127 if (joined_path)
14128 entry->path = PyBytes_FromString(joined_path);
14129 }
14130 PyMem_Free(joined_path);
14131 if (!entry->name)
14132 goto error;
14133
14134 if (path->fd != -1) {
14135 entry->path = entry->name;
14136 Py_INCREF(entry->path);
14137 }
14138 else if (!entry->path)
14139 goto error;
14140
14141 #ifdef HAVE_DIRENT_D_TYPE
14142 entry->d_type = d_type;
14143 #endif
14144 entry->d_ino = d_ino;
14145
14146 return (PyObject *)entry;
14147
14148 error:
14149 Py_XDECREF(entry);
14150 return NULL;
14151 }
14152
14153 #endif
14154
14155
14156 typedef struct {
14157 PyObject_HEAD
14158 path_t path;
14159 #ifdef MS_WINDOWS
14160 HANDLE handle;
14161 WIN32_FIND_DATAW file_data;
14162 int first_time;
14163 #else /* POSIX */
14164 DIR *dirp;
14165 #endif
14166 #ifdef HAVE_FDOPENDIR
14167 int fd;
14168 #endif
14169 } ScandirIterator;
14170
14171 #ifdef MS_WINDOWS
14172
14173 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14174 ScandirIterator_is_closed(ScandirIterator *iterator)
14175 {
14176 return iterator->handle == INVALID_HANDLE_VALUE;
14177 }
14178
14179 static void
ScandirIterator_closedir(ScandirIterator * iterator)14180 ScandirIterator_closedir(ScandirIterator *iterator)
14181 {
14182 HANDLE handle = iterator->handle;
14183
14184 if (handle == INVALID_HANDLE_VALUE)
14185 return;
14186
14187 iterator->handle = INVALID_HANDLE_VALUE;
14188 Py_BEGIN_ALLOW_THREADS
14189 FindClose(handle);
14190 Py_END_ALLOW_THREADS
14191 }
14192
14193 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14194 ScandirIterator_iternext(ScandirIterator *iterator)
14195 {
14196 WIN32_FIND_DATAW *file_data = &iterator->file_data;
14197 BOOL success;
14198 PyObject *entry;
14199
14200 /* Happens if the iterator is iterated twice, or closed explicitly */
14201 if (iterator->handle == INVALID_HANDLE_VALUE)
14202 return NULL;
14203
14204 while (1) {
14205 if (!iterator->first_time) {
14206 Py_BEGIN_ALLOW_THREADS
14207 success = FindNextFileW(iterator->handle, file_data);
14208 Py_END_ALLOW_THREADS
14209 if (!success) {
14210 /* Error or no more files */
14211 if (GetLastError() != ERROR_NO_MORE_FILES)
14212 path_error(&iterator->path);
14213 break;
14214 }
14215 }
14216 iterator->first_time = 0;
14217
14218 /* Skip over . and .. */
14219 if (wcscmp(file_data->cFileName, L".") != 0 &&
14220 wcscmp(file_data->cFileName, L"..") != 0)
14221 {
14222 PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14223 entry = DirEntry_from_find_data(module, &iterator->path, file_data);
14224 if (!entry)
14225 break;
14226 return entry;
14227 }
14228
14229 /* Loop till we get a non-dot directory or finish iterating */
14230 }
14231
14232 /* Error or no more files */
14233 ScandirIterator_closedir(iterator);
14234 return NULL;
14235 }
14236
14237 #else /* POSIX */
14238
14239 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14240 ScandirIterator_is_closed(ScandirIterator *iterator)
14241 {
14242 return !iterator->dirp;
14243 }
14244
14245 static void
ScandirIterator_closedir(ScandirIterator * iterator)14246 ScandirIterator_closedir(ScandirIterator *iterator)
14247 {
14248 DIR *dirp = iterator->dirp;
14249
14250 if (!dirp)
14251 return;
14252
14253 iterator->dirp = NULL;
14254 Py_BEGIN_ALLOW_THREADS
14255 #ifdef HAVE_FDOPENDIR
14256 if (iterator->path.fd != -1)
14257 rewinddir(dirp);
14258 #endif
14259 closedir(dirp);
14260 Py_END_ALLOW_THREADS
14261 return;
14262 }
14263
14264 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14265 ScandirIterator_iternext(ScandirIterator *iterator)
14266 {
14267 struct dirent *direntp;
14268 Py_ssize_t name_len;
14269 int is_dot;
14270 PyObject *entry;
14271
14272 /* Happens if the iterator is iterated twice, or closed explicitly */
14273 if (!iterator->dirp)
14274 return NULL;
14275
14276 while (1) {
14277 errno = 0;
14278 Py_BEGIN_ALLOW_THREADS
14279 direntp = readdir(iterator->dirp);
14280 Py_END_ALLOW_THREADS
14281
14282 if (!direntp) {
14283 /* Error or no more files */
14284 if (errno != 0)
14285 path_error(&iterator->path);
14286 break;
14287 }
14288
14289 /* Skip over . and .. */
14290 name_len = NAMLEN(direntp);
14291 is_dot = direntp->d_name[0] == '.' &&
14292 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
14293 if (!is_dot) {
14294 PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14295 entry = DirEntry_from_posix_info(module,
14296 &iterator->path, direntp->d_name,
14297 name_len, direntp->d_ino
14298 #ifdef HAVE_DIRENT_D_TYPE
14299 , direntp->d_type
14300 #endif
14301 );
14302 if (!entry)
14303 break;
14304 return entry;
14305 }
14306
14307 /* Loop till we get a non-dot directory or finish iterating */
14308 }
14309
14310 /* Error or no more files */
14311 ScandirIterator_closedir(iterator);
14312 return NULL;
14313 }
14314
14315 #endif
14316
14317 static PyObject *
ScandirIterator_close(ScandirIterator * self,PyObject * args)14318 ScandirIterator_close(ScandirIterator *self, PyObject *args)
14319 {
14320 ScandirIterator_closedir(self);
14321 Py_RETURN_NONE;
14322 }
14323
14324 static PyObject *
ScandirIterator_enter(PyObject * self,PyObject * args)14325 ScandirIterator_enter(PyObject *self, PyObject *args)
14326 {
14327 Py_INCREF(self);
14328 return self;
14329 }
14330
14331 static PyObject *
ScandirIterator_exit(ScandirIterator * self,PyObject * args)14332 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
14333 {
14334 ScandirIterator_closedir(self);
14335 Py_RETURN_NONE;
14336 }
14337
14338 static void
ScandirIterator_finalize(ScandirIterator * iterator)14339 ScandirIterator_finalize(ScandirIterator *iterator)
14340 {
14341 PyObject *error_type, *error_value, *error_traceback;
14342
14343 /* Save the current exception, if any. */
14344 PyErr_Fetch(&error_type, &error_value, &error_traceback);
14345
14346 if (!ScandirIterator_is_closed(iterator)) {
14347 ScandirIterator_closedir(iterator);
14348
14349 if (PyErr_ResourceWarning((PyObject *)iterator, 1,
14350 "unclosed scandir iterator %R", iterator)) {
14351 /* Spurious errors can appear at shutdown */
14352 if (PyErr_ExceptionMatches(PyExc_Warning)) {
14353 PyErr_WriteUnraisable((PyObject *) iterator);
14354 }
14355 }
14356 }
14357
14358 path_cleanup(&iterator->path);
14359
14360 /* Restore the saved exception. */
14361 PyErr_Restore(error_type, error_value, error_traceback);
14362 }
14363
14364 static void
ScandirIterator_dealloc(ScandirIterator * iterator)14365 ScandirIterator_dealloc(ScandirIterator *iterator)
14366 {
14367 PyTypeObject *tp = Py_TYPE(iterator);
14368 if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
14369 return;
14370
14371 freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
14372 free_func(iterator);
14373 Py_DECREF(tp);
14374 }
14375
14376 static PyMethodDef ScandirIterator_methods[] = {
14377 {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
14378 {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
14379 {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
14380 {NULL}
14381 };
14382
14383 static PyType_Slot ScandirIteratorType_slots[] = {
14384 {Py_tp_dealloc, ScandirIterator_dealloc},
14385 {Py_tp_finalize, ScandirIterator_finalize},
14386 {Py_tp_iter, PyObject_SelfIter},
14387 {Py_tp_iternext, ScandirIterator_iternext},
14388 {Py_tp_methods, ScandirIterator_methods},
14389 {0, 0},
14390 };
14391
14392 static PyType_Spec ScandirIteratorType_spec = {
14393 MODNAME ".ScandirIterator",
14394 sizeof(ScandirIterator),
14395 0,
14396 // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
14397 // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
14398 (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
14399 | Py_TPFLAGS_DISALLOW_INSTANTIATION),
14400 ScandirIteratorType_slots
14401 };
14402
14403 /*[clinic input]
14404 os.scandir
14405
14406 path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
14407
14408 Return an iterator of DirEntry objects for given path.
14409
14410 path can be specified as either str, bytes, or a path-like object. If path
14411 is bytes, the names of yielded DirEntry objects will also be bytes; in
14412 all other circumstances they will be str.
14413
14414 If path is None, uses the path='.'.
14415 [clinic start generated code]*/
14416
14417 static PyObject *
os_scandir_impl(PyObject * module,path_t * path)14418 os_scandir_impl(PyObject *module, path_t *path)
14419 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
14420 {
14421 ScandirIterator *iterator;
14422 #ifdef MS_WINDOWS
14423 wchar_t *path_strW;
14424 #else
14425 const char *path_str;
14426 #ifdef HAVE_FDOPENDIR
14427 int fd = -1;
14428 #endif
14429 #endif
14430
14431 if (PySys_Audit("os.scandir", "O",
14432 path->object ? path->object : Py_None) < 0) {
14433 return NULL;
14434 }
14435
14436 PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
14437 iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
14438 if (!iterator)
14439 return NULL;
14440
14441 #ifdef MS_WINDOWS
14442 iterator->handle = INVALID_HANDLE_VALUE;
14443 #else
14444 iterator->dirp = NULL;
14445 #endif
14446
14447 /* Move the ownership to iterator->path */
14448 memcpy(&iterator->path, path, sizeof(path_t));
14449 memset(path, 0, sizeof(path_t));
14450
14451 #ifdef MS_WINDOWS
14452 iterator->first_time = 1;
14453
14454 path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
14455 if (!path_strW)
14456 goto error;
14457
14458 Py_BEGIN_ALLOW_THREADS
14459 iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
14460 Py_END_ALLOW_THREADS
14461
14462 PyMem_Free(path_strW);
14463
14464 if (iterator->handle == INVALID_HANDLE_VALUE) {
14465 path_error(&iterator->path);
14466 goto error;
14467 }
14468 #else /* POSIX */
14469 errno = 0;
14470 #ifdef HAVE_FDOPENDIR
14471 if (iterator->path.fd != -1) {
14472 if (HAVE_FDOPENDIR_RUNTIME) {
14473 /* closedir() closes the FD, so we duplicate it */
14474 fd = _Py_dup(iterator->path.fd);
14475 if (fd == -1)
14476 goto error;
14477
14478 Py_BEGIN_ALLOW_THREADS
14479 iterator->dirp = fdopendir(fd);
14480 Py_END_ALLOW_THREADS
14481 } else {
14482 PyErr_SetString(PyExc_TypeError,
14483 "scandir: path should be string, bytes, os.PathLike or None, not int");
14484 return NULL;
14485 }
14486 }
14487 else
14488 #endif
14489 {
14490 if (iterator->path.narrow)
14491 path_str = iterator->path.narrow;
14492 else
14493 path_str = ".";
14494
14495 Py_BEGIN_ALLOW_THREADS
14496 iterator->dirp = opendir(path_str);
14497 Py_END_ALLOW_THREADS
14498 }
14499
14500 if (!iterator->dirp) {
14501 path_error(&iterator->path);
14502 #ifdef HAVE_FDOPENDIR
14503 if (fd != -1) {
14504 Py_BEGIN_ALLOW_THREADS
14505 close(fd);
14506 Py_END_ALLOW_THREADS
14507 }
14508 #endif
14509 goto error;
14510 }
14511 #endif
14512
14513 return (PyObject *)iterator;
14514
14515 error:
14516 Py_DECREF(iterator);
14517 return NULL;
14518 }
14519
14520 /*
14521 Return the file system path representation of the object.
14522
14523 If the object is str or bytes, then allow it to pass through with
14524 an incremented refcount. If the object defines __fspath__(), then
14525 return the result of that method. All other types raise a TypeError.
14526 */
14527 PyObject *
PyOS_FSPath(PyObject * path)14528 PyOS_FSPath(PyObject *path)
14529 {
14530 /* For error message reasons, this function is manually inlined in
14531 path_converter(). */
14532 PyObject *func = NULL;
14533 PyObject *path_repr = NULL;
14534
14535 if (PyUnicode_Check(path) || PyBytes_Check(path)) {
14536 Py_INCREF(path);
14537 return path;
14538 }
14539
14540 func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
14541 if (NULL == func) {
14542 return PyErr_Format(PyExc_TypeError,
14543 "expected str, bytes or os.PathLike object, "
14544 "not %.200s",
14545 _PyType_Name(Py_TYPE(path)));
14546 }
14547
14548 path_repr = _PyObject_CallNoArgs(func);
14549 Py_DECREF(func);
14550 if (NULL == path_repr) {
14551 return NULL;
14552 }
14553
14554 if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
14555 PyErr_Format(PyExc_TypeError,
14556 "expected %.200s.__fspath__() to return str or bytes, "
14557 "not %.200s", _PyType_Name(Py_TYPE(path)),
14558 _PyType_Name(Py_TYPE(path_repr)));
14559 Py_DECREF(path_repr);
14560 return NULL;
14561 }
14562
14563 return path_repr;
14564 }
14565
14566 /*[clinic input]
14567 os.fspath
14568
14569 path: object
14570
14571 Return the file system path representation of the object.
14572
14573 If the object is str or bytes, then allow it to pass through as-is. If the
14574 object defines __fspath__(), then return the result of that method. All other
14575 types raise a TypeError.
14576 [clinic start generated code]*/
14577
14578 static PyObject *
os_fspath_impl(PyObject * module,PyObject * path)14579 os_fspath_impl(PyObject *module, PyObject *path)
14580 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
14581 {
14582 return PyOS_FSPath(path);
14583 }
14584
14585 #ifdef HAVE_GETRANDOM_SYSCALL
14586 /*[clinic input]
14587 os.getrandom
14588
14589 size: Py_ssize_t
14590 flags: int=0
14591
14592 Obtain a series of random bytes.
14593 [clinic start generated code]*/
14594
14595 static PyObject *
os_getrandom_impl(PyObject * module,Py_ssize_t size,int flags)14596 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
14597 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
14598 {
14599 PyObject *bytes;
14600 Py_ssize_t n;
14601
14602 if (size < 0) {
14603 errno = EINVAL;
14604 return posix_error();
14605 }
14606
14607 bytes = PyBytes_FromStringAndSize(NULL, size);
14608 if (bytes == NULL) {
14609 PyErr_NoMemory();
14610 return NULL;
14611 }
14612
14613 while (1) {
14614 n = syscall(SYS_getrandom,
14615 PyBytes_AS_STRING(bytes),
14616 PyBytes_GET_SIZE(bytes),
14617 flags);
14618 if (n < 0 && errno == EINTR) {
14619 if (PyErr_CheckSignals() < 0) {
14620 goto error;
14621 }
14622
14623 /* getrandom() was interrupted by a signal: retry */
14624 continue;
14625 }
14626 break;
14627 }
14628
14629 if (n < 0) {
14630 PyErr_SetFromErrno(PyExc_OSError);
14631 goto error;
14632 }
14633
14634 if (n != size) {
14635 _PyBytes_Resize(&bytes, n);
14636 }
14637
14638 return bytes;
14639
14640 error:
14641 Py_DECREF(bytes);
14642 return NULL;
14643 }
14644 #endif /* HAVE_GETRANDOM_SYSCALL */
14645
14646 #ifdef MS_WINDOWS
14647 /* bpo-36085: Helper functions for managing DLL search directories
14648 * on win32
14649 */
14650
14651 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
14652 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
14653
14654 /*[clinic input]
14655 os._add_dll_directory
14656
14657 path: path_t
14658
14659 Add a path to the DLL search path.
14660
14661 This search path is used when resolving dependencies for imported
14662 extension modules (the module itself is resolved through sys.path),
14663 and also by ctypes.
14664
14665 Returns an opaque value that may be passed to os.remove_dll_directory
14666 to remove this directory from the search path.
14667 [clinic start generated code]*/
14668
14669 static PyObject *
os__add_dll_directory_impl(PyObject * module,path_t * path)14670 os__add_dll_directory_impl(PyObject *module, path_t *path)
14671 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
14672 {
14673 HMODULE hKernel32;
14674 PAddDllDirectory AddDllDirectory;
14675 DLL_DIRECTORY_COOKIE cookie = 0;
14676 DWORD err = 0;
14677
14678 if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
14679 return NULL;
14680 }
14681
14682 /* For Windows 7, we have to load this. As this will be a fairly
14683 infrequent operation, just do it each time. Kernel32 is always
14684 loaded. */
14685 Py_BEGIN_ALLOW_THREADS
14686 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14687 !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
14688 hKernel32, "AddDllDirectory")) ||
14689 !(cookie = (*AddDllDirectory)(path->wide))) {
14690 err = GetLastError();
14691 }
14692 Py_END_ALLOW_THREADS
14693
14694 if (err) {
14695 return win32_error_object_err("add_dll_directory",
14696 path->object, err);
14697 }
14698
14699 return PyCapsule_New(cookie, "DLL directory cookie", NULL);
14700 }
14701
14702 /*[clinic input]
14703 os._remove_dll_directory
14704
14705 cookie: object
14706
14707 Removes a path from the DLL search path.
14708
14709 The parameter is an opaque value that was returned from
14710 os.add_dll_directory. You can only remove directories that you added
14711 yourself.
14712 [clinic start generated code]*/
14713
14714 static PyObject *
os__remove_dll_directory_impl(PyObject * module,PyObject * cookie)14715 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
14716 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
14717 {
14718 HMODULE hKernel32;
14719 PRemoveDllDirectory RemoveDllDirectory;
14720 DLL_DIRECTORY_COOKIE cookieValue;
14721 DWORD err = 0;
14722
14723 if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
14724 PyErr_SetString(PyExc_TypeError,
14725 "Provided cookie was not returned from os.add_dll_directory");
14726 return NULL;
14727 }
14728
14729 cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
14730 cookie, "DLL directory cookie");
14731
14732 /* For Windows 7, we have to load this. As this will be a fairly
14733 infrequent operation, just do it each time. Kernel32 is always
14734 loaded. */
14735 Py_BEGIN_ALLOW_THREADS
14736 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14737 !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
14738 hKernel32, "RemoveDllDirectory")) ||
14739 !(*RemoveDllDirectory)(cookieValue)) {
14740 err = GetLastError();
14741 }
14742 Py_END_ALLOW_THREADS
14743
14744 if (err) {
14745 return win32_error_object_err("remove_dll_directory",
14746 NULL, err);
14747 }
14748
14749 if (PyCapsule_SetName(cookie, NULL)) {
14750 return NULL;
14751 }
14752
14753 Py_RETURN_NONE;
14754 }
14755
14756 #endif
14757
14758
14759 /* Only check if WIFEXITED is available: expect that it comes
14760 with WEXITSTATUS, WIFSIGNALED, etc.
14761
14762 os.waitstatus_to_exitcode() is implemented in C and not in Python, so
14763 subprocess can safely call it during late Python finalization without
14764 risking that used os attributes were set to None by finalize_modules(). */
14765 #if defined(WIFEXITED) || defined(MS_WINDOWS)
14766 /*[clinic input]
14767 os.waitstatus_to_exitcode
14768
14769 status as status_obj: object
14770
14771 Convert a wait status to an exit code.
14772
14773 On Unix:
14774
14775 * If WIFEXITED(status) is true, return WEXITSTATUS(status).
14776 * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
14777 * Otherwise, raise a ValueError.
14778
14779 On Windows, return status shifted right by 8 bits.
14780
14781 On Unix, if the process is being traced or if waitpid() was called with
14782 WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
14783 This function must not be called if WIFSTOPPED(status) is true.
14784 [clinic start generated code]*/
14785
14786 static PyObject *
os_waitstatus_to_exitcode_impl(PyObject * module,PyObject * status_obj)14787 os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
14788 /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
14789 {
14790 #ifndef MS_WINDOWS
14791 int status = _PyLong_AsInt(status_obj);
14792 if (status == -1 && PyErr_Occurred()) {
14793 return NULL;
14794 }
14795
14796 WAIT_TYPE wait_status;
14797 WAIT_STATUS_INT(wait_status) = status;
14798 int exitcode;
14799 if (WIFEXITED(wait_status)) {
14800 exitcode = WEXITSTATUS(wait_status);
14801 /* Sanity check to provide warranty on the function behavior.
14802 It should not occur in practice */
14803 if (exitcode < 0) {
14804 PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
14805 return NULL;
14806 }
14807 }
14808 else if (WIFSIGNALED(wait_status)) {
14809 int signum = WTERMSIG(wait_status);
14810 /* Sanity check to provide warranty on the function behavior.
14811 It should not occurs in practice */
14812 if (signum <= 0) {
14813 PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
14814 return NULL;
14815 }
14816 exitcode = -signum;
14817 } else if (WIFSTOPPED(wait_status)) {
14818 /* Status only received if the process is being traced
14819 or if waitpid() was called with WUNTRACED option. */
14820 int signum = WSTOPSIG(wait_status);
14821 PyErr_Format(PyExc_ValueError,
14822 "process stopped by delivery of signal %i",
14823 signum);
14824 return NULL;
14825 }
14826 else {
14827 PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
14828 return NULL;
14829 }
14830 return PyLong_FromLong(exitcode);
14831 #else
14832 /* Windows implementation: see os.waitpid() implementation
14833 which uses _cwait(). */
14834 unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
14835 if (status == (unsigned long long)-1 && PyErr_Occurred()) {
14836 return NULL;
14837 }
14838
14839 unsigned long long exitcode = (status >> 8);
14840 /* ExitProcess() accepts an UINT type:
14841 reject exit code which doesn't fit in an UINT */
14842 if (exitcode > UINT_MAX) {
14843 PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
14844 return NULL;
14845 }
14846 return PyLong_FromUnsignedLong((unsigned long)exitcode);
14847 #endif
14848 }
14849 #endif
14850
14851
14852 static PyMethodDef posix_methods[] = {
14853
14854 OS_STAT_METHODDEF
14855 OS_ACCESS_METHODDEF
14856 OS_TTYNAME_METHODDEF
14857 OS_CHDIR_METHODDEF
14858 OS_CHFLAGS_METHODDEF
14859 OS_CHMOD_METHODDEF
14860 OS_FCHMOD_METHODDEF
14861 OS_LCHMOD_METHODDEF
14862 OS_CHOWN_METHODDEF
14863 OS_FCHOWN_METHODDEF
14864 OS_LCHOWN_METHODDEF
14865 OS_LCHFLAGS_METHODDEF
14866 OS_CHROOT_METHODDEF
14867 OS_CTERMID_METHODDEF
14868 OS_GETCWD_METHODDEF
14869 OS_GETCWDB_METHODDEF
14870 OS_LINK_METHODDEF
14871 OS_LISTDIR_METHODDEF
14872 OS_LSTAT_METHODDEF
14873 OS_MKDIR_METHODDEF
14874 OS_NICE_METHODDEF
14875 OS_GETPRIORITY_METHODDEF
14876 OS_SETPRIORITY_METHODDEF
14877 OS_POSIX_SPAWN_METHODDEF
14878 OS_POSIX_SPAWNP_METHODDEF
14879 OS_READLINK_METHODDEF
14880 OS_COPY_FILE_RANGE_METHODDEF
14881 OS_SPLICE_METHODDEF
14882 OS_RENAME_METHODDEF
14883 OS_REPLACE_METHODDEF
14884 OS_RMDIR_METHODDEF
14885 OS_SYMLINK_METHODDEF
14886 OS_SYSTEM_METHODDEF
14887 OS_UMASK_METHODDEF
14888 OS_UNAME_METHODDEF
14889 OS_UNLINK_METHODDEF
14890 OS_REMOVE_METHODDEF
14891 OS_UTIME_METHODDEF
14892 OS_TIMES_METHODDEF
14893 OS__EXIT_METHODDEF
14894 OS__FCOPYFILE_METHODDEF
14895 OS_EXECV_METHODDEF
14896 OS_EXECVE_METHODDEF
14897 OS_SPAWNV_METHODDEF
14898 OS_SPAWNVE_METHODDEF
14899 OS_FORK1_METHODDEF
14900 OS_FORK_METHODDEF
14901 OS_REGISTER_AT_FORK_METHODDEF
14902 OS_SCHED_GET_PRIORITY_MAX_METHODDEF
14903 OS_SCHED_GET_PRIORITY_MIN_METHODDEF
14904 OS_SCHED_GETPARAM_METHODDEF
14905 OS_SCHED_GETSCHEDULER_METHODDEF
14906 OS_SCHED_RR_GET_INTERVAL_METHODDEF
14907 OS_SCHED_SETPARAM_METHODDEF
14908 OS_SCHED_SETSCHEDULER_METHODDEF
14909 OS_SCHED_YIELD_METHODDEF
14910 OS_SCHED_SETAFFINITY_METHODDEF
14911 OS_SCHED_GETAFFINITY_METHODDEF
14912 OS_OPENPTY_METHODDEF
14913 OS_LOGIN_TTY_METHODDEF
14914 OS_FORKPTY_METHODDEF
14915 OS_GETEGID_METHODDEF
14916 OS_GETEUID_METHODDEF
14917 OS_GETGID_METHODDEF
14918 OS_GETGROUPLIST_METHODDEF
14919 OS_GETGROUPS_METHODDEF
14920 OS_GETPID_METHODDEF
14921 OS_GETPGRP_METHODDEF
14922 OS_GETPPID_METHODDEF
14923 OS_GETUID_METHODDEF
14924 OS_GETLOGIN_METHODDEF
14925 OS_KILL_METHODDEF
14926 OS_KILLPG_METHODDEF
14927 OS_PLOCK_METHODDEF
14928 OS_STARTFILE_METHODDEF
14929 OS_SETUID_METHODDEF
14930 OS_SETEUID_METHODDEF
14931 OS_SETREUID_METHODDEF
14932 OS_SETGID_METHODDEF
14933 OS_SETEGID_METHODDEF
14934 OS_SETREGID_METHODDEF
14935 OS_SETGROUPS_METHODDEF
14936 OS_INITGROUPS_METHODDEF
14937 OS_GETPGID_METHODDEF
14938 OS_SETPGRP_METHODDEF
14939 OS_WAIT_METHODDEF
14940 OS_WAIT3_METHODDEF
14941 OS_WAIT4_METHODDEF
14942 OS_WAITID_METHODDEF
14943 OS_WAITPID_METHODDEF
14944 OS_PIDFD_OPEN_METHODDEF
14945 OS_GETSID_METHODDEF
14946 OS_SETSID_METHODDEF
14947 OS_SETPGID_METHODDEF
14948 OS_TCGETPGRP_METHODDEF
14949 OS_TCSETPGRP_METHODDEF
14950 OS_OPEN_METHODDEF
14951 OS_CLOSE_METHODDEF
14952 OS_CLOSERANGE_METHODDEF
14953 OS_DEVICE_ENCODING_METHODDEF
14954 OS_DUP_METHODDEF
14955 OS_DUP2_METHODDEF
14956 OS_LOCKF_METHODDEF
14957 OS_LSEEK_METHODDEF
14958 OS_READ_METHODDEF
14959 OS_READV_METHODDEF
14960 OS_PREAD_METHODDEF
14961 OS_PREADV_METHODDEF
14962 OS_WRITE_METHODDEF
14963 OS_WRITEV_METHODDEF
14964 OS_PWRITE_METHODDEF
14965 OS_PWRITEV_METHODDEF
14966 OS_SENDFILE_METHODDEF
14967 OS_FSTAT_METHODDEF
14968 OS_ISATTY_METHODDEF
14969 OS_PIPE_METHODDEF
14970 OS_PIPE2_METHODDEF
14971 OS_MKFIFO_METHODDEF
14972 OS_MKNOD_METHODDEF
14973 OS_MAJOR_METHODDEF
14974 OS_MINOR_METHODDEF
14975 OS_MAKEDEV_METHODDEF
14976 OS_FTRUNCATE_METHODDEF
14977 OS_TRUNCATE_METHODDEF
14978 OS_POSIX_FALLOCATE_METHODDEF
14979 OS_POSIX_FADVISE_METHODDEF
14980 OS_PUTENV_METHODDEF
14981 OS_UNSETENV_METHODDEF
14982 OS_STRERROR_METHODDEF
14983 OS_FCHDIR_METHODDEF
14984 OS_FSYNC_METHODDEF
14985 OS_SYNC_METHODDEF
14986 OS_FDATASYNC_METHODDEF
14987 OS_WCOREDUMP_METHODDEF
14988 OS_WIFCONTINUED_METHODDEF
14989 OS_WIFSTOPPED_METHODDEF
14990 OS_WIFSIGNALED_METHODDEF
14991 OS_WIFEXITED_METHODDEF
14992 OS_WEXITSTATUS_METHODDEF
14993 OS_WTERMSIG_METHODDEF
14994 OS_WSTOPSIG_METHODDEF
14995 OS_FSTATVFS_METHODDEF
14996 OS_STATVFS_METHODDEF
14997 OS_CONFSTR_METHODDEF
14998 OS_SYSCONF_METHODDEF
14999 OS_FPATHCONF_METHODDEF
15000 OS_PATHCONF_METHODDEF
15001 OS_ABORT_METHODDEF
15002 OS__GETFULLPATHNAME_METHODDEF
15003 OS__GETDISKUSAGE_METHODDEF
15004 OS__GETFINALPATHNAME_METHODDEF
15005 OS__GETVOLUMEPATHNAME_METHODDEF
15006 OS__PATH_SPLITROOT_METHODDEF
15007 OS__PATH_NORMPATH_METHODDEF
15008 OS_GETLOADAVG_METHODDEF
15009 OS_URANDOM_METHODDEF
15010 OS_SETRESUID_METHODDEF
15011 OS_SETRESGID_METHODDEF
15012 OS_GETRESUID_METHODDEF
15013 OS_GETRESGID_METHODDEF
15014
15015 OS_GETXATTR_METHODDEF
15016 OS_SETXATTR_METHODDEF
15017 OS_REMOVEXATTR_METHODDEF
15018 OS_LISTXATTR_METHODDEF
15019
15020 OS_GET_TERMINAL_SIZE_METHODDEF
15021 OS_CPU_COUNT_METHODDEF
15022 OS_GET_INHERITABLE_METHODDEF
15023 OS_SET_INHERITABLE_METHODDEF
15024 OS_GET_HANDLE_INHERITABLE_METHODDEF
15025 OS_SET_HANDLE_INHERITABLE_METHODDEF
15026 OS_GET_BLOCKING_METHODDEF
15027 OS_SET_BLOCKING_METHODDEF
15028 OS_SCANDIR_METHODDEF
15029 OS_FSPATH_METHODDEF
15030 OS_GETRANDOM_METHODDEF
15031 OS_MEMFD_CREATE_METHODDEF
15032 OS_EVENTFD_METHODDEF
15033 OS_EVENTFD_READ_METHODDEF
15034 OS_EVENTFD_WRITE_METHODDEF
15035 OS__ADD_DLL_DIRECTORY_METHODDEF
15036 OS__REMOVE_DLL_DIRECTORY_METHODDEF
15037 OS_WAITSTATUS_TO_EXITCODE_METHODDEF
15038 {NULL, NULL} /* Sentinel */
15039 };
15040
15041 static int
all_ins(PyObject * m)15042 all_ins(PyObject *m)
15043 {
15044 #ifdef F_OK
15045 if (PyModule_AddIntMacro(m, F_OK)) return -1;
15046 #endif
15047 #ifdef R_OK
15048 if (PyModule_AddIntMacro(m, R_OK)) return -1;
15049 #endif
15050 #ifdef W_OK
15051 if (PyModule_AddIntMacro(m, W_OK)) return -1;
15052 #endif
15053 #ifdef X_OK
15054 if (PyModule_AddIntMacro(m, X_OK)) return -1;
15055 #endif
15056 #ifdef NGROUPS_MAX
15057 if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
15058 #endif
15059 #ifdef TMP_MAX
15060 if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
15061 #endif
15062 #ifdef WCONTINUED
15063 if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
15064 #endif
15065 #ifdef WNOHANG
15066 if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
15067 #endif
15068 #ifdef WUNTRACED
15069 if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
15070 #endif
15071 #ifdef O_RDONLY
15072 if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
15073 #endif
15074 #ifdef O_WRONLY
15075 if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
15076 #endif
15077 #ifdef O_RDWR
15078 if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
15079 #endif
15080 #ifdef O_NDELAY
15081 if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
15082 #endif
15083 #ifdef O_NONBLOCK
15084 if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
15085 #endif
15086 #ifdef O_APPEND
15087 if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
15088 #endif
15089 #ifdef O_DSYNC
15090 if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
15091 #endif
15092 #ifdef O_RSYNC
15093 if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
15094 #endif
15095 #ifdef O_SYNC
15096 if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
15097 #endif
15098 #ifdef O_NOCTTY
15099 if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
15100 #endif
15101 #ifdef O_CREAT
15102 if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
15103 #endif
15104 #ifdef O_EXCL
15105 if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
15106 #endif
15107 #ifdef O_TRUNC
15108 if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
15109 #endif
15110 #ifdef O_BINARY
15111 if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
15112 #endif
15113 #ifdef O_TEXT
15114 if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
15115 #endif
15116 #ifdef O_XATTR
15117 if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
15118 #endif
15119 #ifdef O_LARGEFILE
15120 if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
15121 #endif
15122 #ifndef __GNU__
15123 #ifdef O_SHLOCK
15124 if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
15125 #endif
15126 #ifdef O_EXLOCK
15127 if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
15128 #endif
15129 #endif
15130 #ifdef O_EXEC
15131 if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
15132 #endif
15133 #ifdef O_SEARCH
15134 if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
15135 #endif
15136 #ifdef O_PATH
15137 if (PyModule_AddIntMacro(m, O_PATH)) return -1;
15138 #endif
15139 #ifdef O_TTY_INIT
15140 if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
15141 #endif
15142 #ifdef O_TMPFILE
15143 if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
15144 #endif
15145 #ifdef PRIO_PROCESS
15146 if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
15147 #endif
15148 #ifdef PRIO_PGRP
15149 if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
15150 #endif
15151 #ifdef PRIO_USER
15152 if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
15153 #endif
15154 #ifdef O_CLOEXEC
15155 if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
15156 #endif
15157 #ifdef O_ACCMODE
15158 if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
15159 #endif
15160 #ifdef O_EVTONLY
15161 if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
15162 #endif
15163 #ifdef O_FSYNC
15164 if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
15165 #endif
15166 #ifdef O_SYMLINK
15167 if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
15168 #endif
15169
15170 #ifdef SEEK_HOLE
15171 if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
15172 #endif
15173 #ifdef SEEK_DATA
15174 if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
15175 #endif
15176
15177 /* MS Windows */
15178 #ifdef O_NOINHERIT
15179 /* Don't inherit in child processes. */
15180 if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
15181 #endif
15182 #ifdef _O_SHORT_LIVED
15183 /* Optimize for short life (keep in memory). */
15184 /* MS forgot to define this one with a non-underscore form too. */
15185 if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
15186 #endif
15187 #ifdef O_TEMPORARY
15188 /* Automatically delete when last handle is closed. */
15189 if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
15190 #endif
15191 #ifdef O_RANDOM
15192 /* Optimize for random access. */
15193 if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
15194 #endif
15195 #ifdef O_SEQUENTIAL
15196 /* Optimize for sequential access. */
15197 if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
15198 #endif
15199
15200 /* GNU extensions. */
15201 #ifdef O_ASYNC
15202 /* Send a SIGIO signal whenever input or output
15203 becomes available on file descriptor */
15204 if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
15205 #endif
15206 #ifdef O_DIRECT
15207 /* Direct disk access. */
15208 if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
15209 #endif
15210 #ifdef O_DIRECTORY
15211 /* Must be a directory. */
15212 if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
15213 #endif
15214 #ifdef O_NOFOLLOW
15215 /* Do not follow links. */
15216 if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
15217 #endif
15218 #ifdef O_NOFOLLOW_ANY
15219 if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
15220 #endif
15221 #ifdef O_NOLINKS
15222 /* Fails if link count of the named file is greater than 1 */
15223 if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
15224 #endif
15225 #ifdef O_NOATIME
15226 /* Do not update the access time. */
15227 if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
15228 #endif
15229
15230 /* These come from sysexits.h */
15231 #ifdef EX_OK
15232 if (PyModule_AddIntMacro(m, EX_OK)) return -1;
15233 #endif /* EX_OK */
15234 #ifdef EX_USAGE
15235 if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
15236 #endif /* EX_USAGE */
15237 #ifdef EX_DATAERR
15238 if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
15239 #endif /* EX_DATAERR */
15240 #ifdef EX_NOINPUT
15241 if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
15242 #endif /* EX_NOINPUT */
15243 #ifdef EX_NOUSER
15244 if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
15245 #endif /* EX_NOUSER */
15246 #ifdef EX_NOHOST
15247 if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
15248 #endif /* EX_NOHOST */
15249 #ifdef EX_UNAVAILABLE
15250 if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
15251 #endif /* EX_UNAVAILABLE */
15252 #ifdef EX_SOFTWARE
15253 if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
15254 #endif /* EX_SOFTWARE */
15255 #ifdef EX_OSERR
15256 if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
15257 #endif /* EX_OSERR */
15258 #ifdef EX_OSFILE
15259 if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
15260 #endif /* EX_OSFILE */
15261 #ifdef EX_CANTCREAT
15262 if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
15263 #endif /* EX_CANTCREAT */
15264 #ifdef EX_IOERR
15265 if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
15266 #endif /* EX_IOERR */
15267 #ifdef EX_TEMPFAIL
15268 if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
15269 #endif /* EX_TEMPFAIL */
15270 #ifdef EX_PROTOCOL
15271 if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
15272 #endif /* EX_PROTOCOL */
15273 #ifdef EX_NOPERM
15274 if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
15275 #endif /* EX_NOPERM */
15276 #ifdef EX_CONFIG
15277 if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
15278 #endif /* EX_CONFIG */
15279 #ifdef EX_NOTFOUND
15280 if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
15281 #endif /* EX_NOTFOUND */
15282
15283 /* statvfs */
15284 #ifdef ST_RDONLY
15285 if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
15286 #endif /* ST_RDONLY */
15287 #ifdef ST_NOSUID
15288 if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
15289 #endif /* ST_NOSUID */
15290
15291 /* GNU extensions */
15292 #ifdef ST_NODEV
15293 if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
15294 #endif /* ST_NODEV */
15295 #ifdef ST_NOEXEC
15296 if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
15297 #endif /* ST_NOEXEC */
15298 #ifdef ST_SYNCHRONOUS
15299 if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
15300 #endif /* ST_SYNCHRONOUS */
15301 #ifdef ST_MANDLOCK
15302 if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
15303 #endif /* ST_MANDLOCK */
15304 #ifdef ST_WRITE
15305 if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
15306 #endif /* ST_WRITE */
15307 #ifdef ST_APPEND
15308 if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
15309 #endif /* ST_APPEND */
15310 #ifdef ST_NOATIME
15311 if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
15312 #endif /* ST_NOATIME */
15313 #ifdef ST_NODIRATIME
15314 if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
15315 #endif /* ST_NODIRATIME */
15316 #ifdef ST_RELATIME
15317 if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
15318 #endif /* ST_RELATIME */
15319
15320 /* FreeBSD sendfile() constants */
15321 #ifdef SF_NODISKIO
15322 if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
15323 #endif
15324 /* is obsolete since the 11.x release */
15325 #ifdef SF_MNOWAIT
15326 if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
15327 #endif
15328 #ifdef SF_SYNC
15329 if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
15330 #endif
15331 #ifdef SF_NOCACHE
15332 if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
15333 #endif
15334
15335 /* constants for posix_fadvise */
15336 #ifdef POSIX_FADV_NORMAL
15337 if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
15338 #endif
15339 #ifdef POSIX_FADV_SEQUENTIAL
15340 if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
15341 #endif
15342 #ifdef POSIX_FADV_RANDOM
15343 if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
15344 #endif
15345 #ifdef POSIX_FADV_NOREUSE
15346 if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
15347 #endif
15348 #ifdef POSIX_FADV_WILLNEED
15349 if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
15350 #endif
15351 #ifdef POSIX_FADV_DONTNEED
15352 if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
15353 #endif
15354
15355 /* constants for waitid */
15356 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
15357 if (PyModule_AddIntMacro(m, P_PID)) return -1;
15358 if (PyModule_AddIntMacro(m, P_PGID)) return -1;
15359 if (PyModule_AddIntMacro(m, P_ALL)) return -1;
15360 #ifdef P_PIDFD
15361 if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
15362 #endif
15363 #endif
15364 #ifdef WEXITED
15365 if (PyModule_AddIntMacro(m, WEXITED)) return -1;
15366 #endif
15367 #ifdef WNOWAIT
15368 if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
15369 #endif
15370 #ifdef WSTOPPED
15371 if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
15372 #endif
15373 #ifdef CLD_EXITED
15374 if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
15375 #endif
15376 #ifdef CLD_KILLED
15377 if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
15378 #endif
15379 #ifdef CLD_DUMPED
15380 if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
15381 #endif
15382 #ifdef CLD_TRAPPED
15383 if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
15384 #endif
15385 #ifdef CLD_STOPPED
15386 if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
15387 #endif
15388 #ifdef CLD_CONTINUED
15389 if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
15390 #endif
15391
15392 /* constants for lockf */
15393 #ifdef F_LOCK
15394 if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
15395 #endif
15396 #ifdef F_TLOCK
15397 if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
15398 #endif
15399 #ifdef F_ULOCK
15400 if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
15401 #endif
15402 #ifdef F_TEST
15403 if (PyModule_AddIntMacro(m, F_TEST)) return -1;
15404 #endif
15405
15406 #ifdef RWF_DSYNC
15407 if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
15408 #endif
15409 #ifdef RWF_HIPRI
15410 if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
15411 #endif
15412 #ifdef RWF_SYNC
15413 if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
15414 #endif
15415 #ifdef RWF_NOWAIT
15416 if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
15417 #endif
15418 #ifdef RWF_APPEND
15419 if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
15420 #endif
15421
15422 /* constants for splice */
15423 #if defined(HAVE_SPLICE) && defined(__linux__)
15424 if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
15425 if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
15426 if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
15427 #endif
15428
15429 /* constants for posix_spawn */
15430 #ifdef HAVE_POSIX_SPAWN
15431 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
15432 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
15433 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
15434 #endif
15435
15436 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
15437 if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
15438 if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
15439 if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
15440 #endif
15441 #ifdef HAVE_SPAWNV
15442 if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
15443 if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
15444 #endif
15445
15446 #ifdef HAVE_SCHED_H
15447 #ifdef SCHED_OTHER
15448 if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
15449 #endif
15450 #ifdef SCHED_FIFO
15451 if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
15452 #endif
15453 #ifdef SCHED_RR
15454 if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
15455 #endif
15456 #ifdef SCHED_SPORADIC
15457 if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
15458 #endif
15459 #ifdef SCHED_BATCH
15460 if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
15461 #endif
15462 #ifdef SCHED_IDLE
15463 if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
15464 #endif
15465 #ifdef SCHED_RESET_ON_FORK
15466 if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
15467 #endif
15468 #ifdef SCHED_SYS
15469 if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
15470 #endif
15471 #ifdef SCHED_IA
15472 if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
15473 #endif
15474 #ifdef SCHED_FSS
15475 if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
15476 #endif
15477 #ifdef SCHED_FX
15478 if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
15479 #endif
15480 #endif
15481
15482 #ifdef USE_XATTRS
15483 if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
15484 if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
15485 if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
15486 #endif
15487
15488 #if HAVE_DECL_RTLD_LAZY
15489 if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
15490 #endif
15491 #if HAVE_DECL_RTLD_NOW
15492 if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
15493 #endif
15494 #if HAVE_DECL_RTLD_GLOBAL
15495 if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
15496 #endif
15497 #if HAVE_DECL_RTLD_LOCAL
15498 if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
15499 #endif
15500 #if HAVE_DECL_RTLD_NODELETE
15501 if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
15502 #endif
15503 #if HAVE_DECL_RTLD_NOLOAD
15504 if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
15505 #endif
15506 #if HAVE_DECL_RTLD_DEEPBIND
15507 if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
15508 #endif
15509 #if HAVE_DECL_RTLD_MEMBER
15510 if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
15511 #endif
15512
15513 #ifdef HAVE_GETRANDOM_SYSCALL
15514 if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
15515 if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
15516 #endif
15517 #ifdef HAVE_MEMFD_CREATE
15518 if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
15519 if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
15520 #ifdef MFD_HUGETLB
15521 if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
15522 #endif
15523 #ifdef MFD_HUGE_SHIFT
15524 if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
15525 #endif
15526 #ifdef MFD_HUGE_MASK
15527 if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
15528 #endif
15529 #ifdef MFD_HUGE_64KB
15530 if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
15531 #endif
15532 #ifdef MFD_HUGE_512KB
15533 if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
15534 #endif
15535 #ifdef MFD_HUGE_1MB
15536 if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
15537 #endif
15538 #ifdef MFD_HUGE_2MB
15539 if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
15540 #endif
15541 #ifdef MFD_HUGE_8MB
15542 if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
15543 #endif
15544 #ifdef MFD_HUGE_16MB
15545 if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
15546 #endif
15547 #ifdef MFD_HUGE_32MB
15548 if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
15549 #endif
15550 #ifdef MFD_HUGE_256MB
15551 if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
15552 #endif
15553 #ifdef MFD_HUGE_512MB
15554 if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
15555 #endif
15556 #ifdef MFD_HUGE_1GB
15557 if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
15558 #endif
15559 #ifdef MFD_HUGE_2GB
15560 if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
15561 #endif
15562 #ifdef MFD_HUGE_16GB
15563 if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
15564 #endif
15565 #endif /* HAVE_MEMFD_CREATE */
15566
15567 #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15568 if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
15569 #ifdef EFD_NONBLOCK
15570 if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
15571 #endif
15572 #ifdef EFD_SEMAPHORE
15573 if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
15574 #endif
15575 #endif /* HAVE_EVENTFD && EFD_CLOEXEC */
15576
15577 #if defined(__APPLE__)
15578 if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
15579 if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
15580 if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
15581 if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
15582 #endif
15583
15584 #ifdef MS_WINDOWS
15585 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
15586 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
15587 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
15588 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
15589 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
15590 #endif
15591
15592 return 0;
15593 }
15594
15595
15596
15597 #define PROBE(name, test) \
15598 static int name(void) \
15599 { \
15600 if (test) { \
15601 return 1; \
15602 } else { \
15603 return 0; \
15604 } \
15605 }
15606
15607 #ifdef HAVE_FSTATAT
15608 PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
15609 #endif
15610
15611 #ifdef HAVE_FACCESSAT
15612 PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
15613 #endif
15614
15615 #ifdef HAVE_FCHMODAT
15616 PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
15617 #endif
15618
15619 #ifdef HAVE_FCHOWNAT
15620 PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
15621 #endif
15622
15623 #ifdef HAVE_LINKAT
15624 PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
15625 #endif
15626
15627 #ifdef HAVE_FDOPENDIR
15628 PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
15629 #endif
15630
15631 #ifdef HAVE_MKDIRAT
15632 PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
15633 #endif
15634
15635 #ifdef HAVE_MKFIFOAT
15636 PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
15637 #endif
15638
15639 #ifdef HAVE_MKNODAT
15640 PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
15641 #endif
15642
15643 #ifdef HAVE_RENAMEAT
15644 PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
15645 #endif
15646
15647 #ifdef HAVE_UNLINKAT
15648 PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
15649 #endif
15650
15651 #ifdef HAVE_OPENAT
15652 PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
15653 #endif
15654
15655 #ifdef HAVE_READLINKAT
15656 PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
15657 #endif
15658
15659 #ifdef HAVE_SYMLINKAT
15660 PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
15661 #endif
15662
15663 #ifdef HAVE_FUTIMENS
15664 PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
15665 #endif
15666
15667 #ifdef HAVE_UTIMENSAT
15668 PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
15669 #endif
15670
15671
15672
15673
15674 static const struct have_function {
15675 const char * const label;
15676 int (*probe)(void);
15677 } have_functions[] = {
15678
15679 #ifdef HAVE_EVENTFD
15680 {"HAVE_EVENTFD", NULL},
15681 #endif
15682
15683 #ifdef HAVE_FACCESSAT
15684 { "HAVE_FACCESSAT", probe_faccessat },
15685 #endif
15686
15687 #ifdef HAVE_FCHDIR
15688 { "HAVE_FCHDIR", NULL },
15689 #endif
15690
15691 #ifdef HAVE_FCHMOD
15692 { "HAVE_FCHMOD", NULL },
15693 #endif
15694
15695 #ifdef HAVE_FCHMODAT
15696 { "HAVE_FCHMODAT", probe_fchmodat },
15697 #endif
15698
15699 #ifdef HAVE_FCHOWN
15700 { "HAVE_FCHOWN", NULL },
15701 #endif
15702
15703 #ifdef HAVE_FCHOWNAT
15704 { "HAVE_FCHOWNAT", probe_fchownat },
15705 #endif
15706
15707 #ifdef HAVE_FEXECVE
15708 { "HAVE_FEXECVE", NULL },
15709 #endif
15710
15711 #ifdef HAVE_FDOPENDIR
15712 { "HAVE_FDOPENDIR", probe_fdopendir },
15713 #endif
15714
15715 #ifdef HAVE_FPATHCONF
15716 { "HAVE_FPATHCONF", NULL },
15717 #endif
15718
15719 #ifdef HAVE_FSTATAT
15720 { "HAVE_FSTATAT", probe_fstatat },
15721 #endif
15722
15723 #ifdef HAVE_FSTATVFS
15724 { "HAVE_FSTATVFS", NULL },
15725 #endif
15726
15727 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
15728 { "HAVE_FTRUNCATE", NULL },
15729 #endif
15730
15731 #ifdef HAVE_FUTIMENS
15732 { "HAVE_FUTIMENS", probe_futimens },
15733 #endif
15734
15735 #ifdef HAVE_FUTIMES
15736 { "HAVE_FUTIMES", NULL },
15737 #endif
15738
15739 #ifdef HAVE_FUTIMESAT
15740 { "HAVE_FUTIMESAT", NULL },
15741 #endif
15742
15743 #ifdef HAVE_LINKAT
15744 { "HAVE_LINKAT", probe_linkat },
15745 #endif
15746
15747 #ifdef HAVE_LCHFLAGS
15748 { "HAVE_LCHFLAGS", NULL },
15749 #endif
15750
15751 #ifdef HAVE_LCHMOD
15752 { "HAVE_LCHMOD", NULL },
15753 #endif
15754
15755 #ifdef HAVE_LCHOWN
15756 { "HAVE_LCHOWN", NULL },
15757 #endif
15758
15759 #ifdef HAVE_LSTAT
15760 { "HAVE_LSTAT", NULL },
15761 #endif
15762
15763 #ifdef HAVE_LUTIMES
15764 { "HAVE_LUTIMES", NULL },
15765 #endif
15766
15767 #ifdef HAVE_MEMFD_CREATE
15768 { "HAVE_MEMFD_CREATE", NULL },
15769 #endif
15770
15771 #ifdef HAVE_MKDIRAT
15772 { "HAVE_MKDIRAT", probe_mkdirat },
15773 #endif
15774
15775 #ifdef HAVE_MKFIFOAT
15776 { "HAVE_MKFIFOAT", probe_mkfifoat },
15777 #endif
15778
15779 #ifdef HAVE_MKNODAT
15780 { "HAVE_MKNODAT", probe_mknodat },
15781 #endif
15782
15783 #ifdef HAVE_OPENAT
15784 { "HAVE_OPENAT", probe_openat },
15785 #endif
15786
15787 #ifdef HAVE_READLINKAT
15788 { "HAVE_READLINKAT", probe_readlinkat },
15789 #endif
15790
15791 #ifdef HAVE_RENAMEAT
15792 { "HAVE_RENAMEAT", probe_renameat },
15793 #endif
15794
15795 #ifdef HAVE_SYMLINKAT
15796 { "HAVE_SYMLINKAT", probe_symlinkat },
15797 #endif
15798
15799 #ifdef HAVE_UNLINKAT
15800 { "HAVE_UNLINKAT", probe_unlinkat },
15801 #endif
15802
15803 #ifdef HAVE_UTIMENSAT
15804 { "HAVE_UTIMENSAT", probe_utimensat },
15805 #endif
15806
15807 #ifdef MS_WINDOWS
15808 { "MS_WINDOWS", NULL },
15809 #endif
15810
15811 { NULL, NULL }
15812 };
15813
15814
15815 static int
posixmodule_exec(PyObject * m)15816 posixmodule_exec(PyObject *m)
15817 {
15818 _posixstate *state = get_posix_state(m);
15819
15820 #if defined(HAVE_PWRITEV)
15821 if (HAVE_PWRITEV_RUNTIME) {} else {
15822 PyObject* dct = PyModule_GetDict(m);
15823
15824 if (dct == NULL) {
15825 return -1;
15826 }
15827
15828 if (PyDict_DelItemString(dct, "pwritev") == -1) {
15829 PyErr_Clear();
15830 }
15831 if (PyDict_DelItemString(dct, "preadv") == -1) {
15832 PyErr_Clear();
15833 }
15834 }
15835 #endif
15836
15837 /* Initialize environ dictionary */
15838 PyObject *v = convertenviron();
15839 Py_XINCREF(v);
15840 if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
15841 return -1;
15842 Py_DECREF(v);
15843
15844 if (all_ins(m))
15845 return -1;
15846
15847 if (setup_confname_tables(m))
15848 return -1;
15849
15850 Py_INCREF(PyExc_OSError);
15851 PyModule_AddObject(m, "error", PyExc_OSError);
15852
15853 #if defined(HAVE_WAITID) && !defined(__APPLE__)
15854 waitid_result_desc.name = MODNAME ".waitid_result";
15855 PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
15856 if (WaitidResultType == NULL) {
15857 return -1;
15858 }
15859 Py_INCREF(WaitidResultType);
15860 PyModule_AddObject(m, "waitid_result", WaitidResultType);
15861 state->WaitidResultType = WaitidResultType;
15862 #endif
15863
15864 stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
15865 stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
15866 stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
15867 stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
15868 PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
15869 if (StatResultType == NULL) {
15870 return -1;
15871 }
15872 Py_INCREF(StatResultType);
15873 PyModule_AddObject(m, "stat_result", StatResultType);
15874 state->StatResultType = StatResultType;
15875 structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15876 ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
15877
15878 statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
15879 PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
15880 if (StatVFSResultType == NULL) {
15881 return -1;
15882 }
15883 Py_INCREF(StatVFSResultType);
15884 PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
15885 state->StatVFSResultType = StatVFSResultType;
15886 #ifdef NEED_TICKS_PER_SECOND
15887 # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15888 ticks_per_second = sysconf(_SC_CLK_TCK);
15889 # elif defined(HZ)
15890 ticks_per_second = HZ;
15891 # else
15892 ticks_per_second = 60; /* magic fallback value; may be bogus */
15893 # endif
15894 #endif
15895
15896 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
15897 sched_param_desc.name = MODNAME ".sched_param";
15898 PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
15899 if (SchedParamType == NULL) {
15900 return -1;
15901 }
15902 Py_INCREF(SchedParamType);
15903 PyModule_AddObject(m, "sched_param", SchedParamType);
15904 state->SchedParamType = SchedParamType;
15905 ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
15906 #endif
15907
15908 /* initialize TerminalSize_info */
15909 PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
15910 if (TerminalSizeType == NULL) {
15911 return -1;
15912 }
15913 Py_INCREF(TerminalSizeType);
15914 PyModule_AddObject(m, "terminal_size", TerminalSizeType);
15915 state->TerminalSizeType = TerminalSizeType;
15916
15917 /* initialize scandir types */
15918 PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
15919 if (ScandirIteratorType == NULL) {
15920 return -1;
15921 }
15922 state->ScandirIteratorType = ScandirIteratorType;
15923
15924 PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
15925 if (DirEntryType == NULL) {
15926 return -1;
15927 }
15928 Py_INCREF(DirEntryType);
15929 PyModule_AddObject(m, "DirEntry", DirEntryType);
15930 state->DirEntryType = DirEntryType;
15931
15932 times_result_desc.name = MODNAME ".times_result";
15933 PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(×_result_desc);
15934 if (TimesResultType == NULL) {
15935 return -1;
15936 }
15937 Py_INCREF(TimesResultType);
15938 PyModule_AddObject(m, "times_result", TimesResultType);
15939 state->TimesResultType = TimesResultType;
15940
15941 PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
15942 if (UnameResultType == NULL) {
15943 return -1;
15944 }
15945 Py_INCREF(UnameResultType);
15946 PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
15947 state->UnameResultType = (PyObject *)UnameResultType;
15948
15949 if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
15950 return -1;
15951 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
15952 state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
15953 if (state->struct_rusage == NULL)
15954 return -1;
15955 #endif
15956 state->st_mode = PyUnicode_InternFromString("st_mode");
15957 if (state->st_mode == NULL)
15958 return -1;
15959
15960 /* suppress "function not used" warnings */
15961 {
15962 int ignored;
15963 fd_specified("", -1);
15964 follow_symlinks_specified("", 1);
15965 dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
15966 dir_fd_converter(Py_None, &ignored);
15967 dir_fd_unavailable(Py_None, &ignored);
15968 }
15969
15970 /*
15971 * provide list of locally available functions
15972 * so os.py can populate support_* lists
15973 */
15974 PyObject *list = PyList_New(0);
15975 if (!list) {
15976 return -1;
15977 }
15978 for (const struct have_function *trace = have_functions; trace->label; trace++) {
15979 PyObject *unicode;
15980 if (trace->probe && !trace->probe()) continue;
15981 unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
15982 if (!unicode)
15983 return -1;
15984 if (PyList_Append(list, unicode))
15985 return -1;
15986 Py_DECREF(unicode);
15987 }
15988
15989 PyModule_AddObject(m, "_have_functions", list);
15990
15991 return 0;
15992 }
15993
15994
15995 static PyModuleDef_Slot posixmodile_slots[] = {
15996 {Py_mod_exec, posixmodule_exec},
15997 {0, NULL}
15998 };
15999
16000 static struct PyModuleDef posixmodule = {
16001 PyModuleDef_HEAD_INIT,
16002 .m_name = MODNAME,
16003 .m_doc = posix__doc__,
16004 .m_size = sizeof(_posixstate),
16005 .m_methods = posix_methods,
16006 .m_slots = posixmodile_slots,
16007 .m_traverse = _posix_traverse,
16008 .m_clear = _posix_clear,
16009 .m_free = _posix_free,
16010 };
16011
16012 PyMODINIT_FUNC
INITFUNC(void)16013 INITFUNC(void)
16014 {
16015 return PyModuleDef_Init(&posixmodule);
16016 }
16017
16018 #ifdef __cplusplus
16019 }
16020 #endif
16021