1
2 /* POSIX module implementation */
3
4 /* This file is also used for Windows NT/MS-Win. In that case the
5 module actually calls itself 'nt', not 'posix', and a few
6 functions are either unimplemented or implemented differently. The source
7 assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
8 of the compiler used. Different compilers define their own feature
9 test macro, e.g. '_MSC_VER'. */
10
11
12
13 #ifdef __APPLE__
14 /*
15 * Step 1 of support for weak-linking a number of symbols existing on
16 * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block
17 * at the end of this file for more information.
18 */
19 # pragma weak lchown
20 # pragma weak statvfs
21 # pragma weak fstatvfs
22
23 #endif /* __APPLE__ */
24
25 #define PY_SSIZE_T_CLEAN
26
27 #include "Python.h"
28 #ifdef MS_WINDOWS
29 /* include <windows.h> early to avoid conflict with pycore_condvar.h:
30
31 #define WIN32_LEAN_AND_MEAN
32 #include <windows.h>
33
34 FSCTL_GET_REPARSE_POINT is not exported with WIN32_LEAN_AND_MEAN. */
35 # include <windows.h>
36 #endif
37
38 #include "pycore_ceval.h" /* _PyEval_ReInitThreads() */
39 #include "pycore_pystate.h" /* _PyRuntime */
40 #include "pythread.h"
41 #include "structmember.h"
42 #ifndef MS_WINDOWS
43 # include "posixmodule.h"
44 #else
45 # include "winreparse.h"
46 #endif
47
48 /* On android API level 21, 'AT_EACCESS' is not declared although
49 * HAVE_FACCESSAT is defined. */
50 #ifdef __BIONIC__
51 #undef HAVE_FACCESSAT
52 #endif
53
54 #include <stdio.h> /* needed for ctermid() */
55
56 #ifdef __cplusplus
57 extern "C" {
58 #endif
59
60 PyDoc_STRVAR(posix__doc__,
61 "This module provides access to operating system functionality that is\n\
62 standardized by the C Standard and the POSIX standard (a thinly\n\
63 disguised Unix interface). Refer to the library manual and\n\
64 corresponding Unix manual entries for more information on calls.");
65
66
67 #ifdef HAVE_SYS_UIO_H
68 #include <sys/uio.h>
69 #endif
70
71 #ifdef HAVE_SYS_SYSMACROS_H
72 /* GNU C Library: major(), minor(), makedev() */
73 #include <sys/sysmacros.h>
74 #endif
75
76 #ifdef HAVE_SYS_TYPES_H
77 #include <sys/types.h>
78 #endif /* HAVE_SYS_TYPES_H */
79
80 #ifdef HAVE_SYS_STAT_H
81 #include <sys/stat.h>
82 #endif /* HAVE_SYS_STAT_H */
83
84 #ifdef HAVE_SYS_WAIT_H
85 #include <sys/wait.h> /* For WNOHANG */
86 #endif
87
88 #ifdef HAVE_SIGNAL_H
89 #include <signal.h>
90 #endif
91
92 #ifdef HAVE_FCNTL_H
93 #include <fcntl.h>
94 #endif /* HAVE_FCNTL_H */
95
96 #ifdef HAVE_GRP_H
97 #include <grp.h>
98 #endif
99
100 #ifdef HAVE_SYSEXITS_H
101 #include <sysexits.h>
102 #endif /* HAVE_SYSEXITS_H */
103
104 #ifdef HAVE_SYS_LOADAVG_H
105 #include <sys/loadavg.h>
106 #endif
107
108 #ifdef HAVE_SYS_SENDFILE_H
109 #include <sys/sendfile.h>
110 #endif
111
112 #if defined(__APPLE__)
113 #include <copyfile.h>
114 #endif
115
116 #ifdef HAVE_SCHED_H
117 #include <sched.h>
118 #endif
119
120 #ifdef HAVE_COPY_FILE_RANGE
121 #include <unistd.h>
122 #endif
123
124 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
125 #undef HAVE_SCHED_SETAFFINITY
126 #endif
127
128 #if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
129 #define USE_XATTRS
130 #endif
131
132 #ifdef USE_XATTRS
133 #include <sys/xattr.h>
134 #endif
135
136 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
137 #ifdef HAVE_SYS_SOCKET_H
138 #include <sys/socket.h>
139 #endif
140 #endif
141
142 #ifdef HAVE_DLFCN_H
143 #include <dlfcn.h>
144 #endif
145
146 #ifdef __hpux
147 #include <sys/mpctl.h>
148 #endif
149
150 #if defined(__DragonFly__) || \
151 defined(__OpenBSD__) || \
152 defined(__FreeBSD__) || \
153 defined(__NetBSD__) || \
154 defined(__APPLE__)
155 #include <sys/sysctl.h>
156 #endif
157
158 #ifdef HAVE_LINUX_RANDOM_H
159 # include <linux/random.h>
160 #endif
161 #ifdef HAVE_GETRANDOM_SYSCALL
162 # include <sys/syscall.h>
163 #endif
164
165 #if defined(MS_WINDOWS)
166 # define TERMSIZE_USE_CONIO
167 #elif defined(HAVE_SYS_IOCTL_H)
168 # include <sys/ioctl.h>
169 # if defined(HAVE_TERMIOS_H)
170 # include <termios.h>
171 # endif
172 # if defined(TIOCGWINSZ)
173 # define TERMSIZE_USE_IOCTL
174 # endif
175 #endif /* MS_WINDOWS */
176
177 /* Various compilers have only certain posix functions */
178 /* XXX Gosh I wish these were all moved into pyconfig.h */
179 #if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */
180 #define HAVE_OPENDIR 1
181 #define HAVE_SYSTEM 1
182 #include <process.h>
183 #else
184 #ifdef _MSC_VER /* Microsoft compiler */
185 #define HAVE_GETPPID 1
186 #define HAVE_GETLOGIN 1
187 #define HAVE_SPAWNV 1
188 #define HAVE_EXECV 1
189 #define HAVE_WSPAWNV 1
190 #define HAVE_WEXECV 1
191 #define HAVE_PIPE 1
192 #define HAVE_SYSTEM 1
193 #define HAVE_CWAIT 1
194 #define HAVE_FSYNC 1
195 #define fsync _commit
196 #else
197 /* Unix functions that the configure script doesn't check for */
198 #ifndef __VXWORKS__
199 #define HAVE_EXECV 1
200 #define HAVE_FORK 1
201 #if defined(__USLC__) && defined(__SCO_VERSION__) /* SCO UDK Compiler */
202 #define HAVE_FORK1 1
203 #endif
204 #endif
205 #define HAVE_GETEGID 1
206 #define HAVE_GETEUID 1
207 #define HAVE_GETGID 1
208 #define HAVE_GETPPID 1
209 #define HAVE_GETUID 1
210 #define HAVE_KILL 1
211 #define HAVE_OPENDIR 1
212 #define HAVE_PIPE 1
213 #define HAVE_SYSTEM 1
214 #define HAVE_WAIT 1
215 #define HAVE_TTYNAME 1
216 #endif /* _MSC_VER */
217 #endif /* ! __WATCOMC__ || __QNX__ */
218
219
220 /*[clinic input]
221 # one of the few times we lie about this name!
222 module os
223 [clinic start generated code]*/
224 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
225
226 #ifndef _MSC_VER
227
228 #if defined(__sgi)&&_COMPILER_VERSION>=700
229 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
230 (default) */
231 extern char *ctermid_r(char *);
232 #endif
233
234 #endif /* !_MSC_VER */
235
236 #if defined(__VXWORKS__)
237 #include <vxCpuLib.h>
238 #include <rtpLib.h>
239 #include <wait.h>
240 #include <taskLib.h>
241 #ifndef _P_WAIT
242 #define _P_WAIT 0
243 #define _P_NOWAIT 1
244 #define _P_NOWAITO 1
245 #endif
246 #endif /* __VXWORKS__ */
247
248 #ifdef HAVE_POSIX_SPAWN
249 #include <spawn.h>
250 #endif
251
252 #ifdef HAVE_UTIME_H
253 #include <utime.h>
254 #endif /* HAVE_UTIME_H */
255
256 #ifdef HAVE_SYS_UTIME_H
257 #include <sys/utime.h>
258 #define HAVE_UTIME_H /* pretend we do for the rest of this file */
259 #endif /* HAVE_SYS_UTIME_H */
260
261 #ifdef HAVE_SYS_TIMES_H
262 #include <sys/times.h>
263 #endif /* HAVE_SYS_TIMES_H */
264
265 #ifdef HAVE_SYS_PARAM_H
266 #include <sys/param.h>
267 #endif /* HAVE_SYS_PARAM_H */
268
269 #ifdef HAVE_SYS_UTSNAME_H
270 #include <sys/utsname.h>
271 #endif /* HAVE_SYS_UTSNAME_H */
272
273 #ifdef HAVE_DIRENT_H
274 #include <dirent.h>
275 #define NAMLEN(dirent) strlen((dirent)->d_name)
276 #else
277 #if defined(__WATCOMC__) && !defined(__QNX__)
278 #include <direct.h>
279 #define NAMLEN(dirent) strlen((dirent)->d_name)
280 #else
281 #define dirent direct
282 #define NAMLEN(dirent) (dirent)->d_namlen
283 #endif
284 #ifdef HAVE_SYS_NDIR_H
285 #include <sys/ndir.h>
286 #endif
287 #ifdef HAVE_SYS_DIR_H
288 #include <sys/dir.h>
289 #endif
290 #ifdef HAVE_NDIR_H
291 #include <ndir.h>
292 #endif
293 #endif
294
295 #ifdef _MSC_VER
296 #ifdef HAVE_DIRECT_H
297 #include <direct.h>
298 #endif
299 #ifdef HAVE_IO_H
300 #include <io.h>
301 #endif
302 #ifdef HAVE_PROCESS_H
303 #include <process.h>
304 #endif
305 #ifndef IO_REPARSE_TAG_SYMLINK
306 #define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
307 #endif
308 #ifndef IO_REPARSE_TAG_MOUNT_POINT
309 #define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
310 #endif
311 #include "osdefs.h"
312 #include <malloc.h>
313 #include <windows.h>
314 #include <shellapi.h> /* for ShellExecute() */
315 #include <lmcons.h> /* for UNLEN */
316 #define HAVE_SYMLINK
317 #endif /* _MSC_VER */
318
319 #ifndef MAXPATHLEN
320 #if defined(PATH_MAX) && PATH_MAX > 1024
321 #define MAXPATHLEN PATH_MAX
322 #else
323 #define MAXPATHLEN 1024
324 #endif
325 #endif /* MAXPATHLEN */
326
327 #ifdef UNION_WAIT
328 /* Emulate some macros on systems that have a union instead of macros */
329
330 #ifndef WIFEXITED
331 #define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
332 #endif
333
334 #ifndef WEXITSTATUS
335 #define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
336 #endif
337
338 #ifndef WTERMSIG
339 #define WTERMSIG(u_wait) ((u_wait).w_termsig)
340 #endif
341
342 #define WAIT_TYPE union wait
343 #define WAIT_STATUS_INT(s) (s.w_status)
344
345 #else /* !UNION_WAIT */
346 #define WAIT_TYPE int
347 #define WAIT_STATUS_INT(s) (s)
348 #endif /* UNION_WAIT */
349
350 /* Don't use the "_r" form if we don't need it (also, won't have a
351 prototype for it, at least on Solaris -- maybe others as well?). */
352 #if defined(HAVE_CTERMID_R)
353 #define USE_CTERMID_R
354 #endif
355
356 /* choose the appropriate stat and fstat functions and return structs */
357 #undef STAT
358 #undef FSTAT
359 #undef STRUCT_STAT
360 #ifdef MS_WINDOWS
361 # define STAT win32_stat
362 # define LSTAT win32_lstat
363 # define FSTAT _Py_fstat_noraise
364 # define STRUCT_STAT struct _Py_stat_struct
365 #else
366 # define STAT stat
367 # define LSTAT lstat
368 # define FSTAT fstat
369 # define STRUCT_STAT struct stat
370 #endif
371
372 #if defined(MAJOR_IN_MKDEV)
373 #include <sys/mkdev.h>
374 #else
375 #if defined(MAJOR_IN_SYSMACROS)
376 #include <sys/sysmacros.h>
377 #endif
378 #if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
379 #include <sys/mkdev.h>
380 #endif
381 #endif
382
383 #ifdef MS_WINDOWS
384 #define INITFUNC PyInit_nt
385 #define MODNAME "nt"
386 #else
387 #define INITFUNC PyInit_posix
388 #define MODNAME "posix"
389 #endif
390
391 #if defined(__sun)
392 /* Something to implement in autoconf, not present in autoconf 2.69 */
393 #define HAVE_STRUCT_STAT_ST_FSTYPE 1
394 #endif
395
396 /* memfd_create is either defined in sys/mman.h or sys/memfd.h
397 * linux/memfd.h defines additional flags
398 */
399 #ifdef HAVE_SYS_MMAN_H
400 #include <sys/mman.h>
401 #endif
402 #ifdef HAVE_SYS_MEMFD_H
403 #include <sys/memfd.h>
404 #endif
405 #ifdef HAVE_LINUX_MEMFD_H
406 #include <linux/memfd.h>
407 #endif
408
409 #ifdef _Py_MEMORY_SANITIZER
410 # include <sanitizer/msan_interface.h>
411 #endif
412
413 #ifdef HAVE_FORK
414 static void
run_at_forkers(PyObject * lst,int reverse)415 run_at_forkers(PyObject *lst, int reverse)
416 {
417 Py_ssize_t i;
418 PyObject *cpy;
419
420 if (lst != NULL) {
421 assert(PyList_CheckExact(lst));
422
423 /* Use a list copy in case register_at_fork() is called from
424 * one of the callbacks.
425 */
426 cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
427 if (cpy == NULL)
428 PyErr_WriteUnraisable(lst);
429 else {
430 if (reverse)
431 PyList_Reverse(cpy);
432 for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
433 PyObject *func, *res;
434 func = PyList_GET_ITEM(cpy, i);
435 res = PyObject_CallObject(func, NULL);
436 if (res == NULL)
437 PyErr_WriteUnraisable(func);
438 else
439 Py_DECREF(res);
440 }
441 Py_DECREF(cpy);
442 }
443 }
444 }
445
446 void
PyOS_BeforeFork(void)447 PyOS_BeforeFork(void)
448 {
449 run_at_forkers(_PyInterpreterState_Get()->before_forkers, 1);
450
451 _PyImport_AcquireLock();
452 }
453
454 void
PyOS_AfterFork_Parent(void)455 PyOS_AfterFork_Parent(void)
456 {
457 if (_PyImport_ReleaseLock() <= 0)
458 Py_FatalError("failed releasing import lock after fork");
459
460 run_at_forkers(_PyInterpreterState_Get()->after_forkers_parent, 0);
461 }
462
463 void
PyOS_AfterFork_Child(void)464 PyOS_AfterFork_Child(void)
465 {
466 _PyRuntimeState *runtime = &_PyRuntime;
467 _PyGILState_Reinit(runtime);
468 _PyEval_ReInitThreads(runtime);
469 _PyImport_ReInitLock();
470 _PySignal_AfterFork();
471 _PyRuntimeState_ReInitThreads(runtime);
472 _PyInterpreterState_DeleteExceptMain(runtime);
473
474 run_at_forkers(_PyInterpreterState_Get()->after_forkers_child, 0);
475 }
476
477 static int
register_at_forker(PyObject ** lst,PyObject * func)478 register_at_forker(PyObject **lst, PyObject *func)
479 {
480 if (func == NULL) /* nothing to register? do nothing. */
481 return 0;
482 if (*lst == NULL) {
483 *lst = PyList_New(0);
484 if (*lst == NULL)
485 return -1;
486 }
487 return PyList_Append(*lst, func);
488 }
489 #endif
490
491 /* Legacy wrapper */
492 void
PyOS_AfterFork(void)493 PyOS_AfterFork(void)
494 {
495 #ifdef HAVE_FORK
496 PyOS_AfterFork_Child();
497 #endif
498 }
499
500
501 #ifdef MS_WINDOWS
502 /* defined in fileutils.c */
503 void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
504 void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
505 ULONG, struct _Py_stat_struct *);
506 #endif
507
508
509 #ifndef MS_WINDOWS
510 PyObject *
_PyLong_FromUid(uid_t uid)511 _PyLong_FromUid(uid_t uid)
512 {
513 if (uid == (uid_t)-1)
514 return PyLong_FromLong(-1);
515 return PyLong_FromUnsignedLong(uid);
516 }
517
518 PyObject *
_PyLong_FromGid(gid_t gid)519 _PyLong_FromGid(gid_t gid)
520 {
521 if (gid == (gid_t)-1)
522 return PyLong_FromLong(-1);
523 return PyLong_FromUnsignedLong(gid);
524 }
525
526 int
_Py_Uid_Converter(PyObject * obj,void * p)527 _Py_Uid_Converter(PyObject *obj, void *p)
528 {
529 uid_t uid;
530 PyObject *index;
531 int overflow;
532 long result;
533 unsigned long uresult;
534
535 index = PyNumber_Index(obj);
536 if (index == NULL) {
537 PyErr_Format(PyExc_TypeError,
538 "uid should be integer, not %.200s",
539 Py_TYPE(obj)->tp_name);
540 return 0;
541 }
542
543 /*
544 * Handling uid_t is complicated for two reasons:
545 * * Although uid_t is (always?) unsigned, it still
546 * accepts -1.
547 * * We don't know its size in advance--it may be
548 * bigger than an int, or it may be smaller than
549 * a long.
550 *
551 * So a bit of defensive programming is in order.
552 * Start with interpreting the value passed
553 * in as a signed long and see if it works.
554 */
555
556 result = PyLong_AsLongAndOverflow(index, &overflow);
557
558 if (!overflow) {
559 uid = (uid_t)result;
560
561 if (result == -1) {
562 if (PyErr_Occurred())
563 goto fail;
564 /* It's a legitimate -1, we're done. */
565 goto success;
566 }
567
568 /* Any other negative number is disallowed. */
569 if (result < 0)
570 goto underflow;
571
572 /* Ensure the value wasn't truncated. */
573 if (sizeof(uid_t) < sizeof(long) &&
574 (long)uid != result)
575 goto underflow;
576 goto success;
577 }
578
579 if (overflow < 0)
580 goto underflow;
581
582 /*
583 * Okay, the value overflowed a signed long. If it
584 * fits in an *unsigned* long, it may still be okay,
585 * as uid_t may be unsigned long on this platform.
586 */
587 uresult = PyLong_AsUnsignedLong(index);
588 if (PyErr_Occurred()) {
589 if (PyErr_ExceptionMatches(PyExc_OverflowError))
590 goto overflow;
591 goto fail;
592 }
593
594 uid = (uid_t)uresult;
595
596 /*
597 * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
598 * but this value would get interpreted as (uid_t)-1 by chown
599 * and its siblings. That's not what the user meant! So we
600 * throw an overflow exception instead. (We already
601 * handled a real -1 with PyLong_AsLongAndOverflow() above.)
602 */
603 if (uid == (uid_t)-1)
604 goto overflow;
605
606 /* Ensure the value wasn't truncated. */
607 if (sizeof(uid_t) < sizeof(long) &&
608 (unsigned long)uid != uresult)
609 goto overflow;
610 /* fallthrough */
611
612 success:
613 Py_DECREF(index);
614 *(uid_t *)p = uid;
615 return 1;
616
617 underflow:
618 PyErr_SetString(PyExc_OverflowError,
619 "uid is less than minimum");
620 goto fail;
621
622 overflow:
623 PyErr_SetString(PyExc_OverflowError,
624 "uid is greater than maximum");
625 /* fallthrough */
626
627 fail:
628 Py_DECREF(index);
629 return 0;
630 }
631
632 int
_Py_Gid_Converter(PyObject * obj,void * p)633 _Py_Gid_Converter(PyObject *obj, void *p)
634 {
635 gid_t gid;
636 PyObject *index;
637 int overflow;
638 long result;
639 unsigned long uresult;
640
641 index = PyNumber_Index(obj);
642 if (index == NULL) {
643 PyErr_Format(PyExc_TypeError,
644 "gid should be integer, not %.200s",
645 Py_TYPE(obj)->tp_name);
646 return 0;
647 }
648
649 /*
650 * Handling gid_t is complicated for two reasons:
651 * * Although gid_t is (always?) unsigned, it still
652 * accepts -1.
653 * * We don't know its size in advance--it may be
654 * bigger than an int, or it may be smaller than
655 * a long.
656 *
657 * So a bit of defensive programming is in order.
658 * Start with interpreting the value passed
659 * in as a signed long and see if it works.
660 */
661
662 result = PyLong_AsLongAndOverflow(index, &overflow);
663
664 if (!overflow) {
665 gid = (gid_t)result;
666
667 if (result == -1) {
668 if (PyErr_Occurred())
669 goto fail;
670 /* It's a legitimate -1, we're done. */
671 goto success;
672 }
673
674 /* Any other negative number is disallowed. */
675 if (result < 0) {
676 goto underflow;
677 }
678
679 /* Ensure the value wasn't truncated. */
680 if (sizeof(gid_t) < sizeof(long) &&
681 (long)gid != result)
682 goto underflow;
683 goto success;
684 }
685
686 if (overflow < 0)
687 goto underflow;
688
689 /*
690 * Okay, the value overflowed a signed long. If it
691 * fits in an *unsigned* long, it may still be okay,
692 * as gid_t may be unsigned long on this platform.
693 */
694 uresult = PyLong_AsUnsignedLong(index);
695 if (PyErr_Occurred()) {
696 if (PyErr_ExceptionMatches(PyExc_OverflowError))
697 goto overflow;
698 goto fail;
699 }
700
701 gid = (gid_t)uresult;
702
703 /*
704 * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
705 * but this value would get interpreted as (gid_t)-1 by chown
706 * and its siblings. That's not what the user meant! So we
707 * throw an overflow exception instead. (We already
708 * handled a real -1 with PyLong_AsLongAndOverflow() above.)
709 */
710 if (gid == (gid_t)-1)
711 goto overflow;
712
713 /* Ensure the value wasn't truncated. */
714 if (sizeof(gid_t) < sizeof(long) &&
715 (unsigned long)gid != uresult)
716 goto overflow;
717 /* fallthrough */
718
719 success:
720 Py_DECREF(index);
721 *(gid_t *)p = gid;
722 return 1;
723
724 underflow:
725 PyErr_SetString(PyExc_OverflowError,
726 "gid is less than minimum");
727 goto fail;
728
729 overflow:
730 PyErr_SetString(PyExc_OverflowError,
731 "gid is greater than maximum");
732 /* fallthrough */
733
734 fail:
735 Py_DECREF(index);
736 return 0;
737 }
738 #endif /* MS_WINDOWS */
739
740
741 #define _PyLong_FromDev PyLong_FromLongLong
742
743
744 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
745 static int
_Py_Dev_Converter(PyObject * obj,void * p)746 _Py_Dev_Converter(PyObject *obj, void *p)
747 {
748 *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
749 if (PyErr_Occurred())
750 return 0;
751 return 1;
752 }
753 #endif /* HAVE_MKNOD && HAVE_MAKEDEV */
754
755
756 #ifdef AT_FDCWD
757 /*
758 * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
759 * without the int cast, the value gets interpreted as uint (4291925331),
760 * which doesn't play nicely with all the initializer lines in this file that
761 * look like this:
762 * int dir_fd = DEFAULT_DIR_FD;
763 */
764 #define DEFAULT_DIR_FD (int)AT_FDCWD
765 #else
766 #define DEFAULT_DIR_FD (-100)
767 #endif
768
769 static int
_fd_converter(PyObject * o,int * p)770 _fd_converter(PyObject *o, int *p)
771 {
772 int overflow;
773 long long_value;
774
775 PyObject *index = PyNumber_Index(o);
776 if (index == NULL) {
777 return 0;
778 }
779
780 assert(PyLong_Check(index));
781 long_value = PyLong_AsLongAndOverflow(index, &overflow);
782 Py_DECREF(index);
783 assert(!PyErr_Occurred());
784 if (overflow > 0 || long_value > INT_MAX) {
785 PyErr_SetString(PyExc_OverflowError,
786 "fd is greater than maximum");
787 return 0;
788 }
789 if (overflow < 0 || long_value < INT_MIN) {
790 PyErr_SetString(PyExc_OverflowError,
791 "fd is less than minimum");
792 return 0;
793 }
794
795 *p = (int)long_value;
796 return 1;
797 }
798
799 static int
dir_fd_converter(PyObject * o,void * p)800 dir_fd_converter(PyObject *o, void *p)
801 {
802 if (o == Py_None) {
803 *(int *)p = DEFAULT_DIR_FD;
804 return 1;
805 }
806 else if (PyIndex_Check(o)) {
807 return _fd_converter(o, (int *)p);
808 }
809 else {
810 PyErr_Format(PyExc_TypeError,
811 "argument should be integer or None, not %.200s",
812 Py_TYPE(o)->tp_name);
813 return 0;
814 }
815 }
816
817
818 /*
819 * A PyArg_ParseTuple "converter" function
820 * that handles filesystem paths in the manner
821 * preferred by the os module.
822 *
823 * path_converter accepts (Unicode) strings and their
824 * subclasses, and bytes and their subclasses. What
825 * it does with the argument depends on the platform:
826 *
827 * * On Windows, if we get a (Unicode) string we
828 * extract the wchar_t * and return it; if we get
829 * bytes we decode to wchar_t * and return that.
830 *
831 * * On all other platforms, strings are encoded
832 * to bytes using PyUnicode_FSConverter, then we
833 * extract the char * from the bytes object and
834 * return that.
835 *
836 * path_converter also optionally accepts signed
837 * integers (representing open file descriptors) instead
838 * of path strings.
839 *
840 * Input fields:
841 * path.nullable
842 * If nonzero, the path is permitted to be None.
843 * path.allow_fd
844 * If nonzero, the path is permitted to be a file handle
845 * (a signed int) instead of a string.
846 * path.function_name
847 * If non-NULL, path_converter will use that as the name
848 * of the function in error messages.
849 * (If path.function_name is NULL it omits the function name.)
850 * path.argument_name
851 * If non-NULL, path_converter will use that as the name
852 * of the parameter in error messages.
853 * (If path.argument_name is NULL it uses "path".)
854 *
855 * Output fields:
856 * path.wide
857 * Points to the path if it was expressed as Unicode
858 * and was not encoded. (Only used on Windows.)
859 * path.narrow
860 * Points to the path if it was expressed as bytes,
861 * or it was Unicode and was encoded to bytes. (On Windows,
862 * is a non-zero integer if the path was expressed as bytes.
863 * The type is deliberately incompatible to prevent misuse.)
864 * path.fd
865 * Contains a file descriptor if path.accept_fd was true
866 * and the caller provided a signed integer instead of any
867 * sort of string.
868 *
869 * WARNING: if your "path" parameter is optional, and is
870 * unspecified, path_converter will never get called.
871 * So if you set allow_fd, you *MUST* initialize path.fd = -1
872 * yourself!
873 * path.length
874 * The length of the path in characters, if specified as
875 * a string.
876 * path.object
877 * The original object passed in (if get a PathLike object,
878 * the result of PyOS_FSPath() is treated as the original object).
879 * Own a reference to the object.
880 * path.cleanup
881 * For internal use only. May point to a temporary object.
882 * (Pay no attention to the man behind the curtain.)
883 *
884 * At most one of path.wide or path.narrow will be non-NULL.
885 * If path was None and path.nullable was set,
886 * or if path was an integer and path.allow_fd was set,
887 * both path.wide and path.narrow will be NULL
888 * and path.length will be 0.
889 *
890 * path_converter takes care to not write to the path_t
891 * unless it's successful. However it must reset the
892 * "cleanup" field each time it's called.
893 *
894 * Use as follows:
895 * path_t path;
896 * memset(&path, 0, sizeof(path));
897 * PyArg_ParseTuple(args, "O&", path_converter, &path);
898 * // ... use values from path ...
899 * path_cleanup(&path);
900 *
901 * (Note that if PyArg_Parse fails you don't need to call
902 * path_cleanup(). However it is safe to do so.)
903 */
904 typedef struct {
905 const char *function_name;
906 const char *argument_name;
907 int nullable;
908 int allow_fd;
909 const wchar_t *wide;
910 #ifdef MS_WINDOWS
911 BOOL narrow;
912 #else
913 const char *narrow;
914 #endif
915 int fd;
916 Py_ssize_t length;
917 PyObject *object;
918 PyObject *cleanup;
919 } path_t;
920
921 #ifdef MS_WINDOWS
922 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
923 {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
924 #else
925 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
926 {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
927 #endif
928
929 static void
path_cleanup(path_t * path)930 path_cleanup(path_t *path)
931 {
932 Py_CLEAR(path->object);
933 Py_CLEAR(path->cleanup);
934 }
935
936 static int
path_converter(PyObject * o,void * p)937 path_converter(PyObject *o, void *p)
938 {
939 path_t *path = (path_t *)p;
940 PyObject *bytes = NULL;
941 Py_ssize_t length = 0;
942 int is_index, is_buffer, is_bytes, is_unicode;
943 const char *narrow;
944 #ifdef MS_WINDOWS
945 PyObject *wo = NULL;
946 const wchar_t *wide;
947 #endif
948
949 #define FORMAT_EXCEPTION(exc, fmt) \
950 PyErr_Format(exc, "%s%s" fmt, \
951 path->function_name ? path->function_name : "", \
952 path->function_name ? ": " : "", \
953 path->argument_name ? path->argument_name : "path")
954
955 /* Py_CLEANUP_SUPPORTED support */
956 if (o == NULL) {
957 path_cleanup(path);
958 return 1;
959 }
960
961 /* Ensure it's always safe to call path_cleanup(). */
962 path->object = path->cleanup = NULL;
963 /* path->object owns a reference to the original object */
964 Py_INCREF(o);
965
966 if ((o == Py_None) && path->nullable) {
967 path->wide = NULL;
968 #ifdef MS_WINDOWS
969 path->narrow = FALSE;
970 #else
971 path->narrow = NULL;
972 #endif
973 path->fd = -1;
974 goto success_exit;
975 }
976
977 /* Only call this here so that we don't treat the return value of
978 os.fspath() as an fd or buffer. */
979 is_index = path->allow_fd && PyIndex_Check(o);
980 is_buffer = PyObject_CheckBuffer(o);
981 is_bytes = PyBytes_Check(o);
982 is_unicode = PyUnicode_Check(o);
983
984 if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
985 /* Inline PyOS_FSPath() for better error messages. */
986 _Py_IDENTIFIER(__fspath__);
987 PyObject *func, *res;
988
989 func = _PyObject_LookupSpecial(o, &PyId___fspath__);
990 if (NULL == func) {
991 goto error_format;
992 }
993 res = _PyObject_CallNoArg(func);
994 Py_DECREF(func);
995 if (NULL == res) {
996 goto error_exit;
997 }
998 else if (PyUnicode_Check(res)) {
999 is_unicode = 1;
1000 }
1001 else if (PyBytes_Check(res)) {
1002 is_bytes = 1;
1003 }
1004 else {
1005 PyErr_Format(PyExc_TypeError,
1006 "expected %.200s.__fspath__() to return str or bytes, "
1007 "not %.200s", Py_TYPE(o)->tp_name,
1008 Py_TYPE(res)->tp_name);
1009 Py_DECREF(res);
1010 goto error_exit;
1011 }
1012
1013 /* still owns a reference to the original object */
1014 Py_DECREF(o);
1015 o = res;
1016 }
1017
1018 if (is_unicode) {
1019 #ifdef MS_WINDOWS
1020 wide = PyUnicode_AsUnicodeAndSize(o, &length);
1021 if (!wide) {
1022 goto error_exit;
1023 }
1024 if (length > 32767) {
1025 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1026 goto error_exit;
1027 }
1028 if (wcslen(wide) != length) {
1029 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1030 goto error_exit;
1031 }
1032
1033 path->wide = wide;
1034 path->narrow = FALSE;
1035 path->fd = -1;
1036 goto success_exit;
1037 #else
1038 if (!PyUnicode_FSConverter(o, &bytes)) {
1039 goto error_exit;
1040 }
1041 #endif
1042 }
1043 else if (is_bytes) {
1044 bytes = o;
1045 Py_INCREF(bytes);
1046 }
1047 else if (is_buffer) {
1048 /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1049 after removing support of non-bytes buffer objects. */
1050 if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
1051 "%s%s%s should be %s, not %.200s",
1052 path->function_name ? path->function_name : "",
1053 path->function_name ? ": " : "",
1054 path->argument_name ? path->argument_name : "path",
1055 path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1056 "integer or None" :
1057 path->allow_fd ? "string, bytes, os.PathLike or integer" :
1058 path->nullable ? "string, bytes, os.PathLike or None" :
1059 "string, bytes or os.PathLike",
1060 Py_TYPE(o)->tp_name)) {
1061 goto error_exit;
1062 }
1063 bytes = PyBytes_FromObject(o);
1064 if (!bytes) {
1065 goto error_exit;
1066 }
1067 }
1068 else if (is_index) {
1069 if (!_fd_converter(o, &path->fd)) {
1070 goto error_exit;
1071 }
1072 path->wide = NULL;
1073 #ifdef MS_WINDOWS
1074 path->narrow = FALSE;
1075 #else
1076 path->narrow = NULL;
1077 #endif
1078 goto success_exit;
1079 }
1080 else {
1081 error_format:
1082 PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1083 path->function_name ? path->function_name : "",
1084 path->function_name ? ": " : "",
1085 path->argument_name ? path->argument_name : "path",
1086 path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1087 "integer or None" :
1088 path->allow_fd ? "string, bytes, os.PathLike or integer" :
1089 path->nullable ? "string, bytes, os.PathLike or None" :
1090 "string, bytes or os.PathLike",
1091 Py_TYPE(o)->tp_name);
1092 goto error_exit;
1093 }
1094
1095 length = PyBytes_GET_SIZE(bytes);
1096 narrow = PyBytes_AS_STRING(bytes);
1097 if ((size_t)length != strlen(narrow)) {
1098 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1099 goto error_exit;
1100 }
1101
1102 #ifdef MS_WINDOWS
1103 wo = PyUnicode_DecodeFSDefaultAndSize(
1104 narrow,
1105 length
1106 );
1107 if (!wo) {
1108 goto error_exit;
1109 }
1110
1111 wide = PyUnicode_AsUnicodeAndSize(wo, &length);
1112 if (!wide) {
1113 goto error_exit;
1114 }
1115 if (length > 32767) {
1116 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1117 goto error_exit;
1118 }
1119 if (wcslen(wide) != length) {
1120 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1121 goto error_exit;
1122 }
1123 path->wide = wide;
1124 path->narrow = TRUE;
1125 path->cleanup = wo;
1126 Py_DECREF(bytes);
1127 #else
1128 path->wide = NULL;
1129 path->narrow = narrow;
1130 if (bytes == o) {
1131 /* Still a reference owned by path->object, don't have to
1132 worry about path->narrow is used after free. */
1133 Py_DECREF(bytes);
1134 }
1135 else {
1136 path->cleanup = bytes;
1137 }
1138 #endif
1139 path->fd = -1;
1140
1141 success_exit:
1142 path->length = length;
1143 path->object = o;
1144 return Py_CLEANUP_SUPPORTED;
1145
1146 error_exit:
1147 Py_XDECREF(o);
1148 Py_XDECREF(bytes);
1149 #ifdef MS_WINDOWS
1150 Py_XDECREF(wo);
1151 #endif
1152 return 0;
1153 }
1154
1155 static void
argument_unavailable_error(const char * function_name,const char * argument_name)1156 argument_unavailable_error(const char *function_name, const char *argument_name)
1157 {
1158 PyErr_Format(PyExc_NotImplementedError,
1159 "%s%s%s unavailable on this platform",
1160 (function_name != NULL) ? function_name : "",
1161 (function_name != NULL) ? ": ": "",
1162 argument_name);
1163 }
1164
1165 static int
dir_fd_unavailable(PyObject * o,void * p)1166 dir_fd_unavailable(PyObject *o, void *p)
1167 {
1168 int dir_fd;
1169 if (!dir_fd_converter(o, &dir_fd))
1170 return 0;
1171 if (dir_fd != DEFAULT_DIR_FD) {
1172 argument_unavailable_error(NULL, "dir_fd");
1173 return 0;
1174 }
1175 *(int *)p = dir_fd;
1176 return 1;
1177 }
1178
1179 static int
fd_specified(const char * function_name,int fd)1180 fd_specified(const char *function_name, int fd)
1181 {
1182 if (fd == -1)
1183 return 0;
1184
1185 argument_unavailable_error(function_name, "fd");
1186 return 1;
1187 }
1188
1189 static int
follow_symlinks_specified(const char * function_name,int follow_symlinks)1190 follow_symlinks_specified(const char *function_name, int follow_symlinks)
1191 {
1192 if (follow_symlinks)
1193 return 0;
1194
1195 argument_unavailable_error(function_name, "follow_symlinks");
1196 return 1;
1197 }
1198
1199 static int
path_and_dir_fd_invalid(const char * function_name,path_t * path,int dir_fd)1200 path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1201 {
1202 if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1203 #ifndef MS_WINDOWS
1204 && !path->narrow
1205 #endif
1206 ) {
1207 PyErr_Format(PyExc_ValueError,
1208 "%s: can't specify dir_fd without matching path",
1209 function_name);
1210 return 1;
1211 }
1212 return 0;
1213 }
1214
1215 static int
dir_fd_and_fd_invalid(const char * function_name,int dir_fd,int fd)1216 dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1217 {
1218 if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1219 PyErr_Format(PyExc_ValueError,
1220 "%s: can't specify both dir_fd and fd",
1221 function_name);
1222 return 1;
1223 }
1224 return 0;
1225 }
1226
1227 static int
fd_and_follow_symlinks_invalid(const char * function_name,int fd,int follow_symlinks)1228 fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1229 int follow_symlinks)
1230 {
1231 if ((fd > 0) && (!follow_symlinks)) {
1232 PyErr_Format(PyExc_ValueError,
1233 "%s: cannot use fd and follow_symlinks together",
1234 function_name);
1235 return 1;
1236 }
1237 return 0;
1238 }
1239
1240 static int
dir_fd_and_follow_symlinks_invalid(const char * function_name,int dir_fd,int follow_symlinks)1241 dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1242 int follow_symlinks)
1243 {
1244 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1245 PyErr_Format(PyExc_ValueError,
1246 "%s: cannot use dir_fd and follow_symlinks together",
1247 function_name);
1248 return 1;
1249 }
1250 return 0;
1251 }
1252
1253 #ifdef MS_WINDOWS
1254 typedef long long Py_off_t;
1255 #else
1256 typedef off_t Py_off_t;
1257 #endif
1258
1259 static int
Py_off_t_converter(PyObject * arg,void * addr)1260 Py_off_t_converter(PyObject *arg, void *addr)
1261 {
1262 #ifdef HAVE_LARGEFILE_SUPPORT
1263 *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1264 #else
1265 *((Py_off_t *)addr) = PyLong_AsLong(arg);
1266 #endif
1267 if (PyErr_Occurred())
1268 return 0;
1269 return 1;
1270 }
1271
1272 static PyObject *
PyLong_FromPy_off_t(Py_off_t offset)1273 PyLong_FromPy_off_t(Py_off_t offset)
1274 {
1275 #ifdef HAVE_LARGEFILE_SUPPORT
1276 return PyLong_FromLongLong(offset);
1277 #else
1278 return PyLong_FromLong(offset);
1279 #endif
1280 }
1281
1282 #ifdef HAVE_SIGSET_T
1283 /* Convert an iterable of integers to a sigset.
1284 Return 1 on success, return 0 and raise an exception on error. */
1285 int
_Py_Sigset_Converter(PyObject * obj,void * addr)1286 _Py_Sigset_Converter(PyObject *obj, void *addr)
1287 {
1288 sigset_t *mask = (sigset_t *)addr;
1289 PyObject *iterator, *item;
1290 long signum;
1291 int overflow;
1292
1293 // The extra parens suppress the unreachable-code warning with clang on MacOS
1294 if (sigemptyset(mask) < (0)) {
1295 /* Probably only if mask == NULL. */
1296 PyErr_SetFromErrno(PyExc_OSError);
1297 return 0;
1298 }
1299
1300 iterator = PyObject_GetIter(obj);
1301 if (iterator == NULL) {
1302 return 0;
1303 }
1304
1305 while ((item = PyIter_Next(iterator)) != NULL) {
1306 signum = PyLong_AsLongAndOverflow(item, &overflow);
1307 Py_DECREF(item);
1308 if (signum <= 0 || signum >= NSIG) {
1309 if (overflow || signum != -1 || !PyErr_Occurred()) {
1310 PyErr_Format(PyExc_ValueError,
1311 "signal number %ld out of range", signum);
1312 }
1313 goto error;
1314 }
1315 if (sigaddset(mask, (int)signum)) {
1316 if (errno != EINVAL) {
1317 /* Probably impossible */
1318 PyErr_SetFromErrno(PyExc_OSError);
1319 goto error;
1320 }
1321 /* For backwards compatibility, allow idioms such as
1322 * `range(1, NSIG)` but warn about invalid signal numbers
1323 */
1324 const char msg[] =
1325 "invalid signal number %ld, please use valid_signals()";
1326 if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1327 goto error;
1328 }
1329 }
1330 }
1331 if (!PyErr_Occurred()) {
1332 Py_DECREF(iterator);
1333 return 1;
1334 }
1335
1336 error:
1337 Py_DECREF(iterator);
1338 return 0;
1339 }
1340 #endif /* HAVE_SIGSET_T */
1341
1342 #ifdef MS_WINDOWS
1343
1344 static int
win32_get_reparse_tag(HANDLE reparse_point_handle,ULONG * reparse_tag)1345 win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1346 {
1347 char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1348 _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1349 DWORD n_bytes_returned;
1350
1351 if (0 == DeviceIoControl(
1352 reparse_point_handle,
1353 FSCTL_GET_REPARSE_POINT,
1354 NULL, 0, /* in buffer */
1355 target_buffer, sizeof(target_buffer),
1356 &n_bytes_returned,
1357 NULL)) /* we're not using OVERLAPPED_IO */
1358 return FALSE;
1359
1360 if (reparse_tag)
1361 *reparse_tag = rdb->ReparseTag;
1362
1363 return TRUE;
1364 }
1365
1366 #endif /* MS_WINDOWS */
1367
1368 /* Return a dictionary corresponding to the POSIX environment table */
1369 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1370 /* On Darwin/MacOSX a shared library or framework has no access to
1371 ** environ directly, we must obtain it with _NSGetEnviron(). See also
1372 ** man environ(7).
1373 */
1374 #include <crt_externs.h>
1375 #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1376 extern char **environ;
1377 #endif /* !_MSC_VER */
1378
1379 static PyObject *
convertenviron(void)1380 convertenviron(void)
1381 {
1382 PyObject *d;
1383 #ifdef MS_WINDOWS
1384 wchar_t **e;
1385 #else
1386 char **e;
1387 #endif
1388
1389 d = PyDict_New();
1390 if (d == NULL)
1391 return NULL;
1392 #ifdef MS_WINDOWS
1393 /* _wenviron must be initialized in this way if the program is started
1394 through main() instead of wmain(). */
1395 _wgetenv(L"");
1396 e = _wenviron;
1397 #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1398 /* environ is not accessible as an extern in a shared object on OSX; use
1399 _NSGetEnviron to resolve it. The value changes if you add environment
1400 variables between calls to Py_Initialize, so don't cache the value. */
1401 e = *_NSGetEnviron();
1402 #else
1403 e = environ;
1404 #endif
1405 if (e == NULL)
1406 return d;
1407 for (; *e != NULL; e++) {
1408 PyObject *k;
1409 PyObject *v;
1410 #ifdef MS_WINDOWS
1411 const wchar_t *p = wcschr(*e, L'=');
1412 #else
1413 const char *p = strchr(*e, '=');
1414 #endif
1415 if (p == NULL)
1416 continue;
1417 #ifdef MS_WINDOWS
1418 k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1419 #else
1420 k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1421 #endif
1422 if (k == NULL) {
1423 Py_DECREF(d);
1424 return NULL;
1425 }
1426 #ifdef MS_WINDOWS
1427 v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1428 #else
1429 v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1430 #endif
1431 if (v == NULL) {
1432 Py_DECREF(k);
1433 Py_DECREF(d);
1434 return NULL;
1435 }
1436 if (PyDict_GetItemWithError(d, k) == NULL) {
1437 if (PyErr_Occurred() || PyDict_SetItem(d, k, v) != 0) {
1438 Py_DECREF(v);
1439 Py_DECREF(k);
1440 Py_DECREF(d);
1441 return NULL;
1442 }
1443 }
1444 Py_DECREF(k);
1445 Py_DECREF(v);
1446 }
1447 return d;
1448 }
1449
1450 /* Set a POSIX-specific error from errno, and return NULL */
1451
1452 static PyObject *
posix_error(void)1453 posix_error(void)
1454 {
1455 return PyErr_SetFromErrno(PyExc_OSError);
1456 }
1457
1458 #ifdef MS_WINDOWS
1459 static PyObject *
win32_error(const char * function,const char * filename)1460 win32_error(const char* function, const char* filename)
1461 {
1462 /* XXX We should pass the function name along in the future.
1463 (winreg.c also wants to pass the function name.)
1464 This would however require an additional param to the
1465 Windows error object, which is non-trivial.
1466 */
1467 errno = GetLastError();
1468 if (filename)
1469 return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1470 else
1471 return PyErr_SetFromWindowsErr(errno);
1472 }
1473
1474 static PyObject *
win32_error_object_err(const char * function,PyObject * filename,DWORD err)1475 win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1476 {
1477 /* XXX - see win32_error for comments on 'function' */
1478 if (filename)
1479 return PyErr_SetExcFromWindowsErrWithFilenameObject(
1480 PyExc_OSError,
1481 err,
1482 filename);
1483 else
1484 return PyErr_SetFromWindowsErr(err);
1485 }
1486
1487 static PyObject *
win32_error_object(const char * function,PyObject * filename)1488 win32_error_object(const char* function, PyObject* filename)
1489 {
1490 errno = GetLastError();
1491 return win32_error_object_err(function, filename, errno);
1492 }
1493
1494 #endif /* MS_WINDOWS */
1495
1496 static PyObject *
posix_path_object_error(PyObject * path)1497 posix_path_object_error(PyObject *path)
1498 {
1499 return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1500 }
1501
1502 static PyObject *
path_object_error(PyObject * path)1503 path_object_error(PyObject *path)
1504 {
1505 #ifdef MS_WINDOWS
1506 return PyErr_SetExcFromWindowsErrWithFilenameObject(
1507 PyExc_OSError, 0, path);
1508 #else
1509 return posix_path_object_error(path);
1510 #endif
1511 }
1512
1513 static PyObject *
path_object_error2(PyObject * path,PyObject * path2)1514 path_object_error2(PyObject *path, PyObject *path2)
1515 {
1516 #ifdef MS_WINDOWS
1517 return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1518 PyExc_OSError, 0, path, path2);
1519 #else
1520 return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1521 #endif
1522 }
1523
1524 static PyObject *
path_error(path_t * path)1525 path_error(path_t *path)
1526 {
1527 return path_object_error(path->object);
1528 }
1529
1530 static PyObject *
posix_path_error(path_t * path)1531 posix_path_error(path_t *path)
1532 {
1533 return posix_path_object_error(path->object);
1534 }
1535
1536 static PyObject *
path_error2(path_t * path,path_t * path2)1537 path_error2(path_t *path, path_t *path2)
1538 {
1539 return path_object_error2(path->object, path2->object);
1540 }
1541
1542
1543 /* POSIX generic methods */
1544
1545 static int
fildes_converter(PyObject * o,void * p)1546 fildes_converter(PyObject *o, void *p)
1547 {
1548 int fd;
1549 int *pointer = (int *)p;
1550 fd = PyObject_AsFileDescriptor(o);
1551 if (fd < 0)
1552 return 0;
1553 *pointer = fd;
1554 return 1;
1555 }
1556
1557 static PyObject *
posix_fildes_fd(int fd,int (* func)(int))1558 posix_fildes_fd(int fd, int (*func)(int))
1559 {
1560 int res;
1561 int async_err = 0;
1562
1563 do {
1564 Py_BEGIN_ALLOW_THREADS
1565 _Py_BEGIN_SUPPRESS_IPH
1566 res = (*func)(fd);
1567 _Py_END_SUPPRESS_IPH
1568 Py_END_ALLOW_THREADS
1569 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1570 if (res != 0)
1571 return (!async_err) ? posix_error() : NULL;
1572 Py_RETURN_NONE;
1573 }
1574
1575
1576 #ifdef MS_WINDOWS
1577 /* This is a reimplementation of the C library's chdir function,
1578 but one that produces Win32 errors instead of DOS error codes.
1579 chdir is essentially a wrapper around SetCurrentDirectory; however,
1580 it also needs to set "magic" environment variables indicating
1581 the per-drive current directory, which are of the form =<drive>: */
1582 static BOOL __stdcall
win32_wchdir(LPCWSTR path)1583 win32_wchdir(LPCWSTR path)
1584 {
1585 wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1586 int result;
1587 wchar_t env[4] = L"=x:";
1588
1589 if(!SetCurrentDirectoryW(path))
1590 return FALSE;
1591 result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1592 if (!result)
1593 return FALSE;
1594 if (result > Py_ARRAY_LENGTH(path_buf)) {
1595 new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1596 if (!new_path) {
1597 SetLastError(ERROR_OUTOFMEMORY);
1598 return FALSE;
1599 }
1600 result = GetCurrentDirectoryW(result, new_path);
1601 if (!result) {
1602 PyMem_RawFree(new_path);
1603 return FALSE;
1604 }
1605 }
1606 int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1607 wcsncmp(new_path, L"//", 2) == 0);
1608 if (!is_unc_like_path) {
1609 env[1] = new_path[0];
1610 result = SetEnvironmentVariableW(env, new_path);
1611 }
1612 if (new_path != path_buf)
1613 PyMem_RawFree(new_path);
1614 return result ? TRUE : FALSE;
1615 }
1616 #endif
1617
1618 #ifdef MS_WINDOWS
1619 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1620 - time stamps are restricted to second resolution
1621 - file modification times suffer from forth-and-back conversions between
1622 UTC and local time
1623 Therefore, we implement our own stat, based on the Win32 API directly.
1624 */
1625 #define HAVE_STAT_NSEC 1
1626 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1627 #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1628
1629 static void
find_data_to_file_info(WIN32_FIND_DATAW * pFileData,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1630 find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1631 BY_HANDLE_FILE_INFORMATION *info,
1632 ULONG *reparse_tag)
1633 {
1634 memset(info, 0, sizeof(*info));
1635 info->dwFileAttributes = pFileData->dwFileAttributes;
1636 info->ftCreationTime = pFileData->ftCreationTime;
1637 info->ftLastAccessTime = pFileData->ftLastAccessTime;
1638 info->ftLastWriteTime = pFileData->ftLastWriteTime;
1639 info->nFileSizeHigh = pFileData->nFileSizeHigh;
1640 info->nFileSizeLow = pFileData->nFileSizeLow;
1641 /* info->nNumberOfLinks = 1; */
1642 if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1643 *reparse_tag = pFileData->dwReserved0;
1644 else
1645 *reparse_tag = 0;
1646 }
1647
1648 static BOOL
attributes_from_dir(LPCWSTR pszFile,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1649 attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1650 {
1651 HANDLE hFindFile;
1652 WIN32_FIND_DATAW FileData;
1653 hFindFile = FindFirstFileW(pszFile, &FileData);
1654 if (hFindFile == INVALID_HANDLE_VALUE)
1655 return FALSE;
1656 FindClose(hFindFile);
1657 find_data_to_file_info(&FileData, info, reparse_tag);
1658 return TRUE;
1659 }
1660
1661 static int
win32_xstat_impl(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1662 win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1663 BOOL traverse)
1664 {
1665 HANDLE hFile;
1666 BY_HANDLE_FILE_INFORMATION fileInfo;
1667 FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1668 DWORD fileType, error;
1669 BOOL isUnhandledTag = FALSE;
1670 int retval = 0;
1671
1672 DWORD access = FILE_READ_ATTRIBUTES;
1673 DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1674 if (!traverse) {
1675 flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1676 }
1677
1678 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1679 if (hFile == INVALID_HANDLE_VALUE) {
1680 /* Either the path doesn't exist, or the caller lacks access. */
1681 error = GetLastError();
1682 switch (error) {
1683 case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */
1684 case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1685 /* Try reading the parent directory. */
1686 if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1687 /* Cannot read the parent directory. */
1688 SetLastError(error);
1689 return -1;
1690 }
1691 if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1692 if (traverse ||
1693 !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1694 /* The stat call has to traverse but cannot, so fail. */
1695 SetLastError(error);
1696 return -1;
1697 }
1698 }
1699 break;
1700
1701 case ERROR_INVALID_PARAMETER:
1702 /* \\.\con requires read or write access. */
1703 hFile = CreateFileW(path, access | GENERIC_READ,
1704 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1705 OPEN_EXISTING, flags, NULL);
1706 if (hFile == INVALID_HANDLE_VALUE) {
1707 SetLastError(error);
1708 return -1;
1709 }
1710 break;
1711
1712 case ERROR_CANT_ACCESS_FILE:
1713 /* bpo37834: open unhandled reparse points if traverse fails. */
1714 if (traverse) {
1715 traverse = FALSE;
1716 isUnhandledTag = TRUE;
1717 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1718 flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1719 }
1720 if (hFile == INVALID_HANDLE_VALUE) {
1721 SetLastError(error);
1722 return -1;
1723 }
1724 break;
1725
1726 default:
1727 return -1;
1728 }
1729 }
1730
1731 if (hFile != INVALID_HANDLE_VALUE) {
1732 /* Handle types other than files on disk. */
1733 fileType = GetFileType(hFile);
1734 if (fileType != FILE_TYPE_DISK) {
1735 if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1736 retval = -1;
1737 goto cleanup;
1738 }
1739 DWORD fileAttributes = GetFileAttributesW(path);
1740 memset(result, 0, sizeof(*result));
1741 if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1742 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1743 /* \\.\pipe\ or \\.\mailslot\ */
1744 result->st_mode = _S_IFDIR;
1745 } else if (fileType == FILE_TYPE_CHAR) {
1746 /* \\.\nul */
1747 result->st_mode = _S_IFCHR;
1748 } else if (fileType == FILE_TYPE_PIPE) {
1749 /* \\.\pipe\spam */
1750 result->st_mode = _S_IFIFO;
1751 }
1752 /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1753 goto cleanup;
1754 }
1755
1756 /* Query the reparse tag, and traverse a non-link. */
1757 if (!traverse) {
1758 if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
1759 &tagInfo, sizeof(tagInfo))) {
1760 /* Allow devices that do not support FileAttributeTagInfo. */
1761 switch (GetLastError()) {
1762 case ERROR_INVALID_PARAMETER:
1763 case ERROR_INVALID_FUNCTION:
1764 case ERROR_NOT_SUPPORTED:
1765 tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1766 tagInfo.ReparseTag = 0;
1767 break;
1768 default:
1769 retval = -1;
1770 goto cleanup;
1771 }
1772 } else if (tagInfo.FileAttributes &
1773 FILE_ATTRIBUTE_REPARSE_POINT) {
1774 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1775 if (isUnhandledTag) {
1776 /* Traversing previously failed for either this link
1777 or its target. */
1778 SetLastError(ERROR_CANT_ACCESS_FILE);
1779 retval = -1;
1780 goto cleanup;
1781 }
1782 /* Traverse a non-link, but not if traversing already failed
1783 for an unhandled tag. */
1784 } else if (!isUnhandledTag) {
1785 CloseHandle(hFile);
1786 return win32_xstat_impl(path, result, TRUE);
1787 }
1788 }
1789 }
1790
1791 if (!GetFileInformationByHandle(hFile, &fileInfo)) {
1792 switch (GetLastError()) {
1793 case ERROR_INVALID_PARAMETER:
1794 case ERROR_INVALID_FUNCTION:
1795 case ERROR_NOT_SUPPORTED:
1796 /* Volumes and physical disks are block devices, e.g.
1797 \\.\C: and \\.\PhysicalDrive0. */
1798 memset(result, 0, sizeof(*result));
1799 result->st_mode = 0x6000; /* S_IFBLK */
1800 goto cleanup;
1801 }
1802 retval = -1;
1803 goto cleanup;
1804 }
1805 }
1806
1807 _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
1808
1809 if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
1810 /* Fix the file execute permissions. This hack sets S_IEXEC if
1811 the filename has an extension that is commonly used by files
1812 that CreateProcessW can execute. A real implementation calls
1813 GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
1814 AccessCheck to check for generic read, write, and execute
1815 access. */
1816 const wchar_t *fileExtension = wcsrchr(path, '.');
1817 if (fileExtension) {
1818 if (_wcsicmp(fileExtension, L".exe") == 0 ||
1819 _wcsicmp(fileExtension, L".bat") == 0 ||
1820 _wcsicmp(fileExtension, L".cmd") == 0 ||
1821 _wcsicmp(fileExtension, L".com") == 0) {
1822 result->st_mode |= 0111;
1823 }
1824 }
1825 }
1826
1827 cleanup:
1828 if (hFile != INVALID_HANDLE_VALUE) {
1829 /* Preserve last error if we are failing */
1830 error = retval ? GetLastError() : 0;
1831 if (!CloseHandle(hFile)) {
1832 retval = -1;
1833 } else if (retval) {
1834 /* Restore last error */
1835 SetLastError(error);
1836 }
1837 }
1838
1839 return retval;
1840 }
1841
1842 static int
win32_xstat(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1843 win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
1844 {
1845 /* Protocol violation: we explicitly clear errno, instead of
1846 setting it to a POSIX error. Callers should use GetLastError. */
1847 int code = win32_xstat_impl(path, result, traverse);
1848 errno = 0;
1849 return code;
1850 }
1851 /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
1852
1853 In Posix, stat automatically traverses symlinks and returns the stat
1854 structure for the target. In Windows, the equivalent GetFileAttributes by
1855 default does not traverse symlinks and instead returns attributes for
1856 the symlink.
1857
1858 Instead, we will open the file (which *does* traverse symlinks by default)
1859 and GetFileInformationByHandle(). */
1860
1861 static int
win32_lstat(const wchar_t * path,struct _Py_stat_struct * result)1862 win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
1863 {
1864 return win32_xstat(path, result, FALSE);
1865 }
1866
1867 static int
win32_stat(const wchar_t * path,struct _Py_stat_struct * result)1868 win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
1869 {
1870 return win32_xstat(path, result, TRUE);
1871 }
1872
1873 #endif /* MS_WINDOWS */
1874
1875 PyDoc_STRVAR(stat_result__doc__,
1876 "stat_result: Result from stat, fstat, or lstat.\n\n\
1877 This object may be accessed either as a tuple of\n\
1878 (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
1879 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
1880 \n\
1881 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
1882 or st_flags, they are available as attributes only.\n\
1883 \n\
1884 See os.stat for more information.");
1885
1886 static PyStructSequence_Field stat_result_fields[] = {
1887 {"st_mode", "protection bits"},
1888 {"st_ino", "inode"},
1889 {"st_dev", "device"},
1890 {"st_nlink", "number of hard links"},
1891 {"st_uid", "user ID of owner"},
1892 {"st_gid", "group ID of owner"},
1893 {"st_size", "total size, in bytes"},
1894 /* The NULL is replaced with PyStructSequence_UnnamedField later. */
1895 {NULL, "integer time of last access"},
1896 {NULL, "integer time of last modification"},
1897 {NULL, "integer time of last change"},
1898 {"st_atime", "time of last access"},
1899 {"st_mtime", "time of last modification"},
1900 {"st_ctime", "time of last change"},
1901 {"st_atime_ns", "time of last access in nanoseconds"},
1902 {"st_mtime_ns", "time of last modification in nanoseconds"},
1903 {"st_ctime_ns", "time of last change in nanoseconds"},
1904 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1905 {"st_blksize", "blocksize for filesystem I/O"},
1906 #endif
1907 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1908 {"st_blocks", "number of blocks allocated"},
1909 #endif
1910 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1911 {"st_rdev", "device type (if inode device)"},
1912 #endif
1913 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
1914 {"st_flags", "user defined flags for file"},
1915 #endif
1916 #ifdef HAVE_STRUCT_STAT_ST_GEN
1917 {"st_gen", "generation number"},
1918 #endif
1919 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1920 {"st_birthtime", "time of creation"},
1921 #endif
1922 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
1923 {"st_file_attributes", "Windows file attribute bits"},
1924 #endif
1925 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
1926 {"st_fstype", "Type of filesystem"},
1927 #endif
1928 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
1929 {"st_reparse_tag", "Windows reparse tag"},
1930 #endif
1931 {0}
1932 };
1933
1934 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1935 #define ST_BLKSIZE_IDX 16
1936 #else
1937 #define ST_BLKSIZE_IDX 15
1938 #endif
1939
1940 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1941 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
1942 #else
1943 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
1944 #endif
1945
1946 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1947 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
1948 #else
1949 #define ST_RDEV_IDX ST_BLOCKS_IDX
1950 #endif
1951
1952 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
1953 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
1954 #else
1955 #define ST_FLAGS_IDX ST_RDEV_IDX
1956 #endif
1957
1958 #ifdef HAVE_STRUCT_STAT_ST_GEN
1959 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
1960 #else
1961 #define ST_GEN_IDX ST_FLAGS_IDX
1962 #endif
1963
1964 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1965 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
1966 #else
1967 #define ST_BIRTHTIME_IDX ST_GEN_IDX
1968 #endif
1969
1970 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
1971 #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
1972 #else
1973 #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
1974 #endif
1975
1976 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
1977 #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
1978 #else
1979 #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
1980 #endif
1981
1982 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
1983 #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
1984 #else
1985 #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
1986 #endif
1987
1988 static PyStructSequence_Desc stat_result_desc = {
1989 "stat_result", /* name */
1990 stat_result__doc__, /* doc */
1991 stat_result_fields,
1992 10
1993 };
1994
1995 PyDoc_STRVAR(statvfs_result__doc__,
1996 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
1997 This object may be accessed either as a tuple of\n\
1998 (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
1999 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2000 \n\
2001 See os.statvfs for more information.");
2002
2003 static PyStructSequence_Field statvfs_result_fields[] = {
2004 {"f_bsize", },
2005 {"f_frsize", },
2006 {"f_blocks", },
2007 {"f_bfree", },
2008 {"f_bavail", },
2009 {"f_files", },
2010 {"f_ffree", },
2011 {"f_favail", },
2012 {"f_flag", },
2013 {"f_namemax",},
2014 {"f_fsid", },
2015 {0}
2016 };
2017
2018 static PyStructSequence_Desc statvfs_result_desc = {
2019 "statvfs_result", /* name */
2020 statvfs_result__doc__, /* doc */
2021 statvfs_result_fields,
2022 10
2023 };
2024
2025 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2026 PyDoc_STRVAR(waitid_result__doc__,
2027 "waitid_result: Result from waitid.\n\n\
2028 This object may be accessed either as a tuple of\n\
2029 (si_pid, si_uid, si_signo, si_status, si_code),\n\
2030 or via the attributes si_pid, si_uid, and so on.\n\
2031 \n\
2032 See os.waitid for more information.");
2033
2034 static PyStructSequence_Field waitid_result_fields[] = {
2035 {"si_pid", },
2036 {"si_uid", },
2037 {"si_signo", },
2038 {"si_status", },
2039 {"si_code", },
2040 {0}
2041 };
2042
2043 static PyStructSequence_Desc waitid_result_desc = {
2044 "waitid_result", /* name */
2045 waitid_result__doc__, /* doc */
2046 waitid_result_fields,
2047 5
2048 };
2049 static PyTypeObject* WaitidResultType;
2050 #endif
2051
2052 static int initialized;
2053 static PyTypeObject* StatResultType;
2054 static PyTypeObject* StatVFSResultType;
2055 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2056 static PyTypeObject* SchedParamType;
2057 #endif
2058 static newfunc structseq_new;
2059
2060 static PyObject *
statresult_new(PyTypeObject * type,PyObject * args,PyObject * kwds)2061 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2062 {
2063 PyStructSequence *result;
2064 int i;
2065
2066 result = (PyStructSequence*)structseq_new(type, args, kwds);
2067 if (!result)
2068 return NULL;
2069 /* If we have been initialized from a tuple,
2070 st_?time might be set to None. Initialize it
2071 from the int slots. */
2072 for (i = 7; i <= 9; i++) {
2073 if (result->ob_item[i+3] == Py_None) {
2074 Py_DECREF(Py_None);
2075 Py_INCREF(result->ob_item[i]);
2076 result->ob_item[i+3] = result->ob_item[i];
2077 }
2078 }
2079 return (PyObject*)result;
2080 }
2081
2082
2083 static PyObject *billion = NULL;
2084
2085 static void
fill_time(PyObject * v,int index,time_t sec,unsigned long nsec)2086 fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
2087 {
2088 PyObject *s = _PyLong_FromTime_t(sec);
2089 PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2090 PyObject *s_in_ns = NULL;
2091 PyObject *ns_total = NULL;
2092 PyObject *float_s = NULL;
2093
2094 if (!(s && ns_fractional))
2095 goto exit;
2096
2097 s_in_ns = PyNumber_Multiply(s, billion);
2098 if (!s_in_ns)
2099 goto exit;
2100
2101 ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2102 if (!ns_total)
2103 goto exit;
2104
2105 float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2106 if (!float_s) {
2107 goto exit;
2108 }
2109
2110 PyStructSequence_SET_ITEM(v, index, s);
2111 PyStructSequence_SET_ITEM(v, index+3, float_s);
2112 PyStructSequence_SET_ITEM(v, index+6, ns_total);
2113 s = NULL;
2114 float_s = NULL;
2115 ns_total = NULL;
2116 exit:
2117 Py_XDECREF(s);
2118 Py_XDECREF(ns_fractional);
2119 Py_XDECREF(s_in_ns);
2120 Py_XDECREF(ns_total);
2121 Py_XDECREF(float_s);
2122 }
2123
2124 /* pack a system stat C structure into the Python stat tuple
2125 (used by posix_stat() and posix_fstat()) */
2126 static PyObject*
_pystat_fromstructstat(STRUCT_STAT * st)2127 _pystat_fromstructstat(STRUCT_STAT *st)
2128 {
2129 unsigned long ansec, mnsec, cnsec;
2130 PyObject *v = PyStructSequence_New(StatResultType);
2131 if (v == NULL)
2132 return NULL;
2133
2134 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2135 Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(st->st_ino));
2136 PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2137 #ifdef MS_WINDOWS
2138 PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
2139 #else
2140 PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2141 #endif
2142 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2143 #if defined(MS_WINDOWS)
2144 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2145 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2146 #else
2147 PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2148 PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2149 #endif
2150 Py_BUILD_ASSERT(sizeof(long long) >= sizeof(st->st_size));
2151 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2152
2153 #if defined(HAVE_STAT_TV_NSEC)
2154 ansec = st->st_atim.tv_nsec;
2155 mnsec = st->st_mtim.tv_nsec;
2156 cnsec = st->st_ctim.tv_nsec;
2157 #elif defined(HAVE_STAT_TV_NSEC2)
2158 ansec = st->st_atimespec.tv_nsec;
2159 mnsec = st->st_mtimespec.tv_nsec;
2160 cnsec = st->st_ctimespec.tv_nsec;
2161 #elif defined(HAVE_STAT_NSEC)
2162 ansec = st->st_atime_nsec;
2163 mnsec = st->st_mtime_nsec;
2164 cnsec = st->st_ctime_nsec;
2165 #else
2166 ansec = mnsec = cnsec = 0;
2167 #endif
2168 fill_time(v, 7, st->st_atime, ansec);
2169 fill_time(v, 8, st->st_mtime, mnsec);
2170 fill_time(v, 9, st->st_ctime, cnsec);
2171
2172 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2173 PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2174 PyLong_FromLong((long)st->st_blksize));
2175 #endif
2176 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2177 PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2178 PyLong_FromLong((long)st->st_blocks));
2179 #endif
2180 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2181 PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2182 PyLong_FromLong((long)st->st_rdev));
2183 #endif
2184 #ifdef HAVE_STRUCT_STAT_ST_GEN
2185 PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2186 PyLong_FromLong((long)st->st_gen));
2187 #endif
2188 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2189 {
2190 PyObject *val;
2191 unsigned long bsec,bnsec;
2192 bsec = (long)st->st_birthtime;
2193 #ifdef HAVE_STAT_TV_NSEC2
2194 bnsec = st->st_birthtimespec.tv_nsec;
2195 #else
2196 bnsec = 0;
2197 #endif
2198 val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2199 PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2200 val);
2201 }
2202 #endif
2203 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2204 PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2205 PyLong_FromLong((long)st->st_flags));
2206 #endif
2207 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2208 PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2209 PyLong_FromUnsignedLong(st->st_file_attributes));
2210 #endif
2211 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2212 PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2213 PyUnicode_FromString(st->st_fstype));
2214 #endif
2215 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2216 PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2217 PyLong_FromUnsignedLong(st->st_reparse_tag));
2218 #endif
2219
2220 if (PyErr_Occurred()) {
2221 Py_DECREF(v);
2222 return NULL;
2223 }
2224
2225 return v;
2226 }
2227
2228 /* POSIX methods */
2229
2230
2231 static PyObject *
posix_do_stat(const char * function_name,path_t * path,int dir_fd,int follow_symlinks)2232 posix_do_stat(const char *function_name, path_t *path,
2233 int dir_fd, int follow_symlinks)
2234 {
2235 STRUCT_STAT st;
2236 int result;
2237
2238 #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2239 if (follow_symlinks_specified(function_name, follow_symlinks))
2240 return NULL;
2241 #endif
2242
2243 if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2244 dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2245 fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2246 return NULL;
2247
2248 Py_BEGIN_ALLOW_THREADS
2249 if (path->fd != -1)
2250 result = FSTAT(path->fd, &st);
2251 #ifdef MS_WINDOWS
2252 else if (follow_symlinks)
2253 result = win32_stat(path->wide, &st);
2254 else
2255 result = win32_lstat(path->wide, &st);
2256 #else
2257 else
2258 #if defined(HAVE_LSTAT)
2259 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2260 result = LSTAT(path->narrow, &st);
2261 else
2262 #endif /* HAVE_LSTAT */
2263 #ifdef HAVE_FSTATAT
2264 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks)
2265 result = fstatat(dir_fd, path->narrow, &st,
2266 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2267 else
2268 #endif /* HAVE_FSTATAT */
2269 result = STAT(path->narrow, &st);
2270 #endif /* MS_WINDOWS */
2271 Py_END_ALLOW_THREADS
2272
2273 if (result != 0) {
2274 return path_error(path);
2275 }
2276
2277 return _pystat_fromstructstat(&st);
2278 }
2279
2280 /*[python input]
2281
2282 for s in """
2283
2284 FACCESSAT
2285 FCHMODAT
2286 FCHOWNAT
2287 FSTATAT
2288 LINKAT
2289 MKDIRAT
2290 MKFIFOAT
2291 MKNODAT
2292 OPENAT
2293 READLINKAT
2294 SYMLINKAT
2295 UNLINKAT
2296
2297 """.strip().split():
2298 s = s.strip()
2299 print("""
2300 #ifdef HAVE_{s}
2301 #define {s}_DIR_FD_CONVERTER dir_fd_converter
2302 #else
2303 #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2304 #endif
2305 """.rstrip().format(s=s))
2306
2307 for s in """
2308
2309 FCHDIR
2310 FCHMOD
2311 FCHOWN
2312 FDOPENDIR
2313 FEXECVE
2314 FPATHCONF
2315 FSTATVFS
2316 FTRUNCATE
2317
2318 """.strip().split():
2319 s = s.strip()
2320 print("""
2321 #ifdef HAVE_{s}
2322 #define PATH_HAVE_{s} 1
2323 #else
2324 #define PATH_HAVE_{s} 0
2325 #endif
2326
2327 """.rstrip().format(s=s))
2328 [python start generated code]*/
2329
2330 #ifdef HAVE_FACCESSAT
2331 #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2332 #else
2333 #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2334 #endif
2335
2336 #ifdef HAVE_FCHMODAT
2337 #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2338 #else
2339 #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2340 #endif
2341
2342 #ifdef HAVE_FCHOWNAT
2343 #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2344 #else
2345 #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2346 #endif
2347
2348 #ifdef HAVE_FSTATAT
2349 #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2350 #else
2351 #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2352 #endif
2353
2354 #ifdef HAVE_LINKAT
2355 #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2356 #else
2357 #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2358 #endif
2359
2360 #ifdef HAVE_MKDIRAT
2361 #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2362 #else
2363 #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2364 #endif
2365
2366 #ifdef HAVE_MKFIFOAT
2367 #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2368 #else
2369 #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2370 #endif
2371
2372 #ifdef HAVE_MKNODAT
2373 #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2374 #else
2375 #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2376 #endif
2377
2378 #ifdef HAVE_OPENAT
2379 #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2380 #else
2381 #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2382 #endif
2383
2384 #ifdef HAVE_READLINKAT
2385 #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2386 #else
2387 #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2388 #endif
2389
2390 #ifdef HAVE_SYMLINKAT
2391 #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2392 #else
2393 #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2394 #endif
2395
2396 #ifdef HAVE_UNLINKAT
2397 #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2398 #else
2399 #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2400 #endif
2401
2402 #ifdef HAVE_FCHDIR
2403 #define PATH_HAVE_FCHDIR 1
2404 #else
2405 #define PATH_HAVE_FCHDIR 0
2406 #endif
2407
2408 #ifdef HAVE_FCHMOD
2409 #define PATH_HAVE_FCHMOD 1
2410 #else
2411 #define PATH_HAVE_FCHMOD 0
2412 #endif
2413
2414 #ifdef HAVE_FCHOWN
2415 #define PATH_HAVE_FCHOWN 1
2416 #else
2417 #define PATH_HAVE_FCHOWN 0
2418 #endif
2419
2420 #ifdef HAVE_FDOPENDIR
2421 #define PATH_HAVE_FDOPENDIR 1
2422 #else
2423 #define PATH_HAVE_FDOPENDIR 0
2424 #endif
2425
2426 #ifdef HAVE_FEXECVE
2427 #define PATH_HAVE_FEXECVE 1
2428 #else
2429 #define PATH_HAVE_FEXECVE 0
2430 #endif
2431
2432 #ifdef HAVE_FPATHCONF
2433 #define PATH_HAVE_FPATHCONF 1
2434 #else
2435 #define PATH_HAVE_FPATHCONF 0
2436 #endif
2437
2438 #ifdef HAVE_FSTATVFS
2439 #define PATH_HAVE_FSTATVFS 1
2440 #else
2441 #define PATH_HAVE_FSTATVFS 0
2442 #endif
2443
2444 #ifdef HAVE_FTRUNCATE
2445 #define PATH_HAVE_FTRUNCATE 1
2446 #else
2447 #define PATH_HAVE_FTRUNCATE 0
2448 #endif
2449 /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2450
2451 #ifdef MS_WINDOWS
2452 #undef PATH_HAVE_FTRUNCATE
2453 #define PATH_HAVE_FTRUNCATE 1
2454 #endif
2455
2456 /*[python input]
2457
2458 class path_t_converter(CConverter):
2459
2460 type = "path_t"
2461 impl_by_reference = True
2462 parse_by_reference = True
2463
2464 converter = 'path_converter'
2465
2466 def converter_init(self, *, allow_fd=False, nullable=False):
2467 # right now path_t doesn't support default values.
2468 # to support a default value, you'll need to override initialize().
2469 if self.default not in (unspecified, None):
2470 fail("Can't specify a default to the path_t converter!")
2471
2472 if self.c_default not in (None, 'Py_None'):
2473 raise RuntimeError("Can't specify a c_default to the path_t converter!")
2474
2475 self.nullable = nullable
2476 self.allow_fd = allow_fd
2477
2478 def pre_render(self):
2479 def strify(value):
2480 if isinstance(value, str):
2481 return value
2482 return str(int(bool(value)))
2483
2484 # add self.py_name here when merging with posixmodule conversion
2485 self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2486 self.function.name,
2487 self.name,
2488 strify(self.nullable),
2489 strify(self.allow_fd),
2490 )
2491
2492 def cleanup(self):
2493 return "path_cleanup(&" + self.name + ");\n"
2494
2495
2496 class dir_fd_converter(CConverter):
2497 type = 'int'
2498
2499 def converter_init(self, requires=None):
2500 if self.default in (unspecified, None):
2501 self.c_default = 'DEFAULT_DIR_FD'
2502 if isinstance(requires, str):
2503 self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2504 else:
2505 self.converter = 'dir_fd_converter'
2506
2507 class fildes_converter(CConverter):
2508 type = 'int'
2509 converter = 'fildes_converter'
2510
2511 class uid_t_converter(CConverter):
2512 type = "uid_t"
2513 converter = '_Py_Uid_Converter'
2514
2515 class gid_t_converter(CConverter):
2516 type = "gid_t"
2517 converter = '_Py_Gid_Converter'
2518
2519 class dev_t_converter(CConverter):
2520 type = 'dev_t'
2521 converter = '_Py_Dev_Converter'
2522
2523 class dev_t_return_converter(unsigned_long_return_converter):
2524 type = 'dev_t'
2525 conversion_fn = '_PyLong_FromDev'
2526 unsigned_cast = '(dev_t)'
2527
2528 class FSConverter_converter(CConverter):
2529 type = 'PyObject *'
2530 converter = 'PyUnicode_FSConverter'
2531 def converter_init(self):
2532 if self.default is not unspecified:
2533 fail("FSConverter_converter does not support default values")
2534 self.c_default = 'NULL'
2535
2536 def cleanup(self):
2537 return "Py_XDECREF(" + self.name + ");\n"
2538
2539 class pid_t_converter(CConverter):
2540 type = 'pid_t'
2541 format_unit = '" _Py_PARSE_PID "'
2542
2543 class idtype_t_converter(int_converter):
2544 type = 'idtype_t'
2545
2546 class id_t_converter(CConverter):
2547 type = 'id_t'
2548 format_unit = '" _Py_PARSE_PID "'
2549
2550 class intptr_t_converter(CConverter):
2551 type = 'intptr_t'
2552 format_unit = '" _Py_PARSE_INTPTR "'
2553
2554 class Py_off_t_converter(CConverter):
2555 type = 'Py_off_t'
2556 converter = 'Py_off_t_converter'
2557
2558 class Py_off_t_return_converter(long_return_converter):
2559 type = 'Py_off_t'
2560 conversion_fn = 'PyLong_FromPy_off_t'
2561
2562 class path_confname_converter(CConverter):
2563 type="int"
2564 converter="conv_path_confname"
2565
2566 class confstr_confname_converter(path_confname_converter):
2567 converter='conv_confstr_confname'
2568
2569 class sysconf_confname_converter(path_confname_converter):
2570 converter="conv_sysconf_confname"
2571
2572 class sched_param_converter(CConverter):
2573 type = 'struct sched_param'
2574 converter = 'convert_sched_param'
2575 impl_by_reference = True;
2576
2577 [python start generated code]*/
2578 /*[python end generated code: output=da39a3ee5e6b4b0d input=418fce0e01144461]*/
2579
2580 /*[clinic input]
2581
2582 os.stat
2583
2584 path : path_t(allow_fd=True)
2585 Path to be examined; can be string, bytes, a path-like object or
2586 open-file-descriptor int.
2587
2588 *
2589
2590 dir_fd : dir_fd(requires='fstatat') = None
2591 If not None, it should be a file descriptor open to a directory,
2592 and path should be a relative string; path will then be relative to
2593 that directory.
2594
2595 follow_symlinks: bool = True
2596 If False, and the last element of the path is a symbolic link,
2597 stat will examine the symbolic link itself instead of the file
2598 the link points to.
2599
2600 Perform a stat system call on the given path.
2601
2602 dir_fd and follow_symlinks may not be implemented
2603 on your platform. If they are unavailable, using them will raise a
2604 NotImplementedError.
2605
2606 It's an error to use dir_fd or follow_symlinks when specifying path as
2607 an open file descriptor.
2608
2609 [clinic start generated code]*/
2610
2611 static PyObject *
os_stat_impl(PyObject * module,path_t * path,int dir_fd,int follow_symlinks)2612 os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2613 /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2614 {
2615 return posix_do_stat("stat", path, dir_fd, follow_symlinks);
2616 }
2617
2618
2619 /*[clinic input]
2620 os.lstat
2621
2622 path : path_t
2623
2624 *
2625
2626 dir_fd : dir_fd(requires='fstatat') = None
2627
2628 Perform a stat system call on the given path, without following symbolic links.
2629
2630 Like stat(), but do not follow symbolic links.
2631 Equivalent to stat(path, follow_symlinks=False).
2632 [clinic start generated code]*/
2633
2634 static PyObject *
os_lstat_impl(PyObject * module,path_t * path,int dir_fd)2635 os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2636 /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2637 {
2638 int follow_symlinks = 0;
2639 return posix_do_stat("lstat", path, dir_fd, follow_symlinks);
2640 }
2641
2642
2643 /*[clinic input]
2644 os.access -> bool
2645
2646 path: path_t
2647 Path to be tested; can be string, bytes, or a path-like object.
2648
2649 mode: int
2650 Operating-system mode bitfield. Can be F_OK to test existence,
2651 or the inclusive-OR of R_OK, W_OK, and X_OK.
2652
2653 *
2654
2655 dir_fd : dir_fd(requires='faccessat') = None
2656 If not None, it should be a file descriptor open to a directory,
2657 and path should be relative; path will then be relative to that
2658 directory.
2659
2660 effective_ids: bool = False
2661 If True, access will use the effective uid/gid instead of
2662 the real uid/gid.
2663
2664 follow_symlinks: bool = True
2665 If False, and the last element of the path is a symbolic link,
2666 access will examine the symbolic link itself instead of the file
2667 the link points to.
2668
2669 Use the real uid/gid to test for access to a path.
2670
2671 {parameters}
2672 dir_fd, effective_ids, and follow_symlinks may not be implemented
2673 on your platform. If they are unavailable, using them will raise a
2674 NotImplementedError.
2675
2676 Note that most operations will use the effective uid/gid, therefore this
2677 routine can be used in a suid/sgid environment to test if the invoking user
2678 has the specified access to the path.
2679
2680 [clinic start generated code]*/
2681
2682 static int
os_access_impl(PyObject * module,path_t * path,int mode,int dir_fd,int effective_ids,int follow_symlinks)2683 os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2684 int effective_ids, int follow_symlinks)
2685 /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
2686 {
2687 int return_value;
2688
2689 #ifdef MS_WINDOWS
2690 DWORD attr;
2691 #else
2692 int result;
2693 #endif
2694
2695 #ifndef HAVE_FACCESSAT
2696 if (follow_symlinks_specified("access", follow_symlinks))
2697 return -1;
2698
2699 if (effective_ids) {
2700 argument_unavailable_error("access", "effective_ids");
2701 return -1;
2702 }
2703 #endif
2704
2705 #ifdef MS_WINDOWS
2706 Py_BEGIN_ALLOW_THREADS
2707 attr = GetFileAttributesW(path->wide);
2708 Py_END_ALLOW_THREADS
2709
2710 /*
2711 * Access is possible if
2712 * * we didn't get a -1, and
2713 * * write access wasn't requested,
2714 * * or the file isn't read-only,
2715 * * or it's a directory.
2716 * (Directories cannot be read-only on Windows.)
2717 */
2718 return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
2719 (!(mode & 2) ||
2720 !(attr & FILE_ATTRIBUTE_READONLY) ||
2721 (attr & FILE_ATTRIBUTE_DIRECTORY));
2722 #else
2723
2724 Py_BEGIN_ALLOW_THREADS
2725 #ifdef HAVE_FACCESSAT
2726 if ((dir_fd != DEFAULT_DIR_FD) ||
2727 effective_ids ||
2728 !follow_symlinks) {
2729 int flags = 0;
2730 if (!follow_symlinks)
2731 flags |= AT_SYMLINK_NOFOLLOW;
2732 if (effective_ids)
2733 flags |= AT_EACCESS;
2734 result = faccessat(dir_fd, path->narrow, mode, flags);
2735 }
2736 else
2737 #endif
2738 result = access(path->narrow, mode);
2739 Py_END_ALLOW_THREADS
2740 return_value = !result;
2741 #endif
2742
2743 return return_value;
2744 }
2745
2746 #ifndef F_OK
2747 #define F_OK 0
2748 #endif
2749 #ifndef R_OK
2750 #define R_OK 4
2751 #endif
2752 #ifndef W_OK
2753 #define W_OK 2
2754 #endif
2755 #ifndef X_OK
2756 #define X_OK 1
2757 #endif
2758
2759
2760 #ifdef HAVE_TTYNAME
2761 /*[clinic input]
2762 os.ttyname
2763
2764 fd: int
2765 Integer file descriptor handle.
2766
2767 /
2768
2769 Return the name of the terminal device connected to 'fd'.
2770 [clinic start generated code]*/
2771
2772 static PyObject *
os_ttyname_impl(PyObject * module,int fd)2773 os_ttyname_impl(PyObject *module, int fd)
2774 /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
2775 {
2776 char *ret;
2777
2778 ret = ttyname(fd);
2779 if (ret == NULL) {
2780 return posix_error();
2781 }
2782 return PyUnicode_DecodeFSDefault(ret);
2783 }
2784 #endif
2785
2786 #ifdef HAVE_CTERMID
2787 /*[clinic input]
2788 os.ctermid
2789
2790 Return the name of the controlling terminal for this process.
2791 [clinic start generated code]*/
2792
2793 static PyObject *
os_ctermid_impl(PyObject * module)2794 os_ctermid_impl(PyObject *module)
2795 /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
2796 {
2797 char *ret;
2798 char buffer[L_ctermid];
2799
2800 #ifdef USE_CTERMID_R
2801 ret = ctermid_r(buffer);
2802 #else
2803 ret = ctermid(buffer);
2804 #endif
2805 if (ret == NULL)
2806 return posix_error();
2807 return PyUnicode_DecodeFSDefault(buffer);
2808 }
2809 #endif /* HAVE_CTERMID */
2810
2811
2812 /*[clinic input]
2813 os.chdir
2814
2815 path: path_t(allow_fd='PATH_HAVE_FCHDIR')
2816
2817 Change the current working directory to the specified path.
2818
2819 path may always be specified as a string.
2820 On some platforms, path may also be specified as an open file descriptor.
2821 If this functionality is unavailable, using it raises an exception.
2822 [clinic start generated code]*/
2823
2824 static PyObject *
os_chdir_impl(PyObject * module,path_t * path)2825 os_chdir_impl(PyObject *module, path_t *path)
2826 /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
2827 {
2828 int result;
2829
2830 Py_BEGIN_ALLOW_THREADS
2831 #ifdef MS_WINDOWS
2832 /* on unix, success = 0, on windows, success = !0 */
2833 result = !win32_wchdir(path->wide);
2834 #else
2835 #ifdef HAVE_FCHDIR
2836 if (path->fd != -1)
2837 result = fchdir(path->fd);
2838 else
2839 #endif
2840 result = chdir(path->narrow);
2841 #endif
2842 Py_END_ALLOW_THREADS
2843
2844 if (result) {
2845 return path_error(path);
2846 }
2847
2848 Py_RETURN_NONE;
2849 }
2850
2851
2852 #ifdef HAVE_FCHDIR
2853 /*[clinic input]
2854 os.fchdir
2855
2856 fd: fildes
2857
2858 Change to the directory of the given file descriptor.
2859
2860 fd must be opened on a directory, not a file.
2861 Equivalent to os.chdir(fd).
2862
2863 [clinic start generated code]*/
2864
2865 static PyObject *
os_fchdir_impl(PyObject * module,int fd)2866 os_fchdir_impl(PyObject *module, int fd)
2867 /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
2868 {
2869 return posix_fildes_fd(fd, fchdir);
2870 }
2871 #endif /* HAVE_FCHDIR */
2872
2873
2874 /*[clinic input]
2875 os.chmod
2876
2877 path: path_t(allow_fd='PATH_HAVE_FCHMOD')
2878 Path to be modified. May always be specified as a str, bytes, or a path-like object.
2879 On some platforms, path may also be specified as an open file descriptor.
2880 If this functionality is unavailable, using it raises an exception.
2881
2882 mode: int
2883 Operating-system mode bitfield.
2884
2885 *
2886
2887 dir_fd : dir_fd(requires='fchmodat') = None
2888 If not None, it should be a file descriptor open to a directory,
2889 and path should be relative; path will then be relative to that
2890 directory.
2891
2892 follow_symlinks: bool = True
2893 If False, and the last element of the path is a symbolic link,
2894 chmod will modify the symbolic link itself instead of the file
2895 the link points to.
2896
2897 Change the access permissions of a file.
2898
2899 It is an error to use dir_fd or follow_symlinks when specifying path as
2900 an open file descriptor.
2901 dir_fd and follow_symlinks may not be implemented on your platform.
2902 If they are unavailable, using them will raise a NotImplementedError.
2903
2904 [clinic start generated code]*/
2905
2906 static PyObject *
os_chmod_impl(PyObject * module,path_t * path,int mode,int dir_fd,int follow_symlinks)2907 os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2908 int follow_symlinks)
2909 /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
2910 {
2911 int result;
2912
2913 #ifdef MS_WINDOWS
2914 DWORD attr;
2915 #endif
2916
2917 #ifdef HAVE_FCHMODAT
2918 int fchmodat_nofollow_unsupported = 0;
2919 #endif
2920
2921 #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
2922 if (follow_symlinks_specified("chmod", follow_symlinks))
2923 return NULL;
2924 #endif
2925
2926 #ifdef MS_WINDOWS
2927 Py_BEGIN_ALLOW_THREADS
2928 attr = GetFileAttributesW(path->wide);
2929 if (attr == INVALID_FILE_ATTRIBUTES)
2930 result = 0;
2931 else {
2932 if (mode & _S_IWRITE)
2933 attr &= ~FILE_ATTRIBUTE_READONLY;
2934 else
2935 attr |= FILE_ATTRIBUTE_READONLY;
2936 result = SetFileAttributesW(path->wide, attr);
2937 }
2938 Py_END_ALLOW_THREADS
2939
2940 if (!result) {
2941 return path_error(path);
2942 }
2943 #else /* MS_WINDOWS */
2944 Py_BEGIN_ALLOW_THREADS
2945 #ifdef HAVE_FCHMOD
2946 if (path->fd != -1)
2947 result = fchmod(path->fd, mode);
2948 else
2949 #endif
2950 #ifdef HAVE_LCHMOD
2951 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2952 result = lchmod(path->narrow, mode);
2953 else
2954 #endif
2955 #ifdef HAVE_FCHMODAT
2956 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2957 /*
2958 * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
2959 * The documentation specifically shows how to use it,
2960 * and then says it isn't implemented yet.
2961 * (true on linux with glibc 2.15, and openindiana 3.x)
2962 *
2963 * Once it is supported, os.chmod will automatically
2964 * support dir_fd and follow_symlinks=False. (Hopefully.)
2965 * Until then, we need to be careful what exception we raise.
2966 */
2967 result = fchmodat(dir_fd, path->narrow, mode,
2968 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2969 /*
2970 * But wait! We can't throw the exception without allowing threads,
2971 * and we can't do that in this nested scope. (Macro trickery, sigh.)
2972 */
2973 fchmodat_nofollow_unsupported =
2974 result &&
2975 ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
2976 !follow_symlinks;
2977 }
2978 else
2979 #endif
2980 result = chmod(path->narrow, mode);
2981 Py_END_ALLOW_THREADS
2982
2983 if (result) {
2984 #ifdef HAVE_FCHMODAT
2985 if (fchmodat_nofollow_unsupported) {
2986 if (dir_fd != DEFAULT_DIR_FD)
2987 dir_fd_and_follow_symlinks_invalid("chmod",
2988 dir_fd, follow_symlinks);
2989 else
2990 follow_symlinks_specified("chmod", follow_symlinks);
2991 return NULL;
2992 }
2993 else
2994 #endif
2995 return path_error(path);
2996 }
2997 #endif
2998
2999 Py_RETURN_NONE;
3000 }
3001
3002
3003 #ifdef HAVE_FCHMOD
3004 /*[clinic input]
3005 os.fchmod
3006
3007 fd: int
3008 mode: int
3009
3010 Change the access permissions of the file given by file descriptor fd.
3011
3012 Equivalent to os.chmod(fd, mode).
3013 [clinic start generated code]*/
3014
3015 static PyObject *
os_fchmod_impl(PyObject * module,int fd,int mode)3016 os_fchmod_impl(PyObject *module, int fd, int mode)
3017 /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
3018 {
3019 int res;
3020 int async_err = 0;
3021
3022 do {
3023 Py_BEGIN_ALLOW_THREADS
3024 res = fchmod(fd, mode);
3025 Py_END_ALLOW_THREADS
3026 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3027 if (res != 0)
3028 return (!async_err) ? posix_error() : NULL;
3029
3030 Py_RETURN_NONE;
3031 }
3032 #endif /* HAVE_FCHMOD */
3033
3034
3035 #ifdef HAVE_LCHMOD
3036 /*[clinic input]
3037 os.lchmod
3038
3039 path: path_t
3040 mode: int
3041
3042 Change the access permissions of a file, without following symbolic links.
3043
3044 If path is a symlink, this affects the link itself rather than the target.
3045 Equivalent to chmod(path, mode, follow_symlinks=False)."
3046 [clinic start generated code]*/
3047
3048 static PyObject *
os_lchmod_impl(PyObject * module,path_t * path,int mode)3049 os_lchmod_impl(PyObject *module, path_t *path, int mode)
3050 /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3051 {
3052 int res;
3053 Py_BEGIN_ALLOW_THREADS
3054 res = lchmod(path->narrow, mode);
3055 Py_END_ALLOW_THREADS
3056 if (res < 0) {
3057 path_error(path);
3058 return NULL;
3059 }
3060 Py_RETURN_NONE;
3061 }
3062 #endif /* HAVE_LCHMOD */
3063
3064
3065 #ifdef HAVE_CHFLAGS
3066 /*[clinic input]
3067 os.chflags
3068
3069 path: path_t
3070 flags: unsigned_long(bitwise=True)
3071 follow_symlinks: bool=True
3072
3073 Set file flags.
3074
3075 If follow_symlinks is False, and the last element of the path is a symbolic
3076 link, chflags will change flags on the symbolic link itself instead of the
3077 file the link points to.
3078 follow_symlinks may not be implemented on your platform. If it is
3079 unavailable, using it will raise a NotImplementedError.
3080
3081 [clinic start generated code]*/
3082
3083 static PyObject *
os_chflags_impl(PyObject * module,path_t * path,unsigned long flags,int follow_symlinks)3084 os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3085 int follow_symlinks)
3086 /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3087 {
3088 int result;
3089
3090 #ifndef HAVE_LCHFLAGS
3091 if (follow_symlinks_specified("chflags", follow_symlinks))
3092 return NULL;
3093 #endif
3094
3095 Py_BEGIN_ALLOW_THREADS
3096 #ifdef HAVE_LCHFLAGS
3097 if (!follow_symlinks)
3098 result = lchflags(path->narrow, flags);
3099 else
3100 #endif
3101 result = chflags(path->narrow, flags);
3102 Py_END_ALLOW_THREADS
3103
3104 if (result)
3105 return path_error(path);
3106
3107 Py_RETURN_NONE;
3108 }
3109 #endif /* HAVE_CHFLAGS */
3110
3111
3112 #ifdef HAVE_LCHFLAGS
3113 /*[clinic input]
3114 os.lchflags
3115
3116 path: path_t
3117 flags: unsigned_long(bitwise=True)
3118
3119 Set file flags.
3120
3121 This function will not follow symbolic links.
3122 Equivalent to chflags(path, flags, follow_symlinks=False).
3123 [clinic start generated code]*/
3124
3125 static PyObject *
os_lchflags_impl(PyObject * module,path_t * path,unsigned long flags)3126 os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3127 /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3128 {
3129 int res;
3130 Py_BEGIN_ALLOW_THREADS
3131 res = lchflags(path->narrow, flags);
3132 Py_END_ALLOW_THREADS
3133 if (res < 0) {
3134 return path_error(path);
3135 }
3136 Py_RETURN_NONE;
3137 }
3138 #endif /* HAVE_LCHFLAGS */
3139
3140
3141 #ifdef HAVE_CHROOT
3142 /*[clinic input]
3143 os.chroot
3144 path: path_t
3145
3146 Change root directory to path.
3147
3148 [clinic start generated code]*/
3149
3150 static PyObject *
os_chroot_impl(PyObject * module,path_t * path)3151 os_chroot_impl(PyObject *module, path_t *path)
3152 /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3153 {
3154 int res;
3155 Py_BEGIN_ALLOW_THREADS
3156 res = chroot(path->narrow);
3157 Py_END_ALLOW_THREADS
3158 if (res < 0)
3159 return path_error(path);
3160 Py_RETURN_NONE;
3161 }
3162 #endif /* HAVE_CHROOT */
3163
3164
3165 #ifdef HAVE_FSYNC
3166 /*[clinic input]
3167 os.fsync
3168
3169 fd: fildes
3170
3171 Force write of fd to disk.
3172 [clinic start generated code]*/
3173
3174 static PyObject *
os_fsync_impl(PyObject * module,int fd)3175 os_fsync_impl(PyObject *module, int fd)
3176 /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3177 {
3178 return posix_fildes_fd(fd, fsync);
3179 }
3180 #endif /* HAVE_FSYNC */
3181
3182
3183 #ifdef HAVE_SYNC
3184 /*[clinic input]
3185 os.sync
3186
3187 Force write of everything to disk.
3188 [clinic start generated code]*/
3189
3190 static PyObject *
os_sync_impl(PyObject * module)3191 os_sync_impl(PyObject *module)
3192 /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3193 {
3194 Py_BEGIN_ALLOW_THREADS
3195 sync();
3196 Py_END_ALLOW_THREADS
3197 Py_RETURN_NONE;
3198 }
3199 #endif /* HAVE_SYNC */
3200
3201
3202 #ifdef HAVE_FDATASYNC
3203 #ifdef __hpux
3204 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3205 #endif
3206
3207 /*[clinic input]
3208 os.fdatasync
3209
3210 fd: fildes
3211
3212 Force write of fd to disk without forcing update of metadata.
3213 [clinic start generated code]*/
3214
3215 static PyObject *
os_fdatasync_impl(PyObject * module,int fd)3216 os_fdatasync_impl(PyObject *module, int fd)
3217 /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3218 {
3219 return posix_fildes_fd(fd, fdatasync);
3220 }
3221 #endif /* HAVE_FDATASYNC */
3222
3223
3224 #ifdef HAVE_CHOWN
3225 /*[clinic input]
3226 os.chown
3227
3228 path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3229 Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3230
3231 uid: uid_t
3232
3233 gid: gid_t
3234
3235 *
3236
3237 dir_fd : dir_fd(requires='fchownat') = None
3238 If not None, it should be a file descriptor open to a directory,
3239 and path should be relative; path will then be relative to that
3240 directory.
3241
3242 follow_symlinks: bool = True
3243 If False, and the last element of the path is a symbolic link,
3244 stat will examine the symbolic link itself instead of the file
3245 the link points to.
3246
3247 Change the owner and group id of path to the numeric uid and gid.\
3248
3249 path may always be specified as a string.
3250 On some platforms, path may also be specified as an open file descriptor.
3251 If this functionality is unavailable, using it raises an exception.
3252 If dir_fd is not None, it should be a file descriptor open to a directory,
3253 and path should be relative; path will then be relative to that directory.
3254 If follow_symlinks is False, and the last element of the path is a symbolic
3255 link, chown will modify the symbolic link itself instead of the file the
3256 link points to.
3257 It is an error to use dir_fd or follow_symlinks when specifying path as
3258 an open file descriptor.
3259 dir_fd and follow_symlinks may not be implemented on your platform.
3260 If they are unavailable, using them will raise a NotImplementedError.
3261
3262 [clinic start generated code]*/
3263
3264 static PyObject *
os_chown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid,int dir_fd,int follow_symlinks)3265 os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3266 int dir_fd, int follow_symlinks)
3267 /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3268 {
3269 int result;
3270
3271 #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3272 if (follow_symlinks_specified("chown", follow_symlinks))
3273 return NULL;
3274 #endif
3275 if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3276 fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3277 return NULL;
3278
3279 #ifdef __APPLE__
3280 /*
3281 * This is for Mac OS X 10.3, which doesn't have lchown.
3282 * (But we still have an lchown symbol because of weak-linking.)
3283 * It doesn't have fchownat either. So there's no possibility
3284 * of a graceful failover.
3285 */
3286 if ((!follow_symlinks) && (lchown == NULL)) {
3287 follow_symlinks_specified("chown", follow_symlinks);
3288 return NULL;
3289 }
3290 #endif
3291
3292 Py_BEGIN_ALLOW_THREADS
3293 #ifdef HAVE_FCHOWN
3294 if (path->fd != -1)
3295 result = fchown(path->fd, uid, gid);
3296 else
3297 #endif
3298 #ifdef HAVE_LCHOWN
3299 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3300 result = lchown(path->narrow, uid, gid);
3301 else
3302 #endif
3303 #ifdef HAVE_FCHOWNAT
3304 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
3305 result = fchownat(dir_fd, path->narrow, uid, gid,
3306 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3307 else
3308 #endif
3309 result = chown(path->narrow, uid, gid);
3310 Py_END_ALLOW_THREADS
3311
3312 if (result)
3313 return path_error(path);
3314
3315 Py_RETURN_NONE;
3316 }
3317 #endif /* HAVE_CHOWN */
3318
3319
3320 #ifdef HAVE_FCHOWN
3321 /*[clinic input]
3322 os.fchown
3323
3324 fd: int
3325 uid: uid_t
3326 gid: gid_t
3327
3328 Change the owner and group id of the file specified by file descriptor.
3329
3330 Equivalent to os.chown(fd, uid, gid).
3331
3332 [clinic start generated code]*/
3333
3334 static PyObject *
os_fchown_impl(PyObject * module,int fd,uid_t uid,gid_t gid)3335 os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3336 /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3337 {
3338 int res;
3339 int async_err = 0;
3340
3341 do {
3342 Py_BEGIN_ALLOW_THREADS
3343 res = fchown(fd, uid, gid);
3344 Py_END_ALLOW_THREADS
3345 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3346 if (res != 0)
3347 return (!async_err) ? posix_error() : NULL;
3348
3349 Py_RETURN_NONE;
3350 }
3351 #endif /* HAVE_FCHOWN */
3352
3353
3354 #ifdef HAVE_LCHOWN
3355 /*[clinic input]
3356 os.lchown
3357
3358 path : path_t
3359 uid: uid_t
3360 gid: gid_t
3361
3362 Change the owner and group id of path to the numeric uid and gid.
3363
3364 This function will not follow symbolic links.
3365 Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3366 [clinic start generated code]*/
3367
3368 static PyObject *
os_lchown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid)3369 os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3370 /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3371 {
3372 int res;
3373 Py_BEGIN_ALLOW_THREADS
3374 res = lchown(path->narrow, uid, gid);
3375 Py_END_ALLOW_THREADS
3376 if (res < 0) {
3377 return path_error(path);
3378 }
3379 Py_RETURN_NONE;
3380 }
3381 #endif /* HAVE_LCHOWN */
3382
3383
3384 static PyObject *
posix_getcwd(int use_bytes)3385 posix_getcwd(int use_bytes)
3386 {
3387 #ifdef MS_WINDOWS
3388 wchar_t wbuf[MAXPATHLEN];
3389 wchar_t *wbuf2 = wbuf;
3390 DWORD len;
3391
3392 Py_BEGIN_ALLOW_THREADS
3393 len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3394 /* If the buffer is large enough, len does not include the
3395 terminating \0. If the buffer is too small, len includes
3396 the space needed for the terminator. */
3397 if (len >= Py_ARRAY_LENGTH(wbuf)) {
3398 if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3399 wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3400 }
3401 else {
3402 wbuf2 = NULL;
3403 }
3404 if (wbuf2) {
3405 len = GetCurrentDirectoryW(len, wbuf2);
3406 }
3407 }
3408 Py_END_ALLOW_THREADS
3409
3410 if (!wbuf2) {
3411 PyErr_NoMemory();
3412 return NULL;
3413 }
3414 if (!len) {
3415 if (wbuf2 != wbuf)
3416 PyMem_RawFree(wbuf2);
3417 return PyErr_SetFromWindowsErr(0);
3418 }
3419
3420 PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3421 if (wbuf2 != wbuf) {
3422 PyMem_RawFree(wbuf2);
3423 }
3424
3425 if (use_bytes) {
3426 if (resobj == NULL) {
3427 return NULL;
3428 }
3429 Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3430 }
3431
3432 return resobj;
3433 #else
3434 const size_t chunk = 1024;
3435
3436 char *buf = NULL;
3437 char *cwd = NULL;
3438 size_t buflen = 0;
3439
3440 Py_BEGIN_ALLOW_THREADS
3441 do {
3442 char *newbuf;
3443 if (buflen <= PY_SSIZE_T_MAX - chunk) {
3444 buflen += chunk;
3445 newbuf = PyMem_RawRealloc(buf, buflen);
3446 }
3447 else {
3448 newbuf = NULL;
3449 }
3450 if (newbuf == NULL) {
3451 PyMem_RawFree(buf);
3452 buf = NULL;
3453 break;
3454 }
3455 buf = newbuf;
3456
3457 cwd = getcwd(buf, buflen);
3458 } while (cwd == NULL && errno == ERANGE);
3459 Py_END_ALLOW_THREADS
3460
3461 if (buf == NULL) {
3462 return PyErr_NoMemory();
3463 }
3464 if (cwd == NULL) {
3465 PyMem_RawFree(buf);
3466 return posix_error();
3467 }
3468
3469 PyObject *obj;
3470 if (use_bytes) {
3471 obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3472 }
3473 else {
3474 obj = PyUnicode_DecodeFSDefault(buf);
3475 }
3476 PyMem_RawFree(buf);
3477
3478 return obj;
3479 #endif /* !MS_WINDOWS */
3480 }
3481
3482
3483 /*[clinic input]
3484 os.getcwd
3485
3486 Return a unicode string representing the current working directory.
3487 [clinic start generated code]*/
3488
3489 static PyObject *
os_getcwd_impl(PyObject * module)3490 os_getcwd_impl(PyObject *module)
3491 /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3492 {
3493 return posix_getcwd(0);
3494 }
3495
3496
3497 /*[clinic input]
3498 os.getcwdb
3499
3500 Return a bytes string representing the current working directory.
3501 [clinic start generated code]*/
3502
3503 static PyObject *
os_getcwdb_impl(PyObject * module)3504 os_getcwdb_impl(PyObject *module)
3505 /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3506 {
3507 return posix_getcwd(1);
3508 }
3509
3510
3511 #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3512 #define HAVE_LINK 1
3513 #endif
3514
3515 #ifdef HAVE_LINK
3516 /*[clinic input]
3517
3518 os.link
3519
3520 src : path_t
3521 dst : path_t
3522 *
3523 src_dir_fd : dir_fd = None
3524 dst_dir_fd : dir_fd = None
3525 follow_symlinks: bool = True
3526
3527 Create a hard link to a file.
3528
3529 If either src_dir_fd or dst_dir_fd is not None, it should be a file
3530 descriptor open to a directory, and the respective path string (src or dst)
3531 should be relative; the path will then be relative to that directory.
3532 If follow_symlinks is False, and the last element of src is a symbolic
3533 link, link will create a link to the symbolic link itself instead of the
3534 file the link points to.
3535 src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3536 platform. If they are unavailable, using them will raise a
3537 NotImplementedError.
3538 [clinic start generated code]*/
3539
3540 static PyObject *
os_link_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int follow_symlinks)3541 os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3542 int dst_dir_fd, int follow_symlinks)
3543 /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3544 {
3545 #ifdef MS_WINDOWS
3546 BOOL result = FALSE;
3547 #else
3548 int result;
3549 #endif
3550
3551 #ifndef HAVE_LINKAT
3552 if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3553 argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3554 return NULL;
3555 }
3556 #endif
3557
3558 #ifndef MS_WINDOWS
3559 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3560 PyErr_SetString(PyExc_NotImplementedError,
3561 "link: src and dst must be the same type");
3562 return NULL;
3563 }
3564 #endif
3565
3566 #ifdef MS_WINDOWS
3567 Py_BEGIN_ALLOW_THREADS
3568 result = CreateHardLinkW(dst->wide, src->wide, NULL);
3569 Py_END_ALLOW_THREADS
3570
3571 if (!result)
3572 return path_error2(src, dst);
3573 #else
3574 Py_BEGIN_ALLOW_THREADS
3575 #ifdef HAVE_LINKAT
3576 if ((src_dir_fd != DEFAULT_DIR_FD) ||
3577 (dst_dir_fd != DEFAULT_DIR_FD) ||
3578 (!follow_symlinks))
3579 result = linkat(src_dir_fd, src->narrow,
3580 dst_dir_fd, dst->narrow,
3581 follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3582 else
3583 #endif /* HAVE_LINKAT */
3584 result = link(src->narrow, dst->narrow);
3585 Py_END_ALLOW_THREADS
3586
3587 if (result)
3588 return path_error2(src, dst);
3589 #endif /* MS_WINDOWS */
3590
3591 Py_RETURN_NONE;
3592 }
3593 #endif
3594
3595
3596 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3597 static PyObject *
_listdir_windows_no_opendir(path_t * path,PyObject * list)3598 _listdir_windows_no_opendir(path_t *path, PyObject *list)
3599 {
3600 PyObject *v;
3601 HANDLE hFindFile = INVALID_HANDLE_VALUE;
3602 BOOL result;
3603 wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
3604 /* only claim to have space for MAX_PATH */
3605 Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
3606 wchar_t *wnamebuf = NULL;
3607
3608 WIN32_FIND_DATAW wFileData;
3609 const wchar_t *po_wchars;
3610
3611 if (!path->wide) { /* Default arg: "." */
3612 po_wchars = L".";
3613 len = 1;
3614 } else {
3615 po_wchars = path->wide;
3616 len = wcslen(path->wide);
3617 }
3618 /* The +5 is so we can append "\\*.*\0" */
3619 wnamebuf = PyMem_New(wchar_t, len + 5);
3620 if (!wnamebuf) {
3621 PyErr_NoMemory();
3622 goto exit;
3623 }
3624 wcscpy(wnamebuf, po_wchars);
3625 if (len > 0) {
3626 wchar_t wch = wnamebuf[len-1];
3627 if (wch != SEP && wch != ALTSEP && wch != L':')
3628 wnamebuf[len++] = SEP;
3629 wcscpy(wnamebuf + len, L"*.*");
3630 }
3631 if ((list = PyList_New(0)) == NULL) {
3632 goto exit;
3633 }
3634 Py_BEGIN_ALLOW_THREADS
3635 hFindFile = FindFirstFileW(wnamebuf, &wFileData);
3636 Py_END_ALLOW_THREADS
3637 if (hFindFile == INVALID_HANDLE_VALUE) {
3638 int error = GetLastError();
3639 if (error == ERROR_FILE_NOT_FOUND)
3640 goto exit;
3641 Py_DECREF(list);
3642 list = path_error(path);
3643 goto exit;
3644 }
3645 do {
3646 /* Skip over . and .. */
3647 if (wcscmp(wFileData.cFileName, L".") != 0 &&
3648 wcscmp(wFileData.cFileName, L"..") != 0) {
3649 v = PyUnicode_FromWideChar(wFileData.cFileName,
3650 wcslen(wFileData.cFileName));
3651 if (path->narrow && v) {
3652 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
3653 }
3654 if (v == NULL) {
3655 Py_DECREF(list);
3656 list = NULL;
3657 break;
3658 }
3659 if (PyList_Append(list, v) != 0) {
3660 Py_DECREF(v);
3661 Py_DECREF(list);
3662 list = NULL;
3663 break;
3664 }
3665 Py_DECREF(v);
3666 }
3667 Py_BEGIN_ALLOW_THREADS
3668 result = FindNextFileW(hFindFile, &wFileData);
3669 Py_END_ALLOW_THREADS
3670 /* FindNextFile sets error to ERROR_NO_MORE_FILES if
3671 it got to the end of the directory. */
3672 if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
3673 Py_DECREF(list);
3674 list = path_error(path);
3675 goto exit;
3676 }
3677 } while (result == TRUE);
3678
3679 exit:
3680 if (hFindFile != INVALID_HANDLE_VALUE) {
3681 if (FindClose(hFindFile) == FALSE) {
3682 if (list != NULL) {
3683 Py_DECREF(list);
3684 list = path_error(path);
3685 }
3686 }
3687 }
3688 PyMem_Free(wnamebuf);
3689
3690 return list;
3691 } /* end of _listdir_windows_no_opendir */
3692
3693 #else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
3694
3695 static PyObject *
_posix_listdir(path_t * path,PyObject * list)3696 _posix_listdir(path_t *path, PyObject *list)
3697 {
3698 PyObject *v;
3699 DIR *dirp = NULL;
3700 struct dirent *ep;
3701 int return_str; /* if false, return bytes */
3702 #ifdef HAVE_FDOPENDIR
3703 int fd = -1;
3704 #endif
3705
3706 errno = 0;
3707 #ifdef HAVE_FDOPENDIR
3708 if (path->fd != -1) {
3709 /* closedir() closes the FD, so we duplicate it */
3710 fd = _Py_dup(path->fd);
3711 if (fd == -1)
3712 return NULL;
3713
3714 return_str = 1;
3715
3716 Py_BEGIN_ALLOW_THREADS
3717 dirp = fdopendir(fd);
3718 Py_END_ALLOW_THREADS
3719 }
3720 else
3721 #endif
3722 {
3723 const char *name;
3724 if (path->narrow) {
3725 name = path->narrow;
3726 /* only return bytes if they specified a bytes-like object */
3727 return_str = !PyObject_CheckBuffer(path->object);
3728 }
3729 else {
3730 name = ".";
3731 return_str = 1;
3732 }
3733
3734 Py_BEGIN_ALLOW_THREADS
3735 dirp = opendir(name);
3736 Py_END_ALLOW_THREADS
3737 }
3738
3739 if (dirp == NULL) {
3740 list = path_error(path);
3741 #ifdef HAVE_FDOPENDIR
3742 if (fd != -1) {
3743 Py_BEGIN_ALLOW_THREADS
3744 close(fd);
3745 Py_END_ALLOW_THREADS
3746 }
3747 #endif
3748 goto exit;
3749 }
3750 if ((list = PyList_New(0)) == NULL) {
3751 goto exit;
3752 }
3753 for (;;) {
3754 errno = 0;
3755 Py_BEGIN_ALLOW_THREADS
3756 ep = readdir(dirp);
3757 Py_END_ALLOW_THREADS
3758 if (ep == NULL) {
3759 if (errno == 0) {
3760 break;
3761 } else {
3762 Py_DECREF(list);
3763 list = path_error(path);
3764 goto exit;
3765 }
3766 }
3767 if (ep->d_name[0] == '.' &&
3768 (NAMLEN(ep) == 1 ||
3769 (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
3770 continue;
3771 if (return_str)
3772 v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
3773 else
3774 v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
3775 if (v == NULL) {
3776 Py_CLEAR(list);
3777 break;
3778 }
3779 if (PyList_Append(list, v) != 0) {
3780 Py_DECREF(v);
3781 Py_CLEAR(list);
3782 break;
3783 }
3784 Py_DECREF(v);
3785 }
3786
3787 exit:
3788 if (dirp != NULL) {
3789 Py_BEGIN_ALLOW_THREADS
3790 #ifdef HAVE_FDOPENDIR
3791 if (fd > -1)
3792 rewinddir(dirp);
3793 #endif
3794 closedir(dirp);
3795 Py_END_ALLOW_THREADS
3796 }
3797
3798 return list;
3799 } /* end of _posix_listdir */
3800 #endif /* which OS */
3801
3802
3803 /*[clinic input]
3804 os.listdir
3805
3806 path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
3807
3808 Return a list containing the names of the files in the directory.
3809
3810 path can be specified as either str, bytes, or a path-like object. If path is bytes,
3811 the filenames returned will also be bytes; in all other circumstances
3812 the filenames returned will be str.
3813 If path is None, uses the path='.'.
3814 On some platforms, path may also be specified as an open file descriptor;\
3815 the file descriptor must refer to a directory.
3816 If this functionality is unavailable, using it raises NotImplementedError.
3817
3818 The list is in arbitrary order. It does not include the special
3819 entries '.' and '..' even if they are present in the directory.
3820
3821
3822 [clinic start generated code]*/
3823
3824 static PyObject *
os_listdir_impl(PyObject * module,path_t * path)3825 os_listdir_impl(PyObject *module, path_t *path)
3826 /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
3827 {
3828 if (PySys_Audit("os.listdir", "O",
3829 path->object ? path->object : Py_None) < 0) {
3830 return NULL;
3831 }
3832 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3833 return _listdir_windows_no_opendir(path, NULL);
3834 #else
3835 return _posix_listdir(path, NULL);
3836 #endif
3837 }
3838
3839 #ifdef MS_WINDOWS
3840 /* A helper function for abspath on win32 */
3841 /*[clinic input]
3842 os._getfullpathname
3843
3844 path: path_t
3845 /
3846
3847 [clinic start generated code]*/
3848
3849 static PyObject *
os__getfullpathname_impl(PyObject * module,path_t * path)3850 os__getfullpathname_impl(PyObject *module, path_t *path)
3851 /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
3852 {
3853 wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
3854 wchar_t *wtemp;
3855 DWORD result;
3856 PyObject *v;
3857
3858 result = GetFullPathNameW(path->wide,
3859 Py_ARRAY_LENGTH(woutbuf),
3860 woutbuf, &wtemp);
3861 if (result > Py_ARRAY_LENGTH(woutbuf)) {
3862 woutbufp = PyMem_New(wchar_t, result);
3863 if (!woutbufp)
3864 return PyErr_NoMemory();
3865 result = GetFullPathNameW(path->wide, result, woutbufp, &wtemp);
3866 }
3867 if (result) {
3868 v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp));
3869 if (path->narrow)
3870 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
3871 } else
3872 v = win32_error_object("GetFullPathNameW", path->object);
3873 if (woutbufp != woutbuf)
3874 PyMem_Free(woutbufp);
3875 return v;
3876 }
3877
3878
3879 /*[clinic input]
3880 os._getfinalpathname
3881
3882 path: path_t
3883 /
3884
3885 A helper function for samepath on windows.
3886 [clinic start generated code]*/
3887
3888 static PyObject *
os__getfinalpathname_impl(PyObject * module,path_t * path)3889 os__getfinalpathname_impl(PyObject *module, path_t *path)
3890 /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
3891 {
3892 HANDLE hFile;
3893 wchar_t buf[MAXPATHLEN], *target_path = buf;
3894 int buf_size = Py_ARRAY_LENGTH(buf);
3895 int result_length;
3896 PyObject *result;
3897
3898 Py_BEGIN_ALLOW_THREADS
3899 hFile = CreateFileW(
3900 path->wide,
3901 0, /* desired access */
3902 0, /* share mode */
3903 NULL, /* security attributes */
3904 OPEN_EXISTING,
3905 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
3906 FILE_FLAG_BACKUP_SEMANTICS,
3907 NULL);
3908 Py_END_ALLOW_THREADS
3909
3910 if (hFile == INVALID_HANDLE_VALUE) {
3911 return win32_error_object("CreateFileW", path->object);
3912 }
3913
3914 /* We have a good handle to the target, use it to determine the
3915 target path name. */
3916 while (1) {
3917 Py_BEGIN_ALLOW_THREADS
3918 result_length = GetFinalPathNameByHandleW(hFile, target_path,
3919 buf_size, VOLUME_NAME_DOS);
3920 Py_END_ALLOW_THREADS
3921
3922 if (!result_length) {
3923 result = win32_error_object("GetFinalPathNameByHandleW",
3924 path->object);
3925 goto cleanup;
3926 }
3927
3928 if (result_length < buf_size) {
3929 break;
3930 }
3931
3932 wchar_t *tmp;
3933 tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
3934 result_length * sizeof(*tmp));
3935 if (!tmp) {
3936 result = PyErr_NoMemory();
3937 goto cleanup;
3938 }
3939
3940 buf_size = result_length;
3941 target_path = tmp;
3942 }
3943
3944 result = PyUnicode_FromWideChar(target_path, result_length);
3945 if (result && path->narrow) {
3946 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
3947 }
3948
3949 cleanup:
3950 if (target_path != buf) {
3951 PyMem_Free(target_path);
3952 }
3953 CloseHandle(hFile);
3954 return result;
3955 }
3956
3957
3958 /*[clinic input]
3959 os._getvolumepathname
3960
3961 path: path_t
3962
3963 A helper function for ismount on Win32.
3964 [clinic start generated code]*/
3965
3966 static PyObject *
os__getvolumepathname_impl(PyObject * module,path_t * path)3967 os__getvolumepathname_impl(PyObject *module, path_t *path)
3968 /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
3969 {
3970 PyObject *result;
3971 wchar_t *mountpath=NULL;
3972 size_t buflen;
3973 BOOL ret;
3974
3975 /* Volume path should be shorter than entire path */
3976 buflen = Py_MAX(path->length, MAX_PATH);
3977
3978 if (buflen > PY_DWORD_MAX) {
3979 PyErr_SetString(PyExc_OverflowError, "path too long");
3980 return NULL;
3981 }
3982
3983 mountpath = PyMem_New(wchar_t, buflen);
3984 if (mountpath == NULL)
3985 return PyErr_NoMemory();
3986
3987 Py_BEGIN_ALLOW_THREADS
3988 ret = GetVolumePathNameW(path->wide, mountpath,
3989 Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
3990 Py_END_ALLOW_THREADS
3991
3992 if (!ret) {
3993 result = win32_error_object("_getvolumepathname", path->object);
3994 goto exit;
3995 }
3996 result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
3997 if (path->narrow)
3998 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
3999
4000 exit:
4001 PyMem_Free(mountpath);
4002 return result;
4003 }
4004
4005 #endif /* MS_WINDOWS */
4006
4007
4008 /*[clinic input]
4009 os.mkdir
4010
4011 path : path_t
4012
4013 mode: int = 0o777
4014
4015 *
4016
4017 dir_fd : dir_fd(requires='mkdirat') = None
4018
4019 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4020
4021 Create a directory.
4022
4023 If dir_fd is not None, it should be a file descriptor open to a directory,
4024 and path should be relative; path will then be relative to that directory.
4025 dir_fd may not be implemented on your platform.
4026 If it is unavailable, using it will raise a NotImplementedError.
4027
4028 The mode argument is ignored on Windows.
4029 [clinic start generated code]*/
4030
4031 static PyObject *
os_mkdir_impl(PyObject * module,path_t * path,int mode,int dir_fd)4032 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4033 /*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/
4034 {
4035 int result;
4036
4037 #ifdef MS_WINDOWS
4038 Py_BEGIN_ALLOW_THREADS
4039 result = CreateDirectoryW(path->wide, NULL);
4040 Py_END_ALLOW_THREADS
4041
4042 if (!result)
4043 return path_error(path);
4044 #else
4045 Py_BEGIN_ALLOW_THREADS
4046 #if HAVE_MKDIRAT
4047 if (dir_fd != DEFAULT_DIR_FD)
4048 result = mkdirat(dir_fd, path->narrow, mode);
4049 else
4050 #endif
4051 #if defined(__WATCOMC__) && !defined(__QNX__)
4052 result = mkdir(path->narrow);
4053 #else
4054 result = mkdir(path->narrow, mode);
4055 #endif
4056 Py_END_ALLOW_THREADS
4057 if (result < 0)
4058 return path_error(path);
4059 #endif /* MS_WINDOWS */
4060 Py_RETURN_NONE;
4061 }
4062
4063
4064 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4065 #if defined(HAVE_SYS_RESOURCE_H)
4066 #include <sys/resource.h>
4067 #endif
4068
4069
4070 #ifdef HAVE_NICE
4071 /*[clinic input]
4072 os.nice
4073
4074 increment: int
4075 /
4076
4077 Add increment to the priority of process and return the new priority.
4078 [clinic start generated code]*/
4079
4080 static PyObject *
os_nice_impl(PyObject * module,int increment)4081 os_nice_impl(PyObject *module, int increment)
4082 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4083 {
4084 int value;
4085
4086 /* There are two flavours of 'nice': one that returns the new
4087 priority (as required by almost all standards out there) and the
4088 Linux/FreeBSD one, which returns '0' on success and advices
4089 the use of getpriority() to get the new priority.
4090
4091 If we are of the nice family that returns the new priority, we
4092 need to clear errno before the call, and check if errno is filled
4093 before calling posix_error() on a returnvalue of -1, because the
4094 -1 may be the actual new priority! */
4095
4096 errno = 0;
4097 value = nice(increment);
4098 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4099 if (value == 0)
4100 value = getpriority(PRIO_PROCESS, 0);
4101 #endif
4102 if (value == -1 && errno != 0)
4103 /* either nice() or getpriority() returned an error */
4104 return posix_error();
4105 return PyLong_FromLong((long) value);
4106 }
4107 #endif /* HAVE_NICE */
4108
4109
4110 #ifdef HAVE_GETPRIORITY
4111 /*[clinic input]
4112 os.getpriority
4113
4114 which: int
4115 who: int
4116
4117 Return program scheduling priority.
4118 [clinic start generated code]*/
4119
4120 static PyObject *
os_getpriority_impl(PyObject * module,int which,int who)4121 os_getpriority_impl(PyObject *module, int which, int who)
4122 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4123 {
4124 int retval;
4125
4126 errno = 0;
4127 retval = getpriority(which, who);
4128 if (errno != 0)
4129 return posix_error();
4130 return PyLong_FromLong((long)retval);
4131 }
4132 #endif /* HAVE_GETPRIORITY */
4133
4134
4135 #ifdef HAVE_SETPRIORITY
4136 /*[clinic input]
4137 os.setpriority
4138
4139 which: int
4140 who: int
4141 priority: int
4142
4143 Set program scheduling priority.
4144 [clinic start generated code]*/
4145
4146 static PyObject *
os_setpriority_impl(PyObject * module,int which,int who,int priority)4147 os_setpriority_impl(PyObject *module, int which, int who, int priority)
4148 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4149 {
4150 int retval;
4151
4152 retval = setpriority(which, who, priority);
4153 if (retval == -1)
4154 return posix_error();
4155 Py_RETURN_NONE;
4156 }
4157 #endif /* HAVE_SETPRIORITY */
4158
4159
4160 static PyObject *
internal_rename(path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int is_replace)4161 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4162 {
4163 const char *function_name = is_replace ? "replace" : "rename";
4164 int dir_fd_specified;
4165
4166 #ifdef MS_WINDOWS
4167 BOOL result;
4168 int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4169 #else
4170 int result;
4171 #endif
4172
4173 dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4174 (dst_dir_fd != DEFAULT_DIR_FD);
4175 #ifndef HAVE_RENAMEAT
4176 if (dir_fd_specified) {
4177 argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4178 return NULL;
4179 }
4180 #endif
4181
4182 #ifdef MS_WINDOWS
4183 Py_BEGIN_ALLOW_THREADS
4184 result = MoveFileExW(src->wide, dst->wide, flags);
4185 Py_END_ALLOW_THREADS
4186
4187 if (!result)
4188 return path_error2(src, dst);
4189
4190 #else
4191 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4192 PyErr_Format(PyExc_ValueError,
4193 "%s: src and dst must be the same type", function_name);
4194 return NULL;
4195 }
4196
4197 Py_BEGIN_ALLOW_THREADS
4198 #ifdef HAVE_RENAMEAT
4199 if (dir_fd_specified)
4200 result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4201 else
4202 #endif
4203 result = rename(src->narrow, dst->narrow);
4204 Py_END_ALLOW_THREADS
4205
4206 if (result)
4207 return path_error2(src, dst);
4208 #endif
4209 Py_RETURN_NONE;
4210 }
4211
4212
4213 /*[clinic input]
4214 os.rename
4215
4216 src : path_t
4217 dst : path_t
4218 *
4219 src_dir_fd : dir_fd = None
4220 dst_dir_fd : dir_fd = None
4221
4222 Rename a file or directory.
4223
4224 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4225 descriptor open to a directory, and the respective path string (src or dst)
4226 should be relative; the path will then be relative to that directory.
4227 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4228 If they are unavailable, using them will raise a NotImplementedError.
4229 [clinic start generated code]*/
4230
4231 static PyObject *
os_rename_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4232 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4233 int dst_dir_fd)
4234 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4235 {
4236 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4237 }
4238
4239
4240 /*[clinic input]
4241 os.replace = os.rename
4242
4243 Rename a file or directory, overwriting the destination.
4244
4245 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4246 descriptor open to a directory, and the respective path string (src or dst)
4247 should be relative; the path will then be relative to that directory.
4248 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4249 If they are unavailable, using them will raise a NotImplementedError.
4250 [clinic start generated code]*/
4251
4252 static PyObject *
os_replace_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4253 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4254 int dst_dir_fd)
4255 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4256 {
4257 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4258 }
4259
4260
4261 /*[clinic input]
4262 os.rmdir
4263
4264 path: path_t
4265 *
4266 dir_fd: dir_fd(requires='unlinkat') = None
4267
4268 Remove a directory.
4269
4270 If dir_fd is not None, it should be a file descriptor open to a directory,
4271 and path should be relative; path will then be relative to that directory.
4272 dir_fd may not be implemented on your platform.
4273 If it is unavailable, using it will raise a NotImplementedError.
4274 [clinic start generated code]*/
4275
4276 static PyObject *
os_rmdir_impl(PyObject * module,path_t * path,int dir_fd)4277 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4278 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4279 {
4280 int result;
4281
4282 Py_BEGIN_ALLOW_THREADS
4283 #ifdef MS_WINDOWS
4284 /* Windows, success=1, UNIX, success=0 */
4285 result = !RemoveDirectoryW(path->wide);
4286 #else
4287 #ifdef HAVE_UNLINKAT
4288 if (dir_fd != DEFAULT_DIR_FD)
4289 result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4290 else
4291 #endif
4292 result = rmdir(path->narrow);
4293 #endif
4294 Py_END_ALLOW_THREADS
4295
4296 if (result)
4297 return path_error(path);
4298
4299 Py_RETURN_NONE;
4300 }
4301
4302
4303 #ifdef HAVE_SYSTEM
4304 #ifdef MS_WINDOWS
4305 /*[clinic input]
4306 os.system -> long
4307
4308 command: Py_UNICODE
4309
4310 Execute the command in a subshell.
4311 [clinic start generated code]*/
4312
4313 static long
os_system_impl(PyObject * module,const Py_UNICODE * command)4314 os_system_impl(PyObject *module, const Py_UNICODE *command)
4315 /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4316 {
4317 long result;
4318
4319 if (PySys_Audit("os.system", "(u)", command) < 0) {
4320 return -1;
4321 }
4322
4323 Py_BEGIN_ALLOW_THREADS
4324 _Py_BEGIN_SUPPRESS_IPH
4325 result = _wsystem(command);
4326 _Py_END_SUPPRESS_IPH
4327 Py_END_ALLOW_THREADS
4328 return result;
4329 }
4330 #else /* MS_WINDOWS */
4331 /*[clinic input]
4332 os.system -> long
4333
4334 command: FSConverter
4335
4336 Execute the command in a subshell.
4337 [clinic start generated code]*/
4338
4339 static long
os_system_impl(PyObject * module,PyObject * command)4340 os_system_impl(PyObject *module, PyObject *command)
4341 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4342 {
4343 long result;
4344 const char *bytes = PyBytes_AsString(command);
4345
4346 if (PySys_Audit("os.system", "(O)", command) < 0) {
4347 return -1;
4348 }
4349
4350 Py_BEGIN_ALLOW_THREADS
4351 result = system(bytes);
4352 Py_END_ALLOW_THREADS
4353 return result;
4354 }
4355 #endif
4356 #endif /* HAVE_SYSTEM */
4357
4358
4359 /*[clinic input]
4360 os.umask
4361
4362 mask: int
4363 /
4364
4365 Set the current numeric umask and return the previous umask.
4366 [clinic start generated code]*/
4367
4368 static PyObject *
os_umask_impl(PyObject * module,int mask)4369 os_umask_impl(PyObject *module, int mask)
4370 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4371 {
4372 int i = (int)umask(mask);
4373 if (i < 0)
4374 return posix_error();
4375 return PyLong_FromLong((long)i);
4376 }
4377
4378 #ifdef MS_WINDOWS
4379
4380 /* override the default DeleteFileW behavior so that directory
4381 symlinks can be removed with this function, the same as with
4382 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)4383 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
4384 {
4385 WIN32_FILE_ATTRIBUTE_DATA info;
4386 WIN32_FIND_DATAW find_data;
4387 HANDLE find_data_handle;
4388 int is_directory = 0;
4389 int is_link = 0;
4390
4391 if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
4392 is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4393
4394 /* Get WIN32_FIND_DATA structure for the path to determine if
4395 it is a symlink */
4396 if(is_directory &&
4397 info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
4398 find_data_handle = FindFirstFileW(lpFileName, &find_data);
4399
4400 if(find_data_handle != INVALID_HANDLE_VALUE) {
4401 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
4402 IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
4403 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
4404 find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
4405 FindClose(find_data_handle);
4406 }
4407 }
4408 }
4409
4410 if (is_directory && is_link)
4411 return RemoveDirectoryW(lpFileName);
4412
4413 return DeleteFileW(lpFileName);
4414 }
4415 #endif /* MS_WINDOWS */
4416
4417
4418 /*[clinic input]
4419 os.unlink
4420
4421 path: path_t
4422 *
4423 dir_fd: dir_fd(requires='unlinkat')=None
4424
4425 Remove a file (same as remove()).
4426
4427 If dir_fd is not None, it should be a file descriptor open to a directory,
4428 and path should be relative; path will then be relative to that directory.
4429 dir_fd may not be implemented on your platform.
4430 If it is unavailable, using it will raise a NotImplementedError.
4431
4432 [clinic start generated code]*/
4433
4434 static PyObject *
os_unlink_impl(PyObject * module,path_t * path,int dir_fd)4435 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
4436 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
4437 {
4438 int result;
4439
4440 Py_BEGIN_ALLOW_THREADS
4441 _Py_BEGIN_SUPPRESS_IPH
4442 #ifdef MS_WINDOWS
4443 /* Windows, success=1, UNIX, success=0 */
4444 result = !Py_DeleteFileW(path->wide);
4445 #else
4446 #ifdef HAVE_UNLINKAT
4447 if (dir_fd != DEFAULT_DIR_FD)
4448 result = unlinkat(dir_fd, path->narrow, 0);
4449 else
4450 #endif /* HAVE_UNLINKAT */
4451 result = unlink(path->narrow);
4452 #endif
4453 _Py_END_SUPPRESS_IPH
4454 Py_END_ALLOW_THREADS
4455
4456 if (result)
4457 return path_error(path);
4458
4459 Py_RETURN_NONE;
4460 }
4461
4462
4463 /*[clinic input]
4464 os.remove = os.unlink
4465
4466 Remove a file (same as unlink()).
4467
4468 If dir_fd is not None, it should be a file descriptor open to a directory,
4469 and path should be relative; path will then be relative to that directory.
4470 dir_fd may not be implemented on your platform.
4471 If it is unavailable, using it will raise a NotImplementedError.
4472 [clinic start generated code]*/
4473
4474 static PyObject *
os_remove_impl(PyObject * module,path_t * path,int dir_fd)4475 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
4476 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
4477 {
4478 return os_unlink_impl(module, path, dir_fd);
4479 }
4480
4481
4482 static PyStructSequence_Field uname_result_fields[] = {
4483 {"sysname", "operating system name"},
4484 {"nodename", "name of machine on network (implementation-defined)"},
4485 {"release", "operating system release"},
4486 {"version", "operating system version"},
4487 {"machine", "hardware identifier"},
4488 {NULL}
4489 };
4490
4491 PyDoc_STRVAR(uname_result__doc__,
4492 "uname_result: Result from os.uname().\n\n\
4493 This object may be accessed either as a tuple of\n\
4494 (sysname, nodename, release, version, machine),\n\
4495 or via the attributes sysname, nodename, release, version, and machine.\n\
4496 \n\
4497 See os.uname for more information.");
4498
4499 static PyStructSequence_Desc uname_result_desc = {
4500 "uname_result", /* name */
4501 uname_result__doc__, /* doc */
4502 uname_result_fields,
4503 5
4504 };
4505
4506 static PyTypeObject* UnameResultType;
4507
4508
4509 #ifdef HAVE_UNAME
4510 /*[clinic input]
4511 os.uname
4512
4513 Return an object identifying the current operating system.
4514
4515 The object behaves like a named tuple with the following fields:
4516 (sysname, nodename, release, version, machine)
4517
4518 [clinic start generated code]*/
4519
4520 static PyObject *
os_uname_impl(PyObject * module)4521 os_uname_impl(PyObject *module)
4522 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
4523 {
4524 struct utsname u;
4525 int res;
4526 PyObject *value;
4527
4528 Py_BEGIN_ALLOW_THREADS
4529 res = uname(&u);
4530 Py_END_ALLOW_THREADS
4531 if (res < 0)
4532 return posix_error();
4533
4534 value = PyStructSequence_New(UnameResultType);
4535 if (value == NULL)
4536 return NULL;
4537
4538 #define SET(i, field) \
4539 { \
4540 PyObject *o = PyUnicode_DecodeFSDefault(field); \
4541 if (!o) { \
4542 Py_DECREF(value); \
4543 return NULL; \
4544 } \
4545 PyStructSequence_SET_ITEM(value, i, o); \
4546 } \
4547
4548 SET(0, u.sysname);
4549 SET(1, u.nodename);
4550 SET(2, u.release);
4551 SET(3, u.version);
4552 SET(4, u.machine);
4553
4554 #undef SET
4555
4556 return value;
4557 }
4558 #endif /* HAVE_UNAME */
4559
4560
4561
4562 typedef struct {
4563 int now;
4564 time_t atime_s;
4565 long atime_ns;
4566 time_t mtime_s;
4567 long mtime_ns;
4568 } utime_t;
4569
4570 /*
4571 * these macros assume that "ut" is a pointer to a utime_t
4572 * they also intentionally leak the declaration of a pointer named "time"
4573 */
4574 #define UTIME_TO_TIMESPEC \
4575 struct timespec ts[2]; \
4576 struct timespec *time; \
4577 if (ut->now) \
4578 time = NULL; \
4579 else { \
4580 ts[0].tv_sec = ut->atime_s; \
4581 ts[0].tv_nsec = ut->atime_ns; \
4582 ts[1].tv_sec = ut->mtime_s; \
4583 ts[1].tv_nsec = ut->mtime_ns; \
4584 time = ts; \
4585 } \
4586
4587 #define UTIME_TO_TIMEVAL \
4588 struct timeval tv[2]; \
4589 struct timeval *time; \
4590 if (ut->now) \
4591 time = NULL; \
4592 else { \
4593 tv[0].tv_sec = ut->atime_s; \
4594 tv[0].tv_usec = ut->atime_ns / 1000; \
4595 tv[1].tv_sec = ut->mtime_s; \
4596 tv[1].tv_usec = ut->mtime_ns / 1000; \
4597 time = tv; \
4598 } \
4599
4600 #define UTIME_TO_UTIMBUF \
4601 struct utimbuf u; \
4602 struct utimbuf *time; \
4603 if (ut->now) \
4604 time = NULL; \
4605 else { \
4606 u.actime = ut->atime_s; \
4607 u.modtime = ut->mtime_s; \
4608 time = &u; \
4609 }
4610
4611 #define UTIME_TO_TIME_T \
4612 time_t timet[2]; \
4613 time_t *time; \
4614 if (ut->now) \
4615 time = NULL; \
4616 else { \
4617 timet[0] = ut->atime_s; \
4618 timet[1] = ut->mtime_s; \
4619 time = timet; \
4620 } \
4621
4622
4623 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
4624
4625 static int
utime_dir_fd(utime_t * ut,int dir_fd,const char * path,int follow_symlinks)4626 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
4627 {
4628 #ifdef HAVE_UTIMENSAT
4629 int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
4630 UTIME_TO_TIMESPEC;
4631 return utimensat(dir_fd, path, time, flags);
4632 #elif defined(HAVE_FUTIMESAT)
4633 UTIME_TO_TIMEVAL;
4634 /*
4635 * follow_symlinks will never be false here;
4636 * we only allow !follow_symlinks and dir_fd together
4637 * if we have utimensat()
4638 */
4639 assert(follow_symlinks);
4640 return futimesat(dir_fd, path, time);
4641 #endif
4642 }
4643
4644 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
4645 #else
4646 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
4647 #endif
4648
4649 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
4650
4651 static int
utime_fd(utime_t * ut,int fd)4652 utime_fd(utime_t *ut, int fd)
4653 {
4654 #ifdef HAVE_FUTIMENS
4655 UTIME_TO_TIMESPEC;
4656 return futimens(fd, time);
4657 #else
4658 UTIME_TO_TIMEVAL;
4659 return futimes(fd, time);
4660 #endif
4661 }
4662
4663 #define PATH_UTIME_HAVE_FD 1
4664 #else
4665 #define PATH_UTIME_HAVE_FD 0
4666 #endif
4667
4668 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
4669 # define UTIME_HAVE_NOFOLLOW_SYMLINKS
4670 #endif
4671
4672 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
4673
4674 static int
utime_nofollow_symlinks(utime_t * ut,const char * path)4675 utime_nofollow_symlinks(utime_t *ut, const char *path)
4676 {
4677 #ifdef HAVE_UTIMENSAT
4678 UTIME_TO_TIMESPEC;
4679 return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
4680 #else
4681 UTIME_TO_TIMEVAL;
4682 return lutimes(path, time);
4683 #endif
4684 }
4685
4686 #endif
4687
4688 #ifndef MS_WINDOWS
4689
4690 static int
utime_default(utime_t * ut,const char * path)4691 utime_default(utime_t *ut, const char *path)
4692 {
4693 #ifdef HAVE_UTIMENSAT
4694 UTIME_TO_TIMESPEC;
4695 return utimensat(DEFAULT_DIR_FD, path, time, 0);
4696 #elif defined(HAVE_UTIMES)
4697 UTIME_TO_TIMEVAL;
4698 return utimes(path, time);
4699 #elif defined(HAVE_UTIME_H)
4700 UTIME_TO_UTIMBUF;
4701 return utime(path, time);
4702 #else
4703 UTIME_TO_TIME_T;
4704 return utime(path, time);
4705 #endif
4706 }
4707
4708 #endif
4709
4710 static int
split_py_long_to_s_and_ns(PyObject * py_long,time_t * s,long * ns)4711 split_py_long_to_s_and_ns(PyObject *py_long, time_t *s, long *ns)
4712 {
4713 int result = 0;
4714 PyObject *divmod;
4715 divmod = PyNumber_Divmod(py_long, billion);
4716 if (!divmod)
4717 goto exit;
4718 if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
4719 PyErr_Format(PyExc_TypeError,
4720 "%.200s.__divmod__() must return a 2-tuple, not %.200s",
4721 Py_TYPE(py_long)->tp_name, Py_TYPE(divmod)->tp_name);
4722 goto exit;
4723 }
4724 *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
4725 if ((*s == -1) && PyErr_Occurred())
4726 goto exit;
4727 *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
4728 if ((*ns == -1) && PyErr_Occurred())
4729 goto exit;
4730
4731 result = 1;
4732 exit:
4733 Py_XDECREF(divmod);
4734 return result;
4735 }
4736
4737
4738 /*[clinic input]
4739 os.utime
4740
4741 path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
4742 times: object = None
4743 *
4744 ns: object = NULL
4745 dir_fd: dir_fd(requires='futimensat') = None
4746 follow_symlinks: bool=True
4747
4748 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
4749
4750 Set the access and modified time of path.
4751
4752 path may always be specified as a string.
4753 On some platforms, path may also be specified as an open file descriptor.
4754 If this functionality is unavailable, using it raises an exception.
4755
4756 If times is not None, it must be a tuple (atime, mtime);
4757 atime and mtime should be expressed as float seconds since the epoch.
4758 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
4759 atime_ns and mtime_ns should be expressed as integer nanoseconds
4760 since the epoch.
4761 If times is None and ns is unspecified, utime uses the current time.
4762 Specifying tuples for both times and ns is an error.
4763
4764 If dir_fd is not None, it should be a file descriptor open to a directory,
4765 and path should be relative; path will then be relative to that directory.
4766 If follow_symlinks is False, and the last element of the path is a symbolic
4767 link, utime will modify the symbolic link itself instead of the file the
4768 link points to.
4769 It is an error to use dir_fd or follow_symlinks when specifying path
4770 as an open file descriptor.
4771 dir_fd and follow_symlinks may not be available on your platform.
4772 If they are unavailable, using them will raise a NotImplementedError.
4773
4774 [clinic start generated code]*/
4775
4776 static PyObject *
os_utime_impl(PyObject * module,path_t * path,PyObject * times,PyObject * ns,int dir_fd,int follow_symlinks)4777 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
4778 int dir_fd, int follow_symlinks)
4779 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
4780 {
4781 #ifdef MS_WINDOWS
4782 HANDLE hFile;
4783 FILETIME atime, mtime;
4784 #else
4785 int result;
4786 #endif
4787
4788 utime_t utime;
4789
4790 memset(&utime, 0, sizeof(utime_t));
4791
4792 if (times != Py_None && ns) {
4793 PyErr_SetString(PyExc_ValueError,
4794 "utime: you may specify either 'times'"
4795 " or 'ns' but not both");
4796 return NULL;
4797 }
4798
4799 if (times != Py_None) {
4800 time_t a_sec, m_sec;
4801 long a_nsec, m_nsec;
4802 if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
4803 PyErr_SetString(PyExc_TypeError,
4804 "utime: 'times' must be either"
4805 " a tuple of two ints or None");
4806 return NULL;
4807 }
4808 utime.now = 0;
4809 if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
4810 &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
4811 _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
4812 &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
4813 return NULL;
4814 }
4815 utime.atime_s = a_sec;
4816 utime.atime_ns = a_nsec;
4817 utime.mtime_s = m_sec;
4818 utime.mtime_ns = m_nsec;
4819 }
4820 else if (ns) {
4821 if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
4822 PyErr_SetString(PyExc_TypeError,
4823 "utime: 'ns' must be a tuple of two ints");
4824 return NULL;
4825 }
4826 utime.now = 0;
4827 if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0),
4828 &utime.atime_s, &utime.atime_ns) ||
4829 !split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1),
4830 &utime.mtime_s, &utime.mtime_ns)) {
4831 return NULL;
4832 }
4833 }
4834 else {
4835 /* times and ns are both None/unspecified. use "now". */
4836 utime.now = 1;
4837 }
4838
4839 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
4840 if (follow_symlinks_specified("utime", follow_symlinks))
4841 return NULL;
4842 #endif
4843
4844 if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
4845 dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
4846 fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
4847 return NULL;
4848
4849 #if !defined(HAVE_UTIMENSAT)
4850 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
4851 PyErr_SetString(PyExc_ValueError,
4852 "utime: cannot use dir_fd and follow_symlinks "
4853 "together on this platform");
4854 return NULL;
4855 }
4856 #endif
4857
4858 #ifdef MS_WINDOWS
4859 Py_BEGIN_ALLOW_THREADS
4860 hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
4861 NULL, OPEN_EXISTING,
4862 FILE_FLAG_BACKUP_SEMANTICS, NULL);
4863 Py_END_ALLOW_THREADS
4864 if (hFile == INVALID_HANDLE_VALUE) {
4865 path_error(path);
4866 return NULL;
4867 }
4868
4869 if (utime.now) {
4870 GetSystemTimeAsFileTime(&mtime);
4871 atime = mtime;
4872 }
4873 else {
4874 _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
4875 _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
4876 }
4877 if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
4878 /* Avoid putting the file name into the error here,
4879 as that may confuse the user into believing that
4880 something is wrong with the file, when it also
4881 could be the time stamp that gives a problem. */
4882 PyErr_SetFromWindowsErr(0);
4883 CloseHandle(hFile);
4884 return NULL;
4885 }
4886 CloseHandle(hFile);
4887 #else /* MS_WINDOWS */
4888 Py_BEGIN_ALLOW_THREADS
4889
4890 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
4891 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4892 result = utime_nofollow_symlinks(&utime, path->narrow);
4893 else
4894 #endif
4895
4896 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
4897 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
4898 result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
4899 else
4900 #endif
4901
4902 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
4903 if (path->fd != -1)
4904 result = utime_fd(&utime, path->fd);
4905 else
4906 #endif
4907
4908 result = utime_default(&utime, path->narrow);
4909
4910 Py_END_ALLOW_THREADS
4911
4912 if (result < 0) {
4913 /* see previous comment about not putting filename in error here */
4914 posix_error();
4915 return NULL;
4916 }
4917
4918 #endif /* MS_WINDOWS */
4919
4920 Py_RETURN_NONE;
4921 }
4922
4923 /* Process operations */
4924
4925
4926 /*[clinic input]
4927 os._exit
4928
4929 status: int
4930
4931 Exit to the system with specified status, without normal exit processing.
4932 [clinic start generated code]*/
4933
4934 static PyObject *
os__exit_impl(PyObject * module,int status)4935 os__exit_impl(PyObject *module, int status)
4936 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
4937 {
4938 _exit(status);
4939 return NULL; /* Make gcc -Wall happy */
4940 }
4941
4942 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
4943 #define EXECV_CHAR wchar_t
4944 #else
4945 #define EXECV_CHAR char
4946 #endif
4947
4948 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
4949 static void
free_string_array(EXECV_CHAR ** array,Py_ssize_t count)4950 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
4951 {
4952 Py_ssize_t i;
4953 for (i = 0; i < count; i++)
4954 PyMem_Free(array[i]);
4955 PyMem_DEL(array);
4956 }
4957
4958 static int
fsconvert_strdup(PyObject * o,EXECV_CHAR ** out)4959 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
4960 {
4961 Py_ssize_t size;
4962 PyObject *ub;
4963 int result = 0;
4964 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
4965 if (!PyUnicode_FSDecoder(o, &ub))
4966 return 0;
4967 *out = PyUnicode_AsWideCharString(ub, &size);
4968 if (*out)
4969 result = 1;
4970 #else
4971 if (!PyUnicode_FSConverter(o, &ub))
4972 return 0;
4973 size = PyBytes_GET_SIZE(ub);
4974 *out = PyMem_Malloc(size + 1);
4975 if (*out) {
4976 memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
4977 result = 1;
4978 } else
4979 PyErr_NoMemory();
4980 #endif
4981 Py_DECREF(ub);
4982 return result;
4983 }
4984 #endif
4985
4986 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
4987 static EXECV_CHAR**
parse_envlist(PyObject * env,Py_ssize_t * envc_ptr)4988 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
4989 {
4990 Py_ssize_t i, pos, envc;
4991 PyObject *keys=NULL, *vals=NULL;
4992 PyObject *key, *val, *key2, *val2, *keyval;
4993 EXECV_CHAR **envlist;
4994
4995 i = PyMapping_Size(env);
4996 if (i < 0)
4997 return NULL;
4998 envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
4999 if (envlist == NULL) {
5000 PyErr_NoMemory();
5001 return NULL;
5002 }
5003 envc = 0;
5004 keys = PyMapping_Keys(env);
5005 if (!keys)
5006 goto error;
5007 vals = PyMapping_Values(env);
5008 if (!vals)
5009 goto error;
5010 if (!PyList_Check(keys) || !PyList_Check(vals)) {
5011 PyErr_Format(PyExc_TypeError,
5012 "env.keys() or env.values() is not a list");
5013 goto error;
5014 }
5015
5016 for (pos = 0; pos < i; pos++) {
5017 key = PyList_GetItem(keys, pos);
5018 val = PyList_GetItem(vals, pos);
5019 if (!key || !val)
5020 goto error;
5021
5022 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5023 if (!PyUnicode_FSDecoder(key, &key2))
5024 goto error;
5025 if (!PyUnicode_FSDecoder(val, &val2)) {
5026 Py_DECREF(key2);
5027 goto error;
5028 }
5029 /* Search from index 1 because on Windows starting '=' is allowed for
5030 defining hidden environment variables. */
5031 if (PyUnicode_GET_LENGTH(key2) == 0 ||
5032 PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5033 {
5034 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5035 Py_DECREF(key2);
5036 Py_DECREF(val2);
5037 goto error;
5038 }
5039 keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5040 #else
5041 if (!PyUnicode_FSConverter(key, &key2))
5042 goto error;
5043 if (!PyUnicode_FSConverter(val, &val2)) {
5044 Py_DECREF(key2);
5045 goto error;
5046 }
5047 if (PyBytes_GET_SIZE(key2) == 0 ||
5048 strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5049 {
5050 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5051 Py_DECREF(key2);
5052 Py_DECREF(val2);
5053 goto error;
5054 }
5055 keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5056 PyBytes_AS_STRING(val2));
5057 #endif
5058 Py_DECREF(key2);
5059 Py_DECREF(val2);
5060 if (!keyval)
5061 goto error;
5062
5063 if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5064 Py_DECREF(keyval);
5065 goto error;
5066 }
5067
5068 Py_DECREF(keyval);
5069 }
5070 Py_DECREF(vals);
5071 Py_DECREF(keys);
5072
5073 envlist[envc] = 0;
5074 *envc_ptr = envc;
5075 return envlist;
5076
5077 error:
5078 Py_XDECREF(keys);
5079 Py_XDECREF(vals);
5080 free_string_array(envlist, envc);
5081 return NULL;
5082 }
5083
5084 static EXECV_CHAR**
parse_arglist(PyObject * argv,Py_ssize_t * argc)5085 parse_arglist(PyObject* argv, Py_ssize_t *argc)
5086 {
5087 int i;
5088 EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5089 if (argvlist == NULL) {
5090 PyErr_NoMemory();
5091 return NULL;
5092 }
5093 for (i = 0; i < *argc; i++) {
5094 PyObject* item = PySequence_ITEM(argv, i);
5095 if (item == NULL)
5096 goto fail;
5097 if (!fsconvert_strdup(item, &argvlist[i])) {
5098 Py_DECREF(item);
5099 goto fail;
5100 }
5101 Py_DECREF(item);
5102 }
5103 argvlist[*argc] = NULL;
5104 return argvlist;
5105 fail:
5106 *argc = i;
5107 free_string_array(argvlist, *argc);
5108 return NULL;
5109 }
5110
5111 #endif
5112
5113
5114 #ifdef HAVE_EXECV
5115 /*[clinic input]
5116 os.execv
5117
5118 path: path_t
5119 Path of executable file.
5120 argv: object
5121 Tuple or list of strings.
5122 /
5123
5124 Execute an executable path with arguments, replacing current process.
5125 [clinic start generated code]*/
5126
5127 static PyObject *
os_execv_impl(PyObject * module,path_t * path,PyObject * argv)5128 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5129 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5130 {
5131 EXECV_CHAR **argvlist;
5132 Py_ssize_t argc;
5133
5134 /* execv has two arguments: (path, argv), where
5135 argv is a list or tuple of strings. */
5136
5137 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5138 PyErr_SetString(PyExc_TypeError,
5139 "execv() arg 2 must be a tuple or list");
5140 return NULL;
5141 }
5142 argc = PySequence_Size(argv);
5143 if (argc < 1) {
5144 PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5145 return NULL;
5146 }
5147
5148 argvlist = parse_arglist(argv, &argc);
5149 if (argvlist == NULL) {
5150 return NULL;
5151 }
5152 if (!argvlist[0][0]) {
5153 PyErr_SetString(PyExc_ValueError,
5154 "execv() arg 2 first element cannot be empty");
5155 free_string_array(argvlist, argc);
5156 return NULL;
5157 }
5158
5159 _Py_BEGIN_SUPPRESS_IPH
5160 #ifdef HAVE_WEXECV
5161 _wexecv(path->wide, argvlist);
5162 #else
5163 execv(path->narrow, argvlist);
5164 #endif
5165 _Py_END_SUPPRESS_IPH
5166
5167 /* If we get here it's definitely an error */
5168
5169 free_string_array(argvlist, argc);
5170 return posix_error();
5171 }
5172
5173
5174 /*[clinic input]
5175 os.execve
5176
5177 path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5178 Path of executable file.
5179 argv: object
5180 Tuple or list of strings.
5181 env: object
5182 Dictionary of strings mapping to strings.
5183
5184 Execute an executable path with arguments, replacing current process.
5185 [clinic start generated code]*/
5186
5187 static PyObject *
os_execve_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env)5188 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5189 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5190 {
5191 EXECV_CHAR **argvlist = NULL;
5192 EXECV_CHAR **envlist;
5193 Py_ssize_t argc, envc;
5194
5195 /* execve has three arguments: (path, argv, env), where
5196 argv is a list or tuple of strings and env is a dictionary
5197 like posix.environ. */
5198
5199 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5200 PyErr_SetString(PyExc_TypeError,
5201 "execve: argv must be a tuple or list");
5202 goto fail;
5203 }
5204 argc = PySequence_Size(argv);
5205 if (argc < 1) {
5206 PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5207 return NULL;
5208 }
5209
5210 if (!PyMapping_Check(env)) {
5211 PyErr_SetString(PyExc_TypeError,
5212 "execve: environment must be a mapping object");
5213 goto fail;
5214 }
5215
5216 argvlist = parse_arglist(argv, &argc);
5217 if (argvlist == NULL) {
5218 goto fail;
5219 }
5220 if (!argvlist[0][0]) {
5221 PyErr_SetString(PyExc_ValueError,
5222 "execve: argv first element cannot be empty");
5223 goto fail;
5224 }
5225
5226 envlist = parse_envlist(env, &envc);
5227 if (envlist == NULL)
5228 goto fail;
5229
5230 _Py_BEGIN_SUPPRESS_IPH
5231 #ifdef HAVE_FEXECVE
5232 if (path->fd > -1)
5233 fexecve(path->fd, argvlist, envlist);
5234 else
5235 #endif
5236 #ifdef HAVE_WEXECV
5237 _wexecve(path->wide, argvlist, envlist);
5238 #else
5239 execve(path->narrow, argvlist, envlist);
5240 #endif
5241 _Py_END_SUPPRESS_IPH
5242
5243 /* If we get here it's definitely an error */
5244
5245 posix_path_error(path);
5246
5247 free_string_array(envlist, envc);
5248 fail:
5249 if (argvlist)
5250 free_string_array(argvlist, argc);
5251 return NULL;
5252 }
5253
5254 #endif /* HAVE_EXECV */
5255
5256 #ifdef HAVE_POSIX_SPAWN
5257
5258 enum posix_spawn_file_actions_identifier {
5259 POSIX_SPAWN_OPEN,
5260 POSIX_SPAWN_CLOSE,
5261 POSIX_SPAWN_DUP2
5262 };
5263
5264 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
5265 static int
5266 convert_sched_param(PyObject *param, struct sched_param *res);
5267 #endif
5268
5269 static int
parse_posix_spawn_flags(const char * func_name,PyObject * setpgroup,int resetids,int setsid,PyObject * setsigmask,PyObject * setsigdef,PyObject * scheduler,posix_spawnattr_t * attrp)5270 parse_posix_spawn_flags(const char *func_name, PyObject *setpgroup,
5271 int resetids, int setsid, PyObject *setsigmask,
5272 PyObject *setsigdef, PyObject *scheduler,
5273 posix_spawnattr_t *attrp)
5274 {
5275 long all_flags = 0;
5276
5277 errno = posix_spawnattr_init(attrp);
5278 if (errno) {
5279 posix_error();
5280 return -1;
5281 }
5282
5283 if (setpgroup) {
5284 pid_t pgid = PyLong_AsPid(setpgroup);
5285 if (pgid == (pid_t)-1 && PyErr_Occurred()) {
5286 goto fail;
5287 }
5288 errno = posix_spawnattr_setpgroup(attrp, pgid);
5289 if (errno) {
5290 posix_error();
5291 goto fail;
5292 }
5293 all_flags |= POSIX_SPAWN_SETPGROUP;
5294 }
5295
5296 if (resetids) {
5297 all_flags |= POSIX_SPAWN_RESETIDS;
5298 }
5299
5300 if (setsid) {
5301 #ifdef POSIX_SPAWN_SETSID
5302 all_flags |= POSIX_SPAWN_SETSID;
5303 #elif defined(POSIX_SPAWN_SETSID_NP)
5304 all_flags |= POSIX_SPAWN_SETSID_NP;
5305 #else
5306 argument_unavailable_error(func_name, "setsid");
5307 return -1;
5308 #endif
5309 }
5310
5311 if (setsigmask) {
5312 sigset_t set;
5313 if (!_Py_Sigset_Converter(setsigmask, &set)) {
5314 goto fail;
5315 }
5316 errno = posix_spawnattr_setsigmask(attrp, &set);
5317 if (errno) {
5318 posix_error();
5319 goto fail;
5320 }
5321 all_flags |= POSIX_SPAWN_SETSIGMASK;
5322 }
5323
5324 if (setsigdef) {
5325 sigset_t set;
5326 if (!_Py_Sigset_Converter(setsigdef, &set)) {
5327 goto fail;
5328 }
5329 errno = posix_spawnattr_setsigdefault(attrp, &set);
5330 if (errno) {
5331 posix_error();
5332 goto fail;
5333 }
5334 all_flags |= POSIX_SPAWN_SETSIGDEF;
5335 }
5336
5337 if (scheduler) {
5338 #ifdef POSIX_SPAWN_SETSCHEDULER
5339 PyObject *py_schedpolicy;
5340 struct sched_param schedparam;
5341
5342 if (!PyArg_ParseTuple(scheduler, "OO&"
5343 ";A scheduler tuple must have two elements",
5344 &py_schedpolicy, convert_sched_param, &schedparam)) {
5345 goto fail;
5346 }
5347 if (py_schedpolicy != Py_None) {
5348 int schedpolicy = _PyLong_AsInt(py_schedpolicy);
5349
5350 if (schedpolicy == -1 && PyErr_Occurred()) {
5351 goto fail;
5352 }
5353 errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
5354 if (errno) {
5355 posix_error();
5356 goto fail;
5357 }
5358 all_flags |= POSIX_SPAWN_SETSCHEDULER;
5359 }
5360 errno = posix_spawnattr_setschedparam(attrp, &schedparam);
5361 if (errno) {
5362 posix_error();
5363 goto fail;
5364 }
5365 all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
5366 #else
5367 PyErr_SetString(PyExc_NotImplementedError,
5368 "The scheduler option is not supported in this system.");
5369 goto fail;
5370 #endif
5371 }
5372
5373 errno = posix_spawnattr_setflags(attrp, all_flags);
5374 if (errno) {
5375 posix_error();
5376 goto fail;
5377 }
5378
5379 return 0;
5380
5381 fail:
5382 (void)posix_spawnattr_destroy(attrp);
5383 return -1;
5384 }
5385
5386 static int
parse_file_actions(PyObject * file_actions,posix_spawn_file_actions_t * file_actionsp,PyObject * temp_buffer)5387 parse_file_actions(PyObject *file_actions,
5388 posix_spawn_file_actions_t *file_actionsp,
5389 PyObject *temp_buffer)
5390 {
5391 PyObject *seq;
5392 PyObject *file_action = NULL;
5393 PyObject *tag_obj;
5394
5395 seq = PySequence_Fast(file_actions,
5396 "file_actions must be a sequence or None");
5397 if (seq == NULL) {
5398 return -1;
5399 }
5400
5401 errno = posix_spawn_file_actions_init(file_actionsp);
5402 if (errno) {
5403 posix_error();
5404 Py_DECREF(seq);
5405 return -1;
5406 }
5407
5408 for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
5409 file_action = PySequence_Fast_GET_ITEM(seq, i);
5410 Py_INCREF(file_action);
5411 if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
5412 PyErr_SetString(PyExc_TypeError,
5413 "Each file_actions element must be a non-empty tuple");
5414 goto fail;
5415 }
5416 long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
5417 if (tag == -1 && PyErr_Occurred()) {
5418 goto fail;
5419 }
5420
5421 /* Populate the file_actions object */
5422 switch (tag) {
5423 case POSIX_SPAWN_OPEN: {
5424 int fd, oflag;
5425 PyObject *path;
5426 unsigned long mode;
5427 if (!PyArg_ParseTuple(file_action, "OiO&ik"
5428 ";A open file_action tuple must have 5 elements",
5429 &tag_obj, &fd, PyUnicode_FSConverter, &path,
5430 &oflag, &mode))
5431 {
5432 goto fail;
5433 }
5434 if (PyList_Append(temp_buffer, path)) {
5435 Py_DECREF(path);
5436 goto fail;
5437 }
5438 errno = posix_spawn_file_actions_addopen(file_actionsp,
5439 fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
5440 Py_DECREF(path);
5441 if (errno) {
5442 posix_error();
5443 goto fail;
5444 }
5445 break;
5446 }
5447 case POSIX_SPAWN_CLOSE: {
5448 int fd;
5449 if (!PyArg_ParseTuple(file_action, "Oi"
5450 ";A close file_action tuple must have 2 elements",
5451 &tag_obj, &fd))
5452 {
5453 goto fail;
5454 }
5455 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
5456 if (errno) {
5457 posix_error();
5458 goto fail;
5459 }
5460 break;
5461 }
5462 case POSIX_SPAWN_DUP2: {
5463 int fd1, fd2;
5464 if (!PyArg_ParseTuple(file_action, "Oii"
5465 ";A dup2 file_action tuple must have 3 elements",
5466 &tag_obj, &fd1, &fd2))
5467 {
5468 goto fail;
5469 }
5470 errno = posix_spawn_file_actions_adddup2(file_actionsp,
5471 fd1, fd2);
5472 if (errno) {
5473 posix_error();
5474 goto fail;
5475 }
5476 break;
5477 }
5478 default: {
5479 PyErr_SetString(PyExc_TypeError,
5480 "Unknown file_actions identifier");
5481 goto fail;
5482 }
5483 }
5484 Py_DECREF(file_action);
5485 }
5486
5487 Py_DECREF(seq);
5488 return 0;
5489
5490 fail:
5491 Py_DECREF(seq);
5492 Py_DECREF(file_action);
5493 (void)posix_spawn_file_actions_destroy(file_actionsp);
5494 return -1;
5495 }
5496
5497
5498 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)5499 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
5500 PyObject *env, PyObject *file_actions,
5501 PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
5502 PyObject *setsigdef, PyObject *scheduler)
5503 {
5504 const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
5505 EXECV_CHAR **argvlist = NULL;
5506 EXECV_CHAR **envlist = NULL;
5507 posix_spawn_file_actions_t file_actions_buf;
5508 posix_spawn_file_actions_t *file_actionsp = NULL;
5509 posix_spawnattr_t attr;
5510 posix_spawnattr_t *attrp = NULL;
5511 Py_ssize_t argc, envc;
5512 PyObject *result = NULL;
5513 PyObject *temp_buffer = NULL;
5514 pid_t pid;
5515 int err_code;
5516
5517 /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
5518 argv is a list or tuple of strings and env is a dictionary
5519 like posix.environ. */
5520
5521 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5522 PyErr_Format(PyExc_TypeError,
5523 "%s: argv must be a tuple or list", func_name);
5524 goto exit;
5525 }
5526 argc = PySequence_Size(argv);
5527 if (argc < 1) {
5528 PyErr_Format(PyExc_ValueError,
5529 "%s: argv must not be empty", func_name);
5530 return NULL;
5531 }
5532
5533 if (!PyMapping_Check(env)) {
5534 PyErr_Format(PyExc_TypeError,
5535 "%s: environment must be a mapping object", func_name);
5536 goto exit;
5537 }
5538
5539 argvlist = parse_arglist(argv, &argc);
5540 if (argvlist == NULL) {
5541 goto exit;
5542 }
5543 if (!argvlist[0][0]) {
5544 PyErr_Format(PyExc_ValueError,
5545 "%s: argv first element cannot be empty", func_name);
5546 goto exit;
5547 }
5548
5549 envlist = parse_envlist(env, &envc);
5550 if (envlist == NULL) {
5551 goto exit;
5552 }
5553
5554 if (file_actions != NULL && file_actions != Py_None) {
5555 /* There is a bug in old versions of glibc that makes some of the
5556 * helper functions for manipulating file actions not copy the provided
5557 * buffers. The problem is that posix_spawn_file_actions_addopen does not
5558 * copy the value of path for some old versions of glibc (<2.20).
5559 * The use of temp_buffer here is a workaround that keeps the
5560 * python objects that own the buffers alive until posix_spawn gets called.
5561 * Check https://bugs.python.org/issue33630 and
5562 * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
5563 temp_buffer = PyList_New(0);
5564 if (!temp_buffer) {
5565 goto exit;
5566 }
5567 if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
5568 goto exit;
5569 }
5570 file_actionsp = &file_actions_buf;
5571 }
5572
5573 if (parse_posix_spawn_flags(func_name, setpgroup, resetids, setsid,
5574 setsigmask, setsigdef, scheduler, &attr)) {
5575 goto exit;
5576 }
5577 attrp = &attr;
5578
5579 _Py_BEGIN_SUPPRESS_IPH
5580 #ifdef HAVE_POSIX_SPAWNP
5581 if (use_posix_spawnp) {
5582 err_code = posix_spawnp(&pid, path->narrow,
5583 file_actionsp, attrp, argvlist, envlist);
5584 }
5585 else
5586 #endif /* HAVE_POSIX_SPAWNP */
5587 {
5588 err_code = posix_spawn(&pid, path->narrow,
5589 file_actionsp, attrp, argvlist, envlist);
5590 }
5591 _Py_END_SUPPRESS_IPH
5592
5593 if (err_code) {
5594 errno = err_code;
5595 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
5596 goto exit;
5597 }
5598 #ifdef _Py_MEMORY_SANITIZER
5599 __msan_unpoison(&pid, sizeof(pid));
5600 #endif
5601 result = PyLong_FromPid(pid);
5602
5603 exit:
5604 if (file_actionsp) {
5605 (void)posix_spawn_file_actions_destroy(file_actionsp);
5606 }
5607 if (attrp) {
5608 (void)posix_spawnattr_destroy(attrp);
5609 }
5610 if (envlist) {
5611 free_string_array(envlist, envc);
5612 }
5613 if (argvlist) {
5614 free_string_array(argvlist, argc);
5615 }
5616 Py_XDECREF(temp_buffer);
5617 return result;
5618 }
5619
5620
5621 /*[clinic input]
5622
5623 os.posix_spawn
5624 path: path_t
5625 Path of executable file.
5626 argv: object
5627 Tuple or list of strings.
5628 env: object
5629 Dictionary of strings mapping to strings.
5630 /
5631 *
5632 file_actions: object(c_default='NULL') = ()
5633 A sequence of file action tuples.
5634 setpgroup: object = NULL
5635 The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
5636 resetids: bool(accept={int}) = False
5637 If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
5638 setsid: bool(accept={int}) = False
5639 If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
5640 setsigmask: object(c_default='NULL') = ()
5641 The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
5642 setsigdef: object(c_default='NULL') = ()
5643 The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
5644 scheduler: object = NULL
5645 A tuple with the scheduler policy (optional) and parameters.
5646
5647 Execute the program specified by path in a new process.
5648 [clinic start generated code]*/
5649
5650 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)5651 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
5652 PyObject *env, PyObject *file_actions,
5653 PyObject *setpgroup, int resetids, int setsid,
5654 PyObject *setsigmask, PyObject *setsigdef,
5655 PyObject *scheduler)
5656 /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
5657 {
5658 return py_posix_spawn(0, module, path, argv, env, file_actions,
5659 setpgroup, resetids, setsid, setsigmask, setsigdef,
5660 scheduler);
5661 }
5662 #endif /* HAVE_POSIX_SPAWN */
5663
5664
5665
5666 #ifdef HAVE_POSIX_SPAWNP
5667 /*[clinic input]
5668
5669 os.posix_spawnp
5670 path: path_t
5671 Path of executable file.
5672 argv: object
5673 Tuple or list of strings.
5674 env: object
5675 Dictionary of strings mapping to strings.
5676 /
5677 *
5678 file_actions: object(c_default='NULL') = ()
5679 A sequence of file action tuples.
5680 setpgroup: object = NULL
5681 The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
5682 resetids: bool(accept={int}) = False
5683 If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
5684 setsid: bool(accept={int}) = False
5685 If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
5686 setsigmask: object(c_default='NULL') = ()
5687 The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
5688 setsigdef: object(c_default='NULL') = ()
5689 The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
5690 scheduler: object = NULL
5691 A tuple with the scheduler policy (optional) and parameters.
5692
5693 Execute the program specified by path in a new process.
5694 [clinic start generated code]*/
5695
5696 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)5697 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
5698 PyObject *env, PyObject *file_actions,
5699 PyObject *setpgroup, int resetids, int setsid,
5700 PyObject *setsigmask, PyObject *setsigdef,
5701 PyObject *scheduler)
5702 /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
5703 {
5704 return py_posix_spawn(1, module, path, argv, env, file_actions,
5705 setpgroup, resetids, setsid, setsigmask, setsigdef,
5706 scheduler);
5707 }
5708 #endif /* HAVE_POSIX_SPAWNP */
5709
5710 #ifdef HAVE_RTPSPAWN
5711 static intptr_t
_rtp_spawn(int mode,const char * rtpFileName,const char * argv[],const char * envp[])5712 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
5713 const char *envp[])
5714 {
5715 RTP_ID rtpid;
5716 int status;
5717 pid_t res;
5718 int async_err = 0;
5719
5720 /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
5721 uStackSize=0 cannot be used, the default stack size is too small for
5722 Python. */
5723 if (envp) {
5724 rtpid = rtpSpawn(rtpFileName, argv, envp,
5725 100, 0x1000000, 0, VX_FP_TASK);
5726 }
5727 else {
5728 rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
5729 100, 0x1000000, 0, VX_FP_TASK);
5730 }
5731 if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
5732 do {
5733 res = waitpid((pid_t)rtpid, &status, 0);
5734 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
5735
5736 if (res < 0)
5737 return RTP_ID_ERROR;
5738 return ((intptr_t)status);
5739 }
5740 return ((intptr_t)rtpid);
5741 }
5742 #endif
5743
5744 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
5745 /*[clinic input]
5746 os.spawnv
5747
5748 mode: int
5749 Mode of process creation.
5750 path: path_t
5751 Path of executable file.
5752 argv: object
5753 Tuple or list of strings.
5754 /
5755
5756 Execute the program specified by path in a new process.
5757 [clinic start generated code]*/
5758
5759 static PyObject *
os_spawnv_impl(PyObject * module,int mode,path_t * path,PyObject * argv)5760 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
5761 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
5762 {
5763 EXECV_CHAR **argvlist;
5764 int i;
5765 Py_ssize_t argc;
5766 intptr_t spawnval;
5767 PyObject *(*getitem)(PyObject *, Py_ssize_t);
5768
5769 /* spawnv has three arguments: (mode, path, argv), where
5770 argv is a list or tuple of strings. */
5771
5772 if (PyList_Check(argv)) {
5773 argc = PyList_Size(argv);
5774 getitem = PyList_GetItem;
5775 }
5776 else if (PyTuple_Check(argv)) {
5777 argc = PyTuple_Size(argv);
5778 getitem = PyTuple_GetItem;
5779 }
5780 else {
5781 PyErr_SetString(PyExc_TypeError,
5782 "spawnv() arg 2 must be a tuple or list");
5783 return NULL;
5784 }
5785 if (argc == 0) {
5786 PyErr_SetString(PyExc_ValueError,
5787 "spawnv() arg 2 cannot be empty");
5788 return NULL;
5789 }
5790
5791 argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
5792 if (argvlist == NULL) {
5793 return PyErr_NoMemory();
5794 }
5795 for (i = 0; i < argc; i++) {
5796 if (!fsconvert_strdup((*getitem)(argv, i),
5797 &argvlist[i])) {
5798 free_string_array(argvlist, i);
5799 PyErr_SetString(
5800 PyExc_TypeError,
5801 "spawnv() arg 2 must contain only strings");
5802 return NULL;
5803 }
5804 if (i == 0 && !argvlist[0][0]) {
5805 free_string_array(argvlist, i + 1);
5806 PyErr_SetString(
5807 PyExc_ValueError,
5808 "spawnv() arg 2 first element cannot be empty");
5809 return NULL;
5810 }
5811 }
5812 argvlist[argc] = NULL;
5813
5814 #if !defined(HAVE_RTPSPAWN)
5815 if (mode == _OLD_P_OVERLAY)
5816 mode = _P_OVERLAY;
5817 #endif
5818
5819 Py_BEGIN_ALLOW_THREADS
5820 _Py_BEGIN_SUPPRESS_IPH
5821 #ifdef HAVE_WSPAWNV
5822 spawnval = _wspawnv(mode, path->wide, argvlist);
5823 #elif defined(HAVE_RTPSPAWN)
5824 spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
5825 #else
5826 spawnval = _spawnv(mode, path->narrow, argvlist);
5827 #endif
5828 _Py_END_SUPPRESS_IPH
5829 Py_END_ALLOW_THREADS
5830
5831 free_string_array(argvlist, argc);
5832
5833 if (spawnval == -1)
5834 return posix_error();
5835 else
5836 return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
5837 }
5838
5839 /*[clinic input]
5840 os.spawnve
5841
5842 mode: int
5843 Mode of process creation.
5844 path: path_t
5845 Path of executable file.
5846 argv: object
5847 Tuple or list of strings.
5848 env: object
5849 Dictionary of strings mapping to strings.
5850 /
5851
5852 Execute the program specified by path in a new process.
5853 [clinic start generated code]*/
5854
5855 static PyObject *
os_spawnve_impl(PyObject * module,int mode,path_t * path,PyObject * argv,PyObject * env)5856 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
5857 PyObject *env)
5858 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
5859 {
5860 EXECV_CHAR **argvlist;
5861 EXECV_CHAR **envlist;
5862 PyObject *res = NULL;
5863 Py_ssize_t argc, i, envc;
5864 intptr_t spawnval;
5865 PyObject *(*getitem)(PyObject *, Py_ssize_t);
5866 Py_ssize_t lastarg = 0;
5867
5868 /* spawnve has four arguments: (mode, path, argv, env), where
5869 argv is a list or tuple of strings and env is a dictionary
5870 like posix.environ. */
5871
5872 if (PyList_Check(argv)) {
5873 argc = PyList_Size(argv);
5874 getitem = PyList_GetItem;
5875 }
5876 else if (PyTuple_Check(argv)) {
5877 argc = PyTuple_Size(argv);
5878 getitem = PyTuple_GetItem;
5879 }
5880 else {
5881 PyErr_SetString(PyExc_TypeError,
5882 "spawnve() arg 2 must be a tuple or list");
5883 goto fail_0;
5884 }
5885 if (argc == 0) {
5886 PyErr_SetString(PyExc_ValueError,
5887 "spawnve() arg 2 cannot be empty");
5888 goto fail_0;
5889 }
5890 if (!PyMapping_Check(env)) {
5891 PyErr_SetString(PyExc_TypeError,
5892 "spawnve() arg 3 must be a mapping object");
5893 goto fail_0;
5894 }
5895
5896 argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
5897 if (argvlist == NULL) {
5898 PyErr_NoMemory();
5899 goto fail_0;
5900 }
5901 for (i = 0; i < argc; i++) {
5902 if (!fsconvert_strdup((*getitem)(argv, i),
5903 &argvlist[i]))
5904 {
5905 lastarg = i;
5906 goto fail_1;
5907 }
5908 if (i == 0 && !argvlist[0][0]) {
5909 lastarg = i + 1;
5910 PyErr_SetString(
5911 PyExc_ValueError,
5912 "spawnv() arg 2 first element cannot be empty");
5913 goto fail_1;
5914 }
5915 }
5916 lastarg = argc;
5917 argvlist[argc] = NULL;
5918
5919 envlist = parse_envlist(env, &envc);
5920 if (envlist == NULL)
5921 goto fail_1;
5922
5923 #if !defined(HAVE_RTPSPAWN)
5924 if (mode == _OLD_P_OVERLAY)
5925 mode = _P_OVERLAY;
5926 #endif
5927
5928 Py_BEGIN_ALLOW_THREADS
5929 _Py_BEGIN_SUPPRESS_IPH
5930 #ifdef HAVE_WSPAWNV
5931 spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
5932 #elif defined(HAVE_RTPSPAWN)
5933 spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
5934 (const char **)envlist);
5935 #else
5936 spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
5937 #endif
5938 _Py_END_SUPPRESS_IPH
5939 Py_END_ALLOW_THREADS
5940
5941 if (spawnval == -1)
5942 (void) posix_error();
5943 else
5944 res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
5945
5946 while (--envc >= 0)
5947 PyMem_DEL(envlist[envc]);
5948 PyMem_DEL(envlist);
5949 fail_1:
5950 free_string_array(argvlist, lastarg);
5951 fail_0:
5952 return res;
5953 }
5954
5955 #endif /* HAVE_SPAWNV */
5956
5957
5958 #ifdef HAVE_FORK
5959
5960 /* Helper function to validate arguments.
5961 Returns 0 on success. non-zero on failure with a TypeError raised.
5962 If obj is non-NULL it must be callable. */
5963 static int
check_null_or_callable(PyObject * obj,const char * obj_name)5964 check_null_or_callable(PyObject *obj, const char* obj_name)
5965 {
5966 if (obj && !PyCallable_Check(obj)) {
5967 PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
5968 obj_name, Py_TYPE(obj)->tp_name);
5969 return -1;
5970 }
5971 return 0;
5972 }
5973
5974 /*[clinic input]
5975 os.register_at_fork
5976
5977 *
5978 before: object=NULL
5979 A callable to be called in the parent before the fork() syscall.
5980 after_in_child: object=NULL
5981 A callable to be called in the child after fork().
5982 after_in_parent: object=NULL
5983 A callable to be called in the parent after fork().
5984
5985 Register callables to be called when forking a new process.
5986
5987 'before' callbacks are called in reverse order.
5988 'after_in_child' and 'after_in_parent' callbacks are called in order.
5989
5990 [clinic start generated code]*/
5991
5992 static PyObject *
os_register_at_fork_impl(PyObject * module,PyObject * before,PyObject * after_in_child,PyObject * after_in_parent)5993 os_register_at_fork_impl(PyObject *module, PyObject *before,
5994 PyObject *after_in_child, PyObject *after_in_parent)
5995 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
5996 {
5997 PyInterpreterState *interp;
5998
5999 if (!before && !after_in_child && !after_in_parent) {
6000 PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6001 return NULL;
6002 }
6003 if (check_null_or_callable(before, "before") ||
6004 check_null_or_callable(after_in_child, "after_in_child") ||
6005 check_null_or_callable(after_in_parent, "after_in_parent")) {
6006 return NULL;
6007 }
6008 interp = _PyInterpreterState_Get();
6009
6010 if (register_at_forker(&interp->before_forkers, before)) {
6011 return NULL;
6012 }
6013 if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6014 return NULL;
6015 }
6016 if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6017 return NULL;
6018 }
6019 Py_RETURN_NONE;
6020 }
6021 #endif /* HAVE_FORK */
6022
6023
6024 #ifdef HAVE_FORK1
6025 /*[clinic input]
6026 os.fork1
6027
6028 Fork a child process with a single multiplexed (i.e., not bound) thread.
6029
6030 Return 0 to child process and PID of child to parent process.
6031 [clinic start generated code]*/
6032
6033 static PyObject *
os_fork1_impl(PyObject * module)6034 os_fork1_impl(PyObject *module)
6035 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6036 {
6037 pid_t pid;
6038
6039 if (_PyInterpreterState_Get() != PyInterpreterState_Main()) {
6040 PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6041 return NULL;
6042 }
6043 PyOS_BeforeFork();
6044 pid = fork1();
6045 if (pid == 0) {
6046 /* child: this clobbers and resets the import lock. */
6047 PyOS_AfterFork_Child();
6048 } else {
6049 /* parent: release the import lock. */
6050 PyOS_AfterFork_Parent();
6051 }
6052 if (pid == -1)
6053 return posix_error();
6054 return PyLong_FromPid(pid);
6055 }
6056 #endif /* HAVE_FORK1 */
6057
6058
6059 #ifdef HAVE_FORK
6060 /*[clinic input]
6061 os.fork
6062
6063 Fork a child process.
6064
6065 Return 0 to child process and PID of child to parent process.
6066 [clinic start generated code]*/
6067
6068 static PyObject *
os_fork_impl(PyObject * module)6069 os_fork_impl(PyObject *module)
6070 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6071 {
6072 pid_t pid;
6073
6074 if (_PyInterpreterState_Get() != PyInterpreterState_Main()) {
6075 PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6076 return NULL;
6077 }
6078 PyOS_BeforeFork();
6079 pid = fork();
6080 if (pid == 0) {
6081 /* child: this clobbers and resets the import lock. */
6082 PyOS_AfterFork_Child();
6083 } else {
6084 /* parent: release the import lock. */
6085 PyOS_AfterFork_Parent();
6086 }
6087 if (pid == -1)
6088 return posix_error();
6089 return PyLong_FromPid(pid);
6090 }
6091 #endif /* HAVE_FORK */
6092
6093
6094 #ifdef HAVE_SCHED_H
6095 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6096 /*[clinic input]
6097 os.sched_get_priority_max
6098
6099 policy: int
6100
6101 Get the maximum scheduling priority for policy.
6102 [clinic start generated code]*/
6103
6104 static PyObject *
os_sched_get_priority_max_impl(PyObject * module,int policy)6105 os_sched_get_priority_max_impl(PyObject *module, int policy)
6106 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6107 {
6108 int max;
6109
6110 max = sched_get_priority_max(policy);
6111 if (max < 0)
6112 return posix_error();
6113 return PyLong_FromLong(max);
6114 }
6115
6116
6117 /*[clinic input]
6118 os.sched_get_priority_min
6119
6120 policy: int
6121
6122 Get the minimum scheduling priority for policy.
6123 [clinic start generated code]*/
6124
6125 static PyObject *
os_sched_get_priority_min_impl(PyObject * module,int policy)6126 os_sched_get_priority_min_impl(PyObject *module, int policy)
6127 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6128 {
6129 int min = sched_get_priority_min(policy);
6130 if (min < 0)
6131 return posix_error();
6132 return PyLong_FromLong(min);
6133 }
6134 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6135
6136
6137 #ifdef HAVE_SCHED_SETSCHEDULER
6138 /*[clinic input]
6139 os.sched_getscheduler
6140 pid: pid_t
6141 /
6142
6143 Get the scheduling policy for the process identifiedy by pid.
6144
6145 Passing 0 for pid returns the scheduling policy for the calling process.
6146 [clinic start generated code]*/
6147
6148 static PyObject *
os_sched_getscheduler_impl(PyObject * module,pid_t pid)6149 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6150 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=5f14cfd1f189e1a0]*/
6151 {
6152 int policy;
6153
6154 policy = sched_getscheduler(pid);
6155 if (policy < 0)
6156 return posix_error();
6157 return PyLong_FromLong(policy);
6158 }
6159 #endif /* HAVE_SCHED_SETSCHEDULER */
6160
6161
6162 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6163 /*[clinic input]
6164 class os.sched_param "PyObject *" "SchedParamType"
6165
6166 @classmethod
6167 os.sched_param.__new__
6168
6169 sched_priority: object
6170 A scheduling parameter.
6171
6172 Current has only one field: sched_priority");
6173 [clinic start generated code]*/
6174
6175 static PyObject *
os_sched_param_impl(PyTypeObject * type,PyObject * sched_priority)6176 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6177 /*[clinic end generated code: output=48f4067d60f48c13 input=ab4de35a9a7811f2]*/
6178 {
6179 PyObject *res;
6180
6181 res = PyStructSequence_New(type);
6182 if (!res)
6183 return NULL;
6184 Py_INCREF(sched_priority);
6185 PyStructSequence_SET_ITEM(res, 0, sched_priority);
6186 return res;
6187 }
6188
6189
6190 PyDoc_VAR(os_sched_param__doc__);
6191
6192 static PyStructSequence_Field sched_param_fields[] = {
6193 {"sched_priority", "the scheduling priority"},
6194 {0}
6195 };
6196
6197 static PyStructSequence_Desc sched_param_desc = {
6198 "sched_param", /* name */
6199 os_sched_param__doc__, /* doc */
6200 sched_param_fields,
6201 1
6202 };
6203
6204 static int
convert_sched_param(PyObject * param,struct sched_param * res)6205 convert_sched_param(PyObject *param, struct sched_param *res)
6206 {
6207 long priority;
6208
6209 if (Py_TYPE(param) != SchedParamType) {
6210 PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
6211 return 0;
6212 }
6213 priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
6214 if (priority == -1 && PyErr_Occurred())
6215 return 0;
6216 if (priority > INT_MAX || priority < INT_MIN) {
6217 PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
6218 return 0;
6219 }
6220 res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
6221 return 1;
6222 }
6223 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
6224
6225
6226 #ifdef HAVE_SCHED_SETSCHEDULER
6227 /*[clinic input]
6228 os.sched_setscheduler
6229
6230 pid: pid_t
6231 policy: int
6232 param: sched_param
6233 /
6234
6235 Set the scheduling policy for the process identified by pid.
6236
6237 If pid is 0, the calling process is changed.
6238 param is an instance of sched_param.
6239 [clinic start generated code]*/
6240
6241 static PyObject *
os_sched_setscheduler_impl(PyObject * module,pid_t pid,int policy,struct sched_param * param)6242 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
6243 struct sched_param *param)
6244 /*[clinic end generated code: output=b0ac0a70d3b1d705 input=c581f9469a5327dd]*/
6245 {
6246 /*
6247 ** sched_setscheduler() returns 0 in Linux, but the previous
6248 ** scheduling policy under Solaris/Illumos, and others.
6249 ** On error, -1 is returned in all Operating Systems.
6250 */
6251 if (sched_setscheduler(pid, policy, param) == -1)
6252 return posix_error();
6253 Py_RETURN_NONE;
6254 }
6255 #endif /* HAVE_SCHED_SETSCHEDULER*/
6256
6257
6258 #ifdef HAVE_SCHED_SETPARAM
6259 /*[clinic input]
6260 os.sched_getparam
6261 pid: pid_t
6262 /
6263
6264 Returns scheduling parameters for the process identified by pid.
6265
6266 If pid is 0, returns parameters for the calling process.
6267 Return value is an instance of sched_param.
6268 [clinic start generated code]*/
6269
6270 static PyObject *
os_sched_getparam_impl(PyObject * module,pid_t pid)6271 os_sched_getparam_impl(PyObject *module, pid_t pid)
6272 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
6273 {
6274 struct sched_param param;
6275 PyObject *result;
6276 PyObject *priority;
6277
6278 if (sched_getparam(pid, ¶m))
6279 return posix_error();
6280 result = PyStructSequence_New(SchedParamType);
6281 if (!result)
6282 return NULL;
6283 priority = PyLong_FromLong(param.sched_priority);
6284 if (!priority) {
6285 Py_DECREF(result);
6286 return NULL;
6287 }
6288 PyStructSequence_SET_ITEM(result, 0, priority);
6289 return result;
6290 }
6291
6292
6293 /*[clinic input]
6294 os.sched_setparam
6295 pid: pid_t
6296 param: sched_param
6297 /
6298
6299 Set scheduling parameters for the process identified by pid.
6300
6301 If pid is 0, sets parameters for the calling process.
6302 param should be an instance of sched_param.
6303 [clinic start generated code]*/
6304
6305 static PyObject *
os_sched_setparam_impl(PyObject * module,pid_t pid,struct sched_param * param)6306 os_sched_setparam_impl(PyObject *module, pid_t pid,
6307 struct sched_param *param)
6308 /*[clinic end generated code: output=8af013f78a32b591 input=6b8d6dfcecdc21bd]*/
6309 {
6310 if (sched_setparam(pid, param))
6311 return posix_error();
6312 Py_RETURN_NONE;
6313 }
6314 #endif /* HAVE_SCHED_SETPARAM */
6315
6316
6317 #ifdef HAVE_SCHED_RR_GET_INTERVAL
6318 /*[clinic input]
6319 os.sched_rr_get_interval -> double
6320 pid: pid_t
6321 /
6322
6323 Return the round-robin quantum for the process identified by pid, in seconds.
6324
6325 Value returned is a float.
6326 [clinic start generated code]*/
6327
6328 static double
os_sched_rr_get_interval_impl(PyObject * module,pid_t pid)6329 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
6330 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
6331 {
6332 struct timespec interval;
6333 if (sched_rr_get_interval(pid, &interval)) {
6334 posix_error();
6335 return -1.0;
6336 }
6337 #ifdef _Py_MEMORY_SANITIZER
6338 __msan_unpoison(&interval, sizeof(interval));
6339 #endif
6340 return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
6341 }
6342 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
6343
6344
6345 /*[clinic input]
6346 os.sched_yield
6347
6348 Voluntarily relinquish the CPU.
6349 [clinic start generated code]*/
6350
6351 static PyObject *
os_sched_yield_impl(PyObject * module)6352 os_sched_yield_impl(PyObject *module)
6353 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
6354 {
6355 if (sched_yield())
6356 return posix_error();
6357 Py_RETURN_NONE;
6358 }
6359
6360 #ifdef HAVE_SCHED_SETAFFINITY
6361 /* The minimum number of CPUs allocated in a cpu_set_t */
6362 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
6363
6364 /*[clinic input]
6365 os.sched_setaffinity
6366 pid: pid_t
6367 mask : object
6368 /
6369
6370 Set the CPU affinity of the process identified by pid to mask.
6371
6372 mask should be an iterable of integers identifying CPUs.
6373 [clinic start generated code]*/
6374
6375 static PyObject *
os_sched_setaffinity_impl(PyObject * module,pid_t pid,PyObject * mask)6376 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
6377 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
6378 {
6379 int ncpus;
6380 size_t setsize;
6381 cpu_set_t *cpu_set = NULL;
6382 PyObject *iterator = NULL, *item;
6383
6384 iterator = PyObject_GetIter(mask);
6385 if (iterator == NULL)
6386 return NULL;
6387
6388 ncpus = NCPUS_START;
6389 setsize = CPU_ALLOC_SIZE(ncpus);
6390 cpu_set = CPU_ALLOC(ncpus);
6391 if (cpu_set == NULL) {
6392 PyErr_NoMemory();
6393 goto error;
6394 }
6395 CPU_ZERO_S(setsize, cpu_set);
6396
6397 while ((item = PyIter_Next(iterator))) {
6398 long cpu;
6399 if (!PyLong_Check(item)) {
6400 PyErr_Format(PyExc_TypeError,
6401 "expected an iterator of ints, "
6402 "but iterator yielded %R",
6403 Py_TYPE(item));
6404 Py_DECREF(item);
6405 goto error;
6406 }
6407 cpu = PyLong_AsLong(item);
6408 Py_DECREF(item);
6409 if (cpu < 0) {
6410 if (!PyErr_Occurred())
6411 PyErr_SetString(PyExc_ValueError, "negative CPU number");
6412 goto error;
6413 }
6414 if (cpu > INT_MAX - 1) {
6415 PyErr_SetString(PyExc_OverflowError, "CPU number too large");
6416 goto error;
6417 }
6418 if (cpu >= ncpus) {
6419 /* Grow CPU mask to fit the CPU number */
6420 int newncpus = ncpus;
6421 cpu_set_t *newmask;
6422 size_t newsetsize;
6423 while (newncpus <= cpu) {
6424 if (newncpus > INT_MAX / 2)
6425 newncpus = cpu + 1;
6426 else
6427 newncpus = newncpus * 2;
6428 }
6429 newmask = CPU_ALLOC(newncpus);
6430 if (newmask == NULL) {
6431 PyErr_NoMemory();
6432 goto error;
6433 }
6434 newsetsize = CPU_ALLOC_SIZE(newncpus);
6435 CPU_ZERO_S(newsetsize, newmask);
6436 memcpy(newmask, cpu_set, setsize);
6437 CPU_FREE(cpu_set);
6438 setsize = newsetsize;
6439 cpu_set = newmask;
6440 ncpus = newncpus;
6441 }
6442 CPU_SET_S(cpu, setsize, cpu_set);
6443 }
6444 if (PyErr_Occurred()) {
6445 goto error;
6446 }
6447 Py_CLEAR(iterator);
6448
6449 if (sched_setaffinity(pid, setsize, cpu_set)) {
6450 posix_error();
6451 goto error;
6452 }
6453 CPU_FREE(cpu_set);
6454 Py_RETURN_NONE;
6455
6456 error:
6457 if (cpu_set)
6458 CPU_FREE(cpu_set);
6459 Py_XDECREF(iterator);
6460 return NULL;
6461 }
6462
6463
6464 /*[clinic input]
6465 os.sched_getaffinity
6466 pid: pid_t
6467 /
6468
6469 Return the affinity of the process identified by pid (or the current process if zero).
6470
6471 The affinity is returned as a set of CPU identifiers.
6472 [clinic start generated code]*/
6473
6474 static PyObject *
os_sched_getaffinity_impl(PyObject * module,pid_t pid)6475 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
6476 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
6477 {
6478 int cpu, ncpus, count;
6479 size_t setsize;
6480 cpu_set_t *mask = NULL;
6481 PyObject *res = NULL;
6482
6483 ncpus = NCPUS_START;
6484 while (1) {
6485 setsize = CPU_ALLOC_SIZE(ncpus);
6486 mask = CPU_ALLOC(ncpus);
6487 if (mask == NULL)
6488 return PyErr_NoMemory();
6489 if (sched_getaffinity(pid, setsize, mask) == 0)
6490 break;
6491 CPU_FREE(mask);
6492 if (errno != EINVAL)
6493 return posix_error();
6494 if (ncpus > INT_MAX / 2) {
6495 PyErr_SetString(PyExc_OverflowError, "could not allocate "
6496 "a large enough CPU set");
6497 return NULL;
6498 }
6499 ncpus = ncpus * 2;
6500 }
6501
6502 res = PySet_New(NULL);
6503 if (res == NULL)
6504 goto error;
6505 for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
6506 if (CPU_ISSET_S(cpu, setsize, mask)) {
6507 PyObject *cpu_num = PyLong_FromLong(cpu);
6508 --count;
6509 if (cpu_num == NULL)
6510 goto error;
6511 if (PySet_Add(res, cpu_num)) {
6512 Py_DECREF(cpu_num);
6513 goto error;
6514 }
6515 Py_DECREF(cpu_num);
6516 }
6517 }
6518 CPU_FREE(mask);
6519 return res;
6520
6521 error:
6522 if (mask)
6523 CPU_FREE(mask);
6524 Py_XDECREF(res);
6525 return NULL;
6526 }
6527
6528 #endif /* HAVE_SCHED_SETAFFINITY */
6529
6530 #endif /* HAVE_SCHED_H */
6531
6532
6533 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
6534 /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
6535 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
6536 #define DEV_PTY_FILE "/dev/ptc"
6537 #define HAVE_DEV_PTMX
6538 #else
6539 #define DEV_PTY_FILE "/dev/ptmx"
6540 #endif
6541
6542 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
6543 #ifdef HAVE_PTY_H
6544 #include <pty.h>
6545 #else
6546 #ifdef HAVE_LIBUTIL_H
6547 #include <libutil.h>
6548 #else
6549 #ifdef HAVE_UTIL_H
6550 #include <util.h>
6551 #endif /* HAVE_UTIL_H */
6552 #endif /* HAVE_LIBUTIL_H */
6553 #endif /* HAVE_PTY_H */
6554 #ifdef HAVE_STROPTS_H
6555 #include <stropts.h>
6556 #endif
6557 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */
6558
6559
6560 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
6561 /*[clinic input]
6562 os.openpty
6563
6564 Open a pseudo-terminal.
6565
6566 Return a tuple of (master_fd, slave_fd) containing open file descriptors
6567 for both the master and slave ends.
6568 [clinic start generated code]*/
6569
6570 static PyObject *
os_openpty_impl(PyObject * module)6571 os_openpty_impl(PyObject *module)
6572 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
6573 {
6574 int master_fd = -1, slave_fd = -1;
6575 #ifndef HAVE_OPENPTY
6576 char * slave_name;
6577 #endif
6578 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
6579 PyOS_sighandler_t sig_saved;
6580 #if defined(__sun) && defined(__SVR4)
6581 extern char *ptsname(int fildes);
6582 #endif
6583 #endif
6584
6585 #ifdef HAVE_OPENPTY
6586 if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
6587 goto posix_error;
6588
6589 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
6590 goto error;
6591 if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
6592 goto error;
6593
6594 #elif defined(HAVE__GETPTY)
6595 slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
6596 if (slave_name == NULL)
6597 goto posix_error;
6598 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
6599 goto error;
6600
6601 slave_fd = _Py_open(slave_name, O_RDWR);
6602 if (slave_fd < 0)
6603 goto error;
6604
6605 #else
6606 master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
6607 if (master_fd < 0)
6608 goto posix_error;
6609
6610 sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
6611
6612 /* change permission of slave */
6613 if (grantpt(master_fd) < 0) {
6614 PyOS_setsig(SIGCHLD, sig_saved);
6615 goto posix_error;
6616 }
6617
6618 /* unlock slave */
6619 if (unlockpt(master_fd) < 0) {
6620 PyOS_setsig(SIGCHLD, sig_saved);
6621 goto posix_error;
6622 }
6623
6624 PyOS_setsig(SIGCHLD, sig_saved);
6625
6626 slave_name = ptsname(master_fd); /* get name of slave */
6627 if (slave_name == NULL)
6628 goto posix_error;
6629
6630 slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
6631 if (slave_fd == -1)
6632 goto error;
6633
6634 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
6635 goto posix_error;
6636
6637 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
6638 ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
6639 ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
6640 #ifndef __hpux
6641 ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
6642 #endif /* __hpux */
6643 #endif /* HAVE_CYGWIN */
6644 #endif /* HAVE_OPENPTY */
6645
6646 return Py_BuildValue("(ii)", master_fd, slave_fd);
6647
6648 posix_error:
6649 posix_error();
6650 error:
6651 if (master_fd != -1)
6652 close(master_fd);
6653 if (slave_fd != -1)
6654 close(slave_fd);
6655 return NULL;
6656 }
6657 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
6658
6659
6660 #ifdef HAVE_FORKPTY
6661 /*[clinic input]
6662 os.forkpty
6663
6664 Fork a new process with a new pseudo-terminal as controlling tty.
6665
6666 Returns a tuple of (pid, master_fd).
6667 Like fork(), return pid of 0 to the child process,
6668 and pid of child to the parent process.
6669 To both, return fd of newly opened pseudo-terminal.
6670 [clinic start generated code]*/
6671
6672 static PyObject *
os_forkpty_impl(PyObject * module)6673 os_forkpty_impl(PyObject *module)
6674 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
6675 {
6676 int master_fd = -1;
6677 pid_t pid;
6678
6679 if (_PyInterpreterState_Get() != PyInterpreterState_Main()) {
6680 PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6681 return NULL;
6682 }
6683 PyOS_BeforeFork();
6684 pid = forkpty(&master_fd, NULL, NULL, NULL);
6685 if (pid == 0) {
6686 /* child: this clobbers and resets the import lock. */
6687 PyOS_AfterFork_Child();
6688 } else {
6689 /* parent: release the import lock. */
6690 PyOS_AfterFork_Parent();
6691 }
6692 if (pid == -1)
6693 return posix_error();
6694 return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
6695 }
6696 #endif /* HAVE_FORKPTY */
6697
6698
6699 #ifdef HAVE_GETEGID
6700 /*[clinic input]
6701 os.getegid
6702
6703 Return the current process's effective group id.
6704 [clinic start generated code]*/
6705
6706 static PyObject *
os_getegid_impl(PyObject * module)6707 os_getegid_impl(PyObject *module)
6708 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
6709 {
6710 return _PyLong_FromGid(getegid());
6711 }
6712 #endif /* HAVE_GETEGID */
6713
6714
6715 #ifdef HAVE_GETEUID
6716 /*[clinic input]
6717 os.geteuid
6718
6719 Return the current process's effective user id.
6720 [clinic start generated code]*/
6721
6722 static PyObject *
os_geteuid_impl(PyObject * module)6723 os_geteuid_impl(PyObject *module)
6724 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
6725 {
6726 return _PyLong_FromUid(geteuid());
6727 }
6728 #endif /* HAVE_GETEUID */
6729
6730
6731 #ifdef HAVE_GETGID
6732 /*[clinic input]
6733 os.getgid
6734
6735 Return the current process's group id.
6736 [clinic start generated code]*/
6737
6738 static PyObject *
os_getgid_impl(PyObject * module)6739 os_getgid_impl(PyObject *module)
6740 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
6741 {
6742 return _PyLong_FromGid(getgid());
6743 }
6744 #endif /* HAVE_GETGID */
6745
6746
6747 #ifdef HAVE_GETPID
6748 /*[clinic input]
6749 os.getpid
6750
6751 Return the current process id.
6752 [clinic start generated code]*/
6753
6754 static PyObject *
os_getpid_impl(PyObject * module)6755 os_getpid_impl(PyObject *module)
6756 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
6757 {
6758 return PyLong_FromPid(getpid());
6759 }
6760 #endif /* HAVE_GETPID */
6761
6762 #ifdef NGROUPS_MAX
6763 #define MAX_GROUPS NGROUPS_MAX
6764 #else
6765 /* defined to be 16 on Solaris7, so this should be a small number */
6766 #define MAX_GROUPS 64
6767 #endif
6768
6769 #ifdef HAVE_GETGROUPLIST
6770
6771 /* AC 3.5: funny apple logic below */
6772 PyDoc_STRVAR(posix_getgrouplist__doc__,
6773 "getgrouplist(user, group) -> list of groups to which a user belongs\n\n\
6774 Returns a list of groups to which a user belongs.\n\n\
6775 user: username to lookup\n\
6776 group: base group id of the user");
6777
6778 static PyObject *
posix_getgrouplist(PyObject * self,PyObject * args)6779 posix_getgrouplist(PyObject *self, PyObject *args)
6780 {
6781 const char *user;
6782 int i, ngroups;
6783 PyObject *list;
6784 #ifdef __APPLE__
6785 int *groups, basegid;
6786 #else
6787 gid_t *groups, basegid;
6788 #endif
6789
6790 /*
6791 * NGROUPS_MAX is defined by POSIX.1 as the maximum
6792 * number of supplimental groups a users can belong to.
6793 * We have to increment it by one because
6794 * getgrouplist() returns both the supplemental groups
6795 * and the primary group, i.e. all of the groups the
6796 * user belongs to.
6797 */
6798 ngroups = 1 + MAX_GROUPS;
6799
6800 #ifdef __APPLE__
6801 if (!PyArg_ParseTuple(args, "si:getgrouplist", &user, &basegid))
6802 return NULL;
6803 #else
6804 if (!PyArg_ParseTuple(args, "sO&:getgrouplist", &user,
6805 _Py_Gid_Converter, &basegid))
6806 return NULL;
6807 #endif
6808
6809 #ifdef __APPLE__
6810 groups = PyMem_New(int, ngroups);
6811 #else
6812 groups = PyMem_New(gid_t, ngroups);
6813 #endif
6814 if (groups == NULL)
6815 return PyErr_NoMemory();
6816
6817 if (getgrouplist(user, basegid, groups, &ngroups) == -1) {
6818 PyMem_Del(groups);
6819 return posix_error();
6820 }
6821
6822 #ifdef _Py_MEMORY_SANITIZER
6823 /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
6824 __msan_unpoison(&ngroups, sizeof(ngroups));
6825 __msan_unpoison(groups, ngroups*sizeof(*groups));
6826 #endif
6827
6828 list = PyList_New(ngroups);
6829 if (list == NULL) {
6830 PyMem_Del(groups);
6831 return NULL;
6832 }
6833
6834 for (i = 0; i < ngroups; i++) {
6835 #ifdef __APPLE__
6836 PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
6837 #else
6838 PyObject *o = _PyLong_FromGid(groups[i]);
6839 #endif
6840 if (o == NULL) {
6841 Py_DECREF(list);
6842 PyMem_Del(groups);
6843 return NULL;
6844 }
6845 PyList_SET_ITEM(list, i, o);
6846 }
6847
6848 PyMem_Del(groups);
6849
6850 return list;
6851 }
6852 #endif /* HAVE_GETGROUPLIST */
6853
6854
6855 #ifdef HAVE_GETGROUPS
6856 /*[clinic input]
6857 os.getgroups
6858
6859 Return list of supplemental group IDs for the process.
6860 [clinic start generated code]*/
6861
6862 static PyObject *
os_getgroups_impl(PyObject * module)6863 os_getgroups_impl(PyObject *module)
6864 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
6865 {
6866 PyObject *result = NULL;
6867 gid_t grouplist[MAX_GROUPS];
6868
6869 /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
6870 * This is a helper variable to store the intermediate result when
6871 * that happens.
6872 *
6873 * To keep the code readable the OSX behaviour is unconditional,
6874 * according to the POSIX spec this should be safe on all unix-y
6875 * systems.
6876 */
6877 gid_t* alt_grouplist = grouplist;
6878 int n;
6879
6880 #ifdef __APPLE__
6881 /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if
6882 * there are more groups than can fit in grouplist. Therefore, on OS X
6883 * always first call getgroups with length 0 to get the actual number
6884 * of groups.
6885 */
6886 n = getgroups(0, NULL);
6887 if (n < 0) {
6888 return posix_error();
6889 } else if (n <= MAX_GROUPS) {
6890 /* groups will fit in existing array */
6891 alt_grouplist = grouplist;
6892 } else {
6893 alt_grouplist = PyMem_New(gid_t, n);
6894 if (alt_grouplist == NULL) {
6895 return PyErr_NoMemory();
6896 }
6897 }
6898
6899 n = getgroups(n, alt_grouplist);
6900 if (n == -1) {
6901 if (alt_grouplist != grouplist) {
6902 PyMem_Free(alt_grouplist);
6903 }
6904 return posix_error();
6905 }
6906 #else
6907 n = getgroups(MAX_GROUPS, grouplist);
6908 if (n < 0) {
6909 if (errno == EINVAL) {
6910 n = getgroups(0, NULL);
6911 if (n == -1) {
6912 return posix_error();
6913 }
6914 if (n == 0) {
6915 /* Avoid malloc(0) */
6916 alt_grouplist = grouplist;
6917 } else {
6918 alt_grouplist = PyMem_New(gid_t, n);
6919 if (alt_grouplist == NULL) {
6920 return PyErr_NoMemory();
6921 }
6922 n = getgroups(n, alt_grouplist);
6923 if (n == -1) {
6924 PyMem_Free(alt_grouplist);
6925 return posix_error();
6926 }
6927 }
6928 } else {
6929 return posix_error();
6930 }
6931 }
6932 #endif
6933
6934 result = PyList_New(n);
6935 if (result != NULL) {
6936 int i;
6937 for (i = 0; i < n; ++i) {
6938 PyObject *o = _PyLong_FromGid(alt_grouplist[i]);
6939 if (o == NULL) {
6940 Py_DECREF(result);
6941 result = NULL;
6942 break;
6943 }
6944 PyList_SET_ITEM(result, i, o);
6945 }
6946 }
6947
6948 if (alt_grouplist != grouplist) {
6949 PyMem_Free(alt_grouplist);
6950 }
6951
6952 return result;
6953 }
6954 #endif /* HAVE_GETGROUPS */
6955
6956 #ifdef HAVE_INITGROUPS
6957 PyDoc_STRVAR(posix_initgroups__doc__,
6958 "initgroups(username, gid) -> None\n\n\
6959 Call the system initgroups() to initialize the group access list with all of\n\
6960 the groups of which the specified username is a member, plus the specified\n\
6961 group id.");
6962
6963 /* AC 3.5: funny apple logic */
6964 static PyObject *
posix_initgroups(PyObject * self,PyObject * args)6965 posix_initgroups(PyObject *self, PyObject *args)
6966 {
6967 PyObject *oname;
6968 const char *username;
6969 int res;
6970 #ifdef __APPLE__
6971 int gid;
6972 #else
6973 gid_t gid;
6974 #endif
6975
6976 #ifdef __APPLE__
6977 if (!PyArg_ParseTuple(args, "O&i:initgroups",
6978 PyUnicode_FSConverter, &oname,
6979 &gid))
6980 #else
6981 if (!PyArg_ParseTuple(args, "O&O&:initgroups",
6982 PyUnicode_FSConverter, &oname,
6983 _Py_Gid_Converter, &gid))
6984 #endif
6985 return NULL;
6986 username = PyBytes_AS_STRING(oname);
6987
6988 res = initgroups(username, gid);
6989 Py_DECREF(oname);
6990 if (res == -1)
6991 return PyErr_SetFromErrno(PyExc_OSError);
6992
6993 Py_RETURN_NONE;
6994 }
6995 #endif /* HAVE_INITGROUPS */
6996
6997
6998 #ifdef HAVE_GETPGID
6999 /*[clinic input]
7000 os.getpgid
7001
7002 pid: pid_t
7003
7004 Call the system call getpgid(), and return the result.
7005 [clinic start generated code]*/
7006
7007 static PyObject *
os_getpgid_impl(PyObject * module,pid_t pid)7008 os_getpgid_impl(PyObject *module, pid_t pid)
7009 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7010 {
7011 pid_t pgid = getpgid(pid);
7012 if (pgid < 0)
7013 return posix_error();
7014 return PyLong_FromPid(pgid);
7015 }
7016 #endif /* HAVE_GETPGID */
7017
7018
7019 #ifdef HAVE_GETPGRP
7020 /*[clinic input]
7021 os.getpgrp
7022
7023 Return the current process group id.
7024 [clinic start generated code]*/
7025
7026 static PyObject *
os_getpgrp_impl(PyObject * module)7027 os_getpgrp_impl(PyObject *module)
7028 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7029 {
7030 #ifdef GETPGRP_HAVE_ARG
7031 return PyLong_FromPid(getpgrp(0));
7032 #else /* GETPGRP_HAVE_ARG */
7033 return PyLong_FromPid(getpgrp());
7034 #endif /* GETPGRP_HAVE_ARG */
7035 }
7036 #endif /* HAVE_GETPGRP */
7037
7038
7039 #ifdef HAVE_SETPGRP
7040 /*[clinic input]
7041 os.setpgrp
7042
7043 Make the current process the leader of its process group.
7044 [clinic start generated code]*/
7045
7046 static PyObject *
os_setpgrp_impl(PyObject * module)7047 os_setpgrp_impl(PyObject *module)
7048 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7049 {
7050 #ifdef SETPGRP_HAVE_ARG
7051 if (setpgrp(0, 0) < 0)
7052 #else /* SETPGRP_HAVE_ARG */
7053 if (setpgrp() < 0)
7054 #endif /* SETPGRP_HAVE_ARG */
7055 return posix_error();
7056 Py_RETURN_NONE;
7057 }
7058 #endif /* HAVE_SETPGRP */
7059
7060 #ifdef HAVE_GETPPID
7061
7062 #ifdef MS_WINDOWS
7063 #include <tlhelp32.h>
7064
7065 static PyObject*
win32_getppid()7066 win32_getppid()
7067 {
7068 HANDLE snapshot;
7069 pid_t mypid;
7070 PyObject* result = NULL;
7071 BOOL have_record;
7072 PROCESSENTRY32 pe;
7073
7074 mypid = getpid(); /* This function never fails */
7075
7076 snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7077 if (snapshot == INVALID_HANDLE_VALUE)
7078 return PyErr_SetFromWindowsErr(GetLastError());
7079
7080 pe.dwSize = sizeof(pe);
7081 have_record = Process32First(snapshot, &pe);
7082 while (have_record) {
7083 if (mypid == (pid_t)pe.th32ProcessID) {
7084 /* We could cache the ulong value in a static variable. */
7085 result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7086 break;
7087 }
7088
7089 have_record = Process32Next(snapshot, &pe);
7090 }
7091
7092 /* If our loop exits and our pid was not found (result will be NULL)
7093 * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7094 * error anyway, so let's raise it. */
7095 if (!result)
7096 result = PyErr_SetFromWindowsErr(GetLastError());
7097
7098 CloseHandle(snapshot);
7099
7100 return result;
7101 }
7102 #endif /*MS_WINDOWS*/
7103
7104
7105 /*[clinic input]
7106 os.getppid
7107
7108 Return the parent's process id.
7109
7110 If the parent process has already exited, Windows machines will still
7111 return its id; others systems will return the id of the 'init' process (1).
7112 [clinic start generated code]*/
7113
7114 static PyObject *
os_getppid_impl(PyObject * module)7115 os_getppid_impl(PyObject *module)
7116 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7117 {
7118 #ifdef MS_WINDOWS
7119 return win32_getppid();
7120 #else
7121 return PyLong_FromPid(getppid());
7122 #endif
7123 }
7124 #endif /* HAVE_GETPPID */
7125
7126
7127 #ifdef HAVE_GETLOGIN
7128 /*[clinic input]
7129 os.getlogin
7130
7131 Return the actual login name.
7132 [clinic start generated code]*/
7133
7134 static PyObject *
os_getlogin_impl(PyObject * module)7135 os_getlogin_impl(PyObject *module)
7136 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7137 {
7138 PyObject *result = NULL;
7139 #ifdef MS_WINDOWS
7140 wchar_t user_name[UNLEN + 1];
7141 DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7142
7143 if (GetUserNameW(user_name, &num_chars)) {
7144 /* num_chars is the number of unicode chars plus null terminator */
7145 result = PyUnicode_FromWideChar(user_name, num_chars - 1);
7146 }
7147 else
7148 result = PyErr_SetFromWindowsErr(GetLastError());
7149 #else
7150 char *name;
7151 int old_errno = errno;
7152
7153 errno = 0;
7154 name = getlogin();
7155 if (name == NULL) {
7156 if (errno)
7157 posix_error();
7158 else
7159 PyErr_SetString(PyExc_OSError, "unable to determine login name");
7160 }
7161 else
7162 result = PyUnicode_DecodeFSDefault(name);
7163 errno = old_errno;
7164 #endif
7165 return result;
7166 }
7167 #endif /* HAVE_GETLOGIN */
7168
7169
7170 #ifdef HAVE_GETUID
7171 /*[clinic input]
7172 os.getuid
7173
7174 Return the current process's user id.
7175 [clinic start generated code]*/
7176
7177 static PyObject *
os_getuid_impl(PyObject * module)7178 os_getuid_impl(PyObject *module)
7179 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7180 {
7181 return _PyLong_FromUid(getuid());
7182 }
7183 #endif /* HAVE_GETUID */
7184
7185
7186 #ifdef MS_WINDOWS
7187 #define HAVE_KILL
7188 #endif /* MS_WINDOWS */
7189
7190 #ifdef HAVE_KILL
7191 /*[clinic input]
7192 os.kill
7193
7194 pid: pid_t
7195 signal: Py_ssize_t
7196 /
7197
7198 Kill a process with a signal.
7199 [clinic start generated code]*/
7200
7201 static PyObject *
os_kill_impl(PyObject * module,pid_t pid,Py_ssize_t signal)7202 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
7203 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
7204 #ifndef MS_WINDOWS
7205 {
7206 if (kill(pid, (int)signal) == -1)
7207 return posix_error();
7208 Py_RETURN_NONE;
7209 }
7210 #else /* !MS_WINDOWS */
7211 {
7212 PyObject *result;
7213 DWORD sig = (DWORD)signal;
7214 DWORD err;
7215 HANDLE handle;
7216
7217 /* Console processes which share a common console can be sent CTRL+C or
7218 CTRL+BREAK events, provided they handle said events. */
7219 if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
7220 if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
7221 err = GetLastError();
7222 PyErr_SetFromWindowsErr(err);
7223 }
7224 else
7225 Py_RETURN_NONE;
7226 }
7227
7228 /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
7229 attempt to open and terminate the process. */
7230 handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
7231 if (handle == NULL) {
7232 err = GetLastError();
7233 return PyErr_SetFromWindowsErr(err);
7234 }
7235
7236 if (TerminateProcess(handle, sig) == 0) {
7237 err = GetLastError();
7238 result = PyErr_SetFromWindowsErr(err);
7239 } else {
7240 Py_INCREF(Py_None);
7241 result = Py_None;
7242 }
7243
7244 CloseHandle(handle);
7245 return result;
7246 }
7247 #endif /* !MS_WINDOWS */
7248 #endif /* HAVE_KILL */
7249
7250
7251 #ifdef HAVE_KILLPG
7252 /*[clinic input]
7253 os.killpg
7254
7255 pgid: pid_t
7256 signal: int
7257 /
7258
7259 Kill a process group with a signal.
7260 [clinic start generated code]*/
7261
7262 static PyObject *
os_killpg_impl(PyObject * module,pid_t pgid,int signal)7263 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
7264 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
7265 {
7266 /* XXX some man pages make the `pgid` parameter an int, others
7267 a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
7268 take the same type. Moreover, pid_t is always at least as wide as
7269 int (else compilation of this module fails), which is safe. */
7270 if (killpg(pgid, signal) == -1)
7271 return posix_error();
7272 Py_RETURN_NONE;
7273 }
7274 #endif /* HAVE_KILLPG */
7275
7276
7277 #ifdef HAVE_PLOCK
7278 #ifdef HAVE_SYS_LOCK_H
7279 #include <sys/lock.h>
7280 #endif
7281
7282 /*[clinic input]
7283 os.plock
7284 op: int
7285 /
7286
7287 Lock program segments into memory.");
7288 [clinic start generated code]*/
7289
7290 static PyObject *
os_plock_impl(PyObject * module,int op)7291 os_plock_impl(PyObject *module, int op)
7292 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
7293 {
7294 if (plock(op) == -1)
7295 return posix_error();
7296 Py_RETURN_NONE;
7297 }
7298 #endif /* HAVE_PLOCK */
7299
7300
7301 #ifdef HAVE_SETUID
7302 /*[clinic input]
7303 os.setuid
7304
7305 uid: uid_t
7306 /
7307
7308 Set the current process's user id.
7309 [clinic start generated code]*/
7310
7311 static PyObject *
os_setuid_impl(PyObject * module,uid_t uid)7312 os_setuid_impl(PyObject *module, uid_t uid)
7313 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
7314 {
7315 if (setuid(uid) < 0)
7316 return posix_error();
7317 Py_RETURN_NONE;
7318 }
7319 #endif /* HAVE_SETUID */
7320
7321
7322 #ifdef HAVE_SETEUID
7323 /*[clinic input]
7324 os.seteuid
7325
7326 euid: uid_t
7327 /
7328
7329 Set the current process's effective user id.
7330 [clinic start generated code]*/
7331
7332 static PyObject *
os_seteuid_impl(PyObject * module,uid_t euid)7333 os_seteuid_impl(PyObject *module, uid_t euid)
7334 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
7335 {
7336 if (seteuid(euid) < 0)
7337 return posix_error();
7338 Py_RETURN_NONE;
7339 }
7340 #endif /* HAVE_SETEUID */
7341
7342
7343 #ifdef HAVE_SETEGID
7344 /*[clinic input]
7345 os.setegid
7346
7347 egid: gid_t
7348 /
7349
7350 Set the current process's effective group id.
7351 [clinic start generated code]*/
7352
7353 static PyObject *
os_setegid_impl(PyObject * module,gid_t egid)7354 os_setegid_impl(PyObject *module, gid_t egid)
7355 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
7356 {
7357 if (setegid(egid) < 0)
7358 return posix_error();
7359 Py_RETURN_NONE;
7360 }
7361 #endif /* HAVE_SETEGID */
7362
7363
7364 #ifdef HAVE_SETREUID
7365 /*[clinic input]
7366 os.setreuid
7367
7368 ruid: uid_t
7369 euid: uid_t
7370 /
7371
7372 Set the current process's real and effective user ids.
7373 [clinic start generated code]*/
7374
7375 static PyObject *
os_setreuid_impl(PyObject * module,uid_t ruid,uid_t euid)7376 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
7377 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
7378 {
7379 if (setreuid(ruid, euid) < 0) {
7380 return posix_error();
7381 } else {
7382 Py_RETURN_NONE;
7383 }
7384 }
7385 #endif /* HAVE_SETREUID */
7386
7387
7388 #ifdef HAVE_SETREGID
7389 /*[clinic input]
7390 os.setregid
7391
7392 rgid: gid_t
7393 egid: gid_t
7394 /
7395
7396 Set the current process's real and effective group ids.
7397 [clinic start generated code]*/
7398
7399 static PyObject *
os_setregid_impl(PyObject * module,gid_t rgid,gid_t egid)7400 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
7401 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
7402 {
7403 if (setregid(rgid, egid) < 0)
7404 return posix_error();
7405 Py_RETURN_NONE;
7406 }
7407 #endif /* HAVE_SETREGID */
7408
7409
7410 #ifdef HAVE_SETGID
7411 /*[clinic input]
7412 os.setgid
7413 gid: gid_t
7414 /
7415
7416 Set the current process's group id.
7417 [clinic start generated code]*/
7418
7419 static PyObject *
os_setgid_impl(PyObject * module,gid_t gid)7420 os_setgid_impl(PyObject *module, gid_t gid)
7421 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
7422 {
7423 if (setgid(gid) < 0)
7424 return posix_error();
7425 Py_RETURN_NONE;
7426 }
7427 #endif /* HAVE_SETGID */
7428
7429
7430 #ifdef HAVE_SETGROUPS
7431 /*[clinic input]
7432 os.setgroups
7433
7434 groups: object
7435 /
7436
7437 Set the groups of the current process to list.
7438 [clinic start generated code]*/
7439
7440 static PyObject *
os_setgroups(PyObject * module,PyObject * groups)7441 os_setgroups(PyObject *module, PyObject *groups)
7442 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
7443 {
7444 Py_ssize_t i, len;
7445 gid_t grouplist[MAX_GROUPS];
7446
7447 if (!PySequence_Check(groups)) {
7448 PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
7449 return NULL;
7450 }
7451 len = PySequence_Size(groups);
7452 if (len < 0) {
7453 return NULL;
7454 }
7455 if (len > MAX_GROUPS) {
7456 PyErr_SetString(PyExc_ValueError, "too many groups");
7457 return NULL;
7458 }
7459 for(i = 0; i < len; i++) {
7460 PyObject *elem;
7461 elem = PySequence_GetItem(groups, i);
7462 if (!elem)
7463 return NULL;
7464 if (!PyLong_Check(elem)) {
7465 PyErr_SetString(PyExc_TypeError,
7466 "groups must be integers");
7467 Py_DECREF(elem);
7468 return NULL;
7469 } else {
7470 if (!_Py_Gid_Converter(elem, &grouplist[i])) {
7471 Py_DECREF(elem);
7472 return NULL;
7473 }
7474 }
7475 Py_DECREF(elem);
7476 }
7477
7478 if (setgroups(len, grouplist) < 0)
7479 return posix_error();
7480 Py_RETURN_NONE;
7481 }
7482 #endif /* HAVE_SETGROUPS */
7483
7484 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
7485 static PyObject *
wait_helper(pid_t pid,int status,struct rusage * ru)7486 wait_helper(pid_t pid, int status, struct rusage *ru)
7487 {
7488 PyObject *result;
7489 static PyObject *struct_rusage;
7490 _Py_IDENTIFIER(struct_rusage);
7491
7492 if (pid == -1)
7493 return posix_error();
7494
7495 if (struct_rusage == NULL) {
7496 PyObject *m = PyImport_ImportModuleNoBlock("resource");
7497 if (m == NULL)
7498 return NULL;
7499 struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage);
7500 Py_DECREF(m);
7501 if (struct_rusage == NULL)
7502 return NULL;
7503 }
7504
7505 /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
7506 result = PyStructSequence_New((PyTypeObject*) struct_rusage);
7507 if (!result)
7508 return NULL;
7509
7510 #ifndef doubletime
7511 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
7512 #endif
7513
7514 PyStructSequence_SET_ITEM(result, 0,
7515 PyFloat_FromDouble(doubletime(ru->ru_utime)));
7516 PyStructSequence_SET_ITEM(result, 1,
7517 PyFloat_FromDouble(doubletime(ru->ru_stime)));
7518 #define SET_INT(result, index, value)\
7519 PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
7520 SET_INT(result, 2, ru->ru_maxrss);
7521 SET_INT(result, 3, ru->ru_ixrss);
7522 SET_INT(result, 4, ru->ru_idrss);
7523 SET_INT(result, 5, ru->ru_isrss);
7524 SET_INT(result, 6, ru->ru_minflt);
7525 SET_INT(result, 7, ru->ru_majflt);
7526 SET_INT(result, 8, ru->ru_nswap);
7527 SET_INT(result, 9, ru->ru_inblock);
7528 SET_INT(result, 10, ru->ru_oublock);
7529 SET_INT(result, 11, ru->ru_msgsnd);
7530 SET_INT(result, 12, ru->ru_msgrcv);
7531 SET_INT(result, 13, ru->ru_nsignals);
7532 SET_INT(result, 14, ru->ru_nvcsw);
7533 SET_INT(result, 15, ru->ru_nivcsw);
7534 #undef SET_INT
7535
7536 if (PyErr_Occurred()) {
7537 Py_DECREF(result);
7538 return NULL;
7539 }
7540
7541 return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
7542 }
7543 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
7544
7545
7546 #ifdef HAVE_WAIT3
7547 /*[clinic input]
7548 os.wait3
7549
7550 options: int
7551 Wait for completion of a child process.
7552
7553 Returns a tuple of information about the child process:
7554 (pid, status, rusage)
7555 [clinic start generated code]*/
7556
7557 static PyObject *
os_wait3_impl(PyObject * module,int options)7558 os_wait3_impl(PyObject *module, int options)
7559 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
7560 {
7561 pid_t pid;
7562 struct rusage ru;
7563 int async_err = 0;
7564 WAIT_TYPE status;
7565 WAIT_STATUS_INT(status) = 0;
7566
7567 do {
7568 Py_BEGIN_ALLOW_THREADS
7569 pid = wait3(&status, options, &ru);
7570 Py_END_ALLOW_THREADS
7571 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7572 if (pid < 0)
7573 return (!async_err) ? posix_error() : NULL;
7574
7575 return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
7576 }
7577 #endif /* HAVE_WAIT3 */
7578
7579
7580 #ifdef HAVE_WAIT4
7581 /*[clinic input]
7582
7583 os.wait4
7584
7585 pid: pid_t
7586 options: int
7587
7588 Wait for completion of a specific child process.
7589
7590 Returns a tuple of information about the child process:
7591 (pid, status, rusage)
7592 [clinic start generated code]*/
7593
7594 static PyObject *
os_wait4_impl(PyObject * module,pid_t pid,int options)7595 os_wait4_impl(PyObject *module, pid_t pid, int options)
7596 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
7597 {
7598 pid_t res;
7599 struct rusage ru;
7600 int async_err = 0;
7601 WAIT_TYPE status;
7602 WAIT_STATUS_INT(status) = 0;
7603
7604 do {
7605 Py_BEGIN_ALLOW_THREADS
7606 res = wait4(pid, &status, options, &ru);
7607 Py_END_ALLOW_THREADS
7608 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7609 if (res < 0)
7610 return (!async_err) ? posix_error() : NULL;
7611
7612 return wait_helper(res, WAIT_STATUS_INT(status), &ru);
7613 }
7614 #endif /* HAVE_WAIT4 */
7615
7616
7617 #if defined(HAVE_WAITID) && !defined(__APPLE__)
7618 /*[clinic input]
7619 os.waitid
7620
7621 idtype: idtype_t
7622 Must be one of be P_PID, P_PGID or P_ALL.
7623 id: id_t
7624 The id to wait on.
7625 options: int
7626 Constructed from the ORing of one or more of WEXITED, WSTOPPED
7627 or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
7628 /
7629
7630 Returns the result of waiting for a process or processes.
7631
7632 Returns either waitid_result or None if WNOHANG is specified and there are
7633 no children in a waitable state.
7634 [clinic start generated code]*/
7635
7636 static PyObject *
os_waitid_impl(PyObject * module,idtype_t idtype,id_t id,int options)7637 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
7638 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
7639 {
7640 PyObject *result;
7641 int res;
7642 int async_err = 0;
7643 siginfo_t si;
7644 si.si_pid = 0;
7645
7646 do {
7647 Py_BEGIN_ALLOW_THREADS
7648 res = waitid(idtype, id, &si, options);
7649 Py_END_ALLOW_THREADS
7650 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7651 if (res < 0)
7652 return (!async_err) ? posix_error() : NULL;
7653
7654 if (si.si_pid == 0)
7655 Py_RETURN_NONE;
7656
7657 result = PyStructSequence_New(WaitidResultType);
7658 if (!result)
7659 return NULL;
7660
7661 PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
7662 PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
7663 PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
7664 PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
7665 PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
7666 if (PyErr_Occurred()) {
7667 Py_DECREF(result);
7668 return NULL;
7669 }
7670
7671 return result;
7672 }
7673 #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
7674
7675
7676 #if defined(HAVE_WAITPID)
7677 /*[clinic input]
7678 os.waitpid
7679 pid: pid_t
7680 options: int
7681 /
7682
7683 Wait for completion of a given child process.
7684
7685 Returns a tuple of information regarding the child process:
7686 (pid, status)
7687
7688 The options argument is ignored on Windows.
7689 [clinic start generated code]*/
7690
7691 static PyObject *
os_waitpid_impl(PyObject * module,pid_t pid,int options)7692 os_waitpid_impl(PyObject *module, pid_t pid, int options)
7693 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
7694 {
7695 pid_t res;
7696 int async_err = 0;
7697 WAIT_TYPE status;
7698 WAIT_STATUS_INT(status) = 0;
7699
7700 do {
7701 Py_BEGIN_ALLOW_THREADS
7702 res = waitpid(pid, &status, options);
7703 Py_END_ALLOW_THREADS
7704 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7705 if (res < 0)
7706 return (!async_err) ? posix_error() : NULL;
7707
7708 return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
7709 }
7710 #elif defined(HAVE_CWAIT)
7711 /* MS C has a variant of waitpid() that's usable for most purposes. */
7712 /*[clinic input]
7713 os.waitpid
7714 pid: intptr_t
7715 options: int
7716 /
7717
7718 Wait for completion of a given process.
7719
7720 Returns a tuple of information regarding the process:
7721 (pid, status << 8)
7722
7723 The options argument is ignored on Windows.
7724 [clinic start generated code]*/
7725
7726 static PyObject *
os_waitpid_impl(PyObject * module,intptr_t pid,int options)7727 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
7728 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
7729 {
7730 int status;
7731 intptr_t res;
7732 int async_err = 0;
7733
7734 do {
7735 Py_BEGIN_ALLOW_THREADS
7736 _Py_BEGIN_SUPPRESS_IPH
7737 res = _cwait(&status, pid, options);
7738 _Py_END_SUPPRESS_IPH
7739 Py_END_ALLOW_THREADS
7740 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7741 if (res < 0)
7742 return (!async_err) ? posix_error() : NULL;
7743
7744 /* shift the status left a byte so this is more like the POSIX waitpid */
7745 return Py_BuildValue(_Py_PARSE_INTPTR "i", res, status << 8);
7746 }
7747 #endif
7748
7749
7750 #ifdef HAVE_WAIT
7751 /*[clinic input]
7752 os.wait
7753
7754 Wait for completion of a child process.
7755
7756 Returns a tuple of information about the child process:
7757 (pid, status)
7758 [clinic start generated code]*/
7759
7760 static PyObject *
os_wait_impl(PyObject * module)7761 os_wait_impl(PyObject *module)
7762 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
7763 {
7764 pid_t pid;
7765 int async_err = 0;
7766 WAIT_TYPE status;
7767 WAIT_STATUS_INT(status) = 0;
7768
7769 do {
7770 Py_BEGIN_ALLOW_THREADS
7771 pid = wait(&status);
7772 Py_END_ALLOW_THREADS
7773 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7774 if (pid < 0)
7775 return (!async_err) ? posix_error() : NULL;
7776
7777 return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
7778 }
7779 #endif /* HAVE_WAIT */
7780
7781
7782 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
7783 /*[clinic input]
7784 os.readlink
7785
7786 path: path_t
7787 *
7788 dir_fd: dir_fd(requires='readlinkat') = None
7789
7790 Return a string representing the path to which the symbolic link points.
7791
7792 If dir_fd is not None, it should be a file descriptor open to a directory,
7793 and path should be relative; path will then be relative to that directory.
7794
7795 dir_fd may not be implemented on your platform. If it is unavailable,
7796 using it will raise a NotImplementedError.
7797 [clinic start generated code]*/
7798
7799 static PyObject *
os_readlink_impl(PyObject * module,path_t * path,int dir_fd)7800 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
7801 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
7802 {
7803 #if defined(HAVE_READLINK)
7804 char buffer[MAXPATHLEN+1];
7805 ssize_t length;
7806
7807 Py_BEGIN_ALLOW_THREADS
7808 #ifdef HAVE_READLINKAT
7809 if (dir_fd != DEFAULT_DIR_FD)
7810 length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
7811 else
7812 #endif
7813 length = readlink(path->narrow, buffer, MAXPATHLEN);
7814 Py_END_ALLOW_THREADS
7815
7816 if (length < 0) {
7817 return path_error(path);
7818 }
7819 buffer[length] = '\0';
7820
7821 if (PyUnicode_Check(path->object))
7822 return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
7823 else
7824 return PyBytes_FromStringAndSize(buffer, length);
7825 #elif defined(MS_WINDOWS)
7826 DWORD n_bytes_returned;
7827 DWORD io_result = 0;
7828 HANDLE reparse_point_handle;
7829 char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
7830 _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
7831 PyObject *result = NULL;
7832
7833 /* First get a handle to the reparse point */
7834 Py_BEGIN_ALLOW_THREADS
7835 reparse_point_handle = CreateFileW(
7836 path->wide,
7837 0,
7838 0,
7839 0,
7840 OPEN_EXISTING,
7841 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
7842 0);
7843 if (reparse_point_handle != INVALID_HANDLE_VALUE) {
7844 /* New call DeviceIoControl to read the reparse point */
7845 io_result = DeviceIoControl(
7846 reparse_point_handle,
7847 FSCTL_GET_REPARSE_POINT,
7848 0, 0, /* in buffer */
7849 target_buffer, sizeof(target_buffer),
7850 &n_bytes_returned,
7851 0 /* we're not using OVERLAPPED_IO */
7852 );
7853 CloseHandle(reparse_point_handle);
7854 }
7855 Py_END_ALLOW_THREADS
7856
7857 if (io_result == 0) {
7858 return path_error(path);
7859 }
7860
7861 wchar_t *name = NULL;
7862 Py_ssize_t nameLen = 0;
7863 if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
7864 {
7865 name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
7866 rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
7867 nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
7868 }
7869 else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
7870 {
7871 name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
7872 rdb->MountPointReparseBuffer.SubstituteNameOffset);
7873 nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
7874 }
7875 else
7876 {
7877 PyErr_SetString(PyExc_ValueError, "not a symbolic link");
7878 }
7879 if (name) {
7880 if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
7881 /* Our buffer is mutable, so this is okay */
7882 name[1] = L'\\';
7883 }
7884 result = PyUnicode_FromWideChar(name, nameLen);
7885 if (result && path->narrow) {
7886 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
7887 }
7888 }
7889 return result;
7890 #endif
7891 }
7892 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
7893
7894 #ifdef HAVE_SYMLINK
7895
7896 #if defined(MS_WINDOWS)
7897
7898 /* Remove the last portion of the path - return 0 on success */
7899 static int
_dirnameW(WCHAR * path)7900 _dirnameW(WCHAR *path)
7901 {
7902 WCHAR *ptr;
7903 size_t length = wcsnlen_s(path, MAX_PATH);
7904 if (length == MAX_PATH) {
7905 return -1;
7906 }
7907
7908 /* walk the path from the end until a backslash is encountered */
7909 for(ptr = path + length; ptr != path; ptr--) {
7910 if (*ptr == L'\\' || *ptr == L'/') {
7911 break;
7912 }
7913 }
7914 *ptr = 0;
7915 return 0;
7916 }
7917
7918 /* Is this path absolute? */
7919 static int
_is_absW(const WCHAR * path)7920 _is_absW(const WCHAR *path)
7921 {
7922 return path[0] == L'\\' || path[0] == L'/' ||
7923 (path[0] && path[1] == L':');
7924 }
7925
7926 /* join root and rest with a backslash - return 0 on success */
7927 static int
_joinW(WCHAR * dest_path,const WCHAR * root,const WCHAR * rest)7928 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
7929 {
7930 if (_is_absW(rest)) {
7931 return wcscpy_s(dest_path, MAX_PATH, rest);
7932 }
7933
7934 if (wcscpy_s(dest_path, MAX_PATH, root)) {
7935 return -1;
7936 }
7937
7938 if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
7939 return -1;
7940 }
7941
7942 return wcscat_s(dest_path, MAX_PATH, rest);
7943 }
7944
7945 /* Return True if the path at src relative to dest is a directory */
7946 static int
_check_dirW(LPCWSTR src,LPCWSTR dest)7947 _check_dirW(LPCWSTR src, LPCWSTR dest)
7948 {
7949 WIN32_FILE_ATTRIBUTE_DATA src_info;
7950 WCHAR dest_parent[MAX_PATH];
7951 WCHAR src_resolved[MAX_PATH] = L"";
7952
7953 /* dest_parent = os.path.dirname(dest) */
7954 if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
7955 _dirnameW(dest_parent)) {
7956 return 0;
7957 }
7958 /* src_resolved = os.path.join(dest_parent, src) */
7959 if (_joinW(src_resolved, dest_parent, src)) {
7960 return 0;
7961 }
7962 return (
7963 GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
7964 && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
7965 );
7966 }
7967 #endif
7968
7969
7970 /*[clinic input]
7971 os.symlink
7972 src: path_t
7973 dst: path_t
7974 target_is_directory: bool = False
7975 *
7976 dir_fd: dir_fd(requires='symlinkat')=None
7977
7978 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
7979
7980 Create a symbolic link pointing to src named dst.
7981
7982 target_is_directory is required on Windows if the target is to be
7983 interpreted as a directory. (On Windows, symlink requires
7984 Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
7985 target_is_directory is ignored on non-Windows platforms.
7986
7987 If dir_fd is not None, it should be a file descriptor open to a directory,
7988 and path should be relative; path will then be relative to that directory.
7989 dir_fd may not be implemented on your platform.
7990 If it is unavailable, using it will raise a NotImplementedError.
7991
7992 [clinic start generated code]*/
7993
7994 static PyObject *
os_symlink_impl(PyObject * module,path_t * src,path_t * dst,int target_is_directory,int dir_fd)7995 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
7996 int target_is_directory, int dir_fd)
7997 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
7998 {
7999 #ifdef MS_WINDOWS
8000 DWORD result;
8001 DWORD flags = 0;
8002
8003 /* Assumed true, set to false if detected to not be available. */
8004 static int windows_has_symlink_unprivileged_flag = TRUE;
8005 #else
8006 int result;
8007 #endif
8008
8009 #ifdef MS_WINDOWS
8010
8011 if (windows_has_symlink_unprivileged_flag) {
8012 /* Allow non-admin symlinks if system allows it. */
8013 flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8014 }
8015
8016 Py_BEGIN_ALLOW_THREADS
8017 _Py_BEGIN_SUPPRESS_IPH
8018 /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8019 if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8020 flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8021 }
8022
8023 result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8024 _Py_END_SUPPRESS_IPH
8025 Py_END_ALLOW_THREADS
8026
8027 if (windows_has_symlink_unprivileged_flag && !result &&
8028 ERROR_INVALID_PARAMETER == GetLastError()) {
8029
8030 Py_BEGIN_ALLOW_THREADS
8031 _Py_BEGIN_SUPPRESS_IPH
8032 /* This error might be caused by
8033 SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8034 Try again, and update windows_has_symlink_unprivileged_flag if we
8035 are successful this time.
8036
8037 NOTE: There is a risk of a race condition here if there are other
8038 conditions than the flag causing ERROR_INVALID_PARAMETER, and
8039 another process (or thread) changes that condition in between our
8040 calls to CreateSymbolicLink.
8041 */
8042 flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8043 result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8044 _Py_END_SUPPRESS_IPH
8045 Py_END_ALLOW_THREADS
8046
8047 if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8048 windows_has_symlink_unprivileged_flag = FALSE;
8049 }
8050 }
8051
8052 if (!result)
8053 return path_error2(src, dst);
8054
8055 #else
8056
8057 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8058 PyErr_SetString(PyExc_ValueError,
8059 "symlink: src and dst must be the same type");
8060 return NULL;
8061 }
8062
8063 Py_BEGIN_ALLOW_THREADS
8064 #if HAVE_SYMLINKAT
8065 if (dir_fd != DEFAULT_DIR_FD)
8066 result = symlinkat(src->narrow, dir_fd, dst->narrow);
8067 else
8068 #endif
8069 result = symlink(src->narrow, dst->narrow);
8070 Py_END_ALLOW_THREADS
8071
8072 if (result)
8073 return path_error2(src, dst);
8074 #endif
8075
8076 Py_RETURN_NONE;
8077 }
8078 #endif /* HAVE_SYMLINK */
8079
8080
8081
8082
8083 static PyStructSequence_Field times_result_fields[] = {
8084 {"user", "user time"},
8085 {"system", "system time"},
8086 {"children_user", "user time of children"},
8087 {"children_system", "system time of children"},
8088 {"elapsed", "elapsed time since an arbitrary point in the past"},
8089 {NULL}
8090 };
8091
8092 PyDoc_STRVAR(times_result__doc__,
8093 "times_result: Result from os.times().\n\n\
8094 This object may be accessed either as a tuple of\n\
8095 (user, system, children_user, children_system, elapsed),\n\
8096 or via the attributes user, system, children_user, children_system,\n\
8097 and elapsed.\n\
8098 \n\
8099 See os.times for more information.");
8100
8101 static PyStructSequence_Desc times_result_desc = {
8102 "times_result", /* name */
8103 times_result__doc__, /* doc */
8104 times_result_fields,
8105 5
8106 };
8107
8108 static PyTypeObject* TimesResultType;
8109
8110 #ifdef MS_WINDOWS
8111 #define HAVE_TIMES /* mandatory, for the method table */
8112 #endif
8113
8114 #ifdef HAVE_TIMES
8115
8116 static PyObject *
build_times_result(double user,double system,double children_user,double children_system,double elapsed)8117 build_times_result(double user, double system,
8118 double children_user, double children_system,
8119 double elapsed)
8120 {
8121 PyObject *value = PyStructSequence_New(TimesResultType);
8122 if (value == NULL)
8123 return NULL;
8124
8125 #define SET(i, field) \
8126 { \
8127 PyObject *o = PyFloat_FromDouble(field); \
8128 if (!o) { \
8129 Py_DECREF(value); \
8130 return NULL; \
8131 } \
8132 PyStructSequence_SET_ITEM(value, i, o); \
8133 } \
8134
8135 SET(0, user);
8136 SET(1, system);
8137 SET(2, children_user);
8138 SET(3, children_system);
8139 SET(4, elapsed);
8140
8141 #undef SET
8142
8143 return value;
8144 }
8145
8146
8147 #ifndef MS_WINDOWS
8148 #define NEED_TICKS_PER_SECOND
8149 static long ticks_per_second = -1;
8150 #endif /* MS_WINDOWS */
8151
8152 /*[clinic input]
8153 os.times
8154
8155 Return a collection containing process timing information.
8156
8157 The object returned behaves like a named tuple with these fields:
8158 (utime, stime, cutime, cstime, elapsed_time)
8159 All fields are floating point numbers.
8160 [clinic start generated code]*/
8161
8162 static PyObject *
os_times_impl(PyObject * module)8163 os_times_impl(PyObject *module)
8164 /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
8165 #ifdef MS_WINDOWS
8166 {
8167 FILETIME create, exit, kernel, user;
8168 HANDLE hProc;
8169 hProc = GetCurrentProcess();
8170 GetProcessTimes(hProc, &create, &exit, &kernel, &user);
8171 /* The fields of a FILETIME structure are the hi and lo part
8172 of a 64-bit value expressed in 100 nanosecond units.
8173 1e7 is one second in such units; 1e-7 the inverse.
8174 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
8175 */
8176 return build_times_result(
8177 (double)(user.dwHighDateTime*429.4967296 +
8178 user.dwLowDateTime*1e-7),
8179 (double)(kernel.dwHighDateTime*429.4967296 +
8180 kernel.dwLowDateTime*1e-7),
8181 (double)0,
8182 (double)0,
8183 (double)0);
8184 }
8185 #else /* MS_WINDOWS */
8186 {
8187
8188
8189 struct tms t;
8190 clock_t c;
8191 errno = 0;
8192 c = times(&t);
8193 if (c == (clock_t) -1)
8194 return posix_error();
8195 return build_times_result(
8196 (double)t.tms_utime / ticks_per_second,
8197 (double)t.tms_stime / ticks_per_second,
8198 (double)t.tms_cutime / ticks_per_second,
8199 (double)t.tms_cstime / ticks_per_second,
8200 (double)c / ticks_per_second);
8201 }
8202 #endif /* MS_WINDOWS */
8203 #endif /* HAVE_TIMES */
8204
8205
8206 #ifdef HAVE_GETSID
8207 /*[clinic input]
8208 os.getsid
8209
8210 pid: pid_t
8211 /
8212
8213 Call the system call getsid(pid) and return the result.
8214 [clinic start generated code]*/
8215
8216 static PyObject *
os_getsid_impl(PyObject * module,pid_t pid)8217 os_getsid_impl(PyObject *module, pid_t pid)
8218 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
8219 {
8220 int sid;
8221 sid = getsid(pid);
8222 if (sid < 0)
8223 return posix_error();
8224 return PyLong_FromLong((long)sid);
8225 }
8226 #endif /* HAVE_GETSID */
8227
8228
8229 #ifdef HAVE_SETSID
8230 /*[clinic input]
8231 os.setsid
8232
8233 Call the system call setsid().
8234 [clinic start generated code]*/
8235
8236 static PyObject *
os_setsid_impl(PyObject * module)8237 os_setsid_impl(PyObject *module)
8238 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
8239 {
8240 if (setsid() < 0)
8241 return posix_error();
8242 Py_RETURN_NONE;
8243 }
8244 #endif /* HAVE_SETSID */
8245
8246
8247 #ifdef HAVE_SETPGID
8248 /*[clinic input]
8249 os.setpgid
8250
8251 pid: pid_t
8252 pgrp: pid_t
8253 /
8254
8255 Call the system call setpgid(pid, pgrp).
8256 [clinic start generated code]*/
8257
8258 static PyObject *
os_setpgid_impl(PyObject * module,pid_t pid,pid_t pgrp)8259 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
8260 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
8261 {
8262 if (setpgid(pid, pgrp) < 0)
8263 return posix_error();
8264 Py_RETURN_NONE;
8265 }
8266 #endif /* HAVE_SETPGID */
8267
8268
8269 #ifdef HAVE_TCGETPGRP
8270 /*[clinic input]
8271 os.tcgetpgrp
8272
8273 fd: int
8274 /
8275
8276 Return the process group associated with the terminal specified by fd.
8277 [clinic start generated code]*/
8278
8279 static PyObject *
os_tcgetpgrp_impl(PyObject * module,int fd)8280 os_tcgetpgrp_impl(PyObject *module, int fd)
8281 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
8282 {
8283 pid_t pgid = tcgetpgrp(fd);
8284 if (pgid < 0)
8285 return posix_error();
8286 return PyLong_FromPid(pgid);
8287 }
8288 #endif /* HAVE_TCGETPGRP */
8289
8290
8291 #ifdef HAVE_TCSETPGRP
8292 /*[clinic input]
8293 os.tcsetpgrp
8294
8295 fd: int
8296 pgid: pid_t
8297 /
8298
8299 Set the process group associated with the terminal specified by fd.
8300 [clinic start generated code]*/
8301
8302 static PyObject *
os_tcsetpgrp_impl(PyObject * module,int fd,pid_t pgid)8303 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
8304 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
8305 {
8306 if (tcsetpgrp(fd, pgid) < 0)
8307 return posix_error();
8308 Py_RETURN_NONE;
8309 }
8310 #endif /* HAVE_TCSETPGRP */
8311
8312 /* Functions acting on file descriptors */
8313
8314 #ifdef O_CLOEXEC
8315 extern int _Py_open_cloexec_works;
8316 #endif
8317
8318
8319 /*[clinic input]
8320 os.open -> int
8321 path: path_t
8322 flags: int
8323 mode: int = 0o777
8324 *
8325 dir_fd: dir_fd(requires='openat') = None
8326
8327 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
8328
8329 Open a file for low level IO. Returns a file descriptor (integer).
8330
8331 If dir_fd is not None, it should be a file descriptor open to a directory,
8332 and path should be relative; path will then be relative to that directory.
8333 dir_fd may not be implemented on your platform.
8334 If it is unavailable, using it will raise a NotImplementedError.
8335 [clinic start generated code]*/
8336
8337 static int
os_open_impl(PyObject * module,path_t * path,int flags,int mode,int dir_fd)8338 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
8339 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
8340 {
8341 int fd;
8342 int async_err = 0;
8343
8344 #ifdef O_CLOEXEC
8345 int *atomic_flag_works = &_Py_open_cloexec_works;
8346 #elif !defined(MS_WINDOWS)
8347 int *atomic_flag_works = NULL;
8348 #endif
8349
8350 #ifdef MS_WINDOWS
8351 flags |= O_NOINHERIT;
8352 #elif defined(O_CLOEXEC)
8353 flags |= O_CLOEXEC;
8354 #endif
8355
8356 if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
8357 return -1;
8358 }
8359
8360 _Py_BEGIN_SUPPRESS_IPH
8361 do {
8362 Py_BEGIN_ALLOW_THREADS
8363 #ifdef MS_WINDOWS
8364 fd = _wopen(path->wide, flags, mode);
8365 #else
8366 #ifdef HAVE_OPENAT
8367 if (dir_fd != DEFAULT_DIR_FD)
8368 fd = openat(dir_fd, path->narrow, flags, mode);
8369 else
8370 #endif /* HAVE_OPENAT */
8371 fd = open(path->narrow, flags, mode);
8372 #endif /* !MS_WINDOWS */
8373 Py_END_ALLOW_THREADS
8374 } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8375 _Py_END_SUPPRESS_IPH
8376
8377 if (fd < 0) {
8378 if (!async_err)
8379 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
8380 return -1;
8381 }
8382
8383 #ifndef MS_WINDOWS
8384 if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
8385 close(fd);
8386 return -1;
8387 }
8388 #endif
8389
8390 return fd;
8391 }
8392
8393
8394 /*[clinic input]
8395 os.close
8396
8397 fd: int
8398
8399 Close a file descriptor.
8400 [clinic start generated code]*/
8401
8402 static PyObject *
os_close_impl(PyObject * module,int fd)8403 os_close_impl(PyObject *module, int fd)
8404 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
8405 {
8406 int res;
8407 /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
8408 * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
8409 * for more details.
8410 */
8411 Py_BEGIN_ALLOW_THREADS
8412 _Py_BEGIN_SUPPRESS_IPH
8413 res = close(fd);
8414 _Py_END_SUPPRESS_IPH
8415 Py_END_ALLOW_THREADS
8416 if (res < 0)
8417 return posix_error();
8418 Py_RETURN_NONE;
8419 }
8420
8421
8422 #ifdef HAVE_FDWALK
8423 static int
_fdwalk_close_func(void * lohi,int fd)8424 _fdwalk_close_func(void *lohi, int fd)
8425 {
8426 int lo = ((int *)lohi)[0];
8427 int hi = ((int *)lohi)[1];
8428
8429 if (fd >= hi)
8430 return 1;
8431 else if (fd >= lo)
8432 close(fd);
8433 return 0;
8434 }
8435 #endif /* HAVE_FDWALK */
8436
8437 /*[clinic input]
8438 os.closerange
8439
8440 fd_low: int
8441 fd_high: int
8442 /
8443
8444 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
8445 [clinic start generated code]*/
8446
8447 static PyObject *
os_closerange_impl(PyObject * module,int fd_low,int fd_high)8448 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
8449 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
8450 {
8451 #ifdef HAVE_FDWALK
8452 int lohi[2];
8453 #else
8454 int i;
8455 #endif
8456 Py_BEGIN_ALLOW_THREADS
8457 _Py_BEGIN_SUPPRESS_IPH
8458 #ifdef HAVE_FDWALK
8459 lohi[0] = Py_MAX(fd_low, 0);
8460 lohi[1] = fd_high;
8461 fdwalk(_fdwalk_close_func, lohi);
8462 #else
8463 for (i = Py_MAX(fd_low, 0); i < fd_high; i++)
8464 close(i);
8465 #endif
8466 _Py_END_SUPPRESS_IPH
8467 Py_END_ALLOW_THREADS
8468 Py_RETURN_NONE;
8469 }
8470
8471
8472 /*[clinic input]
8473 os.dup -> int
8474
8475 fd: int
8476 /
8477
8478 Return a duplicate of a file descriptor.
8479 [clinic start generated code]*/
8480
8481 static int
os_dup_impl(PyObject * module,int fd)8482 os_dup_impl(PyObject *module, int fd)
8483 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
8484 {
8485 return _Py_dup(fd);
8486 }
8487
8488
8489 /*[clinic input]
8490 os.dup2 -> int
8491 fd: int
8492 fd2: int
8493 inheritable: bool=True
8494
8495 Duplicate file descriptor.
8496 [clinic start generated code]*/
8497
8498 static int
os_dup2_impl(PyObject * module,int fd,int fd2,int inheritable)8499 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
8500 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
8501 {
8502 int res = 0;
8503 #if defined(HAVE_DUP3) && \
8504 !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
8505 /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
8506 static int dup3_works = -1;
8507 #endif
8508
8509 if (fd < 0 || fd2 < 0) {
8510 posix_error();
8511 return -1;
8512 }
8513
8514 /* dup2() can fail with EINTR if the target FD is already open, because it
8515 * then has to be closed. See os_close_impl() for why we don't handle EINTR
8516 * upon close(), and therefore below.
8517 */
8518 #ifdef MS_WINDOWS
8519 Py_BEGIN_ALLOW_THREADS
8520 _Py_BEGIN_SUPPRESS_IPH
8521 res = dup2(fd, fd2);
8522 _Py_END_SUPPRESS_IPH
8523 Py_END_ALLOW_THREADS
8524 if (res < 0) {
8525 posix_error();
8526 return -1;
8527 }
8528 res = fd2; // msvcrt dup2 returns 0 on success.
8529
8530 /* Character files like console cannot be make non-inheritable */
8531 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
8532 close(fd2);
8533 return -1;
8534 }
8535
8536 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
8537 Py_BEGIN_ALLOW_THREADS
8538 if (!inheritable)
8539 res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
8540 else
8541 res = dup2(fd, fd2);
8542 Py_END_ALLOW_THREADS
8543 if (res < 0) {
8544 posix_error();
8545 return -1;
8546 }
8547
8548 #else
8549
8550 #ifdef HAVE_DUP3
8551 if (!inheritable && dup3_works != 0) {
8552 Py_BEGIN_ALLOW_THREADS
8553 res = dup3(fd, fd2, O_CLOEXEC);
8554 Py_END_ALLOW_THREADS
8555 if (res < 0) {
8556 if (dup3_works == -1)
8557 dup3_works = (errno != ENOSYS);
8558 if (dup3_works) {
8559 posix_error();
8560 return -1;
8561 }
8562 }
8563 }
8564
8565 if (inheritable || dup3_works == 0)
8566 {
8567 #endif
8568 Py_BEGIN_ALLOW_THREADS
8569 res = dup2(fd, fd2);
8570 Py_END_ALLOW_THREADS
8571 if (res < 0) {
8572 posix_error();
8573 return -1;
8574 }
8575
8576 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
8577 close(fd2);
8578 return -1;
8579 }
8580 #ifdef HAVE_DUP3
8581 }
8582 #endif
8583
8584 #endif
8585
8586 return res;
8587 }
8588
8589
8590 #ifdef HAVE_LOCKF
8591 /*[clinic input]
8592 os.lockf
8593
8594 fd: int
8595 An open file descriptor.
8596 command: int
8597 One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
8598 length: Py_off_t
8599 The number of bytes to lock, starting at the current position.
8600 /
8601
8602 Apply, test or remove a POSIX lock on an open file descriptor.
8603
8604 [clinic start generated code]*/
8605
8606 static PyObject *
os_lockf_impl(PyObject * module,int fd,int command,Py_off_t length)8607 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
8608 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
8609 {
8610 int res;
8611
8612 Py_BEGIN_ALLOW_THREADS
8613 res = lockf(fd, command, length);
8614 Py_END_ALLOW_THREADS
8615
8616 if (res < 0)
8617 return posix_error();
8618
8619 Py_RETURN_NONE;
8620 }
8621 #endif /* HAVE_LOCKF */
8622
8623
8624 /*[clinic input]
8625 os.lseek -> Py_off_t
8626
8627 fd: int
8628 position: Py_off_t
8629 how: int
8630 /
8631
8632 Set the position of a file descriptor. Return the new position.
8633
8634 Return the new cursor position in number of bytes
8635 relative to the beginning of the file.
8636 [clinic start generated code]*/
8637
8638 static Py_off_t
os_lseek_impl(PyObject * module,int fd,Py_off_t position,int how)8639 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
8640 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
8641 {
8642 Py_off_t result;
8643
8644 #ifdef SEEK_SET
8645 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
8646 switch (how) {
8647 case 0: how = SEEK_SET; break;
8648 case 1: how = SEEK_CUR; break;
8649 case 2: how = SEEK_END; break;
8650 }
8651 #endif /* SEEK_END */
8652
8653 Py_BEGIN_ALLOW_THREADS
8654 _Py_BEGIN_SUPPRESS_IPH
8655 #ifdef MS_WINDOWS
8656 result = _lseeki64(fd, position, how);
8657 #else
8658 result = lseek(fd, position, how);
8659 #endif
8660 _Py_END_SUPPRESS_IPH
8661 Py_END_ALLOW_THREADS
8662 if (result < 0)
8663 posix_error();
8664
8665 return result;
8666 }
8667
8668
8669 /*[clinic input]
8670 os.read
8671 fd: int
8672 length: Py_ssize_t
8673 /
8674
8675 Read from a file descriptor. Returns a bytes object.
8676 [clinic start generated code]*/
8677
8678 static PyObject *
os_read_impl(PyObject * module,int fd,Py_ssize_t length)8679 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
8680 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
8681 {
8682 Py_ssize_t n;
8683 PyObject *buffer;
8684
8685 if (length < 0) {
8686 errno = EINVAL;
8687 return posix_error();
8688 }
8689
8690 length = Py_MIN(length, _PY_READ_MAX);
8691
8692 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
8693 if (buffer == NULL)
8694 return NULL;
8695
8696 n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
8697 if (n == -1) {
8698 Py_DECREF(buffer);
8699 return NULL;
8700 }
8701
8702 if (n != length)
8703 _PyBytes_Resize(&buffer, n);
8704
8705 return buffer;
8706 }
8707
8708 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
8709 || defined(__APPLE__))) \
8710 || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
8711 || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
8712 static int
iov_setup(struct iovec ** iov,Py_buffer ** buf,PyObject * seq,Py_ssize_t cnt,int type)8713 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
8714 {
8715 Py_ssize_t i, j;
8716
8717 *iov = PyMem_New(struct iovec, cnt);
8718 if (*iov == NULL) {
8719 PyErr_NoMemory();
8720 return -1;
8721 }
8722
8723 *buf = PyMem_New(Py_buffer, cnt);
8724 if (*buf == NULL) {
8725 PyMem_Del(*iov);
8726 PyErr_NoMemory();
8727 return -1;
8728 }
8729
8730 for (i = 0; i < cnt; i++) {
8731 PyObject *item = PySequence_GetItem(seq, i);
8732 if (item == NULL)
8733 goto fail;
8734 if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
8735 Py_DECREF(item);
8736 goto fail;
8737 }
8738 Py_DECREF(item);
8739 (*iov)[i].iov_base = (*buf)[i].buf;
8740 (*iov)[i].iov_len = (*buf)[i].len;
8741 }
8742 return 0;
8743
8744 fail:
8745 PyMem_Del(*iov);
8746 for (j = 0; j < i; j++) {
8747 PyBuffer_Release(&(*buf)[j]);
8748 }
8749 PyMem_Del(*buf);
8750 return -1;
8751 }
8752
8753 static void
iov_cleanup(struct iovec * iov,Py_buffer * buf,int cnt)8754 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
8755 {
8756 int i;
8757 PyMem_Del(iov);
8758 for (i = 0; i < cnt; i++) {
8759 PyBuffer_Release(&buf[i]);
8760 }
8761 PyMem_Del(buf);
8762 }
8763 #endif
8764
8765
8766 #ifdef HAVE_READV
8767 /*[clinic input]
8768 os.readv -> Py_ssize_t
8769
8770 fd: int
8771 buffers: object
8772 /
8773
8774 Read from a file descriptor fd into an iterable of buffers.
8775
8776 The buffers should be mutable buffers accepting bytes.
8777 readv will transfer data into each buffer until it is full
8778 and then move on to the next buffer in the sequence to hold
8779 the rest of the data.
8780
8781 readv returns the total number of bytes read,
8782 which may be less than the total capacity of all the buffers.
8783 [clinic start generated code]*/
8784
8785 static Py_ssize_t
os_readv_impl(PyObject * module,int fd,PyObject * buffers)8786 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
8787 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
8788 {
8789 Py_ssize_t cnt, n;
8790 int async_err = 0;
8791 struct iovec *iov;
8792 Py_buffer *buf;
8793
8794 if (!PySequence_Check(buffers)) {
8795 PyErr_SetString(PyExc_TypeError,
8796 "readv() arg 2 must be a sequence");
8797 return -1;
8798 }
8799
8800 cnt = PySequence_Size(buffers);
8801 if (cnt < 0)
8802 return -1;
8803
8804 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
8805 return -1;
8806
8807 do {
8808 Py_BEGIN_ALLOW_THREADS
8809 n = readv(fd, iov, cnt);
8810 Py_END_ALLOW_THREADS
8811 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8812
8813 iov_cleanup(iov, buf, cnt);
8814 if (n < 0) {
8815 if (!async_err)
8816 posix_error();
8817 return -1;
8818 }
8819
8820 return n;
8821 }
8822 #endif /* HAVE_READV */
8823
8824
8825 #ifdef HAVE_PREAD
8826 /*[clinic input]
8827 # TODO length should be size_t! but Python doesn't support parsing size_t yet.
8828 os.pread
8829
8830 fd: int
8831 length: int
8832 offset: Py_off_t
8833 /
8834
8835 Read a number of bytes from a file descriptor starting at a particular offset.
8836
8837 Read length bytes from file descriptor fd, starting at offset bytes from
8838 the beginning of the file. The file offset remains unchanged.
8839 [clinic start generated code]*/
8840
8841 static PyObject *
os_pread_impl(PyObject * module,int fd,int length,Py_off_t offset)8842 os_pread_impl(PyObject *module, int fd, int length, Py_off_t offset)
8843 /*[clinic end generated code: output=435b29ee32b54a78 input=084948dcbaa35d4c]*/
8844 {
8845 Py_ssize_t n;
8846 int async_err = 0;
8847 PyObject *buffer;
8848
8849 if (length < 0) {
8850 errno = EINVAL;
8851 return posix_error();
8852 }
8853 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
8854 if (buffer == NULL)
8855 return NULL;
8856
8857 do {
8858 Py_BEGIN_ALLOW_THREADS
8859 _Py_BEGIN_SUPPRESS_IPH
8860 n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
8861 _Py_END_SUPPRESS_IPH
8862 Py_END_ALLOW_THREADS
8863 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8864
8865 if (n < 0) {
8866 Py_DECREF(buffer);
8867 return (!async_err) ? posix_error() : NULL;
8868 }
8869 if (n != length)
8870 _PyBytes_Resize(&buffer, n);
8871 return buffer;
8872 }
8873 #endif /* HAVE_PREAD */
8874
8875 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
8876 /*[clinic input]
8877 os.preadv -> Py_ssize_t
8878
8879 fd: int
8880 buffers: object
8881 offset: Py_off_t
8882 flags: int = 0
8883 /
8884
8885 Reads from a file descriptor into a number of mutable bytes-like objects.
8886
8887 Combines the functionality of readv() and pread(). As readv(), it will
8888 transfer data into each buffer until it is full and then move on to the next
8889 buffer in the sequence to hold the rest of the data. Its fourth argument,
8890 specifies the file offset at which the input operation is to be performed. It
8891 will return the total number of bytes read (which can be less than the total
8892 capacity of all the objects).
8893
8894 The flags argument contains a bitwise OR of zero or more of the following flags:
8895
8896 - RWF_HIPRI
8897 - RWF_NOWAIT
8898
8899 Using non-zero flags requires Linux 4.6 or newer.
8900 [clinic start generated code]*/
8901
8902 static Py_ssize_t
os_preadv_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)8903 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
8904 int flags)
8905 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
8906 {
8907 Py_ssize_t cnt, n;
8908 int async_err = 0;
8909 struct iovec *iov;
8910 Py_buffer *buf;
8911
8912 if (!PySequence_Check(buffers)) {
8913 PyErr_SetString(PyExc_TypeError,
8914 "preadv2() arg 2 must be a sequence");
8915 return -1;
8916 }
8917
8918 cnt = PySequence_Size(buffers);
8919 if (cnt < 0) {
8920 return -1;
8921 }
8922
8923 #ifndef HAVE_PREADV2
8924 if(flags != 0) {
8925 argument_unavailable_error("preadv2", "flags");
8926 return -1;
8927 }
8928 #endif
8929
8930 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
8931 return -1;
8932 }
8933 #ifdef HAVE_PREADV2
8934 do {
8935 Py_BEGIN_ALLOW_THREADS
8936 _Py_BEGIN_SUPPRESS_IPH
8937 n = preadv2(fd, iov, cnt, offset, flags);
8938 _Py_END_SUPPRESS_IPH
8939 Py_END_ALLOW_THREADS
8940 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8941 #else
8942 do {
8943 Py_BEGIN_ALLOW_THREADS
8944 _Py_BEGIN_SUPPRESS_IPH
8945 n = preadv(fd, iov, cnt, offset);
8946 _Py_END_SUPPRESS_IPH
8947 Py_END_ALLOW_THREADS
8948 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8949 #endif
8950
8951 iov_cleanup(iov, buf, cnt);
8952 if (n < 0) {
8953 if (!async_err) {
8954 posix_error();
8955 }
8956 return -1;
8957 }
8958
8959 return n;
8960 }
8961 #endif /* HAVE_PREADV */
8962
8963
8964 /*[clinic input]
8965 os.write -> Py_ssize_t
8966
8967 fd: int
8968 data: Py_buffer
8969 /
8970
8971 Write a bytes object to a file descriptor.
8972 [clinic start generated code]*/
8973
8974 static Py_ssize_t
os_write_impl(PyObject * module,int fd,Py_buffer * data)8975 os_write_impl(PyObject *module, int fd, Py_buffer *data)
8976 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
8977 {
8978 return _Py_write(fd, data->buf, data->len);
8979 }
8980
8981 #ifdef HAVE_SENDFILE
8982 PyDoc_STRVAR(posix_sendfile__doc__,
8983 "sendfile(out, in, offset, count) -> byteswritten\n\
8984 sendfile(out, in, offset, count[, headers][, trailers], flags=0)\n\
8985 -> byteswritten\n\
8986 Copy count bytes from file descriptor in to file descriptor out.");
8987
8988 /* AC 3.5: don't bother converting, has optional group*/
8989 static PyObject *
posix_sendfile(PyObject * self,PyObject * args,PyObject * kwdict)8990 posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
8991 {
8992 int in, out;
8993 Py_ssize_t ret;
8994 int async_err = 0;
8995 off_t offset;
8996
8997 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
8998 #ifndef __APPLE__
8999 Py_ssize_t len;
9000 #endif
9001 PyObject *headers = NULL, *trailers = NULL;
9002 Py_buffer *hbuf, *tbuf;
9003 off_t sbytes;
9004 struct sf_hdtr sf;
9005 int flags = 0;
9006 /* Beware that "in" clashes with Python's own "in" operator keyword */
9007 static char *keywords[] = {"out", "in",
9008 "offset", "count",
9009 "headers", "trailers", "flags", NULL};
9010
9011 sf.headers = NULL;
9012 sf.trailers = NULL;
9013
9014 #ifdef __APPLE__
9015 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile",
9016 keywords, &out, &in, Py_off_t_converter, &offset, Py_off_t_converter, &sbytes,
9017 #else
9018 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile",
9019 keywords, &out, &in, Py_off_t_converter, &offset, &len,
9020 #endif
9021 &headers, &trailers, &flags))
9022 return NULL;
9023 if (headers != NULL) {
9024 if (!PySequence_Check(headers)) {
9025 PyErr_SetString(PyExc_TypeError,
9026 "sendfile() headers must be a sequence");
9027 return NULL;
9028 } else {
9029 Py_ssize_t i = PySequence_Size(headers);
9030 if (i < 0)
9031 return NULL;
9032 if (i > INT_MAX) {
9033 PyErr_SetString(PyExc_OverflowError,
9034 "sendfile() header is too large");
9035 return NULL;
9036 }
9037 if (i > 0) {
9038 sf.hdr_cnt = (int)i;
9039 if (iov_setup(&(sf.headers), &hbuf,
9040 headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9041 return NULL;
9042 #ifdef __APPLE__
9043 for (i = 0; i < sf.hdr_cnt; i++) {
9044 Py_ssize_t blen = sf.headers[i].iov_len;
9045 # define OFF_T_MAX 0x7fffffffffffffff
9046 if (sbytes >= OFF_T_MAX - blen) {
9047 PyErr_SetString(PyExc_OverflowError,
9048 "sendfile() header is too large");
9049 return NULL;
9050 }
9051 sbytes += blen;
9052 }
9053 #endif
9054 }
9055 }
9056 }
9057 if (trailers != NULL) {
9058 if (!PySequence_Check(trailers)) {
9059 PyErr_SetString(PyExc_TypeError,
9060 "sendfile() trailers must be a sequence");
9061 return NULL;
9062 } else {
9063 Py_ssize_t i = PySequence_Size(trailers);
9064 if (i < 0)
9065 return NULL;
9066 if (i > INT_MAX) {
9067 PyErr_SetString(PyExc_OverflowError,
9068 "sendfile() trailer is too large");
9069 return NULL;
9070 }
9071 if (i > 0) {
9072 sf.trl_cnt = (int)i;
9073 if (iov_setup(&(sf.trailers), &tbuf,
9074 trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
9075 return NULL;
9076 }
9077 }
9078 }
9079
9080 _Py_BEGIN_SUPPRESS_IPH
9081 do {
9082 Py_BEGIN_ALLOW_THREADS
9083 #ifdef __APPLE__
9084 ret = sendfile(in, out, offset, &sbytes, &sf, flags);
9085 #else
9086 ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);
9087 #endif
9088 Py_END_ALLOW_THREADS
9089 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9090 _Py_END_SUPPRESS_IPH
9091
9092 if (sf.headers != NULL)
9093 iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
9094 if (sf.trailers != NULL)
9095 iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
9096
9097 if (ret < 0) {
9098 if ((errno == EAGAIN) || (errno == EBUSY)) {
9099 if (sbytes != 0) {
9100 // some data has been sent
9101 goto done;
9102 }
9103 else {
9104 // no data has been sent; upper application is supposed
9105 // to retry on EAGAIN or EBUSY
9106 return posix_error();
9107 }
9108 }
9109 return (!async_err) ? posix_error() : NULL;
9110 }
9111 goto done;
9112
9113 done:
9114 #if !defined(HAVE_LARGEFILE_SUPPORT)
9115 return Py_BuildValue("l", sbytes);
9116 #else
9117 return Py_BuildValue("L", sbytes);
9118 #endif
9119
9120 #else
9121 Py_ssize_t count;
9122 PyObject *offobj;
9123 static char *keywords[] = {"out", "in",
9124 "offset", "count", NULL};
9125 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",
9126 keywords, &out, &in, &offobj, &count))
9127 return NULL;
9128 #ifdef __linux__
9129 if (offobj == Py_None) {
9130 do {
9131 Py_BEGIN_ALLOW_THREADS
9132 ret = sendfile(out, in, NULL, count);
9133 Py_END_ALLOW_THREADS
9134 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9135 if (ret < 0)
9136 return (!async_err) ? posix_error() : NULL;
9137 return Py_BuildValue("n", ret);
9138 }
9139 #endif
9140 if (!Py_off_t_converter(offobj, &offset))
9141 return NULL;
9142
9143 do {
9144 Py_BEGIN_ALLOW_THREADS
9145 ret = sendfile(out, in, &offset, count);
9146 Py_END_ALLOW_THREADS
9147 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9148 if (ret < 0)
9149 return (!async_err) ? posix_error() : NULL;
9150 return Py_BuildValue("n", ret);
9151 #endif
9152 }
9153 #endif /* HAVE_SENDFILE */
9154
9155
9156 #if defined(__APPLE__)
9157 /*[clinic input]
9158 os._fcopyfile
9159
9160 infd: int
9161 outfd: int
9162 flags: int
9163 /
9164
9165 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
9166 [clinic start generated code]*/
9167
9168 static PyObject *
os__fcopyfile_impl(PyObject * module,int infd,int outfd,int flags)9169 os__fcopyfile_impl(PyObject *module, int infd, int outfd, int flags)
9170 /*[clinic end generated code: output=8e8885c721ec38e3 input=69e0770e600cb44f]*/
9171 {
9172 int ret;
9173
9174 Py_BEGIN_ALLOW_THREADS
9175 ret = fcopyfile(infd, outfd, NULL, flags);
9176 Py_END_ALLOW_THREADS
9177 if (ret < 0)
9178 return posix_error();
9179 Py_RETURN_NONE;
9180 }
9181 #endif
9182
9183
9184 /*[clinic input]
9185 os.fstat
9186
9187 fd : int
9188
9189 Perform a stat system call on the given file descriptor.
9190
9191 Like stat(), but for an open file descriptor.
9192 Equivalent to os.stat(fd).
9193 [clinic start generated code]*/
9194
9195 static PyObject *
os_fstat_impl(PyObject * module,int fd)9196 os_fstat_impl(PyObject *module, int fd)
9197 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
9198 {
9199 STRUCT_STAT st;
9200 int res;
9201 int async_err = 0;
9202
9203 do {
9204 Py_BEGIN_ALLOW_THREADS
9205 res = FSTAT(fd, &st);
9206 Py_END_ALLOW_THREADS
9207 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9208 if (res != 0) {
9209 #ifdef MS_WINDOWS
9210 return PyErr_SetFromWindowsErr(0);
9211 #else
9212 return (!async_err) ? posix_error() : NULL;
9213 #endif
9214 }
9215
9216 return _pystat_fromstructstat(&st);
9217 }
9218
9219
9220 /*[clinic input]
9221 os.isatty -> bool
9222 fd: int
9223 /
9224
9225 Return True if the fd is connected to a terminal.
9226
9227 Return True if the file descriptor is an open file descriptor
9228 connected to the slave end of a terminal.
9229 [clinic start generated code]*/
9230
9231 static int
os_isatty_impl(PyObject * module,int fd)9232 os_isatty_impl(PyObject *module, int fd)
9233 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
9234 {
9235 int return_value;
9236 _Py_BEGIN_SUPPRESS_IPH
9237 return_value = isatty(fd);
9238 _Py_END_SUPPRESS_IPH
9239 return return_value;
9240 }
9241
9242
9243 #ifdef HAVE_PIPE
9244 /*[clinic input]
9245 os.pipe
9246
9247 Create a pipe.
9248
9249 Returns a tuple of two file descriptors:
9250 (read_fd, write_fd)
9251 [clinic start generated code]*/
9252
9253 static PyObject *
os_pipe_impl(PyObject * module)9254 os_pipe_impl(PyObject *module)
9255 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
9256 {
9257 int fds[2];
9258 #ifdef MS_WINDOWS
9259 HANDLE read, write;
9260 SECURITY_ATTRIBUTES attr;
9261 BOOL ok;
9262 #else
9263 int res;
9264 #endif
9265
9266 #ifdef MS_WINDOWS
9267 attr.nLength = sizeof(attr);
9268 attr.lpSecurityDescriptor = NULL;
9269 attr.bInheritHandle = FALSE;
9270
9271 Py_BEGIN_ALLOW_THREADS
9272 _Py_BEGIN_SUPPRESS_IPH
9273 ok = CreatePipe(&read, &write, &attr, 0);
9274 if (ok) {
9275 fds[0] = _open_osfhandle((intptr_t)read, _O_RDONLY);
9276 fds[1] = _open_osfhandle((intptr_t)write, _O_WRONLY);
9277 if (fds[0] == -1 || fds[1] == -1) {
9278 CloseHandle(read);
9279 CloseHandle(write);
9280 ok = 0;
9281 }
9282 }
9283 _Py_END_SUPPRESS_IPH
9284 Py_END_ALLOW_THREADS
9285
9286 if (!ok)
9287 return PyErr_SetFromWindowsErr(0);
9288 #else
9289
9290 #ifdef HAVE_PIPE2
9291 Py_BEGIN_ALLOW_THREADS
9292 res = pipe2(fds, O_CLOEXEC);
9293 Py_END_ALLOW_THREADS
9294
9295 if (res != 0 && errno == ENOSYS)
9296 {
9297 #endif
9298 Py_BEGIN_ALLOW_THREADS
9299 res = pipe(fds);
9300 Py_END_ALLOW_THREADS
9301
9302 if (res == 0) {
9303 if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
9304 close(fds[0]);
9305 close(fds[1]);
9306 return NULL;
9307 }
9308 if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
9309 close(fds[0]);
9310 close(fds[1]);
9311 return NULL;
9312 }
9313 }
9314 #ifdef HAVE_PIPE2
9315 }
9316 #endif
9317
9318 if (res != 0)
9319 return PyErr_SetFromErrno(PyExc_OSError);
9320 #endif /* !MS_WINDOWS */
9321 return Py_BuildValue("(ii)", fds[0], fds[1]);
9322 }
9323 #endif /* HAVE_PIPE */
9324
9325
9326 #ifdef HAVE_PIPE2
9327 /*[clinic input]
9328 os.pipe2
9329
9330 flags: int
9331 /
9332
9333 Create a pipe with flags set atomically.
9334
9335 Returns a tuple of two file descriptors:
9336 (read_fd, write_fd)
9337
9338 flags can be constructed by ORing together one or more of these values:
9339 O_NONBLOCK, O_CLOEXEC.
9340 [clinic start generated code]*/
9341
9342 static PyObject *
os_pipe2_impl(PyObject * module,int flags)9343 os_pipe2_impl(PyObject *module, int flags)
9344 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
9345 {
9346 int fds[2];
9347 int res;
9348
9349 res = pipe2(fds, flags);
9350 if (res != 0)
9351 return posix_error();
9352 return Py_BuildValue("(ii)", fds[0], fds[1]);
9353 }
9354 #endif /* HAVE_PIPE2 */
9355
9356
9357 #ifdef HAVE_WRITEV
9358 /*[clinic input]
9359 os.writev -> Py_ssize_t
9360 fd: int
9361 buffers: object
9362 /
9363
9364 Iterate over buffers, and write the contents of each to a file descriptor.
9365
9366 Returns the total number of bytes written.
9367 buffers must be a sequence of bytes-like objects.
9368 [clinic start generated code]*/
9369
9370 static Py_ssize_t
os_writev_impl(PyObject * module,int fd,PyObject * buffers)9371 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
9372 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
9373 {
9374 Py_ssize_t cnt;
9375 Py_ssize_t result;
9376 int async_err = 0;
9377 struct iovec *iov;
9378 Py_buffer *buf;
9379
9380 if (!PySequence_Check(buffers)) {
9381 PyErr_SetString(PyExc_TypeError,
9382 "writev() arg 2 must be a sequence");
9383 return -1;
9384 }
9385 cnt = PySequence_Size(buffers);
9386 if (cnt < 0)
9387 return -1;
9388
9389 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
9390 return -1;
9391 }
9392
9393 do {
9394 Py_BEGIN_ALLOW_THREADS
9395 result = writev(fd, iov, cnt);
9396 Py_END_ALLOW_THREADS
9397 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9398
9399 iov_cleanup(iov, buf, cnt);
9400 if (result < 0 && !async_err)
9401 posix_error();
9402
9403 return result;
9404 }
9405 #endif /* HAVE_WRITEV */
9406
9407
9408 #ifdef HAVE_PWRITE
9409 /*[clinic input]
9410 os.pwrite -> Py_ssize_t
9411
9412 fd: int
9413 buffer: Py_buffer
9414 offset: Py_off_t
9415 /
9416
9417 Write bytes to a file descriptor starting at a particular offset.
9418
9419 Write buffer to fd, starting at offset bytes from the beginning of
9420 the file. Returns the number of bytes writte. Does not change the
9421 current file offset.
9422 [clinic start generated code]*/
9423
9424 static Py_ssize_t
os_pwrite_impl(PyObject * module,int fd,Py_buffer * buffer,Py_off_t offset)9425 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
9426 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
9427 {
9428 Py_ssize_t size;
9429 int async_err = 0;
9430
9431 do {
9432 Py_BEGIN_ALLOW_THREADS
9433 _Py_BEGIN_SUPPRESS_IPH
9434 size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
9435 _Py_END_SUPPRESS_IPH
9436 Py_END_ALLOW_THREADS
9437 } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9438
9439 if (size < 0 && !async_err)
9440 posix_error();
9441 return size;
9442 }
9443 #endif /* HAVE_PWRITE */
9444
9445 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9446 /*[clinic input]
9447 os.pwritev -> Py_ssize_t
9448
9449 fd: int
9450 buffers: object
9451 offset: Py_off_t
9452 flags: int = 0
9453 /
9454
9455 Writes the contents of bytes-like objects to a file descriptor at a given offset.
9456
9457 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
9458 of bytes-like objects. Buffers are processed in array order. Entire contents of first
9459 buffer is written before proceeding to second, and so on. The operating system may
9460 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
9461 This function writes the contents of each object to the file descriptor and returns
9462 the total number of bytes written.
9463
9464 The flags argument contains a bitwise OR of zero or more of the following flags:
9465
9466 - RWF_DSYNC
9467 - RWF_SYNC
9468
9469 Using non-zero flags requires Linux 4.7 or newer.
9470 [clinic start generated code]*/
9471
9472 static Py_ssize_t
os_pwritev_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9473 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9474 int flags)
9475 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=803dc5ddbf0cfd3b]*/
9476 {
9477 Py_ssize_t cnt;
9478 Py_ssize_t result;
9479 int async_err = 0;
9480 struct iovec *iov;
9481 Py_buffer *buf;
9482
9483 if (!PySequence_Check(buffers)) {
9484 PyErr_SetString(PyExc_TypeError,
9485 "pwritev() arg 2 must be a sequence");
9486 return -1;
9487 }
9488
9489 cnt = PySequence_Size(buffers);
9490 if (cnt < 0) {
9491 return -1;
9492 }
9493
9494 #ifndef HAVE_PWRITEV2
9495 if(flags != 0) {
9496 argument_unavailable_error("pwritev2", "flags");
9497 return -1;
9498 }
9499 #endif
9500
9501 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
9502 return -1;
9503 }
9504 #ifdef HAVE_PWRITEV2
9505 do {
9506 Py_BEGIN_ALLOW_THREADS
9507 _Py_BEGIN_SUPPRESS_IPH
9508 result = pwritev2(fd, iov, cnt, offset, flags);
9509 _Py_END_SUPPRESS_IPH
9510 Py_END_ALLOW_THREADS
9511 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9512 #else
9513 do {
9514 Py_BEGIN_ALLOW_THREADS
9515 _Py_BEGIN_SUPPRESS_IPH
9516 result = pwritev(fd, iov, cnt, offset);
9517 _Py_END_SUPPRESS_IPH
9518 Py_END_ALLOW_THREADS
9519 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9520 #endif
9521
9522 iov_cleanup(iov, buf, cnt);
9523 if (result < 0) {
9524 if (!async_err) {
9525 posix_error();
9526 }
9527 return -1;
9528 }
9529
9530 return result;
9531 }
9532 #endif /* HAVE_PWRITEV */
9533
9534 #ifdef HAVE_COPY_FILE_RANGE
9535 /*[clinic input]
9536
9537 os.copy_file_range
9538 src: int
9539 Source file descriptor.
9540 dst: int
9541 Destination file descriptor.
9542 count: Py_ssize_t
9543 Number of bytes to copy.
9544 offset_src: object = None
9545 Starting offset in src.
9546 offset_dst: object = None
9547 Starting offset in dst.
9548
9549 Copy count bytes from one file descriptor to another.
9550
9551 If offset_src is None, then src is read from the current position;
9552 respectively for offset_dst.
9553 [clinic start generated code]*/
9554
9555 static PyObject *
os_copy_file_range_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst)9556 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
9557 PyObject *offset_src, PyObject *offset_dst)
9558 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
9559 {
9560 off_t offset_src_val, offset_dst_val;
9561 off_t *p_offset_src = NULL;
9562 off_t *p_offset_dst = NULL;
9563 Py_ssize_t ret;
9564 int async_err = 0;
9565 /* The flags argument is provided to allow
9566 * for future extensions and currently must be to 0. */
9567 int flags = 0;
9568
9569
9570 if (count < 0) {
9571 PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
9572 return NULL;
9573 }
9574
9575 if (offset_src != Py_None) {
9576 if (!Py_off_t_converter(offset_src, &offset_src_val)) {
9577 return NULL;
9578 }
9579 p_offset_src = &offset_src_val;
9580 }
9581
9582 if (offset_dst != Py_None) {
9583 if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
9584 return NULL;
9585 }
9586 p_offset_dst = &offset_dst_val;
9587 }
9588
9589 do {
9590 Py_BEGIN_ALLOW_THREADS
9591 ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
9592 Py_END_ALLOW_THREADS
9593 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9594
9595 if (ret < 0) {
9596 return (!async_err) ? posix_error() : NULL;
9597 }
9598
9599 return PyLong_FromSsize_t(ret);
9600 }
9601 #endif /* HAVE_COPY_FILE_RANGE*/
9602
9603 #ifdef HAVE_MKFIFO
9604 /*[clinic input]
9605 os.mkfifo
9606
9607 path: path_t
9608 mode: int=0o666
9609 *
9610 dir_fd: dir_fd(requires='mkfifoat')=None
9611
9612 Create a "fifo" (a POSIX named pipe).
9613
9614 If dir_fd is not None, it should be a file descriptor open to a directory,
9615 and path should be relative; path will then be relative to that directory.
9616 dir_fd may not be implemented on your platform.
9617 If it is unavailable, using it will raise a NotImplementedError.
9618 [clinic start generated code]*/
9619
9620 static PyObject *
os_mkfifo_impl(PyObject * module,path_t * path,int mode,int dir_fd)9621 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
9622 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
9623 {
9624 int result;
9625 int async_err = 0;
9626
9627 do {
9628 Py_BEGIN_ALLOW_THREADS
9629 #ifdef HAVE_MKFIFOAT
9630 if (dir_fd != DEFAULT_DIR_FD)
9631 result = mkfifoat(dir_fd, path->narrow, mode);
9632 else
9633 #endif
9634 result = mkfifo(path->narrow, mode);
9635 Py_END_ALLOW_THREADS
9636 } while (result != 0 && errno == EINTR &&
9637 !(async_err = PyErr_CheckSignals()));
9638 if (result != 0)
9639 return (!async_err) ? posix_error() : NULL;
9640
9641 Py_RETURN_NONE;
9642 }
9643 #endif /* HAVE_MKFIFO */
9644
9645
9646 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
9647 /*[clinic input]
9648 os.mknod
9649
9650 path: path_t
9651 mode: int=0o600
9652 device: dev_t=0
9653 *
9654 dir_fd: dir_fd(requires='mknodat')=None
9655
9656 Create a node in the file system.
9657
9658 Create a node in the file system (file, device special file or named pipe)
9659 at path. mode specifies both the permissions to use and the
9660 type of node to be created, being combined (bitwise OR) with one of
9661 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,
9662 device defines the newly created device special file (probably using
9663 os.makedev()). Otherwise device is ignored.
9664
9665 If dir_fd is not None, it should be a file descriptor open to a directory,
9666 and path should be relative; path will then be relative to that directory.
9667 dir_fd may not be implemented on your platform.
9668 If it is unavailable, using it will raise a NotImplementedError.
9669 [clinic start generated code]*/
9670
9671 static PyObject *
os_mknod_impl(PyObject * module,path_t * path,int mode,dev_t device,int dir_fd)9672 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
9673 int dir_fd)
9674 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
9675 {
9676 int result;
9677 int async_err = 0;
9678
9679 do {
9680 Py_BEGIN_ALLOW_THREADS
9681 #ifdef HAVE_MKNODAT
9682 if (dir_fd != DEFAULT_DIR_FD)
9683 result = mknodat(dir_fd, path->narrow, mode, device);
9684 else
9685 #endif
9686 result = mknod(path->narrow, mode, device);
9687 Py_END_ALLOW_THREADS
9688 } while (result != 0 && errno == EINTR &&
9689 !(async_err = PyErr_CheckSignals()));
9690 if (result != 0)
9691 return (!async_err) ? posix_error() : NULL;
9692
9693 Py_RETURN_NONE;
9694 }
9695 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
9696
9697
9698 #ifdef HAVE_DEVICE_MACROS
9699 /*[clinic input]
9700 os.major -> unsigned_int
9701
9702 device: dev_t
9703 /
9704
9705 Extracts a device major number from a raw device number.
9706 [clinic start generated code]*/
9707
9708 static unsigned int
os_major_impl(PyObject * module,dev_t device)9709 os_major_impl(PyObject *module, dev_t device)
9710 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
9711 {
9712 return major(device);
9713 }
9714
9715
9716 /*[clinic input]
9717 os.minor -> unsigned_int
9718
9719 device: dev_t
9720 /
9721
9722 Extracts a device minor number from a raw device number.
9723 [clinic start generated code]*/
9724
9725 static unsigned int
os_minor_impl(PyObject * module,dev_t device)9726 os_minor_impl(PyObject *module, dev_t device)
9727 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
9728 {
9729 return minor(device);
9730 }
9731
9732
9733 /*[clinic input]
9734 os.makedev -> dev_t
9735
9736 major: int
9737 minor: int
9738 /
9739
9740 Composes a raw device number from the major and minor device numbers.
9741 [clinic start generated code]*/
9742
9743 static dev_t
os_makedev_impl(PyObject * module,int major,int minor)9744 os_makedev_impl(PyObject *module, int major, int minor)
9745 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
9746 {
9747 return makedev(major, minor);
9748 }
9749 #endif /* HAVE_DEVICE_MACROS */
9750
9751
9752 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
9753 /*[clinic input]
9754 os.ftruncate
9755
9756 fd: int
9757 length: Py_off_t
9758 /
9759
9760 Truncate a file, specified by file descriptor, to a specific length.
9761 [clinic start generated code]*/
9762
9763 static PyObject *
os_ftruncate_impl(PyObject * module,int fd,Py_off_t length)9764 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
9765 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
9766 {
9767 int result;
9768 int async_err = 0;
9769
9770 if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
9771 return NULL;
9772 }
9773
9774 do {
9775 Py_BEGIN_ALLOW_THREADS
9776 _Py_BEGIN_SUPPRESS_IPH
9777 #ifdef MS_WINDOWS
9778 result = _chsize_s(fd, length);
9779 #else
9780 result = ftruncate(fd, length);
9781 #endif
9782 _Py_END_SUPPRESS_IPH
9783 Py_END_ALLOW_THREADS
9784 } while (result != 0 && errno == EINTR &&
9785 !(async_err = PyErr_CheckSignals()));
9786 if (result != 0)
9787 return (!async_err) ? posix_error() : NULL;
9788 Py_RETURN_NONE;
9789 }
9790 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
9791
9792
9793 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
9794 /*[clinic input]
9795 os.truncate
9796 path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
9797 length: Py_off_t
9798
9799 Truncate a file, specified by path, to a specific length.
9800
9801 On some platforms, path may also be specified as an open file descriptor.
9802 If this functionality is unavailable, using it raises an exception.
9803 [clinic start generated code]*/
9804
9805 static PyObject *
os_truncate_impl(PyObject * module,path_t * path,Py_off_t length)9806 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
9807 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
9808 {
9809 int result;
9810 #ifdef MS_WINDOWS
9811 int fd;
9812 #endif
9813
9814 if (path->fd != -1)
9815 return os_ftruncate_impl(module, path->fd, length);
9816
9817 if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
9818 return NULL;
9819 }
9820
9821 Py_BEGIN_ALLOW_THREADS
9822 _Py_BEGIN_SUPPRESS_IPH
9823 #ifdef MS_WINDOWS
9824 fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
9825 if (fd < 0)
9826 result = -1;
9827 else {
9828 result = _chsize_s(fd, length);
9829 close(fd);
9830 if (result < 0)
9831 errno = result;
9832 }
9833 #else
9834 result = truncate(path->narrow, length);
9835 #endif
9836 _Py_END_SUPPRESS_IPH
9837 Py_END_ALLOW_THREADS
9838 if (result < 0)
9839 return posix_path_error(path);
9840
9841 Py_RETURN_NONE;
9842 }
9843 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
9844
9845
9846 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
9847 and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
9848 defined, which is the case in Python on AIX. AIX bug report:
9849 http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
9850 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
9851 # define POSIX_FADVISE_AIX_BUG
9852 #endif
9853
9854
9855 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
9856 /*[clinic input]
9857 os.posix_fallocate
9858
9859 fd: int
9860 offset: Py_off_t
9861 length: Py_off_t
9862 /
9863
9864 Ensure a file has allocated at least a particular number of bytes on disk.
9865
9866 Ensure that the file specified by fd encompasses a range of bytes
9867 starting at offset bytes from the beginning and continuing for length bytes.
9868 [clinic start generated code]*/
9869
9870 static PyObject *
os_posix_fallocate_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length)9871 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
9872 Py_off_t length)
9873 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
9874 {
9875 int result;
9876 int async_err = 0;
9877
9878 do {
9879 Py_BEGIN_ALLOW_THREADS
9880 result = posix_fallocate(fd, offset, length);
9881 Py_END_ALLOW_THREADS
9882 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
9883
9884 if (result == 0)
9885 Py_RETURN_NONE;
9886
9887 if (async_err)
9888 return NULL;
9889
9890 errno = result;
9891 return posix_error();
9892 }
9893 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
9894
9895
9896 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
9897 /*[clinic input]
9898 os.posix_fadvise
9899
9900 fd: int
9901 offset: Py_off_t
9902 length: Py_off_t
9903 advice: int
9904 /
9905
9906 Announce an intention to access data in a specific pattern.
9907
9908 Announce an intention to access data in a specific pattern, thus allowing
9909 the kernel to make optimizations.
9910 The advice applies to the region of the file specified by fd starting at
9911 offset and continuing for length bytes.
9912 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
9913 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
9914 POSIX_FADV_DONTNEED.
9915 [clinic start generated code]*/
9916
9917 static PyObject *
os_posix_fadvise_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length,int advice)9918 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
9919 Py_off_t length, int advice)
9920 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
9921 {
9922 int result;
9923 int async_err = 0;
9924
9925 do {
9926 Py_BEGIN_ALLOW_THREADS
9927 result = posix_fadvise(fd, offset, length, advice);
9928 Py_END_ALLOW_THREADS
9929 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
9930
9931 if (result == 0)
9932 Py_RETURN_NONE;
9933
9934 if (async_err)
9935 return NULL;
9936
9937 errno = result;
9938 return posix_error();
9939 }
9940 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
9941
9942 #ifdef HAVE_PUTENV
9943
9944 /* Save putenv() parameters as values here, so we can collect them when they
9945 * get re-set with another call for the same key. */
9946 static PyObject *posix_putenv_garbage;
9947
9948 static void
posix_putenv_garbage_setitem(PyObject * name,PyObject * value)9949 posix_putenv_garbage_setitem(PyObject *name, PyObject *value)
9950 {
9951 /* Install the first arg and newstr in posix_putenv_garbage;
9952 * this will cause previous value to be collected. This has to
9953 * happen after the real putenv() call because the old value
9954 * was still accessible until then. */
9955 if (PyDict_SetItem(posix_putenv_garbage, name, value))
9956 /* really not much we can do; just leak */
9957 PyErr_Clear();
9958 else
9959 Py_DECREF(value);
9960 }
9961
9962
9963 #ifdef MS_WINDOWS
9964 /*[clinic input]
9965 os.putenv
9966
9967 name: unicode
9968 value: unicode
9969 /
9970
9971 Change or add an environment variable.
9972 [clinic start generated code]*/
9973
9974 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)9975 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
9976 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
9977 {
9978 const wchar_t *env;
9979 Py_ssize_t size;
9980
9981 /* Search from index 1 because on Windows starting '=' is allowed for
9982 defining hidden environment variables. */
9983 if (PyUnicode_GET_LENGTH(name) == 0 ||
9984 PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
9985 {
9986 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
9987 return NULL;
9988 }
9989 PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value);
9990 if (unicode == NULL) {
9991 return NULL;
9992 }
9993
9994 env = PyUnicode_AsUnicodeAndSize(unicode, &size);
9995 if (env == NULL)
9996 goto error;
9997 if (size > _MAX_ENV) {
9998 PyErr_Format(PyExc_ValueError,
9999 "the environment variable is longer than %u characters",
10000 _MAX_ENV);
10001 goto error;
10002 }
10003 if (wcslen(env) != (size_t)size) {
10004 PyErr_SetString(PyExc_ValueError, "embedded null character");
10005 goto error;
10006 }
10007
10008 if (_wputenv(env)) {
10009 posix_error();
10010 goto error;
10011 }
10012
10013 posix_putenv_garbage_setitem(name, unicode);
10014 Py_RETURN_NONE;
10015
10016 error:
10017 Py_DECREF(unicode);
10018 return NULL;
10019 }
10020 #else /* MS_WINDOWS */
10021 /*[clinic input]
10022 os.putenv
10023
10024 name: FSConverter
10025 value: FSConverter
10026 /
10027
10028 Change or add an environment variable.
10029 [clinic start generated code]*/
10030
10031 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10032 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10033 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
10034 {
10035 PyObject *bytes = NULL;
10036 char *env;
10037 const char *name_string = PyBytes_AS_STRING(name);
10038 const char *value_string = PyBytes_AS_STRING(value);
10039
10040 if (strchr(name_string, '=') != NULL) {
10041 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10042 return NULL;
10043 }
10044 bytes = PyBytes_FromFormat("%s=%s", name_string, value_string);
10045 if (bytes == NULL) {
10046 return NULL;
10047 }
10048
10049 env = PyBytes_AS_STRING(bytes);
10050 if (putenv(env)) {
10051 Py_DECREF(bytes);
10052 return posix_error();
10053 }
10054
10055 posix_putenv_garbage_setitem(name, bytes);
10056 Py_RETURN_NONE;
10057 }
10058 #endif /* MS_WINDOWS */
10059 #endif /* HAVE_PUTENV */
10060
10061
10062 #ifdef HAVE_UNSETENV
10063 /*[clinic input]
10064 os.unsetenv
10065 name: FSConverter
10066 /
10067
10068 Delete an environment variable.
10069 [clinic start generated code]*/
10070
10071 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)10072 os_unsetenv_impl(PyObject *module, PyObject *name)
10073 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
10074 {
10075 #ifndef HAVE_BROKEN_UNSETENV
10076 int err;
10077 #endif
10078
10079 #ifdef HAVE_BROKEN_UNSETENV
10080 unsetenv(PyBytes_AS_STRING(name));
10081 #else
10082 err = unsetenv(PyBytes_AS_STRING(name));
10083 if (err)
10084 return posix_error();
10085 #endif
10086
10087 /* Remove the key from posix_putenv_garbage;
10088 * this will cause it to be collected. This has to
10089 * happen after the real unsetenv() call because the
10090 * old value was still accessible until then.
10091 */
10092 if (PyDict_DelItem(posix_putenv_garbage, name)) {
10093 /* really not much we can do; just leak */
10094 if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
10095 return NULL;
10096 }
10097 PyErr_Clear();
10098 }
10099 Py_RETURN_NONE;
10100 }
10101 #endif /* HAVE_UNSETENV */
10102
10103
10104 /*[clinic input]
10105 os.strerror
10106
10107 code: int
10108 /
10109
10110 Translate an error code to a message string.
10111 [clinic start generated code]*/
10112
10113 static PyObject *
os_strerror_impl(PyObject * module,int code)10114 os_strerror_impl(PyObject *module, int code)
10115 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
10116 {
10117 char *message = strerror(code);
10118 if (message == NULL) {
10119 PyErr_SetString(PyExc_ValueError,
10120 "strerror() argument out of range");
10121 return NULL;
10122 }
10123 return PyUnicode_DecodeLocale(message, "surrogateescape");
10124 }
10125
10126
10127 #ifdef HAVE_SYS_WAIT_H
10128 #ifdef WCOREDUMP
10129 /*[clinic input]
10130 os.WCOREDUMP -> bool
10131
10132 status: int
10133 /
10134
10135 Return True if the process returning status was dumped to a core file.
10136 [clinic start generated code]*/
10137
10138 static int
os_WCOREDUMP_impl(PyObject * module,int status)10139 os_WCOREDUMP_impl(PyObject *module, int status)
10140 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
10141 {
10142 WAIT_TYPE wait_status;
10143 WAIT_STATUS_INT(wait_status) = status;
10144 return WCOREDUMP(wait_status);
10145 }
10146 #endif /* WCOREDUMP */
10147
10148
10149 #ifdef WIFCONTINUED
10150 /*[clinic input]
10151 os.WIFCONTINUED -> bool
10152
10153 status: int
10154
10155 Return True if a particular process was continued from a job control stop.
10156
10157 Return True if the process returning status was continued from a
10158 job control stop.
10159 [clinic start generated code]*/
10160
10161 static int
os_WIFCONTINUED_impl(PyObject * module,int status)10162 os_WIFCONTINUED_impl(PyObject *module, int status)
10163 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
10164 {
10165 WAIT_TYPE wait_status;
10166 WAIT_STATUS_INT(wait_status) = status;
10167 return WIFCONTINUED(wait_status);
10168 }
10169 #endif /* WIFCONTINUED */
10170
10171
10172 #ifdef WIFSTOPPED
10173 /*[clinic input]
10174 os.WIFSTOPPED -> bool
10175
10176 status: int
10177
10178 Return True if the process returning status was stopped.
10179 [clinic start generated code]*/
10180
10181 static int
os_WIFSTOPPED_impl(PyObject * module,int status)10182 os_WIFSTOPPED_impl(PyObject *module, int status)
10183 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
10184 {
10185 WAIT_TYPE wait_status;
10186 WAIT_STATUS_INT(wait_status) = status;
10187 return WIFSTOPPED(wait_status);
10188 }
10189 #endif /* WIFSTOPPED */
10190
10191
10192 #ifdef WIFSIGNALED
10193 /*[clinic input]
10194 os.WIFSIGNALED -> bool
10195
10196 status: int
10197
10198 Return True if the process returning status was terminated by a signal.
10199 [clinic start generated code]*/
10200
10201 static int
os_WIFSIGNALED_impl(PyObject * module,int status)10202 os_WIFSIGNALED_impl(PyObject *module, int status)
10203 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
10204 {
10205 WAIT_TYPE wait_status;
10206 WAIT_STATUS_INT(wait_status) = status;
10207 return WIFSIGNALED(wait_status);
10208 }
10209 #endif /* WIFSIGNALED */
10210
10211
10212 #ifdef WIFEXITED
10213 /*[clinic input]
10214 os.WIFEXITED -> bool
10215
10216 status: int
10217
10218 Return True if the process returning status exited via the exit() system call.
10219 [clinic start generated code]*/
10220
10221 static int
os_WIFEXITED_impl(PyObject * module,int status)10222 os_WIFEXITED_impl(PyObject *module, int status)
10223 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
10224 {
10225 WAIT_TYPE wait_status;
10226 WAIT_STATUS_INT(wait_status) = status;
10227 return WIFEXITED(wait_status);
10228 }
10229 #endif /* WIFEXITED */
10230
10231
10232 #ifdef WEXITSTATUS
10233 /*[clinic input]
10234 os.WEXITSTATUS -> int
10235
10236 status: int
10237
10238 Return the process return code from status.
10239 [clinic start generated code]*/
10240
10241 static int
os_WEXITSTATUS_impl(PyObject * module,int status)10242 os_WEXITSTATUS_impl(PyObject *module, int status)
10243 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
10244 {
10245 WAIT_TYPE wait_status;
10246 WAIT_STATUS_INT(wait_status) = status;
10247 return WEXITSTATUS(wait_status);
10248 }
10249 #endif /* WEXITSTATUS */
10250
10251
10252 #ifdef WTERMSIG
10253 /*[clinic input]
10254 os.WTERMSIG -> int
10255
10256 status: int
10257
10258 Return the signal that terminated the process that provided the status value.
10259 [clinic start generated code]*/
10260
10261 static int
os_WTERMSIG_impl(PyObject * module,int status)10262 os_WTERMSIG_impl(PyObject *module, int status)
10263 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
10264 {
10265 WAIT_TYPE wait_status;
10266 WAIT_STATUS_INT(wait_status) = status;
10267 return WTERMSIG(wait_status);
10268 }
10269 #endif /* WTERMSIG */
10270
10271
10272 #ifdef WSTOPSIG
10273 /*[clinic input]
10274 os.WSTOPSIG -> int
10275
10276 status: int
10277
10278 Return the signal that stopped the process that provided the status value.
10279 [clinic start generated code]*/
10280
10281 static int
os_WSTOPSIG_impl(PyObject * module,int status)10282 os_WSTOPSIG_impl(PyObject *module, int status)
10283 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
10284 {
10285 WAIT_TYPE wait_status;
10286 WAIT_STATUS_INT(wait_status) = status;
10287 return WSTOPSIG(wait_status);
10288 }
10289 #endif /* WSTOPSIG */
10290 #endif /* HAVE_SYS_WAIT_H */
10291
10292
10293 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
10294 #ifdef _SCO_DS
10295 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
10296 needed definitions in sys/statvfs.h */
10297 #define _SVID3
10298 #endif
10299 #include <sys/statvfs.h>
10300
10301 static PyObject*
_pystatvfs_fromstructstatvfs(struct statvfs st)10302 _pystatvfs_fromstructstatvfs(struct statvfs st) {
10303 PyObject *v = PyStructSequence_New(StatVFSResultType);
10304 if (v == NULL)
10305 return NULL;
10306
10307 #if !defined(HAVE_LARGEFILE_SUPPORT)
10308 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
10309 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
10310 PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
10311 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
10312 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
10313 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
10314 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
10315 PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
10316 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
10317 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
10318 #else
10319 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
10320 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
10321 PyStructSequence_SET_ITEM(v, 2,
10322 PyLong_FromLongLong((long long) st.f_blocks));
10323 PyStructSequence_SET_ITEM(v, 3,
10324 PyLong_FromLongLong((long long) st.f_bfree));
10325 PyStructSequence_SET_ITEM(v, 4,
10326 PyLong_FromLongLong((long long) st.f_bavail));
10327 PyStructSequence_SET_ITEM(v, 5,
10328 PyLong_FromLongLong((long long) st.f_files));
10329 PyStructSequence_SET_ITEM(v, 6,
10330 PyLong_FromLongLong((long long) st.f_ffree));
10331 PyStructSequence_SET_ITEM(v, 7,
10332 PyLong_FromLongLong((long long) st.f_favail));
10333 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
10334 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
10335 #endif
10336 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
10337 * (issue #32390). */
10338 #if defined(_AIX) && defined(_ALL_SOURCE)
10339 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
10340 #else
10341 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
10342 #endif
10343 if (PyErr_Occurred()) {
10344 Py_DECREF(v);
10345 return NULL;
10346 }
10347
10348 return v;
10349 }
10350
10351
10352 /*[clinic input]
10353 os.fstatvfs
10354 fd: int
10355 /
10356
10357 Perform an fstatvfs system call on the given fd.
10358
10359 Equivalent to statvfs(fd).
10360 [clinic start generated code]*/
10361
10362 static PyObject *
os_fstatvfs_impl(PyObject * module,int fd)10363 os_fstatvfs_impl(PyObject *module, int fd)
10364 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
10365 {
10366 int result;
10367 int async_err = 0;
10368 struct statvfs st;
10369
10370 do {
10371 Py_BEGIN_ALLOW_THREADS
10372 result = fstatvfs(fd, &st);
10373 Py_END_ALLOW_THREADS
10374 } while (result != 0 && errno == EINTR &&
10375 !(async_err = PyErr_CheckSignals()));
10376 if (result != 0)
10377 return (!async_err) ? posix_error() : NULL;
10378
10379 return _pystatvfs_fromstructstatvfs(st);
10380 }
10381 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
10382
10383
10384 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
10385 #include <sys/statvfs.h>
10386 /*[clinic input]
10387 os.statvfs
10388
10389 path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
10390
10391 Perform a statvfs system call on the given path.
10392
10393 path may always be specified as a string.
10394 On some platforms, path may also be specified as an open file descriptor.
10395 If this functionality is unavailable, using it raises an exception.
10396 [clinic start generated code]*/
10397
10398 static PyObject *
os_statvfs_impl(PyObject * module,path_t * path)10399 os_statvfs_impl(PyObject *module, path_t *path)
10400 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
10401 {
10402 int result;
10403 struct statvfs st;
10404
10405 Py_BEGIN_ALLOW_THREADS
10406 #ifdef HAVE_FSTATVFS
10407 if (path->fd != -1) {
10408 #ifdef __APPLE__
10409 /* handle weak-linking on Mac OS X 10.3 */
10410 if (fstatvfs == NULL) {
10411 fd_specified("statvfs", path->fd);
10412 return NULL;
10413 }
10414 #endif
10415 result = fstatvfs(path->fd, &st);
10416 }
10417 else
10418 #endif
10419 result = statvfs(path->narrow, &st);
10420 Py_END_ALLOW_THREADS
10421
10422 if (result) {
10423 return path_error(path);
10424 }
10425
10426 return _pystatvfs_fromstructstatvfs(st);
10427 }
10428 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
10429
10430
10431 #ifdef MS_WINDOWS
10432 /*[clinic input]
10433 os._getdiskusage
10434
10435 path: path_t
10436
10437 Return disk usage statistics about the given path as a (total, free) tuple.
10438 [clinic start generated code]*/
10439
10440 static PyObject *
os__getdiskusage_impl(PyObject * module,path_t * path)10441 os__getdiskusage_impl(PyObject *module, path_t *path)
10442 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
10443 {
10444 BOOL retval;
10445 ULARGE_INTEGER _, total, free;
10446 DWORD err = 0;
10447
10448 Py_BEGIN_ALLOW_THREADS
10449 retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
10450 Py_END_ALLOW_THREADS
10451 if (retval == 0) {
10452 if (GetLastError() == ERROR_DIRECTORY) {
10453 wchar_t *dir_path = NULL;
10454
10455 dir_path = PyMem_New(wchar_t, path->length + 1);
10456 if (dir_path == NULL) {
10457 return PyErr_NoMemory();
10458 }
10459
10460 wcscpy_s(dir_path, path->length + 1, path->wide);
10461
10462 if (_dirnameW(dir_path) != -1) {
10463 Py_BEGIN_ALLOW_THREADS
10464 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
10465 Py_END_ALLOW_THREADS
10466 }
10467 /* Record the last error in case it's modified by PyMem_Free. */
10468 err = GetLastError();
10469 PyMem_Free(dir_path);
10470 if (retval) {
10471 goto success;
10472 }
10473 }
10474 return PyErr_SetFromWindowsErr(err);
10475 }
10476
10477 success:
10478 return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
10479 }
10480 #endif /* MS_WINDOWS */
10481
10482
10483 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
10484 * It maps strings representing configuration variable names to
10485 * integer values, allowing those functions to be called with the
10486 * magic names instead of polluting the module's namespace with tons of
10487 * rarely-used constants. There are three separate tables that use
10488 * these definitions.
10489 *
10490 * This code is always included, even if none of the interfaces that
10491 * need it are included. The #if hackery needed to avoid it would be
10492 * sufficiently pervasive that it's not worth the loss of readability.
10493 */
10494 struct constdef {
10495 const char *name;
10496 int value;
10497 };
10498
10499 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)10500 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
10501 size_t tablesize)
10502 {
10503 if (PyLong_Check(arg)) {
10504 int value = _PyLong_AsInt(arg);
10505 if (value == -1 && PyErr_Occurred())
10506 return 0;
10507 *valuep = value;
10508 return 1;
10509 }
10510 else {
10511 /* look up the value in the table using a binary search */
10512 size_t lo = 0;
10513 size_t mid;
10514 size_t hi = tablesize;
10515 int cmp;
10516 const char *confname;
10517 if (!PyUnicode_Check(arg)) {
10518 PyErr_SetString(PyExc_TypeError,
10519 "configuration names must be strings or integers");
10520 return 0;
10521 }
10522 confname = PyUnicode_AsUTF8(arg);
10523 if (confname == NULL)
10524 return 0;
10525 while (lo < hi) {
10526 mid = (lo + hi) / 2;
10527 cmp = strcmp(confname, table[mid].name);
10528 if (cmp < 0)
10529 hi = mid;
10530 else if (cmp > 0)
10531 lo = mid + 1;
10532 else {
10533 *valuep = table[mid].value;
10534 return 1;
10535 }
10536 }
10537 PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
10538 return 0;
10539 }
10540 }
10541
10542
10543 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
10544 static struct constdef posix_constants_pathconf[] = {
10545 #ifdef _PC_ABI_AIO_XFER_MAX
10546 {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
10547 #endif
10548 #ifdef _PC_ABI_ASYNC_IO
10549 {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
10550 #endif
10551 #ifdef _PC_ASYNC_IO
10552 {"PC_ASYNC_IO", _PC_ASYNC_IO},
10553 #endif
10554 #ifdef _PC_CHOWN_RESTRICTED
10555 {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
10556 #endif
10557 #ifdef _PC_FILESIZEBITS
10558 {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
10559 #endif
10560 #ifdef _PC_LAST
10561 {"PC_LAST", _PC_LAST},
10562 #endif
10563 #ifdef _PC_LINK_MAX
10564 {"PC_LINK_MAX", _PC_LINK_MAX},
10565 #endif
10566 #ifdef _PC_MAX_CANON
10567 {"PC_MAX_CANON", _PC_MAX_CANON},
10568 #endif
10569 #ifdef _PC_MAX_INPUT
10570 {"PC_MAX_INPUT", _PC_MAX_INPUT},
10571 #endif
10572 #ifdef _PC_NAME_MAX
10573 {"PC_NAME_MAX", _PC_NAME_MAX},
10574 #endif
10575 #ifdef _PC_NO_TRUNC
10576 {"PC_NO_TRUNC", _PC_NO_TRUNC},
10577 #endif
10578 #ifdef _PC_PATH_MAX
10579 {"PC_PATH_MAX", _PC_PATH_MAX},
10580 #endif
10581 #ifdef _PC_PIPE_BUF
10582 {"PC_PIPE_BUF", _PC_PIPE_BUF},
10583 #endif
10584 #ifdef _PC_PRIO_IO
10585 {"PC_PRIO_IO", _PC_PRIO_IO},
10586 #endif
10587 #ifdef _PC_SOCK_MAXBUF
10588 {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
10589 #endif
10590 #ifdef _PC_SYNC_IO
10591 {"PC_SYNC_IO", _PC_SYNC_IO},
10592 #endif
10593 #ifdef _PC_VDISABLE
10594 {"PC_VDISABLE", _PC_VDISABLE},
10595 #endif
10596 #ifdef _PC_ACL_ENABLED
10597 {"PC_ACL_ENABLED", _PC_ACL_ENABLED},
10598 #endif
10599 #ifdef _PC_MIN_HOLE_SIZE
10600 {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE},
10601 #endif
10602 #ifdef _PC_ALLOC_SIZE_MIN
10603 {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN},
10604 #endif
10605 #ifdef _PC_REC_INCR_XFER_SIZE
10606 {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE},
10607 #endif
10608 #ifdef _PC_REC_MAX_XFER_SIZE
10609 {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE},
10610 #endif
10611 #ifdef _PC_REC_MIN_XFER_SIZE
10612 {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE},
10613 #endif
10614 #ifdef _PC_REC_XFER_ALIGN
10615 {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN},
10616 #endif
10617 #ifdef _PC_SYMLINK_MAX
10618 {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX},
10619 #endif
10620 #ifdef _PC_XATTR_ENABLED
10621 {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED},
10622 #endif
10623 #ifdef _PC_XATTR_EXISTS
10624 {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
10625 #endif
10626 #ifdef _PC_TIMESTAMP_RESOLUTION
10627 {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
10628 #endif
10629 };
10630
10631 static int
conv_path_confname(PyObject * arg,int * valuep)10632 conv_path_confname(PyObject *arg, int *valuep)
10633 {
10634 return conv_confname(arg, valuep, posix_constants_pathconf,
10635 sizeof(posix_constants_pathconf)
10636 / sizeof(struct constdef));
10637 }
10638 #endif
10639
10640
10641 #ifdef HAVE_FPATHCONF
10642 /*[clinic input]
10643 os.fpathconf -> long
10644
10645 fd: int
10646 name: path_confname
10647 /
10648
10649 Return the configuration limit name for the file descriptor fd.
10650
10651 If there is no limit, return -1.
10652 [clinic start generated code]*/
10653
10654 static long
os_fpathconf_impl(PyObject * module,int fd,int name)10655 os_fpathconf_impl(PyObject *module, int fd, int name)
10656 /*[clinic end generated code: output=d5b7042425fc3e21 input=5942a024d3777810]*/
10657 {
10658 long limit;
10659
10660 errno = 0;
10661 limit = fpathconf(fd, name);
10662 if (limit == -1 && errno != 0)
10663 posix_error();
10664
10665 return limit;
10666 }
10667 #endif /* HAVE_FPATHCONF */
10668
10669
10670 #ifdef HAVE_PATHCONF
10671 /*[clinic input]
10672 os.pathconf -> long
10673 path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
10674 name: path_confname
10675
10676 Return the configuration limit name for the file or directory path.
10677
10678 If there is no limit, return -1.
10679 On some platforms, path may also be specified as an open file descriptor.
10680 If this functionality is unavailable, using it raises an exception.
10681 [clinic start generated code]*/
10682
10683 static long
os_pathconf_impl(PyObject * module,path_t * path,int name)10684 os_pathconf_impl(PyObject *module, path_t *path, int name)
10685 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
10686 {
10687 long limit;
10688
10689 errno = 0;
10690 #ifdef HAVE_FPATHCONF
10691 if (path->fd != -1)
10692 limit = fpathconf(path->fd, name);
10693 else
10694 #endif
10695 limit = pathconf(path->narrow, name);
10696 if (limit == -1 && errno != 0) {
10697 if (errno == EINVAL)
10698 /* could be a path or name problem */
10699 posix_error();
10700 else
10701 path_error(path);
10702 }
10703
10704 return limit;
10705 }
10706 #endif /* HAVE_PATHCONF */
10707
10708 #ifdef HAVE_CONFSTR
10709 static struct constdef posix_constants_confstr[] = {
10710 #ifdef _CS_ARCHITECTURE
10711 {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
10712 #endif
10713 #ifdef _CS_GNU_LIBC_VERSION
10714 {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION},
10715 #endif
10716 #ifdef _CS_GNU_LIBPTHREAD_VERSION
10717 {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION},
10718 #endif
10719 #ifdef _CS_HOSTNAME
10720 {"CS_HOSTNAME", _CS_HOSTNAME},
10721 #endif
10722 #ifdef _CS_HW_PROVIDER
10723 {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
10724 #endif
10725 #ifdef _CS_HW_SERIAL
10726 {"CS_HW_SERIAL", _CS_HW_SERIAL},
10727 #endif
10728 #ifdef _CS_INITTAB_NAME
10729 {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
10730 #endif
10731 #ifdef _CS_LFS64_CFLAGS
10732 {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
10733 #endif
10734 #ifdef _CS_LFS64_LDFLAGS
10735 {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
10736 #endif
10737 #ifdef _CS_LFS64_LIBS
10738 {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
10739 #endif
10740 #ifdef _CS_LFS64_LINTFLAGS
10741 {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
10742 #endif
10743 #ifdef _CS_LFS_CFLAGS
10744 {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
10745 #endif
10746 #ifdef _CS_LFS_LDFLAGS
10747 {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
10748 #endif
10749 #ifdef _CS_LFS_LIBS
10750 {"CS_LFS_LIBS", _CS_LFS_LIBS},
10751 #endif
10752 #ifdef _CS_LFS_LINTFLAGS
10753 {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
10754 #endif
10755 #ifdef _CS_MACHINE
10756 {"CS_MACHINE", _CS_MACHINE},
10757 #endif
10758 #ifdef _CS_PATH
10759 {"CS_PATH", _CS_PATH},
10760 #endif
10761 #ifdef _CS_RELEASE
10762 {"CS_RELEASE", _CS_RELEASE},
10763 #endif
10764 #ifdef _CS_SRPC_DOMAIN
10765 {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
10766 #endif
10767 #ifdef _CS_SYSNAME
10768 {"CS_SYSNAME", _CS_SYSNAME},
10769 #endif
10770 #ifdef _CS_VERSION
10771 {"CS_VERSION", _CS_VERSION},
10772 #endif
10773 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
10774 {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
10775 #endif
10776 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
10777 {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
10778 #endif
10779 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
10780 {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
10781 #endif
10782 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
10783 {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
10784 #endif
10785 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
10786 {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
10787 #endif
10788 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
10789 {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
10790 #endif
10791 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
10792 {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
10793 #endif
10794 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
10795 {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
10796 #endif
10797 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
10798 {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
10799 #endif
10800 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
10801 {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
10802 #endif
10803 #ifdef _CS_XBS5_LP64_OFF64_LIBS
10804 {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
10805 #endif
10806 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
10807 {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
10808 #endif
10809 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
10810 {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
10811 #endif
10812 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
10813 {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
10814 #endif
10815 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
10816 {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
10817 #endif
10818 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
10819 {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
10820 #endif
10821 #ifdef _MIPS_CS_AVAIL_PROCESSORS
10822 {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
10823 #endif
10824 #ifdef _MIPS_CS_BASE
10825 {"MIPS_CS_BASE", _MIPS_CS_BASE},
10826 #endif
10827 #ifdef _MIPS_CS_HOSTID
10828 {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
10829 #endif
10830 #ifdef _MIPS_CS_HW_NAME
10831 {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
10832 #endif
10833 #ifdef _MIPS_CS_NUM_PROCESSORS
10834 {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
10835 #endif
10836 #ifdef _MIPS_CS_OSREL_MAJ
10837 {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
10838 #endif
10839 #ifdef _MIPS_CS_OSREL_MIN
10840 {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
10841 #endif
10842 #ifdef _MIPS_CS_OSREL_PATCH
10843 {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
10844 #endif
10845 #ifdef _MIPS_CS_OS_NAME
10846 {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
10847 #endif
10848 #ifdef _MIPS_CS_OS_PROVIDER
10849 {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
10850 #endif
10851 #ifdef _MIPS_CS_PROCESSORS
10852 {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
10853 #endif
10854 #ifdef _MIPS_CS_SERIAL
10855 {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
10856 #endif
10857 #ifdef _MIPS_CS_VENDOR
10858 {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
10859 #endif
10860 };
10861
10862 static int
conv_confstr_confname(PyObject * arg,int * valuep)10863 conv_confstr_confname(PyObject *arg, int *valuep)
10864 {
10865 return conv_confname(arg, valuep, posix_constants_confstr,
10866 sizeof(posix_constants_confstr)
10867 / sizeof(struct constdef));
10868 }
10869
10870
10871 /*[clinic input]
10872 os.confstr
10873
10874 name: confstr_confname
10875 /
10876
10877 Return a string-valued system configuration variable.
10878 [clinic start generated code]*/
10879
10880 static PyObject *
os_confstr_impl(PyObject * module,int name)10881 os_confstr_impl(PyObject *module, int name)
10882 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
10883 {
10884 PyObject *result = NULL;
10885 char buffer[255];
10886 size_t len;
10887
10888 errno = 0;
10889 len = confstr(name, buffer, sizeof(buffer));
10890 if (len == 0) {
10891 if (errno) {
10892 posix_error();
10893 return NULL;
10894 }
10895 else {
10896 Py_RETURN_NONE;
10897 }
10898 }
10899
10900 if (len >= sizeof(buffer)) {
10901 size_t len2;
10902 char *buf = PyMem_Malloc(len);
10903 if (buf == NULL)
10904 return PyErr_NoMemory();
10905 len2 = confstr(name, buf, len);
10906 assert(len == len2);
10907 result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
10908 PyMem_Free(buf);
10909 }
10910 else
10911 result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
10912 return result;
10913 }
10914 #endif /* HAVE_CONFSTR */
10915
10916
10917 #ifdef HAVE_SYSCONF
10918 static struct constdef posix_constants_sysconf[] = {
10919 #ifdef _SC_2_CHAR_TERM
10920 {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
10921 #endif
10922 #ifdef _SC_2_C_BIND
10923 {"SC_2_C_BIND", _SC_2_C_BIND},
10924 #endif
10925 #ifdef _SC_2_C_DEV
10926 {"SC_2_C_DEV", _SC_2_C_DEV},
10927 #endif
10928 #ifdef _SC_2_C_VERSION
10929 {"SC_2_C_VERSION", _SC_2_C_VERSION},
10930 #endif
10931 #ifdef _SC_2_FORT_DEV
10932 {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
10933 #endif
10934 #ifdef _SC_2_FORT_RUN
10935 {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
10936 #endif
10937 #ifdef _SC_2_LOCALEDEF
10938 {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
10939 #endif
10940 #ifdef _SC_2_SW_DEV
10941 {"SC_2_SW_DEV", _SC_2_SW_DEV},
10942 #endif
10943 #ifdef _SC_2_UPE
10944 {"SC_2_UPE", _SC_2_UPE},
10945 #endif
10946 #ifdef _SC_2_VERSION
10947 {"SC_2_VERSION", _SC_2_VERSION},
10948 #endif
10949 #ifdef _SC_ABI_ASYNCHRONOUS_IO
10950 {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
10951 #endif
10952 #ifdef _SC_ACL
10953 {"SC_ACL", _SC_ACL},
10954 #endif
10955 #ifdef _SC_AIO_LISTIO_MAX
10956 {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
10957 #endif
10958 #ifdef _SC_AIO_MAX
10959 {"SC_AIO_MAX", _SC_AIO_MAX},
10960 #endif
10961 #ifdef _SC_AIO_PRIO_DELTA_MAX
10962 {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
10963 #endif
10964 #ifdef _SC_ARG_MAX
10965 {"SC_ARG_MAX", _SC_ARG_MAX},
10966 #endif
10967 #ifdef _SC_ASYNCHRONOUS_IO
10968 {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
10969 #endif
10970 #ifdef _SC_ATEXIT_MAX
10971 {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
10972 #endif
10973 #ifdef _SC_AUDIT
10974 {"SC_AUDIT", _SC_AUDIT},
10975 #endif
10976 #ifdef _SC_AVPHYS_PAGES
10977 {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
10978 #endif
10979 #ifdef _SC_BC_BASE_MAX
10980 {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
10981 #endif
10982 #ifdef _SC_BC_DIM_MAX
10983 {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
10984 #endif
10985 #ifdef _SC_BC_SCALE_MAX
10986 {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
10987 #endif
10988 #ifdef _SC_BC_STRING_MAX
10989 {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
10990 #endif
10991 #ifdef _SC_CAP
10992 {"SC_CAP", _SC_CAP},
10993 #endif
10994 #ifdef _SC_CHARCLASS_NAME_MAX
10995 {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
10996 #endif
10997 #ifdef _SC_CHAR_BIT
10998 {"SC_CHAR_BIT", _SC_CHAR_BIT},
10999 #endif
11000 #ifdef _SC_CHAR_MAX
11001 {"SC_CHAR_MAX", _SC_CHAR_MAX},
11002 #endif
11003 #ifdef _SC_CHAR_MIN
11004 {"SC_CHAR_MIN", _SC_CHAR_MIN},
11005 #endif
11006 #ifdef _SC_CHILD_MAX
11007 {"SC_CHILD_MAX", _SC_CHILD_MAX},
11008 #endif
11009 #ifdef _SC_CLK_TCK
11010 {"SC_CLK_TCK", _SC_CLK_TCK},
11011 #endif
11012 #ifdef _SC_COHER_BLKSZ
11013 {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
11014 #endif
11015 #ifdef _SC_COLL_WEIGHTS_MAX
11016 {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
11017 #endif
11018 #ifdef _SC_DCACHE_ASSOC
11019 {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
11020 #endif
11021 #ifdef _SC_DCACHE_BLKSZ
11022 {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
11023 #endif
11024 #ifdef _SC_DCACHE_LINESZ
11025 {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
11026 #endif
11027 #ifdef _SC_DCACHE_SZ
11028 {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
11029 #endif
11030 #ifdef _SC_DCACHE_TBLKSZ
11031 {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
11032 #endif
11033 #ifdef _SC_DELAYTIMER_MAX
11034 {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
11035 #endif
11036 #ifdef _SC_EQUIV_CLASS_MAX
11037 {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
11038 #endif
11039 #ifdef _SC_EXPR_NEST_MAX
11040 {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
11041 #endif
11042 #ifdef _SC_FSYNC
11043 {"SC_FSYNC", _SC_FSYNC},
11044 #endif
11045 #ifdef _SC_GETGR_R_SIZE_MAX
11046 {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
11047 #endif
11048 #ifdef _SC_GETPW_R_SIZE_MAX
11049 {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
11050 #endif
11051 #ifdef _SC_ICACHE_ASSOC
11052 {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
11053 #endif
11054 #ifdef _SC_ICACHE_BLKSZ
11055 {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
11056 #endif
11057 #ifdef _SC_ICACHE_LINESZ
11058 {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
11059 #endif
11060 #ifdef _SC_ICACHE_SZ
11061 {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
11062 #endif
11063 #ifdef _SC_INF
11064 {"SC_INF", _SC_INF},
11065 #endif
11066 #ifdef _SC_INT_MAX
11067 {"SC_INT_MAX", _SC_INT_MAX},
11068 #endif
11069 #ifdef _SC_INT_MIN
11070 {"SC_INT_MIN", _SC_INT_MIN},
11071 #endif
11072 #ifdef _SC_IOV_MAX
11073 {"SC_IOV_MAX", _SC_IOV_MAX},
11074 #endif
11075 #ifdef _SC_IP_SECOPTS
11076 {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
11077 #endif
11078 #ifdef _SC_JOB_CONTROL
11079 {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
11080 #endif
11081 #ifdef _SC_KERN_POINTERS
11082 {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
11083 #endif
11084 #ifdef _SC_KERN_SIM
11085 {"SC_KERN_SIM", _SC_KERN_SIM},
11086 #endif
11087 #ifdef _SC_LINE_MAX
11088 {"SC_LINE_MAX", _SC_LINE_MAX},
11089 #endif
11090 #ifdef _SC_LOGIN_NAME_MAX
11091 {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
11092 #endif
11093 #ifdef _SC_LOGNAME_MAX
11094 {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
11095 #endif
11096 #ifdef _SC_LONG_BIT
11097 {"SC_LONG_BIT", _SC_LONG_BIT},
11098 #endif
11099 #ifdef _SC_MAC
11100 {"SC_MAC", _SC_MAC},
11101 #endif
11102 #ifdef _SC_MAPPED_FILES
11103 {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
11104 #endif
11105 #ifdef _SC_MAXPID
11106 {"SC_MAXPID", _SC_MAXPID},
11107 #endif
11108 #ifdef _SC_MB_LEN_MAX
11109 {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
11110 #endif
11111 #ifdef _SC_MEMLOCK
11112 {"SC_MEMLOCK", _SC_MEMLOCK},
11113 #endif
11114 #ifdef _SC_MEMLOCK_RANGE
11115 {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
11116 #endif
11117 #ifdef _SC_MEMORY_PROTECTION
11118 {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
11119 #endif
11120 #ifdef _SC_MESSAGE_PASSING
11121 {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
11122 #endif
11123 #ifdef _SC_MMAP_FIXED_ALIGNMENT
11124 {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
11125 #endif
11126 #ifdef _SC_MQ_OPEN_MAX
11127 {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
11128 #endif
11129 #ifdef _SC_MQ_PRIO_MAX
11130 {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},
11131 #endif
11132 #ifdef _SC_NACLS_MAX
11133 {"SC_NACLS_MAX", _SC_NACLS_MAX},
11134 #endif
11135 #ifdef _SC_NGROUPS_MAX
11136 {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX},
11137 #endif
11138 #ifdef _SC_NL_ARGMAX
11139 {"SC_NL_ARGMAX", _SC_NL_ARGMAX},
11140 #endif
11141 #ifdef _SC_NL_LANGMAX
11142 {"SC_NL_LANGMAX", _SC_NL_LANGMAX},
11143 #endif
11144 #ifdef _SC_NL_MSGMAX
11145 {"SC_NL_MSGMAX", _SC_NL_MSGMAX},
11146 #endif
11147 #ifdef _SC_NL_NMAX
11148 {"SC_NL_NMAX", _SC_NL_NMAX},
11149 #endif
11150 #ifdef _SC_NL_SETMAX
11151 {"SC_NL_SETMAX", _SC_NL_SETMAX},
11152 #endif
11153 #ifdef _SC_NL_TEXTMAX
11154 {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX},
11155 #endif
11156 #ifdef _SC_NPROCESSORS_CONF
11157 {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
11158 #endif
11159 #ifdef _SC_NPROCESSORS_ONLN
11160 {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
11161 #endif
11162 #ifdef _SC_NPROC_CONF
11163 {"SC_NPROC_CONF", _SC_NPROC_CONF},
11164 #endif
11165 #ifdef _SC_NPROC_ONLN
11166 {"SC_NPROC_ONLN", _SC_NPROC_ONLN},
11167 #endif
11168 #ifdef _SC_NZERO
11169 {"SC_NZERO", _SC_NZERO},
11170 #endif
11171 #ifdef _SC_OPEN_MAX
11172 {"SC_OPEN_MAX", _SC_OPEN_MAX},
11173 #endif
11174 #ifdef _SC_PAGESIZE
11175 {"SC_PAGESIZE", _SC_PAGESIZE},
11176 #endif
11177 #ifdef _SC_PAGE_SIZE
11178 {"SC_PAGE_SIZE", _SC_PAGE_SIZE},
11179 #endif
11180 #ifdef _SC_PASS_MAX
11181 {"SC_PASS_MAX", _SC_PASS_MAX},
11182 #endif
11183 #ifdef _SC_PHYS_PAGES
11184 {"SC_PHYS_PAGES", _SC_PHYS_PAGES},
11185 #endif
11186 #ifdef _SC_PII
11187 {"SC_PII", _SC_PII},
11188 #endif
11189 #ifdef _SC_PII_INTERNET
11190 {"SC_PII_INTERNET", _SC_PII_INTERNET},
11191 #endif
11192 #ifdef _SC_PII_INTERNET_DGRAM
11193 {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM},
11194 #endif
11195 #ifdef _SC_PII_INTERNET_STREAM
11196 {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM},
11197 #endif
11198 #ifdef _SC_PII_OSI
11199 {"SC_PII_OSI", _SC_PII_OSI},
11200 #endif
11201 #ifdef _SC_PII_OSI_CLTS
11202 {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
11203 #endif
11204 #ifdef _SC_PII_OSI_COTS
11205 {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
11206 #endif
11207 #ifdef _SC_PII_OSI_M
11208 {"SC_PII_OSI_M", _SC_PII_OSI_M},
11209 #endif
11210 #ifdef _SC_PII_SOCKET
11211 {"SC_PII_SOCKET", _SC_PII_SOCKET},
11212 #endif
11213 #ifdef _SC_PII_XTI
11214 {"SC_PII_XTI", _SC_PII_XTI},
11215 #endif
11216 #ifdef _SC_POLL
11217 {"SC_POLL", _SC_POLL},
11218 #endif
11219 #ifdef _SC_PRIORITIZED_IO
11220 {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO},
11221 #endif
11222 #ifdef _SC_PRIORITY_SCHEDULING
11223 {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING},
11224 #endif
11225 #ifdef _SC_REALTIME_SIGNALS
11226 {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS},
11227 #endif
11228 #ifdef _SC_RE_DUP_MAX
11229 {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX},
11230 #endif
11231 #ifdef _SC_RTSIG_MAX
11232 {"SC_RTSIG_MAX", _SC_RTSIG_MAX},
11233 #endif
11234 #ifdef _SC_SAVED_IDS
11235 {"SC_SAVED_IDS", _SC_SAVED_IDS},
11236 #endif
11237 #ifdef _SC_SCHAR_MAX
11238 {"SC_SCHAR_MAX", _SC_SCHAR_MAX},
11239 #endif
11240 #ifdef _SC_SCHAR_MIN
11241 {"SC_SCHAR_MIN", _SC_SCHAR_MIN},
11242 #endif
11243 #ifdef _SC_SELECT
11244 {"SC_SELECT", _SC_SELECT},
11245 #endif
11246 #ifdef _SC_SEMAPHORES
11247 {"SC_SEMAPHORES", _SC_SEMAPHORES},
11248 #endif
11249 #ifdef _SC_SEM_NSEMS_MAX
11250 {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX},
11251 #endif
11252 #ifdef _SC_SEM_VALUE_MAX
11253 {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX},
11254 #endif
11255 #ifdef _SC_SHARED_MEMORY_OBJECTS
11256 {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS},
11257 #endif
11258 #ifdef _SC_SHRT_MAX
11259 {"SC_SHRT_MAX", _SC_SHRT_MAX},
11260 #endif
11261 #ifdef _SC_SHRT_MIN
11262 {"SC_SHRT_MIN", _SC_SHRT_MIN},
11263 #endif
11264 #ifdef _SC_SIGQUEUE_MAX
11265 {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
11266 #endif
11267 #ifdef _SC_SIGRT_MAX
11268 {"SC_SIGRT_MAX", _SC_SIGRT_MAX},
11269 #endif
11270 #ifdef _SC_SIGRT_MIN
11271 {"SC_SIGRT_MIN", _SC_SIGRT_MIN},
11272 #endif
11273 #ifdef _SC_SOFTPOWER
11274 {"SC_SOFTPOWER", _SC_SOFTPOWER},
11275 #endif
11276 #ifdef _SC_SPLIT_CACHE
11277 {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE},
11278 #endif
11279 #ifdef _SC_SSIZE_MAX
11280 {"SC_SSIZE_MAX", _SC_SSIZE_MAX},
11281 #endif
11282 #ifdef _SC_STACK_PROT
11283 {"SC_STACK_PROT", _SC_STACK_PROT},
11284 #endif
11285 #ifdef _SC_STREAM_MAX
11286 {"SC_STREAM_MAX", _SC_STREAM_MAX},
11287 #endif
11288 #ifdef _SC_SYNCHRONIZED_IO
11289 {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO},
11290 #endif
11291 #ifdef _SC_THREADS
11292 {"SC_THREADS", _SC_THREADS},
11293 #endif
11294 #ifdef _SC_THREAD_ATTR_STACKADDR
11295 {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR},
11296 #endif
11297 #ifdef _SC_THREAD_ATTR_STACKSIZE
11298 {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE},
11299 #endif
11300 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
11301 {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
11302 #endif
11303 #ifdef _SC_THREAD_KEYS_MAX
11304 {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
11305 #endif
11306 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
11307 {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING},
11308 #endif
11309 #ifdef _SC_THREAD_PRIO_INHERIT
11310 {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT},
11311 #endif
11312 #ifdef _SC_THREAD_PRIO_PROTECT
11313 {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT},
11314 #endif
11315 #ifdef _SC_THREAD_PROCESS_SHARED
11316 {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED},
11317 #endif
11318 #ifdef _SC_THREAD_SAFE_FUNCTIONS
11319 {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS},
11320 #endif
11321 #ifdef _SC_THREAD_STACK_MIN
11322 {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
11323 #endif
11324 #ifdef _SC_THREAD_THREADS_MAX
11325 {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
11326 #endif
11327 #ifdef _SC_TIMERS
11328 {"SC_TIMERS", _SC_TIMERS},
11329 #endif
11330 #ifdef _SC_TIMER_MAX
11331 {"SC_TIMER_MAX", _SC_TIMER_MAX},
11332 #endif
11333 #ifdef _SC_TTY_NAME_MAX
11334 {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
11335 #endif
11336 #ifdef _SC_TZNAME_MAX
11337 {"SC_TZNAME_MAX", _SC_TZNAME_MAX},
11338 #endif
11339 #ifdef _SC_T_IOV_MAX
11340 {"SC_T_IOV_MAX", _SC_T_IOV_MAX},
11341 #endif
11342 #ifdef _SC_UCHAR_MAX
11343 {"SC_UCHAR_MAX", _SC_UCHAR_MAX},
11344 #endif
11345 #ifdef _SC_UINT_MAX
11346 {"SC_UINT_MAX", _SC_UINT_MAX},
11347 #endif
11348 #ifdef _SC_UIO_MAXIOV
11349 {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV},
11350 #endif
11351 #ifdef _SC_ULONG_MAX
11352 {"SC_ULONG_MAX", _SC_ULONG_MAX},
11353 #endif
11354 #ifdef _SC_USHRT_MAX
11355 {"SC_USHRT_MAX", _SC_USHRT_MAX},
11356 #endif
11357 #ifdef _SC_VERSION
11358 {"SC_VERSION", _SC_VERSION},
11359 #endif
11360 #ifdef _SC_WORD_BIT
11361 {"SC_WORD_BIT", _SC_WORD_BIT},
11362 #endif
11363 #ifdef _SC_XBS5_ILP32_OFF32
11364 {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32},
11365 #endif
11366 #ifdef _SC_XBS5_ILP32_OFFBIG
11367 {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG},
11368 #endif
11369 #ifdef _SC_XBS5_LP64_OFF64
11370 {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64},
11371 #endif
11372 #ifdef _SC_XBS5_LPBIG_OFFBIG
11373 {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG},
11374 #endif
11375 #ifdef _SC_XOPEN_CRYPT
11376 {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT},
11377 #endif
11378 #ifdef _SC_XOPEN_ENH_I18N
11379 {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N},
11380 #endif
11381 #ifdef _SC_XOPEN_LEGACY
11382 {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
11383 #endif
11384 #ifdef _SC_XOPEN_REALTIME
11385 {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME},
11386 #endif
11387 #ifdef _SC_XOPEN_REALTIME_THREADS
11388 {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS},
11389 #endif
11390 #ifdef _SC_XOPEN_SHM
11391 {"SC_XOPEN_SHM", _SC_XOPEN_SHM},
11392 #endif
11393 #ifdef _SC_XOPEN_UNIX
11394 {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX},
11395 #endif
11396 #ifdef _SC_XOPEN_VERSION
11397 {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION},
11398 #endif
11399 #ifdef _SC_XOPEN_XCU_VERSION
11400 {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION},
11401 #endif
11402 #ifdef _SC_XOPEN_XPG2
11403 {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2},
11404 #endif
11405 #ifdef _SC_XOPEN_XPG3
11406 {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3},
11407 #endif
11408 #ifdef _SC_XOPEN_XPG4
11409 {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4},
11410 #endif
11411 };
11412
11413 static int
conv_sysconf_confname(PyObject * arg,int * valuep)11414 conv_sysconf_confname(PyObject *arg, int *valuep)
11415 {
11416 return conv_confname(arg, valuep, posix_constants_sysconf,
11417 sizeof(posix_constants_sysconf)
11418 / sizeof(struct constdef));
11419 }
11420
11421
11422 /*[clinic input]
11423 os.sysconf -> long
11424 name: sysconf_confname
11425 /
11426
11427 Return an integer-valued system configuration variable.
11428 [clinic start generated code]*/
11429
11430 static long
os_sysconf_impl(PyObject * module,int name)11431 os_sysconf_impl(PyObject *module, int name)
11432 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
11433 {
11434 long value;
11435
11436 errno = 0;
11437 value = sysconf(name);
11438 if (value == -1 && errno != 0)
11439 posix_error();
11440 return value;
11441 }
11442 #endif /* HAVE_SYSCONF */
11443
11444
11445 /* This code is used to ensure that the tables of configuration value names
11446 * are in sorted order as required by conv_confname(), and also to build
11447 * the exported dictionaries that are used to publish information about the
11448 * names available on the host platform.
11449 *
11450 * Sorting the table at runtime ensures that the table is properly ordered
11451 * when used, even for platforms we're not able to test on. It also makes
11452 * it easier to add additional entries to the tables.
11453 */
11454
11455 static int
cmp_constdefs(const void * v1,const void * v2)11456 cmp_constdefs(const void *v1, const void *v2)
11457 {
11458 const struct constdef *c1 =
11459 (const struct constdef *) v1;
11460 const struct constdef *c2 =
11461 (const struct constdef *) v2;
11462
11463 return strcmp(c1->name, c2->name);
11464 }
11465
11466 static int
setup_confname_table(struct constdef * table,size_t tablesize,const char * tablename,PyObject * module)11467 setup_confname_table(struct constdef *table, size_t tablesize,
11468 const char *tablename, PyObject *module)
11469 {
11470 PyObject *d = NULL;
11471 size_t i;
11472
11473 qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
11474 d = PyDict_New();
11475 if (d == NULL)
11476 return -1;
11477
11478 for (i=0; i < tablesize; ++i) {
11479 PyObject *o = PyLong_FromLong(table[i].value);
11480 if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
11481 Py_XDECREF(o);
11482 Py_DECREF(d);
11483 return -1;
11484 }
11485 Py_DECREF(o);
11486 }
11487 return PyModule_AddObject(module, tablename, d);
11488 }
11489
11490 /* Return -1 on failure, 0 on success. */
11491 static int
setup_confname_tables(PyObject * module)11492 setup_confname_tables(PyObject *module)
11493 {
11494 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11495 if (setup_confname_table(posix_constants_pathconf,
11496 sizeof(posix_constants_pathconf)
11497 / sizeof(struct constdef),
11498 "pathconf_names", module))
11499 return -1;
11500 #endif
11501 #ifdef HAVE_CONFSTR
11502 if (setup_confname_table(posix_constants_confstr,
11503 sizeof(posix_constants_confstr)
11504 / sizeof(struct constdef),
11505 "confstr_names", module))
11506 return -1;
11507 #endif
11508 #ifdef HAVE_SYSCONF
11509 if (setup_confname_table(posix_constants_sysconf,
11510 sizeof(posix_constants_sysconf)
11511 / sizeof(struct constdef),
11512 "sysconf_names", module))
11513 return -1;
11514 #endif
11515 return 0;
11516 }
11517
11518
11519 /*[clinic input]
11520 os.abort
11521
11522 Abort the interpreter immediately.
11523
11524 This function 'dumps core' or otherwise fails in the hardest way possible
11525 on the hosting operating system. This function never returns.
11526 [clinic start generated code]*/
11527
11528 static PyObject *
os_abort_impl(PyObject * module)11529 os_abort_impl(PyObject *module)
11530 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
11531 {
11532 abort();
11533 /*NOTREACHED*/
11534 #ifndef __clang__
11535 /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
11536 GCC emits a warning without "return NULL;" (compiler bug?), but Clang
11537 is smarter and emits a warning on the return. */
11538 Py_FatalError("abort() called from Python code didn't abort!");
11539 return NULL;
11540 #endif
11541 }
11542
11543 #ifdef MS_WINDOWS
11544 /* Grab ShellExecute dynamically from shell32 */
11545 static int has_ShellExecute = -1;
11546 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
11547 LPCWSTR, INT);
11548 static int
check_ShellExecute()11549 check_ShellExecute()
11550 {
11551 HINSTANCE hShell32;
11552
11553 /* only recheck */
11554 if (-1 == has_ShellExecute) {
11555 Py_BEGIN_ALLOW_THREADS
11556 /* Security note: this call is not vulnerable to "DLL hijacking".
11557 SHELL32 is part of "KnownDLLs" and so Windows always load
11558 the system SHELL32.DLL, even if there is another SHELL32.DLL
11559 in the DLL search path. */
11560 hShell32 = LoadLibraryW(L"SHELL32");
11561 if (hShell32) {
11562 *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
11563 "ShellExecuteW");
11564 has_ShellExecute = Py_ShellExecuteW != NULL;
11565 } else {
11566 has_ShellExecute = 0;
11567 }
11568 Py_END_ALLOW_THREADS
11569 }
11570 return has_ShellExecute;
11571 }
11572
11573
11574 /*[clinic input]
11575 os.startfile
11576 filepath: path_t
11577 operation: Py_UNICODE = NULL
11578
11579 Start a file with its associated application.
11580
11581 When "operation" is not specified or "open", this acts like
11582 double-clicking the file in Explorer, or giving the file name as an
11583 argument to the DOS "start" command: the file is opened with whatever
11584 application (if any) its extension is associated.
11585 When another "operation" is given, it specifies what should be done with
11586 the file. A typical operation is "print".
11587
11588 startfile returns as soon as the associated application is launched.
11589 There is no option to wait for the application to close, and no way
11590 to retrieve the application's exit status.
11591
11592 The filepath is relative to the current directory. If you want to use
11593 an absolute path, make sure the first character is not a slash ("/");
11594 the underlying Win32 ShellExecute function doesn't work if it is.
11595 [clinic start generated code]*/
11596
11597 static PyObject *
os_startfile_impl(PyObject * module,path_t * filepath,const Py_UNICODE * operation)11598 os_startfile_impl(PyObject *module, path_t *filepath,
11599 const Py_UNICODE *operation)
11600 /*[clinic end generated code: output=66dc311c94d50797 input=c940888a5390f039]*/
11601 {
11602 HINSTANCE rc;
11603
11604 if(!check_ShellExecute()) {
11605 /* If the OS doesn't have ShellExecute, return a
11606 NotImplementedError. */
11607 return PyErr_Format(PyExc_NotImplementedError,
11608 "startfile not available on this platform");
11609 }
11610
11611 Py_BEGIN_ALLOW_THREADS
11612 rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
11613 NULL, NULL, SW_SHOWNORMAL);
11614 Py_END_ALLOW_THREADS
11615
11616 if (rc <= (HINSTANCE)32) {
11617 win32_error_object("startfile", filepath->object);
11618 return NULL;
11619 }
11620 Py_RETURN_NONE;
11621 }
11622 #endif /* MS_WINDOWS */
11623
11624
11625 #ifdef HAVE_GETLOADAVG
11626 /*[clinic input]
11627 os.getloadavg
11628
11629 Return average recent system load information.
11630
11631 Return the number of processes in the system run queue averaged over
11632 the last 1, 5, and 15 minutes as a tuple of three floats.
11633 Raises OSError if the load average was unobtainable.
11634 [clinic start generated code]*/
11635
11636 static PyObject *
os_getloadavg_impl(PyObject * module)11637 os_getloadavg_impl(PyObject *module)
11638 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
11639 {
11640 double loadavg[3];
11641 if (getloadavg(loadavg, 3)!=3) {
11642 PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
11643 return NULL;
11644 } else
11645 return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
11646 }
11647 #endif /* HAVE_GETLOADAVG */
11648
11649
11650 /*[clinic input]
11651 os.device_encoding
11652 fd: int
11653
11654 Return a string describing the encoding of a terminal's file descriptor.
11655
11656 The file descriptor must be attached to a terminal.
11657 If the device is not a terminal, return None.
11658 [clinic start generated code]*/
11659
11660 static PyObject *
os_device_encoding_impl(PyObject * module,int fd)11661 os_device_encoding_impl(PyObject *module, int fd)
11662 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
11663 {
11664 return _Py_device_encoding(fd);
11665 }
11666
11667
11668 #ifdef HAVE_SETRESUID
11669 /*[clinic input]
11670 os.setresuid
11671
11672 ruid: uid_t
11673 euid: uid_t
11674 suid: uid_t
11675 /
11676
11677 Set the current process's real, effective, and saved user ids.
11678 [clinic start generated code]*/
11679
11680 static PyObject *
os_setresuid_impl(PyObject * module,uid_t ruid,uid_t euid,uid_t suid)11681 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
11682 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
11683 {
11684 if (setresuid(ruid, euid, suid) < 0)
11685 return posix_error();
11686 Py_RETURN_NONE;
11687 }
11688 #endif /* HAVE_SETRESUID */
11689
11690
11691 #ifdef HAVE_SETRESGID
11692 /*[clinic input]
11693 os.setresgid
11694
11695 rgid: gid_t
11696 egid: gid_t
11697 sgid: gid_t
11698 /
11699
11700 Set the current process's real, effective, and saved group ids.
11701 [clinic start generated code]*/
11702
11703 static PyObject *
os_setresgid_impl(PyObject * module,gid_t rgid,gid_t egid,gid_t sgid)11704 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
11705 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
11706 {
11707 if (setresgid(rgid, egid, sgid) < 0)
11708 return posix_error();
11709 Py_RETURN_NONE;
11710 }
11711 #endif /* HAVE_SETRESGID */
11712
11713
11714 #ifdef HAVE_GETRESUID
11715 /*[clinic input]
11716 os.getresuid
11717
11718 Return a tuple of the current process's real, effective, and saved user ids.
11719 [clinic start generated code]*/
11720
11721 static PyObject *
os_getresuid_impl(PyObject * module)11722 os_getresuid_impl(PyObject *module)
11723 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
11724 {
11725 uid_t ruid, euid, suid;
11726 if (getresuid(&ruid, &euid, &suid) < 0)
11727 return posix_error();
11728 return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
11729 _PyLong_FromUid(euid),
11730 _PyLong_FromUid(suid));
11731 }
11732 #endif /* HAVE_GETRESUID */
11733
11734
11735 #ifdef HAVE_GETRESGID
11736 /*[clinic input]
11737 os.getresgid
11738
11739 Return a tuple of the current process's real, effective, and saved group ids.
11740 [clinic start generated code]*/
11741
11742 static PyObject *
os_getresgid_impl(PyObject * module)11743 os_getresgid_impl(PyObject *module)
11744 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
11745 {
11746 gid_t rgid, egid, sgid;
11747 if (getresgid(&rgid, &egid, &sgid) < 0)
11748 return posix_error();
11749 return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
11750 _PyLong_FromGid(egid),
11751 _PyLong_FromGid(sgid));
11752 }
11753 #endif /* HAVE_GETRESGID */
11754
11755
11756 #ifdef USE_XATTRS
11757 /*[clinic input]
11758 os.getxattr
11759
11760 path: path_t(allow_fd=True)
11761 attribute: path_t
11762 *
11763 follow_symlinks: bool = True
11764
11765 Return the value of extended attribute attribute on path.
11766
11767 path may be either a string, a path-like object, or an open file descriptor.
11768 If follow_symlinks is False, and the last element of the path is a symbolic
11769 link, getxattr will examine the symbolic link itself instead of the file
11770 the link points to.
11771
11772 [clinic start generated code]*/
11773
11774 static PyObject *
os_getxattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)11775 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
11776 int follow_symlinks)
11777 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
11778 {
11779 Py_ssize_t i;
11780 PyObject *buffer = NULL;
11781
11782 if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
11783 return NULL;
11784
11785 for (i = 0; ; i++) {
11786 void *ptr;
11787 ssize_t result;
11788 static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
11789 Py_ssize_t buffer_size = buffer_sizes[i];
11790 if (!buffer_size) {
11791 path_error(path);
11792 return NULL;
11793 }
11794 buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
11795 if (!buffer)
11796 return NULL;
11797 ptr = PyBytes_AS_STRING(buffer);
11798
11799 Py_BEGIN_ALLOW_THREADS;
11800 if (path->fd >= 0)
11801 result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
11802 else if (follow_symlinks)
11803 result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
11804 else
11805 result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
11806 Py_END_ALLOW_THREADS;
11807
11808 if (result < 0) {
11809 Py_DECREF(buffer);
11810 if (errno == ERANGE)
11811 continue;
11812 path_error(path);
11813 return NULL;
11814 }
11815
11816 if (result != buffer_size) {
11817 /* Can only shrink. */
11818 _PyBytes_Resize(&buffer, result);
11819 }
11820 break;
11821 }
11822
11823 return buffer;
11824 }
11825
11826
11827 /*[clinic input]
11828 os.setxattr
11829
11830 path: path_t(allow_fd=True)
11831 attribute: path_t
11832 value: Py_buffer
11833 flags: int = 0
11834 *
11835 follow_symlinks: bool = True
11836
11837 Set extended attribute attribute on path to value.
11838
11839 path may be either a string, a path-like object, or an open file descriptor.
11840 If follow_symlinks is False, and the last element of the path is a symbolic
11841 link, setxattr will modify the symbolic link itself instead of the file
11842 the link points to.
11843
11844 [clinic start generated code]*/
11845
11846 static PyObject *
os_setxattr_impl(PyObject * module,path_t * path,path_t * attribute,Py_buffer * value,int flags,int follow_symlinks)11847 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
11848 Py_buffer *value, int flags, int follow_symlinks)
11849 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
11850 {
11851 ssize_t result;
11852
11853 if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
11854 return NULL;
11855
11856 Py_BEGIN_ALLOW_THREADS;
11857 if (path->fd > -1)
11858 result = fsetxattr(path->fd, attribute->narrow,
11859 value->buf, value->len, flags);
11860 else if (follow_symlinks)
11861 result = setxattr(path->narrow, attribute->narrow,
11862 value->buf, value->len, flags);
11863 else
11864 result = lsetxattr(path->narrow, attribute->narrow,
11865 value->buf, value->len, flags);
11866 Py_END_ALLOW_THREADS;
11867
11868 if (result) {
11869 path_error(path);
11870 return NULL;
11871 }
11872
11873 Py_RETURN_NONE;
11874 }
11875
11876
11877 /*[clinic input]
11878 os.removexattr
11879
11880 path: path_t(allow_fd=True)
11881 attribute: path_t
11882 *
11883 follow_symlinks: bool = True
11884
11885 Remove extended attribute attribute on path.
11886
11887 path may be either a string, a path-like object, or an open file descriptor.
11888 If follow_symlinks is False, and the last element of the path is a symbolic
11889 link, removexattr will modify the symbolic link itself instead of the file
11890 the link points to.
11891
11892 [clinic start generated code]*/
11893
11894 static PyObject *
os_removexattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)11895 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
11896 int follow_symlinks)
11897 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
11898 {
11899 ssize_t result;
11900
11901 if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
11902 return NULL;
11903
11904 Py_BEGIN_ALLOW_THREADS;
11905 if (path->fd > -1)
11906 result = fremovexattr(path->fd, attribute->narrow);
11907 else if (follow_symlinks)
11908 result = removexattr(path->narrow, attribute->narrow);
11909 else
11910 result = lremovexattr(path->narrow, attribute->narrow);
11911 Py_END_ALLOW_THREADS;
11912
11913 if (result) {
11914 return path_error(path);
11915 }
11916
11917 Py_RETURN_NONE;
11918 }
11919
11920
11921 /*[clinic input]
11922 os.listxattr
11923
11924 path: path_t(allow_fd=True, nullable=True) = None
11925 *
11926 follow_symlinks: bool = True
11927
11928 Return a list of extended attributes on path.
11929
11930 path may be either None, a string, a path-like object, or an open file descriptor.
11931 if path is None, listxattr will examine the current directory.
11932 If follow_symlinks is False, and the last element of the path is a symbolic
11933 link, listxattr will examine the symbolic link itself instead of the file
11934 the link points to.
11935 [clinic start generated code]*/
11936
11937 static PyObject *
os_listxattr_impl(PyObject * module,path_t * path,int follow_symlinks)11938 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
11939 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
11940 {
11941 Py_ssize_t i;
11942 PyObject *result = NULL;
11943 const char *name;
11944 char *buffer = NULL;
11945
11946 if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
11947 goto exit;
11948
11949 name = path->narrow ? path->narrow : ".";
11950
11951 for (i = 0; ; i++) {
11952 const char *start, *trace, *end;
11953 ssize_t length;
11954 static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
11955 Py_ssize_t buffer_size = buffer_sizes[i];
11956 if (!buffer_size) {
11957 /* ERANGE */
11958 path_error(path);
11959 break;
11960 }
11961 buffer = PyMem_MALLOC(buffer_size);
11962 if (!buffer) {
11963 PyErr_NoMemory();
11964 break;
11965 }
11966
11967 Py_BEGIN_ALLOW_THREADS;
11968 if (path->fd > -1)
11969 length = flistxattr(path->fd, buffer, buffer_size);
11970 else if (follow_symlinks)
11971 length = listxattr(name, buffer, buffer_size);
11972 else
11973 length = llistxattr(name, buffer, buffer_size);
11974 Py_END_ALLOW_THREADS;
11975
11976 if (length < 0) {
11977 if (errno == ERANGE) {
11978 PyMem_FREE(buffer);
11979 buffer = NULL;
11980 continue;
11981 }
11982 path_error(path);
11983 break;
11984 }
11985
11986 result = PyList_New(0);
11987 if (!result) {
11988 goto exit;
11989 }
11990
11991 end = buffer + length;
11992 for (trace = start = buffer; trace != end; trace++) {
11993 if (!*trace) {
11994 int error;
11995 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
11996 trace - start);
11997 if (!attribute) {
11998 Py_DECREF(result);
11999 result = NULL;
12000 goto exit;
12001 }
12002 error = PyList_Append(result, attribute);
12003 Py_DECREF(attribute);
12004 if (error) {
12005 Py_DECREF(result);
12006 result = NULL;
12007 goto exit;
12008 }
12009 start = trace + 1;
12010 }
12011 }
12012 break;
12013 }
12014 exit:
12015 if (buffer)
12016 PyMem_FREE(buffer);
12017 return result;
12018 }
12019 #endif /* USE_XATTRS */
12020
12021
12022 /*[clinic input]
12023 os.urandom
12024
12025 size: Py_ssize_t
12026 /
12027
12028 Return a bytes object containing random bytes suitable for cryptographic use.
12029 [clinic start generated code]*/
12030
12031 static PyObject *
os_urandom_impl(PyObject * module,Py_ssize_t size)12032 os_urandom_impl(PyObject *module, Py_ssize_t size)
12033 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
12034 {
12035 PyObject *bytes;
12036 int result;
12037
12038 if (size < 0)
12039 return PyErr_Format(PyExc_ValueError,
12040 "negative argument not allowed");
12041 bytes = PyBytes_FromStringAndSize(NULL, size);
12042 if (bytes == NULL)
12043 return NULL;
12044
12045 result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
12046 if (result == -1) {
12047 Py_DECREF(bytes);
12048 return NULL;
12049 }
12050 return bytes;
12051 }
12052
12053 #ifdef HAVE_MEMFD_CREATE
12054 /*[clinic input]
12055 os.memfd_create
12056
12057 name: FSConverter
12058 flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
12059
12060 [clinic start generated code]*/
12061
12062 static PyObject *
os_memfd_create_impl(PyObject * module,PyObject * name,unsigned int flags)12063 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
12064 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
12065 {
12066 int fd;
12067 const char *bytes = PyBytes_AS_STRING(name);
12068 Py_BEGIN_ALLOW_THREADS
12069 fd = memfd_create(bytes, flags);
12070 Py_END_ALLOW_THREADS
12071 if (fd == -1) {
12072 return PyErr_SetFromErrno(PyExc_OSError);
12073 }
12074 return PyLong_FromLong(fd);
12075 }
12076 #endif
12077
12078 /* Terminal size querying */
12079
12080 static PyTypeObject* TerminalSizeType;
12081
12082 PyDoc_STRVAR(TerminalSize_docstring,
12083 "A tuple of (columns, lines) for holding terminal window size");
12084
12085 static PyStructSequence_Field TerminalSize_fields[] = {
12086 {"columns", "width of the terminal window in characters"},
12087 {"lines", "height of the terminal window in characters"},
12088 {NULL, NULL}
12089 };
12090
12091 static PyStructSequence_Desc TerminalSize_desc = {
12092 "os.terminal_size",
12093 TerminalSize_docstring,
12094 TerminalSize_fields,
12095 2,
12096 };
12097
12098 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
12099 /* AC 3.5: fd should accept None */
12100 PyDoc_STRVAR(termsize__doc__,
12101 "Return the size of the terminal window as (columns, lines).\n" \
12102 "\n" \
12103 "The optional argument fd (default standard output) specifies\n" \
12104 "which file descriptor should be queried.\n" \
12105 "\n" \
12106 "If the file descriptor is not connected to a terminal, an OSError\n" \
12107 "is thrown.\n" \
12108 "\n" \
12109 "This function will only be defined if an implementation is\n" \
12110 "available for this system.\n" \
12111 "\n" \
12112 "shutil.get_terminal_size is the high-level function which should\n" \
12113 "normally be used, os.get_terminal_size is the low-level implementation.");
12114
12115 static PyObject*
get_terminal_size(PyObject * self,PyObject * args)12116 get_terminal_size(PyObject *self, PyObject *args)
12117 {
12118 int columns, lines;
12119 PyObject *termsize;
12120
12121 int fd = fileno(stdout);
12122 /* Under some conditions stdout may not be connected and
12123 * fileno(stdout) may point to an invalid file descriptor. For example
12124 * GUI apps don't have valid standard streams by default.
12125 *
12126 * If this happens, and the optional fd argument is not present,
12127 * the ioctl below will fail returning EBADF. This is what we want.
12128 */
12129
12130 if (!PyArg_ParseTuple(args, "|i", &fd))
12131 return NULL;
12132
12133 #ifdef TERMSIZE_USE_IOCTL
12134 {
12135 struct winsize w;
12136 if (ioctl(fd, TIOCGWINSZ, &w))
12137 return PyErr_SetFromErrno(PyExc_OSError);
12138 columns = w.ws_col;
12139 lines = w.ws_row;
12140 }
12141 #endif /* TERMSIZE_USE_IOCTL */
12142
12143 #ifdef TERMSIZE_USE_CONIO
12144 {
12145 DWORD nhandle;
12146 HANDLE handle;
12147 CONSOLE_SCREEN_BUFFER_INFO csbi;
12148 switch (fd) {
12149 case 0: nhandle = STD_INPUT_HANDLE;
12150 break;
12151 case 1: nhandle = STD_OUTPUT_HANDLE;
12152 break;
12153 case 2: nhandle = STD_ERROR_HANDLE;
12154 break;
12155 default:
12156 return PyErr_Format(PyExc_ValueError, "bad file descriptor");
12157 }
12158 handle = GetStdHandle(nhandle);
12159 if (handle == NULL)
12160 return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
12161 if (handle == INVALID_HANDLE_VALUE)
12162 return PyErr_SetFromWindowsErr(0);
12163
12164 if (!GetConsoleScreenBufferInfo(handle, &csbi))
12165 return PyErr_SetFromWindowsErr(0);
12166
12167 columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
12168 lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
12169 }
12170 #endif /* TERMSIZE_USE_CONIO */
12171
12172 termsize = PyStructSequence_New(TerminalSizeType);
12173 if (termsize == NULL)
12174 return NULL;
12175 PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
12176 PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
12177 if (PyErr_Occurred()) {
12178 Py_DECREF(termsize);
12179 return NULL;
12180 }
12181 return termsize;
12182 }
12183 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
12184
12185
12186 /*[clinic input]
12187 os.cpu_count
12188
12189 Return the number of CPUs in the system; return None if indeterminable.
12190
12191 This number is not equivalent to the number of CPUs the current process can
12192 use. The number of usable CPUs can be obtained with
12193 ``len(os.sched_getaffinity(0))``
12194 [clinic start generated code]*/
12195
12196 static PyObject *
os_cpu_count_impl(PyObject * module)12197 os_cpu_count_impl(PyObject *module)
12198 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
12199 {
12200 int ncpu = 0;
12201 #ifdef MS_WINDOWS
12202 /* Declare prototype here to avoid pulling in all of the Win7 APIs in 3.8 */
12203 DWORD WINAPI GetActiveProcessorCount(WORD group);
12204 ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
12205 #elif defined(__hpux)
12206 ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
12207 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
12208 ncpu = sysconf(_SC_NPROCESSORS_ONLN);
12209 #elif defined(__DragonFly__) || \
12210 defined(__OpenBSD__) || \
12211 defined(__FreeBSD__) || \
12212 defined(__NetBSD__) || \
12213 defined(__APPLE__)
12214 int mib[2];
12215 size_t len = sizeof(ncpu);
12216 mib[0] = CTL_HW;
12217 mib[1] = HW_NCPU;
12218 if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
12219 ncpu = 0;
12220 #endif
12221 if (ncpu >= 1)
12222 return PyLong_FromLong(ncpu);
12223 else
12224 Py_RETURN_NONE;
12225 }
12226
12227
12228 /*[clinic input]
12229 os.get_inheritable -> bool
12230
12231 fd: int
12232 /
12233
12234 Get the close-on-exe flag of the specified file descriptor.
12235 [clinic start generated code]*/
12236
12237 static int
os_get_inheritable_impl(PyObject * module,int fd)12238 os_get_inheritable_impl(PyObject *module, int fd)
12239 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
12240 {
12241 int return_value;
12242 _Py_BEGIN_SUPPRESS_IPH
12243 return_value = _Py_get_inheritable(fd);
12244 _Py_END_SUPPRESS_IPH
12245 return return_value;
12246 }
12247
12248
12249 /*[clinic input]
12250 os.set_inheritable
12251 fd: int
12252 inheritable: int
12253 /
12254
12255 Set the inheritable flag of the specified file descriptor.
12256 [clinic start generated code]*/
12257
12258 static PyObject *
os_set_inheritable_impl(PyObject * module,int fd,int inheritable)12259 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
12260 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
12261 {
12262 int result;
12263
12264 _Py_BEGIN_SUPPRESS_IPH
12265 result = _Py_set_inheritable(fd, inheritable, NULL);
12266 _Py_END_SUPPRESS_IPH
12267 if (result < 0)
12268 return NULL;
12269 Py_RETURN_NONE;
12270 }
12271
12272
12273 #ifdef MS_WINDOWS
12274 /*[clinic input]
12275 os.get_handle_inheritable -> bool
12276 handle: intptr_t
12277 /
12278
12279 Get the close-on-exe flag of the specified file descriptor.
12280 [clinic start generated code]*/
12281
12282 static int
os_get_handle_inheritable_impl(PyObject * module,intptr_t handle)12283 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
12284 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
12285 {
12286 DWORD flags;
12287
12288 if (!GetHandleInformation((HANDLE)handle, &flags)) {
12289 PyErr_SetFromWindowsErr(0);
12290 return -1;
12291 }
12292
12293 return flags & HANDLE_FLAG_INHERIT;
12294 }
12295
12296
12297 /*[clinic input]
12298 os.set_handle_inheritable
12299 handle: intptr_t
12300 inheritable: bool
12301 /
12302
12303 Set the inheritable flag of the specified handle.
12304 [clinic start generated code]*/
12305
12306 static PyObject *
os_set_handle_inheritable_impl(PyObject * module,intptr_t handle,int inheritable)12307 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
12308 int inheritable)
12309 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
12310 {
12311 DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
12312 if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
12313 PyErr_SetFromWindowsErr(0);
12314 return NULL;
12315 }
12316 Py_RETURN_NONE;
12317 }
12318 #endif /* MS_WINDOWS */
12319
12320 #ifndef MS_WINDOWS
12321 /*[clinic input]
12322 os.get_blocking -> bool
12323 fd: int
12324 /
12325
12326 Get the blocking mode of the file descriptor.
12327
12328 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
12329 [clinic start generated code]*/
12330
12331 static int
os_get_blocking_impl(PyObject * module,int fd)12332 os_get_blocking_impl(PyObject *module, int fd)
12333 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
12334 {
12335 int blocking;
12336
12337 _Py_BEGIN_SUPPRESS_IPH
12338 blocking = _Py_get_blocking(fd);
12339 _Py_END_SUPPRESS_IPH
12340 return blocking;
12341 }
12342
12343 /*[clinic input]
12344 os.set_blocking
12345 fd: int
12346 blocking: bool(accept={int})
12347 /
12348
12349 Set the blocking mode of the specified file descriptor.
12350
12351 Set the O_NONBLOCK flag if blocking is False,
12352 clear the O_NONBLOCK flag otherwise.
12353 [clinic start generated code]*/
12354
12355 static PyObject *
os_set_blocking_impl(PyObject * module,int fd,int blocking)12356 os_set_blocking_impl(PyObject *module, int fd, int blocking)
12357 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
12358 {
12359 int result;
12360
12361 _Py_BEGIN_SUPPRESS_IPH
12362 result = _Py_set_blocking(fd, blocking);
12363 _Py_END_SUPPRESS_IPH
12364 if (result < 0)
12365 return NULL;
12366 Py_RETURN_NONE;
12367 }
12368 #endif /* !MS_WINDOWS */
12369
12370
12371 /*[clinic input]
12372 class os.DirEntry "DirEntry *" "&DirEntryType"
12373 [clinic start generated code]*/
12374 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3138f09f7c683f1d]*/
12375
12376 typedef struct {
12377 PyObject_HEAD
12378 PyObject *name;
12379 PyObject *path;
12380 PyObject *stat;
12381 PyObject *lstat;
12382 #ifdef MS_WINDOWS
12383 struct _Py_stat_struct win32_lstat;
12384 uint64_t win32_file_index;
12385 int got_file_index;
12386 #else /* POSIX */
12387 #ifdef HAVE_DIRENT_D_TYPE
12388 unsigned char d_type;
12389 #endif
12390 ino_t d_ino;
12391 int dir_fd;
12392 #endif
12393 } DirEntry;
12394
12395 static void
DirEntry_dealloc(DirEntry * entry)12396 DirEntry_dealloc(DirEntry *entry)
12397 {
12398 Py_XDECREF(entry->name);
12399 Py_XDECREF(entry->path);
12400 Py_XDECREF(entry->stat);
12401 Py_XDECREF(entry->lstat);
12402 Py_TYPE(entry)->tp_free((PyObject *)entry);
12403 }
12404
12405 /* Forward reference */
12406 static int
12407 DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits);
12408
12409 /*[clinic input]
12410 os.DirEntry.is_symlink -> bool
12411
12412 Return True if the entry is a symbolic link; cached per entry.
12413 [clinic start generated code]*/
12414
12415 static int
os_DirEntry_is_symlink_impl(DirEntry * self)12416 os_DirEntry_is_symlink_impl(DirEntry *self)
12417 /*[clinic end generated code: output=42244667d7bcfc25 input=1605a1b4b96976c3]*/
12418 {
12419 #ifdef MS_WINDOWS
12420 return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
12421 #elif defined(HAVE_DIRENT_D_TYPE)
12422 /* POSIX */
12423 if (self->d_type != DT_UNKNOWN)
12424 return self->d_type == DT_LNK;
12425 else
12426 return DirEntry_test_mode(self, 0, S_IFLNK);
12427 #else
12428 /* POSIX without d_type */
12429 return DirEntry_test_mode(self, 0, S_IFLNK);
12430 #endif
12431 }
12432
12433 static PyObject *
DirEntry_fetch_stat(DirEntry * self,int follow_symlinks)12434 DirEntry_fetch_stat(DirEntry *self, int follow_symlinks)
12435 {
12436 int result;
12437 STRUCT_STAT st;
12438 PyObject *ub;
12439
12440 #ifdef MS_WINDOWS
12441 if (!PyUnicode_FSDecoder(self->path, &ub))
12442 return NULL;
12443 const wchar_t *path = PyUnicode_AsUnicode(ub);
12444 #else /* POSIX */
12445 if (!PyUnicode_FSConverter(self->path, &ub))
12446 return NULL;
12447 const char *path = PyBytes_AS_STRING(ub);
12448 if (self->dir_fd != DEFAULT_DIR_FD) {
12449 #ifdef HAVE_FSTATAT
12450 result = fstatat(self->dir_fd, path, &st,
12451 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
12452 #else
12453 PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
12454 return NULL;
12455 #endif /* HAVE_FSTATAT */
12456 }
12457 else
12458 #endif
12459 {
12460 if (follow_symlinks)
12461 result = STAT(path, &st);
12462 else
12463 result = LSTAT(path, &st);
12464 }
12465 Py_DECREF(ub);
12466
12467 if (result != 0)
12468 return path_object_error(self->path);
12469
12470 return _pystat_fromstructstat(&st);
12471 }
12472
12473 static PyObject *
DirEntry_get_lstat(DirEntry * self)12474 DirEntry_get_lstat(DirEntry *self)
12475 {
12476 if (!self->lstat) {
12477 #ifdef MS_WINDOWS
12478 self->lstat = _pystat_fromstructstat(&self->win32_lstat);
12479 #else /* POSIX */
12480 self->lstat = DirEntry_fetch_stat(self, 0);
12481 #endif
12482 }
12483 Py_XINCREF(self->lstat);
12484 return self->lstat;
12485 }
12486
12487 /*[clinic input]
12488 os.DirEntry.stat
12489 *
12490 follow_symlinks: bool = True
12491
12492 Return stat_result object for the entry; cached per entry.
12493 [clinic start generated code]*/
12494
12495 static PyObject *
os_DirEntry_stat_impl(DirEntry * self,int follow_symlinks)12496 os_DirEntry_stat_impl(DirEntry *self, int follow_symlinks)
12497 /*[clinic end generated code: output=008593b3a6d01305 input=280d14c1d6f1d00d]*/
12498 {
12499 if (!follow_symlinks)
12500 return DirEntry_get_lstat(self);
12501
12502 if (!self->stat) {
12503 int result = os_DirEntry_is_symlink_impl(self);
12504 if (result == -1)
12505 return NULL;
12506 else if (result)
12507 self->stat = DirEntry_fetch_stat(self, 1);
12508 else
12509 self->stat = DirEntry_get_lstat(self);
12510 }
12511
12512 Py_XINCREF(self->stat);
12513 return self->stat;
12514 }
12515
12516 /* Set exception and return -1 on error, 0 for False, 1 for True */
12517 static int
DirEntry_test_mode(DirEntry * self,int follow_symlinks,unsigned short mode_bits)12518 DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits)
12519 {
12520 PyObject *stat = NULL;
12521 PyObject *st_mode = NULL;
12522 long mode;
12523 int result;
12524 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
12525 int is_symlink;
12526 int need_stat;
12527 #endif
12528 #ifdef MS_WINDOWS
12529 unsigned long dir_bits;
12530 #endif
12531 _Py_IDENTIFIER(st_mode);
12532
12533 #ifdef MS_WINDOWS
12534 is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
12535 need_stat = follow_symlinks && is_symlink;
12536 #elif defined(HAVE_DIRENT_D_TYPE)
12537 is_symlink = self->d_type == DT_LNK;
12538 need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
12539 #endif
12540
12541 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
12542 if (need_stat) {
12543 #endif
12544 stat = os_DirEntry_stat_impl(self, follow_symlinks);
12545 if (!stat) {
12546 if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
12547 /* If file doesn't exist (anymore), then return False
12548 (i.e., say it's not a file/directory) */
12549 PyErr_Clear();
12550 return 0;
12551 }
12552 goto error;
12553 }
12554 st_mode = _PyObject_GetAttrId(stat, &PyId_st_mode);
12555 if (!st_mode)
12556 goto error;
12557
12558 mode = PyLong_AsLong(st_mode);
12559 if (mode == -1 && PyErr_Occurred())
12560 goto error;
12561 Py_CLEAR(st_mode);
12562 Py_CLEAR(stat);
12563 result = (mode & S_IFMT) == mode_bits;
12564 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
12565 }
12566 else if (is_symlink) {
12567 assert(mode_bits != S_IFLNK);
12568 result = 0;
12569 }
12570 else {
12571 assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
12572 #ifdef MS_WINDOWS
12573 dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
12574 if (mode_bits == S_IFDIR)
12575 result = dir_bits != 0;
12576 else
12577 result = dir_bits == 0;
12578 #else /* POSIX */
12579 if (mode_bits == S_IFDIR)
12580 result = self->d_type == DT_DIR;
12581 else
12582 result = self->d_type == DT_REG;
12583 #endif
12584 }
12585 #endif
12586
12587 return result;
12588
12589 error:
12590 Py_XDECREF(st_mode);
12591 Py_XDECREF(stat);
12592 return -1;
12593 }
12594
12595 /*[clinic input]
12596 os.DirEntry.is_dir -> bool
12597 *
12598 follow_symlinks: bool = True
12599
12600 Return True if the entry is a directory; cached per entry.
12601 [clinic start generated code]*/
12602
12603 static int
os_DirEntry_is_dir_impl(DirEntry * self,int follow_symlinks)12604 os_DirEntry_is_dir_impl(DirEntry *self, int follow_symlinks)
12605 /*[clinic end generated code: output=ad2e8d54365da287 input=0135232766f53f58]*/
12606 {
12607 return DirEntry_test_mode(self, follow_symlinks, S_IFDIR);
12608 }
12609
12610 /*[clinic input]
12611 os.DirEntry.is_file -> bool
12612 *
12613 follow_symlinks: bool = True
12614
12615 Return True if the entry is a file; cached per entry.
12616 [clinic start generated code]*/
12617
12618 static int
os_DirEntry_is_file_impl(DirEntry * self,int follow_symlinks)12619 os_DirEntry_is_file_impl(DirEntry *self, int follow_symlinks)
12620 /*[clinic end generated code: output=8462ade481d8a476 input=0dc90be168b041ee]*/
12621 {
12622 return DirEntry_test_mode(self, follow_symlinks, S_IFREG);
12623 }
12624
12625 /*[clinic input]
12626 os.DirEntry.inode
12627
12628 Return inode of the entry; cached per entry.
12629 [clinic start generated code]*/
12630
12631 static PyObject *
os_DirEntry_inode_impl(DirEntry * self)12632 os_DirEntry_inode_impl(DirEntry *self)
12633 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
12634 {
12635 #ifdef MS_WINDOWS
12636 if (!self->got_file_index) {
12637 PyObject *unicode;
12638 const wchar_t *path;
12639 STRUCT_STAT stat;
12640 int result;
12641
12642 if (!PyUnicode_FSDecoder(self->path, &unicode))
12643 return NULL;
12644 path = PyUnicode_AsUnicode(unicode);
12645 result = LSTAT(path, &stat);
12646 Py_DECREF(unicode);
12647
12648 if (result != 0)
12649 return path_object_error(self->path);
12650
12651 self->win32_file_index = stat.st_ino;
12652 self->got_file_index = 1;
12653 }
12654 Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->win32_file_index));
12655 return PyLong_FromUnsignedLongLong(self->win32_file_index);
12656 #else /* POSIX */
12657 Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->d_ino));
12658 return PyLong_FromUnsignedLongLong(self->d_ino);
12659 #endif
12660 }
12661
12662 static PyObject *
DirEntry_repr(DirEntry * self)12663 DirEntry_repr(DirEntry *self)
12664 {
12665 return PyUnicode_FromFormat("<DirEntry %R>", self->name);
12666 }
12667
12668 /*[clinic input]
12669 os.DirEntry.__fspath__
12670
12671 Returns the path for the entry.
12672 [clinic start generated code]*/
12673
12674 static PyObject *
os_DirEntry___fspath___impl(DirEntry * self)12675 os_DirEntry___fspath___impl(DirEntry *self)
12676 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
12677 {
12678 Py_INCREF(self->path);
12679 return self->path;
12680 }
12681
12682 static PyMemberDef DirEntry_members[] = {
12683 {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
12684 "the entry's base filename, relative to scandir() \"path\" argument"},
12685 {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
12686 "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
12687 {NULL}
12688 };
12689
12690 #include "clinic/posixmodule.c.h"
12691
12692 static PyMethodDef DirEntry_methods[] = {
12693 OS_DIRENTRY_IS_DIR_METHODDEF
12694 OS_DIRENTRY_IS_FILE_METHODDEF
12695 OS_DIRENTRY_IS_SYMLINK_METHODDEF
12696 OS_DIRENTRY_STAT_METHODDEF
12697 OS_DIRENTRY_INODE_METHODDEF
12698 OS_DIRENTRY___FSPATH___METHODDEF
12699 {NULL}
12700 };
12701
12702 static PyTypeObject DirEntryType = {
12703 PyVarObject_HEAD_INIT(NULL, 0)
12704 MODNAME ".DirEntry", /* tp_name */
12705 sizeof(DirEntry), /* tp_basicsize */
12706 0, /* tp_itemsize */
12707 /* methods */
12708 (destructor)DirEntry_dealloc, /* tp_dealloc */
12709 0, /* tp_vectorcall_offset */
12710 0, /* tp_getattr */
12711 0, /* tp_setattr */
12712 0, /* tp_as_async */
12713 (reprfunc)DirEntry_repr, /* tp_repr */
12714 0, /* tp_as_number */
12715 0, /* tp_as_sequence */
12716 0, /* tp_as_mapping */
12717 0, /* tp_hash */
12718 0, /* tp_call */
12719 0, /* tp_str */
12720 0, /* tp_getattro */
12721 0, /* tp_setattro */
12722 0, /* tp_as_buffer */
12723 Py_TPFLAGS_DEFAULT, /* tp_flags */
12724 0, /* tp_doc */
12725 0, /* tp_traverse */
12726 0, /* tp_clear */
12727 0, /* tp_richcompare */
12728 0, /* tp_weaklistoffset */
12729 0, /* tp_iter */
12730 0, /* tp_iternext */
12731 DirEntry_methods, /* tp_methods */
12732 DirEntry_members, /* tp_members */
12733 };
12734
12735 #ifdef MS_WINDOWS
12736
12737 static wchar_t *
join_path_filenameW(const wchar_t * path_wide,const wchar_t * filename)12738 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
12739 {
12740 Py_ssize_t path_len;
12741 Py_ssize_t size;
12742 wchar_t *result;
12743 wchar_t ch;
12744
12745 if (!path_wide) { /* Default arg: "." */
12746 path_wide = L".";
12747 path_len = 1;
12748 }
12749 else {
12750 path_len = wcslen(path_wide);
12751 }
12752
12753 /* The +1's are for the path separator and the NUL */
12754 size = path_len + 1 + wcslen(filename) + 1;
12755 result = PyMem_New(wchar_t, size);
12756 if (!result) {
12757 PyErr_NoMemory();
12758 return NULL;
12759 }
12760 wcscpy(result, path_wide);
12761 if (path_len > 0) {
12762 ch = result[path_len - 1];
12763 if (ch != SEP && ch != ALTSEP && ch != L':')
12764 result[path_len++] = SEP;
12765 wcscpy(result + path_len, filename);
12766 }
12767 return result;
12768 }
12769
12770 static PyObject *
DirEntry_from_find_data(path_t * path,WIN32_FIND_DATAW * dataW)12771 DirEntry_from_find_data(path_t *path, WIN32_FIND_DATAW *dataW)
12772 {
12773 DirEntry *entry;
12774 BY_HANDLE_FILE_INFORMATION file_info;
12775 ULONG reparse_tag;
12776 wchar_t *joined_path;
12777
12778 entry = PyObject_New(DirEntry, &DirEntryType);
12779 if (!entry)
12780 return NULL;
12781 entry->name = NULL;
12782 entry->path = NULL;
12783 entry->stat = NULL;
12784 entry->lstat = NULL;
12785 entry->got_file_index = 0;
12786
12787 entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
12788 if (!entry->name)
12789 goto error;
12790 if (path->narrow) {
12791 Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
12792 if (!entry->name)
12793 goto error;
12794 }
12795
12796 joined_path = join_path_filenameW(path->wide, dataW->cFileName);
12797 if (!joined_path)
12798 goto error;
12799
12800 entry->path = PyUnicode_FromWideChar(joined_path, -1);
12801 PyMem_Free(joined_path);
12802 if (!entry->path)
12803 goto error;
12804 if (path->narrow) {
12805 Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
12806 if (!entry->path)
12807 goto error;
12808 }
12809
12810 find_data_to_file_info(dataW, &file_info, &reparse_tag);
12811 _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
12812
12813 return (PyObject *)entry;
12814
12815 error:
12816 Py_DECREF(entry);
12817 return NULL;
12818 }
12819
12820 #else /* POSIX */
12821
12822 static char *
join_path_filename(const char * path_narrow,const char * filename,Py_ssize_t filename_len)12823 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
12824 {
12825 Py_ssize_t path_len;
12826 Py_ssize_t size;
12827 char *result;
12828
12829 if (!path_narrow) { /* Default arg: "." */
12830 path_narrow = ".";
12831 path_len = 1;
12832 }
12833 else {
12834 path_len = strlen(path_narrow);
12835 }
12836
12837 if (filename_len == -1)
12838 filename_len = strlen(filename);
12839
12840 /* The +1's are for the path separator and the NUL */
12841 size = path_len + 1 + filename_len + 1;
12842 result = PyMem_New(char, size);
12843 if (!result) {
12844 PyErr_NoMemory();
12845 return NULL;
12846 }
12847 strcpy(result, path_narrow);
12848 if (path_len > 0 && result[path_len - 1] != '/')
12849 result[path_len++] = '/';
12850 strcpy(result + path_len, filename);
12851 return result;
12852 }
12853
12854 static PyObject *
DirEntry_from_posix_info(path_t * path,const char * name,Py_ssize_t name_len,ino_t d_ino,unsigned char d_type)12855 DirEntry_from_posix_info(path_t *path, const char *name, Py_ssize_t name_len,
12856 ino_t d_ino
12857 #ifdef HAVE_DIRENT_D_TYPE
12858 , unsigned char d_type
12859 #endif
12860 )
12861 {
12862 DirEntry *entry;
12863 char *joined_path;
12864
12865 entry = PyObject_New(DirEntry, &DirEntryType);
12866 if (!entry)
12867 return NULL;
12868 entry->name = NULL;
12869 entry->path = NULL;
12870 entry->stat = NULL;
12871 entry->lstat = NULL;
12872
12873 if (path->fd != -1) {
12874 entry->dir_fd = path->fd;
12875 joined_path = NULL;
12876 }
12877 else {
12878 entry->dir_fd = DEFAULT_DIR_FD;
12879 joined_path = join_path_filename(path->narrow, name, name_len);
12880 if (!joined_path)
12881 goto error;
12882 }
12883
12884 if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
12885 entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
12886 if (joined_path)
12887 entry->path = PyUnicode_DecodeFSDefault(joined_path);
12888 }
12889 else {
12890 entry->name = PyBytes_FromStringAndSize(name, name_len);
12891 if (joined_path)
12892 entry->path = PyBytes_FromString(joined_path);
12893 }
12894 PyMem_Free(joined_path);
12895 if (!entry->name)
12896 goto error;
12897
12898 if (path->fd != -1) {
12899 entry->path = entry->name;
12900 Py_INCREF(entry->path);
12901 }
12902 else if (!entry->path)
12903 goto error;
12904
12905 #ifdef HAVE_DIRENT_D_TYPE
12906 entry->d_type = d_type;
12907 #endif
12908 entry->d_ino = d_ino;
12909
12910 return (PyObject *)entry;
12911
12912 error:
12913 Py_XDECREF(entry);
12914 return NULL;
12915 }
12916
12917 #endif
12918
12919
12920 typedef struct {
12921 PyObject_HEAD
12922 path_t path;
12923 #ifdef MS_WINDOWS
12924 HANDLE handle;
12925 WIN32_FIND_DATAW file_data;
12926 int first_time;
12927 #else /* POSIX */
12928 DIR *dirp;
12929 #endif
12930 #ifdef HAVE_FDOPENDIR
12931 int fd;
12932 #endif
12933 } ScandirIterator;
12934
12935 #ifdef MS_WINDOWS
12936
12937 static int
ScandirIterator_is_closed(ScandirIterator * iterator)12938 ScandirIterator_is_closed(ScandirIterator *iterator)
12939 {
12940 return iterator->handle == INVALID_HANDLE_VALUE;
12941 }
12942
12943 static void
ScandirIterator_closedir(ScandirIterator * iterator)12944 ScandirIterator_closedir(ScandirIterator *iterator)
12945 {
12946 HANDLE handle = iterator->handle;
12947
12948 if (handle == INVALID_HANDLE_VALUE)
12949 return;
12950
12951 iterator->handle = INVALID_HANDLE_VALUE;
12952 Py_BEGIN_ALLOW_THREADS
12953 FindClose(handle);
12954 Py_END_ALLOW_THREADS
12955 }
12956
12957 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)12958 ScandirIterator_iternext(ScandirIterator *iterator)
12959 {
12960 WIN32_FIND_DATAW *file_data = &iterator->file_data;
12961 BOOL success;
12962 PyObject *entry;
12963
12964 /* Happens if the iterator is iterated twice, or closed explicitly */
12965 if (iterator->handle == INVALID_HANDLE_VALUE)
12966 return NULL;
12967
12968 while (1) {
12969 if (!iterator->first_time) {
12970 Py_BEGIN_ALLOW_THREADS
12971 success = FindNextFileW(iterator->handle, file_data);
12972 Py_END_ALLOW_THREADS
12973 if (!success) {
12974 /* Error or no more files */
12975 if (GetLastError() != ERROR_NO_MORE_FILES)
12976 path_error(&iterator->path);
12977 break;
12978 }
12979 }
12980 iterator->first_time = 0;
12981
12982 /* Skip over . and .. */
12983 if (wcscmp(file_data->cFileName, L".") != 0 &&
12984 wcscmp(file_data->cFileName, L"..") != 0) {
12985 entry = DirEntry_from_find_data(&iterator->path, file_data);
12986 if (!entry)
12987 break;
12988 return entry;
12989 }
12990
12991 /* Loop till we get a non-dot directory or finish iterating */
12992 }
12993
12994 /* Error or no more files */
12995 ScandirIterator_closedir(iterator);
12996 return NULL;
12997 }
12998
12999 #else /* POSIX */
13000
13001 static int
ScandirIterator_is_closed(ScandirIterator * iterator)13002 ScandirIterator_is_closed(ScandirIterator *iterator)
13003 {
13004 return !iterator->dirp;
13005 }
13006
13007 static void
ScandirIterator_closedir(ScandirIterator * iterator)13008 ScandirIterator_closedir(ScandirIterator *iterator)
13009 {
13010 DIR *dirp = iterator->dirp;
13011
13012 if (!dirp)
13013 return;
13014
13015 iterator->dirp = NULL;
13016 Py_BEGIN_ALLOW_THREADS
13017 #ifdef HAVE_FDOPENDIR
13018 if (iterator->path.fd != -1)
13019 rewinddir(dirp);
13020 #endif
13021 closedir(dirp);
13022 Py_END_ALLOW_THREADS
13023 return;
13024 }
13025
13026 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)13027 ScandirIterator_iternext(ScandirIterator *iterator)
13028 {
13029 struct dirent *direntp;
13030 Py_ssize_t name_len;
13031 int is_dot;
13032 PyObject *entry;
13033
13034 /* Happens if the iterator is iterated twice, or closed explicitly */
13035 if (!iterator->dirp)
13036 return NULL;
13037
13038 while (1) {
13039 errno = 0;
13040 Py_BEGIN_ALLOW_THREADS
13041 direntp = readdir(iterator->dirp);
13042 Py_END_ALLOW_THREADS
13043
13044 if (!direntp) {
13045 /* Error or no more files */
13046 if (errno != 0)
13047 path_error(&iterator->path);
13048 break;
13049 }
13050
13051 /* Skip over . and .. */
13052 name_len = NAMLEN(direntp);
13053 is_dot = direntp->d_name[0] == '.' &&
13054 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
13055 if (!is_dot) {
13056 entry = DirEntry_from_posix_info(&iterator->path, direntp->d_name,
13057 name_len, direntp->d_ino
13058 #ifdef HAVE_DIRENT_D_TYPE
13059 , direntp->d_type
13060 #endif
13061 );
13062 if (!entry)
13063 break;
13064 return entry;
13065 }
13066
13067 /* Loop till we get a non-dot directory or finish iterating */
13068 }
13069
13070 /* Error or no more files */
13071 ScandirIterator_closedir(iterator);
13072 return NULL;
13073 }
13074
13075 #endif
13076
13077 static PyObject *
ScandirIterator_close(ScandirIterator * self,PyObject * args)13078 ScandirIterator_close(ScandirIterator *self, PyObject *args)
13079 {
13080 ScandirIterator_closedir(self);
13081 Py_RETURN_NONE;
13082 }
13083
13084 static PyObject *
ScandirIterator_enter(PyObject * self,PyObject * args)13085 ScandirIterator_enter(PyObject *self, PyObject *args)
13086 {
13087 Py_INCREF(self);
13088 return self;
13089 }
13090
13091 static PyObject *
ScandirIterator_exit(ScandirIterator * self,PyObject * args)13092 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
13093 {
13094 ScandirIterator_closedir(self);
13095 Py_RETURN_NONE;
13096 }
13097
13098 static void
ScandirIterator_finalize(ScandirIterator * iterator)13099 ScandirIterator_finalize(ScandirIterator *iterator)
13100 {
13101 PyObject *error_type, *error_value, *error_traceback;
13102
13103 /* Save the current exception, if any. */
13104 PyErr_Fetch(&error_type, &error_value, &error_traceback);
13105
13106 if (!ScandirIterator_is_closed(iterator)) {
13107 ScandirIterator_closedir(iterator);
13108
13109 if (PyErr_ResourceWarning((PyObject *)iterator, 1,
13110 "unclosed scandir iterator %R", iterator)) {
13111 /* Spurious errors can appear at shutdown */
13112 if (PyErr_ExceptionMatches(PyExc_Warning)) {
13113 PyErr_WriteUnraisable((PyObject *) iterator);
13114 }
13115 }
13116 }
13117
13118 path_cleanup(&iterator->path);
13119
13120 /* Restore the saved exception. */
13121 PyErr_Restore(error_type, error_value, error_traceback);
13122 }
13123
13124 static void
ScandirIterator_dealloc(ScandirIterator * iterator)13125 ScandirIterator_dealloc(ScandirIterator *iterator)
13126 {
13127 if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
13128 return;
13129
13130 Py_TYPE(iterator)->tp_free((PyObject *)iterator);
13131 }
13132
13133 static PyMethodDef ScandirIterator_methods[] = {
13134 {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
13135 {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
13136 {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
13137 {NULL}
13138 };
13139
13140 static PyTypeObject ScandirIteratorType = {
13141 PyVarObject_HEAD_INIT(NULL, 0)
13142 MODNAME ".ScandirIterator", /* tp_name */
13143 sizeof(ScandirIterator), /* tp_basicsize */
13144 0, /* tp_itemsize */
13145 /* methods */
13146 (destructor)ScandirIterator_dealloc, /* tp_dealloc */
13147 0, /* tp_vectorcall_offset */
13148 0, /* tp_getattr */
13149 0, /* tp_setattr */
13150 0, /* tp_as_async */
13151 0, /* tp_repr */
13152 0, /* tp_as_number */
13153 0, /* tp_as_sequence */
13154 0, /* tp_as_mapping */
13155 0, /* tp_hash */
13156 0, /* tp_call */
13157 0, /* tp_str */
13158 0, /* tp_getattro */
13159 0, /* tp_setattro */
13160 0, /* tp_as_buffer */
13161 Py_TPFLAGS_DEFAULT, /* tp_flags */
13162 0, /* tp_doc */
13163 0, /* tp_traverse */
13164 0, /* tp_clear */
13165 0, /* tp_richcompare */
13166 0, /* tp_weaklistoffset */
13167 PyObject_SelfIter, /* tp_iter */
13168 (iternextfunc)ScandirIterator_iternext, /* tp_iternext */
13169 ScandirIterator_methods, /* tp_methods */
13170 0, /* tp_members */
13171 0, /* tp_getset */
13172 0, /* tp_base */
13173 0, /* tp_dict */
13174 0, /* tp_descr_get */
13175 0, /* tp_descr_set */
13176 0, /* tp_dictoffset */
13177 0, /* tp_init */
13178 0, /* tp_alloc */
13179 0, /* tp_new */
13180 0, /* tp_free */
13181 0, /* tp_is_gc */
13182 0, /* tp_bases */
13183 0, /* tp_mro */
13184 0, /* tp_cache */
13185 0, /* tp_subclasses */
13186 0, /* tp_weaklist */
13187 0, /* tp_del */
13188 0, /* tp_version_tag */
13189 (destructor)ScandirIterator_finalize, /* tp_finalize */
13190 };
13191
13192 /*[clinic input]
13193 os.scandir
13194
13195 path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
13196
13197 Return an iterator of DirEntry objects for given path.
13198
13199 path can be specified as either str, bytes, or a path-like object. If path
13200 is bytes, the names of yielded DirEntry objects will also be bytes; in
13201 all other circumstances they will be str.
13202
13203 If path is None, uses the path='.'.
13204 [clinic start generated code]*/
13205
13206 static PyObject *
os_scandir_impl(PyObject * module,path_t * path)13207 os_scandir_impl(PyObject *module, path_t *path)
13208 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
13209 {
13210 ScandirIterator *iterator;
13211 #ifdef MS_WINDOWS
13212 wchar_t *path_strW;
13213 #else
13214 const char *path_str;
13215 #ifdef HAVE_FDOPENDIR
13216 int fd = -1;
13217 #endif
13218 #endif
13219
13220 if (PySys_Audit("os.scandir", "O",
13221 path->object ? path->object : Py_None) < 0) {
13222 return NULL;
13223 }
13224
13225 iterator = PyObject_New(ScandirIterator, &ScandirIteratorType);
13226 if (!iterator)
13227 return NULL;
13228
13229 #ifdef MS_WINDOWS
13230 iterator->handle = INVALID_HANDLE_VALUE;
13231 #else
13232 iterator->dirp = NULL;
13233 #endif
13234
13235 memcpy(&iterator->path, path, sizeof(path_t));
13236 /* Move the ownership to iterator->path */
13237 path->object = NULL;
13238 path->cleanup = NULL;
13239
13240 #ifdef MS_WINDOWS
13241 iterator->first_time = 1;
13242
13243 path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
13244 if (!path_strW)
13245 goto error;
13246
13247 Py_BEGIN_ALLOW_THREADS
13248 iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
13249 Py_END_ALLOW_THREADS
13250
13251 PyMem_Free(path_strW);
13252
13253 if (iterator->handle == INVALID_HANDLE_VALUE) {
13254 path_error(&iterator->path);
13255 goto error;
13256 }
13257 #else /* POSIX */
13258 errno = 0;
13259 #ifdef HAVE_FDOPENDIR
13260 if (path->fd != -1) {
13261 /* closedir() closes the FD, so we duplicate it */
13262 fd = _Py_dup(path->fd);
13263 if (fd == -1)
13264 goto error;
13265
13266 Py_BEGIN_ALLOW_THREADS
13267 iterator->dirp = fdopendir(fd);
13268 Py_END_ALLOW_THREADS
13269 }
13270 else
13271 #endif
13272 {
13273 if (iterator->path.narrow)
13274 path_str = iterator->path.narrow;
13275 else
13276 path_str = ".";
13277
13278 Py_BEGIN_ALLOW_THREADS
13279 iterator->dirp = opendir(path_str);
13280 Py_END_ALLOW_THREADS
13281 }
13282
13283 if (!iterator->dirp) {
13284 path_error(&iterator->path);
13285 #ifdef HAVE_FDOPENDIR
13286 if (fd != -1) {
13287 Py_BEGIN_ALLOW_THREADS
13288 close(fd);
13289 Py_END_ALLOW_THREADS
13290 }
13291 #endif
13292 goto error;
13293 }
13294 #endif
13295
13296 return (PyObject *)iterator;
13297
13298 error:
13299 Py_DECREF(iterator);
13300 return NULL;
13301 }
13302
13303 /*
13304 Return the file system path representation of the object.
13305
13306 If the object is str or bytes, then allow it to pass through with
13307 an incremented refcount. If the object defines __fspath__(), then
13308 return the result of that method. All other types raise a TypeError.
13309 */
13310 PyObject *
PyOS_FSPath(PyObject * path)13311 PyOS_FSPath(PyObject *path)
13312 {
13313 /* For error message reasons, this function is manually inlined in
13314 path_converter(). */
13315 _Py_IDENTIFIER(__fspath__);
13316 PyObject *func = NULL;
13317 PyObject *path_repr = NULL;
13318
13319 if (PyUnicode_Check(path) || PyBytes_Check(path)) {
13320 Py_INCREF(path);
13321 return path;
13322 }
13323
13324 func = _PyObject_LookupSpecial(path, &PyId___fspath__);
13325 if (NULL == func) {
13326 return PyErr_Format(PyExc_TypeError,
13327 "expected str, bytes or os.PathLike object, "
13328 "not %.200s",
13329 Py_TYPE(path)->tp_name);
13330 }
13331
13332 path_repr = _PyObject_CallNoArg(func);
13333 Py_DECREF(func);
13334 if (NULL == path_repr) {
13335 return NULL;
13336 }
13337
13338 if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
13339 PyErr_Format(PyExc_TypeError,
13340 "expected %.200s.__fspath__() to return str or bytes, "
13341 "not %.200s", Py_TYPE(path)->tp_name,
13342 Py_TYPE(path_repr)->tp_name);
13343 Py_DECREF(path_repr);
13344 return NULL;
13345 }
13346
13347 return path_repr;
13348 }
13349
13350 /*[clinic input]
13351 os.fspath
13352
13353 path: object
13354
13355 Return the file system path representation of the object.
13356
13357 If the object is str or bytes, then allow it to pass through as-is. If the
13358 object defines __fspath__(), then return the result of that method. All other
13359 types raise a TypeError.
13360 [clinic start generated code]*/
13361
13362 static PyObject *
os_fspath_impl(PyObject * module,PyObject * path)13363 os_fspath_impl(PyObject *module, PyObject *path)
13364 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
13365 {
13366 return PyOS_FSPath(path);
13367 }
13368
13369 #ifdef HAVE_GETRANDOM_SYSCALL
13370 /*[clinic input]
13371 os.getrandom
13372
13373 size: Py_ssize_t
13374 flags: int=0
13375
13376 Obtain a series of random bytes.
13377 [clinic start generated code]*/
13378
13379 static PyObject *
os_getrandom_impl(PyObject * module,Py_ssize_t size,int flags)13380 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
13381 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
13382 {
13383 PyObject *bytes;
13384 Py_ssize_t n;
13385
13386 if (size < 0) {
13387 errno = EINVAL;
13388 return posix_error();
13389 }
13390
13391 bytes = PyBytes_FromStringAndSize(NULL, size);
13392 if (bytes == NULL) {
13393 PyErr_NoMemory();
13394 return NULL;
13395 }
13396
13397 while (1) {
13398 n = syscall(SYS_getrandom,
13399 PyBytes_AS_STRING(bytes),
13400 PyBytes_GET_SIZE(bytes),
13401 flags);
13402 if (n < 0 && errno == EINTR) {
13403 if (PyErr_CheckSignals() < 0) {
13404 goto error;
13405 }
13406
13407 /* getrandom() was interrupted by a signal: retry */
13408 continue;
13409 }
13410 break;
13411 }
13412
13413 if (n < 0) {
13414 PyErr_SetFromErrno(PyExc_OSError);
13415 goto error;
13416 }
13417
13418 if (n != size) {
13419 _PyBytes_Resize(&bytes, n);
13420 }
13421
13422 return bytes;
13423
13424 error:
13425 Py_DECREF(bytes);
13426 return NULL;
13427 }
13428 #endif /* HAVE_GETRANDOM_SYSCALL */
13429
13430 #ifdef MS_WINDOWS
13431 /* bpo-36085: Helper functions for managing DLL search directories
13432 * on win32
13433 */
13434
13435 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
13436 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
13437
13438 /*[clinic input]
13439 os._add_dll_directory
13440
13441 path: path_t
13442
13443 Add a path to the DLL search path.
13444
13445 This search path is used when resolving dependencies for imported
13446 extension modules (the module itself is resolved through sys.path),
13447 and also by ctypes.
13448
13449 Returns an opaque value that may be passed to os.remove_dll_directory
13450 to remove this directory from the search path.
13451 [clinic start generated code]*/
13452
13453 static PyObject *
os__add_dll_directory_impl(PyObject * module,path_t * path)13454 os__add_dll_directory_impl(PyObject *module, path_t *path)
13455 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
13456 {
13457 HMODULE hKernel32;
13458 PAddDllDirectory AddDllDirectory;
13459 DLL_DIRECTORY_COOKIE cookie = 0;
13460 DWORD err = 0;
13461
13462 /* For Windows 7, we have to load this. As this will be a fairly
13463 infrequent operation, just do it each time. Kernel32 is always
13464 loaded. */
13465 Py_BEGIN_ALLOW_THREADS
13466 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
13467 !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
13468 hKernel32, "AddDllDirectory")) ||
13469 !(cookie = (*AddDllDirectory)(path->wide))) {
13470 err = GetLastError();
13471 }
13472 Py_END_ALLOW_THREADS
13473
13474 if (err) {
13475 return win32_error_object_err("add_dll_directory",
13476 path->object, err);
13477 }
13478
13479 return PyCapsule_New(cookie, "DLL directory cookie", NULL);
13480 }
13481
13482 /*[clinic input]
13483 os._remove_dll_directory
13484
13485 cookie: object
13486
13487 Removes a path from the DLL search path.
13488
13489 The parameter is an opaque value that was returned from
13490 os.add_dll_directory. You can only remove directories that you added
13491 yourself.
13492 [clinic start generated code]*/
13493
13494 static PyObject *
os__remove_dll_directory_impl(PyObject * module,PyObject * cookie)13495 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
13496 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
13497 {
13498 HMODULE hKernel32;
13499 PRemoveDllDirectory RemoveDllDirectory;
13500 DLL_DIRECTORY_COOKIE cookieValue;
13501 DWORD err = 0;
13502
13503 if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
13504 PyErr_SetString(PyExc_TypeError,
13505 "Provided cookie was not returned from os.add_dll_directory");
13506 return NULL;
13507 }
13508
13509 cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
13510 cookie, "DLL directory cookie");
13511
13512 /* For Windows 7, we have to load this. As this will be a fairly
13513 infrequent operation, just do it each time. Kernel32 is always
13514 loaded. */
13515 Py_BEGIN_ALLOW_THREADS
13516 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
13517 !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
13518 hKernel32, "RemoveDllDirectory")) ||
13519 !(*RemoveDllDirectory)(cookieValue)) {
13520 err = GetLastError();
13521 }
13522 Py_END_ALLOW_THREADS
13523
13524 if (err) {
13525 return win32_error_object_err("remove_dll_directory",
13526 NULL, err);
13527 }
13528
13529 if (PyCapsule_SetName(cookie, NULL)) {
13530 return NULL;
13531 }
13532
13533 Py_RETURN_NONE;
13534 }
13535
13536 #endif
13537
13538 static PyMethodDef posix_methods[] = {
13539
13540 OS_STAT_METHODDEF
13541 OS_ACCESS_METHODDEF
13542 OS_TTYNAME_METHODDEF
13543 OS_CHDIR_METHODDEF
13544 OS_CHFLAGS_METHODDEF
13545 OS_CHMOD_METHODDEF
13546 OS_FCHMOD_METHODDEF
13547 OS_LCHMOD_METHODDEF
13548 OS_CHOWN_METHODDEF
13549 OS_FCHOWN_METHODDEF
13550 OS_LCHOWN_METHODDEF
13551 OS_LCHFLAGS_METHODDEF
13552 OS_CHROOT_METHODDEF
13553 OS_CTERMID_METHODDEF
13554 OS_GETCWD_METHODDEF
13555 OS_GETCWDB_METHODDEF
13556 OS_LINK_METHODDEF
13557 OS_LISTDIR_METHODDEF
13558 OS_LSTAT_METHODDEF
13559 OS_MKDIR_METHODDEF
13560 OS_NICE_METHODDEF
13561 OS_GETPRIORITY_METHODDEF
13562 OS_SETPRIORITY_METHODDEF
13563 OS_POSIX_SPAWN_METHODDEF
13564 OS_POSIX_SPAWNP_METHODDEF
13565 OS_READLINK_METHODDEF
13566 OS_COPY_FILE_RANGE_METHODDEF
13567 OS_RENAME_METHODDEF
13568 OS_REPLACE_METHODDEF
13569 OS_RMDIR_METHODDEF
13570 OS_SYMLINK_METHODDEF
13571 OS_SYSTEM_METHODDEF
13572 OS_UMASK_METHODDEF
13573 OS_UNAME_METHODDEF
13574 OS_UNLINK_METHODDEF
13575 OS_REMOVE_METHODDEF
13576 OS_UTIME_METHODDEF
13577 OS_TIMES_METHODDEF
13578 OS__EXIT_METHODDEF
13579 OS__FCOPYFILE_METHODDEF
13580 OS_EXECV_METHODDEF
13581 OS_EXECVE_METHODDEF
13582 OS_SPAWNV_METHODDEF
13583 OS_SPAWNVE_METHODDEF
13584 OS_FORK1_METHODDEF
13585 OS_FORK_METHODDEF
13586 OS_REGISTER_AT_FORK_METHODDEF
13587 OS_SCHED_GET_PRIORITY_MAX_METHODDEF
13588 OS_SCHED_GET_PRIORITY_MIN_METHODDEF
13589 OS_SCHED_GETPARAM_METHODDEF
13590 OS_SCHED_GETSCHEDULER_METHODDEF
13591 OS_SCHED_RR_GET_INTERVAL_METHODDEF
13592 OS_SCHED_SETPARAM_METHODDEF
13593 OS_SCHED_SETSCHEDULER_METHODDEF
13594 OS_SCHED_YIELD_METHODDEF
13595 OS_SCHED_SETAFFINITY_METHODDEF
13596 OS_SCHED_GETAFFINITY_METHODDEF
13597 OS_OPENPTY_METHODDEF
13598 OS_FORKPTY_METHODDEF
13599 OS_GETEGID_METHODDEF
13600 OS_GETEUID_METHODDEF
13601 OS_GETGID_METHODDEF
13602 #ifdef HAVE_GETGROUPLIST
13603 {"getgrouplist", posix_getgrouplist, METH_VARARGS, posix_getgrouplist__doc__},
13604 #endif
13605 OS_GETGROUPS_METHODDEF
13606 OS_GETPID_METHODDEF
13607 OS_GETPGRP_METHODDEF
13608 OS_GETPPID_METHODDEF
13609 OS_GETUID_METHODDEF
13610 OS_GETLOGIN_METHODDEF
13611 OS_KILL_METHODDEF
13612 OS_KILLPG_METHODDEF
13613 OS_PLOCK_METHODDEF
13614 #ifdef MS_WINDOWS
13615 OS_STARTFILE_METHODDEF
13616 #endif
13617 OS_SETUID_METHODDEF
13618 OS_SETEUID_METHODDEF
13619 OS_SETREUID_METHODDEF
13620 OS_SETGID_METHODDEF
13621 OS_SETEGID_METHODDEF
13622 OS_SETREGID_METHODDEF
13623 OS_SETGROUPS_METHODDEF
13624 #ifdef HAVE_INITGROUPS
13625 {"initgroups", posix_initgroups, METH_VARARGS, posix_initgroups__doc__},
13626 #endif /* HAVE_INITGROUPS */
13627 OS_GETPGID_METHODDEF
13628 OS_SETPGRP_METHODDEF
13629 OS_WAIT_METHODDEF
13630 OS_WAIT3_METHODDEF
13631 OS_WAIT4_METHODDEF
13632 OS_WAITID_METHODDEF
13633 OS_WAITPID_METHODDEF
13634 OS_GETSID_METHODDEF
13635 OS_SETSID_METHODDEF
13636 OS_SETPGID_METHODDEF
13637 OS_TCGETPGRP_METHODDEF
13638 OS_TCSETPGRP_METHODDEF
13639 OS_OPEN_METHODDEF
13640 OS_CLOSE_METHODDEF
13641 OS_CLOSERANGE_METHODDEF
13642 OS_DEVICE_ENCODING_METHODDEF
13643 OS_DUP_METHODDEF
13644 OS_DUP2_METHODDEF
13645 OS_LOCKF_METHODDEF
13646 OS_LSEEK_METHODDEF
13647 OS_READ_METHODDEF
13648 OS_READV_METHODDEF
13649 OS_PREAD_METHODDEF
13650 OS_PREADV_METHODDEF
13651 OS_WRITE_METHODDEF
13652 OS_WRITEV_METHODDEF
13653 OS_PWRITE_METHODDEF
13654 OS_PWRITEV_METHODDEF
13655 #ifdef HAVE_SENDFILE
13656 {"sendfile", (PyCFunction)(void(*)(void))posix_sendfile, METH_VARARGS | METH_KEYWORDS,
13657 posix_sendfile__doc__},
13658 #endif
13659 OS_FSTAT_METHODDEF
13660 OS_ISATTY_METHODDEF
13661 OS_PIPE_METHODDEF
13662 OS_PIPE2_METHODDEF
13663 OS_MKFIFO_METHODDEF
13664 OS_MKNOD_METHODDEF
13665 OS_MAJOR_METHODDEF
13666 OS_MINOR_METHODDEF
13667 OS_MAKEDEV_METHODDEF
13668 OS_FTRUNCATE_METHODDEF
13669 OS_TRUNCATE_METHODDEF
13670 OS_POSIX_FALLOCATE_METHODDEF
13671 OS_POSIX_FADVISE_METHODDEF
13672 OS_PUTENV_METHODDEF
13673 OS_UNSETENV_METHODDEF
13674 OS_STRERROR_METHODDEF
13675 OS_FCHDIR_METHODDEF
13676 OS_FSYNC_METHODDEF
13677 OS_SYNC_METHODDEF
13678 OS_FDATASYNC_METHODDEF
13679 OS_WCOREDUMP_METHODDEF
13680 OS_WIFCONTINUED_METHODDEF
13681 OS_WIFSTOPPED_METHODDEF
13682 OS_WIFSIGNALED_METHODDEF
13683 OS_WIFEXITED_METHODDEF
13684 OS_WEXITSTATUS_METHODDEF
13685 OS_WTERMSIG_METHODDEF
13686 OS_WSTOPSIG_METHODDEF
13687 OS_FSTATVFS_METHODDEF
13688 OS_STATVFS_METHODDEF
13689 OS_CONFSTR_METHODDEF
13690 OS_SYSCONF_METHODDEF
13691 OS_FPATHCONF_METHODDEF
13692 OS_PATHCONF_METHODDEF
13693 OS_ABORT_METHODDEF
13694 OS__GETFULLPATHNAME_METHODDEF
13695 OS__GETDISKUSAGE_METHODDEF
13696 OS__GETFINALPATHNAME_METHODDEF
13697 OS__GETVOLUMEPATHNAME_METHODDEF
13698 OS_GETLOADAVG_METHODDEF
13699 OS_URANDOM_METHODDEF
13700 OS_SETRESUID_METHODDEF
13701 OS_SETRESGID_METHODDEF
13702 OS_GETRESUID_METHODDEF
13703 OS_GETRESGID_METHODDEF
13704
13705 OS_GETXATTR_METHODDEF
13706 OS_SETXATTR_METHODDEF
13707 OS_REMOVEXATTR_METHODDEF
13708 OS_LISTXATTR_METHODDEF
13709
13710 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
13711 {"get_terminal_size", get_terminal_size, METH_VARARGS, termsize__doc__},
13712 #endif
13713 OS_CPU_COUNT_METHODDEF
13714 OS_GET_INHERITABLE_METHODDEF
13715 OS_SET_INHERITABLE_METHODDEF
13716 OS_GET_HANDLE_INHERITABLE_METHODDEF
13717 OS_SET_HANDLE_INHERITABLE_METHODDEF
13718 #ifndef MS_WINDOWS
13719 OS_GET_BLOCKING_METHODDEF
13720 OS_SET_BLOCKING_METHODDEF
13721 #endif
13722 OS_SCANDIR_METHODDEF
13723 OS_FSPATH_METHODDEF
13724 OS_GETRANDOM_METHODDEF
13725 OS_MEMFD_CREATE_METHODDEF
13726 #ifdef MS_WINDOWS
13727 OS__ADD_DLL_DIRECTORY_METHODDEF
13728 OS__REMOVE_DLL_DIRECTORY_METHODDEF
13729 #endif
13730 {NULL, NULL} /* Sentinel */
13731 };
13732
13733 static int
all_ins(PyObject * m)13734 all_ins(PyObject *m)
13735 {
13736 #ifdef F_OK
13737 if (PyModule_AddIntMacro(m, F_OK)) return -1;
13738 #endif
13739 #ifdef R_OK
13740 if (PyModule_AddIntMacro(m, R_OK)) return -1;
13741 #endif
13742 #ifdef W_OK
13743 if (PyModule_AddIntMacro(m, W_OK)) return -1;
13744 #endif
13745 #ifdef X_OK
13746 if (PyModule_AddIntMacro(m, X_OK)) return -1;
13747 #endif
13748 #ifdef NGROUPS_MAX
13749 if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
13750 #endif
13751 #ifdef TMP_MAX
13752 if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
13753 #endif
13754 #ifdef WCONTINUED
13755 if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
13756 #endif
13757 #ifdef WNOHANG
13758 if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
13759 #endif
13760 #ifdef WUNTRACED
13761 if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
13762 #endif
13763 #ifdef O_RDONLY
13764 if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
13765 #endif
13766 #ifdef O_WRONLY
13767 if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
13768 #endif
13769 #ifdef O_RDWR
13770 if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
13771 #endif
13772 #ifdef O_NDELAY
13773 if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
13774 #endif
13775 #ifdef O_NONBLOCK
13776 if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
13777 #endif
13778 #ifdef O_APPEND
13779 if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
13780 #endif
13781 #ifdef O_DSYNC
13782 if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
13783 #endif
13784 #ifdef O_RSYNC
13785 if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
13786 #endif
13787 #ifdef O_SYNC
13788 if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
13789 #endif
13790 #ifdef O_NOCTTY
13791 if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
13792 #endif
13793 #ifdef O_CREAT
13794 if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
13795 #endif
13796 #ifdef O_EXCL
13797 if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
13798 #endif
13799 #ifdef O_TRUNC
13800 if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
13801 #endif
13802 #ifdef O_BINARY
13803 if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
13804 #endif
13805 #ifdef O_TEXT
13806 if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
13807 #endif
13808 #ifdef O_XATTR
13809 if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
13810 #endif
13811 #ifdef O_LARGEFILE
13812 if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
13813 #endif
13814 #ifndef __GNU__
13815 #ifdef O_SHLOCK
13816 if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
13817 #endif
13818 #ifdef O_EXLOCK
13819 if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
13820 #endif
13821 #endif
13822 #ifdef O_EXEC
13823 if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
13824 #endif
13825 #ifdef O_SEARCH
13826 if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
13827 #endif
13828 #ifdef O_PATH
13829 if (PyModule_AddIntMacro(m, O_PATH)) return -1;
13830 #endif
13831 #ifdef O_TTY_INIT
13832 if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
13833 #endif
13834 #ifdef O_TMPFILE
13835 if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
13836 #endif
13837 #ifdef PRIO_PROCESS
13838 if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
13839 #endif
13840 #ifdef PRIO_PGRP
13841 if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
13842 #endif
13843 #ifdef PRIO_USER
13844 if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
13845 #endif
13846 #ifdef O_CLOEXEC
13847 if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
13848 #endif
13849 #ifdef O_ACCMODE
13850 if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
13851 #endif
13852
13853
13854 #ifdef SEEK_HOLE
13855 if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
13856 #endif
13857 #ifdef SEEK_DATA
13858 if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
13859 #endif
13860
13861 /* MS Windows */
13862 #ifdef O_NOINHERIT
13863 /* Don't inherit in child processes. */
13864 if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
13865 #endif
13866 #ifdef _O_SHORT_LIVED
13867 /* Optimize for short life (keep in memory). */
13868 /* MS forgot to define this one with a non-underscore form too. */
13869 if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
13870 #endif
13871 #ifdef O_TEMPORARY
13872 /* Automatically delete when last handle is closed. */
13873 if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
13874 #endif
13875 #ifdef O_RANDOM
13876 /* Optimize for random access. */
13877 if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
13878 #endif
13879 #ifdef O_SEQUENTIAL
13880 /* Optimize for sequential access. */
13881 if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
13882 #endif
13883
13884 /* GNU extensions. */
13885 #ifdef O_ASYNC
13886 /* Send a SIGIO signal whenever input or output
13887 becomes available on file descriptor */
13888 if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
13889 #endif
13890 #ifdef O_DIRECT
13891 /* Direct disk access. */
13892 if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
13893 #endif
13894 #ifdef O_DIRECTORY
13895 /* Must be a directory. */
13896 if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
13897 #endif
13898 #ifdef O_NOFOLLOW
13899 /* Do not follow links. */
13900 if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
13901 #endif
13902 #ifdef O_NOLINKS
13903 /* Fails if link count of the named file is greater than 1 */
13904 if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
13905 #endif
13906 #ifdef O_NOATIME
13907 /* Do not update the access time. */
13908 if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
13909 #endif
13910
13911 /* These come from sysexits.h */
13912 #ifdef EX_OK
13913 if (PyModule_AddIntMacro(m, EX_OK)) return -1;
13914 #endif /* EX_OK */
13915 #ifdef EX_USAGE
13916 if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
13917 #endif /* EX_USAGE */
13918 #ifdef EX_DATAERR
13919 if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
13920 #endif /* EX_DATAERR */
13921 #ifdef EX_NOINPUT
13922 if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
13923 #endif /* EX_NOINPUT */
13924 #ifdef EX_NOUSER
13925 if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
13926 #endif /* EX_NOUSER */
13927 #ifdef EX_NOHOST
13928 if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
13929 #endif /* EX_NOHOST */
13930 #ifdef EX_UNAVAILABLE
13931 if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
13932 #endif /* EX_UNAVAILABLE */
13933 #ifdef EX_SOFTWARE
13934 if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
13935 #endif /* EX_SOFTWARE */
13936 #ifdef EX_OSERR
13937 if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
13938 #endif /* EX_OSERR */
13939 #ifdef EX_OSFILE
13940 if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
13941 #endif /* EX_OSFILE */
13942 #ifdef EX_CANTCREAT
13943 if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
13944 #endif /* EX_CANTCREAT */
13945 #ifdef EX_IOERR
13946 if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
13947 #endif /* EX_IOERR */
13948 #ifdef EX_TEMPFAIL
13949 if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
13950 #endif /* EX_TEMPFAIL */
13951 #ifdef EX_PROTOCOL
13952 if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
13953 #endif /* EX_PROTOCOL */
13954 #ifdef EX_NOPERM
13955 if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
13956 #endif /* EX_NOPERM */
13957 #ifdef EX_CONFIG
13958 if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
13959 #endif /* EX_CONFIG */
13960 #ifdef EX_NOTFOUND
13961 if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
13962 #endif /* EX_NOTFOUND */
13963
13964 /* statvfs */
13965 #ifdef ST_RDONLY
13966 if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
13967 #endif /* ST_RDONLY */
13968 #ifdef ST_NOSUID
13969 if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
13970 #endif /* ST_NOSUID */
13971
13972 /* GNU extensions */
13973 #ifdef ST_NODEV
13974 if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
13975 #endif /* ST_NODEV */
13976 #ifdef ST_NOEXEC
13977 if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
13978 #endif /* ST_NOEXEC */
13979 #ifdef ST_SYNCHRONOUS
13980 if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
13981 #endif /* ST_SYNCHRONOUS */
13982 #ifdef ST_MANDLOCK
13983 if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
13984 #endif /* ST_MANDLOCK */
13985 #ifdef ST_WRITE
13986 if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
13987 #endif /* ST_WRITE */
13988 #ifdef ST_APPEND
13989 if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
13990 #endif /* ST_APPEND */
13991 #ifdef ST_NOATIME
13992 if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
13993 #endif /* ST_NOATIME */
13994 #ifdef ST_NODIRATIME
13995 if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
13996 #endif /* ST_NODIRATIME */
13997 #ifdef ST_RELATIME
13998 if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
13999 #endif /* ST_RELATIME */
14000
14001 /* FreeBSD sendfile() constants */
14002 #ifdef SF_NODISKIO
14003 if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
14004 #endif
14005 #ifdef SF_MNOWAIT
14006 if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
14007 #endif
14008 #ifdef SF_SYNC
14009 if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
14010 #endif
14011
14012 /* constants for posix_fadvise */
14013 #ifdef POSIX_FADV_NORMAL
14014 if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
14015 #endif
14016 #ifdef POSIX_FADV_SEQUENTIAL
14017 if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
14018 #endif
14019 #ifdef POSIX_FADV_RANDOM
14020 if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
14021 #endif
14022 #ifdef POSIX_FADV_NOREUSE
14023 if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
14024 #endif
14025 #ifdef POSIX_FADV_WILLNEED
14026 if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
14027 #endif
14028 #ifdef POSIX_FADV_DONTNEED
14029 if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
14030 #endif
14031
14032 /* constants for waitid */
14033 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
14034 if (PyModule_AddIntMacro(m, P_PID)) return -1;
14035 if (PyModule_AddIntMacro(m, P_PGID)) return -1;
14036 if (PyModule_AddIntMacro(m, P_ALL)) return -1;
14037 #endif
14038 #ifdef WEXITED
14039 if (PyModule_AddIntMacro(m, WEXITED)) return -1;
14040 #endif
14041 #ifdef WNOWAIT
14042 if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
14043 #endif
14044 #ifdef WSTOPPED
14045 if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
14046 #endif
14047 #ifdef CLD_EXITED
14048 if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
14049 #endif
14050 #ifdef CLD_DUMPED
14051 if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
14052 #endif
14053 #ifdef CLD_TRAPPED
14054 if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
14055 #endif
14056 #ifdef CLD_CONTINUED
14057 if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
14058 #endif
14059
14060 /* constants for lockf */
14061 #ifdef F_LOCK
14062 if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
14063 #endif
14064 #ifdef F_TLOCK
14065 if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
14066 #endif
14067 #ifdef F_ULOCK
14068 if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
14069 #endif
14070 #ifdef F_TEST
14071 if (PyModule_AddIntMacro(m, F_TEST)) return -1;
14072 #endif
14073
14074 #ifdef RWF_DSYNC
14075 if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
14076 #endif
14077 #ifdef RWF_HIPRI
14078 if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
14079 #endif
14080 #ifdef RWF_SYNC
14081 if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
14082 #endif
14083 #ifdef RWF_NOWAIT
14084 if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
14085 #endif
14086
14087 /* constants for posix_spawn */
14088 #ifdef HAVE_POSIX_SPAWN
14089 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
14090 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
14091 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
14092 #endif
14093
14094 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
14095 if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
14096 if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
14097 if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
14098 #endif
14099 #ifdef HAVE_SPAWNV
14100 if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
14101 if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
14102 #endif
14103
14104 #ifdef HAVE_SCHED_H
14105 #ifdef SCHED_OTHER
14106 if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
14107 #endif
14108 #ifdef SCHED_FIFO
14109 if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
14110 #endif
14111 #ifdef SCHED_RR
14112 if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
14113 #endif
14114 #ifdef SCHED_SPORADIC
14115 if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
14116 #endif
14117 #ifdef SCHED_BATCH
14118 if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
14119 #endif
14120 #ifdef SCHED_IDLE
14121 if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
14122 #endif
14123 #ifdef SCHED_RESET_ON_FORK
14124 if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
14125 #endif
14126 #ifdef SCHED_SYS
14127 if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
14128 #endif
14129 #ifdef SCHED_IA
14130 if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
14131 #endif
14132 #ifdef SCHED_FSS
14133 if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
14134 #endif
14135 #ifdef SCHED_FX
14136 if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
14137 #endif
14138 #endif
14139
14140 #ifdef USE_XATTRS
14141 if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
14142 if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
14143 if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
14144 #endif
14145
14146 #if HAVE_DECL_RTLD_LAZY
14147 if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
14148 #endif
14149 #if HAVE_DECL_RTLD_NOW
14150 if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
14151 #endif
14152 #if HAVE_DECL_RTLD_GLOBAL
14153 if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
14154 #endif
14155 #if HAVE_DECL_RTLD_LOCAL
14156 if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
14157 #endif
14158 #if HAVE_DECL_RTLD_NODELETE
14159 if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
14160 #endif
14161 #if HAVE_DECL_RTLD_NOLOAD
14162 if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
14163 #endif
14164 #if HAVE_DECL_RTLD_DEEPBIND
14165 if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
14166 #endif
14167 #if HAVE_DECL_RTLD_MEMBER
14168 if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
14169 #endif
14170
14171 #ifdef HAVE_GETRANDOM_SYSCALL
14172 if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
14173 if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
14174 #endif
14175 #ifdef HAVE_MEMFD_CREATE
14176 if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
14177 if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
14178 #ifdef MFD_HUGETLB
14179 if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
14180 #endif
14181 #ifdef MFD_HUGE_SHIFT
14182 if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
14183 #endif
14184 #ifdef MFD_HUGE_MASK
14185 if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
14186 #endif
14187 #ifdef MFD_HUGE_64KB
14188 if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
14189 #endif
14190 #ifdef MFD_HUGE_512KB
14191 if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
14192 #endif
14193 #ifdef MFD_HUGE_1MB
14194 if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
14195 #endif
14196 #ifdef MFD_HUGE_2MB
14197 if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
14198 #endif
14199 #ifdef MFD_HUGE_8MB
14200 if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
14201 #endif
14202 #ifdef MFD_HUGE_16MB
14203 if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
14204 #endif
14205 #ifdef MFD_HUGE_32MB
14206 if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
14207 #endif
14208 #ifdef MFD_HUGE_256MB
14209 if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
14210 #endif
14211 #ifdef MFD_HUGE_512MB
14212 if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
14213 #endif
14214 #ifdef MFD_HUGE_1GB
14215 if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
14216 #endif
14217 #ifdef MFD_HUGE_2GB
14218 if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
14219 #endif
14220 #ifdef MFD_HUGE_16GB
14221 if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
14222 #endif
14223 #endif
14224
14225 #if defined(__APPLE__)
14226 if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
14227 #endif
14228
14229 #ifdef MS_WINDOWS
14230 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
14231 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
14232 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
14233 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
14234 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
14235 #endif
14236
14237 return 0;
14238 }
14239
14240
14241 static struct PyModuleDef posixmodule = {
14242 PyModuleDef_HEAD_INIT,
14243 MODNAME,
14244 posix__doc__,
14245 -1,
14246 posix_methods,
14247 NULL,
14248 NULL,
14249 NULL,
14250 NULL
14251 };
14252
14253
14254 static const char * const have_functions[] = {
14255
14256 #ifdef HAVE_FACCESSAT
14257 "HAVE_FACCESSAT",
14258 #endif
14259
14260 #ifdef HAVE_FCHDIR
14261 "HAVE_FCHDIR",
14262 #endif
14263
14264 #ifdef HAVE_FCHMOD
14265 "HAVE_FCHMOD",
14266 #endif
14267
14268 #ifdef HAVE_FCHMODAT
14269 "HAVE_FCHMODAT",
14270 #endif
14271
14272 #ifdef HAVE_FCHOWN
14273 "HAVE_FCHOWN",
14274 #endif
14275
14276 #ifdef HAVE_FCHOWNAT
14277 "HAVE_FCHOWNAT",
14278 #endif
14279
14280 #ifdef HAVE_FEXECVE
14281 "HAVE_FEXECVE",
14282 #endif
14283
14284 #ifdef HAVE_FDOPENDIR
14285 "HAVE_FDOPENDIR",
14286 #endif
14287
14288 #ifdef HAVE_FPATHCONF
14289 "HAVE_FPATHCONF",
14290 #endif
14291
14292 #ifdef HAVE_FSTATAT
14293 "HAVE_FSTATAT",
14294 #endif
14295
14296 #ifdef HAVE_FSTATVFS
14297 "HAVE_FSTATVFS",
14298 #endif
14299
14300 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
14301 "HAVE_FTRUNCATE",
14302 #endif
14303
14304 #ifdef HAVE_FUTIMENS
14305 "HAVE_FUTIMENS",
14306 #endif
14307
14308 #ifdef HAVE_FUTIMES
14309 "HAVE_FUTIMES",
14310 #endif
14311
14312 #ifdef HAVE_FUTIMESAT
14313 "HAVE_FUTIMESAT",
14314 #endif
14315
14316 #ifdef HAVE_LINKAT
14317 "HAVE_LINKAT",
14318 #endif
14319
14320 #ifdef HAVE_LCHFLAGS
14321 "HAVE_LCHFLAGS",
14322 #endif
14323
14324 #ifdef HAVE_LCHMOD
14325 "HAVE_LCHMOD",
14326 #endif
14327
14328 #ifdef HAVE_LCHOWN
14329 "HAVE_LCHOWN",
14330 #endif
14331
14332 #ifdef HAVE_LSTAT
14333 "HAVE_LSTAT",
14334 #endif
14335
14336 #ifdef HAVE_LUTIMES
14337 "HAVE_LUTIMES",
14338 #endif
14339
14340 #ifdef HAVE_MEMFD_CREATE
14341 "HAVE_MEMFD_CREATE",
14342 #endif
14343
14344 #ifdef HAVE_MKDIRAT
14345 "HAVE_MKDIRAT",
14346 #endif
14347
14348 #ifdef HAVE_MKFIFOAT
14349 "HAVE_MKFIFOAT",
14350 #endif
14351
14352 #ifdef HAVE_MKNODAT
14353 "HAVE_MKNODAT",
14354 #endif
14355
14356 #ifdef HAVE_OPENAT
14357 "HAVE_OPENAT",
14358 #endif
14359
14360 #ifdef HAVE_READLINKAT
14361 "HAVE_READLINKAT",
14362 #endif
14363
14364 #ifdef HAVE_RENAMEAT
14365 "HAVE_RENAMEAT",
14366 #endif
14367
14368 #ifdef HAVE_SYMLINKAT
14369 "HAVE_SYMLINKAT",
14370 #endif
14371
14372 #ifdef HAVE_UNLINKAT
14373 "HAVE_UNLINKAT",
14374 #endif
14375
14376 #ifdef HAVE_UTIMENSAT
14377 "HAVE_UTIMENSAT",
14378 #endif
14379
14380 #ifdef MS_WINDOWS
14381 "MS_WINDOWS",
14382 #endif
14383
14384 NULL
14385 };
14386
14387
14388 PyMODINIT_FUNC
INITFUNC(void)14389 INITFUNC(void)
14390 {
14391 PyObject *m, *v;
14392 PyObject *list;
14393 const char * const *trace;
14394
14395 m = PyModule_Create(&posixmodule);
14396 if (m == NULL)
14397 return NULL;
14398
14399 /* Initialize environ dictionary */
14400 v = convertenviron();
14401 Py_XINCREF(v);
14402 if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
14403 return NULL;
14404 Py_DECREF(v);
14405
14406 if (all_ins(m))
14407 return NULL;
14408
14409 if (setup_confname_tables(m))
14410 return NULL;
14411
14412 Py_INCREF(PyExc_OSError);
14413 PyModule_AddObject(m, "error", PyExc_OSError);
14414
14415 #ifdef HAVE_PUTENV
14416 if (posix_putenv_garbage == NULL)
14417 posix_putenv_garbage = PyDict_New();
14418 #endif
14419
14420 if (!initialized) {
14421 #if defined(HAVE_WAITID) && !defined(__APPLE__)
14422 waitid_result_desc.name = MODNAME ".waitid_result";
14423 WaitidResultType = PyStructSequence_NewType(&waitid_result_desc);
14424 if (WaitidResultType == NULL) {
14425 return NULL;
14426 }
14427 #endif
14428
14429 stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
14430 stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
14431 stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
14432 stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
14433 StatResultType = PyStructSequence_NewType(&stat_result_desc);
14434 if (StatResultType == NULL) {
14435 return NULL;
14436 }
14437 structseq_new = StatResultType->tp_new;
14438 StatResultType->tp_new = statresult_new;
14439
14440 statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
14441 StatVFSResultType = PyStructSequence_NewType(&statvfs_result_desc);
14442 if (StatVFSResultType == NULL) {
14443 return NULL;
14444 }
14445 #ifdef NEED_TICKS_PER_SECOND
14446 # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
14447 ticks_per_second = sysconf(_SC_CLK_TCK);
14448 # elif defined(HZ)
14449 ticks_per_second = HZ;
14450 # else
14451 ticks_per_second = 60; /* magic fallback value; may be bogus */
14452 # endif
14453 #endif
14454
14455 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
14456 sched_param_desc.name = MODNAME ".sched_param";
14457 SchedParamType = PyStructSequence_NewType(&sched_param_desc);
14458 if (SchedParamType == NULL) {
14459 return NULL;
14460 }
14461 SchedParamType->tp_new = os_sched_param;
14462 #endif
14463
14464 /* initialize TerminalSize_info */
14465 TerminalSizeType = PyStructSequence_NewType(&TerminalSize_desc);
14466 if (TerminalSizeType == NULL) {
14467 return NULL;
14468 }
14469
14470 /* initialize scandir types */
14471 if (PyType_Ready(&ScandirIteratorType) < 0)
14472 return NULL;
14473 if (PyType_Ready(&DirEntryType) < 0)
14474 return NULL;
14475 }
14476 #if defined(HAVE_WAITID) && !defined(__APPLE__)
14477 Py_INCREF((PyObject*) WaitidResultType);
14478 PyModule_AddObject(m, "waitid_result", (PyObject*) WaitidResultType);
14479 #endif
14480 Py_INCREF((PyObject*) StatResultType);
14481 PyModule_AddObject(m, "stat_result", (PyObject*) StatResultType);
14482 Py_INCREF((PyObject*) StatVFSResultType);
14483 PyModule_AddObject(m, "statvfs_result",
14484 (PyObject*) StatVFSResultType);
14485
14486 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
14487 Py_INCREF(SchedParamType);
14488 PyModule_AddObject(m, "sched_param", (PyObject *)SchedParamType);
14489 #endif
14490
14491 times_result_desc.name = MODNAME ".times_result";
14492 TimesResultType = PyStructSequence_NewType(×_result_desc);
14493 if (TimesResultType == NULL) {
14494 return NULL;
14495 }
14496 PyModule_AddObject(m, "times_result", (PyObject *)TimesResultType);
14497
14498 uname_result_desc.name = MODNAME ".uname_result";
14499 UnameResultType = PyStructSequence_NewType(&uname_result_desc);
14500 if (UnameResultType == NULL) {
14501 return NULL;
14502 }
14503 PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
14504
14505 #ifdef __APPLE__
14506 /*
14507 * Step 2 of weak-linking support on Mac OS X.
14508 *
14509 * The code below removes functions that are not available on the
14510 * currently active platform.
14511 *
14512 * This block allow one to use a python binary that was build on
14513 * OSX 10.4 on OSX 10.3, without losing access to new APIs on
14514 * OSX 10.4.
14515 */
14516 #ifdef HAVE_FSTATVFS
14517 if (fstatvfs == NULL) {
14518 if (PyObject_DelAttrString(m, "fstatvfs") == -1) {
14519 return NULL;
14520 }
14521 }
14522 #endif /* HAVE_FSTATVFS */
14523
14524 #ifdef HAVE_STATVFS
14525 if (statvfs == NULL) {
14526 if (PyObject_DelAttrString(m, "statvfs") == -1) {
14527 return NULL;
14528 }
14529 }
14530 #endif /* HAVE_STATVFS */
14531
14532 # ifdef HAVE_LCHOWN
14533 if (lchown == NULL) {
14534 if (PyObject_DelAttrString(m, "lchown") == -1) {
14535 return NULL;
14536 }
14537 }
14538 #endif /* HAVE_LCHOWN */
14539
14540
14541 #endif /* __APPLE__ */
14542
14543 Py_INCREF(TerminalSizeType);
14544 PyModule_AddObject(m, "terminal_size", (PyObject*)TerminalSizeType);
14545
14546 billion = PyLong_FromLong(1000000000);
14547 if (!billion)
14548 return NULL;
14549
14550 /* suppress "function not used" warnings */
14551 {
14552 int ignored;
14553 fd_specified("", -1);
14554 follow_symlinks_specified("", 1);
14555 dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
14556 dir_fd_converter(Py_None, &ignored);
14557 dir_fd_unavailable(Py_None, &ignored);
14558 }
14559
14560 /*
14561 * provide list of locally available functions
14562 * so os.py can populate support_* lists
14563 */
14564 list = PyList_New(0);
14565 if (!list)
14566 return NULL;
14567 for (trace = have_functions; *trace; trace++) {
14568 PyObject *unicode = PyUnicode_DecodeASCII(*trace, strlen(*trace), NULL);
14569 if (!unicode)
14570 return NULL;
14571 if (PyList_Append(list, unicode))
14572 return NULL;
14573 Py_DECREF(unicode);
14574 }
14575 PyModule_AddObject(m, "_have_functions", list);
14576
14577 Py_INCREF((PyObject *) &DirEntryType);
14578 PyModule_AddObject(m, "DirEntry", (PyObject *)&DirEntryType);
14579
14580 initialized = 1;
14581
14582 return m;
14583 }
14584
14585 #ifdef __cplusplus
14586 }
14587 #endif
14588