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