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 /* Our selection logic for which function to use is as follows:
8633 * 1. If close_range(2) is available, always prefer that; it's better for
8634 * contiguous ranges like this than fdwalk(3) which entails iterating over
8635 * the entire fd space and simply doing nothing for those outside the range.
8636 * 2. If closefrom(2) is available, we'll attempt to use that next if we're
8637 * closing up to sysconf(_SC_OPEN_MAX).
8638 * 2a. Fallback to fdwalk(3) if we're not closing up to sysconf(_SC_OPEN_MAX),
8639 * as that will be more performant if the range happens to have any chunk of
8640 * non-opened fd in the middle.
8641 * 2b. If fdwalk(3) isn't available, just do a plain close(2) loop.
8642 */
8643 #if defined(__FreeBSD__) || defined(__DragonFly__)
8644 #define USE_CLOSEFROM
8645 #endif /* __FreeBSD__ */
8646
8647 #ifdef HAVE_FDWALK
8648 #define USE_FDWALK
8649 #endif /* HAVE_FDWALK */
8650
8651 #ifdef USE_FDWALK
8652 static int
_fdwalk_close_func(void * lohi,int fd)8653 _fdwalk_close_func(void *lohi, int fd)
8654 {
8655 int lo = ((int *)lohi)[0];
8656 int hi = ((int *)lohi)[1];
8657
8658 if (fd >= hi)
8659 return 1;
8660 else if (fd >= lo)
8661 close(fd);
8662 return 0;
8663 }
8664 #endif /* USE_FDWALK */
8665
8666 /* Closes all file descriptors in [first, last], ignoring errors. */
8667 void
_Py_closerange(int first,int last)8668 _Py_closerange(int first, int last)
8669 {
8670 first = Py_MAX(first, 0);
8671 _Py_BEGIN_SUPPRESS_IPH
8672 #ifdef HAVE_CLOSE_RANGE
8673 if (close_range(first, last, 0) == 0 || errno != ENOSYS) {
8674 /* Any errors encountered while closing file descriptors are ignored;
8675 * ENOSYS means no kernel support, though,
8676 * so we'll fallback to the other methods. */
8677 }
8678 else
8679 #endif /* HAVE_CLOSE_RANGE */
8680 #ifdef USE_CLOSEFROM
8681 if (last >= sysconf(_SC_OPEN_MAX)) {
8682 /* Any errors encountered while closing file descriptors are ignored */
8683 closefrom(first);
8684 }
8685 else
8686 #endif /* USE_CLOSEFROM */
8687 #ifdef USE_FDWALK
8688 {
8689 int lohi[2];
8690 lohi[0] = first;
8691 lohi[1] = last + 1;
8692 fdwalk(_fdwalk_close_func, lohi);
8693 }
8694 #else
8695 {
8696 for (int i = first; i <= last; i++) {
8697 /* Ignore errors */
8698 (void)close(i);
8699 }
8700 }
8701 #endif /* USE_FDWALK */
8702 _Py_END_SUPPRESS_IPH
8703 }
8704
8705 /*[clinic input]
8706 os.closerange
8707
8708 fd_low: int
8709 fd_high: int
8710 /
8711
8712 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
8713 [clinic start generated code]*/
8714
8715 static PyObject *
os_closerange_impl(PyObject * module,int fd_low,int fd_high)8716 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
8717 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
8718 {
8719 Py_BEGIN_ALLOW_THREADS
8720 _Py_closerange(fd_low, fd_high - 1);
8721 Py_END_ALLOW_THREADS
8722 Py_RETURN_NONE;
8723 }
8724
8725
8726 /*[clinic input]
8727 os.dup -> int
8728
8729 fd: int
8730 /
8731
8732 Return a duplicate of a file descriptor.
8733 [clinic start generated code]*/
8734
8735 static int
os_dup_impl(PyObject * module,int fd)8736 os_dup_impl(PyObject *module, int fd)
8737 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
8738 {
8739 return _Py_dup(fd);
8740 }
8741
8742
8743 /*[clinic input]
8744 os.dup2 -> int
8745 fd: int
8746 fd2: int
8747 inheritable: bool=True
8748
8749 Duplicate file descriptor.
8750 [clinic start generated code]*/
8751
8752 static int
os_dup2_impl(PyObject * module,int fd,int fd2,int inheritable)8753 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
8754 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
8755 {
8756 int res = 0;
8757 #if defined(HAVE_DUP3) && \
8758 !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
8759 /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
8760 static int dup3_works = -1;
8761 #endif
8762
8763 if (fd < 0 || fd2 < 0) {
8764 posix_error();
8765 return -1;
8766 }
8767
8768 /* dup2() can fail with EINTR if the target FD is already open, because it
8769 * then has to be closed. See os_close_impl() for why we don't handle EINTR
8770 * upon close(), and therefore below.
8771 */
8772 #ifdef MS_WINDOWS
8773 Py_BEGIN_ALLOW_THREADS
8774 _Py_BEGIN_SUPPRESS_IPH
8775 res = dup2(fd, fd2);
8776 _Py_END_SUPPRESS_IPH
8777 Py_END_ALLOW_THREADS
8778 if (res < 0) {
8779 posix_error();
8780 return -1;
8781 }
8782 res = fd2; // msvcrt dup2 returns 0 on success.
8783
8784 /* Character files like console cannot be make non-inheritable */
8785 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
8786 close(fd2);
8787 return -1;
8788 }
8789
8790 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
8791 Py_BEGIN_ALLOW_THREADS
8792 if (!inheritable)
8793 res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
8794 else
8795 res = dup2(fd, fd2);
8796 Py_END_ALLOW_THREADS
8797 if (res < 0) {
8798 posix_error();
8799 return -1;
8800 }
8801
8802 #else
8803
8804 #ifdef HAVE_DUP3
8805 if (!inheritable && dup3_works != 0) {
8806 Py_BEGIN_ALLOW_THREADS
8807 res = dup3(fd, fd2, O_CLOEXEC);
8808 Py_END_ALLOW_THREADS
8809 if (res < 0) {
8810 if (dup3_works == -1)
8811 dup3_works = (errno != ENOSYS);
8812 if (dup3_works) {
8813 posix_error();
8814 return -1;
8815 }
8816 }
8817 }
8818
8819 if (inheritable || dup3_works == 0)
8820 {
8821 #endif
8822 Py_BEGIN_ALLOW_THREADS
8823 res = dup2(fd, fd2);
8824 Py_END_ALLOW_THREADS
8825 if (res < 0) {
8826 posix_error();
8827 return -1;
8828 }
8829
8830 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
8831 close(fd2);
8832 return -1;
8833 }
8834 #ifdef HAVE_DUP3
8835 }
8836 #endif
8837
8838 #endif
8839
8840 return res;
8841 }
8842
8843
8844 #ifdef HAVE_LOCKF
8845 /*[clinic input]
8846 os.lockf
8847
8848 fd: int
8849 An open file descriptor.
8850 command: int
8851 One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
8852 length: Py_off_t
8853 The number of bytes to lock, starting at the current position.
8854 /
8855
8856 Apply, test or remove a POSIX lock on an open file descriptor.
8857
8858 [clinic start generated code]*/
8859
8860 static PyObject *
os_lockf_impl(PyObject * module,int fd,int command,Py_off_t length)8861 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
8862 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
8863 {
8864 int res;
8865
8866 if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
8867 return NULL;
8868 }
8869
8870 Py_BEGIN_ALLOW_THREADS
8871 res = lockf(fd, command, length);
8872 Py_END_ALLOW_THREADS
8873
8874 if (res < 0)
8875 return posix_error();
8876
8877 Py_RETURN_NONE;
8878 }
8879 #endif /* HAVE_LOCKF */
8880
8881
8882 /*[clinic input]
8883 os.lseek -> Py_off_t
8884
8885 fd: int
8886 position: Py_off_t
8887 how: int
8888 /
8889
8890 Set the position of a file descriptor. Return the new position.
8891
8892 Return the new cursor position in number of bytes
8893 relative to the beginning of the file.
8894 [clinic start generated code]*/
8895
8896 static Py_off_t
os_lseek_impl(PyObject * module,int fd,Py_off_t position,int how)8897 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
8898 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
8899 {
8900 Py_off_t result;
8901
8902 #ifdef SEEK_SET
8903 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
8904 switch (how) {
8905 case 0: how = SEEK_SET; break;
8906 case 1: how = SEEK_CUR; break;
8907 case 2: how = SEEK_END; break;
8908 }
8909 #endif /* SEEK_END */
8910
8911 Py_BEGIN_ALLOW_THREADS
8912 _Py_BEGIN_SUPPRESS_IPH
8913 #ifdef MS_WINDOWS
8914 result = _lseeki64(fd, position, how);
8915 #else
8916 result = lseek(fd, position, how);
8917 #endif
8918 _Py_END_SUPPRESS_IPH
8919 Py_END_ALLOW_THREADS
8920 if (result < 0)
8921 posix_error();
8922
8923 return result;
8924 }
8925
8926
8927 /*[clinic input]
8928 os.read
8929 fd: int
8930 length: Py_ssize_t
8931 /
8932
8933 Read from a file descriptor. Returns a bytes object.
8934 [clinic start generated code]*/
8935
8936 static PyObject *
os_read_impl(PyObject * module,int fd,Py_ssize_t length)8937 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
8938 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
8939 {
8940 Py_ssize_t n;
8941 PyObject *buffer;
8942
8943 if (length < 0) {
8944 errno = EINVAL;
8945 return posix_error();
8946 }
8947
8948 length = Py_MIN(length, _PY_READ_MAX);
8949
8950 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
8951 if (buffer == NULL)
8952 return NULL;
8953
8954 n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
8955 if (n == -1) {
8956 Py_DECREF(buffer);
8957 return NULL;
8958 }
8959
8960 if (n != length)
8961 _PyBytes_Resize(&buffer, n);
8962
8963 return buffer;
8964 }
8965
8966 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
8967 || defined(__APPLE__))) \
8968 || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
8969 || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
8970 static int
iov_setup(struct iovec ** iov,Py_buffer ** buf,PyObject * seq,Py_ssize_t cnt,int type)8971 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
8972 {
8973 Py_ssize_t i, j;
8974
8975 *iov = PyMem_New(struct iovec, cnt);
8976 if (*iov == NULL) {
8977 PyErr_NoMemory();
8978 return -1;
8979 }
8980
8981 *buf = PyMem_New(Py_buffer, cnt);
8982 if (*buf == NULL) {
8983 PyMem_Del(*iov);
8984 PyErr_NoMemory();
8985 return -1;
8986 }
8987
8988 for (i = 0; i < cnt; i++) {
8989 PyObject *item = PySequence_GetItem(seq, i);
8990 if (item == NULL)
8991 goto fail;
8992 if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
8993 Py_DECREF(item);
8994 goto fail;
8995 }
8996 Py_DECREF(item);
8997 (*iov)[i].iov_base = (*buf)[i].buf;
8998 (*iov)[i].iov_len = (*buf)[i].len;
8999 }
9000 return 0;
9001
9002 fail:
9003 PyMem_Del(*iov);
9004 for (j = 0; j < i; j++) {
9005 PyBuffer_Release(&(*buf)[j]);
9006 }
9007 PyMem_Del(*buf);
9008 return -1;
9009 }
9010
9011 static void
iov_cleanup(struct iovec * iov,Py_buffer * buf,int cnt)9012 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9013 {
9014 int i;
9015 PyMem_Del(iov);
9016 for (i = 0; i < cnt; i++) {
9017 PyBuffer_Release(&buf[i]);
9018 }
9019 PyMem_Del(buf);
9020 }
9021 #endif
9022
9023
9024 #ifdef HAVE_READV
9025 /*[clinic input]
9026 os.readv -> Py_ssize_t
9027
9028 fd: int
9029 buffers: object
9030 /
9031
9032 Read from a file descriptor fd into an iterable of buffers.
9033
9034 The buffers should be mutable buffers accepting bytes.
9035 readv will transfer data into each buffer until it is full
9036 and then move on to the next buffer in the sequence to hold
9037 the rest of the data.
9038
9039 readv returns the total number of bytes read,
9040 which may be less than the total capacity of all the buffers.
9041 [clinic start generated code]*/
9042
9043 static Py_ssize_t
os_readv_impl(PyObject * module,int fd,PyObject * buffers)9044 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9045 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9046 {
9047 Py_ssize_t cnt, n;
9048 int async_err = 0;
9049 struct iovec *iov;
9050 Py_buffer *buf;
9051
9052 if (!PySequence_Check(buffers)) {
9053 PyErr_SetString(PyExc_TypeError,
9054 "readv() arg 2 must be a sequence");
9055 return -1;
9056 }
9057
9058 cnt = PySequence_Size(buffers);
9059 if (cnt < 0)
9060 return -1;
9061
9062 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9063 return -1;
9064
9065 do {
9066 Py_BEGIN_ALLOW_THREADS
9067 n = readv(fd, iov, cnt);
9068 Py_END_ALLOW_THREADS
9069 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9070
9071 iov_cleanup(iov, buf, cnt);
9072 if (n < 0) {
9073 if (!async_err)
9074 posix_error();
9075 return -1;
9076 }
9077
9078 return n;
9079 }
9080 #endif /* HAVE_READV */
9081
9082
9083 #ifdef HAVE_PREAD
9084 /*[clinic input]
9085 # TODO length should be size_t! but Python doesn't support parsing size_t yet.
9086 os.pread
9087
9088 fd: int
9089 length: int
9090 offset: Py_off_t
9091 /
9092
9093 Read a number of bytes from a file descriptor starting at a particular offset.
9094
9095 Read length bytes from file descriptor fd, starting at offset bytes from
9096 the beginning of the file. The file offset remains unchanged.
9097 [clinic start generated code]*/
9098
9099 static PyObject *
os_pread_impl(PyObject * module,int fd,int length,Py_off_t offset)9100 os_pread_impl(PyObject *module, int fd, int length, Py_off_t offset)
9101 /*[clinic end generated code: output=435b29ee32b54a78 input=084948dcbaa35d4c]*/
9102 {
9103 Py_ssize_t n;
9104 int async_err = 0;
9105 PyObject *buffer;
9106
9107 if (length < 0) {
9108 errno = EINVAL;
9109 return posix_error();
9110 }
9111 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9112 if (buffer == NULL)
9113 return NULL;
9114
9115 do {
9116 Py_BEGIN_ALLOW_THREADS
9117 _Py_BEGIN_SUPPRESS_IPH
9118 n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9119 _Py_END_SUPPRESS_IPH
9120 Py_END_ALLOW_THREADS
9121 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9122
9123 if (n < 0) {
9124 Py_DECREF(buffer);
9125 return (!async_err) ? posix_error() : NULL;
9126 }
9127 if (n != length)
9128 _PyBytes_Resize(&buffer, n);
9129 return buffer;
9130 }
9131 #endif /* HAVE_PREAD */
9132
9133 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9134 /*[clinic input]
9135 os.preadv -> Py_ssize_t
9136
9137 fd: int
9138 buffers: object
9139 offset: Py_off_t
9140 flags: int = 0
9141 /
9142
9143 Reads from a file descriptor into a number of mutable bytes-like objects.
9144
9145 Combines the functionality of readv() and pread(). As readv(), it will
9146 transfer data into each buffer until it is full and then move on to the next
9147 buffer in the sequence to hold the rest of the data. Its fourth argument,
9148 specifies the file offset at which the input operation is to be performed. It
9149 will return the total number of bytes read (which can be less than the total
9150 capacity of all the objects).
9151
9152 The flags argument contains a bitwise OR of zero or more of the following flags:
9153
9154 - RWF_HIPRI
9155 - RWF_NOWAIT
9156
9157 Using non-zero flags requires Linux 4.6 or newer.
9158 [clinic start generated code]*/
9159
9160 static Py_ssize_t
os_preadv_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9161 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9162 int flags)
9163 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9164 {
9165 Py_ssize_t cnt, n;
9166 int async_err = 0;
9167 struct iovec *iov;
9168 Py_buffer *buf;
9169
9170 if (!PySequence_Check(buffers)) {
9171 PyErr_SetString(PyExc_TypeError,
9172 "preadv2() arg 2 must be a sequence");
9173 return -1;
9174 }
9175
9176 cnt = PySequence_Size(buffers);
9177 if (cnt < 0) {
9178 return -1;
9179 }
9180
9181 #ifndef HAVE_PREADV2
9182 if(flags != 0) {
9183 argument_unavailable_error("preadv2", "flags");
9184 return -1;
9185 }
9186 #endif
9187
9188 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9189 return -1;
9190 }
9191 #ifdef HAVE_PREADV2
9192 do {
9193 Py_BEGIN_ALLOW_THREADS
9194 _Py_BEGIN_SUPPRESS_IPH
9195 n = preadv2(fd, iov, cnt, offset, flags);
9196 _Py_END_SUPPRESS_IPH
9197 Py_END_ALLOW_THREADS
9198 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9199 #else
9200 do {
9201 Py_BEGIN_ALLOW_THREADS
9202 _Py_BEGIN_SUPPRESS_IPH
9203 n = preadv(fd, iov, cnt, offset);
9204 _Py_END_SUPPRESS_IPH
9205 Py_END_ALLOW_THREADS
9206 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9207 #endif
9208
9209 iov_cleanup(iov, buf, cnt);
9210 if (n < 0) {
9211 if (!async_err) {
9212 posix_error();
9213 }
9214 return -1;
9215 }
9216
9217 return n;
9218 }
9219 #endif /* HAVE_PREADV */
9220
9221
9222 /*[clinic input]
9223 os.write -> Py_ssize_t
9224
9225 fd: int
9226 data: Py_buffer
9227 /
9228
9229 Write a bytes object to a file descriptor.
9230 [clinic start generated code]*/
9231
9232 static Py_ssize_t
os_write_impl(PyObject * module,int fd,Py_buffer * data)9233 os_write_impl(PyObject *module, int fd, Py_buffer *data)
9234 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9235 {
9236 return _Py_write(fd, data->buf, data->len);
9237 }
9238
9239 #ifdef HAVE_SENDFILE
9240 PyDoc_STRVAR(posix_sendfile__doc__,
9241 "sendfile(out, in, offset, count) -> byteswritten\n\
9242 sendfile(out, in, offset, count[, headers][, trailers], flags=0)\n\
9243 -> byteswritten\n\
9244 Copy count bytes from file descriptor in to file descriptor out.");
9245
9246 /* AC 3.5: don't bother converting, has optional group*/
9247 static PyObject *
posix_sendfile(PyObject * self,PyObject * args,PyObject * kwdict)9248 posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
9249 {
9250 int in, out;
9251 Py_ssize_t ret;
9252 int async_err = 0;
9253 off_t offset;
9254
9255 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9256 #ifndef __APPLE__
9257 Py_ssize_t len;
9258 #endif
9259 PyObject *headers = NULL, *trailers = NULL;
9260 Py_buffer *hbuf, *tbuf;
9261 off_t sbytes;
9262 struct sf_hdtr sf;
9263 int flags = 0;
9264 /* Beware that "in" clashes with Python's own "in" operator keyword */
9265 static char *keywords[] = {"out", "in",
9266 "offset", "count",
9267 "headers", "trailers", "flags", NULL};
9268
9269 sf.headers = NULL;
9270 sf.trailers = NULL;
9271
9272 #ifdef __APPLE__
9273 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile",
9274 keywords, &out, &in, Py_off_t_converter, &offset, Py_off_t_converter, &sbytes,
9275 #else
9276 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile",
9277 keywords, &out, &in, Py_off_t_converter, &offset, &len,
9278 #endif
9279 &headers, &trailers, &flags))
9280 return NULL;
9281 if (headers != NULL) {
9282 if (!PySequence_Check(headers)) {
9283 PyErr_SetString(PyExc_TypeError,
9284 "sendfile() headers must be a sequence");
9285 return NULL;
9286 } else {
9287 Py_ssize_t i = PySequence_Size(headers);
9288 if (i < 0)
9289 return NULL;
9290 if (i > INT_MAX) {
9291 PyErr_SetString(PyExc_OverflowError,
9292 "sendfile() header is too large");
9293 return NULL;
9294 }
9295 if (i > 0) {
9296 sf.hdr_cnt = (int)i;
9297 if (iov_setup(&(sf.headers), &hbuf,
9298 headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9299 return NULL;
9300 #ifdef __APPLE__
9301 for (i = 0; i < sf.hdr_cnt; i++) {
9302 Py_ssize_t blen = sf.headers[i].iov_len;
9303 # define OFF_T_MAX 0x7fffffffffffffff
9304 if (sbytes >= OFF_T_MAX - blen) {
9305 PyErr_SetString(PyExc_OverflowError,
9306 "sendfile() header is too large");
9307 return NULL;
9308 }
9309 sbytes += blen;
9310 }
9311 #endif
9312 }
9313 }
9314 }
9315 if (trailers != NULL) {
9316 if (!PySequence_Check(trailers)) {
9317 PyErr_SetString(PyExc_TypeError,
9318 "sendfile() trailers must be a sequence");
9319 return NULL;
9320 } else {
9321 Py_ssize_t i = PySequence_Size(trailers);
9322 if (i < 0)
9323 return NULL;
9324 if (i > INT_MAX) {
9325 PyErr_SetString(PyExc_OverflowError,
9326 "sendfile() trailer is too large");
9327 return NULL;
9328 }
9329 if (i > 0) {
9330 sf.trl_cnt = (int)i;
9331 if (iov_setup(&(sf.trailers), &tbuf,
9332 trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
9333 return NULL;
9334 }
9335 }
9336 }
9337
9338 _Py_BEGIN_SUPPRESS_IPH
9339 do {
9340 Py_BEGIN_ALLOW_THREADS
9341 #ifdef __APPLE__
9342 ret = sendfile(in, out, offset, &sbytes, &sf, flags);
9343 #else
9344 ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);
9345 #endif
9346 Py_END_ALLOW_THREADS
9347 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9348 _Py_END_SUPPRESS_IPH
9349
9350 if (sf.headers != NULL)
9351 iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
9352 if (sf.trailers != NULL)
9353 iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
9354
9355 if (ret < 0) {
9356 if ((errno == EAGAIN) || (errno == EBUSY)) {
9357 if (sbytes != 0) {
9358 // some data has been sent
9359 goto done;
9360 }
9361 else {
9362 // no data has been sent; upper application is supposed
9363 // to retry on EAGAIN or EBUSY
9364 return posix_error();
9365 }
9366 }
9367 return (!async_err) ? posix_error() : NULL;
9368 }
9369 goto done;
9370
9371 done:
9372 #if !defined(HAVE_LARGEFILE_SUPPORT)
9373 return Py_BuildValue("l", sbytes);
9374 #else
9375 return Py_BuildValue("L", sbytes);
9376 #endif
9377
9378 #else
9379 Py_ssize_t count;
9380 PyObject *offobj;
9381 static char *keywords[] = {"out", "in",
9382 "offset", "count", NULL};
9383 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",
9384 keywords, &out, &in, &offobj, &count))
9385 return NULL;
9386 #ifdef __linux__
9387 if (offobj == Py_None) {
9388 do {
9389 Py_BEGIN_ALLOW_THREADS
9390 ret = sendfile(out, in, NULL, count);
9391 Py_END_ALLOW_THREADS
9392 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9393 if (ret < 0)
9394 return (!async_err) ? posix_error() : NULL;
9395 return Py_BuildValue("n", ret);
9396 }
9397 #endif
9398 if (!Py_off_t_converter(offobj, &offset))
9399 return NULL;
9400
9401
9402 #if defined(__sun) && defined(__SVR4)
9403 // On illumos specifically sendfile() may perform a partial write but
9404 // return -1/an error (in one confirmed case the destination socket
9405 // had a 5 second timeout set and errno was EAGAIN) and it's on the client
9406 // code to check if the offset parameter was modified by sendfile().
9407 //
9408 // We need this variable to track said change.
9409 off_t original_offset = offset;
9410 #endif
9411
9412 do {
9413 Py_BEGIN_ALLOW_THREADS
9414 ret = sendfile(out, in, &offset, count);
9415 #if defined(__sun) && defined(__SVR4)
9416 // This handles illumos-specific sendfile() partial write behavior,
9417 // see a comment above for more details.
9418 if (ret < 0 && offset != original_offset) {
9419 ret = offset - original_offset;
9420 }
9421 #endif
9422 Py_END_ALLOW_THREADS
9423 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9424 if (ret < 0)
9425 return (!async_err) ? posix_error() : NULL;
9426 return Py_BuildValue("n", ret);
9427 #endif
9428 }
9429 #endif /* HAVE_SENDFILE */
9430
9431
9432 #if defined(__APPLE__)
9433 /*[clinic input]
9434 os._fcopyfile
9435
9436 infd: int
9437 outfd: int
9438 flags: int
9439 /
9440
9441 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
9442 [clinic start generated code]*/
9443
9444 static PyObject *
os__fcopyfile_impl(PyObject * module,int infd,int outfd,int flags)9445 os__fcopyfile_impl(PyObject *module, int infd, int outfd, int flags)
9446 /*[clinic end generated code: output=8e8885c721ec38e3 input=69e0770e600cb44f]*/
9447 {
9448 int ret;
9449
9450 Py_BEGIN_ALLOW_THREADS
9451 ret = fcopyfile(infd, outfd, NULL, flags);
9452 Py_END_ALLOW_THREADS
9453 if (ret < 0)
9454 return posix_error();
9455 Py_RETURN_NONE;
9456 }
9457 #endif
9458
9459
9460 /*[clinic input]
9461 os.fstat
9462
9463 fd : int
9464
9465 Perform a stat system call on the given file descriptor.
9466
9467 Like stat(), but for an open file descriptor.
9468 Equivalent to os.stat(fd).
9469 [clinic start generated code]*/
9470
9471 static PyObject *
os_fstat_impl(PyObject * module,int fd)9472 os_fstat_impl(PyObject *module, int fd)
9473 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
9474 {
9475 STRUCT_STAT st;
9476 int res;
9477 int async_err = 0;
9478
9479 do {
9480 Py_BEGIN_ALLOW_THREADS
9481 res = FSTAT(fd, &st);
9482 Py_END_ALLOW_THREADS
9483 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9484 if (res != 0) {
9485 #ifdef MS_WINDOWS
9486 return PyErr_SetFromWindowsErr(0);
9487 #else
9488 return (!async_err) ? posix_error() : NULL;
9489 #endif
9490 }
9491
9492 return _pystat_fromstructstat(&st);
9493 }
9494
9495
9496 /*[clinic input]
9497 os.isatty -> bool
9498 fd: int
9499 /
9500
9501 Return True if the fd is connected to a terminal.
9502
9503 Return True if the file descriptor is an open file descriptor
9504 connected to the slave end of a terminal.
9505 [clinic start generated code]*/
9506
9507 static int
os_isatty_impl(PyObject * module,int fd)9508 os_isatty_impl(PyObject *module, int fd)
9509 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
9510 {
9511 int return_value;
9512 _Py_BEGIN_SUPPRESS_IPH
9513 return_value = isatty(fd);
9514 _Py_END_SUPPRESS_IPH
9515 return return_value;
9516 }
9517
9518
9519 #ifdef HAVE_PIPE
9520 /*[clinic input]
9521 os.pipe
9522
9523 Create a pipe.
9524
9525 Returns a tuple of two file descriptors:
9526 (read_fd, write_fd)
9527 [clinic start generated code]*/
9528
9529 static PyObject *
os_pipe_impl(PyObject * module)9530 os_pipe_impl(PyObject *module)
9531 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
9532 {
9533 int fds[2];
9534 #ifdef MS_WINDOWS
9535 HANDLE read, write;
9536 SECURITY_ATTRIBUTES attr;
9537 BOOL ok;
9538 #else
9539 int res;
9540 #endif
9541
9542 #ifdef MS_WINDOWS
9543 attr.nLength = sizeof(attr);
9544 attr.lpSecurityDescriptor = NULL;
9545 attr.bInheritHandle = FALSE;
9546
9547 Py_BEGIN_ALLOW_THREADS
9548 _Py_BEGIN_SUPPRESS_IPH
9549 ok = CreatePipe(&read, &write, &attr, 0);
9550 if (ok) {
9551 fds[0] = _open_osfhandle((intptr_t)read, _O_RDONLY);
9552 fds[1] = _open_osfhandle((intptr_t)write, _O_WRONLY);
9553 if (fds[0] == -1 || fds[1] == -1) {
9554 CloseHandle(read);
9555 CloseHandle(write);
9556 ok = 0;
9557 }
9558 }
9559 _Py_END_SUPPRESS_IPH
9560 Py_END_ALLOW_THREADS
9561
9562 if (!ok)
9563 return PyErr_SetFromWindowsErr(0);
9564 #else
9565
9566 #ifdef HAVE_PIPE2
9567 Py_BEGIN_ALLOW_THREADS
9568 res = pipe2(fds, O_CLOEXEC);
9569 Py_END_ALLOW_THREADS
9570
9571 if (res != 0 && errno == ENOSYS)
9572 {
9573 #endif
9574 Py_BEGIN_ALLOW_THREADS
9575 res = pipe(fds);
9576 Py_END_ALLOW_THREADS
9577
9578 if (res == 0) {
9579 if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
9580 close(fds[0]);
9581 close(fds[1]);
9582 return NULL;
9583 }
9584 if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
9585 close(fds[0]);
9586 close(fds[1]);
9587 return NULL;
9588 }
9589 }
9590 #ifdef HAVE_PIPE2
9591 }
9592 #endif
9593
9594 if (res != 0)
9595 return PyErr_SetFromErrno(PyExc_OSError);
9596 #endif /* !MS_WINDOWS */
9597 return Py_BuildValue("(ii)", fds[0], fds[1]);
9598 }
9599 #endif /* HAVE_PIPE */
9600
9601
9602 #ifdef HAVE_PIPE2
9603 /*[clinic input]
9604 os.pipe2
9605
9606 flags: int
9607 /
9608
9609 Create a pipe with flags set atomically.
9610
9611 Returns a tuple of two file descriptors:
9612 (read_fd, write_fd)
9613
9614 flags can be constructed by ORing together one or more of these values:
9615 O_NONBLOCK, O_CLOEXEC.
9616 [clinic start generated code]*/
9617
9618 static PyObject *
os_pipe2_impl(PyObject * module,int flags)9619 os_pipe2_impl(PyObject *module, int flags)
9620 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
9621 {
9622 int fds[2];
9623 int res;
9624
9625 res = pipe2(fds, flags);
9626 if (res != 0)
9627 return posix_error();
9628 return Py_BuildValue("(ii)", fds[0], fds[1]);
9629 }
9630 #endif /* HAVE_PIPE2 */
9631
9632
9633 #ifdef HAVE_WRITEV
9634 /*[clinic input]
9635 os.writev -> Py_ssize_t
9636 fd: int
9637 buffers: object
9638 /
9639
9640 Iterate over buffers, and write the contents of each to a file descriptor.
9641
9642 Returns the total number of bytes written.
9643 buffers must be a sequence of bytes-like objects.
9644 [clinic start generated code]*/
9645
9646 static Py_ssize_t
os_writev_impl(PyObject * module,int fd,PyObject * buffers)9647 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
9648 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
9649 {
9650 Py_ssize_t cnt;
9651 Py_ssize_t result;
9652 int async_err = 0;
9653 struct iovec *iov;
9654 Py_buffer *buf;
9655
9656 if (!PySequence_Check(buffers)) {
9657 PyErr_SetString(PyExc_TypeError,
9658 "writev() arg 2 must be a sequence");
9659 return -1;
9660 }
9661 cnt = PySequence_Size(buffers);
9662 if (cnt < 0)
9663 return -1;
9664
9665 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
9666 return -1;
9667 }
9668
9669 do {
9670 Py_BEGIN_ALLOW_THREADS
9671 result = writev(fd, iov, cnt);
9672 Py_END_ALLOW_THREADS
9673 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9674
9675 iov_cleanup(iov, buf, cnt);
9676 if (result < 0 && !async_err)
9677 posix_error();
9678
9679 return result;
9680 }
9681 #endif /* HAVE_WRITEV */
9682
9683
9684 #ifdef HAVE_PWRITE
9685 /*[clinic input]
9686 os.pwrite -> Py_ssize_t
9687
9688 fd: int
9689 buffer: Py_buffer
9690 offset: Py_off_t
9691 /
9692
9693 Write bytes to a file descriptor starting at a particular offset.
9694
9695 Write buffer to fd, starting at offset bytes from the beginning of
9696 the file. Returns the number of bytes writte. Does not change the
9697 current file offset.
9698 [clinic start generated code]*/
9699
9700 static Py_ssize_t
os_pwrite_impl(PyObject * module,int fd,Py_buffer * buffer,Py_off_t offset)9701 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
9702 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
9703 {
9704 Py_ssize_t size;
9705 int async_err = 0;
9706
9707 do {
9708 Py_BEGIN_ALLOW_THREADS
9709 _Py_BEGIN_SUPPRESS_IPH
9710 size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
9711 _Py_END_SUPPRESS_IPH
9712 Py_END_ALLOW_THREADS
9713 } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9714
9715 if (size < 0 && !async_err)
9716 posix_error();
9717 return size;
9718 }
9719 #endif /* HAVE_PWRITE */
9720
9721 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9722 /*[clinic input]
9723 os.pwritev -> Py_ssize_t
9724
9725 fd: int
9726 buffers: object
9727 offset: Py_off_t
9728 flags: int = 0
9729 /
9730
9731 Writes the contents of bytes-like objects to a file descriptor at a given offset.
9732
9733 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
9734 of bytes-like objects. Buffers are processed in array order. Entire contents of first
9735 buffer is written before proceeding to second, and so on. The operating system may
9736 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
9737 This function writes the contents of each object to the file descriptor and returns
9738 the total number of bytes written.
9739
9740 The flags argument contains a bitwise OR of zero or more of the following flags:
9741
9742 - RWF_DSYNC
9743 - RWF_SYNC
9744
9745 Using non-zero flags requires Linux 4.7 or newer.
9746 [clinic start generated code]*/
9747
9748 static Py_ssize_t
os_pwritev_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9749 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9750 int flags)
9751 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=803dc5ddbf0cfd3b]*/
9752 {
9753 Py_ssize_t cnt;
9754 Py_ssize_t result;
9755 int async_err = 0;
9756 struct iovec *iov;
9757 Py_buffer *buf;
9758
9759 if (!PySequence_Check(buffers)) {
9760 PyErr_SetString(PyExc_TypeError,
9761 "pwritev() arg 2 must be a sequence");
9762 return -1;
9763 }
9764
9765 cnt = PySequence_Size(buffers);
9766 if (cnt < 0) {
9767 return -1;
9768 }
9769
9770 #ifndef HAVE_PWRITEV2
9771 if(flags != 0) {
9772 argument_unavailable_error("pwritev2", "flags");
9773 return -1;
9774 }
9775 #endif
9776
9777 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
9778 return -1;
9779 }
9780 #ifdef HAVE_PWRITEV2
9781 do {
9782 Py_BEGIN_ALLOW_THREADS
9783 _Py_BEGIN_SUPPRESS_IPH
9784 result = pwritev2(fd, iov, cnt, offset, flags);
9785 _Py_END_SUPPRESS_IPH
9786 Py_END_ALLOW_THREADS
9787 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9788 #else
9789 do {
9790 Py_BEGIN_ALLOW_THREADS
9791 _Py_BEGIN_SUPPRESS_IPH
9792 result = pwritev(fd, iov, cnt, offset);
9793 _Py_END_SUPPRESS_IPH
9794 Py_END_ALLOW_THREADS
9795 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9796 #endif
9797
9798 iov_cleanup(iov, buf, cnt);
9799 if (result < 0) {
9800 if (!async_err) {
9801 posix_error();
9802 }
9803 return -1;
9804 }
9805
9806 return result;
9807 }
9808 #endif /* HAVE_PWRITEV */
9809
9810 #ifdef HAVE_COPY_FILE_RANGE
9811 /*[clinic input]
9812
9813 os.copy_file_range
9814 src: int
9815 Source file descriptor.
9816 dst: int
9817 Destination file descriptor.
9818 count: Py_ssize_t
9819 Number of bytes to copy.
9820 offset_src: object = None
9821 Starting offset in src.
9822 offset_dst: object = None
9823 Starting offset in dst.
9824
9825 Copy count bytes from one file descriptor to another.
9826
9827 If offset_src is None, then src is read from the current position;
9828 respectively for offset_dst.
9829 [clinic start generated code]*/
9830
9831 static PyObject *
os_copy_file_range_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst)9832 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
9833 PyObject *offset_src, PyObject *offset_dst)
9834 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
9835 {
9836 off_t offset_src_val, offset_dst_val;
9837 off_t *p_offset_src = NULL;
9838 off_t *p_offset_dst = NULL;
9839 Py_ssize_t ret;
9840 int async_err = 0;
9841 /* The flags argument is provided to allow
9842 * for future extensions and currently must be to 0. */
9843 int flags = 0;
9844
9845
9846 if (count < 0) {
9847 PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
9848 return NULL;
9849 }
9850
9851 if (offset_src != Py_None) {
9852 if (!Py_off_t_converter(offset_src, &offset_src_val)) {
9853 return NULL;
9854 }
9855 p_offset_src = &offset_src_val;
9856 }
9857
9858 if (offset_dst != Py_None) {
9859 if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
9860 return NULL;
9861 }
9862 p_offset_dst = &offset_dst_val;
9863 }
9864
9865 do {
9866 Py_BEGIN_ALLOW_THREADS
9867 ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
9868 Py_END_ALLOW_THREADS
9869 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9870
9871 if (ret < 0) {
9872 return (!async_err) ? posix_error() : NULL;
9873 }
9874
9875 return PyLong_FromSsize_t(ret);
9876 }
9877 #endif /* HAVE_COPY_FILE_RANGE*/
9878
9879 #ifdef HAVE_MKFIFO
9880 /*[clinic input]
9881 os.mkfifo
9882
9883 path: path_t
9884 mode: int=0o666
9885 *
9886 dir_fd: dir_fd(requires='mkfifoat')=None
9887
9888 Create a "fifo" (a POSIX named pipe).
9889
9890 If dir_fd is not None, it should be a file descriptor open to a directory,
9891 and path should be relative; path will then be relative to that directory.
9892 dir_fd may not be implemented on your platform.
9893 If it is unavailable, using it will raise a NotImplementedError.
9894 [clinic start generated code]*/
9895
9896 static PyObject *
os_mkfifo_impl(PyObject * module,path_t * path,int mode,int dir_fd)9897 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
9898 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
9899 {
9900 int result;
9901 int async_err = 0;
9902
9903 do {
9904 Py_BEGIN_ALLOW_THREADS
9905 #ifdef HAVE_MKFIFOAT
9906 if (dir_fd != DEFAULT_DIR_FD)
9907 result = mkfifoat(dir_fd, path->narrow, mode);
9908 else
9909 #endif
9910 result = mkfifo(path->narrow, mode);
9911 Py_END_ALLOW_THREADS
9912 } while (result != 0 && errno == EINTR &&
9913 !(async_err = PyErr_CheckSignals()));
9914 if (result != 0)
9915 return (!async_err) ? posix_error() : NULL;
9916
9917 Py_RETURN_NONE;
9918 }
9919 #endif /* HAVE_MKFIFO */
9920
9921
9922 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
9923 /*[clinic input]
9924 os.mknod
9925
9926 path: path_t
9927 mode: int=0o600
9928 device: dev_t=0
9929 *
9930 dir_fd: dir_fd(requires='mknodat')=None
9931
9932 Create a node in the file system.
9933
9934 Create a node in the file system (file, device special file or named pipe)
9935 at path. mode specifies both the permissions to use and the
9936 type of node to be created, being combined (bitwise OR) with one of
9937 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,
9938 device defines the newly created device special file (probably using
9939 os.makedev()). Otherwise device is ignored.
9940
9941 If dir_fd is not None, it should be a file descriptor open to a directory,
9942 and path should be relative; path will then be relative to that directory.
9943 dir_fd may not be implemented on your platform.
9944 If it is unavailable, using it will raise a NotImplementedError.
9945 [clinic start generated code]*/
9946
9947 static PyObject *
os_mknod_impl(PyObject * module,path_t * path,int mode,dev_t device,int dir_fd)9948 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
9949 int dir_fd)
9950 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
9951 {
9952 int result;
9953 int async_err = 0;
9954
9955 do {
9956 Py_BEGIN_ALLOW_THREADS
9957 #ifdef HAVE_MKNODAT
9958 if (dir_fd != DEFAULT_DIR_FD)
9959 result = mknodat(dir_fd, path->narrow, mode, device);
9960 else
9961 #endif
9962 result = mknod(path->narrow, mode, device);
9963 Py_END_ALLOW_THREADS
9964 } while (result != 0 && errno == EINTR &&
9965 !(async_err = PyErr_CheckSignals()));
9966 if (result != 0)
9967 return (!async_err) ? posix_error() : NULL;
9968
9969 Py_RETURN_NONE;
9970 }
9971 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
9972
9973
9974 #ifdef HAVE_DEVICE_MACROS
9975 /*[clinic input]
9976 os.major -> unsigned_int
9977
9978 device: dev_t
9979 /
9980
9981 Extracts a device major number from a raw device number.
9982 [clinic start generated code]*/
9983
9984 static unsigned int
os_major_impl(PyObject * module,dev_t device)9985 os_major_impl(PyObject *module, dev_t device)
9986 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
9987 {
9988 return major(device);
9989 }
9990
9991
9992 /*[clinic input]
9993 os.minor -> unsigned_int
9994
9995 device: dev_t
9996 /
9997
9998 Extracts a device minor number from a raw device number.
9999 [clinic start generated code]*/
10000
10001 static unsigned int
os_minor_impl(PyObject * module,dev_t device)10002 os_minor_impl(PyObject *module, dev_t device)
10003 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10004 {
10005 return minor(device);
10006 }
10007
10008
10009 /*[clinic input]
10010 os.makedev -> dev_t
10011
10012 major: int
10013 minor: int
10014 /
10015
10016 Composes a raw device number from the major and minor device numbers.
10017 [clinic start generated code]*/
10018
10019 static dev_t
os_makedev_impl(PyObject * module,int major,int minor)10020 os_makedev_impl(PyObject *module, int major, int minor)
10021 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10022 {
10023 return makedev(major, minor);
10024 }
10025 #endif /* HAVE_DEVICE_MACROS */
10026
10027
10028 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10029 /*[clinic input]
10030 os.ftruncate
10031
10032 fd: int
10033 length: Py_off_t
10034 /
10035
10036 Truncate a file, specified by file descriptor, to a specific length.
10037 [clinic start generated code]*/
10038
10039 static PyObject *
os_ftruncate_impl(PyObject * module,int fd,Py_off_t length)10040 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10041 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10042 {
10043 int result;
10044 int async_err = 0;
10045
10046 if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10047 return NULL;
10048 }
10049
10050 do {
10051 Py_BEGIN_ALLOW_THREADS
10052 _Py_BEGIN_SUPPRESS_IPH
10053 #ifdef MS_WINDOWS
10054 result = _chsize_s(fd, length);
10055 #else
10056 result = ftruncate(fd, length);
10057 #endif
10058 _Py_END_SUPPRESS_IPH
10059 Py_END_ALLOW_THREADS
10060 } while (result != 0 && errno == EINTR &&
10061 !(async_err = PyErr_CheckSignals()));
10062 if (result != 0)
10063 return (!async_err) ? posix_error() : NULL;
10064 Py_RETURN_NONE;
10065 }
10066 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10067
10068
10069 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10070 /*[clinic input]
10071 os.truncate
10072 path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10073 length: Py_off_t
10074
10075 Truncate a file, specified by path, to a specific length.
10076
10077 On some platforms, path may also be specified as an open file descriptor.
10078 If this functionality is unavailable, using it raises an exception.
10079 [clinic start generated code]*/
10080
10081 static PyObject *
os_truncate_impl(PyObject * module,path_t * path,Py_off_t length)10082 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10083 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10084 {
10085 int result;
10086 #ifdef MS_WINDOWS
10087 int fd;
10088 #endif
10089
10090 if (path->fd != -1)
10091 return os_ftruncate_impl(module, path->fd, length);
10092
10093 if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10094 return NULL;
10095 }
10096
10097 Py_BEGIN_ALLOW_THREADS
10098 _Py_BEGIN_SUPPRESS_IPH
10099 #ifdef MS_WINDOWS
10100 fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10101 if (fd < 0)
10102 result = -1;
10103 else {
10104 result = _chsize_s(fd, length);
10105 close(fd);
10106 if (result < 0)
10107 errno = result;
10108 }
10109 #else
10110 result = truncate(path->narrow, length);
10111 #endif
10112 _Py_END_SUPPRESS_IPH
10113 Py_END_ALLOW_THREADS
10114 if (result < 0)
10115 return posix_path_error(path);
10116
10117 Py_RETURN_NONE;
10118 }
10119 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10120
10121
10122 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10123 and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10124 defined, which is the case in Python on AIX. AIX bug report:
10125 http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10126 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10127 # define POSIX_FADVISE_AIX_BUG
10128 #endif
10129
10130
10131 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10132 /*[clinic input]
10133 os.posix_fallocate
10134
10135 fd: int
10136 offset: Py_off_t
10137 length: Py_off_t
10138 /
10139
10140 Ensure a file has allocated at least a particular number of bytes on disk.
10141
10142 Ensure that the file specified by fd encompasses a range of bytes
10143 starting at offset bytes from the beginning and continuing for length bytes.
10144 [clinic start generated code]*/
10145
10146 static PyObject *
os_posix_fallocate_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length)10147 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10148 Py_off_t length)
10149 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10150 {
10151 int result;
10152 int async_err = 0;
10153
10154 do {
10155 Py_BEGIN_ALLOW_THREADS
10156 result = posix_fallocate(fd, offset, length);
10157 Py_END_ALLOW_THREADS
10158 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10159
10160 if (result == 0)
10161 Py_RETURN_NONE;
10162
10163 if (async_err)
10164 return NULL;
10165
10166 errno = result;
10167 return posix_error();
10168 }
10169 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
10170
10171
10172 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
10173 /*[clinic input]
10174 os.posix_fadvise
10175
10176 fd: int
10177 offset: Py_off_t
10178 length: Py_off_t
10179 advice: int
10180 /
10181
10182 Announce an intention to access data in a specific pattern.
10183
10184 Announce an intention to access data in a specific pattern, thus allowing
10185 the kernel to make optimizations.
10186 The advice applies to the region of the file specified by fd starting at
10187 offset and continuing for length bytes.
10188 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
10189 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
10190 POSIX_FADV_DONTNEED.
10191 [clinic start generated code]*/
10192
10193 static PyObject *
os_posix_fadvise_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length,int advice)10194 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
10195 Py_off_t length, int advice)
10196 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
10197 {
10198 int result;
10199 int async_err = 0;
10200
10201 do {
10202 Py_BEGIN_ALLOW_THREADS
10203 result = posix_fadvise(fd, offset, length, advice);
10204 Py_END_ALLOW_THREADS
10205 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10206
10207 if (result == 0)
10208 Py_RETURN_NONE;
10209
10210 if (async_err)
10211 return NULL;
10212
10213 errno = result;
10214 return posix_error();
10215 }
10216 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
10217
10218 #ifdef HAVE_PUTENV
10219
10220 /* Save putenv() parameters as values here, so we can collect them when they
10221 * get re-set with another call for the same key. */
10222 static PyObject *posix_putenv_garbage;
10223
10224 static void
posix_putenv_garbage_setitem(PyObject * name,PyObject * value)10225 posix_putenv_garbage_setitem(PyObject *name, PyObject *value)
10226 {
10227 /* Install the first arg and newstr in posix_putenv_garbage;
10228 * this will cause previous value to be collected. This has to
10229 * happen after the real putenv() call because the old value
10230 * was still accessible until then. */
10231 if (PyDict_SetItem(posix_putenv_garbage, name, value))
10232 /* really not much we can do; just leak */
10233 PyErr_Clear();
10234 else
10235 Py_DECREF(value);
10236 }
10237
10238
10239 #ifdef MS_WINDOWS
10240 /*[clinic input]
10241 os.putenv
10242
10243 name: unicode
10244 value: unicode
10245 /
10246
10247 Change or add an environment variable.
10248 [clinic start generated code]*/
10249
10250 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10251 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10252 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
10253 {
10254 const wchar_t *env;
10255 Py_ssize_t size;
10256
10257 /* Search from index 1 because on Windows starting '=' is allowed for
10258 defining hidden environment variables. */
10259 if (PyUnicode_GET_LENGTH(name) == 0 ||
10260 PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
10261 {
10262 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10263 return NULL;
10264 }
10265 PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value);
10266 if (unicode == NULL) {
10267 return NULL;
10268 }
10269
10270 env = PyUnicode_AsUnicodeAndSize(unicode, &size);
10271 if (env == NULL)
10272 goto error;
10273 if (size > _MAX_ENV) {
10274 PyErr_Format(PyExc_ValueError,
10275 "the environment variable is longer than %u characters",
10276 _MAX_ENV);
10277 goto error;
10278 }
10279 if (wcslen(env) != (size_t)size) {
10280 PyErr_SetString(PyExc_ValueError, "embedded null character");
10281 goto error;
10282 }
10283
10284 if (_wputenv(env)) {
10285 posix_error();
10286 goto error;
10287 }
10288
10289 posix_putenv_garbage_setitem(name, unicode);
10290 Py_RETURN_NONE;
10291
10292 error:
10293 Py_DECREF(unicode);
10294 return NULL;
10295 }
10296 #else /* MS_WINDOWS */
10297 /*[clinic input]
10298 os.putenv
10299
10300 name: FSConverter
10301 value: FSConverter
10302 /
10303
10304 Change or add an environment variable.
10305 [clinic start generated code]*/
10306
10307 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10308 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10309 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
10310 {
10311 PyObject *bytes = NULL;
10312 char *env;
10313 const char *name_string = PyBytes_AS_STRING(name);
10314 const char *value_string = PyBytes_AS_STRING(value);
10315
10316 if (strchr(name_string, '=') != NULL) {
10317 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10318 return NULL;
10319 }
10320 if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10321 return NULL;
10322 }
10323 bytes = PyBytes_FromFormat("%s=%s", name_string, value_string);
10324 if (bytes == NULL) {
10325 return NULL;
10326 }
10327
10328 env = PyBytes_AS_STRING(bytes);
10329 if (putenv(env)) {
10330 Py_DECREF(bytes);
10331 return posix_error();
10332 }
10333
10334 posix_putenv_garbage_setitem(name, bytes);
10335 Py_RETURN_NONE;
10336 }
10337 #endif /* MS_WINDOWS */
10338 #endif /* HAVE_PUTENV */
10339
10340
10341 #ifdef HAVE_UNSETENV
10342 /*[clinic input]
10343 os.unsetenv
10344 name: FSConverter
10345 /
10346
10347 Delete an environment variable.
10348 [clinic start generated code]*/
10349
10350 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)10351 os_unsetenv_impl(PyObject *module, PyObject *name)
10352 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
10353 {
10354 #ifndef HAVE_BROKEN_UNSETENV
10355 int err;
10356 #endif
10357
10358 if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
10359 return NULL;
10360 }
10361
10362 #ifdef HAVE_BROKEN_UNSETENV
10363 unsetenv(PyBytes_AS_STRING(name));
10364 #else
10365 err = unsetenv(PyBytes_AS_STRING(name));
10366 if (err)
10367 return posix_error();
10368 #endif
10369
10370 /* Remove the key from posix_putenv_garbage;
10371 * this will cause it to be collected. This has to
10372 * happen after the real unsetenv() call because the
10373 * old value was still accessible until then.
10374 */
10375 if (PyDict_DelItem(posix_putenv_garbage, name)) {
10376 /* really not much we can do; just leak */
10377 if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
10378 return NULL;
10379 }
10380 PyErr_Clear();
10381 }
10382 Py_RETURN_NONE;
10383 }
10384 #endif /* HAVE_UNSETENV */
10385
10386
10387 /*[clinic input]
10388 os.strerror
10389
10390 code: int
10391 /
10392
10393 Translate an error code to a message string.
10394 [clinic start generated code]*/
10395
10396 static PyObject *
os_strerror_impl(PyObject * module,int code)10397 os_strerror_impl(PyObject *module, int code)
10398 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
10399 {
10400 char *message = strerror(code);
10401 if (message == NULL) {
10402 PyErr_SetString(PyExc_ValueError,
10403 "strerror() argument out of range");
10404 return NULL;
10405 }
10406 return PyUnicode_DecodeLocale(message, "surrogateescape");
10407 }
10408
10409
10410 #ifdef HAVE_SYS_WAIT_H
10411 #ifdef WCOREDUMP
10412 /*[clinic input]
10413 os.WCOREDUMP -> bool
10414
10415 status: int
10416 /
10417
10418 Return True if the process returning status was dumped to a core file.
10419 [clinic start generated code]*/
10420
10421 static int
os_WCOREDUMP_impl(PyObject * module,int status)10422 os_WCOREDUMP_impl(PyObject *module, int status)
10423 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
10424 {
10425 WAIT_TYPE wait_status;
10426 WAIT_STATUS_INT(wait_status) = status;
10427 return WCOREDUMP(wait_status);
10428 }
10429 #endif /* WCOREDUMP */
10430
10431
10432 #ifdef WIFCONTINUED
10433 /*[clinic input]
10434 os.WIFCONTINUED -> bool
10435
10436 status: int
10437
10438 Return True if a particular process was continued from a job control stop.
10439
10440 Return True if the process returning status was continued from a
10441 job control stop.
10442 [clinic start generated code]*/
10443
10444 static int
os_WIFCONTINUED_impl(PyObject * module,int status)10445 os_WIFCONTINUED_impl(PyObject *module, int status)
10446 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
10447 {
10448 WAIT_TYPE wait_status;
10449 WAIT_STATUS_INT(wait_status) = status;
10450 return WIFCONTINUED(wait_status);
10451 }
10452 #endif /* WIFCONTINUED */
10453
10454
10455 #ifdef WIFSTOPPED
10456 /*[clinic input]
10457 os.WIFSTOPPED -> bool
10458
10459 status: int
10460
10461 Return True if the process returning status was stopped.
10462 [clinic start generated code]*/
10463
10464 static int
os_WIFSTOPPED_impl(PyObject * module,int status)10465 os_WIFSTOPPED_impl(PyObject *module, int status)
10466 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
10467 {
10468 WAIT_TYPE wait_status;
10469 WAIT_STATUS_INT(wait_status) = status;
10470 return WIFSTOPPED(wait_status);
10471 }
10472 #endif /* WIFSTOPPED */
10473
10474
10475 #ifdef WIFSIGNALED
10476 /*[clinic input]
10477 os.WIFSIGNALED -> bool
10478
10479 status: int
10480
10481 Return True if the process returning status was terminated by a signal.
10482 [clinic start generated code]*/
10483
10484 static int
os_WIFSIGNALED_impl(PyObject * module,int status)10485 os_WIFSIGNALED_impl(PyObject *module, int status)
10486 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
10487 {
10488 WAIT_TYPE wait_status;
10489 WAIT_STATUS_INT(wait_status) = status;
10490 return WIFSIGNALED(wait_status);
10491 }
10492 #endif /* WIFSIGNALED */
10493
10494
10495 #ifdef WIFEXITED
10496 /*[clinic input]
10497 os.WIFEXITED -> bool
10498
10499 status: int
10500
10501 Return True if the process returning status exited via the exit() system call.
10502 [clinic start generated code]*/
10503
10504 static int
os_WIFEXITED_impl(PyObject * module,int status)10505 os_WIFEXITED_impl(PyObject *module, int status)
10506 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
10507 {
10508 WAIT_TYPE wait_status;
10509 WAIT_STATUS_INT(wait_status) = status;
10510 return WIFEXITED(wait_status);
10511 }
10512 #endif /* WIFEXITED */
10513
10514
10515 #ifdef WEXITSTATUS
10516 /*[clinic input]
10517 os.WEXITSTATUS -> int
10518
10519 status: int
10520
10521 Return the process return code from status.
10522 [clinic start generated code]*/
10523
10524 static int
os_WEXITSTATUS_impl(PyObject * module,int status)10525 os_WEXITSTATUS_impl(PyObject *module, int status)
10526 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
10527 {
10528 WAIT_TYPE wait_status;
10529 WAIT_STATUS_INT(wait_status) = status;
10530 return WEXITSTATUS(wait_status);
10531 }
10532 #endif /* WEXITSTATUS */
10533
10534
10535 #ifdef WTERMSIG
10536 /*[clinic input]
10537 os.WTERMSIG -> int
10538
10539 status: int
10540
10541 Return the signal that terminated the process that provided the status value.
10542 [clinic start generated code]*/
10543
10544 static int
os_WTERMSIG_impl(PyObject * module,int status)10545 os_WTERMSIG_impl(PyObject *module, int status)
10546 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
10547 {
10548 WAIT_TYPE wait_status;
10549 WAIT_STATUS_INT(wait_status) = status;
10550 return WTERMSIG(wait_status);
10551 }
10552 #endif /* WTERMSIG */
10553
10554
10555 #ifdef WSTOPSIG
10556 /*[clinic input]
10557 os.WSTOPSIG -> int
10558
10559 status: int
10560
10561 Return the signal that stopped the process that provided the status value.
10562 [clinic start generated code]*/
10563
10564 static int
os_WSTOPSIG_impl(PyObject * module,int status)10565 os_WSTOPSIG_impl(PyObject *module, int status)
10566 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
10567 {
10568 WAIT_TYPE wait_status;
10569 WAIT_STATUS_INT(wait_status) = status;
10570 return WSTOPSIG(wait_status);
10571 }
10572 #endif /* WSTOPSIG */
10573 #endif /* HAVE_SYS_WAIT_H */
10574
10575
10576 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
10577 #ifdef _SCO_DS
10578 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
10579 needed definitions in sys/statvfs.h */
10580 #define _SVID3
10581 #endif
10582 #include <sys/statvfs.h>
10583
10584 static PyObject*
_pystatvfs_fromstructstatvfs(struct statvfs st)10585 _pystatvfs_fromstructstatvfs(struct statvfs st) {
10586 PyObject *v = PyStructSequence_New(StatVFSResultType);
10587 if (v == NULL)
10588 return NULL;
10589
10590 #if !defined(HAVE_LARGEFILE_SUPPORT)
10591 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
10592 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
10593 PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
10594 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
10595 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
10596 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
10597 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
10598 PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
10599 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
10600 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
10601 #else
10602 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
10603 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
10604 PyStructSequence_SET_ITEM(v, 2,
10605 PyLong_FromLongLong((long long) st.f_blocks));
10606 PyStructSequence_SET_ITEM(v, 3,
10607 PyLong_FromLongLong((long long) st.f_bfree));
10608 PyStructSequence_SET_ITEM(v, 4,
10609 PyLong_FromLongLong((long long) st.f_bavail));
10610 PyStructSequence_SET_ITEM(v, 5,
10611 PyLong_FromLongLong((long long) st.f_files));
10612 PyStructSequence_SET_ITEM(v, 6,
10613 PyLong_FromLongLong((long long) st.f_ffree));
10614 PyStructSequence_SET_ITEM(v, 7,
10615 PyLong_FromLongLong((long long) st.f_favail));
10616 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
10617 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
10618 #endif
10619 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
10620 * (issue #32390). */
10621 #if defined(_AIX) && defined(_ALL_SOURCE)
10622 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
10623 #else
10624 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
10625 #endif
10626 if (PyErr_Occurred()) {
10627 Py_DECREF(v);
10628 return NULL;
10629 }
10630
10631 return v;
10632 }
10633
10634
10635 /*[clinic input]
10636 os.fstatvfs
10637 fd: int
10638 /
10639
10640 Perform an fstatvfs system call on the given fd.
10641
10642 Equivalent to statvfs(fd).
10643 [clinic start generated code]*/
10644
10645 static PyObject *
os_fstatvfs_impl(PyObject * module,int fd)10646 os_fstatvfs_impl(PyObject *module, int fd)
10647 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
10648 {
10649 int result;
10650 int async_err = 0;
10651 struct statvfs st;
10652
10653 do {
10654 Py_BEGIN_ALLOW_THREADS
10655 result = fstatvfs(fd, &st);
10656 Py_END_ALLOW_THREADS
10657 } while (result != 0 && errno == EINTR &&
10658 !(async_err = PyErr_CheckSignals()));
10659 if (result != 0)
10660 return (!async_err) ? posix_error() : NULL;
10661
10662 return _pystatvfs_fromstructstatvfs(st);
10663 }
10664 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
10665
10666
10667 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
10668 #include <sys/statvfs.h>
10669 /*[clinic input]
10670 os.statvfs
10671
10672 path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
10673
10674 Perform a statvfs system call on the given path.
10675
10676 path may always be specified as a string.
10677 On some platforms, path may also be specified as an open file descriptor.
10678 If this functionality is unavailable, using it raises an exception.
10679 [clinic start generated code]*/
10680
10681 static PyObject *
os_statvfs_impl(PyObject * module,path_t * path)10682 os_statvfs_impl(PyObject *module, path_t *path)
10683 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
10684 {
10685 int result;
10686 struct statvfs st;
10687
10688 Py_BEGIN_ALLOW_THREADS
10689 #ifdef HAVE_FSTATVFS
10690 if (path->fd != -1) {
10691 #ifdef __APPLE__
10692 /* handle weak-linking on Mac OS X 10.3 */
10693 if (fstatvfs == NULL) {
10694 fd_specified("statvfs", path->fd);
10695 return NULL;
10696 }
10697 #endif
10698 result = fstatvfs(path->fd, &st);
10699 }
10700 else
10701 #endif
10702 result = statvfs(path->narrow, &st);
10703 Py_END_ALLOW_THREADS
10704
10705 if (result) {
10706 return path_error(path);
10707 }
10708
10709 return _pystatvfs_fromstructstatvfs(st);
10710 }
10711 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
10712
10713
10714 #ifdef MS_WINDOWS
10715 /*[clinic input]
10716 os._getdiskusage
10717
10718 path: path_t
10719
10720 Return disk usage statistics about the given path as a (total, free) tuple.
10721 [clinic start generated code]*/
10722
10723 static PyObject *
os__getdiskusage_impl(PyObject * module,path_t * path)10724 os__getdiskusage_impl(PyObject *module, path_t *path)
10725 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
10726 {
10727 BOOL retval;
10728 ULARGE_INTEGER _, total, free;
10729 DWORD err = 0;
10730
10731 Py_BEGIN_ALLOW_THREADS
10732 retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
10733 Py_END_ALLOW_THREADS
10734 if (retval == 0) {
10735 if (GetLastError() == ERROR_DIRECTORY) {
10736 wchar_t *dir_path = NULL;
10737
10738 dir_path = PyMem_New(wchar_t, path->length + 1);
10739 if (dir_path == NULL) {
10740 return PyErr_NoMemory();
10741 }
10742
10743 wcscpy_s(dir_path, path->length + 1, path->wide);
10744
10745 if (_dirnameW(dir_path) != -1) {
10746 Py_BEGIN_ALLOW_THREADS
10747 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
10748 Py_END_ALLOW_THREADS
10749 }
10750 /* Record the last error in case it's modified by PyMem_Free. */
10751 err = GetLastError();
10752 PyMem_Free(dir_path);
10753 if (retval) {
10754 goto success;
10755 }
10756 }
10757 return PyErr_SetFromWindowsErr(err);
10758 }
10759
10760 success:
10761 return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
10762 }
10763 #endif /* MS_WINDOWS */
10764
10765
10766 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
10767 * It maps strings representing configuration variable names to
10768 * integer values, allowing those functions to be called with the
10769 * magic names instead of polluting the module's namespace with tons of
10770 * rarely-used constants. There are three separate tables that use
10771 * these definitions.
10772 *
10773 * This code is always included, even if none of the interfaces that
10774 * need it are included. The #if hackery needed to avoid it would be
10775 * sufficiently pervasive that it's not worth the loss of readability.
10776 */
10777 struct constdef {
10778 const char *name;
10779 int value;
10780 };
10781
10782 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)10783 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
10784 size_t tablesize)
10785 {
10786 if (PyLong_Check(arg)) {
10787 int value = _PyLong_AsInt(arg);
10788 if (value == -1 && PyErr_Occurred())
10789 return 0;
10790 *valuep = value;
10791 return 1;
10792 }
10793 else {
10794 /* look up the value in the table using a binary search */
10795 size_t lo = 0;
10796 size_t mid;
10797 size_t hi = tablesize;
10798 int cmp;
10799 const char *confname;
10800 if (!PyUnicode_Check(arg)) {
10801 PyErr_SetString(PyExc_TypeError,
10802 "configuration names must be strings or integers");
10803 return 0;
10804 }
10805 confname = PyUnicode_AsUTF8(arg);
10806 if (confname == NULL)
10807 return 0;
10808 while (lo < hi) {
10809 mid = (lo + hi) / 2;
10810 cmp = strcmp(confname, table[mid].name);
10811 if (cmp < 0)
10812 hi = mid;
10813 else if (cmp > 0)
10814 lo = mid + 1;
10815 else {
10816 *valuep = table[mid].value;
10817 return 1;
10818 }
10819 }
10820 PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
10821 return 0;
10822 }
10823 }
10824
10825
10826 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
10827 static struct constdef posix_constants_pathconf[] = {
10828 #ifdef _PC_ABI_AIO_XFER_MAX
10829 {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
10830 #endif
10831 #ifdef _PC_ABI_ASYNC_IO
10832 {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
10833 #endif
10834 #ifdef _PC_ASYNC_IO
10835 {"PC_ASYNC_IO", _PC_ASYNC_IO},
10836 #endif
10837 #ifdef _PC_CHOWN_RESTRICTED
10838 {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
10839 #endif
10840 #ifdef _PC_FILESIZEBITS
10841 {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
10842 #endif
10843 #ifdef _PC_LAST
10844 {"PC_LAST", _PC_LAST},
10845 #endif
10846 #ifdef _PC_LINK_MAX
10847 {"PC_LINK_MAX", _PC_LINK_MAX},
10848 #endif
10849 #ifdef _PC_MAX_CANON
10850 {"PC_MAX_CANON", _PC_MAX_CANON},
10851 #endif
10852 #ifdef _PC_MAX_INPUT
10853 {"PC_MAX_INPUT", _PC_MAX_INPUT},
10854 #endif
10855 #ifdef _PC_NAME_MAX
10856 {"PC_NAME_MAX", _PC_NAME_MAX},
10857 #endif
10858 #ifdef _PC_NO_TRUNC
10859 {"PC_NO_TRUNC", _PC_NO_TRUNC},
10860 #endif
10861 #ifdef _PC_PATH_MAX
10862 {"PC_PATH_MAX", _PC_PATH_MAX},
10863 #endif
10864 #ifdef _PC_PIPE_BUF
10865 {"PC_PIPE_BUF", _PC_PIPE_BUF},
10866 #endif
10867 #ifdef _PC_PRIO_IO
10868 {"PC_PRIO_IO", _PC_PRIO_IO},
10869 #endif
10870 #ifdef _PC_SOCK_MAXBUF
10871 {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
10872 #endif
10873 #ifdef _PC_SYNC_IO
10874 {"PC_SYNC_IO", _PC_SYNC_IO},
10875 #endif
10876 #ifdef _PC_VDISABLE
10877 {"PC_VDISABLE", _PC_VDISABLE},
10878 #endif
10879 #ifdef _PC_ACL_ENABLED
10880 {"PC_ACL_ENABLED", _PC_ACL_ENABLED},
10881 #endif
10882 #ifdef _PC_MIN_HOLE_SIZE
10883 {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE},
10884 #endif
10885 #ifdef _PC_ALLOC_SIZE_MIN
10886 {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN},
10887 #endif
10888 #ifdef _PC_REC_INCR_XFER_SIZE
10889 {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE},
10890 #endif
10891 #ifdef _PC_REC_MAX_XFER_SIZE
10892 {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE},
10893 #endif
10894 #ifdef _PC_REC_MIN_XFER_SIZE
10895 {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE},
10896 #endif
10897 #ifdef _PC_REC_XFER_ALIGN
10898 {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN},
10899 #endif
10900 #ifdef _PC_SYMLINK_MAX
10901 {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX},
10902 #endif
10903 #ifdef _PC_XATTR_ENABLED
10904 {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED},
10905 #endif
10906 #ifdef _PC_XATTR_EXISTS
10907 {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
10908 #endif
10909 #ifdef _PC_TIMESTAMP_RESOLUTION
10910 {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
10911 #endif
10912 };
10913
10914 static int
conv_path_confname(PyObject * arg,int * valuep)10915 conv_path_confname(PyObject *arg, int *valuep)
10916 {
10917 return conv_confname(arg, valuep, posix_constants_pathconf,
10918 sizeof(posix_constants_pathconf)
10919 / sizeof(struct constdef));
10920 }
10921 #endif
10922
10923
10924 #ifdef HAVE_FPATHCONF
10925 /*[clinic input]
10926 os.fpathconf -> long
10927
10928 fd: int
10929 name: path_confname
10930 /
10931
10932 Return the configuration limit name for the file descriptor fd.
10933
10934 If there is no limit, return -1.
10935 [clinic start generated code]*/
10936
10937 static long
os_fpathconf_impl(PyObject * module,int fd,int name)10938 os_fpathconf_impl(PyObject *module, int fd, int name)
10939 /*[clinic end generated code: output=d5b7042425fc3e21 input=5942a024d3777810]*/
10940 {
10941 long limit;
10942
10943 errno = 0;
10944 limit = fpathconf(fd, name);
10945 if (limit == -1 && errno != 0)
10946 posix_error();
10947
10948 return limit;
10949 }
10950 #endif /* HAVE_FPATHCONF */
10951
10952
10953 #ifdef HAVE_PATHCONF
10954 /*[clinic input]
10955 os.pathconf -> long
10956 path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
10957 name: path_confname
10958
10959 Return the configuration limit name for the file or directory path.
10960
10961 If there is no limit, return -1.
10962 On some platforms, path may also be specified as an open file descriptor.
10963 If this functionality is unavailable, using it raises an exception.
10964 [clinic start generated code]*/
10965
10966 static long
os_pathconf_impl(PyObject * module,path_t * path,int name)10967 os_pathconf_impl(PyObject *module, path_t *path, int name)
10968 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
10969 {
10970 long limit;
10971
10972 errno = 0;
10973 #ifdef HAVE_FPATHCONF
10974 if (path->fd != -1)
10975 limit = fpathconf(path->fd, name);
10976 else
10977 #endif
10978 limit = pathconf(path->narrow, name);
10979 if (limit == -1 && errno != 0) {
10980 if (errno == EINVAL)
10981 /* could be a path or name problem */
10982 posix_error();
10983 else
10984 path_error(path);
10985 }
10986
10987 return limit;
10988 }
10989 #endif /* HAVE_PATHCONF */
10990
10991 #ifdef HAVE_CONFSTR
10992 static struct constdef posix_constants_confstr[] = {
10993 #ifdef _CS_ARCHITECTURE
10994 {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
10995 #endif
10996 #ifdef _CS_GNU_LIBC_VERSION
10997 {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION},
10998 #endif
10999 #ifdef _CS_GNU_LIBPTHREAD_VERSION
11000 {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION},
11001 #endif
11002 #ifdef _CS_HOSTNAME
11003 {"CS_HOSTNAME", _CS_HOSTNAME},
11004 #endif
11005 #ifdef _CS_HW_PROVIDER
11006 {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
11007 #endif
11008 #ifdef _CS_HW_SERIAL
11009 {"CS_HW_SERIAL", _CS_HW_SERIAL},
11010 #endif
11011 #ifdef _CS_INITTAB_NAME
11012 {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11013 #endif
11014 #ifdef _CS_LFS64_CFLAGS
11015 {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11016 #endif
11017 #ifdef _CS_LFS64_LDFLAGS
11018 {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
11019 #endif
11020 #ifdef _CS_LFS64_LIBS
11021 {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
11022 #endif
11023 #ifdef _CS_LFS64_LINTFLAGS
11024 {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
11025 #endif
11026 #ifdef _CS_LFS_CFLAGS
11027 {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
11028 #endif
11029 #ifdef _CS_LFS_LDFLAGS
11030 {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
11031 #endif
11032 #ifdef _CS_LFS_LIBS
11033 {"CS_LFS_LIBS", _CS_LFS_LIBS},
11034 #endif
11035 #ifdef _CS_LFS_LINTFLAGS
11036 {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
11037 #endif
11038 #ifdef _CS_MACHINE
11039 {"CS_MACHINE", _CS_MACHINE},
11040 #endif
11041 #ifdef _CS_PATH
11042 {"CS_PATH", _CS_PATH},
11043 #endif
11044 #ifdef _CS_RELEASE
11045 {"CS_RELEASE", _CS_RELEASE},
11046 #endif
11047 #ifdef _CS_SRPC_DOMAIN
11048 {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
11049 #endif
11050 #ifdef _CS_SYSNAME
11051 {"CS_SYSNAME", _CS_SYSNAME},
11052 #endif
11053 #ifdef _CS_VERSION
11054 {"CS_VERSION", _CS_VERSION},
11055 #endif
11056 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11057 {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
11058 #endif
11059 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11060 {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
11061 #endif
11062 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11063 {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
11064 #endif
11065 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11066 {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11067 #endif
11068 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11069 {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11070 #endif
11071 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11072 {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11073 #endif
11074 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11075 {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
11076 #endif
11077 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11078 {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11079 #endif
11080 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11081 {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
11082 #endif
11083 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11084 {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
11085 #endif
11086 #ifdef _CS_XBS5_LP64_OFF64_LIBS
11087 {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11088 #endif
11089 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11090 {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
11091 #endif
11092 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11093 {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11094 #endif
11095 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11096 {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11097 #endif
11098 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11099 {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
11100 #endif
11101 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11102 {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11103 #endif
11104 #ifdef _MIPS_CS_AVAIL_PROCESSORS
11105 {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
11106 #endif
11107 #ifdef _MIPS_CS_BASE
11108 {"MIPS_CS_BASE", _MIPS_CS_BASE},
11109 #endif
11110 #ifdef _MIPS_CS_HOSTID
11111 {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
11112 #endif
11113 #ifdef _MIPS_CS_HW_NAME
11114 {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11115 #endif
11116 #ifdef _MIPS_CS_NUM_PROCESSORS
11117 {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
11118 #endif
11119 #ifdef _MIPS_CS_OSREL_MAJ
11120 {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
11121 #endif
11122 #ifdef _MIPS_CS_OSREL_MIN
11123 {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
11124 #endif
11125 #ifdef _MIPS_CS_OSREL_PATCH
11126 {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
11127 #endif
11128 #ifdef _MIPS_CS_OS_NAME
11129 {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11130 #endif
11131 #ifdef _MIPS_CS_OS_PROVIDER
11132 {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
11133 #endif
11134 #ifdef _MIPS_CS_PROCESSORS
11135 {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
11136 #endif
11137 #ifdef _MIPS_CS_SERIAL
11138 {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
11139 #endif
11140 #ifdef _MIPS_CS_VENDOR
11141 {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
11142 #endif
11143 };
11144
11145 static int
conv_confstr_confname(PyObject * arg,int * valuep)11146 conv_confstr_confname(PyObject *arg, int *valuep)
11147 {
11148 return conv_confname(arg, valuep, posix_constants_confstr,
11149 sizeof(posix_constants_confstr)
11150 / sizeof(struct constdef));
11151 }
11152
11153
11154 /*[clinic input]
11155 os.confstr
11156
11157 name: confstr_confname
11158 /
11159
11160 Return a string-valued system configuration variable.
11161 [clinic start generated code]*/
11162
11163 static PyObject *
os_confstr_impl(PyObject * module,int name)11164 os_confstr_impl(PyObject *module, int name)
11165 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11166 {
11167 PyObject *result = NULL;
11168 char buffer[255];
11169 size_t len;
11170
11171 errno = 0;
11172 len = confstr(name, buffer, sizeof(buffer));
11173 if (len == 0) {
11174 if (errno) {
11175 posix_error();
11176 return NULL;
11177 }
11178 else {
11179 Py_RETURN_NONE;
11180 }
11181 }
11182
11183 if (len >= sizeof(buffer)) {
11184 size_t len2;
11185 char *buf = PyMem_Malloc(len);
11186 if (buf == NULL)
11187 return PyErr_NoMemory();
11188 len2 = confstr(name, buf, len);
11189 assert(len == len2);
11190 result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11191 PyMem_Free(buf);
11192 }
11193 else
11194 result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11195 return result;
11196 }
11197 #endif /* HAVE_CONFSTR */
11198
11199
11200 #ifdef HAVE_SYSCONF
11201 static struct constdef posix_constants_sysconf[] = {
11202 #ifdef _SC_2_CHAR_TERM
11203 {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
11204 #endif
11205 #ifdef _SC_2_C_BIND
11206 {"SC_2_C_BIND", _SC_2_C_BIND},
11207 #endif
11208 #ifdef _SC_2_C_DEV
11209 {"SC_2_C_DEV", _SC_2_C_DEV},
11210 #endif
11211 #ifdef _SC_2_C_VERSION
11212 {"SC_2_C_VERSION", _SC_2_C_VERSION},
11213 #endif
11214 #ifdef _SC_2_FORT_DEV
11215 {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
11216 #endif
11217 #ifdef _SC_2_FORT_RUN
11218 {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
11219 #endif
11220 #ifdef _SC_2_LOCALEDEF
11221 {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
11222 #endif
11223 #ifdef _SC_2_SW_DEV
11224 {"SC_2_SW_DEV", _SC_2_SW_DEV},
11225 #endif
11226 #ifdef _SC_2_UPE
11227 {"SC_2_UPE", _SC_2_UPE},
11228 #endif
11229 #ifdef _SC_2_VERSION
11230 {"SC_2_VERSION", _SC_2_VERSION},
11231 #endif
11232 #ifdef _SC_ABI_ASYNCHRONOUS_IO
11233 {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
11234 #endif
11235 #ifdef _SC_ACL
11236 {"SC_ACL", _SC_ACL},
11237 #endif
11238 #ifdef _SC_AIO_LISTIO_MAX
11239 {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
11240 #endif
11241 #ifdef _SC_AIO_MAX
11242 {"SC_AIO_MAX", _SC_AIO_MAX},
11243 #endif
11244 #ifdef _SC_AIO_PRIO_DELTA_MAX
11245 {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
11246 #endif
11247 #ifdef _SC_ARG_MAX
11248 {"SC_ARG_MAX", _SC_ARG_MAX},
11249 #endif
11250 #ifdef _SC_ASYNCHRONOUS_IO
11251 {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
11252 #endif
11253 #ifdef _SC_ATEXIT_MAX
11254 {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
11255 #endif
11256 #ifdef _SC_AUDIT
11257 {"SC_AUDIT", _SC_AUDIT},
11258 #endif
11259 #ifdef _SC_AVPHYS_PAGES
11260 {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
11261 #endif
11262 #ifdef _SC_BC_BASE_MAX
11263 {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
11264 #endif
11265 #ifdef _SC_BC_DIM_MAX
11266 {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
11267 #endif
11268 #ifdef _SC_BC_SCALE_MAX
11269 {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
11270 #endif
11271 #ifdef _SC_BC_STRING_MAX
11272 {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
11273 #endif
11274 #ifdef _SC_CAP
11275 {"SC_CAP", _SC_CAP},
11276 #endif
11277 #ifdef _SC_CHARCLASS_NAME_MAX
11278 {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
11279 #endif
11280 #ifdef _SC_CHAR_BIT
11281 {"SC_CHAR_BIT", _SC_CHAR_BIT},
11282 #endif
11283 #ifdef _SC_CHAR_MAX
11284 {"SC_CHAR_MAX", _SC_CHAR_MAX},
11285 #endif
11286 #ifdef _SC_CHAR_MIN
11287 {"SC_CHAR_MIN", _SC_CHAR_MIN},
11288 #endif
11289 #ifdef _SC_CHILD_MAX
11290 {"SC_CHILD_MAX", _SC_CHILD_MAX},
11291 #endif
11292 #ifdef _SC_CLK_TCK
11293 {"SC_CLK_TCK", _SC_CLK_TCK},
11294 #endif
11295 #ifdef _SC_COHER_BLKSZ
11296 {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
11297 #endif
11298 #ifdef _SC_COLL_WEIGHTS_MAX
11299 {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
11300 #endif
11301 #ifdef _SC_DCACHE_ASSOC
11302 {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
11303 #endif
11304 #ifdef _SC_DCACHE_BLKSZ
11305 {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
11306 #endif
11307 #ifdef _SC_DCACHE_LINESZ
11308 {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
11309 #endif
11310 #ifdef _SC_DCACHE_SZ
11311 {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
11312 #endif
11313 #ifdef _SC_DCACHE_TBLKSZ
11314 {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
11315 #endif
11316 #ifdef _SC_DELAYTIMER_MAX
11317 {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
11318 #endif
11319 #ifdef _SC_EQUIV_CLASS_MAX
11320 {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
11321 #endif
11322 #ifdef _SC_EXPR_NEST_MAX
11323 {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
11324 #endif
11325 #ifdef _SC_FSYNC
11326 {"SC_FSYNC", _SC_FSYNC},
11327 #endif
11328 #ifdef _SC_GETGR_R_SIZE_MAX
11329 {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
11330 #endif
11331 #ifdef _SC_GETPW_R_SIZE_MAX
11332 {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
11333 #endif
11334 #ifdef _SC_ICACHE_ASSOC
11335 {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
11336 #endif
11337 #ifdef _SC_ICACHE_BLKSZ
11338 {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
11339 #endif
11340 #ifdef _SC_ICACHE_LINESZ
11341 {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
11342 #endif
11343 #ifdef _SC_ICACHE_SZ
11344 {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
11345 #endif
11346 #ifdef _SC_INF
11347 {"SC_INF", _SC_INF},
11348 #endif
11349 #ifdef _SC_INT_MAX
11350 {"SC_INT_MAX", _SC_INT_MAX},
11351 #endif
11352 #ifdef _SC_INT_MIN
11353 {"SC_INT_MIN", _SC_INT_MIN},
11354 #endif
11355 #ifdef _SC_IOV_MAX
11356 {"SC_IOV_MAX", _SC_IOV_MAX},
11357 #endif
11358 #ifdef _SC_IP_SECOPTS
11359 {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
11360 #endif
11361 #ifdef _SC_JOB_CONTROL
11362 {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
11363 #endif
11364 #ifdef _SC_KERN_POINTERS
11365 {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
11366 #endif
11367 #ifdef _SC_KERN_SIM
11368 {"SC_KERN_SIM", _SC_KERN_SIM},
11369 #endif
11370 #ifdef _SC_LINE_MAX
11371 {"SC_LINE_MAX", _SC_LINE_MAX},
11372 #endif
11373 #ifdef _SC_LOGIN_NAME_MAX
11374 {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
11375 #endif
11376 #ifdef _SC_LOGNAME_MAX
11377 {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
11378 #endif
11379 #ifdef _SC_LONG_BIT
11380 {"SC_LONG_BIT", _SC_LONG_BIT},
11381 #endif
11382 #ifdef _SC_MAC
11383 {"SC_MAC", _SC_MAC},
11384 #endif
11385 #ifdef _SC_MAPPED_FILES
11386 {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
11387 #endif
11388 #ifdef _SC_MAXPID
11389 {"SC_MAXPID", _SC_MAXPID},
11390 #endif
11391 #ifdef _SC_MB_LEN_MAX
11392 {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
11393 #endif
11394 #ifdef _SC_MEMLOCK
11395 {"SC_MEMLOCK", _SC_MEMLOCK},
11396 #endif
11397 #ifdef _SC_MEMLOCK_RANGE
11398 {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
11399 #endif
11400 #ifdef _SC_MEMORY_PROTECTION
11401 {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
11402 #endif
11403 #ifdef _SC_MESSAGE_PASSING
11404 {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
11405 #endif
11406 #ifdef _SC_MMAP_FIXED_ALIGNMENT
11407 {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
11408 #endif
11409 #ifdef _SC_MQ_OPEN_MAX
11410 {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
11411 #endif
11412 #ifdef _SC_MQ_PRIO_MAX
11413 {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},
11414 #endif
11415 #ifdef _SC_NACLS_MAX
11416 {"SC_NACLS_MAX", _SC_NACLS_MAX},
11417 #endif
11418 #ifdef _SC_NGROUPS_MAX
11419 {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX},
11420 #endif
11421 #ifdef _SC_NL_ARGMAX
11422 {"SC_NL_ARGMAX", _SC_NL_ARGMAX},
11423 #endif
11424 #ifdef _SC_NL_LANGMAX
11425 {"SC_NL_LANGMAX", _SC_NL_LANGMAX},
11426 #endif
11427 #ifdef _SC_NL_MSGMAX
11428 {"SC_NL_MSGMAX", _SC_NL_MSGMAX},
11429 #endif
11430 #ifdef _SC_NL_NMAX
11431 {"SC_NL_NMAX", _SC_NL_NMAX},
11432 #endif
11433 #ifdef _SC_NL_SETMAX
11434 {"SC_NL_SETMAX", _SC_NL_SETMAX},
11435 #endif
11436 #ifdef _SC_NL_TEXTMAX
11437 {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX},
11438 #endif
11439 #ifdef _SC_NPROCESSORS_CONF
11440 {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
11441 #endif
11442 #ifdef _SC_NPROCESSORS_ONLN
11443 {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
11444 #endif
11445 #ifdef _SC_NPROC_CONF
11446 {"SC_NPROC_CONF", _SC_NPROC_CONF},
11447 #endif
11448 #ifdef _SC_NPROC_ONLN
11449 {"SC_NPROC_ONLN", _SC_NPROC_ONLN},
11450 #endif
11451 #ifdef _SC_NZERO
11452 {"SC_NZERO", _SC_NZERO},
11453 #endif
11454 #ifdef _SC_OPEN_MAX
11455 {"SC_OPEN_MAX", _SC_OPEN_MAX},
11456 #endif
11457 #ifdef _SC_PAGESIZE
11458 {"SC_PAGESIZE", _SC_PAGESIZE},
11459 #endif
11460 #ifdef _SC_PAGE_SIZE
11461 {"SC_PAGE_SIZE", _SC_PAGE_SIZE},
11462 #endif
11463 #ifdef _SC_PASS_MAX
11464 {"SC_PASS_MAX", _SC_PASS_MAX},
11465 #endif
11466 #ifdef _SC_PHYS_PAGES
11467 {"SC_PHYS_PAGES", _SC_PHYS_PAGES},
11468 #endif
11469 #ifdef _SC_PII
11470 {"SC_PII", _SC_PII},
11471 #endif
11472 #ifdef _SC_PII_INTERNET
11473 {"SC_PII_INTERNET", _SC_PII_INTERNET},
11474 #endif
11475 #ifdef _SC_PII_INTERNET_DGRAM
11476 {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM},
11477 #endif
11478 #ifdef _SC_PII_INTERNET_STREAM
11479 {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM},
11480 #endif
11481 #ifdef _SC_PII_OSI
11482 {"SC_PII_OSI", _SC_PII_OSI},
11483 #endif
11484 #ifdef _SC_PII_OSI_CLTS
11485 {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
11486 #endif
11487 #ifdef _SC_PII_OSI_COTS
11488 {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
11489 #endif
11490 #ifdef _SC_PII_OSI_M
11491 {"SC_PII_OSI_M", _SC_PII_OSI_M},
11492 #endif
11493 #ifdef _SC_PII_SOCKET
11494 {"SC_PII_SOCKET", _SC_PII_SOCKET},
11495 #endif
11496 #ifdef _SC_PII_XTI
11497 {"SC_PII_XTI", _SC_PII_XTI},
11498 #endif
11499 #ifdef _SC_POLL
11500 {"SC_POLL", _SC_POLL},
11501 #endif
11502 #ifdef _SC_PRIORITIZED_IO
11503 {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO},
11504 #endif
11505 #ifdef _SC_PRIORITY_SCHEDULING
11506 {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING},
11507 #endif
11508 #ifdef _SC_REALTIME_SIGNALS
11509 {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS},
11510 #endif
11511 #ifdef _SC_RE_DUP_MAX
11512 {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX},
11513 #endif
11514 #ifdef _SC_RTSIG_MAX
11515 {"SC_RTSIG_MAX", _SC_RTSIG_MAX},
11516 #endif
11517 #ifdef _SC_SAVED_IDS
11518 {"SC_SAVED_IDS", _SC_SAVED_IDS},
11519 #endif
11520 #ifdef _SC_SCHAR_MAX
11521 {"SC_SCHAR_MAX", _SC_SCHAR_MAX},
11522 #endif
11523 #ifdef _SC_SCHAR_MIN
11524 {"SC_SCHAR_MIN", _SC_SCHAR_MIN},
11525 #endif
11526 #ifdef _SC_SELECT
11527 {"SC_SELECT", _SC_SELECT},
11528 #endif
11529 #ifdef _SC_SEMAPHORES
11530 {"SC_SEMAPHORES", _SC_SEMAPHORES},
11531 #endif
11532 #ifdef _SC_SEM_NSEMS_MAX
11533 {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX},
11534 #endif
11535 #ifdef _SC_SEM_VALUE_MAX
11536 {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX},
11537 #endif
11538 #ifdef _SC_SHARED_MEMORY_OBJECTS
11539 {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS},
11540 #endif
11541 #ifdef _SC_SHRT_MAX
11542 {"SC_SHRT_MAX", _SC_SHRT_MAX},
11543 #endif
11544 #ifdef _SC_SHRT_MIN
11545 {"SC_SHRT_MIN", _SC_SHRT_MIN},
11546 #endif
11547 #ifdef _SC_SIGQUEUE_MAX
11548 {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
11549 #endif
11550 #ifdef _SC_SIGRT_MAX
11551 {"SC_SIGRT_MAX", _SC_SIGRT_MAX},
11552 #endif
11553 #ifdef _SC_SIGRT_MIN
11554 {"SC_SIGRT_MIN", _SC_SIGRT_MIN},
11555 #endif
11556 #ifdef _SC_SOFTPOWER
11557 {"SC_SOFTPOWER", _SC_SOFTPOWER},
11558 #endif
11559 #ifdef _SC_SPLIT_CACHE
11560 {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE},
11561 #endif
11562 #ifdef _SC_SSIZE_MAX
11563 {"SC_SSIZE_MAX", _SC_SSIZE_MAX},
11564 #endif
11565 #ifdef _SC_STACK_PROT
11566 {"SC_STACK_PROT", _SC_STACK_PROT},
11567 #endif
11568 #ifdef _SC_STREAM_MAX
11569 {"SC_STREAM_MAX", _SC_STREAM_MAX},
11570 #endif
11571 #ifdef _SC_SYNCHRONIZED_IO
11572 {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO},
11573 #endif
11574 #ifdef _SC_THREADS
11575 {"SC_THREADS", _SC_THREADS},
11576 #endif
11577 #ifdef _SC_THREAD_ATTR_STACKADDR
11578 {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR},
11579 #endif
11580 #ifdef _SC_THREAD_ATTR_STACKSIZE
11581 {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE},
11582 #endif
11583 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
11584 {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
11585 #endif
11586 #ifdef _SC_THREAD_KEYS_MAX
11587 {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
11588 #endif
11589 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
11590 {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING},
11591 #endif
11592 #ifdef _SC_THREAD_PRIO_INHERIT
11593 {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT},
11594 #endif
11595 #ifdef _SC_THREAD_PRIO_PROTECT
11596 {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT},
11597 #endif
11598 #ifdef _SC_THREAD_PROCESS_SHARED
11599 {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED},
11600 #endif
11601 #ifdef _SC_THREAD_SAFE_FUNCTIONS
11602 {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS},
11603 #endif
11604 #ifdef _SC_THREAD_STACK_MIN
11605 {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
11606 #endif
11607 #ifdef _SC_THREAD_THREADS_MAX
11608 {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
11609 #endif
11610 #ifdef _SC_TIMERS
11611 {"SC_TIMERS", _SC_TIMERS},
11612 #endif
11613 #ifdef _SC_TIMER_MAX
11614 {"SC_TIMER_MAX", _SC_TIMER_MAX},
11615 #endif
11616 #ifdef _SC_TTY_NAME_MAX
11617 {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
11618 #endif
11619 #ifdef _SC_TZNAME_MAX
11620 {"SC_TZNAME_MAX", _SC_TZNAME_MAX},
11621 #endif
11622 #ifdef _SC_T_IOV_MAX
11623 {"SC_T_IOV_MAX", _SC_T_IOV_MAX},
11624 #endif
11625 #ifdef _SC_UCHAR_MAX
11626 {"SC_UCHAR_MAX", _SC_UCHAR_MAX},
11627 #endif
11628 #ifdef _SC_UINT_MAX
11629 {"SC_UINT_MAX", _SC_UINT_MAX},
11630 #endif
11631 #ifdef _SC_UIO_MAXIOV
11632 {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV},
11633 #endif
11634 #ifdef _SC_ULONG_MAX
11635 {"SC_ULONG_MAX", _SC_ULONG_MAX},
11636 #endif
11637 #ifdef _SC_USHRT_MAX
11638 {"SC_USHRT_MAX", _SC_USHRT_MAX},
11639 #endif
11640 #ifdef _SC_VERSION
11641 {"SC_VERSION", _SC_VERSION},
11642 #endif
11643 #ifdef _SC_WORD_BIT
11644 {"SC_WORD_BIT", _SC_WORD_BIT},
11645 #endif
11646 #ifdef _SC_XBS5_ILP32_OFF32
11647 {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32},
11648 #endif
11649 #ifdef _SC_XBS5_ILP32_OFFBIG
11650 {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG},
11651 #endif
11652 #ifdef _SC_XBS5_LP64_OFF64
11653 {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64},
11654 #endif
11655 #ifdef _SC_XBS5_LPBIG_OFFBIG
11656 {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG},
11657 #endif
11658 #ifdef _SC_XOPEN_CRYPT
11659 {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT},
11660 #endif
11661 #ifdef _SC_XOPEN_ENH_I18N
11662 {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N},
11663 #endif
11664 #ifdef _SC_XOPEN_LEGACY
11665 {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
11666 #endif
11667 #ifdef _SC_XOPEN_REALTIME
11668 {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME},
11669 #endif
11670 #ifdef _SC_XOPEN_REALTIME_THREADS
11671 {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS},
11672 #endif
11673 #ifdef _SC_XOPEN_SHM
11674 {"SC_XOPEN_SHM", _SC_XOPEN_SHM},
11675 #endif
11676 #ifdef _SC_XOPEN_UNIX
11677 {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX},
11678 #endif
11679 #ifdef _SC_XOPEN_VERSION
11680 {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION},
11681 #endif
11682 #ifdef _SC_XOPEN_XCU_VERSION
11683 {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION},
11684 #endif
11685 #ifdef _SC_XOPEN_XPG2
11686 {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2},
11687 #endif
11688 #ifdef _SC_XOPEN_XPG3
11689 {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3},
11690 #endif
11691 #ifdef _SC_XOPEN_XPG4
11692 {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4},
11693 #endif
11694 };
11695
11696 static int
conv_sysconf_confname(PyObject * arg,int * valuep)11697 conv_sysconf_confname(PyObject *arg, int *valuep)
11698 {
11699 return conv_confname(arg, valuep, posix_constants_sysconf,
11700 sizeof(posix_constants_sysconf)
11701 / sizeof(struct constdef));
11702 }
11703
11704
11705 /*[clinic input]
11706 os.sysconf -> long
11707 name: sysconf_confname
11708 /
11709
11710 Return an integer-valued system configuration variable.
11711 [clinic start generated code]*/
11712
11713 static long
os_sysconf_impl(PyObject * module,int name)11714 os_sysconf_impl(PyObject *module, int name)
11715 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
11716 {
11717 long value;
11718
11719 errno = 0;
11720 value = sysconf(name);
11721 if (value == -1 && errno != 0)
11722 posix_error();
11723 return value;
11724 }
11725 #endif /* HAVE_SYSCONF */
11726
11727
11728 /* This code is used to ensure that the tables of configuration value names
11729 * are in sorted order as required by conv_confname(), and also to build
11730 * the exported dictionaries that are used to publish information about the
11731 * names available on the host platform.
11732 *
11733 * Sorting the table at runtime ensures that the table is properly ordered
11734 * when used, even for platforms we're not able to test on. It also makes
11735 * it easier to add additional entries to the tables.
11736 */
11737
11738 static int
cmp_constdefs(const void * v1,const void * v2)11739 cmp_constdefs(const void *v1, const void *v2)
11740 {
11741 const struct constdef *c1 =
11742 (const struct constdef *) v1;
11743 const struct constdef *c2 =
11744 (const struct constdef *) v2;
11745
11746 return strcmp(c1->name, c2->name);
11747 }
11748
11749 static int
setup_confname_table(struct constdef * table,size_t tablesize,const char * tablename,PyObject * module)11750 setup_confname_table(struct constdef *table, size_t tablesize,
11751 const char *tablename, PyObject *module)
11752 {
11753 PyObject *d = NULL;
11754 size_t i;
11755
11756 qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
11757 d = PyDict_New();
11758 if (d == NULL)
11759 return -1;
11760
11761 for (i=0; i < tablesize; ++i) {
11762 PyObject *o = PyLong_FromLong(table[i].value);
11763 if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
11764 Py_XDECREF(o);
11765 Py_DECREF(d);
11766 return -1;
11767 }
11768 Py_DECREF(o);
11769 }
11770 return PyModule_AddObject(module, tablename, d);
11771 }
11772
11773 /* Return -1 on failure, 0 on success. */
11774 static int
setup_confname_tables(PyObject * module)11775 setup_confname_tables(PyObject *module)
11776 {
11777 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11778 if (setup_confname_table(posix_constants_pathconf,
11779 sizeof(posix_constants_pathconf)
11780 / sizeof(struct constdef),
11781 "pathconf_names", module))
11782 return -1;
11783 #endif
11784 #ifdef HAVE_CONFSTR
11785 if (setup_confname_table(posix_constants_confstr,
11786 sizeof(posix_constants_confstr)
11787 / sizeof(struct constdef),
11788 "confstr_names", module))
11789 return -1;
11790 #endif
11791 #ifdef HAVE_SYSCONF
11792 if (setup_confname_table(posix_constants_sysconf,
11793 sizeof(posix_constants_sysconf)
11794 / sizeof(struct constdef),
11795 "sysconf_names", module))
11796 return -1;
11797 #endif
11798 return 0;
11799 }
11800
11801
11802 /*[clinic input]
11803 os.abort
11804
11805 Abort the interpreter immediately.
11806
11807 This function 'dumps core' or otherwise fails in the hardest way possible
11808 on the hosting operating system. This function never returns.
11809 [clinic start generated code]*/
11810
11811 static PyObject *
os_abort_impl(PyObject * module)11812 os_abort_impl(PyObject *module)
11813 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
11814 {
11815 abort();
11816 /*NOTREACHED*/
11817 #ifndef __clang__
11818 /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
11819 GCC emits a warning without "return NULL;" (compiler bug?), but Clang
11820 is smarter and emits a warning on the return. */
11821 Py_FatalError("abort() called from Python code didn't abort!");
11822 return NULL;
11823 #endif
11824 }
11825
11826 #ifdef MS_WINDOWS
11827 /* Grab ShellExecute dynamically from shell32 */
11828 static int has_ShellExecute = -1;
11829 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
11830 LPCWSTR, INT);
11831 static int
check_ShellExecute()11832 check_ShellExecute()
11833 {
11834 HINSTANCE hShell32;
11835
11836 /* only recheck */
11837 if (-1 == has_ShellExecute) {
11838 Py_BEGIN_ALLOW_THREADS
11839 /* Security note: this call is not vulnerable to "DLL hijacking".
11840 SHELL32 is part of "KnownDLLs" and so Windows always load
11841 the system SHELL32.DLL, even if there is another SHELL32.DLL
11842 in the DLL search path. */
11843 hShell32 = LoadLibraryW(L"SHELL32");
11844 if (hShell32) {
11845 *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
11846 "ShellExecuteW");
11847 has_ShellExecute = Py_ShellExecuteW != NULL;
11848 } else {
11849 has_ShellExecute = 0;
11850 }
11851 Py_END_ALLOW_THREADS
11852 }
11853 return has_ShellExecute;
11854 }
11855
11856
11857 /*[clinic input]
11858 os.startfile
11859 filepath: path_t
11860 operation: Py_UNICODE = NULL
11861
11862 Start a file with its associated application.
11863
11864 When "operation" is not specified or "open", this acts like
11865 double-clicking the file in Explorer, or giving the file name as an
11866 argument to the DOS "start" command: the file is opened with whatever
11867 application (if any) its extension is associated.
11868 When another "operation" is given, it specifies what should be done with
11869 the file. A typical operation is "print".
11870
11871 startfile returns as soon as the associated application is launched.
11872 There is no option to wait for the application to close, and no way
11873 to retrieve the application's exit status.
11874
11875 The filepath is relative to the current directory. If you want to use
11876 an absolute path, make sure the first character is not a slash ("/");
11877 the underlying Win32 ShellExecute function doesn't work if it is.
11878 [clinic start generated code]*/
11879
11880 static PyObject *
os_startfile_impl(PyObject * module,path_t * filepath,const Py_UNICODE * operation)11881 os_startfile_impl(PyObject *module, path_t *filepath,
11882 const Py_UNICODE *operation)
11883 /*[clinic end generated code: output=66dc311c94d50797 input=c940888a5390f039]*/
11884 {
11885 HINSTANCE rc;
11886
11887 if(!check_ShellExecute()) {
11888 /* If the OS doesn't have ShellExecute, return a
11889 NotImplementedError. */
11890 return PyErr_Format(PyExc_NotImplementedError,
11891 "startfile not available on this platform");
11892 }
11893
11894 if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
11895 return NULL;
11896 }
11897
11898 Py_BEGIN_ALLOW_THREADS
11899 rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
11900 NULL, NULL, SW_SHOWNORMAL);
11901 Py_END_ALLOW_THREADS
11902
11903 if (rc <= (HINSTANCE)32) {
11904 win32_error_object("startfile", filepath->object);
11905 return NULL;
11906 }
11907 Py_RETURN_NONE;
11908 }
11909 #endif /* MS_WINDOWS */
11910
11911
11912 #ifdef HAVE_GETLOADAVG
11913 /*[clinic input]
11914 os.getloadavg
11915
11916 Return average recent system load information.
11917
11918 Return the number of processes in the system run queue averaged over
11919 the last 1, 5, and 15 minutes as a tuple of three floats.
11920 Raises OSError if the load average was unobtainable.
11921 [clinic start generated code]*/
11922
11923 static PyObject *
os_getloadavg_impl(PyObject * module)11924 os_getloadavg_impl(PyObject *module)
11925 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
11926 {
11927 double loadavg[3];
11928 if (getloadavg(loadavg, 3)!=3) {
11929 PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
11930 return NULL;
11931 } else
11932 return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
11933 }
11934 #endif /* HAVE_GETLOADAVG */
11935
11936
11937 /*[clinic input]
11938 os.device_encoding
11939 fd: int
11940
11941 Return a string describing the encoding of a terminal's file descriptor.
11942
11943 The file descriptor must be attached to a terminal.
11944 If the device is not a terminal, return None.
11945 [clinic start generated code]*/
11946
11947 static PyObject *
os_device_encoding_impl(PyObject * module,int fd)11948 os_device_encoding_impl(PyObject *module, int fd)
11949 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
11950 {
11951 return _Py_device_encoding(fd);
11952 }
11953
11954
11955 #ifdef HAVE_SETRESUID
11956 /*[clinic input]
11957 os.setresuid
11958
11959 ruid: uid_t
11960 euid: uid_t
11961 suid: uid_t
11962 /
11963
11964 Set the current process's real, effective, and saved user ids.
11965 [clinic start generated code]*/
11966
11967 static PyObject *
os_setresuid_impl(PyObject * module,uid_t ruid,uid_t euid,uid_t suid)11968 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
11969 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
11970 {
11971 if (setresuid(ruid, euid, suid) < 0)
11972 return posix_error();
11973 Py_RETURN_NONE;
11974 }
11975 #endif /* HAVE_SETRESUID */
11976
11977
11978 #ifdef HAVE_SETRESGID
11979 /*[clinic input]
11980 os.setresgid
11981
11982 rgid: gid_t
11983 egid: gid_t
11984 sgid: gid_t
11985 /
11986
11987 Set the current process's real, effective, and saved group ids.
11988 [clinic start generated code]*/
11989
11990 static PyObject *
os_setresgid_impl(PyObject * module,gid_t rgid,gid_t egid,gid_t sgid)11991 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
11992 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
11993 {
11994 if (setresgid(rgid, egid, sgid) < 0)
11995 return posix_error();
11996 Py_RETURN_NONE;
11997 }
11998 #endif /* HAVE_SETRESGID */
11999
12000
12001 #ifdef HAVE_GETRESUID
12002 /*[clinic input]
12003 os.getresuid
12004
12005 Return a tuple of the current process's real, effective, and saved user ids.
12006 [clinic start generated code]*/
12007
12008 static PyObject *
os_getresuid_impl(PyObject * module)12009 os_getresuid_impl(PyObject *module)
12010 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12011 {
12012 uid_t ruid, euid, suid;
12013 if (getresuid(&ruid, &euid, &suid) < 0)
12014 return posix_error();
12015 return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12016 _PyLong_FromUid(euid),
12017 _PyLong_FromUid(suid));
12018 }
12019 #endif /* HAVE_GETRESUID */
12020
12021
12022 #ifdef HAVE_GETRESGID
12023 /*[clinic input]
12024 os.getresgid
12025
12026 Return a tuple of the current process's real, effective, and saved group ids.
12027 [clinic start generated code]*/
12028
12029 static PyObject *
os_getresgid_impl(PyObject * module)12030 os_getresgid_impl(PyObject *module)
12031 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12032 {
12033 gid_t rgid, egid, sgid;
12034 if (getresgid(&rgid, &egid, &sgid) < 0)
12035 return posix_error();
12036 return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12037 _PyLong_FromGid(egid),
12038 _PyLong_FromGid(sgid));
12039 }
12040 #endif /* HAVE_GETRESGID */
12041
12042
12043 #ifdef USE_XATTRS
12044 /*[clinic input]
12045 os.getxattr
12046
12047 path: path_t(allow_fd=True)
12048 attribute: path_t
12049 *
12050 follow_symlinks: bool = True
12051
12052 Return the value of extended attribute attribute on path.
12053
12054 path may be either a string, a path-like object, or an open file descriptor.
12055 If follow_symlinks is False, and the last element of the path is a symbolic
12056 link, getxattr will examine the symbolic link itself instead of the file
12057 the link points to.
12058
12059 [clinic start generated code]*/
12060
12061 static PyObject *
os_getxattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12062 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12063 int follow_symlinks)
12064 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12065 {
12066 Py_ssize_t i;
12067 PyObject *buffer = NULL;
12068
12069 if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12070 return NULL;
12071
12072 if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12073 return NULL;
12074 }
12075
12076 for (i = 0; ; i++) {
12077 void *ptr;
12078 ssize_t result;
12079 static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12080 Py_ssize_t buffer_size = buffer_sizes[i];
12081 if (!buffer_size) {
12082 path_error(path);
12083 return NULL;
12084 }
12085 buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12086 if (!buffer)
12087 return NULL;
12088 ptr = PyBytes_AS_STRING(buffer);
12089
12090 Py_BEGIN_ALLOW_THREADS;
12091 if (path->fd >= 0)
12092 result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12093 else if (follow_symlinks)
12094 result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12095 else
12096 result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12097 Py_END_ALLOW_THREADS;
12098
12099 if (result < 0) {
12100 Py_DECREF(buffer);
12101 if (errno == ERANGE)
12102 continue;
12103 path_error(path);
12104 return NULL;
12105 }
12106
12107 if (result != buffer_size) {
12108 /* Can only shrink. */
12109 _PyBytes_Resize(&buffer, result);
12110 }
12111 break;
12112 }
12113
12114 return buffer;
12115 }
12116
12117
12118 /*[clinic input]
12119 os.setxattr
12120
12121 path: path_t(allow_fd=True)
12122 attribute: path_t
12123 value: Py_buffer
12124 flags: int = 0
12125 *
12126 follow_symlinks: bool = True
12127
12128 Set extended attribute attribute on path to value.
12129
12130 path may be either a string, a path-like object, or an open file descriptor.
12131 If follow_symlinks is False, and the last element of the path is a symbolic
12132 link, setxattr will modify the symbolic link itself instead of the file
12133 the link points to.
12134
12135 [clinic start generated code]*/
12136
12137 static PyObject *
os_setxattr_impl(PyObject * module,path_t * path,path_t * attribute,Py_buffer * value,int flags,int follow_symlinks)12138 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12139 Py_buffer *value, int flags, int follow_symlinks)
12140 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12141 {
12142 ssize_t result;
12143
12144 if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12145 return NULL;
12146
12147 if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12148 value->buf, value->len, flags) < 0) {
12149 return NULL;
12150 }
12151
12152 Py_BEGIN_ALLOW_THREADS;
12153 if (path->fd > -1)
12154 result = fsetxattr(path->fd, attribute->narrow,
12155 value->buf, value->len, flags);
12156 else if (follow_symlinks)
12157 result = setxattr(path->narrow, attribute->narrow,
12158 value->buf, value->len, flags);
12159 else
12160 result = lsetxattr(path->narrow, attribute->narrow,
12161 value->buf, value->len, flags);
12162 Py_END_ALLOW_THREADS;
12163
12164 if (result) {
12165 path_error(path);
12166 return NULL;
12167 }
12168
12169 Py_RETURN_NONE;
12170 }
12171
12172
12173 /*[clinic input]
12174 os.removexattr
12175
12176 path: path_t(allow_fd=True)
12177 attribute: path_t
12178 *
12179 follow_symlinks: bool = True
12180
12181 Remove extended attribute attribute on path.
12182
12183 path may be either a string, a path-like object, or an open file descriptor.
12184 If follow_symlinks is False, and the last element of the path is a symbolic
12185 link, removexattr will modify the symbolic link itself instead of the file
12186 the link points to.
12187
12188 [clinic start generated code]*/
12189
12190 static PyObject *
os_removexattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12191 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
12192 int follow_symlinks)
12193 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
12194 {
12195 ssize_t result;
12196
12197 if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
12198 return NULL;
12199
12200 if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
12201 return NULL;
12202 }
12203
12204 Py_BEGIN_ALLOW_THREADS;
12205 if (path->fd > -1)
12206 result = fremovexattr(path->fd, attribute->narrow);
12207 else if (follow_symlinks)
12208 result = removexattr(path->narrow, attribute->narrow);
12209 else
12210 result = lremovexattr(path->narrow, attribute->narrow);
12211 Py_END_ALLOW_THREADS;
12212
12213 if (result) {
12214 return path_error(path);
12215 }
12216
12217 Py_RETURN_NONE;
12218 }
12219
12220
12221 /*[clinic input]
12222 os.listxattr
12223
12224 path: path_t(allow_fd=True, nullable=True) = None
12225 *
12226 follow_symlinks: bool = True
12227
12228 Return a list of extended attributes on path.
12229
12230 path may be either None, a string, a path-like object, or an open file descriptor.
12231 if path is None, listxattr will examine the current directory.
12232 If follow_symlinks is False, and the last element of the path is a symbolic
12233 link, listxattr will examine the symbolic link itself instead of the file
12234 the link points to.
12235 [clinic start generated code]*/
12236
12237 static PyObject *
os_listxattr_impl(PyObject * module,path_t * path,int follow_symlinks)12238 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
12239 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
12240 {
12241 Py_ssize_t i;
12242 PyObject *result = NULL;
12243 const char *name;
12244 char *buffer = NULL;
12245
12246 if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
12247 goto exit;
12248
12249 if (PySys_Audit("os.listxattr", "(O)",
12250 path->object ? path->object : Py_None) < 0) {
12251 return NULL;
12252 }
12253
12254 name = path->narrow ? path->narrow : ".";
12255
12256 for (i = 0; ; i++) {
12257 const char *start, *trace, *end;
12258 ssize_t length;
12259 static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
12260 Py_ssize_t buffer_size = buffer_sizes[i];
12261 if (!buffer_size) {
12262 /* ERANGE */
12263 path_error(path);
12264 break;
12265 }
12266 buffer = PyMem_MALLOC(buffer_size);
12267 if (!buffer) {
12268 PyErr_NoMemory();
12269 break;
12270 }
12271
12272 Py_BEGIN_ALLOW_THREADS;
12273 if (path->fd > -1)
12274 length = flistxattr(path->fd, buffer, buffer_size);
12275 else if (follow_symlinks)
12276 length = listxattr(name, buffer, buffer_size);
12277 else
12278 length = llistxattr(name, buffer, buffer_size);
12279 Py_END_ALLOW_THREADS;
12280
12281 if (length < 0) {
12282 if (errno == ERANGE) {
12283 PyMem_FREE(buffer);
12284 buffer = NULL;
12285 continue;
12286 }
12287 path_error(path);
12288 break;
12289 }
12290
12291 result = PyList_New(0);
12292 if (!result) {
12293 goto exit;
12294 }
12295
12296 end = buffer + length;
12297 for (trace = start = buffer; trace != end; trace++) {
12298 if (!*trace) {
12299 int error;
12300 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
12301 trace - start);
12302 if (!attribute) {
12303 Py_DECREF(result);
12304 result = NULL;
12305 goto exit;
12306 }
12307 error = PyList_Append(result, attribute);
12308 Py_DECREF(attribute);
12309 if (error) {
12310 Py_DECREF(result);
12311 result = NULL;
12312 goto exit;
12313 }
12314 start = trace + 1;
12315 }
12316 }
12317 break;
12318 }
12319 exit:
12320 if (buffer)
12321 PyMem_FREE(buffer);
12322 return result;
12323 }
12324 #endif /* USE_XATTRS */
12325
12326
12327 /*[clinic input]
12328 os.urandom
12329
12330 size: Py_ssize_t
12331 /
12332
12333 Return a bytes object containing random bytes suitable for cryptographic use.
12334 [clinic start generated code]*/
12335
12336 static PyObject *
os_urandom_impl(PyObject * module,Py_ssize_t size)12337 os_urandom_impl(PyObject *module, Py_ssize_t size)
12338 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
12339 {
12340 PyObject *bytes;
12341 int result;
12342
12343 if (size < 0)
12344 return PyErr_Format(PyExc_ValueError,
12345 "negative argument not allowed");
12346 bytes = PyBytes_FromStringAndSize(NULL, size);
12347 if (bytes == NULL)
12348 return NULL;
12349
12350 result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
12351 if (result == -1) {
12352 Py_DECREF(bytes);
12353 return NULL;
12354 }
12355 return bytes;
12356 }
12357
12358 #ifdef HAVE_MEMFD_CREATE
12359 /*[clinic input]
12360 os.memfd_create
12361
12362 name: FSConverter
12363 flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
12364
12365 [clinic start generated code]*/
12366
12367 static PyObject *
os_memfd_create_impl(PyObject * module,PyObject * name,unsigned int flags)12368 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
12369 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
12370 {
12371 int fd;
12372 const char *bytes = PyBytes_AS_STRING(name);
12373 Py_BEGIN_ALLOW_THREADS
12374 fd = memfd_create(bytes, flags);
12375 Py_END_ALLOW_THREADS
12376 if (fd == -1) {
12377 return PyErr_SetFromErrno(PyExc_OSError);
12378 }
12379 return PyLong_FromLong(fd);
12380 }
12381 #endif
12382
12383 /* Terminal size querying */
12384
12385 static PyTypeObject* TerminalSizeType;
12386
12387 PyDoc_STRVAR(TerminalSize_docstring,
12388 "A tuple of (columns, lines) for holding terminal window size");
12389
12390 static PyStructSequence_Field TerminalSize_fields[] = {
12391 {"columns", "width of the terminal window in characters"},
12392 {"lines", "height of the terminal window in characters"},
12393 {NULL, NULL}
12394 };
12395
12396 static PyStructSequence_Desc TerminalSize_desc = {
12397 "os.terminal_size",
12398 TerminalSize_docstring,
12399 TerminalSize_fields,
12400 2,
12401 };
12402
12403 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
12404 /* AC 3.5: fd should accept None */
12405 PyDoc_STRVAR(termsize__doc__,
12406 "Return the size of the terminal window as (columns, lines).\n" \
12407 "\n" \
12408 "The optional argument fd (default standard output) specifies\n" \
12409 "which file descriptor should be queried.\n" \
12410 "\n" \
12411 "If the file descriptor is not connected to a terminal, an OSError\n" \
12412 "is thrown.\n" \
12413 "\n" \
12414 "This function will only be defined if an implementation is\n" \
12415 "available for this system.\n" \
12416 "\n" \
12417 "shutil.get_terminal_size is the high-level function which should\n" \
12418 "normally be used, os.get_terminal_size is the low-level implementation.");
12419
12420 static PyObject*
get_terminal_size(PyObject * self,PyObject * args)12421 get_terminal_size(PyObject *self, PyObject *args)
12422 {
12423 int columns, lines;
12424 PyObject *termsize;
12425
12426 int fd = fileno(stdout);
12427 /* Under some conditions stdout may not be connected and
12428 * fileno(stdout) may point to an invalid file descriptor. For example
12429 * GUI apps don't have valid standard streams by default.
12430 *
12431 * If this happens, and the optional fd argument is not present,
12432 * the ioctl below will fail returning EBADF. This is what we want.
12433 */
12434
12435 if (!PyArg_ParseTuple(args, "|i", &fd))
12436 return NULL;
12437
12438 #ifdef TERMSIZE_USE_IOCTL
12439 {
12440 struct winsize w;
12441 if (ioctl(fd, TIOCGWINSZ, &w))
12442 return PyErr_SetFromErrno(PyExc_OSError);
12443 columns = w.ws_col;
12444 lines = w.ws_row;
12445 }
12446 #endif /* TERMSIZE_USE_IOCTL */
12447
12448 #ifdef TERMSIZE_USE_CONIO
12449 {
12450 DWORD nhandle;
12451 HANDLE handle;
12452 CONSOLE_SCREEN_BUFFER_INFO csbi;
12453 switch (fd) {
12454 case 0: nhandle = STD_INPUT_HANDLE;
12455 break;
12456 case 1: nhandle = STD_OUTPUT_HANDLE;
12457 break;
12458 case 2: nhandle = STD_ERROR_HANDLE;
12459 break;
12460 default:
12461 return PyErr_Format(PyExc_ValueError, "bad file descriptor");
12462 }
12463 handle = GetStdHandle(nhandle);
12464 if (handle == NULL)
12465 return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
12466 if (handle == INVALID_HANDLE_VALUE)
12467 return PyErr_SetFromWindowsErr(0);
12468
12469 if (!GetConsoleScreenBufferInfo(handle, &csbi))
12470 return PyErr_SetFromWindowsErr(0);
12471
12472 columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
12473 lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
12474 }
12475 #endif /* TERMSIZE_USE_CONIO */
12476
12477 termsize = PyStructSequence_New(TerminalSizeType);
12478 if (termsize == NULL)
12479 return NULL;
12480 PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
12481 PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
12482 if (PyErr_Occurred()) {
12483 Py_DECREF(termsize);
12484 return NULL;
12485 }
12486 return termsize;
12487 }
12488 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
12489
12490
12491 /*[clinic input]
12492 os.cpu_count
12493
12494 Return the number of CPUs in the system; return None if indeterminable.
12495
12496 This number is not equivalent to the number of CPUs the current process can
12497 use. The number of usable CPUs can be obtained with
12498 ``len(os.sched_getaffinity(0))``
12499 [clinic start generated code]*/
12500
12501 static PyObject *
os_cpu_count_impl(PyObject * module)12502 os_cpu_count_impl(PyObject *module)
12503 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
12504 {
12505 int ncpu = 0;
12506 #ifdef MS_WINDOWS
12507 /* Declare prototype here to avoid pulling in all of the Win7 APIs in 3.8 */
12508 DWORD WINAPI GetActiveProcessorCount(WORD group);
12509 ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
12510 #elif defined(__hpux)
12511 ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
12512 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
12513 ncpu = sysconf(_SC_NPROCESSORS_ONLN);
12514 #elif defined(__DragonFly__) || \
12515 defined(__OpenBSD__) || \
12516 defined(__FreeBSD__) || \
12517 defined(__NetBSD__) || \
12518 defined(__APPLE__)
12519 int mib[2];
12520 size_t len = sizeof(ncpu);
12521 mib[0] = CTL_HW;
12522 mib[1] = HW_NCPU;
12523 if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
12524 ncpu = 0;
12525 #endif
12526 if (ncpu >= 1)
12527 return PyLong_FromLong(ncpu);
12528 else
12529 Py_RETURN_NONE;
12530 }
12531
12532
12533 /*[clinic input]
12534 os.get_inheritable -> bool
12535
12536 fd: int
12537 /
12538
12539 Get the close-on-exe flag of the specified file descriptor.
12540 [clinic start generated code]*/
12541
12542 static int
os_get_inheritable_impl(PyObject * module,int fd)12543 os_get_inheritable_impl(PyObject *module, int fd)
12544 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
12545 {
12546 int return_value;
12547 _Py_BEGIN_SUPPRESS_IPH
12548 return_value = _Py_get_inheritable(fd);
12549 _Py_END_SUPPRESS_IPH
12550 return return_value;
12551 }
12552
12553
12554 /*[clinic input]
12555 os.set_inheritable
12556 fd: int
12557 inheritable: int
12558 /
12559
12560 Set the inheritable flag of the specified file descriptor.
12561 [clinic start generated code]*/
12562
12563 static PyObject *
os_set_inheritable_impl(PyObject * module,int fd,int inheritable)12564 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
12565 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
12566 {
12567 int result;
12568
12569 _Py_BEGIN_SUPPRESS_IPH
12570 result = _Py_set_inheritable(fd, inheritable, NULL);
12571 _Py_END_SUPPRESS_IPH
12572 if (result < 0)
12573 return NULL;
12574 Py_RETURN_NONE;
12575 }
12576
12577
12578 #ifdef MS_WINDOWS
12579 /*[clinic input]
12580 os.get_handle_inheritable -> bool
12581 handle: intptr_t
12582 /
12583
12584 Get the close-on-exe flag of the specified file descriptor.
12585 [clinic start generated code]*/
12586
12587 static int
os_get_handle_inheritable_impl(PyObject * module,intptr_t handle)12588 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
12589 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
12590 {
12591 DWORD flags;
12592
12593 if (!GetHandleInformation((HANDLE)handle, &flags)) {
12594 PyErr_SetFromWindowsErr(0);
12595 return -1;
12596 }
12597
12598 return flags & HANDLE_FLAG_INHERIT;
12599 }
12600
12601
12602 /*[clinic input]
12603 os.set_handle_inheritable
12604 handle: intptr_t
12605 inheritable: bool
12606 /
12607
12608 Set the inheritable flag of the specified handle.
12609 [clinic start generated code]*/
12610
12611 static PyObject *
os_set_handle_inheritable_impl(PyObject * module,intptr_t handle,int inheritable)12612 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
12613 int inheritable)
12614 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
12615 {
12616 DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
12617 if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
12618 PyErr_SetFromWindowsErr(0);
12619 return NULL;
12620 }
12621 Py_RETURN_NONE;
12622 }
12623 #endif /* MS_WINDOWS */
12624
12625 #ifndef MS_WINDOWS
12626 /*[clinic input]
12627 os.get_blocking -> bool
12628 fd: int
12629 /
12630
12631 Get the blocking mode of the file descriptor.
12632
12633 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
12634 [clinic start generated code]*/
12635
12636 static int
os_get_blocking_impl(PyObject * module,int fd)12637 os_get_blocking_impl(PyObject *module, int fd)
12638 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
12639 {
12640 int blocking;
12641
12642 _Py_BEGIN_SUPPRESS_IPH
12643 blocking = _Py_get_blocking(fd);
12644 _Py_END_SUPPRESS_IPH
12645 return blocking;
12646 }
12647
12648 /*[clinic input]
12649 os.set_blocking
12650 fd: int
12651 blocking: bool(accept={int})
12652 /
12653
12654 Set the blocking mode of the specified file descriptor.
12655
12656 Set the O_NONBLOCK flag if blocking is False,
12657 clear the O_NONBLOCK flag otherwise.
12658 [clinic start generated code]*/
12659
12660 static PyObject *
os_set_blocking_impl(PyObject * module,int fd,int blocking)12661 os_set_blocking_impl(PyObject *module, int fd, int blocking)
12662 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
12663 {
12664 int result;
12665
12666 _Py_BEGIN_SUPPRESS_IPH
12667 result = _Py_set_blocking(fd, blocking);
12668 _Py_END_SUPPRESS_IPH
12669 if (result < 0)
12670 return NULL;
12671 Py_RETURN_NONE;
12672 }
12673 #endif /* !MS_WINDOWS */
12674
12675
12676 /*[clinic input]
12677 class os.DirEntry "DirEntry *" "&DirEntryType"
12678 [clinic start generated code]*/
12679 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3138f09f7c683f1d]*/
12680
12681 typedef struct {
12682 PyObject_HEAD
12683 PyObject *name;
12684 PyObject *path;
12685 PyObject *stat;
12686 PyObject *lstat;
12687 #ifdef MS_WINDOWS
12688 struct _Py_stat_struct win32_lstat;
12689 uint64_t win32_file_index;
12690 int got_file_index;
12691 #else /* POSIX */
12692 #ifdef HAVE_DIRENT_D_TYPE
12693 unsigned char d_type;
12694 #endif
12695 ino_t d_ino;
12696 int dir_fd;
12697 #endif
12698 } DirEntry;
12699
12700 static void
DirEntry_dealloc(DirEntry * entry)12701 DirEntry_dealloc(DirEntry *entry)
12702 {
12703 Py_XDECREF(entry->name);
12704 Py_XDECREF(entry->path);
12705 Py_XDECREF(entry->stat);
12706 Py_XDECREF(entry->lstat);
12707 Py_TYPE(entry)->tp_free((PyObject *)entry);
12708 }
12709
12710 /* Forward reference */
12711 static int
12712 DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits);
12713
12714 /*[clinic input]
12715 os.DirEntry.is_symlink -> bool
12716
12717 Return True if the entry is a symbolic link; cached per entry.
12718 [clinic start generated code]*/
12719
12720 static int
os_DirEntry_is_symlink_impl(DirEntry * self)12721 os_DirEntry_is_symlink_impl(DirEntry *self)
12722 /*[clinic end generated code: output=42244667d7bcfc25 input=1605a1b4b96976c3]*/
12723 {
12724 #ifdef MS_WINDOWS
12725 return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
12726 #elif defined(HAVE_DIRENT_D_TYPE)
12727 /* POSIX */
12728 if (self->d_type != DT_UNKNOWN)
12729 return self->d_type == DT_LNK;
12730 else
12731 return DirEntry_test_mode(self, 0, S_IFLNK);
12732 #else
12733 /* POSIX without d_type */
12734 return DirEntry_test_mode(self, 0, S_IFLNK);
12735 #endif
12736 }
12737
12738 static PyObject *
DirEntry_fetch_stat(DirEntry * self,int follow_symlinks)12739 DirEntry_fetch_stat(DirEntry *self, int follow_symlinks)
12740 {
12741 int result;
12742 STRUCT_STAT st;
12743 PyObject *ub;
12744
12745 #ifdef MS_WINDOWS
12746 if (!PyUnicode_FSDecoder(self->path, &ub))
12747 return NULL;
12748 const wchar_t *path = PyUnicode_AsUnicode(ub);
12749 #else /* POSIX */
12750 if (!PyUnicode_FSConverter(self->path, &ub))
12751 return NULL;
12752 const char *path = PyBytes_AS_STRING(ub);
12753 if (self->dir_fd != DEFAULT_DIR_FD) {
12754 #ifdef HAVE_FSTATAT
12755 result = fstatat(self->dir_fd, path, &st,
12756 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
12757 #else
12758 PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
12759 return NULL;
12760 #endif /* HAVE_FSTATAT */
12761 }
12762 else
12763 #endif
12764 {
12765 if (follow_symlinks)
12766 result = STAT(path, &st);
12767 else
12768 result = LSTAT(path, &st);
12769 }
12770 Py_DECREF(ub);
12771
12772 if (result != 0)
12773 return path_object_error(self->path);
12774
12775 return _pystat_fromstructstat(&st);
12776 }
12777
12778 static PyObject *
DirEntry_get_lstat(DirEntry * self)12779 DirEntry_get_lstat(DirEntry *self)
12780 {
12781 if (!self->lstat) {
12782 #ifdef MS_WINDOWS
12783 self->lstat = _pystat_fromstructstat(&self->win32_lstat);
12784 #else /* POSIX */
12785 self->lstat = DirEntry_fetch_stat(self, 0);
12786 #endif
12787 }
12788 Py_XINCREF(self->lstat);
12789 return self->lstat;
12790 }
12791
12792 /*[clinic input]
12793 os.DirEntry.stat
12794 *
12795 follow_symlinks: bool = True
12796
12797 Return stat_result object for the entry; cached per entry.
12798 [clinic start generated code]*/
12799
12800 static PyObject *
os_DirEntry_stat_impl(DirEntry * self,int follow_symlinks)12801 os_DirEntry_stat_impl(DirEntry *self, int follow_symlinks)
12802 /*[clinic end generated code: output=008593b3a6d01305 input=280d14c1d6f1d00d]*/
12803 {
12804 if (!follow_symlinks)
12805 return DirEntry_get_lstat(self);
12806
12807 if (!self->stat) {
12808 int result = os_DirEntry_is_symlink_impl(self);
12809 if (result == -1)
12810 return NULL;
12811 else if (result)
12812 self->stat = DirEntry_fetch_stat(self, 1);
12813 else
12814 self->stat = DirEntry_get_lstat(self);
12815 }
12816
12817 Py_XINCREF(self->stat);
12818 return self->stat;
12819 }
12820
12821 /* Set exception and return -1 on error, 0 for False, 1 for True */
12822 static int
DirEntry_test_mode(DirEntry * self,int follow_symlinks,unsigned short mode_bits)12823 DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits)
12824 {
12825 PyObject *stat = NULL;
12826 PyObject *st_mode = NULL;
12827 long mode;
12828 int result;
12829 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
12830 int is_symlink;
12831 int need_stat;
12832 #endif
12833 #ifdef MS_WINDOWS
12834 unsigned long dir_bits;
12835 #endif
12836 _Py_IDENTIFIER(st_mode);
12837
12838 #ifdef MS_WINDOWS
12839 is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
12840 need_stat = follow_symlinks && is_symlink;
12841 #elif defined(HAVE_DIRENT_D_TYPE)
12842 is_symlink = self->d_type == DT_LNK;
12843 need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
12844 #endif
12845
12846 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
12847 if (need_stat) {
12848 #endif
12849 stat = os_DirEntry_stat_impl(self, follow_symlinks);
12850 if (!stat) {
12851 if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
12852 /* If file doesn't exist (anymore), then return False
12853 (i.e., say it's not a file/directory) */
12854 PyErr_Clear();
12855 return 0;
12856 }
12857 goto error;
12858 }
12859 st_mode = _PyObject_GetAttrId(stat, &PyId_st_mode);
12860 if (!st_mode)
12861 goto error;
12862
12863 mode = PyLong_AsLong(st_mode);
12864 if (mode == -1 && PyErr_Occurred())
12865 goto error;
12866 Py_CLEAR(st_mode);
12867 Py_CLEAR(stat);
12868 result = (mode & S_IFMT) == mode_bits;
12869 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
12870 }
12871 else if (is_symlink) {
12872 assert(mode_bits != S_IFLNK);
12873 result = 0;
12874 }
12875 else {
12876 assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
12877 #ifdef MS_WINDOWS
12878 dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
12879 if (mode_bits == S_IFDIR)
12880 result = dir_bits != 0;
12881 else
12882 result = dir_bits == 0;
12883 #else /* POSIX */
12884 if (mode_bits == S_IFDIR)
12885 result = self->d_type == DT_DIR;
12886 else
12887 result = self->d_type == DT_REG;
12888 #endif
12889 }
12890 #endif
12891
12892 return result;
12893
12894 error:
12895 Py_XDECREF(st_mode);
12896 Py_XDECREF(stat);
12897 return -1;
12898 }
12899
12900 /*[clinic input]
12901 os.DirEntry.is_dir -> bool
12902 *
12903 follow_symlinks: bool = True
12904
12905 Return True if the entry is a directory; cached per entry.
12906 [clinic start generated code]*/
12907
12908 static int
os_DirEntry_is_dir_impl(DirEntry * self,int follow_symlinks)12909 os_DirEntry_is_dir_impl(DirEntry *self, int follow_symlinks)
12910 /*[clinic end generated code: output=ad2e8d54365da287 input=0135232766f53f58]*/
12911 {
12912 return DirEntry_test_mode(self, follow_symlinks, S_IFDIR);
12913 }
12914
12915 /*[clinic input]
12916 os.DirEntry.is_file -> bool
12917 *
12918 follow_symlinks: bool = True
12919
12920 Return True if the entry is a file; cached per entry.
12921 [clinic start generated code]*/
12922
12923 static int
os_DirEntry_is_file_impl(DirEntry * self,int follow_symlinks)12924 os_DirEntry_is_file_impl(DirEntry *self, int follow_symlinks)
12925 /*[clinic end generated code: output=8462ade481d8a476 input=0dc90be168b041ee]*/
12926 {
12927 return DirEntry_test_mode(self, follow_symlinks, S_IFREG);
12928 }
12929
12930 /*[clinic input]
12931 os.DirEntry.inode
12932
12933 Return inode of the entry; cached per entry.
12934 [clinic start generated code]*/
12935
12936 static PyObject *
os_DirEntry_inode_impl(DirEntry * self)12937 os_DirEntry_inode_impl(DirEntry *self)
12938 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
12939 {
12940 #ifdef MS_WINDOWS
12941 if (!self->got_file_index) {
12942 PyObject *unicode;
12943 const wchar_t *path;
12944 STRUCT_STAT stat;
12945 int result;
12946
12947 if (!PyUnicode_FSDecoder(self->path, &unicode))
12948 return NULL;
12949 path = PyUnicode_AsUnicode(unicode);
12950 result = LSTAT(path, &stat);
12951 Py_DECREF(unicode);
12952
12953 if (result != 0)
12954 return path_object_error(self->path);
12955
12956 self->win32_file_index = stat.st_ino;
12957 self->got_file_index = 1;
12958 }
12959 Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->win32_file_index));
12960 return PyLong_FromUnsignedLongLong(self->win32_file_index);
12961 #else /* POSIX */
12962 Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->d_ino));
12963 return PyLong_FromUnsignedLongLong(self->d_ino);
12964 #endif
12965 }
12966
12967 static PyObject *
DirEntry_repr(DirEntry * self)12968 DirEntry_repr(DirEntry *self)
12969 {
12970 return PyUnicode_FromFormat("<DirEntry %R>", self->name);
12971 }
12972
12973 /*[clinic input]
12974 os.DirEntry.__fspath__
12975
12976 Returns the path for the entry.
12977 [clinic start generated code]*/
12978
12979 static PyObject *
os_DirEntry___fspath___impl(DirEntry * self)12980 os_DirEntry___fspath___impl(DirEntry *self)
12981 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
12982 {
12983 Py_INCREF(self->path);
12984 return self->path;
12985 }
12986
12987 static PyMemberDef DirEntry_members[] = {
12988 {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
12989 "the entry's base filename, relative to scandir() \"path\" argument"},
12990 {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
12991 "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
12992 {NULL}
12993 };
12994
12995 #include "clinic/posixmodule.c.h"
12996
12997 static PyMethodDef DirEntry_methods[] = {
12998 OS_DIRENTRY_IS_DIR_METHODDEF
12999 OS_DIRENTRY_IS_FILE_METHODDEF
13000 OS_DIRENTRY_IS_SYMLINK_METHODDEF
13001 OS_DIRENTRY_STAT_METHODDEF
13002 OS_DIRENTRY_INODE_METHODDEF
13003 OS_DIRENTRY___FSPATH___METHODDEF
13004 {NULL}
13005 };
13006
13007 static PyTypeObject DirEntryType = {
13008 PyVarObject_HEAD_INIT(NULL, 0)
13009 MODNAME ".DirEntry", /* tp_name */
13010 sizeof(DirEntry), /* tp_basicsize */
13011 0, /* tp_itemsize */
13012 /* methods */
13013 (destructor)DirEntry_dealloc, /* tp_dealloc */
13014 0, /* tp_vectorcall_offset */
13015 0, /* tp_getattr */
13016 0, /* tp_setattr */
13017 0, /* tp_as_async */
13018 (reprfunc)DirEntry_repr, /* tp_repr */
13019 0, /* tp_as_number */
13020 0, /* tp_as_sequence */
13021 0, /* tp_as_mapping */
13022 0, /* tp_hash */
13023 0, /* tp_call */
13024 0, /* tp_str */
13025 0, /* tp_getattro */
13026 0, /* tp_setattro */
13027 0, /* tp_as_buffer */
13028 Py_TPFLAGS_DEFAULT, /* tp_flags */
13029 0, /* tp_doc */
13030 0, /* tp_traverse */
13031 0, /* tp_clear */
13032 0, /* tp_richcompare */
13033 0, /* tp_weaklistoffset */
13034 0, /* tp_iter */
13035 0, /* tp_iternext */
13036 DirEntry_methods, /* tp_methods */
13037 DirEntry_members, /* tp_members */
13038 };
13039
13040 #ifdef MS_WINDOWS
13041
13042 static wchar_t *
join_path_filenameW(const wchar_t * path_wide,const wchar_t * filename)13043 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
13044 {
13045 Py_ssize_t path_len;
13046 Py_ssize_t size;
13047 wchar_t *result;
13048 wchar_t ch;
13049
13050 if (!path_wide) { /* Default arg: "." */
13051 path_wide = L".";
13052 path_len = 1;
13053 }
13054 else {
13055 path_len = wcslen(path_wide);
13056 }
13057
13058 /* The +1's are for the path separator and the NUL */
13059 size = path_len + 1 + wcslen(filename) + 1;
13060 result = PyMem_New(wchar_t, size);
13061 if (!result) {
13062 PyErr_NoMemory();
13063 return NULL;
13064 }
13065 wcscpy(result, path_wide);
13066 if (path_len > 0) {
13067 ch = result[path_len - 1];
13068 if (ch != SEP && ch != ALTSEP && ch != L':')
13069 result[path_len++] = SEP;
13070 wcscpy(result + path_len, filename);
13071 }
13072 return result;
13073 }
13074
13075 static PyObject *
DirEntry_from_find_data(path_t * path,WIN32_FIND_DATAW * dataW)13076 DirEntry_from_find_data(path_t *path, WIN32_FIND_DATAW *dataW)
13077 {
13078 DirEntry *entry;
13079 BY_HANDLE_FILE_INFORMATION file_info;
13080 ULONG reparse_tag;
13081 wchar_t *joined_path;
13082
13083 entry = PyObject_New(DirEntry, &DirEntryType);
13084 if (!entry)
13085 return NULL;
13086 entry->name = NULL;
13087 entry->path = NULL;
13088 entry->stat = NULL;
13089 entry->lstat = NULL;
13090 entry->got_file_index = 0;
13091
13092 entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
13093 if (!entry->name)
13094 goto error;
13095 if (path->narrow) {
13096 Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
13097 if (!entry->name)
13098 goto error;
13099 }
13100
13101 joined_path = join_path_filenameW(path->wide, dataW->cFileName);
13102 if (!joined_path)
13103 goto error;
13104
13105 entry->path = PyUnicode_FromWideChar(joined_path, -1);
13106 PyMem_Free(joined_path);
13107 if (!entry->path)
13108 goto error;
13109 if (path->narrow) {
13110 Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
13111 if (!entry->path)
13112 goto error;
13113 }
13114
13115 find_data_to_file_info(dataW, &file_info, &reparse_tag);
13116 _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
13117
13118 return (PyObject *)entry;
13119
13120 error:
13121 Py_DECREF(entry);
13122 return NULL;
13123 }
13124
13125 #else /* POSIX */
13126
13127 static char *
join_path_filename(const char * path_narrow,const char * filename,Py_ssize_t filename_len)13128 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
13129 {
13130 Py_ssize_t path_len;
13131 Py_ssize_t size;
13132 char *result;
13133
13134 if (!path_narrow) { /* Default arg: "." */
13135 path_narrow = ".";
13136 path_len = 1;
13137 }
13138 else {
13139 path_len = strlen(path_narrow);
13140 }
13141
13142 if (filename_len == -1)
13143 filename_len = strlen(filename);
13144
13145 /* The +1's are for the path separator and the NUL */
13146 size = path_len + 1 + filename_len + 1;
13147 result = PyMem_New(char, size);
13148 if (!result) {
13149 PyErr_NoMemory();
13150 return NULL;
13151 }
13152 strcpy(result, path_narrow);
13153 if (path_len > 0 && result[path_len - 1] != '/')
13154 result[path_len++] = '/';
13155 strcpy(result + path_len, filename);
13156 return result;
13157 }
13158
13159 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)13160 DirEntry_from_posix_info(path_t *path, const char *name, Py_ssize_t name_len,
13161 ino_t d_ino
13162 #ifdef HAVE_DIRENT_D_TYPE
13163 , unsigned char d_type
13164 #endif
13165 )
13166 {
13167 DirEntry *entry;
13168 char *joined_path;
13169
13170 entry = PyObject_New(DirEntry, &DirEntryType);
13171 if (!entry)
13172 return NULL;
13173 entry->name = NULL;
13174 entry->path = NULL;
13175 entry->stat = NULL;
13176 entry->lstat = NULL;
13177
13178 if (path->fd != -1) {
13179 entry->dir_fd = path->fd;
13180 joined_path = NULL;
13181 }
13182 else {
13183 entry->dir_fd = DEFAULT_DIR_FD;
13184 joined_path = join_path_filename(path->narrow, name, name_len);
13185 if (!joined_path)
13186 goto error;
13187 }
13188
13189 if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
13190 entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
13191 if (joined_path)
13192 entry->path = PyUnicode_DecodeFSDefault(joined_path);
13193 }
13194 else {
13195 entry->name = PyBytes_FromStringAndSize(name, name_len);
13196 if (joined_path)
13197 entry->path = PyBytes_FromString(joined_path);
13198 }
13199 PyMem_Free(joined_path);
13200 if (!entry->name)
13201 goto error;
13202
13203 if (path->fd != -1) {
13204 entry->path = entry->name;
13205 Py_INCREF(entry->path);
13206 }
13207 else if (!entry->path)
13208 goto error;
13209
13210 #ifdef HAVE_DIRENT_D_TYPE
13211 entry->d_type = d_type;
13212 #endif
13213 entry->d_ino = d_ino;
13214
13215 return (PyObject *)entry;
13216
13217 error:
13218 Py_XDECREF(entry);
13219 return NULL;
13220 }
13221
13222 #endif
13223
13224
13225 typedef struct {
13226 PyObject_HEAD
13227 path_t path;
13228 #ifdef MS_WINDOWS
13229 HANDLE handle;
13230 WIN32_FIND_DATAW file_data;
13231 int first_time;
13232 #else /* POSIX */
13233 DIR *dirp;
13234 #endif
13235 #ifdef HAVE_FDOPENDIR
13236 int fd;
13237 #endif
13238 } ScandirIterator;
13239
13240 #ifdef MS_WINDOWS
13241
13242 static int
ScandirIterator_is_closed(ScandirIterator * iterator)13243 ScandirIterator_is_closed(ScandirIterator *iterator)
13244 {
13245 return iterator->handle == INVALID_HANDLE_VALUE;
13246 }
13247
13248 static void
ScandirIterator_closedir(ScandirIterator * iterator)13249 ScandirIterator_closedir(ScandirIterator *iterator)
13250 {
13251 HANDLE handle = iterator->handle;
13252
13253 if (handle == INVALID_HANDLE_VALUE)
13254 return;
13255
13256 iterator->handle = INVALID_HANDLE_VALUE;
13257 Py_BEGIN_ALLOW_THREADS
13258 FindClose(handle);
13259 Py_END_ALLOW_THREADS
13260 }
13261
13262 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)13263 ScandirIterator_iternext(ScandirIterator *iterator)
13264 {
13265 WIN32_FIND_DATAW *file_data = &iterator->file_data;
13266 BOOL success;
13267 PyObject *entry;
13268
13269 /* Happens if the iterator is iterated twice, or closed explicitly */
13270 if (iterator->handle == INVALID_HANDLE_VALUE)
13271 return NULL;
13272
13273 while (1) {
13274 if (!iterator->first_time) {
13275 Py_BEGIN_ALLOW_THREADS
13276 success = FindNextFileW(iterator->handle, file_data);
13277 Py_END_ALLOW_THREADS
13278 if (!success) {
13279 /* Error or no more files */
13280 if (GetLastError() != ERROR_NO_MORE_FILES)
13281 path_error(&iterator->path);
13282 break;
13283 }
13284 }
13285 iterator->first_time = 0;
13286
13287 /* Skip over . and .. */
13288 if (wcscmp(file_data->cFileName, L".") != 0 &&
13289 wcscmp(file_data->cFileName, L"..") != 0) {
13290 entry = DirEntry_from_find_data(&iterator->path, file_data);
13291 if (!entry)
13292 break;
13293 return entry;
13294 }
13295
13296 /* Loop till we get a non-dot directory or finish iterating */
13297 }
13298
13299 /* Error or no more files */
13300 ScandirIterator_closedir(iterator);
13301 return NULL;
13302 }
13303
13304 #else /* POSIX */
13305
13306 static int
ScandirIterator_is_closed(ScandirIterator * iterator)13307 ScandirIterator_is_closed(ScandirIterator *iterator)
13308 {
13309 return !iterator->dirp;
13310 }
13311
13312 static void
ScandirIterator_closedir(ScandirIterator * iterator)13313 ScandirIterator_closedir(ScandirIterator *iterator)
13314 {
13315 DIR *dirp = iterator->dirp;
13316
13317 if (!dirp)
13318 return;
13319
13320 iterator->dirp = NULL;
13321 Py_BEGIN_ALLOW_THREADS
13322 #ifdef HAVE_FDOPENDIR
13323 if (iterator->path.fd != -1)
13324 rewinddir(dirp);
13325 #endif
13326 closedir(dirp);
13327 Py_END_ALLOW_THREADS
13328 return;
13329 }
13330
13331 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)13332 ScandirIterator_iternext(ScandirIterator *iterator)
13333 {
13334 struct dirent *direntp;
13335 Py_ssize_t name_len;
13336 int is_dot;
13337 PyObject *entry;
13338
13339 /* Happens if the iterator is iterated twice, or closed explicitly */
13340 if (!iterator->dirp)
13341 return NULL;
13342
13343 while (1) {
13344 errno = 0;
13345 Py_BEGIN_ALLOW_THREADS
13346 direntp = readdir(iterator->dirp);
13347 Py_END_ALLOW_THREADS
13348
13349 if (!direntp) {
13350 /* Error or no more files */
13351 if (errno != 0)
13352 path_error(&iterator->path);
13353 break;
13354 }
13355
13356 /* Skip over . and .. */
13357 name_len = NAMLEN(direntp);
13358 is_dot = direntp->d_name[0] == '.' &&
13359 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
13360 if (!is_dot) {
13361 entry = DirEntry_from_posix_info(&iterator->path, direntp->d_name,
13362 name_len, direntp->d_ino
13363 #ifdef HAVE_DIRENT_D_TYPE
13364 , direntp->d_type
13365 #endif
13366 );
13367 if (!entry)
13368 break;
13369 return entry;
13370 }
13371
13372 /* Loop till we get a non-dot directory or finish iterating */
13373 }
13374
13375 /* Error or no more files */
13376 ScandirIterator_closedir(iterator);
13377 return NULL;
13378 }
13379
13380 #endif
13381
13382 static PyObject *
ScandirIterator_close(ScandirIterator * self,PyObject * args)13383 ScandirIterator_close(ScandirIterator *self, PyObject *args)
13384 {
13385 ScandirIterator_closedir(self);
13386 Py_RETURN_NONE;
13387 }
13388
13389 static PyObject *
ScandirIterator_enter(PyObject * self,PyObject * args)13390 ScandirIterator_enter(PyObject *self, PyObject *args)
13391 {
13392 Py_INCREF(self);
13393 return self;
13394 }
13395
13396 static PyObject *
ScandirIterator_exit(ScandirIterator * self,PyObject * args)13397 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
13398 {
13399 ScandirIterator_closedir(self);
13400 Py_RETURN_NONE;
13401 }
13402
13403 static void
ScandirIterator_finalize(ScandirIterator * iterator)13404 ScandirIterator_finalize(ScandirIterator *iterator)
13405 {
13406 PyObject *error_type, *error_value, *error_traceback;
13407
13408 /* Save the current exception, if any. */
13409 PyErr_Fetch(&error_type, &error_value, &error_traceback);
13410
13411 if (!ScandirIterator_is_closed(iterator)) {
13412 ScandirIterator_closedir(iterator);
13413
13414 if (PyErr_ResourceWarning((PyObject *)iterator, 1,
13415 "unclosed scandir iterator %R", iterator)) {
13416 /* Spurious errors can appear at shutdown */
13417 if (PyErr_ExceptionMatches(PyExc_Warning)) {
13418 PyErr_WriteUnraisable((PyObject *) iterator);
13419 }
13420 }
13421 }
13422
13423 path_cleanup(&iterator->path);
13424
13425 /* Restore the saved exception. */
13426 PyErr_Restore(error_type, error_value, error_traceback);
13427 }
13428
13429 static void
ScandirIterator_dealloc(ScandirIterator * iterator)13430 ScandirIterator_dealloc(ScandirIterator *iterator)
13431 {
13432 if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
13433 return;
13434
13435 Py_TYPE(iterator)->tp_free((PyObject *)iterator);
13436 }
13437
13438 static PyMethodDef ScandirIterator_methods[] = {
13439 {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
13440 {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
13441 {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
13442 {NULL}
13443 };
13444
13445 static PyTypeObject ScandirIteratorType = {
13446 PyVarObject_HEAD_INIT(NULL, 0)
13447 MODNAME ".ScandirIterator", /* tp_name */
13448 sizeof(ScandirIterator), /* tp_basicsize */
13449 0, /* tp_itemsize */
13450 /* methods */
13451 (destructor)ScandirIterator_dealloc, /* tp_dealloc */
13452 0, /* tp_vectorcall_offset */
13453 0, /* tp_getattr */
13454 0, /* tp_setattr */
13455 0, /* tp_as_async */
13456 0, /* tp_repr */
13457 0, /* tp_as_number */
13458 0, /* tp_as_sequence */
13459 0, /* tp_as_mapping */
13460 0, /* tp_hash */
13461 0, /* tp_call */
13462 0, /* tp_str */
13463 0, /* tp_getattro */
13464 0, /* tp_setattro */
13465 0, /* tp_as_buffer */
13466 Py_TPFLAGS_DEFAULT, /* tp_flags */
13467 0, /* tp_doc */
13468 0, /* tp_traverse */
13469 0, /* tp_clear */
13470 0, /* tp_richcompare */
13471 0, /* tp_weaklistoffset */
13472 PyObject_SelfIter, /* tp_iter */
13473 (iternextfunc)ScandirIterator_iternext, /* tp_iternext */
13474 ScandirIterator_methods, /* tp_methods */
13475 0, /* tp_members */
13476 0, /* tp_getset */
13477 0, /* tp_base */
13478 0, /* tp_dict */
13479 0, /* tp_descr_get */
13480 0, /* tp_descr_set */
13481 0, /* tp_dictoffset */
13482 0, /* tp_init */
13483 0, /* tp_alloc */
13484 0, /* tp_new */
13485 0, /* tp_free */
13486 0, /* tp_is_gc */
13487 0, /* tp_bases */
13488 0, /* tp_mro */
13489 0, /* tp_cache */
13490 0, /* tp_subclasses */
13491 0, /* tp_weaklist */
13492 0, /* tp_del */
13493 0, /* tp_version_tag */
13494 (destructor)ScandirIterator_finalize, /* tp_finalize */
13495 };
13496
13497 /*[clinic input]
13498 os.scandir
13499
13500 path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
13501
13502 Return an iterator of DirEntry objects for given path.
13503
13504 path can be specified as either str, bytes, or a path-like object. If path
13505 is bytes, the names of yielded DirEntry objects will also be bytes; in
13506 all other circumstances they will be str.
13507
13508 If path is None, uses the path='.'.
13509 [clinic start generated code]*/
13510
13511 static PyObject *
os_scandir_impl(PyObject * module,path_t * path)13512 os_scandir_impl(PyObject *module, path_t *path)
13513 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
13514 {
13515 ScandirIterator *iterator;
13516 #ifdef MS_WINDOWS
13517 wchar_t *path_strW;
13518 #else
13519 const char *path_str;
13520 #ifdef HAVE_FDOPENDIR
13521 int fd = -1;
13522 #endif
13523 #endif
13524
13525 if (PySys_Audit("os.scandir", "O",
13526 path->object ? path->object : Py_None) < 0) {
13527 return NULL;
13528 }
13529
13530 iterator = PyObject_New(ScandirIterator, &ScandirIteratorType);
13531 if (!iterator)
13532 return NULL;
13533
13534 #ifdef MS_WINDOWS
13535 iterator->handle = INVALID_HANDLE_VALUE;
13536 #else
13537 iterator->dirp = NULL;
13538 #endif
13539
13540 memcpy(&iterator->path, path, sizeof(path_t));
13541 /* Move the ownership to iterator->path */
13542 path->object = NULL;
13543 path->cleanup = NULL;
13544
13545 #ifdef MS_WINDOWS
13546 iterator->first_time = 1;
13547
13548 path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
13549 if (!path_strW)
13550 goto error;
13551
13552 Py_BEGIN_ALLOW_THREADS
13553 iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
13554 Py_END_ALLOW_THREADS
13555
13556 PyMem_Free(path_strW);
13557
13558 if (iterator->handle == INVALID_HANDLE_VALUE) {
13559 path_error(&iterator->path);
13560 goto error;
13561 }
13562 #else /* POSIX */
13563 errno = 0;
13564 #ifdef HAVE_FDOPENDIR
13565 if (path->fd != -1) {
13566 /* closedir() closes the FD, so we duplicate it */
13567 fd = _Py_dup(path->fd);
13568 if (fd == -1)
13569 goto error;
13570
13571 Py_BEGIN_ALLOW_THREADS
13572 iterator->dirp = fdopendir(fd);
13573 Py_END_ALLOW_THREADS
13574 }
13575 else
13576 #endif
13577 {
13578 if (iterator->path.narrow)
13579 path_str = iterator->path.narrow;
13580 else
13581 path_str = ".";
13582
13583 Py_BEGIN_ALLOW_THREADS
13584 iterator->dirp = opendir(path_str);
13585 Py_END_ALLOW_THREADS
13586 }
13587
13588 if (!iterator->dirp) {
13589 path_error(&iterator->path);
13590 #ifdef HAVE_FDOPENDIR
13591 if (fd != -1) {
13592 Py_BEGIN_ALLOW_THREADS
13593 close(fd);
13594 Py_END_ALLOW_THREADS
13595 }
13596 #endif
13597 goto error;
13598 }
13599 #endif
13600
13601 return (PyObject *)iterator;
13602
13603 error:
13604 Py_DECREF(iterator);
13605 return NULL;
13606 }
13607
13608 /*
13609 Return the file system path representation of the object.
13610
13611 If the object is str or bytes, then allow it to pass through with
13612 an incremented refcount. If the object defines __fspath__(), then
13613 return the result of that method. All other types raise a TypeError.
13614 */
13615 PyObject *
PyOS_FSPath(PyObject * path)13616 PyOS_FSPath(PyObject *path)
13617 {
13618 /* For error message reasons, this function is manually inlined in
13619 path_converter(). */
13620 _Py_IDENTIFIER(__fspath__);
13621 PyObject *func = NULL;
13622 PyObject *path_repr = NULL;
13623
13624 if (PyUnicode_Check(path) || PyBytes_Check(path)) {
13625 Py_INCREF(path);
13626 return path;
13627 }
13628
13629 func = _PyObject_LookupSpecial(path, &PyId___fspath__);
13630 if (NULL == func) {
13631 return PyErr_Format(PyExc_TypeError,
13632 "expected str, bytes or os.PathLike object, "
13633 "not %.200s",
13634 Py_TYPE(path)->tp_name);
13635 }
13636
13637 path_repr = _PyObject_CallNoArg(func);
13638 Py_DECREF(func);
13639 if (NULL == path_repr) {
13640 return NULL;
13641 }
13642
13643 if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
13644 PyErr_Format(PyExc_TypeError,
13645 "expected %.200s.__fspath__() to return str or bytes, "
13646 "not %.200s", Py_TYPE(path)->tp_name,
13647 Py_TYPE(path_repr)->tp_name);
13648 Py_DECREF(path_repr);
13649 return NULL;
13650 }
13651
13652 return path_repr;
13653 }
13654
13655 /*[clinic input]
13656 os.fspath
13657
13658 path: object
13659
13660 Return the file system path representation of the object.
13661
13662 If the object is str or bytes, then allow it to pass through as-is. If the
13663 object defines __fspath__(), then return the result of that method. All other
13664 types raise a TypeError.
13665 [clinic start generated code]*/
13666
13667 static PyObject *
os_fspath_impl(PyObject * module,PyObject * path)13668 os_fspath_impl(PyObject *module, PyObject *path)
13669 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
13670 {
13671 return PyOS_FSPath(path);
13672 }
13673
13674 #ifdef HAVE_GETRANDOM_SYSCALL
13675 /*[clinic input]
13676 os.getrandom
13677
13678 size: Py_ssize_t
13679 flags: int=0
13680
13681 Obtain a series of random bytes.
13682 [clinic start generated code]*/
13683
13684 static PyObject *
os_getrandom_impl(PyObject * module,Py_ssize_t size,int flags)13685 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
13686 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
13687 {
13688 PyObject *bytes;
13689 Py_ssize_t n;
13690
13691 if (size < 0) {
13692 errno = EINVAL;
13693 return posix_error();
13694 }
13695
13696 bytes = PyBytes_FromStringAndSize(NULL, size);
13697 if (bytes == NULL) {
13698 PyErr_NoMemory();
13699 return NULL;
13700 }
13701
13702 while (1) {
13703 n = syscall(SYS_getrandom,
13704 PyBytes_AS_STRING(bytes),
13705 PyBytes_GET_SIZE(bytes),
13706 flags);
13707 if (n < 0 && errno == EINTR) {
13708 if (PyErr_CheckSignals() < 0) {
13709 goto error;
13710 }
13711
13712 /* getrandom() was interrupted by a signal: retry */
13713 continue;
13714 }
13715 break;
13716 }
13717
13718 if (n < 0) {
13719 PyErr_SetFromErrno(PyExc_OSError);
13720 goto error;
13721 }
13722
13723 if (n != size) {
13724 _PyBytes_Resize(&bytes, n);
13725 }
13726
13727 return bytes;
13728
13729 error:
13730 Py_DECREF(bytes);
13731 return NULL;
13732 }
13733 #endif /* HAVE_GETRANDOM_SYSCALL */
13734
13735 #ifdef MS_WINDOWS
13736 /* bpo-36085: Helper functions for managing DLL search directories
13737 * on win32
13738 */
13739
13740 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
13741 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
13742
13743 /*[clinic input]
13744 os._add_dll_directory
13745
13746 path: path_t
13747
13748 Add a path to the DLL search path.
13749
13750 This search path is used when resolving dependencies for imported
13751 extension modules (the module itself is resolved through sys.path),
13752 and also by ctypes.
13753
13754 Returns an opaque value that may be passed to os.remove_dll_directory
13755 to remove this directory from the search path.
13756 [clinic start generated code]*/
13757
13758 static PyObject *
os__add_dll_directory_impl(PyObject * module,path_t * path)13759 os__add_dll_directory_impl(PyObject *module, path_t *path)
13760 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
13761 {
13762 HMODULE hKernel32;
13763 PAddDllDirectory AddDllDirectory;
13764 DLL_DIRECTORY_COOKIE cookie = 0;
13765 DWORD err = 0;
13766
13767 if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
13768 return NULL;
13769 }
13770
13771 /* For Windows 7, we have to load this. As this will be a fairly
13772 infrequent operation, just do it each time. Kernel32 is always
13773 loaded. */
13774 Py_BEGIN_ALLOW_THREADS
13775 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
13776 !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
13777 hKernel32, "AddDllDirectory")) ||
13778 !(cookie = (*AddDllDirectory)(path->wide))) {
13779 err = GetLastError();
13780 }
13781 Py_END_ALLOW_THREADS
13782
13783 if (err) {
13784 return win32_error_object_err("add_dll_directory",
13785 path->object, err);
13786 }
13787
13788 return PyCapsule_New(cookie, "DLL directory cookie", NULL);
13789 }
13790
13791 /*[clinic input]
13792 os._remove_dll_directory
13793
13794 cookie: object
13795
13796 Removes a path from the DLL search path.
13797
13798 The parameter is an opaque value that was returned from
13799 os.add_dll_directory. You can only remove directories that you added
13800 yourself.
13801 [clinic start generated code]*/
13802
13803 static PyObject *
os__remove_dll_directory_impl(PyObject * module,PyObject * cookie)13804 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
13805 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
13806 {
13807 HMODULE hKernel32;
13808 PRemoveDllDirectory RemoveDllDirectory;
13809 DLL_DIRECTORY_COOKIE cookieValue;
13810 DWORD err = 0;
13811
13812 if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
13813 PyErr_SetString(PyExc_TypeError,
13814 "Provided cookie was not returned from os.add_dll_directory");
13815 return NULL;
13816 }
13817
13818 cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
13819 cookie, "DLL directory cookie");
13820
13821 /* For Windows 7, we have to load this. As this will be a fairly
13822 infrequent operation, just do it each time. Kernel32 is always
13823 loaded. */
13824 Py_BEGIN_ALLOW_THREADS
13825 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
13826 !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
13827 hKernel32, "RemoveDllDirectory")) ||
13828 !(*RemoveDllDirectory)(cookieValue)) {
13829 err = GetLastError();
13830 }
13831 Py_END_ALLOW_THREADS
13832
13833 if (err) {
13834 return win32_error_object_err("remove_dll_directory",
13835 NULL, err);
13836 }
13837
13838 if (PyCapsule_SetName(cookie, NULL)) {
13839 return NULL;
13840 }
13841
13842 Py_RETURN_NONE;
13843 }
13844
13845 #endif
13846
13847 static PyMethodDef posix_methods[] = {
13848
13849 OS_STAT_METHODDEF
13850 OS_ACCESS_METHODDEF
13851 OS_TTYNAME_METHODDEF
13852 OS_CHDIR_METHODDEF
13853 OS_CHFLAGS_METHODDEF
13854 OS_CHMOD_METHODDEF
13855 OS_FCHMOD_METHODDEF
13856 OS_LCHMOD_METHODDEF
13857 OS_CHOWN_METHODDEF
13858 OS_FCHOWN_METHODDEF
13859 OS_LCHOWN_METHODDEF
13860 OS_LCHFLAGS_METHODDEF
13861 OS_CHROOT_METHODDEF
13862 OS_CTERMID_METHODDEF
13863 OS_GETCWD_METHODDEF
13864 OS_GETCWDB_METHODDEF
13865 OS_LINK_METHODDEF
13866 OS_LISTDIR_METHODDEF
13867 OS_LSTAT_METHODDEF
13868 OS_MKDIR_METHODDEF
13869 OS_NICE_METHODDEF
13870 OS_GETPRIORITY_METHODDEF
13871 OS_SETPRIORITY_METHODDEF
13872 OS_POSIX_SPAWN_METHODDEF
13873 OS_POSIX_SPAWNP_METHODDEF
13874 OS_READLINK_METHODDEF
13875 OS_COPY_FILE_RANGE_METHODDEF
13876 OS_RENAME_METHODDEF
13877 OS_REPLACE_METHODDEF
13878 OS_RMDIR_METHODDEF
13879 OS_SYMLINK_METHODDEF
13880 OS_SYSTEM_METHODDEF
13881 OS_UMASK_METHODDEF
13882 OS_UNAME_METHODDEF
13883 OS_UNLINK_METHODDEF
13884 OS_REMOVE_METHODDEF
13885 OS_UTIME_METHODDEF
13886 OS_TIMES_METHODDEF
13887 OS__EXIT_METHODDEF
13888 OS__FCOPYFILE_METHODDEF
13889 OS_EXECV_METHODDEF
13890 OS_EXECVE_METHODDEF
13891 OS_SPAWNV_METHODDEF
13892 OS_SPAWNVE_METHODDEF
13893 OS_FORK1_METHODDEF
13894 OS_FORK_METHODDEF
13895 OS_REGISTER_AT_FORK_METHODDEF
13896 OS_SCHED_GET_PRIORITY_MAX_METHODDEF
13897 OS_SCHED_GET_PRIORITY_MIN_METHODDEF
13898 OS_SCHED_GETPARAM_METHODDEF
13899 OS_SCHED_GETSCHEDULER_METHODDEF
13900 OS_SCHED_RR_GET_INTERVAL_METHODDEF
13901 OS_SCHED_SETPARAM_METHODDEF
13902 OS_SCHED_SETSCHEDULER_METHODDEF
13903 OS_SCHED_YIELD_METHODDEF
13904 OS_SCHED_SETAFFINITY_METHODDEF
13905 OS_SCHED_GETAFFINITY_METHODDEF
13906 OS_OPENPTY_METHODDEF
13907 OS_FORKPTY_METHODDEF
13908 OS_GETEGID_METHODDEF
13909 OS_GETEUID_METHODDEF
13910 OS_GETGID_METHODDEF
13911 #ifdef HAVE_GETGROUPLIST
13912 {"getgrouplist", posix_getgrouplist, METH_VARARGS, posix_getgrouplist__doc__},
13913 #endif
13914 OS_GETGROUPS_METHODDEF
13915 OS_GETPID_METHODDEF
13916 OS_GETPGRP_METHODDEF
13917 OS_GETPPID_METHODDEF
13918 OS_GETUID_METHODDEF
13919 OS_GETLOGIN_METHODDEF
13920 OS_KILL_METHODDEF
13921 OS_KILLPG_METHODDEF
13922 OS_PLOCK_METHODDEF
13923 #ifdef MS_WINDOWS
13924 OS_STARTFILE_METHODDEF
13925 #endif
13926 OS_SETUID_METHODDEF
13927 OS_SETEUID_METHODDEF
13928 OS_SETREUID_METHODDEF
13929 OS_SETGID_METHODDEF
13930 OS_SETEGID_METHODDEF
13931 OS_SETREGID_METHODDEF
13932 OS_SETGROUPS_METHODDEF
13933 #ifdef HAVE_INITGROUPS
13934 {"initgroups", posix_initgroups, METH_VARARGS, posix_initgroups__doc__},
13935 #endif /* HAVE_INITGROUPS */
13936 OS_GETPGID_METHODDEF
13937 OS_SETPGRP_METHODDEF
13938 OS_WAIT_METHODDEF
13939 OS_WAIT3_METHODDEF
13940 OS_WAIT4_METHODDEF
13941 OS_WAITID_METHODDEF
13942 OS_WAITPID_METHODDEF
13943 OS_GETSID_METHODDEF
13944 OS_SETSID_METHODDEF
13945 OS_SETPGID_METHODDEF
13946 OS_TCGETPGRP_METHODDEF
13947 OS_TCSETPGRP_METHODDEF
13948 OS_OPEN_METHODDEF
13949 OS_CLOSE_METHODDEF
13950 OS_CLOSERANGE_METHODDEF
13951 OS_DEVICE_ENCODING_METHODDEF
13952 OS_DUP_METHODDEF
13953 OS_DUP2_METHODDEF
13954 OS_LOCKF_METHODDEF
13955 OS_LSEEK_METHODDEF
13956 OS_READ_METHODDEF
13957 OS_READV_METHODDEF
13958 OS_PREAD_METHODDEF
13959 OS_PREADV_METHODDEF
13960 OS_WRITE_METHODDEF
13961 OS_WRITEV_METHODDEF
13962 OS_PWRITE_METHODDEF
13963 OS_PWRITEV_METHODDEF
13964 #ifdef HAVE_SENDFILE
13965 {"sendfile", (PyCFunction)(void(*)(void))posix_sendfile, METH_VARARGS | METH_KEYWORDS,
13966 posix_sendfile__doc__},
13967 #endif
13968 OS_FSTAT_METHODDEF
13969 OS_ISATTY_METHODDEF
13970 OS_PIPE_METHODDEF
13971 OS_PIPE2_METHODDEF
13972 OS_MKFIFO_METHODDEF
13973 OS_MKNOD_METHODDEF
13974 OS_MAJOR_METHODDEF
13975 OS_MINOR_METHODDEF
13976 OS_MAKEDEV_METHODDEF
13977 OS_FTRUNCATE_METHODDEF
13978 OS_TRUNCATE_METHODDEF
13979 OS_POSIX_FALLOCATE_METHODDEF
13980 OS_POSIX_FADVISE_METHODDEF
13981 OS_PUTENV_METHODDEF
13982 OS_UNSETENV_METHODDEF
13983 OS_STRERROR_METHODDEF
13984 OS_FCHDIR_METHODDEF
13985 OS_FSYNC_METHODDEF
13986 OS_SYNC_METHODDEF
13987 OS_FDATASYNC_METHODDEF
13988 OS_WCOREDUMP_METHODDEF
13989 OS_WIFCONTINUED_METHODDEF
13990 OS_WIFSTOPPED_METHODDEF
13991 OS_WIFSIGNALED_METHODDEF
13992 OS_WIFEXITED_METHODDEF
13993 OS_WEXITSTATUS_METHODDEF
13994 OS_WTERMSIG_METHODDEF
13995 OS_WSTOPSIG_METHODDEF
13996 OS_FSTATVFS_METHODDEF
13997 OS_STATVFS_METHODDEF
13998 OS_CONFSTR_METHODDEF
13999 OS_SYSCONF_METHODDEF
14000 OS_FPATHCONF_METHODDEF
14001 OS_PATHCONF_METHODDEF
14002 OS_ABORT_METHODDEF
14003 OS__GETFULLPATHNAME_METHODDEF
14004 OS__GETDISKUSAGE_METHODDEF
14005 OS__GETFINALPATHNAME_METHODDEF
14006 OS__GETVOLUMEPATHNAME_METHODDEF
14007 OS__PATH_SPLITROOT_METHODDEF
14008 OS_GETLOADAVG_METHODDEF
14009 OS_URANDOM_METHODDEF
14010 OS_SETRESUID_METHODDEF
14011 OS_SETRESGID_METHODDEF
14012 OS_GETRESUID_METHODDEF
14013 OS_GETRESGID_METHODDEF
14014
14015 OS_GETXATTR_METHODDEF
14016 OS_SETXATTR_METHODDEF
14017 OS_REMOVEXATTR_METHODDEF
14018 OS_LISTXATTR_METHODDEF
14019
14020 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
14021 {"get_terminal_size", get_terminal_size, METH_VARARGS, termsize__doc__},
14022 #endif
14023 OS_CPU_COUNT_METHODDEF
14024 OS_GET_INHERITABLE_METHODDEF
14025 OS_SET_INHERITABLE_METHODDEF
14026 OS_GET_HANDLE_INHERITABLE_METHODDEF
14027 OS_SET_HANDLE_INHERITABLE_METHODDEF
14028 #ifndef MS_WINDOWS
14029 OS_GET_BLOCKING_METHODDEF
14030 OS_SET_BLOCKING_METHODDEF
14031 #endif
14032 OS_SCANDIR_METHODDEF
14033 OS_FSPATH_METHODDEF
14034 OS_GETRANDOM_METHODDEF
14035 OS_MEMFD_CREATE_METHODDEF
14036 #ifdef MS_WINDOWS
14037 OS__ADD_DLL_DIRECTORY_METHODDEF
14038 OS__REMOVE_DLL_DIRECTORY_METHODDEF
14039 #endif
14040 {NULL, NULL} /* Sentinel */
14041 };
14042
14043 static int
all_ins(PyObject * m)14044 all_ins(PyObject *m)
14045 {
14046 #ifdef F_OK
14047 if (PyModule_AddIntMacro(m, F_OK)) return -1;
14048 #endif
14049 #ifdef R_OK
14050 if (PyModule_AddIntMacro(m, R_OK)) return -1;
14051 #endif
14052 #ifdef W_OK
14053 if (PyModule_AddIntMacro(m, W_OK)) return -1;
14054 #endif
14055 #ifdef X_OK
14056 if (PyModule_AddIntMacro(m, X_OK)) return -1;
14057 #endif
14058 #ifdef NGROUPS_MAX
14059 if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
14060 #endif
14061 #ifdef TMP_MAX
14062 if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
14063 #endif
14064 #ifdef WCONTINUED
14065 if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
14066 #endif
14067 #ifdef WNOHANG
14068 if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
14069 #endif
14070 #ifdef WUNTRACED
14071 if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
14072 #endif
14073 #ifdef O_RDONLY
14074 if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
14075 #endif
14076 #ifdef O_WRONLY
14077 if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
14078 #endif
14079 #ifdef O_RDWR
14080 if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
14081 #endif
14082 #ifdef O_NDELAY
14083 if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
14084 #endif
14085 #ifdef O_NONBLOCK
14086 if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
14087 #endif
14088 #ifdef O_APPEND
14089 if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
14090 #endif
14091 #ifdef O_DSYNC
14092 if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
14093 #endif
14094 #ifdef O_RSYNC
14095 if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
14096 #endif
14097 #ifdef O_SYNC
14098 if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
14099 #endif
14100 #ifdef O_NOCTTY
14101 if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
14102 #endif
14103 #ifdef O_CREAT
14104 if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
14105 #endif
14106 #ifdef O_EXCL
14107 if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
14108 #endif
14109 #ifdef O_TRUNC
14110 if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
14111 #endif
14112 #ifdef O_BINARY
14113 if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
14114 #endif
14115 #ifdef O_TEXT
14116 if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
14117 #endif
14118 #ifdef O_XATTR
14119 if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
14120 #endif
14121 #ifdef O_LARGEFILE
14122 if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
14123 #endif
14124 #ifndef __GNU__
14125 #ifdef O_SHLOCK
14126 if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
14127 #endif
14128 #ifdef O_EXLOCK
14129 if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
14130 #endif
14131 #endif
14132 #ifdef O_EXEC
14133 if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
14134 #endif
14135 #ifdef O_SEARCH
14136 if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
14137 #endif
14138 #ifdef O_PATH
14139 if (PyModule_AddIntMacro(m, O_PATH)) return -1;
14140 #endif
14141 #ifdef O_TTY_INIT
14142 if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
14143 #endif
14144 #ifdef O_TMPFILE
14145 if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
14146 #endif
14147 #ifdef PRIO_PROCESS
14148 if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
14149 #endif
14150 #ifdef PRIO_PGRP
14151 if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
14152 #endif
14153 #ifdef PRIO_USER
14154 if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
14155 #endif
14156 #ifdef O_CLOEXEC
14157 if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
14158 #endif
14159 #ifdef O_ACCMODE
14160 if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
14161 #endif
14162
14163
14164 #ifdef SEEK_HOLE
14165 if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
14166 #endif
14167 #ifdef SEEK_DATA
14168 if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
14169 #endif
14170
14171 /* MS Windows */
14172 #ifdef O_NOINHERIT
14173 /* Don't inherit in child processes. */
14174 if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
14175 #endif
14176 #ifdef _O_SHORT_LIVED
14177 /* Optimize for short life (keep in memory). */
14178 /* MS forgot to define this one with a non-underscore form too. */
14179 if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
14180 #endif
14181 #ifdef O_TEMPORARY
14182 /* Automatically delete when last handle is closed. */
14183 if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
14184 #endif
14185 #ifdef O_RANDOM
14186 /* Optimize for random access. */
14187 if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
14188 #endif
14189 #ifdef O_SEQUENTIAL
14190 /* Optimize for sequential access. */
14191 if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
14192 #endif
14193
14194 /* GNU extensions. */
14195 #ifdef O_ASYNC
14196 /* Send a SIGIO signal whenever input or output
14197 becomes available on file descriptor */
14198 if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
14199 #endif
14200 #ifdef O_DIRECT
14201 /* Direct disk access. */
14202 if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
14203 #endif
14204 #ifdef O_DIRECTORY
14205 /* Must be a directory. */
14206 if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
14207 #endif
14208 #ifdef O_NOFOLLOW
14209 /* Do not follow links. */
14210 if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
14211 #endif
14212 #ifdef O_NOLINKS
14213 /* Fails if link count of the named file is greater than 1 */
14214 if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
14215 #endif
14216 #ifdef O_NOATIME
14217 /* Do not update the access time. */
14218 if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
14219 #endif
14220
14221 /* These come from sysexits.h */
14222 #ifdef EX_OK
14223 if (PyModule_AddIntMacro(m, EX_OK)) return -1;
14224 #endif /* EX_OK */
14225 #ifdef EX_USAGE
14226 if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
14227 #endif /* EX_USAGE */
14228 #ifdef EX_DATAERR
14229 if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
14230 #endif /* EX_DATAERR */
14231 #ifdef EX_NOINPUT
14232 if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
14233 #endif /* EX_NOINPUT */
14234 #ifdef EX_NOUSER
14235 if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
14236 #endif /* EX_NOUSER */
14237 #ifdef EX_NOHOST
14238 if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
14239 #endif /* EX_NOHOST */
14240 #ifdef EX_UNAVAILABLE
14241 if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
14242 #endif /* EX_UNAVAILABLE */
14243 #ifdef EX_SOFTWARE
14244 if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
14245 #endif /* EX_SOFTWARE */
14246 #ifdef EX_OSERR
14247 if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
14248 #endif /* EX_OSERR */
14249 #ifdef EX_OSFILE
14250 if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
14251 #endif /* EX_OSFILE */
14252 #ifdef EX_CANTCREAT
14253 if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
14254 #endif /* EX_CANTCREAT */
14255 #ifdef EX_IOERR
14256 if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
14257 #endif /* EX_IOERR */
14258 #ifdef EX_TEMPFAIL
14259 if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
14260 #endif /* EX_TEMPFAIL */
14261 #ifdef EX_PROTOCOL
14262 if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
14263 #endif /* EX_PROTOCOL */
14264 #ifdef EX_NOPERM
14265 if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
14266 #endif /* EX_NOPERM */
14267 #ifdef EX_CONFIG
14268 if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
14269 #endif /* EX_CONFIG */
14270 #ifdef EX_NOTFOUND
14271 if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
14272 #endif /* EX_NOTFOUND */
14273
14274 /* statvfs */
14275 #ifdef ST_RDONLY
14276 if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
14277 #endif /* ST_RDONLY */
14278 #ifdef ST_NOSUID
14279 if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
14280 #endif /* ST_NOSUID */
14281
14282 /* GNU extensions */
14283 #ifdef ST_NODEV
14284 if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
14285 #endif /* ST_NODEV */
14286 #ifdef ST_NOEXEC
14287 if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
14288 #endif /* ST_NOEXEC */
14289 #ifdef ST_SYNCHRONOUS
14290 if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
14291 #endif /* ST_SYNCHRONOUS */
14292 #ifdef ST_MANDLOCK
14293 if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
14294 #endif /* ST_MANDLOCK */
14295 #ifdef ST_WRITE
14296 if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
14297 #endif /* ST_WRITE */
14298 #ifdef ST_APPEND
14299 if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
14300 #endif /* ST_APPEND */
14301 #ifdef ST_NOATIME
14302 if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
14303 #endif /* ST_NOATIME */
14304 #ifdef ST_NODIRATIME
14305 if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
14306 #endif /* ST_NODIRATIME */
14307 #ifdef ST_RELATIME
14308 if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
14309 #endif /* ST_RELATIME */
14310
14311 /* FreeBSD sendfile() constants */
14312 #ifdef SF_NODISKIO
14313 if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
14314 #endif
14315 #ifdef SF_MNOWAIT
14316 if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
14317 #endif
14318 #ifdef SF_SYNC
14319 if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
14320 #endif
14321
14322 /* constants for posix_fadvise */
14323 #ifdef POSIX_FADV_NORMAL
14324 if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
14325 #endif
14326 #ifdef POSIX_FADV_SEQUENTIAL
14327 if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
14328 #endif
14329 #ifdef POSIX_FADV_RANDOM
14330 if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
14331 #endif
14332 #ifdef POSIX_FADV_NOREUSE
14333 if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
14334 #endif
14335 #ifdef POSIX_FADV_WILLNEED
14336 if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
14337 #endif
14338 #ifdef POSIX_FADV_DONTNEED
14339 if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
14340 #endif
14341
14342 /* constants for waitid */
14343 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
14344 if (PyModule_AddIntMacro(m, P_PID)) return -1;
14345 if (PyModule_AddIntMacro(m, P_PGID)) return -1;
14346 if (PyModule_AddIntMacro(m, P_ALL)) return -1;
14347 #endif
14348 #ifdef WEXITED
14349 if (PyModule_AddIntMacro(m, WEXITED)) return -1;
14350 #endif
14351 #ifdef WNOWAIT
14352 if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
14353 #endif
14354 #ifdef WSTOPPED
14355 if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
14356 #endif
14357 #ifdef CLD_EXITED
14358 if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
14359 #endif
14360 #ifdef CLD_DUMPED
14361 if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
14362 #endif
14363 #ifdef CLD_TRAPPED
14364 if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
14365 #endif
14366 #ifdef CLD_CONTINUED
14367 if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
14368 #endif
14369
14370 /* constants for lockf */
14371 #ifdef F_LOCK
14372 if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
14373 #endif
14374 #ifdef F_TLOCK
14375 if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
14376 #endif
14377 #ifdef F_ULOCK
14378 if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
14379 #endif
14380 #ifdef F_TEST
14381 if (PyModule_AddIntMacro(m, F_TEST)) return -1;
14382 #endif
14383
14384 #ifdef RWF_DSYNC
14385 if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
14386 #endif
14387 #ifdef RWF_HIPRI
14388 if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
14389 #endif
14390 #ifdef RWF_SYNC
14391 if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
14392 #endif
14393 #ifdef RWF_NOWAIT
14394 if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
14395 #endif
14396
14397 /* constants for posix_spawn */
14398 #ifdef HAVE_POSIX_SPAWN
14399 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
14400 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
14401 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
14402 #endif
14403
14404 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
14405 if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
14406 if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
14407 if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
14408 #endif
14409 #ifdef HAVE_SPAWNV
14410 if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
14411 if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
14412 #endif
14413
14414 #ifdef HAVE_SCHED_H
14415 #ifdef SCHED_OTHER
14416 if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
14417 #endif
14418 #ifdef SCHED_FIFO
14419 if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
14420 #endif
14421 #ifdef SCHED_RR
14422 if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
14423 #endif
14424 #ifdef SCHED_SPORADIC
14425 if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
14426 #endif
14427 #ifdef SCHED_BATCH
14428 if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
14429 #endif
14430 #ifdef SCHED_IDLE
14431 if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
14432 #endif
14433 #ifdef SCHED_RESET_ON_FORK
14434 if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
14435 #endif
14436 #ifdef SCHED_SYS
14437 if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
14438 #endif
14439 #ifdef SCHED_IA
14440 if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
14441 #endif
14442 #ifdef SCHED_FSS
14443 if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
14444 #endif
14445 #ifdef SCHED_FX
14446 if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
14447 #endif
14448 #endif
14449
14450 #ifdef USE_XATTRS
14451 if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
14452 if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
14453 if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
14454 #endif
14455
14456 #if HAVE_DECL_RTLD_LAZY
14457 if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
14458 #endif
14459 #if HAVE_DECL_RTLD_NOW
14460 if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
14461 #endif
14462 #if HAVE_DECL_RTLD_GLOBAL
14463 if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
14464 #endif
14465 #if HAVE_DECL_RTLD_LOCAL
14466 if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
14467 #endif
14468 #if HAVE_DECL_RTLD_NODELETE
14469 if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
14470 #endif
14471 #if HAVE_DECL_RTLD_NOLOAD
14472 if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
14473 #endif
14474 #if HAVE_DECL_RTLD_DEEPBIND
14475 if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
14476 #endif
14477 #if HAVE_DECL_RTLD_MEMBER
14478 if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
14479 #endif
14480
14481 #ifdef HAVE_GETRANDOM_SYSCALL
14482 if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
14483 if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
14484 #endif
14485 #ifdef HAVE_MEMFD_CREATE
14486 if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
14487 if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
14488 #ifdef MFD_HUGETLB
14489 if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
14490 #endif
14491 #ifdef MFD_HUGE_SHIFT
14492 if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
14493 #endif
14494 #ifdef MFD_HUGE_MASK
14495 if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
14496 #endif
14497 #ifdef MFD_HUGE_64KB
14498 if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
14499 #endif
14500 #ifdef MFD_HUGE_512KB
14501 if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
14502 #endif
14503 #ifdef MFD_HUGE_1MB
14504 if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
14505 #endif
14506 #ifdef MFD_HUGE_2MB
14507 if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
14508 #endif
14509 #ifdef MFD_HUGE_8MB
14510 if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
14511 #endif
14512 #ifdef MFD_HUGE_16MB
14513 if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
14514 #endif
14515 #ifdef MFD_HUGE_32MB
14516 if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
14517 #endif
14518 #ifdef MFD_HUGE_256MB
14519 if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
14520 #endif
14521 #ifdef MFD_HUGE_512MB
14522 if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
14523 #endif
14524 #ifdef MFD_HUGE_1GB
14525 if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
14526 #endif
14527 #ifdef MFD_HUGE_2GB
14528 if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
14529 #endif
14530 #ifdef MFD_HUGE_16GB
14531 if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
14532 #endif
14533 #endif
14534
14535 #if defined(__APPLE__)
14536 if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
14537 #endif
14538
14539 #ifdef MS_WINDOWS
14540 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
14541 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
14542 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
14543 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
14544 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
14545 #endif
14546
14547 return 0;
14548 }
14549
14550
14551 static struct PyModuleDef posixmodule = {
14552 PyModuleDef_HEAD_INIT,
14553 MODNAME,
14554 posix__doc__,
14555 -1,
14556 posix_methods,
14557 NULL,
14558 NULL,
14559 NULL,
14560 NULL
14561 };
14562
14563
14564 static const char * const have_functions[] = {
14565
14566 #ifdef HAVE_FACCESSAT
14567 "HAVE_FACCESSAT",
14568 #endif
14569
14570 #ifdef HAVE_FCHDIR
14571 "HAVE_FCHDIR",
14572 #endif
14573
14574 #ifdef HAVE_FCHMOD
14575 "HAVE_FCHMOD",
14576 #endif
14577
14578 #ifdef HAVE_FCHMODAT
14579 "HAVE_FCHMODAT",
14580 #endif
14581
14582 #ifdef HAVE_FCHOWN
14583 "HAVE_FCHOWN",
14584 #endif
14585
14586 #ifdef HAVE_FCHOWNAT
14587 "HAVE_FCHOWNAT",
14588 #endif
14589
14590 #ifdef HAVE_FEXECVE
14591 "HAVE_FEXECVE",
14592 #endif
14593
14594 #ifdef HAVE_FDOPENDIR
14595 "HAVE_FDOPENDIR",
14596 #endif
14597
14598 #ifdef HAVE_FPATHCONF
14599 "HAVE_FPATHCONF",
14600 #endif
14601
14602 #ifdef HAVE_FSTATAT
14603 "HAVE_FSTATAT",
14604 #endif
14605
14606 #ifdef HAVE_FSTATVFS
14607 "HAVE_FSTATVFS",
14608 #endif
14609
14610 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
14611 "HAVE_FTRUNCATE",
14612 #endif
14613
14614 #ifdef HAVE_FUTIMENS
14615 "HAVE_FUTIMENS",
14616 #endif
14617
14618 #ifdef HAVE_FUTIMES
14619 "HAVE_FUTIMES",
14620 #endif
14621
14622 #ifdef HAVE_FUTIMESAT
14623 "HAVE_FUTIMESAT",
14624 #endif
14625
14626 #ifdef HAVE_LINKAT
14627 "HAVE_LINKAT",
14628 #endif
14629
14630 #ifdef HAVE_LCHFLAGS
14631 "HAVE_LCHFLAGS",
14632 #endif
14633
14634 #ifdef HAVE_LCHMOD
14635 "HAVE_LCHMOD",
14636 #endif
14637
14638 #ifdef HAVE_LCHOWN
14639 "HAVE_LCHOWN",
14640 #endif
14641
14642 #ifdef HAVE_LSTAT
14643 "HAVE_LSTAT",
14644 #endif
14645
14646 #ifdef HAVE_LUTIMES
14647 "HAVE_LUTIMES",
14648 #endif
14649
14650 #ifdef HAVE_MEMFD_CREATE
14651 "HAVE_MEMFD_CREATE",
14652 #endif
14653
14654 #ifdef HAVE_MKDIRAT
14655 "HAVE_MKDIRAT",
14656 #endif
14657
14658 #ifdef HAVE_MKFIFOAT
14659 "HAVE_MKFIFOAT",
14660 #endif
14661
14662 #ifdef HAVE_MKNODAT
14663 "HAVE_MKNODAT",
14664 #endif
14665
14666 #ifdef HAVE_OPENAT
14667 "HAVE_OPENAT",
14668 #endif
14669
14670 #ifdef HAVE_READLINKAT
14671 "HAVE_READLINKAT",
14672 #endif
14673
14674 #ifdef HAVE_RENAMEAT
14675 "HAVE_RENAMEAT",
14676 #endif
14677
14678 #ifdef HAVE_SYMLINKAT
14679 "HAVE_SYMLINKAT",
14680 #endif
14681
14682 #ifdef HAVE_UNLINKAT
14683 "HAVE_UNLINKAT",
14684 #endif
14685
14686 #ifdef HAVE_UTIMENSAT
14687 "HAVE_UTIMENSAT",
14688 #endif
14689
14690 #ifdef MS_WINDOWS
14691 "MS_WINDOWS",
14692 #endif
14693
14694 NULL
14695 };
14696
14697
14698 PyMODINIT_FUNC
INITFUNC(void)14699 INITFUNC(void)
14700 {
14701 PyObject *m, *v;
14702 PyObject *list;
14703 const char * const *trace;
14704
14705 m = PyModule_Create(&posixmodule);
14706 if (m == NULL)
14707 return NULL;
14708
14709 /* Initialize environ dictionary */
14710 v = convertenviron();
14711 Py_XINCREF(v);
14712 if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
14713 return NULL;
14714 Py_DECREF(v);
14715
14716 if (all_ins(m))
14717 return NULL;
14718
14719 if (setup_confname_tables(m))
14720 return NULL;
14721
14722 Py_INCREF(PyExc_OSError);
14723 PyModule_AddObject(m, "error", PyExc_OSError);
14724
14725 #ifdef HAVE_PUTENV
14726 if (posix_putenv_garbage == NULL)
14727 posix_putenv_garbage = PyDict_New();
14728 #endif
14729
14730 if (!initialized) {
14731 #if defined(HAVE_WAITID) && !defined(__APPLE__)
14732 waitid_result_desc.name = MODNAME ".waitid_result";
14733 WaitidResultType = PyStructSequence_NewType(&waitid_result_desc);
14734 if (WaitidResultType == NULL) {
14735 return NULL;
14736 }
14737 #endif
14738
14739 stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
14740 stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
14741 stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
14742 stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
14743 StatResultType = PyStructSequence_NewType(&stat_result_desc);
14744 if (StatResultType == NULL) {
14745 return NULL;
14746 }
14747 structseq_new = StatResultType->tp_new;
14748 StatResultType->tp_new = statresult_new;
14749
14750 statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
14751 StatVFSResultType = PyStructSequence_NewType(&statvfs_result_desc);
14752 if (StatVFSResultType == NULL) {
14753 return NULL;
14754 }
14755 #ifdef NEED_TICKS_PER_SECOND
14756 # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
14757 ticks_per_second = sysconf(_SC_CLK_TCK);
14758 # elif defined(HZ)
14759 ticks_per_second = HZ;
14760 # else
14761 ticks_per_second = 60; /* magic fallback value; may be bogus */
14762 # endif
14763 #endif
14764
14765 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
14766 sched_param_desc.name = MODNAME ".sched_param";
14767 SchedParamType = PyStructSequence_NewType(&sched_param_desc);
14768 if (SchedParamType == NULL) {
14769 return NULL;
14770 }
14771 SchedParamType->tp_new = os_sched_param;
14772 #endif
14773
14774 /* initialize TerminalSize_info */
14775 TerminalSizeType = PyStructSequence_NewType(&TerminalSize_desc);
14776 if (TerminalSizeType == NULL) {
14777 return NULL;
14778 }
14779
14780 /* initialize scandir types */
14781 if (PyType_Ready(&ScandirIteratorType) < 0)
14782 return NULL;
14783 if (PyType_Ready(&DirEntryType) < 0)
14784 return NULL;
14785 }
14786 #if defined(HAVE_WAITID) && !defined(__APPLE__)
14787 Py_INCREF((PyObject*) WaitidResultType);
14788 PyModule_AddObject(m, "waitid_result", (PyObject*) WaitidResultType);
14789 #endif
14790 Py_INCREF((PyObject*) StatResultType);
14791 PyModule_AddObject(m, "stat_result", (PyObject*) StatResultType);
14792 Py_INCREF((PyObject*) StatVFSResultType);
14793 PyModule_AddObject(m, "statvfs_result",
14794 (PyObject*) StatVFSResultType);
14795
14796 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
14797 Py_INCREF(SchedParamType);
14798 PyModule_AddObject(m, "sched_param", (PyObject *)SchedParamType);
14799 #endif
14800
14801 times_result_desc.name = MODNAME ".times_result";
14802 TimesResultType = PyStructSequence_NewType(×_result_desc);
14803 if (TimesResultType == NULL) {
14804 return NULL;
14805 }
14806 PyModule_AddObject(m, "times_result", (PyObject *)TimesResultType);
14807
14808 uname_result_desc.name = MODNAME ".uname_result";
14809 UnameResultType = PyStructSequence_NewType(&uname_result_desc);
14810 if (UnameResultType == NULL) {
14811 return NULL;
14812 }
14813 PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
14814
14815 #ifdef __APPLE__
14816 /*
14817 * Step 2 of weak-linking support on Mac OS X.
14818 *
14819 * The code below removes functions that are not available on the
14820 * currently active platform.
14821 *
14822 * This block allow one to use a python binary that was build on
14823 * OSX 10.4 on OSX 10.3, without losing access to new APIs on
14824 * OSX 10.4.
14825 */
14826 #ifdef HAVE_FSTATVFS
14827 if (fstatvfs == NULL) {
14828 if (PyObject_DelAttrString(m, "fstatvfs") == -1) {
14829 return NULL;
14830 }
14831 }
14832 #endif /* HAVE_FSTATVFS */
14833
14834 #ifdef HAVE_STATVFS
14835 if (statvfs == NULL) {
14836 if (PyObject_DelAttrString(m, "statvfs") == -1) {
14837 return NULL;
14838 }
14839 }
14840 #endif /* HAVE_STATVFS */
14841
14842 # ifdef HAVE_LCHOWN
14843 if (lchown == NULL) {
14844 if (PyObject_DelAttrString(m, "lchown") == -1) {
14845 return NULL;
14846 }
14847 }
14848 #endif /* HAVE_LCHOWN */
14849
14850
14851 #endif /* __APPLE__ */
14852
14853 Py_INCREF(TerminalSizeType);
14854 PyModule_AddObject(m, "terminal_size", (PyObject*)TerminalSizeType);
14855
14856 billion = PyLong_FromLong(1000000000);
14857 if (!billion)
14858 return NULL;
14859
14860 /* suppress "function not used" warnings */
14861 {
14862 int ignored;
14863 fd_specified("", -1);
14864 follow_symlinks_specified("", 1);
14865 dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
14866 dir_fd_converter(Py_None, &ignored);
14867 dir_fd_unavailable(Py_None, &ignored);
14868 }
14869
14870 /*
14871 * provide list of locally available functions
14872 * so os.py can populate support_* lists
14873 */
14874 list = PyList_New(0);
14875 if (!list)
14876 return NULL;
14877 for (trace = have_functions; *trace; trace++) {
14878 PyObject *unicode = PyUnicode_DecodeASCII(*trace, strlen(*trace), NULL);
14879 if (!unicode)
14880 return NULL;
14881 if (PyList_Append(list, unicode))
14882 return NULL;
14883 Py_DECREF(unicode);
14884 }
14885 PyModule_AddObject(m, "_have_functions", list);
14886
14887 Py_INCREF((PyObject *) &DirEntryType);
14888 PyModule_AddObject(m, "DirEntry", (PyObject *)&DirEntryType);
14889
14890 initialized = 1;
14891
14892 return m;
14893 }
14894
14895 #ifdef __cplusplus
14896 }
14897 #endif
14898