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 #ifdef MS_WINDOWS
38 # include <aclapi.h> // SetEntriesInAcl
39 # include <sddl.h> // SDDL_REVISION_1
40 #endif
41
42 #include "structmember.h" // PyMemberDef
43 #ifndef MS_WINDOWS
44 # include "posixmodule.h"
45 #else
46 # include "winreparse.h"
47 #endif
48
49 #if !defined(EX_OK) && defined(EXIT_SUCCESS)
50 # define EX_OK EXIT_SUCCESS
51 #endif
52
53 /* On android API level 21, 'AT_EACCESS' is not declared although
54 * HAVE_FACCESSAT is defined. */
55 #ifdef __ANDROID__
56 # undef HAVE_FACCESSAT
57 #endif
58
59 #include <stdio.h> // ctermid()
60 #include <stdlib.h> // system()
61
62 /*
63 * A number of APIs are available on macOS from a certain macOS version.
64 * To support building with a new SDK while deploying to older versions
65 * the availability test is split into two:
66 * - HAVE_<FUNCTION>: The configure check for compile time availability
67 * - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
68 *
69 * The latter is always true when not on macOS, or when using a compiler
70 * that does not support __has_builtin (older versions of Xcode).
71 *
72 * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
73 * if (HAVE_<FUNCTION>_RUNTIME) { ... }
74 *
75 * In mixing the test with other tests or using negations will result in compile
76 * errors.
77 */
78 #if defined(__APPLE__)
79
80 #if defined(__has_builtin)
81 #if __has_builtin(__builtin_available)
82 #define HAVE_BUILTIN_AVAILABLE 1
83 #endif
84 #endif
85
86 #ifdef HAVE_BUILTIN_AVAILABLE
87 # define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
88 # define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
89 # define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
90 # define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
91 # define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
92 # define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
93 # define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
94 # define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
95 # define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
96 # define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
97 # define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
98 # define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
99 # define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
100 # define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
101 # define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
102 # define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
103 # define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
104
105 # define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
106
107 #else /* Xcode 8 or earlier */
108
109 /* __builtin_available is not present in these compilers, but
110 * some of the symbols might be weak linked (10.10 SDK or later
111 * deploying on 10.9.
112 *
113 * Fall back to the older style of availability checking for
114 * symbols introduced in macOS 10.10.
115 */
116
117 # ifdef HAVE_FSTATAT
118 # define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
119 # endif
120
121 # ifdef HAVE_FACCESSAT
122 # define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
123 # endif
124
125 # ifdef HAVE_FCHMODAT
126 # define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
127 # endif
128
129 # ifdef HAVE_FCHOWNAT
130 # define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
131 # endif
132
133 # ifdef HAVE_LINKAT
134 # define HAVE_LINKAT_RUNTIME (linkat != NULL)
135 # endif
136
137 # ifdef HAVE_FDOPENDIR
138 # define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
139 # endif
140
141 # ifdef HAVE_MKDIRAT
142 # define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
143 # endif
144
145 # ifdef HAVE_RENAMEAT
146 # define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
147 # endif
148
149 # ifdef HAVE_UNLINKAT
150 # define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
151 # endif
152
153 # ifdef HAVE_OPENAT
154 # define HAVE_OPENAT_RUNTIME (openat != NULL)
155 # endif
156
157 # ifdef HAVE_READLINKAT
158 # define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
159 # endif
160
161 # ifdef HAVE_SYMLINKAT
162 # define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
163 # endif
164
165 # ifdef HAVE_UTIMENSAT
166 # define HAVE_UTIMENSAT_RUNTIME (utimensat != NULL)
167 # endif
168
169 # ifdef HAVE_FUTIMENS
170 # define HAVE_FUTIMENS_RUNTIME (futimens != NULL)
171 # endif
172
173 # ifdef HAVE_PWRITEV
174 # define HAVE_PWRITEV_RUNTIME (pwritev != NULL)
175 # endif
176
177 # ifdef HAVE_MKFIFOAT
178 # define HAVE_MKFIFOAT_RUNTIME (mkfifoat != NULL)
179 # endif
180
181 # ifdef HAVE_MKNODAT
182 # define HAVE_MKNODAT_RUNTIME (mknodat != NULL)
183 # endif
184
185 #endif
186
187 #ifdef HAVE_FUTIMESAT
188 /* Some of the logic for weak linking depends on this assertion */
189 # error "HAVE_FUTIMESAT unexpectedly defined"
190 #endif
191
192 #else
193 # define HAVE_FSTATAT_RUNTIME 1
194 # define HAVE_FACCESSAT_RUNTIME 1
195 # define HAVE_FCHMODAT_RUNTIME 1
196 # define HAVE_FCHOWNAT_RUNTIME 1
197 # define HAVE_LINKAT_RUNTIME 1
198 # define HAVE_FDOPENDIR_RUNTIME 1
199 # define HAVE_MKDIRAT_RUNTIME 1
200 # define HAVE_RENAMEAT_RUNTIME 1
201 # define HAVE_UNLINKAT_RUNTIME 1
202 # define HAVE_OPENAT_RUNTIME 1
203 # define HAVE_READLINKAT_RUNTIME 1
204 # define HAVE_SYMLINKAT_RUNTIME 1
205 # define HAVE_FUTIMENS_RUNTIME 1
206 # define HAVE_UTIMENSAT_RUNTIME 1
207 # define HAVE_PWRITEV_RUNTIME 1
208 # define HAVE_MKFIFOAT_RUNTIME 1
209 # define HAVE_MKNODAT_RUNTIME 1
210 #endif
211
212
213 #ifdef __cplusplus
214 extern "C" {
215 #endif
216
217 PyDoc_STRVAR(posix__doc__,
218 "This module provides access to operating system functionality that is\n\
219 standardized by the C Standard and the POSIX standard (a thinly\n\
220 disguised Unix interface). Refer to the library manual and\n\
221 corresponding Unix manual entries for more information on calls.");
222
223
224 #ifdef HAVE_SYS_UIO_H
225 # include <sys/uio.h>
226 #endif
227
228 #ifdef HAVE_SYS_SYSMACROS_H
229 /* GNU C Library: major(), minor(), makedev() */
230 # include <sys/sysmacros.h>
231 #endif
232
233 #ifdef HAVE_SYS_TYPES_H
234 # include <sys/types.h>
235 #endif /* HAVE_SYS_TYPES_H */
236
237 #ifdef HAVE_SYS_STAT_H
238 # include <sys/stat.h>
239 #endif /* HAVE_SYS_STAT_H */
240
241 #ifdef HAVE_SYS_WAIT_H
242 # include <sys/wait.h> // WNOHANG
243 #endif
244 #ifdef HAVE_LINUX_WAIT_H
245 # include <linux/wait.h> // P_PIDFD
246 #endif
247
248 #ifdef HAVE_SIGNAL_H
249 # include <signal.h>
250 #endif
251
252 #ifdef HAVE_FCNTL_H
253 # include <fcntl.h>
254 #endif
255
256 #ifdef HAVE_GRP_H
257 # include <grp.h>
258 #endif
259
260 #ifdef HAVE_SYSEXITS_H
261 # include <sysexits.h>
262 #endif
263
264 #ifdef HAVE_SYS_LOADAVG_H
265 # include <sys/loadavg.h>
266 #endif
267
268 #ifdef HAVE_SYS_SENDFILE_H
269 # include <sys/sendfile.h>
270 #endif
271
272 #if defined(__APPLE__)
273 # include <copyfile.h>
274 #endif
275
276 #ifdef HAVE_SCHED_H
277 # include <sched.h>
278 #endif
279
280 #ifdef HAVE_COPY_FILE_RANGE
281 # include <unistd.h>
282 #endif
283
284 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
285 # undef HAVE_SCHED_SETAFFINITY
286 #endif
287
288 #if defined(HAVE_SYS_XATTR_H) && defined(__linux__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
289 # define USE_XATTRS
290 # include <linux/limits.h> // Needed for XATTR_SIZE_MAX on musl libc.
291 #endif
292
293 #ifdef USE_XATTRS
294 # include <sys/xattr.h>
295 #endif
296
297 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
298 # ifdef HAVE_SYS_SOCKET_H
299 # include <sys/socket.h>
300 # endif
301 #endif
302
303 #ifdef HAVE_DLFCN_H
304 # include <dlfcn.h>
305 #endif
306
307 #ifdef __hpux
308 # include <sys/mpctl.h>
309 #endif
310
311 #if defined(__DragonFly__) || \
312 defined(__OpenBSD__) || \
313 defined(__FreeBSD__) || \
314 defined(__NetBSD__) || \
315 defined(__APPLE__)
316 # include <sys/sysctl.h>
317 #endif
318
319 #ifdef HAVE_LINUX_RANDOM_H
320 # include <linux/random.h>
321 #endif
322 #ifdef HAVE_GETRANDOM_SYSCALL
323 # include <sys/syscall.h>
324 #endif
325
326 #if defined(MS_WINDOWS)
327 # define TERMSIZE_USE_CONIO
328 #elif defined(HAVE_SYS_IOCTL_H)
329 # include <sys/ioctl.h>
330 # if defined(HAVE_TERMIOS_H)
331 # include <termios.h>
332 # endif
333 # if defined(TIOCGWINSZ)
334 # define TERMSIZE_USE_IOCTL
335 # endif
336 #endif /* MS_WINDOWS */
337
338 /* Various compilers have only certain posix functions */
339 /* XXX Gosh I wish these were all moved into pyconfig.h */
340 #if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */
341 # define HAVE_OPENDIR 1
342 # define HAVE_SYSTEM 1
343 # include <process.h>
344 #else
345 # ifdef _MSC_VER
346 /* Microsoft compiler */
347 # define HAVE_GETPPID 1
348 # define HAVE_GETLOGIN 1
349 # define HAVE_SPAWNV 1
350 # define HAVE_EXECV 1
351 # define HAVE_WSPAWNV 1
352 # define HAVE_WEXECV 1
353 # define HAVE_PIPE 1
354 # define HAVE_SYSTEM 1
355 # define HAVE_CWAIT 1
356 # define HAVE_FSYNC 1
357 # define fsync _commit
358 # endif /* _MSC_VER */
359 #endif /* ! __WATCOMC__ || __QNX__ */
360
361 /*[clinic input]
362 # one of the few times we lie about this name!
363 module os
364 [clinic start generated code]*/
365 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
366
367 #ifndef _MSC_VER
368
369 #if defined(__sgi)&&_COMPILER_VERSION>=700
370 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
371 (default) */
372 extern char *ctermid_r(char *);
373 #endif
374
375 #endif /* !_MSC_VER */
376
377 #if defined(__VXWORKS__)
378 # include <vxCpuLib.h>
379 # include <rtpLib.h>
380 # include <wait.h>
381 # include <taskLib.h>
382 # ifndef _P_WAIT
383 # define _P_WAIT 0
384 # define _P_NOWAIT 1
385 # define _P_NOWAITO 1
386 # endif
387 #endif /* __VXWORKS__ */
388
389 #ifdef HAVE_POSIX_SPAWN
390 # include <spawn.h>
391 #endif
392
393 #ifdef HAVE_UTIME_H
394 # include <utime.h>
395 #endif /* HAVE_UTIME_H */
396
397 #ifdef HAVE_SYS_UTIME_H
398 # include <sys/utime.h>
399 # define HAVE_UTIME_H /* pretend we do for the rest of this file */
400 #endif /* HAVE_SYS_UTIME_H */
401
402 #ifdef HAVE_SYS_TIMES_H
403 # include <sys/times.h>
404 #endif /* HAVE_SYS_TIMES_H */
405
406 #ifdef HAVE_SYS_PARAM_H
407 # include <sys/param.h>
408 #endif /* HAVE_SYS_PARAM_H */
409
410 #ifdef HAVE_SYS_UTSNAME_H
411 # include <sys/utsname.h>
412 #endif /* HAVE_SYS_UTSNAME_H */
413
414 #ifdef HAVE_DIRENT_H
415 # include <dirent.h>
416 # define NAMLEN(dirent) strlen((dirent)->d_name)
417 #else
418 # if defined(__WATCOMC__) && !defined(__QNX__)
419 # include <direct.h>
420 # define NAMLEN(dirent) strlen((dirent)->d_name)
421 # else
422 # define dirent direct
423 # define NAMLEN(dirent) (dirent)->d_namlen
424 # endif
425 # ifdef HAVE_SYS_NDIR_H
426 # include <sys/ndir.h>
427 # endif
428 # ifdef HAVE_SYS_DIR_H
429 # include <sys/dir.h>
430 # endif
431 # ifdef HAVE_NDIR_H
432 # include <ndir.h>
433 # endif
434 #endif
435
436 #ifdef _MSC_VER
437 # ifdef HAVE_DIRECT_H
438 # include <direct.h>
439 # endif
440 # ifdef HAVE_IO_H
441 # include <io.h>
442 # endif
443 # ifdef HAVE_PROCESS_H
444 # include <process.h>
445 # endif
446 # include <malloc.h>
447 #endif /* _MSC_VER */
448
449 #ifndef MAXPATHLEN
450 # if defined(PATH_MAX) && PATH_MAX > 1024
451 # define MAXPATHLEN PATH_MAX
452 # else
453 # define MAXPATHLEN 1024
454 # endif
455 #endif /* MAXPATHLEN */
456
457 #ifdef UNION_WAIT
458 /* Emulate some macros on systems that have a union instead of macros */
459 # ifndef WIFEXITED
460 # define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
461 # endif
462 # ifndef WEXITSTATUS
463 # define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
464 # endif
465 # ifndef WTERMSIG
466 # define WTERMSIG(u_wait) ((u_wait).w_termsig)
467 # endif
468 # define WAIT_TYPE union wait
469 # define WAIT_STATUS_INT(s) (s.w_status)
470 #else
471 /* !UNION_WAIT */
472 # define WAIT_TYPE int
473 # define WAIT_STATUS_INT(s) (s)
474 #endif /* UNION_WAIT */
475
476 /* Don't use the "_r" form if we don't need it (also, won't have a
477 prototype for it, at least on Solaris -- maybe others as well?). */
478 #if defined(HAVE_CTERMID_R)
479 # define USE_CTERMID_R
480 #endif
481
482 /* choose the appropriate stat and fstat functions and return structs */
483 #undef STAT
484 #undef FSTAT
485 #undef STRUCT_STAT
486 #ifdef MS_WINDOWS
487 # define STAT win32_stat
488 # define LSTAT win32_lstat
489 # define FSTAT _Py_fstat_noraise
490 # define STRUCT_STAT struct _Py_stat_struct
491 #else
492 # define STAT stat
493 # define LSTAT lstat
494 # define FSTAT fstat
495 # define STRUCT_STAT struct stat
496 #endif
497
498 #if defined(MAJOR_IN_MKDEV)
499 # include <sys/mkdev.h>
500 #else
501 # if defined(MAJOR_IN_SYSMACROS)
502 # include <sys/sysmacros.h>
503 # endif
504 # if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
505 # include <sys/mkdev.h>
506 # endif
507 #endif
508
509 #ifdef MS_WINDOWS
510 # define INITFUNC PyInit_nt
511 # define MODNAME "nt"
512 #else
513 # define INITFUNC PyInit_posix
514 # define MODNAME "posix"
515 #endif
516
517 #if defined(__sun)
518 /* Something to implement in autoconf, not present in autoconf 2.69 */
519 # define HAVE_STRUCT_STAT_ST_FSTYPE 1
520 #endif
521
522 /* memfd_create is either defined in sys/mman.h or sys/memfd.h
523 * linux/memfd.h defines additional flags
524 */
525 #ifdef HAVE_SYS_MMAN_H
526 # include <sys/mman.h>
527 #endif
528 #ifdef HAVE_SYS_MEMFD_H
529 # include <sys/memfd.h>
530 #endif
531 #ifdef HAVE_LINUX_MEMFD_H
532 # include <linux/memfd.h>
533 #endif
534
535 /* eventfd() */
536 #ifdef HAVE_SYS_EVENTFD_H
537 # include <sys/eventfd.h>
538 #endif
539
540 #ifdef _Py_MEMORY_SANITIZER
541 # include <sanitizer/msan_interface.h>
542 #endif
543
544 #ifdef HAVE_FORK
545 static void
run_at_forkers(PyObject *lst, int reverse)546 run_at_forkers(PyObject *lst, int reverse)
547 {
548 Py_ssize_t i;
549 PyObject *cpy;
550
551 if (lst != NULL) {
552 assert(PyList_CheckExact(lst));
553
554 /* Use a list copy in case register_at_fork() is called from
555 * one of the callbacks.
556 */
557 cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
558 if (cpy == NULL)
559 PyErr_WriteUnraisable(lst);
560 else {
561 if (reverse)
562 PyList_Reverse(cpy);
563 for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
564 PyObject *func, *res;
565 func = PyList_GET_ITEM(cpy, i);
566 res = _PyObject_CallNoArgs(func);
567 if (res == NULL)
568 PyErr_WriteUnraisable(func);
569 else
570 Py_DECREF(res);
571 }
572 Py_DECREF(cpy);
573 }
574 }
575 }
576
577 void
PyOS_BeforeFork(void)578 PyOS_BeforeFork(void)
579 {
580 run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1);
581
582 _PyImport_AcquireLock();
583 }
584
585 void
PyOS_AfterFork_Parent(void)586 PyOS_AfterFork_Parent(void)
587 {
588 if (_PyImport_ReleaseLock() <= 0)
589 Py_FatalError("failed releasing import lock after fork");
590
591 run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0);
592 }
593
594 void
PyOS_AfterFork_Child(void)595 PyOS_AfterFork_Child(void)
596 {
597 PyStatus status;
598 _PyRuntimeState *runtime = &_PyRuntime;
599
600 status = _PyGILState_Reinit(runtime);
601 if (_PyStatus_EXCEPTION(status)) {
602 goto fatal_error;
603 }
604
605 PyThreadState *tstate = _PyThreadState_GET();
606 _Py_EnsureTstateNotNULL(tstate);
607
608 #ifdef PY_HAVE_THREAD_NATIVE_ID
609 tstate->native_thread_id = PyThread_get_thread_native_id();
610 #endif
611
612 status = _PyEval_ReInitThreads(tstate);
613 if (_PyStatus_EXCEPTION(status)) {
614 goto fatal_error;
615 }
616
617 status = _PyImport_ReInitLock();
618 if (_PyStatus_EXCEPTION(status)) {
619 goto fatal_error;
620 }
621
622 _PySignal_AfterFork();
623
624 status = _PyRuntimeState_ReInitThreads(runtime);
625 if (_PyStatus_EXCEPTION(status)) {
626 goto fatal_error;
627 }
628
629 status = _PyInterpreterState_DeleteExceptMain(runtime);
630 if (_PyStatus_EXCEPTION(status)) {
631 goto fatal_error;
632 }
633 assert(_PyThreadState_GET() == tstate);
634
635 run_at_forkers(tstate->interp->after_forkers_child, 0);
636 return;
637
638 fatal_error:
639 Py_ExitStatusException(status);
640 }
641
642 static int
register_at_forker(PyObject **lst, PyObject *func)643 register_at_forker(PyObject **lst, PyObject *func)
644 {
645 if (func == NULL) /* nothing to register? do nothing. */
646 return 0;
647 if (*lst == NULL) {
648 *lst = PyList_New(0);
649 if (*lst == NULL)
650 return -1;
651 }
652 return PyList_Append(*lst, func);
653 }
654 #endif /* HAVE_FORK */
655
656
657 /* Legacy wrapper */
658 void
PyOS_AfterFork(void)659 PyOS_AfterFork(void)
660 {
661 #ifdef HAVE_FORK
662 PyOS_AfterFork_Child();
663 #endif
664 }
665
666
667 #ifdef MS_WINDOWS
668 /* defined in fileutils.c */
669 void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
670 void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
671 ULONG, struct _Py_stat_struct *);
672 #endif
673
674
675 #ifndef MS_WINDOWS
676 PyObject *
_PyLong_FromUid(uid_t uid)677 _PyLong_FromUid(uid_t uid)
678 {
679 if (uid == (uid_t)-1)
680 return PyLong_FromLong(-1);
681 return PyLong_FromUnsignedLong(uid);
682 }
683
684 PyObject *
_PyLong_FromGid(gid_t gid)685 _PyLong_FromGid(gid_t gid)
686 {
687 if (gid == (gid_t)-1)
688 return PyLong_FromLong(-1);
689 return PyLong_FromUnsignedLong(gid);
690 }
691
692 int
_Py_Uid_Converter(PyObject *obj, uid_t *p)693 _Py_Uid_Converter(PyObject *obj, uid_t *p)
694 {
695 uid_t uid;
696 PyObject *index;
697 int overflow;
698 long result;
699 unsigned long uresult;
700
701 index = _PyNumber_Index(obj);
702 if (index == NULL) {
703 PyErr_Format(PyExc_TypeError,
704 "uid should be integer, not %.200s",
705 _PyType_Name(Py_TYPE(obj)));
706 return 0;
707 }
708
709 /*
710 * Handling uid_t is complicated for two reasons:
711 * * Although uid_t is (always?) unsigned, it still
712 * accepts -1.
713 * * We don't know its size in advance--it may be
714 * bigger than an int, or it may be smaller than
715 * a long.
716 *
717 * So a bit of defensive programming is in order.
718 * Start with interpreting the value passed
719 * in as a signed long and see if it works.
720 */
721
722 result = PyLong_AsLongAndOverflow(index, &overflow);
723
724 if (!overflow) {
725 uid = (uid_t)result;
726
727 if (result == -1) {
728 if (PyErr_Occurred())
729 goto fail;
730 /* It's a legitimate -1, we're done. */
731 goto success;
732 }
733
734 /* Any other negative number is disallowed. */
735 if (result < 0)
736 goto underflow;
737
738 /* Ensure the value wasn't truncated. */
739 if (sizeof(uid_t) < sizeof(long) &&
740 (long)uid != result)
741 goto underflow;
742 goto success;
743 }
744
745 if (overflow < 0)
746 goto underflow;
747
748 /*
749 * Okay, the value overflowed a signed long. If it
750 * fits in an *unsigned* long, it may still be okay,
751 * as uid_t may be unsigned long on this platform.
752 */
753 uresult = PyLong_AsUnsignedLong(index);
754 if (PyErr_Occurred()) {
755 if (PyErr_ExceptionMatches(PyExc_OverflowError))
756 goto overflow;
757 goto fail;
758 }
759
760 uid = (uid_t)uresult;
761
762 /*
763 * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
764 * but this value would get interpreted as (uid_t)-1 by chown
765 * and its siblings. That's not what the user meant! So we
766 * throw an overflow exception instead. (We already
767 * handled a real -1 with PyLong_AsLongAndOverflow() above.)
768 */
769 if (uid == (uid_t)-1)
770 goto overflow;
771
772 /* Ensure the value wasn't truncated. */
773 if (sizeof(uid_t) < sizeof(long) &&
774 (unsigned long)uid != uresult)
775 goto overflow;
776 /* fallthrough */
777
778 success:
779 Py_DECREF(index);
780 *p = uid;
781 return 1;
782
783 underflow:
784 PyErr_SetString(PyExc_OverflowError,
785 "uid is less than minimum");
786 goto fail;
787
788 overflow:
789 PyErr_SetString(PyExc_OverflowError,
790 "uid is greater than maximum");
791 /* fallthrough */
792
793 fail:
794 Py_DECREF(index);
795 return 0;
796 }
797
798 int
_Py_Gid_Converter(PyObject *obj, gid_t *p)799 _Py_Gid_Converter(PyObject *obj, gid_t *p)
800 {
801 gid_t gid;
802 PyObject *index;
803 int overflow;
804 long result;
805 unsigned long uresult;
806
807 index = _PyNumber_Index(obj);
808 if (index == NULL) {
809 PyErr_Format(PyExc_TypeError,
810 "gid should be integer, not %.200s",
811 _PyType_Name(Py_TYPE(obj)));
812 return 0;
813 }
814
815 /*
816 * Handling gid_t is complicated for two reasons:
817 * * Although gid_t is (always?) unsigned, it still
818 * accepts -1.
819 * * We don't know its size in advance--it may be
820 * bigger than an int, or it may be smaller than
821 * a long.
822 *
823 * So a bit of defensive programming is in order.
824 * Start with interpreting the value passed
825 * in as a signed long and see if it works.
826 */
827
828 result = PyLong_AsLongAndOverflow(index, &overflow);
829
830 if (!overflow) {
831 gid = (gid_t)result;
832
833 if (result == -1) {
834 if (PyErr_Occurred())
835 goto fail;
836 /* It's a legitimate -1, we're done. */
837 goto success;
838 }
839
840 /* Any other negative number is disallowed. */
841 if (result < 0) {
842 goto underflow;
843 }
844
845 /* Ensure the value wasn't truncated. */
846 if (sizeof(gid_t) < sizeof(long) &&
847 (long)gid != result)
848 goto underflow;
849 goto success;
850 }
851
852 if (overflow < 0)
853 goto underflow;
854
855 /*
856 * Okay, the value overflowed a signed long. If it
857 * fits in an *unsigned* long, it may still be okay,
858 * as gid_t may be unsigned long on this platform.
859 */
860 uresult = PyLong_AsUnsignedLong(index);
861 if (PyErr_Occurred()) {
862 if (PyErr_ExceptionMatches(PyExc_OverflowError))
863 goto overflow;
864 goto fail;
865 }
866
867 gid = (gid_t)uresult;
868
869 /*
870 * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
871 * but this value would get interpreted as (gid_t)-1 by chown
872 * and its siblings. That's not what the user meant! So we
873 * throw an overflow exception instead. (We already
874 * handled a real -1 with PyLong_AsLongAndOverflow() above.)
875 */
876 if (gid == (gid_t)-1)
877 goto overflow;
878
879 /* Ensure the value wasn't truncated. */
880 if (sizeof(gid_t) < sizeof(long) &&
881 (unsigned long)gid != uresult)
882 goto overflow;
883 /* fallthrough */
884
885 success:
886 Py_DECREF(index);
887 *p = gid;
888 return 1;
889
890 underflow:
891 PyErr_SetString(PyExc_OverflowError,
892 "gid is less than minimum");
893 goto fail;
894
895 overflow:
896 PyErr_SetString(PyExc_OverflowError,
897 "gid is greater than maximum");
898 /* fallthrough */
899
900 fail:
901 Py_DECREF(index);
902 return 0;
903 }
904 #endif /* MS_WINDOWS */
905
906
907 #define _PyLong_FromDev PyLong_FromLongLong
908
909
910 #if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
911 static int
_Py_Dev_Converter(PyObject *obj, void *p)912 _Py_Dev_Converter(PyObject *obj, void *p)
913 {
914 *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
915 if (PyErr_Occurred())
916 return 0;
917 return 1;
918 }
919 #endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
920
921
922 #ifdef AT_FDCWD
923 /*
924 * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
925 * without the int cast, the value gets interpreted as uint (4291925331),
926 * which doesn't play nicely with all the initializer lines in this file that
927 * look like this:
928 * int dir_fd = DEFAULT_DIR_FD;
929 */
930 #define DEFAULT_DIR_FD (int)AT_FDCWD
931 #else
932 #define DEFAULT_DIR_FD (-100)
933 #endif
934
935 static int
_fd_converter(PyObject *o, int *p)936 _fd_converter(PyObject *o, int *p)
937 {
938 int overflow;
939 long long_value;
940
941 PyObject *index = _PyNumber_Index(o);
942 if (index == NULL) {
943 return 0;
944 }
945
946 assert(PyLong_Check(index));
947 long_value = PyLong_AsLongAndOverflow(index, &overflow);
948 Py_DECREF(index);
949 assert(!PyErr_Occurred());
950 if (overflow > 0 || long_value > INT_MAX) {
951 PyErr_SetString(PyExc_OverflowError,
952 "fd is greater than maximum");
953 return 0;
954 }
955 if (overflow < 0 || long_value < INT_MIN) {
956 PyErr_SetString(PyExc_OverflowError,
957 "fd is less than minimum");
958 return 0;
959 }
960
961 *p = (int)long_value;
962 return 1;
963 }
964
965 static int
dir_fd_converter(PyObject *o, void *p)966 dir_fd_converter(PyObject *o, void *p)
967 {
968 if (o == Py_None) {
969 *(int *)p = DEFAULT_DIR_FD;
970 return 1;
971 }
972 else if (PyIndex_Check(o)) {
973 return _fd_converter(o, (int *)p);
974 }
975 else {
976 PyErr_Format(PyExc_TypeError,
977 "argument should be integer or None, not %.200s",
978 _PyType_Name(Py_TYPE(o)));
979 return 0;
980 }
981 }
982
983 typedef struct {
984 PyObject *billion;
985 PyObject *DirEntryType;
986 PyObject *ScandirIteratorType;
987 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
988 PyObject *SchedParamType;
989 #endif
990 PyObject *StatResultType;
991 PyObject *StatVFSResultType;
992 PyObject *TerminalSizeType;
993 PyObject *TimesResultType;
994 PyObject *UnameResultType;
995 #if defined(HAVE_WAITID) && !defined(__APPLE__)
996 PyObject *WaitidResultType;
997 #endif
998 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
999 PyObject *struct_rusage;
1000 #endif
1001 PyObject *st_mode;
1002 } _posixstate;
1003
1004
1005 static inline _posixstate*
get_posix_state(PyObject *module)1006 get_posix_state(PyObject *module)
1007 {
1008 void *state = _PyModule_GetState(module);
1009 assert(state != NULL);
1010 return (_posixstate *)state;
1011 }
1012
1013 /*
1014 * A PyArg_ParseTuple "converter" function
1015 * that handles filesystem paths in the manner
1016 * preferred by the os module.
1017 *
1018 * path_converter accepts (Unicode) strings and their
1019 * subclasses, and bytes and their subclasses. What
1020 * it does with the argument depends on the platform:
1021 *
1022 * * On Windows, if we get a (Unicode) string we
1023 * extract the wchar_t * and return it; if we get
1024 * bytes we decode to wchar_t * and return that.
1025 *
1026 * * On all other platforms, strings are encoded
1027 * to bytes using PyUnicode_FSConverter, then we
1028 * extract the char * from the bytes object and
1029 * return that.
1030 *
1031 * path_converter also optionally accepts signed
1032 * integers (representing open file descriptors) instead
1033 * of path strings.
1034 *
1035 * Input fields:
1036 * path.nullable
1037 * If nonzero, the path is permitted to be None.
1038 * path.allow_fd
1039 * If nonzero, the path is permitted to be a file handle
1040 * (a signed int) instead of a string.
1041 * path.function_name
1042 * If non-NULL, path_converter will use that as the name
1043 * of the function in error messages.
1044 * (If path.function_name is NULL it omits the function name.)
1045 * path.argument_name
1046 * If non-NULL, path_converter will use that as the name
1047 * of the parameter in error messages.
1048 * (If path.argument_name is NULL it uses "path".)
1049 *
1050 * Output fields:
1051 * path.wide
1052 * Points to the path if it was expressed as Unicode
1053 * and was not encoded. (Only used on Windows.)
1054 * path.narrow
1055 * Points to the path if it was expressed as bytes,
1056 * or it was Unicode and was encoded to bytes. (On Windows,
1057 * is a non-zero integer if the path was expressed as bytes.
1058 * The type is deliberately incompatible to prevent misuse.)
1059 * path.fd
1060 * Contains a file descriptor if path.accept_fd was true
1061 * and the caller provided a signed integer instead of any
1062 * sort of string.
1063 *
1064 * WARNING: if your "path" parameter is optional, and is
1065 * unspecified, path_converter will never get called.
1066 * So if you set allow_fd, you *MUST* initialize path.fd = -1
1067 * yourself!
1068 * path.length
1069 * The length of the path in characters, if specified as
1070 * a string.
1071 * path.object
1072 * The original object passed in (if get a PathLike object,
1073 * the result of PyOS_FSPath() is treated as the original object).
1074 * Own a reference to the object.
1075 * path.cleanup
1076 * For internal use only. May point to a temporary object.
1077 * (Pay no attention to the man behind the curtain.)
1078 *
1079 * At most one of path.wide or path.narrow will be non-NULL.
1080 * If path was None and path.nullable was set,
1081 * or if path was an integer and path.allow_fd was set,
1082 * both path.wide and path.narrow will be NULL
1083 * and path.length will be 0.
1084 *
1085 * path_converter takes care to not write to the path_t
1086 * unless it's successful. However it must reset the
1087 * "cleanup" field each time it's called.
1088 *
1089 * Use as follows:
1090 * path_t path;
1091 * memset(&path, 0, sizeof(path));
1092 * PyArg_ParseTuple(args, "O&", path_converter, &path);
1093 * // ... use values from path ...
1094 * path_cleanup(&path);
1095 *
1096 * (Note that if PyArg_Parse fails you don't need to call
1097 * path_cleanup(). However it is safe to do so.)
1098 */
1099 typedef struct {
1100 const char *function_name;
1101 const char *argument_name;
1102 int nullable;
1103 int allow_fd;
1104 const wchar_t *wide;
1105 #ifdef MS_WINDOWS
1106 BOOL narrow;
1107 #else
1108 const char *narrow;
1109 #endif
1110 int fd;
1111 Py_ssize_t length;
1112 PyObject *object;
1113 PyObject *cleanup;
1114 } path_t;
1115
1116 #ifdef MS_WINDOWS
1117 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1118 {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
1119 #else
1120 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1121 {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
1122 #endif
1123
1124 static void
path_cleanup(path_t *path)1125 path_cleanup(path_t *path)
1126 {
1127 #if !USE_UNICODE_WCHAR_CACHE
1128 wchar_t *wide = (wchar_t *)path->wide;
1129 path->wide = NULL;
1130 PyMem_Free(wide);
1131 #endif /* USE_UNICODE_WCHAR_CACHE */
1132 Py_CLEAR(path->object);
1133 Py_CLEAR(path->cleanup);
1134 }
1135
1136 static int
path_converter(PyObject *o, void *p)1137 path_converter(PyObject *o, void *p)
1138 {
1139 path_t *path = (path_t *)p;
1140 PyObject *bytes = NULL;
1141 Py_ssize_t length = 0;
1142 int is_index, is_buffer, is_bytes, is_unicode;
1143 const char *narrow;
1144 #ifdef MS_WINDOWS
1145 PyObject *wo = NULL;
1146 wchar_t *wide = NULL;
1147 #endif
1148
1149 #define FORMAT_EXCEPTION(exc, fmt) \
1150 PyErr_Format(exc, "%s%s" fmt, \
1151 path->function_name ? path->function_name : "", \
1152 path->function_name ? ": " : "", \
1153 path->argument_name ? path->argument_name : "path")
1154
1155 /* Py_CLEANUP_SUPPORTED support */
1156 if (o == NULL) {
1157 path_cleanup(path);
1158 return 1;
1159 }
1160
1161 /* Ensure it's always safe to call path_cleanup(). */
1162 path->object = path->cleanup = NULL;
1163 /* path->object owns a reference to the original object */
1164 Py_INCREF(o);
1165
1166 if ((o == Py_None) && path->nullable) {
1167 path->wide = NULL;
1168 #ifdef MS_WINDOWS
1169 path->narrow = FALSE;
1170 #else
1171 path->narrow = NULL;
1172 #endif
1173 path->fd = -1;
1174 goto success_exit;
1175 }
1176
1177 /* Only call this here so that we don't treat the return value of
1178 os.fspath() as an fd or buffer. */
1179 is_index = path->allow_fd && PyIndex_Check(o);
1180 is_buffer = PyObject_CheckBuffer(o);
1181 is_bytes = PyBytes_Check(o);
1182 is_unicode = PyUnicode_Check(o);
1183
1184 if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
1185 /* Inline PyOS_FSPath() for better error messages. */
1186 PyObject *func, *res;
1187
1188 func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1189 if (NULL == func) {
1190 goto error_format;
1191 }
1192 res = _PyObject_CallNoArgs(func);
1193 Py_DECREF(func);
1194 if (NULL == res) {
1195 goto error_exit;
1196 }
1197 else if (PyUnicode_Check(res)) {
1198 is_unicode = 1;
1199 }
1200 else if (PyBytes_Check(res)) {
1201 is_bytes = 1;
1202 }
1203 else {
1204 PyErr_Format(PyExc_TypeError,
1205 "expected %.200s.__fspath__() to return str or bytes, "
1206 "not %.200s", _PyType_Name(Py_TYPE(o)),
1207 _PyType_Name(Py_TYPE(res)));
1208 Py_DECREF(res);
1209 goto error_exit;
1210 }
1211
1212 /* still owns a reference to the original object */
1213 Py_DECREF(o);
1214 o = res;
1215 }
1216
1217 if (is_unicode) {
1218 #ifdef MS_WINDOWS
1219 #if USE_UNICODE_WCHAR_CACHE
1220 _Py_COMP_DIAG_PUSH
1221 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1222 wide = PyUnicode_AsUnicodeAndSize(o, &length);
1223 _Py_COMP_DIAG_POP
1224 #else /* USE_UNICODE_WCHAR_CACHE */
1225 wide = PyUnicode_AsWideCharString(o, &length);
1226 #endif /* USE_UNICODE_WCHAR_CACHE */
1227 if (!wide) {
1228 goto error_exit;
1229 }
1230 if (length > 32767) {
1231 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1232 goto error_exit;
1233 }
1234 if (wcslen(wide) != length) {
1235 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1236 goto error_exit;
1237 }
1238
1239 path->wide = wide;
1240 path->narrow = FALSE;
1241 path->fd = -1;
1242 #if !USE_UNICODE_WCHAR_CACHE
1243 wide = NULL;
1244 #endif /* USE_UNICODE_WCHAR_CACHE */
1245 goto success_exit;
1246 #else
1247 if (!PyUnicode_FSConverter(o, &bytes)) {
1248 goto error_exit;
1249 }
1250 #endif
1251 }
1252 else if (is_bytes) {
1253 bytes = o;
1254 Py_INCREF(bytes);
1255 }
1256 else if (is_buffer) {
1257 /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1258 after removing support of non-bytes buffer objects. */
1259 if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
1260 "%s%s%s should be %s, not %.200s",
1261 path->function_name ? path->function_name : "",
1262 path->function_name ? ": " : "",
1263 path->argument_name ? path->argument_name : "path",
1264 path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1265 "integer or None" :
1266 path->allow_fd ? "string, bytes, os.PathLike or integer" :
1267 path->nullable ? "string, bytes, os.PathLike or None" :
1268 "string, bytes or os.PathLike",
1269 _PyType_Name(Py_TYPE(o)))) {
1270 goto error_exit;
1271 }
1272 bytes = PyBytes_FromObject(o);
1273 if (!bytes) {
1274 goto error_exit;
1275 }
1276 }
1277 else if (is_index) {
1278 if (!_fd_converter(o, &path->fd)) {
1279 goto error_exit;
1280 }
1281 path->wide = NULL;
1282 #ifdef MS_WINDOWS
1283 path->narrow = FALSE;
1284 #else
1285 path->narrow = NULL;
1286 #endif
1287 goto success_exit;
1288 }
1289 else {
1290 error_format:
1291 PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1292 path->function_name ? path->function_name : "",
1293 path->function_name ? ": " : "",
1294 path->argument_name ? path->argument_name : "path",
1295 path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1296 "integer or None" :
1297 path->allow_fd ? "string, bytes, os.PathLike or integer" :
1298 path->nullable ? "string, bytes, os.PathLike or None" :
1299 "string, bytes or os.PathLike",
1300 _PyType_Name(Py_TYPE(o)));
1301 goto error_exit;
1302 }
1303
1304 length = PyBytes_GET_SIZE(bytes);
1305 narrow = PyBytes_AS_STRING(bytes);
1306 if ((size_t)length != strlen(narrow)) {
1307 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1308 goto error_exit;
1309 }
1310
1311 #ifdef MS_WINDOWS
1312 wo = PyUnicode_DecodeFSDefaultAndSize(
1313 narrow,
1314 length
1315 );
1316 if (!wo) {
1317 goto error_exit;
1318 }
1319
1320 #if USE_UNICODE_WCHAR_CACHE
1321 _Py_COMP_DIAG_PUSH
1322 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1323 wide = PyUnicode_AsUnicodeAndSize(wo, &length);
1324 _Py_COMP_DIAG_POP
1325 #else /* USE_UNICODE_WCHAR_CACHE */
1326 wide = PyUnicode_AsWideCharString(wo, &length);
1327 Py_DECREF(wo);
1328 #endif /* USE_UNICODE_WCHAR_CACHE */
1329 if (!wide) {
1330 goto error_exit;
1331 }
1332 if (length > 32767) {
1333 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1334 goto error_exit;
1335 }
1336 if (wcslen(wide) != length) {
1337 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1338 goto error_exit;
1339 }
1340 path->wide = wide;
1341 path->narrow = TRUE;
1342 Py_DECREF(bytes);
1343 #if USE_UNICODE_WCHAR_CACHE
1344 path->cleanup = wo;
1345 #else /* USE_UNICODE_WCHAR_CACHE */
1346 wide = NULL;
1347 #endif /* USE_UNICODE_WCHAR_CACHE */
1348 #else
1349 path->wide = NULL;
1350 path->narrow = narrow;
1351 if (bytes == o) {
1352 /* Still a reference owned by path->object, don't have to
1353 worry about path->narrow is used after free. */
1354 Py_DECREF(bytes);
1355 }
1356 else {
1357 path->cleanup = bytes;
1358 }
1359 #endif
1360 path->fd = -1;
1361
1362 success_exit:
1363 path->length = length;
1364 path->object = o;
1365 return Py_CLEANUP_SUPPORTED;
1366
1367 error_exit:
1368 Py_XDECREF(o);
1369 Py_XDECREF(bytes);
1370 #ifdef MS_WINDOWS
1371 #if USE_UNICODE_WCHAR_CACHE
1372 Py_XDECREF(wo);
1373 #else /* USE_UNICODE_WCHAR_CACHE */
1374 PyMem_Free(wide);
1375 #endif /* USE_UNICODE_WCHAR_CACHE */
1376 #endif
1377 return 0;
1378 }
1379
1380 static void
argument_unavailable_error(const char *function_name, const char *argument_name)1381 argument_unavailable_error(const char *function_name, const char *argument_name)
1382 {
1383 PyErr_Format(PyExc_NotImplementedError,
1384 "%s%s%s unavailable on this platform",
1385 (function_name != NULL) ? function_name : "",
1386 (function_name != NULL) ? ": ": "",
1387 argument_name);
1388 }
1389
1390 static int
dir_fd_unavailable(PyObject *o, void *p)1391 dir_fd_unavailable(PyObject *o, void *p)
1392 {
1393 int dir_fd;
1394 if (!dir_fd_converter(o, &dir_fd))
1395 return 0;
1396 if (dir_fd != DEFAULT_DIR_FD) {
1397 argument_unavailable_error(NULL, "dir_fd");
1398 return 0;
1399 }
1400 *(int *)p = dir_fd;
1401 return 1;
1402 }
1403
1404 static int
fd_specified(const char *function_name, int fd)1405 fd_specified(const char *function_name, int fd)
1406 {
1407 if (fd == -1)
1408 return 0;
1409
1410 argument_unavailable_error(function_name, "fd");
1411 return 1;
1412 }
1413
1414 static int
follow_symlinks_specified(const char *function_name, int follow_symlinks)1415 follow_symlinks_specified(const char *function_name, int follow_symlinks)
1416 {
1417 if (follow_symlinks)
1418 return 0;
1419
1420 argument_unavailable_error(function_name, "follow_symlinks");
1421 return 1;
1422 }
1423
1424 static int
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)1425 path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1426 {
1427 if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1428 #ifndef MS_WINDOWS
1429 && !path->narrow
1430 #endif
1431 ) {
1432 PyErr_Format(PyExc_ValueError,
1433 "%s: can't specify dir_fd without matching path",
1434 function_name);
1435 return 1;
1436 }
1437 return 0;
1438 }
1439
1440 static int
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)1441 dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1442 {
1443 if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1444 PyErr_Format(PyExc_ValueError,
1445 "%s: can't specify both dir_fd and fd",
1446 function_name);
1447 return 1;
1448 }
1449 return 0;
1450 }
1451
1452 static int
fd_and_follow_symlinks_invalid(const char *function_name, int fd, int follow_symlinks)1453 fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1454 int follow_symlinks)
1455 {
1456 if ((fd > 0) && (!follow_symlinks)) {
1457 PyErr_Format(PyExc_ValueError,
1458 "%s: cannot use fd and follow_symlinks together",
1459 function_name);
1460 return 1;
1461 }
1462 return 0;
1463 }
1464
1465 static int
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd, int follow_symlinks)1466 dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1467 int follow_symlinks)
1468 {
1469 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1470 PyErr_Format(PyExc_ValueError,
1471 "%s: cannot use dir_fd and follow_symlinks together",
1472 function_name);
1473 return 1;
1474 }
1475 return 0;
1476 }
1477
1478 #ifdef MS_WINDOWS
1479 typedef long long Py_off_t;
1480 #else
1481 typedef off_t Py_off_t;
1482 #endif
1483
1484 static int
Py_off_t_converter(PyObject *arg, void *addr)1485 Py_off_t_converter(PyObject *arg, void *addr)
1486 {
1487 #ifdef HAVE_LARGEFILE_SUPPORT
1488 *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1489 #else
1490 *((Py_off_t *)addr) = PyLong_AsLong(arg);
1491 #endif
1492 if (PyErr_Occurred())
1493 return 0;
1494 return 1;
1495 }
1496
1497 static PyObject *
PyLong_FromPy_off_t(Py_off_t offset)1498 PyLong_FromPy_off_t(Py_off_t offset)
1499 {
1500 #ifdef HAVE_LARGEFILE_SUPPORT
1501 return PyLong_FromLongLong(offset);
1502 #else
1503 return PyLong_FromLong(offset);
1504 #endif
1505 }
1506
1507 #ifdef HAVE_SIGSET_T
1508 /* Convert an iterable of integers to a sigset.
1509 Return 1 on success, return 0 and raise an exception on error. */
1510 int
_Py_Sigset_Converter(PyObject *obj, void *addr)1511 _Py_Sigset_Converter(PyObject *obj, void *addr)
1512 {
1513 sigset_t *mask = (sigset_t *)addr;
1514 PyObject *iterator, *item;
1515 long signum;
1516 int overflow;
1517
1518 // The extra parens suppress the unreachable-code warning with clang on MacOS
1519 if (sigemptyset(mask) < (0)) {
1520 /* Probably only if mask == NULL. */
1521 PyErr_SetFromErrno(PyExc_OSError);
1522 return 0;
1523 }
1524
1525 iterator = PyObject_GetIter(obj);
1526 if (iterator == NULL) {
1527 return 0;
1528 }
1529
1530 while ((item = PyIter_Next(iterator)) != NULL) {
1531 signum = PyLong_AsLongAndOverflow(item, &overflow);
1532 Py_DECREF(item);
1533 if (signum <= 0 || signum >= Py_NSIG) {
1534 if (overflow || signum != -1 || !PyErr_Occurred()) {
1535 PyErr_Format(PyExc_ValueError,
1536 "signal number %ld out of range [1; %i]",
1537 signum, Py_NSIG - 1);
1538 }
1539 goto error;
1540 }
1541 if (sigaddset(mask, (int)signum)) {
1542 if (errno != EINVAL) {
1543 /* Probably impossible */
1544 PyErr_SetFromErrno(PyExc_OSError);
1545 goto error;
1546 }
1547 /* For backwards compatibility, allow idioms such as
1548 * `range(1, NSIG)` but warn about invalid signal numbers
1549 */
1550 const char msg[] =
1551 "invalid signal number %ld, please use valid_signals()";
1552 if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1553 goto error;
1554 }
1555 }
1556 }
1557 if (!PyErr_Occurred()) {
1558 Py_DECREF(iterator);
1559 return 1;
1560 }
1561
1562 error:
1563 Py_DECREF(iterator);
1564 return 0;
1565 }
1566 #endif /* HAVE_SIGSET_T */
1567
1568 #ifdef MS_WINDOWS
1569
1570 static int
win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)1571 win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1572 {
1573 char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1574 _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1575 DWORD n_bytes_returned;
1576
1577 if (0 == DeviceIoControl(
1578 reparse_point_handle,
1579 FSCTL_GET_REPARSE_POINT,
1580 NULL, 0, /* in buffer */
1581 target_buffer, sizeof(target_buffer),
1582 &n_bytes_returned,
1583 NULL)) /* we're not using OVERLAPPED_IO */
1584 return FALSE;
1585
1586 if (reparse_tag)
1587 *reparse_tag = rdb->ReparseTag;
1588
1589 return TRUE;
1590 }
1591
1592 #endif /* MS_WINDOWS */
1593
1594 /* Return a dictionary corresponding to the POSIX environment table */
1595 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1596 /* On Darwin/MacOSX a shared library or framework has no access to
1597 ** environ directly, we must obtain it with _NSGetEnviron(). See also
1598 ** man environ(7).
1599 */
1600 #include <crt_externs.h>
1601 #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1602 extern char **environ;
1603 #endif /* !_MSC_VER */
1604
1605 static PyObject *
convertenviron(void)1606 convertenviron(void)
1607 {
1608 PyObject *d;
1609 #ifdef MS_WINDOWS
1610 wchar_t **e;
1611 #else
1612 char **e;
1613 #endif
1614
1615 d = PyDict_New();
1616 if (d == NULL)
1617 return NULL;
1618 #ifdef MS_WINDOWS
1619 /* _wenviron must be initialized in this way if the program is started
1620 through main() instead of wmain(). */
1621 _wgetenv(L"");
1622 e = _wenviron;
1623 #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1624 /* environ is not accessible as an extern in a shared object on OSX; use
1625 _NSGetEnviron to resolve it. The value changes if you add environment
1626 variables between calls to Py_Initialize, so don't cache the value. */
1627 e = *_NSGetEnviron();
1628 #else
1629 e = environ;
1630 #endif
1631 if (e == NULL)
1632 return d;
1633 for (; *e != NULL; e++) {
1634 PyObject *k;
1635 PyObject *v;
1636 #ifdef MS_WINDOWS
1637 const wchar_t *p = wcschr(*e, L'=');
1638 #else
1639 const char *p = strchr(*e, '=');
1640 #endif
1641 if (p == NULL)
1642 continue;
1643 #ifdef MS_WINDOWS
1644 k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1645 #else
1646 k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1647 #endif
1648 if (k == NULL) {
1649 Py_DECREF(d);
1650 return NULL;
1651 }
1652 #ifdef MS_WINDOWS
1653 v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1654 #else
1655 v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1656 #endif
1657 if (v == NULL) {
1658 Py_DECREF(k);
1659 Py_DECREF(d);
1660 return NULL;
1661 }
1662 if (PyDict_SetDefault(d, k, v) == NULL) {
1663 Py_DECREF(v);
1664 Py_DECREF(k);
1665 Py_DECREF(d);
1666 return NULL;
1667 }
1668 Py_DECREF(k);
1669 Py_DECREF(v);
1670 }
1671 return d;
1672 }
1673
1674 /* Set a POSIX-specific error from errno, and return NULL */
1675
1676 static PyObject *
posix_error(void)1677 posix_error(void)
1678 {
1679 return PyErr_SetFromErrno(PyExc_OSError);
1680 }
1681
1682 #ifdef MS_WINDOWS
1683 static PyObject *
win32_error(const char* function, const char* filename)1684 win32_error(const char* function, const char* filename)
1685 {
1686 /* XXX We should pass the function name along in the future.
1687 (winreg.c also wants to pass the function name.)
1688 This would however require an additional param to the
1689 Windows error object, which is non-trivial.
1690 */
1691 errno = GetLastError();
1692 if (filename)
1693 return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1694 else
1695 return PyErr_SetFromWindowsErr(errno);
1696 }
1697
1698 static PyObject *
win32_error_object_err(const char* function, PyObject* filename, DWORD err)1699 win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1700 {
1701 /* XXX - see win32_error for comments on 'function' */
1702 if (filename)
1703 return PyErr_SetExcFromWindowsErrWithFilenameObject(
1704 PyExc_OSError,
1705 err,
1706 filename);
1707 else
1708 return PyErr_SetFromWindowsErr(err);
1709 }
1710
1711 static PyObject *
win32_error_object(const char* function, PyObject* filename)1712 win32_error_object(const char* function, PyObject* filename)
1713 {
1714 errno = GetLastError();
1715 return win32_error_object_err(function, filename, errno);
1716 }
1717
1718 #endif /* MS_WINDOWS */
1719
1720 static PyObject *
posix_path_object_error(PyObject *path)1721 posix_path_object_error(PyObject *path)
1722 {
1723 return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1724 }
1725
1726 static PyObject *
path_object_error(PyObject *path)1727 path_object_error(PyObject *path)
1728 {
1729 #ifdef MS_WINDOWS
1730 return PyErr_SetExcFromWindowsErrWithFilenameObject(
1731 PyExc_OSError, 0, path);
1732 #else
1733 return posix_path_object_error(path);
1734 #endif
1735 }
1736
1737 static PyObject *
path_object_error2(PyObject *path, PyObject *path2)1738 path_object_error2(PyObject *path, PyObject *path2)
1739 {
1740 #ifdef MS_WINDOWS
1741 return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1742 PyExc_OSError, 0, path, path2);
1743 #else
1744 return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1745 #endif
1746 }
1747
1748 static PyObject *
path_error(path_t *path)1749 path_error(path_t *path)
1750 {
1751 return path_object_error(path->object);
1752 }
1753
1754 static PyObject *
posix_path_error(path_t *path)1755 posix_path_error(path_t *path)
1756 {
1757 return posix_path_object_error(path->object);
1758 }
1759
1760 static PyObject *
path_error2(path_t *path, path_t *path2)1761 path_error2(path_t *path, path_t *path2)
1762 {
1763 return path_object_error2(path->object, path2->object);
1764 }
1765
1766
1767 /* POSIX generic methods */
1768
1769 static PyObject *
posix_fildes_fd(int fd, int (*func)(int))1770 posix_fildes_fd(int fd, int (*func)(int))
1771 {
1772 int res;
1773 int async_err = 0;
1774
1775 do {
1776 Py_BEGIN_ALLOW_THREADS
1777 _Py_BEGIN_SUPPRESS_IPH
1778 res = (*func)(fd);
1779 _Py_END_SUPPRESS_IPH
1780 Py_END_ALLOW_THREADS
1781 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1782 if (res != 0)
1783 return (!async_err) ? posix_error() : NULL;
1784 Py_RETURN_NONE;
1785 }
1786
1787
1788 #ifdef MS_WINDOWS
1789 /* This is a reimplementation of the C library's chdir function,
1790 but one that produces Win32 errors instead of DOS error codes.
1791 chdir is essentially a wrapper around SetCurrentDirectory; however,
1792 it also needs to set "magic" environment variables indicating
1793 the per-drive current directory, which are of the form =<drive>: */
1794 static BOOL __stdcall
win32_wchdir(LPCWSTR path)1795 win32_wchdir(LPCWSTR path)
1796 {
1797 wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1798 int result;
1799 wchar_t env[4] = L"=x:";
1800
1801 if(!SetCurrentDirectoryW(path))
1802 return FALSE;
1803 result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1804 if (!result)
1805 return FALSE;
1806 if (result > Py_ARRAY_LENGTH(path_buf)) {
1807 new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1808 if (!new_path) {
1809 SetLastError(ERROR_OUTOFMEMORY);
1810 return FALSE;
1811 }
1812 result = GetCurrentDirectoryW(result, new_path);
1813 if (!result) {
1814 PyMem_RawFree(new_path);
1815 return FALSE;
1816 }
1817 }
1818 int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1819 wcsncmp(new_path, L"//", 2) == 0);
1820 if (!is_unc_like_path) {
1821 env[1] = new_path[0];
1822 result = SetEnvironmentVariableW(env, new_path);
1823 }
1824 if (new_path != path_buf)
1825 PyMem_RawFree(new_path);
1826 return result ? TRUE : FALSE;
1827 }
1828 #endif
1829
1830 #ifdef MS_WINDOWS
1831 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1832 - time stamps are restricted to second resolution
1833 - file modification times suffer from forth-and-back conversions between
1834 UTC and local time
1835 Therefore, we implement our own stat, based on the Win32 API directly.
1836 */
1837 #define HAVE_STAT_NSEC 1
1838 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1839 #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1840
1841 static void
find_data_to_file_info(WIN32_FIND_DATAW *pFileData, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)1842 find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1843 BY_HANDLE_FILE_INFORMATION *info,
1844 ULONG *reparse_tag)
1845 {
1846 memset(info, 0, sizeof(*info));
1847 info->dwFileAttributes = pFileData->dwFileAttributes;
1848 info->ftCreationTime = pFileData->ftCreationTime;
1849 info->ftLastAccessTime = pFileData->ftLastAccessTime;
1850 info->ftLastWriteTime = pFileData->ftLastWriteTime;
1851 info->nFileSizeHigh = pFileData->nFileSizeHigh;
1852 info->nFileSizeLow = pFileData->nFileSizeLow;
1853 /* info->nNumberOfLinks = 1; */
1854 if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1855 *reparse_tag = pFileData->dwReserved0;
1856 else
1857 *reparse_tag = 0;
1858 }
1859
1860 static BOOL
attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)1861 attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1862 {
1863 HANDLE hFindFile;
1864 WIN32_FIND_DATAW FileData;
1865 LPCWSTR filename = pszFile;
1866 size_t n = wcslen(pszFile);
1867 if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
1868 // cannot use PyMem_Malloc here because we do not hold the GIL
1869 filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
1870 wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
1871 while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
1872 ((LPWSTR)filename)[n] = L'\0';
1873 }
1874 if (!n || (n == 1 && filename[1] == L':')) {
1875 // Nothing left to query
1876 free((void *)filename);
1877 return FALSE;
1878 }
1879 }
1880 hFindFile = FindFirstFileW(filename, &FileData);
1881 if (pszFile != filename) {
1882 free((void *)filename);
1883 }
1884 if (hFindFile == INVALID_HANDLE_VALUE) {
1885 return FALSE;
1886 }
1887 FindClose(hFindFile);
1888 find_data_to_file_info(&FileData, info, reparse_tag);
1889 return TRUE;
1890 }
1891
1892 static int
win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)1893 win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1894 BOOL traverse)
1895 {
1896 HANDLE hFile;
1897 BY_HANDLE_FILE_INFORMATION fileInfo;
1898 FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1899 DWORD fileType, error;
1900 BOOL isUnhandledTag = FALSE;
1901 int retval = 0;
1902
1903 DWORD access = FILE_READ_ATTRIBUTES;
1904 DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1905 if (!traverse) {
1906 flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1907 }
1908
1909 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1910 if (hFile == INVALID_HANDLE_VALUE) {
1911 /* Either the path doesn't exist, or the caller lacks access. */
1912 error = GetLastError();
1913 switch (error) {
1914 case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */
1915 case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1916 /* Try reading the parent directory. */
1917 if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1918 /* Cannot read the parent directory. */
1919 switch (GetLastError()) {
1920 case ERROR_FILE_NOT_FOUND: /* File cannot be found */
1921 case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
1922 case ERROR_NOT_READY: /* Drive exists but unavailable */
1923 case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
1924 break;
1925 /* Restore the error from CreateFileW(). */
1926 default:
1927 SetLastError(error);
1928 }
1929
1930 return -1;
1931 }
1932 if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1933 if (traverse ||
1934 !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1935 /* The stat call has to traverse but cannot, so fail. */
1936 SetLastError(error);
1937 return -1;
1938 }
1939 }
1940 break;
1941
1942 case ERROR_INVALID_PARAMETER:
1943 /* \\.\con requires read or write access. */
1944 hFile = CreateFileW(path, access | GENERIC_READ,
1945 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1946 OPEN_EXISTING, flags, NULL);
1947 if (hFile == INVALID_HANDLE_VALUE) {
1948 SetLastError(error);
1949 return -1;
1950 }
1951 break;
1952
1953 case ERROR_CANT_ACCESS_FILE:
1954 /* bpo37834: open unhandled reparse points if traverse fails. */
1955 if (traverse) {
1956 traverse = FALSE;
1957 isUnhandledTag = TRUE;
1958 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1959 flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1960 }
1961 if (hFile == INVALID_HANDLE_VALUE) {
1962 SetLastError(error);
1963 return -1;
1964 }
1965 break;
1966
1967 default:
1968 return -1;
1969 }
1970 }
1971
1972 if (hFile != INVALID_HANDLE_VALUE) {
1973 /* Handle types other than files on disk. */
1974 fileType = GetFileType(hFile);
1975 if (fileType != FILE_TYPE_DISK) {
1976 if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1977 retval = -1;
1978 goto cleanup;
1979 }
1980 DWORD fileAttributes = GetFileAttributesW(path);
1981 memset(result, 0, sizeof(*result));
1982 if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1983 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1984 /* \\.\pipe\ or \\.\mailslot\ */
1985 result->st_mode = _S_IFDIR;
1986 } else if (fileType == FILE_TYPE_CHAR) {
1987 /* \\.\nul */
1988 result->st_mode = _S_IFCHR;
1989 } else if (fileType == FILE_TYPE_PIPE) {
1990 /* \\.\pipe\spam */
1991 result->st_mode = _S_IFIFO;
1992 }
1993 /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1994 goto cleanup;
1995 }
1996
1997 /* Query the reparse tag, and traverse a non-link. */
1998 if (!traverse) {
1999 if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
2000 &tagInfo, sizeof(tagInfo))) {
2001 /* Allow devices that do not support FileAttributeTagInfo. */
2002 switch (GetLastError()) {
2003 case ERROR_INVALID_PARAMETER:
2004 case ERROR_INVALID_FUNCTION:
2005 case ERROR_NOT_SUPPORTED:
2006 tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2007 tagInfo.ReparseTag = 0;
2008 break;
2009 default:
2010 retval = -1;
2011 goto cleanup;
2012 }
2013 } else if (tagInfo.FileAttributes &
2014 FILE_ATTRIBUTE_REPARSE_POINT) {
2015 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2016 if (isUnhandledTag) {
2017 /* Traversing previously failed for either this link
2018 or its target. */
2019 SetLastError(ERROR_CANT_ACCESS_FILE);
2020 retval = -1;
2021 goto cleanup;
2022 }
2023 /* Traverse a non-link, but not if traversing already failed
2024 for an unhandled tag. */
2025 } else if (!isUnhandledTag) {
2026 CloseHandle(hFile);
2027 return win32_xstat_impl(path, result, TRUE);
2028 }
2029 }
2030 }
2031
2032 if (!GetFileInformationByHandle(hFile, &fileInfo)) {
2033 switch (GetLastError()) {
2034 case ERROR_INVALID_PARAMETER:
2035 case ERROR_INVALID_FUNCTION:
2036 case ERROR_NOT_SUPPORTED:
2037 /* Volumes and physical disks are block devices, e.g.
2038 \\.\C: and \\.\PhysicalDrive0. */
2039 memset(result, 0, sizeof(*result));
2040 result->st_mode = 0x6000; /* S_IFBLK */
2041 goto cleanup;
2042 }
2043 retval = -1;
2044 goto cleanup;
2045 }
2046 }
2047
2048 _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
2049
2050 if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
2051 /* Fix the file execute permissions. This hack sets S_IEXEC if
2052 the filename has an extension that is commonly used by files
2053 that CreateProcessW can execute. A real implementation calls
2054 GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2055 AccessCheck to check for generic read, write, and execute
2056 access. */
2057 const wchar_t *fileExtension = wcsrchr(path, '.');
2058 if (fileExtension) {
2059 if (_wcsicmp(fileExtension, L".exe") == 0 ||
2060 _wcsicmp(fileExtension, L".bat") == 0 ||
2061 _wcsicmp(fileExtension, L".cmd") == 0 ||
2062 _wcsicmp(fileExtension, L".com") == 0) {
2063 result->st_mode |= 0111;
2064 }
2065 }
2066 }
2067
2068 cleanup:
2069 if (hFile != INVALID_HANDLE_VALUE) {
2070 /* Preserve last error if we are failing */
2071 error = retval ? GetLastError() : 0;
2072 if (!CloseHandle(hFile)) {
2073 retval = -1;
2074 } else if (retval) {
2075 /* Restore last error */
2076 SetLastError(error);
2077 }
2078 }
2079
2080 return retval;
2081 }
2082
2083 static int
win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)2084 win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2085 {
2086 /* Protocol violation: we explicitly clear errno, instead of
2087 setting it to a POSIX error. Callers should use GetLastError. */
2088 int code = win32_xstat_impl(path, result, traverse);
2089 errno = 0;
2090 return code;
2091 }
2092 /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2093
2094 In Posix, stat automatically traverses symlinks and returns the stat
2095 structure for the target. In Windows, the equivalent GetFileAttributes by
2096 default does not traverse symlinks and instead returns attributes for
2097 the symlink.
2098
2099 Instead, we will open the file (which *does* traverse symlinks by default)
2100 and GetFileInformationByHandle(). */
2101
2102 static int
win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)2103 win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2104 {
2105 return win32_xstat(path, result, FALSE);
2106 }
2107
2108 static int
win32_stat(const wchar_t* path, struct _Py_stat_struct *result)2109 win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2110 {
2111 return win32_xstat(path, result, TRUE);
2112 }
2113
2114 #endif /* MS_WINDOWS */
2115
2116 PyDoc_STRVAR(stat_result__doc__,
2117 "stat_result: Result from stat, fstat, or lstat.\n\n\
2118 This object may be accessed either as a tuple of\n\
2119 (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2120 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2121 \n\
2122 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2123 or st_flags, they are available as attributes only.\n\
2124 \n\
2125 See os.stat for more information.");
2126
2127 static PyStructSequence_Field stat_result_fields[] = {
2128 {"st_mode", "protection bits"},
2129 {"st_ino", "inode"},
2130 {"st_dev", "device"},
2131 {"st_nlink", "number of hard links"},
2132 {"st_uid", "user ID of owner"},
2133 {"st_gid", "group ID of owner"},
2134 {"st_size", "total size, in bytes"},
2135 /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2136 {NULL, "integer time of last access"},
2137 {NULL, "integer time of last modification"},
2138 {NULL, "integer time of last change"},
2139 {"st_atime", "time of last access"},
2140 {"st_mtime", "time of last modification"},
2141 {"st_ctime", "time of last change"},
2142 {"st_atime_ns", "time of last access in nanoseconds"},
2143 {"st_mtime_ns", "time of last modification in nanoseconds"},
2144 {"st_ctime_ns", "time of last change in nanoseconds"},
2145 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2146 {"st_blksize", "blocksize for filesystem I/O"},
2147 #endif
2148 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2149 {"st_blocks", "number of blocks allocated"},
2150 #endif
2151 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2152 {"st_rdev", "device type (if inode device)"},
2153 #endif
2154 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2155 {"st_flags", "user defined flags for file"},
2156 #endif
2157 #ifdef HAVE_STRUCT_STAT_ST_GEN
2158 {"st_gen", "generation number"},
2159 #endif
2160 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2161 {"st_birthtime", "time of creation"},
2162 #endif
2163 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2164 {"st_file_attributes", "Windows file attribute bits"},
2165 #endif
2166 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2167 {"st_fstype", "Type of filesystem"},
2168 #endif
2169 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2170 {"st_reparse_tag", "Windows reparse tag"},
2171 #endif
2172 {0}
2173 };
2174
2175 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2176 #define ST_BLKSIZE_IDX 16
2177 #else
2178 #define ST_BLKSIZE_IDX 15
2179 #endif
2180
2181 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2182 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2183 #else
2184 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2185 #endif
2186
2187 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2188 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2189 #else
2190 #define ST_RDEV_IDX ST_BLOCKS_IDX
2191 #endif
2192
2193 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2194 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2195 #else
2196 #define ST_FLAGS_IDX ST_RDEV_IDX
2197 #endif
2198
2199 #ifdef HAVE_STRUCT_STAT_ST_GEN
2200 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
2201 #else
2202 #define ST_GEN_IDX ST_FLAGS_IDX
2203 #endif
2204
2205 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2206 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2207 #else
2208 #define ST_BIRTHTIME_IDX ST_GEN_IDX
2209 #endif
2210
2211 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2212 #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
2213 #else
2214 #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
2215 #endif
2216
2217 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2218 #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2219 #else
2220 #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2221 #endif
2222
2223 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2224 #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2225 #else
2226 #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2227 #endif
2228
2229 static PyStructSequence_Desc stat_result_desc = {
2230 "stat_result", /* name */
2231 stat_result__doc__, /* doc */
2232 stat_result_fields,
2233 10
2234 };
2235
2236 PyDoc_STRVAR(statvfs_result__doc__,
2237 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
2238 This object may be accessed either as a tuple of\n\
2239 (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2240 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2241 \n\
2242 See os.statvfs for more information.");
2243
2244 static PyStructSequence_Field statvfs_result_fields[] = {
2245 {"f_bsize", },
2246 {"f_frsize", },
2247 {"f_blocks", },
2248 {"f_bfree", },
2249 {"f_bavail", },
2250 {"f_files", },
2251 {"f_ffree", },
2252 {"f_favail", },
2253 {"f_flag", },
2254 {"f_namemax",},
2255 {"f_fsid", },
2256 {0}
2257 };
2258
2259 static PyStructSequence_Desc statvfs_result_desc = {
2260 "statvfs_result", /* name */
2261 statvfs_result__doc__, /* doc */
2262 statvfs_result_fields,
2263 10
2264 };
2265
2266 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2267 PyDoc_STRVAR(waitid_result__doc__,
2268 "waitid_result: Result from waitid.\n\n\
2269 This object may be accessed either as a tuple of\n\
2270 (si_pid, si_uid, si_signo, si_status, si_code),\n\
2271 or via the attributes si_pid, si_uid, and so on.\n\
2272 \n\
2273 See os.waitid for more information.");
2274
2275 static PyStructSequence_Field waitid_result_fields[] = {
2276 {"si_pid", },
2277 {"si_uid", },
2278 {"si_signo", },
2279 {"si_status", },
2280 {"si_code", },
2281 {0}
2282 };
2283
2284 static PyStructSequence_Desc waitid_result_desc = {
2285 "waitid_result", /* name */
2286 waitid_result__doc__, /* doc */
2287 waitid_result_fields,
2288 5
2289 };
2290 #endif
2291 static newfunc structseq_new;
2292
2293 static PyObject *
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)2294 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2295 {
2296 PyStructSequence *result;
2297 int i;
2298
2299 result = (PyStructSequence*)structseq_new(type, args, kwds);
2300 if (!result)
2301 return NULL;
2302 /* If we have been initialized from a tuple,
2303 st_?time might be set to None. Initialize it
2304 from the int slots. */
2305 for (i = 7; i <= 9; i++) {
2306 if (result->ob_item[i+3] == Py_None) {
2307 Py_DECREF(Py_None);
2308 Py_INCREF(result->ob_item[i]);
2309 result->ob_item[i+3] = result->ob_item[i];
2310 }
2311 }
2312 return (PyObject*)result;
2313 }
2314
2315 static int
_posix_clear(PyObject *module)2316 _posix_clear(PyObject *module)
2317 {
2318 _posixstate *state = get_posix_state(module);
2319 Py_CLEAR(state->billion);
2320 Py_CLEAR(state->DirEntryType);
2321 Py_CLEAR(state->ScandirIteratorType);
2322 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2323 Py_CLEAR(state->SchedParamType);
2324 #endif
2325 Py_CLEAR(state->StatResultType);
2326 Py_CLEAR(state->StatVFSResultType);
2327 Py_CLEAR(state->TerminalSizeType);
2328 Py_CLEAR(state->TimesResultType);
2329 Py_CLEAR(state->UnameResultType);
2330 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2331 Py_CLEAR(state->WaitidResultType);
2332 #endif
2333 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2334 Py_CLEAR(state->struct_rusage);
2335 #endif
2336 Py_CLEAR(state->st_mode);
2337 return 0;
2338 }
2339
2340 static int
_posix_traverse(PyObject *module, visitproc visit, void *arg)2341 _posix_traverse(PyObject *module, visitproc visit, void *arg)
2342 {
2343 _posixstate *state = get_posix_state(module);
2344 Py_VISIT(state->billion);
2345 Py_VISIT(state->DirEntryType);
2346 Py_VISIT(state->ScandirIteratorType);
2347 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2348 Py_VISIT(state->SchedParamType);
2349 #endif
2350 Py_VISIT(state->StatResultType);
2351 Py_VISIT(state->StatVFSResultType);
2352 Py_VISIT(state->TerminalSizeType);
2353 Py_VISIT(state->TimesResultType);
2354 Py_VISIT(state->UnameResultType);
2355 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2356 Py_VISIT(state->WaitidResultType);
2357 #endif
2358 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2359 Py_VISIT(state->struct_rusage);
2360 #endif
2361 Py_VISIT(state->st_mode);
2362 return 0;
2363 }
2364
2365 static void
_posix_free(void *module)2366 _posix_free(void *module)
2367 {
2368 _posix_clear((PyObject *)module);
2369 }
2370
2371 static void
fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)2372 fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)
2373 {
2374 PyObject *s = _PyLong_FromTime_t(sec);
2375 PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2376 PyObject *s_in_ns = NULL;
2377 PyObject *ns_total = NULL;
2378 PyObject *float_s = NULL;
2379
2380 if (!(s && ns_fractional))
2381 goto exit;
2382
2383 s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2384 if (!s_in_ns)
2385 goto exit;
2386
2387 ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2388 if (!ns_total)
2389 goto exit;
2390
2391 float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2392 if (!float_s) {
2393 goto exit;
2394 }
2395
2396 PyStructSequence_SET_ITEM(v, index, s);
2397 PyStructSequence_SET_ITEM(v, index+3, float_s);
2398 PyStructSequence_SET_ITEM(v, index+6, ns_total);
2399 s = NULL;
2400 float_s = NULL;
2401 ns_total = NULL;
2402 exit:
2403 Py_XDECREF(s);
2404 Py_XDECREF(ns_fractional);
2405 Py_XDECREF(s_in_ns);
2406 Py_XDECREF(ns_total);
2407 Py_XDECREF(float_s);
2408 }
2409
2410 /* pack a system stat C structure into the Python stat tuple
2411 (used by posix_stat() and posix_fstat()) */
2412 static PyObject*
_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)2413 _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2414 {
2415 unsigned long ansec, mnsec, cnsec;
2416 PyObject *StatResultType = get_posix_state(module)->StatResultType;
2417 PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2418 if (v == NULL)
2419 return NULL;
2420
2421 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2422 static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2423 "stat.st_ino is larger than unsigned long long");
2424 PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2425 #ifdef MS_WINDOWS
2426 PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
2427 #else
2428 PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2429 #endif
2430 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2431 #if defined(MS_WINDOWS)
2432 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2433 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2434 #else
2435 PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2436 PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2437 #endif
2438 static_assert(sizeof(long long) >= sizeof(st->st_size),
2439 "stat.st_size is larger than long long");
2440 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2441
2442 #if defined(HAVE_STAT_TV_NSEC)
2443 ansec = st->st_atim.tv_nsec;
2444 mnsec = st->st_mtim.tv_nsec;
2445 cnsec = st->st_ctim.tv_nsec;
2446 #elif defined(HAVE_STAT_TV_NSEC2)
2447 ansec = st->st_atimespec.tv_nsec;
2448 mnsec = st->st_mtimespec.tv_nsec;
2449 cnsec = st->st_ctimespec.tv_nsec;
2450 #elif defined(HAVE_STAT_NSEC)
2451 ansec = st->st_atime_nsec;
2452 mnsec = st->st_mtime_nsec;
2453 cnsec = st->st_ctime_nsec;
2454 #else
2455 ansec = mnsec = cnsec = 0;
2456 #endif
2457 fill_time(module, v, 7, st->st_atime, ansec);
2458 fill_time(module, v, 8, st->st_mtime, mnsec);
2459 fill_time(module, v, 9, st->st_ctime, cnsec);
2460
2461 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2462 PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2463 PyLong_FromLong((long)st->st_blksize));
2464 #endif
2465 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2466 PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2467 PyLong_FromLong((long)st->st_blocks));
2468 #endif
2469 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2470 PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2471 PyLong_FromLong((long)st->st_rdev));
2472 #endif
2473 #ifdef HAVE_STRUCT_STAT_ST_GEN
2474 PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2475 PyLong_FromLong((long)st->st_gen));
2476 #endif
2477 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2478 {
2479 PyObject *val;
2480 unsigned long bsec,bnsec;
2481 bsec = (long)st->st_birthtime;
2482 #ifdef HAVE_STAT_TV_NSEC2
2483 bnsec = st->st_birthtimespec.tv_nsec;
2484 #else
2485 bnsec = 0;
2486 #endif
2487 val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2488 PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2489 val);
2490 }
2491 #endif
2492 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2493 PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2494 PyLong_FromLong((long)st->st_flags));
2495 #endif
2496 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2497 PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2498 PyLong_FromUnsignedLong(st->st_file_attributes));
2499 #endif
2500 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2501 PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2502 PyUnicode_FromString(st->st_fstype));
2503 #endif
2504 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2505 PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2506 PyLong_FromUnsignedLong(st->st_reparse_tag));
2507 #endif
2508
2509 if (PyErr_Occurred()) {
2510 Py_DECREF(v);
2511 return NULL;
2512 }
2513
2514 return v;
2515 }
2516
2517 /* POSIX methods */
2518
2519
2520 static PyObject *
posix_do_stat(PyObject *module, const char *function_name, path_t *path, int dir_fd, int follow_symlinks)2521 posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2522 int dir_fd, int follow_symlinks)
2523 {
2524 STRUCT_STAT st;
2525 int result;
2526
2527 #ifdef HAVE_FSTATAT
2528 int fstatat_unavailable = 0;
2529 #endif
2530
2531 #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2532 if (follow_symlinks_specified(function_name, follow_symlinks))
2533 return NULL;
2534 #endif
2535
2536 if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2537 dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2538 fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2539 return NULL;
2540
2541 Py_BEGIN_ALLOW_THREADS
2542 if (path->fd != -1)
2543 result = FSTAT(path->fd, &st);
2544 #ifdef MS_WINDOWS
2545 else if (follow_symlinks)
2546 result = win32_stat(path->wide, &st);
2547 else
2548 result = win32_lstat(path->wide, &st);
2549 #else
2550 else
2551 #if defined(HAVE_LSTAT)
2552 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2553 result = LSTAT(path->narrow, &st);
2554 else
2555 #endif /* HAVE_LSTAT */
2556 #ifdef HAVE_FSTATAT
2557 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2558 if (HAVE_FSTATAT_RUNTIME) {
2559 result = fstatat(dir_fd, path->narrow, &st,
2560 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2561
2562 } else {
2563 fstatat_unavailable = 1;
2564 }
2565 } else
2566 #endif /* HAVE_FSTATAT */
2567 result = STAT(path->narrow, &st);
2568 #endif /* MS_WINDOWS */
2569 Py_END_ALLOW_THREADS
2570
2571 #ifdef HAVE_FSTATAT
2572 if (fstatat_unavailable) {
2573 argument_unavailable_error("stat", "dir_fd");
2574 return NULL;
2575 }
2576 #endif
2577
2578 if (result != 0) {
2579 return path_error(path);
2580 }
2581
2582 return _pystat_fromstructstat(module, &st);
2583 }
2584
2585 /*[python input]
2586
2587 for s in """
2588
2589 FACCESSAT
2590 FCHMODAT
2591 FCHOWNAT
2592 FSTATAT
2593 LINKAT
2594 MKDIRAT
2595 MKFIFOAT
2596 MKNODAT
2597 OPENAT
2598 READLINKAT
2599 SYMLINKAT
2600 UNLINKAT
2601
2602 """.strip().split():
2603 s = s.strip()
2604 print("""
2605 #ifdef HAVE_{s}
2606 #define {s}_DIR_FD_CONVERTER dir_fd_converter
2607 #else
2608 #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2609 #endif
2610 """.rstrip().format(s=s))
2611
2612 for s in """
2613
2614 FCHDIR
2615 FCHMOD
2616 FCHOWN
2617 FDOPENDIR
2618 FEXECVE
2619 FPATHCONF
2620 FSTATVFS
2621 FTRUNCATE
2622
2623 """.strip().split():
2624 s = s.strip()
2625 print("""
2626 #ifdef HAVE_{s}
2627 #define PATH_HAVE_{s} 1
2628 #else
2629 #define PATH_HAVE_{s} 0
2630 #endif
2631
2632 """.rstrip().format(s=s))
2633 [python start generated code]*/
2634
2635 #ifdef HAVE_FACCESSAT
2636 #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2637 #else
2638 #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2639 #endif
2640
2641 #ifdef HAVE_FCHMODAT
2642 #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2643 #else
2644 #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2645 #endif
2646
2647 #ifdef HAVE_FCHOWNAT
2648 #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2649 #else
2650 #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2651 #endif
2652
2653 #ifdef HAVE_FSTATAT
2654 #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2655 #else
2656 #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2657 #endif
2658
2659 #ifdef HAVE_LINKAT
2660 #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2661 #else
2662 #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2663 #endif
2664
2665 #ifdef HAVE_MKDIRAT
2666 #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2667 #else
2668 #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2669 #endif
2670
2671 #ifdef HAVE_MKFIFOAT
2672 #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2673 #else
2674 #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2675 #endif
2676
2677 #ifdef HAVE_MKNODAT
2678 #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2679 #else
2680 #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2681 #endif
2682
2683 #ifdef HAVE_OPENAT
2684 #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2685 #else
2686 #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2687 #endif
2688
2689 #ifdef HAVE_READLINKAT
2690 #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2691 #else
2692 #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2693 #endif
2694
2695 #ifdef HAVE_SYMLINKAT
2696 #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2697 #else
2698 #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2699 #endif
2700
2701 #ifdef HAVE_UNLINKAT
2702 #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2703 #else
2704 #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2705 #endif
2706
2707 #ifdef HAVE_FCHDIR
2708 #define PATH_HAVE_FCHDIR 1
2709 #else
2710 #define PATH_HAVE_FCHDIR 0
2711 #endif
2712
2713 #ifdef HAVE_FCHMOD
2714 #define PATH_HAVE_FCHMOD 1
2715 #else
2716 #define PATH_HAVE_FCHMOD 0
2717 #endif
2718
2719 #ifdef HAVE_FCHOWN
2720 #define PATH_HAVE_FCHOWN 1
2721 #else
2722 #define PATH_HAVE_FCHOWN 0
2723 #endif
2724
2725 #ifdef HAVE_FDOPENDIR
2726 #define PATH_HAVE_FDOPENDIR 1
2727 #else
2728 #define PATH_HAVE_FDOPENDIR 0
2729 #endif
2730
2731 #ifdef HAVE_FEXECVE
2732 #define PATH_HAVE_FEXECVE 1
2733 #else
2734 #define PATH_HAVE_FEXECVE 0
2735 #endif
2736
2737 #ifdef HAVE_FPATHCONF
2738 #define PATH_HAVE_FPATHCONF 1
2739 #else
2740 #define PATH_HAVE_FPATHCONF 0
2741 #endif
2742
2743 #ifdef HAVE_FSTATVFS
2744 #define PATH_HAVE_FSTATVFS 1
2745 #else
2746 #define PATH_HAVE_FSTATVFS 0
2747 #endif
2748
2749 #ifdef HAVE_FTRUNCATE
2750 #define PATH_HAVE_FTRUNCATE 1
2751 #else
2752 #define PATH_HAVE_FTRUNCATE 0
2753 #endif
2754 /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2755
2756 #ifdef MS_WINDOWS
2757 #undef PATH_HAVE_FTRUNCATE
2758 #define PATH_HAVE_FTRUNCATE 1
2759 #endif
2760
2761 /*[python input]
2762
2763 class path_t_converter(CConverter):
2764
2765 type = "path_t"
2766 impl_by_reference = True
2767 parse_by_reference = True
2768
2769 converter = 'path_converter'
2770
2771 def converter_init(self, *, allow_fd=False, nullable=False):
2772 # right now path_t doesn't support default values.
2773 # to support a default value, you'll need to override initialize().
2774 if self.default not in (unspecified, None):
2775 fail("Can't specify a default to the path_t converter!")
2776
2777 if self.c_default not in (None, 'Py_None'):
2778 raise RuntimeError("Can't specify a c_default to the path_t converter!")
2779
2780 self.nullable = nullable
2781 self.allow_fd = allow_fd
2782
2783 def pre_render(self):
2784 def strify(value):
2785 if isinstance(value, str):
2786 return value
2787 return str(int(bool(value)))
2788
2789 # add self.py_name here when merging with posixmodule conversion
2790 self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2791 self.function.name,
2792 self.name,
2793 strify(self.nullable),
2794 strify(self.allow_fd),
2795 )
2796
2797 def cleanup(self):
2798 return "path_cleanup(&" + self.name + ");\n"
2799
2800
2801 class dir_fd_converter(CConverter):
2802 type = 'int'
2803
2804 def converter_init(self, requires=None):
2805 if self.default in (unspecified, None):
2806 self.c_default = 'DEFAULT_DIR_FD'
2807 if isinstance(requires, str):
2808 self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2809 else:
2810 self.converter = 'dir_fd_converter'
2811
2812 class uid_t_converter(CConverter):
2813 type = "uid_t"
2814 converter = '_Py_Uid_Converter'
2815
2816 class gid_t_converter(CConverter):
2817 type = "gid_t"
2818 converter = '_Py_Gid_Converter'
2819
2820 class dev_t_converter(CConverter):
2821 type = 'dev_t'
2822 converter = '_Py_Dev_Converter'
2823
2824 class dev_t_return_converter(unsigned_long_return_converter):
2825 type = 'dev_t'
2826 conversion_fn = '_PyLong_FromDev'
2827 unsigned_cast = '(dev_t)'
2828
2829 class FSConverter_converter(CConverter):
2830 type = 'PyObject *'
2831 converter = 'PyUnicode_FSConverter'
2832 def converter_init(self):
2833 if self.default is not unspecified:
2834 fail("FSConverter_converter does not support default values")
2835 self.c_default = 'NULL'
2836
2837 def cleanup(self):
2838 return "Py_XDECREF(" + self.name + ");\n"
2839
2840 class pid_t_converter(CConverter):
2841 type = 'pid_t'
2842 format_unit = '" _Py_PARSE_PID "'
2843
2844 class idtype_t_converter(int_converter):
2845 type = 'idtype_t'
2846
2847 class id_t_converter(CConverter):
2848 type = 'id_t'
2849 format_unit = '" _Py_PARSE_PID "'
2850
2851 class intptr_t_converter(CConverter):
2852 type = 'intptr_t'
2853 format_unit = '" _Py_PARSE_INTPTR "'
2854
2855 class Py_off_t_converter(CConverter):
2856 type = 'Py_off_t'
2857 converter = 'Py_off_t_converter'
2858
2859 class Py_off_t_return_converter(long_return_converter):
2860 type = 'Py_off_t'
2861 conversion_fn = 'PyLong_FromPy_off_t'
2862
2863 class path_confname_converter(CConverter):
2864 type="int"
2865 converter="conv_path_confname"
2866
2867 class confstr_confname_converter(path_confname_converter):
2868 converter='conv_confstr_confname'
2869
2870 class sysconf_confname_converter(path_confname_converter):
2871 converter="conv_sysconf_confname"
2872
2873 [python start generated code]*/
2874 /*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/
2875
2876 /*[clinic input]
2877
2878 os.stat
2879
2880 path : path_t(allow_fd=True)
2881 Path to be examined; can be string, bytes, a path-like object or
2882 open-file-descriptor int.
2883
2884 *
2885
2886 dir_fd : dir_fd(requires='fstatat') = None
2887 If not None, it should be a file descriptor open to a directory,
2888 and path should be a relative string; path will then be relative to
2889 that directory.
2890
2891 follow_symlinks: bool = True
2892 If False, and the last element of the path is a symbolic link,
2893 stat will examine the symbolic link itself instead of the file
2894 the link points to.
2895
2896 Perform a stat system call on the given path.
2897
2898 dir_fd and follow_symlinks may not be implemented
2899 on your platform. If they are unavailable, using them will raise a
2900 NotImplementedError.
2901
2902 It's an error to use dir_fd or follow_symlinks when specifying path as
2903 an open file descriptor.
2904
2905 [clinic start generated code]*/
2906
2907 static PyObject *
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)2908 os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2909 /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2910 {
2911 return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
2912 }
2913
2914
2915 /*[clinic input]
2916 os.lstat
2917
2918 path : path_t
2919
2920 *
2921
2922 dir_fd : dir_fd(requires='fstatat') = None
2923
2924 Perform a stat system call on the given path, without following symbolic links.
2925
2926 Like stat(), but do not follow symbolic links.
2927 Equivalent to stat(path, follow_symlinks=False).
2928 [clinic start generated code]*/
2929
2930 static PyObject *
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)2931 os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2932 /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2933 {
2934 int follow_symlinks = 0;
2935 return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
2936 }
2937
2938
2939 /*[clinic input]
2940 os.access -> bool
2941
2942 path: path_t
2943 Path to be tested; can be string, bytes, or a path-like object.
2944
2945 mode: int
2946 Operating-system mode bitfield. Can be F_OK to test existence,
2947 or the inclusive-OR of R_OK, W_OK, and X_OK.
2948
2949 *
2950
2951 dir_fd : dir_fd(requires='faccessat') = None
2952 If not None, it should be a file descriptor open to a directory,
2953 and path should be relative; path will then be relative to that
2954 directory.
2955
2956 effective_ids: bool = False
2957 If True, access will use the effective uid/gid instead of
2958 the real uid/gid.
2959
2960 follow_symlinks: bool = True
2961 If False, and the last element of the path is a symbolic link,
2962 access will examine the symbolic link itself instead of the file
2963 the link points to.
2964
2965 Use the real uid/gid to test for access to a path.
2966
2967 {parameters}
2968 dir_fd, effective_ids, and follow_symlinks may not be implemented
2969 on your platform. If they are unavailable, using them will raise a
2970 NotImplementedError.
2971
2972 Note that most operations will use the effective uid/gid, therefore this
2973 routine can be used in a suid/sgid environment to test if the invoking user
2974 has the specified access to the path.
2975
2976 [clinic start generated code]*/
2977
2978 static int
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks)2979 os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2980 int effective_ids, int follow_symlinks)
2981 /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
2982 {
2983 int return_value;
2984
2985 #ifdef MS_WINDOWS
2986 DWORD attr;
2987 #else
2988 int result;
2989 #endif
2990
2991 #ifdef HAVE_FACCESSAT
2992 int faccessat_unavailable = 0;
2993 #endif
2994
2995 #ifndef HAVE_FACCESSAT
2996 if (follow_symlinks_specified("access", follow_symlinks))
2997 return -1;
2998
2999 if (effective_ids) {
3000 argument_unavailable_error("access", "effective_ids");
3001 return -1;
3002 }
3003 #endif
3004
3005 #ifdef MS_WINDOWS
3006 Py_BEGIN_ALLOW_THREADS
3007 attr = GetFileAttributesW(path->wide);
3008 Py_END_ALLOW_THREADS
3009
3010 /*
3011 * Access is possible if
3012 * * we didn't get a -1, and
3013 * * write access wasn't requested,
3014 * * or the file isn't read-only,
3015 * * or it's a directory.
3016 * (Directories cannot be read-only on Windows.)
3017 */
3018 return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3019 (!(mode & 2) ||
3020 !(attr & FILE_ATTRIBUTE_READONLY) ||
3021 (attr & FILE_ATTRIBUTE_DIRECTORY));
3022 #else
3023
3024 Py_BEGIN_ALLOW_THREADS
3025 #ifdef HAVE_FACCESSAT
3026 if ((dir_fd != DEFAULT_DIR_FD) ||
3027 effective_ids ||
3028 !follow_symlinks) {
3029
3030 if (HAVE_FACCESSAT_RUNTIME) {
3031 int flags = 0;
3032 if (!follow_symlinks)
3033 flags |= AT_SYMLINK_NOFOLLOW;
3034 if (effective_ids)
3035 flags |= AT_EACCESS;
3036 result = faccessat(dir_fd, path->narrow, mode, flags);
3037 } else {
3038 faccessat_unavailable = 1;
3039 }
3040 }
3041 else
3042 #endif
3043 result = access(path->narrow, mode);
3044 Py_END_ALLOW_THREADS
3045
3046 #ifdef HAVE_FACCESSAT
3047 if (faccessat_unavailable) {
3048 if (dir_fd != DEFAULT_DIR_FD) {
3049 argument_unavailable_error("access", "dir_fd");
3050 return -1;
3051 }
3052 if (follow_symlinks_specified("access", follow_symlinks))
3053 return -1;
3054
3055 if (effective_ids) {
3056 argument_unavailable_error("access", "effective_ids");
3057 return -1;
3058 }
3059 /* should be unreachable */
3060 return -1;
3061 }
3062 #endif
3063 return_value = !result;
3064 #endif
3065
3066 return return_value;
3067 }
3068
3069 #ifndef F_OK
3070 #define F_OK 0
3071 #endif
3072 #ifndef R_OK
3073 #define R_OK 4
3074 #endif
3075 #ifndef W_OK
3076 #define W_OK 2
3077 #endif
3078 #ifndef X_OK
3079 #define X_OK 1
3080 #endif
3081
3082
3083 #ifdef HAVE_TTYNAME
3084 /*[clinic input]
3085 os.ttyname
3086
3087 fd: int
3088 Integer file descriptor handle.
3089
3090 /
3091
3092 Return the name of the terminal device connected to 'fd'.
3093 [clinic start generated code]*/
3094
3095 static PyObject *
os_ttyname_impl(PyObject *module, int fd)3096 os_ttyname_impl(PyObject *module, int fd)
3097 /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3098 {
3099
3100 long size = sysconf(_SC_TTY_NAME_MAX);
3101 if (size == -1) {
3102 return posix_error();
3103 }
3104 char *buffer = (char *)PyMem_RawMalloc(size);
3105 if (buffer == NULL) {
3106 return PyErr_NoMemory();
3107 }
3108 int ret = ttyname_r(fd, buffer, size);
3109 if (ret != 0) {
3110 PyMem_RawFree(buffer);
3111 errno = ret;
3112 return posix_error();
3113 }
3114 PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3115 PyMem_RawFree(buffer);
3116 return res;
3117 }
3118 #endif
3119
3120 #ifdef HAVE_CTERMID
3121 /*[clinic input]
3122 os.ctermid
3123
3124 Return the name of the controlling terminal for this process.
3125 [clinic start generated code]*/
3126
3127 static PyObject *
os_ctermid_impl(PyObject *module)3128 os_ctermid_impl(PyObject *module)
3129 /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3130 {
3131 char *ret;
3132 char buffer[L_ctermid];
3133
3134 #ifdef USE_CTERMID_R
3135 ret = ctermid_r(buffer);
3136 #else
3137 ret = ctermid(buffer);
3138 #endif
3139 if (ret == NULL)
3140 return posix_error();
3141 return PyUnicode_DecodeFSDefault(buffer);
3142 }
3143 #endif /* HAVE_CTERMID */
3144
3145
3146 /*[clinic input]
3147 os.chdir
3148
3149 path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3150
3151 Change the current working directory to the specified path.
3152
3153 path may always be specified as a string.
3154 On some platforms, path may also be specified as an open file descriptor.
3155 If this functionality is unavailable, using it raises an exception.
3156 [clinic start generated code]*/
3157
3158 static PyObject *
os_chdir_impl(PyObject *module, path_t *path)3159 os_chdir_impl(PyObject *module, path_t *path)
3160 /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3161 {
3162 int result;
3163
3164 if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3165 return NULL;
3166 }
3167
3168 Py_BEGIN_ALLOW_THREADS
3169 #ifdef MS_WINDOWS
3170 /* on unix, success = 0, on windows, success = !0 */
3171 result = !win32_wchdir(path->wide);
3172 #else
3173 #ifdef HAVE_FCHDIR
3174 if (path->fd != -1)
3175 result = fchdir(path->fd);
3176 else
3177 #endif
3178 result = chdir(path->narrow);
3179 #endif
3180 Py_END_ALLOW_THREADS
3181
3182 if (result) {
3183 return path_error(path);
3184 }
3185
3186 Py_RETURN_NONE;
3187 }
3188
3189
3190 #ifdef HAVE_FCHDIR
3191 /*[clinic input]
3192 os.fchdir
3193
3194 fd: fildes
3195
3196 Change to the directory of the given file descriptor.
3197
3198 fd must be opened on a directory, not a file.
3199 Equivalent to os.chdir(fd).
3200
3201 [clinic start generated code]*/
3202
3203 static PyObject *
os_fchdir_impl(PyObject *module, int fd)3204 os_fchdir_impl(PyObject *module, int fd)
3205 /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3206 {
3207 if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3208 return NULL;
3209 }
3210 return posix_fildes_fd(fd, fchdir);
3211 }
3212 #endif /* HAVE_FCHDIR */
3213
3214
3215 /*[clinic input]
3216 os.chmod
3217
3218 path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3219 Path to be modified. May always be specified as a str, bytes, or a path-like object.
3220 On some platforms, path may also be specified as an open file descriptor.
3221 If this functionality is unavailable, using it raises an exception.
3222
3223 mode: int
3224 Operating-system mode bitfield.
3225
3226 *
3227
3228 dir_fd : dir_fd(requires='fchmodat') = None
3229 If not None, it should be a file descriptor open to a directory,
3230 and path should be relative; path will then be relative to that
3231 directory.
3232
3233 follow_symlinks: bool = True
3234 If False, and the last element of the path is a symbolic link,
3235 chmod will modify the symbolic link itself instead of the file
3236 the link points to.
3237
3238 Change the access permissions of a file.
3239
3240 It is an error to use dir_fd or follow_symlinks when specifying path as
3241 an open file descriptor.
3242 dir_fd and follow_symlinks may not be implemented on your platform.
3243 If they are unavailable, using them will raise a NotImplementedError.
3244
3245 [clinic start generated code]*/
3246
3247 static PyObject *
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, int follow_symlinks)3248 os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3249 int follow_symlinks)
3250 /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
3251 {
3252 int result;
3253
3254 #ifdef MS_WINDOWS
3255 DWORD attr;
3256 #endif
3257
3258 #ifdef HAVE_FCHMODAT
3259 int fchmodat_nofollow_unsupported = 0;
3260 int fchmodat_unsupported = 0;
3261 #endif
3262
3263 #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
3264 if (follow_symlinks_specified("chmod", follow_symlinks))
3265 return NULL;
3266 #endif
3267
3268 if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3269 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3270 return NULL;
3271 }
3272
3273 #ifdef MS_WINDOWS
3274 Py_BEGIN_ALLOW_THREADS
3275 attr = GetFileAttributesW(path->wide);
3276 if (attr == INVALID_FILE_ATTRIBUTES)
3277 result = 0;
3278 else {
3279 if (mode & _S_IWRITE)
3280 attr &= ~FILE_ATTRIBUTE_READONLY;
3281 else
3282 attr |= FILE_ATTRIBUTE_READONLY;
3283 result = SetFileAttributesW(path->wide, attr);
3284 }
3285 Py_END_ALLOW_THREADS
3286
3287 if (!result) {
3288 return path_error(path);
3289 }
3290 #else /* MS_WINDOWS */
3291 Py_BEGIN_ALLOW_THREADS
3292 #ifdef HAVE_FCHMOD
3293 if (path->fd != -1)
3294 result = fchmod(path->fd, mode);
3295 else
3296 #endif /* HAVE_CHMOD */
3297 #ifdef HAVE_LCHMOD
3298 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3299 result = lchmod(path->narrow, mode);
3300 else
3301 #endif /* HAVE_LCHMOD */
3302 #ifdef HAVE_FCHMODAT
3303 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3304 if (HAVE_FCHMODAT_RUNTIME) {
3305 /*
3306 * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3307 * The documentation specifically shows how to use it,
3308 * and then says it isn't implemented yet.
3309 * (true on linux with glibc 2.15, and openindiana 3.x)
3310 *
3311 * Once it is supported, os.chmod will automatically
3312 * support dir_fd and follow_symlinks=False. (Hopefully.)
3313 * Until then, we need to be careful what exception we raise.
3314 */
3315 result = fchmodat(dir_fd, path->narrow, mode,
3316 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3317 /*
3318 * But wait! We can't throw the exception without allowing threads,
3319 * and we can't do that in this nested scope. (Macro trickery, sigh.)
3320 */
3321 fchmodat_nofollow_unsupported =
3322 result &&
3323 ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3324 !follow_symlinks;
3325 } else {
3326 fchmodat_unsupported = 1;
3327 fchmodat_nofollow_unsupported = 1;
3328
3329 result = -1;
3330 }
3331 }
3332 else
3333 #endif /* HAVE_FHCMODAT */
3334 {
3335 #ifdef HAVE_CHMOD
3336 result = chmod(path->narrow, mode);
3337 #elif defined(__wasi__)
3338 // WASI SDK 15.0 does not support chmod.
3339 // Ignore missing syscall for now.
3340 result = 0;
3341 #else
3342 result = -1;
3343 errno = ENOSYS;
3344 #endif
3345 }
3346 Py_END_ALLOW_THREADS
3347
3348 if (result) {
3349 #ifdef HAVE_FCHMODAT
3350 if (fchmodat_unsupported) {
3351 if (dir_fd != DEFAULT_DIR_FD) {
3352 argument_unavailable_error("chmod", "dir_fd");
3353 return NULL;
3354 }
3355 }
3356
3357 if (fchmodat_nofollow_unsupported) {
3358 if (dir_fd != DEFAULT_DIR_FD)
3359 dir_fd_and_follow_symlinks_invalid("chmod",
3360 dir_fd, follow_symlinks);
3361 else
3362 follow_symlinks_specified("chmod", follow_symlinks);
3363 return NULL;
3364 }
3365 else
3366 #endif /* HAVE_FCHMODAT */
3367 return path_error(path);
3368 }
3369 #endif /* MS_WINDOWS */
3370
3371 Py_RETURN_NONE;
3372 }
3373
3374
3375 #ifdef HAVE_FCHMOD
3376 /*[clinic input]
3377 os.fchmod
3378
3379 fd: int
3380 mode: int
3381
3382 Change the access permissions of the file given by file descriptor fd.
3383
3384 Equivalent to os.chmod(fd, mode).
3385 [clinic start generated code]*/
3386
3387 static PyObject *
os_fchmod_impl(PyObject *module, int fd, int mode)3388 os_fchmod_impl(PyObject *module, int fd, int mode)
3389 /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
3390 {
3391 int res;
3392 int async_err = 0;
3393
3394 if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3395 return NULL;
3396 }
3397
3398 do {
3399 Py_BEGIN_ALLOW_THREADS
3400 res = fchmod(fd, mode);
3401 Py_END_ALLOW_THREADS
3402 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3403 if (res != 0)
3404 return (!async_err) ? posix_error() : NULL;
3405
3406 Py_RETURN_NONE;
3407 }
3408 #endif /* HAVE_FCHMOD */
3409
3410
3411 #ifdef HAVE_LCHMOD
3412 /*[clinic input]
3413 os.lchmod
3414
3415 path: path_t
3416 mode: int
3417
3418 Change the access permissions of a file, without following symbolic links.
3419
3420 If path is a symlink, this affects the link itself rather than the target.
3421 Equivalent to chmod(path, mode, follow_symlinks=False)."
3422 [clinic start generated code]*/
3423
3424 static PyObject *
os_lchmod_impl(PyObject *module, path_t *path, int mode)3425 os_lchmod_impl(PyObject *module, path_t *path, int mode)
3426 /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3427 {
3428 int res;
3429 if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3430 return NULL;
3431 }
3432 Py_BEGIN_ALLOW_THREADS
3433 res = lchmod(path->narrow, mode);
3434 Py_END_ALLOW_THREADS
3435 if (res < 0) {
3436 path_error(path);
3437 return NULL;
3438 }
3439 Py_RETURN_NONE;
3440 }
3441 #endif /* HAVE_LCHMOD */
3442
3443
3444 #ifdef HAVE_CHFLAGS
3445 /*[clinic input]
3446 os.chflags
3447
3448 path: path_t
3449 flags: unsigned_long(bitwise=True)
3450 follow_symlinks: bool=True
3451
3452 Set file flags.
3453
3454 If follow_symlinks is False, and the last element of the path is a symbolic
3455 link, chflags will change flags on the symbolic link itself instead of the
3456 file the link points to.
3457 follow_symlinks may not be implemented on your platform. If it is
3458 unavailable, using it will raise a NotImplementedError.
3459
3460 [clinic start generated code]*/
3461
3462 static PyObject *
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags, int follow_symlinks)3463 os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3464 int follow_symlinks)
3465 /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3466 {
3467 int result;
3468
3469 #ifndef HAVE_LCHFLAGS
3470 if (follow_symlinks_specified("chflags", follow_symlinks))
3471 return NULL;
3472 #endif
3473
3474 if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3475 return NULL;
3476 }
3477
3478 Py_BEGIN_ALLOW_THREADS
3479 #ifdef HAVE_LCHFLAGS
3480 if (!follow_symlinks)
3481 result = lchflags(path->narrow, flags);
3482 else
3483 #endif
3484 result = chflags(path->narrow, flags);
3485 Py_END_ALLOW_THREADS
3486
3487 if (result)
3488 return path_error(path);
3489
3490 Py_RETURN_NONE;
3491 }
3492 #endif /* HAVE_CHFLAGS */
3493
3494
3495 #ifdef HAVE_LCHFLAGS
3496 /*[clinic input]
3497 os.lchflags
3498
3499 path: path_t
3500 flags: unsigned_long(bitwise=True)
3501
3502 Set file flags.
3503
3504 This function will not follow symbolic links.
3505 Equivalent to chflags(path, flags, follow_symlinks=False).
3506 [clinic start generated code]*/
3507
3508 static PyObject *
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)3509 os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3510 /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3511 {
3512 int res;
3513 if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3514 return NULL;
3515 }
3516 Py_BEGIN_ALLOW_THREADS
3517 res = lchflags(path->narrow, flags);
3518 Py_END_ALLOW_THREADS
3519 if (res < 0) {
3520 return path_error(path);
3521 }
3522 Py_RETURN_NONE;
3523 }
3524 #endif /* HAVE_LCHFLAGS */
3525
3526
3527 #ifdef HAVE_CHROOT
3528 /*[clinic input]
3529 os.chroot
3530 path: path_t
3531
3532 Change root directory to path.
3533
3534 [clinic start generated code]*/
3535
3536 static PyObject *
os_chroot_impl(PyObject *module, path_t *path)3537 os_chroot_impl(PyObject *module, path_t *path)
3538 /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3539 {
3540 int res;
3541 Py_BEGIN_ALLOW_THREADS
3542 res = chroot(path->narrow);
3543 Py_END_ALLOW_THREADS
3544 if (res < 0)
3545 return path_error(path);
3546 Py_RETURN_NONE;
3547 }
3548 #endif /* HAVE_CHROOT */
3549
3550
3551 #ifdef HAVE_FSYNC
3552 /*[clinic input]
3553 os.fsync
3554
3555 fd: fildes
3556
3557 Force write of fd to disk.
3558 [clinic start generated code]*/
3559
3560 static PyObject *
os_fsync_impl(PyObject *module, int fd)3561 os_fsync_impl(PyObject *module, int fd)
3562 /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3563 {
3564 return posix_fildes_fd(fd, fsync);
3565 }
3566 #endif /* HAVE_FSYNC */
3567
3568
3569 #ifdef HAVE_SYNC
3570 /*[clinic input]
3571 os.sync
3572
3573 Force write of everything to disk.
3574 [clinic start generated code]*/
3575
3576 static PyObject *
os_sync_impl(PyObject *module)3577 os_sync_impl(PyObject *module)
3578 /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3579 {
3580 Py_BEGIN_ALLOW_THREADS
3581 sync();
3582 Py_END_ALLOW_THREADS
3583 Py_RETURN_NONE;
3584 }
3585 #endif /* HAVE_SYNC */
3586
3587
3588 #ifdef HAVE_FDATASYNC
3589 #ifdef __hpux
3590 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3591 #endif
3592
3593 /*[clinic input]
3594 os.fdatasync
3595
3596 fd: fildes
3597
3598 Force write of fd to disk without forcing update of metadata.
3599 [clinic start generated code]*/
3600
3601 static PyObject *
os_fdatasync_impl(PyObject *module, int fd)3602 os_fdatasync_impl(PyObject *module, int fd)
3603 /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3604 {
3605 return posix_fildes_fd(fd, fdatasync);
3606 }
3607 #endif /* HAVE_FDATASYNC */
3608
3609
3610 #ifdef HAVE_CHOWN
3611 /*[clinic input]
3612 os.chown
3613
3614 path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3615 Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3616
3617 uid: uid_t
3618
3619 gid: gid_t
3620
3621 *
3622
3623 dir_fd : dir_fd(requires='fchownat') = None
3624 If not None, it should be a file descriptor open to a directory,
3625 and path should be relative; path will then be relative to that
3626 directory.
3627
3628 follow_symlinks: bool = True
3629 If False, and the last element of the path is a symbolic link,
3630 stat will examine the symbolic link itself instead of the file
3631 the link points to.
3632
3633 Change the owner and group id of path to the numeric uid and gid.\
3634
3635 path may always be specified as a string.
3636 On some platforms, path may also be specified as an open file descriptor.
3637 If this functionality is unavailable, using it raises an exception.
3638 If dir_fd is not None, it should be a file descriptor open to a directory,
3639 and path should be relative; path will then be relative to that directory.
3640 If follow_symlinks is False, and the last element of the path is a symbolic
3641 link, chown will modify the symbolic link itself instead of the file the
3642 link points to.
3643 It is an error to use dir_fd or follow_symlinks when specifying path as
3644 an open file descriptor.
3645 dir_fd and follow_symlinks may not be implemented on your platform.
3646 If they are unavailable, using them will raise a NotImplementedError.
3647
3648 [clinic start generated code]*/
3649
3650 static PyObject *
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, int dir_fd, int follow_symlinks)3651 os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3652 int dir_fd, int follow_symlinks)
3653 /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3654 {
3655 int result;
3656
3657 #if defined(HAVE_FCHOWNAT)
3658 int fchownat_unsupported = 0;
3659 #endif
3660
3661 #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3662 if (follow_symlinks_specified("chown", follow_symlinks))
3663 return NULL;
3664 #endif
3665 if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3666 fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3667 return NULL;
3668
3669 if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3670 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3671 return NULL;
3672 }
3673
3674 Py_BEGIN_ALLOW_THREADS
3675 #ifdef HAVE_FCHOWN
3676 if (path->fd != -1)
3677 result = fchown(path->fd, uid, gid);
3678 else
3679 #endif
3680 #ifdef HAVE_LCHOWN
3681 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3682 result = lchown(path->narrow, uid, gid);
3683 else
3684 #endif
3685 #ifdef HAVE_FCHOWNAT
3686 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
3687 if (HAVE_FCHOWNAT_RUNTIME) {
3688 result = fchownat(dir_fd, path->narrow, uid, gid,
3689 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3690 } else {
3691 fchownat_unsupported = 1;
3692 }
3693 } else
3694 #endif
3695 result = chown(path->narrow, uid, gid);
3696 Py_END_ALLOW_THREADS
3697
3698 #ifdef HAVE_FCHOWNAT
3699 if (fchownat_unsupported) {
3700 /* This would be incorrect if the current platform
3701 * doesn't support lchown.
3702 */
3703 argument_unavailable_error(NULL, "dir_fd");
3704 return NULL;
3705 }
3706 #endif
3707
3708 if (result)
3709 return path_error(path);
3710
3711 Py_RETURN_NONE;
3712 }
3713 #endif /* HAVE_CHOWN */
3714
3715
3716 #ifdef HAVE_FCHOWN
3717 /*[clinic input]
3718 os.fchown
3719
3720 fd: int
3721 uid: uid_t
3722 gid: gid_t
3723
3724 Change the owner and group id of the file specified by file descriptor.
3725
3726 Equivalent to os.chown(fd, uid, gid).
3727
3728 [clinic start generated code]*/
3729
3730 static PyObject *
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)3731 os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3732 /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3733 {
3734 int res;
3735 int async_err = 0;
3736
3737 if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
3738 return NULL;
3739 }
3740
3741 do {
3742 Py_BEGIN_ALLOW_THREADS
3743 res = fchown(fd, uid, gid);
3744 Py_END_ALLOW_THREADS
3745 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3746 if (res != 0)
3747 return (!async_err) ? posix_error() : NULL;
3748
3749 Py_RETURN_NONE;
3750 }
3751 #endif /* HAVE_FCHOWN */
3752
3753
3754 #ifdef HAVE_LCHOWN
3755 /*[clinic input]
3756 os.lchown
3757
3758 path : path_t
3759 uid: uid_t
3760 gid: gid_t
3761
3762 Change the owner and group id of path to the numeric uid and gid.
3763
3764 This function will not follow symbolic links.
3765 Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3766 [clinic start generated code]*/
3767
3768 static PyObject *
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)3769 os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3770 /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3771 {
3772 int res;
3773 if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
3774 return NULL;
3775 }
3776 Py_BEGIN_ALLOW_THREADS
3777 res = lchown(path->narrow, uid, gid);
3778 Py_END_ALLOW_THREADS
3779 if (res < 0) {
3780 return path_error(path);
3781 }
3782 Py_RETURN_NONE;
3783 }
3784 #endif /* HAVE_LCHOWN */
3785
3786
3787 static PyObject *
posix_getcwd(int use_bytes)3788 posix_getcwd(int use_bytes)
3789 {
3790 #ifdef MS_WINDOWS
3791 wchar_t wbuf[MAXPATHLEN];
3792 wchar_t *wbuf2 = wbuf;
3793 DWORD len;
3794
3795 Py_BEGIN_ALLOW_THREADS
3796 len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3797 /* If the buffer is large enough, len does not include the
3798 terminating \0. If the buffer is too small, len includes
3799 the space needed for the terminator. */
3800 if (len >= Py_ARRAY_LENGTH(wbuf)) {
3801 if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3802 wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3803 }
3804 else {
3805 wbuf2 = NULL;
3806 }
3807 if (wbuf2) {
3808 len = GetCurrentDirectoryW(len, wbuf2);
3809 }
3810 }
3811 Py_END_ALLOW_THREADS
3812
3813 if (!wbuf2) {
3814 PyErr_NoMemory();
3815 return NULL;
3816 }
3817 if (!len) {
3818 if (wbuf2 != wbuf)
3819 PyMem_RawFree(wbuf2);
3820 return PyErr_SetFromWindowsErr(0);
3821 }
3822
3823 PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3824 if (wbuf2 != wbuf) {
3825 PyMem_RawFree(wbuf2);
3826 }
3827
3828 if (use_bytes) {
3829 if (resobj == NULL) {
3830 return NULL;
3831 }
3832 Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3833 }
3834
3835 return resobj;
3836 #else
3837 const size_t chunk = 1024;
3838
3839 char *buf = NULL;
3840 char *cwd = NULL;
3841 size_t buflen = 0;
3842
3843 Py_BEGIN_ALLOW_THREADS
3844 do {
3845 char *newbuf;
3846 if (buflen <= PY_SSIZE_T_MAX - chunk) {
3847 buflen += chunk;
3848 newbuf = PyMem_RawRealloc(buf, buflen);
3849 }
3850 else {
3851 newbuf = NULL;
3852 }
3853 if (newbuf == NULL) {
3854 PyMem_RawFree(buf);
3855 buf = NULL;
3856 break;
3857 }
3858 buf = newbuf;
3859
3860 cwd = getcwd(buf, buflen);
3861 } while (cwd == NULL && errno == ERANGE);
3862 Py_END_ALLOW_THREADS
3863
3864 if (buf == NULL) {
3865 return PyErr_NoMemory();
3866 }
3867 if (cwd == NULL) {
3868 PyMem_RawFree(buf);
3869 return posix_error();
3870 }
3871
3872 PyObject *obj;
3873 if (use_bytes) {
3874 obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3875 }
3876 else {
3877 obj = PyUnicode_DecodeFSDefault(buf);
3878 }
3879 PyMem_RawFree(buf);
3880
3881 return obj;
3882 #endif /* !MS_WINDOWS */
3883 }
3884
3885
3886 /*[clinic input]
3887 os.getcwd
3888
3889 Return a unicode string representing the current working directory.
3890 [clinic start generated code]*/
3891
3892 static PyObject *
os_getcwd_impl(PyObject *module)3893 os_getcwd_impl(PyObject *module)
3894 /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3895 {
3896 return posix_getcwd(0);
3897 }
3898
3899
3900 /*[clinic input]
3901 os.getcwdb
3902
3903 Return a bytes string representing the current working directory.
3904 [clinic start generated code]*/
3905
3906 static PyObject *
os_getcwdb_impl(PyObject *module)3907 os_getcwdb_impl(PyObject *module)
3908 /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3909 {
3910 return posix_getcwd(1);
3911 }
3912
3913
3914 #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3915 #define HAVE_LINK 1
3916 #endif
3917
3918 #ifdef HAVE_LINK
3919 /*[clinic input]
3920
3921 os.link
3922
3923 src : path_t
3924 dst : path_t
3925 *
3926 src_dir_fd : dir_fd = None
3927 dst_dir_fd : dir_fd = None
3928 follow_symlinks: bool = True
3929
3930 Create a hard link to a file.
3931
3932 If either src_dir_fd or dst_dir_fd is not None, it should be a file
3933 descriptor open to a directory, and the respective path string (src or dst)
3934 should be relative; the path will then be relative to that directory.
3935 If follow_symlinks is False, and the last element of src is a symbolic
3936 link, link will create a link to the symbolic link itself instead of the
3937 file the link points to.
3938 src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3939 platform. If they are unavailable, using them will raise a
3940 NotImplementedError.
3941 [clinic start generated code]*/
3942
3943 static PyObject *
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int follow_symlinks)3944 os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3945 int dst_dir_fd, int follow_symlinks)
3946 /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3947 {
3948 #ifdef MS_WINDOWS
3949 BOOL result = FALSE;
3950 #else
3951 int result;
3952 #endif
3953 #if defined(HAVE_LINKAT)
3954 int linkat_unavailable = 0;
3955 #endif
3956
3957 #ifndef HAVE_LINKAT
3958 if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3959 argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3960 return NULL;
3961 }
3962 #endif
3963
3964 #ifndef MS_WINDOWS
3965 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3966 PyErr_SetString(PyExc_NotImplementedError,
3967 "link: src and dst must be the same type");
3968 return NULL;
3969 }
3970 #endif
3971
3972 if (PySys_Audit("os.link", "OOii", src->object, dst->object,
3973 src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
3974 dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
3975 return NULL;
3976 }
3977
3978 #ifdef MS_WINDOWS
3979 Py_BEGIN_ALLOW_THREADS
3980 result = CreateHardLinkW(dst->wide, src->wide, NULL);
3981 Py_END_ALLOW_THREADS
3982
3983 if (!result)
3984 return path_error2(src, dst);
3985 #else
3986 Py_BEGIN_ALLOW_THREADS
3987 #ifdef HAVE_LINKAT
3988 if ((src_dir_fd != DEFAULT_DIR_FD) ||
3989 (dst_dir_fd != DEFAULT_DIR_FD) ||
3990 (!follow_symlinks)) {
3991
3992 if (HAVE_LINKAT_RUNTIME) {
3993
3994 result = linkat(src_dir_fd, src->narrow,
3995 dst_dir_fd, dst->narrow,
3996 follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3997
3998 }
3999 #ifdef __APPLE__
4000 else {
4001 if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
4002 /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
4003 result = link(src->narrow, dst->narrow);
4004 } else {
4005 linkat_unavailable = 1;
4006 }
4007 }
4008 #endif
4009 }
4010 else
4011 #endif /* HAVE_LINKAT */
4012 result = link(src->narrow, dst->narrow);
4013 Py_END_ALLOW_THREADS
4014
4015 #ifdef HAVE_LINKAT
4016 if (linkat_unavailable) {
4017 /* Either or both dir_fd arguments were specified */
4018 if (src_dir_fd != DEFAULT_DIR_FD) {
4019 argument_unavailable_error("link", "src_dir_fd");
4020 } else {
4021 argument_unavailable_error("link", "dst_dir_fd");
4022 }
4023 return NULL;
4024 }
4025 #endif
4026
4027 if (result)
4028 return path_error2(src, dst);
4029 #endif /* MS_WINDOWS */
4030
4031 Py_RETURN_NONE;
4032 }
4033 #endif
4034
4035
4036 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4037 static PyObject *
_listdir_windows_no_opendir(path_t *path, PyObject *list)4038 _listdir_windows_no_opendir(path_t *path, PyObject *list)
4039 {
4040 PyObject *v;
4041 HANDLE hFindFile = INVALID_HANDLE_VALUE;
4042 BOOL result;
4043 wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4044 /* only claim to have space for MAX_PATH */
4045 Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4046 wchar_t *wnamebuf = NULL;
4047
4048 WIN32_FIND_DATAW wFileData;
4049 const wchar_t *po_wchars;
4050
4051 if (!path->wide) { /* Default arg: "." */
4052 po_wchars = L".";
4053 len = 1;
4054 } else {
4055 po_wchars = path->wide;
4056 len = wcslen(path->wide);
4057 }
4058 /* The +5 is so we can append "\\*.*\0" */
4059 wnamebuf = PyMem_New(wchar_t, len + 5);
4060 if (!wnamebuf) {
4061 PyErr_NoMemory();
4062 goto exit;
4063 }
4064 wcscpy(wnamebuf, po_wchars);
4065 if (len > 0) {
4066 wchar_t wch = wnamebuf[len-1];
4067 if (wch != SEP && wch != ALTSEP && wch != L':')
4068 wnamebuf[len++] = SEP;
4069 wcscpy(wnamebuf + len, L"*.*");
4070 }
4071 if ((list = PyList_New(0)) == NULL) {
4072 goto exit;
4073 }
4074 Py_BEGIN_ALLOW_THREADS
4075 hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4076 Py_END_ALLOW_THREADS
4077 if (hFindFile == INVALID_HANDLE_VALUE) {
4078 int error = GetLastError();
4079 if (error == ERROR_FILE_NOT_FOUND)
4080 goto exit;
4081 Py_DECREF(list);
4082 list = path_error(path);
4083 goto exit;
4084 }
4085 do {
4086 /* Skip over . and .. */
4087 if (wcscmp(wFileData.cFileName, L".") != 0 &&
4088 wcscmp(wFileData.cFileName, L"..") != 0) {
4089 v = PyUnicode_FromWideChar(wFileData.cFileName,
4090 wcslen(wFileData.cFileName));
4091 if (path->narrow && v) {
4092 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4093 }
4094 if (v == NULL) {
4095 Py_DECREF(list);
4096 list = NULL;
4097 break;
4098 }
4099 if (PyList_Append(list, v) != 0) {
4100 Py_DECREF(v);
4101 Py_DECREF(list);
4102 list = NULL;
4103 break;
4104 }
4105 Py_DECREF(v);
4106 }
4107 Py_BEGIN_ALLOW_THREADS
4108 result = FindNextFileW(hFindFile, &wFileData);
4109 Py_END_ALLOW_THREADS
4110 /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4111 it got to the end of the directory. */
4112 if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4113 Py_DECREF(list);
4114 list = path_error(path);
4115 goto exit;
4116 }
4117 } while (result == TRUE);
4118
4119 exit:
4120 if (hFindFile != INVALID_HANDLE_VALUE) {
4121 if (FindClose(hFindFile) == FALSE) {
4122 if (list != NULL) {
4123 Py_DECREF(list);
4124 list = path_error(path);
4125 }
4126 }
4127 }
4128 PyMem_Free(wnamebuf);
4129
4130 return list;
4131 } /* end of _listdir_windows_no_opendir */
4132
4133 #else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4134
4135 static PyObject *
_posix_listdir(path_t *path, PyObject *list)4136 _posix_listdir(path_t *path, PyObject *list)
4137 {
4138 PyObject *v;
4139 DIR *dirp = NULL;
4140 struct dirent *ep;
4141 int return_str; /* if false, return bytes */
4142 #ifdef HAVE_FDOPENDIR
4143 int fd = -1;
4144 #endif
4145
4146 errno = 0;
4147 #ifdef HAVE_FDOPENDIR
4148 if (path->fd != -1) {
4149 if (HAVE_FDOPENDIR_RUNTIME) {
4150 /* closedir() closes the FD, so we duplicate it */
4151 fd = _Py_dup(path->fd);
4152 if (fd == -1)
4153 return NULL;
4154
4155 return_str = 1;
4156
4157 Py_BEGIN_ALLOW_THREADS
4158 dirp = fdopendir(fd);
4159 Py_END_ALLOW_THREADS
4160 } else {
4161 PyErr_SetString(PyExc_TypeError,
4162 "listdir: path should be string, bytes, os.PathLike or None, not int");
4163 return NULL;
4164 }
4165 }
4166 else
4167 #endif
4168 {
4169 const char *name;
4170 if (path->narrow) {
4171 name = path->narrow;
4172 /* only return bytes if they specified a bytes-like object */
4173 return_str = !PyObject_CheckBuffer(path->object);
4174 }
4175 else {
4176 name = ".";
4177 return_str = 1;
4178 }
4179
4180 Py_BEGIN_ALLOW_THREADS
4181 dirp = opendir(name);
4182 Py_END_ALLOW_THREADS
4183 }
4184
4185 if (dirp == NULL) {
4186 list = path_error(path);
4187 #ifdef HAVE_FDOPENDIR
4188 if (fd != -1) {
4189 Py_BEGIN_ALLOW_THREADS
4190 close(fd);
4191 Py_END_ALLOW_THREADS
4192 }
4193 #endif
4194 goto exit;
4195 }
4196 if ((list = PyList_New(0)) == NULL) {
4197 goto exit;
4198 }
4199 for (;;) {
4200 errno = 0;
4201 Py_BEGIN_ALLOW_THREADS
4202 ep = readdir(dirp);
4203 Py_END_ALLOW_THREADS
4204 if (ep == NULL) {
4205 if (errno == 0) {
4206 break;
4207 } else {
4208 Py_DECREF(list);
4209 list = path_error(path);
4210 goto exit;
4211 }
4212 }
4213 if (ep->d_name[0] == '.' &&
4214 (NAMLEN(ep) == 1 ||
4215 (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4216 continue;
4217 if (return_str)
4218 v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4219 else
4220 v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4221 if (v == NULL) {
4222 Py_CLEAR(list);
4223 break;
4224 }
4225 if (PyList_Append(list, v) != 0) {
4226 Py_DECREF(v);
4227 Py_CLEAR(list);
4228 break;
4229 }
4230 Py_DECREF(v);
4231 }
4232
4233 exit:
4234 if (dirp != NULL) {
4235 Py_BEGIN_ALLOW_THREADS
4236 #ifdef HAVE_FDOPENDIR
4237 if (fd > -1)
4238 rewinddir(dirp);
4239 #endif
4240 closedir(dirp);
4241 Py_END_ALLOW_THREADS
4242 }
4243
4244 return list;
4245 } /* end of _posix_listdir */
4246 #endif /* which OS */
4247
4248
4249 /*[clinic input]
4250 os.listdir
4251
4252 path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4253
4254 Return a list containing the names of the files in the directory.
4255
4256 path can be specified as either str, bytes, or a path-like object. If path is bytes,
4257 the filenames returned will also be bytes; in all other circumstances
4258 the filenames returned will be str.
4259 If path is None, uses the path='.'.
4260 On some platforms, path may also be specified as an open file descriptor;\
4261 the file descriptor must refer to a directory.
4262 If this functionality is unavailable, using it raises NotImplementedError.
4263
4264 The list is in arbitrary order. It does not include the special
4265 entries '.' and '..' even if they are present in the directory.
4266
4267
4268 [clinic start generated code]*/
4269
4270 static PyObject *
os_listdir_impl(PyObject *module, path_t *path)4271 os_listdir_impl(PyObject *module, path_t *path)
4272 /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4273 {
4274 if (PySys_Audit("os.listdir", "O",
4275 path->object ? path->object : Py_None) < 0) {
4276 return NULL;
4277 }
4278 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4279 return _listdir_windows_no_opendir(path, NULL);
4280 #else
4281 return _posix_listdir(path, NULL);
4282 #endif
4283 }
4284
4285 #ifdef MS_WINDOWS
4286 int
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)4287 _PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
4288 {
4289 wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
4290 DWORD result;
4291
4292 result = GetFullPathNameW(path,
4293 Py_ARRAY_LENGTH(woutbuf), woutbuf,
4294 NULL);
4295 if (!result) {
4296 return -1;
4297 }
4298
4299 if (result >= Py_ARRAY_LENGTH(woutbuf)) {
4300 if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4301 woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
4302 }
4303 else {
4304 woutbufp = NULL;
4305 }
4306 if (!woutbufp) {
4307 *abspath_p = NULL;
4308 return 0;
4309 }
4310
4311 result = GetFullPathNameW(path, result, woutbufp, NULL);
4312 if (!result) {
4313 PyMem_RawFree(woutbufp);
4314 return -1;
4315 }
4316 }
4317
4318 if (woutbufp != woutbuf) {
4319 *abspath_p = woutbufp;
4320 return 0;
4321 }
4322
4323 *abspath_p = _PyMem_RawWcsdup(woutbufp);
4324 return 0;
4325 }
4326
4327
4328 /* A helper function for abspath on win32 */
4329 /*[clinic input]
4330 os._getfullpathname
4331
4332 path: path_t
4333 /
4334
4335 [clinic start generated code]*/
4336
4337 static PyObject *
os__getfullpathname_impl(PyObject *module, path_t *path)4338 os__getfullpathname_impl(PyObject *module, path_t *path)
4339 /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
4340 {
4341 wchar_t *abspath;
4342
4343 if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
4344 return win32_error_object("GetFullPathNameW", path->object);
4345 }
4346 if (abspath == NULL) {
4347 return PyErr_NoMemory();
4348 }
4349
4350 PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
4351 PyMem_RawFree(abspath);
4352 if (str == NULL) {
4353 return NULL;
4354 }
4355 if (path->narrow) {
4356 Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
4357 }
4358 return str;
4359 }
4360
4361
4362 /*[clinic input]
4363 os._getfinalpathname
4364
4365 path: path_t
4366 /
4367
4368 A helper function for samepath on windows.
4369 [clinic start generated code]*/
4370
4371 static PyObject *
os__getfinalpathname_impl(PyObject *module, path_t *path)4372 os__getfinalpathname_impl(PyObject *module, path_t *path)
4373 /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
4374 {
4375 HANDLE hFile;
4376 wchar_t buf[MAXPATHLEN], *target_path = buf;
4377 int buf_size = Py_ARRAY_LENGTH(buf);
4378 int result_length;
4379 PyObject *result;
4380
4381 Py_BEGIN_ALLOW_THREADS
4382 hFile = CreateFileW(
4383 path->wide,
4384 0, /* desired access */
4385 0, /* share mode */
4386 NULL, /* security attributes */
4387 OPEN_EXISTING,
4388 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
4389 FILE_FLAG_BACKUP_SEMANTICS,
4390 NULL);
4391 Py_END_ALLOW_THREADS
4392
4393 if (hFile == INVALID_HANDLE_VALUE) {
4394 return win32_error_object("CreateFileW", path->object);
4395 }
4396
4397 /* We have a good handle to the target, use it to determine the
4398 target path name. */
4399 while (1) {
4400 Py_BEGIN_ALLOW_THREADS
4401 result_length = GetFinalPathNameByHandleW(hFile, target_path,
4402 buf_size, VOLUME_NAME_DOS);
4403 Py_END_ALLOW_THREADS
4404
4405 if (!result_length) {
4406 result = win32_error_object("GetFinalPathNameByHandleW",
4407 path->object);
4408 goto cleanup;
4409 }
4410
4411 if (result_length < buf_size) {
4412 break;
4413 }
4414
4415 wchar_t *tmp;
4416 tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
4417 result_length * sizeof(*tmp));
4418 if (!tmp) {
4419 result = PyErr_NoMemory();
4420 goto cleanup;
4421 }
4422
4423 buf_size = result_length;
4424 target_path = tmp;
4425 }
4426
4427 result = PyUnicode_FromWideChar(target_path, result_length);
4428 if (result && path->narrow) {
4429 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4430 }
4431
4432 cleanup:
4433 if (target_path != buf) {
4434 PyMem_Free(target_path);
4435 }
4436 CloseHandle(hFile);
4437 return result;
4438 }
4439
4440
4441 /*[clinic input]
4442 os._getvolumepathname
4443
4444 path: path_t
4445
4446 A helper function for ismount on Win32.
4447 [clinic start generated code]*/
4448
4449 static PyObject *
os__getvolumepathname_impl(PyObject *module, path_t *path)4450 os__getvolumepathname_impl(PyObject *module, path_t *path)
4451 /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
4452 {
4453 PyObject *result;
4454 wchar_t *mountpath=NULL;
4455 size_t buflen;
4456 BOOL ret;
4457
4458 /* Volume path should be shorter than entire path */
4459 buflen = Py_MAX(path->length, MAX_PATH);
4460
4461 if (buflen > PY_DWORD_MAX) {
4462 PyErr_SetString(PyExc_OverflowError, "path too long");
4463 return NULL;
4464 }
4465
4466 mountpath = PyMem_New(wchar_t, buflen);
4467 if (mountpath == NULL)
4468 return PyErr_NoMemory();
4469
4470 Py_BEGIN_ALLOW_THREADS
4471 ret = GetVolumePathNameW(path->wide, mountpath,
4472 Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
4473 Py_END_ALLOW_THREADS
4474
4475 if (!ret) {
4476 result = win32_error_object("_getvolumepathname", path->object);
4477 goto exit;
4478 }
4479 result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
4480 if (path->narrow)
4481 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4482
4483 exit:
4484 PyMem_Free(mountpath);
4485 return result;
4486 }
4487
4488
4489 /*[clinic input]
4490 os._path_splitroot
4491
4492 path: path_t
4493
4494 Removes everything after the root on Win32.
4495 [clinic start generated code]*/
4496
4497 static PyObject *
os__path_splitroot_impl(PyObject *module, path_t *path)4498 os__path_splitroot_impl(PyObject *module, path_t *path)
4499 /*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/
4500 {
4501 wchar_t *buffer;
4502 wchar_t *end;
4503 PyObject *result = NULL;
4504 HRESULT ret;
4505
4506 buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
4507 if (!buffer) {
4508 return NULL;
4509 }
4510 wcscpy(buffer, path->wide);
4511 for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
4512 *p = L'\\';
4513 }
4514
4515 Py_BEGIN_ALLOW_THREADS
4516 ret = PathCchSkipRoot(buffer, &end);
4517 Py_END_ALLOW_THREADS
4518 if (FAILED(ret)) {
4519 result = Py_BuildValue("sO", "", path->object);
4520 } else if (end != buffer) {
4521 size_t rootLen = (size_t)(end - buffer);
4522 result = Py_BuildValue("NN",
4523 PyUnicode_FromWideChar(path->wide, rootLen),
4524 PyUnicode_FromWideChar(path->wide + rootLen, -1)
4525 );
4526 } else {
4527 result = Py_BuildValue("Os", path->object, "");
4528 }
4529 PyMem_Free(buffer);
4530
4531 return result;
4532 }
4533
4534
4535 #endif /* MS_WINDOWS */
4536
4537
4538 /*[clinic input]
4539 os._path_normpath
4540
4541 path: object
4542
4543 Basic path normalization.
4544 [clinic start generated code]*/
4545
4546 static PyObject *
os__path_normpath_impl(PyObject *module, PyObject *path)4547 os__path_normpath_impl(PyObject *module, PyObject *path)
4548 /*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/
4549 {
4550 if (!PyUnicode_Check(path)) {
4551 PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'",
4552 Py_TYPE(path)->tp_name);
4553 return NULL;
4554 }
4555 Py_ssize_t len;
4556 wchar_t *buffer = PyUnicode_AsWideCharString(path, &len);
4557 if (!buffer) {
4558 return NULL;
4559 }
4560 Py_ssize_t norm_len;
4561 wchar_t *norm_path = _Py_normpath_and_size(buffer, len, &norm_len);
4562 PyObject *result = PyUnicode_FromWideChar(norm_path, norm_len);
4563 PyMem_Free(buffer);
4564 return result;
4565 }
4566
4567 /*[clinic input]
4568 os.mkdir
4569
4570 path : path_t
4571
4572 mode: int = 0o777
4573
4574 *
4575
4576 dir_fd : dir_fd(requires='mkdirat') = None
4577
4578 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4579
4580 Create a directory.
4581
4582 If dir_fd is not None, it should be a file descriptor open to a directory,
4583 and path should be relative; path will then be relative to that directory.
4584 dir_fd may not be implemented on your platform.
4585 If it is unavailable, using it will raise a NotImplementedError.
4586
4587 The mode argument is ignored on Windows. Where it is used, the current umask
4588 value is first masked out.
4589 [clinic start generated code]*/
4590
4591 static PyObject *
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)4592 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4593 /*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
4594 {
4595 int result;
4596 #ifdef MS_WINDOWS
4597 int error = 0;
4598 int pathError = 0;
4599 SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
4600 SECURITY_ATTRIBUTES *pSecAttr = NULL;
4601 #endif
4602 #ifdef HAVE_MKDIRAT
4603 int mkdirat_unavailable = 0;
4604 #endif
4605
4606 if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4607 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4608 return NULL;
4609 }
4610
4611 #ifdef MS_WINDOWS
4612 Py_BEGIN_ALLOW_THREADS
4613 if (mode == 0700 /* 0o700 */) {
4614 ULONG sdSize;
4615 pSecAttr = &secAttr;
4616 // Set a discretionary ACL (D) that is protected (P) and includes
4617 // inheritable (OICI) entries that allow (A) full control (FA) to
4618 // SYSTEM (SY), Administrators (BA), and the owner (OW).
4619 if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
4620 L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
4621 SDDL_REVISION_1,
4622 &secAttr.lpSecurityDescriptor,
4623 &sdSize
4624 )) {
4625 error = GetLastError();
4626 }
4627 }
4628 if (!error) {
4629 result = CreateDirectoryW(path->wide, pSecAttr);
4630 if (secAttr.lpSecurityDescriptor &&
4631 // uncommonly, LocalFree returns non-zero on error, but still uses
4632 // GetLastError() to see what the error code is
4633 LocalFree(secAttr.lpSecurityDescriptor)) {
4634 error = GetLastError();
4635 }
4636 }
4637 Py_END_ALLOW_THREADS
4638
4639 if (error) {
4640 return PyErr_SetFromWindowsErr(error);
4641 }
4642 if (!result) {
4643 return path_error(path);
4644 }
4645 #else
4646 Py_BEGIN_ALLOW_THREADS
4647 #if HAVE_MKDIRAT
4648 if (dir_fd != DEFAULT_DIR_FD) {
4649 if (HAVE_MKDIRAT_RUNTIME) {
4650 result = mkdirat(dir_fd, path->narrow, mode);
4651
4652 } else {
4653 mkdirat_unavailable = 1;
4654 }
4655 } else
4656 #endif
4657 #if defined(__WATCOMC__) && !defined(__QNX__)
4658 result = mkdir(path->narrow);
4659 #else
4660 result = mkdir(path->narrow, mode);
4661 #endif
4662 Py_END_ALLOW_THREADS
4663
4664 #if HAVE_MKDIRAT
4665 if (mkdirat_unavailable) {
4666 argument_unavailable_error(NULL, "dir_fd");
4667 return NULL;
4668 }
4669 #endif
4670
4671 if (result < 0)
4672 return path_error(path);
4673 #endif /* MS_WINDOWS */
4674 Py_RETURN_NONE;
4675 }
4676
4677
4678 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4679 #if defined(HAVE_SYS_RESOURCE_H)
4680 #include <sys/resource.h>
4681 #endif
4682
4683
4684 #ifdef HAVE_NICE
4685 /*[clinic input]
4686 os.nice
4687
4688 increment: int
4689 /
4690
4691 Add increment to the priority of process and return the new priority.
4692 [clinic start generated code]*/
4693
4694 static PyObject *
os_nice_impl(PyObject *module, int increment)4695 os_nice_impl(PyObject *module, int increment)
4696 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4697 {
4698 int value;
4699
4700 /* There are two flavours of 'nice': one that returns the new
4701 priority (as required by almost all standards out there) and the
4702 Linux/FreeBSD one, which returns '0' on success and advices
4703 the use of getpriority() to get the new priority.
4704
4705 If we are of the nice family that returns the new priority, we
4706 need to clear errno before the call, and check if errno is filled
4707 before calling posix_error() on a returnvalue of -1, because the
4708 -1 may be the actual new priority! */
4709
4710 errno = 0;
4711 value = nice(increment);
4712 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4713 if (value == 0)
4714 value = getpriority(PRIO_PROCESS, 0);
4715 #endif
4716 if (value == -1 && errno != 0)
4717 /* either nice() or getpriority() returned an error */
4718 return posix_error();
4719 return PyLong_FromLong((long) value);
4720 }
4721 #endif /* HAVE_NICE */
4722
4723
4724 #ifdef HAVE_GETPRIORITY
4725 /*[clinic input]
4726 os.getpriority
4727
4728 which: int
4729 who: int
4730
4731 Return program scheduling priority.
4732 [clinic start generated code]*/
4733
4734 static PyObject *
os_getpriority_impl(PyObject *module, int which, int who)4735 os_getpriority_impl(PyObject *module, int which, int who)
4736 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4737 {
4738 int retval;
4739
4740 errno = 0;
4741 retval = getpriority(which, who);
4742 if (errno != 0)
4743 return posix_error();
4744 return PyLong_FromLong((long)retval);
4745 }
4746 #endif /* HAVE_GETPRIORITY */
4747
4748
4749 #ifdef HAVE_SETPRIORITY
4750 /*[clinic input]
4751 os.setpriority
4752
4753 which: int
4754 who: int
4755 priority: int
4756
4757 Set program scheduling priority.
4758 [clinic start generated code]*/
4759
4760 static PyObject *
os_setpriority_impl(PyObject *module, int which, int who, int priority)4761 os_setpriority_impl(PyObject *module, int which, int who, int priority)
4762 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4763 {
4764 int retval;
4765
4766 retval = setpriority(which, who, priority);
4767 if (retval == -1)
4768 return posix_error();
4769 Py_RETURN_NONE;
4770 }
4771 #endif /* HAVE_SETPRIORITY */
4772
4773
4774 static PyObject *
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)4775 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4776 {
4777 const char *function_name = is_replace ? "replace" : "rename";
4778 int dir_fd_specified;
4779
4780 #ifdef HAVE_RENAMEAT
4781 int renameat_unavailable = 0;
4782 #endif
4783
4784 #ifdef MS_WINDOWS
4785 BOOL result;
4786 int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4787 #else
4788 int result;
4789 #endif
4790
4791 dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4792 (dst_dir_fd != DEFAULT_DIR_FD);
4793 #ifndef HAVE_RENAMEAT
4794 if (dir_fd_specified) {
4795 argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4796 return NULL;
4797 }
4798 #endif
4799
4800 if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
4801 src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4802 dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4803 return NULL;
4804 }
4805
4806 #ifdef MS_WINDOWS
4807 Py_BEGIN_ALLOW_THREADS
4808 result = MoveFileExW(src->wide, dst->wide, flags);
4809 Py_END_ALLOW_THREADS
4810
4811 if (!result)
4812 return path_error2(src, dst);
4813
4814 #else
4815 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4816 PyErr_Format(PyExc_ValueError,
4817 "%s: src and dst must be the same type", function_name);
4818 return NULL;
4819 }
4820
4821 Py_BEGIN_ALLOW_THREADS
4822 #ifdef HAVE_RENAMEAT
4823 if (dir_fd_specified) {
4824 if (HAVE_RENAMEAT_RUNTIME) {
4825 result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4826 } else {
4827 renameat_unavailable = 1;
4828 }
4829 } else
4830 #endif
4831 result = rename(src->narrow, dst->narrow);
4832 Py_END_ALLOW_THREADS
4833
4834
4835 #ifdef HAVE_RENAMEAT
4836 if (renameat_unavailable) {
4837 argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4838 return NULL;
4839 }
4840 #endif
4841
4842 if (result)
4843 return path_error2(src, dst);
4844 #endif
4845 Py_RETURN_NONE;
4846 }
4847
4848
4849 /*[clinic input]
4850 os.rename
4851
4852 src : path_t
4853 dst : path_t
4854 *
4855 src_dir_fd : dir_fd = None
4856 dst_dir_fd : dir_fd = None
4857
4858 Rename a file or directory.
4859
4860 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4861 descriptor open to a directory, and the respective path string (src or dst)
4862 should be relative; the path will then be relative to that directory.
4863 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4864 If they are unavailable, using them will raise a NotImplementedError.
4865 [clinic start generated code]*/
4866
4867 static PyObject *
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd)4868 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4869 int dst_dir_fd)
4870 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4871 {
4872 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4873 }
4874
4875
4876 /*[clinic input]
4877 os.replace = os.rename
4878
4879 Rename a file or directory, overwriting the destination.
4880
4881 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4882 descriptor open to a directory, and the respective path string (src or dst)
4883 should be relative; the path will then be relative to that directory.
4884 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4885 If they are unavailable, using them will raise a NotImplementedError.
4886 [clinic start generated code]*/
4887
4888 static PyObject *
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd)4889 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4890 int dst_dir_fd)
4891 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4892 {
4893 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4894 }
4895
4896
4897 /*[clinic input]
4898 os.rmdir
4899
4900 path: path_t
4901 *
4902 dir_fd: dir_fd(requires='unlinkat') = None
4903
4904 Remove a directory.
4905
4906 If dir_fd is not None, it should be a file descriptor open to a directory,
4907 and path should be relative; path will then be relative to that directory.
4908 dir_fd may not be implemented on your platform.
4909 If it is unavailable, using it will raise a NotImplementedError.
4910 [clinic start generated code]*/
4911
4912 static PyObject *
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)4913 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4914 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4915 {
4916 int result;
4917 #ifdef HAVE_UNLINKAT
4918 int unlinkat_unavailable = 0;
4919 #endif
4920
4921 if (PySys_Audit("os.rmdir", "Oi", path->object,
4922 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4923 return NULL;
4924 }
4925
4926 Py_BEGIN_ALLOW_THREADS
4927 #ifdef MS_WINDOWS
4928 /* Windows, success=1, UNIX, success=0 */
4929 result = !RemoveDirectoryW(path->wide);
4930 #else
4931 #ifdef HAVE_UNLINKAT
4932 if (dir_fd != DEFAULT_DIR_FD) {
4933 if (HAVE_UNLINKAT_RUNTIME) {
4934 result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4935 } else {
4936 unlinkat_unavailable = 1;
4937 result = -1;
4938 }
4939 } else
4940 #endif
4941 result = rmdir(path->narrow);
4942 #endif
4943 Py_END_ALLOW_THREADS
4944
4945 #ifdef HAVE_UNLINKAT
4946 if (unlinkat_unavailable) {
4947 argument_unavailable_error("rmdir", "dir_fd");
4948 return NULL;
4949 }
4950 #endif
4951
4952 if (result)
4953 return path_error(path);
4954
4955 Py_RETURN_NONE;
4956 }
4957
4958
4959 #ifdef HAVE_SYSTEM
4960 #ifdef MS_WINDOWS
4961 /*[clinic input]
4962 os.system -> long
4963
4964 command: Py_UNICODE
4965
4966 Execute the command in a subshell.
4967 [clinic start generated code]*/
4968
4969 static long
os_system_impl(PyObject *module, const Py_UNICODE *command)4970 os_system_impl(PyObject *module, const Py_UNICODE *command)
4971 /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4972 {
4973 long result;
4974
4975 if (PySys_Audit("os.system", "(u)", command) < 0) {
4976 return -1;
4977 }
4978
4979 Py_BEGIN_ALLOW_THREADS
4980 _Py_BEGIN_SUPPRESS_IPH
4981 result = _wsystem(command);
4982 _Py_END_SUPPRESS_IPH
4983 Py_END_ALLOW_THREADS
4984 return result;
4985 }
4986 #else /* MS_WINDOWS */
4987 /*[clinic input]
4988 os.system -> long
4989
4990 command: FSConverter
4991
4992 Execute the command in a subshell.
4993 [clinic start generated code]*/
4994
4995 static long
os_system_impl(PyObject *module, PyObject *command)4996 os_system_impl(PyObject *module, PyObject *command)
4997 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4998 {
4999 long result;
5000 const char *bytes = PyBytes_AsString(command);
5001
5002 if (PySys_Audit("os.system", "(O)", command) < 0) {
5003 return -1;
5004 }
5005
5006 Py_BEGIN_ALLOW_THREADS
5007 result = system(bytes);
5008 Py_END_ALLOW_THREADS
5009 return result;
5010 }
5011 #endif
5012 #endif /* HAVE_SYSTEM */
5013
5014
5015 #ifdef HAVE_UMASK
5016 /*[clinic input]
5017 os.umask
5018
5019 mask: int
5020 /
5021
5022 Set the current numeric umask and return the previous umask.
5023 [clinic start generated code]*/
5024
5025 static PyObject *
os_umask_impl(PyObject *module, int mask)5026 os_umask_impl(PyObject *module, int mask)
5027 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
5028 {
5029 int i = (int)umask(mask);
5030 if (i < 0)
5031 return posix_error();
5032 return PyLong_FromLong((long)i);
5033 }
5034 #endif
5035
5036 #ifdef MS_WINDOWS
5037
5038 /* override the default DeleteFileW behavior so that directory
5039 symlinks can be removed with this function, the same as with
5040 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)5041 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
5042 {
5043 WIN32_FILE_ATTRIBUTE_DATA info;
5044 WIN32_FIND_DATAW find_data;
5045 HANDLE find_data_handle;
5046 int is_directory = 0;
5047 int is_link = 0;
5048
5049 if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
5050 is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
5051
5052 /* Get WIN32_FIND_DATA structure for the path to determine if
5053 it is a symlink */
5054 if(is_directory &&
5055 info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
5056 find_data_handle = FindFirstFileW(lpFileName, &find_data);
5057
5058 if(find_data_handle != INVALID_HANDLE_VALUE) {
5059 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
5060 IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
5061 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
5062 find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
5063 FindClose(find_data_handle);
5064 }
5065 }
5066 }
5067
5068 if (is_directory && is_link)
5069 return RemoveDirectoryW(lpFileName);
5070
5071 return DeleteFileW(lpFileName);
5072 }
5073 #endif /* MS_WINDOWS */
5074
5075
5076 /*[clinic input]
5077 os.unlink
5078
5079 path: path_t
5080 *
5081 dir_fd: dir_fd(requires='unlinkat')=None
5082
5083 Remove a file (same as remove()).
5084
5085 If dir_fd is not None, it should be a file descriptor open to a directory,
5086 and path should be relative; path will then be relative to that directory.
5087 dir_fd may not be implemented on your platform.
5088 If it is unavailable, using it will raise a NotImplementedError.
5089
5090 [clinic start generated code]*/
5091
5092 static PyObject *
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)5093 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
5094 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
5095 {
5096 int result;
5097 #ifdef HAVE_UNLINKAT
5098 int unlinkat_unavailable = 0;
5099 #endif
5100
5101 if (PySys_Audit("os.remove", "Oi", path->object,
5102 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5103 return NULL;
5104 }
5105
5106 Py_BEGIN_ALLOW_THREADS
5107 _Py_BEGIN_SUPPRESS_IPH
5108 #ifdef MS_WINDOWS
5109 /* Windows, success=1, UNIX, success=0 */
5110 result = !Py_DeleteFileW(path->wide);
5111 #else
5112 #ifdef HAVE_UNLINKAT
5113 if (dir_fd != DEFAULT_DIR_FD) {
5114 if (HAVE_UNLINKAT_RUNTIME) {
5115
5116 result = unlinkat(dir_fd, path->narrow, 0);
5117 } else {
5118 unlinkat_unavailable = 1;
5119 }
5120 } else
5121 #endif /* HAVE_UNLINKAT */
5122 result = unlink(path->narrow);
5123 #endif
5124 _Py_END_SUPPRESS_IPH
5125 Py_END_ALLOW_THREADS
5126
5127 #ifdef HAVE_UNLINKAT
5128 if (unlinkat_unavailable) {
5129 argument_unavailable_error(NULL, "dir_fd");
5130 return NULL;
5131 }
5132 #endif
5133
5134 if (result)
5135 return path_error(path);
5136
5137 Py_RETURN_NONE;
5138 }
5139
5140
5141 /*[clinic input]
5142 os.remove = os.unlink
5143
5144 Remove a file (same as unlink()).
5145
5146 If dir_fd is not None, it should be a file descriptor open to a directory,
5147 and path should be relative; path will then be relative to that directory.
5148 dir_fd may not be implemented on your platform.
5149 If it is unavailable, using it will raise a NotImplementedError.
5150 [clinic start generated code]*/
5151
5152 static PyObject *
os_remove_impl(PyObject *module, path_t *path, int dir_fd)5153 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
5154 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
5155 {
5156 return os_unlink_impl(module, path, dir_fd);
5157 }
5158
5159
5160 static PyStructSequence_Field uname_result_fields[] = {
5161 {"sysname", "operating system name"},
5162 {"nodename", "name of machine on network (implementation-defined)"},
5163 {"release", "operating system release"},
5164 {"version", "operating system version"},
5165 {"machine", "hardware identifier"},
5166 {NULL}
5167 };
5168
5169 PyDoc_STRVAR(uname_result__doc__,
5170 "uname_result: Result from os.uname().\n\n\
5171 This object may be accessed either as a tuple of\n\
5172 (sysname, nodename, release, version, machine),\n\
5173 or via the attributes sysname, nodename, release, version, and machine.\n\
5174 \n\
5175 See os.uname for more information.");
5176
5177 static PyStructSequence_Desc uname_result_desc = {
5178 MODNAME ".uname_result", /* name */
5179 uname_result__doc__, /* doc */
5180 uname_result_fields,
5181 5
5182 };
5183
5184 #ifdef HAVE_UNAME
5185 /*[clinic input]
5186 os.uname
5187
5188 Return an object identifying the current operating system.
5189
5190 The object behaves like a named tuple with the following fields:
5191 (sysname, nodename, release, version, machine)
5192
5193 [clinic start generated code]*/
5194
5195 static PyObject *
os_uname_impl(PyObject *module)5196 os_uname_impl(PyObject *module)
5197 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
5198 {
5199 struct utsname u;
5200 int res;
5201 PyObject *value;
5202
5203 Py_BEGIN_ALLOW_THREADS
5204 res = uname(&u);
5205 Py_END_ALLOW_THREADS
5206 if (res < 0)
5207 return posix_error();
5208
5209 PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
5210 value = PyStructSequence_New((PyTypeObject *)UnameResultType);
5211 if (value == NULL)
5212 return NULL;
5213
5214 #define SET(i, field) \
5215 { \
5216 PyObject *o = PyUnicode_DecodeFSDefault(field); \
5217 if (!o) { \
5218 Py_DECREF(value); \
5219 return NULL; \
5220 } \
5221 PyStructSequence_SET_ITEM(value, i, o); \
5222 } \
5223
5224 SET(0, u.sysname);
5225 SET(1, u.nodename);
5226 SET(2, u.release);
5227 SET(3, u.version);
5228 SET(4, u.machine);
5229
5230 #undef SET
5231
5232 return value;
5233 }
5234 #endif /* HAVE_UNAME */
5235
5236
5237
5238 typedef struct {
5239 int now;
5240 time_t atime_s;
5241 long atime_ns;
5242 time_t mtime_s;
5243 long mtime_ns;
5244 } utime_t;
5245
5246 /*
5247 * these macros assume that "ut" is a pointer to a utime_t
5248 * they also intentionally leak the declaration of a pointer named "time"
5249 */
5250 #define UTIME_TO_TIMESPEC \
5251 struct timespec ts[2]; \
5252 struct timespec *time; \
5253 if (ut->now) \
5254 time = NULL; \
5255 else { \
5256 ts[0].tv_sec = ut->atime_s; \
5257 ts[0].tv_nsec = ut->atime_ns; \
5258 ts[1].tv_sec = ut->mtime_s; \
5259 ts[1].tv_nsec = ut->mtime_ns; \
5260 time = ts; \
5261 } \
5262
5263 #define UTIME_TO_TIMEVAL \
5264 struct timeval tv[2]; \
5265 struct timeval *time; \
5266 if (ut->now) \
5267 time = NULL; \
5268 else { \
5269 tv[0].tv_sec = ut->atime_s; \
5270 tv[0].tv_usec = ut->atime_ns / 1000; \
5271 tv[1].tv_sec = ut->mtime_s; \
5272 tv[1].tv_usec = ut->mtime_ns / 1000; \
5273 time = tv; \
5274 } \
5275
5276 #define UTIME_TO_UTIMBUF \
5277 struct utimbuf u; \
5278 struct utimbuf *time; \
5279 if (ut->now) \
5280 time = NULL; \
5281 else { \
5282 u.actime = ut->atime_s; \
5283 u.modtime = ut->mtime_s; \
5284 time = &u; \
5285 }
5286
5287 #define UTIME_TO_TIME_T \
5288 time_t timet[2]; \
5289 time_t *time; \
5290 if (ut->now) \
5291 time = NULL; \
5292 else { \
5293 timet[0] = ut->atime_s; \
5294 timet[1] = ut->mtime_s; \
5295 time = timet; \
5296 } \
5297
5298
5299 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5300
5301 static int
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)5302 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
5303 {
5304 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5305 if (HAVE_UTIMENSAT_RUNTIME) {
5306 int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5307 UTIME_TO_TIMESPEC;
5308 return utimensat(dir_fd, path, time, flags);
5309 } else {
5310 errno = ENOSYS;
5311 return -1;
5312 }
5313 #elif defined(HAVE_UTIMENSAT)
5314 int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5315 UTIME_TO_TIMESPEC;
5316 return utimensat(dir_fd, path, time, flags);
5317 #elif defined(HAVE_FUTIMESAT)
5318 UTIME_TO_TIMEVAL;
5319 /*
5320 * follow_symlinks will never be false here;
5321 * we only allow !follow_symlinks and dir_fd together
5322 * if we have utimensat()
5323 */
5324 assert(follow_symlinks);
5325 return futimesat(dir_fd, path, time);
5326 #endif
5327 }
5328
5329 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
5330 #else
5331 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
5332 #endif
5333
5334 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5335
5336 static int
utime_fd(utime_t *ut, int fd)5337 utime_fd(utime_t *ut, int fd)
5338 {
5339 #ifdef HAVE_FUTIMENS
5340
5341 if (HAVE_FUTIMENS_RUNTIME) {
5342
5343 UTIME_TO_TIMESPEC;
5344 return futimens(fd, time);
5345
5346 } else
5347 #ifndef HAVE_FUTIMES
5348 {
5349 /* Not sure if this can happen */
5350 PyErr_SetString(
5351 PyExc_RuntimeError,
5352 "neither futimens nor futimes are supported"
5353 " on this system");
5354 return -1;
5355 }
5356 #endif
5357
5358 #endif
5359 #ifdef HAVE_FUTIMES
5360 {
5361 UTIME_TO_TIMEVAL;
5362 return futimes(fd, time);
5363 }
5364 #endif
5365 }
5366
5367 #define PATH_UTIME_HAVE_FD 1
5368 #else
5369 #define PATH_UTIME_HAVE_FD 0
5370 #endif
5371
5372 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
5373 # define UTIME_HAVE_NOFOLLOW_SYMLINKS
5374 #endif
5375
5376 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5377
5378 static int
utime_nofollow_symlinks(utime_t *ut, const char *path)5379 utime_nofollow_symlinks(utime_t *ut, const char *path)
5380 {
5381 #ifdef HAVE_UTIMENSAT
5382 if (HAVE_UTIMENSAT_RUNTIME) {
5383 UTIME_TO_TIMESPEC;
5384 return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
5385 } else
5386 #ifndef HAVE_LUTIMES
5387 {
5388 /* Not sure if this can happen */
5389 PyErr_SetString(
5390 PyExc_RuntimeError,
5391 "neither utimensat nor lutimes are supported"
5392 " on this system");
5393 return -1;
5394 }
5395 #endif
5396 #endif
5397
5398 #ifdef HAVE_LUTIMES
5399 {
5400 UTIME_TO_TIMEVAL;
5401 return lutimes(path, time);
5402 }
5403 #endif
5404 }
5405
5406 #endif
5407
5408 #ifndef MS_WINDOWS
5409
5410 static int
utime_default(utime_t *ut, const char *path)5411 utime_default(utime_t *ut, const char *path)
5412 {
5413 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5414 if (HAVE_UTIMENSAT_RUNTIME) {
5415 UTIME_TO_TIMESPEC;
5416 return utimensat(DEFAULT_DIR_FD, path, time, 0);
5417 } else {
5418 UTIME_TO_TIMEVAL;
5419 return utimes(path, time);
5420 }
5421 #elif defined(HAVE_UTIMENSAT)
5422 UTIME_TO_TIMESPEC;
5423 return utimensat(DEFAULT_DIR_FD, path, time, 0);
5424 #elif defined(HAVE_UTIMES)
5425 UTIME_TO_TIMEVAL;
5426 return utimes(path, time);
5427 #elif defined(HAVE_UTIME_H)
5428 UTIME_TO_UTIMBUF;
5429 return utime(path, time);
5430 #else
5431 UTIME_TO_TIME_T;
5432 return utime(path, time);
5433 #endif
5434 }
5435
5436 #endif
5437
5438 static int
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)5439 split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5440 {
5441 int result = 0;
5442 PyObject *divmod;
5443 divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5444 if (!divmod)
5445 goto exit;
5446 if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
5447 PyErr_Format(PyExc_TypeError,
5448 "%.200s.__divmod__() must return a 2-tuple, not %.200s",
5449 _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
5450 goto exit;
5451 }
5452 *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5453 if ((*s == -1) && PyErr_Occurred())
5454 goto exit;
5455 *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5456 if ((*ns == -1) && PyErr_Occurred())
5457 goto exit;
5458
5459 result = 1;
5460 exit:
5461 Py_XDECREF(divmod);
5462 return result;
5463 }
5464
5465
5466 /*[clinic input]
5467 os.utime
5468
5469 path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
5470 times: object = None
5471 *
5472 ns: object = NULL
5473 dir_fd: dir_fd(requires='futimensat') = None
5474 follow_symlinks: bool=True
5475
5476 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
5477
5478 Set the access and modified time of path.
5479
5480 path may always be specified as a string.
5481 On some platforms, path may also be specified as an open file descriptor.
5482 If this functionality is unavailable, using it raises an exception.
5483
5484 If times is not None, it must be a tuple (atime, mtime);
5485 atime and mtime should be expressed as float seconds since the epoch.
5486 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
5487 atime_ns and mtime_ns should be expressed as integer nanoseconds
5488 since the epoch.
5489 If times is None and ns is unspecified, utime uses the current time.
5490 Specifying tuples for both times and ns is an error.
5491
5492 If dir_fd is not None, it should be a file descriptor open to a directory,
5493 and path should be relative; path will then be relative to that directory.
5494 If follow_symlinks is False, and the last element of the path is a symbolic
5495 link, utime will modify the symbolic link itself instead of the file the
5496 link points to.
5497 It is an error to use dir_fd or follow_symlinks when specifying path
5498 as an open file descriptor.
5499 dir_fd and follow_symlinks may not be available on your platform.
5500 If they are unavailable, using them will raise a NotImplementedError.
5501
5502 [clinic start generated code]*/
5503
5504 static PyObject *
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, int dir_fd, int follow_symlinks)5505 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
5506 int dir_fd, int follow_symlinks)
5507 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
5508 {
5509 #ifdef MS_WINDOWS
5510 HANDLE hFile;
5511 FILETIME atime, mtime;
5512 #else
5513 int result;
5514 #endif
5515
5516 utime_t utime;
5517
5518 memset(&utime, 0, sizeof(utime_t));
5519
5520 if (times != Py_None && ns) {
5521 PyErr_SetString(PyExc_ValueError,
5522 "utime: you may specify either 'times'"
5523 " or 'ns' but not both");
5524 return NULL;
5525 }
5526
5527 if (times != Py_None) {
5528 time_t a_sec, m_sec;
5529 long a_nsec, m_nsec;
5530 if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
5531 PyErr_SetString(PyExc_TypeError,
5532 "utime: 'times' must be either"
5533 " a tuple of two ints or None");
5534 return NULL;
5535 }
5536 utime.now = 0;
5537 if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
5538 &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
5539 _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
5540 &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
5541 return NULL;
5542 }
5543 utime.atime_s = a_sec;
5544 utime.atime_ns = a_nsec;
5545 utime.mtime_s = m_sec;
5546 utime.mtime_ns = m_nsec;
5547 }
5548 else if (ns) {
5549 if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
5550 PyErr_SetString(PyExc_TypeError,
5551 "utime: 'ns' must be a tuple of two ints");
5552 return NULL;
5553 }
5554 utime.now = 0;
5555 if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
5556 &utime.atime_s, &utime.atime_ns) ||
5557 !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
5558 &utime.mtime_s, &utime.mtime_ns)) {
5559 return NULL;
5560 }
5561 }
5562 else {
5563 /* times and ns are both None/unspecified. use "now". */
5564 utime.now = 1;
5565 }
5566
5567 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
5568 if (follow_symlinks_specified("utime", follow_symlinks))
5569 return NULL;
5570 #endif
5571
5572 if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
5573 dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
5574 fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
5575 return NULL;
5576
5577 #if !defined(HAVE_UTIMENSAT)
5578 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
5579 PyErr_SetString(PyExc_ValueError,
5580 "utime: cannot use dir_fd and follow_symlinks "
5581 "together on this platform");
5582 return NULL;
5583 }
5584 #endif
5585
5586 if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
5587 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5588 return NULL;
5589 }
5590
5591 #ifdef MS_WINDOWS
5592 Py_BEGIN_ALLOW_THREADS
5593 hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
5594 NULL, OPEN_EXISTING,
5595 FILE_FLAG_BACKUP_SEMANTICS, NULL);
5596 Py_END_ALLOW_THREADS
5597 if (hFile == INVALID_HANDLE_VALUE) {
5598 path_error(path);
5599 return NULL;
5600 }
5601
5602 if (utime.now) {
5603 GetSystemTimeAsFileTime(&mtime);
5604 atime = mtime;
5605 }
5606 else {
5607 _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
5608 _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
5609 }
5610 if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
5611 /* Avoid putting the file name into the error here,
5612 as that may confuse the user into believing that
5613 something is wrong with the file, when it also
5614 could be the time stamp that gives a problem. */
5615 PyErr_SetFromWindowsErr(0);
5616 CloseHandle(hFile);
5617 return NULL;
5618 }
5619 CloseHandle(hFile);
5620 #else /* MS_WINDOWS */
5621 Py_BEGIN_ALLOW_THREADS
5622
5623 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5624 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
5625 result = utime_nofollow_symlinks(&utime, path->narrow);
5626 else
5627 #endif
5628
5629 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5630 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
5631 result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
5632
5633 } else
5634 #endif
5635
5636 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5637 if (path->fd != -1)
5638 result = utime_fd(&utime, path->fd);
5639 else
5640 #endif
5641
5642 result = utime_default(&utime, path->narrow);
5643
5644 Py_END_ALLOW_THREADS
5645
5646 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5647 /* See utime_dir_fd implementation */
5648 if (result == -1 && errno == ENOSYS) {
5649 argument_unavailable_error(NULL, "dir_fd");
5650 return NULL;
5651 }
5652 #endif
5653
5654 if (result < 0) {
5655 /* see previous comment about not putting filename in error here */
5656 posix_error();
5657 return NULL;
5658 }
5659
5660 #endif /* MS_WINDOWS */
5661
5662 Py_RETURN_NONE;
5663 }
5664
5665 /* Process operations */
5666
5667
5668 /*[clinic input]
5669 os._exit
5670
5671 status: int
5672
5673 Exit to the system with specified status, without normal exit processing.
5674 [clinic start generated code]*/
5675
5676 static PyObject *
os__exit_impl(PyObject *module, int status)5677 os__exit_impl(PyObject *module, int status)
5678 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5679 {
5680 _exit(status);
5681 return NULL; /* Make gcc -Wall happy */
5682 }
5683
5684 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5685 #define EXECV_CHAR wchar_t
5686 #else
5687 #define EXECV_CHAR char
5688 #endif
5689
5690 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5691 static void
free_string_array(EXECV_CHAR **array, Py_ssize_t count)5692 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5693 {
5694 Py_ssize_t i;
5695 for (i = 0; i < count; i++)
5696 PyMem_Free(array[i]);
5697 PyMem_Free(array);
5698 }
5699
5700 static int
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)5701 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5702 {
5703 Py_ssize_t size;
5704 PyObject *ub;
5705 int result = 0;
5706 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5707 if (!PyUnicode_FSDecoder(o, &ub))
5708 return 0;
5709 *out = PyUnicode_AsWideCharString(ub, &size);
5710 if (*out)
5711 result = 1;
5712 #else
5713 if (!PyUnicode_FSConverter(o, &ub))
5714 return 0;
5715 size = PyBytes_GET_SIZE(ub);
5716 *out = PyMem_Malloc(size + 1);
5717 if (*out) {
5718 memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5719 result = 1;
5720 } else
5721 PyErr_NoMemory();
5722 #endif
5723 Py_DECREF(ub);
5724 return result;
5725 }
5726 #endif
5727
5728 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5729 static EXECV_CHAR**
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)5730 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5731 {
5732 Py_ssize_t i, pos, envc;
5733 PyObject *keys=NULL, *vals=NULL;
5734 PyObject *key, *val, *key2, *val2, *keyval;
5735 EXECV_CHAR **envlist;
5736
5737 i = PyMapping_Size(env);
5738 if (i < 0)
5739 return NULL;
5740 envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5741 if (envlist == NULL) {
5742 PyErr_NoMemory();
5743 return NULL;
5744 }
5745 envc = 0;
5746 keys = PyMapping_Keys(env);
5747 if (!keys)
5748 goto error;
5749 vals = PyMapping_Values(env);
5750 if (!vals)
5751 goto error;
5752 if (!PyList_Check(keys) || !PyList_Check(vals)) {
5753 PyErr_Format(PyExc_TypeError,
5754 "env.keys() or env.values() is not a list");
5755 goto error;
5756 }
5757
5758 for (pos = 0; pos < i; pos++) {
5759 key = PyList_GetItem(keys, pos);
5760 val = PyList_GetItem(vals, pos);
5761 if (!key || !val)
5762 goto error;
5763
5764 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5765 if (!PyUnicode_FSDecoder(key, &key2))
5766 goto error;
5767 if (!PyUnicode_FSDecoder(val, &val2)) {
5768 Py_DECREF(key2);
5769 goto error;
5770 }
5771 /* Search from index 1 because on Windows starting '=' is allowed for
5772 defining hidden environment variables. */
5773 if (PyUnicode_GET_LENGTH(key2) == 0 ||
5774 PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5775 {
5776 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5777 Py_DECREF(key2);
5778 Py_DECREF(val2);
5779 goto error;
5780 }
5781 keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5782 #else
5783 if (!PyUnicode_FSConverter(key, &key2))
5784 goto error;
5785 if (!PyUnicode_FSConverter(val, &val2)) {
5786 Py_DECREF(key2);
5787 goto error;
5788 }
5789 if (PyBytes_GET_SIZE(key2) == 0 ||
5790 strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5791 {
5792 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5793 Py_DECREF(key2);
5794 Py_DECREF(val2);
5795 goto error;
5796 }
5797 keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5798 PyBytes_AS_STRING(val2));
5799 #endif
5800 Py_DECREF(key2);
5801 Py_DECREF(val2);
5802 if (!keyval)
5803 goto error;
5804
5805 if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5806 Py_DECREF(keyval);
5807 goto error;
5808 }
5809
5810 Py_DECREF(keyval);
5811 }
5812 Py_DECREF(vals);
5813 Py_DECREF(keys);
5814
5815 envlist[envc] = 0;
5816 *envc_ptr = envc;
5817 return envlist;
5818
5819 error:
5820 Py_XDECREF(keys);
5821 Py_XDECREF(vals);
5822 free_string_array(envlist, envc);
5823 return NULL;
5824 }
5825
5826 static EXECV_CHAR**
parse_arglist(PyObject* argv, Py_ssize_t *argc)5827 parse_arglist(PyObject* argv, Py_ssize_t *argc)
5828 {
5829 int i;
5830 EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5831 if (argvlist == NULL) {
5832 PyErr_NoMemory();
5833 return NULL;
5834 }
5835 for (i = 0; i < *argc; i++) {
5836 PyObject* item = PySequence_ITEM(argv, i);
5837 if (item == NULL)
5838 goto fail;
5839 if (!fsconvert_strdup(item, &argvlist[i])) {
5840 Py_DECREF(item);
5841 goto fail;
5842 }
5843 Py_DECREF(item);
5844 }
5845 argvlist[*argc] = NULL;
5846 return argvlist;
5847 fail:
5848 *argc = i;
5849 free_string_array(argvlist, *argc);
5850 return NULL;
5851 }
5852
5853 #endif
5854
5855
5856 #ifdef HAVE_EXECV
5857 /*[clinic input]
5858 os.execv
5859
5860 path: path_t
5861 Path of executable file.
5862 argv: object
5863 Tuple or list of strings.
5864 /
5865
5866 Execute an executable path with arguments, replacing current process.
5867 [clinic start generated code]*/
5868
5869 static PyObject *
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)5870 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5871 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5872 {
5873 EXECV_CHAR **argvlist;
5874 Py_ssize_t argc;
5875
5876 /* execv has two arguments: (path, argv), where
5877 argv is a list or tuple of strings. */
5878
5879 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5880 PyErr_SetString(PyExc_TypeError,
5881 "execv() arg 2 must be a tuple or list");
5882 return NULL;
5883 }
5884 argc = PySequence_Size(argv);
5885 if (argc < 1) {
5886 PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5887 return NULL;
5888 }
5889
5890 argvlist = parse_arglist(argv, &argc);
5891 if (argvlist == NULL) {
5892 return NULL;
5893 }
5894 if (!argvlist[0][0]) {
5895 PyErr_SetString(PyExc_ValueError,
5896 "execv() arg 2 first element cannot be empty");
5897 free_string_array(argvlist, argc);
5898 return NULL;
5899 }
5900
5901 if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5902 free_string_array(argvlist, argc);
5903 return NULL;
5904 }
5905
5906 _Py_BEGIN_SUPPRESS_IPH
5907 #ifdef HAVE_WEXECV
5908 _wexecv(path->wide, argvlist);
5909 #else
5910 execv(path->narrow, argvlist);
5911 #endif
5912 _Py_END_SUPPRESS_IPH
5913
5914 /* If we get here it's definitely an error */
5915
5916 free_string_array(argvlist, argc);
5917 return posix_error();
5918 }
5919
5920
5921 /*[clinic input]
5922 os.execve
5923
5924 path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5925 Path of executable file.
5926 argv: object
5927 Tuple or list of strings.
5928 env: object
5929 Dictionary of strings mapping to strings.
5930
5931 Execute an executable path with arguments, replacing current process.
5932 [clinic start generated code]*/
5933
5934 static PyObject *
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)5935 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5936 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5937 {
5938 EXECV_CHAR **argvlist = NULL;
5939 EXECV_CHAR **envlist;
5940 Py_ssize_t argc, envc;
5941
5942 /* execve has three arguments: (path, argv, env), where
5943 argv is a list or tuple of strings and env is a dictionary
5944 like posix.environ. */
5945
5946 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5947 PyErr_SetString(PyExc_TypeError,
5948 "execve: argv must be a tuple or list");
5949 goto fail_0;
5950 }
5951 argc = PySequence_Size(argv);
5952 if (argc < 1) {
5953 PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5954 return NULL;
5955 }
5956
5957 if (!PyMapping_Check(env)) {
5958 PyErr_SetString(PyExc_TypeError,
5959 "execve: environment must be a mapping object");
5960 goto fail_0;
5961 }
5962
5963 argvlist = parse_arglist(argv, &argc);
5964 if (argvlist == NULL) {
5965 goto fail_0;
5966 }
5967 if (!argvlist[0][0]) {
5968 PyErr_SetString(PyExc_ValueError,
5969 "execve: argv first element cannot be empty");
5970 goto fail_0;
5971 }
5972
5973 envlist = parse_envlist(env, &envc);
5974 if (envlist == NULL)
5975 goto fail_0;
5976
5977 if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5978 goto fail_1;
5979 }
5980
5981 _Py_BEGIN_SUPPRESS_IPH
5982 #ifdef HAVE_FEXECVE
5983 if (path->fd > -1)
5984 fexecve(path->fd, argvlist, envlist);
5985 else
5986 #endif
5987 #ifdef HAVE_WEXECV
5988 _wexecve(path->wide, argvlist, envlist);
5989 #else
5990 execve(path->narrow, argvlist, envlist);
5991 #endif
5992 _Py_END_SUPPRESS_IPH
5993
5994 /* If we get here it's definitely an error */
5995
5996 posix_path_error(path);
5997 fail_1:
5998 free_string_array(envlist, envc);
5999 fail_0:
6000 if (argvlist)
6001 free_string_array(argvlist, argc);
6002 return NULL;
6003 }
6004
6005 #endif /* HAVE_EXECV */
6006
6007 #ifdef HAVE_POSIX_SPAWN
6008
6009 enum posix_spawn_file_actions_identifier {
6010 POSIX_SPAWN_OPEN,
6011 POSIX_SPAWN_CLOSE,
6012 POSIX_SPAWN_DUP2
6013 };
6014
6015 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6016 static int
6017 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
6018 #endif
6019
6020 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)6021 parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
6022 int resetids, int setsid, PyObject *setsigmask,
6023 PyObject *setsigdef, PyObject *scheduler,
6024 posix_spawnattr_t *attrp)
6025 {
6026 long all_flags = 0;
6027
6028 errno = posix_spawnattr_init(attrp);
6029 if (errno) {
6030 posix_error();
6031 return -1;
6032 }
6033
6034 if (setpgroup) {
6035 pid_t pgid = PyLong_AsPid(setpgroup);
6036 if (pgid == (pid_t)-1 && PyErr_Occurred()) {
6037 goto fail;
6038 }
6039 errno = posix_spawnattr_setpgroup(attrp, pgid);
6040 if (errno) {
6041 posix_error();
6042 goto fail;
6043 }
6044 all_flags |= POSIX_SPAWN_SETPGROUP;
6045 }
6046
6047 if (resetids) {
6048 all_flags |= POSIX_SPAWN_RESETIDS;
6049 }
6050
6051 if (setsid) {
6052 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
6053 if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
6054 #endif
6055 #ifdef POSIX_SPAWN_SETSID
6056 all_flags |= POSIX_SPAWN_SETSID;
6057 #elif defined(POSIX_SPAWN_SETSID_NP)
6058 all_flags |= POSIX_SPAWN_SETSID_NP;
6059 #else
6060 argument_unavailable_error(func_name, "setsid");
6061 return -1;
6062 #endif
6063
6064 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
6065 } else {
6066 argument_unavailable_error(func_name, "setsid");
6067 return -1;
6068 }
6069 #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
6070
6071 }
6072
6073 #ifdef HAVE_SIGSET_T
6074 if (setsigmask) {
6075 sigset_t set;
6076 if (!_Py_Sigset_Converter(setsigmask, &set)) {
6077 goto fail;
6078 }
6079 errno = posix_spawnattr_setsigmask(attrp, &set);
6080 if (errno) {
6081 posix_error();
6082 goto fail;
6083 }
6084 all_flags |= POSIX_SPAWN_SETSIGMASK;
6085 }
6086
6087 if (setsigdef) {
6088 sigset_t set;
6089 if (!_Py_Sigset_Converter(setsigdef, &set)) {
6090 goto fail;
6091 }
6092 errno = posix_spawnattr_setsigdefault(attrp, &set);
6093 if (errno) {
6094 posix_error();
6095 goto fail;
6096 }
6097 all_flags |= POSIX_SPAWN_SETSIGDEF;
6098 }
6099 #else
6100 if (setsigmask || setsigdef) {
6101 PyErr_SetString(PyExc_NotImplementedError,
6102 "sigset is not supported on this platform");
6103 goto fail;
6104 }
6105 #endif
6106
6107 if (scheduler) {
6108 #ifdef POSIX_SPAWN_SETSCHEDULER
6109 PyObject *py_schedpolicy;
6110 PyObject *schedparam_obj;
6111 struct sched_param schedparam;
6112
6113 if (!PyArg_ParseTuple(scheduler, "OO"
6114 ";A scheduler tuple must have two elements",
6115 &py_schedpolicy, &schedparam_obj)) {
6116 goto fail;
6117 }
6118 if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
6119 goto fail;
6120 }
6121 if (py_schedpolicy != Py_None) {
6122 int schedpolicy = _PyLong_AsInt(py_schedpolicy);
6123
6124 if (schedpolicy == -1 && PyErr_Occurred()) {
6125 goto fail;
6126 }
6127 errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
6128 if (errno) {
6129 posix_error();
6130 goto fail;
6131 }
6132 all_flags |= POSIX_SPAWN_SETSCHEDULER;
6133 }
6134 errno = posix_spawnattr_setschedparam(attrp, &schedparam);
6135 if (errno) {
6136 posix_error();
6137 goto fail;
6138 }
6139 all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
6140 #else
6141 PyErr_SetString(PyExc_NotImplementedError,
6142 "The scheduler option is not supported in this system.");
6143 goto fail;
6144 #endif
6145 }
6146
6147 errno = posix_spawnattr_setflags(attrp, all_flags);
6148 if (errno) {
6149 posix_error();
6150 goto fail;
6151 }
6152
6153 return 0;
6154
6155 fail:
6156 (void)posix_spawnattr_destroy(attrp);
6157 return -1;
6158 }
6159
6160 static int
parse_file_actions(PyObject *file_actions, posix_spawn_file_actions_t *file_actionsp, PyObject *temp_buffer)6161 parse_file_actions(PyObject *file_actions,
6162 posix_spawn_file_actions_t *file_actionsp,
6163 PyObject *temp_buffer)
6164 {
6165 PyObject *seq;
6166 PyObject *file_action = NULL;
6167 PyObject *tag_obj;
6168
6169 seq = PySequence_Fast(file_actions,
6170 "file_actions must be a sequence or None");
6171 if (seq == NULL) {
6172 return -1;
6173 }
6174
6175 errno = posix_spawn_file_actions_init(file_actionsp);
6176 if (errno) {
6177 posix_error();
6178 Py_DECREF(seq);
6179 return -1;
6180 }
6181
6182 for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
6183 file_action = PySequence_Fast_GET_ITEM(seq, i);
6184 Py_INCREF(file_action);
6185 if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
6186 PyErr_SetString(PyExc_TypeError,
6187 "Each file_actions element must be a non-empty tuple");
6188 goto fail;
6189 }
6190 long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
6191 if (tag == -1 && PyErr_Occurred()) {
6192 goto fail;
6193 }
6194
6195 /* Populate the file_actions object */
6196 switch (tag) {
6197 case POSIX_SPAWN_OPEN: {
6198 int fd, oflag;
6199 PyObject *path;
6200 unsigned long mode;
6201 if (!PyArg_ParseTuple(file_action, "OiO&ik"
6202 ";A open file_action tuple must have 5 elements",
6203 &tag_obj, &fd, PyUnicode_FSConverter, &path,
6204 &oflag, &mode))
6205 {
6206 goto fail;
6207 }
6208 if (PyList_Append(temp_buffer, path)) {
6209 Py_DECREF(path);
6210 goto fail;
6211 }
6212 errno = posix_spawn_file_actions_addopen(file_actionsp,
6213 fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
6214 Py_DECREF(path);
6215 if (errno) {
6216 posix_error();
6217 goto fail;
6218 }
6219 break;
6220 }
6221 case POSIX_SPAWN_CLOSE: {
6222 int fd;
6223 if (!PyArg_ParseTuple(file_action, "Oi"
6224 ";A close file_action tuple must have 2 elements",
6225 &tag_obj, &fd))
6226 {
6227 goto fail;
6228 }
6229 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
6230 if (errno) {
6231 posix_error();
6232 goto fail;
6233 }
6234 break;
6235 }
6236 case POSIX_SPAWN_DUP2: {
6237 int fd1, fd2;
6238 if (!PyArg_ParseTuple(file_action, "Oii"
6239 ";A dup2 file_action tuple must have 3 elements",
6240 &tag_obj, &fd1, &fd2))
6241 {
6242 goto fail;
6243 }
6244 errno = posix_spawn_file_actions_adddup2(file_actionsp,
6245 fd1, fd2);
6246 if (errno) {
6247 posix_error();
6248 goto fail;
6249 }
6250 break;
6251 }
6252 default: {
6253 PyErr_SetString(PyExc_TypeError,
6254 "Unknown file_actions identifier");
6255 goto fail;
6256 }
6257 }
6258 Py_DECREF(file_action);
6259 }
6260
6261 Py_DECREF(seq);
6262 return 0;
6263
6264 fail:
6265 Py_DECREF(seq);
6266 Py_DECREF(file_action);
6267 (void)posix_spawn_file_actions_destroy(file_actionsp);
6268 return -1;
6269 }
6270
6271
6272 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)6273 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
6274 PyObject *env, PyObject *file_actions,
6275 PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
6276 PyObject *setsigdef, PyObject *scheduler)
6277 {
6278 const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
6279 EXECV_CHAR **argvlist = NULL;
6280 EXECV_CHAR **envlist = NULL;
6281 posix_spawn_file_actions_t file_actions_buf;
6282 posix_spawn_file_actions_t *file_actionsp = NULL;
6283 posix_spawnattr_t attr;
6284 posix_spawnattr_t *attrp = NULL;
6285 Py_ssize_t argc, envc;
6286 PyObject *result = NULL;
6287 PyObject *temp_buffer = NULL;
6288 pid_t pid;
6289 int err_code;
6290
6291 /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
6292 argv is a list or tuple of strings and env is a dictionary
6293 like posix.environ. */
6294
6295 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6296 PyErr_Format(PyExc_TypeError,
6297 "%s: argv must be a tuple or list", func_name);
6298 goto exit;
6299 }
6300 argc = PySequence_Size(argv);
6301 if (argc < 1) {
6302 PyErr_Format(PyExc_ValueError,
6303 "%s: argv must not be empty", func_name);
6304 return NULL;
6305 }
6306
6307 if (!PyMapping_Check(env)) {
6308 PyErr_Format(PyExc_TypeError,
6309 "%s: environment must be a mapping object", func_name);
6310 goto exit;
6311 }
6312
6313 argvlist = parse_arglist(argv, &argc);
6314 if (argvlist == NULL) {
6315 goto exit;
6316 }
6317 if (!argvlist[0][0]) {
6318 PyErr_Format(PyExc_ValueError,
6319 "%s: argv first element cannot be empty", func_name);
6320 goto exit;
6321 }
6322
6323 envlist = parse_envlist(env, &envc);
6324 if (envlist == NULL) {
6325 goto exit;
6326 }
6327
6328 if (file_actions != NULL && file_actions != Py_None) {
6329 /* There is a bug in old versions of glibc that makes some of the
6330 * helper functions for manipulating file actions not copy the provided
6331 * buffers. The problem is that posix_spawn_file_actions_addopen does not
6332 * copy the value of path for some old versions of glibc (<2.20).
6333 * The use of temp_buffer here is a workaround that keeps the
6334 * python objects that own the buffers alive until posix_spawn gets called.
6335 * Check https://bugs.python.org/issue33630 and
6336 * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
6337 temp_buffer = PyList_New(0);
6338 if (!temp_buffer) {
6339 goto exit;
6340 }
6341 if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
6342 goto exit;
6343 }
6344 file_actionsp = &file_actions_buf;
6345 }
6346
6347 if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
6348 setsigmask, setsigdef, scheduler, &attr)) {
6349 goto exit;
6350 }
6351 attrp = &attr;
6352
6353 if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
6354 goto exit;
6355 }
6356
6357 _Py_BEGIN_SUPPRESS_IPH
6358 #ifdef HAVE_POSIX_SPAWNP
6359 if (use_posix_spawnp) {
6360 err_code = posix_spawnp(&pid, path->narrow,
6361 file_actionsp, attrp, argvlist, envlist);
6362 }
6363 else
6364 #endif /* HAVE_POSIX_SPAWNP */
6365 {
6366 err_code = posix_spawn(&pid, path->narrow,
6367 file_actionsp, attrp, argvlist, envlist);
6368 }
6369 _Py_END_SUPPRESS_IPH
6370
6371 if (err_code) {
6372 errno = err_code;
6373 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
6374 goto exit;
6375 }
6376 #ifdef _Py_MEMORY_SANITIZER
6377 __msan_unpoison(&pid, sizeof(pid));
6378 #endif
6379 result = PyLong_FromPid(pid);
6380
6381 exit:
6382 if (file_actionsp) {
6383 (void)posix_spawn_file_actions_destroy(file_actionsp);
6384 }
6385 if (attrp) {
6386 (void)posix_spawnattr_destroy(attrp);
6387 }
6388 if (envlist) {
6389 free_string_array(envlist, envc);
6390 }
6391 if (argvlist) {
6392 free_string_array(argvlist, argc);
6393 }
6394 Py_XDECREF(temp_buffer);
6395 return result;
6396 }
6397
6398
6399 /*[clinic input]
6400
6401 os.posix_spawn
6402 path: path_t
6403 Path of executable file.
6404 argv: object
6405 Tuple or list of strings.
6406 env: object
6407 Dictionary of strings mapping to strings.
6408 /
6409 *
6410 file_actions: object(c_default='NULL') = ()
6411 A sequence of file action tuples.
6412 setpgroup: object = NULL
6413 The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6414 resetids: bool(accept={int}) = False
6415 If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
6416 setsid: bool(accept={int}) = False
6417 If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6418 setsigmask: object(c_default='NULL') = ()
6419 The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6420 setsigdef: object(c_default='NULL') = ()
6421 The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6422 scheduler: object = NULL
6423 A tuple with the scheduler policy (optional) and parameters.
6424
6425 Execute the program specified by path in a new process.
6426 [clinic start generated code]*/
6427
6428 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)6429 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
6430 PyObject *env, PyObject *file_actions,
6431 PyObject *setpgroup, int resetids, int setsid,
6432 PyObject *setsigmask, PyObject *setsigdef,
6433 PyObject *scheduler)
6434 /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
6435 {
6436 return py_posix_spawn(0, module, path, argv, env, file_actions,
6437 setpgroup, resetids, setsid, setsigmask, setsigdef,
6438 scheduler);
6439 }
6440 #endif /* HAVE_POSIX_SPAWN */
6441
6442
6443
6444 #ifdef HAVE_POSIX_SPAWNP
6445 /*[clinic input]
6446
6447 os.posix_spawnp
6448 path: path_t
6449 Path of executable file.
6450 argv: object
6451 Tuple or list of strings.
6452 env: object
6453 Dictionary of strings mapping to strings.
6454 /
6455 *
6456 file_actions: object(c_default='NULL') = ()
6457 A sequence of file action tuples.
6458 setpgroup: object = NULL
6459 The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6460 resetids: bool(accept={int}) = False
6461 If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
6462 setsid: bool(accept={int}) = False
6463 If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6464 setsigmask: object(c_default='NULL') = ()
6465 The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6466 setsigdef: object(c_default='NULL') = ()
6467 The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6468 scheduler: object = NULL
6469 A tuple with the scheduler policy (optional) and parameters.
6470
6471 Execute the program specified by path in a new process.
6472 [clinic start generated code]*/
6473
6474 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)6475 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
6476 PyObject *env, PyObject *file_actions,
6477 PyObject *setpgroup, int resetids, int setsid,
6478 PyObject *setsigmask, PyObject *setsigdef,
6479 PyObject *scheduler)
6480 /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
6481 {
6482 return py_posix_spawn(1, module, path, argv, env, file_actions,
6483 setpgroup, resetids, setsid, setsigmask, setsigdef,
6484 scheduler);
6485 }
6486 #endif /* HAVE_POSIX_SPAWNP */
6487
6488 #ifdef HAVE_RTPSPAWN
6489 static intptr_t
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[], const char *envp[])6490 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
6491 const char *envp[])
6492 {
6493 RTP_ID rtpid;
6494 int status;
6495 pid_t res;
6496 int async_err = 0;
6497
6498 /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
6499 uStackSize=0 cannot be used, the default stack size is too small for
6500 Python. */
6501 if (envp) {
6502 rtpid = rtpSpawn(rtpFileName, argv, envp,
6503 100, 0x1000000, 0, VX_FP_TASK);
6504 }
6505 else {
6506 rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
6507 100, 0x1000000, 0, VX_FP_TASK);
6508 }
6509 if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
6510 do {
6511 res = waitpid((pid_t)rtpid, &status, 0);
6512 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6513
6514 if (res < 0)
6515 return RTP_ID_ERROR;
6516 return ((intptr_t)status);
6517 }
6518 return ((intptr_t)rtpid);
6519 }
6520 #endif
6521
6522 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
6523 /*[clinic input]
6524 os.spawnv
6525
6526 mode: int
6527 Mode of process creation.
6528 path: path_t
6529 Path of executable file.
6530 argv: object
6531 Tuple or list of strings.
6532 /
6533
6534 Execute the program specified by path in a new process.
6535 [clinic start generated code]*/
6536
6537 static PyObject *
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)6538 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
6539 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
6540 {
6541 EXECV_CHAR **argvlist;
6542 int i;
6543 Py_ssize_t argc;
6544 intptr_t spawnval;
6545 PyObject *(*getitem)(PyObject *, Py_ssize_t);
6546
6547 /* spawnv has three arguments: (mode, path, argv), where
6548 argv is a list or tuple of strings. */
6549
6550 if (PyList_Check(argv)) {
6551 argc = PyList_Size(argv);
6552 getitem = PyList_GetItem;
6553 }
6554 else if (PyTuple_Check(argv)) {
6555 argc = PyTuple_Size(argv);
6556 getitem = PyTuple_GetItem;
6557 }
6558 else {
6559 PyErr_SetString(PyExc_TypeError,
6560 "spawnv() arg 2 must be a tuple or list");
6561 return NULL;
6562 }
6563 if (argc == 0) {
6564 PyErr_SetString(PyExc_ValueError,
6565 "spawnv() arg 2 cannot be empty");
6566 return NULL;
6567 }
6568
6569 argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6570 if (argvlist == NULL) {
6571 return PyErr_NoMemory();
6572 }
6573 for (i = 0; i < argc; i++) {
6574 if (!fsconvert_strdup((*getitem)(argv, i),
6575 &argvlist[i])) {
6576 free_string_array(argvlist, i);
6577 PyErr_SetString(
6578 PyExc_TypeError,
6579 "spawnv() arg 2 must contain only strings");
6580 return NULL;
6581 }
6582 if (i == 0 && !argvlist[0][0]) {
6583 free_string_array(argvlist, i + 1);
6584 PyErr_SetString(
6585 PyExc_ValueError,
6586 "spawnv() arg 2 first element cannot be empty");
6587 return NULL;
6588 }
6589 }
6590 argvlist[argc] = NULL;
6591
6592 #if !defined(HAVE_RTPSPAWN)
6593 if (mode == _OLD_P_OVERLAY)
6594 mode = _P_OVERLAY;
6595 #endif
6596
6597 if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
6598 Py_None) < 0) {
6599 free_string_array(argvlist, argc);
6600 return NULL;
6601 }
6602
6603 Py_BEGIN_ALLOW_THREADS
6604 _Py_BEGIN_SUPPRESS_IPH
6605 #ifdef HAVE_WSPAWNV
6606 spawnval = _wspawnv(mode, path->wide, argvlist);
6607 #elif defined(HAVE_RTPSPAWN)
6608 spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
6609 #else
6610 spawnval = _spawnv(mode, path->narrow, argvlist);
6611 #endif
6612 _Py_END_SUPPRESS_IPH
6613 Py_END_ALLOW_THREADS
6614
6615 free_string_array(argvlist, argc);
6616
6617 if (spawnval == -1)
6618 return posix_error();
6619 else
6620 return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6621 }
6622
6623 /*[clinic input]
6624 os.spawnve
6625
6626 mode: int
6627 Mode of process creation.
6628 path: path_t
6629 Path of executable file.
6630 argv: object
6631 Tuple or list of strings.
6632 env: object
6633 Dictionary of strings mapping to strings.
6634 /
6635
6636 Execute the program specified by path in a new process.
6637 [clinic start generated code]*/
6638
6639 static PyObject *
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, PyObject *env)6640 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
6641 PyObject *env)
6642 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
6643 {
6644 EXECV_CHAR **argvlist;
6645 EXECV_CHAR **envlist;
6646 PyObject *res = NULL;
6647 Py_ssize_t argc, i, envc;
6648 intptr_t spawnval;
6649 PyObject *(*getitem)(PyObject *, Py_ssize_t);
6650 Py_ssize_t lastarg = 0;
6651
6652 /* spawnve has four arguments: (mode, path, argv, env), where
6653 argv is a list or tuple of strings and env is a dictionary
6654 like posix.environ. */
6655
6656 if (PyList_Check(argv)) {
6657 argc = PyList_Size(argv);
6658 getitem = PyList_GetItem;
6659 }
6660 else if (PyTuple_Check(argv)) {
6661 argc = PyTuple_Size(argv);
6662 getitem = PyTuple_GetItem;
6663 }
6664 else {
6665 PyErr_SetString(PyExc_TypeError,
6666 "spawnve() arg 2 must be a tuple or list");
6667 goto fail_0;
6668 }
6669 if (argc == 0) {
6670 PyErr_SetString(PyExc_ValueError,
6671 "spawnve() arg 2 cannot be empty");
6672 goto fail_0;
6673 }
6674 if (!PyMapping_Check(env)) {
6675 PyErr_SetString(PyExc_TypeError,
6676 "spawnve() arg 3 must be a mapping object");
6677 goto fail_0;
6678 }
6679
6680 argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6681 if (argvlist == NULL) {
6682 PyErr_NoMemory();
6683 goto fail_0;
6684 }
6685 for (i = 0; i < argc; i++) {
6686 if (!fsconvert_strdup((*getitem)(argv, i),
6687 &argvlist[i]))
6688 {
6689 lastarg = i;
6690 goto fail_1;
6691 }
6692 if (i == 0 && !argvlist[0][0]) {
6693 lastarg = i + 1;
6694 PyErr_SetString(
6695 PyExc_ValueError,
6696 "spawnv() arg 2 first element cannot be empty");
6697 goto fail_1;
6698 }
6699 }
6700 lastarg = argc;
6701 argvlist[argc] = NULL;
6702
6703 envlist = parse_envlist(env, &envc);
6704 if (envlist == NULL)
6705 goto fail_1;
6706
6707 #if !defined(HAVE_RTPSPAWN)
6708 if (mode == _OLD_P_OVERLAY)
6709 mode = _P_OVERLAY;
6710 #endif
6711
6712 if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6713 goto fail_2;
6714 }
6715
6716 Py_BEGIN_ALLOW_THREADS
6717 _Py_BEGIN_SUPPRESS_IPH
6718 #ifdef HAVE_WSPAWNV
6719 spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6720 #elif defined(HAVE_RTPSPAWN)
6721 spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6722 (const char **)envlist);
6723 #else
6724 spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6725 #endif
6726 _Py_END_SUPPRESS_IPH
6727 Py_END_ALLOW_THREADS
6728
6729 if (spawnval == -1)
6730 (void) posix_error();
6731 else
6732 res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6733
6734 fail_2:
6735 while (--envc >= 0) {
6736 PyMem_Free(envlist[envc]);
6737 }
6738 PyMem_Free(envlist);
6739 fail_1:
6740 free_string_array(argvlist, lastarg);
6741 fail_0:
6742 return res;
6743 }
6744
6745 #endif /* HAVE_SPAWNV */
6746
6747 #ifdef HAVE_FORK
6748
6749 /* Helper function to validate arguments.
6750 Returns 0 on success. non-zero on failure with a TypeError raised.
6751 If obj is non-NULL it must be callable. */
6752 static int
check_null_or_callable(PyObject *obj, const char* obj_name)6753 check_null_or_callable(PyObject *obj, const char* obj_name)
6754 {
6755 if (obj && !PyCallable_Check(obj)) {
6756 PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6757 obj_name, _PyType_Name(Py_TYPE(obj)));
6758 return -1;
6759 }
6760 return 0;
6761 }
6762
6763 /*[clinic input]
6764 os.register_at_fork
6765
6766 *
6767 before: object=NULL
6768 A callable to be called in the parent before the fork() syscall.
6769 after_in_child: object=NULL
6770 A callable to be called in the child after fork().
6771 after_in_parent: object=NULL
6772 A callable to be called in the parent after fork().
6773
6774 Register callables to be called when forking a new process.
6775
6776 'before' callbacks are called in reverse order.
6777 'after_in_child' and 'after_in_parent' callbacks are called in order.
6778
6779 [clinic start generated code]*/
6780
6781 static PyObject *
os_register_at_fork_impl(PyObject *module, PyObject *before, PyObject *after_in_child, PyObject *after_in_parent)6782 os_register_at_fork_impl(PyObject *module, PyObject *before,
6783 PyObject *after_in_child, PyObject *after_in_parent)
6784 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6785 {
6786 PyInterpreterState *interp;
6787
6788 if (!before && !after_in_child && !after_in_parent) {
6789 PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6790 return NULL;
6791 }
6792 if (check_null_or_callable(before, "before") ||
6793 check_null_or_callable(after_in_child, "after_in_child") ||
6794 check_null_or_callable(after_in_parent, "after_in_parent")) {
6795 return NULL;
6796 }
6797 interp = _PyInterpreterState_GET();
6798
6799 if (register_at_forker(&interp->before_forkers, before)) {
6800 return NULL;
6801 }
6802 if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6803 return NULL;
6804 }
6805 if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6806 return NULL;
6807 }
6808 Py_RETURN_NONE;
6809 }
6810 #endif /* HAVE_FORK */
6811
6812
6813 #ifdef HAVE_FORK1
6814 /*[clinic input]
6815 os.fork1
6816
6817 Fork a child process with a single multiplexed (i.e., not bound) thread.
6818
6819 Return 0 to child process and PID of child to parent process.
6820 [clinic start generated code]*/
6821
6822 static PyObject *
os_fork1_impl(PyObject *module)6823 os_fork1_impl(PyObject *module)
6824 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6825 {
6826 pid_t pid;
6827
6828 if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
6829 PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6830 return NULL;
6831 }
6832 PyOS_BeforeFork();
6833 pid = fork1();
6834 if (pid == 0) {
6835 /* child: this clobbers and resets the import lock. */
6836 PyOS_AfterFork_Child();
6837 } else {
6838 /* parent: release the import lock. */
6839 PyOS_AfterFork_Parent();
6840 }
6841 if (pid == -1)
6842 return posix_error();
6843 return PyLong_FromPid(pid);
6844 }
6845 #endif /* HAVE_FORK1 */
6846
6847
6848 #ifdef HAVE_FORK
6849 /*[clinic input]
6850 os.fork
6851
6852 Fork a child process.
6853
6854 Return 0 to child process and PID of child to parent process.
6855 [clinic start generated code]*/
6856
6857 static PyObject *
os_fork_impl(PyObject *module)6858 os_fork_impl(PyObject *module)
6859 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6860 {
6861 pid_t pid;
6862 PyInterpreterState *interp = _PyInterpreterState_GET();
6863 if (interp->config._isolated_interpreter) {
6864 PyErr_SetString(PyExc_RuntimeError,
6865 "fork not supported for isolated subinterpreters");
6866 return NULL;
6867 }
6868 if (PySys_Audit("os.fork", NULL) < 0) {
6869 return NULL;
6870 }
6871 PyOS_BeforeFork();
6872 pid = fork();
6873 if (pid == 0) {
6874 /* child: this clobbers and resets the import lock. */
6875 PyOS_AfterFork_Child();
6876 } else {
6877 /* parent: release the import lock. */
6878 PyOS_AfterFork_Parent();
6879 }
6880 if (pid == -1)
6881 return posix_error();
6882 return PyLong_FromPid(pid);
6883 }
6884 #endif /* HAVE_FORK */
6885
6886
6887 #ifdef HAVE_SCHED_H
6888 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6889 /*[clinic input]
6890 os.sched_get_priority_max
6891
6892 policy: int
6893
6894 Get the maximum scheduling priority for policy.
6895 [clinic start generated code]*/
6896
6897 static PyObject *
os_sched_get_priority_max_impl(PyObject *module, int policy)6898 os_sched_get_priority_max_impl(PyObject *module, int policy)
6899 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6900 {
6901 int max;
6902
6903 max = sched_get_priority_max(policy);
6904 if (max < 0)
6905 return posix_error();
6906 return PyLong_FromLong(max);
6907 }
6908
6909
6910 /*[clinic input]
6911 os.sched_get_priority_min
6912
6913 policy: int
6914
6915 Get the minimum scheduling priority for policy.
6916 [clinic start generated code]*/
6917
6918 static PyObject *
os_sched_get_priority_min_impl(PyObject *module, int policy)6919 os_sched_get_priority_min_impl(PyObject *module, int policy)
6920 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6921 {
6922 int min = sched_get_priority_min(policy);
6923 if (min < 0)
6924 return posix_error();
6925 return PyLong_FromLong(min);
6926 }
6927 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6928
6929
6930 #ifdef HAVE_SCHED_SETSCHEDULER
6931 /*[clinic input]
6932 os.sched_getscheduler
6933 pid: pid_t
6934 /
6935
6936 Get the scheduling policy for the process identified by pid.
6937
6938 Passing 0 for pid returns the scheduling policy for the calling process.
6939 [clinic start generated code]*/
6940
6941 static PyObject *
os_sched_getscheduler_impl(PyObject *module, pid_t pid)6942 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6943 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
6944 {
6945 int policy;
6946
6947 policy = sched_getscheduler(pid);
6948 if (policy < 0)
6949 return posix_error();
6950 return PyLong_FromLong(policy);
6951 }
6952 #endif /* HAVE_SCHED_SETSCHEDULER */
6953
6954
6955 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6956 /*[clinic input]
6957 class os.sched_param "PyObject *" "SchedParamType"
6958
6959 @classmethod
6960 os.sched_param.__new__
6961
6962 sched_priority: object
6963 A scheduling parameter.
6964
6965 Currently has only one field: sched_priority
6966 [clinic start generated code]*/
6967
6968 static PyObject *
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)6969 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6970 /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
6971 {
6972 PyObject *res;
6973
6974 res = PyStructSequence_New(type);
6975 if (!res)
6976 return NULL;
6977 Py_INCREF(sched_priority);
6978 PyStructSequence_SET_ITEM(res, 0, sched_priority);
6979 return res;
6980 }
6981
6982 PyDoc_VAR(os_sched_param__doc__);
6983
6984 static PyStructSequence_Field sched_param_fields[] = {
6985 {"sched_priority", "the scheduling priority"},
6986 {0}
6987 };
6988
6989 static PyStructSequence_Desc sched_param_desc = {
6990 "sched_param", /* name */
6991 os_sched_param__doc__, /* doc */
6992 sched_param_fields,
6993 1
6994 };
6995
6996 static int
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)6997 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
6998 {
6999 long priority;
7000
7001 if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
7002 PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
7003 return 0;
7004 }
7005 priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
7006 if (priority == -1 && PyErr_Occurred())
7007 return 0;
7008 if (priority > INT_MAX || priority < INT_MIN) {
7009 PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
7010 return 0;
7011 }
7012 res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
7013 return 1;
7014 }
7015 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
7016
7017
7018 #ifdef HAVE_SCHED_SETSCHEDULER
7019 /*[clinic input]
7020 os.sched_setscheduler
7021
7022 pid: pid_t
7023 policy: int
7024 param as param_obj: object
7025 /
7026
7027 Set the scheduling policy for the process identified by pid.
7028
7029 If pid is 0, the calling process is changed.
7030 param is an instance of sched_param.
7031 [clinic start generated code]*/
7032
7033 static PyObject *
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy, PyObject *param_obj)7034 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
7035 PyObject *param_obj)
7036 /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
7037 {
7038 struct sched_param param;
7039 if (!convert_sched_param(module, param_obj, ¶m)) {
7040 return NULL;
7041 }
7042
7043 /*
7044 ** sched_setscheduler() returns 0 in Linux, but the previous
7045 ** scheduling policy under Solaris/Illumos, and others.
7046 ** On error, -1 is returned in all Operating Systems.
7047 */
7048 if (sched_setscheduler(pid, policy, ¶m) == -1)
7049 return posix_error();
7050 Py_RETURN_NONE;
7051 }
7052 #endif /* HAVE_SCHED_SETSCHEDULER*/
7053
7054
7055 #ifdef HAVE_SCHED_SETPARAM
7056 /*[clinic input]
7057 os.sched_getparam
7058 pid: pid_t
7059 /
7060
7061 Returns scheduling parameters for the process identified by pid.
7062
7063 If pid is 0, returns parameters for the calling process.
7064 Return value is an instance of sched_param.
7065 [clinic start generated code]*/
7066
7067 static PyObject *
os_sched_getparam_impl(PyObject *module, pid_t pid)7068 os_sched_getparam_impl(PyObject *module, pid_t pid)
7069 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
7070 {
7071 struct sched_param param;
7072 PyObject *result;
7073 PyObject *priority;
7074
7075 if (sched_getparam(pid, ¶m))
7076 return posix_error();
7077 PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
7078 result = PyStructSequence_New((PyTypeObject *)SchedParamType);
7079 if (!result)
7080 return NULL;
7081 priority = PyLong_FromLong(param.sched_priority);
7082 if (!priority) {
7083 Py_DECREF(result);
7084 return NULL;
7085 }
7086 PyStructSequence_SET_ITEM(result, 0, priority);
7087 return result;
7088 }
7089
7090
7091 /*[clinic input]
7092 os.sched_setparam
7093 pid: pid_t
7094 param as param_obj: object
7095 /
7096
7097 Set scheduling parameters for the process identified by pid.
7098
7099 If pid is 0, sets parameters for the calling process.
7100 param should be an instance of sched_param.
7101 [clinic start generated code]*/
7102
7103 static PyObject *
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)7104 os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
7105 /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
7106 {
7107 struct sched_param param;
7108 if (!convert_sched_param(module, param_obj, ¶m)) {
7109 return NULL;
7110 }
7111
7112 if (sched_setparam(pid, ¶m))
7113 return posix_error();
7114 Py_RETURN_NONE;
7115 }
7116 #endif /* HAVE_SCHED_SETPARAM */
7117
7118
7119 #ifdef HAVE_SCHED_RR_GET_INTERVAL
7120 /*[clinic input]
7121 os.sched_rr_get_interval -> double
7122 pid: pid_t
7123 /
7124
7125 Return the round-robin quantum for the process identified by pid, in seconds.
7126
7127 Value returned is a float.
7128 [clinic start generated code]*/
7129
7130 static double
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)7131 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
7132 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
7133 {
7134 struct timespec interval;
7135 if (sched_rr_get_interval(pid, &interval)) {
7136 posix_error();
7137 return -1.0;
7138 }
7139 #ifdef _Py_MEMORY_SANITIZER
7140 __msan_unpoison(&interval, sizeof(interval));
7141 #endif
7142 return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
7143 }
7144 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
7145
7146
7147 /*[clinic input]
7148 os.sched_yield
7149
7150 Voluntarily relinquish the CPU.
7151 [clinic start generated code]*/
7152
7153 static PyObject *
os_sched_yield_impl(PyObject *module)7154 os_sched_yield_impl(PyObject *module)
7155 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
7156 {
7157 int result;
7158 Py_BEGIN_ALLOW_THREADS
7159 result = sched_yield();
7160 Py_END_ALLOW_THREADS
7161 if (result < 0) {
7162 return posix_error();
7163 }
7164 Py_RETURN_NONE;
7165 }
7166
7167 #ifdef HAVE_SCHED_SETAFFINITY
7168 /* The minimum number of CPUs allocated in a cpu_set_t */
7169 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
7170
7171 /*[clinic input]
7172 os.sched_setaffinity
7173 pid: pid_t
7174 mask : object
7175 /
7176
7177 Set the CPU affinity of the process identified by pid to mask.
7178
7179 mask should be an iterable of integers identifying CPUs.
7180 [clinic start generated code]*/
7181
7182 static PyObject *
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)7183 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
7184 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
7185 {
7186 int ncpus;
7187 size_t setsize;
7188 cpu_set_t *cpu_set = NULL;
7189 PyObject *iterator = NULL, *item;
7190
7191 iterator = PyObject_GetIter(mask);
7192 if (iterator == NULL)
7193 return NULL;
7194
7195 ncpus = NCPUS_START;
7196 setsize = CPU_ALLOC_SIZE(ncpus);
7197 cpu_set = CPU_ALLOC(ncpus);
7198 if (cpu_set == NULL) {
7199 PyErr_NoMemory();
7200 goto error;
7201 }
7202 CPU_ZERO_S(setsize, cpu_set);
7203
7204 while ((item = PyIter_Next(iterator))) {
7205 long cpu;
7206 if (!PyLong_Check(item)) {
7207 PyErr_Format(PyExc_TypeError,
7208 "expected an iterator of ints, "
7209 "but iterator yielded %R",
7210 Py_TYPE(item));
7211 Py_DECREF(item);
7212 goto error;
7213 }
7214 cpu = PyLong_AsLong(item);
7215 Py_DECREF(item);
7216 if (cpu < 0) {
7217 if (!PyErr_Occurred())
7218 PyErr_SetString(PyExc_ValueError, "negative CPU number");
7219 goto error;
7220 }
7221 if (cpu > INT_MAX - 1) {
7222 PyErr_SetString(PyExc_OverflowError, "CPU number too large");
7223 goto error;
7224 }
7225 if (cpu >= ncpus) {
7226 /* Grow CPU mask to fit the CPU number */
7227 int newncpus = ncpus;
7228 cpu_set_t *newmask;
7229 size_t newsetsize;
7230 while (newncpus <= cpu) {
7231 if (newncpus > INT_MAX / 2)
7232 newncpus = cpu + 1;
7233 else
7234 newncpus = newncpus * 2;
7235 }
7236 newmask = CPU_ALLOC(newncpus);
7237 if (newmask == NULL) {
7238 PyErr_NoMemory();
7239 goto error;
7240 }
7241 newsetsize = CPU_ALLOC_SIZE(newncpus);
7242 CPU_ZERO_S(newsetsize, newmask);
7243 memcpy(newmask, cpu_set, setsize);
7244 CPU_FREE(cpu_set);
7245 setsize = newsetsize;
7246 cpu_set = newmask;
7247 ncpus = newncpus;
7248 }
7249 CPU_SET_S(cpu, setsize, cpu_set);
7250 }
7251 if (PyErr_Occurred()) {
7252 goto error;
7253 }
7254 Py_CLEAR(iterator);
7255
7256 if (sched_setaffinity(pid, setsize, cpu_set)) {
7257 posix_error();
7258 goto error;
7259 }
7260 CPU_FREE(cpu_set);
7261 Py_RETURN_NONE;
7262
7263 error:
7264 if (cpu_set)
7265 CPU_FREE(cpu_set);
7266 Py_XDECREF(iterator);
7267 return NULL;
7268 }
7269
7270
7271 /*[clinic input]
7272 os.sched_getaffinity
7273 pid: pid_t
7274 /
7275
7276 Return the affinity of the process identified by pid (or the current process if zero).
7277
7278 The affinity is returned as a set of CPU identifiers.
7279 [clinic start generated code]*/
7280
7281 static PyObject *
os_sched_getaffinity_impl(PyObject *module, pid_t pid)7282 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
7283 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
7284 {
7285 int cpu, ncpus, count;
7286 size_t setsize;
7287 cpu_set_t *mask = NULL;
7288 PyObject *res = NULL;
7289
7290 ncpus = NCPUS_START;
7291 while (1) {
7292 setsize = CPU_ALLOC_SIZE(ncpus);
7293 mask = CPU_ALLOC(ncpus);
7294 if (mask == NULL)
7295 return PyErr_NoMemory();
7296 if (sched_getaffinity(pid, setsize, mask) == 0)
7297 break;
7298 CPU_FREE(mask);
7299 if (errno != EINVAL)
7300 return posix_error();
7301 if (ncpus > INT_MAX / 2) {
7302 PyErr_SetString(PyExc_OverflowError, "could not allocate "
7303 "a large enough CPU set");
7304 return NULL;
7305 }
7306 ncpus = ncpus * 2;
7307 }
7308
7309 res = PySet_New(NULL);
7310 if (res == NULL)
7311 goto error;
7312 for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7313 if (CPU_ISSET_S(cpu, setsize, mask)) {
7314 PyObject *cpu_num = PyLong_FromLong(cpu);
7315 --count;
7316 if (cpu_num == NULL)
7317 goto error;
7318 if (PySet_Add(res, cpu_num)) {
7319 Py_DECREF(cpu_num);
7320 goto error;
7321 }
7322 Py_DECREF(cpu_num);
7323 }
7324 }
7325 CPU_FREE(mask);
7326 return res;
7327
7328 error:
7329 if (mask)
7330 CPU_FREE(mask);
7331 Py_XDECREF(res);
7332 return NULL;
7333 }
7334
7335 #endif /* HAVE_SCHED_SETAFFINITY */
7336
7337 #endif /* HAVE_SCHED_H */
7338
7339
7340 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
7341 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
7342 # define DEV_PTY_FILE "/dev/ptc"
7343 # define HAVE_DEV_PTMX
7344 #else
7345 # define DEV_PTY_FILE "/dev/ptmx"
7346 #endif
7347
7348 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
7349 #ifdef HAVE_PTY_H
7350 #include <pty.h>
7351 #ifdef HAVE_UTMP_H
7352 #include <utmp.h>
7353 #endif /* HAVE_UTMP_H */
7354 #elif defined(HAVE_LIBUTIL_H)
7355 #include <libutil.h>
7356 #elif defined(HAVE_UTIL_H)
7357 #include <util.h>
7358 #endif /* HAVE_PTY_H */
7359 #ifdef HAVE_STROPTS_H
7360 #include <stropts.h>
7361 #endif
7362 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
7363
7364
7365 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7366 /*[clinic input]
7367 os.openpty
7368
7369 Open a pseudo-terminal.
7370
7371 Return a tuple of (master_fd, slave_fd) containing open file descriptors
7372 for both the master and slave ends.
7373 [clinic start generated code]*/
7374
7375 static PyObject *
os_openpty_impl(PyObject *module)7376 os_openpty_impl(PyObject *module)
7377 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
7378 {
7379 int master_fd = -1, slave_fd = -1;
7380 #ifndef HAVE_OPENPTY
7381 char * slave_name;
7382 #endif
7383 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
7384 PyOS_sighandler_t sig_saved;
7385 #if defined(__sun) && defined(__SVR4)
7386 extern char *ptsname(int fildes);
7387 #endif
7388 #endif
7389
7390 #ifdef HAVE_OPENPTY
7391 if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
7392 goto posix_error;
7393
7394 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7395 goto error;
7396 if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
7397 goto error;
7398
7399 #elif defined(HAVE__GETPTY)
7400 slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
7401 if (slave_name == NULL)
7402 goto posix_error;
7403 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7404 goto error;
7405
7406 slave_fd = _Py_open(slave_name, O_RDWR);
7407 if (slave_fd < 0)
7408 goto error;
7409
7410 #else
7411 master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
7412 if (master_fd < 0)
7413 goto posix_error;
7414
7415 sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
7416
7417 /* change permission of slave */
7418 if (grantpt(master_fd) < 0) {
7419 PyOS_setsig(SIGCHLD, sig_saved);
7420 goto posix_error;
7421 }
7422
7423 /* unlock slave */
7424 if (unlockpt(master_fd) < 0) {
7425 PyOS_setsig(SIGCHLD, sig_saved);
7426 goto posix_error;
7427 }
7428
7429 PyOS_setsig(SIGCHLD, sig_saved);
7430
7431 slave_name = ptsname(master_fd); /* get name of slave */
7432 if (slave_name == NULL)
7433 goto posix_error;
7434
7435 slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
7436 if (slave_fd == -1)
7437 goto error;
7438
7439 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7440 goto posix_error;
7441
7442 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
7443 ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
7444 ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
7445 #ifndef __hpux
7446 ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
7447 #endif /* __hpux */
7448 #endif /* HAVE_CYGWIN */
7449 #endif /* HAVE_OPENPTY */
7450
7451 return Py_BuildValue("(ii)", master_fd, slave_fd);
7452
7453 posix_error:
7454 posix_error();
7455 error:
7456 if (master_fd != -1)
7457 close(master_fd);
7458 if (slave_fd != -1)
7459 close(slave_fd);
7460 return NULL;
7461 }
7462 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
7463
7464
7465 #if defined(HAVE_SETSID) && defined(TIOCSCTTY)
7466 #define HAVE_FALLBACK_LOGIN_TTY 1
7467 #endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
7468
7469 #if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
7470 /*[clinic input]
7471 os.login_tty
7472
7473 fd: fildes
7474 /
7475
7476 Prepare the tty of which fd is a file descriptor for a new login session.
7477
7478 Make the calling process a session leader; make the tty the
7479 controlling tty, the stdin, the stdout, and the stderr of the
7480 calling process; close fd.
7481 [clinic start generated code]*/
7482
7483 static PyObject *
os_login_tty_impl(PyObject *module, int fd)7484 os_login_tty_impl(PyObject *module, int fd)
7485 /*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
7486 {
7487 #ifdef HAVE_LOGIN_TTY
7488 if (login_tty(fd) == -1) {
7489 return posix_error();
7490 }
7491 #else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
7492 /* Establish a new session. */
7493 if (setsid() == -1) {
7494 return posix_error();
7495 }
7496
7497 /* The tty becomes the controlling terminal. */
7498 if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
7499 return posix_error();
7500 }
7501
7502 /* The tty becomes stdin/stdout/stderr */
7503 if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
7504 return posix_error();
7505 }
7506 if (fd > 2) {
7507 close(fd);
7508 }
7509 #endif /* HAVE_LOGIN_TTY */
7510 Py_RETURN_NONE;
7511 }
7512 #endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
7513
7514
7515 #ifdef HAVE_FORKPTY
7516 /*[clinic input]
7517 os.forkpty
7518
7519 Fork a new process with a new pseudo-terminal as controlling tty.
7520
7521 Returns a tuple of (pid, master_fd).
7522 Like fork(), return pid of 0 to the child process,
7523 and pid of child to the parent process.
7524 To both, return fd of newly opened pseudo-terminal.
7525 [clinic start generated code]*/
7526
7527 static PyObject *
os_forkpty_impl(PyObject *module)7528 os_forkpty_impl(PyObject *module)
7529 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
7530 {
7531 int master_fd = -1;
7532 pid_t pid;
7533
7534 if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
7535 PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
7536 return NULL;
7537 }
7538 if (PySys_Audit("os.forkpty", NULL) < 0) {
7539 return NULL;
7540 }
7541 PyOS_BeforeFork();
7542 pid = forkpty(&master_fd, NULL, NULL, NULL);
7543 if (pid == 0) {
7544 /* child: this clobbers and resets the import lock. */
7545 PyOS_AfterFork_Child();
7546 } else {
7547 /* parent: release the import lock. */
7548 PyOS_AfterFork_Parent();
7549 }
7550 if (pid == -1) {
7551 return posix_error();
7552 }
7553 return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
7554 }
7555 #endif /* HAVE_FORKPTY */
7556
7557
7558 #ifdef HAVE_GETEGID
7559 /*[clinic input]
7560 os.getegid
7561
7562 Return the current process's effective group id.
7563 [clinic start generated code]*/
7564
7565 static PyObject *
os_getegid_impl(PyObject *module)7566 os_getegid_impl(PyObject *module)
7567 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
7568 {
7569 return _PyLong_FromGid(getegid());
7570 }
7571 #endif /* HAVE_GETEGID */
7572
7573
7574 #ifdef HAVE_GETEUID
7575 /*[clinic input]
7576 os.geteuid
7577
7578 Return the current process's effective user id.
7579 [clinic start generated code]*/
7580
7581 static PyObject *
os_geteuid_impl(PyObject *module)7582 os_geteuid_impl(PyObject *module)
7583 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
7584 {
7585 return _PyLong_FromUid(geteuid());
7586 }
7587 #endif /* HAVE_GETEUID */
7588
7589
7590 #ifdef HAVE_GETGID
7591 /*[clinic input]
7592 os.getgid
7593
7594 Return the current process's group id.
7595 [clinic start generated code]*/
7596
7597 static PyObject *
os_getgid_impl(PyObject *module)7598 os_getgid_impl(PyObject *module)
7599 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
7600 {
7601 return _PyLong_FromGid(getgid());
7602 }
7603 #endif /* HAVE_GETGID */
7604
7605
7606 #ifdef HAVE_GETPID
7607 /*[clinic input]
7608 os.getpid
7609
7610 Return the current process id.
7611 [clinic start generated code]*/
7612
7613 static PyObject *
os_getpid_impl(PyObject *module)7614 os_getpid_impl(PyObject *module)
7615 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
7616 {
7617 return PyLong_FromPid(getpid());
7618 }
7619 #endif /* HAVE_GETPID */
7620
7621 #ifdef NGROUPS_MAX
7622 #define MAX_GROUPS NGROUPS_MAX
7623 #else
7624 /* defined to be 16 on Solaris7, so this should be a small number */
7625 #define MAX_GROUPS 64
7626 #endif
7627
7628 #ifdef HAVE_GETGROUPLIST
7629
7630 #ifdef __APPLE__
7631 /*[clinic input]
7632 os.getgrouplist
7633
7634 user: str
7635 username to lookup
7636 group as basegid: int
7637 base group id of the user
7638 /
7639
7640 Returns a list of groups to which a user belongs.
7641 [clinic start generated code]*/
7642
7643 static PyObject *
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)7644 os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
7645 /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
7646 #else
7647 /*[clinic input]
7648 os.getgrouplist
7649
7650 user: str
7651 username to lookup
7652 group as basegid: gid_t
7653 base group id of the user
7654 /
7655
7656 Returns a list of groups to which a user belongs.
7657 [clinic start generated code]*/
7658
7659 static PyObject *
7660 os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
7661 /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
7662 #endif
7663 {
7664 int i, ngroups;
7665 PyObject *list;
7666 #ifdef __APPLE__
7667 int *groups;
7668 #else
7669 gid_t *groups;
7670 #endif
7671
7672 /*
7673 * NGROUPS_MAX is defined by POSIX.1 as the maximum
7674 * number of supplimental groups a users can belong to.
7675 * We have to increment it by one because
7676 * getgrouplist() returns both the supplemental groups
7677 * and the primary group, i.e. all of the groups the
7678 * user belongs to.
7679 */
7680 ngroups = 1 + MAX_GROUPS;
7681
7682 while (1) {
7683 #ifdef __APPLE__
7684 groups = PyMem_New(int, ngroups);
7685 #else
7686 groups = PyMem_New(gid_t, ngroups);
7687 #endif
7688 if (groups == NULL) {
7689 return PyErr_NoMemory();
7690 }
7691
7692 int old_ngroups = ngroups;
7693 if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
7694 /* Success */
7695 break;
7696 }
7697
7698 /* getgrouplist() fails if the group list is too small */
7699 PyMem_Free(groups);
7700
7701 if (ngroups > old_ngroups) {
7702 /* If the group list is too small, the glibc implementation of
7703 getgrouplist() sets ngroups to the total number of groups and
7704 returns -1. */
7705 }
7706 else {
7707 /* Double the group list size */
7708 if (ngroups > INT_MAX / 2) {
7709 return PyErr_NoMemory();
7710 }
7711 ngroups *= 2;
7712 }
7713
7714 /* Retry getgrouplist() with a larger group list */
7715 }
7716
7717 #ifdef _Py_MEMORY_SANITIZER
7718 /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
7719 __msan_unpoison(&ngroups, sizeof(ngroups));
7720 __msan_unpoison(groups, ngroups*sizeof(*groups));
7721 #endif
7722
7723 list = PyList_New(ngroups);
7724 if (list == NULL) {
7725 PyMem_Free(groups);
7726 return NULL;
7727 }
7728
7729 for (i = 0; i < ngroups; i++) {
7730 #ifdef __APPLE__
7731 PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7732 #else
7733 PyObject *o = _PyLong_FromGid(groups[i]);
7734 #endif
7735 if (o == NULL) {
7736 Py_DECREF(list);
7737 PyMem_Free(groups);
7738 return NULL;
7739 }
7740 PyList_SET_ITEM(list, i, o);
7741 }
7742
7743 PyMem_Free(groups);
7744
7745 return list;
7746 }
7747 #endif /* HAVE_GETGROUPLIST */
7748
7749
7750 #ifdef HAVE_GETGROUPS
7751 /*[clinic input]
7752 os.getgroups
7753
7754 Return list of supplemental group IDs for the process.
7755 [clinic start generated code]*/
7756
7757 static PyObject *
os_getgroups_impl(PyObject *module)7758 os_getgroups_impl(PyObject *module)
7759 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
7760 {
7761 // Call getgroups with length 0 to get the actual number of groups
7762 int n = getgroups(0, NULL);
7763 if (n < 0) {
7764 return posix_error();
7765 }
7766
7767 if (n == 0) {
7768 return PyList_New(0);
7769 }
7770
7771 gid_t *grouplist = PyMem_New(gid_t, n);
7772 if (grouplist == NULL) {
7773 return PyErr_NoMemory();
7774 }
7775
7776 n = getgroups(n, grouplist);
7777 if (n == -1) {
7778 PyMem_Free(grouplist);
7779 return posix_error();
7780 }
7781
7782 PyObject *result = PyList_New(n);
7783 if (result == NULL) {
7784 goto error;
7785 }
7786
7787 for (int i = 0; i < n; ++i) {
7788 PyObject *group = _PyLong_FromGid(grouplist[i]);
7789 if (group == NULL) {
7790 goto error;
7791 }
7792 PyList_SET_ITEM(result, i, group);
7793 }
7794 PyMem_Free(grouplist);
7795
7796 return result;
7797
7798 error:
7799 PyMem_Free(grouplist);
7800 Py_XDECREF(result);
7801 return NULL;
7802 }
7803 #endif /* HAVE_GETGROUPS */
7804
7805 #ifdef HAVE_INITGROUPS
7806 #ifdef __APPLE__
7807 /*[clinic input]
7808 os.initgroups
7809
7810 username as oname: FSConverter
7811 gid: int
7812 /
7813
7814 Initialize the group access list.
7815
7816 Call the system initgroups() to initialize the group access list with all of
7817 the groups of which the specified username is a member, plus the specified
7818 group id.
7819 [clinic start generated code]*/
7820
7821 static PyObject *
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)7822 os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
7823 /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
7824 #else
7825 /*[clinic input]
7826 os.initgroups
7827
7828 username as oname: FSConverter
7829 gid: gid_t
7830 /
7831
7832 Initialize the group access list.
7833
7834 Call the system initgroups() to initialize the group access list with all of
7835 the groups of which the specified username is a member, plus the specified
7836 group id.
7837 [clinic start generated code]*/
7838
7839 static PyObject *
7840 os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
7841 /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
7842 #endif
7843 {
7844 const char *username = PyBytes_AS_STRING(oname);
7845
7846 if (initgroups(username, gid) == -1)
7847 return PyErr_SetFromErrno(PyExc_OSError);
7848
7849 Py_RETURN_NONE;
7850 }
7851 #endif /* HAVE_INITGROUPS */
7852
7853
7854 #ifdef HAVE_GETPGID
7855 /*[clinic input]
7856 os.getpgid
7857
7858 pid: pid_t
7859
7860 Call the system call getpgid(), and return the result.
7861 [clinic start generated code]*/
7862
7863 static PyObject *
os_getpgid_impl(PyObject *module, pid_t pid)7864 os_getpgid_impl(PyObject *module, pid_t pid)
7865 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7866 {
7867 pid_t pgid = getpgid(pid);
7868 if (pgid < 0)
7869 return posix_error();
7870 return PyLong_FromPid(pgid);
7871 }
7872 #endif /* HAVE_GETPGID */
7873
7874
7875 #ifdef HAVE_GETPGRP
7876 /*[clinic input]
7877 os.getpgrp
7878
7879 Return the current process group id.
7880 [clinic start generated code]*/
7881
7882 static PyObject *
os_getpgrp_impl(PyObject *module)7883 os_getpgrp_impl(PyObject *module)
7884 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7885 {
7886 #ifdef GETPGRP_HAVE_ARG
7887 return PyLong_FromPid(getpgrp(0));
7888 #else /* GETPGRP_HAVE_ARG */
7889 return PyLong_FromPid(getpgrp());
7890 #endif /* GETPGRP_HAVE_ARG */
7891 }
7892 #endif /* HAVE_GETPGRP */
7893
7894
7895 #ifdef HAVE_SETPGRP
7896 /*[clinic input]
7897 os.setpgrp
7898
7899 Make the current process the leader of its process group.
7900 [clinic start generated code]*/
7901
7902 static PyObject *
os_setpgrp_impl(PyObject *module)7903 os_setpgrp_impl(PyObject *module)
7904 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7905 {
7906 #ifdef SETPGRP_HAVE_ARG
7907 if (setpgrp(0, 0) < 0)
7908 #else /* SETPGRP_HAVE_ARG */
7909 if (setpgrp() < 0)
7910 #endif /* SETPGRP_HAVE_ARG */
7911 return posix_error();
7912 Py_RETURN_NONE;
7913 }
7914 #endif /* HAVE_SETPGRP */
7915
7916 #ifdef HAVE_GETPPID
7917
7918 #ifdef MS_WINDOWS
7919 #include <tlhelp32.h>
7920
7921 static PyObject*
win32_getppidnull7922 win32_getppid()
7923 {
7924 HANDLE snapshot;
7925 pid_t mypid;
7926 PyObject* result = NULL;
7927 BOOL have_record;
7928 PROCESSENTRY32 pe;
7929
7930 mypid = getpid(); /* This function never fails */
7931
7932 snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7933 if (snapshot == INVALID_HANDLE_VALUE)
7934 return PyErr_SetFromWindowsErr(GetLastError());
7935
7936 pe.dwSize = sizeof(pe);
7937 have_record = Process32First(snapshot, &pe);
7938 while (have_record) {
7939 if (mypid == (pid_t)pe.th32ProcessID) {
7940 /* We could cache the ulong value in a static variable. */
7941 result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7942 break;
7943 }
7944
7945 have_record = Process32Next(snapshot, &pe);
7946 }
7947
7948 /* If our loop exits and our pid was not found (result will be NULL)
7949 * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7950 * error anyway, so let's raise it. */
7951 if (!result)
7952 result = PyErr_SetFromWindowsErr(GetLastError());
7953
7954 CloseHandle(snapshot);
7955
7956 return result;
7957 }
7958 #endif /*MS_WINDOWS*/
7959
7960
7961 /*[clinic input]
7962 os.getppid
7963
7964 Return the parent's process id.
7965
7966 If the parent process has already exited, Windows machines will still
7967 return its id; others systems will return the id of the 'init' process (1).
7968 [clinic start generated code]*/
7969
7970 static PyObject *
os_getppid_impl(PyObject *module)7971 os_getppid_impl(PyObject *module)
7972 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7973 {
7974 #ifdef MS_WINDOWS
7975 return win32_getppid();
7976 #else
7977 return PyLong_FromPid(getppid());
7978 #endif
7979 }
7980 #endif /* HAVE_GETPPID */
7981
7982
7983 #ifdef HAVE_GETLOGIN
7984 /*[clinic input]
7985 os.getlogin
7986
7987 Return the actual login name.
7988 [clinic start generated code]*/
7989
7990 static PyObject *
os_getlogin_impl(PyObject *module)7991 os_getlogin_impl(PyObject *module)
7992 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7993 {
7994 PyObject *result = NULL;
7995 #ifdef MS_WINDOWS
7996 wchar_t user_name[UNLEN + 1];
7997 DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7998
7999 if (GetUserNameW(user_name, &num_chars)) {
8000 /* num_chars is the number of unicode chars plus null terminator */
8001 result = PyUnicode_FromWideChar(user_name, num_chars - 1);
8002 }
8003 else
8004 result = PyErr_SetFromWindowsErr(GetLastError());
8005 #else
8006 char *name;
8007 int old_errno = errno;
8008
8009 errno = 0;
8010 name = getlogin();
8011 if (name == NULL) {
8012 if (errno)
8013 posix_error();
8014 else
8015 PyErr_SetString(PyExc_OSError, "unable to determine login name");
8016 }
8017 else
8018 result = PyUnicode_DecodeFSDefault(name);
8019 errno = old_errno;
8020 #endif
8021 return result;
8022 }
8023 #endif /* HAVE_GETLOGIN */
8024
8025
8026 #ifdef HAVE_GETUID
8027 /*[clinic input]
8028 os.getuid
8029
8030 Return the current process's user id.
8031 [clinic start generated code]*/
8032
8033 static PyObject *
os_getuid_impl(PyObject *module)8034 os_getuid_impl(PyObject *module)
8035 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
8036 {
8037 return _PyLong_FromUid(getuid());
8038 }
8039 #endif /* HAVE_GETUID */
8040
8041
8042 #ifdef MS_WINDOWS
8043 #define HAVE_KILL
8044 #endif /* MS_WINDOWS */
8045
8046 #ifdef HAVE_KILL
8047 /*[clinic input]
8048 os.kill
8049
8050 pid: pid_t
8051 signal: Py_ssize_t
8052 /
8053
8054 Kill a process with a signal.
8055 [clinic start generated code]*/
8056
8057 static PyObject *
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)8058 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
8059 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
8060 {
8061 if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
8062 return NULL;
8063 }
8064 #ifndef MS_WINDOWS
8065 if (kill(pid, (int)signal) == -1) {
8066 return posix_error();
8067 }
8068
8069 // Check immediately if the signal was sent to the current process.
8070 // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
8071 // is cheap.
8072 if (PyErr_CheckSignals()) {
8073 return NULL;
8074 }
8075
8076 Py_RETURN_NONE;
8077 #else /* !MS_WINDOWS */
8078 PyObject *result;
8079 DWORD sig = (DWORD)signal;
8080 DWORD err;
8081 HANDLE handle;
8082
8083 /* Console processes which share a common console can be sent CTRL+C or
8084 CTRL+BREAK events, provided they handle said events. */
8085 if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
8086 if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
8087 err = GetLastError();
8088 PyErr_SetFromWindowsErr(err);
8089 }
8090 else
8091 Py_RETURN_NONE;
8092 }
8093
8094 /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
8095 attempt to open and terminate the process. */
8096 handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
8097 if (handle == NULL) {
8098 err = GetLastError();
8099 return PyErr_SetFromWindowsErr(err);
8100 }
8101
8102 if (TerminateProcess(handle, sig) == 0) {
8103 err = GetLastError();
8104 result = PyErr_SetFromWindowsErr(err);
8105 } else {
8106 Py_INCREF(Py_None);
8107 result = Py_None;
8108 }
8109
8110 CloseHandle(handle);
8111 return result;
8112 #endif /* !MS_WINDOWS */
8113 }
8114 #endif /* HAVE_KILL */
8115
8116
8117 #ifdef HAVE_KILLPG
8118 /*[clinic input]
8119 os.killpg
8120
8121 pgid: pid_t
8122 signal: int
8123 /
8124
8125 Kill a process group with a signal.
8126 [clinic start generated code]*/
8127
8128 static PyObject *
os_killpg_impl(PyObject *module, pid_t pgid, int signal)8129 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
8130 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
8131 {
8132 if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
8133 return NULL;
8134 }
8135 /* XXX some man pages make the `pgid` parameter an int, others
8136 a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
8137 take the same type. Moreover, pid_t is always at least as wide as
8138 int (else compilation of this module fails), which is safe. */
8139 if (killpg(pgid, signal) == -1)
8140 return posix_error();
8141 Py_RETURN_NONE;
8142 }
8143 #endif /* HAVE_KILLPG */
8144
8145
8146 #ifdef HAVE_PLOCK
8147 #ifdef HAVE_SYS_LOCK_H
8148 #include <sys/lock.h>
8149 #endif
8150
8151 /*[clinic input]
8152 os.plock
8153 op: int
8154 /
8155
8156 Lock program segments into memory.");
8157 [clinic start generated code]*/
8158
8159 static PyObject *
os_plock_impl(PyObject *module, int op)8160 os_plock_impl(PyObject *module, int op)
8161 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
8162 {
8163 if (plock(op) == -1)
8164 return posix_error();
8165 Py_RETURN_NONE;
8166 }
8167 #endif /* HAVE_PLOCK */
8168
8169
8170 #ifdef HAVE_SETUID
8171 /*[clinic input]
8172 os.setuid
8173
8174 uid: uid_t
8175 /
8176
8177 Set the current process's user id.
8178 [clinic start generated code]*/
8179
8180 static PyObject *
os_setuid_impl(PyObject *module, uid_t uid)8181 os_setuid_impl(PyObject *module, uid_t uid)
8182 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
8183 {
8184 if (setuid(uid) < 0)
8185 return posix_error();
8186 Py_RETURN_NONE;
8187 }
8188 #endif /* HAVE_SETUID */
8189
8190
8191 #ifdef HAVE_SETEUID
8192 /*[clinic input]
8193 os.seteuid
8194
8195 euid: uid_t
8196 /
8197
8198 Set the current process's effective user id.
8199 [clinic start generated code]*/
8200
8201 static PyObject *
os_seteuid_impl(PyObject *module, uid_t euid)8202 os_seteuid_impl(PyObject *module, uid_t euid)
8203 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
8204 {
8205 if (seteuid(euid) < 0)
8206 return posix_error();
8207 Py_RETURN_NONE;
8208 }
8209 #endif /* HAVE_SETEUID */
8210
8211
8212 #ifdef HAVE_SETEGID
8213 /*[clinic input]
8214 os.setegid
8215
8216 egid: gid_t
8217 /
8218
8219 Set the current process's effective group id.
8220 [clinic start generated code]*/
8221
8222 static PyObject *
os_setegid_impl(PyObject *module, gid_t egid)8223 os_setegid_impl(PyObject *module, gid_t egid)
8224 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
8225 {
8226 if (setegid(egid) < 0)
8227 return posix_error();
8228 Py_RETURN_NONE;
8229 }
8230 #endif /* HAVE_SETEGID */
8231
8232
8233 #ifdef HAVE_SETREUID
8234 /*[clinic input]
8235 os.setreuid
8236
8237 ruid: uid_t
8238 euid: uid_t
8239 /
8240
8241 Set the current process's real and effective user ids.
8242 [clinic start generated code]*/
8243
8244 static PyObject *
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)8245 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
8246 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
8247 {
8248 if (setreuid(ruid, euid) < 0) {
8249 return posix_error();
8250 } else {
8251 Py_RETURN_NONE;
8252 }
8253 }
8254 #endif /* HAVE_SETREUID */
8255
8256
8257 #ifdef HAVE_SETREGID
8258 /*[clinic input]
8259 os.setregid
8260
8261 rgid: gid_t
8262 egid: gid_t
8263 /
8264
8265 Set the current process's real and effective group ids.
8266 [clinic start generated code]*/
8267
8268 static PyObject *
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)8269 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
8270 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
8271 {
8272 if (setregid(rgid, egid) < 0)
8273 return posix_error();
8274 Py_RETURN_NONE;
8275 }
8276 #endif /* HAVE_SETREGID */
8277
8278
8279 #ifdef HAVE_SETGID
8280 /*[clinic input]
8281 os.setgid
8282 gid: gid_t
8283 /
8284
8285 Set the current process's group id.
8286 [clinic start generated code]*/
8287
8288 static PyObject *
os_setgid_impl(PyObject *module, gid_t gid)8289 os_setgid_impl(PyObject *module, gid_t gid)
8290 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
8291 {
8292 if (setgid(gid) < 0)
8293 return posix_error();
8294 Py_RETURN_NONE;
8295 }
8296 #endif /* HAVE_SETGID */
8297
8298
8299 #ifdef HAVE_SETGROUPS
8300 /*[clinic input]
8301 os.setgroups
8302
8303 groups: object
8304 /
8305
8306 Set the groups of the current process to list.
8307 [clinic start generated code]*/
8308
8309 static PyObject *
os_setgroups(PyObject *module, PyObject *groups)8310 os_setgroups(PyObject *module, PyObject *groups)
8311 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
8312 {
8313 if (!PySequence_Check(groups)) {
8314 PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
8315 return NULL;
8316 }
8317 Py_ssize_t len = PySequence_Size(groups);
8318 if (len < 0) {
8319 return NULL;
8320 }
8321 if (len > MAX_GROUPS) {
8322 PyErr_SetString(PyExc_ValueError, "too many groups");
8323 return NULL;
8324 }
8325
8326 gid_t *grouplist = PyMem_New(gid_t, len);
8327 for (Py_ssize_t i = 0; i < len; i++) {
8328 PyObject *elem;
8329 elem = PySequence_GetItem(groups, i);
8330 if (!elem) {
8331 PyMem_Free(grouplist);
8332 return NULL;
8333 }
8334 if (!PyLong_Check(elem)) {
8335 PyErr_SetString(PyExc_TypeError,
8336 "groups must be integers");
8337 Py_DECREF(elem);
8338 PyMem_Free(grouplist);
8339 return NULL;
8340 } else {
8341 if (!_Py_Gid_Converter(elem, &grouplist[i])) {
8342 Py_DECREF(elem);
8343 PyMem_Free(grouplist);
8344 return NULL;
8345 }
8346 }
8347 Py_DECREF(elem);
8348 }
8349
8350 if (setgroups(len, grouplist) < 0) {
8351 PyMem_Free(grouplist);
8352 return posix_error();
8353 }
8354 PyMem_Free(grouplist);
8355 Py_RETURN_NONE;
8356 }
8357 #endif /* HAVE_SETGROUPS */
8358
8359 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
8360 static PyObject *
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)8361 wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
8362 {
8363 PyObject *result;
8364 PyObject *struct_rusage;
8365
8366 if (pid == -1)
8367 return posix_error();
8368
8369 // If wait succeeded but no child was ready to report status, ru will not
8370 // have been populated.
8371 if (pid == 0) {
8372 memset(ru, 0, sizeof(*ru));
8373 }
8374
8375 PyObject *m = PyImport_ImportModule("resource");
8376 if (m == NULL)
8377 return NULL;
8378 struct_rusage = PyObject_GetAttr(m, get_posix_state(module)->struct_rusage);
8379 Py_DECREF(m);
8380 if (struct_rusage == NULL)
8381 return NULL;
8382
8383 /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
8384 result = PyStructSequence_New((PyTypeObject*) struct_rusage);
8385 Py_DECREF(struct_rusage);
8386 if (!result)
8387 return NULL;
8388
8389 #ifndef doubletime
8390 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
8391 #endif
8392
8393 PyStructSequence_SET_ITEM(result, 0,
8394 PyFloat_FromDouble(doubletime(ru->ru_utime)));
8395 PyStructSequence_SET_ITEM(result, 1,
8396 PyFloat_FromDouble(doubletime(ru->ru_stime)));
8397 #define SET_INT(result, index, value)\
8398 PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
8399 SET_INT(result, 2, ru->ru_maxrss);
8400 SET_INT(result, 3, ru->ru_ixrss);
8401 SET_INT(result, 4, ru->ru_idrss);
8402 SET_INT(result, 5, ru->ru_isrss);
8403 SET_INT(result, 6, ru->ru_minflt);
8404 SET_INT(result, 7, ru->ru_majflt);
8405 SET_INT(result, 8, ru->ru_nswap);
8406 SET_INT(result, 9, ru->ru_inblock);
8407 SET_INT(result, 10, ru->ru_oublock);
8408 SET_INT(result, 11, ru->ru_msgsnd);
8409 SET_INT(result, 12, ru->ru_msgrcv);
8410 SET_INT(result, 13, ru->ru_nsignals);
8411 SET_INT(result, 14, ru->ru_nvcsw);
8412 SET_INT(result, 15, ru->ru_nivcsw);
8413 #undef SET_INT
8414
8415 if (PyErr_Occurred()) {
8416 Py_DECREF(result);
8417 return NULL;
8418 }
8419
8420 return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
8421 }
8422 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
8423
8424
8425 #ifdef HAVE_WAIT3
8426 /*[clinic input]
8427 os.wait3
8428
8429 options: int
8430 Wait for completion of a child process.
8431
8432 Returns a tuple of information about the child process:
8433 (pid, status, rusage)
8434 [clinic start generated code]*/
8435
8436 static PyObject *
os_wait3_impl(PyObject *module, int options)8437 os_wait3_impl(PyObject *module, int options)
8438 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
8439 {
8440 pid_t pid;
8441 struct rusage ru;
8442 int async_err = 0;
8443 WAIT_TYPE status;
8444 WAIT_STATUS_INT(status) = 0;
8445
8446 do {
8447 Py_BEGIN_ALLOW_THREADS
8448 pid = wait3(&status, options, &ru);
8449 Py_END_ALLOW_THREADS
8450 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8451 if (pid < 0)
8452 return (!async_err) ? posix_error() : NULL;
8453
8454 return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
8455 }
8456 #endif /* HAVE_WAIT3 */
8457
8458
8459 #ifdef HAVE_WAIT4
8460 /*[clinic input]
8461
8462 os.wait4
8463
8464 pid: pid_t
8465 options: int
8466
8467 Wait for completion of a specific child process.
8468
8469 Returns a tuple of information about the child process:
8470 (pid, status, rusage)
8471 [clinic start generated code]*/
8472
8473 static PyObject *
os_wait4_impl(PyObject *module, pid_t pid, int options)8474 os_wait4_impl(PyObject *module, pid_t pid, int options)
8475 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
8476 {
8477 pid_t res;
8478 struct rusage ru;
8479 int async_err = 0;
8480 WAIT_TYPE status;
8481 WAIT_STATUS_INT(status) = 0;
8482
8483 do {
8484 Py_BEGIN_ALLOW_THREADS
8485 res = wait4(pid, &status, options, &ru);
8486 Py_END_ALLOW_THREADS
8487 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8488 if (res < 0)
8489 return (!async_err) ? posix_error() : NULL;
8490
8491 return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
8492 }
8493 #endif /* HAVE_WAIT4 */
8494
8495
8496 #if defined(HAVE_WAITID) && !defined(__APPLE__)
8497 /*[clinic input]
8498 os.waitid
8499
8500 idtype: idtype_t
8501 Must be one of be P_PID, P_PGID or P_ALL.
8502 id: id_t
8503 The id to wait on.
8504 options: int
8505 Constructed from the ORing of one or more of WEXITED, WSTOPPED
8506 or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
8507 /
8508
8509 Returns the result of waiting for a process or processes.
8510
8511 Returns either waitid_result or None if WNOHANG is specified and there are
8512 no children in a waitable state.
8513 [clinic start generated code]*/
8514
8515 static PyObject *
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)8516 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
8517 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
8518 {
8519 PyObject *result;
8520 int res;
8521 int async_err = 0;
8522 siginfo_t si;
8523 si.si_pid = 0;
8524
8525 do {
8526 Py_BEGIN_ALLOW_THREADS
8527 res = waitid(idtype, id, &si, options);
8528 Py_END_ALLOW_THREADS
8529 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8530 if (res < 0)
8531 return (!async_err) ? posix_error() : NULL;
8532
8533 if (si.si_pid == 0)
8534 Py_RETURN_NONE;
8535
8536 PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
8537 result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
8538 if (!result)
8539 return NULL;
8540
8541 PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
8542 PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
8543 PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
8544 PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
8545 PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
8546 if (PyErr_Occurred()) {
8547 Py_DECREF(result);
8548 return NULL;
8549 }
8550
8551 return result;
8552 }
8553 #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
8554
8555
8556 #if defined(HAVE_WAITPID)
8557 /*[clinic input]
8558 os.waitpid
8559 pid: pid_t
8560 options: int
8561 /
8562
8563 Wait for completion of a given child process.
8564
8565 Returns a tuple of information regarding the child process:
8566 (pid, status)
8567
8568 The options argument is ignored on Windows.
8569 [clinic start generated code]*/
8570
8571 static PyObject *
os_waitpid_impl(PyObject *module, pid_t pid, int options)8572 os_waitpid_impl(PyObject *module, pid_t pid, int options)
8573 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
8574 {
8575 pid_t res;
8576 int async_err = 0;
8577 WAIT_TYPE status;
8578 WAIT_STATUS_INT(status) = 0;
8579
8580 do {
8581 Py_BEGIN_ALLOW_THREADS
8582 res = waitpid(pid, &status, options);
8583 Py_END_ALLOW_THREADS
8584 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8585 if (res < 0)
8586 return (!async_err) ? posix_error() : NULL;
8587
8588 return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
8589 }
8590 #elif defined(HAVE_CWAIT)
8591 /* MS C has a variant of waitpid() that's usable for most purposes. */
8592 /*[clinic input]
8593 os.waitpid
8594 pid: intptr_t
8595 options: int
8596 /
8597
8598 Wait for completion of a given process.
8599
8600 Returns a tuple of information regarding the process:
8601 (pid, status << 8)
8602
8603 The options argument is ignored on Windows.
8604 [clinic start generated code]*/
8605
8606 static PyObject *
os_waitpid_impl(PyObject *module, intptr_t pid, int options)8607 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
8608 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
8609 {
8610 int status;
8611 intptr_t res;
8612 int async_err = 0;
8613
8614 do {
8615 Py_BEGIN_ALLOW_THREADS
8616 _Py_BEGIN_SUPPRESS_IPH
8617 res = _cwait(&status, pid, options);
8618 _Py_END_SUPPRESS_IPH
8619 Py_END_ALLOW_THREADS
8620 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8621 if (res < 0)
8622 return (!async_err) ? posix_error() : NULL;
8623
8624 unsigned long long ustatus = (unsigned int)status;
8625
8626 /* shift the status left a byte so this is more like the POSIX waitpid */
8627 return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
8628 }
8629 #endif
8630
8631
8632 #ifdef HAVE_WAIT
8633 /*[clinic input]
8634 os.wait
8635
8636 Wait for completion of a child process.
8637
8638 Returns a tuple of information about the child process:
8639 (pid, status)
8640 [clinic start generated code]*/
8641
8642 static PyObject *
os_wait_impl(PyObject *module)8643 os_wait_impl(PyObject *module)
8644 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
8645 {
8646 pid_t pid;
8647 int async_err = 0;
8648 WAIT_TYPE status;
8649 WAIT_STATUS_INT(status) = 0;
8650
8651 do {
8652 Py_BEGIN_ALLOW_THREADS
8653 pid = wait(&status);
8654 Py_END_ALLOW_THREADS
8655 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8656 if (pid < 0)
8657 return (!async_err) ? posix_error() : NULL;
8658
8659 return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
8660 }
8661 #endif /* HAVE_WAIT */
8662
8663 #if defined(__linux__) && defined(__NR_pidfd_open)
8664 /*[clinic input]
8665 os.pidfd_open
8666 pid: pid_t
8667 flags: unsigned_int = 0
8668
8669 Return a file descriptor referring to the process *pid*.
8670
8671 The descriptor can be used to perform process management without races and
8672 signals.
8673 [clinic start generated code]*/
8674
8675 static PyObject *
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)8676 os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
8677 /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
8678 {
8679 int fd = syscall(__NR_pidfd_open, pid, flags);
8680 if (fd < 0) {
8681 return posix_error();
8682 }
8683 return PyLong_FromLong(fd);
8684 }
8685 #endif
8686
8687
8688 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
8689 /*[clinic input]
8690 os.readlink
8691
8692 path: path_t
8693 *
8694 dir_fd: dir_fd(requires='readlinkat') = None
8695
8696 Return a string representing the path to which the symbolic link points.
8697
8698 If dir_fd is not None, it should be a file descriptor open to a directory,
8699 and path should be relative; path will then be relative to that directory.
8700
8701 dir_fd may not be implemented on your platform. If it is unavailable,
8702 using it will raise a NotImplementedError.
8703 [clinic start generated code]*/
8704
8705 static PyObject *
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)8706 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
8707 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
8708 {
8709 #if defined(HAVE_READLINK)
8710 char buffer[MAXPATHLEN+1];
8711 ssize_t length;
8712 #ifdef HAVE_READLINKAT
8713 int readlinkat_unavailable = 0;
8714 #endif
8715
8716 Py_BEGIN_ALLOW_THREADS
8717 #ifdef HAVE_READLINKAT
8718 if (dir_fd != DEFAULT_DIR_FD) {
8719 if (HAVE_READLINKAT_RUNTIME) {
8720 length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
8721 } else {
8722 readlinkat_unavailable = 1;
8723 }
8724 } else
8725 #endif
8726 length = readlink(path->narrow, buffer, MAXPATHLEN);
8727 Py_END_ALLOW_THREADS
8728
8729 #ifdef HAVE_READLINKAT
8730 if (readlinkat_unavailable) {
8731 argument_unavailable_error(NULL, "dir_fd");
8732 return NULL;
8733 }
8734 #endif
8735
8736 if (length < 0) {
8737 return path_error(path);
8738 }
8739 buffer[length] = '\0';
8740
8741 if (PyUnicode_Check(path->object))
8742 return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
8743 else
8744 return PyBytes_FromStringAndSize(buffer, length);
8745 #elif defined(MS_WINDOWS)
8746 DWORD n_bytes_returned;
8747 DWORD io_result = 0;
8748 HANDLE reparse_point_handle;
8749 char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
8750 _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
8751 PyObject *result = NULL;
8752
8753 /* First get a handle to the reparse point */
8754 Py_BEGIN_ALLOW_THREADS
8755 reparse_point_handle = CreateFileW(
8756 path->wide,
8757 0,
8758 0,
8759 0,
8760 OPEN_EXISTING,
8761 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
8762 0);
8763 if (reparse_point_handle != INVALID_HANDLE_VALUE) {
8764 /* New call DeviceIoControl to read the reparse point */
8765 io_result = DeviceIoControl(
8766 reparse_point_handle,
8767 FSCTL_GET_REPARSE_POINT,
8768 0, 0, /* in buffer */
8769 target_buffer, sizeof(target_buffer),
8770 &n_bytes_returned,
8771 0 /* we're not using OVERLAPPED_IO */
8772 );
8773 CloseHandle(reparse_point_handle);
8774 }
8775 Py_END_ALLOW_THREADS
8776
8777 if (io_result == 0) {
8778 return path_error(path);
8779 }
8780
8781 wchar_t *name = NULL;
8782 Py_ssize_t nameLen = 0;
8783 if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
8784 {
8785 name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
8786 rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
8787 nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8788 }
8789 else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
8790 {
8791 name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8792 rdb->MountPointReparseBuffer.SubstituteNameOffset);
8793 nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8794 }
8795 else
8796 {
8797 PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8798 }
8799 if (name) {
8800 if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8801 /* Our buffer is mutable, so this is okay */
8802 name[1] = L'\\';
8803 }
8804 result = PyUnicode_FromWideChar(name, nameLen);
8805 if (result && path->narrow) {
8806 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8807 }
8808 }
8809 return result;
8810 #endif
8811 }
8812 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8813
8814 #if defined(MS_WINDOWS)
8815
8816 /* Remove the last portion of the path - return 0 on success */
8817 static int
_dirnameW(WCHAR *path)8818 _dirnameW(WCHAR *path)
8819 {
8820 WCHAR *ptr;
8821 size_t length = wcsnlen_s(path, MAX_PATH);
8822 if (length == MAX_PATH) {
8823 return -1;
8824 }
8825
8826 /* walk the path from the end until a backslash is encountered */
8827 for(ptr = path + length; ptr != path; ptr--) {
8828 if (*ptr == L'\\' || *ptr == L'/') {
8829 break;
8830 }
8831 }
8832 *ptr = 0;
8833 return 0;
8834 }
8835
8836 #endif
8837
8838 #ifdef HAVE_SYMLINK
8839
8840 #if defined(MS_WINDOWS)
8841
8842 /* Is this path absolute? */
8843 static int
_is_absW(const WCHAR *path)8844 _is_absW(const WCHAR *path)
8845 {
8846 return path[0] == L'\\' || path[0] == L'/' ||
8847 (path[0] && path[1] == L':');
8848 }
8849
8850 /* join root and rest with a backslash - return 0 on success */
8851 static int
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)8852 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8853 {
8854 if (_is_absW(rest)) {
8855 return wcscpy_s(dest_path, MAX_PATH, rest);
8856 }
8857
8858 if (wcscpy_s(dest_path, MAX_PATH, root)) {
8859 return -1;
8860 }
8861
8862 if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8863 return -1;
8864 }
8865
8866 return wcscat_s(dest_path, MAX_PATH, rest);
8867 }
8868
8869 /* Return True if the path at src relative to dest is a directory */
8870 static int
_check_dirW(LPCWSTR src, LPCWSTR dest)8871 _check_dirW(LPCWSTR src, LPCWSTR dest)
8872 {
8873 WIN32_FILE_ATTRIBUTE_DATA src_info;
8874 WCHAR dest_parent[MAX_PATH];
8875 WCHAR src_resolved[MAX_PATH] = L"";
8876
8877 /* dest_parent = os.path.dirname(dest) */
8878 if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8879 _dirnameW(dest_parent)) {
8880 return 0;
8881 }
8882 /* src_resolved = os.path.join(dest_parent, src) */
8883 if (_joinW(src_resolved, dest_parent, src)) {
8884 return 0;
8885 }
8886 return (
8887 GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8888 && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8889 );
8890 }
8891 #endif
8892
8893
8894 /*[clinic input]
8895 os.symlink
8896 src: path_t
8897 dst: path_t
8898 target_is_directory: bool = False
8899 *
8900 dir_fd: dir_fd(requires='symlinkat')=None
8901
8902 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8903
8904 Create a symbolic link pointing to src named dst.
8905
8906 target_is_directory is required on Windows if the target is to be
8907 interpreted as a directory. (On Windows, symlink requires
8908 Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8909 target_is_directory is ignored on non-Windows platforms.
8910
8911 If dir_fd is not None, it should be a file descriptor open to a directory,
8912 and path should be relative; path will then be relative to that directory.
8913 dir_fd may not be implemented on your platform.
8914 If it is unavailable, using it will raise a NotImplementedError.
8915
8916 [clinic start generated code]*/
8917
8918 static PyObject *
os_symlink_impl(PyObject *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd)8919 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8920 int target_is_directory, int dir_fd)
8921 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8922 {
8923 #ifdef MS_WINDOWS
8924 DWORD result;
8925 DWORD flags = 0;
8926
8927 /* Assumed true, set to false if detected to not be available. */
8928 static int windows_has_symlink_unprivileged_flag = TRUE;
8929 #else
8930 int result;
8931 #ifdef HAVE_SYMLINKAT
8932 int symlinkat_unavailable = 0;
8933 #endif
8934 #endif
8935
8936 if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8937 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8938 return NULL;
8939 }
8940
8941 #ifdef MS_WINDOWS
8942
8943 if (windows_has_symlink_unprivileged_flag) {
8944 /* Allow non-admin symlinks if system allows it. */
8945 flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8946 }
8947
8948 Py_BEGIN_ALLOW_THREADS
8949 _Py_BEGIN_SUPPRESS_IPH
8950 /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8951 if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8952 flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8953 }
8954
8955 result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8956 _Py_END_SUPPRESS_IPH
8957 Py_END_ALLOW_THREADS
8958
8959 if (windows_has_symlink_unprivileged_flag && !result &&
8960 ERROR_INVALID_PARAMETER == GetLastError()) {
8961
8962 Py_BEGIN_ALLOW_THREADS
8963 _Py_BEGIN_SUPPRESS_IPH
8964 /* This error might be caused by
8965 SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8966 Try again, and update windows_has_symlink_unprivileged_flag if we
8967 are successful this time.
8968
8969 NOTE: There is a risk of a race condition here if there are other
8970 conditions than the flag causing ERROR_INVALID_PARAMETER, and
8971 another process (or thread) changes that condition in between our
8972 calls to CreateSymbolicLink.
8973 */
8974 flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8975 result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8976 _Py_END_SUPPRESS_IPH
8977 Py_END_ALLOW_THREADS
8978
8979 if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8980 windows_has_symlink_unprivileged_flag = FALSE;
8981 }
8982 }
8983
8984 if (!result)
8985 return path_error2(src, dst);
8986
8987 #else
8988
8989 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8990 PyErr_SetString(PyExc_ValueError,
8991 "symlink: src and dst must be the same type");
8992 return NULL;
8993 }
8994
8995 Py_BEGIN_ALLOW_THREADS
8996 #ifdef HAVE_SYMLINKAT
8997 if (dir_fd != DEFAULT_DIR_FD) {
8998 if (HAVE_SYMLINKAT_RUNTIME) {
8999 result = symlinkat(src->narrow, dir_fd, dst->narrow);
9000 } else {
9001 symlinkat_unavailable = 1;
9002 }
9003 } else
9004 #endif
9005 result = symlink(src->narrow, dst->narrow);
9006 Py_END_ALLOW_THREADS
9007
9008 #ifdef HAVE_SYMLINKAT
9009 if (symlinkat_unavailable) {
9010 argument_unavailable_error(NULL, "dir_fd");
9011 return NULL;
9012 }
9013 #endif
9014
9015 if (result)
9016 return path_error2(src, dst);
9017 #endif
9018
9019 Py_RETURN_NONE;
9020 }
9021 #endif /* HAVE_SYMLINK */
9022
9023
9024
9025
9026 static PyStructSequence_Field times_result_fields[] = {
9027 {"user", "user time"},
9028 {"system", "system time"},
9029 {"children_user", "user time of children"},
9030 {"children_system", "system time of children"},
9031 {"elapsed", "elapsed time since an arbitrary point in the past"},
9032 {NULL}
9033 };
9034
9035 PyDoc_STRVAR(times_result__doc__,
9036 "times_result: Result from os.times().\n\n\
9037 This object may be accessed either as a tuple of\n\
9038 (user, system, children_user, children_system, elapsed),\n\
9039 or via the attributes user, system, children_user, children_system,\n\
9040 and elapsed.\n\
9041 \n\
9042 See os.times for more information.");
9043
9044 static PyStructSequence_Desc times_result_desc = {
9045 "times_result", /* name */
9046 times_result__doc__, /* doc */
9047 times_result_fields,
9048 5
9049 };
9050
9051 #ifdef MS_WINDOWS
9052 #define HAVE_TIMES /* mandatory, for the method table */
9053 #endif
9054
9055 #ifdef HAVE_TIMES
9056
9057 static PyObject *
build_times_result(PyObject *module, double user, double system, double children_user, double children_system, double elapsed)9058 build_times_result(PyObject *module, double user, double system,
9059 double children_user, double children_system,
9060 double elapsed)
9061 {
9062 PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
9063 PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
9064 if (value == NULL)
9065 return NULL;
9066
9067 #define SET(i, field) \
9068 { \
9069 PyObject *o = PyFloat_FromDouble(field); \
9070 if (!o) { \
9071 Py_DECREF(value); \
9072 return NULL; \
9073 } \
9074 PyStructSequence_SET_ITEM(value, i, o); \
9075 } \
9076
9077 SET(0, user);
9078 SET(1, system);
9079 SET(2, children_user);
9080 SET(3, children_system);
9081 SET(4, elapsed);
9082
9083 #undef SET
9084
9085 return value;
9086 }
9087
9088
9089 #ifndef MS_WINDOWS
9090 #define NEED_TICKS_PER_SECOND
9091 static long ticks_per_second = -1;
9092 #endif /* MS_WINDOWS */
9093
9094 /*[clinic input]
9095 os.times
9096
9097 Return a collection containing process timing information.
9098
9099 The object returned behaves like a named tuple with these fields:
9100 (utime, stime, cutime, cstime, elapsed_time)
9101 All fields are floating point numbers.
9102 [clinic start generated code]*/
9103
9104 static PyObject *
os_times_impl(PyObject *module)9105 os_times_impl(PyObject *module)
9106 /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
9107 #ifdef MS_WINDOWS
9108 {
9109 FILETIME create, exit, kernel, user;
9110 HANDLE hProc;
9111 hProc = GetCurrentProcess();
9112 GetProcessTimes(hProc, &create, &exit, &kernel, &user);
9113 /* The fields of a FILETIME structure are the hi and lo part
9114 of a 64-bit value expressed in 100 nanosecond units.
9115 1e7 is one second in such units; 1e-7 the inverse.
9116 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
9117 */
9118 return build_times_result(module,
9119 (double)(user.dwHighDateTime*429.4967296 +
9120 user.dwLowDateTime*1e-7),
9121 (double)(kernel.dwHighDateTime*429.4967296 +
9122 kernel.dwLowDateTime*1e-7),
9123 (double)0,
9124 (double)0,
9125 (double)0);
9126 }
9127 #else /* MS_WINDOWS */
9128 {
9129
9130
9131 struct tms t;
9132 clock_t c;
9133 errno = 0;
9134 c = times(&t);
9135 if (c == (clock_t) -1)
9136 return posix_error();
9137 return build_times_result(module,
9138 (double)t.tms_utime / ticks_per_second,
9139 (double)t.tms_stime / ticks_per_second,
9140 (double)t.tms_cutime / ticks_per_second,
9141 (double)t.tms_cstime / ticks_per_second,
9142 (double)c / ticks_per_second);
9143 }
9144 #endif /* MS_WINDOWS */
9145 #endif /* HAVE_TIMES */
9146
9147
9148 #ifdef HAVE_GETSID
9149 /*[clinic input]
9150 os.getsid
9151
9152 pid: pid_t
9153 /
9154
9155 Call the system call getsid(pid) and return the result.
9156 [clinic start generated code]*/
9157
9158 static PyObject *
os_getsid_impl(PyObject *module, pid_t pid)9159 os_getsid_impl(PyObject *module, pid_t pid)
9160 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
9161 {
9162 int sid;
9163 sid = getsid(pid);
9164 if (sid < 0)
9165 return posix_error();
9166 return PyLong_FromLong((long)sid);
9167 }
9168 #endif /* HAVE_GETSID */
9169
9170
9171 #ifdef HAVE_SETSID
9172 /*[clinic input]
9173 os.setsid
9174
9175 Call the system call setsid().
9176 [clinic start generated code]*/
9177
9178 static PyObject *
os_setsid_impl(PyObject *module)9179 os_setsid_impl(PyObject *module)
9180 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
9181 {
9182 if (setsid() < 0)
9183 return posix_error();
9184 Py_RETURN_NONE;
9185 }
9186 #endif /* HAVE_SETSID */
9187
9188
9189 #ifdef HAVE_SETPGID
9190 /*[clinic input]
9191 os.setpgid
9192
9193 pid: pid_t
9194 pgrp: pid_t
9195 /
9196
9197 Call the system call setpgid(pid, pgrp).
9198 [clinic start generated code]*/
9199
9200 static PyObject *
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)9201 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
9202 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
9203 {
9204 if (setpgid(pid, pgrp) < 0)
9205 return posix_error();
9206 Py_RETURN_NONE;
9207 }
9208 #endif /* HAVE_SETPGID */
9209
9210
9211 #ifdef HAVE_TCGETPGRP
9212 /*[clinic input]
9213 os.tcgetpgrp
9214
9215 fd: int
9216 /
9217
9218 Return the process group associated with the terminal specified by fd.
9219 [clinic start generated code]*/
9220
9221 static PyObject *
os_tcgetpgrp_impl(PyObject *module, int fd)9222 os_tcgetpgrp_impl(PyObject *module, int fd)
9223 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
9224 {
9225 pid_t pgid = tcgetpgrp(fd);
9226 if (pgid < 0)
9227 return posix_error();
9228 return PyLong_FromPid(pgid);
9229 }
9230 #endif /* HAVE_TCGETPGRP */
9231
9232
9233 #ifdef HAVE_TCSETPGRP
9234 /*[clinic input]
9235 os.tcsetpgrp
9236
9237 fd: int
9238 pgid: pid_t
9239 /
9240
9241 Set the process group associated with the terminal specified by fd.
9242 [clinic start generated code]*/
9243
9244 static PyObject *
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)9245 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
9246 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
9247 {
9248 if (tcsetpgrp(fd, pgid) < 0)
9249 return posix_error();
9250 Py_RETURN_NONE;
9251 }
9252 #endif /* HAVE_TCSETPGRP */
9253
9254 /* Functions acting on file descriptors */
9255
9256 #ifdef O_CLOEXEC
9257 extern int _Py_open_cloexec_works;
9258 #endif
9259
9260
9261 /*[clinic input]
9262 os.open -> int
9263 path: path_t
9264 flags: int
9265 mode: int = 0o777
9266 *
9267 dir_fd: dir_fd(requires='openat') = None
9268
9269 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
9270
9271 Open a file for low level IO. Returns a file descriptor (integer).
9272
9273 If dir_fd is not None, it should be a file descriptor open to a directory,
9274 and path should be relative; path will then be relative to that directory.
9275 dir_fd may not be implemented on your platform.
9276 If it is unavailable, using it will raise a NotImplementedError.
9277 [clinic start generated code]*/
9278
9279 static int
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)9280 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
9281 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
9282 {
9283 int fd;
9284 int async_err = 0;
9285 #ifdef HAVE_OPENAT
9286 int openat_unavailable = 0;
9287 #endif
9288
9289 #ifdef O_CLOEXEC
9290 int *atomic_flag_works = &_Py_open_cloexec_works;
9291 #elif !defined(MS_WINDOWS)
9292 int *atomic_flag_works = NULL;
9293 #endif
9294
9295 #ifdef MS_WINDOWS
9296 flags |= O_NOINHERIT;
9297 #elif defined(O_CLOEXEC)
9298 flags |= O_CLOEXEC;
9299 #endif
9300
9301 if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
9302 return -1;
9303 }
9304
9305 _Py_BEGIN_SUPPRESS_IPH
9306 do {
9307 Py_BEGIN_ALLOW_THREADS
9308 #ifdef MS_WINDOWS
9309 fd = _wopen(path->wide, flags, mode);
9310 #else
9311 #ifdef HAVE_OPENAT
9312 if (dir_fd != DEFAULT_DIR_FD) {
9313 if (HAVE_OPENAT_RUNTIME) {
9314 fd = openat(dir_fd, path->narrow, flags, mode);
9315
9316 } else {
9317 openat_unavailable = 1;
9318 fd = -1;
9319 }
9320 } else
9321 #endif /* HAVE_OPENAT */
9322 fd = open(path->narrow, flags, mode);
9323 #endif /* !MS_WINDOWS */
9324 Py_END_ALLOW_THREADS
9325 } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9326 _Py_END_SUPPRESS_IPH
9327
9328 #ifdef HAVE_OPENAT
9329 if (openat_unavailable) {
9330 argument_unavailable_error(NULL, "dir_fd");
9331 return -1;
9332 }
9333 #endif
9334
9335 if (fd < 0) {
9336 if (!async_err)
9337 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
9338 return -1;
9339 }
9340
9341 #ifndef MS_WINDOWS
9342 if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
9343 close(fd);
9344 return -1;
9345 }
9346 #endif
9347
9348 return fd;
9349 }
9350
9351
9352 /*[clinic input]
9353 os.close
9354
9355 fd: int
9356
9357 Close a file descriptor.
9358 [clinic start generated code]*/
9359
9360 static PyObject *
os_close_impl(PyObject *module, int fd)9361 os_close_impl(PyObject *module, int fd)
9362 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
9363 {
9364 int res;
9365 /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
9366 * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
9367 * for more details.
9368 */
9369 Py_BEGIN_ALLOW_THREADS
9370 _Py_BEGIN_SUPPRESS_IPH
9371 res = close(fd);
9372 _Py_END_SUPPRESS_IPH
9373 Py_END_ALLOW_THREADS
9374 if (res < 0)
9375 return posix_error();
9376 Py_RETURN_NONE;
9377 }
9378
9379 /*[clinic input]
9380 os.closerange
9381
9382 fd_low: int
9383 fd_high: int
9384 /
9385
9386 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
9387 [clinic start generated code]*/
9388
9389 static PyObject *
os_closerange_impl(PyObject *module, int fd_low, int fd_high)9390 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
9391 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
9392 {
9393 Py_BEGIN_ALLOW_THREADS
9394 _Py_closerange(fd_low, fd_high - 1);
9395 Py_END_ALLOW_THREADS
9396 Py_RETURN_NONE;
9397 }
9398
9399
9400 /*[clinic input]
9401 os.dup -> int
9402
9403 fd: int
9404 /
9405
9406 Return a duplicate of a file descriptor.
9407 [clinic start generated code]*/
9408
9409 static int
os_dup_impl(PyObject *module, int fd)9410 os_dup_impl(PyObject *module, int fd)
9411 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
9412 {
9413 return _Py_dup(fd);
9414 }
9415
9416 // dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
9417 // dup2.c provides working dup2() if and only if F_DUPFD is available.
9418 #if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
9419 /*[clinic input]
9420 os.dup2 -> int
9421 fd: int
9422 fd2: int
9423 inheritable: bool=True
9424
9425 Duplicate file descriptor.
9426 [clinic start generated code]*/
9427
9428 static int
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)9429 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
9430 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
9431 {
9432 int res = 0;
9433 #if defined(HAVE_DUP3) && \
9434 !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
9435 /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
9436 static int dup3_works = -1;
9437 #endif
9438
9439 /* dup2() can fail with EINTR if the target FD is already open, because it
9440 * then has to be closed. See os_close_impl() for why we don't handle EINTR
9441 * upon close(), and therefore below.
9442 */
9443 #ifdef MS_WINDOWS
9444 Py_BEGIN_ALLOW_THREADS
9445 _Py_BEGIN_SUPPRESS_IPH
9446 res = dup2(fd, fd2);
9447 _Py_END_SUPPRESS_IPH
9448 Py_END_ALLOW_THREADS
9449 if (res < 0) {
9450 posix_error();
9451 return -1;
9452 }
9453 res = fd2; // msvcrt dup2 returns 0 on success.
9454
9455 /* Character files like console cannot be make non-inheritable */
9456 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9457 close(fd2);
9458 return -1;
9459 }
9460
9461 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
9462 Py_BEGIN_ALLOW_THREADS
9463 if (!inheritable)
9464 res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
9465 else
9466 res = dup2(fd, fd2);
9467 Py_END_ALLOW_THREADS
9468 if (res < 0) {
9469 posix_error();
9470 return -1;
9471 }
9472
9473 #else
9474
9475 #ifdef HAVE_DUP3
9476 if (!inheritable && dup3_works != 0) {
9477 Py_BEGIN_ALLOW_THREADS
9478 res = dup3(fd, fd2, O_CLOEXEC);
9479 Py_END_ALLOW_THREADS
9480 if (res < 0) {
9481 if (dup3_works == -1)
9482 dup3_works = (errno != ENOSYS);
9483 if (dup3_works) {
9484 posix_error();
9485 return -1;
9486 }
9487 }
9488 }
9489
9490 if (inheritable || dup3_works == 0)
9491 {
9492 #endif
9493 Py_BEGIN_ALLOW_THREADS
9494 res = dup2(fd, fd2);
9495 Py_END_ALLOW_THREADS
9496 if (res < 0) {
9497 posix_error();
9498 return -1;
9499 }
9500
9501 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9502 close(fd2);
9503 return -1;
9504 }
9505 #ifdef HAVE_DUP3
9506 }
9507 #endif
9508
9509 #endif
9510
9511 return res;
9512 }
9513 #endif
9514
9515
9516 #ifdef HAVE_LOCKF
9517 /*[clinic input]
9518 os.lockf
9519
9520 fd: int
9521 An open file descriptor.
9522 command: int
9523 One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
9524 length: Py_off_t
9525 The number of bytes to lock, starting at the current position.
9526 /
9527
9528 Apply, test or remove a POSIX lock on an open file descriptor.
9529
9530 [clinic start generated code]*/
9531
9532 static PyObject *
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)9533 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
9534 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
9535 {
9536 int res;
9537
9538 if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
9539 return NULL;
9540 }
9541
9542 Py_BEGIN_ALLOW_THREADS
9543 res = lockf(fd, command, length);
9544 Py_END_ALLOW_THREADS
9545
9546 if (res < 0)
9547 return posix_error();
9548
9549 Py_RETURN_NONE;
9550 }
9551 #endif /* HAVE_LOCKF */
9552
9553
9554 /*[clinic input]
9555 os.lseek -> Py_off_t
9556
9557 fd: int
9558 position: Py_off_t
9559 how: int
9560 /
9561
9562 Set the position of a file descriptor. Return the new position.
9563
9564 Return the new cursor position in number of bytes
9565 relative to the beginning of the file.
9566 [clinic start generated code]*/
9567
9568 static Py_off_t
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)9569 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
9570 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
9571 {
9572 Py_off_t result;
9573
9574 #ifdef SEEK_SET
9575 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
9576 switch (how) {
9577 case 0: how = SEEK_SET; break;
9578 case 1: how = SEEK_CUR; break;
9579 case 2: how = SEEK_END; break;
9580 }
9581 #endif /* SEEK_END */
9582
9583 Py_BEGIN_ALLOW_THREADS
9584 _Py_BEGIN_SUPPRESS_IPH
9585 #ifdef MS_WINDOWS
9586 result = _lseeki64(fd, position, how);
9587 #else
9588 result = lseek(fd, position, how);
9589 #endif
9590 _Py_END_SUPPRESS_IPH
9591 Py_END_ALLOW_THREADS
9592 if (result < 0)
9593 posix_error();
9594
9595 return result;
9596 }
9597
9598
9599 /*[clinic input]
9600 os.read
9601 fd: int
9602 length: Py_ssize_t
9603 /
9604
9605 Read from a file descriptor. Returns a bytes object.
9606 [clinic start generated code]*/
9607
9608 static PyObject *
os_read_impl(PyObject *module, int fd, Py_ssize_t length)9609 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
9610 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
9611 {
9612 Py_ssize_t n;
9613 PyObject *buffer;
9614
9615 if (length < 0) {
9616 errno = EINVAL;
9617 return posix_error();
9618 }
9619
9620 length = Py_MIN(length, _PY_READ_MAX);
9621
9622 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9623 if (buffer == NULL)
9624 return NULL;
9625
9626 n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
9627 if (n == -1) {
9628 Py_DECREF(buffer);
9629 return NULL;
9630 }
9631
9632 if (n != length)
9633 _PyBytes_Resize(&buffer, n);
9634
9635 return buffer;
9636 }
9637
9638 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
9639 || defined(__APPLE__))) \
9640 || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
9641 || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9642 static int
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)9643 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
9644 {
9645 Py_ssize_t i, j;
9646
9647 *iov = PyMem_New(struct iovec, cnt);
9648 if (*iov == NULL) {
9649 PyErr_NoMemory();
9650 return -1;
9651 }
9652
9653 *buf = PyMem_New(Py_buffer, cnt);
9654 if (*buf == NULL) {
9655 PyMem_Free(*iov);
9656 PyErr_NoMemory();
9657 return -1;
9658 }
9659
9660 for (i = 0; i < cnt; i++) {
9661 PyObject *item = PySequence_GetItem(seq, i);
9662 if (item == NULL)
9663 goto fail;
9664 if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
9665 Py_DECREF(item);
9666 goto fail;
9667 }
9668 Py_DECREF(item);
9669 (*iov)[i].iov_base = (*buf)[i].buf;
9670 (*iov)[i].iov_len = (*buf)[i].len;
9671 }
9672 return 0;
9673
9674 fail:
9675 PyMem_Free(*iov);
9676 for (j = 0; j < i; j++) {
9677 PyBuffer_Release(&(*buf)[j]);
9678 }
9679 PyMem_Free(*buf);
9680 return -1;
9681 }
9682
9683 static void
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)9684 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9685 {
9686 int i;
9687 PyMem_Free(iov);
9688 for (i = 0; i < cnt; i++) {
9689 PyBuffer_Release(&buf[i]);
9690 }
9691 PyMem_Free(buf);
9692 }
9693 #endif
9694
9695
9696 #ifdef HAVE_READV
9697 /*[clinic input]
9698 os.readv -> Py_ssize_t
9699
9700 fd: int
9701 buffers: object
9702 /
9703
9704 Read from a file descriptor fd into an iterable of buffers.
9705
9706 The buffers should be mutable buffers accepting bytes.
9707 readv will transfer data into each buffer until it is full
9708 and then move on to the next buffer in the sequence to hold
9709 the rest of the data.
9710
9711 readv returns the total number of bytes read,
9712 which may be less than the total capacity of all the buffers.
9713 [clinic start generated code]*/
9714
9715 static Py_ssize_t
os_readv_impl(PyObject *module, int fd, PyObject *buffers)9716 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9717 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9718 {
9719 Py_ssize_t cnt, n;
9720 int async_err = 0;
9721 struct iovec *iov;
9722 Py_buffer *buf;
9723
9724 if (!PySequence_Check(buffers)) {
9725 PyErr_SetString(PyExc_TypeError,
9726 "readv() arg 2 must be a sequence");
9727 return -1;
9728 }
9729
9730 cnt = PySequence_Size(buffers);
9731 if (cnt < 0)
9732 return -1;
9733
9734 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9735 return -1;
9736
9737 do {
9738 Py_BEGIN_ALLOW_THREADS
9739 n = readv(fd, iov, cnt);
9740 Py_END_ALLOW_THREADS
9741 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9742
9743 iov_cleanup(iov, buf, cnt);
9744 if (n < 0) {
9745 if (!async_err)
9746 posix_error();
9747 return -1;
9748 }
9749
9750 return n;
9751 }
9752 #endif /* HAVE_READV */
9753
9754
9755 #ifdef HAVE_PREAD
9756 /*[clinic input]
9757 os.pread
9758
9759 fd: int
9760 length: Py_ssize_t
9761 offset: Py_off_t
9762 /
9763
9764 Read a number of bytes from a file descriptor starting at a particular offset.
9765
9766 Read length bytes from file descriptor fd, starting at offset bytes from
9767 the beginning of the file. The file offset remains unchanged.
9768 [clinic start generated code]*/
9769
9770 static PyObject *
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)9771 os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
9772 /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
9773 {
9774 Py_ssize_t n;
9775 int async_err = 0;
9776 PyObject *buffer;
9777
9778 if (length < 0) {
9779 errno = EINVAL;
9780 return posix_error();
9781 }
9782 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9783 if (buffer == NULL)
9784 return NULL;
9785
9786 do {
9787 Py_BEGIN_ALLOW_THREADS
9788 _Py_BEGIN_SUPPRESS_IPH
9789 n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9790 _Py_END_SUPPRESS_IPH
9791 Py_END_ALLOW_THREADS
9792 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9793
9794 if (n < 0) {
9795 Py_DECREF(buffer);
9796 return (!async_err) ? posix_error() : NULL;
9797 }
9798 if (n != length)
9799 _PyBytes_Resize(&buffer, n);
9800 return buffer;
9801 }
9802 #endif /* HAVE_PREAD */
9803
9804 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9805 /*[clinic input]
9806 os.preadv -> Py_ssize_t
9807
9808 fd: int
9809 buffers: object
9810 offset: Py_off_t
9811 flags: int = 0
9812 /
9813
9814 Reads from a file descriptor into a number of mutable bytes-like objects.
9815
9816 Combines the functionality of readv() and pread(). As readv(), it will
9817 transfer data into each buffer until it is full and then move on to the next
9818 buffer in the sequence to hold the rest of the data. Its fourth argument,
9819 specifies the file offset at which the input operation is to be performed. It
9820 will return the total number of bytes read (which can be less than the total
9821 capacity of all the objects).
9822
9823 The flags argument contains a bitwise OR of zero or more of the following flags:
9824
9825 - RWF_HIPRI
9826 - RWF_NOWAIT
9827
9828 Using non-zero flags requires Linux 4.6 or newer.
9829 [clinic start generated code]*/
9830
9831 static Py_ssize_t
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags)9832 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9833 int flags)
9834 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9835 {
9836 Py_ssize_t cnt, n;
9837 int async_err = 0;
9838 struct iovec *iov;
9839 Py_buffer *buf;
9840
9841 if (!PySequence_Check(buffers)) {
9842 PyErr_SetString(PyExc_TypeError,
9843 "preadv2() arg 2 must be a sequence");
9844 return -1;
9845 }
9846
9847 cnt = PySequence_Size(buffers);
9848 if (cnt < 0) {
9849 return -1;
9850 }
9851
9852 #ifndef HAVE_PREADV2
9853 if(flags != 0) {
9854 argument_unavailable_error("preadv2", "flags");
9855 return -1;
9856 }
9857 #endif
9858
9859 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9860 return -1;
9861 }
9862 #ifdef HAVE_PREADV2
9863 do {
9864 Py_BEGIN_ALLOW_THREADS
9865 _Py_BEGIN_SUPPRESS_IPH
9866 n = preadv2(fd, iov, cnt, offset, flags);
9867 _Py_END_SUPPRESS_IPH
9868 Py_END_ALLOW_THREADS
9869 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9870 #else
9871 do {
9872 #if defined(__APPLE__) && defined(__clang__)
9873 /* This entire function will be removed from the module dict when the API
9874 * is not available.
9875 */
9876 #pragma clang diagnostic push
9877 #pragma clang diagnostic ignored "-Wunguarded-availability"
9878 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
9879 #endif
9880 Py_BEGIN_ALLOW_THREADS
9881 _Py_BEGIN_SUPPRESS_IPH
9882 n = preadv(fd, iov, cnt, offset);
9883 _Py_END_SUPPRESS_IPH
9884 Py_END_ALLOW_THREADS
9885 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9886
9887 #if defined(__APPLE__) && defined(__clang__)
9888 #pragma clang diagnostic pop
9889 #endif
9890
9891 #endif
9892
9893 iov_cleanup(iov, buf, cnt);
9894 if (n < 0) {
9895 if (!async_err) {
9896 posix_error();
9897 }
9898 return -1;
9899 }
9900
9901 return n;
9902 }
9903 #endif /* HAVE_PREADV */
9904
9905
9906 /*[clinic input]
9907 os.write -> Py_ssize_t
9908
9909 fd: int
9910 data: Py_buffer
9911 /
9912
9913 Write a bytes object to a file descriptor.
9914 [clinic start generated code]*/
9915
9916 static Py_ssize_t
os_write_impl(PyObject *module, int fd, Py_buffer *data)9917 os_write_impl(PyObject *module, int fd, Py_buffer *data)
9918 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9919 {
9920 return _Py_write(fd, data->buf, data->len);
9921 }
9922
9923 #ifdef HAVE_SENDFILE
9924 #ifdef __APPLE__
9925 /*[clinic input]
9926 os.sendfile
9927
9928 out_fd: int
9929 in_fd: int
9930 offset: Py_off_t
9931 count as sbytes: Py_off_t
9932 headers: object(c_default="NULL") = ()
9933 trailers: object(c_default="NULL") = ()
9934 flags: int = 0
9935
9936 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9937 [clinic start generated code]*/
9938
9939 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)9940 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9941 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
9942 int flags)
9943 /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
9944 #elif defined(__FreeBSD__) || defined(__DragonFly__)
9945 /*[clinic input]
9946 os.sendfile
9947
9948 out_fd: int
9949 in_fd: int
9950 offset: Py_off_t
9951 count: Py_ssize_t
9952 headers: object(c_default="NULL") = ()
9953 trailers: object(c_default="NULL") = ()
9954 flags: int = 0
9955
9956 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9957 [clinic start generated code]*/
9958
9959 static PyObject *
9960 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9961 Py_ssize_t count, PyObject *headers, PyObject *trailers,
9962 int flags)
9963 /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
9964 #else
9965 /*[clinic input]
9966 os.sendfile
9967
9968 out_fd: int
9969 in_fd: int
9970 offset as offobj: object
9971 count: Py_ssize_t
9972
9973 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9974 [clinic start generated code]*/
9975
9976 static PyObject *
9977 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
9978 Py_ssize_t count)
9979 /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
9980 #endif
9981 {
9982 Py_ssize_t ret;
9983 int async_err = 0;
9984
9985 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9986 #ifndef __APPLE__
9987 off_t sbytes;
9988 #endif
9989 Py_buffer *hbuf, *tbuf;
9990 struct sf_hdtr sf;
9991
9992 sf.headers = NULL;
9993 sf.trailers = NULL;
9994
9995 if (headers != NULL) {
9996 if (!PySequence_Check(headers)) {
9997 PyErr_SetString(PyExc_TypeError,
9998 "sendfile() headers must be a sequence");
9999 return NULL;
10000 } else {
10001 Py_ssize_t i = PySequence_Size(headers);
10002 if (i < 0)
10003 return NULL;
10004 if (i > INT_MAX) {
10005 PyErr_SetString(PyExc_OverflowError,
10006 "sendfile() header is too large");
10007 return NULL;
10008 }
10009 if (i > 0) {
10010 sf.hdr_cnt = (int)i;
10011 if (iov_setup(&(sf.headers), &hbuf,
10012 headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
10013 return NULL;
10014 #ifdef __APPLE__
10015 for (i = 0; i < sf.hdr_cnt; i++) {
10016 Py_ssize_t blen = sf.headers[i].iov_len;
10017 # define OFF_T_MAX 0x7fffffffffffffff
10018 if (sbytes >= OFF_T_MAX - blen) {
10019 PyErr_SetString(PyExc_OverflowError,
10020 "sendfile() header is too large");
10021 return NULL;
10022 }
10023 sbytes += blen;
10024 }
10025 #endif
10026 }
10027 }
10028 }
10029 if (trailers != NULL) {
10030 if (!PySequence_Check(trailers)) {
10031 PyErr_SetString(PyExc_TypeError,
10032 "sendfile() trailers must be a sequence");
10033 return NULL;
10034 } else {
10035 Py_ssize_t i = PySequence_Size(trailers);
10036 if (i < 0)
10037 return NULL;
10038 if (i > INT_MAX) {
10039 PyErr_SetString(PyExc_OverflowError,
10040 "sendfile() trailer is too large");
10041 return NULL;
10042 }
10043 if (i > 0) {
10044 sf.trl_cnt = (int)i;
10045 if (iov_setup(&(sf.trailers), &tbuf,
10046 trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
10047 return NULL;
10048 }
10049 }
10050 }
10051
10052 _Py_BEGIN_SUPPRESS_IPH
10053 do {
10054 Py_BEGIN_ALLOW_THREADS
10055 #ifdef __APPLE__
10056 ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
10057 #else
10058 ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
10059 #endif
10060 Py_END_ALLOW_THREADS
10061 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10062 _Py_END_SUPPRESS_IPH
10063
10064 if (sf.headers != NULL)
10065 iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
10066 if (sf.trailers != NULL)
10067 iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
10068
10069 if (ret < 0) {
10070 if ((errno == EAGAIN) || (errno == EBUSY)) {
10071 if (sbytes != 0) {
10072 // some data has been sent
10073 goto done;
10074 }
10075 else {
10076 // no data has been sent; upper application is supposed
10077 // to retry on EAGAIN or EBUSY
10078 return posix_error();
10079 }
10080 }
10081 return (!async_err) ? posix_error() : NULL;
10082 }
10083 goto done;
10084
10085 done:
10086 #if !defined(HAVE_LARGEFILE_SUPPORT)
10087 return Py_BuildValue("l", sbytes);
10088 #else
10089 return Py_BuildValue("L", sbytes);
10090 #endif
10091
10092 #else
10093 #ifdef __linux__
10094 if (offobj == Py_None) {
10095 do {
10096 Py_BEGIN_ALLOW_THREADS
10097 ret = sendfile(out_fd, in_fd, NULL, count);
10098 Py_END_ALLOW_THREADS
10099 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10100 if (ret < 0)
10101 return (!async_err) ? posix_error() : NULL;
10102 return Py_BuildValue("n", ret);
10103 }
10104 #endif
10105 off_t offset;
10106 if (!Py_off_t_converter(offobj, &offset))
10107 return NULL;
10108
10109 #if defined(__sun) && defined(__SVR4)
10110 // On Solaris, sendfile raises EINVAL rather than returning 0
10111 // when the offset is equal or bigger than the in_fd size.
10112 struct stat st;
10113
10114 do {
10115 Py_BEGIN_ALLOW_THREADS
10116 ret = fstat(in_fd, &st);
10117 Py_END_ALLOW_THREADS
10118 } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10119 if (ret < 0)
10120 return (!async_err) ? posix_error() : NULL;
10121
10122 if (offset >= st.st_size) {
10123 return Py_BuildValue("i", 0);
10124 }
10125
10126 // On illumos specifically sendfile() may perform a partial write but
10127 // return -1/an error (in one confirmed case the destination socket
10128 // had a 5 second timeout set and errno was EAGAIN) and it's on the client
10129 // code to check if the offset parameter was modified by sendfile().
10130 //
10131 // We need this variable to track said change.
10132 off_t original_offset = offset;
10133 #endif
10134
10135 do {
10136 Py_BEGIN_ALLOW_THREADS
10137 ret = sendfile(out_fd, in_fd, &offset, count);
10138 #if defined(__sun) && defined(__SVR4)
10139 // This handles illumos-specific sendfile() partial write behavior,
10140 // see a comment above for more details.
10141 if (ret < 0 && offset != original_offset) {
10142 ret = offset - original_offset;
10143 }
10144 #endif
10145 Py_END_ALLOW_THREADS
10146 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10147 if (ret < 0)
10148 return (!async_err) ? posix_error() : NULL;
10149 return Py_BuildValue("n", ret);
10150 #endif
10151 }
10152 #endif /* HAVE_SENDFILE */
10153
10154
10155 #if defined(__APPLE__)
10156 /*[clinic input]
10157 os._fcopyfile
10158
10159 in_fd: int
10160 out_fd: int
10161 flags: int
10162 /
10163
10164 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
10165 [clinic start generated code]*/
10166
10167 static PyObject *
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)10168 os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
10169 /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
10170 {
10171 int ret;
10172
10173 Py_BEGIN_ALLOW_THREADS
10174 ret = fcopyfile(in_fd, out_fd, NULL, flags);
10175 Py_END_ALLOW_THREADS
10176 if (ret < 0)
10177 return posix_error();
10178 Py_RETURN_NONE;
10179 }
10180 #endif
10181
10182
10183 /*[clinic input]
10184 os.fstat
10185
10186 fd : int
10187
10188 Perform a stat system call on the given file descriptor.
10189
10190 Like stat(), but for an open file descriptor.
10191 Equivalent to os.stat(fd).
10192 [clinic start generated code]*/
10193
10194 static PyObject *
os_fstat_impl(PyObject *module, int fd)10195 os_fstat_impl(PyObject *module, int fd)
10196 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
10197 {
10198 STRUCT_STAT st;
10199 int res;
10200 int async_err = 0;
10201
10202 do {
10203 Py_BEGIN_ALLOW_THREADS
10204 res = FSTAT(fd, &st);
10205 Py_END_ALLOW_THREADS
10206 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10207 if (res != 0) {
10208 #ifdef MS_WINDOWS
10209 return PyErr_SetFromWindowsErr(0);
10210 #else
10211 return (!async_err) ? posix_error() : NULL;
10212 #endif
10213 }
10214
10215 return _pystat_fromstructstat(module, &st);
10216 }
10217
10218
10219 /*[clinic input]
10220 os.isatty -> bool
10221 fd: int
10222 /
10223
10224 Return True if the fd is connected to a terminal.
10225
10226 Return True if the file descriptor is an open file descriptor
10227 connected to the slave end of a terminal.
10228 [clinic start generated code]*/
10229
10230 static int
os_isatty_impl(PyObject *module, int fd)10231 os_isatty_impl(PyObject *module, int fd)
10232 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
10233 {
10234 int return_value;
10235 Py_BEGIN_ALLOW_THREADS
10236 _Py_BEGIN_SUPPRESS_IPH
10237 return_value = isatty(fd);
10238 _Py_END_SUPPRESS_IPH
10239 Py_END_ALLOW_THREADS
10240 return return_value;
10241 }
10242
10243
10244 #ifdef HAVE_PIPE
10245 /*[clinic input]
10246 os.pipe
10247
10248 Create a pipe.
10249
10250 Returns a tuple of two file descriptors:
10251 (read_fd, write_fd)
10252 [clinic start generated code]*/
10253
10254 static PyObject *
os_pipe_impl(PyObject *module)10255 os_pipe_impl(PyObject *module)
10256 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
10257 {
10258 int fds[2];
10259 #ifdef MS_WINDOWS
10260 HANDLE read, write;
10261 SECURITY_ATTRIBUTES attr;
10262 BOOL ok;
10263 #else
10264 int res;
10265 #endif
10266
10267 #ifdef MS_WINDOWS
10268 attr.nLength = sizeof(attr);
10269 attr.lpSecurityDescriptor = NULL;
10270 attr.bInheritHandle = FALSE;
10271
10272 Py_BEGIN_ALLOW_THREADS
10273 ok = CreatePipe(&read, &write, &attr, 0);
10274 if (ok) {
10275 fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY);
10276 fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY);
10277 if (fds[0] == -1 || fds[1] == -1) {
10278 CloseHandle(read);
10279 CloseHandle(write);
10280 ok = 0;
10281 }
10282 }
10283 Py_END_ALLOW_THREADS
10284
10285 if (!ok)
10286 return PyErr_SetFromWindowsErr(0);
10287 #else
10288
10289 #ifdef HAVE_PIPE2
10290 Py_BEGIN_ALLOW_THREADS
10291 res = pipe2(fds, O_CLOEXEC);
10292 Py_END_ALLOW_THREADS
10293
10294 if (res != 0 && errno == ENOSYS)
10295 {
10296 #endif
10297 Py_BEGIN_ALLOW_THREADS
10298 res = pipe(fds);
10299 Py_END_ALLOW_THREADS
10300
10301 if (res == 0) {
10302 if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
10303 close(fds[0]);
10304 close(fds[1]);
10305 return NULL;
10306 }
10307 if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
10308 close(fds[0]);
10309 close(fds[1]);
10310 return NULL;
10311 }
10312 }
10313 #ifdef HAVE_PIPE2
10314 }
10315 #endif
10316
10317 if (res != 0)
10318 return PyErr_SetFromErrno(PyExc_OSError);
10319 #endif /* !MS_WINDOWS */
10320 return Py_BuildValue("(ii)", fds[0], fds[1]);
10321 }
10322 #endif /* HAVE_PIPE */
10323
10324
10325 #ifdef HAVE_PIPE2
10326 /*[clinic input]
10327 os.pipe2
10328
10329 flags: int
10330 /
10331
10332 Create a pipe with flags set atomically.
10333
10334 Returns a tuple of two file descriptors:
10335 (read_fd, write_fd)
10336
10337 flags can be constructed by ORing together one or more of these values:
10338 O_NONBLOCK, O_CLOEXEC.
10339 [clinic start generated code]*/
10340
10341 static PyObject *
os_pipe2_impl(PyObject *module, int flags)10342 os_pipe2_impl(PyObject *module, int flags)
10343 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
10344 {
10345 int fds[2];
10346 int res;
10347
10348 res = pipe2(fds, flags);
10349 if (res != 0)
10350 return posix_error();
10351 return Py_BuildValue("(ii)", fds[0], fds[1]);
10352 }
10353 #endif /* HAVE_PIPE2 */
10354
10355
10356 #ifdef HAVE_WRITEV
10357 /*[clinic input]
10358 os.writev -> Py_ssize_t
10359 fd: int
10360 buffers: object
10361 /
10362
10363 Iterate over buffers, and write the contents of each to a file descriptor.
10364
10365 Returns the total number of bytes written.
10366 buffers must be a sequence of bytes-like objects.
10367 [clinic start generated code]*/
10368
10369 static Py_ssize_t
os_writev_impl(PyObject *module, int fd, PyObject *buffers)10370 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
10371 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
10372 {
10373 Py_ssize_t cnt;
10374 Py_ssize_t result;
10375 int async_err = 0;
10376 struct iovec *iov;
10377 Py_buffer *buf;
10378
10379 if (!PySequence_Check(buffers)) {
10380 PyErr_SetString(PyExc_TypeError,
10381 "writev() arg 2 must be a sequence");
10382 return -1;
10383 }
10384 cnt = PySequence_Size(buffers);
10385 if (cnt < 0)
10386 return -1;
10387
10388 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10389 return -1;
10390 }
10391
10392 do {
10393 Py_BEGIN_ALLOW_THREADS
10394 result = writev(fd, iov, cnt);
10395 Py_END_ALLOW_THREADS
10396 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10397
10398 iov_cleanup(iov, buf, cnt);
10399 if (result < 0 && !async_err)
10400 posix_error();
10401
10402 return result;
10403 }
10404 #endif /* HAVE_WRITEV */
10405
10406
10407 #ifdef HAVE_PWRITE
10408 /*[clinic input]
10409 os.pwrite -> Py_ssize_t
10410
10411 fd: int
10412 buffer: Py_buffer
10413 offset: Py_off_t
10414 /
10415
10416 Write bytes to a file descriptor starting at a particular offset.
10417
10418 Write buffer to fd, starting at offset bytes from the beginning of
10419 the file. Returns the number of bytes writte. Does not change the
10420 current file offset.
10421 [clinic start generated code]*/
10422
10423 static Py_ssize_t
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)10424 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
10425 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
10426 {
10427 Py_ssize_t size;
10428 int async_err = 0;
10429
10430 do {
10431 Py_BEGIN_ALLOW_THREADS
10432 _Py_BEGIN_SUPPRESS_IPH
10433 size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
10434 _Py_END_SUPPRESS_IPH
10435 Py_END_ALLOW_THREADS
10436 } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10437
10438 if (size < 0 && !async_err)
10439 posix_error();
10440 return size;
10441 }
10442 #endif /* HAVE_PWRITE */
10443
10444 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
10445 /*[clinic input]
10446 os.pwritev -> Py_ssize_t
10447
10448 fd: int
10449 buffers: object
10450 offset: Py_off_t
10451 flags: int = 0
10452 /
10453
10454 Writes the contents of bytes-like objects to a file descriptor at a given offset.
10455
10456 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
10457 of bytes-like objects. Buffers are processed in array order. Entire contents of first
10458 buffer is written before proceeding to second, and so on. The operating system may
10459 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
10460 This function writes the contents of each object to the file descriptor and returns
10461 the total number of bytes written.
10462
10463 The flags argument contains a bitwise OR of zero or more of the following flags:
10464
10465 - RWF_DSYNC
10466 - RWF_SYNC
10467 - RWF_APPEND
10468
10469 Using non-zero flags requires Linux 4.7 or newer.
10470 [clinic start generated code]*/
10471
10472 static Py_ssize_t
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags)10473 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
10474 int flags)
10475 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
10476 {
10477 Py_ssize_t cnt;
10478 Py_ssize_t result;
10479 int async_err = 0;
10480 struct iovec *iov;
10481 Py_buffer *buf;
10482
10483 if (!PySequence_Check(buffers)) {
10484 PyErr_SetString(PyExc_TypeError,
10485 "pwritev() arg 2 must be a sequence");
10486 return -1;
10487 }
10488
10489 cnt = PySequence_Size(buffers);
10490 if (cnt < 0) {
10491 return -1;
10492 }
10493
10494 #ifndef HAVE_PWRITEV2
10495 if(flags != 0) {
10496 argument_unavailable_error("pwritev2", "flags");
10497 return -1;
10498 }
10499 #endif
10500
10501 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10502 return -1;
10503 }
10504 #ifdef HAVE_PWRITEV2
10505 do {
10506 Py_BEGIN_ALLOW_THREADS
10507 _Py_BEGIN_SUPPRESS_IPH
10508 result = pwritev2(fd, iov, cnt, offset, flags);
10509 _Py_END_SUPPRESS_IPH
10510 Py_END_ALLOW_THREADS
10511 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10512 #else
10513
10514 #if defined(__APPLE__) && defined(__clang__)
10515 /* This entire function will be removed from the module dict when the API
10516 * is not available.
10517 */
10518 #pragma clang diagnostic push
10519 #pragma clang diagnostic ignored "-Wunguarded-availability"
10520 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
10521 #endif
10522 do {
10523 Py_BEGIN_ALLOW_THREADS
10524 _Py_BEGIN_SUPPRESS_IPH
10525 result = pwritev(fd, iov, cnt, offset);
10526 _Py_END_SUPPRESS_IPH
10527 Py_END_ALLOW_THREADS
10528 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10529
10530 #if defined(__APPLE__) && defined(__clang__)
10531 #pragma clang diagnostic pop
10532 #endif
10533
10534 #endif
10535
10536 iov_cleanup(iov, buf, cnt);
10537 if (result < 0) {
10538 if (!async_err) {
10539 posix_error();
10540 }
10541 return -1;
10542 }
10543
10544 return result;
10545 }
10546 #endif /* HAVE_PWRITEV */
10547
10548 #ifdef HAVE_COPY_FILE_RANGE
10549 /*[clinic input]
10550
10551 os.copy_file_range
10552 src: int
10553 Source file descriptor.
10554 dst: int
10555 Destination file descriptor.
10556 count: Py_ssize_t
10557 Number of bytes to copy.
10558 offset_src: object = None
10559 Starting offset in src.
10560 offset_dst: object = None
10561 Starting offset in dst.
10562
10563 Copy count bytes from one file descriptor to another.
10564
10565 If offset_src is None, then src is read from the current position;
10566 respectively for offset_dst.
10567 [clinic start generated code]*/
10568
10569 static PyObject *
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count, PyObject *offset_src, PyObject *offset_dst)10570 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10571 PyObject *offset_src, PyObject *offset_dst)
10572 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
10573 {
10574 off_t offset_src_val, offset_dst_val;
10575 off_t *p_offset_src = NULL;
10576 off_t *p_offset_dst = NULL;
10577 Py_ssize_t ret;
10578 int async_err = 0;
10579 /* The flags argument is provided to allow
10580 * for future extensions and currently must be to 0. */
10581 int flags = 0;
10582
10583
10584 if (count < 0) {
10585 PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10586 return NULL;
10587 }
10588
10589 if (offset_src != Py_None) {
10590 if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10591 return NULL;
10592 }
10593 p_offset_src = &offset_src_val;
10594 }
10595
10596 if (offset_dst != Py_None) {
10597 if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10598 return NULL;
10599 }
10600 p_offset_dst = &offset_dst_val;
10601 }
10602
10603 do {
10604 Py_BEGIN_ALLOW_THREADS
10605 ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
10606 Py_END_ALLOW_THREADS
10607 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10608
10609 if (ret < 0) {
10610 return (!async_err) ? posix_error() : NULL;
10611 }
10612
10613 return PyLong_FromSsize_t(ret);
10614 }
10615 #endif /* HAVE_COPY_FILE_RANGE*/
10616
10617 #if (defined(HAVE_SPLICE) && !defined(_AIX))
10618 /*[clinic input]
10619
10620 os.splice
10621 src: int
10622 Source file descriptor.
10623 dst: int
10624 Destination file descriptor.
10625 count: Py_ssize_t
10626 Number of bytes to copy.
10627 offset_src: object = None
10628 Starting offset in src.
10629 offset_dst: object = None
10630 Starting offset in dst.
10631 flags: unsigned_int = 0
10632 Flags to modify the semantics of the call.
10633
10634 Transfer count bytes from one pipe to a descriptor or vice versa.
10635
10636 If offset_src is None, then src is read from the current position;
10637 respectively for offset_dst. The offset associated to the file
10638 descriptor that refers to a pipe must be None.
10639 [clinic start generated code]*/
10640
10641 static PyObject *
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count, PyObject *offset_src, PyObject *offset_dst, unsigned int flags)10642 os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10643 PyObject *offset_src, PyObject *offset_dst,
10644 unsigned int flags)
10645 /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
10646 {
10647 off_t offset_src_val, offset_dst_val;
10648 off_t *p_offset_src = NULL;
10649 off_t *p_offset_dst = NULL;
10650 Py_ssize_t ret;
10651 int async_err = 0;
10652
10653 if (count < 0) {
10654 PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10655 return NULL;
10656 }
10657
10658 if (offset_src != Py_None) {
10659 if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10660 return NULL;
10661 }
10662 p_offset_src = &offset_src_val;
10663 }
10664
10665 if (offset_dst != Py_None) {
10666 if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10667 return NULL;
10668 }
10669 p_offset_dst = &offset_dst_val;
10670 }
10671
10672 do {
10673 Py_BEGIN_ALLOW_THREADS
10674 ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
10675 Py_END_ALLOW_THREADS
10676 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10677
10678 if (ret < 0) {
10679 return (!async_err) ? posix_error() : NULL;
10680 }
10681
10682 return PyLong_FromSsize_t(ret);
10683 }
10684 #endif /* HAVE_SPLICE*/
10685
10686 #ifdef HAVE_MKFIFO
10687 /*[clinic input]
10688 os.mkfifo
10689
10690 path: path_t
10691 mode: int=0o666
10692 *
10693 dir_fd: dir_fd(requires='mkfifoat')=None
10694
10695 Create a "fifo" (a POSIX named pipe).
10696
10697 If dir_fd is not None, it should be a file descriptor open to a directory,
10698 and path should be relative; path will then be relative to that directory.
10699 dir_fd may not be implemented on your platform.
10700 If it is unavailable, using it will raise a NotImplementedError.
10701 [clinic start generated code]*/
10702
10703 static PyObject *
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)10704 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
10705 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
10706 {
10707 int result;
10708 int async_err = 0;
10709 #ifdef HAVE_MKFIFOAT
10710 int mkfifoat_unavailable = 0;
10711 #endif
10712
10713 do {
10714 Py_BEGIN_ALLOW_THREADS
10715 #ifdef HAVE_MKFIFOAT
10716 if (dir_fd != DEFAULT_DIR_FD) {
10717 if (HAVE_MKFIFOAT_RUNTIME) {
10718 result = mkfifoat(dir_fd, path->narrow, mode);
10719
10720 } else {
10721 mkfifoat_unavailable = 1;
10722 result = 0;
10723 }
10724 } else
10725 #endif
10726 result = mkfifo(path->narrow, mode);
10727 Py_END_ALLOW_THREADS
10728 } while (result != 0 && errno == EINTR &&
10729 !(async_err = PyErr_CheckSignals()));
10730
10731 #ifdef HAVE_MKFIFOAT
10732 if (mkfifoat_unavailable) {
10733 argument_unavailable_error(NULL, "dir_fd");
10734 return NULL;
10735 }
10736 #endif
10737
10738 if (result != 0)
10739 return (!async_err) ? posix_error() : NULL;
10740
10741 Py_RETURN_NONE;
10742 }
10743 #endif /* HAVE_MKFIFO */
10744
10745
10746 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
10747 /*[clinic input]
10748 os.mknod
10749
10750 path: path_t
10751 mode: int=0o600
10752 device: dev_t=0
10753 *
10754 dir_fd: dir_fd(requires='mknodat')=None
10755
10756 Create a node in the file system.
10757
10758 Create a node in the file system (file, device special file or named pipe)
10759 at path. mode specifies both the permissions to use and the
10760 type of node to be created, being combined (bitwise OR) with one of
10761 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,
10762 device defines the newly created device special file (probably using
10763 os.makedev()). Otherwise device is ignored.
10764
10765 If dir_fd is not None, it should be a file descriptor open to a directory,
10766 and path should be relative; path will then be relative to that directory.
10767 dir_fd may not be implemented on your platform.
10768 If it is unavailable, using it will raise a NotImplementedError.
10769 [clinic start generated code]*/
10770
10771 static PyObject *
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device, int dir_fd)10772 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
10773 int dir_fd)
10774 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
10775 {
10776 int result;
10777 int async_err = 0;
10778 #ifdef HAVE_MKNODAT
10779 int mknodat_unavailable = 0;
10780 #endif
10781
10782 do {
10783 Py_BEGIN_ALLOW_THREADS
10784 #ifdef HAVE_MKNODAT
10785 if (dir_fd != DEFAULT_DIR_FD) {
10786 if (HAVE_MKNODAT_RUNTIME) {
10787 result = mknodat(dir_fd, path->narrow, mode, device);
10788
10789 } else {
10790 mknodat_unavailable = 1;
10791 result = 0;
10792 }
10793 } else
10794 #endif
10795 result = mknod(path->narrow, mode, device);
10796 Py_END_ALLOW_THREADS
10797 } while (result != 0 && errno == EINTR &&
10798 !(async_err = PyErr_CheckSignals()));
10799 #ifdef HAVE_MKNODAT
10800 if (mknodat_unavailable) {
10801 argument_unavailable_error(NULL, "dir_fd");
10802 return NULL;
10803 }
10804 #endif
10805 if (result != 0)
10806 return (!async_err) ? posix_error() : NULL;
10807
10808 Py_RETURN_NONE;
10809 }
10810 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
10811
10812
10813 #ifdef HAVE_DEVICE_MACROS
10814 /*[clinic input]
10815 os.major -> unsigned_int
10816
10817 device: dev_t
10818 /
10819
10820 Extracts a device major number from a raw device number.
10821 [clinic start generated code]*/
10822
10823 static unsigned int
os_major_impl(PyObject *module, dev_t device)10824 os_major_impl(PyObject *module, dev_t device)
10825 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
10826 {
10827 return major(device);
10828 }
10829
10830
10831 /*[clinic input]
10832 os.minor -> unsigned_int
10833
10834 device: dev_t
10835 /
10836
10837 Extracts a device minor number from a raw device number.
10838 [clinic start generated code]*/
10839
10840 static unsigned int
os_minor_impl(PyObject *module, dev_t device)10841 os_minor_impl(PyObject *module, dev_t device)
10842 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10843 {
10844 return minor(device);
10845 }
10846
10847
10848 /*[clinic input]
10849 os.makedev -> dev_t
10850
10851 major: int
10852 minor: int
10853 /
10854
10855 Composes a raw device number from the major and minor device numbers.
10856 [clinic start generated code]*/
10857
10858 static dev_t
os_makedev_impl(PyObject *module, int major, int minor)10859 os_makedev_impl(PyObject *module, int major, int minor)
10860 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10861 {
10862 return makedev(major, minor);
10863 }
10864 #endif /* HAVE_DEVICE_MACROS */
10865
10866
10867 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10868 /*[clinic input]
10869 os.ftruncate
10870
10871 fd: int
10872 length: Py_off_t
10873 /
10874
10875 Truncate a file, specified by file descriptor, to a specific length.
10876 [clinic start generated code]*/
10877
10878 static PyObject *
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)10879 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10880 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10881 {
10882 int result;
10883 int async_err = 0;
10884
10885 if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10886 return NULL;
10887 }
10888
10889 do {
10890 Py_BEGIN_ALLOW_THREADS
10891 _Py_BEGIN_SUPPRESS_IPH
10892 #ifdef MS_WINDOWS
10893 result = _chsize_s(fd, length);
10894 #else
10895 result = ftruncate(fd, length);
10896 #endif
10897 _Py_END_SUPPRESS_IPH
10898 Py_END_ALLOW_THREADS
10899 } while (result != 0 && errno == EINTR &&
10900 !(async_err = PyErr_CheckSignals()));
10901 if (result != 0)
10902 return (!async_err) ? posix_error() : NULL;
10903 Py_RETURN_NONE;
10904 }
10905 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10906
10907
10908 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10909 /*[clinic input]
10910 os.truncate
10911 path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10912 length: Py_off_t
10913
10914 Truncate a file, specified by path, to a specific length.
10915
10916 On some platforms, path may also be specified as an open file descriptor.
10917 If this functionality is unavailable, using it raises an exception.
10918 [clinic start generated code]*/
10919
10920 static PyObject *
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)10921 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10922 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10923 {
10924 int result;
10925 #ifdef MS_WINDOWS
10926 int fd;
10927 #endif
10928
10929 if (path->fd != -1)
10930 return os_ftruncate_impl(module, path->fd, length);
10931
10932 if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10933 return NULL;
10934 }
10935
10936 Py_BEGIN_ALLOW_THREADS
10937 _Py_BEGIN_SUPPRESS_IPH
10938 #ifdef MS_WINDOWS
10939 fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10940 if (fd < 0)
10941 result = -1;
10942 else {
10943 result = _chsize_s(fd, length);
10944 close(fd);
10945 if (result < 0)
10946 errno = result;
10947 }
10948 #else
10949 result = truncate(path->narrow, length);
10950 #endif
10951 _Py_END_SUPPRESS_IPH
10952 Py_END_ALLOW_THREADS
10953 if (result < 0)
10954 return posix_path_error(path);
10955
10956 Py_RETURN_NONE;
10957 }
10958 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10959
10960
10961 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10962 and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10963 defined, which is the case in Python on AIX. AIX bug report:
10964 http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10965 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10966 # define POSIX_FADVISE_AIX_BUG
10967 #endif
10968
10969
10970 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10971 /*[clinic input]
10972 os.posix_fallocate
10973
10974 fd: int
10975 offset: Py_off_t
10976 length: Py_off_t
10977 /
10978
10979 Ensure a file has allocated at least a particular number of bytes on disk.
10980
10981 Ensure that the file specified by fd encompasses a range of bytes
10982 starting at offset bytes from the beginning and continuing for length bytes.
10983 [clinic start generated code]*/
10984
10985 static PyObject *
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset, Py_off_t length)10986 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10987 Py_off_t length)
10988 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10989 {
10990 int result;
10991 int async_err = 0;
10992
10993 do {
10994 Py_BEGIN_ALLOW_THREADS
10995 result = posix_fallocate(fd, offset, length);
10996 Py_END_ALLOW_THREADS
10997 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10998
10999 if (result == 0)
11000 Py_RETURN_NONE;
11001
11002 if (async_err)
11003 return NULL;
11004
11005 errno = result;
11006 return posix_error();
11007 }
11008 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
11009
11010
11011 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
11012 /*[clinic input]
11013 os.posix_fadvise
11014
11015 fd: int
11016 offset: Py_off_t
11017 length: Py_off_t
11018 advice: int
11019 /
11020
11021 Announce an intention to access data in a specific pattern.
11022
11023 Announce an intention to access data in a specific pattern, thus allowing
11024 the kernel to make optimizations.
11025 The advice applies to the region of the file specified by fd starting at
11026 offset and continuing for length bytes.
11027 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
11028 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
11029 POSIX_FADV_DONTNEED.
11030 [clinic start generated code]*/
11031
11032 static PyObject *
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, Py_off_t length, int advice)11033 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
11034 Py_off_t length, int advice)
11035 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
11036 {
11037 int result;
11038 int async_err = 0;
11039
11040 do {
11041 Py_BEGIN_ALLOW_THREADS
11042 result = posix_fadvise(fd, offset, length, advice);
11043 Py_END_ALLOW_THREADS
11044 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
11045
11046 if (result == 0)
11047 Py_RETURN_NONE;
11048
11049 if (async_err)
11050 return NULL;
11051
11052 errno = result;
11053 return posix_error();
11054 }
11055 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
11056
11057
11058 #ifdef MS_WINDOWS
11059 static PyObject*
win32_putenv(PyObject *name, PyObject *value)11060 win32_putenv(PyObject *name, PyObject *value)
11061 {
11062 /* Search from index 1 because on Windows starting '=' is allowed for
11063 defining hidden environment variables. */
11064 if (PyUnicode_GET_LENGTH(name) == 0 ||
11065 PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
11066 {
11067 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11068 return NULL;
11069 }
11070 PyObject *unicode;
11071 if (value != NULL) {
11072 unicode = PyUnicode_FromFormat("%U=%U", name, value);
11073 }
11074 else {
11075 unicode = PyUnicode_FromFormat("%U=", name);
11076 }
11077 if (unicode == NULL) {
11078 return NULL;
11079 }
11080
11081 Py_ssize_t size;
11082 /* PyUnicode_AsWideCharString() rejects embedded null characters */
11083 wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
11084 Py_DECREF(unicode);
11085
11086 if (env == NULL) {
11087 return NULL;
11088 }
11089 if (size > _MAX_ENV) {
11090 PyErr_Format(PyExc_ValueError,
11091 "the environment variable is longer than %u characters",
11092 _MAX_ENV);
11093 PyMem_Free(env);
11094 return NULL;
11095 }
11096
11097 /* _wputenv() and SetEnvironmentVariableW() update the environment in the
11098 Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
11099 and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
11100
11101 Prefer _wputenv() to be compatible with C libraries using CRT
11102 variables and CRT functions using these variables (ex: getenv()). */
11103 int err = _wputenv(env);
11104 PyMem_Free(env);
11105
11106 if (err) {
11107 posix_error();
11108 return NULL;
11109 }
11110
11111 Py_RETURN_NONE;
11112 }
11113 #endif
11114
11115
11116 #ifdef MS_WINDOWS
11117 /*[clinic input]
11118 os.putenv
11119
11120 name: unicode
11121 value: unicode
11122 /
11123
11124 Change or add an environment variable.
11125 [clinic start generated code]*/
11126
11127 static PyObject *
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)11128 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11129 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
11130 {
11131 if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11132 return NULL;
11133 }
11134 return win32_putenv(name, value);
11135 }
11136 #else
11137 /*[clinic input]
11138 os.putenv
11139
11140 name: FSConverter
11141 value: FSConverter
11142 /
11143
11144 Change or add an environment variable.
11145 [clinic start generated code]*/
11146
11147 static PyObject *
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)11148 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11149 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
11150 {
11151 const char *name_string = PyBytes_AS_STRING(name);
11152 const char *value_string = PyBytes_AS_STRING(value);
11153
11154 if (strchr(name_string, '=') != NULL) {
11155 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11156 return NULL;
11157 }
11158
11159 if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11160 return NULL;
11161 }
11162
11163 if (setenv(name_string, value_string, 1)) {
11164 return posix_error();
11165 }
11166 Py_RETURN_NONE;
11167 }
11168 #endif /* !defined(MS_WINDOWS) */
11169
11170
11171 #ifdef MS_WINDOWS
11172 /*[clinic input]
11173 os.unsetenv
11174 name: unicode
11175 /
11176
11177 Delete an environment variable.
11178 [clinic start generated code]*/
11179
11180 static PyObject *
os_unsetenv_impl(PyObject *module, PyObject *name)11181 os_unsetenv_impl(PyObject *module, PyObject *name)
11182 /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
11183 {
11184 if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11185 return NULL;
11186 }
11187 return win32_putenv(name, NULL);
11188 }
11189 #else
11190 /*[clinic input]
11191 os.unsetenv
11192 name: FSConverter
11193 /
11194
11195 Delete an environment variable.
11196 [clinic start generated code]*/
11197
11198 static PyObject *
os_unsetenv_impl(PyObject *module, PyObject *name)11199 os_unsetenv_impl(PyObject *module, PyObject *name)
11200 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
11201 {
11202 if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11203 return NULL;
11204 }
11205 #ifdef HAVE_BROKEN_UNSETENV
11206 unsetenv(PyBytes_AS_STRING(name));
11207 #else
11208 int err = unsetenv(PyBytes_AS_STRING(name));
11209 if (err) {
11210 return posix_error();
11211 }
11212 #endif
11213
11214 Py_RETURN_NONE;
11215 }
11216 #endif /* !MS_WINDOWS */
11217
11218
11219 /*[clinic input]
11220 os.strerror
11221
11222 code: int
11223 /
11224
11225 Translate an error code to a message string.
11226 [clinic start generated code]*/
11227
11228 static PyObject *
os_strerror_impl(PyObject *module, int code)11229 os_strerror_impl(PyObject *module, int code)
11230 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
11231 {
11232 char *message = strerror(code);
11233 if (message == NULL) {
11234 PyErr_SetString(PyExc_ValueError,
11235 "strerror() argument out of range");
11236 return NULL;
11237 }
11238 return PyUnicode_DecodeLocale(message, "surrogateescape");
11239 }
11240
11241
11242 #ifdef HAVE_SYS_WAIT_H
11243 #ifdef WCOREDUMP
11244 /*[clinic input]
11245 os.WCOREDUMP -> bool
11246
11247 status: int
11248 /
11249
11250 Return True if the process returning status was dumped to a core file.
11251 [clinic start generated code]*/
11252
11253 static int
os_WCOREDUMP_impl(PyObject *module, int status)11254 os_WCOREDUMP_impl(PyObject *module, int status)
11255 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
11256 {
11257 WAIT_TYPE wait_status;
11258 WAIT_STATUS_INT(wait_status) = status;
11259 return WCOREDUMP(wait_status);
11260 }
11261 #endif /* WCOREDUMP */
11262
11263
11264 #ifdef WIFCONTINUED
11265 /*[clinic input]
11266 os.WIFCONTINUED -> bool
11267
11268 status: int
11269
11270 Return True if a particular process was continued from a job control stop.
11271
11272 Return True if the process returning status was continued from a
11273 job control stop.
11274 [clinic start generated code]*/
11275
11276 static int
os_WIFCONTINUED_impl(PyObject *module, int status)11277 os_WIFCONTINUED_impl(PyObject *module, int status)
11278 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
11279 {
11280 WAIT_TYPE wait_status;
11281 WAIT_STATUS_INT(wait_status) = status;
11282 return WIFCONTINUED(wait_status);
11283 }
11284 #endif /* WIFCONTINUED */
11285
11286
11287 #ifdef WIFSTOPPED
11288 /*[clinic input]
11289 os.WIFSTOPPED -> bool
11290
11291 status: int
11292
11293 Return True if the process returning status was stopped.
11294 [clinic start generated code]*/
11295
11296 static int
os_WIFSTOPPED_impl(PyObject *module, int status)11297 os_WIFSTOPPED_impl(PyObject *module, int status)
11298 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
11299 {
11300 WAIT_TYPE wait_status;
11301 WAIT_STATUS_INT(wait_status) = status;
11302 return WIFSTOPPED(wait_status);
11303 }
11304 #endif /* WIFSTOPPED */
11305
11306
11307 #ifdef WIFSIGNALED
11308 /*[clinic input]
11309 os.WIFSIGNALED -> bool
11310
11311 status: int
11312
11313 Return True if the process returning status was terminated by a signal.
11314 [clinic start generated code]*/
11315
11316 static int
os_WIFSIGNALED_impl(PyObject *module, int status)11317 os_WIFSIGNALED_impl(PyObject *module, int status)
11318 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
11319 {
11320 WAIT_TYPE wait_status;
11321 WAIT_STATUS_INT(wait_status) = status;
11322 return WIFSIGNALED(wait_status);
11323 }
11324 #endif /* WIFSIGNALED */
11325
11326
11327 #ifdef WIFEXITED
11328 /*[clinic input]
11329 os.WIFEXITED -> bool
11330
11331 status: int
11332
11333 Return True if the process returning status exited via the exit() system call.
11334 [clinic start generated code]*/
11335
11336 static int
os_WIFEXITED_impl(PyObject *module, int status)11337 os_WIFEXITED_impl(PyObject *module, int status)
11338 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
11339 {
11340 WAIT_TYPE wait_status;
11341 WAIT_STATUS_INT(wait_status) = status;
11342 return WIFEXITED(wait_status);
11343 }
11344 #endif /* WIFEXITED */
11345
11346
11347 #ifdef WEXITSTATUS
11348 /*[clinic input]
11349 os.WEXITSTATUS -> int
11350
11351 status: int
11352
11353 Return the process return code from status.
11354 [clinic start generated code]*/
11355
11356 static int
os_WEXITSTATUS_impl(PyObject *module, int status)11357 os_WEXITSTATUS_impl(PyObject *module, int status)
11358 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
11359 {
11360 WAIT_TYPE wait_status;
11361 WAIT_STATUS_INT(wait_status) = status;
11362 return WEXITSTATUS(wait_status);
11363 }
11364 #endif /* WEXITSTATUS */
11365
11366
11367 #ifdef WTERMSIG
11368 /*[clinic input]
11369 os.WTERMSIG -> int
11370
11371 status: int
11372
11373 Return the signal that terminated the process that provided the status value.
11374 [clinic start generated code]*/
11375
11376 static int
os_WTERMSIG_impl(PyObject *module, int status)11377 os_WTERMSIG_impl(PyObject *module, int status)
11378 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
11379 {
11380 WAIT_TYPE wait_status;
11381 WAIT_STATUS_INT(wait_status) = status;
11382 return WTERMSIG(wait_status);
11383 }
11384 #endif /* WTERMSIG */
11385
11386
11387 #ifdef WSTOPSIG
11388 /*[clinic input]
11389 os.WSTOPSIG -> int
11390
11391 status: int
11392
11393 Return the signal that stopped the process that provided the status value.
11394 [clinic start generated code]*/
11395
11396 static int
os_WSTOPSIG_impl(PyObject *module, int status)11397 os_WSTOPSIG_impl(PyObject *module, int status)
11398 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
11399 {
11400 WAIT_TYPE wait_status;
11401 WAIT_STATUS_INT(wait_status) = status;
11402 return WSTOPSIG(wait_status);
11403 }
11404 #endif /* WSTOPSIG */
11405 #endif /* HAVE_SYS_WAIT_H */
11406
11407
11408 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
11409 #ifdef _SCO_DS
11410 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
11411 needed definitions in sys/statvfs.h */
11412 #define _SVID3
11413 #endif
11414 #include <sys/statvfs.h>
11415
11416 static PyObject*
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st)11417 _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
11418 PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
11419 PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
11420 if (v == NULL)
11421 return NULL;
11422
11423 #if !defined(HAVE_LARGEFILE_SUPPORT)
11424 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11425 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11426 PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
11427 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
11428 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
11429 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
11430 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
11431 PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
11432 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11433 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11434 #else
11435 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11436 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11437 PyStructSequence_SET_ITEM(v, 2,
11438 PyLong_FromLongLong((long long) st.f_blocks));
11439 PyStructSequence_SET_ITEM(v, 3,
11440 PyLong_FromLongLong((long long) st.f_bfree));
11441 PyStructSequence_SET_ITEM(v, 4,
11442 PyLong_FromLongLong((long long) st.f_bavail));
11443 PyStructSequence_SET_ITEM(v, 5,
11444 PyLong_FromLongLong((long long) st.f_files));
11445 PyStructSequence_SET_ITEM(v, 6,
11446 PyLong_FromLongLong((long long) st.f_ffree));
11447 PyStructSequence_SET_ITEM(v, 7,
11448 PyLong_FromLongLong((long long) st.f_favail));
11449 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11450 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11451 #endif
11452 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
11453 * (issue #32390). */
11454 #if defined(_AIX) && defined(_ALL_SOURCE)
11455 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
11456 #else
11457 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
11458 #endif
11459 if (PyErr_Occurred()) {
11460 Py_DECREF(v);
11461 return NULL;
11462 }
11463
11464 return v;
11465 }
11466
11467
11468 /*[clinic input]
11469 os.fstatvfs
11470 fd: int
11471 /
11472
11473 Perform an fstatvfs system call on the given fd.
11474
11475 Equivalent to statvfs(fd).
11476 [clinic start generated code]*/
11477
11478 static PyObject *
os_fstatvfs_impl(PyObject *module, int fd)11479 os_fstatvfs_impl(PyObject *module, int fd)
11480 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
11481 {
11482 int result;
11483 int async_err = 0;
11484 struct statvfs st;
11485
11486 do {
11487 Py_BEGIN_ALLOW_THREADS
11488 result = fstatvfs(fd, &st);
11489 Py_END_ALLOW_THREADS
11490 } while (result != 0 && errno == EINTR &&
11491 !(async_err = PyErr_CheckSignals()));
11492 if (result != 0)
11493 return (!async_err) ? posix_error() : NULL;
11494
11495 return _pystatvfs_fromstructstatvfs(module, st);
11496 }
11497 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
11498
11499
11500 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
11501 #include <sys/statvfs.h>
11502 /*[clinic input]
11503 os.statvfs
11504
11505 path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
11506
11507 Perform a statvfs system call on the given path.
11508
11509 path may always be specified as a string.
11510 On some platforms, path may also be specified as an open file descriptor.
11511 If this functionality is unavailable, using it raises an exception.
11512 [clinic start generated code]*/
11513
11514 static PyObject *
os_statvfs_impl(PyObject *module, path_t *path)11515 os_statvfs_impl(PyObject *module, path_t *path)
11516 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
11517 {
11518 int result;
11519 struct statvfs st;
11520
11521 Py_BEGIN_ALLOW_THREADS
11522 #ifdef HAVE_FSTATVFS
11523 if (path->fd != -1) {
11524 result = fstatvfs(path->fd, &st);
11525 }
11526 else
11527 #endif
11528 result = statvfs(path->narrow, &st);
11529 Py_END_ALLOW_THREADS
11530
11531 if (result) {
11532 return path_error(path);
11533 }
11534
11535 return _pystatvfs_fromstructstatvfs(module, st);
11536 }
11537 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
11538
11539
11540 #ifdef MS_WINDOWS
11541 /*[clinic input]
11542 os._getdiskusage
11543
11544 path: path_t
11545
11546 Return disk usage statistics about the given path as a (total, free) tuple.
11547 [clinic start generated code]*/
11548
11549 static PyObject *
os__getdiskusage_impl(PyObject *module, path_t *path)11550 os__getdiskusage_impl(PyObject *module, path_t *path)
11551 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
11552 {
11553 BOOL retval;
11554 ULARGE_INTEGER _, total, free;
11555 DWORD err = 0;
11556
11557 Py_BEGIN_ALLOW_THREADS
11558 retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
11559 Py_END_ALLOW_THREADS
11560 if (retval == 0) {
11561 if (GetLastError() == ERROR_DIRECTORY) {
11562 wchar_t *dir_path = NULL;
11563
11564 dir_path = PyMem_New(wchar_t, path->length + 1);
11565 if (dir_path == NULL) {
11566 return PyErr_NoMemory();
11567 }
11568
11569 wcscpy_s(dir_path, path->length + 1, path->wide);
11570
11571 if (_dirnameW(dir_path) != -1) {
11572 Py_BEGIN_ALLOW_THREADS
11573 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
11574 Py_END_ALLOW_THREADS
11575 }
11576 /* Record the last error in case it's modified by PyMem_Free. */
11577 err = GetLastError();
11578 PyMem_Free(dir_path);
11579 if (retval) {
11580 goto success;
11581 }
11582 }
11583 return PyErr_SetFromWindowsErr(err);
11584 }
11585
11586 success:
11587 return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
11588 }
11589 #endif /* MS_WINDOWS */
11590
11591
11592 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
11593 * It maps strings representing configuration variable names to
11594 * integer values, allowing those functions to be called with the
11595 * magic names instead of polluting the module's namespace with tons of
11596 * rarely-used constants. There are three separate tables that use
11597 * these definitions.
11598 *
11599 * This code is always included, even if none of the interfaces that
11600 * need it are included. The #if hackery needed to avoid it would be
11601 * sufficiently pervasive that it's not worth the loss of readability.
11602 */
11603 struct constdef {
11604 const char *name;
11605 int value;
11606 };
11607
11608 static int
conv_confname(PyObject *arg, int *valuep, struct constdef *table, size_t tablesize)11609 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
11610 size_t tablesize)
11611 {
11612 if (PyLong_Check(arg)) {
11613 int value = _PyLong_AsInt(arg);
11614 if (value == -1 && PyErr_Occurred())
11615 return 0;
11616 *valuep = value;
11617 return 1;
11618 }
11619 else {
11620 /* look up the value in the table using a binary search */
11621 size_t lo = 0;
11622 size_t mid;
11623 size_t hi = tablesize;
11624 int cmp;
11625 const char *confname;
11626 if (!PyUnicode_Check(arg)) {
11627 PyErr_SetString(PyExc_TypeError,
11628 "configuration names must be strings or integers");
11629 return 0;
11630 }
11631 confname = PyUnicode_AsUTF8(arg);
11632 if (confname == NULL)
11633 return 0;
11634 while (lo < hi) {
11635 mid = (lo + hi) / 2;
11636 cmp = strcmp(confname, table[mid].name);
11637 if (cmp < 0)
11638 hi = mid;
11639 else if (cmp > 0)
11640 lo = mid + 1;
11641 else {
11642 *valuep = table[mid].value;
11643 return 1;
11644 }
11645 }
11646 PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
11647 return 0;
11648 }
11649 }
11650
11651
11652 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11653 static struct constdef posix_constants_pathconf[] = {
11654 #ifdef _PC_ABI_AIO_XFER_MAX
11655 {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
11656 #endif
11657 #ifdef _PC_ABI_ASYNC_IO
11658 {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
11659 #endif
11660 #ifdef _PC_ASYNC_IO
11661 {"PC_ASYNC_IO", _PC_ASYNC_IO},
11662 #endif
11663 #ifdef _PC_CHOWN_RESTRICTED
11664 {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
11665 #endif
11666 #ifdef _PC_FILESIZEBITS
11667 {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
11668 #endif
11669 #ifdef _PC_LAST
11670 {"PC_LAST", _PC_LAST},
11671 #endif
11672 #ifdef _PC_LINK_MAX
11673 {"PC_LINK_MAX", _PC_LINK_MAX},
11674 #endif
11675 #ifdef _PC_MAX_CANON
11676 {"PC_MAX_CANON", _PC_MAX_CANON},
11677 #endif
11678 #ifdef _PC_MAX_INPUT
11679 {"PC_MAX_INPUT", _PC_MAX_INPUT},
11680 #endif
11681 #ifdef _PC_NAME_MAX
11682 {"PC_NAME_MAX", _PC_NAME_MAX},
11683 #endif
11684 #ifdef _PC_NO_TRUNC
11685 {"PC_NO_TRUNC", _PC_NO_TRUNC},
11686 #endif
11687 #ifdef _PC_PATH_MAX
11688 {"PC_PATH_MAX", _PC_PATH_MAX},
11689 #endif
11690 #ifdef _PC_PIPE_BUF
11691 {"PC_PIPE_BUF", _PC_PIPE_BUF},
11692 #endif
11693 #ifdef _PC_PRIO_IO
11694 {"PC_PRIO_IO", _PC_PRIO_IO},
11695 #endif
11696 #ifdef _PC_SOCK_MAXBUF
11697 {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
11698 #endif
11699 #ifdef _PC_SYNC_IO
11700 {"PC_SYNC_IO", _PC_SYNC_IO},
11701 #endif
11702 #ifdef _PC_VDISABLE
11703 {"PC_VDISABLE", _PC_VDISABLE},
11704 #endif
11705 #ifdef _PC_ACL_ENABLED
11706 {"PC_ACL_ENABLED", _PC_ACL_ENABLED},
11707 #endif
11708 #ifdef _PC_MIN_HOLE_SIZE
11709 {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE},
11710 #endif
11711 #ifdef _PC_ALLOC_SIZE_MIN
11712 {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN},
11713 #endif
11714 #ifdef _PC_REC_INCR_XFER_SIZE
11715 {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE},
11716 #endif
11717 #ifdef _PC_REC_MAX_XFER_SIZE
11718 {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE},
11719 #endif
11720 #ifdef _PC_REC_MIN_XFER_SIZE
11721 {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE},
11722 #endif
11723 #ifdef _PC_REC_XFER_ALIGN
11724 {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN},
11725 #endif
11726 #ifdef _PC_SYMLINK_MAX
11727 {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX},
11728 #endif
11729 #ifdef _PC_XATTR_ENABLED
11730 {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED},
11731 #endif
11732 #ifdef _PC_XATTR_EXISTS
11733 {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
11734 #endif
11735 #ifdef _PC_TIMESTAMP_RESOLUTION
11736 {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
11737 #endif
11738 };
11739
11740 static int
conv_path_confname(PyObject *arg, int *valuep)11741 conv_path_confname(PyObject *arg, int *valuep)
11742 {
11743 return conv_confname(arg, valuep, posix_constants_pathconf,
11744 sizeof(posix_constants_pathconf)
11745 / sizeof(struct constdef));
11746 }
11747 #endif
11748
11749
11750 #ifdef HAVE_FPATHCONF
11751 /*[clinic input]
11752 os.fpathconf -> long
11753
11754 fd: fildes
11755 name: path_confname
11756 /
11757
11758 Return the configuration limit name for the file descriptor fd.
11759
11760 If there is no limit, return -1.
11761 [clinic start generated code]*/
11762
11763 static long
os_fpathconf_impl(PyObject *module, int fd, int name)11764 os_fpathconf_impl(PyObject *module, int fd, int name)
11765 /*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
11766 {
11767 long limit;
11768
11769 errno = 0;
11770 limit = fpathconf(fd, name);
11771 if (limit == -1 && errno != 0)
11772 posix_error();
11773
11774 return limit;
11775 }
11776 #endif /* HAVE_FPATHCONF */
11777
11778
11779 #ifdef HAVE_PATHCONF
11780 /*[clinic input]
11781 os.pathconf -> long
11782 path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
11783 name: path_confname
11784
11785 Return the configuration limit name for the file or directory path.
11786
11787 If there is no limit, return -1.
11788 On some platforms, path may also be specified as an open file descriptor.
11789 If this functionality is unavailable, using it raises an exception.
11790 [clinic start generated code]*/
11791
11792 static long
os_pathconf_impl(PyObject *module, path_t *path, int name)11793 os_pathconf_impl(PyObject *module, path_t *path, int name)
11794 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
11795 {
11796 long limit;
11797
11798 errno = 0;
11799 #ifdef HAVE_FPATHCONF
11800 if (path->fd != -1)
11801 limit = fpathconf(path->fd, name);
11802 else
11803 #endif
11804 limit = pathconf(path->narrow, name);
11805 if (limit == -1 && errno != 0) {
11806 if (errno == EINVAL)
11807 /* could be a path or name problem */
11808 posix_error();
11809 else
11810 path_error(path);
11811 }
11812
11813 return limit;
11814 }
11815 #endif /* HAVE_PATHCONF */
11816
11817 #ifdef HAVE_CONFSTR
11818 static struct constdef posix_constants_confstr[] = {
11819 #ifdef _CS_ARCHITECTURE
11820 {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
11821 #endif
11822 #ifdef _CS_GNU_LIBC_VERSION
11823 {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION},
11824 #endif
11825 #ifdef _CS_GNU_LIBPTHREAD_VERSION
11826 {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION},
11827 #endif
11828 #ifdef _CS_HOSTNAME
11829 {"CS_HOSTNAME", _CS_HOSTNAME},
11830 #endif
11831 #ifdef _CS_HW_PROVIDER
11832 {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
11833 #endif
11834 #ifdef _CS_HW_SERIAL
11835 {"CS_HW_SERIAL", _CS_HW_SERIAL},
11836 #endif
11837 #ifdef _CS_INITTAB_NAME
11838 {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11839 #endif
11840 #ifdef _CS_LFS64_CFLAGS
11841 {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11842 #endif
11843 #ifdef _CS_LFS64_LDFLAGS
11844 {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
11845 #endif
11846 #ifdef _CS_LFS64_LIBS
11847 {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
11848 #endif
11849 #ifdef _CS_LFS64_LINTFLAGS
11850 {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
11851 #endif
11852 #ifdef _CS_LFS_CFLAGS
11853 {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
11854 #endif
11855 #ifdef _CS_LFS_LDFLAGS
11856 {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
11857 #endif
11858 #ifdef _CS_LFS_LIBS
11859 {"CS_LFS_LIBS", _CS_LFS_LIBS},
11860 #endif
11861 #ifdef _CS_LFS_LINTFLAGS
11862 {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
11863 #endif
11864 #ifdef _CS_MACHINE
11865 {"CS_MACHINE", _CS_MACHINE},
11866 #endif
11867 #ifdef _CS_PATH
11868 {"CS_PATH", _CS_PATH},
11869 #endif
11870 #ifdef _CS_RELEASE
11871 {"CS_RELEASE", _CS_RELEASE},
11872 #endif
11873 #ifdef _CS_SRPC_DOMAIN
11874 {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
11875 #endif
11876 #ifdef _CS_SYSNAME
11877 {"CS_SYSNAME", _CS_SYSNAME},
11878 #endif
11879 #ifdef _CS_VERSION
11880 {"CS_VERSION", _CS_VERSION},
11881 #endif
11882 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11883 {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
11884 #endif
11885 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11886 {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
11887 #endif
11888 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11889 {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
11890 #endif
11891 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11892 {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11893 #endif
11894 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11895 {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11896 #endif
11897 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11898 {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11899 #endif
11900 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11901 {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
11902 #endif
11903 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11904 {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11905 #endif
11906 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11907 {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
11908 #endif
11909 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11910 {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
11911 #endif
11912 #ifdef _CS_XBS5_LP64_OFF64_LIBS
11913 {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11914 #endif
11915 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11916 {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
11917 #endif
11918 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11919 {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11920 #endif
11921 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11922 {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11923 #endif
11924 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11925 {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
11926 #endif
11927 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11928 {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11929 #endif
11930 #ifdef _MIPS_CS_AVAIL_PROCESSORS
11931 {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
11932 #endif
11933 #ifdef _MIPS_CS_BASE
11934 {"MIPS_CS_BASE", _MIPS_CS_BASE},
11935 #endif
11936 #ifdef _MIPS_CS_HOSTID
11937 {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
11938 #endif
11939 #ifdef _MIPS_CS_HW_NAME
11940 {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11941 #endif
11942 #ifdef _MIPS_CS_NUM_PROCESSORS
11943 {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
11944 #endif
11945 #ifdef _MIPS_CS_OSREL_MAJ
11946 {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
11947 #endif
11948 #ifdef _MIPS_CS_OSREL_MIN
11949 {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
11950 #endif
11951 #ifdef _MIPS_CS_OSREL_PATCH
11952 {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
11953 #endif
11954 #ifdef _MIPS_CS_OS_NAME
11955 {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11956 #endif
11957 #ifdef _MIPS_CS_OS_PROVIDER
11958 {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
11959 #endif
11960 #ifdef _MIPS_CS_PROCESSORS
11961 {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
11962 #endif
11963 #ifdef _MIPS_CS_SERIAL
11964 {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
11965 #endif
11966 #ifdef _MIPS_CS_VENDOR
11967 {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
11968 #endif
11969 };
11970
11971 static int
conv_confstr_confname(PyObject *arg, int *valuep)11972 conv_confstr_confname(PyObject *arg, int *valuep)
11973 {
11974 return conv_confname(arg, valuep, posix_constants_confstr,
11975 sizeof(posix_constants_confstr)
11976 / sizeof(struct constdef));
11977 }
11978
11979
11980 /*[clinic input]
11981 os.confstr
11982
11983 name: confstr_confname
11984 /
11985
11986 Return a string-valued system configuration variable.
11987 [clinic start generated code]*/
11988
11989 static PyObject *
os_confstr_impl(PyObject *module, int name)11990 os_confstr_impl(PyObject *module, int name)
11991 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11992 {
11993 PyObject *result = NULL;
11994 char buffer[255];
11995 size_t len;
11996
11997 errno = 0;
11998 len = confstr(name, buffer, sizeof(buffer));
11999 if (len == 0) {
12000 if (errno) {
12001 posix_error();
12002 return NULL;
12003 }
12004 else {
12005 Py_RETURN_NONE;
12006 }
12007 }
12008
12009 if (len >= sizeof(buffer)) {
12010 size_t len2;
12011 char *buf = PyMem_Malloc(len);
12012 if (buf == NULL)
12013 return PyErr_NoMemory();
12014 len2 = confstr(name, buf, len);
12015 assert(len == len2);
12016 result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
12017 PyMem_Free(buf);
12018 }
12019 else
12020 result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
12021 return result;
12022 }
12023 #endif /* HAVE_CONFSTR */
12024
12025
12026 #ifdef HAVE_SYSCONF
12027 static struct constdef posix_constants_sysconf[] = {
12028 #ifdef _SC_2_CHAR_TERM
12029 {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
12030 #endif
12031 #ifdef _SC_2_C_BIND
12032 {"SC_2_C_BIND", _SC_2_C_BIND},
12033 #endif
12034 #ifdef _SC_2_C_DEV
12035 {"SC_2_C_DEV", _SC_2_C_DEV},
12036 #endif
12037 #ifdef _SC_2_C_VERSION
12038 {"SC_2_C_VERSION", _SC_2_C_VERSION},
12039 #endif
12040 #ifdef _SC_2_FORT_DEV
12041 {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
12042 #endif
12043 #ifdef _SC_2_FORT_RUN
12044 {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
12045 #endif
12046 #ifdef _SC_2_LOCALEDEF
12047 {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
12048 #endif
12049 #ifdef _SC_2_SW_DEV
12050 {"SC_2_SW_DEV", _SC_2_SW_DEV},
12051 #endif
12052 #ifdef _SC_2_UPE
12053 {"SC_2_UPE", _SC_2_UPE},
12054 #endif
12055 #ifdef _SC_2_VERSION
12056 {"SC_2_VERSION", _SC_2_VERSION},
12057 #endif
12058 #ifdef _SC_ABI_ASYNCHRONOUS_IO
12059 {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
12060 #endif
12061 #ifdef _SC_ACL
12062 {"SC_ACL", _SC_ACL},
12063 #endif
12064 #ifdef _SC_AIO_LISTIO_MAX
12065 {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
12066 #endif
12067 #ifdef _SC_AIO_MAX
12068 {"SC_AIO_MAX", _SC_AIO_MAX},
12069 #endif
12070 #ifdef _SC_AIO_PRIO_DELTA_MAX
12071 {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
12072 #endif
12073 #ifdef _SC_ARG_MAX
12074 {"SC_ARG_MAX", _SC_ARG_MAX},
12075 #endif
12076 #ifdef _SC_ASYNCHRONOUS_IO
12077 {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
12078 #endif
12079 #ifdef _SC_ATEXIT_MAX
12080 {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
12081 #endif
12082 #ifdef _SC_AUDIT
12083 {"SC_AUDIT", _SC_AUDIT},
12084 #endif
12085 #ifdef _SC_AVPHYS_PAGES
12086 {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
12087 #endif
12088 #ifdef _SC_BC_BASE_MAX
12089 {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
12090 #endif
12091 #ifdef _SC_BC_DIM_MAX
12092 {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
12093 #endif
12094 #ifdef _SC_BC_SCALE_MAX
12095 {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
12096 #endif
12097 #ifdef _SC_BC_STRING_MAX
12098 {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
12099 #endif
12100 #ifdef _SC_CAP
12101 {"SC_CAP", _SC_CAP},
12102 #endif
12103 #ifdef _SC_CHARCLASS_NAME_MAX
12104 {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
12105 #endif
12106 #ifdef _SC_CHAR_BIT
12107 {"SC_CHAR_BIT", _SC_CHAR_BIT},
12108 #endif
12109 #ifdef _SC_CHAR_MAX
12110 {"SC_CHAR_MAX", _SC_CHAR_MAX},
12111 #endif
12112 #ifdef _SC_CHAR_MIN
12113 {"SC_CHAR_MIN", _SC_CHAR_MIN},
12114 #endif
12115 #ifdef _SC_CHILD_MAX
12116 {"SC_CHILD_MAX", _SC_CHILD_MAX},
12117 #endif
12118 #ifdef _SC_CLK_TCK
12119 {"SC_CLK_TCK", _SC_CLK_TCK},
12120 #endif
12121 #ifdef _SC_COHER_BLKSZ
12122 {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
12123 #endif
12124 #ifdef _SC_COLL_WEIGHTS_MAX
12125 {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
12126 #endif
12127 #ifdef _SC_DCACHE_ASSOC
12128 {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
12129 #endif
12130 #ifdef _SC_DCACHE_BLKSZ
12131 {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
12132 #endif
12133 #ifdef _SC_DCACHE_LINESZ
12134 {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
12135 #endif
12136 #ifdef _SC_DCACHE_SZ
12137 {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
12138 #endif
12139 #ifdef _SC_DCACHE_TBLKSZ
12140 {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
12141 #endif
12142 #ifdef _SC_DELAYTIMER_MAX
12143 {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
12144 #endif
12145 #ifdef _SC_EQUIV_CLASS_MAX
12146 {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
12147 #endif
12148 #ifdef _SC_EXPR_NEST_MAX
12149 {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
12150 #endif
12151 #ifdef _SC_FSYNC
12152 {"SC_FSYNC", _SC_FSYNC},
12153 #endif
12154 #ifdef _SC_GETGR_R_SIZE_MAX
12155 {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
12156 #endif
12157 #ifdef _SC_GETPW_R_SIZE_MAX
12158 {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
12159 #endif
12160 #ifdef _SC_ICACHE_ASSOC
12161 {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
12162 #endif
12163 #ifdef _SC_ICACHE_BLKSZ
12164 {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
12165 #endif
12166 #ifdef _SC_ICACHE_LINESZ
12167 {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
12168 #endif
12169 #ifdef _SC_ICACHE_SZ
12170 {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
12171 #endif
12172 #ifdef _SC_INF
12173 {"SC_INF", _SC_INF},
12174 #endif
12175 #ifdef _SC_INT_MAX
12176 {"SC_INT_MAX", _SC_INT_MAX},
12177 #endif
12178 #ifdef _SC_INT_MIN
12179 {"SC_INT_MIN", _SC_INT_MIN},
12180 #endif
12181 #ifdef _SC_IOV_MAX
12182 {"SC_IOV_MAX", _SC_IOV_MAX},
12183 #endif
12184 #ifdef _SC_IP_SECOPTS
12185 {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
12186 #endif
12187 #ifdef _SC_JOB_CONTROL
12188 {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
12189 #endif
12190 #ifdef _SC_KERN_POINTERS
12191 {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
12192 #endif
12193 #ifdef _SC_KERN_SIM
12194 {"SC_KERN_SIM", _SC_KERN_SIM},
12195 #endif
12196 #ifdef _SC_LINE_MAX
12197 {"SC_LINE_MAX", _SC_LINE_MAX},
12198 #endif
12199 #ifdef _SC_LOGIN_NAME_MAX
12200 {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
12201 #endif
12202 #ifdef _SC_LOGNAME_MAX
12203 {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
12204 #endif
12205 #ifdef _SC_LONG_BIT
12206 {"SC_LONG_BIT", _SC_LONG_BIT},
12207 #endif
12208 #ifdef _SC_MAC
12209 {"SC_MAC", _SC_MAC},
12210 #endif
12211 #ifdef _SC_MAPPED_FILES
12212 {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
12213 #endif
12214 #ifdef _SC_MAXPID
12215 {"SC_MAXPID", _SC_MAXPID},
12216 #endif
12217 #ifdef _SC_MB_LEN_MAX
12218 {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
12219 #endif
12220 #ifdef _SC_MEMLOCK
12221 {"SC_MEMLOCK", _SC_MEMLOCK},
12222 #endif
12223 #ifdef _SC_MEMLOCK_RANGE
12224 {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
12225 #endif
12226 #ifdef _SC_MEMORY_PROTECTION
12227 {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
12228 #endif
12229 #ifdef _SC_MESSAGE_PASSING
12230 {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
12231 #endif
12232 #ifdef _SC_MMAP_FIXED_ALIGNMENT
12233 {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
12234 #endif
12235 #ifdef _SC_MQ_OPEN_MAX
12236 {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
12237 #endif
12238 #ifdef _SC_MQ_PRIO_MAX
12239 {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},
12240 #endif
12241 #ifdef _SC_NACLS_MAX
12242 {"SC_NACLS_MAX", _SC_NACLS_MAX},
12243 #endif
12244 #ifdef _SC_NGROUPS_MAX
12245 {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX},
12246 #endif
12247 #ifdef _SC_NL_ARGMAX
12248 {"SC_NL_ARGMAX", _SC_NL_ARGMAX},
12249 #endif
12250 #ifdef _SC_NL_LANGMAX
12251 {"SC_NL_LANGMAX", _SC_NL_LANGMAX},
12252 #endif
12253 #ifdef _SC_NL_MSGMAX
12254 {"SC_NL_MSGMAX", _SC_NL_MSGMAX},
12255 #endif
12256 #ifdef _SC_NL_NMAX
12257 {"SC_NL_NMAX", _SC_NL_NMAX},
12258 #endif
12259 #ifdef _SC_NL_SETMAX
12260 {"SC_NL_SETMAX", _SC_NL_SETMAX},
12261 #endif
12262 #ifdef _SC_NL_TEXTMAX
12263 {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX},
12264 #endif
12265 #ifdef _SC_NPROCESSORS_CONF
12266 {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
12267 #endif
12268 #ifdef _SC_NPROCESSORS_ONLN
12269 {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
12270 #endif
12271 #ifdef _SC_NPROC_CONF
12272 {"SC_NPROC_CONF", _SC_NPROC_CONF},
12273 #endif
12274 #ifdef _SC_NPROC_ONLN
12275 {"SC_NPROC_ONLN", _SC_NPROC_ONLN},
12276 #endif
12277 #ifdef _SC_NZERO
12278 {"SC_NZERO", _SC_NZERO},
12279 #endif
12280 #ifdef _SC_OPEN_MAX
12281 {"SC_OPEN_MAX", _SC_OPEN_MAX},
12282 #endif
12283 #ifdef _SC_PAGESIZE
12284 {"SC_PAGESIZE", _SC_PAGESIZE},
12285 #endif
12286 #ifdef _SC_PAGE_SIZE
12287 {"SC_PAGE_SIZE", _SC_PAGE_SIZE},
12288 #endif
12289 #ifdef _SC_AIX_REALMEM
12290 {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
12291 #endif
12292 #ifdef _SC_PASS_MAX
12293 {"SC_PASS_MAX", _SC_PASS_MAX},
12294 #endif
12295 #ifdef _SC_PHYS_PAGES
12296 {"SC_PHYS_PAGES", _SC_PHYS_PAGES},
12297 #endif
12298 #ifdef _SC_PII
12299 {"SC_PII", _SC_PII},
12300 #endif
12301 #ifdef _SC_PII_INTERNET
12302 {"SC_PII_INTERNET", _SC_PII_INTERNET},
12303 #endif
12304 #ifdef _SC_PII_INTERNET_DGRAM
12305 {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM},
12306 #endif
12307 #ifdef _SC_PII_INTERNET_STREAM
12308 {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM},
12309 #endif
12310 #ifdef _SC_PII_OSI
12311 {"SC_PII_OSI", _SC_PII_OSI},
12312 #endif
12313 #ifdef _SC_PII_OSI_CLTS
12314 {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
12315 #endif
12316 #ifdef _SC_PII_OSI_COTS
12317 {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
12318 #endif
12319 #ifdef _SC_PII_OSI_M
12320 {"SC_PII_OSI_M", _SC_PII_OSI_M},
12321 #endif
12322 #ifdef _SC_PII_SOCKET
12323 {"SC_PII_SOCKET", _SC_PII_SOCKET},
12324 #endif
12325 #ifdef _SC_PII_XTI
12326 {"SC_PII_XTI", _SC_PII_XTI},
12327 #endif
12328 #ifdef _SC_POLL
12329 {"SC_POLL", _SC_POLL},
12330 #endif
12331 #ifdef _SC_PRIORITIZED_IO
12332 {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO},
12333 #endif
12334 #ifdef _SC_PRIORITY_SCHEDULING
12335 {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING},
12336 #endif
12337 #ifdef _SC_REALTIME_SIGNALS
12338 {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS},
12339 #endif
12340 #ifdef _SC_RE_DUP_MAX
12341 {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX},
12342 #endif
12343 #ifdef _SC_RTSIG_MAX
12344 {"SC_RTSIG_MAX", _SC_RTSIG_MAX},
12345 #endif
12346 #ifdef _SC_SAVED_IDS
12347 {"SC_SAVED_IDS", _SC_SAVED_IDS},
12348 #endif
12349 #ifdef _SC_SCHAR_MAX
12350 {"SC_SCHAR_MAX", _SC_SCHAR_MAX},
12351 #endif
12352 #ifdef _SC_SCHAR_MIN
12353 {"SC_SCHAR_MIN", _SC_SCHAR_MIN},
12354 #endif
12355 #ifdef _SC_SELECT
12356 {"SC_SELECT", _SC_SELECT},
12357 #endif
12358 #ifdef _SC_SEMAPHORES
12359 {"SC_SEMAPHORES", _SC_SEMAPHORES},
12360 #endif
12361 #ifdef _SC_SEM_NSEMS_MAX
12362 {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX},
12363 #endif
12364 #ifdef _SC_SEM_VALUE_MAX
12365 {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX},
12366 #endif
12367 #ifdef _SC_SHARED_MEMORY_OBJECTS
12368 {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS},
12369 #endif
12370 #ifdef _SC_SHRT_MAX
12371 {"SC_SHRT_MAX", _SC_SHRT_MAX},
12372 #endif
12373 #ifdef _SC_SHRT_MIN
12374 {"SC_SHRT_MIN", _SC_SHRT_MIN},
12375 #endif
12376 #ifdef _SC_SIGQUEUE_MAX
12377 {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
12378 #endif
12379 #ifdef _SC_SIGRT_MAX
12380 {"SC_SIGRT_MAX", _SC_SIGRT_MAX},
12381 #endif
12382 #ifdef _SC_SIGRT_MIN
12383 {"SC_SIGRT_MIN", _SC_SIGRT_MIN},
12384 #endif
12385 #ifdef _SC_SOFTPOWER
12386 {"SC_SOFTPOWER", _SC_SOFTPOWER},
12387 #endif
12388 #ifdef _SC_SPLIT_CACHE
12389 {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE},
12390 #endif
12391 #ifdef _SC_SSIZE_MAX
12392 {"SC_SSIZE_MAX", _SC_SSIZE_MAX},
12393 #endif
12394 #ifdef _SC_STACK_PROT
12395 {"SC_STACK_PROT", _SC_STACK_PROT},
12396 #endif
12397 #ifdef _SC_STREAM_MAX
12398 {"SC_STREAM_MAX", _SC_STREAM_MAX},
12399 #endif
12400 #ifdef _SC_SYNCHRONIZED_IO
12401 {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO},
12402 #endif
12403 #ifdef _SC_THREADS
12404 {"SC_THREADS", _SC_THREADS},
12405 #endif
12406 #ifdef _SC_THREAD_ATTR_STACKADDR
12407 {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR},
12408 #endif
12409 #ifdef _SC_THREAD_ATTR_STACKSIZE
12410 {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE},
12411 #endif
12412 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
12413 {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
12414 #endif
12415 #ifdef _SC_THREAD_KEYS_MAX
12416 {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
12417 #endif
12418 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
12419 {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING},
12420 #endif
12421 #ifdef _SC_THREAD_PRIO_INHERIT
12422 {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT},
12423 #endif
12424 #ifdef _SC_THREAD_PRIO_PROTECT
12425 {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT},
12426 #endif
12427 #ifdef _SC_THREAD_PROCESS_SHARED
12428 {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED},
12429 #endif
12430 #ifdef _SC_THREAD_SAFE_FUNCTIONS
12431 {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS},
12432 #endif
12433 #ifdef _SC_THREAD_STACK_MIN
12434 {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
12435 #endif
12436 #ifdef _SC_THREAD_THREADS_MAX
12437 {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
12438 #endif
12439 #ifdef _SC_TIMERS
12440 {"SC_TIMERS", _SC_TIMERS},
12441 #endif
12442 #ifdef _SC_TIMER_MAX
12443 {"SC_TIMER_MAX", _SC_TIMER_MAX},
12444 #endif
12445 #ifdef _SC_TTY_NAME_MAX
12446 {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
12447 #endif
12448 #ifdef _SC_TZNAME_MAX
12449 {"SC_TZNAME_MAX", _SC_TZNAME_MAX},
12450 #endif
12451 #ifdef _SC_T_IOV_MAX
12452 {"SC_T_IOV_MAX", _SC_T_IOV_MAX},
12453 #endif
12454 #ifdef _SC_UCHAR_MAX
12455 {"SC_UCHAR_MAX", _SC_UCHAR_MAX},
12456 #endif
12457 #ifdef _SC_UINT_MAX
12458 {"SC_UINT_MAX", _SC_UINT_MAX},
12459 #endif
12460 #ifdef _SC_UIO_MAXIOV
12461 {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV},
12462 #endif
12463 #ifdef _SC_ULONG_MAX
12464 {"SC_ULONG_MAX", _SC_ULONG_MAX},
12465 #endif
12466 #ifdef _SC_USHRT_MAX
12467 {"SC_USHRT_MAX", _SC_USHRT_MAX},
12468 #endif
12469 #ifdef _SC_VERSION
12470 {"SC_VERSION", _SC_VERSION},
12471 #endif
12472 #ifdef _SC_WORD_BIT
12473 {"SC_WORD_BIT", _SC_WORD_BIT},
12474 #endif
12475 #ifdef _SC_XBS5_ILP32_OFF32
12476 {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32},
12477 #endif
12478 #ifdef _SC_XBS5_ILP32_OFFBIG
12479 {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG},
12480 #endif
12481 #ifdef _SC_XBS5_LP64_OFF64
12482 {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64},
12483 #endif
12484 #ifdef _SC_XBS5_LPBIG_OFFBIG
12485 {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG},
12486 #endif
12487 #ifdef _SC_XOPEN_CRYPT
12488 {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT},
12489 #endif
12490 #ifdef _SC_XOPEN_ENH_I18N
12491 {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N},
12492 #endif
12493 #ifdef _SC_XOPEN_LEGACY
12494 {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
12495 #endif
12496 #ifdef _SC_XOPEN_REALTIME
12497 {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME},
12498 #endif
12499 #ifdef _SC_XOPEN_REALTIME_THREADS
12500 {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS},
12501 #endif
12502 #ifdef _SC_XOPEN_SHM
12503 {"SC_XOPEN_SHM", _SC_XOPEN_SHM},
12504 #endif
12505 #ifdef _SC_XOPEN_UNIX
12506 {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX},
12507 #endif
12508 #ifdef _SC_XOPEN_VERSION
12509 {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION},
12510 #endif
12511 #ifdef _SC_XOPEN_XCU_VERSION
12512 {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION},
12513 #endif
12514 #ifdef _SC_XOPEN_XPG2
12515 {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2},
12516 #endif
12517 #ifdef _SC_XOPEN_XPG3
12518 {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3},
12519 #endif
12520 #ifdef _SC_XOPEN_XPG4
12521 {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4},
12522 #endif
12523 #ifdef _SC_MINSIGSTKSZ
12524 {"SC_MINSIGSTKSZ", _SC_MINSIGSTKSZ},
12525 #endif
12526 };
12527
12528 static int
conv_sysconf_confname(PyObject *arg, int *valuep)12529 conv_sysconf_confname(PyObject *arg, int *valuep)
12530 {
12531 return conv_confname(arg, valuep, posix_constants_sysconf,
12532 sizeof(posix_constants_sysconf)
12533 / sizeof(struct constdef));
12534 }
12535
12536
12537 /*[clinic input]
12538 os.sysconf -> long
12539 name: sysconf_confname
12540 /
12541
12542 Return an integer-valued system configuration variable.
12543 [clinic start generated code]*/
12544
12545 static long
os_sysconf_impl(PyObject *module, int name)12546 os_sysconf_impl(PyObject *module, int name)
12547 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
12548 {
12549 long value;
12550
12551 errno = 0;
12552 value = sysconf(name);
12553 if (value == -1 && errno != 0)
12554 posix_error();
12555 return value;
12556 }
12557 #endif /* HAVE_SYSCONF */
12558
12559
12560 /* This code is used to ensure that the tables of configuration value names
12561 * are in sorted order as required by conv_confname(), and also to build
12562 * the exported dictionaries that are used to publish information about the
12563 * names available on the host platform.
12564 *
12565 * Sorting the table at runtime ensures that the table is properly ordered
12566 * when used, even for platforms we're not able to test on. It also makes
12567 * it easier to add additional entries to the tables.
12568 */
12569
12570 static int
cmp_constdefs(const void *v1, const void *v2)12571 cmp_constdefs(const void *v1, const void *v2)
12572 {
12573 const struct constdef *c1 =
12574 (const struct constdef *) v1;
12575 const struct constdef *c2 =
12576 (const struct constdef *) v2;
12577
12578 return strcmp(c1->name, c2->name);
12579 }
12580
12581 static int
setup_confname_table(struct constdef *table, size_t tablesize, const char *tablename, PyObject *module)12582 setup_confname_table(struct constdef *table, size_t tablesize,
12583 const char *tablename, PyObject *module)
12584 {
12585 PyObject *d = NULL;
12586 size_t i;
12587
12588 qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
12589 d = PyDict_New();
12590 if (d == NULL)
12591 return -1;
12592
12593 for (i=0; i < tablesize; ++i) {
12594 PyObject *o = PyLong_FromLong(table[i].value);
12595 if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
12596 Py_XDECREF(o);
12597 Py_DECREF(d);
12598 return -1;
12599 }
12600 Py_DECREF(o);
12601 }
12602 return PyModule_AddObject(module, tablename, d);
12603 }
12604
12605 /* Return -1 on failure, 0 on success. */
12606 static int
setup_confname_tables(PyObject *module)12607 setup_confname_tables(PyObject *module)
12608 {
12609 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12610 if (setup_confname_table(posix_constants_pathconf,
12611 sizeof(posix_constants_pathconf)
12612 / sizeof(struct constdef),
12613 "pathconf_names", module))
12614 return -1;
12615 #endif
12616 #ifdef HAVE_CONFSTR
12617 if (setup_confname_table(posix_constants_confstr,
12618 sizeof(posix_constants_confstr)
12619 / sizeof(struct constdef),
12620 "confstr_names", module))
12621 return -1;
12622 #endif
12623 #ifdef HAVE_SYSCONF
12624 if (setup_confname_table(posix_constants_sysconf,
12625 sizeof(posix_constants_sysconf)
12626 / sizeof(struct constdef),
12627 "sysconf_names", module))
12628 return -1;
12629 #endif
12630 return 0;
12631 }
12632
12633
12634 /*[clinic input]
12635 os.abort
12636
12637 Abort the interpreter immediately.
12638
12639 This function 'dumps core' or otherwise fails in the hardest way possible
12640 on the hosting operating system. This function never returns.
12641 [clinic start generated code]*/
12642
12643 static PyObject *
os_abort_impl(PyObject *module)12644 os_abort_impl(PyObject *module)
12645 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
12646 {
12647 abort();
12648 /*NOTREACHED*/
12649 #ifndef __clang__
12650 /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
12651 GCC emits a warning without "return NULL;" (compiler bug?), but Clang
12652 is smarter and emits a warning on the return. */
12653 Py_FatalError("abort() called from Python code didn't abort!");
12654 return NULL;
12655 #endif
12656 }
12657
12658 #ifdef MS_WINDOWS
12659 /* Grab ShellExecute dynamically from shell32 */
12660 static int has_ShellExecute = -1;
12661 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
12662 LPCWSTR, INT);
12663 static int
check_ShellExecutenull12664 check_ShellExecute()
12665 {
12666 HINSTANCE hShell32;
12667
12668 /* only recheck */
12669 if (-1 == has_ShellExecute) {
12670 Py_BEGIN_ALLOW_THREADS
12671 /* Security note: this call is not vulnerable to "DLL hijacking".
12672 SHELL32 is part of "KnownDLLs" and so Windows always load
12673 the system SHELL32.DLL, even if there is another SHELL32.DLL
12674 in the DLL search path. */
12675 hShell32 = LoadLibraryW(L"SHELL32");
12676 if (hShell32) {
12677 *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
12678 "ShellExecuteW");
12679 has_ShellExecute = Py_ShellExecuteW != NULL;
12680 } else {
12681 has_ShellExecute = 0;
12682 }
12683 Py_END_ALLOW_THREADS
12684 }
12685 return has_ShellExecute;
12686 }
12687
12688
12689 /*[clinic input]
12690 os.startfile
12691 filepath: path_t
12692 operation: Py_UNICODE = NULL
12693 arguments: Py_UNICODE = NULL
12694 cwd: path_t(nullable=True) = None
12695 show_cmd: int = 1
12696
12697 Start a file with its associated application.
12698
12699 When "operation" is not specified or "open", this acts like
12700 double-clicking the file in Explorer, or giving the file name as an
12701 argument to the DOS "start" command: the file is opened with whatever
12702 application (if any) its extension is associated.
12703 When another "operation" is given, it specifies what should be done with
12704 the file. A typical operation is "print".
12705
12706 "arguments" is passed to the application, but should be omitted if the
12707 file is a document.
12708
12709 "cwd" is the working directory for the operation. If "filepath" is
12710 relative, it will be resolved against this directory. This argument
12711 should usually be an absolute path.
12712
12713 "show_cmd" can be used to override the recommended visibility option.
12714 See the Windows ShellExecute documentation for values.
12715
12716 startfile returns as soon as the associated application is launched.
12717 There is no option to wait for the application to close, and no way
12718 to retrieve the application's exit status.
12719
12720 The filepath is relative to the current directory. If you want to use
12721 an absolute path, make sure the first character is not a slash ("/");
12722 the underlying Win32 ShellExecute function doesn't work if it is.
12723 [clinic start generated code]*/
12724
12725 static PyObject *
os_startfile_impl(PyObject *module, path_t *filepath, const Py_UNICODE *operation, const Py_UNICODE *arguments, path_t *cwd, int show_cmd)12726 os_startfile_impl(PyObject *module, path_t *filepath,
12727 const Py_UNICODE *operation, const Py_UNICODE *arguments,
12728 path_t *cwd, int show_cmd)
12729 /*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/
12730 {
12731 HINSTANCE rc;
12732
12733 if(!check_ShellExecute()) {
12734 /* If the OS doesn't have ShellExecute, return a
12735 NotImplementedError. */
12736 return PyErr_Format(PyExc_NotImplementedError,
12737 "startfile not available on this platform");
12738 }
12739
12740 if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
12741 return NULL;
12742 }
12743 if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
12744 arguments, cwd->object ? cwd->object : Py_None,
12745 show_cmd) < 0) {
12746 return NULL;
12747 }
12748
12749 Py_BEGIN_ALLOW_THREADS
12750 rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
12751 arguments, cwd->wide, show_cmd);
12752 Py_END_ALLOW_THREADS
12753
12754 if (rc <= (HINSTANCE)32) {
12755 win32_error_object("startfile", filepath->object);
12756 return NULL;
12757 }
12758 Py_RETURN_NONE;
12759 }
12760 #endif /* MS_WINDOWS */
12761
12762
12763 #ifdef HAVE_GETLOADAVG
12764 /*[clinic input]
12765 os.getloadavg
12766
12767 Return average recent system load information.
12768
12769 Return the number of processes in the system run queue averaged over
12770 the last 1, 5, and 15 minutes as a tuple of three floats.
12771 Raises OSError if the load average was unobtainable.
12772 [clinic start generated code]*/
12773
12774 static PyObject *
os_getloadavg_impl(PyObject *module)12775 os_getloadavg_impl(PyObject *module)
12776 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
12777 {
12778 double loadavg[3];
12779 if (getloadavg(loadavg, 3)!=3) {
12780 PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
12781 return NULL;
12782 } else
12783 return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
12784 }
12785 #endif /* HAVE_GETLOADAVG */
12786
12787
12788 /*[clinic input]
12789 os.device_encoding
12790 fd: int
12791
12792 Return a string describing the encoding of a terminal's file descriptor.
12793
12794 The file descriptor must be attached to a terminal.
12795 If the device is not a terminal, return None.
12796 [clinic start generated code]*/
12797
12798 static PyObject *
os_device_encoding_impl(PyObject *module, int fd)12799 os_device_encoding_impl(PyObject *module, int fd)
12800 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
12801 {
12802 return _Py_device_encoding(fd);
12803 }
12804
12805
12806 #ifdef HAVE_SETRESUID
12807 /*[clinic input]
12808 os.setresuid
12809
12810 ruid: uid_t
12811 euid: uid_t
12812 suid: uid_t
12813 /
12814
12815 Set the current process's real, effective, and saved user ids.
12816 [clinic start generated code]*/
12817
12818 static PyObject *
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)12819 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
12820 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
12821 {
12822 if (setresuid(ruid, euid, suid) < 0)
12823 return posix_error();
12824 Py_RETURN_NONE;
12825 }
12826 #endif /* HAVE_SETRESUID */
12827
12828
12829 #ifdef HAVE_SETRESGID
12830 /*[clinic input]
12831 os.setresgid
12832
12833 rgid: gid_t
12834 egid: gid_t
12835 sgid: gid_t
12836 /
12837
12838 Set the current process's real, effective, and saved group ids.
12839 [clinic start generated code]*/
12840
12841 static PyObject *
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)12842 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
12843 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
12844 {
12845 if (setresgid(rgid, egid, sgid) < 0)
12846 return posix_error();
12847 Py_RETURN_NONE;
12848 }
12849 #endif /* HAVE_SETRESGID */
12850
12851
12852 #ifdef HAVE_GETRESUID
12853 /*[clinic input]
12854 os.getresuid
12855
12856 Return a tuple of the current process's real, effective, and saved user ids.
12857 [clinic start generated code]*/
12858
12859 static PyObject *
os_getresuid_impl(PyObject *module)12860 os_getresuid_impl(PyObject *module)
12861 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12862 {
12863 uid_t ruid, euid, suid;
12864 if (getresuid(&ruid, &euid, &suid) < 0)
12865 return posix_error();
12866 return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12867 _PyLong_FromUid(euid),
12868 _PyLong_FromUid(suid));
12869 }
12870 #endif /* HAVE_GETRESUID */
12871
12872
12873 #ifdef HAVE_GETRESGID
12874 /*[clinic input]
12875 os.getresgid
12876
12877 Return a tuple of the current process's real, effective, and saved group ids.
12878 [clinic start generated code]*/
12879
12880 static PyObject *
os_getresgid_impl(PyObject *module)12881 os_getresgid_impl(PyObject *module)
12882 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12883 {
12884 gid_t rgid, egid, sgid;
12885 if (getresgid(&rgid, &egid, &sgid) < 0)
12886 return posix_error();
12887 return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12888 _PyLong_FromGid(egid),
12889 _PyLong_FromGid(sgid));
12890 }
12891 #endif /* HAVE_GETRESGID */
12892
12893
12894 #ifdef USE_XATTRS
12895 /*[clinic input]
12896 os.getxattr
12897
12898 path: path_t(allow_fd=True)
12899 attribute: path_t
12900 *
12901 follow_symlinks: bool = True
12902
12903 Return the value of extended attribute attribute on path.
12904
12905 path may be either a string, a path-like object, or an open file descriptor.
12906 If follow_symlinks is False, and the last element of the path is a symbolic
12907 link, getxattr will examine the symbolic link itself instead of the file
12908 the link points to.
12909
12910 [clinic start generated code]*/
12911
12912 static PyObject *
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, int follow_symlinks)12913 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12914 int follow_symlinks)
12915 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12916 {
12917 Py_ssize_t i;
12918 PyObject *buffer = NULL;
12919
12920 if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12921 return NULL;
12922
12923 if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12924 return NULL;
12925 }
12926
12927 for (i = 0; ; i++) {
12928 void *ptr;
12929 ssize_t result;
12930 static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12931 Py_ssize_t buffer_size = buffer_sizes[i];
12932 if (!buffer_size) {
12933 path_error(path);
12934 return NULL;
12935 }
12936 buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12937 if (!buffer)
12938 return NULL;
12939 ptr = PyBytes_AS_STRING(buffer);
12940
12941 Py_BEGIN_ALLOW_THREADS;
12942 if (path->fd >= 0)
12943 result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12944 else if (follow_symlinks)
12945 result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12946 else
12947 result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12948 Py_END_ALLOW_THREADS;
12949
12950 if (result < 0) {
12951 Py_DECREF(buffer);
12952 if (errno == ERANGE)
12953 continue;
12954 path_error(path);
12955 return NULL;
12956 }
12957
12958 if (result != buffer_size) {
12959 /* Can only shrink. */
12960 _PyBytes_Resize(&buffer, result);
12961 }
12962 break;
12963 }
12964
12965 return buffer;
12966 }
12967
12968
12969 /*[clinic input]
12970 os.setxattr
12971
12972 path: path_t(allow_fd=True)
12973 attribute: path_t
12974 value: Py_buffer
12975 flags: int = 0
12976 *
12977 follow_symlinks: bool = True
12978
12979 Set extended attribute attribute on path to value.
12980
12981 path may be either a string, a path-like object, or an open file descriptor.
12982 If follow_symlinks is False, and the last element of the path is a symbolic
12983 link, setxattr will modify the symbolic link itself instead of the file
12984 the link points to.
12985
12986 [clinic start generated code]*/
12987
12988 static PyObject *
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, Py_buffer *value, int flags, int follow_symlinks)12989 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12990 Py_buffer *value, int flags, int follow_symlinks)
12991 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12992 {
12993 ssize_t result;
12994
12995 if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12996 return NULL;
12997
12998 if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12999 value->buf, value->len, flags) < 0) {
13000 return NULL;
13001 }
13002
13003 Py_BEGIN_ALLOW_THREADS;
13004 if (path->fd > -1)
13005 result = fsetxattr(path->fd, attribute->narrow,
13006 value->buf, value->len, flags);
13007 else if (follow_symlinks)
13008 result = setxattr(path->narrow, attribute->narrow,
13009 value->buf, value->len, flags);
13010 else
13011 result = lsetxattr(path->narrow, attribute->narrow,
13012 value->buf, value->len, flags);
13013 Py_END_ALLOW_THREADS;
13014
13015 if (result) {
13016 path_error(path);
13017 return NULL;
13018 }
13019
13020 Py_RETURN_NONE;
13021 }
13022
13023
13024 /*[clinic input]
13025 os.removexattr
13026
13027 path: path_t(allow_fd=True)
13028 attribute: path_t
13029 *
13030 follow_symlinks: bool = True
13031
13032 Remove extended attribute attribute on path.
13033
13034 path may be either a string, a path-like object, or an open file descriptor.
13035 If follow_symlinks is False, and the last element of the path is a symbolic
13036 link, removexattr will modify the symbolic link itself instead of the file
13037 the link points to.
13038
13039 [clinic start generated code]*/
13040
13041 static PyObject *
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, int follow_symlinks)13042 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
13043 int follow_symlinks)
13044 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
13045 {
13046 ssize_t result;
13047
13048 if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
13049 return NULL;
13050
13051 if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
13052 return NULL;
13053 }
13054
13055 Py_BEGIN_ALLOW_THREADS;
13056 if (path->fd > -1)
13057 result = fremovexattr(path->fd, attribute->narrow);
13058 else if (follow_symlinks)
13059 result = removexattr(path->narrow, attribute->narrow);
13060 else
13061 result = lremovexattr(path->narrow, attribute->narrow);
13062 Py_END_ALLOW_THREADS;
13063
13064 if (result) {
13065 return path_error(path);
13066 }
13067
13068 Py_RETURN_NONE;
13069 }
13070
13071
13072 /*[clinic input]
13073 os.listxattr
13074
13075 path: path_t(allow_fd=True, nullable=True) = None
13076 *
13077 follow_symlinks: bool = True
13078
13079 Return a list of extended attributes on path.
13080
13081 path may be either None, a string, a path-like object, or an open file descriptor.
13082 if path is None, listxattr will examine the current directory.
13083 If follow_symlinks is False, and the last element of the path is a symbolic
13084 link, listxattr will examine the symbolic link itself instead of the file
13085 the link points to.
13086 [clinic start generated code]*/
13087
13088 static PyObject *
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)13089 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
13090 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
13091 {
13092 Py_ssize_t i;
13093 PyObject *result = NULL;
13094 const char *name;
13095 char *buffer = NULL;
13096
13097 if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
13098 goto exit;
13099
13100 if (PySys_Audit("os.listxattr", "(O)",
13101 path->object ? path->object : Py_None) < 0) {
13102 return NULL;
13103 }
13104
13105 name = path->narrow ? path->narrow : ".";
13106
13107 for (i = 0; ; i++) {
13108 const char *start, *trace, *end;
13109 ssize_t length;
13110 static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
13111 Py_ssize_t buffer_size = buffer_sizes[i];
13112 if (!buffer_size) {
13113 /* ERANGE */
13114 path_error(path);
13115 break;
13116 }
13117 buffer = PyMem_Malloc(buffer_size);
13118 if (!buffer) {
13119 PyErr_NoMemory();
13120 break;
13121 }
13122
13123 Py_BEGIN_ALLOW_THREADS;
13124 if (path->fd > -1)
13125 length = flistxattr(path->fd, buffer, buffer_size);
13126 else if (follow_symlinks)
13127 length = listxattr(name, buffer, buffer_size);
13128 else
13129 length = llistxattr(name, buffer, buffer_size);
13130 Py_END_ALLOW_THREADS;
13131
13132 if (length < 0) {
13133 if (errno == ERANGE) {
13134 PyMem_Free(buffer);
13135 buffer = NULL;
13136 continue;
13137 }
13138 path_error(path);
13139 break;
13140 }
13141
13142 result = PyList_New(0);
13143 if (!result) {
13144 goto exit;
13145 }
13146
13147 end = buffer + length;
13148 for (trace = start = buffer; trace != end; trace++) {
13149 if (!*trace) {
13150 int error;
13151 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
13152 trace - start);
13153 if (!attribute) {
13154 Py_DECREF(result);
13155 result = NULL;
13156 goto exit;
13157 }
13158 error = PyList_Append(result, attribute);
13159 Py_DECREF(attribute);
13160 if (error) {
13161 Py_DECREF(result);
13162 result = NULL;
13163 goto exit;
13164 }
13165 start = trace + 1;
13166 }
13167 }
13168 break;
13169 }
13170 exit:
13171 if (buffer)
13172 PyMem_Free(buffer);
13173 return result;
13174 }
13175 #endif /* USE_XATTRS */
13176
13177
13178 /*[clinic input]
13179 os.urandom
13180
13181 size: Py_ssize_t
13182 /
13183
13184 Return a bytes object containing random bytes suitable for cryptographic use.
13185 [clinic start generated code]*/
13186
13187 static PyObject *
os_urandom_impl(PyObject *module, Py_ssize_t size)13188 os_urandom_impl(PyObject *module, Py_ssize_t size)
13189 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
13190 {
13191 PyObject *bytes;
13192 int result;
13193
13194 if (size < 0)
13195 return PyErr_Format(PyExc_ValueError,
13196 "negative argument not allowed");
13197 bytes = PyBytes_FromStringAndSize(NULL, size);
13198 if (bytes == NULL)
13199 return NULL;
13200
13201 result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
13202 if (result == -1) {
13203 Py_DECREF(bytes);
13204 return NULL;
13205 }
13206 return bytes;
13207 }
13208
13209 #ifdef HAVE_MEMFD_CREATE
13210 /*[clinic input]
13211 os.memfd_create
13212
13213 name: FSConverter
13214 flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
13215
13216 [clinic start generated code]*/
13217
13218 static PyObject *
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)13219 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
13220 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
13221 {
13222 int fd;
13223 const char *bytes = PyBytes_AS_STRING(name);
13224 Py_BEGIN_ALLOW_THREADS
13225 fd = memfd_create(bytes, flags);
13226 Py_END_ALLOW_THREADS
13227 if (fd == -1) {
13228 return PyErr_SetFromErrno(PyExc_OSError);
13229 }
13230 return PyLong_FromLong(fd);
13231 }
13232 #endif
13233
13234 #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
13235 /*[clinic input]
13236 os.eventfd
13237
13238 initval: unsigned_int
13239 flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
13240
13241 Creates and returns an event notification file descriptor.
13242 [clinic start generated code]*/
13243
13244 static PyObject *
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)13245 os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
13246 /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
13247
13248 {
13249 /* initval is limited to uint32_t, internal counter is uint64_t */
13250 int fd;
13251 Py_BEGIN_ALLOW_THREADS
13252 fd = eventfd(initval, flags);
13253 Py_END_ALLOW_THREADS
13254 if (fd == -1) {
13255 return PyErr_SetFromErrno(PyExc_OSError);
13256 }
13257 return PyLong_FromLong(fd);
13258 }
13259
13260 /*[clinic input]
13261 os.eventfd_read
13262
13263 fd: fildes
13264
13265 Read eventfd value
13266 [clinic start generated code]*/
13267
13268 static PyObject *
os_eventfd_read_impl(PyObject *module, int fd)13269 os_eventfd_read_impl(PyObject *module, int fd)
13270 /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
13271 {
13272 eventfd_t value;
13273 int result;
13274 Py_BEGIN_ALLOW_THREADS
13275 result = eventfd_read(fd, &value);
13276 Py_END_ALLOW_THREADS
13277 if (result == -1) {
13278 return PyErr_SetFromErrno(PyExc_OSError);
13279 }
13280 return PyLong_FromUnsignedLongLong(value);
13281 }
13282
13283 /*[clinic input]
13284 os.eventfd_write
13285
13286 fd: fildes
13287 value: unsigned_long_long
13288
13289 Write eventfd value.
13290 [clinic start generated code]*/
13291
13292 static PyObject *
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)13293 os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
13294 /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
13295 {
13296 int result;
13297 Py_BEGIN_ALLOW_THREADS
13298 result = eventfd_write(fd, value);
13299 Py_END_ALLOW_THREADS
13300 if (result == -1) {
13301 return PyErr_SetFromErrno(PyExc_OSError);
13302 }
13303 Py_RETURN_NONE;
13304 }
13305 #endif /* HAVE_EVENTFD && EFD_CLOEXEC */
13306
13307 /* Terminal size querying */
13308
13309 PyDoc_STRVAR(TerminalSize_docstring,
13310 "A tuple of (columns, lines) for holding terminal window size");
13311
13312 static PyStructSequence_Field TerminalSize_fields[] = {
13313 {"columns", "width of the terminal window in characters"},
13314 {"lines", "height of the terminal window in characters"},
13315 {NULL, NULL}
13316 };
13317
13318 static PyStructSequence_Desc TerminalSize_desc = {
13319 "os.terminal_size",
13320 TerminalSize_docstring,
13321 TerminalSize_fields,
13322 2,
13323 };
13324
13325 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
13326 /*[clinic input]
13327 os.get_terminal_size
13328
13329 fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
13330 /
13331
13332 Return the size of the terminal window as (columns, lines).
13333
13334 The optional argument fd (default standard output) specifies
13335 which file descriptor should be queried.
13336
13337 If the file descriptor is not connected to a terminal, an OSError
13338 is thrown.
13339
13340 This function will only be defined if an implementation is
13341 available for this system.
13342
13343 shutil.get_terminal_size is the high-level function which should
13344 normally be used, os.get_terminal_size is the low-level implementation.
13345 [clinic start generated code]*/
13346
13347 static PyObject *
os_get_terminal_size_impl(PyObject *module, int fd)13348 os_get_terminal_size_impl(PyObject *module, int fd)
13349 /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
13350 {
13351 int columns, lines;
13352 PyObject *termsize;
13353
13354 /* Under some conditions stdout may not be connected and
13355 * fileno(stdout) may point to an invalid file descriptor. For example
13356 * GUI apps don't have valid standard streams by default.
13357 *
13358 * If this happens, and the optional fd argument is not present,
13359 * the ioctl below will fail returning EBADF. This is what we want.
13360 */
13361
13362 #ifdef TERMSIZE_USE_IOCTL
13363 {
13364 struct winsize w;
13365 if (ioctl(fd, TIOCGWINSZ, &w))
13366 return PyErr_SetFromErrno(PyExc_OSError);
13367 columns = w.ws_col;
13368 lines = w.ws_row;
13369 }
13370 #endif /* TERMSIZE_USE_IOCTL */
13371
13372 #ifdef TERMSIZE_USE_CONIO
13373 {
13374 DWORD nhandle;
13375 HANDLE handle;
13376 CONSOLE_SCREEN_BUFFER_INFO csbi;
13377 switch (fd) {
13378 case 0: nhandle = STD_INPUT_HANDLE;
13379 break;
13380 case 1: nhandle = STD_OUTPUT_HANDLE;
13381 break;
13382 case 2: nhandle = STD_ERROR_HANDLE;
13383 break;
13384 default:
13385 return PyErr_Format(PyExc_ValueError, "bad file descriptor");
13386 }
13387 handle = GetStdHandle(nhandle);
13388 if (handle == NULL)
13389 return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
13390 if (handle == INVALID_HANDLE_VALUE)
13391 return PyErr_SetFromWindowsErr(0);
13392
13393 if (!GetConsoleScreenBufferInfo(handle, &csbi))
13394 return PyErr_SetFromWindowsErr(0);
13395
13396 columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
13397 lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
13398 }
13399 #endif /* TERMSIZE_USE_CONIO */
13400
13401 PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
13402 termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
13403 if (termsize == NULL)
13404 return NULL;
13405 PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
13406 PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
13407 if (PyErr_Occurred()) {
13408 Py_DECREF(termsize);
13409 return NULL;
13410 }
13411 return termsize;
13412 }
13413 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
13414
13415
13416 /*[clinic input]
13417 os.cpu_count
13418
13419 Return the number of CPUs in the system; return None if indeterminable.
13420
13421 This number is not equivalent to the number of CPUs the current process can
13422 use. The number of usable CPUs can be obtained with
13423 ``len(os.sched_getaffinity(0))``
13424 [clinic start generated code]*/
13425
13426 static PyObject *
os_cpu_count_impl(PyObject *module)13427 os_cpu_count_impl(PyObject *module)
13428 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
13429 {
13430 int ncpu = 0;
13431 #ifdef MS_WINDOWS
13432 ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
13433 #elif defined(__hpux)
13434 ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
13435 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
13436 ncpu = sysconf(_SC_NPROCESSORS_ONLN);
13437 #elif defined(__VXWORKS__)
13438 ncpu = _Py_popcount32(vxCpuEnabledGet());
13439 #elif defined(__DragonFly__) || \
13440 defined(__OpenBSD__) || \
13441 defined(__FreeBSD__) || \
13442 defined(__NetBSD__) || \
13443 defined(__APPLE__)
13444 int mib[2];
13445 size_t len = sizeof(ncpu);
13446 mib[0] = CTL_HW;
13447 mib[1] = HW_NCPU;
13448 if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
13449 ncpu = 0;
13450 #endif
13451 if (ncpu >= 1)
13452 return PyLong_FromLong(ncpu);
13453 else
13454 Py_RETURN_NONE;
13455 }
13456
13457
13458 /*[clinic input]
13459 os.get_inheritable -> bool
13460
13461 fd: int
13462 /
13463
13464 Get the close-on-exe flag of the specified file descriptor.
13465 [clinic start generated code]*/
13466
13467 static int
os_get_inheritable_impl(PyObject *module, int fd)13468 os_get_inheritable_impl(PyObject *module, int fd)
13469 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
13470 {
13471 int return_value;
13472 _Py_BEGIN_SUPPRESS_IPH
13473 return_value = _Py_get_inheritable(fd);
13474 _Py_END_SUPPRESS_IPH
13475 return return_value;
13476 }
13477
13478
13479 /*[clinic input]
13480 os.set_inheritable
13481 fd: int
13482 inheritable: int
13483 /
13484
13485 Set the inheritable flag of the specified file descriptor.
13486 [clinic start generated code]*/
13487
13488 static PyObject *
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)13489 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
13490 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
13491 {
13492 int result;
13493
13494 _Py_BEGIN_SUPPRESS_IPH
13495 result = _Py_set_inheritable(fd, inheritable, NULL);
13496 _Py_END_SUPPRESS_IPH
13497 if (result < 0)
13498 return NULL;
13499 Py_RETURN_NONE;
13500 }
13501
13502
13503 #ifdef MS_WINDOWS
13504 /*[clinic input]
13505 os.get_handle_inheritable -> bool
13506 handle: intptr_t
13507 /
13508
13509 Get the close-on-exe flag of the specified file descriptor.
13510 [clinic start generated code]*/
13511
13512 static int
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)13513 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
13514 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
13515 {
13516 DWORD flags;
13517
13518 if (!GetHandleInformation((HANDLE)handle, &flags)) {
13519 PyErr_SetFromWindowsErr(0);
13520 return -1;
13521 }
13522
13523 return flags & HANDLE_FLAG_INHERIT;
13524 }
13525
13526
13527 /*[clinic input]
13528 os.set_handle_inheritable
13529 handle: intptr_t
13530 inheritable: bool
13531 /
13532
13533 Set the inheritable flag of the specified handle.
13534 [clinic start generated code]*/
13535
13536 static PyObject *
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, int inheritable)13537 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
13538 int inheritable)
13539 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
13540 {
13541 DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
13542 if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
13543 PyErr_SetFromWindowsErr(0);
13544 return NULL;
13545 }
13546 Py_RETURN_NONE;
13547 }
13548 #endif /* MS_WINDOWS */
13549
13550 #ifndef MS_WINDOWS
13551 /*[clinic input]
13552 os.get_blocking -> bool
13553 fd: int
13554 /
13555
13556 Get the blocking mode of the file descriptor.
13557
13558 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
13559 [clinic start generated code]*/
13560
13561 static int
os_get_blocking_impl(PyObject *module, int fd)13562 os_get_blocking_impl(PyObject *module, int fd)
13563 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
13564 {
13565 int blocking;
13566
13567 _Py_BEGIN_SUPPRESS_IPH
13568 blocking = _Py_get_blocking(fd);
13569 _Py_END_SUPPRESS_IPH
13570 return blocking;
13571 }
13572
13573 /*[clinic input]
13574 os.set_blocking
13575 fd: int
13576 blocking: bool(accept={int})
13577 /
13578
13579 Set the blocking mode of the specified file descriptor.
13580
13581 Set the O_NONBLOCK flag if blocking is False,
13582 clear the O_NONBLOCK flag otherwise.
13583 [clinic start generated code]*/
13584
13585 static PyObject *
os_set_blocking_impl(PyObject *module, int fd, int blocking)13586 os_set_blocking_impl(PyObject *module, int fd, int blocking)
13587 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
13588 {
13589 int result;
13590
13591 _Py_BEGIN_SUPPRESS_IPH
13592 result = _Py_set_blocking(fd, blocking);
13593 _Py_END_SUPPRESS_IPH
13594 if (result < 0)
13595 return NULL;
13596 Py_RETURN_NONE;
13597 }
13598 #endif /* !MS_WINDOWS */
13599
13600
13601 /*[clinic input]
13602 class os.DirEntry "DirEntry *" "DirEntryType"
13603 [clinic start generated code]*/
13604 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
13605
13606 typedef struct {
13607 PyObject_HEAD
13608 PyObject *name;
13609 PyObject *path;
13610 PyObject *stat;
13611 PyObject *lstat;
13612 #ifdef MS_WINDOWS
13613 struct _Py_stat_struct win32_lstat;
13614 uint64_t win32_file_index;
13615 int got_file_index;
13616 #else /* POSIX */
13617 #ifdef HAVE_DIRENT_D_TYPE
13618 unsigned char d_type;
13619 #endif
13620 ino_t d_ino;
13621 int dir_fd;
13622 #endif
13623 } DirEntry;
13624
13625 static void
DirEntry_dealloc(DirEntry *entry)13626 DirEntry_dealloc(DirEntry *entry)
13627 {
13628 PyTypeObject *tp = Py_TYPE(entry);
13629 Py_XDECREF(entry->name);
13630 Py_XDECREF(entry->path);
13631 Py_XDECREF(entry->stat);
13632 Py_XDECREF(entry->lstat);
13633 freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13634 free_func(entry);
13635 Py_DECREF(tp);
13636 }
13637
13638 /* Forward reference */
13639 static int
13640 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13641 int follow_symlinks, unsigned short mode_bits);
13642
13643 /*[clinic input]
13644 os.DirEntry.is_symlink -> bool
13645 defining_class: defining_class
13646 /
13647
13648 Return True if the entry is a symbolic link; cached per entry.
13649 [clinic start generated code]*/
13650
13651 static int
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)13652 os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
13653 /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
13654 {
13655 #ifdef MS_WINDOWS
13656 return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13657 #elif defined(HAVE_DIRENT_D_TYPE)
13658 /* POSIX */
13659 if (self->d_type != DT_UNKNOWN)
13660 return self->d_type == DT_LNK;
13661 else
13662 return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13663 #else
13664 /* POSIX without d_type */
13665 return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13666 #endif
13667 }
13668
13669 static PyObject *
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)13670 DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
13671 {
13672 int result;
13673 STRUCT_STAT st;
13674 PyObject *ub;
13675
13676 #ifdef MS_WINDOWS
13677 if (!PyUnicode_FSDecoder(self->path, &ub))
13678 return NULL;
13679 #if USE_UNICODE_WCHAR_CACHE
13680 _Py_COMP_DIAG_PUSH
13681 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13682 const wchar_t *path = PyUnicode_AsUnicode(ub);
13683 _Py_COMP_DIAG_POP
13684 #else /* USE_UNICODE_WCHAR_CACHE */
13685 wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
13686 Py_DECREF(ub);
13687 #endif /* USE_UNICODE_WCHAR_CACHE */
13688 #else /* POSIX */
13689 if (!PyUnicode_FSConverter(self->path, &ub))
13690 return NULL;
13691 const char *path = PyBytes_AS_STRING(ub);
13692 if (self->dir_fd != DEFAULT_DIR_FD) {
13693 #ifdef HAVE_FSTATAT
13694 if (HAVE_FSTATAT_RUNTIME) {
13695 Py_BEGIN_ALLOW_THREADS
13696 result = fstatat(self->dir_fd, path, &st,
13697 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
13698 Py_END_ALLOW_THREADS
13699 } else
13700
13701 #endif /* HAVE_FSTATAT */
13702 {
13703 Py_DECREF(ub);
13704 PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
13705 return NULL;
13706 }
13707 }
13708 else
13709 #endif
13710 {
13711 Py_BEGIN_ALLOW_THREADS
13712 if (follow_symlinks) {
13713 result = STAT(path, &st);
13714 }
13715 else {
13716 result = LSTAT(path, &st);
13717 }
13718 Py_END_ALLOW_THREADS
13719 }
13720 #if defined(MS_WINDOWS) && !USE_UNICODE_WCHAR_CACHE
13721 PyMem_Free(path);
13722 #else /* USE_UNICODE_WCHAR_CACHE */
13723 Py_DECREF(ub);
13724 #endif /* USE_UNICODE_WCHAR_CACHE */
13725
13726 if (result != 0)
13727 return path_object_error(self->path);
13728
13729 return _pystat_fromstructstat(module, &st);
13730 }
13731
13732 static PyObject *
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)13733 DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
13734 {
13735 if (!self->lstat) {
13736 PyObject *module = PyType_GetModule(defining_class);
13737 #ifdef MS_WINDOWS
13738 self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
13739 #else /* POSIX */
13740 self->lstat = DirEntry_fetch_stat(module, self, 0);
13741 #endif
13742 }
13743 Py_XINCREF(self->lstat);
13744 return self->lstat;
13745 }
13746
13747 /*[clinic input]
13748 os.DirEntry.stat
13749 defining_class: defining_class
13750 /
13751 *
13752 follow_symlinks: bool = True
13753
13754 Return stat_result object for the entry; cached per entry.
13755 [clinic start generated code]*/
13756
13757 static PyObject *
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class, int follow_symlinks)13758 os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
13759 int follow_symlinks)
13760 /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
13761 {
13762 if (!follow_symlinks) {
13763 return DirEntry_get_lstat(defining_class, self);
13764 }
13765
13766 if (!self->stat) {
13767 int result = os_DirEntry_is_symlink_impl(self, defining_class);
13768 if (result == -1) {
13769 return NULL;
13770 }
13771 if (result) {
13772 PyObject *module = PyType_GetModule(defining_class);
13773 self->stat = DirEntry_fetch_stat(module, self, 1);
13774 }
13775 else {
13776 self->stat = DirEntry_get_lstat(defining_class, self);
13777 }
13778 }
13779
13780 Py_XINCREF(self->stat);
13781 return self->stat;
13782 }
13783
13784 /* Set exception and return -1 on error, 0 for False, 1 for True */
13785 static int
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self, int follow_symlinks, unsigned short mode_bits)13786 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13787 int follow_symlinks, unsigned short mode_bits)
13788 {
13789 PyObject *stat = NULL;
13790 PyObject *st_mode = NULL;
13791 long mode;
13792 int result;
13793 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13794 int is_symlink;
13795 int need_stat;
13796 #endif
13797 #ifdef MS_WINDOWS
13798 unsigned long dir_bits;
13799 #endif
13800
13801 #ifdef MS_WINDOWS
13802 is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13803 need_stat = follow_symlinks && is_symlink;
13804 #elif defined(HAVE_DIRENT_D_TYPE)
13805 is_symlink = self->d_type == DT_LNK;
13806 need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
13807 #endif
13808
13809 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13810 if (need_stat) {
13811 #endif
13812 stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
13813 if (!stat) {
13814 if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
13815 /* If file doesn't exist (anymore), then return False
13816 (i.e., say it's not a file/directory) */
13817 PyErr_Clear();
13818 return 0;
13819 }
13820 goto error;
13821 }
13822 _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
13823 st_mode = PyObject_GetAttr(stat, state->st_mode);
13824 if (!st_mode)
13825 goto error;
13826
13827 mode = PyLong_AsLong(st_mode);
13828 if (mode == -1 && PyErr_Occurred())
13829 goto error;
13830 Py_CLEAR(st_mode);
13831 Py_CLEAR(stat);
13832 result = (mode & S_IFMT) == mode_bits;
13833 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13834 }
13835 else if (is_symlink) {
13836 assert(mode_bits != S_IFLNK);
13837 result = 0;
13838 }
13839 else {
13840 assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
13841 #ifdef MS_WINDOWS
13842 dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
13843 if (mode_bits == S_IFDIR)
13844 result = dir_bits != 0;
13845 else
13846 result = dir_bits == 0;
13847 #else /* POSIX */
13848 if (mode_bits == S_IFDIR)
13849 result = self->d_type == DT_DIR;
13850 else
13851 result = self->d_type == DT_REG;
13852 #endif
13853 }
13854 #endif
13855
13856 return result;
13857
13858 error:
13859 Py_XDECREF(st_mode);
13860 Py_XDECREF(stat);
13861 return -1;
13862 }
13863
13864 /*[clinic input]
13865 os.DirEntry.is_dir -> bool
13866 defining_class: defining_class
13867 /
13868 *
13869 follow_symlinks: bool = True
13870
13871 Return True if the entry is a directory; cached per entry.
13872 [clinic start generated code]*/
13873
13874 static int
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class, int follow_symlinks)13875 os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
13876 int follow_symlinks)
13877 /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
13878 {
13879 return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
13880 }
13881
13882 /*[clinic input]
13883 os.DirEntry.is_file -> bool
13884 defining_class: defining_class
13885 /
13886 *
13887 follow_symlinks: bool = True
13888
13889 Return True if the entry is a file; cached per entry.
13890 [clinic start generated code]*/
13891
13892 static int
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class, int follow_symlinks)13893 os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
13894 int follow_symlinks)
13895 /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
13896 {
13897 return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
13898 }
13899
13900 /*[clinic input]
13901 os.DirEntry.inode
13902
13903 Return inode of the entry; cached per entry.
13904 [clinic start generated code]*/
13905
13906 static PyObject *
os_DirEntry_inode_impl(DirEntry *self)13907 os_DirEntry_inode_impl(DirEntry *self)
13908 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
13909 {
13910 #ifdef MS_WINDOWS
13911 if (!self->got_file_index) {
13912 PyObject *unicode;
13913 STRUCT_STAT stat;
13914 int result;
13915
13916 if (!PyUnicode_FSDecoder(self->path, &unicode))
13917 return NULL;
13918 #if USE_UNICODE_WCHAR_CACHE
13919 _Py_COMP_DIAG_PUSH
13920 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13921 const wchar_t *path = PyUnicode_AsUnicode(unicode);
13922 result = LSTAT(path, &stat);
13923 Py_DECREF(unicode);
13924 _Py_COMP_DIAG_POP
13925 #else /* USE_UNICODE_WCHAR_CACHE */
13926 wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
13927 Py_DECREF(unicode);
13928 result = LSTAT(path, &stat);
13929 PyMem_Free(path);
13930 #endif /* USE_UNICODE_WCHAR_CACHE */
13931
13932 if (result != 0)
13933 return path_object_error(self->path);
13934
13935 self->win32_file_index = stat.st_ino;
13936 self->got_file_index = 1;
13937 }
13938 static_assert(sizeof(unsigned long long) >= sizeof(self->win32_file_index),
13939 "DirEntry.win32_file_index is larger than unsigned long long");
13940 return PyLong_FromUnsignedLongLong(self->win32_file_index);
13941 #else /* POSIX */
13942 static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
13943 "DirEntry.d_ino is larger than unsigned long long");
13944 return PyLong_FromUnsignedLongLong(self->d_ino);
13945 #endif
13946 }
13947
13948 static PyObject *
DirEntry_repr(DirEntry *self)13949 DirEntry_repr(DirEntry *self)
13950 {
13951 return PyUnicode_FromFormat("<DirEntry %R>", self->name);
13952 }
13953
13954 /*[clinic input]
13955 os.DirEntry.__fspath__
13956
13957 Returns the path for the entry.
13958 [clinic start generated code]*/
13959
13960 static PyObject *
os_DirEntry___fspath___impl(DirEntry *self)13961 os_DirEntry___fspath___impl(DirEntry *self)
13962 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
13963 {
13964 Py_INCREF(self->path);
13965 return self->path;
13966 }
13967
13968 static PyMemberDef DirEntry_members[] = {
13969 {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
13970 "the entry's base filename, relative to scandir() \"path\" argument"},
13971 {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
13972 "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
13973 {NULL}
13974 };
13975
13976 #include "clinic/posixmodule.c.h"
13977
13978 static PyMethodDef DirEntry_methods[] = {
13979 OS_DIRENTRY_IS_DIR_METHODDEF
13980 OS_DIRENTRY_IS_FILE_METHODDEF
13981 OS_DIRENTRY_IS_SYMLINK_METHODDEF
13982 OS_DIRENTRY_STAT_METHODDEF
13983 OS_DIRENTRY_INODE_METHODDEF
13984 OS_DIRENTRY___FSPATH___METHODDEF
13985 {"__class_getitem__", Py_GenericAlias,
13986 METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
13987 {NULL}
13988 };
13989
13990 static PyType_Slot DirEntryType_slots[] = {
13991 {Py_tp_dealloc, DirEntry_dealloc},
13992 {Py_tp_repr, DirEntry_repr},
13993 {Py_tp_methods, DirEntry_methods},
13994 {Py_tp_members, DirEntry_members},
13995 {0, 0},
13996 };
13997
13998 static PyType_Spec DirEntryType_spec = {
13999 MODNAME ".DirEntry",
14000 sizeof(DirEntry),
14001 0,
14002 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
14003 DirEntryType_slots
14004 };
14005
14006
14007 #ifdef MS_WINDOWS
14008
14009 static wchar_t *
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)14010 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
14011 {
14012 Py_ssize_t path_len;
14013 Py_ssize_t size;
14014 wchar_t *result;
14015 wchar_t ch;
14016
14017 if (!path_wide) { /* Default arg: "." */
14018 path_wide = L".";
14019 path_len = 1;
14020 }
14021 else {
14022 path_len = wcslen(path_wide);
14023 }
14024
14025 /* The +1's are for the path separator and the NUL */
14026 size = path_len + 1 + wcslen(filename) + 1;
14027 result = PyMem_New(wchar_t, size);
14028 if (!result) {
14029 PyErr_NoMemory();
14030 return NULL;
14031 }
14032 wcscpy(result, path_wide);
14033 if (path_len > 0) {
14034 ch = result[path_len - 1];
14035 if (ch != SEP && ch != ALTSEP && ch != L':')
14036 result[path_len++] = SEP;
14037 wcscpy(result + path_len, filename);
14038 }
14039 return result;
14040 }
14041
14042 static PyObject *
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)14043 DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
14044 {
14045 DirEntry *entry;
14046 BY_HANDLE_FILE_INFORMATION file_info;
14047 ULONG reparse_tag;
14048 wchar_t *joined_path;
14049
14050 PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
14051 entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
14052 if (!entry)
14053 return NULL;
14054 entry->name = NULL;
14055 entry->path = NULL;
14056 entry->stat = NULL;
14057 entry->lstat = NULL;
14058 entry->got_file_index = 0;
14059
14060 entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
14061 if (!entry->name)
14062 goto error;
14063 if (path->narrow) {
14064 Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
14065 if (!entry->name)
14066 goto error;
14067 }
14068
14069 joined_path = join_path_filenameW(path->wide, dataW->cFileName);
14070 if (!joined_path)
14071 goto error;
14072
14073 entry->path = PyUnicode_FromWideChar(joined_path, -1);
14074 PyMem_Free(joined_path);
14075 if (!entry->path)
14076 goto error;
14077 if (path->narrow) {
14078 Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
14079 if (!entry->path)
14080 goto error;
14081 }
14082
14083 find_data_to_file_info(dataW, &file_info, &reparse_tag);
14084 _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
14085
14086 return (PyObject *)entry;
14087
14088 error:
14089 Py_DECREF(entry);
14090 return NULL;
14091 }
14092
14093 #else /* POSIX */
14094
14095 static char *
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)14096 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
14097 {
14098 Py_ssize_t path_len;
14099 Py_ssize_t size;
14100 char *result;
14101
14102 if (!path_narrow) { /* Default arg: "." */
14103 path_narrow = ".";
14104 path_len = 1;
14105 }
14106 else {
14107 path_len = strlen(path_narrow);
14108 }
14109
14110 if (filename_len == -1)
14111 filename_len = strlen(filename);
14112
14113 /* The +1's are for the path separator and the NUL */
14114 size = path_len + 1 + filename_len + 1;
14115 result = PyMem_New(char, size);
14116 if (!result) {
14117 PyErr_NoMemory();
14118 return NULL;
14119 }
14120 strcpy(result, path_narrow);
14121 if (path_len > 0 && result[path_len - 1] != '/')
14122 result[path_len++] = '/';
14123 strcpy(result + path_len, filename);
14124 return result;
14125 }
14126
14127 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 )14128 DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
14129 Py_ssize_t name_len, ino_t d_ino
14130 #ifdef HAVE_DIRENT_D_TYPE
14131 , unsigned char d_type
14132 #endif
14133 )
14134 {
14135 DirEntry *entry;
14136 char *joined_path;
14137
14138 PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
14139 entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
14140 if (!entry)
14141 return NULL;
14142 entry->name = NULL;
14143 entry->path = NULL;
14144 entry->stat = NULL;
14145 entry->lstat = NULL;
14146
14147 if (path->fd != -1) {
14148 entry->dir_fd = path->fd;
14149 joined_path = NULL;
14150 }
14151 else {
14152 entry->dir_fd = DEFAULT_DIR_FD;
14153 joined_path = join_path_filename(path->narrow, name, name_len);
14154 if (!joined_path)
14155 goto error;
14156 }
14157
14158 if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
14159 entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
14160 if (joined_path)
14161 entry->path = PyUnicode_DecodeFSDefault(joined_path);
14162 }
14163 else {
14164 entry->name = PyBytes_FromStringAndSize(name, name_len);
14165 if (joined_path)
14166 entry->path = PyBytes_FromString(joined_path);
14167 }
14168 PyMem_Free(joined_path);
14169 if (!entry->name)
14170 goto error;
14171
14172 if (path->fd != -1) {
14173 entry->path = entry->name;
14174 Py_INCREF(entry->path);
14175 }
14176 else if (!entry->path)
14177 goto error;
14178
14179 #ifdef HAVE_DIRENT_D_TYPE
14180 entry->d_type = d_type;
14181 #endif
14182 entry->d_ino = d_ino;
14183
14184 return (PyObject *)entry;
14185
14186 error:
14187 Py_XDECREF(entry);
14188 return NULL;
14189 }
14190
14191 #endif
14192
14193
14194 typedef struct {
14195 PyObject_HEAD
14196 path_t path;
14197 #ifdef MS_WINDOWS
14198 HANDLE handle;
14199 WIN32_FIND_DATAW file_data;
14200 int first_time;
14201 #else /* POSIX */
14202 DIR *dirp;
14203 #endif
14204 #ifdef HAVE_FDOPENDIR
14205 int fd;
14206 #endif
14207 } ScandirIterator;
14208
14209 #ifdef MS_WINDOWS
14210
14211 static int
ScandirIterator_is_closed(ScandirIterator *iterator)14212 ScandirIterator_is_closed(ScandirIterator *iterator)
14213 {
14214 return iterator->handle == INVALID_HANDLE_VALUE;
14215 }
14216
14217 static void
ScandirIterator_closedir(ScandirIterator *iterator)14218 ScandirIterator_closedir(ScandirIterator *iterator)
14219 {
14220 HANDLE handle = iterator->handle;
14221
14222 if (handle == INVALID_HANDLE_VALUE)
14223 return;
14224
14225 iterator->handle = INVALID_HANDLE_VALUE;
14226 Py_BEGIN_ALLOW_THREADS
14227 FindClose(handle);
14228 Py_END_ALLOW_THREADS
14229 }
14230
14231 static PyObject *
ScandirIterator_iternext(ScandirIterator *iterator)14232 ScandirIterator_iternext(ScandirIterator *iterator)
14233 {
14234 WIN32_FIND_DATAW *file_data = &iterator->file_data;
14235 BOOL success;
14236 PyObject *entry;
14237
14238 /* Happens if the iterator is iterated twice, or closed explicitly */
14239 if (iterator->handle == INVALID_HANDLE_VALUE)
14240 return NULL;
14241
14242 while (1) {
14243 if (!iterator->first_time) {
14244 Py_BEGIN_ALLOW_THREADS
14245 success = FindNextFileW(iterator->handle, file_data);
14246 Py_END_ALLOW_THREADS
14247 if (!success) {
14248 /* Error or no more files */
14249 if (GetLastError() != ERROR_NO_MORE_FILES)
14250 path_error(&iterator->path);
14251 break;
14252 }
14253 }
14254 iterator->first_time = 0;
14255
14256 /* Skip over . and .. */
14257 if (wcscmp(file_data->cFileName, L".") != 0 &&
14258 wcscmp(file_data->cFileName, L"..") != 0)
14259 {
14260 PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14261 entry = DirEntry_from_find_data(module, &iterator->path, file_data);
14262 if (!entry)
14263 break;
14264 return entry;
14265 }
14266
14267 /* Loop till we get a non-dot directory or finish iterating */
14268 }
14269
14270 /* Error or no more files */
14271 ScandirIterator_closedir(iterator);
14272 return NULL;
14273 }
14274
14275 #else /* POSIX */
14276
14277 static int
ScandirIterator_is_closed(ScandirIterator *iterator)14278 ScandirIterator_is_closed(ScandirIterator *iterator)
14279 {
14280 return !iterator->dirp;
14281 }
14282
14283 static void
ScandirIterator_closedir(ScandirIterator *iterator)14284 ScandirIterator_closedir(ScandirIterator *iterator)
14285 {
14286 DIR *dirp = iterator->dirp;
14287
14288 if (!dirp)
14289 return;
14290
14291 iterator->dirp = NULL;
14292 Py_BEGIN_ALLOW_THREADS
14293 #ifdef HAVE_FDOPENDIR
14294 if (iterator->path.fd != -1)
14295 rewinddir(dirp);
14296 #endif
14297 closedir(dirp);
14298 Py_END_ALLOW_THREADS
14299 return;
14300 }
14301
14302 static PyObject *
ScandirIterator_iternext(ScandirIterator *iterator)14303 ScandirIterator_iternext(ScandirIterator *iterator)
14304 {
14305 struct dirent *direntp;
14306 Py_ssize_t name_len;
14307 int is_dot;
14308 PyObject *entry;
14309
14310 /* Happens if the iterator is iterated twice, or closed explicitly */
14311 if (!iterator->dirp)
14312 return NULL;
14313
14314 while (1) {
14315 errno = 0;
14316 Py_BEGIN_ALLOW_THREADS
14317 direntp = readdir(iterator->dirp);
14318 Py_END_ALLOW_THREADS
14319
14320 if (!direntp) {
14321 /* Error or no more files */
14322 if (errno != 0)
14323 path_error(&iterator->path);
14324 break;
14325 }
14326
14327 /* Skip over . and .. */
14328 name_len = NAMLEN(direntp);
14329 is_dot = direntp->d_name[0] == '.' &&
14330 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
14331 if (!is_dot) {
14332 PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14333 entry = DirEntry_from_posix_info(module,
14334 &iterator->path, direntp->d_name,
14335 name_len, direntp->d_ino
14336 #ifdef HAVE_DIRENT_D_TYPE
14337 , direntp->d_type
14338 #endif
14339 );
14340 if (!entry)
14341 break;
14342 return entry;
14343 }
14344
14345 /* Loop till we get a non-dot directory or finish iterating */
14346 }
14347
14348 /* Error or no more files */
14349 ScandirIterator_closedir(iterator);
14350 return NULL;
14351 }
14352
14353 #endif
14354
14355 static PyObject *
ScandirIterator_close(ScandirIterator *self, PyObject *args)14356 ScandirIterator_close(ScandirIterator *self, PyObject *args)
14357 {
14358 ScandirIterator_closedir(self);
14359 Py_RETURN_NONE;
14360 }
14361
14362 static PyObject *
ScandirIterator_enter(PyObject *self, PyObject *args)14363 ScandirIterator_enter(PyObject *self, PyObject *args)
14364 {
14365 Py_INCREF(self);
14366 return self;
14367 }
14368
14369 static PyObject *
ScandirIterator_exit(ScandirIterator *self, PyObject *args)14370 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
14371 {
14372 ScandirIterator_closedir(self);
14373 Py_RETURN_NONE;
14374 }
14375
14376 static void
ScandirIterator_finalize(ScandirIterator *iterator)14377 ScandirIterator_finalize(ScandirIterator *iterator)
14378 {
14379 PyObject *error_type, *error_value, *error_traceback;
14380
14381 /* Save the current exception, if any. */
14382 PyErr_Fetch(&error_type, &error_value, &error_traceback);
14383
14384 if (!ScandirIterator_is_closed(iterator)) {
14385 ScandirIterator_closedir(iterator);
14386
14387 if (PyErr_ResourceWarning((PyObject *)iterator, 1,
14388 "unclosed scandir iterator %R", iterator)) {
14389 /* Spurious errors can appear at shutdown */
14390 if (PyErr_ExceptionMatches(PyExc_Warning)) {
14391 PyErr_WriteUnraisable((PyObject *) iterator);
14392 }
14393 }
14394 }
14395
14396 path_cleanup(&iterator->path);
14397
14398 /* Restore the saved exception. */
14399 PyErr_Restore(error_type, error_value, error_traceback);
14400 }
14401
14402 static void
ScandirIterator_dealloc(ScandirIterator *iterator)14403 ScandirIterator_dealloc(ScandirIterator *iterator)
14404 {
14405 PyTypeObject *tp = Py_TYPE(iterator);
14406 if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
14407 return;
14408
14409 freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
14410 free_func(iterator);
14411 Py_DECREF(tp);
14412 }
14413
14414 static PyMethodDef ScandirIterator_methods[] = {
14415 {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
14416 {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
14417 {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
14418 {NULL}
14419 };
14420
14421 static PyType_Slot ScandirIteratorType_slots[] = {
14422 {Py_tp_dealloc, ScandirIterator_dealloc},
14423 {Py_tp_finalize, ScandirIterator_finalize},
14424 {Py_tp_iter, PyObject_SelfIter},
14425 {Py_tp_iternext, ScandirIterator_iternext},
14426 {Py_tp_methods, ScandirIterator_methods},
14427 {0, 0},
14428 };
14429
14430 static PyType_Spec ScandirIteratorType_spec = {
14431 MODNAME ".ScandirIterator",
14432 sizeof(ScandirIterator),
14433 0,
14434 // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
14435 // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
14436 (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
14437 | Py_TPFLAGS_DISALLOW_INSTANTIATION),
14438 ScandirIteratorType_slots
14439 };
14440
14441 /*[clinic input]
14442 os.scandir
14443
14444 path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
14445
14446 Return an iterator of DirEntry objects for given path.
14447
14448 path can be specified as either str, bytes, or a path-like object. If path
14449 is bytes, the names of yielded DirEntry objects will also be bytes; in
14450 all other circumstances they will be str.
14451
14452 If path is None, uses the path='.'.
14453 [clinic start generated code]*/
14454
14455 static PyObject *
os_scandir_impl(PyObject *module, path_t *path)14456 os_scandir_impl(PyObject *module, path_t *path)
14457 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
14458 {
14459 ScandirIterator *iterator;
14460 #ifdef MS_WINDOWS
14461 wchar_t *path_strW;
14462 #else
14463 const char *path_str;
14464 #ifdef HAVE_FDOPENDIR
14465 int fd = -1;
14466 #endif
14467 #endif
14468
14469 if (PySys_Audit("os.scandir", "O",
14470 path->object ? path->object : Py_None) < 0) {
14471 return NULL;
14472 }
14473
14474 PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
14475 iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
14476 if (!iterator)
14477 return NULL;
14478
14479 #ifdef MS_WINDOWS
14480 iterator->handle = INVALID_HANDLE_VALUE;
14481 #else
14482 iterator->dirp = NULL;
14483 #endif
14484
14485 /* Move the ownership to iterator->path */
14486 memcpy(&iterator->path, path, sizeof(path_t));
14487 memset(path, 0, sizeof(path_t));
14488
14489 #ifdef MS_WINDOWS
14490 iterator->first_time = 1;
14491
14492 path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
14493 if (!path_strW)
14494 goto error;
14495
14496 Py_BEGIN_ALLOW_THREADS
14497 iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
14498 Py_END_ALLOW_THREADS
14499
14500 PyMem_Free(path_strW);
14501
14502 if (iterator->handle == INVALID_HANDLE_VALUE) {
14503 path_error(&iterator->path);
14504 goto error;
14505 }
14506 #else /* POSIX */
14507 errno = 0;
14508 #ifdef HAVE_FDOPENDIR
14509 if (iterator->path.fd != -1) {
14510 if (HAVE_FDOPENDIR_RUNTIME) {
14511 /* closedir() closes the FD, so we duplicate it */
14512 fd = _Py_dup(iterator->path.fd);
14513 if (fd == -1)
14514 goto error;
14515
14516 Py_BEGIN_ALLOW_THREADS
14517 iterator->dirp = fdopendir(fd);
14518 Py_END_ALLOW_THREADS
14519 } else {
14520 PyErr_SetString(PyExc_TypeError,
14521 "scandir: path should be string, bytes, os.PathLike or None, not int");
14522 return NULL;
14523 }
14524 }
14525 else
14526 #endif
14527 {
14528 if (iterator->path.narrow)
14529 path_str = iterator->path.narrow;
14530 else
14531 path_str = ".";
14532
14533 Py_BEGIN_ALLOW_THREADS
14534 iterator->dirp = opendir(path_str);
14535 Py_END_ALLOW_THREADS
14536 }
14537
14538 if (!iterator->dirp) {
14539 path_error(&iterator->path);
14540 #ifdef HAVE_FDOPENDIR
14541 if (fd != -1) {
14542 Py_BEGIN_ALLOW_THREADS
14543 close(fd);
14544 Py_END_ALLOW_THREADS
14545 }
14546 #endif
14547 goto error;
14548 }
14549 #endif
14550
14551 return (PyObject *)iterator;
14552
14553 error:
14554 Py_DECREF(iterator);
14555 return NULL;
14556 }
14557
14558 /*
14559 Return the file system path representation of the object.
14560
14561 If the object is str or bytes, then allow it to pass through with
14562 an incremented refcount. If the object defines __fspath__(), then
14563 return the result of that method. All other types raise a TypeError.
14564 */
14565 PyObject *
PyOS_FSPath(PyObject *path)14566 PyOS_FSPath(PyObject *path)
14567 {
14568 /* For error message reasons, this function is manually inlined in
14569 path_converter(). */
14570 PyObject *func = NULL;
14571 PyObject *path_repr = NULL;
14572
14573 if (PyUnicode_Check(path) || PyBytes_Check(path)) {
14574 Py_INCREF(path);
14575 return path;
14576 }
14577
14578 func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
14579 if (NULL == func) {
14580 return PyErr_Format(PyExc_TypeError,
14581 "expected str, bytes or os.PathLike object, "
14582 "not %.200s",
14583 _PyType_Name(Py_TYPE(path)));
14584 }
14585
14586 path_repr = _PyObject_CallNoArgs(func);
14587 Py_DECREF(func);
14588 if (NULL == path_repr) {
14589 return NULL;
14590 }
14591
14592 if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
14593 PyErr_Format(PyExc_TypeError,
14594 "expected %.200s.__fspath__() to return str or bytes, "
14595 "not %.200s", _PyType_Name(Py_TYPE(path)),
14596 _PyType_Name(Py_TYPE(path_repr)));
14597 Py_DECREF(path_repr);
14598 return NULL;
14599 }
14600
14601 return path_repr;
14602 }
14603
14604 /*[clinic input]
14605 os.fspath
14606
14607 path: object
14608
14609 Return the file system path representation of the object.
14610
14611 If the object is str or bytes, then allow it to pass through as-is. If the
14612 object defines __fspath__(), then return the result of that method. All other
14613 types raise a TypeError.
14614 [clinic start generated code]*/
14615
14616 static PyObject *
os_fspath_impl(PyObject *module, PyObject *path)14617 os_fspath_impl(PyObject *module, PyObject *path)
14618 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
14619 {
14620 return PyOS_FSPath(path);
14621 }
14622
14623 #ifdef HAVE_GETRANDOM_SYSCALL
14624 /*[clinic input]
14625 os.getrandom
14626
14627 size: Py_ssize_t
14628 flags: int=0
14629
14630 Obtain a series of random bytes.
14631 [clinic start generated code]*/
14632
14633 static PyObject *
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)14634 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
14635 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
14636 {
14637 PyObject *bytes;
14638 Py_ssize_t n;
14639
14640 if (size < 0) {
14641 errno = EINVAL;
14642 return posix_error();
14643 }
14644
14645 bytes = PyBytes_FromStringAndSize(NULL, size);
14646 if (bytes == NULL) {
14647 PyErr_NoMemory();
14648 return NULL;
14649 }
14650
14651 while (1) {
14652 n = syscall(SYS_getrandom,
14653 PyBytes_AS_STRING(bytes),
14654 PyBytes_GET_SIZE(bytes),
14655 flags);
14656 if (n < 0 && errno == EINTR) {
14657 if (PyErr_CheckSignals() < 0) {
14658 goto error;
14659 }
14660
14661 /* getrandom() was interrupted by a signal: retry */
14662 continue;
14663 }
14664 break;
14665 }
14666
14667 if (n < 0) {
14668 PyErr_SetFromErrno(PyExc_OSError);
14669 goto error;
14670 }
14671
14672 if (n != size) {
14673 _PyBytes_Resize(&bytes, n);
14674 }
14675
14676 return bytes;
14677
14678 error:
14679 Py_DECREF(bytes);
14680 return NULL;
14681 }
14682 #endif /* HAVE_GETRANDOM_SYSCALL */
14683
14684 #ifdef MS_WINDOWS
14685 /* bpo-36085: Helper functions for managing DLL search directories
14686 * on win32
14687 */
14688
14689 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
14690 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
14691
14692 /*[clinic input]
14693 os._add_dll_directory
14694
14695 path: path_t
14696
14697 Add a path to the DLL search path.
14698
14699 This search path is used when resolving dependencies for imported
14700 extension modules (the module itself is resolved through sys.path),
14701 and also by ctypes.
14702
14703 Returns an opaque value that may be passed to os.remove_dll_directory
14704 to remove this directory from the search path.
14705 [clinic start generated code]*/
14706
14707 static PyObject *
os__add_dll_directory_impl(PyObject *module, path_t *path)14708 os__add_dll_directory_impl(PyObject *module, path_t *path)
14709 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
14710 {
14711 HMODULE hKernel32;
14712 PAddDllDirectory AddDllDirectory;
14713 DLL_DIRECTORY_COOKIE cookie = 0;
14714 DWORD err = 0;
14715
14716 if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
14717 return NULL;
14718 }
14719
14720 /* For Windows 7, we have to load this. As this will be a fairly
14721 infrequent operation, just do it each time. Kernel32 is always
14722 loaded. */
14723 Py_BEGIN_ALLOW_THREADS
14724 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14725 !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
14726 hKernel32, "AddDllDirectory")) ||
14727 !(cookie = (*AddDllDirectory)(path->wide))) {
14728 err = GetLastError();
14729 }
14730 Py_END_ALLOW_THREADS
14731
14732 if (err) {
14733 return win32_error_object_err("add_dll_directory",
14734 path->object, err);
14735 }
14736
14737 return PyCapsule_New(cookie, "DLL directory cookie", NULL);
14738 }
14739
14740 /*[clinic input]
14741 os._remove_dll_directory
14742
14743 cookie: object
14744
14745 Removes a path from the DLL search path.
14746
14747 The parameter is an opaque value that was returned from
14748 os.add_dll_directory. You can only remove directories that you added
14749 yourself.
14750 [clinic start generated code]*/
14751
14752 static PyObject *
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)14753 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
14754 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
14755 {
14756 HMODULE hKernel32;
14757 PRemoveDllDirectory RemoveDllDirectory;
14758 DLL_DIRECTORY_COOKIE cookieValue;
14759 DWORD err = 0;
14760
14761 if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
14762 PyErr_SetString(PyExc_TypeError,
14763 "Provided cookie was not returned from os.add_dll_directory");
14764 return NULL;
14765 }
14766
14767 cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
14768 cookie, "DLL directory cookie");
14769
14770 /* For Windows 7, we have to load this. As this will be a fairly
14771 infrequent operation, just do it each time. Kernel32 is always
14772 loaded. */
14773 Py_BEGIN_ALLOW_THREADS
14774 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14775 !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
14776 hKernel32, "RemoveDllDirectory")) ||
14777 !(*RemoveDllDirectory)(cookieValue)) {
14778 err = GetLastError();
14779 }
14780 Py_END_ALLOW_THREADS
14781
14782 if (err) {
14783 return win32_error_object_err("remove_dll_directory",
14784 NULL, err);
14785 }
14786
14787 if (PyCapsule_SetName(cookie, NULL)) {
14788 return NULL;
14789 }
14790
14791 Py_RETURN_NONE;
14792 }
14793
14794 #endif
14795
14796
14797 /* Only check if WIFEXITED is available: expect that it comes
14798 with WEXITSTATUS, WIFSIGNALED, etc.
14799
14800 os.waitstatus_to_exitcode() is implemented in C and not in Python, so
14801 subprocess can safely call it during late Python finalization without
14802 risking that used os attributes were set to None by finalize_modules(). */
14803 #if defined(WIFEXITED) || defined(MS_WINDOWS)
14804 /*[clinic input]
14805 os.waitstatus_to_exitcode
14806
14807 status as status_obj: object
14808
14809 Convert a wait status to an exit code.
14810
14811 On Unix:
14812
14813 * If WIFEXITED(status) is true, return WEXITSTATUS(status).
14814 * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
14815 * Otherwise, raise a ValueError.
14816
14817 On Windows, return status shifted right by 8 bits.
14818
14819 On Unix, if the process is being traced or if waitpid() was called with
14820 WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
14821 This function must not be called if WIFSTOPPED(status) is true.
14822 [clinic start generated code]*/
14823
14824 static PyObject *
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)14825 os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
14826 /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
14827 {
14828 #ifndef MS_WINDOWS
14829 int status = _PyLong_AsInt(status_obj);
14830 if (status == -1 && PyErr_Occurred()) {
14831 return NULL;
14832 }
14833
14834 WAIT_TYPE wait_status;
14835 WAIT_STATUS_INT(wait_status) = status;
14836 int exitcode;
14837 if (WIFEXITED(wait_status)) {
14838 exitcode = WEXITSTATUS(wait_status);
14839 /* Sanity check to provide warranty on the function behavior.
14840 It should not occur in practice */
14841 if (exitcode < 0) {
14842 PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
14843 return NULL;
14844 }
14845 }
14846 else if (WIFSIGNALED(wait_status)) {
14847 int signum = WTERMSIG(wait_status);
14848 /* Sanity check to provide warranty on the function behavior.
14849 It should not occurs in practice */
14850 if (signum <= 0) {
14851 PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
14852 return NULL;
14853 }
14854 exitcode = -signum;
14855 } else if (WIFSTOPPED(wait_status)) {
14856 /* Status only received if the process is being traced
14857 or if waitpid() was called with WUNTRACED option. */
14858 int signum = WSTOPSIG(wait_status);
14859 PyErr_Format(PyExc_ValueError,
14860 "process stopped by delivery of signal %i",
14861 signum);
14862 return NULL;
14863 }
14864 else {
14865 PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
14866 return NULL;
14867 }
14868 return PyLong_FromLong(exitcode);
14869 #else
14870 /* Windows implementation: see os.waitpid() implementation
14871 which uses _cwait(). */
14872 unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
14873 if (status == (unsigned long long)-1 && PyErr_Occurred()) {
14874 return NULL;
14875 }
14876
14877 unsigned long long exitcode = (status >> 8);
14878 /* ExitProcess() accepts an UINT type:
14879 reject exit code which doesn't fit in an UINT */
14880 if (exitcode > UINT_MAX) {
14881 PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
14882 return NULL;
14883 }
14884 return PyLong_FromUnsignedLong((unsigned long)exitcode);
14885 #endif
14886 }
14887 #endif
14888
14889
14890 static PyMethodDef posix_methods[] = {
14891
14892 OS_STAT_METHODDEF
14893 OS_ACCESS_METHODDEF
14894 OS_TTYNAME_METHODDEF
14895 OS_CHDIR_METHODDEF
14896 OS_CHFLAGS_METHODDEF
14897 OS_CHMOD_METHODDEF
14898 OS_FCHMOD_METHODDEF
14899 OS_LCHMOD_METHODDEF
14900 OS_CHOWN_METHODDEF
14901 OS_FCHOWN_METHODDEF
14902 OS_LCHOWN_METHODDEF
14903 OS_LCHFLAGS_METHODDEF
14904 OS_CHROOT_METHODDEF
14905 OS_CTERMID_METHODDEF
14906 OS_GETCWD_METHODDEF
14907 OS_GETCWDB_METHODDEF
14908 OS_LINK_METHODDEF
14909 OS_LISTDIR_METHODDEF
14910 OS_LSTAT_METHODDEF
14911 OS_MKDIR_METHODDEF
14912 OS_NICE_METHODDEF
14913 OS_GETPRIORITY_METHODDEF
14914 OS_SETPRIORITY_METHODDEF
14915 OS_POSIX_SPAWN_METHODDEF
14916 OS_POSIX_SPAWNP_METHODDEF
14917 OS_READLINK_METHODDEF
14918 OS_COPY_FILE_RANGE_METHODDEF
14919 OS_SPLICE_METHODDEF
14920 OS_RENAME_METHODDEF
14921 OS_REPLACE_METHODDEF
14922 OS_RMDIR_METHODDEF
14923 OS_SYMLINK_METHODDEF
14924 OS_SYSTEM_METHODDEF
14925 OS_UMASK_METHODDEF
14926 OS_UNAME_METHODDEF
14927 OS_UNLINK_METHODDEF
14928 OS_REMOVE_METHODDEF
14929 OS_UTIME_METHODDEF
14930 OS_TIMES_METHODDEF
14931 OS__EXIT_METHODDEF
14932 OS__FCOPYFILE_METHODDEF
14933 OS_EXECV_METHODDEF
14934 OS_EXECVE_METHODDEF
14935 OS_SPAWNV_METHODDEF
14936 OS_SPAWNVE_METHODDEF
14937 OS_FORK1_METHODDEF
14938 OS_FORK_METHODDEF
14939 OS_REGISTER_AT_FORK_METHODDEF
14940 OS_SCHED_GET_PRIORITY_MAX_METHODDEF
14941 OS_SCHED_GET_PRIORITY_MIN_METHODDEF
14942 OS_SCHED_GETPARAM_METHODDEF
14943 OS_SCHED_GETSCHEDULER_METHODDEF
14944 OS_SCHED_RR_GET_INTERVAL_METHODDEF
14945 OS_SCHED_SETPARAM_METHODDEF
14946 OS_SCHED_SETSCHEDULER_METHODDEF
14947 OS_SCHED_YIELD_METHODDEF
14948 OS_SCHED_SETAFFINITY_METHODDEF
14949 OS_SCHED_GETAFFINITY_METHODDEF
14950 OS_OPENPTY_METHODDEF
14951 OS_LOGIN_TTY_METHODDEF
14952 OS_FORKPTY_METHODDEF
14953 OS_GETEGID_METHODDEF
14954 OS_GETEUID_METHODDEF
14955 OS_GETGID_METHODDEF
14956 OS_GETGROUPLIST_METHODDEF
14957 OS_GETGROUPS_METHODDEF
14958 OS_GETPID_METHODDEF
14959 OS_GETPGRP_METHODDEF
14960 OS_GETPPID_METHODDEF
14961 OS_GETUID_METHODDEF
14962 OS_GETLOGIN_METHODDEF
14963 OS_KILL_METHODDEF
14964 OS_KILLPG_METHODDEF
14965 OS_PLOCK_METHODDEF
14966 OS_STARTFILE_METHODDEF
14967 OS_SETUID_METHODDEF
14968 OS_SETEUID_METHODDEF
14969 OS_SETREUID_METHODDEF
14970 OS_SETGID_METHODDEF
14971 OS_SETEGID_METHODDEF
14972 OS_SETREGID_METHODDEF
14973 OS_SETGROUPS_METHODDEF
14974 OS_INITGROUPS_METHODDEF
14975 OS_GETPGID_METHODDEF
14976 OS_SETPGRP_METHODDEF
14977 OS_WAIT_METHODDEF
14978 OS_WAIT3_METHODDEF
14979 OS_WAIT4_METHODDEF
14980 OS_WAITID_METHODDEF
14981 OS_WAITPID_METHODDEF
14982 OS_PIDFD_OPEN_METHODDEF
14983 OS_GETSID_METHODDEF
14984 OS_SETSID_METHODDEF
14985 OS_SETPGID_METHODDEF
14986 OS_TCGETPGRP_METHODDEF
14987 OS_TCSETPGRP_METHODDEF
14988 OS_OPEN_METHODDEF
14989 OS_CLOSE_METHODDEF
14990 OS_CLOSERANGE_METHODDEF
14991 OS_DEVICE_ENCODING_METHODDEF
14992 OS_DUP_METHODDEF
14993 OS_DUP2_METHODDEF
14994 OS_LOCKF_METHODDEF
14995 OS_LSEEK_METHODDEF
14996 OS_READ_METHODDEF
14997 OS_READV_METHODDEF
14998 OS_PREAD_METHODDEF
14999 OS_PREADV_METHODDEF
15000 OS_WRITE_METHODDEF
15001 OS_WRITEV_METHODDEF
15002 OS_PWRITE_METHODDEF
15003 OS_PWRITEV_METHODDEF
15004 OS_SENDFILE_METHODDEF
15005 OS_FSTAT_METHODDEF
15006 OS_ISATTY_METHODDEF
15007 OS_PIPE_METHODDEF
15008 OS_PIPE2_METHODDEF
15009 OS_MKFIFO_METHODDEF
15010 OS_MKNOD_METHODDEF
15011 OS_MAJOR_METHODDEF
15012 OS_MINOR_METHODDEF
15013 OS_MAKEDEV_METHODDEF
15014 OS_FTRUNCATE_METHODDEF
15015 OS_TRUNCATE_METHODDEF
15016 OS_POSIX_FALLOCATE_METHODDEF
15017 OS_POSIX_FADVISE_METHODDEF
15018 OS_PUTENV_METHODDEF
15019 OS_UNSETENV_METHODDEF
15020 OS_STRERROR_METHODDEF
15021 OS_FCHDIR_METHODDEF
15022 OS_FSYNC_METHODDEF
15023 OS_SYNC_METHODDEF
15024 OS_FDATASYNC_METHODDEF
15025 OS_WCOREDUMP_METHODDEF
15026 OS_WIFCONTINUED_METHODDEF
15027 OS_WIFSTOPPED_METHODDEF
15028 OS_WIFSIGNALED_METHODDEF
15029 OS_WIFEXITED_METHODDEF
15030 OS_WEXITSTATUS_METHODDEF
15031 OS_WTERMSIG_METHODDEF
15032 OS_WSTOPSIG_METHODDEF
15033 OS_FSTATVFS_METHODDEF
15034 OS_STATVFS_METHODDEF
15035 OS_CONFSTR_METHODDEF
15036 OS_SYSCONF_METHODDEF
15037 OS_FPATHCONF_METHODDEF
15038 OS_PATHCONF_METHODDEF
15039 OS_ABORT_METHODDEF
15040 OS__GETFULLPATHNAME_METHODDEF
15041 OS__GETDISKUSAGE_METHODDEF
15042 OS__GETFINALPATHNAME_METHODDEF
15043 OS__GETVOLUMEPATHNAME_METHODDEF
15044 OS__PATH_SPLITROOT_METHODDEF
15045 OS__PATH_NORMPATH_METHODDEF
15046 OS_GETLOADAVG_METHODDEF
15047 OS_URANDOM_METHODDEF
15048 OS_SETRESUID_METHODDEF
15049 OS_SETRESGID_METHODDEF
15050 OS_GETRESUID_METHODDEF
15051 OS_GETRESGID_METHODDEF
15052
15053 OS_GETXATTR_METHODDEF
15054 OS_SETXATTR_METHODDEF
15055 OS_REMOVEXATTR_METHODDEF
15056 OS_LISTXATTR_METHODDEF
15057
15058 OS_GET_TERMINAL_SIZE_METHODDEF
15059 OS_CPU_COUNT_METHODDEF
15060 OS_GET_INHERITABLE_METHODDEF
15061 OS_SET_INHERITABLE_METHODDEF
15062 OS_GET_HANDLE_INHERITABLE_METHODDEF
15063 OS_SET_HANDLE_INHERITABLE_METHODDEF
15064 OS_GET_BLOCKING_METHODDEF
15065 OS_SET_BLOCKING_METHODDEF
15066 OS_SCANDIR_METHODDEF
15067 OS_FSPATH_METHODDEF
15068 OS_GETRANDOM_METHODDEF
15069 OS_MEMFD_CREATE_METHODDEF
15070 OS_EVENTFD_METHODDEF
15071 OS_EVENTFD_READ_METHODDEF
15072 OS_EVENTFD_WRITE_METHODDEF
15073 OS__ADD_DLL_DIRECTORY_METHODDEF
15074 OS__REMOVE_DLL_DIRECTORY_METHODDEF
15075 OS_WAITSTATUS_TO_EXITCODE_METHODDEF
15076 {NULL, NULL} /* Sentinel */
15077 };
15078
15079 static int
all_ins(PyObject *m)15080 all_ins(PyObject *m)
15081 {
15082 #ifdef F_OK
15083 if (PyModule_AddIntMacro(m, F_OK)) return -1;
15084 #endif
15085 #ifdef R_OK
15086 if (PyModule_AddIntMacro(m, R_OK)) return -1;
15087 #endif
15088 #ifdef W_OK
15089 if (PyModule_AddIntMacro(m, W_OK)) return -1;
15090 #endif
15091 #ifdef X_OK
15092 if (PyModule_AddIntMacro(m, X_OK)) return -1;
15093 #endif
15094 #ifdef NGROUPS_MAX
15095 if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
15096 #endif
15097 #ifdef TMP_MAX
15098 if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
15099 #endif
15100 #ifdef WCONTINUED
15101 if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
15102 #endif
15103 #ifdef WNOHANG
15104 if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
15105 #endif
15106 #ifdef WUNTRACED
15107 if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
15108 #endif
15109 #ifdef O_RDONLY
15110 if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
15111 #endif
15112 #ifdef O_WRONLY
15113 if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
15114 #endif
15115 #ifdef O_RDWR
15116 if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
15117 #endif
15118 #ifdef O_NDELAY
15119 if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
15120 #endif
15121 #ifdef O_NONBLOCK
15122 if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
15123 #endif
15124 #ifdef O_APPEND
15125 if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
15126 #endif
15127 #ifdef O_DSYNC
15128 if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
15129 #endif
15130 #ifdef O_RSYNC
15131 if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
15132 #endif
15133 #ifdef O_SYNC
15134 if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
15135 #endif
15136 #ifdef O_NOCTTY
15137 if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
15138 #endif
15139 #ifdef O_CREAT
15140 if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
15141 #endif
15142 #ifdef O_EXCL
15143 if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
15144 #endif
15145 #ifdef O_TRUNC
15146 if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
15147 #endif
15148 #ifdef O_BINARY
15149 if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
15150 #endif
15151 #ifdef O_TEXT
15152 if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
15153 #endif
15154 #ifdef O_XATTR
15155 if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
15156 #endif
15157 #ifdef O_LARGEFILE
15158 if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
15159 #endif
15160 #ifndef __GNU__
15161 #ifdef O_SHLOCK
15162 if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
15163 #endif
15164 #ifdef O_EXLOCK
15165 if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
15166 #endif
15167 #endif
15168 #ifdef O_EXEC
15169 if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
15170 #endif
15171 #ifdef O_SEARCH
15172 if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
15173 #endif
15174 #ifdef O_PATH
15175 if (PyModule_AddIntMacro(m, O_PATH)) return -1;
15176 #endif
15177 #ifdef O_TTY_INIT
15178 if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
15179 #endif
15180 #ifdef O_TMPFILE
15181 if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
15182 #endif
15183 #ifdef PRIO_PROCESS
15184 if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
15185 #endif
15186 #ifdef PRIO_PGRP
15187 if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
15188 #endif
15189 #ifdef PRIO_USER
15190 if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
15191 #endif
15192 #ifdef O_CLOEXEC
15193 if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
15194 #endif
15195 #ifdef O_ACCMODE
15196 if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
15197 #endif
15198 #ifdef O_EVTONLY
15199 if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
15200 #endif
15201 #ifdef O_FSYNC
15202 if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
15203 #endif
15204 #ifdef O_SYMLINK
15205 if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
15206 #endif
15207
15208 #ifdef SEEK_HOLE
15209 if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
15210 #endif
15211 #ifdef SEEK_DATA
15212 if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
15213 #endif
15214
15215 /* MS Windows */
15216 #ifdef O_NOINHERIT
15217 /* Don't inherit in child processes. */
15218 if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
15219 #endif
15220 #ifdef _O_SHORT_LIVED
15221 /* Optimize for short life (keep in memory). */
15222 /* MS forgot to define this one with a non-underscore form too. */
15223 if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
15224 #endif
15225 #ifdef O_TEMPORARY
15226 /* Automatically delete when last handle is closed. */
15227 if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
15228 #endif
15229 #ifdef O_RANDOM
15230 /* Optimize for random access. */
15231 if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
15232 #endif
15233 #ifdef O_SEQUENTIAL
15234 /* Optimize for sequential access. */
15235 if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
15236 #endif
15237
15238 /* GNU extensions. */
15239 #ifdef O_ASYNC
15240 /* Send a SIGIO signal whenever input or output
15241 becomes available on file descriptor */
15242 if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
15243 #endif
15244 #ifdef O_DIRECT
15245 /* Direct disk access. */
15246 if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
15247 #endif
15248 #ifdef O_DIRECTORY
15249 /* Must be a directory. */
15250 if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
15251 #endif
15252 #ifdef O_NOFOLLOW
15253 /* Do not follow links. */
15254 if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
15255 #endif
15256 #ifdef O_NOFOLLOW_ANY
15257 if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
15258 #endif
15259 #ifdef O_NOLINKS
15260 /* Fails if link count of the named file is greater than 1 */
15261 if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
15262 #endif
15263 #ifdef O_NOATIME
15264 /* Do not update the access time. */
15265 if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
15266 #endif
15267
15268 /* These come from sysexits.h */
15269 #ifdef EX_OK
15270 if (PyModule_AddIntMacro(m, EX_OK)) return -1;
15271 #endif /* EX_OK */
15272 #ifdef EX_USAGE
15273 if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
15274 #endif /* EX_USAGE */
15275 #ifdef EX_DATAERR
15276 if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
15277 #endif /* EX_DATAERR */
15278 #ifdef EX_NOINPUT
15279 if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
15280 #endif /* EX_NOINPUT */
15281 #ifdef EX_NOUSER
15282 if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
15283 #endif /* EX_NOUSER */
15284 #ifdef EX_NOHOST
15285 if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
15286 #endif /* EX_NOHOST */
15287 #ifdef EX_UNAVAILABLE
15288 if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
15289 #endif /* EX_UNAVAILABLE */
15290 #ifdef EX_SOFTWARE
15291 if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
15292 #endif /* EX_SOFTWARE */
15293 #ifdef EX_OSERR
15294 if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
15295 #endif /* EX_OSERR */
15296 #ifdef EX_OSFILE
15297 if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
15298 #endif /* EX_OSFILE */
15299 #ifdef EX_CANTCREAT
15300 if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
15301 #endif /* EX_CANTCREAT */
15302 #ifdef EX_IOERR
15303 if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
15304 #endif /* EX_IOERR */
15305 #ifdef EX_TEMPFAIL
15306 if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
15307 #endif /* EX_TEMPFAIL */
15308 #ifdef EX_PROTOCOL
15309 if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
15310 #endif /* EX_PROTOCOL */
15311 #ifdef EX_NOPERM
15312 if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
15313 #endif /* EX_NOPERM */
15314 #ifdef EX_CONFIG
15315 if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
15316 #endif /* EX_CONFIG */
15317 #ifdef EX_NOTFOUND
15318 if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
15319 #endif /* EX_NOTFOUND */
15320
15321 /* statvfs */
15322 #ifdef ST_RDONLY
15323 if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
15324 #endif /* ST_RDONLY */
15325 #ifdef ST_NOSUID
15326 if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
15327 #endif /* ST_NOSUID */
15328
15329 /* GNU extensions */
15330 #ifdef ST_NODEV
15331 if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
15332 #endif /* ST_NODEV */
15333 #ifdef ST_NOEXEC
15334 if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
15335 #endif /* ST_NOEXEC */
15336 #ifdef ST_SYNCHRONOUS
15337 if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
15338 #endif /* ST_SYNCHRONOUS */
15339 #ifdef ST_MANDLOCK
15340 if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
15341 #endif /* ST_MANDLOCK */
15342 #ifdef ST_WRITE
15343 if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
15344 #endif /* ST_WRITE */
15345 #ifdef ST_APPEND
15346 if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
15347 #endif /* ST_APPEND */
15348 #ifdef ST_NOATIME
15349 if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
15350 #endif /* ST_NOATIME */
15351 #ifdef ST_NODIRATIME
15352 if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
15353 #endif /* ST_NODIRATIME */
15354 #ifdef ST_RELATIME
15355 if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
15356 #endif /* ST_RELATIME */
15357
15358 /* FreeBSD sendfile() constants */
15359 #ifdef SF_NODISKIO
15360 if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
15361 #endif
15362 /* is obsolete since the 11.x release */
15363 #ifdef SF_MNOWAIT
15364 if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
15365 #endif
15366 #ifdef SF_SYNC
15367 if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
15368 #endif
15369 #ifdef SF_NOCACHE
15370 if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
15371 #endif
15372
15373 /* constants for posix_fadvise */
15374 #ifdef POSIX_FADV_NORMAL
15375 if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
15376 #endif
15377 #ifdef POSIX_FADV_SEQUENTIAL
15378 if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
15379 #endif
15380 #ifdef POSIX_FADV_RANDOM
15381 if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
15382 #endif
15383 #ifdef POSIX_FADV_NOREUSE
15384 if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
15385 #endif
15386 #ifdef POSIX_FADV_WILLNEED
15387 if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
15388 #endif
15389 #ifdef POSIX_FADV_DONTNEED
15390 if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
15391 #endif
15392
15393 /* constants for waitid */
15394 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
15395 if (PyModule_AddIntMacro(m, P_PID)) return -1;
15396 if (PyModule_AddIntMacro(m, P_PGID)) return -1;
15397 if (PyModule_AddIntMacro(m, P_ALL)) return -1;
15398 #ifdef P_PIDFD
15399 if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
15400 #endif
15401 #endif
15402 #ifdef WEXITED
15403 if (PyModule_AddIntMacro(m, WEXITED)) return -1;
15404 #endif
15405 #ifdef WNOWAIT
15406 if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
15407 #endif
15408 #ifdef WSTOPPED
15409 if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
15410 #endif
15411 #ifdef CLD_EXITED
15412 if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
15413 #endif
15414 #ifdef CLD_KILLED
15415 if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
15416 #endif
15417 #ifdef CLD_DUMPED
15418 if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
15419 #endif
15420 #ifdef CLD_TRAPPED
15421 if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
15422 #endif
15423 #ifdef CLD_STOPPED
15424 if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
15425 #endif
15426 #ifdef CLD_CONTINUED
15427 if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
15428 #endif
15429
15430 /* constants for lockf */
15431 #ifdef F_LOCK
15432 if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
15433 #endif
15434 #ifdef F_TLOCK
15435 if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
15436 #endif
15437 #ifdef F_ULOCK
15438 if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
15439 #endif
15440 #ifdef F_TEST
15441 if (PyModule_AddIntMacro(m, F_TEST)) return -1;
15442 #endif
15443
15444 #ifdef RWF_DSYNC
15445 if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
15446 #endif
15447 #ifdef RWF_HIPRI
15448 if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
15449 #endif
15450 #ifdef RWF_SYNC
15451 if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
15452 #endif
15453 #ifdef RWF_NOWAIT
15454 if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
15455 #endif
15456 #ifdef RWF_APPEND
15457 if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
15458 #endif
15459
15460 /* constants for splice */
15461 #if defined(HAVE_SPLICE) && defined(__linux__)
15462 if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
15463 if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
15464 if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
15465 #endif
15466
15467 /* constants for posix_spawn */
15468 #ifdef HAVE_POSIX_SPAWN
15469 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
15470 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
15471 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
15472 #endif
15473
15474 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
15475 if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
15476 if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
15477 if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
15478 #endif
15479 #ifdef HAVE_SPAWNV
15480 if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
15481 if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
15482 #endif
15483
15484 #ifdef HAVE_SCHED_H
15485 #ifdef SCHED_OTHER
15486 if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
15487 #endif
15488 #ifdef SCHED_FIFO
15489 if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
15490 #endif
15491 #ifdef SCHED_RR
15492 if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
15493 #endif
15494 #ifdef SCHED_SPORADIC
15495 if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
15496 #endif
15497 #ifdef SCHED_BATCH
15498 if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
15499 #endif
15500 #ifdef SCHED_IDLE
15501 if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
15502 #endif
15503 #ifdef SCHED_RESET_ON_FORK
15504 if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
15505 #endif
15506 #ifdef SCHED_SYS
15507 if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
15508 #endif
15509 #ifdef SCHED_IA
15510 if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
15511 #endif
15512 #ifdef SCHED_FSS
15513 if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
15514 #endif
15515 #ifdef SCHED_FX
15516 if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
15517 #endif
15518 #endif
15519
15520 #ifdef USE_XATTRS
15521 if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
15522 if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
15523 if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
15524 #endif
15525
15526 #if HAVE_DECL_RTLD_LAZY
15527 if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
15528 #endif
15529 #if HAVE_DECL_RTLD_NOW
15530 if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
15531 #endif
15532 #if HAVE_DECL_RTLD_GLOBAL
15533 if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
15534 #endif
15535 #if HAVE_DECL_RTLD_LOCAL
15536 if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
15537 #endif
15538 #if HAVE_DECL_RTLD_NODELETE
15539 if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
15540 #endif
15541 #if HAVE_DECL_RTLD_NOLOAD
15542 if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
15543 #endif
15544 #if HAVE_DECL_RTLD_DEEPBIND
15545 if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
15546 #endif
15547 #if HAVE_DECL_RTLD_MEMBER
15548 if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
15549 #endif
15550
15551 #ifdef HAVE_GETRANDOM_SYSCALL
15552 if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
15553 if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
15554 #endif
15555 #ifdef HAVE_MEMFD_CREATE
15556 if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
15557 if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
15558 #ifdef MFD_HUGETLB
15559 if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
15560 #endif
15561 #ifdef MFD_HUGE_SHIFT
15562 if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
15563 #endif
15564 #ifdef MFD_HUGE_MASK
15565 if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
15566 #endif
15567 #ifdef MFD_HUGE_64KB
15568 if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
15569 #endif
15570 #ifdef MFD_HUGE_512KB
15571 if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
15572 #endif
15573 #ifdef MFD_HUGE_1MB
15574 if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
15575 #endif
15576 #ifdef MFD_HUGE_2MB
15577 if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
15578 #endif
15579 #ifdef MFD_HUGE_8MB
15580 if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
15581 #endif
15582 #ifdef MFD_HUGE_16MB
15583 if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
15584 #endif
15585 #ifdef MFD_HUGE_32MB
15586 if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
15587 #endif
15588 #ifdef MFD_HUGE_256MB
15589 if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
15590 #endif
15591 #ifdef MFD_HUGE_512MB
15592 if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
15593 #endif
15594 #ifdef MFD_HUGE_1GB
15595 if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
15596 #endif
15597 #ifdef MFD_HUGE_2GB
15598 if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
15599 #endif
15600 #ifdef MFD_HUGE_16GB
15601 if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
15602 #endif
15603 #endif /* HAVE_MEMFD_CREATE */
15604
15605 #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15606 if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
15607 #ifdef EFD_NONBLOCK
15608 if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
15609 #endif
15610 #ifdef EFD_SEMAPHORE
15611 if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
15612 #endif
15613 #endif /* HAVE_EVENTFD && EFD_CLOEXEC */
15614
15615 #if defined(__APPLE__)
15616 if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
15617 if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
15618 if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
15619 if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
15620 #endif
15621
15622 #ifdef MS_WINDOWS
15623 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
15624 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
15625 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
15626 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
15627 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
15628 #endif
15629
15630 return 0;
15631 }
15632
15633
15634
15635 #define PROBE(name, test) \
15636 static int name(void) \
15637 { \
15638 if (test) { \
15639 return 1; \
15640 } else { \
15641 return 0; \
15642 } \
15643 }
15644
15645 #ifdef HAVE_FSTATAT
15646 PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
15647 #endif
15648
15649 #ifdef HAVE_FACCESSAT
15650 PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
15651 #endif
15652
15653 #ifdef HAVE_FCHMODAT
15654 PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
15655 #endif
15656
15657 #ifdef HAVE_FCHOWNAT
15658 PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
15659 #endif
15660
15661 #ifdef HAVE_LINKAT
15662 PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
15663 #endif
15664
15665 #ifdef HAVE_FDOPENDIR
15666 PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
15667 #endif
15668
15669 #ifdef HAVE_MKDIRAT
15670 PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
15671 #endif
15672
15673 #ifdef HAVE_MKFIFOAT
15674 PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
15675 #endif
15676
15677 #ifdef HAVE_MKNODAT
15678 PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
15679 #endif
15680
15681 #ifdef HAVE_RENAMEAT
15682 PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
15683 #endif
15684
15685 #ifdef HAVE_UNLINKAT
15686 PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
15687 #endif
15688
15689 #ifdef HAVE_OPENAT
15690 PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
15691 #endif
15692
15693 #ifdef HAVE_READLINKAT
15694 PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
15695 #endif
15696
15697 #ifdef HAVE_SYMLINKAT
15698 PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
15699 #endif
15700
15701 #ifdef HAVE_FUTIMENS
15702 PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
15703 #endif
15704
15705 #ifdef HAVE_UTIMENSAT
15706 PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
15707 #endif
15708
15709
15710
15711
15712 static const struct have_function {
15713 const char * const label;
15714 int (*probe)(void);
15715 } have_functions[] = {
15716
15717 #ifdef HAVE_EVENTFD
15718 {"HAVE_EVENTFD", NULL},
15719 #endif
15720
15721 #ifdef HAVE_FACCESSAT
15722 { "HAVE_FACCESSAT", probe_faccessat },
15723 #endif
15724
15725 #ifdef HAVE_FCHDIR
15726 { "HAVE_FCHDIR", NULL },
15727 #endif
15728
15729 #ifdef HAVE_FCHMOD
15730 { "HAVE_FCHMOD", NULL },
15731 #endif
15732
15733 #ifdef HAVE_FCHMODAT
15734 { "HAVE_FCHMODAT", probe_fchmodat },
15735 #endif
15736
15737 #ifdef HAVE_FCHOWN
15738 { "HAVE_FCHOWN", NULL },
15739 #endif
15740
15741 #ifdef HAVE_FCHOWNAT
15742 { "HAVE_FCHOWNAT", probe_fchownat },
15743 #endif
15744
15745 #ifdef HAVE_FEXECVE
15746 { "HAVE_FEXECVE", NULL },
15747 #endif
15748
15749 #ifdef HAVE_FDOPENDIR
15750 { "HAVE_FDOPENDIR", probe_fdopendir },
15751 #endif
15752
15753 #ifdef HAVE_FPATHCONF
15754 { "HAVE_FPATHCONF", NULL },
15755 #endif
15756
15757 #ifdef HAVE_FSTATAT
15758 { "HAVE_FSTATAT", probe_fstatat },
15759 #endif
15760
15761 #ifdef HAVE_FSTATVFS
15762 { "HAVE_FSTATVFS", NULL },
15763 #endif
15764
15765 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
15766 { "HAVE_FTRUNCATE", NULL },
15767 #endif
15768
15769 #ifdef HAVE_FUTIMENS
15770 { "HAVE_FUTIMENS", probe_futimens },
15771 #endif
15772
15773 #ifdef HAVE_FUTIMES
15774 { "HAVE_FUTIMES", NULL },
15775 #endif
15776
15777 #ifdef HAVE_FUTIMESAT
15778 { "HAVE_FUTIMESAT", NULL },
15779 #endif
15780
15781 #ifdef HAVE_LINKAT
15782 { "HAVE_LINKAT", probe_linkat },
15783 #endif
15784
15785 #ifdef HAVE_LCHFLAGS
15786 { "HAVE_LCHFLAGS", NULL },
15787 #endif
15788
15789 #ifdef HAVE_LCHMOD
15790 { "HAVE_LCHMOD", NULL },
15791 #endif
15792
15793 #ifdef HAVE_LCHOWN
15794 { "HAVE_LCHOWN", NULL },
15795 #endif
15796
15797 #ifdef HAVE_LSTAT
15798 { "HAVE_LSTAT", NULL },
15799 #endif
15800
15801 #ifdef HAVE_LUTIMES
15802 { "HAVE_LUTIMES", NULL },
15803 #endif
15804
15805 #ifdef HAVE_MEMFD_CREATE
15806 { "HAVE_MEMFD_CREATE", NULL },
15807 #endif
15808
15809 #ifdef HAVE_MKDIRAT
15810 { "HAVE_MKDIRAT", probe_mkdirat },
15811 #endif
15812
15813 #ifdef HAVE_MKFIFOAT
15814 { "HAVE_MKFIFOAT", probe_mkfifoat },
15815 #endif
15816
15817 #ifdef HAVE_MKNODAT
15818 { "HAVE_MKNODAT", probe_mknodat },
15819 #endif
15820
15821 #ifdef HAVE_OPENAT
15822 { "HAVE_OPENAT", probe_openat },
15823 #endif
15824
15825 #ifdef HAVE_READLINKAT
15826 { "HAVE_READLINKAT", probe_readlinkat },
15827 #endif
15828
15829 #ifdef HAVE_RENAMEAT
15830 { "HAVE_RENAMEAT", probe_renameat },
15831 #endif
15832
15833 #ifdef HAVE_SYMLINKAT
15834 { "HAVE_SYMLINKAT", probe_symlinkat },
15835 #endif
15836
15837 #ifdef HAVE_UNLINKAT
15838 { "HAVE_UNLINKAT", probe_unlinkat },
15839 #endif
15840
15841 #ifdef HAVE_UTIMENSAT
15842 { "HAVE_UTIMENSAT", probe_utimensat },
15843 #endif
15844
15845 #ifdef MS_WINDOWS
15846 { "MS_WINDOWS", NULL },
15847 #endif
15848
15849 { NULL, NULL }
15850 };
15851
15852
15853 static int
posixmodule_exec(PyObject *m)15854 posixmodule_exec(PyObject *m)
15855 {
15856 _posixstate *state = get_posix_state(m);
15857
15858 #if defined(HAVE_PWRITEV)
15859 if (HAVE_PWRITEV_RUNTIME) {} else {
15860 PyObject* dct = PyModule_GetDict(m);
15861
15862 if (dct == NULL) {
15863 return -1;
15864 }
15865
15866 if (PyDict_DelItemString(dct, "pwritev") == -1) {
15867 PyErr_Clear();
15868 }
15869 if (PyDict_DelItemString(dct, "preadv") == -1) {
15870 PyErr_Clear();
15871 }
15872 }
15873 #endif
15874
15875 /* Initialize environ dictionary */
15876 PyObject *v = convertenviron();
15877 Py_XINCREF(v);
15878 if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
15879 return -1;
15880 Py_DECREF(v);
15881
15882 if (all_ins(m))
15883 return -1;
15884
15885 if (setup_confname_tables(m))
15886 return -1;
15887
15888 Py_INCREF(PyExc_OSError);
15889 PyModule_AddObject(m, "error", PyExc_OSError);
15890
15891 #if defined(HAVE_WAITID) && !defined(__APPLE__)
15892 waitid_result_desc.name = MODNAME ".waitid_result";
15893 PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
15894 if (WaitidResultType == NULL) {
15895 return -1;
15896 }
15897 Py_INCREF(WaitidResultType);
15898 PyModule_AddObject(m, "waitid_result", WaitidResultType);
15899 state->WaitidResultType = WaitidResultType;
15900 #endif
15901
15902 stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
15903 stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
15904 stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
15905 stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
15906 PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
15907 if (StatResultType == NULL) {
15908 return -1;
15909 }
15910 Py_INCREF(StatResultType);
15911 PyModule_AddObject(m, "stat_result", StatResultType);
15912 state->StatResultType = StatResultType;
15913 structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15914 ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
15915
15916 statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
15917 PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
15918 if (StatVFSResultType == NULL) {
15919 return -1;
15920 }
15921 Py_INCREF(StatVFSResultType);
15922 PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
15923 state->StatVFSResultType = StatVFSResultType;
15924 #ifdef NEED_TICKS_PER_SECOND
15925 # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15926 ticks_per_second = sysconf(_SC_CLK_TCK);
15927 # elif defined(HZ)
15928 ticks_per_second = HZ;
15929 # else
15930 ticks_per_second = 60; /* magic fallback value; may be bogus */
15931 # endif
15932 #endif
15933
15934 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
15935 sched_param_desc.name = MODNAME ".sched_param";
15936 PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
15937 if (SchedParamType == NULL) {
15938 return -1;
15939 }
15940 Py_INCREF(SchedParamType);
15941 PyModule_AddObject(m, "sched_param", SchedParamType);
15942 state->SchedParamType = SchedParamType;
15943 ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
15944 #endif
15945
15946 /* initialize TerminalSize_info */
15947 PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
15948 if (TerminalSizeType == NULL) {
15949 return -1;
15950 }
15951 Py_INCREF(TerminalSizeType);
15952 PyModule_AddObject(m, "terminal_size", TerminalSizeType);
15953 state->TerminalSizeType = TerminalSizeType;
15954
15955 /* initialize scandir types */
15956 PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
15957 if (ScandirIteratorType == NULL) {
15958 return -1;
15959 }
15960 state->ScandirIteratorType = ScandirIteratorType;
15961
15962 PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
15963 if (DirEntryType == NULL) {
15964 return -1;
15965 }
15966 Py_INCREF(DirEntryType);
15967 PyModule_AddObject(m, "DirEntry", DirEntryType);
15968 state->DirEntryType = DirEntryType;
15969
15970 times_result_desc.name = MODNAME ".times_result";
15971 PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(×_result_desc);
15972 if (TimesResultType == NULL) {
15973 return -1;
15974 }
15975 Py_INCREF(TimesResultType);
15976 PyModule_AddObject(m, "times_result", TimesResultType);
15977 state->TimesResultType = TimesResultType;
15978
15979 PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
15980 if (UnameResultType == NULL) {
15981 return -1;
15982 }
15983 Py_INCREF(UnameResultType);
15984 PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
15985 state->UnameResultType = (PyObject *)UnameResultType;
15986
15987 if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
15988 return -1;
15989 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
15990 state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
15991 if (state->struct_rusage == NULL)
15992 return -1;
15993 #endif
15994 state->st_mode = PyUnicode_InternFromString("st_mode");
15995 if (state->st_mode == NULL)
15996 return -1;
15997
15998 /* suppress "function not used" warnings */
15999 {
16000 int ignored;
16001 fd_specified("", -1);
16002 follow_symlinks_specified("", 1);
16003 dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
16004 dir_fd_converter(Py_None, &ignored);
16005 dir_fd_unavailable(Py_None, &ignored);
16006 }
16007
16008 /*
16009 * provide list of locally available functions
16010 * so os.py can populate support_* lists
16011 */
16012 PyObject *list = PyList_New(0);
16013 if (!list) {
16014 return -1;
16015 }
16016 for (const struct have_function *trace = have_functions; trace->label; trace++) {
16017 PyObject *unicode;
16018 if (trace->probe && !trace->probe()) continue;
16019 unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
16020 if (!unicode)
16021 return -1;
16022 if (PyList_Append(list, unicode))
16023 return -1;
16024 Py_DECREF(unicode);
16025 }
16026
16027 PyModule_AddObject(m, "_have_functions", list);
16028
16029 return 0;
16030 }
16031
16032
16033 static PyModuleDef_Slot posixmodile_slots[] = {
16034 {Py_mod_exec, posixmodule_exec},
16035 {0, NULL}
16036 };
16037
16038 static struct PyModuleDef posixmodule = {
16039 PyModuleDef_HEAD_INIT,
16040 .m_name = MODNAME,
16041 .m_doc = posix__doc__,
16042 .m_size = sizeof(_posixstate),
16043 .m_methods = posix_methods,
16044 .m_slots = posixmodile_slots,
16045 .m_traverse = _posix_traverse,
16046 .m_clear = _posix_clear,
16047 .m_free = _posix_free,
16048 };
16049
16050 PyMODINIT_FUNC
INITFUNC(void)16051 INITFUNC(void)
16052 {
16053 return PyModuleDef_Init(&posixmodule);
16054 }
16055
16056 #ifdef __cplusplus
16057 }
16058 #endif
16059