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 #ifdef MS_WINDOWS
14 /* include <windows.h> early to avoid conflict with pycore_condvar.h:
15
16 #define WIN32_LEAN_AND_MEAN
17 #include <windows.h>
18
19 FSCTL_GET_REPARSE_POINT is not exported with WIN32_LEAN_AND_MEAN. */
20 # include <windows.h>
21 #endif
22
23 #include "pycore_ceval.h" // _PyEval_ReInitThreads()
24 #include "pycore_import.h" // _PyImport_ReInitLock()
25 #include "pycore_pystate.h" // _PyInterpreterState_GET()
26 #include "structmember.h" // PyMemberDef
27 #ifndef MS_WINDOWS
28 # include "posixmodule.h"
29 #else
30 # include "winreparse.h"
31 #endif
32
33 /* On android API level 21, 'AT_EACCESS' is not declared although
34 * HAVE_FACCESSAT is defined. */
35 #ifdef __ANDROID__
36 # undef HAVE_FACCESSAT
37 #endif
38
39 #include <stdio.h> /* needed for ctermid() */
40
41 /*
42 * A number of APIs are available on macOS from a certain macOS version.
43 * To support building with a new SDK while deploying to older versions
44 * the availability test is split into two:
45 * - HAVE_<FUNCTION>: The configure check for compile time availability
46 * - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
47 *
48 * The latter is always true when not on macOS, or when using a compiler
49 * that does not support __has_builtin (older versions of Xcode).
50 *
51 * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
52 * if (HAVE_<FUNCTION>_RUNTIME) { ... }
53 *
54 * In mixing the test with other tests or using negations will result in compile
55 * errors.
56 */
57 #if defined(__APPLE__)
58
59 #if defined(__has_builtin)
60 #if __has_builtin(__builtin_available)
61 #define HAVE_BUILTIN_AVAILABLE 1
62 #endif
63 #endif
64
65 #ifdef HAVE_BUILTIN_AVAILABLE
66 # define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
67 # define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
68 # define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
69 # define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
70 # define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
71 # define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
72 # define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
73 # define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
74 # define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
75 # define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
76 # define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
77 # define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
78 # define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
79 # define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
80 # define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
81
82 # define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
83
84 #else /* Xcode 8 or earlier */
85
86 /* __builtin_available is not present in these compilers, but
87 * some of the symbols might be weak linked (10.10 SDK or later
88 * deploying on 10.9.
89 *
90 * Fall back to the older style of availability checking for
91 * symbols introduced in macOS 10.10.
92 */
93
94 # ifdef HAVE_FSTATAT
95 # define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
96 # endif
97
98 # ifdef HAVE_FACCESSAT
99 # define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
100 # endif
101
102 # ifdef HAVE_FCHMODAT
103 # define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
104 # endif
105
106 # ifdef HAVE_FCHOWNAT
107 # define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
108 # endif
109
110 # ifdef HAVE_LINKAT
111 # define HAVE_LINKAT_RUNTIME (linkat != NULL)
112 # endif
113
114 # ifdef HAVE_FDOPENDIR
115 # define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
116 # endif
117
118 # ifdef HAVE_MKDIRAT
119 # define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
120 # endif
121
122 # ifdef HAVE_RENAMEAT
123 # define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
124 # endif
125
126 # ifdef HAVE_UNLINKAT
127 # define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
128 # endif
129
130 # ifdef HAVE_OPENAT
131 # define HAVE_OPENAT_RUNTIME (openat != NULL)
132 # endif
133
134 # ifdef HAVE_READLINKAT
135 # define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
136 # endif
137
138 # ifdef HAVE_SYMLINKAT
139 # define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
140 # endif
141
142 #endif
143
144 #ifdef HAVE_FUTIMESAT
145 /* Some of the logic for weak linking depends on this assertion */
146 # error "HAVE_FUTIMESAT unexpectedly defined"
147 #endif
148
149 #else
150 # define HAVE_FSTATAT_RUNTIME 1
151 # define HAVE_FACCESSAT_RUNTIME 1
152 # define HAVE_FCHMODAT_RUNTIME 1
153 # define HAVE_FCHOWNAT_RUNTIME 1
154 # define HAVE_LINKAT_RUNTIME 1
155 # define HAVE_FDOPENDIR_RUNTIME 1
156 # define HAVE_MKDIRAT_RUNTIME 1
157 # define HAVE_RENAMEAT_RUNTIME 1
158 # define HAVE_UNLINKAT_RUNTIME 1
159 # define HAVE_OPENAT_RUNTIME 1
160 # define HAVE_READLINKAT_RUNTIME 1
161 # define HAVE_SYMLINKAT_RUNTIME 1
162 # define HAVE_FUTIMENS_RUNTIME 1
163 # define HAVE_UTIMENSAT_RUNTIME 1
164 # define HAVE_PWRITEV_RUNTIME 1
165 #endif
166
167
168 #ifdef __cplusplus
169 extern "C" {
170 #endif
171
172 PyDoc_STRVAR(posix__doc__,
173 "This module provides access to operating system functionality that is\n\
174 standardized by the C Standard and the POSIX standard (a thinly\n\
175 disguised Unix interface). Refer to the library manual and\n\
176 corresponding Unix manual entries for more information on calls.");
177
178
179 #ifdef HAVE_SYS_UIO_H
180 # include <sys/uio.h>
181 #endif
182
183 #ifdef HAVE_SYS_SYSMACROS_H
184 /* GNU C Library: major(), minor(), makedev() */
185 # include <sys/sysmacros.h>
186 #endif
187
188 #ifdef HAVE_SYS_TYPES_H
189 # include <sys/types.h>
190 #endif /* HAVE_SYS_TYPES_H */
191
192 #ifdef HAVE_SYS_STAT_H
193 # include <sys/stat.h>
194 #endif /* HAVE_SYS_STAT_H */
195
196 #ifdef HAVE_SYS_WAIT_H
197 # include <sys/wait.h> // WNOHANG
198 #endif
199 #ifdef HAVE_LINUX_WAIT_H
200 # include <linux/wait.h> // P_PIDFD
201 #endif
202
203 #ifdef HAVE_SIGNAL_H
204 # include <signal.h>
205 #endif
206
207 #ifdef HAVE_FCNTL_H
208 # include <fcntl.h>
209 #endif
210
211 #ifdef HAVE_GRP_H
212 # include <grp.h>
213 #endif
214
215 #ifdef HAVE_SYSEXITS_H
216 # include <sysexits.h>
217 #endif
218
219 #ifdef HAVE_SYS_LOADAVG_H
220 # include <sys/loadavg.h>
221 #endif
222
223 #ifdef HAVE_SYS_SENDFILE_H
224 # include <sys/sendfile.h>
225 #endif
226
227 #if defined(__APPLE__)
228 # include <copyfile.h>
229 #endif
230
231 #ifdef HAVE_SCHED_H
232 # include <sched.h>
233 #endif
234
235 #ifdef HAVE_COPY_FILE_RANGE
236 # include <unistd.h>
237 #endif
238
239 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
240 # undef HAVE_SCHED_SETAFFINITY
241 #endif
242
243 #if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
244 # define USE_XATTRS
245 #endif
246
247 #ifdef USE_XATTRS
248 # include <sys/xattr.h>
249 #endif
250
251 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
252 # ifdef HAVE_SYS_SOCKET_H
253 # include <sys/socket.h>
254 # endif
255 #endif
256
257 #ifdef HAVE_DLFCN_H
258 # include <dlfcn.h>
259 #endif
260
261 #ifdef __hpux
262 # include <sys/mpctl.h>
263 #endif
264
265 #if defined(__DragonFly__) || \
266 defined(__OpenBSD__) || \
267 defined(__FreeBSD__) || \
268 defined(__NetBSD__) || \
269 defined(__APPLE__)
270 # include <sys/sysctl.h>
271 #endif
272
273 #ifdef HAVE_LINUX_RANDOM_H
274 # include <linux/random.h>
275 #endif
276 #ifdef HAVE_GETRANDOM_SYSCALL
277 # include <sys/syscall.h>
278 #endif
279
280 #if defined(MS_WINDOWS)
281 # define TERMSIZE_USE_CONIO
282 #elif defined(HAVE_SYS_IOCTL_H)
283 # include <sys/ioctl.h>
284 # if defined(HAVE_TERMIOS_H)
285 # include <termios.h>
286 # endif
287 # if defined(TIOCGWINSZ)
288 # define TERMSIZE_USE_IOCTL
289 # endif
290 #endif /* MS_WINDOWS */
291
292 /* Various compilers have only certain posix functions */
293 /* XXX Gosh I wish these were all moved into pyconfig.h */
294 #if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */
295 # define HAVE_OPENDIR 1
296 # define HAVE_SYSTEM 1
297 # include <process.h>
298 #else
299 # ifdef _MSC_VER
300 /* Microsoft compiler */
301 # define HAVE_GETPPID 1
302 # define HAVE_GETLOGIN 1
303 # define HAVE_SPAWNV 1
304 # define HAVE_EXECV 1
305 # define HAVE_WSPAWNV 1
306 # define HAVE_WEXECV 1
307 # define HAVE_PIPE 1
308 # define HAVE_SYSTEM 1
309 # define HAVE_CWAIT 1
310 # define HAVE_FSYNC 1
311 # define fsync _commit
312 # else
313 /* Unix functions that the configure script doesn't check for */
314 # ifndef __VXWORKS__
315 # define HAVE_EXECV 1
316 # define HAVE_FORK 1
317 # if defined(__USLC__) && defined(__SCO_VERSION__) /* SCO UDK Compiler */
318 # define HAVE_FORK1 1
319 # endif
320 # endif
321 # define HAVE_GETEGID 1
322 # define HAVE_GETEUID 1
323 # define HAVE_GETGID 1
324 # define HAVE_GETPPID 1
325 # define HAVE_GETUID 1
326 # define HAVE_KILL 1
327 # define HAVE_OPENDIR 1
328 # define HAVE_PIPE 1
329 # define HAVE_SYSTEM 1
330 # define HAVE_WAIT 1
331 # define HAVE_TTYNAME 1
332 # endif /* _MSC_VER */
333 #endif /* ! __WATCOMC__ || __QNX__ */
334
335 _Py_IDENTIFIER(__fspath__);
336
337 /*[clinic input]
338 # one of the few times we lie about this name!
339 module os
340 [clinic start generated code]*/
341 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
342
343 #ifndef _MSC_VER
344
345 #if defined(__sgi)&&_COMPILER_VERSION>=700
346 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
347 (default) */
348 extern char *ctermid_r(char *);
349 #endif
350
351 #endif /* !_MSC_VER */
352
353 #if defined(__VXWORKS__)
354 # include <vxCpuLib.h>
355 # include <rtpLib.h>
356 # include <wait.h>
357 # include <taskLib.h>
358 # ifndef _P_WAIT
359 # define _P_WAIT 0
360 # define _P_NOWAIT 1
361 # define _P_NOWAITO 1
362 # endif
363 #endif /* __VXWORKS__ */
364
365 #ifdef HAVE_POSIX_SPAWN
366 # include <spawn.h>
367 #endif
368
369 #ifdef HAVE_UTIME_H
370 # include <utime.h>
371 #endif /* HAVE_UTIME_H */
372
373 #ifdef HAVE_SYS_UTIME_H
374 # include <sys/utime.h>
375 # define HAVE_UTIME_H /* pretend we do for the rest of this file */
376 #endif /* HAVE_SYS_UTIME_H */
377
378 #ifdef HAVE_SYS_TIMES_H
379 # include <sys/times.h>
380 #endif /* HAVE_SYS_TIMES_H */
381
382 #ifdef HAVE_SYS_PARAM_H
383 # include <sys/param.h>
384 #endif /* HAVE_SYS_PARAM_H */
385
386 #ifdef HAVE_SYS_UTSNAME_H
387 # include <sys/utsname.h>
388 #endif /* HAVE_SYS_UTSNAME_H */
389
390 #ifdef HAVE_DIRENT_H
391 # include <dirent.h>
392 # define NAMLEN(dirent) strlen((dirent)->d_name)
393 #else
394 # if defined(__WATCOMC__) && !defined(__QNX__)
395 # include <direct.h>
396 # define NAMLEN(dirent) strlen((dirent)->d_name)
397 # else
398 # define dirent direct
399 # define NAMLEN(dirent) (dirent)->d_namlen
400 # endif
401 # ifdef HAVE_SYS_NDIR_H
402 # include <sys/ndir.h>
403 # endif
404 # ifdef HAVE_SYS_DIR_H
405 # include <sys/dir.h>
406 # endif
407 # ifdef HAVE_NDIR_H
408 # include <ndir.h>
409 # endif
410 #endif
411
412 #ifdef _MSC_VER
413 # ifdef HAVE_DIRECT_H
414 # include <direct.h>
415 # endif
416 # ifdef HAVE_IO_H
417 # include <io.h>
418 # endif
419 # ifdef HAVE_PROCESS_H
420 # include <process.h>
421 # endif
422 # ifndef IO_REPARSE_TAG_SYMLINK
423 # define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
424 # endif
425 # ifndef IO_REPARSE_TAG_MOUNT_POINT
426 # define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
427 # endif
428 # include "osdefs.h" // SEP
429 # include <malloc.h>
430 # include <windows.h>
431 # include <shellapi.h> // ShellExecute()
432 # include <lmcons.h> // UNLEN
433 # define HAVE_SYMLINK
434 #endif /* _MSC_VER */
435
436 #ifndef MAXPATHLEN
437 # if defined(PATH_MAX) && PATH_MAX > 1024
438 # define MAXPATHLEN PATH_MAX
439 # else
440 # define MAXPATHLEN 1024
441 # endif
442 #endif /* MAXPATHLEN */
443
444 #ifdef UNION_WAIT
445 /* Emulate some macros on systems that have a union instead of macros */
446 # ifndef WIFEXITED
447 # define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
448 # endif
449 # ifndef WEXITSTATUS
450 # define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
451 # endif
452 # ifndef WTERMSIG
453 # define WTERMSIG(u_wait) ((u_wait).w_termsig)
454 # endif
455 # define WAIT_TYPE union wait
456 # define WAIT_STATUS_INT(s) (s.w_status)
457 #else
458 /* !UNION_WAIT */
459 # define WAIT_TYPE int
460 # define WAIT_STATUS_INT(s) (s)
461 #endif /* UNION_WAIT */
462
463 /* Don't use the "_r" form if we don't need it (also, won't have a
464 prototype for it, at least on Solaris -- maybe others as well?). */
465 #if defined(HAVE_CTERMID_R)
466 # define USE_CTERMID_R
467 #endif
468
469 /* choose the appropriate stat and fstat functions and return structs */
470 #undef STAT
471 #undef FSTAT
472 #undef STRUCT_STAT
473 #ifdef MS_WINDOWS
474 # define STAT win32_stat
475 # define LSTAT win32_lstat
476 # define FSTAT _Py_fstat_noraise
477 # define STRUCT_STAT struct _Py_stat_struct
478 #else
479 # define STAT stat
480 # define LSTAT lstat
481 # define FSTAT fstat
482 # define STRUCT_STAT struct stat
483 #endif
484
485 #if defined(MAJOR_IN_MKDEV)
486 # include <sys/mkdev.h>
487 #else
488 # if defined(MAJOR_IN_SYSMACROS)
489 # include <sys/sysmacros.h>
490 # endif
491 # if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
492 # include <sys/mkdev.h>
493 # endif
494 #endif
495
496 #ifdef MS_WINDOWS
497 # define INITFUNC PyInit_nt
498 # define MODNAME "nt"
499 #else
500 # define INITFUNC PyInit_posix
501 # define MODNAME "posix"
502 #endif
503
504 #if defined(__sun)
505 /* Something to implement in autoconf, not present in autoconf 2.69 */
506 # define HAVE_STRUCT_STAT_ST_FSTYPE 1
507 #endif
508
509 /* memfd_create is either defined in sys/mman.h or sys/memfd.h
510 * linux/memfd.h defines additional flags
511 */
512 #ifdef HAVE_SYS_MMAN_H
513 # include <sys/mman.h>
514 #endif
515 #ifdef HAVE_SYS_MEMFD_H
516 # include <sys/memfd.h>
517 #endif
518 #ifdef HAVE_LINUX_MEMFD_H
519 # include <linux/memfd.h>
520 #endif
521
522 #ifdef _Py_MEMORY_SANITIZER
523 # include <sanitizer/msan_interface.h>
524 #endif
525
526 #ifdef HAVE_FORK
527 static void
run_at_forkers(PyObject * lst,int reverse)528 run_at_forkers(PyObject *lst, int reverse)
529 {
530 Py_ssize_t i;
531 PyObject *cpy;
532
533 if (lst != NULL) {
534 assert(PyList_CheckExact(lst));
535
536 /* Use a list copy in case register_at_fork() is called from
537 * one of the callbacks.
538 */
539 cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
540 if (cpy == NULL)
541 PyErr_WriteUnraisable(lst);
542 else {
543 if (reverse)
544 PyList_Reverse(cpy);
545 for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
546 PyObject *func, *res;
547 func = PyList_GET_ITEM(cpy, i);
548 res = _PyObject_CallNoArg(func);
549 if (res == NULL)
550 PyErr_WriteUnraisable(func);
551 else
552 Py_DECREF(res);
553 }
554 Py_DECREF(cpy);
555 }
556 }
557 }
558
559 void
PyOS_BeforeFork(void)560 PyOS_BeforeFork(void)
561 {
562 run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1);
563
564 _PyImport_AcquireLock();
565 }
566
567 void
PyOS_AfterFork_Parent(void)568 PyOS_AfterFork_Parent(void)
569 {
570 if (_PyImport_ReleaseLock() <= 0)
571 Py_FatalError("failed releasing import lock after fork");
572
573 run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0);
574 }
575
576 void
PyOS_AfterFork_Child(void)577 PyOS_AfterFork_Child(void)
578 {
579 _PyRuntimeState *runtime = &_PyRuntime;
580 _PyGILState_Reinit(runtime);
581 _PyEval_ReInitThreads(runtime);
582 _PyImport_ReInitLock();
583 _PySignal_AfterFork();
584 _PyRuntimeState_ReInitThreads(runtime);
585 _PyInterpreterState_DeleteExceptMain(runtime);
586
587 run_at_forkers(_PyInterpreterState_GET()->after_forkers_child, 0);
588 }
589
590 static int
register_at_forker(PyObject ** lst,PyObject * func)591 register_at_forker(PyObject **lst, PyObject *func)
592 {
593 if (func == NULL) /* nothing to register? do nothing. */
594 return 0;
595 if (*lst == NULL) {
596 *lst = PyList_New(0);
597 if (*lst == NULL)
598 return -1;
599 }
600 return PyList_Append(*lst, func);
601 }
602 #endif /* HAVE_FORK */
603
604
605 /* Legacy wrapper */
606 void
PyOS_AfterFork(void)607 PyOS_AfterFork(void)
608 {
609 #ifdef HAVE_FORK
610 PyOS_AfterFork_Child();
611 #endif
612 }
613
614
615 #ifdef MS_WINDOWS
616 /* defined in fileutils.c */
617 void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
618 void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
619 ULONG, struct _Py_stat_struct *);
620 #endif
621
622
623 #ifndef MS_WINDOWS
624 PyObject *
_PyLong_FromUid(uid_t uid)625 _PyLong_FromUid(uid_t uid)
626 {
627 if (uid == (uid_t)-1)
628 return PyLong_FromLong(-1);
629 return PyLong_FromUnsignedLong(uid);
630 }
631
632 PyObject *
_PyLong_FromGid(gid_t gid)633 _PyLong_FromGid(gid_t gid)
634 {
635 if (gid == (gid_t)-1)
636 return PyLong_FromLong(-1);
637 return PyLong_FromUnsignedLong(gid);
638 }
639
640 int
_Py_Uid_Converter(PyObject * obj,uid_t * p)641 _Py_Uid_Converter(PyObject *obj, uid_t *p)
642 {
643 uid_t uid;
644 PyObject *index;
645 int overflow;
646 long result;
647 unsigned long uresult;
648
649 index = PyNumber_Index(obj);
650 if (index == NULL) {
651 PyErr_Format(PyExc_TypeError,
652 "uid should be integer, not %.200s",
653 _PyType_Name(Py_TYPE(obj)));
654 return 0;
655 }
656
657 /*
658 * Handling uid_t is complicated for two reasons:
659 * * Although uid_t is (always?) unsigned, it still
660 * accepts -1.
661 * * We don't know its size in advance--it may be
662 * bigger than an int, or it may be smaller than
663 * a long.
664 *
665 * So a bit of defensive programming is in order.
666 * Start with interpreting the value passed
667 * in as a signed long and see if it works.
668 */
669
670 result = PyLong_AsLongAndOverflow(index, &overflow);
671
672 if (!overflow) {
673 uid = (uid_t)result;
674
675 if (result == -1) {
676 if (PyErr_Occurred())
677 goto fail;
678 /* It's a legitimate -1, we're done. */
679 goto success;
680 }
681
682 /* Any other negative number is disallowed. */
683 if (result < 0)
684 goto underflow;
685
686 /* Ensure the value wasn't truncated. */
687 if (sizeof(uid_t) < sizeof(long) &&
688 (long)uid != result)
689 goto underflow;
690 goto success;
691 }
692
693 if (overflow < 0)
694 goto underflow;
695
696 /*
697 * Okay, the value overflowed a signed long. If it
698 * fits in an *unsigned* long, it may still be okay,
699 * as uid_t may be unsigned long on this platform.
700 */
701 uresult = PyLong_AsUnsignedLong(index);
702 if (PyErr_Occurred()) {
703 if (PyErr_ExceptionMatches(PyExc_OverflowError))
704 goto overflow;
705 goto fail;
706 }
707
708 uid = (uid_t)uresult;
709
710 /*
711 * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
712 * but this value would get interpreted as (uid_t)-1 by chown
713 * and its siblings. That's not what the user meant! So we
714 * throw an overflow exception instead. (We already
715 * handled a real -1 with PyLong_AsLongAndOverflow() above.)
716 */
717 if (uid == (uid_t)-1)
718 goto overflow;
719
720 /* Ensure the value wasn't truncated. */
721 if (sizeof(uid_t) < sizeof(long) &&
722 (unsigned long)uid != uresult)
723 goto overflow;
724 /* fallthrough */
725
726 success:
727 Py_DECREF(index);
728 *p = uid;
729 return 1;
730
731 underflow:
732 PyErr_SetString(PyExc_OverflowError,
733 "uid is less than minimum");
734 goto fail;
735
736 overflow:
737 PyErr_SetString(PyExc_OverflowError,
738 "uid is greater than maximum");
739 /* fallthrough */
740
741 fail:
742 Py_DECREF(index);
743 return 0;
744 }
745
746 int
_Py_Gid_Converter(PyObject * obj,gid_t * p)747 _Py_Gid_Converter(PyObject *obj, gid_t *p)
748 {
749 gid_t gid;
750 PyObject *index;
751 int overflow;
752 long result;
753 unsigned long uresult;
754
755 index = PyNumber_Index(obj);
756 if (index == NULL) {
757 PyErr_Format(PyExc_TypeError,
758 "gid should be integer, not %.200s",
759 _PyType_Name(Py_TYPE(obj)));
760 return 0;
761 }
762
763 /*
764 * Handling gid_t is complicated for two reasons:
765 * * Although gid_t is (always?) unsigned, it still
766 * accepts -1.
767 * * We don't know its size in advance--it may be
768 * bigger than an int, or it may be smaller than
769 * a long.
770 *
771 * So a bit of defensive programming is in order.
772 * Start with interpreting the value passed
773 * in as a signed long and see if it works.
774 */
775
776 result = PyLong_AsLongAndOverflow(index, &overflow);
777
778 if (!overflow) {
779 gid = (gid_t)result;
780
781 if (result == -1) {
782 if (PyErr_Occurred())
783 goto fail;
784 /* It's a legitimate -1, we're done. */
785 goto success;
786 }
787
788 /* Any other negative number is disallowed. */
789 if (result < 0) {
790 goto underflow;
791 }
792
793 /* Ensure the value wasn't truncated. */
794 if (sizeof(gid_t) < sizeof(long) &&
795 (long)gid != result)
796 goto underflow;
797 goto success;
798 }
799
800 if (overflow < 0)
801 goto underflow;
802
803 /*
804 * Okay, the value overflowed a signed long. If it
805 * fits in an *unsigned* long, it may still be okay,
806 * as gid_t may be unsigned long on this platform.
807 */
808 uresult = PyLong_AsUnsignedLong(index);
809 if (PyErr_Occurred()) {
810 if (PyErr_ExceptionMatches(PyExc_OverflowError))
811 goto overflow;
812 goto fail;
813 }
814
815 gid = (gid_t)uresult;
816
817 /*
818 * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
819 * but this value would get interpreted as (gid_t)-1 by chown
820 * and its siblings. That's not what the user meant! So we
821 * throw an overflow exception instead. (We already
822 * handled a real -1 with PyLong_AsLongAndOverflow() above.)
823 */
824 if (gid == (gid_t)-1)
825 goto overflow;
826
827 /* Ensure the value wasn't truncated. */
828 if (sizeof(gid_t) < sizeof(long) &&
829 (unsigned long)gid != uresult)
830 goto overflow;
831 /* fallthrough */
832
833 success:
834 Py_DECREF(index);
835 *p = gid;
836 return 1;
837
838 underflow:
839 PyErr_SetString(PyExc_OverflowError,
840 "gid is less than minimum");
841 goto fail;
842
843 overflow:
844 PyErr_SetString(PyExc_OverflowError,
845 "gid is greater than maximum");
846 /* fallthrough */
847
848 fail:
849 Py_DECREF(index);
850 return 0;
851 }
852 #endif /* MS_WINDOWS */
853
854
855 #define _PyLong_FromDev PyLong_FromLongLong
856
857
858 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
859 static int
_Py_Dev_Converter(PyObject * obj,void * p)860 _Py_Dev_Converter(PyObject *obj, void *p)
861 {
862 *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
863 if (PyErr_Occurred())
864 return 0;
865 return 1;
866 }
867 #endif /* HAVE_MKNOD && HAVE_MAKEDEV */
868
869
870 #ifdef AT_FDCWD
871 /*
872 * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
873 * without the int cast, the value gets interpreted as uint (4291925331),
874 * which doesn't play nicely with all the initializer lines in this file that
875 * look like this:
876 * int dir_fd = DEFAULT_DIR_FD;
877 */
878 #define DEFAULT_DIR_FD (int)AT_FDCWD
879 #else
880 #define DEFAULT_DIR_FD (-100)
881 #endif
882
883 static int
_fd_converter(PyObject * o,int * p)884 _fd_converter(PyObject *o, int *p)
885 {
886 int overflow;
887 long long_value;
888
889 PyObject *index = PyNumber_Index(o);
890 if (index == NULL) {
891 return 0;
892 }
893
894 assert(PyLong_Check(index));
895 long_value = PyLong_AsLongAndOverflow(index, &overflow);
896 Py_DECREF(index);
897 assert(!PyErr_Occurred());
898 if (overflow > 0 || long_value > INT_MAX) {
899 PyErr_SetString(PyExc_OverflowError,
900 "fd is greater than maximum");
901 return 0;
902 }
903 if (overflow < 0 || long_value < INT_MIN) {
904 PyErr_SetString(PyExc_OverflowError,
905 "fd is less than minimum");
906 return 0;
907 }
908
909 *p = (int)long_value;
910 return 1;
911 }
912
913 static int
dir_fd_converter(PyObject * o,void * p)914 dir_fd_converter(PyObject *o, void *p)
915 {
916 if (o == Py_None) {
917 *(int *)p = DEFAULT_DIR_FD;
918 return 1;
919 }
920 else if (PyIndex_Check(o)) {
921 return _fd_converter(o, (int *)p);
922 }
923 else {
924 PyErr_Format(PyExc_TypeError,
925 "argument should be integer or None, not %.200s",
926 _PyType_Name(Py_TYPE(o)));
927 return 0;
928 }
929 }
930
931 typedef struct {
932 PyObject *billion;
933 PyObject *DirEntryType;
934 PyObject *ScandirIteratorType;
935 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
936 PyObject *SchedParamType;
937 #endif
938 PyObject *StatResultType;
939 PyObject *StatVFSResultType;
940 PyObject *TerminalSizeType;
941 PyObject *TimesResultType;
942 PyObject *UnameResultType;
943 #if defined(HAVE_WAITID) && !defined(__APPLE__)
944 PyObject *WaitidResultType;
945 #endif
946 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
947 PyObject *struct_rusage;
948 #endif
949 PyObject *st_mode;
950 } _posixstate;
951
952
953 static inline _posixstate*
get_posix_state(PyObject * module)954 get_posix_state(PyObject *module)
955 {
956 void *state = PyModule_GetState(module);
957 assert(state != NULL);
958 return (_posixstate *)state;
959 }
960
961 /*
962 * A PyArg_ParseTuple "converter" function
963 * that handles filesystem paths in the manner
964 * preferred by the os module.
965 *
966 * path_converter accepts (Unicode) strings and their
967 * subclasses, and bytes and their subclasses. What
968 * it does with the argument depends on the platform:
969 *
970 * * On Windows, if we get a (Unicode) string we
971 * extract the wchar_t * and return it; if we get
972 * bytes we decode to wchar_t * and return that.
973 *
974 * * On all other platforms, strings are encoded
975 * to bytes using PyUnicode_FSConverter, then we
976 * extract the char * from the bytes object and
977 * return that.
978 *
979 * path_converter also optionally accepts signed
980 * integers (representing open file descriptors) instead
981 * of path strings.
982 *
983 * Input fields:
984 * path.nullable
985 * If nonzero, the path is permitted to be None.
986 * path.allow_fd
987 * If nonzero, the path is permitted to be a file handle
988 * (a signed int) instead of a string.
989 * path.function_name
990 * If non-NULL, path_converter will use that as the name
991 * of the function in error messages.
992 * (If path.function_name is NULL it omits the function name.)
993 * path.argument_name
994 * If non-NULL, path_converter will use that as the name
995 * of the parameter in error messages.
996 * (If path.argument_name is NULL it uses "path".)
997 *
998 * Output fields:
999 * path.wide
1000 * Points to the path if it was expressed as Unicode
1001 * and was not encoded. (Only used on Windows.)
1002 * path.narrow
1003 * Points to the path if it was expressed as bytes,
1004 * or it was Unicode and was encoded to bytes. (On Windows,
1005 * is a non-zero integer if the path was expressed as bytes.
1006 * The type is deliberately incompatible to prevent misuse.)
1007 * path.fd
1008 * Contains a file descriptor if path.accept_fd was true
1009 * and the caller provided a signed integer instead of any
1010 * sort of string.
1011 *
1012 * WARNING: if your "path" parameter is optional, and is
1013 * unspecified, path_converter will never get called.
1014 * So if you set allow_fd, you *MUST* initialize path.fd = -1
1015 * yourself!
1016 * path.length
1017 * The length of the path in characters, if specified as
1018 * a string.
1019 * path.object
1020 * The original object passed in (if get a PathLike object,
1021 * the result of PyOS_FSPath() is treated as the original object).
1022 * Own a reference to the object.
1023 * path.cleanup
1024 * For internal use only. May point to a temporary object.
1025 * (Pay no attention to the man behind the curtain.)
1026 *
1027 * At most one of path.wide or path.narrow will be non-NULL.
1028 * If path was None and path.nullable was set,
1029 * or if path was an integer and path.allow_fd was set,
1030 * both path.wide and path.narrow will be NULL
1031 * and path.length will be 0.
1032 *
1033 * path_converter takes care to not write to the path_t
1034 * unless it's successful. However it must reset the
1035 * "cleanup" field each time it's called.
1036 *
1037 * Use as follows:
1038 * path_t path;
1039 * memset(&path, 0, sizeof(path));
1040 * PyArg_ParseTuple(args, "O&", path_converter, &path);
1041 * // ... use values from path ...
1042 * path_cleanup(&path);
1043 *
1044 * (Note that if PyArg_Parse fails you don't need to call
1045 * path_cleanup(). However it is safe to do so.)
1046 */
1047 typedef struct {
1048 const char *function_name;
1049 const char *argument_name;
1050 int nullable;
1051 int allow_fd;
1052 const wchar_t *wide;
1053 #ifdef MS_WINDOWS
1054 BOOL narrow;
1055 #else
1056 const char *narrow;
1057 #endif
1058 int fd;
1059 Py_ssize_t length;
1060 PyObject *object;
1061 PyObject *cleanup;
1062 } path_t;
1063
1064 #ifdef MS_WINDOWS
1065 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1066 {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
1067 #else
1068 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1069 {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
1070 #endif
1071
1072 static void
path_cleanup(path_t * path)1073 path_cleanup(path_t *path)
1074 {
1075 Py_CLEAR(path->object);
1076 Py_CLEAR(path->cleanup);
1077 }
1078
1079 static int
path_converter(PyObject * o,void * p)1080 path_converter(PyObject *o, void *p)
1081 {
1082 path_t *path = (path_t *)p;
1083 PyObject *bytes = NULL;
1084 Py_ssize_t length = 0;
1085 int is_index, is_buffer, is_bytes, is_unicode;
1086 const char *narrow;
1087 #ifdef MS_WINDOWS
1088 PyObject *wo = NULL;
1089 const wchar_t *wide;
1090 #endif
1091
1092 #define FORMAT_EXCEPTION(exc, fmt) \
1093 PyErr_Format(exc, "%s%s" fmt, \
1094 path->function_name ? path->function_name : "", \
1095 path->function_name ? ": " : "", \
1096 path->argument_name ? path->argument_name : "path")
1097
1098 /* Py_CLEANUP_SUPPORTED support */
1099 if (o == NULL) {
1100 path_cleanup(path);
1101 return 1;
1102 }
1103
1104 /* Ensure it's always safe to call path_cleanup(). */
1105 path->object = path->cleanup = NULL;
1106 /* path->object owns a reference to the original object */
1107 Py_INCREF(o);
1108
1109 if ((o == Py_None) && path->nullable) {
1110 path->wide = NULL;
1111 #ifdef MS_WINDOWS
1112 path->narrow = FALSE;
1113 #else
1114 path->narrow = NULL;
1115 #endif
1116 path->fd = -1;
1117 goto success_exit;
1118 }
1119
1120 /* Only call this here so that we don't treat the return value of
1121 os.fspath() as an fd or buffer. */
1122 is_index = path->allow_fd && PyIndex_Check(o);
1123 is_buffer = PyObject_CheckBuffer(o);
1124 is_bytes = PyBytes_Check(o);
1125 is_unicode = PyUnicode_Check(o);
1126
1127 if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
1128 /* Inline PyOS_FSPath() for better error messages. */
1129 PyObject *func, *res;
1130
1131 func = _PyObject_LookupSpecial(o, &PyId___fspath__);
1132 if (NULL == func) {
1133 goto error_format;
1134 }
1135 res = _PyObject_CallNoArg(func);
1136 Py_DECREF(func);
1137 if (NULL == res) {
1138 goto error_exit;
1139 }
1140 else if (PyUnicode_Check(res)) {
1141 is_unicode = 1;
1142 }
1143 else if (PyBytes_Check(res)) {
1144 is_bytes = 1;
1145 }
1146 else {
1147 PyErr_Format(PyExc_TypeError,
1148 "expected %.200s.__fspath__() to return str or bytes, "
1149 "not %.200s", _PyType_Name(Py_TYPE(o)),
1150 _PyType_Name(Py_TYPE(res)));
1151 Py_DECREF(res);
1152 goto error_exit;
1153 }
1154
1155 /* still owns a reference to the original object */
1156 Py_DECREF(o);
1157 o = res;
1158 }
1159
1160 if (is_unicode) {
1161 #ifdef MS_WINDOWS
1162 wide = PyUnicode_AsUnicodeAndSize(o, &length);
1163 if (!wide) {
1164 goto error_exit;
1165 }
1166 if (length > 32767) {
1167 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1168 goto error_exit;
1169 }
1170 if (wcslen(wide) != length) {
1171 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1172 goto error_exit;
1173 }
1174
1175 path->wide = wide;
1176 path->narrow = FALSE;
1177 path->fd = -1;
1178 goto success_exit;
1179 #else
1180 if (!PyUnicode_FSConverter(o, &bytes)) {
1181 goto error_exit;
1182 }
1183 #endif
1184 }
1185 else if (is_bytes) {
1186 bytes = o;
1187 Py_INCREF(bytes);
1188 }
1189 else if (is_buffer) {
1190 /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1191 after removing support of non-bytes buffer objects. */
1192 if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
1193 "%s%s%s should be %s, not %.200s",
1194 path->function_name ? path->function_name : "",
1195 path->function_name ? ": " : "",
1196 path->argument_name ? path->argument_name : "path",
1197 path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1198 "integer or None" :
1199 path->allow_fd ? "string, bytes, os.PathLike or integer" :
1200 path->nullable ? "string, bytes, os.PathLike or None" :
1201 "string, bytes or os.PathLike",
1202 _PyType_Name(Py_TYPE(o)))) {
1203 goto error_exit;
1204 }
1205 bytes = PyBytes_FromObject(o);
1206 if (!bytes) {
1207 goto error_exit;
1208 }
1209 }
1210 else if (is_index) {
1211 if (!_fd_converter(o, &path->fd)) {
1212 goto error_exit;
1213 }
1214 path->wide = NULL;
1215 #ifdef MS_WINDOWS
1216 path->narrow = FALSE;
1217 #else
1218 path->narrow = NULL;
1219 #endif
1220 goto success_exit;
1221 }
1222 else {
1223 error_format:
1224 PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1225 path->function_name ? path->function_name : "",
1226 path->function_name ? ": " : "",
1227 path->argument_name ? path->argument_name : "path",
1228 path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1229 "integer or None" :
1230 path->allow_fd ? "string, bytes, os.PathLike or integer" :
1231 path->nullable ? "string, bytes, os.PathLike or None" :
1232 "string, bytes or os.PathLike",
1233 _PyType_Name(Py_TYPE(o)));
1234 goto error_exit;
1235 }
1236
1237 length = PyBytes_GET_SIZE(bytes);
1238 narrow = PyBytes_AS_STRING(bytes);
1239 if ((size_t)length != strlen(narrow)) {
1240 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1241 goto error_exit;
1242 }
1243
1244 #ifdef MS_WINDOWS
1245 wo = PyUnicode_DecodeFSDefaultAndSize(
1246 narrow,
1247 length
1248 );
1249 if (!wo) {
1250 goto error_exit;
1251 }
1252
1253 wide = PyUnicode_AsUnicodeAndSize(wo, &length);
1254 if (!wide) {
1255 goto error_exit;
1256 }
1257 if (length > 32767) {
1258 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1259 goto error_exit;
1260 }
1261 if (wcslen(wide) != length) {
1262 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1263 goto error_exit;
1264 }
1265 path->wide = wide;
1266 path->narrow = TRUE;
1267 path->cleanup = wo;
1268 Py_DECREF(bytes);
1269 #else
1270 path->wide = NULL;
1271 path->narrow = narrow;
1272 if (bytes == o) {
1273 /* Still a reference owned by path->object, don't have to
1274 worry about path->narrow is used after free. */
1275 Py_DECREF(bytes);
1276 }
1277 else {
1278 path->cleanup = bytes;
1279 }
1280 #endif
1281 path->fd = -1;
1282
1283 success_exit:
1284 path->length = length;
1285 path->object = o;
1286 return Py_CLEANUP_SUPPORTED;
1287
1288 error_exit:
1289 Py_XDECREF(o);
1290 Py_XDECREF(bytes);
1291 #ifdef MS_WINDOWS
1292 Py_XDECREF(wo);
1293 #endif
1294 return 0;
1295 }
1296
1297 static void
argument_unavailable_error(const char * function_name,const char * argument_name)1298 argument_unavailable_error(const char *function_name, const char *argument_name)
1299 {
1300 PyErr_Format(PyExc_NotImplementedError,
1301 "%s%s%s unavailable on this platform",
1302 (function_name != NULL) ? function_name : "",
1303 (function_name != NULL) ? ": ": "",
1304 argument_name);
1305 }
1306
1307 static int
dir_fd_unavailable(PyObject * o,void * p)1308 dir_fd_unavailable(PyObject *o, void *p)
1309 {
1310 int dir_fd;
1311 if (!dir_fd_converter(o, &dir_fd))
1312 return 0;
1313 if (dir_fd != DEFAULT_DIR_FD) {
1314 argument_unavailable_error(NULL, "dir_fd");
1315 return 0;
1316 }
1317 *(int *)p = dir_fd;
1318 return 1;
1319 }
1320
1321 static int
fd_specified(const char * function_name,int fd)1322 fd_specified(const char *function_name, int fd)
1323 {
1324 if (fd == -1)
1325 return 0;
1326
1327 argument_unavailable_error(function_name, "fd");
1328 return 1;
1329 }
1330
1331 static int
follow_symlinks_specified(const char * function_name,int follow_symlinks)1332 follow_symlinks_specified(const char *function_name, int follow_symlinks)
1333 {
1334 if (follow_symlinks)
1335 return 0;
1336
1337 argument_unavailable_error(function_name, "follow_symlinks");
1338 return 1;
1339 }
1340
1341 static int
path_and_dir_fd_invalid(const char * function_name,path_t * path,int dir_fd)1342 path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1343 {
1344 if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1345 #ifndef MS_WINDOWS
1346 && !path->narrow
1347 #endif
1348 ) {
1349 PyErr_Format(PyExc_ValueError,
1350 "%s: can't specify dir_fd without matching path",
1351 function_name);
1352 return 1;
1353 }
1354 return 0;
1355 }
1356
1357 static int
dir_fd_and_fd_invalid(const char * function_name,int dir_fd,int fd)1358 dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1359 {
1360 if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1361 PyErr_Format(PyExc_ValueError,
1362 "%s: can't specify both dir_fd and fd",
1363 function_name);
1364 return 1;
1365 }
1366 return 0;
1367 }
1368
1369 static int
fd_and_follow_symlinks_invalid(const char * function_name,int fd,int follow_symlinks)1370 fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1371 int follow_symlinks)
1372 {
1373 if ((fd > 0) && (!follow_symlinks)) {
1374 PyErr_Format(PyExc_ValueError,
1375 "%s: cannot use fd and follow_symlinks together",
1376 function_name);
1377 return 1;
1378 }
1379 return 0;
1380 }
1381
1382 static int
dir_fd_and_follow_symlinks_invalid(const char * function_name,int dir_fd,int follow_symlinks)1383 dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1384 int follow_symlinks)
1385 {
1386 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1387 PyErr_Format(PyExc_ValueError,
1388 "%s: cannot use dir_fd and follow_symlinks together",
1389 function_name);
1390 return 1;
1391 }
1392 return 0;
1393 }
1394
1395 #ifdef MS_WINDOWS
1396 typedef long long Py_off_t;
1397 #else
1398 typedef off_t Py_off_t;
1399 #endif
1400
1401 static int
Py_off_t_converter(PyObject * arg,void * addr)1402 Py_off_t_converter(PyObject *arg, void *addr)
1403 {
1404 #ifdef HAVE_LARGEFILE_SUPPORT
1405 *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1406 #else
1407 *((Py_off_t *)addr) = PyLong_AsLong(arg);
1408 #endif
1409 if (PyErr_Occurred())
1410 return 0;
1411 return 1;
1412 }
1413
1414 static PyObject *
PyLong_FromPy_off_t(Py_off_t offset)1415 PyLong_FromPy_off_t(Py_off_t offset)
1416 {
1417 #ifdef HAVE_LARGEFILE_SUPPORT
1418 return PyLong_FromLongLong(offset);
1419 #else
1420 return PyLong_FromLong(offset);
1421 #endif
1422 }
1423
1424 #ifdef HAVE_SIGSET_T
1425 /* Convert an iterable of integers to a sigset.
1426 Return 1 on success, return 0 and raise an exception on error. */
1427 int
_Py_Sigset_Converter(PyObject * obj,void * addr)1428 _Py_Sigset_Converter(PyObject *obj, void *addr)
1429 {
1430 sigset_t *mask = (sigset_t *)addr;
1431 PyObject *iterator, *item;
1432 long signum;
1433 int overflow;
1434
1435 // The extra parens suppress the unreachable-code warning with clang on MacOS
1436 if (sigemptyset(mask) < (0)) {
1437 /* Probably only if mask == NULL. */
1438 PyErr_SetFromErrno(PyExc_OSError);
1439 return 0;
1440 }
1441
1442 iterator = PyObject_GetIter(obj);
1443 if (iterator == NULL) {
1444 return 0;
1445 }
1446
1447 while ((item = PyIter_Next(iterator)) != NULL) {
1448 signum = PyLong_AsLongAndOverflow(item, &overflow);
1449 Py_DECREF(item);
1450 if (signum <= 0 || signum >= NSIG) {
1451 if (overflow || signum != -1 || !PyErr_Occurred()) {
1452 PyErr_Format(PyExc_ValueError,
1453 "signal number %ld out of range", signum);
1454 }
1455 goto error;
1456 }
1457 if (sigaddset(mask, (int)signum)) {
1458 if (errno != EINVAL) {
1459 /* Probably impossible */
1460 PyErr_SetFromErrno(PyExc_OSError);
1461 goto error;
1462 }
1463 /* For backwards compatibility, allow idioms such as
1464 * `range(1, NSIG)` but warn about invalid signal numbers
1465 */
1466 const char msg[] =
1467 "invalid signal number %ld, please use valid_signals()";
1468 if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1469 goto error;
1470 }
1471 }
1472 }
1473 if (!PyErr_Occurred()) {
1474 Py_DECREF(iterator);
1475 return 1;
1476 }
1477
1478 error:
1479 Py_DECREF(iterator);
1480 return 0;
1481 }
1482 #endif /* HAVE_SIGSET_T */
1483
1484 #ifdef MS_WINDOWS
1485
1486 static int
win32_get_reparse_tag(HANDLE reparse_point_handle,ULONG * reparse_tag)1487 win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1488 {
1489 char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1490 _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1491 DWORD n_bytes_returned;
1492
1493 if (0 == DeviceIoControl(
1494 reparse_point_handle,
1495 FSCTL_GET_REPARSE_POINT,
1496 NULL, 0, /* in buffer */
1497 target_buffer, sizeof(target_buffer),
1498 &n_bytes_returned,
1499 NULL)) /* we're not using OVERLAPPED_IO */
1500 return FALSE;
1501
1502 if (reparse_tag)
1503 *reparse_tag = rdb->ReparseTag;
1504
1505 return TRUE;
1506 }
1507
1508 #endif /* MS_WINDOWS */
1509
1510 /* Return a dictionary corresponding to the POSIX environment table */
1511 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1512 /* On Darwin/MacOSX a shared library or framework has no access to
1513 ** environ directly, we must obtain it with _NSGetEnviron(). See also
1514 ** man environ(7).
1515 */
1516 #include <crt_externs.h>
1517 #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1518 extern char **environ;
1519 #endif /* !_MSC_VER */
1520
1521 static PyObject *
convertenviron(void)1522 convertenviron(void)
1523 {
1524 PyObject *d;
1525 #ifdef MS_WINDOWS
1526 wchar_t **e;
1527 #else
1528 char **e;
1529 #endif
1530
1531 d = PyDict_New();
1532 if (d == NULL)
1533 return NULL;
1534 #ifdef MS_WINDOWS
1535 /* _wenviron must be initialized in this way if the program is started
1536 through main() instead of wmain(). */
1537 _wgetenv(L"");
1538 e = _wenviron;
1539 #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1540 /* environ is not accessible as an extern in a shared object on OSX; use
1541 _NSGetEnviron to resolve it. The value changes if you add environment
1542 variables between calls to Py_Initialize, so don't cache the value. */
1543 e = *_NSGetEnviron();
1544 #else
1545 e = environ;
1546 #endif
1547 if (e == NULL)
1548 return d;
1549 for (; *e != NULL; e++) {
1550 PyObject *k;
1551 PyObject *v;
1552 #ifdef MS_WINDOWS
1553 const wchar_t *p = wcschr(*e, L'=');
1554 #else
1555 const char *p = strchr(*e, '=');
1556 #endif
1557 if (p == NULL)
1558 continue;
1559 #ifdef MS_WINDOWS
1560 k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1561 #else
1562 k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1563 #endif
1564 if (k == NULL) {
1565 Py_DECREF(d);
1566 return NULL;
1567 }
1568 #ifdef MS_WINDOWS
1569 v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1570 #else
1571 v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1572 #endif
1573 if (v == NULL) {
1574 Py_DECREF(k);
1575 Py_DECREF(d);
1576 return NULL;
1577 }
1578 if (PyDict_GetItemWithError(d, k) == NULL) {
1579 if (PyErr_Occurred() || PyDict_SetItem(d, k, v) != 0) {
1580 Py_DECREF(v);
1581 Py_DECREF(k);
1582 Py_DECREF(d);
1583 return NULL;
1584 }
1585 }
1586 Py_DECREF(k);
1587 Py_DECREF(v);
1588 }
1589 return d;
1590 }
1591
1592 /* Set a POSIX-specific error from errno, and return NULL */
1593
1594 static PyObject *
posix_error(void)1595 posix_error(void)
1596 {
1597 return PyErr_SetFromErrno(PyExc_OSError);
1598 }
1599
1600 #ifdef MS_WINDOWS
1601 static PyObject *
win32_error(const char * function,const char * filename)1602 win32_error(const char* function, const char* filename)
1603 {
1604 /* XXX We should pass the function name along in the future.
1605 (winreg.c also wants to pass the function name.)
1606 This would however require an additional param to the
1607 Windows error object, which is non-trivial.
1608 */
1609 errno = GetLastError();
1610 if (filename)
1611 return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1612 else
1613 return PyErr_SetFromWindowsErr(errno);
1614 }
1615
1616 static PyObject *
win32_error_object_err(const char * function,PyObject * filename,DWORD err)1617 win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1618 {
1619 /* XXX - see win32_error for comments on 'function' */
1620 if (filename)
1621 return PyErr_SetExcFromWindowsErrWithFilenameObject(
1622 PyExc_OSError,
1623 err,
1624 filename);
1625 else
1626 return PyErr_SetFromWindowsErr(err);
1627 }
1628
1629 static PyObject *
win32_error_object(const char * function,PyObject * filename)1630 win32_error_object(const char* function, PyObject* filename)
1631 {
1632 errno = GetLastError();
1633 return win32_error_object_err(function, filename, errno);
1634 }
1635
1636 #endif /* MS_WINDOWS */
1637
1638 static PyObject *
posix_path_object_error(PyObject * path)1639 posix_path_object_error(PyObject *path)
1640 {
1641 return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1642 }
1643
1644 static PyObject *
path_object_error(PyObject * path)1645 path_object_error(PyObject *path)
1646 {
1647 #ifdef MS_WINDOWS
1648 return PyErr_SetExcFromWindowsErrWithFilenameObject(
1649 PyExc_OSError, 0, path);
1650 #else
1651 return posix_path_object_error(path);
1652 #endif
1653 }
1654
1655 static PyObject *
path_object_error2(PyObject * path,PyObject * path2)1656 path_object_error2(PyObject *path, PyObject *path2)
1657 {
1658 #ifdef MS_WINDOWS
1659 return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1660 PyExc_OSError, 0, path, path2);
1661 #else
1662 return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1663 #endif
1664 }
1665
1666 static PyObject *
path_error(path_t * path)1667 path_error(path_t *path)
1668 {
1669 return path_object_error(path->object);
1670 }
1671
1672 static PyObject *
posix_path_error(path_t * path)1673 posix_path_error(path_t *path)
1674 {
1675 return posix_path_object_error(path->object);
1676 }
1677
1678 static PyObject *
path_error2(path_t * path,path_t * path2)1679 path_error2(path_t *path, path_t *path2)
1680 {
1681 return path_object_error2(path->object, path2->object);
1682 }
1683
1684
1685 /* POSIX generic methods */
1686
1687 static int
fildes_converter(PyObject * o,void * p)1688 fildes_converter(PyObject *o, void *p)
1689 {
1690 int fd;
1691 int *pointer = (int *)p;
1692 fd = PyObject_AsFileDescriptor(o);
1693 if (fd < 0)
1694 return 0;
1695 *pointer = fd;
1696 return 1;
1697 }
1698
1699 static PyObject *
posix_fildes_fd(int fd,int (* func)(int))1700 posix_fildes_fd(int fd, int (*func)(int))
1701 {
1702 int res;
1703 int async_err = 0;
1704
1705 do {
1706 Py_BEGIN_ALLOW_THREADS
1707 _Py_BEGIN_SUPPRESS_IPH
1708 res = (*func)(fd);
1709 _Py_END_SUPPRESS_IPH
1710 Py_END_ALLOW_THREADS
1711 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1712 if (res != 0)
1713 return (!async_err) ? posix_error() : NULL;
1714 Py_RETURN_NONE;
1715 }
1716
1717
1718 #ifdef MS_WINDOWS
1719 /* This is a reimplementation of the C library's chdir function,
1720 but one that produces Win32 errors instead of DOS error codes.
1721 chdir is essentially a wrapper around SetCurrentDirectory; however,
1722 it also needs to set "magic" environment variables indicating
1723 the per-drive current directory, which are of the form =<drive>: */
1724 static BOOL __stdcall
win32_wchdir(LPCWSTR path)1725 win32_wchdir(LPCWSTR path)
1726 {
1727 wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1728 int result;
1729 wchar_t env[4] = L"=x:";
1730
1731 if(!SetCurrentDirectoryW(path))
1732 return FALSE;
1733 result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1734 if (!result)
1735 return FALSE;
1736 if (result > Py_ARRAY_LENGTH(path_buf)) {
1737 new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1738 if (!new_path) {
1739 SetLastError(ERROR_OUTOFMEMORY);
1740 return FALSE;
1741 }
1742 result = GetCurrentDirectoryW(result, new_path);
1743 if (!result) {
1744 PyMem_RawFree(new_path);
1745 return FALSE;
1746 }
1747 }
1748 int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1749 wcsncmp(new_path, L"//", 2) == 0);
1750 if (!is_unc_like_path) {
1751 env[1] = new_path[0];
1752 result = SetEnvironmentVariableW(env, new_path);
1753 }
1754 if (new_path != path_buf)
1755 PyMem_RawFree(new_path);
1756 return result ? TRUE : FALSE;
1757 }
1758 #endif
1759
1760 #ifdef MS_WINDOWS
1761 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1762 - time stamps are restricted to second resolution
1763 - file modification times suffer from forth-and-back conversions between
1764 UTC and local time
1765 Therefore, we implement our own stat, based on the Win32 API directly.
1766 */
1767 #define HAVE_STAT_NSEC 1
1768 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1769 #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1770
1771 static void
find_data_to_file_info(WIN32_FIND_DATAW * pFileData,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1772 find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1773 BY_HANDLE_FILE_INFORMATION *info,
1774 ULONG *reparse_tag)
1775 {
1776 memset(info, 0, sizeof(*info));
1777 info->dwFileAttributes = pFileData->dwFileAttributes;
1778 info->ftCreationTime = pFileData->ftCreationTime;
1779 info->ftLastAccessTime = pFileData->ftLastAccessTime;
1780 info->ftLastWriteTime = pFileData->ftLastWriteTime;
1781 info->nFileSizeHigh = pFileData->nFileSizeHigh;
1782 info->nFileSizeLow = pFileData->nFileSizeLow;
1783 /* info->nNumberOfLinks = 1; */
1784 if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1785 *reparse_tag = pFileData->dwReserved0;
1786 else
1787 *reparse_tag = 0;
1788 }
1789
1790 static BOOL
attributes_from_dir(LPCWSTR pszFile,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1791 attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1792 {
1793 HANDLE hFindFile;
1794 WIN32_FIND_DATAW FileData;
1795 hFindFile = FindFirstFileW(pszFile, &FileData);
1796 if (hFindFile == INVALID_HANDLE_VALUE)
1797 return FALSE;
1798 FindClose(hFindFile);
1799 find_data_to_file_info(&FileData, info, reparse_tag);
1800 return TRUE;
1801 }
1802
1803 static int
win32_xstat_impl(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1804 win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1805 BOOL traverse)
1806 {
1807 HANDLE hFile;
1808 BY_HANDLE_FILE_INFORMATION fileInfo;
1809 FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1810 DWORD fileType, error;
1811 BOOL isUnhandledTag = FALSE;
1812 int retval = 0;
1813
1814 DWORD access = FILE_READ_ATTRIBUTES;
1815 DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1816 if (!traverse) {
1817 flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1818 }
1819
1820 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1821 if (hFile == INVALID_HANDLE_VALUE) {
1822 /* Either the path doesn't exist, or the caller lacks access. */
1823 error = GetLastError();
1824 switch (error) {
1825 case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */
1826 case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1827 /* Try reading the parent directory. */
1828 if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1829 /* Cannot read the parent directory. */
1830 SetLastError(error);
1831 return -1;
1832 }
1833 if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1834 if (traverse ||
1835 !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1836 /* The stat call has to traverse but cannot, so fail. */
1837 SetLastError(error);
1838 return -1;
1839 }
1840 }
1841 break;
1842
1843 case ERROR_INVALID_PARAMETER:
1844 /* \\.\con requires read or write access. */
1845 hFile = CreateFileW(path, access | GENERIC_READ,
1846 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1847 OPEN_EXISTING, flags, NULL);
1848 if (hFile == INVALID_HANDLE_VALUE) {
1849 SetLastError(error);
1850 return -1;
1851 }
1852 break;
1853
1854 case ERROR_CANT_ACCESS_FILE:
1855 /* bpo37834: open unhandled reparse points if traverse fails. */
1856 if (traverse) {
1857 traverse = FALSE;
1858 isUnhandledTag = TRUE;
1859 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1860 flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1861 }
1862 if (hFile == INVALID_HANDLE_VALUE) {
1863 SetLastError(error);
1864 return -1;
1865 }
1866 break;
1867
1868 default:
1869 return -1;
1870 }
1871 }
1872
1873 if (hFile != INVALID_HANDLE_VALUE) {
1874 /* Handle types other than files on disk. */
1875 fileType = GetFileType(hFile);
1876 if (fileType != FILE_TYPE_DISK) {
1877 if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1878 retval = -1;
1879 goto cleanup;
1880 }
1881 DWORD fileAttributes = GetFileAttributesW(path);
1882 memset(result, 0, sizeof(*result));
1883 if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1884 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1885 /* \\.\pipe\ or \\.\mailslot\ */
1886 result->st_mode = _S_IFDIR;
1887 } else if (fileType == FILE_TYPE_CHAR) {
1888 /* \\.\nul */
1889 result->st_mode = _S_IFCHR;
1890 } else if (fileType == FILE_TYPE_PIPE) {
1891 /* \\.\pipe\spam */
1892 result->st_mode = _S_IFIFO;
1893 }
1894 /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1895 goto cleanup;
1896 }
1897
1898 /* Query the reparse tag, and traverse a non-link. */
1899 if (!traverse) {
1900 if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
1901 &tagInfo, sizeof(tagInfo))) {
1902 /* Allow devices that do not support FileAttributeTagInfo. */
1903 switch (GetLastError()) {
1904 case ERROR_INVALID_PARAMETER:
1905 case ERROR_INVALID_FUNCTION:
1906 case ERROR_NOT_SUPPORTED:
1907 tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1908 tagInfo.ReparseTag = 0;
1909 break;
1910 default:
1911 retval = -1;
1912 goto cleanup;
1913 }
1914 } else if (tagInfo.FileAttributes &
1915 FILE_ATTRIBUTE_REPARSE_POINT) {
1916 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1917 if (isUnhandledTag) {
1918 /* Traversing previously failed for either this link
1919 or its target. */
1920 SetLastError(ERROR_CANT_ACCESS_FILE);
1921 retval = -1;
1922 goto cleanup;
1923 }
1924 /* Traverse a non-link, but not if traversing already failed
1925 for an unhandled tag. */
1926 } else if (!isUnhandledTag) {
1927 CloseHandle(hFile);
1928 return win32_xstat_impl(path, result, TRUE);
1929 }
1930 }
1931 }
1932
1933 if (!GetFileInformationByHandle(hFile, &fileInfo)) {
1934 switch (GetLastError()) {
1935 case ERROR_INVALID_PARAMETER:
1936 case ERROR_INVALID_FUNCTION:
1937 case ERROR_NOT_SUPPORTED:
1938 /* Volumes and physical disks are block devices, e.g.
1939 \\.\C: and \\.\PhysicalDrive0. */
1940 memset(result, 0, sizeof(*result));
1941 result->st_mode = 0x6000; /* S_IFBLK */
1942 goto cleanup;
1943 }
1944 retval = -1;
1945 goto cleanup;
1946 }
1947 }
1948
1949 _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
1950
1951 if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
1952 /* Fix the file execute permissions. This hack sets S_IEXEC if
1953 the filename has an extension that is commonly used by files
1954 that CreateProcessW can execute. A real implementation calls
1955 GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
1956 AccessCheck to check for generic read, write, and execute
1957 access. */
1958 const wchar_t *fileExtension = wcsrchr(path, '.');
1959 if (fileExtension) {
1960 if (_wcsicmp(fileExtension, L".exe") == 0 ||
1961 _wcsicmp(fileExtension, L".bat") == 0 ||
1962 _wcsicmp(fileExtension, L".cmd") == 0 ||
1963 _wcsicmp(fileExtension, L".com") == 0) {
1964 result->st_mode |= 0111;
1965 }
1966 }
1967 }
1968
1969 cleanup:
1970 if (hFile != INVALID_HANDLE_VALUE) {
1971 /* Preserve last error if we are failing */
1972 error = retval ? GetLastError() : 0;
1973 if (!CloseHandle(hFile)) {
1974 retval = -1;
1975 } else if (retval) {
1976 /* Restore last error */
1977 SetLastError(error);
1978 }
1979 }
1980
1981 return retval;
1982 }
1983
1984 static int
win32_xstat(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1985 win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
1986 {
1987 /* Protocol violation: we explicitly clear errno, instead of
1988 setting it to a POSIX error. Callers should use GetLastError. */
1989 int code = win32_xstat_impl(path, result, traverse);
1990 errno = 0;
1991 return code;
1992 }
1993 /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
1994
1995 In Posix, stat automatically traverses symlinks and returns the stat
1996 structure for the target. In Windows, the equivalent GetFileAttributes by
1997 default does not traverse symlinks and instead returns attributes for
1998 the symlink.
1999
2000 Instead, we will open the file (which *does* traverse symlinks by default)
2001 and GetFileInformationByHandle(). */
2002
2003 static int
win32_lstat(const wchar_t * path,struct _Py_stat_struct * result)2004 win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2005 {
2006 return win32_xstat(path, result, FALSE);
2007 }
2008
2009 static int
win32_stat(const wchar_t * path,struct _Py_stat_struct * result)2010 win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2011 {
2012 return win32_xstat(path, result, TRUE);
2013 }
2014
2015 #endif /* MS_WINDOWS */
2016
2017 PyDoc_STRVAR(stat_result__doc__,
2018 "stat_result: Result from stat, fstat, or lstat.\n\n\
2019 This object may be accessed either as a tuple of\n\
2020 (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2021 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2022 \n\
2023 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2024 or st_flags, they are available as attributes only.\n\
2025 \n\
2026 See os.stat for more information.");
2027
2028 static PyStructSequence_Field stat_result_fields[] = {
2029 {"st_mode", "protection bits"},
2030 {"st_ino", "inode"},
2031 {"st_dev", "device"},
2032 {"st_nlink", "number of hard links"},
2033 {"st_uid", "user ID of owner"},
2034 {"st_gid", "group ID of owner"},
2035 {"st_size", "total size, in bytes"},
2036 /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2037 {NULL, "integer time of last access"},
2038 {NULL, "integer time of last modification"},
2039 {NULL, "integer time of last change"},
2040 {"st_atime", "time of last access"},
2041 {"st_mtime", "time of last modification"},
2042 {"st_ctime", "time of last change"},
2043 {"st_atime_ns", "time of last access in nanoseconds"},
2044 {"st_mtime_ns", "time of last modification in nanoseconds"},
2045 {"st_ctime_ns", "time of last change in nanoseconds"},
2046 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2047 {"st_blksize", "blocksize for filesystem I/O"},
2048 #endif
2049 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2050 {"st_blocks", "number of blocks allocated"},
2051 #endif
2052 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2053 {"st_rdev", "device type (if inode device)"},
2054 #endif
2055 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2056 {"st_flags", "user defined flags for file"},
2057 #endif
2058 #ifdef HAVE_STRUCT_STAT_ST_GEN
2059 {"st_gen", "generation number"},
2060 #endif
2061 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2062 {"st_birthtime", "time of creation"},
2063 #endif
2064 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2065 {"st_file_attributes", "Windows file attribute bits"},
2066 #endif
2067 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2068 {"st_fstype", "Type of filesystem"},
2069 #endif
2070 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2071 {"st_reparse_tag", "Windows reparse tag"},
2072 #endif
2073 {0}
2074 };
2075
2076 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2077 #define ST_BLKSIZE_IDX 16
2078 #else
2079 #define ST_BLKSIZE_IDX 15
2080 #endif
2081
2082 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2083 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2084 #else
2085 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2086 #endif
2087
2088 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2089 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2090 #else
2091 #define ST_RDEV_IDX ST_BLOCKS_IDX
2092 #endif
2093
2094 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2095 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2096 #else
2097 #define ST_FLAGS_IDX ST_RDEV_IDX
2098 #endif
2099
2100 #ifdef HAVE_STRUCT_STAT_ST_GEN
2101 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
2102 #else
2103 #define ST_GEN_IDX ST_FLAGS_IDX
2104 #endif
2105
2106 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2107 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2108 #else
2109 #define ST_BIRTHTIME_IDX ST_GEN_IDX
2110 #endif
2111
2112 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2113 #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
2114 #else
2115 #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
2116 #endif
2117
2118 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2119 #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2120 #else
2121 #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2122 #endif
2123
2124 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2125 #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2126 #else
2127 #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2128 #endif
2129
2130 static PyStructSequence_Desc stat_result_desc = {
2131 "stat_result", /* name */
2132 stat_result__doc__, /* doc */
2133 stat_result_fields,
2134 10
2135 };
2136
2137 PyDoc_STRVAR(statvfs_result__doc__,
2138 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
2139 This object may be accessed either as a tuple of\n\
2140 (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2141 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2142 \n\
2143 See os.statvfs for more information.");
2144
2145 static PyStructSequence_Field statvfs_result_fields[] = {
2146 {"f_bsize", },
2147 {"f_frsize", },
2148 {"f_blocks", },
2149 {"f_bfree", },
2150 {"f_bavail", },
2151 {"f_files", },
2152 {"f_ffree", },
2153 {"f_favail", },
2154 {"f_flag", },
2155 {"f_namemax",},
2156 {"f_fsid", },
2157 {0}
2158 };
2159
2160 static PyStructSequence_Desc statvfs_result_desc = {
2161 "statvfs_result", /* name */
2162 statvfs_result__doc__, /* doc */
2163 statvfs_result_fields,
2164 10
2165 };
2166
2167 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2168 PyDoc_STRVAR(waitid_result__doc__,
2169 "waitid_result: Result from waitid.\n\n\
2170 This object may be accessed either as a tuple of\n\
2171 (si_pid, si_uid, si_signo, si_status, si_code),\n\
2172 or via the attributes si_pid, si_uid, and so on.\n\
2173 \n\
2174 See os.waitid for more information.");
2175
2176 static PyStructSequence_Field waitid_result_fields[] = {
2177 {"si_pid", },
2178 {"si_uid", },
2179 {"si_signo", },
2180 {"si_status", },
2181 {"si_code", },
2182 {0}
2183 };
2184
2185 static PyStructSequence_Desc waitid_result_desc = {
2186 "waitid_result", /* name */
2187 waitid_result__doc__, /* doc */
2188 waitid_result_fields,
2189 5
2190 };
2191 #endif
2192 static newfunc structseq_new;
2193
2194 static PyObject *
statresult_new(PyTypeObject * type,PyObject * args,PyObject * kwds)2195 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2196 {
2197 PyStructSequence *result;
2198 int i;
2199
2200 result = (PyStructSequence*)structseq_new(type, args, kwds);
2201 if (!result)
2202 return NULL;
2203 /* If we have been initialized from a tuple,
2204 st_?time might be set to None. Initialize it
2205 from the int slots. */
2206 for (i = 7; i <= 9; i++) {
2207 if (result->ob_item[i+3] == Py_None) {
2208 Py_DECREF(Py_None);
2209 Py_INCREF(result->ob_item[i]);
2210 result->ob_item[i+3] = result->ob_item[i];
2211 }
2212 }
2213 return (PyObject*)result;
2214 }
2215
2216 static int
_posix_clear(PyObject * module)2217 _posix_clear(PyObject *module)
2218 {
2219 _posixstate *state = get_posix_state(module);
2220 Py_CLEAR(state->billion);
2221 Py_CLEAR(state->DirEntryType);
2222 Py_CLEAR(state->ScandirIteratorType);
2223 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2224 Py_CLEAR(state->SchedParamType);
2225 #endif
2226 Py_CLEAR(state->StatResultType);
2227 Py_CLEAR(state->StatVFSResultType);
2228 Py_CLEAR(state->TerminalSizeType);
2229 Py_CLEAR(state->TimesResultType);
2230 Py_CLEAR(state->UnameResultType);
2231 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2232 Py_CLEAR(state->WaitidResultType);
2233 #endif
2234 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2235 Py_CLEAR(state->struct_rusage);
2236 #endif
2237 Py_CLEAR(state->st_mode);
2238 return 0;
2239 }
2240
2241 static int
_posix_traverse(PyObject * module,visitproc visit,void * arg)2242 _posix_traverse(PyObject *module, visitproc visit, void *arg)
2243 {
2244 _posixstate *state = get_posix_state(module);
2245 Py_VISIT(state->billion);
2246 Py_VISIT(state->DirEntryType);
2247 Py_VISIT(state->ScandirIteratorType);
2248 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2249 Py_VISIT(state->SchedParamType);
2250 #endif
2251 Py_VISIT(state->StatResultType);
2252 Py_VISIT(state->StatVFSResultType);
2253 Py_VISIT(state->TerminalSizeType);
2254 Py_VISIT(state->TimesResultType);
2255 Py_VISIT(state->UnameResultType);
2256 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2257 Py_VISIT(state->WaitidResultType);
2258 #endif
2259 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2260 Py_VISIT(state->struct_rusage);
2261 #endif
2262 Py_VISIT(state->st_mode);
2263 return 0;
2264 }
2265
2266 static void
_posix_free(void * module)2267 _posix_free(void *module)
2268 {
2269 _posix_clear((PyObject *)module);
2270 }
2271
2272 static void
fill_time(PyObject * module,PyObject * v,int index,time_t sec,unsigned long nsec)2273 fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)
2274 {
2275 PyObject *s = _PyLong_FromTime_t(sec);
2276 PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2277 PyObject *s_in_ns = NULL;
2278 PyObject *ns_total = NULL;
2279 PyObject *float_s = NULL;
2280
2281 if (!(s && ns_fractional))
2282 goto exit;
2283
2284 s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2285 if (!s_in_ns)
2286 goto exit;
2287
2288 ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2289 if (!ns_total)
2290 goto exit;
2291
2292 float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2293 if (!float_s) {
2294 goto exit;
2295 }
2296
2297 PyStructSequence_SET_ITEM(v, index, s);
2298 PyStructSequence_SET_ITEM(v, index+3, float_s);
2299 PyStructSequence_SET_ITEM(v, index+6, ns_total);
2300 s = NULL;
2301 float_s = NULL;
2302 ns_total = NULL;
2303 exit:
2304 Py_XDECREF(s);
2305 Py_XDECREF(ns_fractional);
2306 Py_XDECREF(s_in_ns);
2307 Py_XDECREF(ns_total);
2308 Py_XDECREF(float_s);
2309 }
2310
2311 /* pack a system stat C structure into the Python stat tuple
2312 (used by posix_stat() and posix_fstat()) */
2313 static PyObject*
_pystat_fromstructstat(PyObject * module,STRUCT_STAT * st)2314 _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2315 {
2316 unsigned long ansec, mnsec, cnsec;
2317 PyObject *StatResultType = get_posix_state(module)->StatResultType;
2318 PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2319 if (v == NULL)
2320 return NULL;
2321
2322 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2323 Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(st->st_ino));
2324 PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2325 #ifdef MS_WINDOWS
2326 PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
2327 #else
2328 PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2329 #endif
2330 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2331 #if defined(MS_WINDOWS)
2332 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2333 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2334 #else
2335 PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2336 PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2337 #endif
2338 Py_BUILD_ASSERT(sizeof(long long) >= sizeof(st->st_size));
2339 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2340
2341 #if defined(HAVE_STAT_TV_NSEC)
2342 ansec = st->st_atim.tv_nsec;
2343 mnsec = st->st_mtim.tv_nsec;
2344 cnsec = st->st_ctim.tv_nsec;
2345 #elif defined(HAVE_STAT_TV_NSEC2)
2346 ansec = st->st_atimespec.tv_nsec;
2347 mnsec = st->st_mtimespec.tv_nsec;
2348 cnsec = st->st_ctimespec.tv_nsec;
2349 #elif defined(HAVE_STAT_NSEC)
2350 ansec = st->st_atime_nsec;
2351 mnsec = st->st_mtime_nsec;
2352 cnsec = st->st_ctime_nsec;
2353 #else
2354 ansec = mnsec = cnsec = 0;
2355 #endif
2356 fill_time(module, v, 7, st->st_atime, ansec);
2357 fill_time(module, v, 8, st->st_mtime, mnsec);
2358 fill_time(module, v, 9, st->st_ctime, cnsec);
2359
2360 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2361 PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2362 PyLong_FromLong((long)st->st_blksize));
2363 #endif
2364 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2365 PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2366 PyLong_FromLong((long)st->st_blocks));
2367 #endif
2368 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2369 PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2370 PyLong_FromLong((long)st->st_rdev));
2371 #endif
2372 #ifdef HAVE_STRUCT_STAT_ST_GEN
2373 PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2374 PyLong_FromLong((long)st->st_gen));
2375 #endif
2376 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2377 {
2378 PyObject *val;
2379 unsigned long bsec,bnsec;
2380 bsec = (long)st->st_birthtime;
2381 #ifdef HAVE_STAT_TV_NSEC2
2382 bnsec = st->st_birthtimespec.tv_nsec;
2383 #else
2384 bnsec = 0;
2385 #endif
2386 val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2387 PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2388 val);
2389 }
2390 #endif
2391 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2392 PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2393 PyLong_FromLong((long)st->st_flags));
2394 #endif
2395 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2396 PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2397 PyLong_FromUnsignedLong(st->st_file_attributes));
2398 #endif
2399 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2400 PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2401 PyUnicode_FromString(st->st_fstype));
2402 #endif
2403 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2404 PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2405 PyLong_FromUnsignedLong(st->st_reparse_tag));
2406 #endif
2407
2408 if (PyErr_Occurred()) {
2409 Py_DECREF(v);
2410 return NULL;
2411 }
2412
2413 return v;
2414 }
2415
2416 /* POSIX methods */
2417
2418
2419 static PyObject *
posix_do_stat(PyObject * module,const char * function_name,path_t * path,int dir_fd,int follow_symlinks)2420 posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2421 int dir_fd, int follow_symlinks)
2422 {
2423 STRUCT_STAT st;
2424 int result;
2425
2426 #ifdef HAVE_FSTATAT
2427 int fstatat_unavailable = 0;
2428 #endif
2429
2430 #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2431 if (follow_symlinks_specified(function_name, follow_symlinks))
2432 return NULL;
2433 #endif
2434
2435 if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2436 dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2437 fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2438 return NULL;
2439
2440 Py_BEGIN_ALLOW_THREADS
2441 if (path->fd != -1)
2442 result = FSTAT(path->fd, &st);
2443 #ifdef MS_WINDOWS
2444 else if (follow_symlinks)
2445 result = win32_stat(path->wide, &st);
2446 else
2447 result = win32_lstat(path->wide, &st);
2448 #else
2449 else
2450 #if defined(HAVE_LSTAT)
2451 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2452 result = LSTAT(path->narrow, &st);
2453 else
2454 #endif /* HAVE_LSTAT */
2455 #ifdef HAVE_FSTATAT
2456 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2457 if (HAVE_FSTATAT_RUNTIME) {
2458 result = fstatat(dir_fd, path->narrow, &st,
2459 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2460
2461 } else {
2462 fstatat_unavailable = 1;
2463 }
2464 } else
2465 #endif /* HAVE_FSTATAT */
2466 result = STAT(path->narrow, &st);
2467 #endif /* MS_WINDOWS */
2468 Py_END_ALLOW_THREADS
2469
2470 #ifdef HAVE_FSTATAT
2471 if (fstatat_unavailable) {
2472 argument_unavailable_error("stat", "dir_fd");
2473 return NULL;
2474 }
2475 #endif
2476
2477 if (result != 0) {
2478 return path_error(path);
2479 }
2480
2481 return _pystat_fromstructstat(module, &st);
2482 }
2483
2484 /*[python input]
2485
2486 for s in """
2487
2488 FACCESSAT
2489 FCHMODAT
2490 FCHOWNAT
2491 FSTATAT
2492 LINKAT
2493 MKDIRAT
2494 MKFIFOAT
2495 MKNODAT
2496 OPENAT
2497 READLINKAT
2498 SYMLINKAT
2499 UNLINKAT
2500
2501 """.strip().split():
2502 s = s.strip()
2503 print("""
2504 #ifdef HAVE_{s}
2505 #define {s}_DIR_FD_CONVERTER dir_fd_converter
2506 #else
2507 #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2508 #endif
2509 """.rstrip().format(s=s))
2510
2511 for s in """
2512
2513 FCHDIR
2514 FCHMOD
2515 FCHOWN
2516 FDOPENDIR
2517 FEXECVE
2518 FPATHCONF
2519 FSTATVFS
2520 FTRUNCATE
2521
2522 """.strip().split():
2523 s = s.strip()
2524 print("""
2525 #ifdef HAVE_{s}
2526 #define PATH_HAVE_{s} 1
2527 #else
2528 #define PATH_HAVE_{s} 0
2529 #endif
2530
2531 """.rstrip().format(s=s))
2532 [python start generated code]*/
2533
2534 #ifdef HAVE_FACCESSAT
2535 #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2536 #else
2537 #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2538 #endif
2539
2540 #ifdef HAVE_FCHMODAT
2541 #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2542 #else
2543 #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2544 #endif
2545
2546 #ifdef HAVE_FCHOWNAT
2547 #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2548 #else
2549 #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2550 #endif
2551
2552 #ifdef HAVE_FSTATAT
2553 #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2554 #else
2555 #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2556 #endif
2557
2558 #ifdef HAVE_LINKAT
2559 #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2560 #else
2561 #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2562 #endif
2563
2564 #ifdef HAVE_MKDIRAT
2565 #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2566 #else
2567 #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2568 #endif
2569
2570 #ifdef HAVE_MKFIFOAT
2571 #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2572 #else
2573 #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2574 #endif
2575
2576 #ifdef HAVE_MKNODAT
2577 #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2578 #else
2579 #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2580 #endif
2581
2582 #ifdef HAVE_OPENAT
2583 #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2584 #else
2585 #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2586 #endif
2587
2588 #ifdef HAVE_READLINKAT
2589 #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2590 #else
2591 #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2592 #endif
2593
2594 #ifdef HAVE_SYMLINKAT
2595 #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2596 #else
2597 #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2598 #endif
2599
2600 #ifdef HAVE_UNLINKAT
2601 #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2602 #else
2603 #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2604 #endif
2605
2606 #ifdef HAVE_FCHDIR
2607 #define PATH_HAVE_FCHDIR 1
2608 #else
2609 #define PATH_HAVE_FCHDIR 0
2610 #endif
2611
2612 #ifdef HAVE_FCHMOD
2613 #define PATH_HAVE_FCHMOD 1
2614 #else
2615 #define PATH_HAVE_FCHMOD 0
2616 #endif
2617
2618 #ifdef HAVE_FCHOWN
2619 #define PATH_HAVE_FCHOWN 1
2620 #else
2621 #define PATH_HAVE_FCHOWN 0
2622 #endif
2623
2624 #ifdef HAVE_FDOPENDIR
2625 #define PATH_HAVE_FDOPENDIR 1
2626 #else
2627 #define PATH_HAVE_FDOPENDIR 0
2628 #endif
2629
2630 #ifdef HAVE_FEXECVE
2631 #define PATH_HAVE_FEXECVE 1
2632 #else
2633 #define PATH_HAVE_FEXECVE 0
2634 #endif
2635
2636 #ifdef HAVE_FPATHCONF
2637 #define PATH_HAVE_FPATHCONF 1
2638 #else
2639 #define PATH_HAVE_FPATHCONF 0
2640 #endif
2641
2642 #ifdef HAVE_FSTATVFS
2643 #define PATH_HAVE_FSTATVFS 1
2644 #else
2645 #define PATH_HAVE_FSTATVFS 0
2646 #endif
2647
2648 #ifdef HAVE_FTRUNCATE
2649 #define PATH_HAVE_FTRUNCATE 1
2650 #else
2651 #define PATH_HAVE_FTRUNCATE 0
2652 #endif
2653 /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2654
2655 #ifdef MS_WINDOWS
2656 #undef PATH_HAVE_FTRUNCATE
2657 #define PATH_HAVE_FTRUNCATE 1
2658 #endif
2659
2660 /*[python input]
2661
2662 class path_t_converter(CConverter):
2663
2664 type = "path_t"
2665 impl_by_reference = True
2666 parse_by_reference = True
2667
2668 converter = 'path_converter'
2669
2670 def converter_init(self, *, allow_fd=False, nullable=False):
2671 # right now path_t doesn't support default values.
2672 # to support a default value, you'll need to override initialize().
2673 if self.default not in (unspecified, None):
2674 fail("Can't specify a default to the path_t converter!")
2675
2676 if self.c_default not in (None, 'Py_None'):
2677 raise RuntimeError("Can't specify a c_default to the path_t converter!")
2678
2679 self.nullable = nullable
2680 self.allow_fd = allow_fd
2681
2682 def pre_render(self):
2683 def strify(value):
2684 if isinstance(value, str):
2685 return value
2686 return str(int(bool(value)))
2687
2688 # add self.py_name here when merging with posixmodule conversion
2689 self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2690 self.function.name,
2691 self.name,
2692 strify(self.nullable),
2693 strify(self.allow_fd),
2694 )
2695
2696 def cleanup(self):
2697 return "path_cleanup(&" + self.name + ");\n"
2698
2699
2700 class dir_fd_converter(CConverter):
2701 type = 'int'
2702
2703 def converter_init(self, requires=None):
2704 if self.default in (unspecified, None):
2705 self.c_default = 'DEFAULT_DIR_FD'
2706 if isinstance(requires, str):
2707 self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2708 else:
2709 self.converter = 'dir_fd_converter'
2710
2711 class fildes_converter(CConverter):
2712 type = 'int'
2713 converter = 'fildes_converter'
2714
2715 class uid_t_converter(CConverter):
2716 type = "uid_t"
2717 converter = '_Py_Uid_Converter'
2718
2719 class gid_t_converter(CConverter):
2720 type = "gid_t"
2721 converter = '_Py_Gid_Converter'
2722
2723 class dev_t_converter(CConverter):
2724 type = 'dev_t'
2725 converter = '_Py_Dev_Converter'
2726
2727 class dev_t_return_converter(unsigned_long_return_converter):
2728 type = 'dev_t'
2729 conversion_fn = '_PyLong_FromDev'
2730 unsigned_cast = '(dev_t)'
2731
2732 class FSConverter_converter(CConverter):
2733 type = 'PyObject *'
2734 converter = 'PyUnicode_FSConverter'
2735 def converter_init(self):
2736 if self.default is not unspecified:
2737 fail("FSConverter_converter does not support default values")
2738 self.c_default = 'NULL'
2739
2740 def cleanup(self):
2741 return "Py_XDECREF(" + self.name + ");\n"
2742
2743 class pid_t_converter(CConverter):
2744 type = 'pid_t'
2745 format_unit = '" _Py_PARSE_PID "'
2746
2747 class idtype_t_converter(int_converter):
2748 type = 'idtype_t'
2749
2750 class id_t_converter(CConverter):
2751 type = 'id_t'
2752 format_unit = '" _Py_PARSE_PID "'
2753
2754 class intptr_t_converter(CConverter):
2755 type = 'intptr_t'
2756 format_unit = '" _Py_PARSE_INTPTR "'
2757
2758 class Py_off_t_converter(CConverter):
2759 type = 'Py_off_t'
2760 converter = 'Py_off_t_converter'
2761
2762 class Py_off_t_return_converter(long_return_converter):
2763 type = 'Py_off_t'
2764 conversion_fn = 'PyLong_FromPy_off_t'
2765
2766 class path_confname_converter(CConverter):
2767 type="int"
2768 converter="conv_path_confname"
2769
2770 class confstr_confname_converter(path_confname_converter):
2771 converter='conv_confstr_confname'
2772
2773 class sysconf_confname_converter(path_confname_converter):
2774 converter="conv_sysconf_confname"
2775
2776 [python start generated code]*/
2777 /*[python end generated code: output=da39a3ee5e6b4b0d input=f1c8ae8d744f6c8b]*/
2778
2779 /*[clinic input]
2780
2781 os.stat
2782
2783 path : path_t(allow_fd=True)
2784 Path to be examined; can be string, bytes, a path-like object or
2785 open-file-descriptor int.
2786
2787 *
2788
2789 dir_fd : dir_fd(requires='fstatat') = None
2790 If not None, it should be a file descriptor open to a directory,
2791 and path should be a relative string; path will then be relative to
2792 that directory.
2793
2794 follow_symlinks: bool = True
2795 If False, and the last element of the path is a symbolic link,
2796 stat will examine the symbolic link itself instead of the file
2797 the link points to.
2798
2799 Perform a stat system call on the given path.
2800
2801 dir_fd and follow_symlinks may not be implemented
2802 on your platform. If they are unavailable, using them will raise a
2803 NotImplementedError.
2804
2805 It's an error to use dir_fd or follow_symlinks when specifying path as
2806 an open file descriptor.
2807
2808 [clinic start generated code]*/
2809
2810 static PyObject *
os_stat_impl(PyObject * module,path_t * path,int dir_fd,int follow_symlinks)2811 os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2812 /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2813 {
2814 return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
2815 }
2816
2817
2818 /*[clinic input]
2819 os.lstat
2820
2821 path : path_t
2822
2823 *
2824
2825 dir_fd : dir_fd(requires='fstatat') = None
2826
2827 Perform a stat system call on the given path, without following symbolic links.
2828
2829 Like stat(), but do not follow symbolic links.
2830 Equivalent to stat(path, follow_symlinks=False).
2831 [clinic start generated code]*/
2832
2833 static PyObject *
os_lstat_impl(PyObject * module,path_t * path,int dir_fd)2834 os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2835 /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2836 {
2837 int follow_symlinks = 0;
2838 return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
2839 }
2840
2841
2842 /*[clinic input]
2843 os.access -> bool
2844
2845 path: path_t
2846 Path to be tested; can be string, bytes, or a path-like object.
2847
2848 mode: int
2849 Operating-system mode bitfield. Can be F_OK to test existence,
2850 or the inclusive-OR of R_OK, W_OK, and X_OK.
2851
2852 *
2853
2854 dir_fd : dir_fd(requires='faccessat') = None
2855 If not None, it should be a file descriptor open to a directory,
2856 and path should be relative; path will then be relative to that
2857 directory.
2858
2859 effective_ids: bool = False
2860 If True, access will use the effective uid/gid instead of
2861 the real uid/gid.
2862
2863 follow_symlinks: bool = True
2864 If False, and the last element of the path is a symbolic link,
2865 access will examine the symbolic link itself instead of the file
2866 the link points to.
2867
2868 Use the real uid/gid to test for access to a path.
2869
2870 {parameters}
2871 dir_fd, effective_ids, and follow_symlinks may not be implemented
2872 on your platform. If they are unavailable, using them will raise a
2873 NotImplementedError.
2874
2875 Note that most operations will use the effective uid/gid, therefore this
2876 routine can be used in a suid/sgid environment to test if the invoking user
2877 has the specified access to the path.
2878
2879 [clinic start generated code]*/
2880
2881 static int
os_access_impl(PyObject * module,path_t * path,int mode,int dir_fd,int effective_ids,int follow_symlinks)2882 os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2883 int effective_ids, int follow_symlinks)
2884 /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
2885 {
2886 int return_value;
2887
2888 #ifdef MS_WINDOWS
2889 DWORD attr;
2890 #else
2891 int result;
2892 #endif
2893
2894 #ifdef HAVE_FACCESSAT
2895 int faccessat_unavailable = 0;
2896 #endif
2897
2898 #ifndef HAVE_FACCESSAT
2899 if (follow_symlinks_specified("access", follow_symlinks))
2900 return -1;
2901
2902 if (effective_ids) {
2903 argument_unavailable_error("access", "effective_ids");
2904 return -1;
2905 }
2906 #endif
2907
2908 #ifdef MS_WINDOWS
2909 Py_BEGIN_ALLOW_THREADS
2910 attr = GetFileAttributesW(path->wide);
2911 Py_END_ALLOW_THREADS
2912
2913 /*
2914 * Access is possible if
2915 * * we didn't get a -1, and
2916 * * write access wasn't requested,
2917 * * or the file isn't read-only,
2918 * * or it's a directory.
2919 * (Directories cannot be read-only on Windows.)
2920 */
2921 return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
2922 (!(mode & 2) ||
2923 !(attr & FILE_ATTRIBUTE_READONLY) ||
2924 (attr & FILE_ATTRIBUTE_DIRECTORY));
2925 #else
2926
2927 Py_BEGIN_ALLOW_THREADS
2928 #ifdef HAVE_FACCESSAT
2929 if ((dir_fd != DEFAULT_DIR_FD) ||
2930 effective_ids ||
2931 !follow_symlinks) {
2932
2933 if (HAVE_FACCESSAT_RUNTIME) {
2934 int flags = 0;
2935 if (!follow_symlinks)
2936 flags |= AT_SYMLINK_NOFOLLOW;
2937 if (effective_ids)
2938 flags |= AT_EACCESS;
2939 result = faccessat(dir_fd, path->narrow, mode, flags);
2940 } else {
2941 faccessat_unavailable = 1;
2942 }
2943 }
2944 else
2945 #endif
2946 result = access(path->narrow, mode);
2947 Py_END_ALLOW_THREADS
2948
2949 #ifdef HAVE_FACCESSAT
2950 if (faccessat_unavailable) {
2951 if (dir_fd != DEFAULT_DIR_FD) {
2952 argument_unavailable_error("access", "dir_fd");
2953 return -1;
2954 }
2955 if (follow_symlinks_specified("access", follow_symlinks))
2956 return -1;
2957
2958 if (effective_ids) {
2959 argument_unavailable_error("access", "effective_ids");
2960 return -1;
2961 }
2962 /* should be unreachable */
2963 return -1;
2964 }
2965 #endif
2966 return_value = !result;
2967 #endif
2968
2969 return return_value;
2970 }
2971
2972 #ifndef F_OK
2973 #define F_OK 0
2974 #endif
2975 #ifndef R_OK
2976 #define R_OK 4
2977 #endif
2978 #ifndef W_OK
2979 #define W_OK 2
2980 #endif
2981 #ifndef X_OK
2982 #define X_OK 1
2983 #endif
2984
2985
2986 #ifdef HAVE_TTYNAME
2987 /*[clinic input]
2988 os.ttyname
2989
2990 fd: int
2991 Integer file descriptor handle.
2992
2993 /
2994
2995 Return the name of the terminal device connected to 'fd'.
2996 [clinic start generated code]*/
2997
2998 static PyObject *
os_ttyname_impl(PyObject * module,int fd)2999 os_ttyname_impl(PyObject *module, int fd)
3000 /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3001 {
3002
3003 long size = sysconf(_SC_TTY_NAME_MAX);
3004 if (size == -1) {
3005 return posix_error();
3006 }
3007 char *buffer = (char *)PyMem_RawMalloc(size);
3008 if (buffer == NULL) {
3009 return PyErr_NoMemory();
3010 }
3011 int ret = ttyname_r(fd, buffer, size);
3012 if (ret != 0) {
3013 PyMem_RawFree(buffer);
3014 errno = ret;
3015 return posix_error();
3016 }
3017 PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3018 PyMem_RawFree(buffer);
3019 return res;
3020 }
3021 #endif
3022
3023 #ifdef HAVE_CTERMID
3024 /*[clinic input]
3025 os.ctermid
3026
3027 Return the name of the controlling terminal for this process.
3028 [clinic start generated code]*/
3029
3030 static PyObject *
os_ctermid_impl(PyObject * module)3031 os_ctermid_impl(PyObject *module)
3032 /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3033 {
3034 char *ret;
3035 char buffer[L_ctermid];
3036
3037 #ifdef USE_CTERMID_R
3038 ret = ctermid_r(buffer);
3039 #else
3040 ret = ctermid(buffer);
3041 #endif
3042 if (ret == NULL)
3043 return posix_error();
3044 return PyUnicode_DecodeFSDefault(buffer);
3045 }
3046 #endif /* HAVE_CTERMID */
3047
3048
3049 /*[clinic input]
3050 os.chdir
3051
3052 path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3053
3054 Change the current working directory to the specified path.
3055
3056 path may always be specified as a string.
3057 On some platforms, path may also be specified as an open file descriptor.
3058 If this functionality is unavailable, using it raises an exception.
3059 [clinic start generated code]*/
3060
3061 static PyObject *
os_chdir_impl(PyObject * module,path_t * path)3062 os_chdir_impl(PyObject *module, path_t *path)
3063 /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3064 {
3065 int result;
3066
3067 if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3068 return NULL;
3069 }
3070
3071 Py_BEGIN_ALLOW_THREADS
3072 #ifdef MS_WINDOWS
3073 /* on unix, success = 0, on windows, success = !0 */
3074 result = !win32_wchdir(path->wide);
3075 #else
3076 #ifdef HAVE_FCHDIR
3077 if (path->fd != -1)
3078 result = fchdir(path->fd);
3079 else
3080 #endif
3081 result = chdir(path->narrow);
3082 #endif
3083 Py_END_ALLOW_THREADS
3084
3085 if (result) {
3086 return path_error(path);
3087 }
3088
3089 Py_RETURN_NONE;
3090 }
3091
3092
3093 #ifdef HAVE_FCHDIR
3094 /*[clinic input]
3095 os.fchdir
3096
3097 fd: fildes
3098
3099 Change to the directory of the given file descriptor.
3100
3101 fd must be opened on a directory, not a file.
3102 Equivalent to os.chdir(fd).
3103
3104 [clinic start generated code]*/
3105
3106 static PyObject *
os_fchdir_impl(PyObject * module,int fd)3107 os_fchdir_impl(PyObject *module, int fd)
3108 /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3109 {
3110 if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3111 return NULL;
3112 }
3113 return posix_fildes_fd(fd, fchdir);
3114 }
3115 #endif /* HAVE_FCHDIR */
3116
3117
3118 /*[clinic input]
3119 os.chmod
3120
3121 path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3122 Path to be modified. May always be specified as a str, bytes, or a path-like object.
3123 On some platforms, path may also be specified as an open file descriptor.
3124 If this functionality is unavailable, using it raises an exception.
3125
3126 mode: int
3127 Operating-system mode bitfield.
3128
3129 *
3130
3131 dir_fd : dir_fd(requires='fchmodat') = None
3132 If not None, it should be a file descriptor open to a directory,
3133 and path should be relative; path will then be relative to that
3134 directory.
3135
3136 follow_symlinks: bool = True
3137 If False, and the last element of the path is a symbolic link,
3138 chmod will modify the symbolic link itself instead of the file
3139 the link points to.
3140
3141 Change the access permissions of a file.
3142
3143 It is an error to use dir_fd or follow_symlinks when specifying path as
3144 an open file descriptor.
3145 dir_fd and follow_symlinks may not be implemented on your platform.
3146 If they are unavailable, using them will raise a NotImplementedError.
3147
3148 [clinic start generated code]*/
3149
3150 static PyObject *
os_chmod_impl(PyObject * module,path_t * path,int mode,int dir_fd,int follow_symlinks)3151 os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3152 int follow_symlinks)
3153 /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
3154 {
3155 int result;
3156
3157 #ifdef MS_WINDOWS
3158 DWORD attr;
3159 #endif
3160
3161 #ifdef HAVE_FCHMODAT
3162 int fchmodat_nofollow_unsupported = 0;
3163 int fchmodat_unsupported = 0;
3164 #endif
3165
3166 #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
3167 if (follow_symlinks_specified("chmod", follow_symlinks))
3168 return NULL;
3169 #endif
3170
3171 if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3172 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3173 return NULL;
3174 }
3175
3176 #ifdef MS_WINDOWS
3177 Py_BEGIN_ALLOW_THREADS
3178 attr = GetFileAttributesW(path->wide);
3179 if (attr == INVALID_FILE_ATTRIBUTES)
3180 result = 0;
3181 else {
3182 if (mode & _S_IWRITE)
3183 attr &= ~FILE_ATTRIBUTE_READONLY;
3184 else
3185 attr |= FILE_ATTRIBUTE_READONLY;
3186 result = SetFileAttributesW(path->wide, attr);
3187 }
3188 Py_END_ALLOW_THREADS
3189
3190 if (!result) {
3191 return path_error(path);
3192 }
3193 #else /* MS_WINDOWS */
3194 Py_BEGIN_ALLOW_THREADS
3195 #ifdef HAVE_FCHMOD
3196 if (path->fd != -1)
3197 result = fchmod(path->fd, mode);
3198 else
3199 #endif /* HAVE_CHMOD */
3200 #ifdef HAVE_LCHMOD
3201 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3202 result = lchmod(path->narrow, mode);
3203 else
3204 #endif /* HAVE_LCHMOD */
3205 #ifdef HAVE_FCHMODAT
3206 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3207 if (HAVE_FCHMODAT_RUNTIME) {
3208 /*
3209 * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3210 * The documentation specifically shows how to use it,
3211 * and then says it isn't implemented yet.
3212 * (true on linux with glibc 2.15, and openindiana 3.x)
3213 *
3214 * Once it is supported, os.chmod will automatically
3215 * support dir_fd and follow_symlinks=False. (Hopefully.)
3216 * Until then, we need to be careful what exception we raise.
3217 */
3218 result = fchmodat(dir_fd, path->narrow, mode,
3219 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3220 /*
3221 * But wait! We can't throw the exception without allowing threads,
3222 * and we can't do that in this nested scope. (Macro trickery, sigh.)
3223 */
3224 fchmodat_nofollow_unsupported =
3225 result &&
3226 ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3227 !follow_symlinks;
3228 } else {
3229 fchmodat_unsupported = 1;
3230 fchmodat_nofollow_unsupported = 1;
3231
3232 result = -1;
3233 }
3234 }
3235 else
3236 #endif /* HAVE_FHCMODAT */
3237 result = chmod(path->narrow, mode);
3238 Py_END_ALLOW_THREADS
3239
3240 if (result) {
3241 #ifdef HAVE_FCHMODAT
3242 if (fchmodat_unsupported) {
3243 if (dir_fd != DEFAULT_DIR_FD) {
3244 argument_unavailable_error("chmod", "dir_fd");
3245 return NULL;
3246 }
3247 }
3248
3249 if (fchmodat_nofollow_unsupported) {
3250 if (dir_fd != DEFAULT_DIR_FD)
3251 dir_fd_and_follow_symlinks_invalid("chmod",
3252 dir_fd, follow_symlinks);
3253 else
3254 follow_symlinks_specified("chmod", follow_symlinks);
3255 return NULL;
3256 }
3257 else
3258 #endif /* HAVE_FCHMODAT */
3259 return path_error(path);
3260 }
3261 #endif /* MS_WINDOWS */
3262
3263 Py_RETURN_NONE;
3264 }
3265
3266
3267 #ifdef HAVE_FCHMOD
3268 /*[clinic input]
3269 os.fchmod
3270
3271 fd: int
3272 mode: int
3273
3274 Change the access permissions of the file given by file descriptor fd.
3275
3276 Equivalent to os.chmod(fd, mode).
3277 [clinic start generated code]*/
3278
3279 static PyObject *
os_fchmod_impl(PyObject * module,int fd,int mode)3280 os_fchmod_impl(PyObject *module, int fd, int mode)
3281 /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
3282 {
3283 int res;
3284 int async_err = 0;
3285
3286 if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3287 return NULL;
3288 }
3289
3290 do {
3291 Py_BEGIN_ALLOW_THREADS
3292 res = fchmod(fd, mode);
3293 Py_END_ALLOW_THREADS
3294 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3295 if (res != 0)
3296 return (!async_err) ? posix_error() : NULL;
3297
3298 Py_RETURN_NONE;
3299 }
3300 #endif /* HAVE_FCHMOD */
3301
3302
3303 #ifdef HAVE_LCHMOD
3304 /*[clinic input]
3305 os.lchmod
3306
3307 path: path_t
3308 mode: int
3309
3310 Change the access permissions of a file, without following symbolic links.
3311
3312 If path is a symlink, this affects the link itself rather than the target.
3313 Equivalent to chmod(path, mode, follow_symlinks=False)."
3314 [clinic start generated code]*/
3315
3316 static PyObject *
os_lchmod_impl(PyObject * module,path_t * path,int mode)3317 os_lchmod_impl(PyObject *module, path_t *path, int mode)
3318 /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3319 {
3320 int res;
3321 if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3322 return NULL;
3323 }
3324 Py_BEGIN_ALLOW_THREADS
3325 res = lchmod(path->narrow, mode);
3326 Py_END_ALLOW_THREADS
3327 if (res < 0) {
3328 path_error(path);
3329 return NULL;
3330 }
3331 Py_RETURN_NONE;
3332 }
3333 #endif /* HAVE_LCHMOD */
3334
3335
3336 #ifdef HAVE_CHFLAGS
3337 /*[clinic input]
3338 os.chflags
3339
3340 path: path_t
3341 flags: unsigned_long(bitwise=True)
3342 follow_symlinks: bool=True
3343
3344 Set file flags.
3345
3346 If follow_symlinks is False, and the last element of the path is a symbolic
3347 link, chflags will change flags on the symbolic link itself instead of the
3348 file the link points to.
3349 follow_symlinks may not be implemented on your platform. If it is
3350 unavailable, using it will raise a NotImplementedError.
3351
3352 [clinic start generated code]*/
3353
3354 static PyObject *
os_chflags_impl(PyObject * module,path_t * path,unsigned long flags,int follow_symlinks)3355 os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3356 int follow_symlinks)
3357 /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3358 {
3359 int result;
3360
3361 #ifndef HAVE_LCHFLAGS
3362 if (follow_symlinks_specified("chflags", follow_symlinks))
3363 return NULL;
3364 #endif
3365
3366 if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3367 return NULL;
3368 }
3369
3370 Py_BEGIN_ALLOW_THREADS
3371 #ifdef HAVE_LCHFLAGS
3372 if (!follow_symlinks)
3373 result = lchflags(path->narrow, flags);
3374 else
3375 #endif
3376 result = chflags(path->narrow, flags);
3377 Py_END_ALLOW_THREADS
3378
3379 if (result)
3380 return path_error(path);
3381
3382 Py_RETURN_NONE;
3383 }
3384 #endif /* HAVE_CHFLAGS */
3385
3386
3387 #ifdef HAVE_LCHFLAGS
3388 /*[clinic input]
3389 os.lchflags
3390
3391 path: path_t
3392 flags: unsigned_long(bitwise=True)
3393
3394 Set file flags.
3395
3396 This function will not follow symbolic links.
3397 Equivalent to chflags(path, flags, follow_symlinks=False).
3398 [clinic start generated code]*/
3399
3400 static PyObject *
os_lchflags_impl(PyObject * module,path_t * path,unsigned long flags)3401 os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3402 /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3403 {
3404 int res;
3405 if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3406 return NULL;
3407 }
3408 Py_BEGIN_ALLOW_THREADS
3409 res = lchflags(path->narrow, flags);
3410 Py_END_ALLOW_THREADS
3411 if (res < 0) {
3412 return path_error(path);
3413 }
3414 Py_RETURN_NONE;
3415 }
3416 #endif /* HAVE_LCHFLAGS */
3417
3418
3419 #ifdef HAVE_CHROOT
3420 /*[clinic input]
3421 os.chroot
3422 path: path_t
3423
3424 Change root directory to path.
3425
3426 [clinic start generated code]*/
3427
3428 static PyObject *
os_chroot_impl(PyObject * module,path_t * path)3429 os_chroot_impl(PyObject *module, path_t *path)
3430 /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3431 {
3432 int res;
3433 Py_BEGIN_ALLOW_THREADS
3434 res = chroot(path->narrow);
3435 Py_END_ALLOW_THREADS
3436 if (res < 0)
3437 return path_error(path);
3438 Py_RETURN_NONE;
3439 }
3440 #endif /* HAVE_CHROOT */
3441
3442
3443 #ifdef HAVE_FSYNC
3444 /*[clinic input]
3445 os.fsync
3446
3447 fd: fildes
3448
3449 Force write of fd to disk.
3450 [clinic start generated code]*/
3451
3452 static PyObject *
os_fsync_impl(PyObject * module,int fd)3453 os_fsync_impl(PyObject *module, int fd)
3454 /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3455 {
3456 return posix_fildes_fd(fd, fsync);
3457 }
3458 #endif /* HAVE_FSYNC */
3459
3460
3461 #ifdef HAVE_SYNC
3462 /*[clinic input]
3463 os.sync
3464
3465 Force write of everything to disk.
3466 [clinic start generated code]*/
3467
3468 static PyObject *
os_sync_impl(PyObject * module)3469 os_sync_impl(PyObject *module)
3470 /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3471 {
3472 Py_BEGIN_ALLOW_THREADS
3473 sync();
3474 Py_END_ALLOW_THREADS
3475 Py_RETURN_NONE;
3476 }
3477 #endif /* HAVE_SYNC */
3478
3479
3480 #ifdef HAVE_FDATASYNC
3481 #ifdef __hpux
3482 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3483 #endif
3484
3485 /*[clinic input]
3486 os.fdatasync
3487
3488 fd: fildes
3489
3490 Force write of fd to disk without forcing update of metadata.
3491 [clinic start generated code]*/
3492
3493 static PyObject *
os_fdatasync_impl(PyObject * module,int fd)3494 os_fdatasync_impl(PyObject *module, int fd)
3495 /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3496 {
3497 return posix_fildes_fd(fd, fdatasync);
3498 }
3499 #endif /* HAVE_FDATASYNC */
3500
3501
3502 #ifdef HAVE_CHOWN
3503 /*[clinic input]
3504 os.chown
3505
3506 path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3507 Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3508
3509 uid: uid_t
3510
3511 gid: gid_t
3512
3513 *
3514
3515 dir_fd : dir_fd(requires='fchownat') = None
3516 If not None, it should be a file descriptor open to a directory,
3517 and path should be relative; path will then be relative to that
3518 directory.
3519
3520 follow_symlinks: bool = True
3521 If False, and the last element of the path is a symbolic link,
3522 stat will examine the symbolic link itself instead of the file
3523 the link points to.
3524
3525 Change the owner and group id of path to the numeric uid and gid.\
3526
3527 path may always be specified as a string.
3528 On some platforms, path may also be specified as an open file descriptor.
3529 If this functionality is unavailable, using it raises an exception.
3530 If dir_fd is not None, it should be a file descriptor open to a directory,
3531 and path should be relative; path will then be relative to that directory.
3532 If follow_symlinks is False, and the last element of the path is a symbolic
3533 link, chown will modify the symbolic link itself instead of the file the
3534 link points to.
3535 It is an error to use dir_fd or follow_symlinks when specifying path as
3536 an open file descriptor.
3537 dir_fd and follow_symlinks may not be implemented on your platform.
3538 If they are unavailable, using them will raise a NotImplementedError.
3539
3540 [clinic start generated code]*/
3541
3542 static PyObject *
os_chown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid,int dir_fd,int follow_symlinks)3543 os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3544 int dir_fd, int follow_symlinks)
3545 /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3546 {
3547 int result;
3548
3549 #if defined(HAVE_FCHOWNAT)
3550 int fchownat_unsupported = 0;
3551 #endif
3552
3553 #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3554 if (follow_symlinks_specified("chown", follow_symlinks))
3555 return NULL;
3556 #endif
3557 if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3558 fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3559 return NULL;
3560
3561 if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3562 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3563 return NULL;
3564 }
3565
3566 Py_BEGIN_ALLOW_THREADS
3567 #ifdef HAVE_FCHOWN
3568 if (path->fd != -1)
3569 result = fchown(path->fd, uid, gid);
3570 else
3571 #endif
3572 #ifdef HAVE_LCHOWN
3573 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3574 result = lchown(path->narrow, uid, gid);
3575 else
3576 #endif
3577 #ifdef HAVE_FCHOWNAT
3578 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
3579 if (HAVE_FCHOWNAT_RUNTIME) {
3580 result = fchownat(dir_fd, path->narrow, uid, gid,
3581 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3582 } else {
3583 fchownat_unsupported = 1;
3584 }
3585 } else
3586 #endif
3587 result = chown(path->narrow, uid, gid);
3588 Py_END_ALLOW_THREADS
3589
3590 #ifdef HAVE_FCHOWNAT
3591 if (fchownat_unsupported) {
3592 /* This would be incorrect if the current platform
3593 * doesn't support lchown.
3594 */
3595 argument_unavailable_error(NULL, "dir_fd");
3596 return NULL;
3597 }
3598 #endif
3599
3600 if (result)
3601 return path_error(path);
3602
3603 Py_RETURN_NONE;
3604 }
3605 #endif /* HAVE_CHOWN */
3606
3607
3608 #ifdef HAVE_FCHOWN
3609 /*[clinic input]
3610 os.fchown
3611
3612 fd: int
3613 uid: uid_t
3614 gid: gid_t
3615
3616 Change the owner and group id of the file specified by file descriptor.
3617
3618 Equivalent to os.chown(fd, uid, gid).
3619
3620 [clinic start generated code]*/
3621
3622 static PyObject *
os_fchown_impl(PyObject * module,int fd,uid_t uid,gid_t gid)3623 os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3624 /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3625 {
3626 int res;
3627 int async_err = 0;
3628
3629 if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
3630 return NULL;
3631 }
3632
3633 do {
3634 Py_BEGIN_ALLOW_THREADS
3635 res = fchown(fd, uid, gid);
3636 Py_END_ALLOW_THREADS
3637 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3638 if (res != 0)
3639 return (!async_err) ? posix_error() : NULL;
3640
3641 Py_RETURN_NONE;
3642 }
3643 #endif /* HAVE_FCHOWN */
3644
3645
3646 #ifdef HAVE_LCHOWN
3647 /*[clinic input]
3648 os.lchown
3649
3650 path : path_t
3651 uid: uid_t
3652 gid: gid_t
3653
3654 Change the owner and group id of path to the numeric uid and gid.
3655
3656 This function will not follow symbolic links.
3657 Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3658 [clinic start generated code]*/
3659
3660 static PyObject *
os_lchown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid)3661 os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3662 /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3663 {
3664 int res;
3665 if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
3666 return NULL;
3667 }
3668 Py_BEGIN_ALLOW_THREADS
3669 res = lchown(path->narrow, uid, gid);
3670 Py_END_ALLOW_THREADS
3671 if (res < 0) {
3672 return path_error(path);
3673 }
3674 Py_RETURN_NONE;
3675 }
3676 #endif /* HAVE_LCHOWN */
3677
3678
3679 static PyObject *
posix_getcwd(int use_bytes)3680 posix_getcwd(int use_bytes)
3681 {
3682 #ifdef MS_WINDOWS
3683 wchar_t wbuf[MAXPATHLEN];
3684 wchar_t *wbuf2 = wbuf;
3685 DWORD len;
3686
3687 Py_BEGIN_ALLOW_THREADS
3688 len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3689 /* If the buffer is large enough, len does not include the
3690 terminating \0. If the buffer is too small, len includes
3691 the space needed for the terminator. */
3692 if (len >= Py_ARRAY_LENGTH(wbuf)) {
3693 if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3694 wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3695 }
3696 else {
3697 wbuf2 = NULL;
3698 }
3699 if (wbuf2) {
3700 len = GetCurrentDirectoryW(len, wbuf2);
3701 }
3702 }
3703 Py_END_ALLOW_THREADS
3704
3705 if (!wbuf2) {
3706 PyErr_NoMemory();
3707 return NULL;
3708 }
3709 if (!len) {
3710 if (wbuf2 != wbuf)
3711 PyMem_RawFree(wbuf2);
3712 return PyErr_SetFromWindowsErr(0);
3713 }
3714
3715 PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3716 if (wbuf2 != wbuf) {
3717 PyMem_RawFree(wbuf2);
3718 }
3719
3720 if (use_bytes) {
3721 if (resobj == NULL) {
3722 return NULL;
3723 }
3724 Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3725 }
3726
3727 return resobj;
3728 #else
3729 const size_t chunk = 1024;
3730
3731 char *buf = NULL;
3732 char *cwd = NULL;
3733 size_t buflen = 0;
3734
3735 Py_BEGIN_ALLOW_THREADS
3736 do {
3737 char *newbuf;
3738 if (buflen <= PY_SSIZE_T_MAX - chunk) {
3739 buflen += chunk;
3740 newbuf = PyMem_RawRealloc(buf, buflen);
3741 }
3742 else {
3743 newbuf = NULL;
3744 }
3745 if (newbuf == NULL) {
3746 PyMem_RawFree(buf);
3747 buf = NULL;
3748 break;
3749 }
3750 buf = newbuf;
3751
3752 cwd = getcwd(buf, buflen);
3753 } while (cwd == NULL && errno == ERANGE);
3754 Py_END_ALLOW_THREADS
3755
3756 if (buf == NULL) {
3757 return PyErr_NoMemory();
3758 }
3759 if (cwd == NULL) {
3760 PyMem_RawFree(buf);
3761 return posix_error();
3762 }
3763
3764 PyObject *obj;
3765 if (use_bytes) {
3766 obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3767 }
3768 else {
3769 obj = PyUnicode_DecodeFSDefault(buf);
3770 }
3771 PyMem_RawFree(buf);
3772
3773 return obj;
3774 #endif /* !MS_WINDOWS */
3775 }
3776
3777
3778 /*[clinic input]
3779 os.getcwd
3780
3781 Return a unicode string representing the current working directory.
3782 [clinic start generated code]*/
3783
3784 static PyObject *
os_getcwd_impl(PyObject * module)3785 os_getcwd_impl(PyObject *module)
3786 /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3787 {
3788 return posix_getcwd(0);
3789 }
3790
3791
3792 /*[clinic input]
3793 os.getcwdb
3794
3795 Return a bytes string representing the current working directory.
3796 [clinic start generated code]*/
3797
3798 static PyObject *
os_getcwdb_impl(PyObject * module)3799 os_getcwdb_impl(PyObject *module)
3800 /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3801 {
3802 return posix_getcwd(1);
3803 }
3804
3805
3806 #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3807 #define HAVE_LINK 1
3808 #endif
3809
3810 #ifdef HAVE_LINK
3811 /*[clinic input]
3812
3813 os.link
3814
3815 src : path_t
3816 dst : path_t
3817 *
3818 src_dir_fd : dir_fd = None
3819 dst_dir_fd : dir_fd = None
3820 follow_symlinks: bool = True
3821
3822 Create a hard link to a file.
3823
3824 If either src_dir_fd or dst_dir_fd is not None, it should be a file
3825 descriptor open to a directory, and the respective path string (src or dst)
3826 should be relative; the path will then be relative to that directory.
3827 If follow_symlinks is False, and the last element of src is a symbolic
3828 link, link will create a link to the symbolic link itself instead of the
3829 file the link points to.
3830 src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3831 platform. If they are unavailable, using them will raise a
3832 NotImplementedError.
3833 [clinic start generated code]*/
3834
3835 static PyObject *
os_link_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int follow_symlinks)3836 os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3837 int dst_dir_fd, int follow_symlinks)
3838 /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3839 {
3840 #ifdef MS_WINDOWS
3841 BOOL result = FALSE;
3842 #else
3843 int result;
3844 #endif
3845 #if defined(HAVE_LINKAT)
3846 int linkat_unavailable = 0;
3847 #endif
3848
3849 #ifndef HAVE_LINKAT
3850 if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3851 argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3852 return NULL;
3853 }
3854 #endif
3855
3856 #ifndef MS_WINDOWS
3857 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3858 PyErr_SetString(PyExc_NotImplementedError,
3859 "link: src and dst must be the same type");
3860 return NULL;
3861 }
3862 #endif
3863
3864 if (PySys_Audit("os.link", "OOii", src->object, dst->object,
3865 src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
3866 dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
3867 return NULL;
3868 }
3869
3870 #ifdef MS_WINDOWS
3871 Py_BEGIN_ALLOW_THREADS
3872 result = CreateHardLinkW(dst->wide, src->wide, NULL);
3873 Py_END_ALLOW_THREADS
3874
3875 if (!result)
3876 return path_error2(src, dst);
3877 #else
3878 Py_BEGIN_ALLOW_THREADS
3879 #ifdef HAVE_LINKAT
3880 if ((src_dir_fd != DEFAULT_DIR_FD) ||
3881 (dst_dir_fd != DEFAULT_DIR_FD) ||
3882 (!follow_symlinks)) {
3883
3884 if (HAVE_LINKAT_RUNTIME) {
3885
3886 result = linkat(src_dir_fd, src->narrow,
3887 dst_dir_fd, dst->narrow,
3888 follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3889
3890 }
3891 #ifdef __APPLE__
3892 else {
3893 if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
3894 /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
3895 result = link(src->narrow, dst->narrow);
3896 } else {
3897 linkat_unavailable = 1;
3898 }
3899 }
3900 #endif
3901 }
3902 else
3903 #endif /* HAVE_LINKAT */
3904 result = link(src->narrow, dst->narrow);
3905 Py_END_ALLOW_THREADS
3906
3907 #ifdef HAVE_LINKAT
3908 if (linkat_unavailable) {
3909 /* Either or both dir_fd arguments were specified */
3910 if (src_dir_fd != DEFAULT_DIR_FD) {
3911 argument_unavailable_error("link", "src_dir_fd");
3912 } else {
3913 argument_unavailable_error("link", "dst_dir_fd");
3914 }
3915 return NULL;
3916 }
3917 #endif
3918
3919 if (result)
3920 return path_error2(src, dst);
3921 #endif /* MS_WINDOWS */
3922
3923 Py_RETURN_NONE;
3924 }
3925 #endif
3926
3927
3928 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3929 static PyObject *
_listdir_windows_no_opendir(path_t * path,PyObject * list)3930 _listdir_windows_no_opendir(path_t *path, PyObject *list)
3931 {
3932 PyObject *v;
3933 HANDLE hFindFile = INVALID_HANDLE_VALUE;
3934 BOOL result;
3935 wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
3936 /* only claim to have space for MAX_PATH */
3937 Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
3938 wchar_t *wnamebuf = NULL;
3939
3940 WIN32_FIND_DATAW wFileData;
3941 const wchar_t *po_wchars;
3942
3943 if (!path->wide) { /* Default arg: "." */
3944 po_wchars = L".";
3945 len = 1;
3946 } else {
3947 po_wchars = path->wide;
3948 len = wcslen(path->wide);
3949 }
3950 /* The +5 is so we can append "\\*.*\0" */
3951 wnamebuf = PyMem_New(wchar_t, len + 5);
3952 if (!wnamebuf) {
3953 PyErr_NoMemory();
3954 goto exit;
3955 }
3956 wcscpy(wnamebuf, po_wchars);
3957 if (len > 0) {
3958 wchar_t wch = wnamebuf[len-1];
3959 if (wch != SEP && wch != ALTSEP && wch != L':')
3960 wnamebuf[len++] = SEP;
3961 wcscpy(wnamebuf + len, L"*.*");
3962 }
3963 if ((list = PyList_New(0)) == NULL) {
3964 goto exit;
3965 }
3966 Py_BEGIN_ALLOW_THREADS
3967 hFindFile = FindFirstFileW(wnamebuf, &wFileData);
3968 Py_END_ALLOW_THREADS
3969 if (hFindFile == INVALID_HANDLE_VALUE) {
3970 int error = GetLastError();
3971 if (error == ERROR_FILE_NOT_FOUND)
3972 goto exit;
3973 Py_DECREF(list);
3974 list = path_error(path);
3975 goto exit;
3976 }
3977 do {
3978 /* Skip over . and .. */
3979 if (wcscmp(wFileData.cFileName, L".") != 0 &&
3980 wcscmp(wFileData.cFileName, L"..") != 0) {
3981 v = PyUnicode_FromWideChar(wFileData.cFileName,
3982 wcslen(wFileData.cFileName));
3983 if (path->narrow && v) {
3984 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
3985 }
3986 if (v == NULL) {
3987 Py_DECREF(list);
3988 list = NULL;
3989 break;
3990 }
3991 if (PyList_Append(list, v) != 0) {
3992 Py_DECREF(v);
3993 Py_DECREF(list);
3994 list = NULL;
3995 break;
3996 }
3997 Py_DECREF(v);
3998 }
3999 Py_BEGIN_ALLOW_THREADS
4000 result = FindNextFileW(hFindFile, &wFileData);
4001 Py_END_ALLOW_THREADS
4002 /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4003 it got to the end of the directory. */
4004 if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4005 Py_DECREF(list);
4006 list = path_error(path);
4007 goto exit;
4008 }
4009 } while (result == TRUE);
4010
4011 exit:
4012 if (hFindFile != INVALID_HANDLE_VALUE) {
4013 if (FindClose(hFindFile) == FALSE) {
4014 if (list != NULL) {
4015 Py_DECREF(list);
4016 list = path_error(path);
4017 }
4018 }
4019 }
4020 PyMem_Free(wnamebuf);
4021
4022 return list;
4023 } /* end of _listdir_windows_no_opendir */
4024
4025 #else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4026
4027 static PyObject *
_posix_listdir(path_t * path,PyObject * list)4028 _posix_listdir(path_t *path, PyObject *list)
4029 {
4030 PyObject *v;
4031 DIR *dirp = NULL;
4032 struct dirent *ep;
4033 int return_str; /* if false, return bytes */
4034 #ifdef HAVE_FDOPENDIR
4035 int fd = -1;
4036 #endif
4037
4038 errno = 0;
4039 #ifdef HAVE_FDOPENDIR
4040 if (path->fd != -1) {
4041 if (HAVE_FDOPENDIR_RUNTIME) {
4042 /* closedir() closes the FD, so we duplicate it */
4043 fd = _Py_dup(path->fd);
4044 if (fd == -1)
4045 return NULL;
4046
4047 return_str = 1;
4048
4049 Py_BEGIN_ALLOW_THREADS
4050 dirp = fdopendir(fd);
4051 Py_END_ALLOW_THREADS
4052 } else {
4053 PyErr_SetString(PyExc_TypeError,
4054 "listdir: path should be string, bytes, os.PathLike or None, not int");
4055 return NULL;
4056 }
4057 }
4058 else
4059 #endif
4060 {
4061 const char *name;
4062 if (path->narrow) {
4063 name = path->narrow;
4064 /* only return bytes if they specified a bytes-like object */
4065 return_str = !PyObject_CheckBuffer(path->object);
4066 }
4067 else {
4068 name = ".";
4069 return_str = 1;
4070 }
4071
4072 Py_BEGIN_ALLOW_THREADS
4073 dirp = opendir(name);
4074 Py_END_ALLOW_THREADS
4075 }
4076
4077 if (dirp == NULL) {
4078 list = path_error(path);
4079 #ifdef HAVE_FDOPENDIR
4080 if (fd != -1) {
4081 Py_BEGIN_ALLOW_THREADS
4082 close(fd);
4083 Py_END_ALLOW_THREADS
4084 }
4085 #endif
4086 goto exit;
4087 }
4088 if ((list = PyList_New(0)) == NULL) {
4089 goto exit;
4090 }
4091 for (;;) {
4092 errno = 0;
4093 Py_BEGIN_ALLOW_THREADS
4094 ep = readdir(dirp);
4095 Py_END_ALLOW_THREADS
4096 if (ep == NULL) {
4097 if (errno == 0) {
4098 break;
4099 } else {
4100 Py_DECREF(list);
4101 list = path_error(path);
4102 goto exit;
4103 }
4104 }
4105 if (ep->d_name[0] == '.' &&
4106 (NAMLEN(ep) == 1 ||
4107 (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4108 continue;
4109 if (return_str)
4110 v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4111 else
4112 v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4113 if (v == NULL) {
4114 Py_CLEAR(list);
4115 break;
4116 }
4117 if (PyList_Append(list, v) != 0) {
4118 Py_DECREF(v);
4119 Py_CLEAR(list);
4120 break;
4121 }
4122 Py_DECREF(v);
4123 }
4124
4125 exit:
4126 if (dirp != NULL) {
4127 Py_BEGIN_ALLOW_THREADS
4128 #ifdef HAVE_FDOPENDIR
4129 if (fd > -1)
4130 rewinddir(dirp);
4131 #endif
4132 closedir(dirp);
4133 Py_END_ALLOW_THREADS
4134 }
4135
4136 return list;
4137 } /* end of _posix_listdir */
4138 #endif /* which OS */
4139
4140
4141 /*[clinic input]
4142 os.listdir
4143
4144 path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4145
4146 Return a list containing the names of the files in the directory.
4147
4148 path can be specified as either str, bytes, or a path-like object. If path is bytes,
4149 the filenames returned will also be bytes; in all other circumstances
4150 the filenames returned will be str.
4151 If path is None, uses the path='.'.
4152 On some platforms, path may also be specified as an open file descriptor;\
4153 the file descriptor must refer to a directory.
4154 If this functionality is unavailable, using it raises NotImplementedError.
4155
4156 The list is in arbitrary order. It does not include the special
4157 entries '.' and '..' even if they are present in the directory.
4158
4159
4160 [clinic start generated code]*/
4161
4162 static PyObject *
os_listdir_impl(PyObject * module,path_t * path)4163 os_listdir_impl(PyObject *module, path_t *path)
4164 /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4165 {
4166 if (PySys_Audit("os.listdir", "O",
4167 path->object ? path->object : Py_None) < 0) {
4168 return NULL;
4169 }
4170 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4171 return _listdir_windows_no_opendir(path, NULL);
4172 #else
4173 return _posix_listdir(path, NULL);
4174 #endif
4175 }
4176
4177 #ifdef MS_WINDOWS
4178 /* A helper function for abspath on win32 */
4179 /*[clinic input]
4180 os._getfullpathname
4181
4182 path: path_t
4183 /
4184
4185 [clinic start generated code]*/
4186
4187 static PyObject *
os__getfullpathname_impl(PyObject * module,path_t * path)4188 os__getfullpathname_impl(PyObject *module, path_t *path)
4189 /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
4190 {
4191 wchar_t *abspath;
4192
4193 /* _Py_abspath() is implemented with GetFullPathNameW() on Windows */
4194 if (_Py_abspath(path->wide, &abspath) < 0) {
4195 return win32_error_object("GetFullPathNameW", path->object);
4196 }
4197 if (abspath == NULL) {
4198 return PyErr_NoMemory();
4199 }
4200
4201 PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
4202 PyMem_RawFree(abspath);
4203 if (str == NULL) {
4204 return NULL;
4205 }
4206 if (path->narrow) {
4207 Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
4208 }
4209 return str;
4210 }
4211
4212
4213 /*[clinic input]
4214 os._getfinalpathname
4215
4216 path: path_t
4217 /
4218
4219 A helper function for samepath on windows.
4220 [clinic start generated code]*/
4221
4222 static PyObject *
os__getfinalpathname_impl(PyObject * module,path_t * path)4223 os__getfinalpathname_impl(PyObject *module, path_t *path)
4224 /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
4225 {
4226 HANDLE hFile;
4227 wchar_t buf[MAXPATHLEN], *target_path = buf;
4228 int buf_size = Py_ARRAY_LENGTH(buf);
4229 int result_length;
4230 PyObject *result;
4231
4232 Py_BEGIN_ALLOW_THREADS
4233 hFile = CreateFileW(
4234 path->wide,
4235 0, /* desired access */
4236 0, /* share mode */
4237 NULL, /* security attributes */
4238 OPEN_EXISTING,
4239 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
4240 FILE_FLAG_BACKUP_SEMANTICS,
4241 NULL);
4242 Py_END_ALLOW_THREADS
4243
4244 if (hFile == INVALID_HANDLE_VALUE) {
4245 return win32_error_object("CreateFileW", path->object);
4246 }
4247
4248 /* We have a good handle to the target, use it to determine the
4249 target path name. */
4250 while (1) {
4251 Py_BEGIN_ALLOW_THREADS
4252 result_length = GetFinalPathNameByHandleW(hFile, target_path,
4253 buf_size, VOLUME_NAME_DOS);
4254 Py_END_ALLOW_THREADS
4255
4256 if (!result_length) {
4257 result = win32_error_object("GetFinalPathNameByHandleW",
4258 path->object);
4259 goto cleanup;
4260 }
4261
4262 if (result_length < buf_size) {
4263 break;
4264 }
4265
4266 wchar_t *tmp;
4267 tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
4268 result_length * sizeof(*tmp));
4269 if (!tmp) {
4270 result = PyErr_NoMemory();
4271 goto cleanup;
4272 }
4273
4274 buf_size = result_length;
4275 target_path = tmp;
4276 }
4277
4278 result = PyUnicode_FromWideChar(target_path, result_length);
4279 if (result && path->narrow) {
4280 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4281 }
4282
4283 cleanup:
4284 if (target_path != buf) {
4285 PyMem_Free(target_path);
4286 }
4287 CloseHandle(hFile);
4288 return result;
4289 }
4290
4291
4292 /*[clinic input]
4293 os._getvolumepathname
4294
4295 path: path_t
4296
4297 A helper function for ismount on Win32.
4298 [clinic start generated code]*/
4299
4300 static PyObject *
os__getvolumepathname_impl(PyObject * module,path_t * path)4301 os__getvolumepathname_impl(PyObject *module, path_t *path)
4302 /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
4303 {
4304 PyObject *result;
4305 wchar_t *mountpath=NULL;
4306 size_t buflen;
4307 BOOL ret;
4308
4309 /* Volume path should be shorter than entire path */
4310 buflen = Py_MAX(path->length, MAX_PATH);
4311
4312 if (buflen > PY_DWORD_MAX) {
4313 PyErr_SetString(PyExc_OverflowError, "path too long");
4314 return NULL;
4315 }
4316
4317 mountpath = PyMem_New(wchar_t, buflen);
4318 if (mountpath == NULL)
4319 return PyErr_NoMemory();
4320
4321 Py_BEGIN_ALLOW_THREADS
4322 ret = GetVolumePathNameW(path->wide, mountpath,
4323 Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
4324 Py_END_ALLOW_THREADS
4325
4326 if (!ret) {
4327 result = win32_error_object("_getvolumepathname", path->object);
4328 goto exit;
4329 }
4330 result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
4331 if (path->narrow)
4332 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4333
4334 exit:
4335 PyMem_Free(mountpath);
4336 return result;
4337 }
4338
4339 #endif /* MS_WINDOWS */
4340
4341
4342 /*[clinic input]
4343 os.mkdir
4344
4345 path : path_t
4346
4347 mode: int = 0o777
4348
4349 *
4350
4351 dir_fd : dir_fd(requires='mkdirat') = None
4352
4353 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4354
4355 Create a directory.
4356
4357 If dir_fd is not None, it should be a file descriptor open to a directory,
4358 and path should be relative; path will then be relative to that directory.
4359 dir_fd may not be implemented on your platform.
4360 If it is unavailable, using it will raise a NotImplementedError.
4361
4362 The mode argument is ignored on Windows.
4363 [clinic start generated code]*/
4364
4365 static PyObject *
os_mkdir_impl(PyObject * module,path_t * path,int mode,int dir_fd)4366 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4367 /*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/
4368 {
4369 int result;
4370 #ifdef HAVE_MKDIRAT
4371 int mkdirat_unavailable = 0;
4372 #endif
4373
4374 if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4375 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4376 return NULL;
4377 }
4378
4379 #ifdef MS_WINDOWS
4380 Py_BEGIN_ALLOW_THREADS
4381 result = CreateDirectoryW(path->wide, NULL);
4382 Py_END_ALLOW_THREADS
4383
4384 if (!result)
4385 return path_error(path);
4386 #else
4387 Py_BEGIN_ALLOW_THREADS
4388 #if HAVE_MKDIRAT
4389 if (dir_fd != DEFAULT_DIR_FD) {
4390 if (HAVE_MKDIRAT_RUNTIME) {
4391 result = mkdirat(dir_fd, path->narrow, mode);
4392
4393 } else {
4394 mkdirat_unavailable = 1;
4395 }
4396 } else
4397 #endif
4398 #if defined(__WATCOMC__) && !defined(__QNX__)
4399 result = mkdir(path->narrow);
4400 #else
4401 result = mkdir(path->narrow, mode);
4402 #endif
4403 Py_END_ALLOW_THREADS
4404
4405 #if HAVE_MKDIRAT
4406 if (mkdirat_unavailable) {
4407 argument_unavailable_error(NULL, "dir_fd");
4408 return NULL;
4409 }
4410 #endif
4411
4412 if (result < 0)
4413 return path_error(path);
4414 #endif /* MS_WINDOWS */
4415 Py_RETURN_NONE;
4416 }
4417
4418
4419 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4420 #if defined(HAVE_SYS_RESOURCE_H)
4421 #include <sys/resource.h>
4422 #endif
4423
4424
4425 #ifdef HAVE_NICE
4426 /*[clinic input]
4427 os.nice
4428
4429 increment: int
4430 /
4431
4432 Add increment to the priority of process and return the new priority.
4433 [clinic start generated code]*/
4434
4435 static PyObject *
os_nice_impl(PyObject * module,int increment)4436 os_nice_impl(PyObject *module, int increment)
4437 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4438 {
4439 int value;
4440
4441 /* There are two flavours of 'nice': one that returns the new
4442 priority (as required by almost all standards out there) and the
4443 Linux/FreeBSD one, which returns '0' on success and advices
4444 the use of getpriority() to get the new priority.
4445
4446 If we are of the nice family that returns the new priority, we
4447 need to clear errno before the call, and check if errno is filled
4448 before calling posix_error() on a returnvalue of -1, because the
4449 -1 may be the actual new priority! */
4450
4451 errno = 0;
4452 value = nice(increment);
4453 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4454 if (value == 0)
4455 value = getpriority(PRIO_PROCESS, 0);
4456 #endif
4457 if (value == -1 && errno != 0)
4458 /* either nice() or getpriority() returned an error */
4459 return posix_error();
4460 return PyLong_FromLong((long) value);
4461 }
4462 #endif /* HAVE_NICE */
4463
4464
4465 #ifdef HAVE_GETPRIORITY
4466 /*[clinic input]
4467 os.getpriority
4468
4469 which: int
4470 who: int
4471
4472 Return program scheduling priority.
4473 [clinic start generated code]*/
4474
4475 static PyObject *
os_getpriority_impl(PyObject * module,int which,int who)4476 os_getpriority_impl(PyObject *module, int which, int who)
4477 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4478 {
4479 int retval;
4480
4481 errno = 0;
4482 retval = getpriority(which, who);
4483 if (errno != 0)
4484 return posix_error();
4485 return PyLong_FromLong((long)retval);
4486 }
4487 #endif /* HAVE_GETPRIORITY */
4488
4489
4490 #ifdef HAVE_SETPRIORITY
4491 /*[clinic input]
4492 os.setpriority
4493
4494 which: int
4495 who: int
4496 priority: int
4497
4498 Set program scheduling priority.
4499 [clinic start generated code]*/
4500
4501 static PyObject *
os_setpriority_impl(PyObject * module,int which,int who,int priority)4502 os_setpriority_impl(PyObject *module, int which, int who, int priority)
4503 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4504 {
4505 int retval;
4506
4507 retval = setpriority(which, who, priority);
4508 if (retval == -1)
4509 return posix_error();
4510 Py_RETURN_NONE;
4511 }
4512 #endif /* HAVE_SETPRIORITY */
4513
4514
4515 static PyObject *
internal_rename(path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int is_replace)4516 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4517 {
4518 const char *function_name = is_replace ? "replace" : "rename";
4519 int dir_fd_specified;
4520
4521 #ifdef HAVE_RENAMEAT
4522 int renameat_unavailable = 0;
4523 #endif
4524
4525 #ifdef MS_WINDOWS
4526 BOOL result;
4527 int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4528 #else
4529 int result;
4530 #endif
4531
4532 dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4533 (dst_dir_fd != DEFAULT_DIR_FD);
4534 #ifndef HAVE_RENAMEAT
4535 if (dir_fd_specified) {
4536 argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4537 return NULL;
4538 }
4539 #endif
4540
4541 if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
4542 src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4543 dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4544 return NULL;
4545 }
4546
4547 #ifdef MS_WINDOWS
4548 Py_BEGIN_ALLOW_THREADS
4549 result = MoveFileExW(src->wide, dst->wide, flags);
4550 Py_END_ALLOW_THREADS
4551
4552 if (!result)
4553 return path_error2(src, dst);
4554
4555 #else
4556 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4557 PyErr_Format(PyExc_ValueError,
4558 "%s: src and dst must be the same type", function_name);
4559 return NULL;
4560 }
4561
4562 Py_BEGIN_ALLOW_THREADS
4563 #ifdef HAVE_RENAMEAT
4564 if (dir_fd_specified) {
4565 if (HAVE_RENAMEAT_RUNTIME) {
4566 result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4567 } else {
4568 renameat_unavailable = 1;
4569 }
4570 } else
4571 #endif
4572 result = rename(src->narrow, dst->narrow);
4573 Py_END_ALLOW_THREADS
4574
4575
4576 #ifdef HAVE_RENAMEAT
4577 if (renameat_unavailable) {
4578 argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4579 return NULL;
4580 }
4581 #endif
4582
4583 if (result)
4584 return path_error2(src, dst);
4585 #endif
4586 Py_RETURN_NONE;
4587 }
4588
4589
4590 /*[clinic input]
4591 os.rename
4592
4593 src : path_t
4594 dst : path_t
4595 *
4596 src_dir_fd : dir_fd = None
4597 dst_dir_fd : dir_fd = None
4598
4599 Rename a file or directory.
4600
4601 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4602 descriptor open to a directory, and the respective path string (src or dst)
4603 should be relative; the path will then be relative to that directory.
4604 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4605 If they are unavailable, using them will raise a NotImplementedError.
4606 [clinic start generated code]*/
4607
4608 static PyObject *
os_rename_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4609 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4610 int dst_dir_fd)
4611 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4612 {
4613 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4614 }
4615
4616
4617 /*[clinic input]
4618 os.replace = os.rename
4619
4620 Rename a file or directory, overwriting the destination.
4621
4622 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4623 descriptor open to a directory, and the respective path string (src or dst)
4624 should be relative; the path will then be relative to that directory.
4625 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4626 If they are unavailable, using them will raise a NotImplementedError.
4627 [clinic start generated code]*/
4628
4629 static PyObject *
os_replace_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4630 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4631 int dst_dir_fd)
4632 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4633 {
4634 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4635 }
4636
4637
4638 /*[clinic input]
4639 os.rmdir
4640
4641 path: path_t
4642 *
4643 dir_fd: dir_fd(requires='unlinkat') = None
4644
4645 Remove a directory.
4646
4647 If dir_fd is not None, it should be a file descriptor open to a directory,
4648 and path should be relative; path will then be relative to that directory.
4649 dir_fd may not be implemented on your platform.
4650 If it is unavailable, using it will raise a NotImplementedError.
4651 [clinic start generated code]*/
4652
4653 static PyObject *
os_rmdir_impl(PyObject * module,path_t * path,int dir_fd)4654 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4655 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4656 {
4657 int result;
4658 #ifdef HAVE_UNLINKAT
4659 int unlinkat_unavailable = 0;
4660 #endif
4661
4662 if (PySys_Audit("os.rmdir", "Oi", path->object,
4663 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4664 return NULL;
4665 }
4666
4667 Py_BEGIN_ALLOW_THREADS
4668 #ifdef MS_WINDOWS
4669 /* Windows, success=1, UNIX, success=0 */
4670 result = !RemoveDirectoryW(path->wide);
4671 #else
4672 #ifdef HAVE_UNLINKAT
4673 if (dir_fd != DEFAULT_DIR_FD) {
4674 if (HAVE_UNLINKAT_RUNTIME) {
4675 result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4676 } else {
4677 unlinkat_unavailable = 1;
4678 result = -1;
4679 }
4680 } else
4681 #endif
4682 result = rmdir(path->narrow);
4683 #endif
4684 Py_END_ALLOW_THREADS
4685
4686 #ifdef HAVE_UNLINKAT
4687 if (unlinkat_unavailable) {
4688 argument_unavailable_error("rmdir", "dir_fd");
4689 return NULL;
4690 }
4691 #endif
4692
4693 if (result)
4694 return path_error(path);
4695
4696 Py_RETURN_NONE;
4697 }
4698
4699
4700 #ifdef HAVE_SYSTEM
4701 #ifdef MS_WINDOWS
4702 /*[clinic input]
4703 os.system -> long
4704
4705 command: Py_UNICODE
4706
4707 Execute the command in a subshell.
4708 [clinic start generated code]*/
4709
4710 static long
os_system_impl(PyObject * module,const Py_UNICODE * command)4711 os_system_impl(PyObject *module, const Py_UNICODE *command)
4712 /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4713 {
4714 long result;
4715
4716 if (PySys_Audit("os.system", "(u)", command) < 0) {
4717 return -1;
4718 }
4719
4720 Py_BEGIN_ALLOW_THREADS
4721 _Py_BEGIN_SUPPRESS_IPH
4722 result = _wsystem(command);
4723 _Py_END_SUPPRESS_IPH
4724 Py_END_ALLOW_THREADS
4725 return result;
4726 }
4727 #else /* MS_WINDOWS */
4728 /*[clinic input]
4729 os.system -> long
4730
4731 command: FSConverter
4732
4733 Execute the command in a subshell.
4734 [clinic start generated code]*/
4735
4736 static long
os_system_impl(PyObject * module,PyObject * command)4737 os_system_impl(PyObject *module, PyObject *command)
4738 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4739 {
4740 long result;
4741 const char *bytes = PyBytes_AsString(command);
4742
4743 if (PySys_Audit("os.system", "(O)", command) < 0) {
4744 return -1;
4745 }
4746
4747 Py_BEGIN_ALLOW_THREADS
4748 result = system(bytes);
4749 Py_END_ALLOW_THREADS
4750 return result;
4751 }
4752 #endif
4753 #endif /* HAVE_SYSTEM */
4754
4755
4756 /*[clinic input]
4757 os.umask
4758
4759 mask: int
4760 /
4761
4762 Set the current numeric umask and return the previous umask.
4763 [clinic start generated code]*/
4764
4765 static PyObject *
os_umask_impl(PyObject * module,int mask)4766 os_umask_impl(PyObject *module, int mask)
4767 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4768 {
4769 int i = (int)umask(mask);
4770 if (i < 0)
4771 return posix_error();
4772 return PyLong_FromLong((long)i);
4773 }
4774
4775 #ifdef MS_WINDOWS
4776
4777 /* override the default DeleteFileW behavior so that directory
4778 symlinks can be removed with this function, the same as with
4779 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)4780 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
4781 {
4782 WIN32_FILE_ATTRIBUTE_DATA info;
4783 WIN32_FIND_DATAW find_data;
4784 HANDLE find_data_handle;
4785 int is_directory = 0;
4786 int is_link = 0;
4787
4788 if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
4789 is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4790
4791 /* Get WIN32_FIND_DATA structure for the path to determine if
4792 it is a symlink */
4793 if(is_directory &&
4794 info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
4795 find_data_handle = FindFirstFileW(lpFileName, &find_data);
4796
4797 if(find_data_handle != INVALID_HANDLE_VALUE) {
4798 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
4799 IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
4800 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
4801 find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
4802 FindClose(find_data_handle);
4803 }
4804 }
4805 }
4806
4807 if (is_directory && is_link)
4808 return RemoveDirectoryW(lpFileName);
4809
4810 return DeleteFileW(lpFileName);
4811 }
4812 #endif /* MS_WINDOWS */
4813
4814
4815 /*[clinic input]
4816 os.unlink
4817
4818 path: path_t
4819 *
4820 dir_fd: dir_fd(requires='unlinkat')=None
4821
4822 Remove a file (same as remove()).
4823
4824 If dir_fd is not None, it should be a file descriptor open to a directory,
4825 and path should be relative; path will then be relative to that directory.
4826 dir_fd may not be implemented on your platform.
4827 If it is unavailable, using it will raise a NotImplementedError.
4828
4829 [clinic start generated code]*/
4830
4831 static PyObject *
os_unlink_impl(PyObject * module,path_t * path,int dir_fd)4832 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
4833 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
4834 {
4835 int result;
4836 #ifdef HAVE_UNLINKAT
4837 int unlinkat_unavailable = 0;
4838 #endif
4839
4840 if (PySys_Audit("os.remove", "Oi", path->object,
4841 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4842 return NULL;
4843 }
4844
4845 Py_BEGIN_ALLOW_THREADS
4846 _Py_BEGIN_SUPPRESS_IPH
4847 #ifdef MS_WINDOWS
4848 /* Windows, success=1, UNIX, success=0 */
4849 result = !Py_DeleteFileW(path->wide);
4850 #else
4851 #ifdef HAVE_UNLINKAT
4852 if (dir_fd != DEFAULT_DIR_FD) {
4853 if (HAVE_UNLINKAT_RUNTIME) {
4854
4855 result = unlinkat(dir_fd, path->narrow, 0);
4856 } else {
4857 unlinkat_unavailable = 1;
4858 }
4859 } else
4860 #endif /* HAVE_UNLINKAT */
4861 result = unlink(path->narrow);
4862 #endif
4863 _Py_END_SUPPRESS_IPH
4864 Py_END_ALLOW_THREADS
4865
4866 #ifdef HAVE_UNLINKAT
4867 if (unlinkat_unavailable) {
4868 argument_unavailable_error(NULL, "dir_fd");
4869 return NULL;
4870 }
4871 #endif
4872
4873 if (result)
4874 return path_error(path);
4875
4876 Py_RETURN_NONE;
4877 }
4878
4879
4880 /*[clinic input]
4881 os.remove = os.unlink
4882
4883 Remove a file (same as unlink()).
4884
4885 If dir_fd is not None, it should be a file descriptor open to a directory,
4886 and path should be relative; path will then be relative to that directory.
4887 dir_fd may not be implemented on your platform.
4888 If it is unavailable, using it will raise a NotImplementedError.
4889 [clinic start generated code]*/
4890
4891 static PyObject *
os_remove_impl(PyObject * module,path_t * path,int dir_fd)4892 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
4893 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
4894 {
4895 return os_unlink_impl(module, path, dir_fd);
4896 }
4897
4898
4899 static PyStructSequence_Field uname_result_fields[] = {
4900 {"sysname", "operating system name"},
4901 {"nodename", "name of machine on network (implementation-defined)"},
4902 {"release", "operating system release"},
4903 {"version", "operating system version"},
4904 {"machine", "hardware identifier"},
4905 {NULL}
4906 };
4907
4908 PyDoc_STRVAR(uname_result__doc__,
4909 "uname_result: Result from os.uname().\n\n\
4910 This object may be accessed either as a tuple of\n\
4911 (sysname, nodename, release, version, machine),\n\
4912 or via the attributes sysname, nodename, release, version, and machine.\n\
4913 \n\
4914 See os.uname for more information.");
4915
4916 static PyStructSequence_Desc uname_result_desc = {
4917 MODNAME ".uname_result", /* name */
4918 uname_result__doc__, /* doc */
4919 uname_result_fields,
4920 5
4921 };
4922
4923 #ifdef HAVE_UNAME
4924 /*[clinic input]
4925 os.uname
4926
4927 Return an object identifying the current operating system.
4928
4929 The object behaves like a named tuple with the following fields:
4930 (sysname, nodename, release, version, machine)
4931
4932 [clinic start generated code]*/
4933
4934 static PyObject *
os_uname_impl(PyObject * module)4935 os_uname_impl(PyObject *module)
4936 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
4937 {
4938 struct utsname u;
4939 int res;
4940 PyObject *value;
4941
4942 Py_BEGIN_ALLOW_THREADS
4943 res = uname(&u);
4944 Py_END_ALLOW_THREADS
4945 if (res < 0)
4946 return posix_error();
4947
4948 PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
4949 value = PyStructSequence_New((PyTypeObject *)UnameResultType);
4950 if (value == NULL)
4951 return NULL;
4952
4953 #define SET(i, field) \
4954 { \
4955 PyObject *o = PyUnicode_DecodeFSDefault(field); \
4956 if (!o) { \
4957 Py_DECREF(value); \
4958 return NULL; \
4959 } \
4960 PyStructSequence_SET_ITEM(value, i, o); \
4961 } \
4962
4963 SET(0, u.sysname);
4964 SET(1, u.nodename);
4965 SET(2, u.release);
4966 SET(3, u.version);
4967 SET(4, u.machine);
4968
4969 #undef SET
4970
4971 return value;
4972 }
4973 #endif /* HAVE_UNAME */
4974
4975
4976
4977 typedef struct {
4978 int now;
4979 time_t atime_s;
4980 long atime_ns;
4981 time_t mtime_s;
4982 long mtime_ns;
4983 } utime_t;
4984
4985 /*
4986 * these macros assume that "ut" is a pointer to a utime_t
4987 * they also intentionally leak the declaration of a pointer named "time"
4988 */
4989 #define UTIME_TO_TIMESPEC \
4990 struct timespec ts[2]; \
4991 struct timespec *time; \
4992 if (ut->now) \
4993 time = NULL; \
4994 else { \
4995 ts[0].tv_sec = ut->atime_s; \
4996 ts[0].tv_nsec = ut->atime_ns; \
4997 ts[1].tv_sec = ut->mtime_s; \
4998 ts[1].tv_nsec = ut->mtime_ns; \
4999 time = ts; \
5000 } \
5001
5002 #define UTIME_TO_TIMEVAL \
5003 struct timeval tv[2]; \
5004 struct timeval *time; \
5005 if (ut->now) \
5006 time = NULL; \
5007 else { \
5008 tv[0].tv_sec = ut->atime_s; \
5009 tv[0].tv_usec = ut->atime_ns / 1000; \
5010 tv[1].tv_sec = ut->mtime_s; \
5011 tv[1].tv_usec = ut->mtime_ns / 1000; \
5012 time = tv; \
5013 } \
5014
5015 #define UTIME_TO_UTIMBUF \
5016 struct utimbuf u; \
5017 struct utimbuf *time; \
5018 if (ut->now) \
5019 time = NULL; \
5020 else { \
5021 u.actime = ut->atime_s; \
5022 u.modtime = ut->mtime_s; \
5023 time = &u; \
5024 }
5025
5026 #define UTIME_TO_TIME_T \
5027 time_t timet[2]; \
5028 time_t *time; \
5029 if (ut->now) \
5030 time = NULL; \
5031 else { \
5032 timet[0] = ut->atime_s; \
5033 timet[1] = ut->mtime_s; \
5034 time = timet; \
5035 } \
5036
5037
5038 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5039
5040 static int
utime_dir_fd(utime_t * ut,int dir_fd,const char * path,int follow_symlinks)5041 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
5042 {
5043 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5044 if (HAVE_UTIMENSAT_RUNTIME) {
5045 int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5046 UTIME_TO_TIMESPEC;
5047 return utimensat(dir_fd, path, time, flags);
5048 } else {
5049 errno = ENOSYS;
5050 return -1;
5051 }
5052 #elif defined(HAVE_UTIMENSAT)
5053 int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5054 UTIME_TO_TIMESPEC;
5055 return utimensat(dir_fd, path, time, flags);
5056 #elif defined(HAVE_FUTIMESAT)
5057 UTIME_TO_TIMEVAL;
5058 /*
5059 * follow_symlinks will never be false here;
5060 * we only allow !follow_symlinks and dir_fd together
5061 * if we have utimensat()
5062 */
5063 assert(follow_symlinks);
5064 return futimesat(dir_fd, path, time);
5065 #endif
5066 }
5067
5068 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
5069 #else
5070 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
5071 #endif
5072
5073 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5074
5075 static int
utime_fd(utime_t * ut,int fd)5076 utime_fd(utime_t *ut, int fd)
5077 {
5078 #ifdef HAVE_FUTIMENS
5079
5080 if (HAVE_FUTIMENS_RUNTIME) {
5081
5082 UTIME_TO_TIMESPEC;
5083 return futimens(fd, time);
5084
5085 } else
5086 #ifndef HAVE_FUTIMES
5087 {
5088 /* Not sure if this can happen */
5089 PyErr_SetString(
5090 PyExc_RuntimeError,
5091 "neither futimens nor futimes are supported"
5092 " on this system");
5093 return -1;
5094 }
5095 #endif
5096
5097 #endif
5098 #ifdef HAVE_FUTIMES
5099 {
5100 UTIME_TO_TIMEVAL;
5101 return futimes(fd, time);
5102 }
5103 #endif
5104 }
5105
5106 #define PATH_UTIME_HAVE_FD 1
5107 #else
5108 #define PATH_UTIME_HAVE_FD 0
5109 #endif
5110
5111 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
5112 # define UTIME_HAVE_NOFOLLOW_SYMLINKS
5113 #endif
5114
5115 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5116
5117 static int
utime_nofollow_symlinks(utime_t * ut,const char * path)5118 utime_nofollow_symlinks(utime_t *ut, const char *path)
5119 {
5120 #ifdef HAVE_UTIMENSAT
5121 if (HAVE_UTIMENSAT_RUNTIME) {
5122 UTIME_TO_TIMESPEC;
5123 return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
5124 } else
5125 #ifndef HAVE_LUTIMES
5126 {
5127 /* Not sure if this can happen */
5128 PyErr_SetString(
5129 PyExc_RuntimeError,
5130 "neither utimensat nor lutimes are supported"
5131 " on this system");
5132 return -1;
5133 }
5134 #endif
5135 #endif
5136
5137 #ifdef HAVE_LUTIMES
5138 {
5139 UTIME_TO_TIMEVAL;
5140 return lutimes(path, time);
5141 }
5142 #endif
5143 }
5144
5145 #endif
5146
5147 #ifndef MS_WINDOWS
5148
5149 static int
utime_default(utime_t * ut,const char * path)5150 utime_default(utime_t *ut, const char *path)
5151 {
5152 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5153 if (HAVE_UTIMENSAT_RUNTIME) {
5154 UTIME_TO_TIMESPEC;
5155 return utimensat(DEFAULT_DIR_FD, path, time, 0);
5156 } else {
5157 UTIME_TO_TIMEVAL;
5158 return utimes(path, time);
5159 }
5160 #elif defined(HAVE_UTIMENSAT)
5161 UTIME_TO_TIMESPEC;
5162 return utimensat(DEFAULT_DIR_FD, path, time, 0);
5163 #elif defined(HAVE_UTIMES)
5164 UTIME_TO_TIMEVAL;
5165 return utimes(path, time);
5166 #elif defined(HAVE_UTIME_H)
5167 UTIME_TO_UTIMBUF;
5168 return utime(path, time);
5169 #else
5170 UTIME_TO_TIME_T;
5171 return utime(path, time);
5172 #endif
5173 }
5174
5175 #endif
5176
5177 static int
split_py_long_to_s_and_ns(PyObject * module,PyObject * py_long,time_t * s,long * ns)5178 split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5179 {
5180 int result = 0;
5181 PyObject *divmod;
5182 divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5183 if (!divmod)
5184 goto exit;
5185 if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
5186 PyErr_Format(PyExc_TypeError,
5187 "%.200s.__divmod__() must return a 2-tuple, not %.200s",
5188 _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
5189 goto exit;
5190 }
5191 *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5192 if ((*s == -1) && PyErr_Occurred())
5193 goto exit;
5194 *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5195 if ((*ns == -1) && PyErr_Occurred())
5196 goto exit;
5197
5198 result = 1;
5199 exit:
5200 Py_XDECREF(divmod);
5201 return result;
5202 }
5203
5204
5205 /*[clinic input]
5206 os.utime
5207
5208 path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
5209 times: object = None
5210 *
5211 ns: object = NULL
5212 dir_fd: dir_fd(requires='futimensat') = None
5213 follow_symlinks: bool=True
5214
5215 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
5216
5217 Set the access and modified time of path.
5218
5219 path may always be specified as a string.
5220 On some platforms, path may also be specified as an open file descriptor.
5221 If this functionality is unavailable, using it raises an exception.
5222
5223 If times is not None, it must be a tuple (atime, mtime);
5224 atime and mtime should be expressed as float seconds since the epoch.
5225 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
5226 atime_ns and mtime_ns should be expressed as integer nanoseconds
5227 since the epoch.
5228 If times is None and ns is unspecified, utime uses the current time.
5229 Specifying tuples for both times and ns is an error.
5230
5231 If dir_fd is not None, it should be a file descriptor open to a directory,
5232 and path should be relative; path will then be relative to that directory.
5233 If follow_symlinks is False, and the last element of the path is a symbolic
5234 link, utime will modify the symbolic link itself instead of the file the
5235 link points to.
5236 It is an error to use dir_fd or follow_symlinks when specifying path
5237 as an open file descriptor.
5238 dir_fd and follow_symlinks may not be available on your platform.
5239 If they are unavailable, using them will raise a NotImplementedError.
5240
5241 [clinic start generated code]*/
5242
5243 static PyObject *
os_utime_impl(PyObject * module,path_t * path,PyObject * times,PyObject * ns,int dir_fd,int follow_symlinks)5244 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
5245 int dir_fd, int follow_symlinks)
5246 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
5247 {
5248 #ifdef MS_WINDOWS
5249 HANDLE hFile;
5250 FILETIME atime, mtime;
5251 #else
5252 int result;
5253 #endif
5254
5255 utime_t utime;
5256
5257 memset(&utime, 0, sizeof(utime_t));
5258
5259 if (times != Py_None && ns) {
5260 PyErr_SetString(PyExc_ValueError,
5261 "utime: you may specify either 'times'"
5262 " or 'ns' but not both");
5263 return NULL;
5264 }
5265
5266 if (times != Py_None) {
5267 time_t a_sec, m_sec;
5268 long a_nsec, m_nsec;
5269 if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
5270 PyErr_SetString(PyExc_TypeError,
5271 "utime: 'times' must be either"
5272 " a tuple of two ints or None");
5273 return NULL;
5274 }
5275 utime.now = 0;
5276 if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
5277 &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
5278 _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
5279 &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
5280 return NULL;
5281 }
5282 utime.atime_s = a_sec;
5283 utime.atime_ns = a_nsec;
5284 utime.mtime_s = m_sec;
5285 utime.mtime_ns = m_nsec;
5286 }
5287 else if (ns) {
5288 if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
5289 PyErr_SetString(PyExc_TypeError,
5290 "utime: 'ns' must be a tuple of two ints");
5291 return NULL;
5292 }
5293 utime.now = 0;
5294 if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
5295 &utime.atime_s, &utime.atime_ns) ||
5296 !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
5297 &utime.mtime_s, &utime.mtime_ns)) {
5298 return NULL;
5299 }
5300 }
5301 else {
5302 /* times and ns are both None/unspecified. use "now". */
5303 utime.now = 1;
5304 }
5305
5306 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
5307 if (follow_symlinks_specified("utime", follow_symlinks))
5308 return NULL;
5309 #endif
5310
5311 if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
5312 dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
5313 fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
5314 return NULL;
5315
5316 #if !defined(HAVE_UTIMENSAT)
5317 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
5318 PyErr_SetString(PyExc_ValueError,
5319 "utime: cannot use dir_fd and follow_symlinks "
5320 "together on this platform");
5321 return NULL;
5322 }
5323 #endif
5324
5325 if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
5326 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5327 return NULL;
5328 }
5329
5330 #ifdef MS_WINDOWS
5331 Py_BEGIN_ALLOW_THREADS
5332 hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
5333 NULL, OPEN_EXISTING,
5334 FILE_FLAG_BACKUP_SEMANTICS, NULL);
5335 Py_END_ALLOW_THREADS
5336 if (hFile == INVALID_HANDLE_VALUE) {
5337 path_error(path);
5338 return NULL;
5339 }
5340
5341 if (utime.now) {
5342 GetSystemTimeAsFileTime(&mtime);
5343 atime = mtime;
5344 }
5345 else {
5346 _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
5347 _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
5348 }
5349 if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
5350 /* Avoid putting the file name into the error here,
5351 as that may confuse the user into believing that
5352 something is wrong with the file, when it also
5353 could be the time stamp that gives a problem. */
5354 PyErr_SetFromWindowsErr(0);
5355 CloseHandle(hFile);
5356 return NULL;
5357 }
5358 CloseHandle(hFile);
5359 #else /* MS_WINDOWS */
5360 Py_BEGIN_ALLOW_THREADS
5361
5362 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5363 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
5364 result = utime_nofollow_symlinks(&utime, path->narrow);
5365 else
5366 #endif
5367
5368 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5369 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
5370 result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
5371
5372 } else
5373 #endif
5374
5375 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5376 if (path->fd != -1)
5377 result = utime_fd(&utime, path->fd);
5378 else
5379 #endif
5380
5381 result = utime_default(&utime, path->narrow);
5382
5383 Py_END_ALLOW_THREADS
5384
5385 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5386 /* See utime_dir_fd implementation */
5387 if (result == -1 && errno == ENOSYS) {
5388 argument_unavailable_error(NULL, "dir_fd");
5389 return NULL;
5390 }
5391 #endif
5392
5393 if (result < 0) {
5394 /* see previous comment about not putting filename in error here */
5395 posix_error();
5396 return NULL;
5397 }
5398
5399 #endif /* MS_WINDOWS */
5400
5401 Py_RETURN_NONE;
5402 }
5403
5404 /* Process operations */
5405
5406
5407 /*[clinic input]
5408 os._exit
5409
5410 status: int
5411
5412 Exit to the system with specified status, without normal exit processing.
5413 [clinic start generated code]*/
5414
5415 static PyObject *
os__exit_impl(PyObject * module,int status)5416 os__exit_impl(PyObject *module, int status)
5417 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5418 {
5419 _exit(status);
5420 return NULL; /* Make gcc -Wall happy */
5421 }
5422
5423 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5424 #define EXECV_CHAR wchar_t
5425 #else
5426 #define EXECV_CHAR char
5427 #endif
5428
5429 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5430 static void
free_string_array(EXECV_CHAR ** array,Py_ssize_t count)5431 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5432 {
5433 Py_ssize_t i;
5434 for (i = 0; i < count; i++)
5435 PyMem_Free(array[i]);
5436 PyMem_DEL(array);
5437 }
5438
5439 static int
fsconvert_strdup(PyObject * o,EXECV_CHAR ** out)5440 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5441 {
5442 Py_ssize_t size;
5443 PyObject *ub;
5444 int result = 0;
5445 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5446 if (!PyUnicode_FSDecoder(o, &ub))
5447 return 0;
5448 *out = PyUnicode_AsWideCharString(ub, &size);
5449 if (*out)
5450 result = 1;
5451 #else
5452 if (!PyUnicode_FSConverter(o, &ub))
5453 return 0;
5454 size = PyBytes_GET_SIZE(ub);
5455 *out = PyMem_Malloc(size + 1);
5456 if (*out) {
5457 memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5458 result = 1;
5459 } else
5460 PyErr_NoMemory();
5461 #endif
5462 Py_DECREF(ub);
5463 return result;
5464 }
5465 #endif
5466
5467 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5468 static EXECV_CHAR**
parse_envlist(PyObject * env,Py_ssize_t * envc_ptr)5469 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5470 {
5471 Py_ssize_t i, pos, envc;
5472 PyObject *keys=NULL, *vals=NULL;
5473 PyObject *key, *val, *key2, *val2, *keyval;
5474 EXECV_CHAR **envlist;
5475
5476 i = PyMapping_Size(env);
5477 if (i < 0)
5478 return NULL;
5479 envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5480 if (envlist == NULL) {
5481 PyErr_NoMemory();
5482 return NULL;
5483 }
5484 envc = 0;
5485 keys = PyMapping_Keys(env);
5486 if (!keys)
5487 goto error;
5488 vals = PyMapping_Values(env);
5489 if (!vals)
5490 goto error;
5491 if (!PyList_Check(keys) || !PyList_Check(vals)) {
5492 PyErr_Format(PyExc_TypeError,
5493 "env.keys() or env.values() is not a list");
5494 goto error;
5495 }
5496
5497 for (pos = 0; pos < i; pos++) {
5498 key = PyList_GetItem(keys, pos);
5499 val = PyList_GetItem(vals, pos);
5500 if (!key || !val)
5501 goto error;
5502
5503 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5504 if (!PyUnicode_FSDecoder(key, &key2))
5505 goto error;
5506 if (!PyUnicode_FSDecoder(val, &val2)) {
5507 Py_DECREF(key2);
5508 goto error;
5509 }
5510 /* Search from index 1 because on Windows starting '=' is allowed for
5511 defining hidden environment variables. */
5512 if (PyUnicode_GET_LENGTH(key2) == 0 ||
5513 PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5514 {
5515 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5516 Py_DECREF(key2);
5517 Py_DECREF(val2);
5518 goto error;
5519 }
5520 keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5521 #else
5522 if (!PyUnicode_FSConverter(key, &key2))
5523 goto error;
5524 if (!PyUnicode_FSConverter(val, &val2)) {
5525 Py_DECREF(key2);
5526 goto error;
5527 }
5528 if (PyBytes_GET_SIZE(key2) == 0 ||
5529 strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5530 {
5531 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5532 Py_DECREF(key2);
5533 Py_DECREF(val2);
5534 goto error;
5535 }
5536 keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5537 PyBytes_AS_STRING(val2));
5538 #endif
5539 Py_DECREF(key2);
5540 Py_DECREF(val2);
5541 if (!keyval)
5542 goto error;
5543
5544 if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5545 Py_DECREF(keyval);
5546 goto error;
5547 }
5548
5549 Py_DECREF(keyval);
5550 }
5551 Py_DECREF(vals);
5552 Py_DECREF(keys);
5553
5554 envlist[envc] = 0;
5555 *envc_ptr = envc;
5556 return envlist;
5557
5558 error:
5559 Py_XDECREF(keys);
5560 Py_XDECREF(vals);
5561 free_string_array(envlist, envc);
5562 return NULL;
5563 }
5564
5565 static EXECV_CHAR**
parse_arglist(PyObject * argv,Py_ssize_t * argc)5566 parse_arglist(PyObject* argv, Py_ssize_t *argc)
5567 {
5568 int i;
5569 EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5570 if (argvlist == NULL) {
5571 PyErr_NoMemory();
5572 return NULL;
5573 }
5574 for (i = 0; i < *argc; i++) {
5575 PyObject* item = PySequence_ITEM(argv, i);
5576 if (item == NULL)
5577 goto fail;
5578 if (!fsconvert_strdup(item, &argvlist[i])) {
5579 Py_DECREF(item);
5580 goto fail;
5581 }
5582 Py_DECREF(item);
5583 }
5584 argvlist[*argc] = NULL;
5585 return argvlist;
5586 fail:
5587 *argc = i;
5588 free_string_array(argvlist, *argc);
5589 return NULL;
5590 }
5591
5592 #endif
5593
5594
5595 #ifdef HAVE_EXECV
5596 /*[clinic input]
5597 os.execv
5598
5599 path: path_t
5600 Path of executable file.
5601 argv: object
5602 Tuple or list of strings.
5603 /
5604
5605 Execute an executable path with arguments, replacing current process.
5606 [clinic start generated code]*/
5607
5608 static PyObject *
os_execv_impl(PyObject * module,path_t * path,PyObject * argv)5609 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5610 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5611 {
5612 EXECV_CHAR **argvlist;
5613 Py_ssize_t argc;
5614
5615 /* execv has two arguments: (path, argv), where
5616 argv is a list or tuple of strings. */
5617
5618 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5619 PyErr_SetString(PyExc_TypeError,
5620 "execv() arg 2 must be a tuple or list");
5621 return NULL;
5622 }
5623 argc = PySequence_Size(argv);
5624 if (argc < 1) {
5625 PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5626 return NULL;
5627 }
5628
5629 argvlist = parse_arglist(argv, &argc);
5630 if (argvlist == NULL) {
5631 return NULL;
5632 }
5633 if (!argvlist[0][0]) {
5634 PyErr_SetString(PyExc_ValueError,
5635 "execv() arg 2 first element cannot be empty");
5636 free_string_array(argvlist, argc);
5637 return NULL;
5638 }
5639
5640 if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5641 free_string_array(argvlist, argc);
5642 return NULL;
5643 }
5644
5645 _Py_BEGIN_SUPPRESS_IPH
5646 #ifdef HAVE_WEXECV
5647 _wexecv(path->wide, argvlist);
5648 #else
5649 execv(path->narrow, argvlist);
5650 #endif
5651 _Py_END_SUPPRESS_IPH
5652
5653 /* If we get here it's definitely an error */
5654
5655 free_string_array(argvlist, argc);
5656 return posix_error();
5657 }
5658
5659
5660 /*[clinic input]
5661 os.execve
5662
5663 path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5664 Path of executable file.
5665 argv: object
5666 Tuple or list of strings.
5667 env: object
5668 Dictionary of strings mapping to strings.
5669
5670 Execute an executable path with arguments, replacing current process.
5671 [clinic start generated code]*/
5672
5673 static PyObject *
os_execve_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env)5674 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5675 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5676 {
5677 EXECV_CHAR **argvlist = NULL;
5678 EXECV_CHAR **envlist;
5679 Py_ssize_t argc, envc;
5680
5681 /* execve has three arguments: (path, argv, env), where
5682 argv is a list or tuple of strings and env is a dictionary
5683 like posix.environ. */
5684
5685 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5686 PyErr_SetString(PyExc_TypeError,
5687 "execve: argv must be a tuple or list");
5688 goto fail_0;
5689 }
5690 argc = PySequence_Size(argv);
5691 if (argc < 1) {
5692 PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5693 return NULL;
5694 }
5695
5696 if (!PyMapping_Check(env)) {
5697 PyErr_SetString(PyExc_TypeError,
5698 "execve: environment must be a mapping object");
5699 goto fail_0;
5700 }
5701
5702 argvlist = parse_arglist(argv, &argc);
5703 if (argvlist == NULL) {
5704 goto fail_0;
5705 }
5706 if (!argvlist[0][0]) {
5707 PyErr_SetString(PyExc_ValueError,
5708 "execve: argv first element cannot be empty");
5709 goto fail_0;
5710 }
5711
5712 envlist = parse_envlist(env, &envc);
5713 if (envlist == NULL)
5714 goto fail_0;
5715
5716 if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5717 goto fail_1;
5718 }
5719
5720 _Py_BEGIN_SUPPRESS_IPH
5721 #ifdef HAVE_FEXECVE
5722 if (path->fd > -1)
5723 fexecve(path->fd, argvlist, envlist);
5724 else
5725 #endif
5726 #ifdef HAVE_WEXECV
5727 _wexecve(path->wide, argvlist, envlist);
5728 #else
5729 execve(path->narrow, argvlist, envlist);
5730 #endif
5731 _Py_END_SUPPRESS_IPH
5732
5733 /* If we get here it's definitely an error */
5734
5735 posix_path_error(path);
5736 fail_1:
5737 free_string_array(envlist, envc);
5738 fail_0:
5739 if (argvlist)
5740 free_string_array(argvlist, argc);
5741 return NULL;
5742 }
5743
5744 #endif /* HAVE_EXECV */
5745
5746 #ifdef HAVE_POSIX_SPAWN
5747
5748 enum posix_spawn_file_actions_identifier {
5749 POSIX_SPAWN_OPEN,
5750 POSIX_SPAWN_CLOSE,
5751 POSIX_SPAWN_DUP2
5752 };
5753
5754 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
5755 static int
5756 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
5757 #endif
5758
5759 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)5760 parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
5761 int resetids, int setsid, PyObject *setsigmask,
5762 PyObject *setsigdef, PyObject *scheduler,
5763 posix_spawnattr_t *attrp)
5764 {
5765 long all_flags = 0;
5766
5767 errno = posix_spawnattr_init(attrp);
5768 if (errno) {
5769 posix_error();
5770 return -1;
5771 }
5772
5773 if (setpgroup) {
5774 pid_t pgid = PyLong_AsPid(setpgroup);
5775 if (pgid == (pid_t)-1 && PyErr_Occurred()) {
5776 goto fail;
5777 }
5778 errno = posix_spawnattr_setpgroup(attrp, pgid);
5779 if (errno) {
5780 posix_error();
5781 goto fail;
5782 }
5783 all_flags |= POSIX_SPAWN_SETPGROUP;
5784 }
5785
5786 if (resetids) {
5787 all_flags |= POSIX_SPAWN_RESETIDS;
5788 }
5789
5790 if (setsid) {
5791 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5792 if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
5793 #endif
5794 #ifdef POSIX_SPAWN_SETSID
5795 all_flags |= POSIX_SPAWN_SETSID;
5796 #elif defined(POSIX_SPAWN_SETSID_NP)
5797 all_flags |= POSIX_SPAWN_SETSID_NP;
5798 #else
5799 argument_unavailable_error(func_name, "setsid");
5800 return -1;
5801 #endif
5802
5803 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5804 } else {
5805 argument_unavailable_error(func_name, "setsid");
5806 return -1;
5807 }
5808 #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
5809
5810 }
5811
5812 if (setsigmask) {
5813 sigset_t set;
5814 if (!_Py_Sigset_Converter(setsigmask, &set)) {
5815 goto fail;
5816 }
5817 errno = posix_spawnattr_setsigmask(attrp, &set);
5818 if (errno) {
5819 posix_error();
5820 goto fail;
5821 }
5822 all_flags |= POSIX_SPAWN_SETSIGMASK;
5823 }
5824
5825 if (setsigdef) {
5826 sigset_t set;
5827 if (!_Py_Sigset_Converter(setsigdef, &set)) {
5828 goto fail;
5829 }
5830 errno = posix_spawnattr_setsigdefault(attrp, &set);
5831 if (errno) {
5832 posix_error();
5833 goto fail;
5834 }
5835 all_flags |= POSIX_SPAWN_SETSIGDEF;
5836 }
5837
5838 if (scheduler) {
5839 #ifdef POSIX_SPAWN_SETSCHEDULER
5840 PyObject *py_schedpolicy;
5841 PyObject *schedparam_obj;
5842 struct sched_param schedparam;
5843
5844 if (!PyArg_ParseTuple(scheduler, "OO"
5845 ";A scheduler tuple must have two elements",
5846 &py_schedpolicy, &schedparam_obj)) {
5847 goto fail;
5848 }
5849 if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
5850 goto fail;
5851 }
5852 if (py_schedpolicy != Py_None) {
5853 int schedpolicy = _PyLong_AsInt(py_schedpolicy);
5854
5855 if (schedpolicy == -1 && PyErr_Occurred()) {
5856 goto fail;
5857 }
5858 errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
5859 if (errno) {
5860 posix_error();
5861 goto fail;
5862 }
5863 all_flags |= POSIX_SPAWN_SETSCHEDULER;
5864 }
5865 errno = posix_spawnattr_setschedparam(attrp, &schedparam);
5866 if (errno) {
5867 posix_error();
5868 goto fail;
5869 }
5870 all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
5871 #else
5872 PyErr_SetString(PyExc_NotImplementedError,
5873 "The scheduler option is not supported in this system.");
5874 goto fail;
5875 #endif
5876 }
5877
5878 errno = posix_spawnattr_setflags(attrp, all_flags);
5879 if (errno) {
5880 posix_error();
5881 goto fail;
5882 }
5883
5884 return 0;
5885
5886 fail:
5887 (void)posix_spawnattr_destroy(attrp);
5888 return -1;
5889 }
5890
5891 static int
parse_file_actions(PyObject * file_actions,posix_spawn_file_actions_t * file_actionsp,PyObject * temp_buffer)5892 parse_file_actions(PyObject *file_actions,
5893 posix_spawn_file_actions_t *file_actionsp,
5894 PyObject *temp_buffer)
5895 {
5896 PyObject *seq;
5897 PyObject *file_action = NULL;
5898 PyObject *tag_obj;
5899
5900 seq = PySequence_Fast(file_actions,
5901 "file_actions must be a sequence or None");
5902 if (seq == NULL) {
5903 return -1;
5904 }
5905
5906 errno = posix_spawn_file_actions_init(file_actionsp);
5907 if (errno) {
5908 posix_error();
5909 Py_DECREF(seq);
5910 return -1;
5911 }
5912
5913 for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
5914 file_action = PySequence_Fast_GET_ITEM(seq, i);
5915 Py_INCREF(file_action);
5916 if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
5917 PyErr_SetString(PyExc_TypeError,
5918 "Each file_actions element must be a non-empty tuple");
5919 goto fail;
5920 }
5921 long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
5922 if (tag == -1 && PyErr_Occurred()) {
5923 goto fail;
5924 }
5925
5926 /* Populate the file_actions object */
5927 switch (tag) {
5928 case POSIX_SPAWN_OPEN: {
5929 int fd, oflag;
5930 PyObject *path;
5931 unsigned long mode;
5932 if (!PyArg_ParseTuple(file_action, "OiO&ik"
5933 ";A open file_action tuple must have 5 elements",
5934 &tag_obj, &fd, PyUnicode_FSConverter, &path,
5935 &oflag, &mode))
5936 {
5937 goto fail;
5938 }
5939 if (PyList_Append(temp_buffer, path)) {
5940 Py_DECREF(path);
5941 goto fail;
5942 }
5943 errno = posix_spawn_file_actions_addopen(file_actionsp,
5944 fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
5945 Py_DECREF(path);
5946 if (errno) {
5947 posix_error();
5948 goto fail;
5949 }
5950 break;
5951 }
5952 case POSIX_SPAWN_CLOSE: {
5953 int fd;
5954 if (!PyArg_ParseTuple(file_action, "Oi"
5955 ";A close file_action tuple must have 2 elements",
5956 &tag_obj, &fd))
5957 {
5958 goto fail;
5959 }
5960 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
5961 if (errno) {
5962 posix_error();
5963 goto fail;
5964 }
5965 break;
5966 }
5967 case POSIX_SPAWN_DUP2: {
5968 int fd1, fd2;
5969 if (!PyArg_ParseTuple(file_action, "Oii"
5970 ";A dup2 file_action tuple must have 3 elements",
5971 &tag_obj, &fd1, &fd2))
5972 {
5973 goto fail;
5974 }
5975 errno = posix_spawn_file_actions_adddup2(file_actionsp,
5976 fd1, fd2);
5977 if (errno) {
5978 posix_error();
5979 goto fail;
5980 }
5981 break;
5982 }
5983 default: {
5984 PyErr_SetString(PyExc_TypeError,
5985 "Unknown file_actions identifier");
5986 goto fail;
5987 }
5988 }
5989 Py_DECREF(file_action);
5990 }
5991
5992 Py_DECREF(seq);
5993 return 0;
5994
5995 fail:
5996 Py_DECREF(seq);
5997 Py_DECREF(file_action);
5998 (void)posix_spawn_file_actions_destroy(file_actionsp);
5999 return -1;
6000 }
6001
6002
6003 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)6004 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
6005 PyObject *env, PyObject *file_actions,
6006 PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
6007 PyObject *setsigdef, PyObject *scheduler)
6008 {
6009 const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
6010 EXECV_CHAR **argvlist = NULL;
6011 EXECV_CHAR **envlist = NULL;
6012 posix_spawn_file_actions_t file_actions_buf;
6013 posix_spawn_file_actions_t *file_actionsp = NULL;
6014 posix_spawnattr_t attr;
6015 posix_spawnattr_t *attrp = NULL;
6016 Py_ssize_t argc, envc;
6017 PyObject *result = NULL;
6018 PyObject *temp_buffer = NULL;
6019 pid_t pid;
6020 int err_code;
6021
6022 /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
6023 argv is a list or tuple of strings and env is a dictionary
6024 like posix.environ. */
6025
6026 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6027 PyErr_Format(PyExc_TypeError,
6028 "%s: argv must be a tuple or list", func_name);
6029 goto exit;
6030 }
6031 argc = PySequence_Size(argv);
6032 if (argc < 1) {
6033 PyErr_Format(PyExc_ValueError,
6034 "%s: argv must not be empty", func_name);
6035 return NULL;
6036 }
6037
6038 if (!PyMapping_Check(env)) {
6039 PyErr_Format(PyExc_TypeError,
6040 "%s: environment must be a mapping object", func_name);
6041 goto exit;
6042 }
6043
6044 argvlist = parse_arglist(argv, &argc);
6045 if (argvlist == NULL) {
6046 goto exit;
6047 }
6048 if (!argvlist[0][0]) {
6049 PyErr_Format(PyExc_ValueError,
6050 "%s: argv first element cannot be empty", func_name);
6051 goto exit;
6052 }
6053
6054 envlist = parse_envlist(env, &envc);
6055 if (envlist == NULL) {
6056 goto exit;
6057 }
6058
6059 if (file_actions != NULL && file_actions != Py_None) {
6060 /* There is a bug in old versions of glibc that makes some of the
6061 * helper functions for manipulating file actions not copy the provided
6062 * buffers. The problem is that posix_spawn_file_actions_addopen does not
6063 * copy the value of path for some old versions of glibc (<2.20).
6064 * The use of temp_buffer here is a workaround that keeps the
6065 * python objects that own the buffers alive until posix_spawn gets called.
6066 * Check https://bugs.python.org/issue33630 and
6067 * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
6068 temp_buffer = PyList_New(0);
6069 if (!temp_buffer) {
6070 goto exit;
6071 }
6072 if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
6073 goto exit;
6074 }
6075 file_actionsp = &file_actions_buf;
6076 }
6077
6078 if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
6079 setsigmask, setsigdef, scheduler, &attr)) {
6080 goto exit;
6081 }
6082 attrp = &attr;
6083
6084 if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
6085 goto exit;
6086 }
6087
6088 _Py_BEGIN_SUPPRESS_IPH
6089 #ifdef HAVE_POSIX_SPAWNP
6090 if (use_posix_spawnp) {
6091 err_code = posix_spawnp(&pid, path->narrow,
6092 file_actionsp, attrp, argvlist, envlist);
6093 }
6094 else
6095 #endif /* HAVE_POSIX_SPAWNP */
6096 {
6097 err_code = posix_spawn(&pid, path->narrow,
6098 file_actionsp, attrp, argvlist, envlist);
6099 }
6100 _Py_END_SUPPRESS_IPH
6101
6102 if (err_code) {
6103 errno = err_code;
6104 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
6105 goto exit;
6106 }
6107 #ifdef _Py_MEMORY_SANITIZER
6108 __msan_unpoison(&pid, sizeof(pid));
6109 #endif
6110 result = PyLong_FromPid(pid);
6111
6112 exit:
6113 if (file_actionsp) {
6114 (void)posix_spawn_file_actions_destroy(file_actionsp);
6115 }
6116 if (attrp) {
6117 (void)posix_spawnattr_destroy(attrp);
6118 }
6119 if (envlist) {
6120 free_string_array(envlist, envc);
6121 }
6122 if (argvlist) {
6123 free_string_array(argvlist, argc);
6124 }
6125 Py_XDECREF(temp_buffer);
6126 return result;
6127 }
6128
6129
6130 /*[clinic input]
6131
6132 os.posix_spawn
6133 path: path_t
6134 Path of executable file.
6135 argv: object
6136 Tuple or list of strings.
6137 env: object
6138 Dictionary of strings mapping to strings.
6139 /
6140 *
6141 file_actions: object(c_default='NULL') = ()
6142 A sequence of file action tuples.
6143 setpgroup: object = NULL
6144 The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6145 resetids: bool(accept={int}) = False
6146 If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
6147 setsid: bool(accept={int}) = False
6148 If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6149 setsigmask: object(c_default='NULL') = ()
6150 The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6151 setsigdef: object(c_default='NULL') = ()
6152 The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6153 scheduler: object = NULL
6154 A tuple with the scheduler policy (optional) and parameters.
6155
6156 Execute the program specified by path in a new process.
6157 [clinic start generated code]*/
6158
6159 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)6160 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
6161 PyObject *env, PyObject *file_actions,
6162 PyObject *setpgroup, int resetids, int setsid,
6163 PyObject *setsigmask, PyObject *setsigdef,
6164 PyObject *scheduler)
6165 /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
6166 {
6167 return py_posix_spawn(0, module, path, argv, env, file_actions,
6168 setpgroup, resetids, setsid, setsigmask, setsigdef,
6169 scheduler);
6170 }
6171 #endif /* HAVE_POSIX_SPAWN */
6172
6173
6174
6175 #ifdef HAVE_POSIX_SPAWNP
6176 /*[clinic input]
6177
6178 os.posix_spawnp
6179 path: path_t
6180 Path of executable file.
6181 argv: object
6182 Tuple or list of strings.
6183 env: object
6184 Dictionary of strings mapping to strings.
6185 /
6186 *
6187 file_actions: object(c_default='NULL') = ()
6188 A sequence of file action tuples.
6189 setpgroup: object = NULL
6190 The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6191 resetids: bool(accept={int}) = False
6192 If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
6193 setsid: bool(accept={int}) = False
6194 If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6195 setsigmask: object(c_default='NULL') = ()
6196 The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6197 setsigdef: object(c_default='NULL') = ()
6198 The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6199 scheduler: object = NULL
6200 A tuple with the scheduler policy (optional) and parameters.
6201
6202 Execute the program specified by path in a new process.
6203 [clinic start generated code]*/
6204
6205 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)6206 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
6207 PyObject *env, PyObject *file_actions,
6208 PyObject *setpgroup, int resetids, int setsid,
6209 PyObject *setsigmask, PyObject *setsigdef,
6210 PyObject *scheduler)
6211 /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
6212 {
6213 return py_posix_spawn(1, module, path, argv, env, file_actions,
6214 setpgroup, resetids, setsid, setsigmask, setsigdef,
6215 scheduler);
6216 }
6217 #endif /* HAVE_POSIX_SPAWNP */
6218
6219 #ifdef HAVE_RTPSPAWN
6220 static intptr_t
_rtp_spawn(int mode,const char * rtpFileName,const char * argv[],const char * envp[])6221 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
6222 const char *envp[])
6223 {
6224 RTP_ID rtpid;
6225 int status;
6226 pid_t res;
6227 int async_err = 0;
6228
6229 /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
6230 uStackSize=0 cannot be used, the default stack size is too small for
6231 Python. */
6232 if (envp) {
6233 rtpid = rtpSpawn(rtpFileName, argv, envp,
6234 100, 0x1000000, 0, VX_FP_TASK);
6235 }
6236 else {
6237 rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
6238 100, 0x1000000, 0, VX_FP_TASK);
6239 }
6240 if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
6241 do {
6242 res = waitpid((pid_t)rtpid, &status, 0);
6243 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6244
6245 if (res < 0)
6246 return RTP_ID_ERROR;
6247 return ((intptr_t)status);
6248 }
6249 return ((intptr_t)rtpid);
6250 }
6251 #endif
6252
6253 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
6254 /*[clinic input]
6255 os.spawnv
6256
6257 mode: int
6258 Mode of process creation.
6259 path: path_t
6260 Path of executable file.
6261 argv: object
6262 Tuple or list of strings.
6263 /
6264
6265 Execute the program specified by path in a new process.
6266 [clinic start generated code]*/
6267
6268 static PyObject *
os_spawnv_impl(PyObject * module,int mode,path_t * path,PyObject * argv)6269 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
6270 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
6271 {
6272 EXECV_CHAR **argvlist;
6273 int i;
6274 Py_ssize_t argc;
6275 intptr_t spawnval;
6276 PyObject *(*getitem)(PyObject *, Py_ssize_t);
6277
6278 /* spawnv has three arguments: (mode, path, argv), where
6279 argv is a list or tuple of strings. */
6280
6281 if (PyList_Check(argv)) {
6282 argc = PyList_Size(argv);
6283 getitem = PyList_GetItem;
6284 }
6285 else if (PyTuple_Check(argv)) {
6286 argc = PyTuple_Size(argv);
6287 getitem = PyTuple_GetItem;
6288 }
6289 else {
6290 PyErr_SetString(PyExc_TypeError,
6291 "spawnv() arg 2 must be a tuple or list");
6292 return NULL;
6293 }
6294 if (argc == 0) {
6295 PyErr_SetString(PyExc_ValueError,
6296 "spawnv() arg 2 cannot be empty");
6297 return NULL;
6298 }
6299
6300 argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6301 if (argvlist == NULL) {
6302 return PyErr_NoMemory();
6303 }
6304 for (i = 0; i < argc; i++) {
6305 if (!fsconvert_strdup((*getitem)(argv, i),
6306 &argvlist[i])) {
6307 free_string_array(argvlist, i);
6308 PyErr_SetString(
6309 PyExc_TypeError,
6310 "spawnv() arg 2 must contain only strings");
6311 return NULL;
6312 }
6313 if (i == 0 && !argvlist[0][0]) {
6314 free_string_array(argvlist, i + 1);
6315 PyErr_SetString(
6316 PyExc_ValueError,
6317 "spawnv() arg 2 first element cannot be empty");
6318 return NULL;
6319 }
6320 }
6321 argvlist[argc] = NULL;
6322
6323 #if !defined(HAVE_RTPSPAWN)
6324 if (mode == _OLD_P_OVERLAY)
6325 mode = _P_OVERLAY;
6326 #endif
6327
6328 if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
6329 Py_None) < 0) {
6330 free_string_array(argvlist, argc);
6331 return NULL;
6332 }
6333
6334 Py_BEGIN_ALLOW_THREADS
6335 _Py_BEGIN_SUPPRESS_IPH
6336 #ifdef HAVE_WSPAWNV
6337 spawnval = _wspawnv(mode, path->wide, argvlist);
6338 #elif defined(HAVE_RTPSPAWN)
6339 spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
6340 #else
6341 spawnval = _spawnv(mode, path->narrow, argvlist);
6342 #endif
6343 _Py_END_SUPPRESS_IPH
6344 Py_END_ALLOW_THREADS
6345
6346 free_string_array(argvlist, argc);
6347
6348 if (spawnval == -1)
6349 return posix_error();
6350 else
6351 return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6352 }
6353
6354 /*[clinic input]
6355 os.spawnve
6356
6357 mode: int
6358 Mode of process creation.
6359 path: path_t
6360 Path of executable file.
6361 argv: object
6362 Tuple or list of strings.
6363 env: object
6364 Dictionary of strings mapping to strings.
6365 /
6366
6367 Execute the program specified by path in a new process.
6368 [clinic start generated code]*/
6369
6370 static PyObject *
os_spawnve_impl(PyObject * module,int mode,path_t * path,PyObject * argv,PyObject * env)6371 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
6372 PyObject *env)
6373 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
6374 {
6375 EXECV_CHAR **argvlist;
6376 EXECV_CHAR **envlist;
6377 PyObject *res = NULL;
6378 Py_ssize_t argc, i, envc;
6379 intptr_t spawnval;
6380 PyObject *(*getitem)(PyObject *, Py_ssize_t);
6381 Py_ssize_t lastarg = 0;
6382
6383 /* spawnve has four arguments: (mode, path, argv, env), where
6384 argv is a list or tuple of strings and env is a dictionary
6385 like posix.environ. */
6386
6387 if (PyList_Check(argv)) {
6388 argc = PyList_Size(argv);
6389 getitem = PyList_GetItem;
6390 }
6391 else if (PyTuple_Check(argv)) {
6392 argc = PyTuple_Size(argv);
6393 getitem = PyTuple_GetItem;
6394 }
6395 else {
6396 PyErr_SetString(PyExc_TypeError,
6397 "spawnve() arg 2 must be a tuple or list");
6398 goto fail_0;
6399 }
6400 if (argc == 0) {
6401 PyErr_SetString(PyExc_ValueError,
6402 "spawnve() arg 2 cannot be empty");
6403 goto fail_0;
6404 }
6405 if (!PyMapping_Check(env)) {
6406 PyErr_SetString(PyExc_TypeError,
6407 "spawnve() arg 3 must be a mapping object");
6408 goto fail_0;
6409 }
6410
6411 argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6412 if (argvlist == NULL) {
6413 PyErr_NoMemory();
6414 goto fail_0;
6415 }
6416 for (i = 0; i < argc; i++) {
6417 if (!fsconvert_strdup((*getitem)(argv, i),
6418 &argvlist[i]))
6419 {
6420 lastarg = i;
6421 goto fail_1;
6422 }
6423 if (i == 0 && !argvlist[0][0]) {
6424 lastarg = i + 1;
6425 PyErr_SetString(
6426 PyExc_ValueError,
6427 "spawnv() arg 2 first element cannot be empty");
6428 goto fail_1;
6429 }
6430 }
6431 lastarg = argc;
6432 argvlist[argc] = NULL;
6433
6434 envlist = parse_envlist(env, &envc);
6435 if (envlist == NULL)
6436 goto fail_1;
6437
6438 #if !defined(HAVE_RTPSPAWN)
6439 if (mode == _OLD_P_OVERLAY)
6440 mode = _P_OVERLAY;
6441 #endif
6442
6443 if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6444 goto fail_2;
6445 }
6446
6447 Py_BEGIN_ALLOW_THREADS
6448 _Py_BEGIN_SUPPRESS_IPH
6449 #ifdef HAVE_WSPAWNV
6450 spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6451 #elif defined(HAVE_RTPSPAWN)
6452 spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6453 (const char **)envlist);
6454 #else
6455 spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6456 #endif
6457 _Py_END_SUPPRESS_IPH
6458 Py_END_ALLOW_THREADS
6459
6460 if (spawnval == -1)
6461 (void) posix_error();
6462 else
6463 res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6464
6465 fail_2:
6466 while (--envc >= 0)
6467 PyMem_DEL(envlist[envc]);
6468 PyMem_DEL(envlist);
6469 fail_1:
6470 free_string_array(argvlist, lastarg);
6471 fail_0:
6472 return res;
6473 }
6474
6475 #endif /* HAVE_SPAWNV */
6476
6477
6478 #ifdef HAVE_FORK
6479
6480 /* Helper function to validate arguments.
6481 Returns 0 on success. non-zero on failure with a TypeError raised.
6482 If obj is non-NULL it must be callable. */
6483 static int
check_null_or_callable(PyObject * obj,const char * obj_name)6484 check_null_or_callable(PyObject *obj, const char* obj_name)
6485 {
6486 if (obj && !PyCallable_Check(obj)) {
6487 PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6488 obj_name, _PyType_Name(Py_TYPE(obj)));
6489 return -1;
6490 }
6491 return 0;
6492 }
6493
6494 /*[clinic input]
6495 os.register_at_fork
6496
6497 *
6498 before: object=NULL
6499 A callable to be called in the parent before the fork() syscall.
6500 after_in_child: object=NULL
6501 A callable to be called in the child after fork().
6502 after_in_parent: object=NULL
6503 A callable to be called in the parent after fork().
6504
6505 Register callables to be called when forking a new process.
6506
6507 'before' callbacks are called in reverse order.
6508 'after_in_child' and 'after_in_parent' callbacks are called in order.
6509
6510 [clinic start generated code]*/
6511
6512 static PyObject *
os_register_at_fork_impl(PyObject * module,PyObject * before,PyObject * after_in_child,PyObject * after_in_parent)6513 os_register_at_fork_impl(PyObject *module, PyObject *before,
6514 PyObject *after_in_child, PyObject *after_in_parent)
6515 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6516 {
6517 PyInterpreterState *interp;
6518
6519 if (!before && !after_in_child && !after_in_parent) {
6520 PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6521 return NULL;
6522 }
6523 if (check_null_or_callable(before, "before") ||
6524 check_null_or_callable(after_in_child, "after_in_child") ||
6525 check_null_or_callable(after_in_parent, "after_in_parent")) {
6526 return NULL;
6527 }
6528 interp = _PyInterpreterState_GET();
6529
6530 if (register_at_forker(&interp->before_forkers, before)) {
6531 return NULL;
6532 }
6533 if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6534 return NULL;
6535 }
6536 if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6537 return NULL;
6538 }
6539 Py_RETURN_NONE;
6540 }
6541 #endif /* HAVE_FORK */
6542
6543
6544 #ifdef HAVE_FORK1
6545 /*[clinic input]
6546 os.fork1
6547
6548 Fork a child process with a single multiplexed (i.e., not bound) thread.
6549
6550 Return 0 to child process and PID of child to parent process.
6551 [clinic start generated code]*/
6552
6553 static PyObject *
os_fork1_impl(PyObject * module)6554 os_fork1_impl(PyObject *module)
6555 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6556 {
6557 pid_t pid;
6558
6559 if (_PyInterpreterState_GET() != PyInterpreterState_Main()) {
6560 PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6561 return NULL;
6562 }
6563 PyOS_BeforeFork();
6564 pid = fork1();
6565 if (pid == 0) {
6566 /* child: this clobbers and resets the import lock. */
6567 PyOS_AfterFork_Child();
6568 } else {
6569 /* parent: release the import lock. */
6570 PyOS_AfterFork_Parent();
6571 }
6572 if (pid == -1)
6573 return posix_error();
6574 return PyLong_FromPid(pid);
6575 }
6576 #endif /* HAVE_FORK1 */
6577
6578
6579 #ifdef HAVE_FORK
6580 /*[clinic input]
6581 os.fork
6582
6583 Fork a child process.
6584
6585 Return 0 to child process and PID of child to parent process.
6586 [clinic start generated code]*/
6587
6588 static PyObject *
os_fork_impl(PyObject * module)6589 os_fork_impl(PyObject *module)
6590 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6591 {
6592 pid_t pid;
6593 PyInterpreterState *interp = _PyInterpreterState_GET();
6594 if (interp->config._isolated_interpreter) {
6595 PyErr_SetString(PyExc_RuntimeError,
6596 "fork not supported for isolated subinterpreters");
6597 return NULL;
6598 }
6599 if (PySys_Audit("os.fork", NULL) < 0) {
6600 return NULL;
6601 }
6602 PyOS_BeforeFork();
6603 pid = fork();
6604 if (pid == 0) {
6605 /* child: this clobbers and resets the import lock. */
6606 PyOS_AfterFork_Child();
6607 } else {
6608 /* parent: release the import lock. */
6609 PyOS_AfterFork_Parent();
6610 }
6611 if (pid == -1)
6612 return posix_error();
6613 return PyLong_FromPid(pid);
6614 }
6615 #endif /* HAVE_FORK */
6616
6617
6618 #ifdef HAVE_SCHED_H
6619 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6620 /*[clinic input]
6621 os.sched_get_priority_max
6622
6623 policy: int
6624
6625 Get the maximum scheduling priority for policy.
6626 [clinic start generated code]*/
6627
6628 static PyObject *
os_sched_get_priority_max_impl(PyObject * module,int policy)6629 os_sched_get_priority_max_impl(PyObject *module, int policy)
6630 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6631 {
6632 int max;
6633
6634 max = sched_get_priority_max(policy);
6635 if (max < 0)
6636 return posix_error();
6637 return PyLong_FromLong(max);
6638 }
6639
6640
6641 /*[clinic input]
6642 os.sched_get_priority_min
6643
6644 policy: int
6645
6646 Get the minimum scheduling priority for policy.
6647 [clinic start generated code]*/
6648
6649 static PyObject *
os_sched_get_priority_min_impl(PyObject * module,int policy)6650 os_sched_get_priority_min_impl(PyObject *module, int policy)
6651 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6652 {
6653 int min = sched_get_priority_min(policy);
6654 if (min < 0)
6655 return posix_error();
6656 return PyLong_FromLong(min);
6657 }
6658 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6659
6660
6661 #ifdef HAVE_SCHED_SETSCHEDULER
6662 /*[clinic input]
6663 os.sched_getscheduler
6664 pid: pid_t
6665 /
6666
6667 Get the scheduling policy for the process identified by pid.
6668
6669 Passing 0 for pid returns the scheduling policy for the calling process.
6670 [clinic start generated code]*/
6671
6672 static PyObject *
os_sched_getscheduler_impl(PyObject * module,pid_t pid)6673 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6674 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
6675 {
6676 int policy;
6677
6678 policy = sched_getscheduler(pid);
6679 if (policy < 0)
6680 return posix_error();
6681 return PyLong_FromLong(policy);
6682 }
6683 #endif /* HAVE_SCHED_SETSCHEDULER */
6684
6685
6686 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6687 /*[clinic input]
6688 class os.sched_param "PyObject *" "SchedParamType"
6689
6690 @classmethod
6691 os.sched_param.__new__
6692
6693 sched_priority: object
6694 A scheduling parameter.
6695
6696 Currently has only one field: sched_priority
6697 [clinic start generated code]*/
6698
6699 static PyObject *
os_sched_param_impl(PyTypeObject * type,PyObject * sched_priority)6700 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6701 /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
6702 {
6703 PyObject *res;
6704
6705 res = PyStructSequence_New(type);
6706 if (!res)
6707 return NULL;
6708 Py_INCREF(sched_priority);
6709 PyStructSequence_SET_ITEM(res, 0, sched_priority);
6710 return res;
6711 }
6712
6713 PyDoc_VAR(os_sched_param__doc__);
6714
6715 static PyStructSequence_Field sched_param_fields[] = {
6716 {"sched_priority", "the scheduling priority"},
6717 {0}
6718 };
6719
6720 static PyStructSequence_Desc sched_param_desc = {
6721 "sched_param", /* name */
6722 os_sched_param__doc__, /* doc */
6723 sched_param_fields,
6724 1
6725 };
6726
6727 static int
convert_sched_param(PyObject * module,PyObject * param,struct sched_param * res)6728 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
6729 {
6730 long priority;
6731
6732 if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
6733 PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
6734 return 0;
6735 }
6736 priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
6737 if (priority == -1 && PyErr_Occurred())
6738 return 0;
6739 if (priority > INT_MAX || priority < INT_MIN) {
6740 PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
6741 return 0;
6742 }
6743 res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
6744 return 1;
6745 }
6746 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
6747
6748
6749 #ifdef HAVE_SCHED_SETSCHEDULER
6750 /*[clinic input]
6751 os.sched_setscheduler
6752
6753 pid: pid_t
6754 policy: int
6755 param as param_obj: object
6756 /
6757
6758 Set the scheduling policy for the process identified by pid.
6759
6760 If pid is 0, the calling process is changed.
6761 param is an instance of sched_param.
6762 [clinic start generated code]*/
6763
6764 static PyObject *
os_sched_setscheduler_impl(PyObject * module,pid_t pid,int policy,PyObject * param_obj)6765 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
6766 PyObject *param_obj)
6767 /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
6768 {
6769 struct sched_param param;
6770 if (!convert_sched_param(module, param_obj, ¶m)) {
6771 return NULL;
6772 }
6773
6774 /*
6775 ** sched_setscheduler() returns 0 in Linux, but the previous
6776 ** scheduling policy under Solaris/Illumos, and others.
6777 ** On error, -1 is returned in all Operating Systems.
6778 */
6779 if (sched_setscheduler(pid, policy, ¶m) == -1)
6780 return posix_error();
6781 Py_RETURN_NONE;
6782 }
6783 #endif /* HAVE_SCHED_SETSCHEDULER*/
6784
6785
6786 #ifdef HAVE_SCHED_SETPARAM
6787 /*[clinic input]
6788 os.sched_getparam
6789 pid: pid_t
6790 /
6791
6792 Returns scheduling parameters for the process identified by pid.
6793
6794 If pid is 0, returns parameters for the calling process.
6795 Return value is an instance of sched_param.
6796 [clinic start generated code]*/
6797
6798 static PyObject *
os_sched_getparam_impl(PyObject * module,pid_t pid)6799 os_sched_getparam_impl(PyObject *module, pid_t pid)
6800 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
6801 {
6802 struct sched_param param;
6803 PyObject *result;
6804 PyObject *priority;
6805
6806 if (sched_getparam(pid, ¶m))
6807 return posix_error();
6808 PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
6809 result = PyStructSequence_New((PyTypeObject *)SchedParamType);
6810 if (!result)
6811 return NULL;
6812 priority = PyLong_FromLong(param.sched_priority);
6813 if (!priority) {
6814 Py_DECREF(result);
6815 return NULL;
6816 }
6817 PyStructSequence_SET_ITEM(result, 0, priority);
6818 return result;
6819 }
6820
6821
6822 /*[clinic input]
6823 os.sched_setparam
6824 pid: pid_t
6825 param as param_obj: object
6826 /
6827
6828 Set scheduling parameters for the process identified by pid.
6829
6830 If pid is 0, sets parameters for the calling process.
6831 param should be an instance of sched_param.
6832 [clinic start generated code]*/
6833
6834 static PyObject *
os_sched_setparam_impl(PyObject * module,pid_t pid,PyObject * param_obj)6835 os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
6836 /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
6837 {
6838 struct sched_param param;
6839 if (!convert_sched_param(module, param_obj, ¶m)) {
6840 return NULL;
6841 }
6842
6843 if (sched_setparam(pid, ¶m))
6844 return posix_error();
6845 Py_RETURN_NONE;
6846 }
6847 #endif /* HAVE_SCHED_SETPARAM */
6848
6849
6850 #ifdef HAVE_SCHED_RR_GET_INTERVAL
6851 /*[clinic input]
6852 os.sched_rr_get_interval -> double
6853 pid: pid_t
6854 /
6855
6856 Return the round-robin quantum for the process identified by pid, in seconds.
6857
6858 Value returned is a float.
6859 [clinic start generated code]*/
6860
6861 static double
os_sched_rr_get_interval_impl(PyObject * module,pid_t pid)6862 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
6863 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
6864 {
6865 struct timespec interval;
6866 if (sched_rr_get_interval(pid, &interval)) {
6867 posix_error();
6868 return -1.0;
6869 }
6870 #ifdef _Py_MEMORY_SANITIZER
6871 __msan_unpoison(&interval, sizeof(interval));
6872 #endif
6873 return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
6874 }
6875 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
6876
6877
6878 /*[clinic input]
6879 os.sched_yield
6880
6881 Voluntarily relinquish the CPU.
6882 [clinic start generated code]*/
6883
6884 static PyObject *
os_sched_yield_impl(PyObject * module)6885 os_sched_yield_impl(PyObject *module)
6886 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
6887 {
6888 if (sched_yield())
6889 return posix_error();
6890 Py_RETURN_NONE;
6891 }
6892
6893 #ifdef HAVE_SCHED_SETAFFINITY
6894 /* The minimum number of CPUs allocated in a cpu_set_t */
6895 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
6896
6897 /*[clinic input]
6898 os.sched_setaffinity
6899 pid: pid_t
6900 mask : object
6901 /
6902
6903 Set the CPU affinity of the process identified by pid to mask.
6904
6905 mask should be an iterable of integers identifying CPUs.
6906 [clinic start generated code]*/
6907
6908 static PyObject *
os_sched_setaffinity_impl(PyObject * module,pid_t pid,PyObject * mask)6909 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
6910 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
6911 {
6912 int ncpus;
6913 size_t setsize;
6914 cpu_set_t *cpu_set = NULL;
6915 PyObject *iterator = NULL, *item;
6916
6917 iterator = PyObject_GetIter(mask);
6918 if (iterator == NULL)
6919 return NULL;
6920
6921 ncpus = NCPUS_START;
6922 setsize = CPU_ALLOC_SIZE(ncpus);
6923 cpu_set = CPU_ALLOC(ncpus);
6924 if (cpu_set == NULL) {
6925 PyErr_NoMemory();
6926 goto error;
6927 }
6928 CPU_ZERO_S(setsize, cpu_set);
6929
6930 while ((item = PyIter_Next(iterator))) {
6931 long cpu;
6932 if (!PyLong_Check(item)) {
6933 PyErr_Format(PyExc_TypeError,
6934 "expected an iterator of ints, "
6935 "but iterator yielded %R",
6936 Py_TYPE(item));
6937 Py_DECREF(item);
6938 goto error;
6939 }
6940 cpu = PyLong_AsLong(item);
6941 Py_DECREF(item);
6942 if (cpu < 0) {
6943 if (!PyErr_Occurred())
6944 PyErr_SetString(PyExc_ValueError, "negative CPU number");
6945 goto error;
6946 }
6947 if (cpu > INT_MAX - 1) {
6948 PyErr_SetString(PyExc_OverflowError, "CPU number too large");
6949 goto error;
6950 }
6951 if (cpu >= ncpus) {
6952 /* Grow CPU mask to fit the CPU number */
6953 int newncpus = ncpus;
6954 cpu_set_t *newmask;
6955 size_t newsetsize;
6956 while (newncpus <= cpu) {
6957 if (newncpus > INT_MAX / 2)
6958 newncpus = cpu + 1;
6959 else
6960 newncpus = newncpus * 2;
6961 }
6962 newmask = CPU_ALLOC(newncpus);
6963 if (newmask == NULL) {
6964 PyErr_NoMemory();
6965 goto error;
6966 }
6967 newsetsize = CPU_ALLOC_SIZE(newncpus);
6968 CPU_ZERO_S(newsetsize, newmask);
6969 memcpy(newmask, cpu_set, setsize);
6970 CPU_FREE(cpu_set);
6971 setsize = newsetsize;
6972 cpu_set = newmask;
6973 ncpus = newncpus;
6974 }
6975 CPU_SET_S(cpu, setsize, cpu_set);
6976 }
6977 if (PyErr_Occurred()) {
6978 goto error;
6979 }
6980 Py_CLEAR(iterator);
6981
6982 if (sched_setaffinity(pid, setsize, cpu_set)) {
6983 posix_error();
6984 goto error;
6985 }
6986 CPU_FREE(cpu_set);
6987 Py_RETURN_NONE;
6988
6989 error:
6990 if (cpu_set)
6991 CPU_FREE(cpu_set);
6992 Py_XDECREF(iterator);
6993 return NULL;
6994 }
6995
6996
6997 /*[clinic input]
6998 os.sched_getaffinity
6999 pid: pid_t
7000 /
7001
7002 Return the affinity of the process identified by pid (or the current process if zero).
7003
7004 The affinity is returned as a set of CPU identifiers.
7005 [clinic start generated code]*/
7006
7007 static PyObject *
os_sched_getaffinity_impl(PyObject * module,pid_t pid)7008 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
7009 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
7010 {
7011 int cpu, ncpus, count;
7012 size_t setsize;
7013 cpu_set_t *mask = NULL;
7014 PyObject *res = NULL;
7015
7016 ncpus = NCPUS_START;
7017 while (1) {
7018 setsize = CPU_ALLOC_SIZE(ncpus);
7019 mask = CPU_ALLOC(ncpus);
7020 if (mask == NULL)
7021 return PyErr_NoMemory();
7022 if (sched_getaffinity(pid, setsize, mask) == 0)
7023 break;
7024 CPU_FREE(mask);
7025 if (errno != EINVAL)
7026 return posix_error();
7027 if (ncpus > INT_MAX / 2) {
7028 PyErr_SetString(PyExc_OverflowError, "could not allocate "
7029 "a large enough CPU set");
7030 return NULL;
7031 }
7032 ncpus = ncpus * 2;
7033 }
7034
7035 res = PySet_New(NULL);
7036 if (res == NULL)
7037 goto error;
7038 for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7039 if (CPU_ISSET_S(cpu, setsize, mask)) {
7040 PyObject *cpu_num = PyLong_FromLong(cpu);
7041 --count;
7042 if (cpu_num == NULL)
7043 goto error;
7044 if (PySet_Add(res, cpu_num)) {
7045 Py_DECREF(cpu_num);
7046 goto error;
7047 }
7048 Py_DECREF(cpu_num);
7049 }
7050 }
7051 CPU_FREE(mask);
7052 return res;
7053
7054 error:
7055 if (mask)
7056 CPU_FREE(mask);
7057 Py_XDECREF(res);
7058 return NULL;
7059 }
7060
7061 #endif /* HAVE_SCHED_SETAFFINITY */
7062
7063 #endif /* HAVE_SCHED_H */
7064
7065
7066 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
7067 /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
7068 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
7069 #define DEV_PTY_FILE "/dev/ptc"
7070 #define HAVE_DEV_PTMX
7071 #else
7072 #define DEV_PTY_FILE "/dev/ptmx"
7073 #endif
7074
7075 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
7076 #ifdef HAVE_PTY_H
7077 #include <pty.h>
7078 #else
7079 #ifdef HAVE_LIBUTIL_H
7080 #include <libutil.h>
7081 #else
7082 #ifdef HAVE_UTIL_H
7083 #include <util.h>
7084 #endif /* HAVE_UTIL_H */
7085 #endif /* HAVE_LIBUTIL_H */
7086 #endif /* HAVE_PTY_H */
7087 #ifdef HAVE_STROPTS_H
7088 #include <stropts.h>
7089 #endif
7090 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */
7091
7092
7093 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7094 /*[clinic input]
7095 os.openpty
7096
7097 Open a pseudo-terminal.
7098
7099 Return a tuple of (master_fd, slave_fd) containing open file descriptors
7100 for both the master and slave ends.
7101 [clinic start generated code]*/
7102
7103 static PyObject *
os_openpty_impl(PyObject * module)7104 os_openpty_impl(PyObject *module)
7105 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
7106 {
7107 int master_fd = -1, slave_fd = -1;
7108 #ifndef HAVE_OPENPTY
7109 char * slave_name;
7110 #endif
7111 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
7112 PyOS_sighandler_t sig_saved;
7113 #if defined(__sun) && defined(__SVR4)
7114 extern char *ptsname(int fildes);
7115 #endif
7116 #endif
7117
7118 #ifdef HAVE_OPENPTY
7119 if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
7120 goto posix_error;
7121
7122 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7123 goto error;
7124 if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
7125 goto error;
7126
7127 #elif defined(HAVE__GETPTY)
7128 slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
7129 if (slave_name == NULL)
7130 goto posix_error;
7131 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7132 goto error;
7133
7134 slave_fd = _Py_open(slave_name, O_RDWR);
7135 if (slave_fd < 0)
7136 goto error;
7137
7138 #else
7139 master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
7140 if (master_fd < 0)
7141 goto posix_error;
7142
7143 sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
7144
7145 /* change permission of slave */
7146 if (grantpt(master_fd) < 0) {
7147 PyOS_setsig(SIGCHLD, sig_saved);
7148 goto posix_error;
7149 }
7150
7151 /* unlock slave */
7152 if (unlockpt(master_fd) < 0) {
7153 PyOS_setsig(SIGCHLD, sig_saved);
7154 goto posix_error;
7155 }
7156
7157 PyOS_setsig(SIGCHLD, sig_saved);
7158
7159 slave_name = ptsname(master_fd); /* get name of slave */
7160 if (slave_name == NULL)
7161 goto posix_error;
7162
7163 slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
7164 if (slave_fd == -1)
7165 goto error;
7166
7167 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7168 goto posix_error;
7169
7170 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
7171 ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
7172 ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
7173 #ifndef __hpux
7174 ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
7175 #endif /* __hpux */
7176 #endif /* HAVE_CYGWIN */
7177 #endif /* HAVE_OPENPTY */
7178
7179 return Py_BuildValue("(ii)", master_fd, slave_fd);
7180
7181 posix_error:
7182 posix_error();
7183 error:
7184 if (master_fd != -1)
7185 close(master_fd);
7186 if (slave_fd != -1)
7187 close(slave_fd);
7188 return NULL;
7189 }
7190 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
7191
7192
7193 #ifdef HAVE_FORKPTY
7194 /*[clinic input]
7195 os.forkpty
7196
7197 Fork a new process with a new pseudo-terminal as controlling tty.
7198
7199 Returns a tuple of (pid, master_fd).
7200 Like fork(), return pid of 0 to the child process,
7201 and pid of child to the parent process.
7202 To both, return fd of newly opened pseudo-terminal.
7203 [clinic start generated code]*/
7204
7205 static PyObject *
os_forkpty_impl(PyObject * module)7206 os_forkpty_impl(PyObject *module)
7207 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
7208 {
7209 int master_fd = -1;
7210 pid_t pid;
7211
7212 if (_PyInterpreterState_GET() != PyInterpreterState_Main()) {
7213 PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
7214 return NULL;
7215 }
7216 if (PySys_Audit("os.forkpty", NULL) < 0) {
7217 return NULL;
7218 }
7219 PyOS_BeforeFork();
7220 pid = forkpty(&master_fd, NULL, NULL, NULL);
7221 if (pid == 0) {
7222 /* child: this clobbers and resets the import lock. */
7223 PyOS_AfterFork_Child();
7224 } else {
7225 /* parent: release the import lock. */
7226 PyOS_AfterFork_Parent();
7227 }
7228 if (pid == -1)
7229 return posix_error();
7230 return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
7231 }
7232 #endif /* HAVE_FORKPTY */
7233
7234
7235 #ifdef HAVE_GETEGID
7236 /*[clinic input]
7237 os.getegid
7238
7239 Return the current process's effective group id.
7240 [clinic start generated code]*/
7241
7242 static PyObject *
os_getegid_impl(PyObject * module)7243 os_getegid_impl(PyObject *module)
7244 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
7245 {
7246 return _PyLong_FromGid(getegid());
7247 }
7248 #endif /* HAVE_GETEGID */
7249
7250
7251 #ifdef HAVE_GETEUID
7252 /*[clinic input]
7253 os.geteuid
7254
7255 Return the current process's effective user id.
7256 [clinic start generated code]*/
7257
7258 static PyObject *
os_geteuid_impl(PyObject * module)7259 os_geteuid_impl(PyObject *module)
7260 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
7261 {
7262 return _PyLong_FromUid(geteuid());
7263 }
7264 #endif /* HAVE_GETEUID */
7265
7266
7267 #ifdef HAVE_GETGID
7268 /*[clinic input]
7269 os.getgid
7270
7271 Return the current process's group id.
7272 [clinic start generated code]*/
7273
7274 static PyObject *
os_getgid_impl(PyObject * module)7275 os_getgid_impl(PyObject *module)
7276 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
7277 {
7278 return _PyLong_FromGid(getgid());
7279 }
7280 #endif /* HAVE_GETGID */
7281
7282
7283 #ifdef HAVE_GETPID
7284 /*[clinic input]
7285 os.getpid
7286
7287 Return the current process id.
7288 [clinic start generated code]*/
7289
7290 static PyObject *
os_getpid_impl(PyObject * module)7291 os_getpid_impl(PyObject *module)
7292 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
7293 {
7294 return PyLong_FromPid(getpid());
7295 }
7296 #endif /* HAVE_GETPID */
7297
7298 #ifdef NGROUPS_MAX
7299 #define MAX_GROUPS NGROUPS_MAX
7300 #else
7301 /* defined to be 16 on Solaris7, so this should be a small number */
7302 #define MAX_GROUPS 64
7303 #endif
7304
7305 #ifdef HAVE_GETGROUPLIST
7306
7307 #ifdef __APPLE__
7308 /*[clinic input]
7309 os.getgrouplist
7310
7311 user: str
7312 username to lookup
7313 group as basegid: int
7314 base group id of the user
7315 /
7316
7317 Returns a list of groups to which a user belongs.
7318 [clinic start generated code]*/
7319
7320 static PyObject *
os_getgrouplist_impl(PyObject * module,const char * user,int basegid)7321 os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
7322 /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
7323 #else
7324 /*[clinic input]
7325 os.getgrouplist
7326
7327 user: str
7328 username to lookup
7329 group as basegid: gid_t
7330 base group id of the user
7331 /
7332
7333 Returns a list of groups to which a user belongs.
7334 [clinic start generated code]*/
7335
7336 static PyObject *
7337 os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
7338 /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
7339 #endif
7340 {
7341 int i, ngroups;
7342 PyObject *list;
7343 #ifdef __APPLE__
7344 int *groups;
7345 #else
7346 gid_t *groups;
7347 #endif
7348
7349 /*
7350 * NGROUPS_MAX is defined by POSIX.1 as the maximum
7351 * number of supplimental groups a users can belong to.
7352 * We have to increment it by one because
7353 * getgrouplist() returns both the supplemental groups
7354 * and the primary group, i.e. all of the groups the
7355 * user belongs to.
7356 */
7357 ngroups = 1 + MAX_GROUPS;
7358
7359 while (1) {
7360 #ifdef __APPLE__
7361 groups = PyMem_New(int, ngroups);
7362 #else
7363 groups = PyMem_New(gid_t, ngroups);
7364 #endif
7365 if (groups == NULL) {
7366 return PyErr_NoMemory();
7367 }
7368
7369 int old_ngroups = ngroups;
7370 if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
7371 /* Success */
7372 break;
7373 }
7374
7375 /* getgrouplist() fails if the group list is too small */
7376 PyMem_Free(groups);
7377
7378 if (ngroups > old_ngroups) {
7379 /* If the group list is too small, the glibc implementation of
7380 getgrouplist() sets ngroups to the total number of groups and
7381 returns -1. */
7382 }
7383 else {
7384 /* Double the group list size */
7385 if (ngroups > INT_MAX / 2) {
7386 return PyErr_NoMemory();
7387 }
7388 ngroups *= 2;
7389 }
7390
7391 /* Retry getgrouplist() with a larger group list */
7392 }
7393
7394 #ifdef _Py_MEMORY_SANITIZER
7395 /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
7396 __msan_unpoison(&ngroups, sizeof(ngroups));
7397 __msan_unpoison(groups, ngroups*sizeof(*groups));
7398 #endif
7399
7400 list = PyList_New(ngroups);
7401 if (list == NULL) {
7402 PyMem_Del(groups);
7403 return NULL;
7404 }
7405
7406 for (i = 0; i < ngroups; i++) {
7407 #ifdef __APPLE__
7408 PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7409 #else
7410 PyObject *o = _PyLong_FromGid(groups[i]);
7411 #endif
7412 if (o == NULL) {
7413 Py_DECREF(list);
7414 PyMem_Del(groups);
7415 return NULL;
7416 }
7417 PyList_SET_ITEM(list, i, o);
7418 }
7419
7420 PyMem_Del(groups);
7421
7422 return list;
7423 }
7424 #endif /* HAVE_GETGROUPLIST */
7425
7426
7427 #ifdef HAVE_GETGROUPS
7428 /*[clinic input]
7429 os.getgroups
7430
7431 Return list of supplemental group IDs for the process.
7432 [clinic start generated code]*/
7433
7434 static PyObject *
os_getgroups_impl(PyObject * module)7435 os_getgroups_impl(PyObject *module)
7436 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
7437 {
7438 PyObject *result = NULL;
7439 gid_t grouplist[MAX_GROUPS];
7440
7441 /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
7442 * This is a helper variable to store the intermediate result when
7443 * that happens.
7444 *
7445 * To keep the code readable the OSX behaviour is unconditional,
7446 * according to the POSIX spec this should be safe on all unix-y
7447 * systems.
7448 */
7449 gid_t* alt_grouplist = grouplist;
7450 int n;
7451
7452 #ifdef __APPLE__
7453 /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if
7454 * there are more groups than can fit in grouplist. Therefore, on OS X
7455 * always first call getgroups with length 0 to get the actual number
7456 * of groups.
7457 */
7458 n = getgroups(0, NULL);
7459 if (n < 0) {
7460 return posix_error();
7461 } else if (n <= MAX_GROUPS) {
7462 /* groups will fit in existing array */
7463 alt_grouplist = grouplist;
7464 } else {
7465 alt_grouplist = PyMem_New(gid_t, n);
7466 if (alt_grouplist == NULL) {
7467 return PyErr_NoMemory();
7468 }
7469 }
7470
7471 n = getgroups(n, alt_grouplist);
7472 if (n == -1) {
7473 if (alt_grouplist != grouplist) {
7474 PyMem_Free(alt_grouplist);
7475 }
7476 return posix_error();
7477 }
7478 #else
7479 n = getgroups(MAX_GROUPS, grouplist);
7480 if (n < 0) {
7481 if (errno == EINVAL) {
7482 n = getgroups(0, NULL);
7483 if (n == -1) {
7484 return posix_error();
7485 }
7486 if (n == 0) {
7487 /* Avoid malloc(0) */
7488 alt_grouplist = grouplist;
7489 } else {
7490 alt_grouplist = PyMem_New(gid_t, n);
7491 if (alt_grouplist == NULL) {
7492 return PyErr_NoMemory();
7493 }
7494 n = getgroups(n, alt_grouplist);
7495 if (n == -1) {
7496 PyMem_Free(alt_grouplist);
7497 return posix_error();
7498 }
7499 }
7500 } else {
7501 return posix_error();
7502 }
7503 }
7504 #endif
7505
7506 result = PyList_New(n);
7507 if (result != NULL) {
7508 int i;
7509 for (i = 0; i < n; ++i) {
7510 PyObject *o = _PyLong_FromGid(alt_grouplist[i]);
7511 if (o == NULL) {
7512 Py_DECREF(result);
7513 result = NULL;
7514 break;
7515 }
7516 PyList_SET_ITEM(result, i, o);
7517 }
7518 }
7519
7520 if (alt_grouplist != grouplist) {
7521 PyMem_Free(alt_grouplist);
7522 }
7523
7524 return result;
7525 }
7526 #endif /* HAVE_GETGROUPS */
7527
7528 #ifdef HAVE_INITGROUPS
7529 #ifdef __APPLE__
7530 /*[clinic input]
7531 os.initgroups
7532
7533 username as oname: FSConverter
7534 gid: int
7535 /
7536
7537 Initialize the group access list.
7538
7539 Call the system initgroups() to initialize the group access list with all of
7540 the groups of which the specified username is a member, plus the specified
7541 group id.
7542 [clinic start generated code]*/
7543
7544 static PyObject *
os_initgroups_impl(PyObject * module,PyObject * oname,int gid)7545 os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
7546 /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
7547 #else
7548 /*[clinic input]
7549 os.initgroups
7550
7551 username as oname: FSConverter
7552 gid: gid_t
7553 /
7554
7555 Initialize the group access list.
7556
7557 Call the system initgroups() to initialize the group access list with all of
7558 the groups of which the specified username is a member, plus the specified
7559 group id.
7560 [clinic start generated code]*/
7561
7562 static PyObject *
7563 os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
7564 /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
7565 #endif
7566 {
7567 const char *username = PyBytes_AS_STRING(oname);
7568
7569 if (initgroups(username, gid) == -1)
7570 return PyErr_SetFromErrno(PyExc_OSError);
7571
7572 Py_RETURN_NONE;
7573 }
7574 #endif /* HAVE_INITGROUPS */
7575
7576
7577 #ifdef HAVE_GETPGID
7578 /*[clinic input]
7579 os.getpgid
7580
7581 pid: pid_t
7582
7583 Call the system call getpgid(), and return the result.
7584 [clinic start generated code]*/
7585
7586 static PyObject *
os_getpgid_impl(PyObject * module,pid_t pid)7587 os_getpgid_impl(PyObject *module, pid_t pid)
7588 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7589 {
7590 pid_t pgid = getpgid(pid);
7591 if (pgid < 0)
7592 return posix_error();
7593 return PyLong_FromPid(pgid);
7594 }
7595 #endif /* HAVE_GETPGID */
7596
7597
7598 #ifdef HAVE_GETPGRP
7599 /*[clinic input]
7600 os.getpgrp
7601
7602 Return the current process group id.
7603 [clinic start generated code]*/
7604
7605 static PyObject *
os_getpgrp_impl(PyObject * module)7606 os_getpgrp_impl(PyObject *module)
7607 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7608 {
7609 #ifdef GETPGRP_HAVE_ARG
7610 return PyLong_FromPid(getpgrp(0));
7611 #else /* GETPGRP_HAVE_ARG */
7612 return PyLong_FromPid(getpgrp());
7613 #endif /* GETPGRP_HAVE_ARG */
7614 }
7615 #endif /* HAVE_GETPGRP */
7616
7617
7618 #ifdef HAVE_SETPGRP
7619 /*[clinic input]
7620 os.setpgrp
7621
7622 Make the current process the leader of its process group.
7623 [clinic start generated code]*/
7624
7625 static PyObject *
os_setpgrp_impl(PyObject * module)7626 os_setpgrp_impl(PyObject *module)
7627 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7628 {
7629 #ifdef SETPGRP_HAVE_ARG
7630 if (setpgrp(0, 0) < 0)
7631 #else /* SETPGRP_HAVE_ARG */
7632 if (setpgrp() < 0)
7633 #endif /* SETPGRP_HAVE_ARG */
7634 return posix_error();
7635 Py_RETURN_NONE;
7636 }
7637 #endif /* HAVE_SETPGRP */
7638
7639 #ifdef HAVE_GETPPID
7640
7641 #ifdef MS_WINDOWS
7642 #include <tlhelp32.h>
7643
7644 static PyObject*
win32_getppid()7645 win32_getppid()
7646 {
7647 HANDLE snapshot;
7648 pid_t mypid;
7649 PyObject* result = NULL;
7650 BOOL have_record;
7651 PROCESSENTRY32 pe;
7652
7653 mypid = getpid(); /* This function never fails */
7654
7655 snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7656 if (snapshot == INVALID_HANDLE_VALUE)
7657 return PyErr_SetFromWindowsErr(GetLastError());
7658
7659 pe.dwSize = sizeof(pe);
7660 have_record = Process32First(snapshot, &pe);
7661 while (have_record) {
7662 if (mypid == (pid_t)pe.th32ProcessID) {
7663 /* We could cache the ulong value in a static variable. */
7664 result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7665 break;
7666 }
7667
7668 have_record = Process32Next(snapshot, &pe);
7669 }
7670
7671 /* If our loop exits and our pid was not found (result will be NULL)
7672 * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7673 * error anyway, so let's raise it. */
7674 if (!result)
7675 result = PyErr_SetFromWindowsErr(GetLastError());
7676
7677 CloseHandle(snapshot);
7678
7679 return result;
7680 }
7681 #endif /*MS_WINDOWS*/
7682
7683
7684 /*[clinic input]
7685 os.getppid
7686
7687 Return the parent's process id.
7688
7689 If the parent process has already exited, Windows machines will still
7690 return its id; others systems will return the id of the 'init' process (1).
7691 [clinic start generated code]*/
7692
7693 static PyObject *
os_getppid_impl(PyObject * module)7694 os_getppid_impl(PyObject *module)
7695 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7696 {
7697 #ifdef MS_WINDOWS
7698 return win32_getppid();
7699 #else
7700 return PyLong_FromPid(getppid());
7701 #endif
7702 }
7703 #endif /* HAVE_GETPPID */
7704
7705
7706 #ifdef HAVE_GETLOGIN
7707 /*[clinic input]
7708 os.getlogin
7709
7710 Return the actual login name.
7711 [clinic start generated code]*/
7712
7713 static PyObject *
os_getlogin_impl(PyObject * module)7714 os_getlogin_impl(PyObject *module)
7715 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7716 {
7717 PyObject *result = NULL;
7718 #ifdef MS_WINDOWS
7719 wchar_t user_name[UNLEN + 1];
7720 DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7721
7722 if (GetUserNameW(user_name, &num_chars)) {
7723 /* num_chars is the number of unicode chars plus null terminator */
7724 result = PyUnicode_FromWideChar(user_name, num_chars - 1);
7725 }
7726 else
7727 result = PyErr_SetFromWindowsErr(GetLastError());
7728 #else
7729 char *name;
7730 int old_errno = errno;
7731
7732 errno = 0;
7733 name = getlogin();
7734 if (name == NULL) {
7735 if (errno)
7736 posix_error();
7737 else
7738 PyErr_SetString(PyExc_OSError, "unable to determine login name");
7739 }
7740 else
7741 result = PyUnicode_DecodeFSDefault(name);
7742 errno = old_errno;
7743 #endif
7744 return result;
7745 }
7746 #endif /* HAVE_GETLOGIN */
7747
7748
7749 #ifdef HAVE_GETUID
7750 /*[clinic input]
7751 os.getuid
7752
7753 Return the current process's user id.
7754 [clinic start generated code]*/
7755
7756 static PyObject *
os_getuid_impl(PyObject * module)7757 os_getuid_impl(PyObject *module)
7758 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7759 {
7760 return _PyLong_FromUid(getuid());
7761 }
7762 #endif /* HAVE_GETUID */
7763
7764
7765 #ifdef MS_WINDOWS
7766 #define HAVE_KILL
7767 #endif /* MS_WINDOWS */
7768
7769 #ifdef HAVE_KILL
7770 /*[clinic input]
7771 os.kill
7772
7773 pid: pid_t
7774 signal: Py_ssize_t
7775 /
7776
7777 Kill a process with a signal.
7778 [clinic start generated code]*/
7779
7780 static PyObject *
os_kill_impl(PyObject * module,pid_t pid,Py_ssize_t signal)7781 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
7782 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
7783 {
7784 if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
7785 return NULL;
7786 }
7787 #ifndef MS_WINDOWS
7788 if (kill(pid, (int)signal) == -1)
7789 return posix_error();
7790 Py_RETURN_NONE;
7791 #else /* !MS_WINDOWS */
7792 PyObject *result;
7793 DWORD sig = (DWORD)signal;
7794 DWORD err;
7795 HANDLE handle;
7796
7797 /* Console processes which share a common console can be sent CTRL+C or
7798 CTRL+BREAK events, provided they handle said events. */
7799 if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
7800 if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
7801 err = GetLastError();
7802 PyErr_SetFromWindowsErr(err);
7803 }
7804 else
7805 Py_RETURN_NONE;
7806 }
7807
7808 /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
7809 attempt to open and terminate the process. */
7810 handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
7811 if (handle == NULL) {
7812 err = GetLastError();
7813 return PyErr_SetFromWindowsErr(err);
7814 }
7815
7816 if (TerminateProcess(handle, sig) == 0) {
7817 err = GetLastError();
7818 result = PyErr_SetFromWindowsErr(err);
7819 } else {
7820 Py_INCREF(Py_None);
7821 result = Py_None;
7822 }
7823
7824 CloseHandle(handle);
7825 return result;
7826 #endif /* !MS_WINDOWS */
7827 }
7828 #endif /* HAVE_KILL */
7829
7830
7831 #ifdef HAVE_KILLPG
7832 /*[clinic input]
7833 os.killpg
7834
7835 pgid: pid_t
7836 signal: int
7837 /
7838
7839 Kill a process group with a signal.
7840 [clinic start generated code]*/
7841
7842 static PyObject *
os_killpg_impl(PyObject * module,pid_t pgid,int signal)7843 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
7844 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
7845 {
7846 if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
7847 return NULL;
7848 }
7849 /* XXX some man pages make the `pgid` parameter an int, others
7850 a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
7851 take the same type. Moreover, pid_t is always at least as wide as
7852 int (else compilation of this module fails), which is safe. */
7853 if (killpg(pgid, signal) == -1)
7854 return posix_error();
7855 Py_RETURN_NONE;
7856 }
7857 #endif /* HAVE_KILLPG */
7858
7859
7860 #ifdef HAVE_PLOCK
7861 #ifdef HAVE_SYS_LOCK_H
7862 #include <sys/lock.h>
7863 #endif
7864
7865 /*[clinic input]
7866 os.plock
7867 op: int
7868 /
7869
7870 Lock program segments into memory.");
7871 [clinic start generated code]*/
7872
7873 static PyObject *
os_plock_impl(PyObject * module,int op)7874 os_plock_impl(PyObject *module, int op)
7875 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
7876 {
7877 if (plock(op) == -1)
7878 return posix_error();
7879 Py_RETURN_NONE;
7880 }
7881 #endif /* HAVE_PLOCK */
7882
7883
7884 #ifdef HAVE_SETUID
7885 /*[clinic input]
7886 os.setuid
7887
7888 uid: uid_t
7889 /
7890
7891 Set the current process's user id.
7892 [clinic start generated code]*/
7893
7894 static PyObject *
os_setuid_impl(PyObject * module,uid_t uid)7895 os_setuid_impl(PyObject *module, uid_t uid)
7896 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
7897 {
7898 if (setuid(uid) < 0)
7899 return posix_error();
7900 Py_RETURN_NONE;
7901 }
7902 #endif /* HAVE_SETUID */
7903
7904
7905 #ifdef HAVE_SETEUID
7906 /*[clinic input]
7907 os.seteuid
7908
7909 euid: uid_t
7910 /
7911
7912 Set the current process's effective user id.
7913 [clinic start generated code]*/
7914
7915 static PyObject *
os_seteuid_impl(PyObject * module,uid_t euid)7916 os_seteuid_impl(PyObject *module, uid_t euid)
7917 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
7918 {
7919 if (seteuid(euid) < 0)
7920 return posix_error();
7921 Py_RETURN_NONE;
7922 }
7923 #endif /* HAVE_SETEUID */
7924
7925
7926 #ifdef HAVE_SETEGID
7927 /*[clinic input]
7928 os.setegid
7929
7930 egid: gid_t
7931 /
7932
7933 Set the current process's effective group id.
7934 [clinic start generated code]*/
7935
7936 static PyObject *
os_setegid_impl(PyObject * module,gid_t egid)7937 os_setegid_impl(PyObject *module, gid_t egid)
7938 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
7939 {
7940 if (setegid(egid) < 0)
7941 return posix_error();
7942 Py_RETURN_NONE;
7943 }
7944 #endif /* HAVE_SETEGID */
7945
7946
7947 #ifdef HAVE_SETREUID
7948 /*[clinic input]
7949 os.setreuid
7950
7951 ruid: uid_t
7952 euid: uid_t
7953 /
7954
7955 Set the current process's real and effective user ids.
7956 [clinic start generated code]*/
7957
7958 static PyObject *
os_setreuid_impl(PyObject * module,uid_t ruid,uid_t euid)7959 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
7960 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
7961 {
7962 if (setreuid(ruid, euid) < 0) {
7963 return posix_error();
7964 } else {
7965 Py_RETURN_NONE;
7966 }
7967 }
7968 #endif /* HAVE_SETREUID */
7969
7970
7971 #ifdef HAVE_SETREGID
7972 /*[clinic input]
7973 os.setregid
7974
7975 rgid: gid_t
7976 egid: gid_t
7977 /
7978
7979 Set the current process's real and effective group ids.
7980 [clinic start generated code]*/
7981
7982 static PyObject *
os_setregid_impl(PyObject * module,gid_t rgid,gid_t egid)7983 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
7984 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
7985 {
7986 if (setregid(rgid, egid) < 0)
7987 return posix_error();
7988 Py_RETURN_NONE;
7989 }
7990 #endif /* HAVE_SETREGID */
7991
7992
7993 #ifdef HAVE_SETGID
7994 /*[clinic input]
7995 os.setgid
7996 gid: gid_t
7997 /
7998
7999 Set the current process's group id.
8000 [clinic start generated code]*/
8001
8002 static PyObject *
os_setgid_impl(PyObject * module,gid_t gid)8003 os_setgid_impl(PyObject *module, gid_t gid)
8004 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
8005 {
8006 if (setgid(gid) < 0)
8007 return posix_error();
8008 Py_RETURN_NONE;
8009 }
8010 #endif /* HAVE_SETGID */
8011
8012
8013 #ifdef HAVE_SETGROUPS
8014 /*[clinic input]
8015 os.setgroups
8016
8017 groups: object
8018 /
8019
8020 Set the groups of the current process to list.
8021 [clinic start generated code]*/
8022
8023 static PyObject *
os_setgroups(PyObject * module,PyObject * groups)8024 os_setgroups(PyObject *module, PyObject *groups)
8025 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
8026 {
8027 Py_ssize_t i, len;
8028 gid_t grouplist[MAX_GROUPS];
8029
8030 if (!PySequence_Check(groups)) {
8031 PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
8032 return NULL;
8033 }
8034 len = PySequence_Size(groups);
8035 if (len < 0) {
8036 return NULL;
8037 }
8038 if (len > MAX_GROUPS) {
8039 PyErr_SetString(PyExc_ValueError, "too many groups");
8040 return NULL;
8041 }
8042 for(i = 0; i < len; i++) {
8043 PyObject *elem;
8044 elem = PySequence_GetItem(groups, i);
8045 if (!elem)
8046 return NULL;
8047 if (!PyLong_Check(elem)) {
8048 PyErr_SetString(PyExc_TypeError,
8049 "groups must be integers");
8050 Py_DECREF(elem);
8051 return NULL;
8052 } else {
8053 if (!_Py_Gid_Converter(elem, &grouplist[i])) {
8054 Py_DECREF(elem);
8055 return NULL;
8056 }
8057 }
8058 Py_DECREF(elem);
8059 }
8060
8061 if (setgroups(len, grouplist) < 0)
8062 return posix_error();
8063 Py_RETURN_NONE;
8064 }
8065 #endif /* HAVE_SETGROUPS */
8066
8067 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
8068 static PyObject *
wait_helper(PyObject * module,pid_t pid,int status,struct rusage * ru)8069 wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
8070 {
8071 PyObject *result;
8072 PyObject *struct_rusage;
8073
8074 if (pid == -1)
8075 return posix_error();
8076
8077 // If wait succeeded but no child was ready to report status, ru will not
8078 // have been populated.
8079 if (pid == 0) {
8080 memset(ru, 0, sizeof(*ru));
8081 }
8082
8083 PyObject *m = PyImport_ImportModuleNoBlock("resource");
8084 if (m == NULL)
8085 return NULL;
8086 struct_rusage = PyObject_GetAttr(m, get_posix_state(module)->struct_rusage);
8087 Py_DECREF(m);
8088 if (struct_rusage == NULL)
8089 return NULL;
8090
8091 /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
8092 result = PyStructSequence_New((PyTypeObject*) struct_rusage);
8093 Py_DECREF(struct_rusage);
8094 if (!result)
8095 return NULL;
8096
8097 #ifndef doubletime
8098 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
8099 #endif
8100
8101 PyStructSequence_SET_ITEM(result, 0,
8102 PyFloat_FromDouble(doubletime(ru->ru_utime)));
8103 PyStructSequence_SET_ITEM(result, 1,
8104 PyFloat_FromDouble(doubletime(ru->ru_stime)));
8105 #define SET_INT(result, index, value)\
8106 PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
8107 SET_INT(result, 2, ru->ru_maxrss);
8108 SET_INT(result, 3, ru->ru_ixrss);
8109 SET_INT(result, 4, ru->ru_idrss);
8110 SET_INT(result, 5, ru->ru_isrss);
8111 SET_INT(result, 6, ru->ru_minflt);
8112 SET_INT(result, 7, ru->ru_majflt);
8113 SET_INT(result, 8, ru->ru_nswap);
8114 SET_INT(result, 9, ru->ru_inblock);
8115 SET_INT(result, 10, ru->ru_oublock);
8116 SET_INT(result, 11, ru->ru_msgsnd);
8117 SET_INT(result, 12, ru->ru_msgrcv);
8118 SET_INT(result, 13, ru->ru_nsignals);
8119 SET_INT(result, 14, ru->ru_nvcsw);
8120 SET_INT(result, 15, ru->ru_nivcsw);
8121 #undef SET_INT
8122
8123 if (PyErr_Occurred()) {
8124 Py_DECREF(result);
8125 return NULL;
8126 }
8127
8128 return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
8129 }
8130 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
8131
8132
8133 #ifdef HAVE_WAIT3
8134 /*[clinic input]
8135 os.wait3
8136
8137 options: int
8138 Wait for completion of a child process.
8139
8140 Returns a tuple of information about the child process:
8141 (pid, status, rusage)
8142 [clinic start generated code]*/
8143
8144 static PyObject *
os_wait3_impl(PyObject * module,int options)8145 os_wait3_impl(PyObject *module, int options)
8146 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
8147 {
8148 pid_t pid;
8149 struct rusage ru;
8150 int async_err = 0;
8151 WAIT_TYPE status;
8152 WAIT_STATUS_INT(status) = 0;
8153
8154 do {
8155 Py_BEGIN_ALLOW_THREADS
8156 pid = wait3(&status, options, &ru);
8157 Py_END_ALLOW_THREADS
8158 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8159 if (pid < 0)
8160 return (!async_err) ? posix_error() : NULL;
8161
8162 return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
8163 }
8164 #endif /* HAVE_WAIT3 */
8165
8166
8167 #ifdef HAVE_WAIT4
8168 /*[clinic input]
8169
8170 os.wait4
8171
8172 pid: pid_t
8173 options: int
8174
8175 Wait for completion of a specific child process.
8176
8177 Returns a tuple of information about the child process:
8178 (pid, status, rusage)
8179 [clinic start generated code]*/
8180
8181 static PyObject *
os_wait4_impl(PyObject * module,pid_t pid,int options)8182 os_wait4_impl(PyObject *module, pid_t pid, int options)
8183 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
8184 {
8185 pid_t res;
8186 struct rusage ru;
8187 int async_err = 0;
8188 WAIT_TYPE status;
8189 WAIT_STATUS_INT(status) = 0;
8190
8191 do {
8192 Py_BEGIN_ALLOW_THREADS
8193 res = wait4(pid, &status, options, &ru);
8194 Py_END_ALLOW_THREADS
8195 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8196 if (res < 0)
8197 return (!async_err) ? posix_error() : NULL;
8198
8199 return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
8200 }
8201 #endif /* HAVE_WAIT4 */
8202
8203
8204 #if defined(HAVE_WAITID) && !defined(__APPLE__)
8205 /*[clinic input]
8206 os.waitid
8207
8208 idtype: idtype_t
8209 Must be one of be P_PID, P_PGID or P_ALL.
8210 id: id_t
8211 The id to wait on.
8212 options: int
8213 Constructed from the ORing of one or more of WEXITED, WSTOPPED
8214 or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
8215 /
8216
8217 Returns the result of waiting for a process or processes.
8218
8219 Returns either waitid_result or None if WNOHANG is specified and there are
8220 no children in a waitable state.
8221 [clinic start generated code]*/
8222
8223 static PyObject *
os_waitid_impl(PyObject * module,idtype_t idtype,id_t id,int options)8224 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
8225 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
8226 {
8227 PyObject *result;
8228 int res;
8229 int async_err = 0;
8230 siginfo_t si;
8231 si.si_pid = 0;
8232
8233 do {
8234 Py_BEGIN_ALLOW_THREADS
8235 res = waitid(idtype, id, &si, options);
8236 Py_END_ALLOW_THREADS
8237 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8238 if (res < 0)
8239 return (!async_err) ? posix_error() : NULL;
8240
8241 if (si.si_pid == 0)
8242 Py_RETURN_NONE;
8243
8244 PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
8245 result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
8246 if (!result)
8247 return NULL;
8248
8249 PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
8250 PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
8251 PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
8252 PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
8253 PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
8254 if (PyErr_Occurred()) {
8255 Py_DECREF(result);
8256 return NULL;
8257 }
8258
8259 return result;
8260 }
8261 #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
8262
8263
8264 #if defined(HAVE_WAITPID)
8265 /*[clinic input]
8266 os.waitpid
8267 pid: pid_t
8268 options: int
8269 /
8270
8271 Wait for completion of a given child process.
8272
8273 Returns a tuple of information regarding the child process:
8274 (pid, status)
8275
8276 The options argument is ignored on Windows.
8277 [clinic start generated code]*/
8278
8279 static PyObject *
os_waitpid_impl(PyObject * module,pid_t pid,int options)8280 os_waitpid_impl(PyObject *module, pid_t pid, int options)
8281 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
8282 {
8283 pid_t res;
8284 int async_err = 0;
8285 WAIT_TYPE status;
8286 WAIT_STATUS_INT(status) = 0;
8287
8288 do {
8289 Py_BEGIN_ALLOW_THREADS
8290 res = waitpid(pid, &status, options);
8291 Py_END_ALLOW_THREADS
8292 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8293 if (res < 0)
8294 return (!async_err) ? posix_error() : NULL;
8295
8296 return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
8297 }
8298 #elif defined(HAVE_CWAIT)
8299 /* MS C has a variant of waitpid() that's usable for most purposes. */
8300 /*[clinic input]
8301 os.waitpid
8302 pid: intptr_t
8303 options: int
8304 /
8305
8306 Wait for completion of a given process.
8307
8308 Returns a tuple of information regarding the process:
8309 (pid, status << 8)
8310
8311 The options argument is ignored on Windows.
8312 [clinic start generated code]*/
8313
8314 static PyObject *
os_waitpid_impl(PyObject * module,intptr_t pid,int options)8315 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
8316 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
8317 {
8318 int status;
8319 intptr_t res;
8320 int async_err = 0;
8321
8322 do {
8323 Py_BEGIN_ALLOW_THREADS
8324 _Py_BEGIN_SUPPRESS_IPH
8325 res = _cwait(&status, pid, options);
8326 _Py_END_SUPPRESS_IPH
8327 Py_END_ALLOW_THREADS
8328 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8329 if (res < 0)
8330 return (!async_err) ? posix_error() : NULL;
8331
8332 unsigned long long ustatus = (unsigned int)status;
8333
8334 /* shift the status left a byte so this is more like the POSIX waitpid */
8335 return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
8336 }
8337 #endif
8338
8339
8340 #ifdef HAVE_WAIT
8341 /*[clinic input]
8342 os.wait
8343
8344 Wait for completion of a child process.
8345
8346 Returns a tuple of information about the child process:
8347 (pid, status)
8348 [clinic start generated code]*/
8349
8350 static PyObject *
os_wait_impl(PyObject * module)8351 os_wait_impl(PyObject *module)
8352 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
8353 {
8354 pid_t pid;
8355 int async_err = 0;
8356 WAIT_TYPE status;
8357 WAIT_STATUS_INT(status) = 0;
8358
8359 do {
8360 Py_BEGIN_ALLOW_THREADS
8361 pid = wait(&status);
8362 Py_END_ALLOW_THREADS
8363 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8364 if (pid < 0)
8365 return (!async_err) ? posix_error() : NULL;
8366
8367 return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
8368 }
8369 #endif /* HAVE_WAIT */
8370
8371 #if defined(__linux__) && defined(__NR_pidfd_open)
8372 /*[clinic input]
8373 os.pidfd_open
8374 pid: pid_t
8375 flags: unsigned_int = 0
8376
8377 Return a file descriptor referring to the process *pid*.
8378
8379 The descriptor can be used to perform process management without races and
8380 signals.
8381 [clinic start generated code]*/
8382
8383 static PyObject *
os_pidfd_open_impl(PyObject * module,pid_t pid,unsigned int flags)8384 os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
8385 /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
8386 {
8387 int fd = syscall(__NR_pidfd_open, pid, flags);
8388 if (fd < 0) {
8389 return posix_error();
8390 }
8391 return PyLong_FromLong(fd);
8392 }
8393 #endif
8394
8395
8396 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
8397 /*[clinic input]
8398 os.readlink
8399
8400 path: path_t
8401 *
8402 dir_fd: dir_fd(requires='readlinkat') = None
8403
8404 Return a string representing the path to which the symbolic link points.
8405
8406 If dir_fd is not None, it should be a file descriptor open to a directory,
8407 and path should be relative; path will then be relative to that directory.
8408
8409 dir_fd may not be implemented on your platform. If it is unavailable,
8410 using it will raise a NotImplementedError.
8411 [clinic start generated code]*/
8412
8413 static PyObject *
os_readlink_impl(PyObject * module,path_t * path,int dir_fd)8414 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
8415 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
8416 {
8417 #if defined(HAVE_READLINK)
8418 char buffer[MAXPATHLEN+1];
8419 ssize_t length;
8420 #ifdef HAVE_READLINKAT
8421 int readlinkat_unavailable = 0;
8422 #endif
8423
8424 Py_BEGIN_ALLOW_THREADS
8425 #ifdef HAVE_READLINKAT
8426 if (dir_fd != DEFAULT_DIR_FD) {
8427 if (HAVE_READLINKAT_RUNTIME) {
8428 length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
8429 } else {
8430 readlinkat_unavailable = 1;
8431 }
8432 } else
8433 #endif
8434 length = readlink(path->narrow, buffer, MAXPATHLEN);
8435 Py_END_ALLOW_THREADS
8436
8437 #ifdef HAVE_READLINKAT
8438 if (readlinkat_unavailable) {
8439 argument_unavailable_error(NULL, "dir_fd");
8440 return NULL;
8441 }
8442 #endif
8443
8444 if (length < 0) {
8445 return path_error(path);
8446 }
8447 buffer[length] = '\0';
8448
8449 if (PyUnicode_Check(path->object))
8450 return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
8451 else
8452 return PyBytes_FromStringAndSize(buffer, length);
8453 #elif defined(MS_WINDOWS)
8454 DWORD n_bytes_returned;
8455 DWORD io_result = 0;
8456 HANDLE reparse_point_handle;
8457 char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
8458 _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
8459 PyObject *result = NULL;
8460
8461 /* First get a handle to the reparse point */
8462 Py_BEGIN_ALLOW_THREADS
8463 reparse_point_handle = CreateFileW(
8464 path->wide,
8465 0,
8466 0,
8467 0,
8468 OPEN_EXISTING,
8469 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
8470 0);
8471 if (reparse_point_handle != INVALID_HANDLE_VALUE) {
8472 /* New call DeviceIoControl to read the reparse point */
8473 io_result = DeviceIoControl(
8474 reparse_point_handle,
8475 FSCTL_GET_REPARSE_POINT,
8476 0, 0, /* in buffer */
8477 target_buffer, sizeof(target_buffer),
8478 &n_bytes_returned,
8479 0 /* we're not using OVERLAPPED_IO */
8480 );
8481 CloseHandle(reparse_point_handle);
8482 }
8483 Py_END_ALLOW_THREADS
8484
8485 if (io_result == 0) {
8486 return path_error(path);
8487 }
8488
8489 wchar_t *name = NULL;
8490 Py_ssize_t nameLen = 0;
8491 if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
8492 {
8493 name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
8494 rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
8495 nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8496 }
8497 else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
8498 {
8499 name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8500 rdb->MountPointReparseBuffer.SubstituteNameOffset);
8501 nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8502 }
8503 else
8504 {
8505 PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8506 }
8507 if (name) {
8508 if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8509 /* Our buffer is mutable, so this is okay */
8510 name[1] = L'\\';
8511 }
8512 result = PyUnicode_FromWideChar(name, nameLen);
8513 if (result && path->narrow) {
8514 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8515 }
8516 }
8517 return result;
8518 #endif
8519 }
8520 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8521
8522 #if defined(MS_WINDOWS)
8523
8524 /* Remove the last portion of the path - return 0 on success */
8525 static int
_dirnameW(WCHAR * path)8526 _dirnameW(WCHAR *path)
8527 {
8528 WCHAR *ptr;
8529 size_t length = wcsnlen_s(path, MAX_PATH);
8530 if (length == MAX_PATH) {
8531 return -1;
8532 }
8533
8534 /* walk the path from the end until a backslash is encountered */
8535 for(ptr = path + length; ptr != path; ptr--) {
8536 if (*ptr == L'\\' || *ptr == L'/') {
8537 break;
8538 }
8539 }
8540 *ptr = 0;
8541 return 0;
8542 }
8543
8544 #endif
8545
8546 #ifdef HAVE_SYMLINK
8547
8548 #if defined(MS_WINDOWS)
8549
8550 /* Is this path absolute? */
8551 static int
_is_absW(const WCHAR * path)8552 _is_absW(const WCHAR *path)
8553 {
8554 return path[0] == L'\\' || path[0] == L'/' ||
8555 (path[0] && path[1] == L':');
8556 }
8557
8558 /* join root and rest with a backslash - return 0 on success */
8559 static int
_joinW(WCHAR * dest_path,const WCHAR * root,const WCHAR * rest)8560 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8561 {
8562 if (_is_absW(rest)) {
8563 return wcscpy_s(dest_path, MAX_PATH, rest);
8564 }
8565
8566 if (wcscpy_s(dest_path, MAX_PATH, root)) {
8567 return -1;
8568 }
8569
8570 if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8571 return -1;
8572 }
8573
8574 return wcscat_s(dest_path, MAX_PATH, rest);
8575 }
8576
8577 /* Return True if the path at src relative to dest is a directory */
8578 static int
_check_dirW(LPCWSTR src,LPCWSTR dest)8579 _check_dirW(LPCWSTR src, LPCWSTR dest)
8580 {
8581 WIN32_FILE_ATTRIBUTE_DATA src_info;
8582 WCHAR dest_parent[MAX_PATH];
8583 WCHAR src_resolved[MAX_PATH] = L"";
8584
8585 /* dest_parent = os.path.dirname(dest) */
8586 if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8587 _dirnameW(dest_parent)) {
8588 return 0;
8589 }
8590 /* src_resolved = os.path.join(dest_parent, src) */
8591 if (_joinW(src_resolved, dest_parent, src)) {
8592 return 0;
8593 }
8594 return (
8595 GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8596 && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8597 );
8598 }
8599 #endif
8600
8601
8602 /*[clinic input]
8603 os.symlink
8604 src: path_t
8605 dst: path_t
8606 target_is_directory: bool = False
8607 *
8608 dir_fd: dir_fd(requires='symlinkat')=None
8609
8610 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8611
8612 Create a symbolic link pointing to src named dst.
8613
8614 target_is_directory is required on Windows if the target is to be
8615 interpreted as a directory. (On Windows, symlink requires
8616 Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8617 target_is_directory is ignored on non-Windows platforms.
8618
8619 If dir_fd is not None, it should be a file descriptor open to a directory,
8620 and path should be relative; path will then be relative to that directory.
8621 dir_fd may not be implemented on your platform.
8622 If it is unavailable, using it will raise a NotImplementedError.
8623
8624 [clinic start generated code]*/
8625
8626 static PyObject *
os_symlink_impl(PyObject * module,path_t * src,path_t * dst,int target_is_directory,int dir_fd)8627 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8628 int target_is_directory, int dir_fd)
8629 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8630 {
8631 #ifdef MS_WINDOWS
8632 DWORD result;
8633 DWORD flags = 0;
8634
8635 /* Assumed true, set to false if detected to not be available. */
8636 static int windows_has_symlink_unprivileged_flag = TRUE;
8637 #else
8638 int result;
8639 #ifdef HAVE_SYMLINKAT
8640 int symlinkat_unavailable = 0;
8641 #endif
8642 #endif
8643
8644 if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8645 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8646 return NULL;
8647 }
8648
8649 #ifdef MS_WINDOWS
8650
8651 if (windows_has_symlink_unprivileged_flag) {
8652 /* Allow non-admin symlinks if system allows it. */
8653 flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8654 }
8655
8656 Py_BEGIN_ALLOW_THREADS
8657 _Py_BEGIN_SUPPRESS_IPH
8658 /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8659 if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8660 flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8661 }
8662
8663 result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8664 _Py_END_SUPPRESS_IPH
8665 Py_END_ALLOW_THREADS
8666
8667 if (windows_has_symlink_unprivileged_flag && !result &&
8668 ERROR_INVALID_PARAMETER == GetLastError()) {
8669
8670 Py_BEGIN_ALLOW_THREADS
8671 _Py_BEGIN_SUPPRESS_IPH
8672 /* This error might be caused by
8673 SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8674 Try again, and update windows_has_symlink_unprivileged_flag if we
8675 are successful this time.
8676
8677 NOTE: There is a risk of a race condition here if there are other
8678 conditions than the flag causing ERROR_INVALID_PARAMETER, and
8679 another process (or thread) changes that condition in between our
8680 calls to CreateSymbolicLink.
8681 */
8682 flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8683 result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8684 _Py_END_SUPPRESS_IPH
8685 Py_END_ALLOW_THREADS
8686
8687 if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8688 windows_has_symlink_unprivileged_flag = FALSE;
8689 }
8690 }
8691
8692 if (!result)
8693 return path_error2(src, dst);
8694
8695 #else
8696
8697 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8698 PyErr_SetString(PyExc_ValueError,
8699 "symlink: src and dst must be the same type");
8700 return NULL;
8701 }
8702
8703 Py_BEGIN_ALLOW_THREADS
8704 #ifdef HAVE_SYMLINKAT
8705 if (dir_fd != DEFAULT_DIR_FD) {
8706 if (HAVE_SYMLINKAT_RUNTIME) {
8707 result = symlinkat(src->narrow, dir_fd, dst->narrow);
8708 } else {
8709 symlinkat_unavailable = 1;
8710 }
8711 } else
8712 #endif
8713 result = symlink(src->narrow, dst->narrow);
8714 Py_END_ALLOW_THREADS
8715
8716 #ifdef HAVE_SYMLINKAT
8717 if (symlinkat_unavailable) {
8718 argument_unavailable_error(NULL, "dir_fd");
8719 return NULL;
8720 }
8721 #endif
8722
8723 if (result)
8724 return path_error2(src, dst);
8725 #endif
8726
8727 Py_RETURN_NONE;
8728 }
8729 #endif /* HAVE_SYMLINK */
8730
8731
8732
8733
8734 static PyStructSequence_Field times_result_fields[] = {
8735 {"user", "user time"},
8736 {"system", "system time"},
8737 {"children_user", "user time of children"},
8738 {"children_system", "system time of children"},
8739 {"elapsed", "elapsed time since an arbitrary point in the past"},
8740 {NULL}
8741 };
8742
8743 PyDoc_STRVAR(times_result__doc__,
8744 "times_result: Result from os.times().\n\n\
8745 This object may be accessed either as a tuple of\n\
8746 (user, system, children_user, children_system, elapsed),\n\
8747 or via the attributes user, system, children_user, children_system,\n\
8748 and elapsed.\n\
8749 \n\
8750 See os.times for more information.");
8751
8752 static PyStructSequence_Desc times_result_desc = {
8753 "times_result", /* name */
8754 times_result__doc__, /* doc */
8755 times_result_fields,
8756 5
8757 };
8758
8759 #ifdef MS_WINDOWS
8760 #define HAVE_TIMES /* mandatory, for the method table */
8761 #endif
8762
8763 #ifdef HAVE_TIMES
8764
8765 static PyObject *
build_times_result(PyObject * module,double user,double system,double children_user,double children_system,double elapsed)8766 build_times_result(PyObject *module, double user, double system,
8767 double children_user, double children_system,
8768 double elapsed)
8769 {
8770 PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
8771 PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
8772 if (value == NULL)
8773 return NULL;
8774
8775 #define SET(i, field) \
8776 { \
8777 PyObject *o = PyFloat_FromDouble(field); \
8778 if (!o) { \
8779 Py_DECREF(value); \
8780 return NULL; \
8781 } \
8782 PyStructSequence_SET_ITEM(value, i, o); \
8783 } \
8784
8785 SET(0, user);
8786 SET(1, system);
8787 SET(2, children_user);
8788 SET(3, children_system);
8789 SET(4, elapsed);
8790
8791 #undef SET
8792
8793 return value;
8794 }
8795
8796
8797 #ifndef MS_WINDOWS
8798 #define NEED_TICKS_PER_SECOND
8799 static long ticks_per_second = -1;
8800 #endif /* MS_WINDOWS */
8801
8802 /*[clinic input]
8803 os.times
8804
8805 Return a collection containing process timing information.
8806
8807 The object returned behaves like a named tuple with these fields:
8808 (utime, stime, cutime, cstime, elapsed_time)
8809 All fields are floating point numbers.
8810 [clinic start generated code]*/
8811
8812 static PyObject *
os_times_impl(PyObject * module)8813 os_times_impl(PyObject *module)
8814 /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
8815 #ifdef MS_WINDOWS
8816 {
8817 FILETIME create, exit, kernel, user;
8818 HANDLE hProc;
8819 hProc = GetCurrentProcess();
8820 GetProcessTimes(hProc, &create, &exit, &kernel, &user);
8821 /* The fields of a FILETIME structure are the hi and lo part
8822 of a 64-bit value expressed in 100 nanosecond units.
8823 1e7 is one second in such units; 1e-7 the inverse.
8824 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
8825 */
8826 return build_times_result(module,
8827 (double)(user.dwHighDateTime*429.4967296 +
8828 user.dwLowDateTime*1e-7),
8829 (double)(kernel.dwHighDateTime*429.4967296 +
8830 kernel.dwLowDateTime*1e-7),
8831 (double)0,
8832 (double)0,
8833 (double)0);
8834 }
8835 #else /* MS_WINDOWS */
8836 {
8837
8838
8839 struct tms t;
8840 clock_t c;
8841 errno = 0;
8842 c = times(&t);
8843 if (c == (clock_t) -1)
8844 return posix_error();
8845 return build_times_result(module,
8846 (double)t.tms_utime / ticks_per_second,
8847 (double)t.tms_stime / ticks_per_second,
8848 (double)t.tms_cutime / ticks_per_second,
8849 (double)t.tms_cstime / ticks_per_second,
8850 (double)c / ticks_per_second);
8851 }
8852 #endif /* MS_WINDOWS */
8853 #endif /* HAVE_TIMES */
8854
8855
8856 #ifdef HAVE_GETSID
8857 /*[clinic input]
8858 os.getsid
8859
8860 pid: pid_t
8861 /
8862
8863 Call the system call getsid(pid) and return the result.
8864 [clinic start generated code]*/
8865
8866 static PyObject *
os_getsid_impl(PyObject * module,pid_t pid)8867 os_getsid_impl(PyObject *module, pid_t pid)
8868 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
8869 {
8870 int sid;
8871 sid = getsid(pid);
8872 if (sid < 0)
8873 return posix_error();
8874 return PyLong_FromLong((long)sid);
8875 }
8876 #endif /* HAVE_GETSID */
8877
8878
8879 #ifdef HAVE_SETSID
8880 /*[clinic input]
8881 os.setsid
8882
8883 Call the system call setsid().
8884 [clinic start generated code]*/
8885
8886 static PyObject *
os_setsid_impl(PyObject * module)8887 os_setsid_impl(PyObject *module)
8888 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
8889 {
8890 if (setsid() < 0)
8891 return posix_error();
8892 Py_RETURN_NONE;
8893 }
8894 #endif /* HAVE_SETSID */
8895
8896
8897 #ifdef HAVE_SETPGID
8898 /*[clinic input]
8899 os.setpgid
8900
8901 pid: pid_t
8902 pgrp: pid_t
8903 /
8904
8905 Call the system call setpgid(pid, pgrp).
8906 [clinic start generated code]*/
8907
8908 static PyObject *
os_setpgid_impl(PyObject * module,pid_t pid,pid_t pgrp)8909 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
8910 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
8911 {
8912 if (setpgid(pid, pgrp) < 0)
8913 return posix_error();
8914 Py_RETURN_NONE;
8915 }
8916 #endif /* HAVE_SETPGID */
8917
8918
8919 #ifdef HAVE_TCGETPGRP
8920 /*[clinic input]
8921 os.tcgetpgrp
8922
8923 fd: int
8924 /
8925
8926 Return the process group associated with the terminal specified by fd.
8927 [clinic start generated code]*/
8928
8929 static PyObject *
os_tcgetpgrp_impl(PyObject * module,int fd)8930 os_tcgetpgrp_impl(PyObject *module, int fd)
8931 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
8932 {
8933 pid_t pgid = tcgetpgrp(fd);
8934 if (pgid < 0)
8935 return posix_error();
8936 return PyLong_FromPid(pgid);
8937 }
8938 #endif /* HAVE_TCGETPGRP */
8939
8940
8941 #ifdef HAVE_TCSETPGRP
8942 /*[clinic input]
8943 os.tcsetpgrp
8944
8945 fd: int
8946 pgid: pid_t
8947 /
8948
8949 Set the process group associated with the terminal specified by fd.
8950 [clinic start generated code]*/
8951
8952 static PyObject *
os_tcsetpgrp_impl(PyObject * module,int fd,pid_t pgid)8953 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
8954 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
8955 {
8956 if (tcsetpgrp(fd, pgid) < 0)
8957 return posix_error();
8958 Py_RETURN_NONE;
8959 }
8960 #endif /* HAVE_TCSETPGRP */
8961
8962 /* Functions acting on file descriptors */
8963
8964 #ifdef O_CLOEXEC
8965 extern int _Py_open_cloexec_works;
8966 #endif
8967
8968
8969 /*[clinic input]
8970 os.open -> int
8971 path: path_t
8972 flags: int
8973 mode: int = 0o777
8974 *
8975 dir_fd: dir_fd(requires='openat') = None
8976
8977 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
8978
8979 Open a file for low level IO. Returns a file descriptor (integer).
8980
8981 If dir_fd is not None, it should be a file descriptor open to a directory,
8982 and path should be relative; path will then be relative to that directory.
8983 dir_fd may not be implemented on your platform.
8984 If it is unavailable, using it will raise a NotImplementedError.
8985 [clinic start generated code]*/
8986
8987 static int
os_open_impl(PyObject * module,path_t * path,int flags,int mode,int dir_fd)8988 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
8989 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
8990 {
8991 int fd;
8992 int async_err = 0;
8993 #ifdef HAVE_OPENAT
8994 int openat_unavailable = 0;
8995 #endif
8996
8997 #ifdef O_CLOEXEC
8998 int *atomic_flag_works = &_Py_open_cloexec_works;
8999 #elif !defined(MS_WINDOWS)
9000 int *atomic_flag_works = NULL;
9001 #endif
9002
9003 #ifdef MS_WINDOWS
9004 flags |= O_NOINHERIT;
9005 #elif defined(O_CLOEXEC)
9006 flags |= O_CLOEXEC;
9007 #endif
9008
9009 if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
9010 return -1;
9011 }
9012
9013 _Py_BEGIN_SUPPRESS_IPH
9014 do {
9015 Py_BEGIN_ALLOW_THREADS
9016 #ifdef MS_WINDOWS
9017 fd = _wopen(path->wide, flags, mode);
9018 #else
9019 #ifdef HAVE_OPENAT
9020 if (dir_fd != DEFAULT_DIR_FD) {
9021 if (HAVE_OPENAT_RUNTIME) {
9022 fd = openat(dir_fd, path->narrow, flags, mode);
9023
9024 } else {
9025 openat_unavailable = 1;
9026 fd = -1;
9027 }
9028 } else
9029 #endif /* HAVE_OPENAT */
9030 fd = open(path->narrow, flags, mode);
9031 #endif /* !MS_WINDOWS */
9032 Py_END_ALLOW_THREADS
9033 } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9034 _Py_END_SUPPRESS_IPH
9035
9036 #ifdef HAVE_OPENAT
9037 if (openat_unavailable) {
9038 argument_unavailable_error(NULL, "dir_fd");
9039 return -1;
9040 }
9041 #endif
9042
9043 if (fd < 0) {
9044 if (!async_err)
9045 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
9046 return -1;
9047 }
9048
9049 #ifndef MS_WINDOWS
9050 if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
9051 close(fd);
9052 return -1;
9053 }
9054 #endif
9055
9056 return fd;
9057 }
9058
9059
9060 /*[clinic input]
9061 os.close
9062
9063 fd: int
9064
9065 Close a file descriptor.
9066 [clinic start generated code]*/
9067
9068 static PyObject *
os_close_impl(PyObject * module,int fd)9069 os_close_impl(PyObject *module, int fd)
9070 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
9071 {
9072 int res;
9073 /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
9074 * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
9075 * for more details.
9076 */
9077 Py_BEGIN_ALLOW_THREADS
9078 _Py_BEGIN_SUPPRESS_IPH
9079 res = close(fd);
9080 _Py_END_SUPPRESS_IPH
9081 Py_END_ALLOW_THREADS
9082 if (res < 0)
9083 return posix_error();
9084 Py_RETURN_NONE;
9085 }
9086
9087
9088 #ifdef HAVE_FDWALK
9089 static int
_fdwalk_close_func(void * lohi,int fd)9090 _fdwalk_close_func(void *lohi, int fd)
9091 {
9092 int lo = ((int *)lohi)[0];
9093 int hi = ((int *)lohi)[1];
9094
9095 if (fd >= hi) {
9096 return 1;
9097 }
9098 else if (fd >= lo) {
9099 /* Ignore errors */
9100 (void)close(fd);
9101 }
9102 return 0;
9103 }
9104 #endif /* HAVE_FDWALK */
9105
9106 /*[clinic input]
9107 os.closerange
9108
9109 fd_low: int
9110 fd_high: int
9111 /
9112
9113 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
9114 [clinic start generated code]*/
9115
9116 static PyObject *
os_closerange_impl(PyObject * module,int fd_low,int fd_high)9117 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
9118 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
9119 {
9120 #ifdef HAVE_FDWALK
9121 int lohi[2];
9122 #endif
9123 Py_BEGIN_ALLOW_THREADS
9124 _Py_BEGIN_SUPPRESS_IPH
9125 #ifdef HAVE_FDWALK
9126 lohi[0] = Py_MAX(fd_low, 0);
9127 lohi[1] = fd_high;
9128 fdwalk(_fdwalk_close_func, lohi);
9129 #else
9130 fd_low = Py_MAX(fd_low, 0);
9131 #ifdef __FreeBSD__
9132 if (fd_high >= sysconf(_SC_OPEN_MAX)) {
9133 /* Any errors encountered while closing file descriptors are ignored */
9134 closefrom(fd_low);
9135 }
9136 else
9137 #endif
9138 {
9139 for (int i = fd_low; i < fd_high; i++) {
9140 /* Ignore errors */
9141 (void)close(i);
9142 }
9143 }
9144 #endif
9145 _Py_END_SUPPRESS_IPH
9146 Py_END_ALLOW_THREADS
9147 Py_RETURN_NONE;
9148 }
9149
9150
9151 /*[clinic input]
9152 os.dup -> int
9153
9154 fd: int
9155 /
9156
9157 Return a duplicate of a file descriptor.
9158 [clinic start generated code]*/
9159
9160 static int
os_dup_impl(PyObject * module,int fd)9161 os_dup_impl(PyObject *module, int fd)
9162 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
9163 {
9164 return _Py_dup(fd);
9165 }
9166
9167
9168 /*[clinic input]
9169 os.dup2 -> int
9170 fd: int
9171 fd2: int
9172 inheritable: bool=True
9173
9174 Duplicate file descriptor.
9175 [clinic start generated code]*/
9176
9177 static int
os_dup2_impl(PyObject * module,int fd,int fd2,int inheritable)9178 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
9179 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
9180 {
9181 int res = 0;
9182 #if defined(HAVE_DUP3) && \
9183 !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
9184 /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
9185 static int dup3_works = -1;
9186 #endif
9187
9188 if (fd < 0 || fd2 < 0) {
9189 posix_error();
9190 return -1;
9191 }
9192
9193 /* dup2() can fail with EINTR if the target FD is already open, because it
9194 * then has to be closed. See os_close_impl() for why we don't handle EINTR
9195 * upon close(), and therefore below.
9196 */
9197 #ifdef MS_WINDOWS
9198 Py_BEGIN_ALLOW_THREADS
9199 _Py_BEGIN_SUPPRESS_IPH
9200 res = dup2(fd, fd2);
9201 _Py_END_SUPPRESS_IPH
9202 Py_END_ALLOW_THREADS
9203 if (res < 0) {
9204 posix_error();
9205 return -1;
9206 }
9207 res = fd2; // msvcrt dup2 returns 0 on success.
9208
9209 /* Character files like console cannot be make non-inheritable */
9210 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9211 close(fd2);
9212 return -1;
9213 }
9214
9215 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
9216 Py_BEGIN_ALLOW_THREADS
9217 if (!inheritable)
9218 res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
9219 else
9220 res = dup2(fd, fd2);
9221 Py_END_ALLOW_THREADS
9222 if (res < 0) {
9223 posix_error();
9224 return -1;
9225 }
9226
9227 #else
9228
9229 #ifdef HAVE_DUP3
9230 if (!inheritable && dup3_works != 0) {
9231 Py_BEGIN_ALLOW_THREADS
9232 res = dup3(fd, fd2, O_CLOEXEC);
9233 Py_END_ALLOW_THREADS
9234 if (res < 0) {
9235 if (dup3_works == -1)
9236 dup3_works = (errno != ENOSYS);
9237 if (dup3_works) {
9238 posix_error();
9239 return -1;
9240 }
9241 }
9242 }
9243
9244 if (inheritable || dup3_works == 0)
9245 {
9246 #endif
9247 Py_BEGIN_ALLOW_THREADS
9248 res = dup2(fd, fd2);
9249 Py_END_ALLOW_THREADS
9250 if (res < 0) {
9251 posix_error();
9252 return -1;
9253 }
9254
9255 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9256 close(fd2);
9257 return -1;
9258 }
9259 #ifdef HAVE_DUP3
9260 }
9261 #endif
9262
9263 #endif
9264
9265 return res;
9266 }
9267
9268
9269 #ifdef HAVE_LOCKF
9270 /*[clinic input]
9271 os.lockf
9272
9273 fd: int
9274 An open file descriptor.
9275 command: int
9276 One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
9277 length: Py_off_t
9278 The number of bytes to lock, starting at the current position.
9279 /
9280
9281 Apply, test or remove a POSIX lock on an open file descriptor.
9282
9283 [clinic start generated code]*/
9284
9285 static PyObject *
os_lockf_impl(PyObject * module,int fd,int command,Py_off_t length)9286 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
9287 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
9288 {
9289 int res;
9290
9291 if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
9292 return NULL;
9293 }
9294
9295 Py_BEGIN_ALLOW_THREADS
9296 res = lockf(fd, command, length);
9297 Py_END_ALLOW_THREADS
9298
9299 if (res < 0)
9300 return posix_error();
9301
9302 Py_RETURN_NONE;
9303 }
9304 #endif /* HAVE_LOCKF */
9305
9306
9307 /*[clinic input]
9308 os.lseek -> Py_off_t
9309
9310 fd: int
9311 position: Py_off_t
9312 how: int
9313 /
9314
9315 Set the position of a file descriptor. Return the new position.
9316
9317 Return the new cursor position in number of bytes
9318 relative to the beginning of the file.
9319 [clinic start generated code]*/
9320
9321 static Py_off_t
os_lseek_impl(PyObject * module,int fd,Py_off_t position,int how)9322 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
9323 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
9324 {
9325 Py_off_t result;
9326
9327 #ifdef SEEK_SET
9328 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
9329 switch (how) {
9330 case 0: how = SEEK_SET; break;
9331 case 1: how = SEEK_CUR; break;
9332 case 2: how = SEEK_END; break;
9333 }
9334 #endif /* SEEK_END */
9335
9336 Py_BEGIN_ALLOW_THREADS
9337 _Py_BEGIN_SUPPRESS_IPH
9338 #ifdef MS_WINDOWS
9339 result = _lseeki64(fd, position, how);
9340 #else
9341 result = lseek(fd, position, how);
9342 #endif
9343 _Py_END_SUPPRESS_IPH
9344 Py_END_ALLOW_THREADS
9345 if (result < 0)
9346 posix_error();
9347
9348 return result;
9349 }
9350
9351
9352 /*[clinic input]
9353 os.read
9354 fd: int
9355 length: Py_ssize_t
9356 /
9357
9358 Read from a file descriptor. Returns a bytes object.
9359 [clinic start generated code]*/
9360
9361 static PyObject *
os_read_impl(PyObject * module,int fd,Py_ssize_t length)9362 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
9363 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
9364 {
9365 Py_ssize_t n;
9366 PyObject *buffer;
9367
9368 if (length < 0) {
9369 errno = EINVAL;
9370 return posix_error();
9371 }
9372
9373 length = Py_MIN(length, _PY_READ_MAX);
9374
9375 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9376 if (buffer == NULL)
9377 return NULL;
9378
9379 n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
9380 if (n == -1) {
9381 Py_DECREF(buffer);
9382 return NULL;
9383 }
9384
9385 if (n != length)
9386 _PyBytes_Resize(&buffer, n);
9387
9388 return buffer;
9389 }
9390
9391 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
9392 || defined(__APPLE__))) \
9393 || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
9394 || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9395 static int
iov_setup(struct iovec ** iov,Py_buffer ** buf,PyObject * seq,Py_ssize_t cnt,int type)9396 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
9397 {
9398 Py_ssize_t i, j;
9399
9400 *iov = PyMem_New(struct iovec, cnt);
9401 if (*iov == NULL) {
9402 PyErr_NoMemory();
9403 return -1;
9404 }
9405
9406 *buf = PyMem_New(Py_buffer, cnt);
9407 if (*buf == NULL) {
9408 PyMem_Del(*iov);
9409 PyErr_NoMemory();
9410 return -1;
9411 }
9412
9413 for (i = 0; i < cnt; i++) {
9414 PyObject *item = PySequence_GetItem(seq, i);
9415 if (item == NULL)
9416 goto fail;
9417 if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
9418 Py_DECREF(item);
9419 goto fail;
9420 }
9421 Py_DECREF(item);
9422 (*iov)[i].iov_base = (*buf)[i].buf;
9423 (*iov)[i].iov_len = (*buf)[i].len;
9424 }
9425 return 0;
9426
9427 fail:
9428 PyMem_Del(*iov);
9429 for (j = 0; j < i; j++) {
9430 PyBuffer_Release(&(*buf)[j]);
9431 }
9432 PyMem_Del(*buf);
9433 return -1;
9434 }
9435
9436 static void
iov_cleanup(struct iovec * iov,Py_buffer * buf,int cnt)9437 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9438 {
9439 int i;
9440 PyMem_Del(iov);
9441 for (i = 0; i < cnt; i++) {
9442 PyBuffer_Release(&buf[i]);
9443 }
9444 PyMem_Del(buf);
9445 }
9446 #endif
9447
9448
9449 #ifdef HAVE_READV
9450 /*[clinic input]
9451 os.readv -> Py_ssize_t
9452
9453 fd: int
9454 buffers: object
9455 /
9456
9457 Read from a file descriptor fd into an iterable of buffers.
9458
9459 The buffers should be mutable buffers accepting bytes.
9460 readv will transfer data into each buffer until it is full
9461 and then move on to the next buffer in the sequence to hold
9462 the rest of the data.
9463
9464 readv returns the total number of bytes read,
9465 which may be less than the total capacity of all the buffers.
9466 [clinic start generated code]*/
9467
9468 static Py_ssize_t
os_readv_impl(PyObject * module,int fd,PyObject * buffers)9469 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9470 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9471 {
9472 Py_ssize_t cnt, n;
9473 int async_err = 0;
9474 struct iovec *iov;
9475 Py_buffer *buf;
9476
9477 if (!PySequence_Check(buffers)) {
9478 PyErr_SetString(PyExc_TypeError,
9479 "readv() arg 2 must be a sequence");
9480 return -1;
9481 }
9482
9483 cnt = PySequence_Size(buffers);
9484 if (cnt < 0)
9485 return -1;
9486
9487 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9488 return -1;
9489
9490 do {
9491 Py_BEGIN_ALLOW_THREADS
9492 n = readv(fd, iov, cnt);
9493 Py_END_ALLOW_THREADS
9494 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9495
9496 iov_cleanup(iov, buf, cnt);
9497 if (n < 0) {
9498 if (!async_err)
9499 posix_error();
9500 return -1;
9501 }
9502
9503 return n;
9504 }
9505 #endif /* HAVE_READV */
9506
9507
9508 #ifdef HAVE_PREAD
9509 /*[clinic input]
9510 os.pread
9511
9512 fd: int
9513 length: Py_ssize_t
9514 offset: Py_off_t
9515 /
9516
9517 Read a number of bytes from a file descriptor starting at a particular offset.
9518
9519 Read length bytes from file descriptor fd, starting at offset bytes from
9520 the beginning of the file. The file offset remains unchanged.
9521 [clinic start generated code]*/
9522
9523 static PyObject *
os_pread_impl(PyObject * module,int fd,Py_ssize_t length,Py_off_t offset)9524 os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
9525 /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
9526 {
9527 Py_ssize_t n;
9528 int async_err = 0;
9529 PyObject *buffer;
9530
9531 if (length < 0) {
9532 errno = EINVAL;
9533 return posix_error();
9534 }
9535 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9536 if (buffer == NULL)
9537 return NULL;
9538
9539 do {
9540 Py_BEGIN_ALLOW_THREADS
9541 _Py_BEGIN_SUPPRESS_IPH
9542 n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9543 _Py_END_SUPPRESS_IPH
9544 Py_END_ALLOW_THREADS
9545 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9546
9547 if (n < 0) {
9548 Py_DECREF(buffer);
9549 return (!async_err) ? posix_error() : NULL;
9550 }
9551 if (n != length)
9552 _PyBytes_Resize(&buffer, n);
9553 return buffer;
9554 }
9555 #endif /* HAVE_PREAD */
9556
9557 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9558 /*[clinic input]
9559 os.preadv -> Py_ssize_t
9560
9561 fd: int
9562 buffers: object
9563 offset: Py_off_t
9564 flags: int = 0
9565 /
9566
9567 Reads from a file descriptor into a number of mutable bytes-like objects.
9568
9569 Combines the functionality of readv() and pread(). As readv(), it will
9570 transfer data into each buffer until it is full and then move on to the next
9571 buffer in the sequence to hold the rest of the data. Its fourth argument,
9572 specifies the file offset at which the input operation is to be performed. It
9573 will return the total number of bytes read (which can be less than the total
9574 capacity of all the objects).
9575
9576 The flags argument contains a bitwise OR of zero or more of the following flags:
9577
9578 - RWF_HIPRI
9579 - RWF_NOWAIT
9580
9581 Using non-zero flags requires Linux 4.6 or newer.
9582 [clinic start generated code]*/
9583
9584 static Py_ssize_t
os_preadv_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9585 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9586 int flags)
9587 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9588 {
9589 Py_ssize_t cnt, n;
9590 int async_err = 0;
9591 struct iovec *iov;
9592 Py_buffer *buf;
9593
9594 if (!PySequence_Check(buffers)) {
9595 PyErr_SetString(PyExc_TypeError,
9596 "preadv2() arg 2 must be a sequence");
9597 return -1;
9598 }
9599
9600 cnt = PySequence_Size(buffers);
9601 if (cnt < 0) {
9602 return -1;
9603 }
9604
9605 #ifndef HAVE_PREADV2
9606 if(flags != 0) {
9607 argument_unavailable_error("preadv2", "flags");
9608 return -1;
9609 }
9610 #endif
9611
9612 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9613 return -1;
9614 }
9615 #ifdef HAVE_PREADV2
9616 do {
9617 Py_BEGIN_ALLOW_THREADS
9618 _Py_BEGIN_SUPPRESS_IPH
9619 n = preadv2(fd, iov, cnt, offset, flags);
9620 _Py_END_SUPPRESS_IPH
9621 Py_END_ALLOW_THREADS
9622 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9623 #else
9624 do {
9625 #ifdef __APPLE__
9626 /* This entire function will be removed from the module dict when the API
9627 * is not available.
9628 */
9629 #pragma clang diagnostic push
9630 #pragma clang diagnostic ignored "-Wunguarded-availability"
9631 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
9632 #endif
9633 Py_BEGIN_ALLOW_THREADS
9634 _Py_BEGIN_SUPPRESS_IPH
9635 n = preadv(fd, iov, cnt, offset);
9636 _Py_END_SUPPRESS_IPH
9637 Py_END_ALLOW_THREADS
9638 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9639
9640 #ifdef __APPLE__
9641 #pragma clang diagnostic pop
9642 #endif
9643
9644 #endif
9645
9646 iov_cleanup(iov, buf, cnt);
9647 if (n < 0) {
9648 if (!async_err) {
9649 posix_error();
9650 }
9651 return -1;
9652 }
9653
9654 return n;
9655 }
9656 #endif /* HAVE_PREADV */
9657
9658
9659 /*[clinic input]
9660 os.write -> Py_ssize_t
9661
9662 fd: int
9663 data: Py_buffer
9664 /
9665
9666 Write a bytes object to a file descriptor.
9667 [clinic start generated code]*/
9668
9669 static Py_ssize_t
os_write_impl(PyObject * module,int fd,Py_buffer * data)9670 os_write_impl(PyObject *module, int fd, Py_buffer *data)
9671 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9672 {
9673 return _Py_write(fd, data->buf, data->len);
9674 }
9675
9676 #ifdef HAVE_SENDFILE
9677 #ifdef __APPLE__
9678 /*[clinic input]
9679 os.sendfile
9680
9681 out_fd: int
9682 in_fd: int
9683 offset: Py_off_t
9684 count as sbytes: Py_off_t
9685 headers: object(c_default="NULL") = ()
9686 trailers: object(c_default="NULL") = ()
9687 flags: int = 0
9688
9689 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9690 [clinic start generated code]*/
9691
9692 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)9693 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9694 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
9695 int flags)
9696 /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
9697 #elif defined(__FreeBSD__) || defined(__DragonFly__)
9698 /*[clinic input]
9699 os.sendfile
9700
9701 out_fd: int
9702 in_fd: int
9703 offset: Py_off_t
9704 count: Py_ssize_t
9705 headers: object(c_default="NULL") = ()
9706 trailers: object(c_default="NULL") = ()
9707 flags: int = 0
9708
9709 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9710 [clinic start generated code]*/
9711
9712 static PyObject *
9713 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9714 Py_ssize_t count, PyObject *headers, PyObject *trailers,
9715 int flags)
9716 /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
9717 #else
9718 /*[clinic input]
9719 os.sendfile
9720
9721 out_fd: int
9722 in_fd: int
9723 offset as offobj: object
9724 count: Py_ssize_t
9725
9726 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9727 [clinic start generated code]*/
9728
9729 static PyObject *
9730 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
9731 Py_ssize_t count)
9732 /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
9733 #endif
9734 {
9735 Py_ssize_t ret;
9736 int async_err = 0;
9737
9738 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9739 #ifndef __APPLE__
9740 off_t sbytes;
9741 #endif
9742 Py_buffer *hbuf, *tbuf;
9743 struct sf_hdtr sf;
9744
9745 sf.headers = NULL;
9746 sf.trailers = NULL;
9747
9748 if (headers != NULL) {
9749 if (!PySequence_Check(headers)) {
9750 PyErr_SetString(PyExc_TypeError,
9751 "sendfile() headers must be a sequence");
9752 return NULL;
9753 } else {
9754 Py_ssize_t i = PySequence_Size(headers);
9755 if (i < 0)
9756 return NULL;
9757 if (i > INT_MAX) {
9758 PyErr_SetString(PyExc_OverflowError,
9759 "sendfile() header is too large");
9760 return NULL;
9761 }
9762 if (i > 0) {
9763 sf.hdr_cnt = (int)i;
9764 if (iov_setup(&(sf.headers), &hbuf,
9765 headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9766 return NULL;
9767 #ifdef __APPLE__
9768 for (i = 0; i < sf.hdr_cnt; i++) {
9769 Py_ssize_t blen = sf.headers[i].iov_len;
9770 # define OFF_T_MAX 0x7fffffffffffffff
9771 if (sbytes >= OFF_T_MAX - blen) {
9772 PyErr_SetString(PyExc_OverflowError,
9773 "sendfile() header is too large");
9774 return NULL;
9775 }
9776 sbytes += blen;
9777 }
9778 #endif
9779 }
9780 }
9781 }
9782 if (trailers != NULL) {
9783 if (!PySequence_Check(trailers)) {
9784 PyErr_SetString(PyExc_TypeError,
9785 "sendfile() trailers must be a sequence");
9786 return NULL;
9787 } else {
9788 Py_ssize_t i = PySequence_Size(trailers);
9789 if (i < 0)
9790 return NULL;
9791 if (i > INT_MAX) {
9792 PyErr_SetString(PyExc_OverflowError,
9793 "sendfile() trailer is too large");
9794 return NULL;
9795 }
9796 if (i > 0) {
9797 sf.trl_cnt = (int)i;
9798 if (iov_setup(&(sf.trailers), &tbuf,
9799 trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
9800 return NULL;
9801 }
9802 }
9803 }
9804
9805 _Py_BEGIN_SUPPRESS_IPH
9806 do {
9807 Py_BEGIN_ALLOW_THREADS
9808 #ifdef __APPLE__
9809 ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
9810 #else
9811 ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
9812 #endif
9813 Py_END_ALLOW_THREADS
9814 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9815 _Py_END_SUPPRESS_IPH
9816
9817 if (sf.headers != NULL)
9818 iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
9819 if (sf.trailers != NULL)
9820 iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
9821
9822 if (ret < 0) {
9823 if ((errno == EAGAIN) || (errno == EBUSY)) {
9824 if (sbytes != 0) {
9825 // some data has been sent
9826 goto done;
9827 }
9828 else {
9829 // no data has been sent; upper application is supposed
9830 // to retry on EAGAIN or EBUSY
9831 return posix_error();
9832 }
9833 }
9834 return (!async_err) ? posix_error() : NULL;
9835 }
9836 goto done;
9837
9838 done:
9839 #if !defined(HAVE_LARGEFILE_SUPPORT)
9840 return Py_BuildValue("l", sbytes);
9841 #else
9842 return Py_BuildValue("L", sbytes);
9843 #endif
9844
9845 #else
9846 #ifdef __linux__
9847 if (offobj == Py_None) {
9848 do {
9849 Py_BEGIN_ALLOW_THREADS
9850 ret = sendfile(out_fd, in_fd, NULL, count);
9851 Py_END_ALLOW_THREADS
9852 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9853 if (ret < 0)
9854 return (!async_err) ? posix_error() : NULL;
9855 return Py_BuildValue("n", ret);
9856 }
9857 #endif
9858 off_t offset;
9859 if (!Py_off_t_converter(offobj, &offset))
9860 return NULL;
9861
9862 #if defined(__sun) && defined(__SVR4)
9863 // On Solaris, sendfile raises EINVAL rather than returning 0
9864 // when the offset is equal or bigger than the in_fd size.
9865 struct stat st;
9866
9867 do {
9868 Py_BEGIN_ALLOW_THREADS
9869 ret = fstat(in_fd, &st);
9870 Py_END_ALLOW_THREADS
9871 } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9872 if (ret < 0)
9873 return (!async_err) ? posix_error() : NULL;
9874
9875 if (offset >= st.st_size) {
9876 return Py_BuildValue("i", 0);
9877 }
9878
9879 // On illumos specifically sendfile() may perform a partial write but
9880 // return -1/an error (in one confirmed case the destination socket
9881 // had a 5 second timeout set and errno was EAGAIN) and it's on the client
9882 // code to check if the offset parameter was modified by sendfile().
9883 //
9884 // We need this variable to track said change.
9885 off_t original_offset = offset;
9886 #endif
9887
9888 do {
9889 Py_BEGIN_ALLOW_THREADS
9890 ret = sendfile(out_fd, in_fd, &offset, count);
9891 #if defined(__sun) && defined(__SVR4)
9892 // This handles illumos-specific sendfile() partial write behavior,
9893 // see a comment above for more details.
9894 if (ret < 0 && offset != original_offset) {
9895 ret = offset - original_offset;
9896 }
9897 #endif
9898 Py_END_ALLOW_THREADS
9899 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9900 if (ret < 0)
9901 return (!async_err) ? posix_error() : NULL;
9902 return Py_BuildValue("n", ret);
9903 #endif
9904 }
9905 #endif /* HAVE_SENDFILE */
9906
9907
9908 #if defined(__APPLE__)
9909 /*[clinic input]
9910 os._fcopyfile
9911
9912 in_fd: int
9913 out_fd: int
9914 flags: int
9915 /
9916
9917 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
9918 [clinic start generated code]*/
9919
9920 static PyObject *
os__fcopyfile_impl(PyObject * module,int in_fd,int out_fd,int flags)9921 os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
9922 /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
9923 {
9924 int ret;
9925
9926 Py_BEGIN_ALLOW_THREADS
9927 ret = fcopyfile(in_fd, out_fd, NULL, flags);
9928 Py_END_ALLOW_THREADS
9929 if (ret < 0)
9930 return posix_error();
9931 Py_RETURN_NONE;
9932 }
9933 #endif
9934
9935
9936 /*[clinic input]
9937 os.fstat
9938
9939 fd : int
9940
9941 Perform a stat system call on the given file descriptor.
9942
9943 Like stat(), but for an open file descriptor.
9944 Equivalent to os.stat(fd).
9945 [clinic start generated code]*/
9946
9947 static PyObject *
os_fstat_impl(PyObject * module,int fd)9948 os_fstat_impl(PyObject *module, int fd)
9949 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
9950 {
9951 STRUCT_STAT st;
9952 int res;
9953 int async_err = 0;
9954
9955 do {
9956 Py_BEGIN_ALLOW_THREADS
9957 res = FSTAT(fd, &st);
9958 Py_END_ALLOW_THREADS
9959 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9960 if (res != 0) {
9961 #ifdef MS_WINDOWS
9962 return PyErr_SetFromWindowsErr(0);
9963 #else
9964 return (!async_err) ? posix_error() : NULL;
9965 #endif
9966 }
9967
9968 return _pystat_fromstructstat(module, &st);
9969 }
9970
9971
9972 /*[clinic input]
9973 os.isatty -> bool
9974 fd: int
9975 /
9976
9977 Return True if the fd is connected to a terminal.
9978
9979 Return True if the file descriptor is an open file descriptor
9980 connected to the slave end of a terminal.
9981 [clinic start generated code]*/
9982
9983 static int
os_isatty_impl(PyObject * module,int fd)9984 os_isatty_impl(PyObject *module, int fd)
9985 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
9986 {
9987 int return_value;
9988 _Py_BEGIN_SUPPRESS_IPH
9989 return_value = isatty(fd);
9990 _Py_END_SUPPRESS_IPH
9991 return return_value;
9992 }
9993
9994
9995 #ifdef HAVE_PIPE
9996 /*[clinic input]
9997 os.pipe
9998
9999 Create a pipe.
10000
10001 Returns a tuple of two file descriptors:
10002 (read_fd, write_fd)
10003 [clinic start generated code]*/
10004
10005 static PyObject *
os_pipe_impl(PyObject * module)10006 os_pipe_impl(PyObject *module)
10007 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
10008 {
10009 int fds[2];
10010 #ifdef MS_WINDOWS
10011 HANDLE read, write;
10012 SECURITY_ATTRIBUTES attr;
10013 BOOL ok;
10014 #else
10015 int res;
10016 #endif
10017
10018 #ifdef MS_WINDOWS
10019 attr.nLength = sizeof(attr);
10020 attr.lpSecurityDescriptor = NULL;
10021 attr.bInheritHandle = FALSE;
10022
10023 Py_BEGIN_ALLOW_THREADS
10024 _Py_BEGIN_SUPPRESS_IPH
10025 ok = CreatePipe(&read, &write, &attr, 0);
10026 if (ok) {
10027 fds[0] = _open_osfhandle((intptr_t)read, _O_RDONLY);
10028 fds[1] = _open_osfhandle((intptr_t)write, _O_WRONLY);
10029 if (fds[0] == -1 || fds[1] == -1) {
10030 CloseHandle(read);
10031 CloseHandle(write);
10032 ok = 0;
10033 }
10034 }
10035 _Py_END_SUPPRESS_IPH
10036 Py_END_ALLOW_THREADS
10037
10038 if (!ok)
10039 return PyErr_SetFromWindowsErr(0);
10040 #else
10041
10042 #ifdef HAVE_PIPE2
10043 Py_BEGIN_ALLOW_THREADS
10044 res = pipe2(fds, O_CLOEXEC);
10045 Py_END_ALLOW_THREADS
10046
10047 if (res != 0 && errno == ENOSYS)
10048 {
10049 #endif
10050 Py_BEGIN_ALLOW_THREADS
10051 res = pipe(fds);
10052 Py_END_ALLOW_THREADS
10053
10054 if (res == 0) {
10055 if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
10056 close(fds[0]);
10057 close(fds[1]);
10058 return NULL;
10059 }
10060 if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
10061 close(fds[0]);
10062 close(fds[1]);
10063 return NULL;
10064 }
10065 }
10066 #ifdef HAVE_PIPE2
10067 }
10068 #endif
10069
10070 if (res != 0)
10071 return PyErr_SetFromErrno(PyExc_OSError);
10072 #endif /* !MS_WINDOWS */
10073 return Py_BuildValue("(ii)", fds[0], fds[1]);
10074 }
10075 #endif /* HAVE_PIPE */
10076
10077
10078 #ifdef HAVE_PIPE2
10079 /*[clinic input]
10080 os.pipe2
10081
10082 flags: int
10083 /
10084
10085 Create a pipe with flags set atomically.
10086
10087 Returns a tuple of two file descriptors:
10088 (read_fd, write_fd)
10089
10090 flags can be constructed by ORing together one or more of these values:
10091 O_NONBLOCK, O_CLOEXEC.
10092 [clinic start generated code]*/
10093
10094 static PyObject *
os_pipe2_impl(PyObject * module,int flags)10095 os_pipe2_impl(PyObject *module, int flags)
10096 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
10097 {
10098 int fds[2];
10099 int res;
10100
10101 res = pipe2(fds, flags);
10102 if (res != 0)
10103 return posix_error();
10104 return Py_BuildValue("(ii)", fds[0], fds[1]);
10105 }
10106 #endif /* HAVE_PIPE2 */
10107
10108
10109 #ifdef HAVE_WRITEV
10110 /*[clinic input]
10111 os.writev -> Py_ssize_t
10112 fd: int
10113 buffers: object
10114 /
10115
10116 Iterate over buffers, and write the contents of each to a file descriptor.
10117
10118 Returns the total number of bytes written.
10119 buffers must be a sequence of bytes-like objects.
10120 [clinic start generated code]*/
10121
10122 static Py_ssize_t
os_writev_impl(PyObject * module,int fd,PyObject * buffers)10123 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
10124 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
10125 {
10126 Py_ssize_t cnt;
10127 Py_ssize_t result;
10128 int async_err = 0;
10129 struct iovec *iov;
10130 Py_buffer *buf;
10131
10132 if (!PySequence_Check(buffers)) {
10133 PyErr_SetString(PyExc_TypeError,
10134 "writev() arg 2 must be a sequence");
10135 return -1;
10136 }
10137 cnt = PySequence_Size(buffers);
10138 if (cnt < 0)
10139 return -1;
10140
10141 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10142 return -1;
10143 }
10144
10145 do {
10146 Py_BEGIN_ALLOW_THREADS
10147 result = writev(fd, iov, cnt);
10148 Py_END_ALLOW_THREADS
10149 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10150
10151 iov_cleanup(iov, buf, cnt);
10152 if (result < 0 && !async_err)
10153 posix_error();
10154
10155 return result;
10156 }
10157 #endif /* HAVE_WRITEV */
10158
10159
10160 #ifdef HAVE_PWRITE
10161 /*[clinic input]
10162 os.pwrite -> Py_ssize_t
10163
10164 fd: int
10165 buffer: Py_buffer
10166 offset: Py_off_t
10167 /
10168
10169 Write bytes to a file descriptor starting at a particular offset.
10170
10171 Write buffer to fd, starting at offset bytes from the beginning of
10172 the file. Returns the number of bytes writte. Does not change the
10173 current file offset.
10174 [clinic start generated code]*/
10175
10176 static Py_ssize_t
os_pwrite_impl(PyObject * module,int fd,Py_buffer * buffer,Py_off_t offset)10177 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
10178 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
10179 {
10180 Py_ssize_t size;
10181 int async_err = 0;
10182
10183 do {
10184 Py_BEGIN_ALLOW_THREADS
10185 _Py_BEGIN_SUPPRESS_IPH
10186 size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
10187 _Py_END_SUPPRESS_IPH
10188 Py_END_ALLOW_THREADS
10189 } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10190
10191 if (size < 0 && !async_err)
10192 posix_error();
10193 return size;
10194 }
10195 #endif /* HAVE_PWRITE */
10196
10197 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
10198 /*[clinic input]
10199 os.pwritev -> Py_ssize_t
10200
10201 fd: int
10202 buffers: object
10203 offset: Py_off_t
10204 flags: int = 0
10205 /
10206
10207 Writes the contents of bytes-like objects to a file descriptor at a given offset.
10208
10209 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
10210 of bytes-like objects. Buffers are processed in array order. Entire contents of first
10211 buffer is written before proceeding to second, and so on. The operating system may
10212 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
10213 This function writes the contents of each object to the file descriptor and returns
10214 the total number of bytes written.
10215
10216 The flags argument contains a bitwise OR of zero or more of the following flags:
10217
10218 - RWF_DSYNC
10219 - RWF_SYNC
10220
10221 Using non-zero flags requires Linux 4.7 or newer.
10222 [clinic start generated code]*/
10223
10224 static Py_ssize_t
os_pwritev_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)10225 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
10226 int flags)
10227 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=803dc5ddbf0cfd3b]*/
10228 {
10229 Py_ssize_t cnt;
10230 Py_ssize_t result;
10231 int async_err = 0;
10232 struct iovec *iov;
10233 Py_buffer *buf;
10234
10235 if (!PySequence_Check(buffers)) {
10236 PyErr_SetString(PyExc_TypeError,
10237 "pwritev() arg 2 must be a sequence");
10238 return -1;
10239 }
10240
10241 cnt = PySequence_Size(buffers);
10242 if (cnt < 0) {
10243 return -1;
10244 }
10245
10246 #ifndef HAVE_PWRITEV2
10247 if(flags != 0) {
10248 argument_unavailable_error("pwritev2", "flags");
10249 return -1;
10250 }
10251 #endif
10252
10253 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10254 return -1;
10255 }
10256 #ifdef HAVE_PWRITEV2
10257 do {
10258 Py_BEGIN_ALLOW_THREADS
10259 _Py_BEGIN_SUPPRESS_IPH
10260 result = pwritev2(fd, iov, cnt, offset, flags);
10261 _Py_END_SUPPRESS_IPH
10262 Py_END_ALLOW_THREADS
10263 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10264 #else
10265
10266 #ifdef __APPLE__
10267 /* This entire function will be removed from the module dict when the API
10268 * is not available.
10269 */
10270 #pragma clang diagnostic push
10271 #pragma clang diagnostic ignored "-Wunguarded-availability"
10272 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
10273 #endif
10274 do {
10275 Py_BEGIN_ALLOW_THREADS
10276 _Py_BEGIN_SUPPRESS_IPH
10277 result = pwritev(fd, iov, cnt, offset);
10278 _Py_END_SUPPRESS_IPH
10279 Py_END_ALLOW_THREADS
10280 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10281
10282 #ifdef __APPLE__
10283 #pragma clang diagnostic pop
10284 #endif
10285
10286 #endif
10287
10288 iov_cleanup(iov, buf, cnt);
10289 if (result < 0) {
10290 if (!async_err) {
10291 posix_error();
10292 }
10293 return -1;
10294 }
10295
10296 return result;
10297 }
10298 #endif /* HAVE_PWRITEV */
10299
10300 #ifdef HAVE_COPY_FILE_RANGE
10301 /*[clinic input]
10302
10303 os.copy_file_range
10304 src: int
10305 Source file descriptor.
10306 dst: int
10307 Destination file descriptor.
10308 count: Py_ssize_t
10309 Number of bytes to copy.
10310 offset_src: object = None
10311 Starting offset in src.
10312 offset_dst: object = None
10313 Starting offset in dst.
10314
10315 Copy count bytes from one file descriptor to another.
10316
10317 If offset_src is None, then src is read from the current position;
10318 respectively for offset_dst.
10319 [clinic start generated code]*/
10320
10321 static PyObject *
os_copy_file_range_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst)10322 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10323 PyObject *offset_src, PyObject *offset_dst)
10324 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
10325 {
10326 off_t offset_src_val, offset_dst_val;
10327 off_t *p_offset_src = NULL;
10328 off_t *p_offset_dst = NULL;
10329 Py_ssize_t ret;
10330 int async_err = 0;
10331 /* The flags argument is provided to allow
10332 * for future extensions and currently must be to 0. */
10333 int flags = 0;
10334
10335
10336 if (count < 0) {
10337 PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10338 return NULL;
10339 }
10340
10341 if (offset_src != Py_None) {
10342 if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10343 return NULL;
10344 }
10345 p_offset_src = &offset_src_val;
10346 }
10347
10348 if (offset_dst != Py_None) {
10349 if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10350 return NULL;
10351 }
10352 p_offset_dst = &offset_dst_val;
10353 }
10354
10355 do {
10356 Py_BEGIN_ALLOW_THREADS
10357 ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
10358 Py_END_ALLOW_THREADS
10359 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10360
10361 if (ret < 0) {
10362 return (!async_err) ? posix_error() : NULL;
10363 }
10364
10365 return PyLong_FromSsize_t(ret);
10366 }
10367 #endif /* HAVE_COPY_FILE_RANGE*/
10368
10369 #ifdef HAVE_MKFIFO
10370 /*[clinic input]
10371 os.mkfifo
10372
10373 path: path_t
10374 mode: int=0o666
10375 *
10376 dir_fd: dir_fd(requires='mkfifoat')=None
10377
10378 Create a "fifo" (a POSIX named pipe).
10379
10380 If dir_fd is not None, it should be a file descriptor open to a directory,
10381 and path should be relative; path will then be relative to that directory.
10382 dir_fd may not be implemented on your platform.
10383 If it is unavailable, using it will raise a NotImplementedError.
10384 [clinic start generated code]*/
10385
10386 static PyObject *
os_mkfifo_impl(PyObject * module,path_t * path,int mode,int dir_fd)10387 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
10388 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
10389 {
10390 int result;
10391 int async_err = 0;
10392
10393 do {
10394 Py_BEGIN_ALLOW_THREADS
10395 #ifdef HAVE_MKFIFOAT
10396 if (dir_fd != DEFAULT_DIR_FD)
10397 result = mkfifoat(dir_fd, path->narrow, mode);
10398 else
10399 #endif
10400 result = mkfifo(path->narrow, mode);
10401 Py_END_ALLOW_THREADS
10402 } while (result != 0 && errno == EINTR &&
10403 !(async_err = PyErr_CheckSignals()));
10404 if (result != 0)
10405 return (!async_err) ? posix_error() : NULL;
10406
10407 Py_RETURN_NONE;
10408 }
10409 #endif /* HAVE_MKFIFO */
10410
10411
10412 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
10413 /*[clinic input]
10414 os.mknod
10415
10416 path: path_t
10417 mode: int=0o600
10418 device: dev_t=0
10419 *
10420 dir_fd: dir_fd(requires='mknodat')=None
10421
10422 Create a node in the file system.
10423
10424 Create a node in the file system (file, device special file or named pipe)
10425 at path. mode specifies both the permissions to use and the
10426 type of node to be created, being combined (bitwise OR) with one of
10427 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,
10428 device defines the newly created device special file (probably using
10429 os.makedev()). Otherwise device is ignored.
10430
10431 If dir_fd is not None, it should be a file descriptor open to a directory,
10432 and path should be relative; path will then be relative to that directory.
10433 dir_fd may not be implemented on your platform.
10434 If it is unavailable, using it will raise a NotImplementedError.
10435 [clinic start generated code]*/
10436
10437 static PyObject *
os_mknod_impl(PyObject * module,path_t * path,int mode,dev_t device,int dir_fd)10438 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
10439 int dir_fd)
10440 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
10441 {
10442 int result;
10443 int async_err = 0;
10444
10445 do {
10446 Py_BEGIN_ALLOW_THREADS
10447 #ifdef HAVE_MKNODAT
10448 if (dir_fd != DEFAULT_DIR_FD)
10449 result = mknodat(dir_fd, path->narrow, mode, device);
10450 else
10451 #endif
10452 result = mknod(path->narrow, mode, device);
10453 Py_END_ALLOW_THREADS
10454 } while (result != 0 && errno == EINTR &&
10455 !(async_err = PyErr_CheckSignals()));
10456 if (result != 0)
10457 return (!async_err) ? posix_error() : NULL;
10458
10459 Py_RETURN_NONE;
10460 }
10461 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
10462
10463
10464 #ifdef HAVE_DEVICE_MACROS
10465 /*[clinic input]
10466 os.major -> unsigned_int
10467
10468 device: dev_t
10469 /
10470
10471 Extracts a device major number from a raw device number.
10472 [clinic start generated code]*/
10473
10474 static unsigned int
os_major_impl(PyObject * module,dev_t device)10475 os_major_impl(PyObject *module, dev_t device)
10476 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
10477 {
10478 return major(device);
10479 }
10480
10481
10482 /*[clinic input]
10483 os.minor -> unsigned_int
10484
10485 device: dev_t
10486 /
10487
10488 Extracts a device minor number from a raw device number.
10489 [clinic start generated code]*/
10490
10491 static unsigned int
os_minor_impl(PyObject * module,dev_t device)10492 os_minor_impl(PyObject *module, dev_t device)
10493 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10494 {
10495 return minor(device);
10496 }
10497
10498
10499 /*[clinic input]
10500 os.makedev -> dev_t
10501
10502 major: int
10503 minor: int
10504 /
10505
10506 Composes a raw device number from the major and minor device numbers.
10507 [clinic start generated code]*/
10508
10509 static dev_t
os_makedev_impl(PyObject * module,int major,int minor)10510 os_makedev_impl(PyObject *module, int major, int minor)
10511 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10512 {
10513 return makedev(major, minor);
10514 }
10515 #endif /* HAVE_DEVICE_MACROS */
10516
10517
10518 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10519 /*[clinic input]
10520 os.ftruncate
10521
10522 fd: int
10523 length: Py_off_t
10524 /
10525
10526 Truncate a file, specified by file descriptor, to a specific length.
10527 [clinic start generated code]*/
10528
10529 static PyObject *
os_ftruncate_impl(PyObject * module,int fd,Py_off_t length)10530 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10531 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10532 {
10533 int result;
10534 int async_err = 0;
10535
10536 if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10537 return NULL;
10538 }
10539
10540 do {
10541 Py_BEGIN_ALLOW_THREADS
10542 _Py_BEGIN_SUPPRESS_IPH
10543 #ifdef MS_WINDOWS
10544 result = _chsize_s(fd, length);
10545 #else
10546 result = ftruncate(fd, length);
10547 #endif
10548 _Py_END_SUPPRESS_IPH
10549 Py_END_ALLOW_THREADS
10550 } while (result != 0 && errno == EINTR &&
10551 !(async_err = PyErr_CheckSignals()));
10552 if (result != 0)
10553 return (!async_err) ? posix_error() : NULL;
10554 Py_RETURN_NONE;
10555 }
10556 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10557
10558
10559 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10560 /*[clinic input]
10561 os.truncate
10562 path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10563 length: Py_off_t
10564
10565 Truncate a file, specified by path, to a specific length.
10566
10567 On some platforms, path may also be specified as an open file descriptor.
10568 If this functionality is unavailable, using it raises an exception.
10569 [clinic start generated code]*/
10570
10571 static PyObject *
os_truncate_impl(PyObject * module,path_t * path,Py_off_t length)10572 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10573 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10574 {
10575 int result;
10576 #ifdef MS_WINDOWS
10577 int fd;
10578 #endif
10579
10580 if (path->fd != -1)
10581 return os_ftruncate_impl(module, path->fd, length);
10582
10583 if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10584 return NULL;
10585 }
10586
10587 Py_BEGIN_ALLOW_THREADS
10588 _Py_BEGIN_SUPPRESS_IPH
10589 #ifdef MS_WINDOWS
10590 fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10591 if (fd < 0)
10592 result = -1;
10593 else {
10594 result = _chsize_s(fd, length);
10595 close(fd);
10596 if (result < 0)
10597 errno = result;
10598 }
10599 #else
10600 result = truncate(path->narrow, length);
10601 #endif
10602 _Py_END_SUPPRESS_IPH
10603 Py_END_ALLOW_THREADS
10604 if (result < 0)
10605 return posix_path_error(path);
10606
10607 Py_RETURN_NONE;
10608 }
10609 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10610
10611
10612 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10613 and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10614 defined, which is the case in Python on AIX. AIX bug report:
10615 http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10616 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10617 # define POSIX_FADVISE_AIX_BUG
10618 #endif
10619
10620
10621 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10622 /*[clinic input]
10623 os.posix_fallocate
10624
10625 fd: int
10626 offset: Py_off_t
10627 length: Py_off_t
10628 /
10629
10630 Ensure a file has allocated at least a particular number of bytes on disk.
10631
10632 Ensure that the file specified by fd encompasses a range of bytes
10633 starting at offset bytes from the beginning and continuing for length bytes.
10634 [clinic start generated code]*/
10635
10636 static PyObject *
os_posix_fallocate_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length)10637 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10638 Py_off_t length)
10639 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10640 {
10641 int result;
10642 int async_err = 0;
10643
10644 do {
10645 Py_BEGIN_ALLOW_THREADS
10646 result = posix_fallocate(fd, offset, length);
10647 Py_END_ALLOW_THREADS
10648 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10649
10650 if (result == 0)
10651 Py_RETURN_NONE;
10652
10653 if (async_err)
10654 return NULL;
10655
10656 errno = result;
10657 return posix_error();
10658 }
10659 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
10660
10661
10662 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
10663 /*[clinic input]
10664 os.posix_fadvise
10665
10666 fd: int
10667 offset: Py_off_t
10668 length: Py_off_t
10669 advice: int
10670 /
10671
10672 Announce an intention to access data in a specific pattern.
10673
10674 Announce an intention to access data in a specific pattern, thus allowing
10675 the kernel to make optimizations.
10676 The advice applies to the region of the file specified by fd starting at
10677 offset and continuing for length bytes.
10678 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
10679 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
10680 POSIX_FADV_DONTNEED.
10681 [clinic start generated code]*/
10682
10683 static PyObject *
os_posix_fadvise_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length,int advice)10684 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
10685 Py_off_t length, int advice)
10686 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
10687 {
10688 int result;
10689 int async_err = 0;
10690
10691 do {
10692 Py_BEGIN_ALLOW_THREADS
10693 result = posix_fadvise(fd, offset, length, advice);
10694 Py_END_ALLOW_THREADS
10695 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10696
10697 if (result == 0)
10698 Py_RETURN_NONE;
10699
10700 if (async_err)
10701 return NULL;
10702
10703 errno = result;
10704 return posix_error();
10705 }
10706 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
10707
10708
10709 #ifdef MS_WINDOWS
10710 static PyObject*
win32_putenv(PyObject * name,PyObject * value)10711 win32_putenv(PyObject *name, PyObject *value)
10712 {
10713 /* Search from index 1 because on Windows starting '=' is allowed for
10714 defining hidden environment variables. */
10715 if (PyUnicode_GET_LENGTH(name) == 0 ||
10716 PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
10717 {
10718 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10719 return NULL;
10720 }
10721 PyObject *unicode;
10722 if (value != NULL) {
10723 unicode = PyUnicode_FromFormat("%U=%U", name, value);
10724 }
10725 else {
10726 unicode = PyUnicode_FromFormat("%U=", name);
10727 }
10728 if (unicode == NULL) {
10729 return NULL;
10730 }
10731
10732 Py_ssize_t size;
10733 /* PyUnicode_AsWideCharString() rejects embedded null characters */
10734 wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
10735 Py_DECREF(unicode);
10736
10737 if (env == NULL) {
10738 return NULL;
10739 }
10740 if (size > _MAX_ENV) {
10741 PyErr_Format(PyExc_ValueError,
10742 "the environment variable is longer than %u characters",
10743 _MAX_ENV);
10744 PyMem_Free(env);
10745 return NULL;
10746 }
10747
10748 /* _wputenv() and SetEnvironmentVariableW() update the environment in the
10749 Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
10750 and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
10751
10752 Prefer _wputenv() to be compatible with C libraries using CRT
10753 variables and CRT functions using these variables (ex: getenv()). */
10754 int err = _wputenv(env);
10755 PyMem_Free(env);
10756
10757 if (err) {
10758 posix_error();
10759 return NULL;
10760 }
10761
10762 Py_RETURN_NONE;
10763 }
10764 #endif
10765
10766
10767 #ifdef MS_WINDOWS
10768 /*[clinic input]
10769 os.putenv
10770
10771 name: unicode
10772 value: unicode
10773 /
10774
10775 Change or add an environment variable.
10776 [clinic start generated code]*/
10777
10778 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10779 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10780 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
10781 {
10782 if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10783 return NULL;
10784 }
10785 return win32_putenv(name, value);
10786 }
10787 #else
10788 /*[clinic input]
10789 os.putenv
10790
10791 name: FSConverter
10792 value: FSConverter
10793 /
10794
10795 Change or add an environment variable.
10796 [clinic start generated code]*/
10797
10798 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10799 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10800 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
10801 {
10802 const char *name_string = PyBytes_AS_STRING(name);
10803 const char *value_string = PyBytes_AS_STRING(value);
10804
10805 if (strchr(name_string, '=') != NULL) {
10806 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10807 return NULL;
10808 }
10809
10810 if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10811 return NULL;
10812 }
10813
10814 if (setenv(name_string, value_string, 1)) {
10815 return posix_error();
10816 }
10817 Py_RETURN_NONE;
10818 }
10819 #endif /* !defined(MS_WINDOWS) */
10820
10821
10822 #ifdef MS_WINDOWS
10823 /*[clinic input]
10824 os.unsetenv
10825 name: unicode
10826 /
10827
10828 Delete an environment variable.
10829 [clinic start generated code]*/
10830
10831 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)10832 os_unsetenv_impl(PyObject *module, PyObject *name)
10833 /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
10834 {
10835 if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
10836 return NULL;
10837 }
10838 return win32_putenv(name, NULL);
10839 }
10840 #else
10841 /*[clinic input]
10842 os.unsetenv
10843 name: FSConverter
10844 /
10845
10846 Delete an environment variable.
10847 [clinic start generated code]*/
10848
10849 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)10850 os_unsetenv_impl(PyObject *module, PyObject *name)
10851 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
10852 {
10853 if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
10854 return NULL;
10855 }
10856 #ifdef HAVE_BROKEN_UNSETENV
10857 unsetenv(PyBytes_AS_STRING(name));
10858 #else
10859 int err = unsetenv(PyBytes_AS_STRING(name));
10860 if (err) {
10861 return posix_error();
10862 }
10863 #endif
10864
10865 Py_RETURN_NONE;
10866 }
10867 #endif /* !MS_WINDOWS */
10868
10869
10870 /*[clinic input]
10871 os.strerror
10872
10873 code: int
10874 /
10875
10876 Translate an error code to a message string.
10877 [clinic start generated code]*/
10878
10879 static PyObject *
os_strerror_impl(PyObject * module,int code)10880 os_strerror_impl(PyObject *module, int code)
10881 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
10882 {
10883 char *message = strerror(code);
10884 if (message == NULL) {
10885 PyErr_SetString(PyExc_ValueError,
10886 "strerror() argument out of range");
10887 return NULL;
10888 }
10889 return PyUnicode_DecodeLocale(message, "surrogateescape");
10890 }
10891
10892
10893 #ifdef HAVE_SYS_WAIT_H
10894 #ifdef WCOREDUMP
10895 /*[clinic input]
10896 os.WCOREDUMP -> bool
10897
10898 status: int
10899 /
10900
10901 Return True if the process returning status was dumped to a core file.
10902 [clinic start generated code]*/
10903
10904 static int
os_WCOREDUMP_impl(PyObject * module,int status)10905 os_WCOREDUMP_impl(PyObject *module, int status)
10906 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
10907 {
10908 WAIT_TYPE wait_status;
10909 WAIT_STATUS_INT(wait_status) = status;
10910 return WCOREDUMP(wait_status);
10911 }
10912 #endif /* WCOREDUMP */
10913
10914
10915 #ifdef WIFCONTINUED
10916 /*[clinic input]
10917 os.WIFCONTINUED -> bool
10918
10919 status: int
10920
10921 Return True if a particular process was continued from a job control stop.
10922
10923 Return True if the process returning status was continued from a
10924 job control stop.
10925 [clinic start generated code]*/
10926
10927 static int
os_WIFCONTINUED_impl(PyObject * module,int status)10928 os_WIFCONTINUED_impl(PyObject *module, int status)
10929 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
10930 {
10931 WAIT_TYPE wait_status;
10932 WAIT_STATUS_INT(wait_status) = status;
10933 return WIFCONTINUED(wait_status);
10934 }
10935 #endif /* WIFCONTINUED */
10936
10937
10938 #ifdef WIFSTOPPED
10939 /*[clinic input]
10940 os.WIFSTOPPED -> bool
10941
10942 status: int
10943
10944 Return True if the process returning status was stopped.
10945 [clinic start generated code]*/
10946
10947 static int
os_WIFSTOPPED_impl(PyObject * module,int status)10948 os_WIFSTOPPED_impl(PyObject *module, int status)
10949 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
10950 {
10951 WAIT_TYPE wait_status;
10952 WAIT_STATUS_INT(wait_status) = status;
10953 return WIFSTOPPED(wait_status);
10954 }
10955 #endif /* WIFSTOPPED */
10956
10957
10958 #ifdef WIFSIGNALED
10959 /*[clinic input]
10960 os.WIFSIGNALED -> bool
10961
10962 status: int
10963
10964 Return True if the process returning status was terminated by a signal.
10965 [clinic start generated code]*/
10966
10967 static int
os_WIFSIGNALED_impl(PyObject * module,int status)10968 os_WIFSIGNALED_impl(PyObject *module, int status)
10969 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
10970 {
10971 WAIT_TYPE wait_status;
10972 WAIT_STATUS_INT(wait_status) = status;
10973 return WIFSIGNALED(wait_status);
10974 }
10975 #endif /* WIFSIGNALED */
10976
10977
10978 #ifdef WIFEXITED
10979 /*[clinic input]
10980 os.WIFEXITED -> bool
10981
10982 status: int
10983
10984 Return True if the process returning status exited via the exit() system call.
10985 [clinic start generated code]*/
10986
10987 static int
os_WIFEXITED_impl(PyObject * module,int status)10988 os_WIFEXITED_impl(PyObject *module, int status)
10989 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
10990 {
10991 WAIT_TYPE wait_status;
10992 WAIT_STATUS_INT(wait_status) = status;
10993 return WIFEXITED(wait_status);
10994 }
10995 #endif /* WIFEXITED */
10996
10997
10998 #ifdef WEXITSTATUS
10999 /*[clinic input]
11000 os.WEXITSTATUS -> int
11001
11002 status: int
11003
11004 Return the process return code from status.
11005 [clinic start generated code]*/
11006
11007 static int
os_WEXITSTATUS_impl(PyObject * module,int status)11008 os_WEXITSTATUS_impl(PyObject *module, int status)
11009 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
11010 {
11011 WAIT_TYPE wait_status;
11012 WAIT_STATUS_INT(wait_status) = status;
11013 return WEXITSTATUS(wait_status);
11014 }
11015 #endif /* WEXITSTATUS */
11016
11017
11018 #ifdef WTERMSIG
11019 /*[clinic input]
11020 os.WTERMSIG -> int
11021
11022 status: int
11023
11024 Return the signal that terminated the process that provided the status value.
11025 [clinic start generated code]*/
11026
11027 static int
os_WTERMSIG_impl(PyObject * module,int status)11028 os_WTERMSIG_impl(PyObject *module, int status)
11029 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
11030 {
11031 WAIT_TYPE wait_status;
11032 WAIT_STATUS_INT(wait_status) = status;
11033 return WTERMSIG(wait_status);
11034 }
11035 #endif /* WTERMSIG */
11036
11037
11038 #ifdef WSTOPSIG
11039 /*[clinic input]
11040 os.WSTOPSIG -> int
11041
11042 status: int
11043
11044 Return the signal that stopped the process that provided the status value.
11045 [clinic start generated code]*/
11046
11047 static int
os_WSTOPSIG_impl(PyObject * module,int status)11048 os_WSTOPSIG_impl(PyObject *module, int status)
11049 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
11050 {
11051 WAIT_TYPE wait_status;
11052 WAIT_STATUS_INT(wait_status) = status;
11053 return WSTOPSIG(wait_status);
11054 }
11055 #endif /* WSTOPSIG */
11056 #endif /* HAVE_SYS_WAIT_H */
11057
11058
11059 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
11060 #ifdef _SCO_DS
11061 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
11062 needed definitions in sys/statvfs.h */
11063 #define _SVID3
11064 #endif
11065 #include <sys/statvfs.h>
11066
11067 static PyObject*
_pystatvfs_fromstructstatvfs(PyObject * module,struct statvfs st)11068 _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
11069 PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
11070 PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
11071 if (v == NULL)
11072 return NULL;
11073
11074 #if !defined(HAVE_LARGEFILE_SUPPORT)
11075 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11076 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11077 PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
11078 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
11079 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
11080 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
11081 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
11082 PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
11083 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11084 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11085 #else
11086 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11087 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11088 PyStructSequence_SET_ITEM(v, 2,
11089 PyLong_FromLongLong((long long) st.f_blocks));
11090 PyStructSequence_SET_ITEM(v, 3,
11091 PyLong_FromLongLong((long long) st.f_bfree));
11092 PyStructSequence_SET_ITEM(v, 4,
11093 PyLong_FromLongLong((long long) st.f_bavail));
11094 PyStructSequence_SET_ITEM(v, 5,
11095 PyLong_FromLongLong((long long) st.f_files));
11096 PyStructSequence_SET_ITEM(v, 6,
11097 PyLong_FromLongLong((long long) st.f_ffree));
11098 PyStructSequence_SET_ITEM(v, 7,
11099 PyLong_FromLongLong((long long) st.f_favail));
11100 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11101 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11102 #endif
11103 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
11104 * (issue #32390). */
11105 #if defined(_AIX) && defined(_ALL_SOURCE)
11106 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
11107 #else
11108 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
11109 #endif
11110 if (PyErr_Occurred()) {
11111 Py_DECREF(v);
11112 return NULL;
11113 }
11114
11115 return v;
11116 }
11117
11118
11119 /*[clinic input]
11120 os.fstatvfs
11121 fd: int
11122 /
11123
11124 Perform an fstatvfs system call on the given fd.
11125
11126 Equivalent to statvfs(fd).
11127 [clinic start generated code]*/
11128
11129 static PyObject *
os_fstatvfs_impl(PyObject * module,int fd)11130 os_fstatvfs_impl(PyObject *module, int fd)
11131 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
11132 {
11133 int result;
11134 int async_err = 0;
11135 struct statvfs st;
11136
11137 do {
11138 Py_BEGIN_ALLOW_THREADS
11139 result = fstatvfs(fd, &st);
11140 Py_END_ALLOW_THREADS
11141 } while (result != 0 && errno == EINTR &&
11142 !(async_err = PyErr_CheckSignals()));
11143 if (result != 0)
11144 return (!async_err) ? posix_error() : NULL;
11145
11146 return _pystatvfs_fromstructstatvfs(module, st);
11147 }
11148 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
11149
11150
11151 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
11152 #include <sys/statvfs.h>
11153 /*[clinic input]
11154 os.statvfs
11155
11156 path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
11157
11158 Perform a statvfs system call on the given path.
11159
11160 path may always be specified as a string.
11161 On some platforms, path may also be specified as an open file descriptor.
11162 If this functionality is unavailable, using it raises an exception.
11163 [clinic start generated code]*/
11164
11165 static PyObject *
os_statvfs_impl(PyObject * module,path_t * path)11166 os_statvfs_impl(PyObject *module, path_t *path)
11167 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
11168 {
11169 int result;
11170 struct statvfs st;
11171
11172 Py_BEGIN_ALLOW_THREADS
11173 #ifdef HAVE_FSTATVFS
11174 if (path->fd != -1) {
11175 result = fstatvfs(path->fd, &st);
11176 }
11177 else
11178 #endif
11179 result = statvfs(path->narrow, &st);
11180 Py_END_ALLOW_THREADS
11181
11182 if (result) {
11183 return path_error(path);
11184 }
11185
11186 return _pystatvfs_fromstructstatvfs(module, st);
11187 }
11188 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
11189
11190
11191 #ifdef MS_WINDOWS
11192 /*[clinic input]
11193 os._getdiskusage
11194
11195 path: path_t
11196
11197 Return disk usage statistics about the given path as a (total, free) tuple.
11198 [clinic start generated code]*/
11199
11200 static PyObject *
os__getdiskusage_impl(PyObject * module,path_t * path)11201 os__getdiskusage_impl(PyObject *module, path_t *path)
11202 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
11203 {
11204 BOOL retval;
11205 ULARGE_INTEGER _, total, free;
11206 DWORD err = 0;
11207
11208 Py_BEGIN_ALLOW_THREADS
11209 retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
11210 Py_END_ALLOW_THREADS
11211 if (retval == 0) {
11212 if (GetLastError() == ERROR_DIRECTORY) {
11213 wchar_t *dir_path = NULL;
11214
11215 dir_path = PyMem_New(wchar_t, path->length + 1);
11216 if (dir_path == NULL) {
11217 return PyErr_NoMemory();
11218 }
11219
11220 wcscpy_s(dir_path, path->length + 1, path->wide);
11221
11222 if (_dirnameW(dir_path) != -1) {
11223 Py_BEGIN_ALLOW_THREADS
11224 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
11225 Py_END_ALLOW_THREADS
11226 }
11227 /* Record the last error in case it's modified by PyMem_Free. */
11228 err = GetLastError();
11229 PyMem_Free(dir_path);
11230 if (retval) {
11231 goto success;
11232 }
11233 }
11234 return PyErr_SetFromWindowsErr(err);
11235 }
11236
11237 success:
11238 return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
11239 }
11240 #endif /* MS_WINDOWS */
11241
11242
11243 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
11244 * It maps strings representing configuration variable names to
11245 * integer values, allowing those functions to be called with the
11246 * magic names instead of polluting the module's namespace with tons of
11247 * rarely-used constants. There are three separate tables that use
11248 * these definitions.
11249 *
11250 * This code is always included, even if none of the interfaces that
11251 * need it are included. The #if hackery needed to avoid it would be
11252 * sufficiently pervasive that it's not worth the loss of readability.
11253 */
11254 struct constdef {
11255 const char *name;
11256 int value;
11257 };
11258
11259 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)11260 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
11261 size_t tablesize)
11262 {
11263 if (PyLong_Check(arg)) {
11264 int value = _PyLong_AsInt(arg);
11265 if (value == -1 && PyErr_Occurred())
11266 return 0;
11267 *valuep = value;
11268 return 1;
11269 }
11270 else {
11271 /* look up the value in the table using a binary search */
11272 size_t lo = 0;
11273 size_t mid;
11274 size_t hi = tablesize;
11275 int cmp;
11276 const char *confname;
11277 if (!PyUnicode_Check(arg)) {
11278 PyErr_SetString(PyExc_TypeError,
11279 "configuration names must be strings or integers");
11280 return 0;
11281 }
11282 confname = PyUnicode_AsUTF8(arg);
11283 if (confname == NULL)
11284 return 0;
11285 while (lo < hi) {
11286 mid = (lo + hi) / 2;
11287 cmp = strcmp(confname, table[mid].name);
11288 if (cmp < 0)
11289 hi = mid;
11290 else if (cmp > 0)
11291 lo = mid + 1;
11292 else {
11293 *valuep = table[mid].value;
11294 return 1;
11295 }
11296 }
11297 PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
11298 return 0;
11299 }
11300 }
11301
11302
11303 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11304 static struct constdef posix_constants_pathconf[] = {
11305 #ifdef _PC_ABI_AIO_XFER_MAX
11306 {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
11307 #endif
11308 #ifdef _PC_ABI_ASYNC_IO
11309 {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
11310 #endif
11311 #ifdef _PC_ASYNC_IO
11312 {"PC_ASYNC_IO", _PC_ASYNC_IO},
11313 #endif
11314 #ifdef _PC_CHOWN_RESTRICTED
11315 {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
11316 #endif
11317 #ifdef _PC_FILESIZEBITS
11318 {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
11319 #endif
11320 #ifdef _PC_LAST
11321 {"PC_LAST", _PC_LAST},
11322 #endif
11323 #ifdef _PC_LINK_MAX
11324 {"PC_LINK_MAX", _PC_LINK_MAX},
11325 #endif
11326 #ifdef _PC_MAX_CANON
11327 {"PC_MAX_CANON", _PC_MAX_CANON},
11328 #endif
11329 #ifdef _PC_MAX_INPUT
11330 {"PC_MAX_INPUT", _PC_MAX_INPUT},
11331 #endif
11332 #ifdef _PC_NAME_MAX
11333 {"PC_NAME_MAX", _PC_NAME_MAX},
11334 #endif
11335 #ifdef _PC_NO_TRUNC
11336 {"PC_NO_TRUNC", _PC_NO_TRUNC},
11337 #endif
11338 #ifdef _PC_PATH_MAX
11339 {"PC_PATH_MAX", _PC_PATH_MAX},
11340 #endif
11341 #ifdef _PC_PIPE_BUF
11342 {"PC_PIPE_BUF", _PC_PIPE_BUF},
11343 #endif
11344 #ifdef _PC_PRIO_IO
11345 {"PC_PRIO_IO", _PC_PRIO_IO},
11346 #endif
11347 #ifdef _PC_SOCK_MAXBUF
11348 {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
11349 #endif
11350 #ifdef _PC_SYNC_IO
11351 {"PC_SYNC_IO", _PC_SYNC_IO},
11352 #endif
11353 #ifdef _PC_VDISABLE
11354 {"PC_VDISABLE", _PC_VDISABLE},
11355 #endif
11356 #ifdef _PC_ACL_ENABLED
11357 {"PC_ACL_ENABLED", _PC_ACL_ENABLED},
11358 #endif
11359 #ifdef _PC_MIN_HOLE_SIZE
11360 {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE},
11361 #endif
11362 #ifdef _PC_ALLOC_SIZE_MIN
11363 {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN},
11364 #endif
11365 #ifdef _PC_REC_INCR_XFER_SIZE
11366 {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE},
11367 #endif
11368 #ifdef _PC_REC_MAX_XFER_SIZE
11369 {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE},
11370 #endif
11371 #ifdef _PC_REC_MIN_XFER_SIZE
11372 {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE},
11373 #endif
11374 #ifdef _PC_REC_XFER_ALIGN
11375 {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN},
11376 #endif
11377 #ifdef _PC_SYMLINK_MAX
11378 {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX},
11379 #endif
11380 #ifdef _PC_XATTR_ENABLED
11381 {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED},
11382 #endif
11383 #ifdef _PC_XATTR_EXISTS
11384 {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
11385 #endif
11386 #ifdef _PC_TIMESTAMP_RESOLUTION
11387 {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
11388 #endif
11389 };
11390
11391 static int
conv_path_confname(PyObject * arg,int * valuep)11392 conv_path_confname(PyObject *arg, int *valuep)
11393 {
11394 return conv_confname(arg, valuep, posix_constants_pathconf,
11395 sizeof(posix_constants_pathconf)
11396 / sizeof(struct constdef));
11397 }
11398 #endif
11399
11400
11401 #ifdef HAVE_FPATHCONF
11402 /*[clinic input]
11403 os.fpathconf -> long
11404
11405 fd: int
11406 name: path_confname
11407 /
11408
11409 Return the configuration limit name for the file descriptor fd.
11410
11411 If there is no limit, return -1.
11412 [clinic start generated code]*/
11413
11414 static long
os_fpathconf_impl(PyObject * module,int fd,int name)11415 os_fpathconf_impl(PyObject *module, int fd, int name)
11416 /*[clinic end generated code: output=d5b7042425fc3e21 input=5942a024d3777810]*/
11417 {
11418 long limit;
11419
11420 errno = 0;
11421 limit = fpathconf(fd, name);
11422 if (limit == -1 && errno != 0)
11423 posix_error();
11424
11425 return limit;
11426 }
11427 #endif /* HAVE_FPATHCONF */
11428
11429
11430 #ifdef HAVE_PATHCONF
11431 /*[clinic input]
11432 os.pathconf -> long
11433 path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
11434 name: path_confname
11435
11436 Return the configuration limit name for the file or directory path.
11437
11438 If there is no limit, return -1.
11439 On some platforms, path may also be specified as an open file descriptor.
11440 If this functionality is unavailable, using it raises an exception.
11441 [clinic start generated code]*/
11442
11443 static long
os_pathconf_impl(PyObject * module,path_t * path,int name)11444 os_pathconf_impl(PyObject *module, path_t *path, int name)
11445 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
11446 {
11447 long limit;
11448
11449 errno = 0;
11450 #ifdef HAVE_FPATHCONF
11451 if (path->fd != -1)
11452 limit = fpathconf(path->fd, name);
11453 else
11454 #endif
11455 limit = pathconf(path->narrow, name);
11456 if (limit == -1 && errno != 0) {
11457 if (errno == EINVAL)
11458 /* could be a path or name problem */
11459 posix_error();
11460 else
11461 path_error(path);
11462 }
11463
11464 return limit;
11465 }
11466 #endif /* HAVE_PATHCONF */
11467
11468 #ifdef HAVE_CONFSTR
11469 static struct constdef posix_constants_confstr[] = {
11470 #ifdef _CS_ARCHITECTURE
11471 {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
11472 #endif
11473 #ifdef _CS_GNU_LIBC_VERSION
11474 {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION},
11475 #endif
11476 #ifdef _CS_GNU_LIBPTHREAD_VERSION
11477 {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION},
11478 #endif
11479 #ifdef _CS_HOSTNAME
11480 {"CS_HOSTNAME", _CS_HOSTNAME},
11481 #endif
11482 #ifdef _CS_HW_PROVIDER
11483 {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
11484 #endif
11485 #ifdef _CS_HW_SERIAL
11486 {"CS_HW_SERIAL", _CS_HW_SERIAL},
11487 #endif
11488 #ifdef _CS_INITTAB_NAME
11489 {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11490 #endif
11491 #ifdef _CS_LFS64_CFLAGS
11492 {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11493 #endif
11494 #ifdef _CS_LFS64_LDFLAGS
11495 {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
11496 #endif
11497 #ifdef _CS_LFS64_LIBS
11498 {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
11499 #endif
11500 #ifdef _CS_LFS64_LINTFLAGS
11501 {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
11502 #endif
11503 #ifdef _CS_LFS_CFLAGS
11504 {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
11505 #endif
11506 #ifdef _CS_LFS_LDFLAGS
11507 {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
11508 #endif
11509 #ifdef _CS_LFS_LIBS
11510 {"CS_LFS_LIBS", _CS_LFS_LIBS},
11511 #endif
11512 #ifdef _CS_LFS_LINTFLAGS
11513 {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
11514 #endif
11515 #ifdef _CS_MACHINE
11516 {"CS_MACHINE", _CS_MACHINE},
11517 #endif
11518 #ifdef _CS_PATH
11519 {"CS_PATH", _CS_PATH},
11520 #endif
11521 #ifdef _CS_RELEASE
11522 {"CS_RELEASE", _CS_RELEASE},
11523 #endif
11524 #ifdef _CS_SRPC_DOMAIN
11525 {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
11526 #endif
11527 #ifdef _CS_SYSNAME
11528 {"CS_SYSNAME", _CS_SYSNAME},
11529 #endif
11530 #ifdef _CS_VERSION
11531 {"CS_VERSION", _CS_VERSION},
11532 #endif
11533 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11534 {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
11535 #endif
11536 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11537 {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
11538 #endif
11539 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11540 {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
11541 #endif
11542 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11543 {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11544 #endif
11545 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11546 {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11547 #endif
11548 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11549 {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11550 #endif
11551 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11552 {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
11553 #endif
11554 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11555 {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11556 #endif
11557 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11558 {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
11559 #endif
11560 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11561 {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
11562 #endif
11563 #ifdef _CS_XBS5_LP64_OFF64_LIBS
11564 {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11565 #endif
11566 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11567 {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
11568 #endif
11569 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11570 {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11571 #endif
11572 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11573 {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11574 #endif
11575 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11576 {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
11577 #endif
11578 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11579 {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11580 #endif
11581 #ifdef _MIPS_CS_AVAIL_PROCESSORS
11582 {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
11583 #endif
11584 #ifdef _MIPS_CS_BASE
11585 {"MIPS_CS_BASE", _MIPS_CS_BASE},
11586 #endif
11587 #ifdef _MIPS_CS_HOSTID
11588 {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
11589 #endif
11590 #ifdef _MIPS_CS_HW_NAME
11591 {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11592 #endif
11593 #ifdef _MIPS_CS_NUM_PROCESSORS
11594 {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
11595 #endif
11596 #ifdef _MIPS_CS_OSREL_MAJ
11597 {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
11598 #endif
11599 #ifdef _MIPS_CS_OSREL_MIN
11600 {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
11601 #endif
11602 #ifdef _MIPS_CS_OSREL_PATCH
11603 {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
11604 #endif
11605 #ifdef _MIPS_CS_OS_NAME
11606 {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11607 #endif
11608 #ifdef _MIPS_CS_OS_PROVIDER
11609 {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
11610 #endif
11611 #ifdef _MIPS_CS_PROCESSORS
11612 {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
11613 #endif
11614 #ifdef _MIPS_CS_SERIAL
11615 {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
11616 #endif
11617 #ifdef _MIPS_CS_VENDOR
11618 {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
11619 #endif
11620 };
11621
11622 static int
conv_confstr_confname(PyObject * arg,int * valuep)11623 conv_confstr_confname(PyObject *arg, int *valuep)
11624 {
11625 return conv_confname(arg, valuep, posix_constants_confstr,
11626 sizeof(posix_constants_confstr)
11627 / sizeof(struct constdef));
11628 }
11629
11630
11631 /*[clinic input]
11632 os.confstr
11633
11634 name: confstr_confname
11635 /
11636
11637 Return a string-valued system configuration variable.
11638 [clinic start generated code]*/
11639
11640 static PyObject *
os_confstr_impl(PyObject * module,int name)11641 os_confstr_impl(PyObject *module, int name)
11642 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11643 {
11644 PyObject *result = NULL;
11645 char buffer[255];
11646 size_t len;
11647
11648 errno = 0;
11649 len = confstr(name, buffer, sizeof(buffer));
11650 if (len == 0) {
11651 if (errno) {
11652 posix_error();
11653 return NULL;
11654 }
11655 else {
11656 Py_RETURN_NONE;
11657 }
11658 }
11659
11660 if (len >= sizeof(buffer)) {
11661 size_t len2;
11662 char *buf = PyMem_Malloc(len);
11663 if (buf == NULL)
11664 return PyErr_NoMemory();
11665 len2 = confstr(name, buf, len);
11666 assert(len == len2);
11667 result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11668 PyMem_Free(buf);
11669 }
11670 else
11671 result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11672 return result;
11673 }
11674 #endif /* HAVE_CONFSTR */
11675
11676
11677 #ifdef HAVE_SYSCONF
11678 static struct constdef posix_constants_sysconf[] = {
11679 #ifdef _SC_2_CHAR_TERM
11680 {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
11681 #endif
11682 #ifdef _SC_2_C_BIND
11683 {"SC_2_C_BIND", _SC_2_C_BIND},
11684 #endif
11685 #ifdef _SC_2_C_DEV
11686 {"SC_2_C_DEV", _SC_2_C_DEV},
11687 #endif
11688 #ifdef _SC_2_C_VERSION
11689 {"SC_2_C_VERSION", _SC_2_C_VERSION},
11690 #endif
11691 #ifdef _SC_2_FORT_DEV
11692 {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
11693 #endif
11694 #ifdef _SC_2_FORT_RUN
11695 {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
11696 #endif
11697 #ifdef _SC_2_LOCALEDEF
11698 {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
11699 #endif
11700 #ifdef _SC_2_SW_DEV
11701 {"SC_2_SW_DEV", _SC_2_SW_DEV},
11702 #endif
11703 #ifdef _SC_2_UPE
11704 {"SC_2_UPE", _SC_2_UPE},
11705 #endif
11706 #ifdef _SC_2_VERSION
11707 {"SC_2_VERSION", _SC_2_VERSION},
11708 #endif
11709 #ifdef _SC_ABI_ASYNCHRONOUS_IO
11710 {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
11711 #endif
11712 #ifdef _SC_ACL
11713 {"SC_ACL", _SC_ACL},
11714 #endif
11715 #ifdef _SC_AIO_LISTIO_MAX
11716 {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
11717 #endif
11718 #ifdef _SC_AIO_MAX
11719 {"SC_AIO_MAX", _SC_AIO_MAX},
11720 #endif
11721 #ifdef _SC_AIO_PRIO_DELTA_MAX
11722 {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
11723 #endif
11724 #ifdef _SC_ARG_MAX
11725 {"SC_ARG_MAX", _SC_ARG_MAX},
11726 #endif
11727 #ifdef _SC_ASYNCHRONOUS_IO
11728 {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
11729 #endif
11730 #ifdef _SC_ATEXIT_MAX
11731 {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
11732 #endif
11733 #ifdef _SC_AUDIT
11734 {"SC_AUDIT", _SC_AUDIT},
11735 #endif
11736 #ifdef _SC_AVPHYS_PAGES
11737 {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
11738 #endif
11739 #ifdef _SC_BC_BASE_MAX
11740 {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
11741 #endif
11742 #ifdef _SC_BC_DIM_MAX
11743 {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
11744 #endif
11745 #ifdef _SC_BC_SCALE_MAX
11746 {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
11747 #endif
11748 #ifdef _SC_BC_STRING_MAX
11749 {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
11750 #endif
11751 #ifdef _SC_CAP
11752 {"SC_CAP", _SC_CAP},
11753 #endif
11754 #ifdef _SC_CHARCLASS_NAME_MAX
11755 {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
11756 #endif
11757 #ifdef _SC_CHAR_BIT
11758 {"SC_CHAR_BIT", _SC_CHAR_BIT},
11759 #endif
11760 #ifdef _SC_CHAR_MAX
11761 {"SC_CHAR_MAX", _SC_CHAR_MAX},
11762 #endif
11763 #ifdef _SC_CHAR_MIN
11764 {"SC_CHAR_MIN", _SC_CHAR_MIN},
11765 #endif
11766 #ifdef _SC_CHILD_MAX
11767 {"SC_CHILD_MAX", _SC_CHILD_MAX},
11768 #endif
11769 #ifdef _SC_CLK_TCK
11770 {"SC_CLK_TCK", _SC_CLK_TCK},
11771 #endif
11772 #ifdef _SC_COHER_BLKSZ
11773 {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
11774 #endif
11775 #ifdef _SC_COLL_WEIGHTS_MAX
11776 {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
11777 #endif
11778 #ifdef _SC_DCACHE_ASSOC
11779 {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
11780 #endif
11781 #ifdef _SC_DCACHE_BLKSZ
11782 {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
11783 #endif
11784 #ifdef _SC_DCACHE_LINESZ
11785 {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
11786 #endif
11787 #ifdef _SC_DCACHE_SZ
11788 {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
11789 #endif
11790 #ifdef _SC_DCACHE_TBLKSZ
11791 {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
11792 #endif
11793 #ifdef _SC_DELAYTIMER_MAX
11794 {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
11795 #endif
11796 #ifdef _SC_EQUIV_CLASS_MAX
11797 {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
11798 #endif
11799 #ifdef _SC_EXPR_NEST_MAX
11800 {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
11801 #endif
11802 #ifdef _SC_FSYNC
11803 {"SC_FSYNC", _SC_FSYNC},
11804 #endif
11805 #ifdef _SC_GETGR_R_SIZE_MAX
11806 {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
11807 #endif
11808 #ifdef _SC_GETPW_R_SIZE_MAX
11809 {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
11810 #endif
11811 #ifdef _SC_ICACHE_ASSOC
11812 {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
11813 #endif
11814 #ifdef _SC_ICACHE_BLKSZ
11815 {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
11816 #endif
11817 #ifdef _SC_ICACHE_LINESZ
11818 {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
11819 #endif
11820 #ifdef _SC_ICACHE_SZ
11821 {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
11822 #endif
11823 #ifdef _SC_INF
11824 {"SC_INF", _SC_INF},
11825 #endif
11826 #ifdef _SC_INT_MAX
11827 {"SC_INT_MAX", _SC_INT_MAX},
11828 #endif
11829 #ifdef _SC_INT_MIN
11830 {"SC_INT_MIN", _SC_INT_MIN},
11831 #endif
11832 #ifdef _SC_IOV_MAX
11833 {"SC_IOV_MAX", _SC_IOV_MAX},
11834 #endif
11835 #ifdef _SC_IP_SECOPTS
11836 {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
11837 #endif
11838 #ifdef _SC_JOB_CONTROL
11839 {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
11840 #endif
11841 #ifdef _SC_KERN_POINTERS
11842 {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
11843 #endif
11844 #ifdef _SC_KERN_SIM
11845 {"SC_KERN_SIM", _SC_KERN_SIM},
11846 #endif
11847 #ifdef _SC_LINE_MAX
11848 {"SC_LINE_MAX", _SC_LINE_MAX},
11849 #endif
11850 #ifdef _SC_LOGIN_NAME_MAX
11851 {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
11852 #endif
11853 #ifdef _SC_LOGNAME_MAX
11854 {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
11855 #endif
11856 #ifdef _SC_LONG_BIT
11857 {"SC_LONG_BIT", _SC_LONG_BIT},
11858 #endif
11859 #ifdef _SC_MAC
11860 {"SC_MAC", _SC_MAC},
11861 #endif
11862 #ifdef _SC_MAPPED_FILES
11863 {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
11864 #endif
11865 #ifdef _SC_MAXPID
11866 {"SC_MAXPID", _SC_MAXPID},
11867 #endif
11868 #ifdef _SC_MB_LEN_MAX
11869 {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
11870 #endif
11871 #ifdef _SC_MEMLOCK
11872 {"SC_MEMLOCK", _SC_MEMLOCK},
11873 #endif
11874 #ifdef _SC_MEMLOCK_RANGE
11875 {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
11876 #endif
11877 #ifdef _SC_MEMORY_PROTECTION
11878 {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
11879 #endif
11880 #ifdef _SC_MESSAGE_PASSING
11881 {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
11882 #endif
11883 #ifdef _SC_MMAP_FIXED_ALIGNMENT
11884 {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
11885 #endif
11886 #ifdef _SC_MQ_OPEN_MAX
11887 {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
11888 #endif
11889 #ifdef _SC_MQ_PRIO_MAX
11890 {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},
11891 #endif
11892 #ifdef _SC_NACLS_MAX
11893 {"SC_NACLS_MAX", _SC_NACLS_MAX},
11894 #endif
11895 #ifdef _SC_NGROUPS_MAX
11896 {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX},
11897 #endif
11898 #ifdef _SC_NL_ARGMAX
11899 {"SC_NL_ARGMAX", _SC_NL_ARGMAX},
11900 #endif
11901 #ifdef _SC_NL_LANGMAX
11902 {"SC_NL_LANGMAX", _SC_NL_LANGMAX},
11903 #endif
11904 #ifdef _SC_NL_MSGMAX
11905 {"SC_NL_MSGMAX", _SC_NL_MSGMAX},
11906 #endif
11907 #ifdef _SC_NL_NMAX
11908 {"SC_NL_NMAX", _SC_NL_NMAX},
11909 #endif
11910 #ifdef _SC_NL_SETMAX
11911 {"SC_NL_SETMAX", _SC_NL_SETMAX},
11912 #endif
11913 #ifdef _SC_NL_TEXTMAX
11914 {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX},
11915 #endif
11916 #ifdef _SC_NPROCESSORS_CONF
11917 {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
11918 #endif
11919 #ifdef _SC_NPROCESSORS_ONLN
11920 {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
11921 #endif
11922 #ifdef _SC_NPROC_CONF
11923 {"SC_NPROC_CONF", _SC_NPROC_CONF},
11924 #endif
11925 #ifdef _SC_NPROC_ONLN
11926 {"SC_NPROC_ONLN", _SC_NPROC_ONLN},
11927 #endif
11928 #ifdef _SC_NZERO
11929 {"SC_NZERO", _SC_NZERO},
11930 #endif
11931 #ifdef _SC_OPEN_MAX
11932 {"SC_OPEN_MAX", _SC_OPEN_MAX},
11933 #endif
11934 #ifdef _SC_PAGESIZE
11935 {"SC_PAGESIZE", _SC_PAGESIZE},
11936 #endif
11937 #ifdef _SC_PAGE_SIZE
11938 {"SC_PAGE_SIZE", _SC_PAGE_SIZE},
11939 #endif
11940 #ifdef _SC_AIX_REALMEM
11941 {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
11942 #endif
11943 #ifdef _SC_PASS_MAX
11944 {"SC_PASS_MAX", _SC_PASS_MAX},
11945 #endif
11946 #ifdef _SC_PHYS_PAGES
11947 {"SC_PHYS_PAGES", _SC_PHYS_PAGES},
11948 #endif
11949 #ifdef _SC_PII
11950 {"SC_PII", _SC_PII},
11951 #endif
11952 #ifdef _SC_PII_INTERNET
11953 {"SC_PII_INTERNET", _SC_PII_INTERNET},
11954 #endif
11955 #ifdef _SC_PII_INTERNET_DGRAM
11956 {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM},
11957 #endif
11958 #ifdef _SC_PII_INTERNET_STREAM
11959 {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM},
11960 #endif
11961 #ifdef _SC_PII_OSI
11962 {"SC_PII_OSI", _SC_PII_OSI},
11963 #endif
11964 #ifdef _SC_PII_OSI_CLTS
11965 {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
11966 #endif
11967 #ifdef _SC_PII_OSI_COTS
11968 {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
11969 #endif
11970 #ifdef _SC_PII_OSI_M
11971 {"SC_PII_OSI_M", _SC_PII_OSI_M},
11972 #endif
11973 #ifdef _SC_PII_SOCKET
11974 {"SC_PII_SOCKET", _SC_PII_SOCKET},
11975 #endif
11976 #ifdef _SC_PII_XTI
11977 {"SC_PII_XTI", _SC_PII_XTI},
11978 #endif
11979 #ifdef _SC_POLL
11980 {"SC_POLL", _SC_POLL},
11981 #endif
11982 #ifdef _SC_PRIORITIZED_IO
11983 {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO},
11984 #endif
11985 #ifdef _SC_PRIORITY_SCHEDULING
11986 {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING},
11987 #endif
11988 #ifdef _SC_REALTIME_SIGNALS
11989 {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS},
11990 #endif
11991 #ifdef _SC_RE_DUP_MAX
11992 {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX},
11993 #endif
11994 #ifdef _SC_RTSIG_MAX
11995 {"SC_RTSIG_MAX", _SC_RTSIG_MAX},
11996 #endif
11997 #ifdef _SC_SAVED_IDS
11998 {"SC_SAVED_IDS", _SC_SAVED_IDS},
11999 #endif
12000 #ifdef _SC_SCHAR_MAX
12001 {"SC_SCHAR_MAX", _SC_SCHAR_MAX},
12002 #endif
12003 #ifdef _SC_SCHAR_MIN
12004 {"SC_SCHAR_MIN", _SC_SCHAR_MIN},
12005 #endif
12006 #ifdef _SC_SELECT
12007 {"SC_SELECT", _SC_SELECT},
12008 #endif
12009 #ifdef _SC_SEMAPHORES
12010 {"SC_SEMAPHORES", _SC_SEMAPHORES},
12011 #endif
12012 #ifdef _SC_SEM_NSEMS_MAX
12013 {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX},
12014 #endif
12015 #ifdef _SC_SEM_VALUE_MAX
12016 {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX},
12017 #endif
12018 #ifdef _SC_SHARED_MEMORY_OBJECTS
12019 {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS},
12020 #endif
12021 #ifdef _SC_SHRT_MAX
12022 {"SC_SHRT_MAX", _SC_SHRT_MAX},
12023 #endif
12024 #ifdef _SC_SHRT_MIN
12025 {"SC_SHRT_MIN", _SC_SHRT_MIN},
12026 #endif
12027 #ifdef _SC_SIGQUEUE_MAX
12028 {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
12029 #endif
12030 #ifdef _SC_SIGRT_MAX
12031 {"SC_SIGRT_MAX", _SC_SIGRT_MAX},
12032 #endif
12033 #ifdef _SC_SIGRT_MIN
12034 {"SC_SIGRT_MIN", _SC_SIGRT_MIN},
12035 #endif
12036 #ifdef _SC_SOFTPOWER
12037 {"SC_SOFTPOWER", _SC_SOFTPOWER},
12038 #endif
12039 #ifdef _SC_SPLIT_CACHE
12040 {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE},
12041 #endif
12042 #ifdef _SC_SSIZE_MAX
12043 {"SC_SSIZE_MAX", _SC_SSIZE_MAX},
12044 #endif
12045 #ifdef _SC_STACK_PROT
12046 {"SC_STACK_PROT", _SC_STACK_PROT},
12047 #endif
12048 #ifdef _SC_STREAM_MAX
12049 {"SC_STREAM_MAX", _SC_STREAM_MAX},
12050 #endif
12051 #ifdef _SC_SYNCHRONIZED_IO
12052 {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO},
12053 #endif
12054 #ifdef _SC_THREADS
12055 {"SC_THREADS", _SC_THREADS},
12056 #endif
12057 #ifdef _SC_THREAD_ATTR_STACKADDR
12058 {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR},
12059 #endif
12060 #ifdef _SC_THREAD_ATTR_STACKSIZE
12061 {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE},
12062 #endif
12063 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
12064 {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
12065 #endif
12066 #ifdef _SC_THREAD_KEYS_MAX
12067 {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
12068 #endif
12069 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
12070 {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING},
12071 #endif
12072 #ifdef _SC_THREAD_PRIO_INHERIT
12073 {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT},
12074 #endif
12075 #ifdef _SC_THREAD_PRIO_PROTECT
12076 {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT},
12077 #endif
12078 #ifdef _SC_THREAD_PROCESS_SHARED
12079 {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED},
12080 #endif
12081 #ifdef _SC_THREAD_SAFE_FUNCTIONS
12082 {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS},
12083 #endif
12084 #ifdef _SC_THREAD_STACK_MIN
12085 {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
12086 #endif
12087 #ifdef _SC_THREAD_THREADS_MAX
12088 {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
12089 #endif
12090 #ifdef _SC_TIMERS
12091 {"SC_TIMERS", _SC_TIMERS},
12092 #endif
12093 #ifdef _SC_TIMER_MAX
12094 {"SC_TIMER_MAX", _SC_TIMER_MAX},
12095 #endif
12096 #ifdef _SC_TTY_NAME_MAX
12097 {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
12098 #endif
12099 #ifdef _SC_TZNAME_MAX
12100 {"SC_TZNAME_MAX", _SC_TZNAME_MAX},
12101 #endif
12102 #ifdef _SC_T_IOV_MAX
12103 {"SC_T_IOV_MAX", _SC_T_IOV_MAX},
12104 #endif
12105 #ifdef _SC_UCHAR_MAX
12106 {"SC_UCHAR_MAX", _SC_UCHAR_MAX},
12107 #endif
12108 #ifdef _SC_UINT_MAX
12109 {"SC_UINT_MAX", _SC_UINT_MAX},
12110 #endif
12111 #ifdef _SC_UIO_MAXIOV
12112 {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV},
12113 #endif
12114 #ifdef _SC_ULONG_MAX
12115 {"SC_ULONG_MAX", _SC_ULONG_MAX},
12116 #endif
12117 #ifdef _SC_USHRT_MAX
12118 {"SC_USHRT_MAX", _SC_USHRT_MAX},
12119 #endif
12120 #ifdef _SC_VERSION
12121 {"SC_VERSION", _SC_VERSION},
12122 #endif
12123 #ifdef _SC_WORD_BIT
12124 {"SC_WORD_BIT", _SC_WORD_BIT},
12125 #endif
12126 #ifdef _SC_XBS5_ILP32_OFF32
12127 {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32},
12128 #endif
12129 #ifdef _SC_XBS5_ILP32_OFFBIG
12130 {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG},
12131 #endif
12132 #ifdef _SC_XBS5_LP64_OFF64
12133 {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64},
12134 #endif
12135 #ifdef _SC_XBS5_LPBIG_OFFBIG
12136 {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG},
12137 #endif
12138 #ifdef _SC_XOPEN_CRYPT
12139 {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT},
12140 #endif
12141 #ifdef _SC_XOPEN_ENH_I18N
12142 {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N},
12143 #endif
12144 #ifdef _SC_XOPEN_LEGACY
12145 {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
12146 #endif
12147 #ifdef _SC_XOPEN_REALTIME
12148 {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME},
12149 #endif
12150 #ifdef _SC_XOPEN_REALTIME_THREADS
12151 {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS},
12152 #endif
12153 #ifdef _SC_XOPEN_SHM
12154 {"SC_XOPEN_SHM", _SC_XOPEN_SHM},
12155 #endif
12156 #ifdef _SC_XOPEN_UNIX
12157 {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX},
12158 #endif
12159 #ifdef _SC_XOPEN_VERSION
12160 {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION},
12161 #endif
12162 #ifdef _SC_XOPEN_XCU_VERSION
12163 {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION},
12164 #endif
12165 #ifdef _SC_XOPEN_XPG2
12166 {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2},
12167 #endif
12168 #ifdef _SC_XOPEN_XPG3
12169 {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3},
12170 #endif
12171 #ifdef _SC_XOPEN_XPG4
12172 {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4},
12173 #endif
12174 };
12175
12176 static int
conv_sysconf_confname(PyObject * arg,int * valuep)12177 conv_sysconf_confname(PyObject *arg, int *valuep)
12178 {
12179 return conv_confname(arg, valuep, posix_constants_sysconf,
12180 sizeof(posix_constants_sysconf)
12181 / sizeof(struct constdef));
12182 }
12183
12184
12185 /*[clinic input]
12186 os.sysconf -> long
12187 name: sysconf_confname
12188 /
12189
12190 Return an integer-valued system configuration variable.
12191 [clinic start generated code]*/
12192
12193 static long
os_sysconf_impl(PyObject * module,int name)12194 os_sysconf_impl(PyObject *module, int name)
12195 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
12196 {
12197 long value;
12198
12199 errno = 0;
12200 value = sysconf(name);
12201 if (value == -1 && errno != 0)
12202 posix_error();
12203 return value;
12204 }
12205 #endif /* HAVE_SYSCONF */
12206
12207
12208 /* This code is used to ensure that the tables of configuration value names
12209 * are in sorted order as required by conv_confname(), and also to build
12210 * the exported dictionaries that are used to publish information about the
12211 * names available on the host platform.
12212 *
12213 * Sorting the table at runtime ensures that the table is properly ordered
12214 * when used, even for platforms we're not able to test on. It also makes
12215 * it easier to add additional entries to the tables.
12216 */
12217
12218 static int
cmp_constdefs(const void * v1,const void * v2)12219 cmp_constdefs(const void *v1, const void *v2)
12220 {
12221 const struct constdef *c1 =
12222 (const struct constdef *) v1;
12223 const struct constdef *c2 =
12224 (const struct constdef *) v2;
12225
12226 return strcmp(c1->name, c2->name);
12227 }
12228
12229 static int
setup_confname_table(struct constdef * table,size_t tablesize,const char * tablename,PyObject * module)12230 setup_confname_table(struct constdef *table, size_t tablesize,
12231 const char *tablename, PyObject *module)
12232 {
12233 PyObject *d = NULL;
12234 size_t i;
12235
12236 qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
12237 d = PyDict_New();
12238 if (d == NULL)
12239 return -1;
12240
12241 for (i=0; i < tablesize; ++i) {
12242 PyObject *o = PyLong_FromLong(table[i].value);
12243 if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
12244 Py_XDECREF(o);
12245 Py_DECREF(d);
12246 return -1;
12247 }
12248 Py_DECREF(o);
12249 }
12250 return PyModule_AddObject(module, tablename, d);
12251 }
12252
12253 /* Return -1 on failure, 0 on success. */
12254 static int
setup_confname_tables(PyObject * module)12255 setup_confname_tables(PyObject *module)
12256 {
12257 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12258 if (setup_confname_table(posix_constants_pathconf,
12259 sizeof(posix_constants_pathconf)
12260 / sizeof(struct constdef),
12261 "pathconf_names", module))
12262 return -1;
12263 #endif
12264 #ifdef HAVE_CONFSTR
12265 if (setup_confname_table(posix_constants_confstr,
12266 sizeof(posix_constants_confstr)
12267 / sizeof(struct constdef),
12268 "confstr_names", module))
12269 return -1;
12270 #endif
12271 #ifdef HAVE_SYSCONF
12272 if (setup_confname_table(posix_constants_sysconf,
12273 sizeof(posix_constants_sysconf)
12274 / sizeof(struct constdef),
12275 "sysconf_names", module))
12276 return -1;
12277 #endif
12278 return 0;
12279 }
12280
12281
12282 /*[clinic input]
12283 os.abort
12284
12285 Abort the interpreter immediately.
12286
12287 This function 'dumps core' or otherwise fails in the hardest way possible
12288 on the hosting operating system. This function never returns.
12289 [clinic start generated code]*/
12290
12291 static PyObject *
os_abort_impl(PyObject * module)12292 os_abort_impl(PyObject *module)
12293 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
12294 {
12295 abort();
12296 /*NOTREACHED*/
12297 #ifndef __clang__
12298 /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
12299 GCC emits a warning without "return NULL;" (compiler bug?), but Clang
12300 is smarter and emits a warning on the return. */
12301 Py_FatalError("abort() called from Python code didn't abort!");
12302 return NULL;
12303 #endif
12304 }
12305
12306 #ifdef MS_WINDOWS
12307 /* Grab ShellExecute dynamically from shell32 */
12308 static int has_ShellExecute = -1;
12309 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
12310 LPCWSTR, INT);
12311 static int
check_ShellExecute()12312 check_ShellExecute()
12313 {
12314 HINSTANCE hShell32;
12315
12316 /* only recheck */
12317 if (-1 == has_ShellExecute) {
12318 Py_BEGIN_ALLOW_THREADS
12319 /* Security note: this call is not vulnerable to "DLL hijacking".
12320 SHELL32 is part of "KnownDLLs" and so Windows always load
12321 the system SHELL32.DLL, even if there is another SHELL32.DLL
12322 in the DLL search path. */
12323 hShell32 = LoadLibraryW(L"SHELL32");
12324 if (hShell32) {
12325 *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
12326 "ShellExecuteW");
12327 has_ShellExecute = Py_ShellExecuteW != NULL;
12328 } else {
12329 has_ShellExecute = 0;
12330 }
12331 Py_END_ALLOW_THREADS
12332 }
12333 return has_ShellExecute;
12334 }
12335
12336
12337 /*[clinic input]
12338 os.startfile
12339 filepath: path_t
12340 operation: Py_UNICODE = NULL
12341
12342 Start a file with its associated application.
12343
12344 When "operation" is not specified or "open", this acts like
12345 double-clicking the file in Explorer, or giving the file name as an
12346 argument to the DOS "start" command: the file is opened with whatever
12347 application (if any) its extension is associated.
12348 When another "operation" is given, it specifies what should be done with
12349 the file. A typical operation is "print".
12350
12351 startfile returns as soon as the associated application is launched.
12352 There is no option to wait for the application to close, and no way
12353 to retrieve the application's exit status.
12354
12355 The filepath is relative to the current directory. If you want to use
12356 an absolute path, make sure the first character is not a slash ("/");
12357 the underlying Win32 ShellExecute function doesn't work if it is.
12358 [clinic start generated code]*/
12359
12360 static PyObject *
os_startfile_impl(PyObject * module,path_t * filepath,const Py_UNICODE * operation)12361 os_startfile_impl(PyObject *module, path_t *filepath,
12362 const Py_UNICODE *operation)
12363 /*[clinic end generated code: output=66dc311c94d50797 input=c940888a5390f039]*/
12364 {
12365 HINSTANCE rc;
12366
12367 if(!check_ShellExecute()) {
12368 /* If the OS doesn't have ShellExecute, return a
12369 NotImplementedError. */
12370 return PyErr_Format(PyExc_NotImplementedError,
12371 "startfile not available on this platform");
12372 }
12373
12374 if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
12375 return NULL;
12376 }
12377
12378 Py_BEGIN_ALLOW_THREADS
12379 rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
12380 NULL, NULL, SW_SHOWNORMAL);
12381 Py_END_ALLOW_THREADS
12382
12383 if (rc <= (HINSTANCE)32) {
12384 win32_error_object("startfile", filepath->object);
12385 return NULL;
12386 }
12387 Py_RETURN_NONE;
12388 }
12389 #endif /* MS_WINDOWS */
12390
12391
12392 #ifdef HAVE_GETLOADAVG
12393 /*[clinic input]
12394 os.getloadavg
12395
12396 Return average recent system load information.
12397
12398 Return the number of processes in the system run queue averaged over
12399 the last 1, 5, and 15 minutes as a tuple of three floats.
12400 Raises OSError if the load average was unobtainable.
12401 [clinic start generated code]*/
12402
12403 static PyObject *
os_getloadavg_impl(PyObject * module)12404 os_getloadavg_impl(PyObject *module)
12405 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
12406 {
12407 double loadavg[3];
12408 if (getloadavg(loadavg, 3)!=3) {
12409 PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
12410 return NULL;
12411 } else
12412 return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
12413 }
12414 #endif /* HAVE_GETLOADAVG */
12415
12416
12417 /*[clinic input]
12418 os.device_encoding
12419 fd: int
12420
12421 Return a string describing the encoding of a terminal's file descriptor.
12422
12423 The file descriptor must be attached to a terminal.
12424 If the device is not a terminal, return None.
12425 [clinic start generated code]*/
12426
12427 static PyObject *
os_device_encoding_impl(PyObject * module,int fd)12428 os_device_encoding_impl(PyObject *module, int fd)
12429 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
12430 {
12431 return _Py_device_encoding(fd);
12432 }
12433
12434
12435 #ifdef HAVE_SETRESUID
12436 /*[clinic input]
12437 os.setresuid
12438
12439 ruid: uid_t
12440 euid: uid_t
12441 suid: uid_t
12442 /
12443
12444 Set the current process's real, effective, and saved user ids.
12445 [clinic start generated code]*/
12446
12447 static PyObject *
os_setresuid_impl(PyObject * module,uid_t ruid,uid_t euid,uid_t suid)12448 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
12449 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
12450 {
12451 if (setresuid(ruid, euid, suid) < 0)
12452 return posix_error();
12453 Py_RETURN_NONE;
12454 }
12455 #endif /* HAVE_SETRESUID */
12456
12457
12458 #ifdef HAVE_SETRESGID
12459 /*[clinic input]
12460 os.setresgid
12461
12462 rgid: gid_t
12463 egid: gid_t
12464 sgid: gid_t
12465 /
12466
12467 Set the current process's real, effective, and saved group ids.
12468 [clinic start generated code]*/
12469
12470 static PyObject *
os_setresgid_impl(PyObject * module,gid_t rgid,gid_t egid,gid_t sgid)12471 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
12472 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
12473 {
12474 if (setresgid(rgid, egid, sgid) < 0)
12475 return posix_error();
12476 Py_RETURN_NONE;
12477 }
12478 #endif /* HAVE_SETRESGID */
12479
12480
12481 #ifdef HAVE_GETRESUID
12482 /*[clinic input]
12483 os.getresuid
12484
12485 Return a tuple of the current process's real, effective, and saved user ids.
12486 [clinic start generated code]*/
12487
12488 static PyObject *
os_getresuid_impl(PyObject * module)12489 os_getresuid_impl(PyObject *module)
12490 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12491 {
12492 uid_t ruid, euid, suid;
12493 if (getresuid(&ruid, &euid, &suid) < 0)
12494 return posix_error();
12495 return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12496 _PyLong_FromUid(euid),
12497 _PyLong_FromUid(suid));
12498 }
12499 #endif /* HAVE_GETRESUID */
12500
12501
12502 #ifdef HAVE_GETRESGID
12503 /*[clinic input]
12504 os.getresgid
12505
12506 Return a tuple of the current process's real, effective, and saved group ids.
12507 [clinic start generated code]*/
12508
12509 static PyObject *
os_getresgid_impl(PyObject * module)12510 os_getresgid_impl(PyObject *module)
12511 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12512 {
12513 gid_t rgid, egid, sgid;
12514 if (getresgid(&rgid, &egid, &sgid) < 0)
12515 return posix_error();
12516 return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12517 _PyLong_FromGid(egid),
12518 _PyLong_FromGid(sgid));
12519 }
12520 #endif /* HAVE_GETRESGID */
12521
12522
12523 #ifdef USE_XATTRS
12524 /*[clinic input]
12525 os.getxattr
12526
12527 path: path_t(allow_fd=True)
12528 attribute: path_t
12529 *
12530 follow_symlinks: bool = True
12531
12532 Return the value of extended attribute attribute on path.
12533
12534 path may be either a string, a path-like object, or an open file descriptor.
12535 If follow_symlinks is False, and the last element of the path is a symbolic
12536 link, getxattr will examine the symbolic link itself instead of the file
12537 the link points to.
12538
12539 [clinic start generated code]*/
12540
12541 static PyObject *
os_getxattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12542 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12543 int follow_symlinks)
12544 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12545 {
12546 Py_ssize_t i;
12547 PyObject *buffer = NULL;
12548
12549 if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12550 return NULL;
12551
12552 if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12553 return NULL;
12554 }
12555
12556 for (i = 0; ; i++) {
12557 void *ptr;
12558 ssize_t result;
12559 static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12560 Py_ssize_t buffer_size = buffer_sizes[i];
12561 if (!buffer_size) {
12562 path_error(path);
12563 return NULL;
12564 }
12565 buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12566 if (!buffer)
12567 return NULL;
12568 ptr = PyBytes_AS_STRING(buffer);
12569
12570 Py_BEGIN_ALLOW_THREADS;
12571 if (path->fd >= 0)
12572 result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12573 else if (follow_symlinks)
12574 result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12575 else
12576 result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12577 Py_END_ALLOW_THREADS;
12578
12579 if (result < 0) {
12580 Py_DECREF(buffer);
12581 if (errno == ERANGE)
12582 continue;
12583 path_error(path);
12584 return NULL;
12585 }
12586
12587 if (result != buffer_size) {
12588 /* Can only shrink. */
12589 _PyBytes_Resize(&buffer, result);
12590 }
12591 break;
12592 }
12593
12594 return buffer;
12595 }
12596
12597
12598 /*[clinic input]
12599 os.setxattr
12600
12601 path: path_t(allow_fd=True)
12602 attribute: path_t
12603 value: Py_buffer
12604 flags: int = 0
12605 *
12606 follow_symlinks: bool = True
12607
12608 Set extended attribute attribute on path to value.
12609
12610 path may be either a string, a path-like object, or an open file descriptor.
12611 If follow_symlinks is False, and the last element of the path is a symbolic
12612 link, setxattr will modify the symbolic link itself instead of the file
12613 the link points to.
12614
12615 [clinic start generated code]*/
12616
12617 static PyObject *
os_setxattr_impl(PyObject * module,path_t * path,path_t * attribute,Py_buffer * value,int flags,int follow_symlinks)12618 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12619 Py_buffer *value, int flags, int follow_symlinks)
12620 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12621 {
12622 ssize_t result;
12623
12624 if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12625 return NULL;
12626
12627 if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12628 value->buf, value->len, flags) < 0) {
12629 return NULL;
12630 }
12631
12632 Py_BEGIN_ALLOW_THREADS;
12633 if (path->fd > -1)
12634 result = fsetxattr(path->fd, attribute->narrow,
12635 value->buf, value->len, flags);
12636 else if (follow_symlinks)
12637 result = setxattr(path->narrow, attribute->narrow,
12638 value->buf, value->len, flags);
12639 else
12640 result = lsetxattr(path->narrow, attribute->narrow,
12641 value->buf, value->len, flags);
12642 Py_END_ALLOW_THREADS;
12643
12644 if (result) {
12645 path_error(path);
12646 return NULL;
12647 }
12648
12649 Py_RETURN_NONE;
12650 }
12651
12652
12653 /*[clinic input]
12654 os.removexattr
12655
12656 path: path_t(allow_fd=True)
12657 attribute: path_t
12658 *
12659 follow_symlinks: bool = True
12660
12661 Remove extended attribute attribute on path.
12662
12663 path may be either a string, a path-like object, or an open file descriptor.
12664 If follow_symlinks is False, and the last element of the path is a symbolic
12665 link, removexattr will modify the symbolic link itself instead of the file
12666 the link points to.
12667
12668 [clinic start generated code]*/
12669
12670 static PyObject *
os_removexattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12671 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
12672 int follow_symlinks)
12673 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
12674 {
12675 ssize_t result;
12676
12677 if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
12678 return NULL;
12679
12680 if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
12681 return NULL;
12682 }
12683
12684 Py_BEGIN_ALLOW_THREADS;
12685 if (path->fd > -1)
12686 result = fremovexattr(path->fd, attribute->narrow);
12687 else if (follow_symlinks)
12688 result = removexattr(path->narrow, attribute->narrow);
12689 else
12690 result = lremovexattr(path->narrow, attribute->narrow);
12691 Py_END_ALLOW_THREADS;
12692
12693 if (result) {
12694 return path_error(path);
12695 }
12696
12697 Py_RETURN_NONE;
12698 }
12699
12700
12701 /*[clinic input]
12702 os.listxattr
12703
12704 path: path_t(allow_fd=True, nullable=True) = None
12705 *
12706 follow_symlinks: bool = True
12707
12708 Return a list of extended attributes on path.
12709
12710 path may be either None, a string, a path-like object, or an open file descriptor.
12711 if path is None, listxattr will examine the current directory.
12712 If follow_symlinks is False, and the last element of the path is a symbolic
12713 link, listxattr will examine the symbolic link itself instead of the file
12714 the link points to.
12715 [clinic start generated code]*/
12716
12717 static PyObject *
os_listxattr_impl(PyObject * module,path_t * path,int follow_symlinks)12718 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
12719 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
12720 {
12721 Py_ssize_t i;
12722 PyObject *result = NULL;
12723 const char *name;
12724 char *buffer = NULL;
12725
12726 if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
12727 goto exit;
12728
12729 if (PySys_Audit("os.listxattr", "(O)",
12730 path->object ? path->object : Py_None) < 0) {
12731 return NULL;
12732 }
12733
12734 name = path->narrow ? path->narrow : ".";
12735
12736 for (i = 0; ; i++) {
12737 const char *start, *trace, *end;
12738 ssize_t length;
12739 static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
12740 Py_ssize_t buffer_size = buffer_sizes[i];
12741 if (!buffer_size) {
12742 /* ERANGE */
12743 path_error(path);
12744 break;
12745 }
12746 buffer = PyMem_MALLOC(buffer_size);
12747 if (!buffer) {
12748 PyErr_NoMemory();
12749 break;
12750 }
12751
12752 Py_BEGIN_ALLOW_THREADS;
12753 if (path->fd > -1)
12754 length = flistxattr(path->fd, buffer, buffer_size);
12755 else if (follow_symlinks)
12756 length = listxattr(name, buffer, buffer_size);
12757 else
12758 length = llistxattr(name, buffer, buffer_size);
12759 Py_END_ALLOW_THREADS;
12760
12761 if (length < 0) {
12762 if (errno == ERANGE) {
12763 PyMem_FREE(buffer);
12764 buffer = NULL;
12765 continue;
12766 }
12767 path_error(path);
12768 break;
12769 }
12770
12771 result = PyList_New(0);
12772 if (!result) {
12773 goto exit;
12774 }
12775
12776 end = buffer + length;
12777 for (trace = start = buffer; trace != end; trace++) {
12778 if (!*trace) {
12779 int error;
12780 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
12781 trace - start);
12782 if (!attribute) {
12783 Py_DECREF(result);
12784 result = NULL;
12785 goto exit;
12786 }
12787 error = PyList_Append(result, attribute);
12788 Py_DECREF(attribute);
12789 if (error) {
12790 Py_DECREF(result);
12791 result = NULL;
12792 goto exit;
12793 }
12794 start = trace + 1;
12795 }
12796 }
12797 break;
12798 }
12799 exit:
12800 if (buffer)
12801 PyMem_FREE(buffer);
12802 return result;
12803 }
12804 #endif /* USE_XATTRS */
12805
12806
12807 /*[clinic input]
12808 os.urandom
12809
12810 size: Py_ssize_t
12811 /
12812
12813 Return a bytes object containing random bytes suitable for cryptographic use.
12814 [clinic start generated code]*/
12815
12816 static PyObject *
os_urandom_impl(PyObject * module,Py_ssize_t size)12817 os_urandom_impl(PyObject *module, Py_ssize_t size)
12818 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
12819 {
12820 PyObject *bytes;
12821 int result;
12822
12823 if (size < 0)
12824 return PyErr_Format(PyExc_ValueError,
12825 "negative argument not allowed");
12826 bytes = PyBytes_FromStringAndSize(NULL, size);
12827 if (bytes == NULL)
12828 return NULL;
12829
12830 result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
12831 if (result == -1) {
12832 Py_DECREF(bytes);
12833 return NULL;
12834 }
12835 return bytes;
12836 }
12837
12838 #ifdef HAVE_MEMFD_CREATE
12839 /*[clinic input]
12840 os.memfd_create
12841
12842 name: FSConverter
12843 flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
12844
12845 [clinic start generated code]*/
12846
12847 static PyObject *
os_memfd_create_impl(PyObject * module,PyObject * name,unsigned int flags)12848 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
12849 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
12850 {
12851 int fd;
12852 const char *bytes = PyBytes_AS_STRING(name);
12853 Py_BEGIN_ALLOW_THREADS
12854 fd = memfd_create(bytes, flags);
12855 Py_END_ALLOW_THREADS
12856 if (fd == -1) {
12857 return PyErr_SetFromErrno(PyExc_OSError);
12858 }
12859 return PyLong_FromLong(fd);
12860 }
12861 #endif
12862
12863 /* Terminal size querying */
12864
12865 PyDoc_STRVAR(TerminalSize_docstring,
12866 "A tuple of (columns, lines) for holding terminal window size");
12867
12868 static PyStructSequence_Field TerminalSize_fields[] = {
12869 {"columns", "width of the terminal window in characters"},
12870 {"lines", "height of the terminal window in characters"},
12871 {NULL, NULL}
12872 };
12873
12874 static PyStructSequence_Desc TerminalSize_desc = {
12875 "os.terminal_size",
12876 TerminalSize_docstring,
12877 TerminalSize_fields,
12878 2,
12879 };
12880
12881 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
12882 /*[clinic input]
12883 os.get_terminal_size
12884
12885 fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
12886 /
12887
12888 Return the size of the terminal window as (columns, lines).
12889
12890 The optional argument fd (default standard output) specifies
12891 which file descriptor should be queried.
12892
12893 If the file descriptor is not connected to a terminal, an OSError
12894 is thrown.
12895
12896 This function will only be defined if an implementation is
12897 available for this system.
12898
12899 shutil.get_terminal_size is the high-level function which should
12900 normally be used, os.get_terminal_size is the low-level implementation.
12901 [clinic start generated code]*/
12902
12903 static PyObject *
os_get_terminal_size_impl(PyObject * module,int fd)12904 os_get_terminal_size_impl(PyObject *module, int fd)
12905 /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
12906 {
12907 int columns, lines;
12908 PyObject *termsize;
12909
12910 /* Under some conditions stdout may not be connected and
12911 * fileno(stdout) may point to an invalid file descriptor. For example
12912 * GUI apps don't have valid standard streams by default.
12913 *
12914 * If this happens, and the optional fd argument is not present,
12915 * the ioctl below will fail returning EBADF. This is what we want.
12916 */
12917
12918 #ifdef TERMSIZE_USE_IOCTL
12919 {
12920 struct winsize w;
12921 if (ioctl(fd, TIOCGWINSZ, &w))
12922 return PyErr_SetFromErrno(PyExc_OSError);
12923 columns = w.ws_col;
12924 lines = w.ws_row;
12925 }
12926 #endif /* TERMSIZE_USE_IOCTL */
12927
12928 #ifdef TERMSIZE_USE_CONIO
12929 {
12930 DWORD nhandle;
12931 HANDLE handle;
12932 CONSOLE_SCREEN_BUFFER_INFO csbi;
12933 switch (fd) {
12934 case 0: nhandle = STD_INPUT_HANDLE;
12935 break;
12936 case 1: nhandle = STD_OUTPUT_HANDLE;
12937 break;
12938 case 2: nhandle = STD_ERROR_HANDLE;
12939 break;
12940 default:
12941 return PyErr_Format(PyExc_ValueError, "bad file descriptor");
12942 }
12943 handle = GetStdHandle(nhandle);
12944 if (handle == NULL)
12945 return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
12946 if (handle == INVALID_HANDLE_VALUE)
12947 return PyErr_SetFromWindowsErr(0);
12948
12949 if (!GetConsoleScreenBufferInfo(handle, &csbi))
12950 return PyErr_SetFromWindowsErr(0);
12951
12952 columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
12953 lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
12954 }
12955 #endif /* TERMSIZE_USE_CONIO */
12956
12957 PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
12958 termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
12959 if (termsize == NULL)
12960 return NULL;
12961 PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
12962 PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
12963 if (PyErr_Occurred()) {
12964 Py_DECREF(termsize);
12965 return NULL;
12966 }
12967 return termsize;
12968 }
12969 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
12970
12971
12972 /*[clinic input]
12973 os.cpu_count
12974
12975 Return the number of CPUs in the system; return None if indeterminable.
12976
12977 This number is not equivalent to the number of CPUs the current process can
12978 use. The number of usable CPUs can be obtained with
12979 ``len(os.sched_getaffinity(0))``
12980 [clinic start generated code]*/
12981
12982 static PyObject *
os_cpu_count_impl(PyObject * module)12983 os_cpu_count_impl(PyObject *module)
12984 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
12985 {
12986 int ncpu = 0;
12987 #ifdef MS_WINDOWS
12988 ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
12989 #elif defined(__hpux)
12990 ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
12991 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
12992 ncpu = sysconf(_SC_NPROCESSORS_ONLN);
12993 #elif defined(__DragonFly__) || \
12994 defined(__OpenBSD__) || \
12995 defined(__FreeBSD__) || \
12996 defined(__NetBSD__) || \
12997 defined(__APPLE__)
12998 int mib[2];
12999 size_t len = sizeof(ncpu);
13000 mib[0] = CTL_HW;
13001 mib[1] = HW_NCPU;
13002 if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
13003 ncpu = 0;
13004 #endif
13005 if (ncpu >= 1)
13006 return PyLong_FromLong(ncpu);
13007 else
13008 Py_RETURN_NONE;
13009 }
13010
13011
13012 /*[clinic input]
13013 os.get_inheritable -> bool
13014
13015 fd: int
13016 /
13017
13018 Get the close-on-exe flag of the specified file descriptor.
13019 [clinic start generated code]*/
13020
13021 static int
os_get_inheritable_impl(PyObject * module,int fd)13022 os_get_inheritable_impl(PyObject *module, int fd)
13023 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
13024 {
13025 int return_value;
13026 _Py_BEGIN_SUPPRESS_IPH
13027 return_value = _Py_get_inheritable(fd);
13028 _Py_END_SUPPRESS_IPH
13029 return return_value;
13030 }
13031
13032
13033 /*[clinic input]
13034 os.set_inheritable
13035 fd: int
13036 inheritable: int
13037 /
13038
13039 Set the inheritable flag of the specified file descriptor.
13040 [clinic start generated code]*/
13041
13042 static PyObject *
os_set_inheritable_impl(PyObject * module,int fd,int inheritable)13043 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
13044 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
13045 {
13046 int result;
13047
13048 _Py_BEGIN_SUPPRESS_IPH
13049 result = _Py_set_inheritable(fd, inheritable, NULL);
13050 _Py_END_SUPPRESS_IPH
13051 if (result < 0)
13052 return NULL;
13053 Py_RETURN_NONE;
13054 }
13055
13056
13057 #ifdef MS_WINDOWS
13058 /*[clinic input]
13059 os.get_handle_inheritable -> bool
13060 handle: intptr_t
13061 /
13062
13063 Get the close-on-exe flag of the specified file descriptor.
13064 [clinic start generated code]*/
13065
13066 static int
os_get_handle_inheritable_impl(PyObject * module,intptr_t handle)13067 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
13068 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
13069 {
13070 DWORD flags;
13071
13072 if (!GetHandleInformation((HANDLE)handle, &flags)) {
13073 PyErr_SetFromWindowsErr(0);
13074 return -1;
13075 }
13076
13077 return flags & HANDLE_FLAG_INHERIT;
13078 }
13079
13080
13081 /*[clinic input]
13082 os.set_handle_inheritable
13083 handle: intptr_t
13084 inheritable: bool
13085 /
13086
13087 Set the inheritable flag of the specified handle.
13088 [clinic start generated code]*/
13089
13090 static PyObject *
os_set_handle_inheritable_impl(PyObject * module,intptr_t handle,int inheritable)13091 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
13092 int inheritable)
13093 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
13094 {
13095 DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
13096 if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
13097 PyErr_SetFromWindowsErr(0);
13098 return NULL;
13099 }
13100 Py_RETURN_NONE;
13101 }
13102 #endif /* MS_WINDOWS */
13103
13104 #ifndef MS_WINDOWS
13105 /*[clinic input]
13106 os.get_blocking -> bool
13107 fd: int
13108 /
13109
13110 Get the blocking mode of the file descriptor.
13111
13112 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
13113 [clinic start generated code]*/
13114
13115 static int
os_get_blocking_impl(PyObject * module,int fd)13116 os_get_blocking_impl(PyObject *module, int fd)
13117 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
13118 {
13119 int blocking;
13120
13121 _Py_BEGIN_SUPPRESS_IPH
13122 blocking = _Py_get_blocking(fd);
13123 _Py_END_SUPPRESS_IPH
13124 return blocking;
13125 }
13126
13127 /*[clinic input]
13128 os.set_blocking
13129 fd: int
13130 blocking: bool(accept={int})
13131 /
13132
13133 Set the blocking mode of the specified file descriptor.
13134
13135 Set the O_NONBLOCK flag if blocking is False,
13136 clear the O_NONBLOCK flag otherwise.
13137 [clinic start generated code]*/
13138
13139 static PyObject *
os_set_blocking_impl(PyObject * module,int fd,int blocking)13140 os_set_blocking_impl(PyObject *module, int fd, int blocking)
13141 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
13142 {
13143 int result;
13144
13145 _Py_BEGIN_SUPPRESS_IPH
13146 result = _Py_set_blocking(fd, blocking);
13147 _Py_END_SUPPRESS_IPH
13148 if (result < 0)
13149 return NULL;
13150 Py_RETURN_NONE;
13151 }
13152 #endif /* !MS_WINDOWS */
13153
13154
13155 /*[clinic input]
13156 class os.DirEntry "DirEntry *" "DirEntryType"
13157 [clinic start generated code]*/
13158 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
13159
13160 typedef struct {
13161 PyObject_HEAD
13162 PyObject *name;
13163 PyObject *path;
13164 PyObject *stat;
13165 PyObject *lstat;
13166 #ifdef MS_WINDOWS
13167 struct _Py_stat_struct win32_lstat;
13168 uint64_t win32_file_index;
13169 int got_file_index;
13170 #else /* POSIX */
13171 #ifdef HAVE_DIRENT_D_TYPE
13172 unsigned char d_type;
13173 #endif
13174 ino_t d_ino;
13175 int dir_fd;
13176 #endif
13177 } DirEntry;
13178
13179 static PyObject *
_disabled_new(PyTypeObject * type,PyObject * args,PyObject * kwargs)13180 _disabled_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
13181 {
13182 PyErr_Format(PyExc_TypeError,
13183 "cannot create '%.100s' instances", _PyType_Name(type));
13184 return NULL;
13185 }
13186
13187 static void
DirEntry_dealloc(DirEntry * entry)13188 DirEntry_dealloc(DirEntry *entry)
13189 {
13190 PyTypeObject *tp = Py_TYPE(entry);
13191 Py_XDECREF(entry->name);
13192 Py_XDECREF(entry->path);
13193 Py_XDECREF(entry->stat);
13194 Py_XDECREF(entry->lstat);
13195 freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13196 free_func(entry);
13197 Py_DECREF(tp);
13198 }
13199
13200 /* Forward reference */
13201 static int
13202 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13203 int follow_symlinks, unsigned short mode_bits);
13204
13205 /*[clinic input]
13206 os.DirEntry.is_symlink -> bool
13207 defining_class: defining_class
13208 /
13209
13210 Return True if the entry is a symbolic link; cached per entry.
13211 [clinic start generated code]*/
13212
13213 static int
os_DirEntry_is_symlink_impl(DirEntry * self,PyTypeObject * defining_class)13214 os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
13215 /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
13216 {
13217 #ifdef MS_WINDOWS
13218 return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13219 #elif defined(HAVE_DIRENT_D_TYPE)
13220 /* POSIX */
13221 if (self->d_type != DT_UNKNOWN)
13222 return self->d_type == DT_LNK;
13223 else
13224 return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13225 #else
13226 /* POSIX without d_type */
13227 return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13228 #endif
13229 }
13230
13231 static PyObject *
DirEntry_fetch_stat(PyObject * module,DirEntry * self,int follow_symlinks)13232 DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
13233 {
13234 int result;
13235 STRUCT_STAT st;
13236 PyObject *ub;
13237
13238 #ifdef MS_WINDOWS
13239 if (!PyUnicode_FSDecoder(self->path, &ub))
13240 return NULL;
13241 const wchar_t *path = PyUnicode_AsUnicode(ub);
13242 #else /* POSIX */
13243 if (!PyUnicode_FSConverter(self->path, &ub))
13244 return NULL;
13245 const char *path = PyBytes_AS_STRING(ub);
13246 if (self->dir_fd != DEFAULT_DIR_FD) {
13247 #ifdef HAVE_FSTATAT
13248 if (HAVE_FSTATAT_RUNTIME) {
13249 result = fstatat(self->dir_fd, path, &st,
13250 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
13251 } else
13252
13253 #endif /* HAVE_FSTATAT */
13254 {
13255 Py_DECREF(ub);
13256 PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
13257 return NULL;
13258 }
13259 }
13260 else
13261 #endif
13262 {
13263 if (follow_symlinks)
13264 result = STAT(path, &st);
13265 else
13266 result = LSTAT(path, &st);
13267 }
13268 Py_DECREF(ub);
13269
13270 if (result != 0)
13271 return path_object_error(self->path);
13272
13273 return _pystat_fromstructstat(module, &st);
13274 }
13275
13276 static PyObject *
DirEntry_get_lstat(PyTypeObject * defining_class,DirEntry * self)13277 DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
13278 {
13279 if (!self->lstat) {
13280 PyObject *module = PyType_GetModule(defining_class);
13281 #ifdef MS_WINDOWS
13282 self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
13283 #else /* POSIX */
13284 self->lstat = DirEntry_fetch_stat(module, self, 0);
13285 #endif
13286 }
13287 Py_XINCREF(self->lstat);
13288 return self->lstat;
13289 }
13290
13291 /*[clinic input]
13292 os.DirEntry.stat
13293 defining_class: defining_class
13294 /
13295 *
13296 follow_symlinks: bool = True
13297
13298 Return stat_result object for the entry; cached per entry.
13299 [clinic start generated code]*/
13300
13301 static PyObject *
os_DirEntry_stat_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13302 os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
13303 int follow_symlinks)
13304 /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
13305 {
13306 if (!follow_symlinks) {
13307 return DirEntry_get_lstat(defining_class, self);
13308 }
13309
13310 if (!self->stat) {
13311 int result = os_DirEntry_is_symlink_impl(self, defining_class);
13312 if (result == -1) {
13313 return NULL;
13314 }
13315 if (result) {
13316 PyObject *module = PyType_GetModule(defining_class);
13317 self->stat = DirEntry_fetch_stat(module, self, 1);
13318 }
13319 else {
13320 self->stat = DirEntry_get_lstat(defining_class, self);
13321 }
13322 }
13323
13324 Py_XINCREF(self->stat);
13325 return self->stat;
13326 }
13327
13328 /* Set exception and return -1 on error, 0 for False, 1 for True */
13329 static int
DirEntry_test_mode(PyTypeObject * defining_class,DirEntry * self,int follow_symlinks,unsigned short mode_bits)13330 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13331 int follow_symlinks, unsigned short mode_bits)
13332 {
13333 PyObject *stat = NULL;
13334 PyObject *st_mode = NULL;
13335 long mode;
13336 int result;
13337 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13338 int is_symlink;
13339 int need_stat;
13340 #endif
13341 #ifdef MS_WINDOWS
13342 unsigned long dir_bits;
13343 #endif
13344
13345 #ifdef MS_WINDOWS
13346 is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13347 need_stat = follow_symlinks && is_symlink;
13348 #elif defined(HAVE_DIRENT_D_TYPE)
13349 is_symlink = self->d_type == DT_LNK;
13350 need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
13351 #endif
13352
13353 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13354 if (need_stat) {
13355 #endif
13356 stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
13357 if (!stat) {
13358 if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
13359 /* If file doesn't exist (anymore), then return False
13360 (i.e., say it's not a file/directory) */
13361 PyErr_Clear();
13362 return 0;
13363 }
13364 goto error;
13365 }
13366 _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
13367 st_mode = PyObject_GetAttr(stat, state->st_mode);
13368 if (!st_mode)
13369 goto error;
13370
13371 mode = PyLong_AsLong(st_mode);
13372 if (mode == -1 && PyErr_Occurred())
13373 goto error;
13374 Py_CLEAR(st_mode);
13375 Py_CLEAR(stat);
13376 result = (mode & S_IFMT) == mode_bits;
13377 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13378 }
13379 else if (is_symlink) {
13380 assert(mode_bits != S_IFLNK);
13381 result = 0;
13382 }
13383 else {
13384 assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
13385 #ifdef MS_WINDOWS
13386 dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
13387 if (mode_bits == S_IFDIR)
13388 result = dir_bits != 0;
13389 else
13390 result = dir_bits == 0;
13391 #else /* POSIX */
13392 if (mode_bits == S_IFDIR)
13393 result = self->d_type == DT_DIR;
13394 else
13395 result = self->d_type == DT_REG;
13396 #endif
13397 }
13398 #endif
13399
13400 return result;
13401
13402 error:
13403 Py_XDECREF(st_mode);
13404 Py_XDECREF(stat);
13405 return -1;
13406 }
13407
13408 /*[clinic input]
13409 os.DirEntry.is_dir -> bool
13410 defining_class: defining_class
13411 /
13412 *
13413 follow_symlinks: bool = True
13414
13415 Return True if the entry is a directory; cached per entry.
13416 [clinic start generated code]*/
13417
13418 static int
os_DirEntry_is_dir_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13419 os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
13420 int follow_symlinks)
13421 /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
13422 {
13423 return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
13424 }
13425
13426 /*[clinic input]
13427 os.DirEntry.is_file -> bool
13428 defining_class: defining_class
13429 /
13430 *
13431 follow_symlinks: bool = True
13432
13433 Return True if the entry is a file; cached per entry.
13434 [clinic start generated code]*/
13435
13436 static int
os_DirEntry_is_file_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13437 os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
13438 int follow_symlinks)
13439 /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
13440 {
13441 return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
13442 }
13443
13444 /*[clinic input]
13445 os.DirEntry.inode
13446
13447 Return inode of the entry; cached per entry.
13448 [clinic start generated code]*/
13449
13450 static PyObject *
os_DirEntry_inode_impl(DirEntry * self)13451 os_DirEntry_inode_impl(DirEntry *self)
13452 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
13453 {
13454 #ifdef MS_WINDOWS
13455 if (!self->got_file_index) {
13456 PyObject *unicode;
13457 const wchar_t *path;
13458 STRUCT_STAT stat;
13459 int result;
13460
13461 if (!PyUnicode_FSDecoder(self->path, &unicode))
13462 return NULL;
13463 path = PyUnicode_AsUnicode(unicode);
13464 result = LSTAT(path, &stat);
13465 Py_DECREF(unicode);
13466
13467 if (result != 0)
13468 return path_object_error(self->path);
13469
13470 self->win32_file_index = stat.st_ino;
13471 self->got_file_index = 1;
13472 }
13473 Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->win32_file_index));
13474 return PyLong_FromUnsignedLongLong(self->win32_file_index);
13475 #else /* POSIX */
13476 Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->d_ino));
13477 return PyLong_FromUnsignedLongLong(self->d_ino);
13478 #endif
13479 }
13480
13481 static PyObject *
DirEntry_repr(DirEntry * self)13482 DirEntry_repr(DirEntry *self)
13483 {
13484 return PyUnicode_FromFormat("<DirEntry %R>", self->name);
13485 }
13486
13487 /*[clinic input]
13488 os.DirEntry.__fspath__
13489
13490 Returns the path for the entry.
13491 [clinic start generated code]*/
13492
13493 static PyObject *
os_DirEntry___fspath___impl(DirEntry * self)13494 os_DirEntry___fspath___impl(DirEntry *self)
13495 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
13496 {
13497 Py_INCREF(self->path);
13498 return self->path;
13499 }
13500
13501 static PyMemberDef DirEntry_members[] = {
13502 {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
13503 "the entry's base filename, relative to scandir() \"path\" argument"},
13504 {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
13505 "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
13506 {NULL}
13507 };
13508
13509 #include "clinic/posixmodule.c.h"
13510
13511 static PyMethodDef DirEntry_methods[] = {
13512 OS_DIRENTRY_IS_DIR_METHODDEF
13513 OS_DIRENTRY_IS_FILE_METHODDEF
13514 OS_DIRENTRY_IS_SYMLINK_METHODDEF
13515 OS_DIRENTRY_STAT_METHODDEF
13516 OS_DIRENTRY_INODE_METHODDEF
13517 OS_DIRENTRY___FSPATH___METHODDEF
13518 {"__class_getitem__", (PyCFunction)Py_GenericAlias,
13519 METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
13520 {NULL}
13521 };
13522
13523 static PyType_Slot DirEntryType_slots[] = {
13524 {Py_tp_new, _disabled_new},
13525 {Py_tp_dealloc, DirEntry_dealloc},
13526 {Py_tp_repr, DirEntry_repr},
13527 {Py_tp_methods, DirEntry_methods},
13528 {Py_tp_members, DirEntry_members},
13529 {0, 0},
13530 };
13531
13532 static PyType_Spec DirEntryType_spec = {
13533 MODNAME ".DirEntry",
13534 sizeof(DirEntry),
13535 0,
13536 Py_TPFLAGS_DEFAULT,
13537 DirEntryType_slots
13538 };
13539
13540
13541 #ifdef MS_WINDOWS
13542
13543 static wchar_t *
join_path_filenameW(const wchar_t * path_wide,const wchar_t * filename)13544 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
13545 {
13546 Py_ssize_t path_len;
13547 Py_ssize_t size;
13548 wchar_t *result;
13549 wchar_t ch;
13550
13551 if (!path_wide) { /* Default arg: "." */
13552 path_wide = L".";
13553 path_len = 1;
13554 }
13555 else {
13556 path_len = wcslen(path_wide);
13557 }
13558
13559 /* The +1's are for the path separator and the NUL */
13560 size = path_len + 1 + wcslen(filename) + 1;
13561 result = PyMem_New(wchar_t, size);
13562 if (!result) {
13563 PyErr_NoMemory();
13564 return NULL;
13565 }
13566 wcscpy(result, path_wide);
13567 if (path_len > 0) {
13568 ch = result[path_len - 1];
13569 if (ch != SEP && ch != ALTSEP && ch != L':')
13570 result[path_len++] = SEP;
13571 wcscpy(result + path_len, filename);
13572 }
13573 return result;
13574 }
13575
13576 static PyObject *
DirEntry_from_find_data(PyObject * module,path_t * path,WIN32_FIND_DATAW * dataW)13577 DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
13578 {
13579 DirEntry *entry;
13580 BY_HANDLE_FILE_INFORMATION file_info;
13581 ULONG reparse_tag;
13582 wchar_t *joined_path;
13583
13584 PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13585 entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13586 if (!entry)
13587 return NULL;
13588 entry->name = NULL;
13589 entry->path = NULL;
13590 entry->stat = NULL;
13591 entry->lstat = NULL;
13592 entry->got_file_index = 0;
13593
13594 entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
13595 if (!entry->name)
13596 goto error;
13597 if (path->narrow) {
13598 Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
13599 if (!entry->name)
13600 goto error;
13601 }
13602
13603 joined_path = join_path_filenameW(path->wide, dataW->cFileName);
13604 if (!joined_path)
13605 goto error;
13606
13607 entry->path = PyUnicode_FromWideChar(joined_path, -1);
13608 PyMem_Free(joined_path);
13609 if (!entry->path)
13610 goto error;
13611 if (path->narrow) {
13612 Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
13613 if (!entry->path)
13614 goto error;
13615 }
13616
13617 find_data_to_file_info(dataW, &file_info, &reparse_tag);
13618 _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
13619
13620 return (PyObject *)entry;
13621
13622 error:
13623 Py_DECREF(entry);
13624 return NULL;
13625 }
13626
13627 #else /* POSIX */
13628
13629 static char *
join_path_filename(const char * path_narrow,const char * filename,Py_ssize_t filename_len)13630 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
13631 {
13632 Py_ssize_t path_len;
13633 Py_ssize_t size;
13634 char *result;
13635
13636 if (!path_narrow) { /* Default arg: "." */
13637 path_narrow = ".";
13638 path_len = 1;
13639 }
13640 else {
13641 path_len = strlen(path_narrow);
13642 }
13643
13644 if (filename_len == -1)
13645 filename_len = strlen(filename);
13646
13647 /* The +1's are for the path separator and the NUL */
13648 size = path_len + 1 + filename_len + 1;
13649 result = PyMem_New(char, size);
13650 if (!result) {
13651 PyErr_NoMemory();
13652 return NULL;
13653 }
13654 strcpy(result, path_narrow);
13655 if (path_len > 0 && result[path_len - 1] != '/')
13656 result[path_len++] = '/';
13657 strcpy(result + path_len, filename);
13658 return result;
13659 }
13660
13661 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)13662 DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
13663 Py_ssize_t name_len, ino_t d_ino
13664 #ifdef HAVE_DIRENT_D_TYPE
13665 , unsigned char d_type
13666 #endif
13667 )
13668 {
13669 DirEntry *entry;
13670 char *joined_path;
13671
13672 PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13673 entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13674 if (!entry)
13675 return NULL;
13676 entry->name = NULL;
13677 entry->path = NULL;
13678 entry->stat = NULL;
13679 entry->lstat = NULL;
13680
13681 if (path->fd != -1) {
13682 entry->dir_fd = path->fd;
13683 joined_path = NULL;
13684 }
13685 else {
13686 entry->dir_fd = DEFAULT_DIR_FD;
13687 joined_path = join_path_filename(path->narrow, name, name_len);
13688 if (!joined_path)
13689 goto error;
13690 }
13691
13692 if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
13693 entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
13694 if (joined_path)
13695 entry->path = PyUnicode_DecodeFSDefault(joined_path);
13696 }
13697 else {
13698 entry->name = PyBytes_FromStringAndSize(name, name_len);
13699 if (joined_path)
13700 entry->path = PyBytes_FromString(joined_path);
13701 }
13702 PyMem_Free(joined_path);
13703 if (!entry->name)
13704 goto error;
13705
13706 if (path->fd != -1) {
13707 entry->path = entry->name;
13708 Py_INCREF(entry->path);
13709 }
13710 else if (!entry->path)
13711 goto error;
13712
13713 #ifdef HAVE_DIRENT_D_TYPE
13714 entry->d_type = d_type;
13715 #endif
13716 entry->d_ino = d_ino;
13717
13718 return (PyObject *)entry;
13719
13720 error:
13721 Py_XDECREF(entry);
13722 return NULL;
13723 }
13724
13725 #endif
13726
13727
13728 typedef struct {
13729 PyObject_HEAD
13730 path_t path;
13731 #ifdef MS_WINDOWS
13732 HANDLE handle;
13733 WIN32_FIND_DATAW file_data;
13734 int first_time;
13735 #else /* POSIX */
13736 DIR *dirp;
13737 #endif
13738 #ifdef HAVE_FDOPENDIR
13739 int fd;
13740 #endif
13741 } ScandirIterator;
13742
13743 #ifdef MS_WINDOWS
13744
13745 static int
ScandirIterator_is_closed(ScandirIterator * iterator)13746 ScandirIterator_is_closed(ScandirIterator *iterator)
13747 {
13748 return iterator->handle == INVALID_HANDLE_VALUE;
13749 }
13750
13751 static void
ScandirIterator_closedir(ScandirIterator * iterator)13752 ScandirIterator_closedir(ScandirIterator *iterator)
13753 {
13754 HANDLE handle = iterator->handle;
13755
13756 if (handle == INVALID_HANDLE_VALUE)
13757 return;
13758
13759 iterator->handle = INVALID_HANDLE_VALUE;
13760 Py_BEGIN_ALLOW_THREADS
13761 FindClose(handle);
13762 Py_END_ALLOW_THREADS
13763 }
13764
13765 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)13766 ScandirIterator_iternext(ScandirIterator *iterator)
13767 {
13768 WIN32_FIND_DATAW *file_data = &iterator->file_data;
13769 BOOL success;
13770 PyObject *entry;
13771
13772 /* Happens if the iterator is iterated twice, or closed explicitly */
13773 if (iterator->handle == INVALID_HANDLE_VALUE)
13774 return NULL;
13775
13776 while (1) {
13777 if (!iterator->first_time) {
13778 Py_BEGIN_ALLOW_THREADS
13779 success = FindNextFileW(iterator->handle, file_data);
13780 Py_END_ALLOW_THREADS
13781 if (!success) {
13782 /* Error or no more files */
13783 if (GetLastError() != ERROR_NO_MORE_FILES)
13784 path_error(&iterator->path);
13785 break;
13786 }
13787 }
13788 iterator->first_time = 0;
13789
13790 /* Skip over . and .. */
13791 if (wcscmp(file_data->cFileName, L".") != 0 &&
13792 wcscmp(file_data->cFileName, L"..") != 0)
13793 {
13794 PyObject *module = PyType_GetModule(Py_TYPE(iterator));
13795 entry = DirEntry_from_find_data(module, &iterator->path, file_data);
13796 if (!entry)
13797 break;
13798 return entry;
13799 }
13800
13801 /* Loop till we get a non-dot directory or finish iterating */
13802 }
13803
13804 /* Error or no more files */
13805 ScandirIterator_closedir(iterator);
13806 return NULL;
13807 }
13808
13809 #else /* POSIX */
13810
13811 static int
ScandirIterator_is_closed(ScandirIterator * iterator)13812 ScandirIterator_is_closed(ScandirIterator *iterator)
13813 {
13814 return !iterator->dirp;
13815 }
13816
13817 static void
ScandirIterator_closedir(ScandirIterator * iterator)13818 ScandirIterator_closedir(ScandirIterator *iterator)
13819 {
13820 DIR *dirp = iterator->dirp;
13821
13822 if (!dirp)
13823 return;
13824
13825 iterator->dirp = NULL;
13826 Py_BEGIN_ALLOW_THREADS
13827 #ifdef HAVE_FDOPENDIR
13828 if (iterator->path.fd != -1)
13829 rewinddir(dirp);
13830 #endif
13831 closedir(dirp);
13832 Py_END_ALLOW_THREADS
13833 return;
13834 }
13835
13836 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)13837 ScandirIterator_iternext(ScandirIterator *iterator)
13838 {
13839 struct dirent *direntp;
13840 Py_ssize_t name_len;
13841 int is_dot;
13842 PyObject *entry;
13843
13844 /* Happens if the iterator is iterated twice, or closed explicitly */
13845 if (!iterator->dirp)
13846 return NULL;
13847
13848 while (1) {
13849 errno = 0;
13850 Py_BEGIN_ALLOW_THREADS
13851 direntp = readdir(iterator->dirp);
13852 Py_END_ALLOW_THREADS
13853
13854 if (!direntp) {
13855 /* Error or no more files */
13856 if (errno != 0)
13857 path_error(&iterator->path);
13858 break;
13859 }
13860
13861 /* Skip over . and .. */
13862 name_len = NAMLEN(direntp);
13863 is_dot = direntp->d_name[0] == '.' &&
13864 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
13865 if (!is_dot) {
13866 PyObject *module = PyType_GetModule(Py_TYPE(iterator));
13867 entry = DirEntry_from_posix_info(module,
13868 &iterator->path, direntp->d_name,
13869 name_len, direntp->d_ino
13870 #ifdef HAVE_DIRENT_D_TYPE
13871 , direntp->d_type
13872 #endif
13873 );
13874 if (!entry)
13875 break;
13876 return entry;
13877 }
13878
13879 /* Loop till we get a non-dot directory or finish iterating */
13880 }
13881
13882 /* Error or no more files */
13883 ScandirIterator_closedir(iterator);
13884 return NULL;
13885 }
13886
13887 #endif
13888
13889 static PyObject *
ScandirIterator_close(ScandirIterator * self,PyObject * args)13890 ScandirIterator_close(ScandirIterator *self, PyObject *args)
13891 {
13892 ScandirIterator_closedir(self);
13893 Py_RETURN_NONE;
13894 }
13895
13896 static PyObject *
ScandirIterator_enter(PyObject * self,PyObject * args)13897 ScandirIterator_enter(PyObject *self, PyObject *args)
13898 {
13899 Py_INCREF(self);
13900 return self;
13901 }
13902
13903 static PyObject *
ScandirIterator_exit(ScandirIterator * self,PyObject * args)13904 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
13905 {
13906 ScandirIterator_closedir(self);
13907 Py_RETURN_NONE;
13908 }
13909
13910 static void
ScandirIterator_finalize(ScandirIterator * iterator)13911 ScandirIterator_finalize(ScandirIterator *iterator)
13912 {
13913 PyObject *error_type, *error_value, *error_traceback;
13914
13915 /* Save the current exception, if any. */
13916 PyErr_Fetch(&error_type, &error_value, &error_traceback);
13917
13918 if (!ScandirIterator_is_closed(iterator)) {
13919 ScandirIterator_closedir(iterator);
13920
13921 if (PyErr_ResourceWarning((PyObject *)iterator, 1,
13922 "unclosed scandir iterator %R", iterator)) {
13923 /* Spurious errors can appear at shutdown */
13924 if (PyErr_ExceptionMatches(PyExc_Warning)) {
13925 PyErr_WriteUnraisable((PyObject *) iterator);
13926 }
13927 }
13928 }
13929
13930 path_cleanup(&iterator->path);
13931
13932 /* Restore the saved exception. */
13933 PyErr_Restore(error_type, error_value, error_traceback);
13934 }
13935
13936 static void
ScandirIterator_dealloc(ScandirIterator * iterator)13937 ScandirIterator_dealloc(ScandirIterator *iterator)
13938 {
13939 PyTypeObject *tp = Py_TYPE(iterator);
13940 if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
13941 return;
13942
13943 freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13944 free_func(iterator);
13945 Py_DECREF(tp);
13946 }
13947
13948 static PyMethodDef ScandirIterator_methods[] = {
13949 {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
13950 {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
13951 {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
13952 {NULL}
13953 };
13954
13955 static PyType_Slot ScandirIteratorType_slots[] = {
13956 {Py_tp_new, _disabled_new},
13957 {Py_tp_dealloc, ScandirIterator_dealloc},
13958 {Py_tp_finalize, ScandirIterator_finalize},
13959 {Py_tp_iter, PyObject_SelfIter},
13960 {Py_tp_iternext, ScandirIterator_iternext},
13961 {Py_tp_methods, ScandirIterator_methods},
13962 {0, 0},
13963 };
13964
13965 static PyType_Spec ScandirIteratorType_spec = {
13966 MODNAME ".ScandirIterator",
13967 sizeof(ScandirIterator),
13968 0,
13969 // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
13970 // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
13971 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE,
13972 ScandirIteratorType_slots
13973 };
13974
13975 /*[clinic input]
13976 os.scandir
13977
13978 path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
13979
13980 Return an iterator of DirEntry objects for given path.
13981
13982 path can be specified as either str, bytes, or a path-like object. If path
13983 is bytes, the names of yielded DirEntry objects will also be bytes; in
13984 all other circumstances they will be str.
13985
13986 If path is None, uses the path='.'.
13987 [clinic start generated code]*/
13988
13989 static PyObject *
os_scandir_impl(PyObject * module,path_t * path)13990 os_scandir_impl(PyObject *module, path_t *path)
13991 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
13992 {
13993 ScandirIterator *iterator;
13994 #ifdef MS_WINDOWS
13995 wchar_t *path_strW;
13996 #else
13997 const char *path_str;
13998 #ifdef HAVE_FDOPENDIR
13999 int fd = -1;
14000 #endif
14001 #endif
14002
14003 if (PySys_Audit("os.scandir", "O",
14004 path->object ? path->object : Py_None) < 0) {
14005 return NULL;
14006 }
14007
14008 PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
14009 iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
14010 if (!iterator)
14011 return NULL;
14012
14013 #ifdef MS_WINDOWS
14014 iterator->handle = INVALID_HANDLE_VALUE;
14015 #else
14016 iterator->dirp = NULL;
14017 #endif
14018
14019 memcpy(&iterator->path, path, sizeof(path_t));
14020 /* Move the ownership to iterator->path */
14021 path->object = NULL;
14022 path->cleanup = NULL;
14023
14024 #ifdef MS_WINDOWS
14025 iterator->first_time = 1;
14026
14027 path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
14028 if (!path_strW)
14029 goto error;
14030
14031 Py_BEGIN_ALLOW_THREADS
14032 iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
14033 Py_END_ALLOW_THREADS
14034
14035 PyMem_Free(path_strW);
14036
14037 if (iterator->handle == INVALID_HANDLE_VALUE) {
14038 path_error(&iterator->path);
14039 goto error;
14040 }
14041 #else /* POSIX */
14042 errno = 0;
14043 #ifdef HAVE_FDOPENDIR
14044 if (iterator->path.fd != -1) {
14045 if (HAVE_FDOPENDIR_RUNTIME) {
14046 /* closedir() closes the FD, so we duplicate it */
14047 fd = _Py_dup(path->fd);
14048 if (fd == -1)
14049 goto error;
14050
14051 Py_BEGIN_ALLOW_THREADS
14052 iterator->dirp = fdopendir(fd);
14053 Py_END_ALLOW_THREADS
14054 } else {
14055 PyErr_SetString(PyExc_TypeError,
14056 "scandir: path should be string, bytes, os.PathLike or None, not int");
14057 return NULL;
14058 }
14059 }
14060 else
14061 #endif
14062 {
14063 if (iterator->path.narrow)
14064 path_str = iterator->path.narrow;
14065 else
14066 path_str = ".";
14067
14068 Py_BEGIN_ALLOW_THREADS
14069 iterator->dirp = opendir(path_str);
14070 Py_END_ALLOW_THREADS
14071 }
14072
14073 if (!iterator->dirp) {
14074 path_error(&iterator->path);
14075 #ifdef HAVE_FDOPENDIR
14076 if (fd != -1) {
14077 Py_BEGIN_ALLOW_THREADS
14078 close(fd);
14079 Py_END_ALLOW_THREADS
14080 }
14081 #endif
14082 goto error;
14083 }
14084 #endif
14085
14086 return (PyObject *)iterator;
14087
14088 error:
14089 Py_DECREF(iterator);
14090 return NULL;
14091 }
14092
14093 /*
14094 Return the file system path representation of the object.
14095
14096 If the object is str or bytes, then allow it to pass through with
14097 an incremented refcount. If the object defines __fspath__(), then
14098 return the result of that method. All other types raise a TypeError.
14099 */
14100 PyObject *
PyOS_FSPath(PyObject * path)14101 PyOS_FSPath(PyObject *path)
14102 {
14103 /* For error message reasons, this function is manually inlined in
14104 path_converter(). */
14105 PyObject *func = NULL;
14106 PyObject *path_repr = NULL;
14107
14108 if (PyUnicode_Check(path) || PyBytes_Check(path)) {
14109 Py_INCREF(path);
14110 return path;
14111 }
14112
14113 func = _PyObject_LookupSpecial(path, &PyId___fspath__);
14114 if (NULL == func) {
14115 return PyErr_Format(PyExc_TypeError,
14116 "expected str, bytes or os.PathLike object, "
14117 "not %.200s",
14118 _PyType_Name(Py_TYPE(path)));
14119 }
14120
14121 path_repr = _PyObject_CallNoArg(func);
14122 Py_DECREF(func);
14123 if (NULL == path_repr) {
14124 return NULL;
14125 }
14126
14127 if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
14128 PyErr_Format(PyExc_TypeError,
14129 "expected %.200s.__fspath__() to return str or bytes, "
14130 "not %.200s", _PyType_Name(Py_TYPE(path)),
14131 _PyType_Name(Py_TYPE(path_repr)));
14132 Py_DECREF(path_repr);
14133 return NULL;
14134 }
14135
14136 return path_repr;
14137 }
14138
14139 /*[clinic input]
14140 os.fspath
14141
14142 path: object
14143
14144 Return the file system path representation of the object.
14145
14146 If the object is str or bytes, then allow it to pass through as-is. If the
14147 object defines __fspath__(), then return the result of that method. All other
14148 types raise a TypeError.
14149 [clinic start generated code]*/
14150
14151 static PyObject *
os_fspath_impl(PyObject * module,PyObject * path)14152 os_fspath_impl(PyObject *module, PyObject *path)
14153 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
14154 {
14155 return PyOS_FSPath(path);
14156 }
14157
14158 #ifdef HAVE_GETRANDOM_SYSCALL
14159 /*[clinic input]
14160 os.getrandom
14161
14162 size: Py_ssize_t
14163 flags: int=0
14164
14165 Obtain a series of random bytes.
14166 [clinic start generated code]*/
14167
14168 static PyObject *
os_getrandom_impl(PyObject * module,Py_ssize_t size,int flags)14169 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
14170 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
14171 {
14172 PyObject *bytes;
14173 Py_ssize_t n;
14174
14175 if (size < 0) {
14176 errno = EINVAL;
14177 return posix_error();
14178 }
14179
14180 bytes = PyBytes_FromStringAndSize(NULL, size);
14181 if (bytes == NULL) {
14182 PyErr_NoMemory();
14183 return NULL;
14184 }
14185
14186 while (1) {
14187 n = syscall(SYS_getrandom,
14188 PyBytes_AS_STRING(bytes),
14189 PyBytes_GET_SIZE(bytes),
14190 flags);
14191 if (n < 0 && errno == EINTR) {
14192 if (PyErr_CheckSignals() < 0) {
14193 goto error;
14194 }
14195
14196 /* getrandom() was interrupted by a signal: retry */
14197 continue;
14198 }
14199 break;
14200 }
14201
14202 if (n < 0) {
14203 PyErr_SetFromErrno(PyExc_OSError);
14204 goto error;
14205 }
14206
14207 if (n != size) {
14208 _PyBytes_Resize(&bytes, n);
14209 }
14210
14211 return bytes;
14212
14213 error:
14214 Py_DECREF(bytes);
14215 return NULL;
14216 }
14217 #endif /* HAVE_GETRANDOM_SYSCALL */
14218
14219 #ifdef MS_WINDOWS
14220 /* bpo-36085: Helper functions for managing DLL search directories
14221 * on win32
14222 */
14223
14224 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
14225 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
14226
14227 /*[clinic input]
14228 os._add_dll_directory
14229
14230 path: path_t
14231
14232 Add a path to the DLL search path.
14233
14234 This search path is used when resolving dependencies for imported
14235 extension modules (the module itself is resolved through sys.path),
14236 and also by ctypes.
14237
14238 Returns an opaque value that may be passed to os.remove_dll_directory
14239 to remove this directory from the search path.
14240 [clinic start generated code]*/
14241
14242 static PyObject *
os__add_dll_directory_impl(PyObject * module,path_t * path)14243 os__add_dll_directory_impl(PyObject *module, path_t *path)
14244 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
14245 {
14246 HMODULE hKernel32;
14247 PAddDllDirectory AddDllDirectory;
14248 DLL_DIRECTORY_COOKIE cookie = 0;
14249 DWORD err = 0;
14250
14251 if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
14252 return NULL;
14253 }
14254
14255 /* For Windows 7, we have to load this. As this will be a fairly
14256 infrequent operation, just do it each time. Kernel32 is always
14257 loaded. */
14258 Py_BEGIN_ALLOW_THREADS
14259 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14260 !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
14261 hKernel32, "AddDllDirectory")) ||
14262 !(cookie = (*AddDllDirectory)(path->wide))) {
14263 err = GetLastError();
14264 }
14265 Py_END_ALLOW_THREADS
14266
14267 if (err) {
14268 return win32_error_object_err("add_dll_directory",
14269 path->object, err);
14270 }
14271
14272 return PyCapsule_New(cookie, "DLL directory cookie", NULL);
14273 }
14274
14275 /*[clinic input]
14276 os._remove_dll_directory
14277
14278 cookie: object
14279
14280 Removes a path from the DLL search path.
14281
14282 The parameter is an opaque value that was returned from
14283 os.add_dll_directory. You can only remove directories that you added
14284 yourself.
14285 [clinic start generated code]*/
14286
14287 static PyObject *
os__remove_dll_directory_impl(PyObject * module,PyObject * cookie)14288 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
14289 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
14290 {
14291 HMODULE hKernel32;
14292 PRemoveDllDirectory RemoveDllDirectory;
14293 DLL_DIRECTORY_COOKIE cookieValue;
14294 DWORD err = 0;
14295
14296 if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
14297 PyErr_SetString(PyExc_TypeError,
14298 "Provided cookie was not returned from os.add_dll_directory");
14299 return NULL;
14300 }
14301
14302 cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
14303 cookie, "DLL directory cookie");
14304
14305 /* For Windows 7, we have to load this. As this will be a fairly
14306 infrequent operation, just do it each time. Kernel32 is always
14307 loaded. */
14308 Py_BEGIN_ALLOW_THREADS
14309 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14310 !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
14311 hKernel32, "RemoveDllDirectory")) ||
14312 !(*RemoveDllDirectory)(cookieValue)) {
14313 err = GetLastError();
14314 }
14315 Py_END_ALLOW_THREADS
14316
14317 if (err) {
14318 return win32_error_object_err("remove_dll_directory",
14319 NULL, err);
14320 }
14321
14322 if (PyCapsule_SetName(cookie, NULL)) {
14323 return NULL;
14324 }
14325
14326 Py_RETURN_NONE;
14327 }
14328
14329 #endif
14330
14331
14332 /* Only check if WIFEXITED is available: expect that it comes
14333 with WEXITSTATUS, WIFSIGNALED, etc.
14334
14335 os.waitstatus_to_exitcode() is implemented in C and not in Python, so
14336 subprocess can safely call it during late Python finalization without
14337 risking that used os attributes were set to None by _PyImport_Cleanup(). */
14338 #if defined(WIFEXITED) || defined(MS_WINDOWS)
14339 /*[clinic input]
14340 os.waitstatus_to_exitcode
14341
14342 status as status_obj: object
14343
14344 Convert a wait status to an exit code.
14345
14346 On Unix:
14347
14348 * If WIFEXITED(status) is true, return WEXITSTATUS(status).
14349 * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
14350 * Otherwise, raise a ValueError.
14351
14352 On Windows, return status shifted right by 8 bits.
14353
14354 On Unix, if the process is being traced or if waitpid() was called with
14355 WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
14356 This function must not be called if WIFSTOPPED(status) is true.
14357 [clinic start generated code]*/
14358
14359 static PyObject *
os_waitstatus_to_exitcode_impl(PyObject * module,PyObject * status_obj)14360 os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
14361 /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
14362 {
14363 if (PyFloat_Check(status_obj)) {
14364 PyErr_SetString(PyExc_TypeError,
14365 "integer argument expected, got float" );
14366 return NULL;
14367 }
14368 #ifndef MS_WINDOWS
14369 int status = _PyLong_AsInt(status_obj);
14370 if (status == -1 && PyErr_Occurred()) {
14371 return NULL;
14372 }
14373
14374 WAIT_TYPE wait_status;
14375 WAIT_STATUS_INT(wait_status) = status;
14376 int exitcode;
14377 if (WIFEXITED(wait_status)) {
14378 exitcode = WEXITSTATUS(wait_status);
14379 /* Sanity check to provide warranty on the function behavior.
14380 It should not occur in practice */
14381 if (exitcode < 0) {
14382 PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
14383 return NULL;
14384 }
14385 }
14386 else if (WIFSIGNALED(wait_status)) {
14387 int signum = WTERMSIG(wait_status);
14388 /* Sanity check to provide warranty on the function behavior.
14389 It should not occurs in practice */
14390 if (signum <= 0) {
14391 PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
14392 return NULL;
14393 }
14394 exitcode = -signum;
14395 } else if (WIFSTOPPED(wait_status)) {
14396 /* Status only received if the process is being traced
14397 or if waitpid() was called with WUNTRACED option. */
14398 int signum = WSTOPSIG(wait_status);
14399 PyErr_Format(PyExc_ValueError,
14400 "process stopped by delivery of signal %i",
14401 signum);
14402 return NULL;
14403 }
14404 else {
14405 PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
14406 return NULL;
14407 }
14408 return PyLong_FromLong(exitcode);
14409 #else
14410 /* Windows implementation: see os.waitpid() implementation
14411 which uses _cwait(). */
14412 unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
14413 if (status == (unsigned long long)-1 && PyErr_Occurred()) {
14414 return NULL;
14415 }
14416
14417 unsigned long long exitcode = (status >> 8);
14418 /* ExitProcess() accepts an UINT type:
14419 reject exit code which doesn't fit in an UINT */
14420 if (exitcode > UINT_MAX) {
14421 PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
14422 return NULL;
14423 }
14424 return PyLong_FromUnsignedLong((unsigned long)exitcode);
14425 #endif
14426 }
14427 #endif
14428
14429
14430 static PyMethodDef posix_methods[] = {
14431
14432 OS_STAT_METHODDEF
14433 OS_ACCESS_METHODDEF
14434 OS_TTYNAME_METHODDEF
14435 OS_CHDIR_METHODDEF
14436 OS_CHFLAGS_METHODDEF
14437 OS_CHMOD_METHODDEF
14438 OS_FCHMOD_METHODDEF
14439 OS_LCHMOD_METHODDEF
14440 OS_CHOWN_METHODDEF
14441 OS_FCHOWN_METHODDEF
14442 OS_LCHOWN_METHODDEF
14443 OS_LCHFLAGS_METHODDEF
14444 OS_CHROOT_METHODDEF
14445 OS_CTERMID_METHODDEF
14446 OS_GETCWD_METHODDEF
14447 OS_GETCWDB_METHODDEF
14448 OS_LINK_METHODDEF
14449 OS_LISTDIR_METHODDEF
14450 OS_LSTAT_METHODDEF
14451 OS_MKDIR_METHODDEF
14452 OS_NICE_METHODDEF
14453 OS_GETPRIORITY_METHODDEF
14454 OS_SETPRIORITY_METHODDEF
14455 OS_POSIX_SPAWN_METHODDEF
14456 OS_POSIX_SPAWNP_METHODDEF
14457 OS_READLINK_METHODDEF
14458 OS_COPY_FILE_RANGE_METHODDEF
14459 OS_RENAME_METHODDEF
14460 OS_REPLACE_METHODDEF
14461 OS_RMDIR_METHODDEF
14462 OS_SYMLINK_METHODDEF
14463 OS_SYSTEM_METHODDEF
14464 OS_UMASK_METHODDEF
14465 OS_UNAME_METHODDEF
14466 OS_UNLINK_METHODDEF
14467 OS_REMOVE_METHODDEF
14468 OS_UTIME_METHODDEF
14469 OS_TIMES_METHODDEF
14470 OS__EXIT_METHODDEF
14471 OS__FCOPYFILE_METHODDEF
14472 OS_EXECV_METHODDEF
14473 OS_EXECVE_METHODDEF
14474 OS_SPAWNV_METHODDEF
14475 OS_SPAWNVE_METHODDEF
14476 OS_FORK1_METHODDEF
14477 OS_FORK_METHODDEF
14478 OS_REGISTER_AT_FORK_METHODDEF
14479 OS_SCHED_GET_PRIORITY_MAX_METHODDEF
14480 OS_SCHED_GET_PRIORITY_MIN_METHODDEF
14481 OS_SCHED_GETPARAM_METHODDEF
14482 OS_SCHED_GETSCHEDULER_METHODDEF
14483 OS_SCHED_RR_GET_INTERVAL_METHODDEF
14484 OS_SCHED_SETPARAM_METHODDEF
14485 OS_SCHED_SETSCHEDULER_METHODDEF
14486 OS_SCHED_YIELD_METHODDEF
14487 OS_SCHED_SETAFFINITY_METHODDEF
14488 OS_SCHED_GETAFFINITY_METHODDEF
14489 OS_OPENPTY_METHODDEF
14490 OS_FORKPTY_METHODDEF
14491 OS_GETEGID_METHODDEF
14492 OS_GETEUID_METHODDEF
14493 OS_GETGID_METHODDEF
14494 OS_GETGROUPLIST_METHODDEF
14495 OS_GETGROUPS_METHODDEF
14496 OS_GETPID_METHODDEF
14497 OS_GETPGRP_METHODDEF
14498 OS_GETPPID_METHODDEF
14499 OS_GETUID_METHODDEF
14500 OS_GETLOGIN_METHODDEF
14501 OS_KILL_METHODDEF
14502 OS_KILLPG_METHODDEF
14503 OS_PLOCK_METHODDEF
14504 OS_STARTFILE_METHODDEF
14505 OS_SETUID_METHODDEF
14506 OS_SETEUID_METHODDEF
14507 OS_SETREUID_METHODDEF
14508 OS_SETGID_METHODDEF
14509 OS_SETEGID_METHODDEF
14510 OS_SETREGID_METHODDEF
14511 OS_SETGROUPS_METHODDEF
14512 OS_INITGROUPS_METHODDEF
14513 OS_GETPGID_METHODDEF
14514 OS_SETPGRP_METHODDEF
14515 OS_WAIT_METHODDEF
14516 OS_WAIT3_METHODDEF
14517 OS_WAIT4_METHODDEF
14518 OS_WAITID_METHODDEF
14519 OS_WAITPID_METHODDEF
14520 OS_PIDFD_OPEN_METHODDEF
14521 OS_GETSID_METHODDEF
14522 OS_SETSID_METHODDEF
14523 OS_SETPGID_METHODDEF
14524 OS_TCGETPGRP_METHODDEF
14525 OS_TCSETPGRP_METHODDEF
14526 OS_OPEN_METHODDEF
14527 OS_CLOSE_METHODDEF
14528 OS_CLOSERANGE_METHODDEF
14529 OS_DEVICE_ENCODING_METHODDEF
14530 OS_DUP_METHODDEF
14531 OS_DUP2_METHODDEF
14532 OS_LOCKF_METHODDEF
14533 OS_LSEEK_METHODDEF
14534 OS_READ_METHODDEF
14535 OS_READV_METHODDEF
14536 OS_PREAD_METHODDEF
14537 OS_PREADV_METHODDEF
14538 OS_WRITE_METHODDEF
14539 OS_WRITEV_METHODDEF
14540 OS_PWRITE_METHODDEF
14541 OS_PWRITEV_METHODDEF
14542 OS_SENDFILE_METHODDEF
14543 OS_FSTAT_METHODDEF
14544 OS_ISATTY_METHODDEF
14545 OS_PIPE_METHODDEF
14546 OS_PIPE2_METHODDEF
14547 OS_MKFIFO_METHODDEF
14548 OS_MKNOD_METHODDEF
14549 OS_MAJOR_METHODDEF
14550 OS_MINOR_METHODDEF
14551 OS_MAKEDEV_METHODDEF
14552 OS_FTRUNCATE_METHODDEF
14553 OS_TRUNCATE_METHODDEF
14554 OS_POSIX_FALLOCATE_METHODDEF
14555 OS_POSIX_FADVISE_METHODDEF
14556 OS_PUTENV_METHODDEF
14557 OS_UNSETENV_METHODDEF
14558 OS_STRERROR_METHODDEF
14559 OS_FCHDIR_METHODDEF
14560 OS_FSYNC_METHODDEF
14561 OS_SYNC_METHODDEF
14562 OS_FDATASYNC_METHODDEF
14563 OS_WCOREDUMP_METHODDEF
14564 OS_WIFCONTINUED_METHODDEF
14565 OS_WIFSTOPPED_METHODDEF
14566 OS_WIFSIGNALED_METHODDEF
14567 OS_WIFEXITED_METHODDEF
14568 OS_WEXITSTATUS_METHODDEF
14569 OS_WTERMSIG_METHODDEF
14570 OS_WSTOPSIG_METHODDEF
14571 OS_FSTATVFS_METHODDEF
14572 OS_STATVFS_METHODDEF
14573 OS_CONFSTR_METHODDEF
14574 OS_SYSCONF_METHODDEF
14575 OS_FPATHCONF_METHODDEF
14576 OS_PATHCONF_METHODDEF
14577 OS_ABORT_METHODDEF
14578 OS__GETFULLPATHNAME_METHODDEF
14579 OS__GETDISKUSAGE_METHODDEF
14580 OS__GETFINALPATHNAME_METHODDEF
14581 OS__GETVOLUMEPATHNAME_METHODDEF
14582 OS_GETLOADAVG_METHODDEF
14583 OS_URANDOM_METHODDEF
14584 OS_SETRESUID_METHODDEF
14585 OS_SETRESGID_METHODDEF
14586 OS_GETRESUID_METHODDEF
14587 OS_GETRESGID_METHODDEF
14588
14589 OS_GETXATTR_METHODDEF
14590 OS_SETXATTR_METHODDEF
14591 OS_REMOVEXATTR_METHODDEF
14592 OS_LISTXATTR_METHODDEF
14593
14594 OS_GET_TERMINAL_SIZE_METHODDEF
14595 OS_CPU_COUNT_METHODDEF
14596 OS_GET_INHERITABLE_METHODDEF
14597 OS_SET_INHERITABLE_METHODDEF
14598 OS_GET_HANDLE_INHERITABLE_METHODDEF
14599 OS_SET_HANDLE_INHERITABLE_METHODDEF
14600 OS_GET_BLOCKING_METHODDEF
14601 OS_SET_BLOCKING_METHODDEF
14602 OS_SCANDIR_METHODDEF
14603 OS_FSPATH_METHODDEF
14604 OS_GETRANDOM_METHODDEF
14605 OS_MEMFD_CREATE_METHODDEF
14606 OS__ADD_DLL_DIRECTORY_METHODDEF
14607 OS__REMOVE_DLL_DIRECTORY_METHODDEF
14608 OS_WAITSTATUS_TO_EXITCODE_METHODDEF
14609 {NULL, NULL} /* Sentinel */
14610 };
14611
14612 static int
all_ins(PyObject * m)14613 all_ins(PyObject *m)
14614 {
14615 #ifdef F_OK
14616 if (PyModule_AddIntMacro(m, F_OK)) return -1;
14617 #endif
14618 #ifdef R_OK
14619 if (PyModule_AddIntMacro(m, R_OK)) return -1;
14620 #endif
14621 #ifdef W_OK
14622 if (PyModule_AddIntMacro(m, W_OK)) return -1;
14623 #endif
14624 #ifdef X_OK
14625 if (PyModule_AddIntMacro(m, X_OK)) return -1;
14626 #endif
14627 #ifdef NGROUPS_MAX
14628 if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
14629 #endif
14630 #ifdef TMP_MAX
14631 if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
14632 #endif
14633 #ifdef WCONTINUED
14634 if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
14635 #endif
14636 #ifdef WNOHANG
14637 if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
14638 #endif
14639 #ifdef WUNTRACED
14640 if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
14641 #endif
14642 #ifdef O_RDONLY
14643 if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
14644 #endif
14645 #ifdef O_WRONLY
14646 if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
14647 #endif
14648 #ifdef O_RDWR
14649 if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
14650 #endif
14651 #ifdef O_NDELAY
14652 if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
14653 #endif
14654 #ifdef O_NONBLOCK
14655 if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
14656 #endif
14657 #ifdef O_APPEND
14658 if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
14659 #endif
14660 #ifdef O_DSYNC
14661 if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
14662 #endif
14663 #ifdef O_RSYNC
14664 if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
14665 #endif
14666 #ifdef O_SYNC
14667 if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
14668 #endif
14669 #ifdef O_NOCTTY
14670 if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
14671 #endif
14672 #ifdef O_CREAT
14673 if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
14674 #endif
14675 #ifdef O_EXCL
14676 if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
14677 #endif
14678 #ifdef O_TRUNC
14679 if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
14680 #endif
14681 #ifdef O_BINARY
14682 if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
14683 #endif
14684 #ifdef O_TEXT
14685 if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
14686 #endif
14687 #ifdef O_XATTR
14688 if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
14689 #endif
14690 #ifdef O_LARGEFILE
14691 if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
14692 #endif
14693 #ifndef __GNU__
14694 #ifdef O_SHLOCK
14695 if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
14696 #endif
14697 #ifdef O_EXLOCK
14698 if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
14699 #endif
14700 #endif
14701 #ifdef O_EXEC
14702 if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
14703 #endif
14704 #ifdef O_SEARCH
14705 if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
14706 #endif
14707 #ifdef O_PATH
14708 if (PyModule_AddIntMacro(m, O_PATH)) return -1;
14709 #endif
14710 #ifdef O_TTY_INIT
14711 if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
14712 #endif
14713 #ifdef O_TMPFILE
14714 if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
14715 #endif
14716 #ifdef PRIO_PROCESS
14717 if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
14718 #endif
14719 #ifdef PRIO_PGRP
14720 if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
14721 #endif
14722 #ifdef PRIO_USER
14723 if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
14724 #endif
14725 #ifdef O_CLOEXEC
14726 if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
14727 #endif
14728 #ifdef O_ACCMODE
14729 if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
14730 #endif
14731
14732
14733 #ifdef SEEK_HOLE
14734 if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
14735 #endif
14736 #ifdef SEEK_DATA
14737 if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
14738 #endif
14739
14740 /* MS Windows */
14741 #ifdef O_NOINHERIT
14742 /* Don't inherit in child processes. */
14743 if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
14744 #endif
14745 #ifdef _O_SHORT_LIVED
14746 /* Optimize for short life (keep in memory). */
14747 /* MS forgot to define this one with a non-underscore form too. */
14748 if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
14749 #endif
14750 #ifdef O_TEMPORARY
14751 /* Automatically delete when last handle is closed. */
14752 if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
14753 #endif
14754 #ifdef O_RANDOM
14755 /* Optimize for random access. */
14756 if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
14757 #endif
14758 #ifdef O_SEQUENTIAL
14759 /* Optimize for sequential access. */
14760 if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
14761 #endif
14762
14763 /* GNU extensions. */
14764 #ifdef O_ASYNC
14765 /* Send a SIGIO signal whenever input or output
14766 becomes available on file descriptor */
14767 if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
14768 #endif
14769 #ifdef O_DIRECT
14770 /* Direct disk access. */
14771 if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
14772 #endif
14773 #ifdef O_DIRECTORY
14774 /* Must be a directory. */
14775 if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
14776 #endif
14777 #ifdef O_NOFOLLOW
14778 /* Do not follow links. */
14779 if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
14780 #endif
14781 #ifdef O_NOLINKS
14782 /* Fails if link count of the named file is greater than 1 */
14783 if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
14784 #endif
14785 #ifdef O_NOATIME
14786 /* Do not update the access time. */
14787 if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
14788 #endif
14789
14790 /* These come from sysexits.h */
14791 #ifdef EX_OK
14792 if (PyModule_AddIntMacro(m, EX_OK)) return -1;
14793 #endif /* EX_OK */
14794 #ifdef EX_USAGE
14795 if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
14796 #endif /* EX_USAGE */
14797 #ifdef EX_DATAERR
14798 if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
14799 #endif /* EX_DATAERR */
14800 #ifdef EX_NOINPUT
14801 if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
14802 #endif /* EX_NOINPUT */
14803 #ifdef EX_NOUSER
14804 if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
14805 #endif /* EX_NOUSER */
14806 #ifdef EX_NOHOST
14807 if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
14808 #endif /* EX_NOHOST */
14809 #ifdef EX_UNAVAILABLE
14810 if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
14811 #endif /* EX_UNAVAILABLE */
14812 #ifdef EX_SOFTWARE
14813 if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
14814 #endif /* EX_SOFTWARE */
14815 #ifdef EX_OSERR
14816 if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
14817 #endif /* EX_OSERR */
14818 #ifdef EX_OSFILE
14819 if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
14820 #endif /* EX_OSFILE */
14821 #ifdef EX_CANTCREAT
14822 if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
14823 #endif /* EX_CANTCREAT */
14824 #ifdef EX_IOERR
14825 if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
14826 #endif /* EX_IOERR */
14827 #ifdef EX_TEMPFAIL
14828 if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
14829 #endif /* EX_TEMPFAIL */
14830 #ifdef EX_PROTOCOL
14831 if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
14832 #endif /* EX_PROTOCOL */
14833 #ifdef EX_NOPERM
14834 if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
14835 #endif /* EX_NOPERM */
14836 #ifdef EX_CONFIG
14837 if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
14838 #endif /* EX_CONFIG */
14839 #ifdef EX_NOTFOUND
14840 if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
14841 #endif /* EX_NOTFOUND */
14842
14843 /* statvfs */
14844 #ifdef ST_RDONLY
14845 if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
14846 #endif /* ST_RDONLY */
14847 #ifdef ST_NOSUID
14848 if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
14849 #endif /* ST_NOSUID */
14850
14851 /* GNU extensions */
14852 #ifdef ST_NODEV
14853 if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
14854 #endif /* ST_NODEV */
14855 #ifdef ST_NOEXEC
14856 if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
14857 #endif /* ST_NOEXEC */
14858 #ifdef ST_SYNCHRONOUS
14859 if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
14860 #endif /* ST_SYNCHRONOUS */
14861 #ifdef ST_MANDLOCK
14862 if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
14863 #endif /* ST_MANDLOCK */
14864 #ifdef ST_WRITE
14865 if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
14866 #endif /* ST_WRITE */
14867 #ifdef ST_APPEND
14868 if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
14869 #endif /* ST_APPEND */
14870 #ifdef ST_NOATIME
14871 if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
14872 #endif /* ST_NOATIME */
14873 #ifdef ST_NODIRATIME
14874 if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
14875 #endif /* ST_NODIRATIME */
14876 #ifdef ST_RELATIME
14877 if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
14878 #endif /* ST_RELATIME */
14879
14880 /* FreeBSD sendfile() constants */
14881 #ifdef SF_NODISKIO
14882 if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
14883 #endif
14884 #ifdef SF_MNOWAIT
14885 if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
14886 #endif
14887 #ifdef SF_SYNC
14888 if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
14889 #endif
14890
14891 /* constants for posix_fadvise */
14892 #ifdef POSIX_FADV_NORMAL
14893 if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
14894 #endif
14895 #ifdef POSIX_FADV_SEQUENTIAL
14896 if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
14897 #endif
14898 #ifdef POSIX_FADV_RANDOM
14899 if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
14900 #endif
14901 #ifdef POSIX_FADV_NOREUSE
14902 if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
14903 #endif
14904 #ifdef POSIX_FADV_WILLNEED
14905 if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
14906 #endif
14907 #ifdef POSIX_FADV_DONTNEED
14908 if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
14909 #endif
14910
14911 /* constants for waitid */
14912 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
14913 if (PyModule_AddIntMacro(m, P_PID)) return -1;
14914 if (PyModule_AddIntMacro(m, P_PGID)) return -1;
14915 if (PyModule_AddIntMacro(m, P_ALL)) return -1;
14916 #ifdef P_PIDFD
14917 if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
14918 #endif
14919 #endif
14920 #ifdef WEXITED
14921 if (PyModule_AddIntMacro(m, WEXITED)) return -1;
14922 #endif
14923 #ifdef WNOWAIT
14924 if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
14925 #endif
14926 #ifdef WSTOPPED
14927 if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
14928 #endif
14929 #ifdef CLD_EXITED
14930 if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
14931 #endif
14932 #ifdef CLD_KILLED
14933 if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
14934 #endif
14935 #ifdef CLD_DUMPED
14936 if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
14937 #endif
14938 #ifdef CLD_TRAPPED
14939 if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
14940 #endif
14941 #ifdef CLD_STOPPED
14942 if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
14943 #endif
14944 #ifdef CLD_CONTINUED
14945 if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
14946 #endif
14947
14948 /* constants for lockf */
14949 #ifdef F_LOCK
14950 if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
14951 #endif
14952 #ifdef F_TLOCK
14953 if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
14954 #endif
14955 #ifdef F_ULOCK
14956 if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
14957 #endif
14958 #ifdef F_TEST
14959 if (PyModule_AddIntMacro(m, F_TEST)) return -1;
14960 #endif
14961
14962 #ifdef RWF_DSYNC
14963 if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
14964 #endif
14965 #ifdef RWF_HIPRI
14966 if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
14967 #endif
14968 #ifdef RWF_SYNC
14969 if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
14970 #endif
14971 #ifdef RWF_NOWAIT
14972 if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
14973 #endif
14974
14975 /* constants for posix_spawn */
14976 #ifdef HAVE_POSIX_SPAWN
14977 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
14978 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
14979 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
14980 #endif
14981
14982 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
14983 if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
14984 if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
14985 if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
14986 #endif
14987 #ifdef HAVE_SPAWNV
14988 if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
14989 if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
14990 #endif
14991
14992 #ifdef HAVE_SCHED_H
14993 #ifdef SCHED_OTHER
14994 if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
14995 #endif
14996 #ifdef SCHED_FIFO
14997 if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
14998 #endif
14999 #ifdef SCHED_RR
15000 if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
15001 #endif
15002 #ifdef SCHED_SPORADIC
15003 if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
15004 #endif
15005 #ifdef SCHED_BATCH
15006 if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
15007 #endif
15008 #ifdef SCHED_IDLE
15009 if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
15010 #endif
15011 #ifdef SCHED_RESET_ON_FORK
15012 if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
15013 #endif
15014 #ifdef SCHED_SYS
15015 if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
15016 #endif
15017 #ifdef SCHED_IA
15018 if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
15019 #endif
15020 #ifdef SCHED_FSS
15021 if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
15022 #endif
15023 #ifdef SCHED_FX
15024 if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
15025 #endif
15026 #endif
15027
15028 #ifdef USE_XATTRS
15029 if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
15030 if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
15031 if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
15032 #endif
15033
15034 #if HAVE_DECL_RTLD_LAZY
15035 if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
15036 #endif
15037 #if HAVE_DECL_RTLD_NOW
15038 if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
15039 #endif
15040 #if HAVE_DECL_RTLD_GLOBAL
15041 if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
15042 #endif
15043 #if HAVE_DECL_RTLD_LOCAL
15044 if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
15045 #endif
15046 #if HAVE_DECL_RTLD_NODELETE
15047 if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
15048 #endif
15049 #if HAVE_DECL_RTLD_NOLOAD
15050 if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
15051 #endif
15052 #if HAVE_DECL_RTLD_DEEPBIND
15053 if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
15054 #endif
15055 #if HAVE_DECL_RTLD_MEMBER
15056 if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
15057 #endif
15058
15059 #ifdef HAVE_GETRANDOM_SYSCALL
15060 if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
15061 if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
15062 #endif
15063 #ifdef HAVE_MEMFD_CREATE
15064 if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
15065 if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
15066 #ifdef MFD_HUGETLB
15067 if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
15068 #endif
15069 #ifdef MFD_HUGE_SHIFT
15070 if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
15071 #endif
15072 #ifdef MFD_HUGE_MASK
15073 if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
15074 #endif
15075 #ifdef MFD_HUGE_64KB
15076 if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
15077 #endif
15078 #ifdef MFD_HUGE_512KB
15079 if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
15080 #endif
15081 #ifdef MFD_HUGE_1MB
15082 if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
15083 #endif
15084 #ifdef MFD_HUGE_2MB
15085 if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
15086 #endif
15087 #ifdef MFD_HUGE_8MB
15088 if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
15089 #endif
15090 #ifdef MFD_HUGE_16MB
15091 if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
15092 #endif
15093 #ifdef MFD_HUGE_32MB
15094 if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
15095 #endif
15096 #ifdef MFD_HUGE_256MB
15097 if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
15098 #endif
15099 #ifdef MFD_HUGE_512MB
15100 if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
15101 #endif
15102 #ifdef MFD_HUGE_1GB
15103 if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
15104 #endif
15105 #ifdef MFD_HUGE_2GB
15106 if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
15107 #endif
15108 #ifdef MFD_HUGE_16GB
15109 if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
15110 #endif
15111 #endif
15112
15113 #if defined(__APPLE__)
15114 if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
15115 #endif
15116
15117 #ifdef MS_WINDOWS
15118 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
15119 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
15120 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
15121 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
15122 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
15123 #endif
15124
15125 return 0;
15126 }
15127
15128
15129
15130 #define PROBE(name, test) \
15131 static int name(void) \
15132 { \
15133 if (test) { \
15134 return 1; \
15135 } else { \
15136 return 0; \
15137 } \
15138 }
15139
15140 #ifdef HAVE_FSTATAT
15141 PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
15142 #endif
15143
15144 #ifdef HAVE_FACCESSAT
15145 PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
15146 #endif
15147
15148 #ifdef HAVE_FCHMODAT
15149 PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
15150 #endif
15151
15152 #ifdef HAVE_FCHOWNAT
15153 PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
15154 #endif
15155
15156 #ifdef HAVE_LINKAT
15157 PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
15158 #endif
15159
15160 #ifdef HAVE_FDOPENDIR
15161 PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
15162 #endif
15163
15164 #ifdef HAVE_MKDIRAT
15165 PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
15166 #endif
15167
15168 #ifdef HAVE_RENAMEAT
15169 PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
15170 #endif
15171
15172 #ifdef HAVE_UNLINKAT
15173 PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
15174 #endif
15175
15176 #ifdef HAVE_OPENAT
15177 PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
15178 #endif
15179
15180 #ifdef HAVE_READLINKAT
15181 PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
15182 #endif
15183
15184 #ifdef HAVE_SYMLINKAT
15185 PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
15186 #endif
15187
15188 #ifdef HAVE_FUTIMENS
15189 PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
15190 #endif
15191
15192 #ifdef HAVE_UTIMENSAT
15193 PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
15194 #endif
15195
15196
15197
15198
15199 static const struct have_function {
15200 const char * const label;
15201 int (*probe)(void);
15202 } have_functions[] = {
15203
15204 #ifdef HAVE_FACCESSAT
15205 { "HAVE_FACCESSAT", probe_faccessat },
15206 #endif
15207
15208 #ifdef HAVE_FCHDIR
15209 { "HAVE_FCHDIR", NULL },
15210 #endif
15211
15212 #ifdef HAVE_FCHMOD
15213 { "HAVE_FCHMOD", NULL },
15214 #endif
15215
15216 #ifdef HAVE_FCHMODAT
15217 { "HAVE_FCHMODAT", probe_fchmodat },
15218 #endif
15219
15220 #ifdef HAVE_FCHOWN
15221 { "HAVE_FCHOWN", NULL },
15222 #endif
15223
15224 #ifdef HAVE_FCHOWNAT
15225 { "HAVE_FCHOWNAT", probe_fchownat },
15226 #endif
15227
15228 #ifdef HAVE_FEXECVE
15229 { "HAVE_FEXECVE", NULL },
15230 #endif
15231
15232 #ifdef HAVE_FDOPENDIR
15233 { "HAVE_FDOPENDIR", probe_fdopendir },
15234 #endif
15235
15236 #ifdef HAVE_FPATHCONF
15237 { "HAVE_FPATHCONF", NULL },
15238 #endif
15239
15240 #ifdef HAVE_FSTATAT
15241 { "HAVE_FSTATAT", probe_fstatat },
15242 #endif
15243
15244 #ifdef HAVE_FSTATVFS
15245 { "HAVE_FSTATVFS", NULL },
15246 #endif
15247
15248 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
15249 { "HAVE_FTRUNCATE", NULL },
15250 #endif
15251
15252 #ifdef HAVE_FUTIMENS
15253 { "HAVE_FUTIMENS", probe_futimens },
15254 #endif
15255
15256 #ifdef HAVE_FUTIMES
15257 { "HAVE_FUTIMES", NULL },
15258 #endif
15259
15260 #ifdef HAVE_FUTIMESAT
15261 { "HAVE_FUTIMESAT", NULL },
15262 #endif
15263
15264 #ifdef HAVE_LINKAT
15265 { "HAVE_LINKAT", probe_linkat },
15266 #endif
15267
15268 #ifdef HAVE_LCHFLAGS
15269 { "HAVE_LCHFLAGS", NULL },
15270 #endif
15271
15272 #ifdef HAVE_LCHMOD
15273 { "HAVE_LCHMOD", NULL },
15274 #endif
15275
15276 #ifdef HAVE_LCHOWN
15277 { "HAVE_LCHOWN", NULL },
15278 #endif
15279
15280 #ifdef HAVE_LSTAT
15281 { "HAVE_LSTAT", NULL },
15282 #endif
15283
15284 #ifdef HAVE_LUTIMES
15285 { "HAVE_LUTIMES", NULL },
15286 #endif
15287
15288 #ifdef HAVE_MEMFD_CREATE
15289 { "HAVE_MEMFD_CREATE", NULL },
15290 #endif
15291
15292 #ifdef HAVE_MKDIRAT
15293 { "HAVE_MKDIRAT", probe_mkdirat },
15294 #endif
15295
15296 #ifdef HAVE_MKFIFOAT
15297 { "HAVE_MKFIFOAT", NULL },
15298 #endif
15299
15300 #ifdef HAVE_MKNODAT
15301 { "HAVE_MKNODAT", NULL },
15302 #endif
15303
15304 #ifdef HAVE_OPENAT
15305 { "HAVE_OPENAT", probe_openat },
15306 #endif
15307
15308 #ifdef HAVE_READLINKAT
15309 { "HAVE_READLINKAT", probe_readlinkat },
15310 #endif
15311
15312 #ifdef HAVE_RENAMEAT
15313 { "HAVE_RENAMEAT", probe_renameat },
15314 #endif
15315
15316 #ifdef HAVE_SYMLINKAT
15317 { "HAVE_SYMLINKAT", probe_symlinkat },
15318 #endif
15319
15320 #ifdef HAVE_UNLINKAT
15321 { "HAVE_UNLINKAT", probe_unlinkat },
15322 #endif
15323
15324 #ifdef HAVE_UTIMENSAT
15325 { "HAVE_UTIMENSAT", probe_utimensat },
15326 #endif
15327
15328 #ifdef MS_WINDOWS
15329 { "MS_WINDOWS", NULL },
15330 #endif
15331
15332 { NULL, NULL }
15333 };
15334
15335
15336 static int
posixmodule_exec(PyObject * m)15337 posixmodule_exec(PyObject *m)
15338 {
15339 _posixstate *state = get_posix_state(m);
15340
15341 #if defined(HAVE_PWRITEV)
15342 if (HAVE_PWRITEV_RUNTIME) {} else {
15343 PyObject* dct = PyModule_GetDict(m);
15344
15345 if (dct == NULL) {
15346 return -1;
15347 }
15348
15349 if (PyDict_DelItemString(dct, "pwritev") == -1) {
15350 PyErr_Clear();
15351 }
15352 if (PyDict_DelItemString(dct, "preadv") == -1) {
15353 PyErr_Clear();
15354 }
15355 }
15356 #endif
15357
15358 /* Initialize environ dictionary */
15359 PyObject *v = convertenviron();
15360 Py_XINCREF(v);
15361 if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
15362 return -1;
15363 Py_DECREF(v);
15364
15365 if (all_ins(m))
15366 return -1;
15367
15368 if (setup_confname_tables(m))
15369 return -1;
15370
15371 Py_INCREF(PyExc_OSError);
15372 PyModule_AddObject(m, "error", PyExc_OSError);
15373
15374 #if defined(HAVE_WAITID) && !defined(__APPLE__)
15375 waitid_result_desc.name = MODNAME ".waitid_result";
15376 PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
15377 if (WaitidResultType == NULL) {
15378 return -1;
15379 }
15380 Py_INCREF(WaitidResultType);
15381 PyModule_AddObject(m, "waitid_result", WaitidResultType);
15382 state->WaitidResultType = WaitidResultType;
15383 #endif
15384
15385 stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
15386 stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
15387 stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
15388 stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
15389 PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
15390 if (StatResultType == NULL) {
15391 return -1;
15392 }
15393 Py_INCREF(StatResultType);
15394 PyModule_AddObject(m, "stat_result", StatResultType);
15395 state->StatResultType = StatResultType;
15396 structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15397 ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
15398
15399 statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
15400 PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
15401 if (StatVFSResultType == NULL) {
15402 return -1;
15403 }
15404 Py_INCREF(StatVFSResultType);
15405 PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
15406 state->StatVFSResultType = StatVFSResultType;
15407 #ifdef NEED_TICKS_PER_SECOND
15408 # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15409 ticks_per_second = sysconf(_SC_CLK_TCK);
15410 # elif defined(HZ)
15411 ticks_per_second = HZ;
15412 # else
15413 ticks_per_second = 60; /* magic fallback value; may be bogus */
15414 # endif
15415 #endif
15416
15417 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
15418 sched_param_desc.name = MODNAME ".sched_param";
15419 PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
15420 if (SchedParamType == NULL) {
15421 return -1;
15422 }
15423 Py_INCREF(SchedParamType);
15424 PyModule_AddObject(m, "sched_param", SchedParamType);
15425 state->SchedParamType = SchedParamType;
15426 ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
15427 #endif
15428
15429 /* initialize TerminalSize_info */
15430 PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
15431 if (TerminalSizeType == NULL) {
15432 return -1;
15433 }
15434 Py_INCREF(TerminalSizeType);
15435 PyModule_AddObject(m, "terminal_size", TerminalSizeType);
15436 state->TerminalSizeType = TerminalSizeType;
15437
15438 /* initialize scandir types */
15439 PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
15440 if (ScandirIteratorType == NULL) {
15441 return -1;
15442 }
15443 state->ScandirIteratorType = ScandirIteratorType;
15444
15445 PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
15446 if (DirEntryType == NULL) {
15447 return -1;
15448 }
15449 Py_INCREF(DirEntryType);
15450 PyModule_AddObject(m, "DirEntry", DirEntryType);
15451 state->DirEntryType = DirEntryType;
15452
15453 times_result_desc.name = MODNAME ".times_result";
15454 PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(×_result_desc);
15455 if (TimesResultType == NULL) {
15456 return -1;
15457 }
15458 Py_INCREF(TimesResultType);
15459 PyModule_AddObject(m, "times_result", TimesResultType);
15460 state->TimesResultType = TimesResultType;
15461
15462 PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
15463 if (UnameResultType == NULL) {
15464 return -1;
15465 }
15466 Py_INCREF(UnameResultType);
15467 PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
15468 state->UnameResultType = (PyObject *)UnameResultType;
15469
15470 if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
15471 return -1;
15472 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
15473 state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
15474 if (state->struct_rusage == NULL)
15475 return -1;
15476 #endif
15477 state->st_mode = PyUnicode_InternFromString("st_mode");
15478 if (state->st_mode == NULL)
15479 return -1;
15480
15481 /* suppress "function not used" warnings */
15482 {
15483 int ignored;
15484 fd_specified("", -1);
15485 follow_symlinks_specified("", 1);
15486 dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
15487 dir_fd_converter(Py_None, &ignored);
15488 dir_fd_unavailable(Py_None, &ignored);
15489 }
15490
15491 /*
15492 * provide list of locally available functions
15493 * so os.py can populate support_* lists
15494 */
15495 PyObject *list = PyList_New(0);
15496 if (!list) {
15497 return -1;
15498 }
15499 for (const struct have_function *trace = have_functions; trace->label; trace++) {
15500 PyObject *unicode;
15501 if (trace->probe && !trace->probe()) continue;
15502 unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
15503 if (!unicode)
15504 return -1;
15505 if (PyList_Append(list, unicode))
15506 return -1;
15507 Py_DECREF(unicode);
15508 }
15509
15510 PyModule_AddObject(m, "_have_functions", list);
15511
15512 return 0;
15513 }
15514
15515
15516 static PyModuleDef_Slot posixmodile_slots[] = {
15517 {Py_mod_exec, posixmodule_exec},
15518 {0, NULL}
15519 };
15520
15521 static struct PyModuleDef posixmodule = {
15522 PyModuleDef_HEAD_INIT,
15523 .m_name = MODNAME,
15524 .m_doc = posix__doc__,
15525 .m_size = sizeof(_posixstate),
15526 .m_methods = posix_methods,
15527 .m_slots = posixmodile_slots,
15528 .m_traverse = _posix_traverse,
15529 .m_clear = _posix_clear,
15530 .m_free = _posix_free,
15531 };
15532
15533 PyMODINIT_FUNC
INITFUNC(void)15534 INITFUNC(void)
15535 {
15536 return PyModuleDef_Init(&posixmodule);
15537 }
15538
15539 #ifdef __cplusplus
15540 }
15541 #endif
15542