1 /* POSIX module implementation */
2
3 /* This file is also used for Windows NT/MS-Win. In that case the
4 module actually calls itself 'nt', not 'posix', and a few
5 functions are either unimplemented or implemented differently. The source
6 assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
7 of the compiler used. Different compilers define their own feature
8 test macro, e.g. '_MSC_VER'. */
9
10 #define PY_SSIZE_T_CLEAN
11
12 #include "Python.h"
13 // Include <windows.h> before pycore internal headers. FSCTL_GET_REPARSE_POINT
14 // is not exported by <windows.h> if the WIN32_LEAN_AND_MEAN macro is defined,
15 // whereas pycore_condvar.h defines the WIN32_LEAN_AND_MEAN macro.
16 #ifdef MS_WINDOWS
17 # include <windows.h>
18 # include <pathcch.h>
19 #endif
20
21 #ifdef __VXWORKS__
22 # include "pycore_bitutils.h" // _Py_popcount32()
23 #endif
24 #include "pycore_call.h" // _PyObject_CallNoArgs()
25 #include "pycore_fileutils.h" // _Py_closerange()
26 #include "pycore_moduleobject.h" // _PyModule_GetState()
27 #include "pycore_ceval.h" // _PyEval_ReInitThreads()
28 #include "pycore_import.h" // _PyImport_ReInitLock()
29 #include "pycore_initconfig.h" // _PyStatus_EXCEPTION()
30 #include "pycore_pystate.h" // _PyInterpreterState_GET()
31
32 #include "structmember.h" // PyMemberDef
33 #ifndef MS_WINDOWS
34 # include "posixmodule.h"
35 #else
36 # include "winreparse.h"
37 #endif
38
39 #if !defined(EX_OK) && defined(EXIT_SUCCESS)
40 # define EX_OK EXIT_SUCCESS
41 #endif
42
43 /* On android API level 21, 'AT_EACCESS' is not declared although
44 * HAVE_FACCESSAT is defined. */
45 #ifdef __ANDROID__
46 # undef HAVE_FACCESSAT
47 #endif
48
49 #include <stdio.h> // ctermid()
50 #include <stdlib.h> // system()
51
52 /*
53 * A number of APIs are available on macOS from a certain macOS version.
54 * To support building with a new SDK while deploying to older versions
55 * the availability test is split into two:
56 * - HAVE_<FUNCTION>: The configure check for compile time availability
57 * - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
58 *
59 * The latter is always true when not on macOS, or when using a compiler
60 * that does not support __has_builtin (older versions of Xcode).
61 *
62 * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
63 * if (HAVE_<FUNCTION>_RUNTIME) { ... }
64 *
65 * In mixing the test with other tests or using negations will result in compile
66 * errors.
67 */
68 #if defined(__APPLE__)
69
70 #if defined(__has_builtin)
71 #if __has_builtin(__builtin_available)
72 #define HAVE_BUILTIN_AVAILABLE 1
73 #endif
74 #endif
75
76 #ifdef HAVE_BUILTIN_AVAILABLE
77 # define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
78 # define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
79 # define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
80 # define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
81 # define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
82 # define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
83 # define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
84 # define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
85 # define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
86 # define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
87 # define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
88 # define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
89 # define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
90 # define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
91 # define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
92
93 # define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
94
95 #else /* Xcode 8 or earlier */
96
97 /* __builtin_available is not present in these compilers, but
98 * some of the symbols might be weak linked (10.10 SDK or later
99 * deploying on 10.9.
100 *
101 * Fall back to the older style of availability checking for
102 * symbols introduced in macOS 10.10.
103 */
104
105 # ifdef HAVE_FSTATAT
106 # define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
107 # endif
108
109 # ifdef HAVE_FACCESSAT
110 # define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
111 # endif
112
113 # ifdef HAVE_FCHMODAT
114 # define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
115 # endif
116
117 # ifdef HAVE_FCHOWNAT
118 # define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
119 # endif
120
121 # ifdef HAVE_LINKAT
122 # define HAVE_LINKAT_RUNTIME (linkat != NULL)
123 # endif
124
125 # ifdef HAVE_FDOPENDIR
126 # define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
127 # endif
128
129 # ifdef HAVE_MKDIRAT
130 # define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
131 # endif
132
133 # ifdef HAVE_RENAMEAT
134 # define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
135 # endif
136
137 # ifdef HAVE_UNLINKAT
138 # define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
139 # endif
140
141 # ifdef HAVE_OPENAT
142 # define HAVE_OPENAT_RUNTIME (openat != NULL)
143 # endif
144
145 # ifdef HAVE_READLINKAT
146 # define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
147 # endif
148
149 # ifdef HAVE_SYMLINKAT
150 # define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
151 # endif
152
153 #endif
154
155 #ifdef HAVE_FUTIMESAT
156 /* Some of the logic for weak linking depends on this assertion */
157 # error "HAVE_FUTIMESAT unexpectedly defined"
158 #endif
159
160 #else
161 # define HAVE_FSTATAT_RUNTIME 1
162 # define HAVE_FACCESSAT_RUNTIME 1
163 # define HAVE_FCHMODAT_RUNTIME 1
164 # define HAVE_FCHOWNAT_RUNTIME 1
165 # define HAVE_LINKAT_RUNTIME 1
166 # define HAVE_FDOPENDIR_RUNTIME 1
167 # define HAVE_MKDIRAT_RUNTIME 1
168 # define HAVE_RENAMEAT_RUNTIME 1
169 # define HAVE_UNLINKAT_RUNTIME 1
170 # define HAVE_OPENAT_RUNTIME 1
171 # define HAVE_READLINKAT_RUNTIME 1
172 # define HAVE_SYMLINKAT_RUNTIME 1
173 # define HAVE_FUTIMENS_RUNTIME 1
174 # define HAVE_UTIMENSAT_RUNTIME 1
175 # define HAVE_PWRITEV_RUNTIME 1
176 #endif
177
178
179 #ifdef __cplusplus
180 extern "C" {
181 #endif
182
183 PyDoc_STRVAR(posix__doc__,
184 "This module provides access to operating system functionality that is\n\
185 standardized by the C Standard and the POSIX standard (a thinly\n\
186 disguised Unix interface). Refer to the library manual and\n\
187 corresponding Unix manual entries for more information on calls.");
188
189
190 #ifdef HAVE_SYS_UIO_H
191 # include <sys/uio.h>
192 #endif
193
194 #ifdef HAVE_SYS_SYSMACROS_H
195 /* GNU C Library: major(), minor(), makedev() */
196 # include <sys/sysmacros.h>
197 #endif
198
199 #ifdef HAVE_SYS_TYPES_H
200 # include <sys/types.h>
201 #endif /* HAVE_SYS_TYPES_H */
202
203 #ifdef HAVE_SYS_STAT_H
204 # include <sys/stat.h>
205 #endif /* HAVE_SYS_STAT_H */
206
207 #ifdef HAVE_SYS_WAIT_H
208 # include <sys/wait.h> // WNOHANG
209 #endif
210 #ifdef HAVE_LINUX_WAIT_H
211 # include <linux/wait.h> // P_PIDFD
212 #endif
213
214 #ifdef HAVE_SIGNAL_H
215 # include <signal.h>
216 #endif
217
218 #ifdef HAVE_FCNTL_H
219 # include <fcntl.h>
220 #endif
221
222 #ifdef HAVE_GRP_H
223 # include <grp.h>
224 #endif
225
226 #ifdef HAVE_SYSEXITS_H
227 # include <sysexits.h>
228 #endif
229
230 #ifdef HAVE_SYS_LOADAVG_H
231 # include <sys/loadavg.h>
232 #endif
233
234 #ifdef HAVE_SYS_SENDFILE_H
235 # include <sys/sendfile.h>
236 #endif
237
238 #if defined(__APPLE__)
239 # include <copyfile.h>
240 #endif
241
242 #ifdef HAVE_SCHED_H
243 # include <sched.h>
244 #endif
245
246 #ifdef HAVE_COPY_FILE_RANGE
247 # include <unistd.h>
248 #endif
249
250 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
251 # undef HAVE_SCHED_SETAFFINITY
252 #endif
253
254 #if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
255 # define USE_XATTRS
256 #endif
257
258 #ifdef USE_XATTRS
259 # include <sys/xattr.h>
260 #endif
261
262 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
263 # ifdef HAVE_SYS_SOCKET_H
264 # include <sys/socket.h>
265 # endif
266 #endif
267
268 #ifdef HAVE_DLFCN_H
269 # include <dlfcn.h>
270 #endif
271
272 #ifdef __hpux
273 # include <sys/mpctl.h>
274 #endif
275
276 #if defined(__DragonFly__) || \
277 defined(__OpenBSD__) || \
278 defined(__FreeBSD__) || \
279 defined(__NetBSD__) || \
280 defined(__APPLE__)
281 # include <sys/sysctl.h>
282 #endif
283
284 #ifdef HAVE_LINUX_RANDOM_H
285 # include <linux/random.h>
286 #endif
287 #ifdef HAVE_GETRANDOM_SYSCALL
288 # include <sys/syscall.h>
289 #endif
290
291 #if defined(MS_WINDOWS)
292 # define TERMSIZE_USE_CONIO
293 #elif defined(HAVE_SYS_IOCTL_H)
294 # include <sys/ioctl.h>
295 # if defined(HAVE_TERMIOS_H)
296 # include <termios.h>
297 # endif
298 # if defined(TIOCGWINSZ)
299 # define TERMSIZE_USE_IOCTL
300 # endif
301 #endif /* MS_WINDOWS */
302
303 /* Various compilers have only certain posix functions */
304 /* XXX Gosh I wish these were all moved into pyconfig.h */
305 #if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */
306 # define HAVE_OPENDIR 1
307 # define HAVE_SYSTEM 1
308 # include <process.h>
309 #else
310 # ifdef _MSC_VER
311 /* Microsoft compiler */
312 # define HAVE_GETPPID 1
313 # define HAVE_GETLOGIN 1
314 # define HAVE_SPAWNV 1
315 # define HAVE_EXECV 1
316 # define HAVE_WSPAWNV 1
317 # define HAVE_WEXECV 1
318 # define HAVE_PIPE 1
319 # define HAVE_SYSTEM 1
320 # define HAVE_CWAIT 1
321 # define HAVE_FSYNC 1
322 # define fsync _commit
323 # endif /* _MSC_VER */
324 #endif /* ! __WATCOMC__ || __QNX__ */
325
326 _Py_IDENTIFIER(__fspath__);
327
328 /*[clinic input]
329 # one of the few times we lie about this name!
330 module os
331 [clinic start generated code]*/
332 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
333
334 #ifndef _MSC_VER
335
336 #if defined(__sgi)&&_COMPILER_VERSION>=700
337 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
338 (default) */
339 extern char *ctermid_r(char *);
340 #endif
341
342 #endif /* !_MSC_VER */
343
344 #if defined(__VXWORKS__)
345 # include <vxCpuLib.h>
346 # include <rtpLib.h>
347 # include <wait.h>
348 # include <taskLib.h>
349 # ifndef _P_WAIT
350 # define _P_WAIT 0
351 # define _P_NOWAIT 1
352 # define _P_NOWAITO 1
353 # endif
354 #endif /* __VXWORKS__ */
355
356 #ifdef HAVE_POSIX_SPAWN
357 # include <spawn.h>
358 #endif
359
360 #ifdef HAVE_UTIME_H
361 # include <utime.h>
362 #endif /* HAVE_UTIME_H */
363
364 #ifdef HAVE_SYS_UTIME_H
365 # include <sys/utime.h>
366 # define HAVE_UTIME_H /* pretend we do for the rest of this file */
367 #endif /* HAVE_SYS_UTIME_H */
368
369 #ifdef HAVE_SYS_TIMES_H
370 # include <sys/times.h>
371 #endif /* HAVE_SYS_TIMES_H */
372
373 #ifdef HAVE_SYS_PARAM_H
374 # include <sys/param.h>
375 #endif /* HAVE_SYS_PARAM_H */
376
377 #ifdef HAVE_SYS_UTSNAME_H
378 # include <sys/utsname.h>
379 #endif /* HAVE_SYS_UTSNAME_H */
380
381 #ifdef HAVE_DIRENT_H
382 # include <dirent.h>
383 # define NAMLEN(dirent) strlen((dirent)->d_name)
384 #else
385 # if defined(__WATCOMC__) && !defined(__QNX__)
386 # include <direct.h>
387 # define NAMLEN(dirent) strlen((dirent)->d_name)
388 # else
389 # define dirent direct
390 # define NAMLEN(dirent) (dirent)->d_namlen
391 # endif
392 # ifdef HAVE_SYS_NDIR_H
393 # include <sys/ndir.h>
394 # endif
395 # ifdef HAVE_SYS_DIR_H
396 # include <sys/dir.h>
397 # endif
398 # ifdef HAVE_NDIR_H
399 # include <ndir.h>
400 # endif
401 #endif
402
403 #ifdef _MSC_VER
404 # ifdef HAVE_DIRECT_H
405 # include <direct.h>
406 # endif
407 # ifdef HAVE_IO_H
408 # include <io.h>
409 # endif
410 # ifdef HAVE_PROCESS_H
411 # include <process.h>
412 # endif
413 # ifndef IO_REPARSE_TAG_SYMLINK
414 # define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
415 # endif
416 # ifndef IO_REPARSE_TAG_MOUNT_POINT
417 # define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
418 # endif
419 # include "osdefs.h" // SEP
420 # include <malloc.h>
421 # include <windows.h>
422 # include <shellapi.h> // ShellExecute()
423 # include <lmcons.h> // UNLEN
424 # define HAVE_SYMLINK
425 #endif /* _MSC_VER */
426
427 #ifndef MAXPATHLEN
428 # if defined(PATH_MAX) && PATH_MAX > 1024
429 # define MAXPATHLEN PATH_MAX
430 # else
431 # define MAXPATHLEN 1024
432 # endif
433 #endif /* MAXPATHLEN */
434
435 #ifdef UNION_WAIT
436 /* Emulate some macros on systems that have a union instead of macros */
437 # ifndef WIFEXITED
438 # define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
439 # endif
440 # ifndef WEXITSTATUS
441 # define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
442 # endif
443 # ifndef WTERMSIG
444 # define WTERMSIG(u_wait) ((u_wait).w_termsig)
445 # endif
446 # define WAIT_TYPE union wait
447 # define WAIT_STATUS_INT(s) (s.w_status)
448 #else
449 /* !UNION_WAIT */
450 # define WAIT_TYPE int
451 # define WAIT_STATUS_INT(s) (s)
452 #endif /* UNION_WAIT */
453
454 /* Don't use the "_r" form if we don't need it (also, won't have a
455 prototype for it, at least on Solaris -- maybe others as well?). */
456 #if defined(HAVE_CTERMID_R)
457 # define USE_CTERMID_R
458 #endif
459
460 /* choose the appropriate stat and fstat functions and return structs */
461 #undef STAT
462 #undef FSTAT
463 #undef STRUCT_STAT
464 #ifdef MS_WINDOWS
465 # define STAT win32_stat
466 # define LSTAT win32_lstat
467 # define FSTAT _Py_fstat_noraise
468 # define STRUCT_STAT struct _Py_stat_struct
469 #else
470 # define STAT stat
471 # define LSTAT lstat
472 # define FSTAT fstat
473 # define STRUCT_STAT struct stat
474 #endif
475
476 #if defined(MAJOR_IN_MKDEV)
477 # include <sys/mkdev.h>
478 #else
479 # if defined(MAJOR_IN_SYSMACROS)
480 # include <sys/sysmacros.h>
481 # endif
482 # if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
483 # include <sys/mkdev.h>
484 # endif
485 #endif
486
487 #ifdef MS_WINDOWS
488 # define INITFUNC PyInit_nt
489 # define MODNAME "nt"
490 #else
491 # define INITFUNC PyInit_posix
492 # define MODNAME "posix"
493 #endif
494
495 #if defined(__sun)
496 /* Something to implement in autoconf, not present in autoconf 2.69 */
497 # define HAVE_STRUCT_STAT_ST_FSTYPE 1
498 #endif
499
500 /* memfd_create is either defined in sys/mman.h or sys/memfd.h
501 * linux/memfd.h defines additional flags
502 */
503 #ifdef HAVE_SYS_MMAN_H
504 # include <sys/mman.h>
505 #endif
506 #ifdef HAVE_SYS_MEMFD_H
507 # include <sys/memfd.h>
508 #endif
509 #ifdef HAVE_LINUX_MEMFD_H
510 # include <linux/memfd.h>
511 #endif
512
513 /* eventfd() */
514 #ifdef HAVE_SYS_EVENTFD_H
515 # include <sys/eventfd.h>
516 #endif
517
518 #ifdef _Py_MEMORY_SANITIZER
519 # include <sanitizer/msan_interface.h>
520 #endif
521
522 #ifdef HAVE_FORK
523 static void
run_at_forkers(PyObject * lst,int reverse)524 run_at_forkers(PyObject *lst, int reverse)
525 {
526 Py_ssize_t i;
527 PyObject *cpy;
528
529 if (lst != NULL) {
530 assert(PyList_CheckExact(lst));
531
532 /* Use a list copy in case register_at_fork() is called from
533 * one of the callbacks.
534 */
535 cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
536 if (cpy == NULL)
537 PyErr_WriteUnraisable(lst);
538 else {
539 if (reverse)
540 PyList_Reverse(cpy);
541 for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
542 PyObject *func, *res;
543 func = PyList_GET_ITEM(cpy, i);
544 res = _PyObject_CallNoArgs(func);
545 if (res == NULL)
546 PyErr_WriteUnraisable(func);
547 else
548 Py_DECREF(res);
549 }
550 Py_DECREF(cpy);
551 }
552 }
553 }
554
555 void
PyOS_BeforeFork(void)556 PyOS_BeforeFork(void)
557 {
558 run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1);
559
560 _PyImport_AcquireLock();
561 }
562
563 void
PyOS_AfterFork_Parent(void)564 PyOS_AfterFork_Parent(void)
565 {
566 if (_PyImport_ReleaseLock() <= 0)
567 Py_FatalError("failed releasing import lock after fork");
568
569 run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0);
570 }
571
572 void
PyOS_AfterFork_Child(void)573 PyOS_AfterFork_Child(void)
574 {
575 PyStatus status;
576 _PyRuntimeState *runtime = &_PyRuntime;
577
578 status = _PyGILState_Reinit(runtime);
579 if (_PyStatus_EXCEPTION(status)) {
580 goto fatal_error;
581 }
582
583 PyThreadState *tstate = _PyThreadState_GET();
584 _Py_EnsureTstateNotNULL(tstate);
585
586 status = _PyEval_ReInitThreads(tstate);
587 if (_PyStatus_EXCEPTION(status)) {
588 goto fatal_error;
589 }
590
591 status = _PyImport_ReInitLock();
592 if (_PyStatus_EXCEPTION(status)) {
593 goto fatal_error;
594 }
595
596 _PySignal_AfterFork();
597
598 status = _PyRuntimeState_ReInitThreads(runtime);
599 if (_PyStatus_EXCEPTION(status)) {
600 goto fatal_error;
601 }
602
603 status = _PyInterpreterState_DeleteExceptMain(runtime);
604 if (_PyStatus_EXCEPTION(status)) {
605 goto fatal_error;
606 }
607 assert(_PyThreadState_GET() == tstate);
608
609 run_at_forkers(tstate->interp->after_forkers_child, 0);
610 return;
611
612 fatal_error:
613 Py_ExitStatusException(status);
614 }
615
616 static int
register_at_forker(PyObject ** lst,PyObject * func)617 register_at_forker(PyObject **lst, PyObject *func)
618 {
619 if (func == NULL) /* nothing to register? do nothing. */
620 return 0;
621 if (*lst == NULL) {
622 *lst = PyList_New(0);
623 if (*lst == NULL)
624 return -1;
625 }
626 return PyList_Append(*lst, func);
627 }
628 #endif /* HAVE_FORK */
629
630
631 /* Legacy wrapper */
632 void
PyOS_AfterFork(void)633 PyOS_AfterFork(void)
634 {
635 #ifdef HAVE_FORK
636 PyOS_AfterFork_Child();
637 #endif
638 }
639
640
641 #ifdef MS_WINDOWS
642 /* defined in fileutils.c */
643 void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
644 void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
645 ULONG, struct _Py_stat_struct *);
646 #endif
647
648
649 #ifndef MS_WINDOWS
650 PyObject *
_PyLong_FromUid(uid_t uid)651 _PyLong_FromUid(uid_t uid)
652 {
653 if (uid == (uid_t)-1)
654 return PyLong_FromLong(-1);
655 return PyLong_FromUnsignedLong(uid);
656 }
657
658 PyObject *
_PyLong_FromGid(gid_t gid)659 _PyLong_FromGid(gid_t gid)
660 {
661 if (gid == (gid_t)-1)
662 return PyLong_FromLong(-1);
663 return PyLong_FromUnsignedLong(gid);
664 }
665
666 int
_Py_Uid_Converter(PyObject * obj,uid_t * p)667 _Py_Uid_Converter(PyObject *obj, uid_t *p)
668 {
669 uid_t uid;
670 PyObject *index;
671 int overflow;
672 long result;
673 unsigned long uresult;
674
675 index = _PyNumber_Index(obj);
676 if (index == NULL) {
677 PyErr_Format(PyExc_TypeError,
678 "uid should be integer, not %.200s",
679 _PyType_Name(Py_TYPE(obj)));
680 return 0;
681 }
682
683 /*
684 * Handling uid_t is complicated for two reasons:
685 * * Although uid_t is (always?) unsigned, it still
686 * accepts -1.
687 * * We don't know its size in advance--it may be
688 * bigger than an int, or it may be smaller than
689 * a long.
690 *
691 * So a bit of defensive programming is in order.
692 * Start with interpreting the value passed
693 * in as a signed long and see if it works.
694 */
695
696 result = PyLong_AsLongAndOverflow(index, &overflow);
697
698 if (!overflow) {
699 uid = (uid_t)result;
700
701 if (result == -1) {
702 if (PyErr_Occurred())
703 goto fail;
704 /* It's a legitimate -1, we're done. */
705 goto success;
706 }
707
708 /* Any other negative number is disallowed. */
709 if (result < 0)
710 goto underflow;
711
712 /* Ensure the value wasn't truncated. */
713 if (sizeof(uid_t) < sizeof(long) &&
714 (long)uid != result)
715 goto underflow;
716 goto success;
717 }
718
719 if (overflow < 0)
720 goto underflow;
721
722 /*
723 * Okay, the value overflowed a signed long. If it
724 * fits in an *unsigned* long, it may still be okay,
725 * as uid_t may be unsigned long on this platform.
726 */
727 uresult = PyLong_AsUnsignedLong(index);
728 if (PyErr_Occurred()) {
729 if (PyErr_ExceptionMatches(PyExc_OverflowError))
730 goto overflow;
731 goto fail;
732 }
733
734 uid = (uid_t)uresult;
735
736 /*
737 * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
738 * but this value would get interpreted as (uid_t)-1 by chown
739 * and its siblings. That's not what the user meant! So we
740 * throw an overflow exception instead. (We already
741 * handled a real -1 with PyLong_AsLongAndOverflow() above.)
742 */
743 if (uid == (uid_t)-1)
744 goto overflow;
745
746 /* Ensure the value wasn't truncated. */
747 if (sizeof(uid_t) < sizeof(long) &&
748 (unsigned long)uid != uresult)
749 goto overflow;
750 /* fallthrough */
751
752 success:
753 Py_DECREF(index);
754 *p = uid;
755 return 1;
756
757 underflow:
758 PyErr_SetString(PyExc_OverflowError,
759 "uid is less than minimum");
760 goto fail;
761
762 overflow:
763 PyErr_SetString(PyExc_OverflowError,
764 "uid is greater than maximum");
765 /* fallthrough */
766
767 fail:
768 Py_DECREF(index);
769 return 0;
770 }
771
772 int
_Py_Gid_Converter(PyObject * obj,gid_t * p)773 _Py_Gid_Converter(PyObject *obj, gid_t *p)
774 {
775 gid_t gid;
776 PyObject *index;
777 int overflow;
778 long result;
779 unsigned long uresult;
780
781 index = _PyNumber_Index(obj);
782 if (index == NULL) {
783 PyErr_Format(PyExc_TypeError,
784 "gid should be integer, not %.200s",
785 _PyType_Name(Py_TYPE(obj)));
786 return 0;
787 }
788
789 /*
790 * Handling gid_t is complicated for two reasons:
791 * * Although gid_t is (always?) unsigned, it still
792 * accepts -1.
793 * * We don't know its size in advance--it may be
794 * bigger than an int, or it may be smaller than
795 * a long.
796 *
797 * So a bit of defensive programming is in order.
798 * Start with interpreting the value passed
799 * in as a signed long and see if it works.
800 */
801
802 result = PyLong_AsLongAndOverflow(index, &overflow);
803
804 if (!overflow) {
805 gid = (gid_t)result;
806
807 if (result == -1) {
808 if (PyErr_Occurred())
809 goto fail;
810 /* It's a legitimate -1, we're done. */
811 goto success;
812 }
813
814 /* Any other negative number is disallowed. */
815 if (result < 0) {
816 goto underflow;
817 }
818
819 /* Ensure the value wasn't truncated. */
820 if (sizeof(gid_t) < sizeof(long) &&
821 (long)gid != result)
822 goto underflow;
823 goto success;
824 }
825
826 if (overflow < 0)
827 goto underflow;
828
829 /*
830 * Okay, the value overflowed a signed long. If it
831 * fits in an *unsigned* long, it may still be okay,
832 * as gid_t may be unsigned long on this platform.
833 */
834 uresult = PyLong_AsUnsignedLong(index);
835 if (PyErr_Occurred()) {
836 if (PyErr_ExceptionMatches(PyExc_OverflowError))
837 goto overflow;
838 goto fail;
839 }
840
841 gid = (gid_t)uresult;
842
843 /*
844 * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
845 * but this value would get interpreted as (gid_t)-1 by chown
846 * and its siblings. That's not what the user meant! So we
847 * throw an overflow exception instead. (We already
848 * handled a real -1 with PyLong_AsLongAndOverflow() above.)
849 */
850 if (gid == (gid_t)-1)
851 goto overflow;
852
853 /* Ensure the value wasn't truncated. */
854 if (sizeof(gid_t) < sizeof(long) &&
855 (unsigned long)gid != uresult)
856 goto overflow;
857 /* fallthrough */
858
859 success:
860 Py_DECREF(index);
861 *p = gid;
862 return 1;
863
864 underflow:
865 PyErr_SetString(PyExc_OverflowError,
866 "gid is less than minimum");
867 goto fail;
868
869 overflow:
870 PyErr_SetString(PyExc_OverflowError,
871 "gid is greater than maximum");
872 /* fallthrough */
873
874 fail:
875 Py_DECREF(index);
876 return 0;
877 }
878 #endif /* MS_WINDOWS */
879
880
881 #define _PyLong_FromDev PyLong_FromLongLong
882
883
884 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
885 static int
_Py_Dev_Converter(PyObject * obj,void * p)886 _Py_Dev_Converter(PyObject *obj, void *p)
887 {
888 *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
889 if (PyErr_Occurred())
890 return 0;
891 return 1;
892 }
893 #endif /* HAVE_MKNOD && HAVE_MAKEDEV */
894
895
896 #ifdef AT_FDCWD
897 /*
898 * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
899 * without the int cast, the value gets interpreted as uint (4291925331),
900 * which doesn't play nicely with all the initializer lines in this file that
901 * look like this:
902 * int dir_fd = DEFAULT_DIR_FD;
903 */
904 #define DEFAULT_DIR_FD (int)AT_FDCWD
905 #else
906 #define DEFAULT_DIR_FD (-100)
907 #endif
908
909 static int
_fd_converter(PyObject * o,int * p)910 _fd_converter(PyObject *o, int *p)
911 {
912 int overflow;
913 long long_value;
914
915 PyObject *index = _PyNumber_Index(o);
916 if (index == NULL) {
917 return 0;
918 }
919
920 assert(PyLong_Check(index));
921 long_value = PyLong_AsLongAndOverflow(index, &overflow);
922 Py_DECREF(index);
923 assert(!PyErr_Occurred());
924 if (overflow > 0 || long_value > INT_MAX) {
925 PyErr_SetString(PyExc_OverflowError,
926 "fd is greater than maximum");
927 return 0;
928 }
929 if (overflow < 0 || long_value < INT_MIN) {
930 PyErr_SetString(PyExc_OverflowError,
931 "fd is less than minimum");
932 return 0;
933 }
934
935 *p = (int)long_value;
936 return 1;
937 }
938
939 static int
dir_fd_converter(PyObject * o,void * p)940 dir_fd_converter(PyObject *o, void *p)
941 {
942 if (o == Py_None) {
943 *(int *)p = DEFAULT_DIR_FD;
944 return 1;
945 }
946 else if (PyIndex_Check(o)) {
947 return _fd_converter(o, (int *)p);
948 }
949 else {
950 PyErr_Format(PyExc_TypeError,
951 "argument should be integer or None, not %.200s",
952 _PyType_Name(Py_TYPE(o)));
953 return 0;
954 }
955 }
956
957 typedef struct {
958 PyObject *billion;
959 PyObject *DirEntryType;
960 PyObject *ScandirIteratorType;
961 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
962 PyObject *SchedParamType;
963 #endif
964 PyObject *StatResultType;
965 PyObject *StatVFSResultType;
966 PyObject *TerminalSizeType;
967 PyObject *TimesResultType;
968 PyObject *UnameResultType;
969 #if defined(HAVE_WAITID) && !defined(__APPLE__)
970 PyObject *WaitidResultType;
971 #endif
972 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
973 PyObject *struct_rusage;
974 #endif
975 PyObject *st_mode;
976 } _posixstate;
977
978
979 static inline _posixstate*
get_posix_state(PyObject * module)980 get_posix_state(PyObject *module)
981 {
982 void *state = _PyModule_GetState(module);
983 assert(state != NULL);
984 return (_posixstate *)state;
985 }
986
987 /*
988 * A PyArg_ParseTuple "converter" function
989 * that handles filesystem paths in the manner
990 * preferred by the os module.
991 *
992 * path_converter accepts (Unicode) strings and their
993 * subclasses, and bytes and their subclasses. What
994 * it does with the argument depends on the platform:
995 *
996 * * On Windows, if we get a (Unicode) string we
997 * extract the wchar_t * and return it; if we get
998 * bytes we decode to wchar_t * and return that.
999 *
1000 * * On all other platforms, strings are encoded
1001 * to bytes using PyUnicode_FSConverter, then we
1002 * extract the char * from the bytes object and
1003 * return that.
1004 *
1005 * path_converter also optionally accepts signed
1006 * integers (representing open file descriptors) instead
1007 * of path strings.
1008 *
1009 * Input fields:
1010 * path.nullable
1011 * If nonzero, the path is permitted to be None.
1012 * path.allow_fd
1013 * If nonzero, the path is permitted to be a file handle
1014 * (a signed int) instead of a string.
1015 * path.function_name
1016 * If non-NULL, path_converter will use that as the name
1017 * of the function in error messages.
1018 * (If path.function_name is NULL it omits the function name.)
1019 * path.argument_name
1020 * If non-NULL, path_converter will use that as the name
1021 * of the parameter in error messages.
1022 * (If path.argument_name is NULL it uses "path".)
1023 *
1024 * Output fields:
1025 * path.wide
1026 * Points to the path if it was expressed as Unicode
1027 * and was not encoded. (Only used on Windows.)
1028 * path.narrow
1029 * Points to the path if it was expressed as bytes,
1030 * or it was Unicode and was encoded to bytes. (On Windows,
1031 * is a non-zero integer if the path was expressed as bytes.
1032 * The type is deliberately incompatible to prevent misuse.)
1033 * path.fd
1034 * Contains a file descriptor if path.accept_fd was true
1035 * and the caller provided a signed integer instead of any
1036 * sort of string.
1037 *
1038 * WARNING: if your "path" parameter is optional, and is
1039 * unspecified, path_converter will never get called.
1040 * So if you set allow_fd, you *MUST* initialize path.fd = -1
1041 * yourself!
1042 * path.length
1043 * The length of the path in characters, if specified as
1044 * a string.
1045 * path.object
1046 * The original object passed in (if get a PathLike object,
1047 * the result of PyOS_FSPath() is treated as the original object).
1048 * Own a reference to the object.
1049 * path.cleanup
1050 * For internal use only. May point to a temporary object.
1051 * (Pay no attention to the man behind the curtain.)
1052 *
1053 * At most one of path.wide or path.narrow will be non-NULL.
1054 * If path was None and path.nullable was set,
1055 * or if path was an integer and path.allow_fd was set,
1056 * both path.wide and path.narrow will be NULL
1057 * and path.length will be 0.
1058 *
1059 * path_converter takes care to not write to the path_t
1060 * unless it's successful. However it must reset the
1061 * "cleanup" field each time it's called.
1062 *
1063 * Use as follows:
1064 * path_t path;
1065 * memset(&path, 0, sizeof(path));
1066 * PyArg_ParseTuple(args, "O&", path_converter, &path);
1067 * // ... use values from path ...
1068 * path_cleanup(&path);
1069 *
1070 * (Note that if PyArg_Parse fails you don't need to call
1071 * path_cleanup(). However it is safe to do so.)
1072 */
1073 typedef struct {
1074 const char *function_name;
1075 const char *argument_name;
1076 int nullable;
1077 int allow_fd;
1078 const wchar_t *wide;
1079 #ifdef MS_WINDOWS
1080 BOOL narrow;
1081 #else
1082 const char *narrow;
1083 #endif
1084 int fd;
1085 Py_ssize_t length;
1086 PyObject *object;
1087 PyObject *cleanup;
1088 } path_t;
1089
1090 #ifdef MS_WINDOWS
1091 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1092 {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
1093 #else
1094 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1095 {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
1096 #endif
1097
1098 static void
path_cleanup(path_t * path)1099 path_cleanup(path_t *path)
1100 {
1101 #if !USE_UNICODE_WCHAR_CACHE
1102 wchar_t *wide = (wchar_t *)path->wide;
1103 path->wide = NULL;
1104 PyMem_Free(wide);
1105 #endif /* USE_UNICODE_WCHAR_CACHE */
1106 Py_CLEAR(path->object);
1107 Py_CLEAR(path->cleanup);
1108 }
1109
1110 static int
path_converter(PyObject * o,void * p)1111 path_converter(PyObject *o, void *p)
1112 {
1113 path_t *path = (path_t *)p;
1114 PyObject *bytes = NULL;
1115 Py_ssize_t length = 0;
1116 int is_index, is_buffer, is_bytes, is_unicode;
1117 const char *narrow;
1118 #ifdef MS_WINDOWS
1119 PyObject *wo = NULL;
1120 wchar_t *wide = NULL;
1121 #endif
1122
1123 #define FORMAT_EXCEPTION(exc, fmt) \
1124 PyErr_Format(exc, "%s%s" fmt, \
1125 path->function_name ? path->function_name : "", \
1126 path->function_name ? ": " : "", \
1127 path->argument_name ? path->argument_name : "path")
1128
1129 /* Py_CLEANUP_SUPPORTED support */
1130 if (o == NULL) {
1131 path_cleanup(path);
1132 return 1;
1133 }
1134
1135 /* Ensure it's always safe to call path_cleanup(). */
1136 path->object = path->cleanup = NULL;
1137 /* path->object owns a reference to the original object */
1138 Py_INCREF(o);
1139
1140 if ((o == Py_None) && path->nullable) {
1141 path->wide = NULL;
1142 #ifdef MS_WINDOWS
1143 path->narrow = FALSE;
1144 #else
1145 path->narrow = NULL;
1146 #endif
1147 path->fd = -1;
1148 goto success_exit;
1149 }
1150
1151 /* Only call this here so that we don't treat the return value of
1152 os.fspath() as an fd or buffer. */
1153 is_index = path->allow_fd && PyIndex_Check(o);
1154 is_buffer = PyObject_CheckBuffer(o);
1155 is_bytes = PyBytes_Check(o);
1156 is_unicode = PyUnicode_Check(o);
1157
1158 if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
1159 /* Inline PyOS_FSPath() for better error messages. */
1160 PyObject *func, *res;
1161
1162 func = _PyObject_LookupSpecial(o, &PyId___fspath__);
1163 if (NULL == func) {
1164 goto error_format;
1165 }
1166 res = _PyObject_CallNoArgs(func);
1167 Py_DECREF(func);
1168 if (NULL == res) {
1169 goto error_exit;
1170 }
1171 else if (PyUnicode_Check(res)) {
1172 is_unicode = 1;
1173 }
1174 else if (PyBytes_Check(res)) {
1175 is_bytes = 1;
1176 }
1177 else {
1178 PyErr_Format(PyExc_TypeError,
1179 "expected %.200s.__fspath__() to return str or bytes, "
1180 "not %.200s", _PyType_Name(Py_TYPE(o)),
1181 _PyType_Name(Py_TYPE(res)));
1182 Py_DECREF(res);
1183 goto error_exit;
1184 }
1185
1186 /* still owns a reference to the original object */
1187 Py_DECREF(o);
1188 o = res;
1189 }
1190
1191 if (is_unicode) {
1192 #ifdef MS_WINDOWS
1193 #if USE_UNICODE_WCHAR_CACHE
1194 _Py_COMP_DIAG_PUSH
1195 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1196 wide = PyUnicode_AsUnicodeAndSize(o, &length);
1197 _Py_COMP_DIAG_POP
1198 #else /* USE_UNICODE_WCHAR_CACHE */
1199 wide = PyUnicode_AsWideCharString(o, &length);
1200 #endif /* USE_UNICODE_WCHAR_CACHE */
1201 if (!wide) {
1202 goto error_exit;
1203 }
1204 if (length > 32767) {
1205 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1206 goto error_exit;
1207 }
1208 if (wcslen(wide) != length) {
1209 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1210 goto error_exit;
1211 }
1212
1213 path->wide = wide;
1214 path->narrow = FALSE;
1215 path->fd = -1;
1216 #if !USE_UNICODE_WCHAR_CACHE
1217 wide = NULL;
1218 #endif /* USE_UNICODE_WCHAR_CACHE */
1219 goto success_exit;
1220 #else
1221 if (!PyUnicode_FSConverter(o, &bytes)) {
1222 goto error_exit;
1223 }
1224 #endif
1225 }
1226 else if (is_bytes) {
1227 bytes = o;
1228 Py_INCREF(bytes);
1229 }
1230 else if (is_buffer) {
1231 /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1232 after removing support of non-bytes buffer objects. */
1233 if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
1234 "%s%s%s should be %s, not %.200s",
1235 path->function_name ? path->function_name : "",
1236 path->function_name ? ": " : "",
1237 path->argument_name ? path->argument_name : "path",
1238 path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1239 "integer or None" :
1240 path->allow_fd ? "string, bytes, os.PathLike or integer" :
1241 path->nullable ? "string, bytes, os.PathLike or None" :
1242 "string, bytes or os.PathLike",
1243 _PyType_Name(Py_TYPE(o)))) {
1244 goto error_exit;
1245 }
1246 bytes = PyBytes_FromObject(o);
1247 if (!bytes) {
1248 goto error_exit;
1249 }
1250 }
1251 else if (is_index) {
1252 if (!_fd_converter(o, &path->fd)) {
1253 goto error_exit;
1254 }
1255 path->wide = NULL;
1256 #ifdef MS_WINDOWS
1257 path->narrow = FALSE;
1258 #else
1259 path->narrow = NULL;
1260 #endif
1261 goto success_exit;
1262 }
1263 else {
1264 error_format:
1265 PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1266 path->function_name ? path->function_name : "",
1267 path->function_name ? ": " : "",
1268 path->argument_name ? path->argument_name : "path",
1269 path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1270 "integer or None" :
1271 path->allow_fd ? "string, bytes, os.PathLike or integer" :
1272 path->nullable ? "string, bytes, os.PathLike or None" :
1273 "string, bytes or os.PathLike",
1274 _PyType_Name(Py_TYPE(o)));
1275 goto error_exit;
1276 }
1277
1278 length = PyBytes_GET_SIZE(bytes);
1279 narrow = PyBytes_AS_STRING(bytes);
1280 if ((size_t)length != strlen(narrow)) {
1281 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1282 goto error_exit;
1283 }
1284
1285 #ifdef MS_WINDOWS
1286 wo = PyUnicode_DecodeFSDefaultAndSize(
1287 narrow,
1288 length
1289 );
1290 if (!wo) {
1291 goto error_exit;
1292 }
1293
1294 #if USE_UNICODE_WCHAR_CACHE
1295 _Py_COMP_DIAG_PUSH
1296 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1297 wide = PyUnicode_AsUnicodeAndSize(wo, &length);
1298 _Py_COMP_DIAG_POP
1299 #else /* USE_UNICODE_WCHAR_CACHE */
1300 wide = PyUnicode_AsWideCharString(wo, &length);
1301 Py_DECREF(wo);
1302 #endif /* USE_UNICODE_WCHAR_CACHE */
1303 if (!wide) {
1304 goto error_exit;
1305 }
1306 if (length > 32767) {
1307 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1308 goto error_exit;
1309 }
1310 if (wcslen(wide) != length) {
1311 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1312 goto error_exit;
1313 }
1314 path->wide = wide;
1315 path->narrow = TRUE;
1316 Py_DECREF(bytes);
1317 #if USE_UNICODE_WCHAR_CACHE
1318 path->cleanup = wo;
1319 #else /* USE_UNICODE_WCHAR_CACHE */
1320 wide = NULL;
1321 #endif /* USE_UNICODE_WCHAR_CACHE */
1322 #else
1323 path->wide = NULL;
1324 path->narrow = narrow;
1325 if (bytes == o) {
1326 /* Still a reference owned by path->object, don't have to
1327 worry about path->narrow is used after free. */
1328 Py_DECREF(bytes);
1329 }
1330 else {
1331 path->cleanup = bytes;
1332 }
1333 #endif
1334 path->fd = -1;
1335
1336 success_exit:
1337 path->length = length;
1338 path->object = o;
1339 return Py_CLEANUP_SUPPORTED;
1340
1341 error_exit:
1342 Py_XDECREF(o);
1343 Py_XDECREF(bytes);
1344 #ifdef MS_WINDOWS
1345 #if USE_UNICODE_WCHAR_CACHE
1346 Py_XDECREF(wo);
1347 #else /* USE_UNICODE_WCHAR_CACHE */
1348 PyMem_Free(wide);
1349 #endif /* USE_UNICODE_WCHAR_CACHE */
1350 #endif
1351 return 0;
1352 }
1353
1354 static void
argument_unavailable_error(const char * function_name,const char * argument_name)1355 argument_unavailable_error(const char *function_name, const char *argument_name)
1356 {
1357 PyErr_Format(PyExc_NotImplementedError,
1358 "%s%s%s unavailable on this platform",
1359 (function_name != NULL) ? function_name : "",
1360 (function_name != NULL) ? ": ": "",
1361 argument_name);
1362 }
1363
1364 static int
dir_fd_unavailable(PyObject * o,void * p)1365 dir_fd_unavailable(PyObject *o, void *p)
1366 {
1367 int dir_fd;
1368 if (!dir_fd_converter(o, &dir_fd))
1369 return 0;
1370 if (dir_fd != DEFAULT_DIR_FD) {
1371 argument_unavailable_error(NULL, "dir_fd");
1372 return 0;
1373 }
1374 *(int *)p = dir_fd;
1375 return 1;
1376 }
1377
1378 static int
fd_specified(const char * function_name,int fd)1379 fd_specified(const char *function_name, int fd)
1380 {
1381 if (fd == -1)
1382 return 0;
1383
1384 argument_unavailable_error(function_name, "fd");
1385 return 1;
1386 }
1387
1388 static int
follow_symlinks_specified(const char * function_name,int follow_symlinks)1389 follow_symlinks_specified(const char *function_name, int follow_symlinks)
1390 {
1391 if (follow_symlinks)
1392 return 0;
1393
1394 argument_unavailable_error(function_name, "follow_symlinks");
1395 return 1;
1396 }
1397
1398 static int
path_and_dir_fd_invalid(const char * function_name,path_t * path,int dir_fd)1399 path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1400 {
1401 if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1402 #ifndef MS_WINDOWS
1403 && !path->narrow
1404 #endif
1405 ) {
1406 PyErr_Format(PyExc_ValueError,
1407 "%s: can't specify dir_fd without matching path",
1408 function_name);
1409 return 1;
1410 }
1411 return 0;
1412 }
1413
1414 static int
dir_fd_and_fd_invalid(const char * function_name,int dir_fd,int fd)1415 dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1416 {
1417 if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1418 PyErr_Format(PyExc_ValueError,
1419 "%s: can't specify both dir_fd and fd",
1420 function_name);
1421 return 1;
1422 }
1423 return 0;
1424 }
1425
1426 static int
fd_and_follow_symlinks_invalid(const char * function_name,int fd,int follow_symlinks)1427 fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1428 int follow_symlinks)
1429 {
1430 if ((fd > 0) && (!follow_symlinks)) {
1431 PyErr_Format(PyExc_ValueError,
1432 "%s: cannot use fd and follow_symlinks together",
1433 function_name);
1434 return 1;
1435 }
1436 return 0;
1437 }
1438
1439 static int
dir_fd_and_follow_symlinks_invalid(const char * function_name,int dir_fd,int follow_symlinks)1440 dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1441 int follow_symlinks)
1442 {
1443 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1444 PyErr_Format(PyExc_ValueError,
1445 "%s: cannot use dir_fd and follow_symlinks together",
1446 function_name);
1447 return 1;
1448 }
1449 return 0;
1450 }
1451
1452 #ifdef MS_WINDOWS
1453 typedef long long Py_off_t;
1454 #else
1455 typedef off_t Py_off_t;
1456 #endif
1457
1458 static int
Py_off_t_converter(PyObject * arg,void * addr)1459 Py_off_t_converter(PyObject *arg, void *addr)
1460 {
1461 #ifdef HAVE_LARGEFILE_SUPPORT
1462 *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1463 #else
1464 *((Py_off_t *)addr) = PyLong_AsLong(arg);
1465 #endif
1466 if (PyErr_Occurred())
1467 return 0;
1468 return 1;
1469 }
1470
1471 static PyObject *
PyLong_FromPy_off_t(Py_off_t offset)1472 PyLong_FromPy_off_t(Py_off_t offset)
1473 {
1474 #ifdef HAVE_LARGEFILE_SUPPORT
1475 return PyLong_FromLongLong(offset);
1476 #else
1477 return PyLong_FromLong(offset);
1478 #endif
1479 }
1480
1481 #ifdef HAVE_SIGSET_T
1482 /* Convert an iterable of integers to a sigset.
1483 Return 1 on success, return 0 and raise an exception on error. */
1484 int
_Py_Sigset_Converter(PyObject * obj,void * addr)1485 _Py_Sigset_Converter(PyObject *obj, void *addr)
1486 {
1487 sigset_t *mask = (sigset_t *)addr;
1488 PyObject *iterator, *item;
1489 long signum;
1490 int overflow;
1491
1492 // The extra parens suppress the unreachable-code warning with clang on MacOS
1493 if (sigemptyset(mask) < (0)) {
1494 /* Probably only if mask == NULL. */
1495 PyErr_SetFromErrno(PyExc_OSError);
1496 return 0;
1497 }
1498
1499 iterator = PyObject_GetIter(obj);
1500 if (iterator == NULL) {
1501 return 0;
1502 }
1503
1504 while ((item = PyIter_Next(iterator)) != NULL) {
1505 signum = PyLong_AsLongAndOverflow(item, &overflow);
1506 Py_DECREF(item);
1507 if (signum <= 0 || signum >= NSIG) {
1508 if (overflow || signum != -1 || !PyErr_Occurred()) {
1509 PyErr_Format(PyExc_ValueError,
1510 "signal number %ld out of range", signum);
1511 }
1512 goto error;
1513 }
1514 if (sigaddset(mask, (int)signum)) {
1515 if (errno != EINVAL) {
1516 /* Probably impossible */
1517 PyErr_SetFromErrno(PyExc_OSError);
1518 goto error;
1519 }
1520 /* For backwards compatibility, allow idioms such as
1521 * `range(1, NSIG)` but warn about invalid signal numbers
1522 */
1523 const char msg[] =
1524 "invalid signal number %ld, please use valid_signals()";
1525 if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1526 goto error;
1527 }
1528 }
1529 }
1530 if (!PyErr_Occurred()) {
1531 Py_DECREF(iterator);
1532 return 1;
1533 }
1534
1535 error:
1536 Py_DECREF(iterator);
1537 return 0;
1538 }
1539 #endif /* HAVE_SIGSET_T */
1540
1541 #ifdef MS_WINDOWS
1542
1543 static int
win32_get_reparse_tag(HANDLE reparse_point_handle,ULONG * reparse_tag)1544 win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1545 {
1546 char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1547 _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1548 DWORD n_bytes_returned;
1549
1550 if (0 == DeviceIoControl(
1551 reparse_point_handle,
1552 FSCTL_GET_REPARSE_POINT,
1553 NULL, 0, /* in buffer */
1554 target_buffer, sizeof(target_buffer),
1555 &n_bytes_returned,
1556 NULL)) /* we're not using OVERLAPPED_IO */
1557 return FALSE;
1558
1559 if (reparse_tag)
1560 *reparse_tag = rdb->ReparseTag;
1561
1562 return TRUE;
1563 }
1564
1565 #endif /* MS_WINDOWS */
1566
1567 /* Return a dictionary corresponding to the POSIX environment table */
1568 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1569 /* On Darwin/MacOSX a shared library or framework has no access to
1570 ** environ directly, we must obtain it with _NSGetEnviron(). See also
1571 ** man environ(7).
1572 */
1573 #include <crt_externs.h>
1574 #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1575 extern char **environ;
1576 #endif /* !_MSC_VER */
1577
1578 static PyObject *
convertenviron(void)1579 convertenviron(void)
1580 {
1581 PyObject *d;
1582 #ifdef MS_WINDOWS
1583 wchar_t **e;
1584 #else
1585 char **e;
1586 #endif
1587
1588 d = PyDict_New();
1589 if (d == NULL)
1590 return NULL;
1591 #ifdef MS_WINDOWS
1592 /* _wenviron must be initialized in this way if the program is started
1593 through main() instead of wmain(). */
1594 _wgetenv(L"");
1595 e = _wenviron;
1596 #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1597 /* environ is not accessible as an extern in a shared object on OSX; use
1598 _NSGetEnviron to resolve it. The value changes if you add environment
1599 variables between calls to Py_Initialize, so don't cache the value. */
1600 e = *_NSGetEnviron();
1601 #else
1602 e = environ;
1603 #endif
1604 if (e == NULL)
1605 return d;
1606 for (; *e != NULL; e++) {
1607 PyObject *k;
1608 PyObject *v;
1609 #ifdef MS_WINDOWS
1610 const wchar_t *p = wcschr(*e, L'=');
1611 #else
1612 const char *p = strchr(*e, '=');
1613 #endif
1614 if (p == NULL)
1615 continue;
1616 #ifdef MS_WINDOWS
1617 k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1618 #else
1619 k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1620 #endif
1621 if (k == NULL) {
1622 Py_DECREF(d);
1623 return NULL;
1624 }
1625 #ifdef MS_WINDOWS
1626 v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1627 #else
1628 v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1629 #endif
1630 if (v == NULL) {
1631 Py_DECREF(k);
1632 Py_DECREF(d);
1633 return NULL;
1634 }
1635 if (PyDict_SetDefault(d, k, v) == NULL) {
1636 Py_DECREF(v);
1637 Py_DECREF(k);
1638 Py_DECREF(d);
1639 return NULL;
1640 }
1641 Py_DECREF(k);
1642 Py_DECREF(v);
1643 }
1644 return d;
1645 }
1646
1647 /* Set a POSIX-specific error from errno, and return NULL */
1648
1649 static PyObject *
posix_error(void)1650 posix_error(void)
1651 {
1652 return PyErr_SetFromErrno(PyExc_OSError);
1653 }
1654
1655 #ifdef MS_WINDOWS
1656 static PyObject *
win32_error(const char * function,const char * filename)1657 win32_error(const char* function, const char* filename)
1658 {
1659 /* XXX We should pass the function name along in the future.
1660 (winreg.c also wants to pass the function name.)
1661 This would however require an additional param to the
1662 Windows error object, which is non-trivial.
1663 */
1664 errno = GetLastError();
1665 if (filename)
1666 return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1667 else
1668 return PyErr_SetFromWindowsErr(errno);
1669 }
1670
1671 static PyObject *
win32_error_object_err(const char * function,PyObject * filename,DWORD err)1672 win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1673 {
1674 /* XXX - see win32_error for comments on 'function' */
1675 if (filename)
1676 return PyErr_SetExcFromWindowsErrWithFilenameObject(
1677 PyExc_OSError,
1678 err,
1679 filename);
1680 else
1681 return PyErr_SetFromWindowsErr(err);
1682 }
1683
1684 static PyObject *
win32_error_object(const char * function,PyObject * filename)1685 win32_error_object(const char* function, PyObject* filename)
1686 {
1687 errno = GetLastError();
1688 return win32_error_object_err(function, filename, errno);
1689 }
1690
1691 #endif /* MS_WINDOWS */
1692
1693 static PyObject *
posix_path_object_error(PyObject * path)1694 posix_path_object_error(PyObject *path)
1695 {
1696 return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1697 }
1698
1699 static PyObject *
path_object_error(PyObject * path)1700 path_object_error(PyObject *path)
1701 {
1702 #ifdef MS_WINDOWS
1703 return PyErr_SetExcFromWindowsErrWithFilenameObject(
1704 PyExc_OSError, 0, path);
1705 #else
1706 return posix_path_object_error(path);
1707 #endif
1708 }
1709
1710 static PyObject *
path_object_error2(PyObject * path,PyObject * path2)1711 path_object_error2(PyObject *path, PyObject *path2)
1712 {
1713 #ifdef MS_WINDOWS
1714 return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1715 PyExc_OSError, 0, path, path2);
1716 #else
1717 return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1718 #endif
1719 }
1720
1721 static PyObject *
path_error(path_t * path)1722 path_error(path_t *path)
1723 {
1724 return path_object_error(path->object);
1725 }
1726
1727 static PyObject *
posix_path_error(path_t * path)1728 posix_path_error(path_t *path)
1729 {
1730 return posix_path_object_error(path->object);
1731 }
1732
1733 static PyObject *
path_error2(path_t * path,path_t * path2)1734 path_error2(path_t *path, path_t *path2)
1735 {
1736 return path_object_error2(path->object, path2->object);
1737 }
1738
1739
1740 /* POSIX generic methods */
1741
1742 static PyObject *
posix_fildes_fd(int fd,int (* func)(int))1743 posix_fildes_fd(int fd, int (*func)(int))
1744 {
1745 int res;
1746 int async_err = 0;
1747
1748 do {
1749 Py_BEGIN_ALLOW_THREADS
1750 _Py_BEGIN_SUPPRESS_IPH
1751 res = (*func)(fd);
1752 _Py_END_SUPPRESS_IPH
1753 Py_END_ALLOW_THREADS
1754 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1755 if (res != 0)
1756 return (!async_err) ? posix_error() : NULL;
1757 Py_RETURN_NONE;
1758 }
1759
1760
1761 #ifdef MS_WINDOWS
1762 /* This is a reimplementation of the C library's chdir function,
1763 but one that produces Win32 errors instead of DOS error codes.
1764 chdir is essentially a wrapper around SetCurrentDirectory; however,
1765 it also needs to set "magic" environment variables indicating
1766 the per-drive current directory, which are of the form =<drive>: */
1767 static BOOL __stdcall
win32_wchdir(LPCWSTR path)1768 win32_wchdir(LPCWSTR path)
1769 {
1770 wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1771 int result;
1772 wchar_t env[4] = L"=x:";
1773
1774 if(!SetCurrentDirectoryW(path))
1775 return FALSE;
1776 result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1777 if (!result)
1778 return FALSE;
1779 if (result > Py_ARRAY_LENGTH(path_buf)) {
1780 new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1781 if (!new_path) {
1782 SetLastError(ERROR_OUTOFMEMORY);
1783 return FALSE;
1784 }
1785 result = GetCurrentDirectoryW(result, new_path);
1786 if (!result) {
1787 PyMem_RawFree(new_path);
1788 return FALSE;
1789 }
1790 }
1791 int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1792 wcsncmp(new_path, L"//", 2) == 0);
1793 if (!is_unc_like_path) {
1794 env[1] = new_path[0];
1795 result = SetEnvironmentVariableW(env, new_path);
1796 }
1797 if (new_path != path_buf)
1798 PyMem_RawFree(new_path);
1799 return result ? TRUE : FALSE;
1800 }
1801 #endif
1802
1803 #ifdef MS_WINDOWS
1804 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1805 - time stamps are restricted to second resolution
1806 - file modification times suffer from forth-and-back conversions between
1807 UTC and local time
1808 Therefore, we implement our own stat, based on the Win32 API directly.
1809 */
1810 #define HAVE_STAT_NSEC 1
1811 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1812 #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1813
1814 static void
find_data_to_file_info(WIN32_FIND_DATAW * pFileData,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1815 find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1816 BY_HANDLE_FILE_INFORMATION *info,
1817 ULONG *reparse_tag)
1818 {
1819 memset(info, 0, sizeof(*info));
1820 info->dwFileAttributes = pFileData->dwFileAttributes;
1821 info->ftCreationTime = pFileData->ftCreationTime;
1822 info->ftLastAccessTime = pFileData->ftLastAccessTime;
1823 info->ftLastWriteTime = pFileData->ftLastWriteTime;
1824 info->nFileSizeHigh = pFileData->nFileSizeHigh;
1825 info->nFileSizeLow = pFileData->nFileSizeLow;
1826 /* info->nNumberOfLinks = 1; */
1827 if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1828 *reparse_tag = pFileData->dwReserved0;
1829 else
1830 *reparse_tag = 0;
1831 }
1832
1833 static BOOL
attributes_from_dir(LPCWSTR pszFile,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1834 attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1835 {
1836 HANDLE hFindFile;
1837 WIN32_FIND_DATAW FileData;
1838 LPCWSTR filename = pszFile;
1839 size_t n = wcslen(pszFile);
1840 if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
1841 // cannot use PyMem_Malloc here because we do not hold the GIL
1842 filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
1843 wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
1844 while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
1845 ((LPWSTR)filename)[n] = L'\0';
1846 }
1847 if (!n || (n == 1 && filename[1] == L':')) {
1848 // Nothing left to query
1849 free((void *)filename);
1850 return FALSE;
1851 }
1852 }
1853 hFindFile = FindFirstFileW(filename, &FileData);
1854 if (pszFile != filename) {
1855 free((void *)filename);
1856 }
1857 if (hFindFile == INVALID_HANDLE_VALUE) {
1858 return FALSE;
1859 }
1860 FindClose(hFindFile);
1861 find_data_to_file_info(&FileData, info, reparse_tag);
1862 return TRUE;
1863 }
1864
1865 static int
win32_xstat_impl(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1866 win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1867 BOOL traverse)
1868 {
1869 HANDLE hFile;
1870 BY_HANDLE_FILE_INFORMATION fileInfo;
1871 FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1872 DWORD fileType, error;
1873 BOOL isUnhandledTag = FALSE;
1874 int retval = 0;
1875
1876 DWORD access = FILE_READ_ATTRIBUTES;
1877 DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1878 if (!traverse) {
1879 flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1880 }
1881
1882 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1883 if (hFile == INVALID_HANDLE_VALUE) {
1884 /* Either the path doesn't exist, or the caller lacks access. */
1885 error = GetLastError();
1886 switch (error) {
1887 case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */
1888 case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1889 /* Try reading the parent directory. */
1890 if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1891 /* Cannot read the parent directory. */
1892 SetLastError(error);
1893 return -1;
1894 }
1895 if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1896 if (traverse ||
1897 !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1898 /* The stat call has to traverse but cannot, so fail. */
1899 SetLastError(error);
1900 return -1;
1901 }
1902 }
1903 break;
1904
1905 case ERROR_INVALID_PARAMETER:
1906 /* \\.\con requires read or write access. */
1907 hFile = CreateFileW(path, access | GENERIC_READ,
1908 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1909 OPEN_EXISTING, flags, NULL);
1910 if (hFile == INVALID_HANDLE_VALUE) {
1911 SetLastError(error);
1912 return -1;
1913 }
1914 break;
1915
1916 case ERROR_CANT_ACCESS_FILE:
1917 /* bpo37834: open unhandled reparse points if traverse fails. */
1918 if (traverse) {
1919 traverse = FALSE;
1920 isUnhandledTag = TRUE;
1921 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1922 flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1923 }
1924 if (hFile == INVALID_HANDLE_VALUE) {
1925 SetLastError(error);
1926 return -1;
1927 }
1928 break;
1929
1930 default:
1931 return -1;
1932 }
1933 }
1934
1935 if (hFile != INVALID_HANDLE_VALUE) {
1936 /* Handle types other than files on disk. */
1937 fileType = GetFileType(hFile);
1938 if (fileType != FILE_TYPE_DISK) {
1939 if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1940 retval = -1;
1941 goto cleanup;
1942 }
1943 DWORD fileAttributes = GetFileAttributesW(path);
1944 memset(result, 0, sizeof(*result));
1945 if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1946 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1947 /* \\.\pipe\ or \\.\mailslot\ */
1948 result->st_mode = _S_IFDIR;
1949 } else if (fileType == FILE_TYPE_CHAR) {
1950 /* \\.\nul */
1951 result->st_mode = _S_IFCHR;
1952 } else if (fileType == FILE_TYPE_PIPE) {
1953 /* \\.\pipe\spam */
1954 result->st_mode = _S_IFIFO;
1955 }
1956 /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1957 goto cleanup;
1958 }
1959
1960 /* Query the reparse tag, and traverse a non-link. */
1961 if (!traverse) {
1962 if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
1963 &tagInfo, sizeof(tagInfo))) {
1964 /* Allow devices that do not support FileAttributeTagInfo. */
1965 switch (GetLastError()) {
1966 case ERROR_INVALID_PARAMETER:
1967 case ERROR_INVALID_FUNCTION:
1968 case ERROR_NOT_SUPPORTED:
1969 tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1970 tagInfo.ReparseTag = 0;
1971 break;
1972 default:
1973 retval = -1;
1974 goto cleanup;
1975 }
1976 } else if (tagInfo.FileAttributes &
1977 FILE_ATTRIBUTE_REPARSE_POINT) {
1978 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1979 if (isUnhandledTag) {
1980 /* Traversing previously failed for either this link
1981 or its target. */
1982 SetLastError(ERROR_CANT_ACCESS_FILE);
1983 retval = -1;
1984 goto cleanup;
1985 }
1986 /* Traverse a non-link, but not if traversing already failed
1987 for an unhandled tag. */
1988 } else if (!isUnhandledTag) {
1989 CloseHandle(hFile);
1990 return win32_xstat_impl(path, result, TRUE);
1991 }
1992 }
1993 }
1994
1995 if (!GetFileInformationByHandle(hFile, &fileInfo)) {
1996 switch (GetLastError()) {
1997 case ERROR_INVALID_PARAMETER:
1998 case ERROR_INVALID_FUNCTION:
1999 case ERROR_NOT_SUPPORTED:
2000 /* Volumes and physical disks are block devices, e.g.
2001 \\.\C: and \\.\PhysicalDrive0. */
2002 memset(result, 0, sizeof(*result));
2003 result->st_mode = 0x6000; /* S_IFBLK */
2004 goto cleanup;
2005 }
2006 retval = -1;
2007 goto cleanup;
2008 }
2009 }
2010
2011 _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
2012
2013 if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
2014 /* Fix the file execute permissions. This hack sets S_IEXEC if
2015 the filename has an extension that is commonly used by files
2016 that CreateProcessW can execute. A real implementation calls
2017 GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2018 AccessCheck to check for generic read, write, and execute
2019 access. */
2020 const wchar_t *fileExtension = wcsrchr(path, '.');
2021 if (fileExtension) {
2022 if (_wcsicmp(fileExtension, L".exe") == 0 ||
2023 _wcsicmp(fileExtension, L".bat") == 0 ||
2024 _wcsicmp(fileExtension, L".cmd") == 0 ||
2025 _wcsicmp(fileExtension, L".com") == 0) {
2026 result->st_mode |= 0111;
2027 }
2028 }
2029 }
2030
2031 cleanup:
2032 if (hFile != INVALID_HANDLE_VALUE) {
2033 /* Preserve last error if we are failing */
2034 error = retval ? GetLastError() : 0;
2035 if (!CloseHandle(hFile)) {
2036 retval = -1;
2037 } else if (retval) {
2038 /* Restore last error */
2039 SetLastError(error);
2040 }
2041 }
2042
2043 return retval;
2044 }
2045
2046 static int
win32_xstat(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)2047 win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2048 {
2049 /* Protocol violation: we explicitly clear errno, instead of
2050 setting it to a POSIX error. Callers should use GetLastError. */
2051 int code = win32_xstat_impl(path, result, traverse);
2052 errno = 0;
2053 return code;
2054 }
2055 /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2056
2057 In Posix, stat automatically traverses symlinks and returns the stat
2058 structure for the target. In Windows, the equivalent GetFileAttributes by
2059 default does not traverse symlinks and instead returns attributes for
2060 the symlink.
2061
2062 Instead, we will open the file (which *does* traverse symlinks by default)
2063 and GetFileInformationByHandle(). */
2064
2065 static int
win32_lstat(const wchar_t * path,struct _Py_stat_struct * result)2066 win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2067 {
2068 return win32_xstat(path, result, FALSE);
2069 }
2070
2071 static int
win32_stat(const wchar_t * path,struct _Py_stat_struct * result)2072 win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2073 {
2074 return win32_xstat(path, result, TRUE);
2075 }
2076
2077 #endif /* MS_WINDOWS */
2078
2079 PyDoc_STRVAR(stat_result__doc__,
2080 "stat_result: Result from stat, fstat, or lstat.\n\n\
2081 This object may be accessed either as a tuple of\n\
2082 (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2083 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2084 \n\
2085 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2086 or st_flags, they are available as attributes only.\n\
2087 \n\
2088 See os.stat for more information.");
2089
2090 static PyStructSequence_Field stat_result_fields[] = {
2091 {"st_mode", "protection bits"},
2092 {"st_ino", "inode"},
2093 {"st_dev", "device"},
2094 {"st_nlink", "number of hard links"},
2095 {"st_uid", "user ID of owner"},
2096 {"st_gid", "group ID of owner"},
2097 {"st_size", "total size, in bytes"},
2098 /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2099 {NULL, "integer time of last access"},
2100 {NULL, "integer time of last modification"},
2101 {NULL, "integer time of last change"},
2102 {"st_atime", "time of last access"},
2103 {"st_mtime", "time of last modification"},
2104 {"st_ctime", "time of last change"},
2105 {"st_atime_ns", "time of last access in nanoseconds"},
2106 {"st_mtime_ns", "time of last modification in nanoseconds"},
2107 {"st_ctime_ns", "time of last change in nanoseconds"},
2108 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2109 {"st_blksize", "blocksize for filesystem I/O"},
2110 #endif
2111 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2112 {"st_blocks", "number of blocks allocated"},
2113 #endif
2114 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2115 {"st_rdev", "device type (if inode device)"},
2116 #endif
2117 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2118 {"st_flags", "user defined flags for file"},
2119 #endif
2120 #ifdef HAVE_STRUCT_STAT_ST_GEN
2121 {"st_gen", "generation number"},
2122 #endif
2123 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2124 {"st_birthtime", "time of creation"},
2125 #endif
2126 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2127 {"st_file_attributes", "Windows file attribute bits"},
2128 #endif
2129 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2130 {"st_fstype", "Type of filesystem"},
2131 #endif
2132 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2133 {"st_reparse_tag", "Windows reparse tag"},
2134 #endif
2135 {0}
2136 };
2137
2138 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2139 #define ST_BLKSIZE_IDX 16
2140 #else
2141 #define ST_BLKSIZE_IDX 15
2142 #endif
2143
2144 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2145 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2146 #else
2147 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2148 #endif
2149
2150 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2151 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2152 #else
2153 #define ST_RDEV_IDX ST_BLOCKS_IDX
2154 #endif
2155
2156 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2157 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2158 #else
2159 #define ST_FLAGS_IDX ST_RDEV_IDX
2160 #endif
2161
2162 #ifdef HAVE_STRUCT_STAT_ST_GEN
2163 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
2164 #else
2165 #define ST_GEN_IDX ST_FLAGS_IDX
2166 #endif
2167
2168 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2169 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2170 #else
2171 #define ST_BIRTHTIME_IDX ST_GEN_IDX
2172 #endif
2173
2174 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2175 #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
2176 #else
2177 #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
2178 #endif
2179
2180 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2181 #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2182 #else
2183 #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2184 #endif
2185
2186 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2187 #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2188 #else
2189 #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2190 #endif
2191
2192 static PyStructSequence_Desc stat_result_desc = {
2193 "stat_result", /* name */
2194 stat_result__doc__, /* doc */
2195 stat_result_fields,
2196 10
2197 };
2198
2199 PyDoc_STRVAR(statvfs_result__doc__,
2200 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
2201 This object may be accessed either as a tuple of\n\
2202 (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2203 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2204 \n\
2205 See os.statvfs for more information.");
2206
2207 static PyStructSequence_Field statvfs_result_fields[] = {
2208 {"f_bsize", },
2209 {"f_frsize", },
2210 {"f_blocks", },
2211 {"f_bfree", },
2212 {"f_bavail", },
2213 {"f_files", },
2214 {"f_ffree", },
2215 {"f_favail", },
2216 {"f_flag", },
2217 {"f_namemax",},
2218 {"f_fsid", },
2219 {0}
2220 };
2221
2222 static PyStructSequence_Desc statvfs_result_desc = {
2223 "statvfs_result", /* name */
2224 statvfs_result__doc__, /* doc */
2225 statvfs_result_fields,
2226 10
2227 };
2228
2229 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2230 PyDoc_STRVAR(waitid_result__doc__,
2231 "waitid_result: Result from waitid.\n\n\
2232 This object may be accessed either as a tuple of\n\
2233 (si_pid, si_uid, si_signo, si_status, si_code),\n\
2234 or via the attributes si_pid, si_uid, and so on.\n\
2235 \n\
2236 See os.waitid for more information.");
2237
2238 static PyStructSequence_Field waitid_result_fields[] = {
2239 {"si_pid", },
2240 {"si_uid", },
2241 {"si_signo", },
2242 {"si_status", },
2243 {"si_code", },
2244 {0}
2245 };
2246
2247 static PyStructSequence_Desc waitid_result_desc = {
2248 "waitid_result", /* name */
2249 waitid_result__doc__, /* doc */
2250 waitid_result_fields,
2251 5
2252 };
2253 #endif
2254 static newfunc structseq_new;
2255
2256 static PyObject *
statresult_new(PyTypeObject * type,PyObject * args,PyObject * kwds)2257 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2258 {
2259 PyStructSequence *result;
2260 int i;
2261
2262 result = (PyStructSequence*)structseq_new(type, args, kwds);
2263 if (!result)
2264 return NULL;
2265 /* If we have been initialized from a tuple,
2266 st_?time might be set to None. Initialize it
2267 from the int slots. */
2268 for (i = 7; i <= 9; i++) {
2269 if (result->ob_item[i+3] == Py_None) {
2270 Py_DECREF(Py_None);
2271 Py_INCREF(result->ob_item[i]);
2272 result->ob_item[i+3] = result->ob_item[i];
2273 }
2274 }
2275 return (PyObject*)result;
2276 }
2277
2278 static int
_posix_clear(PyObject * module)2279 _posix_clear(PyObject *module)
2280 {
2281 _posixstate *state = get_posix_state(module);
2282 Py_CLEAR(state->billion);
2283 Py_CLEAR(state->DirEntryType);
2284 Py_CLEAR(state->ScandirIteratorType);
2285 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2286 Py_CLEAR(state->SchedParamType);
2287 #endif
2288 Py_CLEAR(state->StatResultType);
2289 Py_CLEAR(state->StatVFSResultType);
2290 Py_CLEAR(state->TerminalSizeType);
2291 Py_CLEAR(state->TimesResultType);
2292 Py_CLEAR(state->UnameResultType);
2293 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2294 Py_CLEAR(state->WaitidResultType);
2295 #endif
2296 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2297 Py_CLEAR(state->struct_rusage);
2298 #endif
2299 Py_CLEAR(state->st_mode);
2300 return 0;
2301 }
2302
2303 static int
_posix_traverse(PyObject * module,visitproc visit,void * arg)2304 _posix_traverse(PyObject *module, visitproc visit, void *arg)
2305 {
2306 _posixstate *state = get_posix_state(module);
2307 Py_VISIT(state->billion);
2308 Py_VISIT(state->DirEntryType);
2309 Py_VISIT(state->ScandirIteratorType);
2310 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2311 Py_VISIT(state->SchedParamType);
2312 #endif
2313 Py_VISIT(state->StatResultType);
2314 Py_VISIT(state->StatVFSResultType);
2315 Py_VISIT(state->TerminalSizeType);
2316 Py_VISIT(state->TimesResultType);
2317 Py_VISIT(state->UnameResultType);
2318 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2319 Py_VISIT(state->WaitidResultType);
2320 #endif
2321 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2322 Py_VISIT(state->struct_rusage);
2323 #endif
2324 Py_VISIT(state->st_mode);
2325 return 0;
2326 }
2327
2328 static void
_posix_free(void * module)2329 _posix_free(void *module)
2330 {
2331 _posix_clear((PyObject *)module);
2332 }
2333
2334 static void
fill_time(PyObject * module,PyObject * v,int index,time_t sec,unsigned long nsec)2335 fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)
2336 {
2337 PyObject *s = _PyLong_FromTime_t(sec);
2338 PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2339 PyObject *s_in_ns = NULL;
2340 PyObject *ns_total = NULL;
2341 PyObject *float_s = NULL;
2342
2343 if (!(s && ns_fractional))
2344 goto exit;
2345
2346 s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2347 if (!s_in_ns)
2348 goto exit;
2349
2350 ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2351 if (!ns_total)
2352 goto exit;
2353
2354 float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2355 if (!float_s) {
2356 goto exit;
2357 }
2358
2359 PyStructSequence_SET_ITEM(v, index, s);
2360 PyStructSequence_SET_ITEM(v, index+3, float_s);
2361 PyStructSequence_SET_ITEM(v, index+6, ns_total);
2362 s = NULL;
2363 float_s = NULL;
2364 ns_total = NULL;
2365 exit:
2366 Py_XDECREF(s);
2367 Py_XDECREF(ns_fractional);
2368 Py_XDECREF(s_in_ns);
2369 Py_XDECREF(ns_total);
2370 Py_XDECREF(float_s);
2371 }
2372
2373 /* pack a system stat C structure into the Python stat tuple
2374 (used by posix_stat() and posix_fstat()) */
2375 static PyObject*
_pystat_fromstructstat(PyObject * module,STRUCT_STAT * st)2376 _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2377 {
2378 unsigned long ansec, mnsec, cnsec;
2379 PyObject *StatResultType = get_posix_state(module)->StatResultType;
2380 PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2381 if (v == NULL)
2382 return NULL;
2383
2384 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2385 Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(st->st_ino));
2386 PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2387 #ifdef MS_WINDOWS
2388 PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
2389 #else
2390 PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2391 #endif
2392 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2393 #if defined(MS_WINDOWS)
2394 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2395 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2396 #else
2397 PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2398 PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2399 #endif
2400 Py_BUILD_ASSERT(sizeof(long long) >= sizeof(st->st_size));
2401 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2402
2403 #if defined(HAVE_STAT_TV_NSEC)
2404 ansec = st->st_atim.tv_nsec;
2405 mnsec = st->st_mtim.tv_nsec;
2406 cnsec = st->st_ctim.tv_nsec;
2407 #elif defined(HAVE_STAT_TV_NSEC2)
2408 ansec = st->st_atimespec.tv_nsec;
2409 mnsec = st->st_mtimespec.tv_nsec;
2410 cnsec = st->st_ctimespec.tv_nsec;
2411 #elif defined(HAVE_STAT_NSEC)
2412 ansec = st->st_atime_nsec;
2413 mnsec = st->st_mtime_nsec;
2414 cnsec = st->st_ctime_nsec;
2415 #else
2416 ansec = mnsec = cnsec = 0;
2417 #endif
2418 fill_time(module, v, 7, st->st_atime, ansec);
2419 fill_time(module, v, 8, st->st_mtime, mnsec);
2420 fill_time(module, v, 9, st->st_ctime, cnsec);
2421
2422 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2423 PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2424 PyLong_FromLong((long)st->st_blksize));
2425 #endif
2426 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2427 PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2428 PyLong_FromLong((long)st->st_blocks));
2429 #endif
2430 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2431 PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2432 PyLong_FromLong((long)st->st_rdev));
2433 #endif
2434 #ifdef HAVE_STRUCT_STAT_ST_GEN
2435 PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2436 PyLong_FromLong((long)st->st_gen));
2437 #endif
2438 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2439 {
2440 PyObject *val;
2441 unsigned long bsec,bnsec;
2442 bsec = (long)st->st_birthtime;
2443 #ifdef HAVE_STAT_TV_NSEC2
2444 bnsec = st->st_birthtimespec.tv_nsec;
2445 #else
2446 bnsec = 0;
2447 #endif
2448 val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2449 PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2450 val);
2451 }
2452 #endif
2453 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2454 PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2455 PyLong_FromLong((long)st->st_flags));
2456 #endif
2457 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2458 PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2459 PyLong_FromUnsignedLong(st->st_file_attributes));
2460 #endif
2461 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2462 PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2463 PyUnicode_FromString(st->st_fstype));
2464 #endif
2465 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2466 PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2467 PyLong_FromUnsignedLong(st->st_reparse_tag));
2468 #endif
2469
2470 if (PyErr_Occurred()) {
2471 Py_DECREF(v);
2472 return NULL;
2473 }
2474
2475 return v;
2476 }
2477
2478 /* POSIX methods */
2479
2480
2481 static PyObject *
posix_do_stat(PyObject * module,const char * function_name,path_t * path,int dir_fd,int follow_symlinks)2482 posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2483 int dir_fd, int follow_symlinks)
2484 {
2485 STRUCT_STAT st;
2486 int result;
2487
2488 #ifdef HAVE_FSTATAT
2489 int fstatat_unavailable = 0;
2490 #endif
2491
2492 #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2493 if (follow_symlinks_specified(function_name, follow_symlinks))
2494 return NULL;
2495 #endif
2496
2497 if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2498 dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2499 fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2500 return NULL;
2501
2502 Py_BEGIN_ALLOW_THREADS
2503 if (path->fd != -1)
2504 result = FSTAT(path->fd, &st);
2505 #ifdef MS_WINDOWS
2506 else if (follow_symlinks)
2507 result = win32_stat(path->wide, &st);
2508 else
2509 result = win32_lstat(path->wide, &st);
2510 #else
2511 else
2512 #if defined(HAVE_LSTAT)
2513 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2514 result = LSTAT(path->narrow, &st);
2515 else
2516 #endif /* HAVE_LSTAT */
2517 #ifdef HAVE_FSTATAT
2518 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2519 if (HAVE_FSTATAT_RUNTIME) {
2520 result = fstatat(dir_fd, path->narrow, &st,
2521 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2522
2523 } else {
2524 fstatat_unavailable = 1;
2525 }
2526 } else
2527 #endif /* HAVE_FSTATAT */
2528 result = STAT(path->narrow, &st);
2529 #endif /* MS_WINDOWS */
2530 Py_END_ALLOW_THREADS
2531
2532 #ifdef HAVE_FSTATAT
2533 if (fstatat_unavailable) {
2534 argument_unavailable_error("stat", "dir_fd");
2535 return NULL;
2536 }
2537 #endif
2538
2539 if (result != 0) {
2540 return path_error(path);
2541 }
2542
2543 return _pystat_fromstructstat(module, &st);
2544 }
2545
2546 /*[python input]
2547
2548 for s in """
2549
2550 FACCESSAT
2551 FCHMODAT
2552 FCHOWNAT
2553 FSTATAT
2554 LINKAT
2555 MKDIRAT
2556 MKFIFOAT
2557 MKNODAT
2558 OPENAT
2559 READLINKAT
2560 SYMLINKAT
2561 UNLINKAT
2562
2563 """.strip().split():
2564 s = s.strip()
2565 print("""
2566 #ifdef HAVE_{s}
2567 #define {s}_DIR_FD_CONVERTER dir_fd_converter
2568 #else
2569 #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2570 #endif
2571 """.rstrip().format(s=s))
2572
2573 for s in """
2574
2575 FCHDIR
2576 FCHMOD
2577 FCHOWN
2578 FDOPENDIR
2579 FEXECVE
2580 FPATHCONF
2581 FSTATVFS
2582 FTRUNCATE
2583
2584 """.strip().split():
2585 s = s.strip()
2586 print("""
2587 #ifdef HAVE_{s}
2588 #define PATH_HAVE_{s} 1
2589 #else
2590 #define PATH_HAVE_{s} 0
2591 #endif
2592
2593 """.rstrip().format(s=s))
2594 [python start generated code]*/
2595
2596 #ifdef HAVE_FACCESSAT
2597 #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2598 #else
2599 #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2600 #endif
2601
2602 #ifdef HAVE_FCHMODAT
2603 #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2604 #else
2605 #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2606 #endif
2607
2608 #ifdef HAVE_FCHOWNAT
2609 #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2610 #else
2611 #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2612 #endif
2613
2614 #ifdef HAVE_FSTATAT
2615 #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2616 #else
2617 #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2618 #endif
2619
2620 #ifdef HAVE_LINKAT
2621 #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2622 #else
2623 #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2624 #endif
2625
2626 #ifdef HAVE_MKDIRAT
2627 #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2628 #else
2629 #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2630 #endif
2631
2632 #ifdef HAVE_MKFIFOAT
2633 #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2634 #else
2635 #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2636 #endif
2637
2638 #ifdef HAVE_MKNODAT
2639 #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2640 #else
2641 #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2642 #endif
2643
2644 #ifdef HAVE_OPENAT
2645 #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2646 #else
2647 #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2648 #endif
2649
2650 #ifdef HAVE_READLINKAT
2651 #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2652 #else
2653 #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2654 #endif
2655
2656 #ifdef HAVE_SYMLINKAT
2657 #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2658 #else
2659 #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2660 #endif
2661
2662 #ifdef HAVE_UNLINKAT
2663 #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2664 #else
2665 #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2666 #endif
2667
2668 #ifdef HAVE_FCHDIR
2669 #define PATH_HAVE_FCHDIR 1
2670 #else
2671 #define PATH_HAVE_FCHDIR 0
2672 #endif
2673
2674 #ifdef HAVE_FCHMOD
2675 #define PATH_HAVE_FCHMOD 1
2676 #else
2677 #define PATH_HAVE_FCHMOD 0
2678 #endif
2679
2680 #ifdef HAVE_FCHOWN
2681 #define PATH_HAVE_FCHOWN 1
2682 #else
2683 #define PATH_HAVE_FCHOWN 0
2684 #endif
2685
2686 #ifdef HAVE_FDOPENDIR
2687 #define PATH_HAVE_FDOPENDIR 1
2688 #else
2689 #define PATH_HAVE_FDOPENDIR 0
2690 #endif
2691
2692 #ifdef HAVE_FEXECVE
2693 #define PATH_HAVE_FEXECVE 1
2694 #else
2695 #define PATH_HAVE_FEXECVE 0
2696 #endif
2697
2698 #ifdef HAVE_FPATHCONF
2699 #define PATH_HAVE_FPATHCONF 1
2700 #else
2701 #define PATH_HAVE_FPATHCONF 0
2702 #endif
2703
2704 #ifdef HAVE_FSTATVFS
2705 #define PATH_HAVE_FSTATVFS 1
2706 #else
2707 #define PATH_HAVE_FSTATVFS 0
2708 #endif
2709
2710 #ifdef HAVE_FTRUNCATE
2711 #define PATH_HAVE_FTRUNCATE 1
2712 #else
2713 #define PATH_HAVE_FTRUNCATE 0
2714 #endif
2715 /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2716
2717 #ifdef MS_WINDOWS
2718 #undef PATH_HAVE_FTRUNCATE
2719 #define PATH_HAVE_FTRUNCATE 1
2720 #endif
2721
2722 /*[python input]
2723
2724 class path_t_converter(CConverter):
2725
2726 type = "path_t"
2727 impl_by_reference = True
2728 parse_by_reference = True
2729
2730 converter = 'path_converter'
2731
2732 def converter_init(self, *, allow_fd=False, nullable=False):
2733 # right now path_t doesn't support default values.
2734 # to support a default value, you'll need to override initialize().
2735 if self.default not in (unspecified, None):
2736 fail("Can't specify a default to the path_t converter!")
2737
2738 if self.c_default not in (None, 'Py_None'):
2739 raise RuntimeError("Can't specify a c_default to the path_t converter!")
2740
2741 self.nullable = nullable
2742 self.allow_fd = allow_fd
2743
2744 def pre_render(self):
2745 def strify(value):
2746 if isinstance(value, str):
2747 return value
2748 return str(int(bool(value)))
2749
2750 # add self.py_name here when merging with posixmodule conversion
2751 self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2752 self.function.name,
2753 self.name,
2754 strify(self.nullable),
2755 strify(self.allow_fd),
2756 )
2757
2758 def cleanup(self):
2759 return "path_cleanup(&" + self.name + ");\n"
2760
2761
2762 class dir_fd_converter(CConverter):
2763 type = 'int'
2764
2765 def converter_init(self, requires=None):
2766 if self.default in (unspecified, None):
2767 self.c_default = 'DEFAULT_DIR_FD'
2768 if isinstance(requires, str):
2769 self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2770 else:
2771 self.converter = 'dir_fd_converter'
2772
2773 class uid_t_converter(CConverter):
2774 type = "uid_t"
2775 converter = '_Py_Uid_Converter'
2776
2777 class gid_t_converter(CConverter):
2778 type = "gid_t"
2779 converter = '_Py_Gid_Converter'
2780
2781 class dev_t_converter(CConverter):
2782 type = 'dev_t'
2783 converter = '_Py_Dev_Converter'
2784
2785 class dev_t_return_converter(unsigned_long_return_converter):
2786 type = 'dev_t'
2787 conversion_fn = '_PyLong_FromDev'
2788 unsigned_cast = '(dev_t)'
2789
2790 class FSConverter_converter(CConverter):
2791 type = 'PyObject *'
2792 converter = 'PyUnicode_FSConverter'
2793 def converter_init(self):
2794 if self.default is not unspecified:
2795 fail("FSConverter_converter does not support default values")
2796 self.c_default = 'NULL'
2797
2798 def cleanup(self):
2799 return "Py_XDECREF(" + self.name + ");\n"
2800
2801 class pid_t_converter(CConverter):
2802 type = 'pid_t'
2803 format_unit = '" _Py_PARSE_PID "'
2804
2805 class idtype_t_converter(int_converter):
2806 type = 'idtype_t'
2807
2808 class id_t_converter(CConverter):
2809 type = 'id_t'
2810 format_unit = '" _Py_PARSE_PID "'
2811
2812 class intptr_t_converter(CConverter):
2813 type = 'intptr_t'
2814 format_unit = '" _Py_PARSE_INTPTR "'
2815
2816 class Py_off_t_converter(CConverter):
2817 type = 'Py_off_t'
2818 converter = 'Py_off_t_converter'
2819
2820 class Py_off_t_return_converter(long_return_converter):
2821 type = 'Py_off_t'
2822 conversion_fn = 'PyLong_FromPy_off_t'
2823
2824 class path_confname_converter(CConverter):
2825 type="int"
2826 converter="conv_path_confname"
2827
2828 class confstr_confname_converter(path_confname_converter):
2829 converter='conv_confstr_confname'
2830
2831 class sysconf_confname_converter(path_confname_converter):
2832 converter="conv_sysconf_confname"
2833
2834 [python start generated code]*/
2835 /*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/
2836
2837 /*[clinic input]
2838
2839 os.stat
2840
2841 path : path_t(allow_fd=True)
2842 Path to be examined; can be string, bytes, a path-like object or
2843 open-file-descriptor int.
2844
2845 *
2846
2847 dir_fd : dir_fd(requires='fstatat') = None
2848 If not None, it should be a file descriptor open to a directory,
2849 and path should be a relative string; path will then be relative to
2850 that directory.
2851
2852 follow_symlinks: bool = True
2853 If False, and the last element of the path is a symbolic link,
2854 stat will examine the symbolic link itself instead of the file
2855 the link points to.
2856
2857 Perform a stat system call on the given path.
2858
2859 dir_fd and follow_symlinks may not be implemented
2860 on your platform. If they are unavailable, using them will raise a
2861 NotImplementedError.
2862
2863 It's an error to use dir_fd or follow_symlinks when specifying path as
2864 an open file descriptor.
2865
2866 [clinic start generated code]*/
2867
2868 static PyObject *
os_stat_impl(PyObject * module,path_t * path,int dir_fd,int follow_symlinks)2869 os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2870 /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2871 {
2872 return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
2873 }
2874
2875
2876 /*[clinic input]
2877 os.lstat
2878
2879 path : path_t
2880
2881 *
2882
2883 dir_fd : dir_fd(requires='fstatat') = None
2884
2885 Perform a stat system call on the given path, without following symbolic links.
2886
2887 Like stat(), but do not follow symbolic links.
2888 Equivalent to stat(path, follow_symlinks=False).
2889 [clinic start generated code]*/
2890
2891 static PyObject *
os_lstat_impl(PyObject * module,path_t * path,int dir_fd)2892 os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2893 /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2894 {
2895 int follow_symlinks = 0;
2896 return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
2897 }
2898
2899
2900 /*[clinic input]
2901 os.access -> bool
2902
2903 path: path_t
2904 Path to be tested; can be string, bytes, or a path-like object.
2905
2906 mode: int
2907 Operating-system mode bitfield. Can be F_OK to test existence,
2908 or the inclusive-OR of R_OK, W_OK, and X_OK.
2909
2910 *
2911
2912 dir_fd : dir_fd(requires='faccessat') = None
2913 If not None, it should be a file descriptor open to a directory,
2914 and path should be relative; path will then be relative to that
2915 directory.
2916
2917 effective_ids: bool = False
2918 If True, access will use the effective uid/gid instead of
2919 the real uid/gid.
2920
2921 follow_symlinks: bool = True
2922 If False, and the last element of the path is a symbolic link,
2923 access will examine the symbolic link itself instead of the file
2924 the link points to.
2925
2926 Use the real uid/gid to test for access to a path.
2927
2928 {parameters}
2929 dir_fd, effective_ids, and follow_symlinks may not be implemented
2930 on your platform. If they are unavailable, using them will raise a
2931 NotImplementedError.
2932
2933 Note that most operations will use the effective uid/gid, therefore this
2934 routine can be used in a suid/sgid environment to test if the invoking user
2935 has the specified access to the path.
2936
2937 [clinic start generated code]*/
2938
2939 static int
os_access_impl(PyObject * module,path_t * path,int mode,int dir_fd,int effective_ids,int follow_symlinks)2940 os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2941 int effective_ids, int follow_symlinks)
2942 /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
2943 {
2944 int return_value;
2945
2946 #ifdef MS_WINDOWS
2947 DWORD attr;
2948 #else
2949 int result;
2950 #endif
2951
2952 #ifdef HAVE_FACCESSAT
2953 int faccessat_unavailable = 0;
2954 #endif
2955
2956 #ifndef HAVE_FACCESSAT
2957 if (follow_symlinks_specified("access", follow_symlinks))
2958 return -1;
2959
2960 if (effective_ids) {
2961 argument_unavailable_error("access", "effective_ids");
2962 return -1;
2963 }
2964 #endif
2965
2966 #ifdef MS_WINDOWS
2967 Py_BEGIN_ALLOW_THREADS
2968 attr = GetFileAttributesW(path->wide);
2969 Py_END_ALLOW_THREADS
2970
2971 /*
2972 * Access is possible if
2973 * * we didn't get a -1, and
2974 * * write access wasn't requested,
2975 * * or the file isn't read-only,
2976 * * or it's a directory.
2977 * (Directories cannot be read-only on Windows.)
2978 */
2979 return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
2980 (!(mode & 2) ||
2981 !(attr & FILE_ATTRIBUTE_READONLY) ||
2982 (attr & FILE_ATTRIBUTE_DIRECTORY));
2983 #else
2984
2985 Py_BEGIN_ALLOW_THREADS
2986 #ifdef HAVE_FACCESSAT
2987 if ((dir_fd != DEFAULT_DIR_FD) ||
2988 effective_ids ||
2989 !follow_symlinks) {
2990
2991 if (HAVE_FACCESSAT_RUNTIME) {
2992 int flags = 0;
2993 if (!follow_symlinks)
2994 flags |= AT_SYMLINK_NOFOLLOW;
2995 if (effective_ids)
2996 flags |= AT_EACCESS;
2997 result = faccessat(dir_fd, path->narrow, mode, flags);
2998 } else {
2999 faccessat_unavailable = 1;
3000 }
3001 }
3002 else
3003 #endif
3004 result = access(path->narrow, mode);
3005 Py_END_ALLOW_THREADS
3006
3007 #ifdef HAVE_FACCESSAT
3008 if (faccessat_unavailable) {
3009 if (dir_fd != DEFAULT_DIR_FD) {
3010 argument_unavailable_error("access", "dir_fd");
3011 return -1;
3012 }
3013 if (follow_symlinks_specified("access", follow_symlinks))
3014 return -1;
3015
3016 if (effective_ids) {
3017 argument_unavailable_error("access", "effective_ids");
3018 return -1;
3019 }
3020 /* should be unreachable */
3021 return -1;
3022 }
3023 #endif
3024 return_value = !result;
3025 #endif
3026
3027 return return_value;
3028 }
3029
3030 #ifndef F_OK
3031 #define F_OK 0
3032 #endif
3033 #ifndef R_OK
3034 #define R_OK 4
3035 #endif
3036 #ifndef W_OK
3037 #define W_OK 2
3038 #endif
3039 #ifndef X_OK
3040 #define X_OK 1
3041 #endif
3042
3043
3044 #ifdef HAVE_TTYNAME
3045 /*[clinic input]
3046 os.ttyname
3047
3048 fd: int
3049 Integer file descriptor handle.
3050
3051 /
3052
3053 Return the name of the terminal device connected to 'fd'.
3054 [clinic start generated code]*/
3055
3056 static PyObject *
os_ttyname_impl(PyObject * module,int fd)3057 os_ttyname_impl(PyObject *module, int fd)
3058 /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3059 {
3060
3061 long size = sysconf(_SC_TTY_NAME_MAX);
3062 if (size == -1) {
3063 return posix_error();
3064 }
3065 char *buffer = (char *)PyMem_RawMalloc(size);
3066 if (buffer == NULL) {
3067 return PyErr_NoMemory();
3068 }
3069 int ret = ttyname_r(fd, buffer, size);
3070 if (ret != 0) {
3071 PyMem_RawFree(buffer);
3072 errno = ret;
3073 return posix_error();
3074 }
3075 PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3076 PyMem_RawFree(buffer);
3077 return res;
3078 }
3079 #endif
3080
3081 #ifdef HAVE_CTERMID
3082 /*[clinic input]
3083 os.ctermid
3084
3085 Return the name of the controlling terminal for this process.
3086 [clinic start generated code]*/
3087
3088 static PyObject *
os_ctermid_impl(PyObject * module)3089 os_ctermid_impl(PyObject *module)
3090 /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3091 {
3092 char *ret;
3093 char buffer[L_ctermid];
3094
3095 #ifdef USE_CTERMID_R
3096 ret = ctermid_r(buffer);
3097 #else
3098 ret = ctermid(buffer);
3099 #endif
3100 if (ret == NULL)
3101 return posix_error();
3102 return PyUnicode_DecodeFSDefault(buffer);
3103 }
3104 #endif /* HAVE_CTERMID */
3105
3106
3107 /*[clinic input]
3108 os.chdir
3109
3110 path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3111
3112 Change the current working directory to the specified path.
3113
3114 path may always be specified as a string.
3115 On some platforms, path may also be specified as an open file descriptor.
3116 If this functionality is unavailable, using it raises an exception.
3117 [clinic start generated code]*/
3118
3119 static PyObject *
os_chdir_impl(PyObject * module,path_t * path)3120 os_chdir_impl(PyObject *module, path_t *path)
3121 /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3122 {
3123 int result;
3124
3125 if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3126 return NULL;
3127 }
3128
3129 Py_BEGIN_ALLOW_THREADS
3130 #ifdef MS_WINDOWS
3131 /* on unix, success = 0, on windows, success = !0 */
3132 result = !win32_wchdir(path->wide);
3133 #else
3134 #ifdef HAVE_FCHDIR
3135 if (path->fd != -1)
3136 result = fchdir(path->fd);
3137 else
3138 #endif
3139 result = chdir(path->narrow);
3140 #endif
3141 Py_END_ALLOW_THREADS
3142
3143 if (result) {
3144 return path_error(path);
3145 }
3146
3147 Py_RETURN_NONE;
3148 }
3149
3150
3151 #ifdef HAVE_FCHDIR
3152 /*[clinic input]
3153 os.fchdir
3154
3155 fd: fildes
3156
3157 Change to the directory of the given file descriptor.
3158
3159 fd must be opened on a directory, not a file.
3160 Equivalent to os.chdir(fd).
3161
3162 [clinic start generated code]*/
3163
3164 static PyObject *
os_fchdir_impl(PyObject * module,int fd)3165 os_fchdir_impl(PyObject *module, int fd)
3166 /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3167 {
3168 if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3169 return NULL;
3170 }
3171 return posix_fildes_fd(fd, fchdir);
3172 }
3173 #endif /* HAVE_FCHDIR */
3174
3175
3176 /*[clinic input]
3177 os.chmod
3178
3179 path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3180 Path to be modified. May always be specified as a str, bytes, or a path-like object.
3181 On some platforms, path may also be specified as an open file descriptor.
3182 If this functionality is unavailable, using it raises an exception.
3183
3184 mode: int
3185 Operating-system mode bitfield.
3186
3187 *
3188
3189 dir_fd : dir_fd(requires='fchmodat') = None
3190 If not None, it should be a file descriptor open to a directory,
3191 and path should be relative; path will then be relative to that
3192 directory.
3193
3194 follow_symlinks: bool = True
3195 If False, and the last element of the path is a symbolic link,
3196 chmod will modify the symbolic link itself instead of the file
3197 the link points to.
3198
3199 Change the access permissions of a file.
3200
3201 It is an error to use dir_fd or follow_symlinks when specifying path as
3202 an open file descriptor.
3203 dir_fd and follow_symlinks may not be implemented on your platform.
3204 If they are unavailable, using them will raise a NotImplementedError.
3205
3206 [clinic start generated code]*/
3207
3208 static PyObject *
os_chmod_impl(PyObject * module,path_t * path,int mode,int dir_fd,int follow_symlinks)3209 os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3210 int follow_symlinks)
3211 /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
3212 {
3213 int result;
3214
3215 #ifdef MS_WINDOWS
3216 DWORD attr;
3217 #endif
3218
3219 #ifdef HAVE_FCHMODAT
3220 int fchmodat_nofollow_unsupported = 0;
3221 int fchmodat_unsupported = 0;
3222 #endif
3223
3224 #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
3225 if (follow_symlinks_specified("chmod", follow_symlinks))
3226 return NULL;
3227 #endif
3228
3229 if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3230 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3231 return NULL;
3232 }
3233
3234 #ifdef MS_WINDOWS
3235 Py_BEGIN_ALLOW_THREADS
3236 attr = GetFileAttributesW(path->wide);
3237 if (attr == INVALID_FILE_ATTRIBUTES)
3238 result = 0;
3239 else {
3240 if (mode & _S_IWRITE)
3241 attr &= ~FILE_ATTRIBUTE_READONLY;
3242 else
3243 attr |= FILE_ATTRIBUTE_READONLY;
3244 result = SetFileAttributesW(path->wide, attr);
3245 }
3246 Py_END_ALLOW_THREADS
3247
3248 if (!result) {
3249 return path_error(path);
3250 }
3251 #else /* MS_WINDOWS */
3252 Py_BEGIN_ALLOW_THREADS
3253 #ifdef HAVE_FCHMOD
3254 if (path->fd != -1)
3255 result = fchmod(path->fd, mode);
3256 else
3257 #endif /* HAVE_CHMOD */
3258 #ifdef HAVE_LCHMOD
3259 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3260 result = lchmod(path->narrow, mode);
3261 else
3262 #endif /* HAVE_LCHMOD */
3263 #ifdef HAVE_FCHMODAT
3264 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3265 if (HAVE_FCHMODAT_RUNTIME) {
3266 /*
3267 * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3268 * The documentation specifically shows how to use it,
3269 * and then says it isn't implemented yet.
3270 * (true on linux with glibc 2.15, and openindiana 3.x)
3271 *
3272 * Once it is supported, os.chmod will automatically
3273 * support dir_fd and follow_symlinks=False. (Hopefully.)
3274 * Until then, we need to be careful what exception we raise.
3275 */
3276 result = fchmodat(dir_fd, path->narrow, mode,
3277 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3278 /*
3279 * But wait! We can't throw the exception without allowing threads,
3280 * and we can't do that in this nested scope. (Macro trickery, sigh.)
3281 */
3282 fchmodat_nofollow_unsupported =
3283 result &&
3284 ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3285 !follow_symlinks;
3286 } else {
3287 fchmodat_unsupported = 1;
3288 fchmodat_nofollow_unsupported = 1;
3289
3290 result = -1;
3291 }
3292 }
3293 else
3294 #endif /* HAVE_FHCMODAT */
3295 result = chmod(path->narrow, mode);
3296 Py_END_ALLOW_THREADS
3297
3298 if (result) {
3299 #ifdef HAVE_FCHMODAT
3300 if (fchmodat_unsupported) {
3301 if (dir_fd != DEFAULT_DIR_FD) {
3302 argument_unavailable_error("chmod", "dir_fd");
3303 return NULL;
3304 }
3305 }
3306
3307 if (fchmodat_nofollow_unsupported) {
3308 if (dir_fd != DEFAULT_DIR_FD)
3309 dir_fd_and_follow_symlinks_invalid("chmod",
3310 dir_fd, follow_symlinks);
3311 else
3312 follow_symlinks_specified("chmod", follow_symlinks);
3313 return NULL;
3314 }
3315 else
3316 #endif /* HAVE_FCHMODAT */
3317 return path_error(path);
3318 }
3319 #endif /* MS_WINDOWS */
3320
3321 Py_RETURN_NONE;
3322 }
3323
3324
3325 #ifdef HAVE_FCHMOD
3326 /*[clinic input]
3327 os.fchmod
3328
3329 fd: int
3330 mode: int
3331
3332 Change the access permissions of the file given by file descriptor fd.
3333
3334 Equivalent to os.chmod(fd, mode).
3335 [clinic start generated code]*/
3336
3337 static PyObject *
os_fchmod_impl(PyObject * module,int fd,int mode)3338 os_fchmod_impl(PyObject *module, int fd, int mode)
3339 /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
3340 {
3341 int res;
3342 int async_err = 0;
3343
3344 if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3345 return NULL;
3346 }
3347
3348 do {
3349 Py_BEGIN_ALLOW_THREADS
3350 res = fchmod(fd, mode);
3351 Py_END_ALLOW_THREADS
3352 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3353 if (res != 0)
3354 return (!async_err) ? posix_error() : NULL;
3355
3356 Py_RETURN_NONE;
3357 }
3358 #endif /* HAVE_FCHMOD */
3359
3360
3361 #ifdef HAVE_LCHMOD
3362 /*[clinic input]
3363 os.lchmod
3364
3365 path: path_t
3366 mode: int
3367
3368 Change the access permissions of a file, without following symbolic links.
3369
3370 If path is a symlink, this affects the link itself rather than the target.
3371 Equivalent to chmod(path, mode, follow_symlinks=False)."
3372 [clinic start generated code]*/
3373
3374 static PyObject *
os_lchmod_impl(PyObject * module,path_t * path,int mode)3375 os_lchmod_impl(PyObject *module, path_t *path, int mode)
3376 /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3377 {
3378 int res;
3379 if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3380 return NULL;
3381 }
3382 Py_BEGIN_ALLOW_THREADS
3383 res = lchmod(path->narrow, mode);
3384 Py_END_ALLOW_THREADS
3385 if (res < 0) {
3386 path_error(path);
3387 return NULL;
3388 }
3389 Py_RETURN_NONE;
3390 }
3391 #endif /* HAVE_LCHMOD */
3392
3393
3394 #ifdef HAVE_CHFLAGS
3395 /*[clinic input]
3396 os.chflags
3397
3398 path: path_t
3399 flags: unsigned_long(bitwise=True)
3400 follow_symlinks: bool=True
3401
3402 Set file flags.
3403
3404 If follow_symlinks is False, and the last element of the path is a symbolic
3405 link, chflags will change flags on the symbolic link itself instead of the
3406 file the link points to.
3407 follow_symlinks may not be implemented on your platform. If it is
3408 unavailable, using it will raise a NotImplementedError.
3409
3410 [clinic start generated code]*/
3411
3412 static PyObject *
os_chflags_impl(PyObject * module,path_t * path,unsigned long flags,int follow_symlinks)3413 os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3414 int follow_symlinks)
3415 /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3416 {
3417 int result;
3418
3419 #ifndef HAVE_LCHFLAGS
3420 if (follow_symlinks_specified("chflags", follow_symlinks))
3421 return NULL;
3422 #endif
3423
3424 if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3425 return NULL;
3426 }
3427
3428 Py_BEGIN_ALLOW_THREADS
3429 #ifdef HAVE_LCHFLAGS
3430 if (!follow_symlinks)
3431 result = lchflags(path->narrow, flags);
3432 else
3433 #endif
3434 result = chflags(path->narrow, flags);
3435 Py_END_ALLOW_THREADS
3436
3437 if (result)
3438 return path_error(path);
3439
3440 Py_RETURN_NONE;
3441 }
3442 #endif /* HAVE_CHFLAGS */
3443
3444
3445 #ifdef HAVE_LCHFLAGS
3446 /*[clinic input]
3447 os.lchflags
3448
3449 path: path_t
3450 flags: unsigned_long(bitwise=True)
3451
3452 Set file flags.
3453
3454 This function will not follow symbolic links.
3455 Equivalent to chflags(path, flags, follow_symlinks=False).
3456 [clinic start generated code]*/
3457
3458 static PyObject *
os_lchflags_impl(PyObject * module,path_t * path,unsigned long flags)3459 os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3460 /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3461 {
3462 int res;
3463 if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3464 return NULL;
3465 }
3466 Py_BEGIN_ALLOW_THREADS
3467 res = lchflags(path->narrow, flags);
3468 Py_END_ALLOW_THREADS
3469 if (res < 0) {
3470 return path_error(path);
3471 }
3472 Py_RETURN_NONE;
3473 }
3474 #endif /* HAVE_LCHFLAGS */
3475
3476
3477 #ifdef HAVE_CHROOT
3478 /*[clinic input]
3479 os.chroot
3480 path: path_t
3481
3482 Change root directory to path.
3483
3484 [clinic start generated code]*/
3485
3486 static PyObject *
os_chroot_impl(PyObject * module,path_t * path)3487 os_chroot_impl(PyObject *module, path_t *path)
3488 /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3489 {
3490 int res;
3491 Py_BEGIN_ALLOW_THREADS
3492 res = chroot(path->narrow);
3493 Py_END_ALLOW_THREADS
3494 if (res < 0)
3495 return path_error(path);
3496 Py_RETURN_NONE;
3497 }
3498 #endif /* HAVE_CHROOT */
3499
3500
3501 #ifdef HAVE_FSYNC
3502 /*[clinic input]
3503 os.fsync
3504
3505 fd: fildes
3506
3507 Force write of fd to disk.
3508 [clinic start generated code]*/
3509
3510 static PyObject *
os_fsync_impl(PyObject * module,int fd)3511 os_fsync_impl(PyObject *module, int fd)
3512 /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3513 {
3514 return posix_fildes_fd(fd, fsync);
3515 }
3516 #endif /* HAVE_FSYNC */
3517
3518
3519 #ifdef HAVE_SYNC
3520 /*[clinic input]
3521 os.sync
3522
3523 Force write of everything to disk.
3524 [clinic start generated code]*/
3525
3526 static PyObject *
os_sync_impl(PyObject * module)3527 os_sync_impl(PyObject *module)
3528 /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3529 {
3530 Py_BEGIN_ALLOW_THREADS
3531 sync();
3532 Py_END_ALLOW_THREADS
3533 Py_RETURN_NONE;
3534 }
3535 #endif /* HAVE_SYNC */
3536
3537
3538 #ifdef HAVE_FDATASYNC
3539 #ifdef __hpux
3540 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3541 #endif
3542
3543 /*[clinic input]
3544 os.fdatasync
3545
3546 fd: fildes
3547
3548 Force write of fd to disk without forcing update of metadata.
3549 [clinic start generated code]*/
3550
3551 static PyObject *
os_fdatasync_impl(PyObject * module,int fd)3552 os_fdatasync_impl(PyObject *module, int fd)
3553 /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3554 {
3555 return posix_fildes_fd(fd, fdatasync);
3556 }
3557 #endif /* HAVE_FDATASYNC */
3558
3559
3560 #ifdef HAVE_CHOWN
3561 /*[clinic input]
3562 os.chown
3563
3564 path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3565 Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3566
3567 uid: uid_t
3568
3569 gid: gid_t
3570
3571 *
3572
3573 dir_fd : dir_fd(requires='fchownat') = None
3574 If not None, it should be a file descriptor open to a directory,
3575 and path should be relative; path will then be relative to that
3576 directory.
3577
3578 follow_symlinks: bool = True
3579 If False, and the last element of the path is a symbolic link,
3580 stat will examine the symbolic link itself instead of the file
3581 the link points to.
3582
3583 Change the owner and group id of path to the numeric uid and gid.\
3584
3585 path may always be specified as a string.
3586 On some platforms, path may also be specified as an open file descriptor.
3587 If this functionality is unavailable, using it raises an exception.
3588 If dir_fd is not None, it should be a file descriptor open to a directory,
3589 and path should be relative; path will then be relative to that directory.
3590 If follow_symlinks is False, and the last element of the path is a symbolic
3591 link, chown will modify the symbolic link itself instead of the file the
3592 link points to.
3593 It is an error to use dir_fd or follow_symlinks when specifying path as
3594 an open file descriptor.
3595 dir_fd and follow_symlinks may not be implemented on your platform.
3596 If they are unavailable, using them will raise a NotImplementedError.
3597
3598 [clinic start generated code]*/
3599
3600 static PyObject *
os_chown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid,int dir_fd,int follow_symlinks)3601 os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3602 int dir_fd, int follow_symlinks)
3603 /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3604 {
3605 int result;
3606
3607 #if defined(HAVE_FCHOWNAT)
3608 int fchownat_unsupported = 0;
3609 #endif
3610
3611 #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3612 if (follow_symlinks_specified("chown", follow_symlinks))
3613 return NULL;
3614 #endif
3615 if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3616 fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3617 return NULL;
3618
3619 if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3620 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3621 return NULL;
3622 }
3623
3624 Py_BEGIN_ALLOW_THREADS
3625 #ifdef HAVE_FCHOWN
3626 if (path->fd != -1)
3627 result = fchown(path->fd, uid, gid);
3628 else
3629 #endif
3630 #ifdef HAVE_LCHOWN
3631 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3632 result = lchown(path->narrow, uid, gid);
3633 else
3634 #endif
3635 #ifdef HAVE_FCHOWNAT
3636 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
3637 if (HAVE_FCHOWNAT_RUNTIME) {
3638 result = fchownat(dir_fd, path->narrow, uid, gid,
3639 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3640 } else {
3641 fchownat_unsupported = 1;
3642 }
3643 } else
3644 #endif
3645 result = chown(path->narrow, uid, gid);
3646 Py_END_ALLOW_THREADS
3647
3648 #ifdef HAVE_FCHOWNAT
3649 if (fchownat_unsupported) {
3650 /* This would be incorrect if the current platform
3651 * doesn't support lchown.
3652 */
3653 argument_unavailable_error(NULL, "dir_fd");
3654 return NULL;
3655 }
3656 #endif
3657
3658 if (result)
3659 return path_error(path);
3660
3661 Py_RETURN_NONE;
3662 }
3663 #endif /* HAVE_CHOWN */
3664
3665
3666 #ifdef HAVE_FCHOWN
3667 /*[clinic input]
3668 os.fchown
3669
3670 fd: int
3671 uid: uid_t
3672 gid: gid_t
3673
3674 Change the owner and group id of the file specified by file descriptor.
3675
3676 Equivalent to os.chown(fd, uid, gid).
3677
3678 [clinic start generated code]*/
3679
3680 static PyObject *
os_fchown_impl(PyObject * module,int fd,uid_t uid,gid_t gid)3681 os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3682 /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3683 {
3684 int res;
3685 int async_err = 0;
3686
3687 if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
3688 return NULL;
3689 }
3690
3691 do {
3692 Py_BEGIN_ALLOW_THREADS
3693 res = fchown(fd, uid, gid);
3694 Py_END_ALLOW_THREADS
3695 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3696 if (res != 0)
3697 return (!async_err) ? posix_error() : NULL;
3698
3699 Py_RETURN_NONE;
3700 }
3701 #endif /* HAVE_FCHOWN */
3702
3703
3704 #ifdef HAVE_LCHOWN
3705 /*[clinic input]
3706 os.lchown
3707
3708 path : path_t
3709 uid: uid_t
3710 gid: gid_t
3711
3712 Change the owner and group id of path to the numeric uid and gid.
3713
3714 This function will not follow symbolic links.
3715 Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3716 [clinic start generated code]*/
3717
3718 static PyObject *
os_lchown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid)3719 os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3720 /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3721 {
3722 int res;
3723 if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
3724 return NULL;
3725 }
3726 Py_BEGIN_ALLOW_THREADS
3727 res = lchown(path->narrow, uid, gid);
3728 Py_END_ALLOW_THREADS
3729 if (res < 0) {
3730 return path_error(path);
3731 }
3732 Py_RETURN_NONE;
3733 }
3734 #endif /* HAVE_LCHOWN */
3735
3736
3737 static PyObject *
posix_getcwd(int use_bytes)3738 posix_getcwd(int use_bytes)
3739 {
3740 #ifdef MS_WINDOWS
3741 wchar_t wbuf[MAXPATHLEN];
3742 wchar_t *wbuf2 = wbuf;
3743 DWORD len;
3744
3745 Py_BEGIN_ALLOW_THREADS
3746 len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3747 /* If the buffer is large enough, len does not include the
3748 terminating \0. If the buffer is too small, len includes
3749 the space needed for the terminator. */
3750 if (len >= Py_ARRAY_LENGTH(wbuf)) {
3751 if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3752 wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3753 }
3754 else {
3755 wbuf2 = NULL;
3756 }
3757 if (wbuf2) {
3758 len = GetCurrentDirectoryW(len, wbuf2);
3759 }
3760 }
3761 Py_END_ALLOW_THREADS
3762
3763 if (!wbuf2) {
3764 PyErr_NoMemory();
3765 return NULL;
3766 }
3767 if (!len) {
3768 if (wbuf2 != wbuf)
3769 PyMem_RawFree(wbuf2);
3770 return PyErr_SetFromWindowsErr(0);
3771 }
3772
3773 PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3774 if (wbuf2 != wbuf) {
3775 PyMem_RawFree(wbuf2);
3776 }
3777
3778 if (use_bytes) {
3779 if (resobj == NULL) {
3780 return NULL;
3781 }
3782 Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3783 }
3784
3785 return resobj;
3786 #else
3787 const size_t chunk = 1024;
3788
3789 char *buf = NULL;
3790 char *cwd = NULL;
3791 size_t buflen = 0;
3792
3793 Py_BEGIN_ALLOW_THREADS
3794 do {
3795 char *newbuf;
3796 if (buflen <= PY_SSIZE_T_MAX - chunk) {
3797 buflen += chunk;
3798 newbuf = PyMem_RawRealloc(buf, buflen);
3799 }
3800 else {
3801 newbuf = NULL;
3802 }
3803 if (newbuf == NULL) {
3804 PyMem_RawFree(buf);
3805 buf = NULL;
3806 break;
3807 }
3808 buf = newbuf;
3809
3810 cwd = getcwd(buf, buflen);
3811 } while (cwd == NULL && errno == ERANGE);
3812 Py_END_ALLOW_THREADS
3813
3814 if (buf == NULL) {
3815 return PyErr_NoMemory();
3816 }
3817 if (cwd == NULL) {
3818 PyMem_RawFree(buf);
3819 return posix_error();
3820 }
3821
3822 PyObject *obj;
3823 if (use_bytes) {
3824 obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3825 }
3826 else {
3827 obj = PyUnicode_DecodeFSDefault(buf);
3828 }
3829 PyMem_RawFree(buf);
3830
3831 return obj;
3832 #endif /* !MS_WINDOWS */
3833 }
3834
3835
3836 /*[clinic input]
3837 os.getcwd
3838
3839 Return a unicode string representing the current working directory.
3840 [clinic start generated code]*/
3841
3842 static PyObject *
os_getcwd_impl(PyObject * module)3843 os_getcwd_impl(PyObject *module)
3844 /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3845 {
3846 return posix_getcwd(0);
3847 }
3848
3849
3850 /*[clinic input]
3851 os.getcwdb
3852
3853 Return a bytes string representing the current working directory.
3854 [clinic start generated code]*/
3855
3856 static PyObject *
os_getcwdb_impl(PyObject * module)3857 os_getcwdb_impl(PyObject *module)
3858 /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3859 {
3860 return posix_getcwd(1);
3861 }
3862
3863
3864 #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3865 #define HAVE_LINK 1
3866 #endif
3867
3868 #ifdef HAVE_LINK
3869 /*[clinic input]
3870
3871 os.link
3872
3873 src : path_t
3874 dst : path_t
3875 *
3876 src_dir_fd : dir_fd = None
3877 dst_dir_fd : dir_fd = None
3878 follow_symlinks: bool = True
3879
3880 Create a hard link to a file.
3881
3882 If either src_dir_fd or dst_dir_fd is not None, it should be a file
3883 descriptor open to a directory, and the respective path string (src or dst)
3884 should be relative; the path will then be relative to that directory.
3885 If follow_symlinks is False, and the last element of src is a symbolic
3886 link, link will create a link to the symbolic link itself instead of the
3887 file the link points to.
3888 src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3889 platform. If they are unavailable, using them will raise a
3890 NotImplementedError.
3891 [clinic start generated code]*/
3892
3893 static PyObject *
os_link_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int follow_symlinks)3894 os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3895 int dst_dir_fd, int follow_symlinks)
3896 /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3897 {
3898 #ifdef MS_WINDOWS
3899 BOOL result = FALSE;
3900 #else
3901 int result;
3902 #endif
3903 #if defined(HAVE_LINKAT)
3904 int linkat_unavailable = 0;
3905 #endif
3906
3907 #ifndef HAVE_LINKAT
3908 if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3909 argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3910 return NULL;
3911 }
3912 #endif
3913
3914 #ifndef MS_WINDOWS
3915 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3916 PyErr_SetString(PyExc_NotImplementedError,
3917 "link: src and dst must be the same type");
3918 return NULL;
3919 }
3920 #endif
3921
3922 if (PySys_Audit("os.link", "OOii", src->object, dst->object,
3923 src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
3924 dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
3925 return NULL;
3926 }
3927
3928 #ifdef MS_WINDOWS
3929 Py_BEGIN_ALLOW_THREADS
3930 result = CreateHardLinkW(dst->wide, src->wide, NULL);
3931 Py_END_ALLOW_THREADS
3932
3933 if (!result)
3934 return path_error2(src, dst);
3935 #else
3936 Py_BEGIN_ALLOW_THREADS
3937 #ifdef HAVE_LINKAT
3938 if ((src_dir_fd != DEFAULT_DIR_FD) ||
3939 (dst_dir_fd != DEFAULT_DIR_FD) ||
3940 (!follow_symlinks)) {
3941
3942 if (HAVE_LINKAT_RUNTIME) {
3943
3944 result = linkat(src_dir_fd, src->narrow,
3945 dst_dir_fd, dst->narrow,
3946 follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3947
3948 }
3949 #ifdef __APPLE__
3950 else {
3951 if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
3952 /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
3953 result = link(src->narrow, dst->narrow);
3954 } else {
3955 linkat_unavailable = 1;
3956 }
3957 }
3958 #endif
3959 }
3960 else
3961 #endif /* HAVE_LINKAT */
3962 result = link(src->narrow, dst->narrow);
3963 Py_END_ALLOW_THREADS
3964
3965 #ifdef HAVE_LINKAT
3966 if (linkat_unavailable) {
3967 /* Either or both dir_fd arguments were specified */
3968 if (src_dir_fd != DEFAULT_DIR_FD) {
3969 argument_unavailable_error("link", "src_dir_fd");
3970 } else {
3971 argument_unavailable_error("link", "dst_dir_fd");
3972 }
3973 return NULL;
3974 }
3975 #endif
3976
3977 if (result)
3978 return path_error2(src, dst);
3979 #endif /* MS_WINDOWS */
3980
3981 Py_RETURN_NONE;
3982 }
3983 #endif
3984
3985
3986 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3987 static PyObject *
_listdir_windows_no_opendir(path_t * path,PyObject * list)3988 _listdir_windows_no_opendir(path_t *path, PyObject *list)
3989 {
3990 PyObject *v;
3991 HANDLE hFindFile = INVALID_HANDLE_VALUE;
3992 BOOL result;
3993 wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
3994 /* only claim to have space for MAX_PATH */
3995 Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
3996 wchar_t *wnamebuf = NULL;
3997
3998 WIN32_FIND_DATAW wFileData;
3999 const wchar_t *po_wchars;
4000
4001 if (!path->wide) { /* Default arg: "." */
4002 po_wchars = L".";
4003 len = 1;
4004 } else {
4005 po_wchars = path->wide;
4006 len = wcslen(path->wide);
4007 }
4008 /* The +5 is so we can append "\\*.*\0" */
4009 wnamebuf = PyMem_New(wchar_t, len + 5);
4010 if (!wnamebuf) {
4011 PyErr_NoMemory();
4012 goto exit;
4013 }
4014 wcscpy(wnamebuf, po_wchars);
4015 if (len > 0) {
4016 wchar_t wch = wnamebuf[len-1];
4017 if (wch != SEP && wch != ALTSEP && wch != L':')
4018 wnamebuf[len++] = SEP;
4019 wcscpy(wnamebuf + len, L"*.*");
4020 }
4021 if ((list = PyList_New(0)) == NULL) {
4022 goto exit;
4023 }
4024 Py_BEGIN_ALLOW_THREADS
4025 hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4026 Py_END_ALLOW_THREADS
4027 if (hFindFile == INVALID_HANDLE_VALUE) {
4028 int error = GetLastError();
4029 if (error == ERROR_FILE_NOT_FOUND)
4030 goto exit;
4031 Py_DECREF(list);
4032 list = path_error(path);
4033 goto exit;
4034 }
4035 do {
4036 /* Skip over . and .. */
4037 if (wcscmp(wFileData.cFileName, L".") != 0 &&
4038 wcscmp(wFileData.cFileName, L"..") != 0) {
4039 v = PyUnicode_FromWideChar(wFileData.cFileName,
4040 wcslen(wFileData.cFileName));
4041 if (path->narrow && v) {
4042 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4043 }
4044 if (v == NULL) {
4045 Py_DECREF(list);
4046 list = NULL;
4047 break;
4048 }
4049 if (PyList_Append(list, v) != 0) {
4050 Py_DECREF(v);
4051 Py_DECREF(list);
4052 list = NULL;
4053 break;
4054 }
4055 Py_DECREF(v);
4056 }
4057 Py_BEGIN_ALLOW_THREADS
4058 result = FindNextFileW(hFindFile, &wFileData);
4059 Py_END_ALLOW_THREADS
4060 /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4061 it got to the end of the directory. */
4062 if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4063 Py_DECREF(list);
4064 list = path_error(path);
4065 goto exit;
4066 }
4067 } while (result == TRUE);
4068
4069 exit:
4070 if (hFindFile != INVALID_HANDLE_VALUE) {
4071 if (FindClose(hFindFile) == FALSE) {
4072 if (list != NULL) {
4073 Py_DECREF(list);
4074 list = path_error(path);
4075 }
4076 }
4077 }
4078 PyMem_Free(wnamebuf);
4079
4080 return list;
4081 } /* end of _listdir_windows_no_opendir */
4082
4083 #else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4084
4085 static PyObject *
_posix_listdir(path_t * path,PyObject * list)4086 _posix_listdir(path_t *path, PyObject *list)
4087 {
4088 PyObject *v;
4089 DIR *dirp = NULL;
4090 struct dirent *ep;
4091 int return_str; /* if false, return bytes */
4092 #ifdef HAVE_FDOPENDIR
4093 int fd = -1;
4094 #endif
4095
4096 errno = 0;
4097 #ifdef HAVE_FDOPENDIR
4098 if (path->fd != -1) {
4099 if (HAVE_FDOPENDIR_RUNTIME) {
4100 /* closedir() closes the FD, so we duplicate it */
4101 fd = _Py_dup(path->fd);
4102 if (fd == -1)
4103 return NULL;
4104
4105 return_str = 1;
4106
4107 Py_BEGIN_ALLOW_THREADS
4108 dirp = fdopendir(fd);
4109 Py_END_ALLOW_THREADS
4110 } else {
4111 PyErr_SetString(PyExc_TypeError,
4112 "listdir: path should be string, bytes, os.PathLike or None, not int");
4113 return NULL;
4114 }
4115 }
4116 else
4117 #endif
4118 {
4119 const char *name;
4120 if (path->narrow) {
4121 name = path->narrow;
4122 /* only return bytes if they specified a bytes-like object */
4123 return_str = !PyObject_CheckBuffer(path->object);
4124 }
4125 else {
4126 name = ".";
4127 return_str = 1;
4128 }
4129
4130 Py_BEGIN_ALLOW_THREADS
4131 dirp = opendir(name);
4132 Py_END_ALLOW_THREADS
4133 }
4134
4135 if (dirp == NULL) {
4136 list = path_error(path);
4137 #ifdef HAVE_FDOPENDIR
4138 if (fd != -1) {
4139 Py_BEGIN_ALLOW_THREADS
4140 close(fd);
4141 Py_END_ALLOW_THREADS
4142 }
4143 #endif
4144 goto exit;
4145 }
4146 if ((list = PyList_New(0)) == NULL) {
4147 goto exit;
4148 }
4149 for (;;) {
4150 errno = 0;
4151 Py_BEGIN_ALLOW_THREADS
4152 ep = readdir(dirp);
4153 Py_END_ALLOW_THREADS
4154 if (ep == NULL) {
4155 if (errno == 0) {
4156 break;
4157 } else {
4158 Py_DECREF(list);
4159 list = path_error(path);
4160 goto exit;
4161 }
4162 }
4163 if (ep->d_name[0] == '.' &&
4164 (NAMLEN(ep) == 1 ||
4165 (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4166 continue;
4167 if (return_str)
4168 v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4169 else
4170 v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4171 if (v == NULL) {
4172 Py_CLEAR(list);
4173 break;
4174 }
4175 if (PyList_Append(list, v) != 0) {
4176 Py_DECREF(v);
4177 Py_CLEAR(list);
4178 break;
4179 }
4180 Py_DECREF(v);
4181 }
4182
4183 exit:
4184 if (dirp != NULL) {
4185 Py_BEGIN_ALLOW_THREADS
4186 #ifdef HAVE_FDOPENDIR
4187 if (fd > -1)
4188 rewinddir(dirp);
4189 #endif
4190 closedir(dirp);
4191 Py_END_ALLOW_THREADS
4192 }
4193
4194 return list;
4195 } /* end of _posix_listdir */
4196 #endif /* which OS */
4197
4198
4199 /*[clinic input]
4200 os.listdir
4201
4202 path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4203
4204 Return a list containing the names of the files in the directory.
4205
4206 path can be specified as either str, bytes, or a path-like object. If path is bytes,
4207 the filenames returned will also be bytes; in all other circumstances
4208 the filenames returned will be str.
4209 If path is None, uses the path='.'.
4210 On some platforms, path may also be specified as an open file descriptor;\
4211 the file descriptor must refer to a directory.
4212 If this functionality is unavailable, using it raises NotImplementedError.
4213
4214 The list is in arbitrary order. It does not include the special
4215 entries '.' and '..' even if they are present in the directory.
4216
4217
4218 [clinic start generated code]*/
4219
4220 static PyObject *
os_listdir_impl(PyObject * module,path_t * path)4221 os_listdir_impl(PyObject *module, path_t *path)
4222 /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4223 {
4224 if (PySys_Audit("os.listdir", "O",
4225 path->object ? path->object : Py_None) < 0) {
4226 return NULL;
4227 }
4228 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4229 return _listdir_windows_no_opendir(path, NULL);
4230 #else
4231 return _posix_listdir(path, NULL);
4232 #endif
4233 }
4234
4235 #ifdef MS_WINDOWS
4236 /* A helper function for abspath on win32 */
4237 /*[clinic input]
4238 os._getfullpathname
4239
4240 path: path_t
4241 /
4242
4243 [clinic start generated code]*/
4244
4245 static PyObject *
os__getfullpathname_impl(PyObject * module,path_t * path)4246 os__getfullpathname_impl(PyObject *module, path_t *path)
4247 /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
4248 {
4249 wchar_t *abspath;
4250
4251 /* _Py_abspath() is implemented with GetFullPathNameW() on Windows */
4252 if (_Py_abspath(path->wide, &abspath) < 0) {
4253 return win32_error_object("GetFullPathNameW", path->object);
4254 }
4255 if (abspath == NULL) {
4256 return PyErr_NoMemory();
4257 }
4258
4259 PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
4260 PyMem_RawFree(abspath);
4261 if (str == NULL) {
4262 return NULL;
4263 }
4264 if (path->narrow) {
4265 Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
4266 }
4267 return str;
4268 }
4269
4270
4271 /*[clinic input]
4272 os._getfinalpathname
4273
4274 path: path_t
4275 /
4276
4277 A helper function for samepath on windows.
4278 [clinic start generated code]*/
4279
4280 static PyObject *
os__getfinalpathname_impl(PyObject * module,path_t * path)4281 os__getfinalpathname_impl(PyObject *module, path_t *path)
4282 /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
4283 {
4284 HANDLE hFile;
4285 wchar_t buf[MAXPATHLEN], *target_path = buf;
4286 int buf_size = Py_ARRAY_LENGTH(buf);
4287 int result_length;
4288 PyObject *result;
4289
4290 Py_BEGIN_ALLOW_THREADS
4291 hFile = CreateFileW(
4292 path->wide,
4293 0, /* desired access */
4294 0, /* share mode */
4295 NULL, /* security attributes */
4296 OPEN_EXISTING,
4297 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
4298 FILE_FLAG_BACKUP_SEMANTICS,
4299 NULL);
4300 Py_END_ALLOW_THREADS
4301
4302 if (hFile == INVALID_HANDLE_VALUE) {
4303 return win32_error_object("CreateFileW", path->object);
4304 }
4305
4306 /* We have a good handle to the target, use it to determine the
4307 target path name. */
4308 while (1) {
4309 Py_BEGIN_ALLOW_THREADS
4310 result_length = GetFinalPathNameByHandleW(hFile, target_path,
4311 buf_size, VOLUME_NAME_DOS);
4312 Py_END_ALLOW_THREADS
4313
4314 if (!result_length) {
4315 result = win32_error_object("GetFinalPathNameByHandleW",
4316 path->object);
4317 goto cleanup;
4318 }
4319
4320 if (result_length < buf_size) {
4321 break;
4322 }
4323
4324 wchar_t *tmp;
4325 tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
4326 result_length * sizeof(*tmp));
4327 if (!tmp) {
4328 result = PyErr_NoMemory();
4329 goto cleanup;
4330 }
4331
4332 buf_size = result_length;
4333 target_path = tmp;
4334 }
4335
4336 result = PyUnicode_FromWideChar(target_path, result_length);
4337 if (result && path->narrow) {
4338 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4339 }
4340
4341 cleanup:
4342 if (target_path != buf) {
4343 PyMem_Free(target_path);
4344 }
4345 CloseHandle(hFile);
4346 return result;
4347 }
4348
4349
4350 /*[clinic input]
4351 os._getvolumepathname
4352
4353 path: path_t
4354
4355 A helper function for ismount on Win32.
4356 [clinic start generated code]*/
4357
4358 static PyObject *
os__getvolumepathname_impl(PyObject * module,path_t * path)4359 os__getvolumepathname_impl(PyObject *module, path_t *path)
4360 /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
4361 {
4362 PyObject *result;
4363 wchar_t *mountpath=NULL;
4364 size_t buflen;
4365 BOOL ret;
4366
4367 /* Volume path should be shorter than entire path */
4368 buflen = Py_MAX(path->length, MAX_PATH);
4369
4370 if (buflen > PY_DWORD_MAX) {
4371 PyErr_SetString(PyExc_OverflowError, "path too long");
4372 return NULL;
4373 }
4374
4375 mountpath = PyMem_New(wchar_t, buflen);
4376 if (mountpath == NULL)
4377 return PyErr_NoMemory();
4378
4379 Py_BEGIN_ALLOW_THREADS
4380 ret = GetVolumePathNameW(path->wide, mountpath,
4381 Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
4382 Py_END_ALLOW_THREADS
4383
4384 if (!ret) {
4385 result = win32_error_object("_getvolumepathname", path->object);
4386 goto exit;
4387 }
4388 result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
4389 if (path->narrow)
4390 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4391
4392 exit:
4393 PyMem_Free(mountpath);
4394 return result;
4395 }
4396
4397
4398 /*[clinic input]
4399 os._path_splitroot
4400
4401 path: path_t
4402
4403 Removes everything after the root on Win32.
4404 [clinic start generated code]*/
4405
4406 static PyObject *
os__path_splitroot_impl(PyObject * module,path_t * path)4407 os__path_splitroot_impl(PyObject *module, path_t *path)
4408 /*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/
4409 {
4410 wchar_t *buffer;
4411 wchar_t *end;
4412 PyObject *result = NULL;
4413 HRESULT ret;
4414
4415 buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
4416 if (!buffer) {
4417 return NULL;
4418 }
4419 wcscpy(buffer, path->wide);
4420 for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
4421 *p = L'\\';
4422 }
4423
4424 Py_BEGIN_ALLOW_THREADS
4425 ret = PathCchSkipRoot(buffer, &end);
4426 Py_END_ALLOW_THREADS
4427 if (FAILED(ret)) {
4428 result = Py_BuildValue("sO", "", path->object);
4429 } else if (end != buffer) {
4430 size_t rootLen = (size_t)(end - buffer);
4431 result = Py_BuildValue("NN",
4432 PyUnicode_FromWideChar(path->wide, rootLen),
4433 PyUnicode_FromWideChar(path->wide + rootLen, -1)
4434 );
4435 } else {
4436 result = Py_BuildValue("Os", path->object, "");
4437 }
4438 PyMem_Free(buffer);
4439
4440 return result;
4441 }
4442
4443
4444 #endif /* MS_WINDOWS */
4445
4446
4447 /*[clinic input]
4448 os._path_normpath
4449
4450 path: object
4451
4452 Basic path normalization.
4453 [clinic start generated code]*/
4454
4455 static PyObject *
os__path_normpath_impl(PyObject * module,PyObject * path)4456 os__path_normpath_impl(PyObject *module, PyObject *path)
4457 /*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/
4458 {
4459 if (!PyUnicode_Check(path)) {
4460 PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'",
4461 Py_TYPE(path)->tp_name);
4462 return NULL;
4463 }
4464 Py_ssize_t len;
4465 wchar_t *buffer = PyUnicode_AsWideCharString(path, &len);
4466 if (!buffer) {
4467 return NULL;
4468 }
4469 PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1);
4470 PyMem_Free(buffer);
4471 return result;
4472 }
4473
4474 /*[clinic input]
4475 os.mkdir
4476
4477 path : path_t
4478
4479 mode: int = 0o777
4480
4481 *
4482
4483 dir_fd : dir_fd(requires='mkdirat') = None
4484
4485 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4486
4487 Create a directory.
4488
4489 If dir_fd is not None, it should be a file descriptor open to a directory,
4490 and path should be relative; path will then be relative to that directory.
4491 dir_fd may not be implemented on your platform.
4492 If it is unavailable, using it will raise a NotImplementedError.
4493
4494 The mode argument is ignored on Windows.
4495 [clinic start generated code]*/
4496
4497 static PyObject *
os_mkdir_impl(PyObject * module,path_t * path,int mode,int dir_fd)4498 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4499 /*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/
4500 {
4501 int result;
4502 #ifdef HAVE_MKDIRAT
4503 int mkdirat_unavailable = 0;
4504 #endif
4505
4506 if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4507 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4508 return NULL;
4509 }
4510
4511 #ifdef MS_WINDOWS
4512 Py_BEGIN_ALLOW_THREADS
4513 result = CreateDirectoryW(path->wide, NULL);
4514 Py_END_ALLOW_THREADS
4515
4516 if (!result)
4517 return path_error(path);
4518 #else
4519 Py_BEGIN_ALLOW_THREADS
4520 #if HAVE_MKDIRAT
4521 if (dir_fd != DEFAULT_DIR_FD) {
4522 if (HAVE_MKDIRAT_RUNTIME) {
4523 result = mkdirat(dir_fd, path->narrow, mode);
4524
4525 } else {
4526 mkdirat_unavailable = 1;
4527 }
4528 } else
4529 #endif
4530 #if defined(__WATCOMC__) && !defined(__QNX__)
4531 result = mkdir(path->narrow);
4532 #else
4533 result = mkdir(path->narrow, mode);
4534 #endif
4535 Py_END_ALLOW_THREADS
4536
4537 #if HAVE_MKDIRAT
4538 if (mkdirat_unavailable) {
4539 argument_unavailable_error(NULL, "dir_fd");
4540 return NULL;
4541 }
4542 #endif
4543
4544 if (result < 0)
4545 return path_error(path);
4546 #endif /* MS_WINDOWS */
4547 Py_RETURN_NONE;
4548 }
4549
4550
4551 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4552 #if defined(HAVE_SYS_RESOURCE_H)
4553 #include <sys/resource.h>
4554 #endif
4555
4556
4557 #ifdef HAVE_NICE
4558 /*[clinic input]
4559 os.nice
4560
4561 increment: int
4562 /
4563
4564 Add increment to the priority of process and return the new priority.
4565 [clinic start generated code]*/
4566
4567 static PyObject *
os_nice_impl(PyObject * module,int increment)4568 os_nice_impl(PyObject *module, int increment)
4569 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4570 {
4571 int value;
4572
4573 /* There are two flavours of 'nice': one that returns the new
4574 priority (as required by almost all standards out there) and the
4575 Linux/FreeBSD one, which returns '0' on success and advices
4576 the use of getpriority() to get the new priority.
4577
4578 If we are of the nice family that returns the new priority, we
4579 need to clear errno before the call, and check if errno is filled
4580 before calling posix_error() on a returnvalue of -1, because the
4581 -1 may be the actual new priority! */
4582
4583 errno = 0;
4584 value = nice(increment);
4585 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4586 if (value == 0)
4587 value = getpriority(PRIO_PROCESS, 0);
4588 #endif
4589 if (value == -1 && errno != 0)
4590 /* either nice() or getpriority() returned an error */
4591 return posix_error();
4592 return PyLong_FromLong((long) value);
4593 }
4594 #endif /* HAVE_NICE */
4595
4596
4597 #ifdef HAVE_GETPRIORITY
4598 /*[clinic input]
4599 os.getpriority
4600
4601 which: int
4602 who: int
4603
4604 Return program scheduling priority.
4605 [clinic start generated code]*/
4606
4607 static PyObject *
os_getpriority_impl(PyObject * module,int which,int who)4608 os_getpriority_impl(PyObject *module, int which, int who)
4609 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4610 {
4611 int retval;
4612
4613 errno = 0;
4614 retval = getpriority(which, who);
4615 if (errno != 0)
4616 return posix_error();
4617 return PyLong_FromLong((long)retval);
4618 }
4619 #endif /* HAVE_GETPRIORITY */
4620
4621
4622 #ifdef HAVE_SETPRIORITY
4623 /*[clinic input]
4624 os.setpriority
4625
4626 which: int
4627 who: int
4628 priority: int
4629
4630 Set program scheduling priority.
4631 [clinic start generated code]*/
4632
4633 static PyObject *
os_setpriority_impl(PyObject * module,int which,int who,int priority)4634 os_setpriority_impl(PyObject *module, int which, int who, int priority)
4635 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4636 {
4637 int retval;
4638
4639 retval = setpriority(which, who, priority);
4640 if (retval == -1)
4641 return posix_error();
4642 Py_RETURN_NONE;
4643 }
4644 #endif /* HAVE_SETPRIORITY */
4645
4646
4647 static PyObject *
internal_rename(path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int is_replace)4648 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4649 {
4650 const char *function_name = is_replace ? "replace" : "rename";
4651 int dir_fd_specified;
4652
4653 #ifdef HAVE_RENAMEAT
4654 int renameat_unavailable = 0;
4655 #endif
4656
4657 #ifdef MS_WINDOWS
4658 BOOL result;
4659 int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4660 #else
4661 int result;
4662 #endif
4663
4664 dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4665 (dst_dir_fd != DEFAULT_DIR_FD);
4666 #ifndef HAVE_RENAMEAT
4667 if (dir_fd_specified) {
4668 argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4669 return NULL;
4670 }
4671 #endif
4672
4673 if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
4674 src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4675 dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4676 return NULL;
4677 }
4678
4679 #ifdef MS_WINDOWS
4680 Py_BEGIN_ALLOW_THREADS
4681 result = MoveFileExW(src->wide, dst->wide, flags);
4682 Py_END_ALLOW_THREADS
4683
4684 if (!result)
4685 return path_error2(src, dst);
4686
4687 #else
4688 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4689 PyErr_Format(PyExc_ValueError,
4690 "%s: src and dst must be the same type", function_name);
4691 return NULL;
4692 }
4693
4694 Py_BEGIN_ALLOW_THREADS
4695 #ifdef HAVE_RENAMEAT
4696 if (dir_fd_specified) {
4697 if (HAVE_RENAMEAT_RUNTIME) {
4698 result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4699 } else {
4700 renameat_unavailable = 1;
4701 }
4702 } else
4703 #endif
4704 result = rename(src->narrow, dst->narrow);
4705 Py_END_ALLOW_THREADS
4706
4707
4708 #ifdef HAVE_RENAMEAT
4709 if (renameat_unavailable) {
4710 argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4711 return NULL;
4712 }
4713 #endif
4714
4715 if (result)
4716 return path_error2(src, dst);
4717 #endif
4718 Py_RETURN_NONE;
4719 }
4720
4721
4722 /*[clinic input]
4723 os.rename
4724
4725 src : path_t
4726 dst : path_t
4727 *
4728 src_dir_fd : dir_fd = None
4729 dst_dir_fd : dir_fd = None
4730
4731 Rename a file or directory.
4732
4733 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4734 descriptor open to a directory, and the respective path string (src or dst)
4735 should be relative; the path will then be relative to that directory.
4736 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4737 If they are unavailable, using them will raise a NotImplementedError.
4738 [clinic start generated code]*/
4739
4740 static PyObject *
os_rename_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4741 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4742 int dst_dir_fd)
4743 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4744 {
4745 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4746 }
4747
4748
4749 /*[clinic input]
4750 os.replace = os.rename
4751
4752 Rename a file or directory, overwriting the destination.
4753
4754 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4755 descriptor open to a directory, and the respective path string (src or dst)
4756 should be relative; the path will then be relative to that directory.
4757 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4758 If they are unavailable, using them will raise a NotImplementedError.
4759 [clinic start generated code]*/
4760
4761 static PyObject *
os_replace_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4762 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4763 int dst_dir_fd)
4764 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4765 {
4766 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4767 }
4768
4769
4770 /*[clinic input]
4771 os.rmdir
4772
4773 path: path_t
4774 *
4775 dir_fd: dir_fd(requires='unlinkat') = None
4776
4777 Remove a directory.
4778
4779 If dir_fd is not None, it should be a file descriptor open to a directory,
4780 and path should be relative; path will then be relative to that directory.
4781 dir_fd may not be implemented on your platform.
4782 If it is unavailable, using it will raise a NotImplementedError.
4783 [clinic start generated code]*/
4784
4785 static PyObject *
os_rmdir_impl(PyObject * module,path_t * path,int dir_fd)4786 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4787 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4788 {
4789 int result;
4790 #ifdef HAVE_UNLINKAT
4791 int unlinkat_unavailable = 0;
4792 #endif
4793
4794 if (PySys_Audit("os.rmdir", "Oi", path->object,
4795 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4796 return NULL;
4797 }
4798
4799 Py_BEGIN_ALLOW_THREADS
4800 #ifdef MS_WINDOWS
4801 /* Windows, success=1, UNIX, success=0 */
4802 result = !RemoveDirectoryW(path->wide);
4803 #else
4804 #ifdef HAVE_UNLINKAT
4805 if (dir_fd != DEFAULT_DIR_FD) {
4806 if (HAVE_UNLINKAT_RUNTIME) {
4807 result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4808 } else {
4809 unlinkat_unavailable = 1;
4810 result = -1;
4811 }
4812 } else
4813 #endif
4814 result = rmdir(path->narrow);
4815 #endif
4816 Py_END_ALLOW_THREADS
4817
4818 #ifdef HAVE_UNLINKAT
4819 if (unlinkat_unavailable) {
4820 argument_unavailable_error("rmdir", "dir_fd");
4821 return NULL;
4822 }
4823 #endif
4824
4825 if (result)
4826 return path_error(path);
4827
4828 Py_RETURN_NONE;
4829 }
4830
4831
4832 #ifdef HAVE_SYSTEM
4833 #ifdef MS_WINDOWS
4834 /*[clinic input]
4835 os.system -> long
4836
4837 command: Py_UNICODE
4838
4839 Execute the command in a subshell.
4840 [clinic start generated code]*/
4841
4842 static long
os_system_impl(PyObject * module,const Py_UNICODE * command)4843 os_system_impl(PyObject *module, const Py_UNICODE *command)
4844 /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4845 {
4846 long result;
4847
4848 if (PySys_Audit("os.system", "(u)", command) < 0) {
4849 return -1;
4850 }
4851
4852 Py_BEGIN_ALLOW_THREADS
4853 _Py_BEGIN_SUPPRESS_IPH
4854 result = _wsystem(command);
4855 _Py_END_SUPPRESS_IPH
4856 Py_END_ALLOW_THREADS
4857 return result;
4858 }
4859 #else /* MS_WINDOWS */
4860 /*[clinic input]
4861 os.system -> long
4862
4863 command: FSConverter
4864
4865 Execute the command in a subshell.
4866 [clinic start generated code]*/
4867
4868 static long
os_system_impl(PyObject * module,PyObject * command)4869 os_system_impl(PyObject *module, PyObject *command)
4870 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4871 {
4872 long result;
4873 const char *bytes = PyBytes_AsString(command);
4874
4875 if (PySys_Audit("os.system", "(O)", command) < 0) {
4876 return -1;
4877 }
4878
4879 Py_BEGIN_ALLOW_THREADS
4880 result = system(bytes);
4881 Py_END_ALLOW_THREADS
4882 return result;
4883 }
4884 #endif
4885 #endif /* HAVE_SYSTEM */
4886
4887
4888 /*[clinic input]
4889 os.umask
4890
4891 mask: int
4892 /
4893
4894 Set the current numeric umask and return the previous umask.
4895 [clinic start generated code]*/
4896
4897 static PyObject *
os_umask_impl(PyObject * module,int mask)4898 os_umask_impl(PyObject *module, int mask)
4899 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4900 {
4901 int i = (int)umask(mask);
4902 if (i < 0)
4903 return posix_error();
4904 return PyLong_FromLong((long)i);
4905 }
4906
4907 #ifdef MS_WINDOWS
4908
4909 /* override the default DeleteFileW behavior so that directory
4910 symlinks can be removed with this function, the same as with
4911 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)4912 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
4913 {
4914 WIN32_FILE_ATTRIBUTE_DATA info;
4915 WIN32_FIND_DATAW find_data;
4916 HANDLE find_data_handle;
4917 int is_directory = 0;
4918 int is_link = 0;
4919
4920 if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
4921 is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4922
4923 /* Get WIN32_FIND_DATA structure for the path to determine if
4924 it is a symlink */
4925 if(is_directory &&
4926 info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
4927 find_data_handle = FindFirstFileW(lpFileName, &find_data);
4928
4929 if(find_data_handle != INVALID_HANDLE_VALUE) {
4930 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
4931 IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
4932 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
4933 find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
4934 FindClose(find_data_handle);
4935 }
4936 }
4937 }
4938
4939 if (is_directory && is_link)
4940 return RemoveDirectoryW(lpFileName);
4941
4942 return DeleteFileW(lpFileName);
4943 }
4944 #endif /* MS_WINDOWS */
4945
4946
4947 /*[clinic input]
4948 os.unlink
4949
4950 path: path_t
4951 *
4952 dir_fd: dir_fd(requires='unlinkat')=None
4953
4954 Remove a file (same as remove()).
4955
4956 If dir_fd is not None, it should be a file descriptor open to a directory,
4957 and path should be relative; path will then be relative to that directory.
4958 dir_fd may not be implemented on your platform.
4959 If it is unavailable, using it will raise a NotImplementedError.
4960
4961 [clinic start generated code]*/
4962
4963 static PyObject *
os_unlink_impl(PyObject * module,path_t * path,int dir_fd)4964 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
4965 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
4966 {
4967 int result;
4968 #ifdef HAVE_UNLINKAT
4969 int unlinkat_unavailable = 0;
4970 #endif
4971
4972 if (PySys_Audit("os.remove", "Oi", path->object,
4973 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4974 return NULL;
4975 }
4976
4977 Py_BEGIN_ALLOW_THREADS
4978 _Py_BEGIN_SUPPRESS_IPH
4979 #ifdef MS_WINDOWS
4980 /* Windows, success=1, UNIX, success=0 */
4981 result = !Py_DeleteFileW(path->wide);
4982 #else
4983 #ifdef HAVE_UNLINKAT
4984 if (dir_fd != DEFAULT_DIR_FD) {
4985 if (HAVE_UNLINKAT_RUNTIME) {
4986
4987 result = unlinkat(dir_fd, path->narrow, 0);
4988 } else {
4989 unlinkat_unavailable = 1;
4990 }
4991 } else
4992 #endif /* HAVE_UNLINKAT */
4993 result = unlink(path->narrow);
4994 #endif
4995 _Py_END_SUPPRESS_IPH
4996 Py_END_ALLOW_THREADS
4997
4998 #ifdef HAVE_UNLINKAT
4999 if (unlinkat_unavailable) {
5000 argument_unavailable_error(NULL, "dir_fd");
5001 return NULL;
5002 }
5003 #endif
5004
5005 if (result)
5006 return path_error(path);
5007
5008 Py_RETURN_NONE;
5009 }
5010
5011
5012 /*[clinic input]
5013 os.remove = os.unlink
5014
5015 Remove a file (same as unlink()).
5016
5017 If dir_fd is not None, it should be a file descriptor open to a directory,
5018 and path should be relative; path will then be relative to that directory.
5019 dir_fd may not be implemented on your platform.
5020 If it is unavailable, using it will raise a NotImplementedError.
5021 [clinic start generated code]*/
5022
5023 static PyObject *
os_remove_impl(PyObject * module,path_t * path,int dir_fd)5024 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
5025 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
5026 {
5027 return os_unlink_impl(module, path, dir_fd);
5028 }
5029
5030
5031 static PyStructSequence_Field uname_result_fields[] = {
5032 {"sysname", "operating system name"},
5033 {"nodename", "name of machine on network (implementation-defined)"},
5034 {"release", "operating system release"},
5035 {"version", "operating system version"},
5036 {"machine", "hardware identifier"},
5037 {NULL}
5038 };
5039
5040 PyDoc_STRVAR(uname_result__doc__,
5041 "uname_result: Result from os.uname().\n\n\
5042 This object may be accessed either as a tuple of\n\
5043 (sysname, nodename, release, version, machine),\n\
5044 or via the attributes sysname, nodename, release, version, and machine.\n\
5045 \n\
5046 See os.uname for more information.");
5047
5048 static PyStructSequence_Desc uname_result_desc = {
5049 MODNAME ".uname_result", /* name */
5050 uname_result__doc__, /* doc */
5051 uname_result_fields,
5052 5
5053 };
5054
5055 #ifdef HAVE_UNAME
5056 /*[clinic input]
5057 os.uname
5058
5059 Return an object identifying the current operating system.
5060
5061 The object behaves like a named tuple with the following fields:
5062 (sysname, nodename, release, version, machine)
5063
5064 [clinic start generated code]*/
5065
5066 static PyObject *
os_uname_impl(PyObject * module)5067 os_uname_impl(PyObject *module)
5068 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
5069 {
5070 struct utsname u;
5071 int res;
5072 PyObject *value;
5073
5074 Py_BEGIN_ALLOW_THREADS
5075 res = uname(&u);
5076 Py_END_ALLOW_THREADS
5077 if (res < 0)
5078 return posix_error();
5079
5080 PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
5081 value = PyStructSequence_New((PyTypeObject *)UnameResultType);
5082 if (value == NULL)
5083 return NULL;
5084
5085 #define SET(i, field) \
5086 { \
5087 PyObject *o = PyUnicode_DecodeFSDefault(field); \
5088 if (!o) { \
5089 Py_DECREF(value); \
5090 return NULL; \
5091 } \
5092 PyStructSequence_SET_ITEM(value, i, o); \
5093 } \
5094
5095 SET(0, u.sysname);
5096 SET(1, u.nodename);
5097 SET(2, u.release);
5098 SET(3, u.version);
5099 SET(4, u.machine);
5100
5101 #undef SET
5102
5103 return value;
5104 }
5105 #endif /* HAVE_UNAME */
5106
5107
5108
5109 typedef struct {
5110 int now;
5111 time_t atime_s;
5112 long atime_ns;
5113 time_t mtime_s;
5114 long mtime_ns;
5115 } utime_t;
5116
5117 /*
5118 * these macros assume that "ut" is a pointer to a utime_t
5119 * they also intentionally leak the declaration of a pointer named "time"
5120 */
5121 #define UTIME_TO_TIMESPEC \
5122 struct timespec ts[2]; \
5123 struct timespec *time; \
5124 if (ut->now) \
5125 time = NULL; \
5126 else { \
5127 ts[0].tv_sec = ut->atime_s; \
5128 ts[0].tv_nsec = ut->atime_ns; \
5129 ts[1].tv_sec = ut->mtime_s; \
5130 ts[1].tv_nsec = ut->mtime_ns; \
5131 time = ts; \
5132 } \
5133
5134 #define UTIME_TO_TIMEVAL \
5135 struct timeval tv[2]; \
5136 struct timeval *time; \
5137 if (ut->now) \
5138 time = NULL; \
5139 else { \
5140 tv[0].tv_sec = ut->atime_s; \
5141 tv[0].tv_usec = ut->atime_ns / 1000; \
5142 tv[1].tv_sec = ut->mtime_s; \
5143 tv[1].tv_usec = ut->mtime_ns / 1000; \
5144 time = tv; \
5145 } \
5146
5147 #define UTIME_TO_UTIMBUF \
5148 struct utimbuf u; \
5149 struct utimbuf *time; \
5150 if (ut->now) \
5151 time = NULL; \
5152 else { \
5153 u.actime = ut->atime_s; \
5154 u.modtime = ut->mtime_s; \
5155 time = &u; \
5156 }
5157
5158 #define UTIME_TO_TIME_T \
5159 time_t timet[2]; \
5160 time_t *time; \
5161 if (ut->now) \
5162 time = NULL; \
5163 else { \
5164 timet[0] = ut->atime_s; \
5165 timet[1] = ut->mtime_s; \
5166 time = timet; \
5167 } \
5168
5169
5170 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5171
5172 static int
utime_dir_fd(utime_t * ut,int dir_fd,const char * path,int follow_symlinks)5173 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
5174 {
5175 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5176 if (HAVE_UTIMENSAT_RUNTIME) {
5177 int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5178 UTIME_TO_TIMESPEC;
5179 return utimensat(dir_fd, path, time, flags);
5180 } else {
5181 errno = ENOSYS;
5182 return -1;
5183 }
5184 #elif defined(HAVE_UTIMENSAT)
5185 int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5186 UTIME_TO_TIMESPEC;
5187 return utimensat(dir_fd, path, time, flags);
5188 #elif defined(HAVE_FUTIMESAT)
5189 UTIME_TO_TIMEVAL;
5190 /*
5191 * follow_symlinks will never be false here;
5192 * we only allow !follow_symlinks and dir_fd together
5193 * if we have utimensat()
5194 */
5195 assert(follow_symlinks);
5196 return futimesat(dir_fd, path, time);
5197 #endif
5198 }
5199
5200 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
5201 #else
5202 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
5203 #endif
5204
5205 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5206
5207 static int
utime_fd(utime_t * ut,int fd)5208 utime_fd(utime_t *ut, int fd)
5209 {
5210 #ifdef HAVE_FUTIMENS
5211
5212 if (HAVE_FUTIMENS_RUNTIME) {
5213
5214 UTIME_TO_TIMESPEC;
5215 return futimens(fd, time);
5216
5217 } else
5218 #ifndef HAVE_FUTIMES
5219 {
5220 /* Not sure if this can happen */
5221 PyErr_SetString(
5222 PyExc_RuntimeError,
5223 "neither futimens nor futimes are supported"
5224 " on this system");
5225 return -1;
5226 }
5227 #endif
5228
5229 #endif
5230 #ifdef HAVE_FUTIMES
5231 {
5232 UTIME_TO_TIMEVAL;
5233 return futimes(fd, time);
5234 }
5235 #endif
5236 }
5237
5238 #define PATH_UTIME_HAVE_FD 1
5239 #else
5240 #define PATH_UTIME_HAVE_FD 0
5241 #endif
5242
5243 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
5244 # define UTIME_HAVE_NOFOLLOW_SYMLINKS
5245 #endif
5246
5247 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5248
5249 static int
utime_nofollow_symlinks(utime_t * ut,const char * path)5250 utime_nofollow_symlinks(utime_t *ut, const char *path)
5251 {
5252 #ifdef HAVE_UTIMENSAT
5253 if (HAVE_UTIMENSAT_RUNTIME) {
5254 UTIME_TO_TIMESPEC;
5255 return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
5256 } else
5257 #ifndef HAVE_LUTIMES
5258 {
5259 /* Not sure if this can happen */
5260 PyErr_SetString(
5261 PyExc_RuntimeError,
5262 "neither utimensat nor lutimes are supported"
5263 " on this system");
5264 return -1;
5265 }
5266 #endif
5267 #endif
5268
5269 #ifdef HAVE_LUTIMES
5270 {
5271 UTIME_TO_TIMEVAL;
5272 return lutimes(path, time);
5273 }
5274 #endif
5275 }
5276
5277 #endif
5278
5279 #ifndef MS_WINDOWS
5280
5281 static int
utime_default(utime_t * ut,const char * path)5282 utime_default(utime_t *ut, const char *path)
5283 {
5284 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5285 if (HAVE_UTIMENSAT_RUNTIME) {
5286 UTIME_TO_TIMESPEC;
5287 return utimensat(DEFAULT_DIR_FD, path, time, 0);
5288 } else {
5289 UTIME_TO_TIMEVAL;
5290 return utimes(path, time);
5291 }
5292 #elif defined(HAVE_UTIMENSAT)
5293 UTIME_TO_TIMESPEC;
5294 return utimensat(DEFAULT_DIR_FD, path, time, 0);
5295 #elif defined(HAVE_UTIMES)
5296 UTIME_TO_TIMEVAL;
5297 return utimes(path, time);
5298 #elif defined(HAVE_UTIME_H)
5299 UTIME_TO_UTIMBUF;
5300 return utime(path, time);
5301 #else
5302 UTIME_TO_TIME_T;
5303 return utime(path, time);
5304 #endif
5305 }
5306
5307 #endif
5308
5309 static int
split_py_long_to_s_and_ns(PyObject * module,PyObject * py_long,time_t * s,long * ns)5310 split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5311 {
5312 int result = 0;
5313 PyObject *divmod;
5314 divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5315 if (!divmod)
5316 goto exit;
5317 if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
5318 PyErr_Format(PyExc_TypeError,
5319 "%.200s.__divmod__() must return a 2-tuple, not %.200s",
5320 _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
5321 goto exit;
5322 }
5323 *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5324 if ((*s == -1) && PyErr_Occurred())
5325 goto exit;
5326 *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5327 if ((*ns == -1) && PyErr_Occurred())
5328 goto exit;
5329
5330 result = 1;
5331 exit:
5332 Py_XDECREF(divmod);
5333 return result;
5334 }
5335
5336
5337 /*[clinic input]
5338 os.utime
5339
5340 path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
5341 times: object = None
5342 *
5343 ns: object = NULL
5344 dir_fd: dir_fd(requires='futimensat') = None
5345 follow_symlinks: bool=True
5346
5347 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
5348
5349 Set the access and modified time of path.
5350
5351 path may always be specified as a string.
5352 On some platforms, path may also be specified as an open file descriptor.
5353 If this functionality is unavailable, using it raises an exception.
5354
5355 If times is not None, it must be a tuple (atime, mtime);
5356 atime and mtime should be expressed as float seconds since the epoch.
5357 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
5358 atime_ns and mtime_ns should be expressed as integer nanoseconds
5359 since the epoch.
5360 If times is None and ns is unspecified, utime uses the current time.
5361 Specifying tuples for both times and ns is an error.
5362
5363 If dir_fd is not None, it should be a file descriptor open to a directory,
5364 and path should be relative; path will then be relative to that directory.
5365 If follow_symlinks is False, and the last element of the path is a symbolic
5366 link, utime will modify the symbolic link itself instead of the file the
5367 link points to.
5368 It is an error to use dir_fd or follow_symlinks when specifying path
5369 as an open file descriptor.
5370 dir_fd and follow_symlinks may not be available on your platform.
5371 If they are unavailable, using them will raise a NotImplementedError.
5372
5373 [clinic start generated code]*/
5374
5375 static PyObject *
os_utime_impl(PyObject * module,path_t * path,PyObject * times,PyObject * ns,int dir_fd,int follow_symlinks)5376 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
5377 int dir_fd, int follow_symlinks)
5378 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
5379 {
5380 #ifdef MS_WINDOWS
5381 HANDLE hFile;
5382 FILETIME atime, mtime;
5383 #else
5384 int result;
5385 #endif
5386
5387 utime_t utime;
5388
5389 memset(&utime, 0, sizeof(utime_t));
5390
5391 if (times != Py_None && ns) {
5392 PyErr_SetString(PyExc_ValueError,
5393 "utime: you may specify either 'times'"
5394 " or 'ns' but not both");
5395 return NULL;
5396 }
5397
5398 if (times != Py_None) {
5399 time_t a_sec, m_sec;
5400 long a_nsec, m_nsec;
5401 if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
5402 PyErr_SetString(PyExc_TypeError,
5403 "utime: 'times' must be either"
5404 " a tuple of two ints or None");
5405 return NULL;
5406 }
5407 utime.now = 0;
5408 if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
5409 &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
5410 _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
5411 &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
5412 return NULL;
5413 }
5414 utime.atime_s = a_sec;
5415 utime.atime_ns = a_nsec;
5416 utime.mtime_s = m_sec;
5417 utime.mtime_ns = m_nsec;
5418 }
5419 else if (ns) {
5420 if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
5421 PyErr_SetString(PyExc_TypeError,
5422 "utime: 'ns' must be a tuple of two ints");
5423 return NULL;
5424 }
5425 utime.now = 0;
5426 if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
5427 &utime.atime_s, &utime.atime_ns) ||
5428 !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
5429 &utime.mtime_s, &utime.mtime_ns)) {
5430 return NULL;
5431 }
5432 }
5433 else {
5434 /* times and ns are both None/unspecified. use "now". */
5435 utime.now = 1;
5436 }
5437
5438 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
5439 if (follow_symlinks_specified("utime", follow_symlinks))
5440 return NULL;
5441 #endif
5442
5443 if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
5444 dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
5445 fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
5446 return NULL;
5447
5448 #if !defined(HAVE_UTIMENSAT)
5449 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
5450 PyErr_SetString(PyExc_ValueError,
5451 "utime: cannot use dir_fd and follow_symlinks "
5452 "together on this platform");
5453 return NULL;
5454 }
5455 #endif
5456
5457 if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
5458 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5459 return NULL;
5460 }
5461
5462 #ifdef MS_WINDOWS
5463 Py_BEGIN_ALLOW_THREADS
5464 hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
5465 NULL, OPEN_EXISTING,
5466 FILE_FLAG_BACKUP_SEMANTICS, NULL);
5467 Py_END_ALLOW_THREADS
5468 if (hFile == INVALID_HANDLE_VALUE) {
5469 path_error(path);
5470 return NULL;
5471 }
5472
5473 if (utime.now) {
5474 GetSystemTimeAsFileTime(&mtime);
5475 atime = mtime;
5476 }
5477 else {
5478 _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
5479 _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
5480 }
5481 if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
5482 /* Avoid putting the file name into the error here,
5483 as that may confuse the user into believing that
5484 something is wrong with the file, when it also
5485 could be the time stamp that gives a problem. */
5486 PyErr_SetFromWindowsErr(0);
5487 CloseHandle(hFile);
5488 return NULL;
5489 }
5490 CloseHandle(hFile);
5491 #else /* MS_WINDOWS */
5492 Py_BEGIN_ALLOW_THREADS
5493
5494 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5495 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
5496 result = utime_nofollow_symlinks(&utime, path->narrow);
5497 else
5498 #endif
5499
5500 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5501 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
5502 result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
5503
5504 } else
5505 #endif
5506
5507 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5508 if (path->fd != -1)
5509 result = utime_fd(&utime, path->fd);
5510 else
5511 #endif
5512
5513 result = utime_default(&utime, path->narrow);
5514
5515 Py_END_ALLOW_THREADS
5516
5517 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5518 /* See utime_dir_fd implementation */
5519 if (result == -1 && errno == ENOSYS) {
5520 argument_unavailable_error(NULL, "dir_fd");
5521 return NULL;
5522 }
5523 #endif
5524
5525 if (result < 0) {
5526 /* see previous comment about not putting filename in error here */
5527 posix_error();
5528 return NULL;
5529 }
5530
5531 #endif /* MS_WINDOWS */
5532
5533 Py_RETURN_NONE;
5534 }
5535
5536 /* Process operations */
5537
5538
5539 /*[clinic input]
5540 os._exit
5541
5542 status: int
5543
5544 Exit to the system with specified status, without normal exit processing.
5545 [clinic start generated code]*/
5546
5547 static PyObject *
os__exit_impl(PyObject * module,int status)5548 os__exit_impl(PyObject *module, int status)
5549 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5550 {
5551 _exit(status);
5552 return NULL; /* Make gcc -Wall happy */
5553 }
5554
5555 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5556 #define EXECV_CHAR wchar_t
5557 #else
5558 #define EXECV_CHAR char
5559 #endif
5560
5561 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5562 static void
free_string_array(EXECV_CHAR ** array,Py_ssize_t count)5563 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5564 {
5565 Py_ssize_t i;
5566 for (i = 0; i < count; i++)
5567 PyMem_Free(array[i]);
5568 PyMem_Free(array);
5569 }
5570
5571 static int
fsconvert_strdup(PyObject * o,EXECV_CHAR ** out)5572 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5573 {
5574 Py_ssize_t size;
5575 PyObject *ub;
5576 int result = 0;
5577 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5578 if (!PyUnicode_FSDecoder(o, &ub))
5579 return 0;
5580 *out = PyUnicode_AsWideCharString(ub, &size);
5581 if (*out)
5582 result = 1;
5583 #else
5584 if (!PyUnicode_FSConverter(o, &ub))
5585 return 0;
5586 size = PyBytes_GET_SIZE(ub);
5587 *out = PyMem_Malloc(size + 1);
5588 if (*out) {
5589 memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5590 result = 1;
5591 } else
5592 PyErr_NoMemory();
5593 #endif
5594 Py_DECREF(ub);
5595 return result;
5596 }
5597 #endif
5598
5599 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5600 static EXECV_CHAR**
parse_envlist(PyObject * env,Py_ssize_t * envc_ptr)5601 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5602 {
5603 Py_ssize_t i, pos, envc;
5604 PyObject *keys=NULL, *vals=NULL;
5605 PyObject *key, *val, *key2, *val2, *keyval;
5606 EXECV_CHAR **envlist;
5607
5608 i = PyMapping_Size(env);
5609 if (i < 0)
5610 return NULL;
5611 envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5612 if (envlist == NULL) {
5613 PyErr_NoMemory();
5614 return NULL;
5615 }
5616 envc = 0;
5617 keys = PyMapping_Keys(env);
5618 if (!keys)
5619 goto error;
5620 vals = PyMapping_Values(env);
5621 if (!vals)
5622 goto error;
5623 if (!PyList_Check(keys) || !PyList_Check(vals)) {
5624 PyErr_Format(PyExc_TypeError,
5625 "env.keys() or env.values() is not a list");
5626 goto error;
5627 }
5628
5629 for (pos = 0; pos < i; pos++) {
5630 key = PyList_GetItem(keys, pos);
5631 val = PyList_GetItem(vals, pos);
5632 if (!key || !val)
5633 goto error;
5634
5635 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5636 if (!PyUnicode_FSDecoder(key, &key2))
5637 goto error;
5638 if (!PyUnicode_FSDecoder(val, &val2)) {
5639 Py_DECREF(key2);
5640 goto error;
5641 }
5642 /* Search from index 1 because on Windows starting '=' is allowed for
5643 defining hidden environment variables. */
5644 if (PyUnicode_GET_LENGTH(key2) == 0 ||
5645 PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5646 {
5647 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5648 Py_DECREF(key2);
5649 Py_DECREF(val2);
5650 goto error;
5651 }
5652 keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5653 #else
5654 if (!PyUnicode_FSConverter(key, &key2))
5655 goto error;
5656 if (!PyUnicode_FSConverter(val, &val2)) {
5657 Py_DECREF(key2);
5658 goto error;
5659 }
5660 if (PyBytes_GET_SIZE(key2) == 0 ||
5661 strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5662 {
5663 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5664 Py_DECREF(key2);
5665 Py_DECREF(val2);
5666 goto error;
5667 }
5668 keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5669 PyBytes_AS_STRING(val2));
5670 #endif
5671 Py_DECREF(key2);
5672 Py_DECREF(val2);
5673 if (!keyval)
5674 goto error;
5675
5676 if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5677 Py_DECREF(keyval);
5678 goto error;
5679 }
5680
5681 Py_DECREF(keyval);
5682 }
5683 Py_DECREF(vals);
5684 Py_DECREF(keys);
5685
5686 envlist[envc] = 0;
5687 *envc_ptr = envc;
5688 return envlist;
5689
5690 error:
5691 Py_XDECREF(keys);
5692 Py_XDECREF(vals);
5693 free_string_array(envlist, envc);
5694 return NULL;
5695 }
5696
5697 static EXECV_CHAR**
parse_arglist(PyObject * argv,Py_ssize_t * argc)5698 parse_arglist(PyObject* argv, Py_ssize_t *argc)
5699 {
5700 int i;
5701 EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5702 if (argvlist == NULL) {
5703 PyErr_NoMemory();
5704 return NULL;
5705 }
5706 for (i = 0; i < *argc; i++) {
5707 PyObject* item = PySequence_ITEM(argv, i);
5708 if (item == NULL)
5709 goto fail;
5710 if (!fsconvert_strdup(item, &argvlist[i])) {
5711 Py_DECREF(item);
5712 goto fail;
5713 }
5714 Py_DECREF(item);
5715 }
5716 argvlist[*argc] = NULL;
5717 return argvlist;
5718 fail:
5719 *argc = i;
5720 free_string_array(argvlist, *argc);
5721 return NULL;
5722 }
5723
5724 #endif
5725
5726
5727 #ifdef HAVE_EXECV
5728 /*[clinic input]
5729 os.execv
5730
5731 path: path_t
5732 Path of executable file.
5733 argv: object
5734 Tuple or list of strings.
5735 /
5736
5737 Execute an executable path with arguments, replacing current process.
5738 [clinic start generated code]*/
5739
5740 static PyObject *
os_execv_impl(PyObject * module,path_t * path,PyObject * argv)5741 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5742 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5743 {
5744 EXECV_CHAR **argvlist;
5745 Py_ssize_t argc;
5746
5747 /* execv has two arguments: (path, argv), where
5748 argv is a list or tuple of strings. */
5749
5750 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5751 PyErr_SetString(PyExc_TypeError,
5752 "execv() arg 2 must be a tuple or list");
5753 return NULL;
5754 }
5755 argc = PySequence_Size(argv);
5756 if (argc < 1) {
5757 PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5758 return NULL;
5759 }
5760
5761 argvlist = parse_arglist(argv, &argc);
5762 if (argvlist == NULL) {
5763 return NULL;
5764 }
5765 if (!argvlist[0][0]) {
5766 PyErr_SetString(PyExc_ValueError,
5767 "execv() arg 2 first element cannot be empty");
5768 free_string_array(argvlist, argc);
5769 return NULL;
5770 }
5771
5772 if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5773 free_string_array(argvlist, argc);
5774 return NULL;
5775 }
5776
5777 _Py_BEGIN_SUPPRESS_IPH
5778 #ifdef HAVE_WEXECV
5779 _wexecv(path->wide, argvlist);
5780 #else
5781 execv(path->narrow, argvlist);
5782 #endif
5783 _Py_END_SUPPRESS_IPH
5784
5785 /* If we get here it's definitely an error */
5786
5787 free_string_array(argvlist, argc);
5788 return posix_error();
5789 }
5790
5791
5792 /*[clinic input]
5793 os.execve
5794
5795 path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5796 Path of executable file.
5797 argv: object
5798 Tuple or list of strings.
5799 env: object
5800 Dictionary of strings mapping to strings.
5801
5802 Execute an executable path with arguments, replacing current process.
5803 [clinic start generated code]*/
5804
5805 static PyObject *
os_execve_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env)5806 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5807 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5808 {
5809 EXECV_CHAR **argvlist = NULL;
5810 EXECV_CHAR **envlist;
5811 Py_ssize_t argc, envc;
5812
5813 /* execve has three arguments: (path, argv, env), where
5814 argv is a list or tuple of strings and env is a dictionary
5815 like posix.environ. */
5816
5817 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5818 PyErr_SetString(PyExc_TypeError,
5819 "execve: argv must be a tuple or list");
5820 goto fail_0;
5821 }
5822 argc = PySequence_Size(argv);
5823 if (argc < 1) {
5824 PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5825 return NULL;
5826 }
5827
5828 if (!PyMapping_Check(env)) {
5829 PyErr_SetString(PyExc_TypeError,
5830 "execve: environment must be a mapping object");
5831 goto fail_0;
5832 }
5833
5834 argvlist = parse_arglist(argv, &argc);
5835 if (argvlist == NULL) {
5836 goto fail_0;
5837 }
5838 if (!argvlist[0][0]) {
5839 PyErr_SetString(PyExc_ValueError,
5840 "execve: argv first element cannot be empty");
5841 goto fail_0;
5842 }
5843
5844 envlist = parse_envlist(env, &envc);
5845 if (envlist == NULL)
5846 goto fail_0;
5847
5848 if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5849 goto fail_1;
5850 }
5851
5852 _Py_BEGIN_SUPPRESS_IPH
5853 #ifdef HAVE_FEXECVE
5854 if (path->fd > -1)
5855 fexecve(path->fd, argvlist, envlist);
5856 else
5857 #endif
5858 #ifdef HAVE_WEXECV
5859 _wexecve(path->wide, argvlist, envlist);
5860 #else
5861 execve(path->narrow, argvlist, envlist);
5862 #endif
5863 _Py_END_SUPPRESS_IPH
5864
5865 /* If we get here it's definitely an error */
5866
5867 posix_path_error(path);
5868 fail_1:
5869 free_string_array(envlist, envc);
5870 fail_0:
5871 if (argvlist)
5872 free_string_array(argvlist, argc);
5873 return NULL;
5874 }
5875
5876 #endif /* HAVE_EXECV */
5877
5878 #ifdef HAVE_POSIX_SPAWN
5879
5880 enum posix_spawn_file_actions_identifier {
5881 POSIX_SPAWN_OPEN,
5882 POSIX_SPAWN_CLOSE,
5883 POSIX_SPAWN_DUP2
5884 };
5885
5886 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
5887 static int
5888 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
5889 #endif
5890
5891 static int
parse_posix_spawn_flags(PyObject * module,const char * func_name,PyObject * setpgroup,int resetids,int setsid,PyObject * setsigmask,PyObject * setsigdef,PyObject * scheduler,posix_spawnattr_t * attrp)5892 parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
5893 int resetids, int setsid, PyObject *setsigmask,
5894 PyObject *setsigdef, PyObject *scheduler,
5895 posix_spawnattr_t *attrp)
5896 {
5897 long all_flags = 0;
5898
5899 errno = posix_spawnattr_init(attrp);
5900 if (errno) {
5901 posix_error();
5902 return -1;
5903 }
5904
5905 if (setpgroup) {
5906 pid_t pgid = PyLong_AsPid(setpgroup);
5907 if (pgid == (pid_t)-1 && PyErr_Occurred()) {
5908 goto fail;
5909 }
5910 errno = posix_spawnattr_setpgroup(attrp, pgid);
5911 if (errno) {
5912 posix_error();
5913 goto fail;
5914 }
5915 all_flags |= POSIX_SPAWN_SETPGROUP;
5916 }
5917
5918 if (resetids) {
5919 all_flags |= POSIX_SPAWN_RESETIDS;
5920 }
5921
5922 if (setsid) {
5923 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5924 if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
5925 #endif
5926 #ifdef POSIX_SPAWN_SETSID
5927 all_flags |= POSIX_SPAWN_SETSID;
5928 #elif defined(POSIX_SPAWN_SETSID_NP)
5929 all_flags |= POSIX_SPAWN_SETSID_NP;
5930 #else
5931 argument_unavailable_error(func_name, "setsid");
5932 return -1;
5933 #endif
5934
5935 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5936 } else {
5937 argument_unavailable_error(func_name, "setsid");
5938 return -1;
5939 }
5940 #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
5941
5942 }
5943
5944 #ifdef HAVE_SIGSET_T
5945 if (setsigmask) {
5946 sigset_t set;
5947 if (!_Py_Sigset_Converter(setsigmask, &set)) {
5948 goto fail;
5949 }
5950 errno = posix_spawnattr_setsigmask(attrp, &set);
5951 if (errno) {
5952 posix_error();
5953 goto fail;
5954 }
5955 all_flags |= POSIX_SPAWN_SETSIGMASK;
5956 }
5957
5958 if (setsigdef) {
5959 sigset_t set;
5960 if (!_Py_Sigset_Converter(setsigdef, &set)) {
5961 goto fail;
5962 }
5963 errno = posix_spawnattr_setsigdefault(attrp, &set);
5964 if (errno) {
5965 posix_error();
5966 goto fail;
5967 }
5968 all_flags |= POSIX_SPAWN_SETSIGDEF;
5969 }
5970 #else
5971 if (setsigmask || setsigdef) {
5972 PyErr_SetString(PyExc_NotImplementedError,
5973 "sigset is not supported on this platform");
5974 goto fail;
5975 }
5976 #endif
5977
5978 if (scheduler) {
5979 #ifdef POSIX_SPAWN_SETSCHEDULER
5980 PyObject *py_schedpolicy;
5981 PyObject *schedparam_obj;
5982 struct sched_param schedparam;
5983
5984 if (!PyArg_ParseTuple(scheduler, "OO"
5985 ";A scheduler tuple must have two elements",
5986 &py_schedpolicy, &schedparam_obj)) {
5987 goto fail;
5988 }
5989 if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
5990 goto fail;
5991 }
5992 if (py_schedpolicy != Py_None) {
5993 int schedpolicy = _PyLong_AsInt(py_schedpolicy);
5994
5995 if (schedpolicy == -1 && PyErr_Occurred()) {
5996 goto fail;
5997 }
5998 errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
5999 if (errno) {
6000 posix_error();
6001 goto fail;
6002 }
6003 all_flags |= POSIX_SPAWN_SETSCHEDULER;
6004 }
6005 errno = posix_spawnattr_setschedparam(attrp, &schedparam);
6006 if (errno) {
6007 posix_error();
6008 goto fail;
6009 }
6010 all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
6011 #else
6012 PyErr_SetString(PyExc_NotImplementedError,
6013 "The scheduler option is not supported in this system.");
6014 goto fail;
6015 #endif
6016 }
6017
6018 errno = posix_spawnattr_setflags(attrp, all_flags);
6019 if (errno) {
6020 posix_error();
6021 goto fail;
6022 }
6023
6024 return 0;
6025
6026 fail:
6027 (void)posix_spawnattr_destroy(attrp);
6028 return -1;
6029 }
6030
6031 static int
parse_file_actions(PyObject * file_actions,posix_spawn_file_actions_t * file_actionsp,PyObject * temp_buffer)6032 parse_file_actions(PyObject *file_actions,
6033 posix_spawn_file_actions_t *file_actionsp,
6034 PyObject *temp_buffer)
6035 {
6036 PyObject *seq;
6037 PyObject *file_action = NULL;
6038 PyObject *tag_obj;
6039
6040 seq = PySequence_Fast(file_actions,
6041 "file_actions must be a sequence or None");
6042 if (seq == NULL) {
6043 return -1;
6044 }
6045
6046 errno = posix_spawn_file_actions_init(file_actionsp);
6047 if (errno) {
6048 posix_error();
6049 Py_DECREF(seq);
6050 return -1;
6051 }
6052
6053 for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
6054 file_action = PySequence_Fast_GET_ITEM(seq, i);
6055 Py_INCREF(file_action);
6056 if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
6057 PyErr_SetString(PyExc_TypeError,
6058 "Each file_actions element must be a non-empty tuple");
6059 goto fail;
6060 }
6061 long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
6062 if (tag == -1 && PyErr_Occurred()) {
6063 goto fail;
6064 }
6065
6066 /* Populate the file_actions object */
6067 switch (tag) {
6068 case POSIX_SPAWN_OPEN: {
6069 int fd, oflag;
6070 PyObject *path;
6071 unsigned long mode;
6072 if (!PyArg_ParseTuple(file_action, "OiO&ik"
6073 ";A open file_action tuple must have 5 elements",
6074 &tag_obj, &fd, PyUnicode_FSConverter, &path,
6075 &oflag, &mode))
6076 {
6077 goto fail;
6078 }
6079 if (PyList_Append(temp_buffer, path)) {
6080 Py_DECREF(path);
6081 goto fail;
6082 }
6083 errno = posix_spawn_file_actions_addopen(file_actionsp,
6084 fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
6085 Py_DECREF(path);
6086 if (errno) {
6087 posix_error();
6088 goto fail;
6089 }
6090 break;
6091 }
6092 case POSIX_SPAWN_CLOSE: {
6093 int fd;
6094 if (!PyArg_ParseTuple(file_action, "Oi"
6095 ";A close file_action tuple must have 2 elements",
6096 &tag_obj, &fd))
6097 {
6098 goto fail;
6099 }
6100 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
6101 if (errno) {
6102 posix_error();
6103 goto fail;
6104 }
6105 break;
6106 }
6107 case POSIX_SPAWN_DUP2: {
6108 int fd1, fd2;
6109 if (!PyArg_ParseTuple(file_action, "Oii"
6110 ";A dup2 file_action tuple must have 3 elements",
6111 &tag_obj, &fd1, &fd2))
6112 {
6113 goto fail;
6114 }
6115 errno = posix_spawn_file_actions_adddup2(file_actionsp,
6116 fd1, fd2);
6117 if (errno) {
6118 posix_error();
6119 goto fail;
6120 }
6121 break;
6122 }
6123 default: {
6124 PyErr_SetString(PyExc_TypeError,
6125 "Unknown file_actions identifier");
6126 goto fail;
6127 }
6128 }
6129 Py_DECREF(file_action);
6130 }
6131
6132 Py_DECREF(seq);
6133 return 0;
6134
6135 fail:
6136 Py_DECREF(seq);
6137 Py_DECREF(file_action);
6138 (void)posix_spawn_file_actions_destroy(file_actionsp);
6139 return -1;
6140 }
6141
6142
6143 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)6144 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
6145 PyObject *env, PyObject *file_actions,
6146 PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
6147 PyObject *setsigdef, PyObject *scheduler)
6148 {
6149 const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
6150 EXECV_CHAR **argvlist = NULL;
6151 EXECV_CHAR **envlist = NULL;
6152 posix_spawn_file_actions_t file_actions_buf;
6153 posix_spawn_file_actions_t *file_actionsp = NULL;
6154 posix_spawnattr_t attr;
6155 posix_spawnattr_t *attrp = NULL;
6156 Py_ssize_t argc, envc;
6157 PyObject *result = NULL;
6158 PyObject *temp_buffer = NULL;
6159 pid_t pid;
6160 int err_code;
6161
6162 /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
6163 argv is a list or tuple of strings and env is a dictionary
6164 like posix.environ. */
6165
6166 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6167 PyErr_Format(PyExc_TypeError,
6168 "%s: argv must be a tuple or list", func_name);
6169 goto exit;
6170 }
6171 argc = PySequence_Size(argv);
6172 if (argc < 1) {
6173 PyErr_Format(PyExc_ValueError,
6174 "%s: argv must not be empty", func_name);
6175 return NULL;
6176 }
6177
6178 if (!PyMapping_Check(env)) {
6179 PyErr_Format(PyExc_TypeError,
6180 "%s: environment must be a mapping object", func_name);
6181 goto exit;
6182 }
6183
6184 argvlist = parse_arglist(argv, &argc);
6185 if (argvlist == NULL) {
6186 goto exit;
6187 }
6188 if (!argvlist[0][0]) {
6189 PyErr_Format(PyExc_ValueError,
6190 "%s: argv first element cannot be empty", func_name);
6191 goto exit;
6192 }
6193
6194 envlist = parse_envlist(env, &envc);
6195 if (envlist == NULL) {
6196 goto exit;
6197 }
6198
6199 if (file_actions != NULL && file_actions != Py_None) {
6200 /* There is a bug in old versions of glibc that makes some of the
6201 * helper functions for manipulating file actions not copy the provided
6202 * buffers. The problem is that posix_spawn_file_actions_addopen does not
6203 * copy the value of path for some old versions of glibc (<2.20).
6204 * The use of temp_buffer here is a workaround that keeps the
6205 * python objects that own the buffers alive until posix_spawn gets called.
6206 * Check https://bugs.python.org/issue33630 and
6207 * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
6208 temp_buffer = PyList_New(0);
6209 if (!temp_buffer) {
6210 goto exit;
6211 }
6212 if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
6213 goto exit;
6214 }
6215 file_actionsp = &file_actions_buf;
6216 }
6217
6218 if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
6219 setsigmask, setsigdef, scheduler, &attr)) {
6220 goto exit;
6221 }
6222 attrp = &attr;
6223
6224 if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
6225 goto exit;
6226 }
6227
6228 _Py_BEGIN_SUPPRESS_IPH
6229 #ifdef HAVE_POSIX_SPAWNP
6230 if (use_posix_spawnp) {
6231 err_code = posix_spawnp(&pid, path->narrow,
6232 file_actionsp, attrp, argvlist, envlist);
6233 }
6234 else
6235 #endif /* HAVE_POSIX_SPAWNP */
6236 {
6237 err_code = posix_spawn(&pid, path->narrow,
6238 file_actionsp, attrp, argvlist, envlist);
6239 }
6240 _Py_END_SUPPRESS_IPH
6241
6242 if (err_code) {
6243 errno = err_code;
6244 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
6245 goto exit;
6246 }
6247 #ifdef _Py_MEMORY_SANITIZER
6248 __msan_unpoison(&pid, sizeof(pid));
6249 #endif
6250 result = PyLong_FromPid(pid);
6251
6252 exit:
6253 if (file_actionsp) {
6254 (void)posix_spawn_file_actions_destroy(file_actionsp);
6255 }
6256 if (attrp) {
6257 (void)posix_spawnattr_destroy(attrp);
6258 }
6259 if (envlist) {
6260 free_string_array(envlist, envc);
6261 }
6262 if (argvlist) {
6263 free_string_array(argvlist, argc);
6264 }
6265 Py_XDECREF(temp_buffer);
6266 return result;
6267 }
6268
6269
6270 /*[clinic input]
6271
6272 os.posix_spawn
6273 path: path_t
6274 Path of executable file.
6275 argv: object
6276 Tuple or list of strings.
6277 env: object
6278 Dictionary of strings mapping to strings.
6279 /
6280 *
6281 file_actions: object(c_default='NULL') = ()
6282 A sequence of file action tuples.
6283 setpgroup: object = NULL
6284 The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6285 resetids: bool(accept={int}) = False
6286 If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
6287 setsid: bool(accept={int}) = False
6288 If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6289 setsigmask: object(c_default='NULL') = ()
6290 The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6291 setsigdef: object(c_default='NULL') = ()
6292 The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6293 scheduler: object = NULL
6294 A tuple with the scheduler policy (optional) and parameters.
6295
6296 Execute the program specified by path in a new process.
6297 [clinic start generated code]*/
6298
6299 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)6300 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
6301 PyObject *env, PyObject *file_actions,
6302 PyObject *setpgroup, int resetids, int setsid,
6303 PyObject *setsigmask, PyObject *setsigdef,
6304 PyObject *scheduler)
6305 /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
6306 {
6307 return py_posix_spawn(0, module, path, argv, env, file_actions,
6308 setpgroup, resetids, setsid, setsigmask, setsigdef,
6309 scheduler);
6310 }
6311 #endif /* HAVE_POSIX_SPAWN */
6312
6313
6314
6315 #ifdef HAVE_POSIX_SPAWNP
6316 /*[clinic input]
6317
6318 os.posix_spawnp
6319 path: path_t
6320 Path of executable file.
6321 argv: object
6322 Tuple or list of strings.
6323 env: object
6324 Dictionary of strings mapping to strings.
6325 /
6326 *
6327 file_actions: object(c_default='NULL') = ()
6328 A sequence of file action tuples.
6329 setpgroup: object = NULL
6330 The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6331 resetids: bool(accept={int}) = False
6332 If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
6333 setsid: bool(accept={int}) = False
6334 If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6335 setsigmask: object(c_default='NULL') = ()
6336 The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6337 setsigdef: object(c_default='NULL') = ()
6338 The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6339 scheduler: object = NULL
6340 A tuple with the scheduler policy (optional) and parameters.
6341
6342 Execute the program specified by path in a new process.
6343 [clinic start generated code]*/
6344
6345 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)6346 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
6347 PyObject *env, PyObject *file_actions,
6348 PyObject *setpgroup, int resetids, int setsid,
6349 PyObject *setsigmask, PyObject *setsigdef,
6350 PyObject *scheduler)
6351 /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
6352 {
6353 return py_posix_spawn(1, module, path, argv, env, file_actions,
6354 setpgroup, resetids, setsid, setsigmask, setsigdef,
6355 scheduler);
6356 }
6357 #endif /* HAVE_POSIX_SPAWNP */
6358
6359 #ifdef HAVE_RTPSPAWN
6360 static intptr_t
_rtp_spawn(int mode,const char * rtpFileName,const char * argv[],const char * envp[])6361 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
6362 const char *envp[])
6363 {
6364 RTP_ID rtpid;
6365 int status;
6366 pid_t res;
6367 int async_err = 0;
6368
6369 /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
6370 uStackSize=0 cannot be used, the default stack size is too small for
6371 Python. */
6372 if (envp) {
6373 rtpid = rtpSpawn(rtpFileName, argv, envp,
6374 100, 0x1000000, 0, VX_FP_TASK);
6375 }
6376 else {
6377 rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
6378 100, 0x1000000, 0, VX_FP_TASK);
6379 }
6380 if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
6381 do {
6382 res = waitpid((pid_t)rtpid, &status, 0);
6383 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6384
6385 if (res < 0)
6386 return RTP_ID_ERROR;
6387 return ((intptr_t)status);
6388 }
6389 return ((intptr_t)rtpid);
6390 }
6391 #endif
6392
6393 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
6394 /*[clinic input]
6395 os.spawnv
6396
6397 mode: int
6398 Mode of process creation.
6399 path: path_t
6400 Path of executable file.
6401 argv: object
6402 Tuple or list of strings.
6403 /
6404
6405 Execute the program specified by path in a new process.
6406 [clinic start generated code]*/
6407
6408 static PyObject *
os_spawnv_impl(PyObject * module,int mode,path_t * path,PyObject * argv)6409 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
6410 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
6411 {
6412 EXECV_CHAR **argvlist;
6413 int i;
6414 Py_ssize_t argc;
6415 intptr_t spawnval;
6416 PyObject *(*getitem)(PyObject *, Py_ssize_t);
6417
6418 /* spawnv has three arguments: (mode, path, argv), where
6419 argv is a list or tuple of strings. */
6420
6421 if (PyList_Check(argv)) {
6422 argc = PyList_Size(argv);
6423 getitem = PyList_GetItem;
6424 }
6425 else if (PyTuple_Check(argv)) {
6426 argc = PyTuple_Size(argv);
6427 getitem = PyTuple_GetItem;
6428 }
6429 else {
6430 PyErr_SetString(PyExc_TypeError,
6431 "spawnv() arg 2 must be a tuple or list");
6432 return NULL;
6433 }
6434 if (argc == 0) {
6435 PyErr_SetString(PyExc_ValueError,
6436 "spawnv() arg 2 cannot be empty");
6437 return NULL;
6438 }
6439
6440 argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6441 if (argvlist == NULL) {
6442 return PyErr_NoMemory();
6443 }
6444 for (i = 0; i < argc; i++) {
6445 if (!fsconvert_strdup((*getitem)(argv, i),
6446 &argvlist[i])) {
6447 free_string_array(argvlist, i);
6448 PyErr_SetString(
6449 PyExc_TypeError,
6450 "spawnv() arg 2 must contain only strings");
6451 return NULL;
6452 }
6453 if (i == 0 && !argvlist[0][0]) {
6454 free_string_array(argvlist, i + 1);
6455 PyErr_SetString(
6456 PyExc_ValueError,
6457 "spawnv() arg 2 first element cannot be empty");
6458 return NULL;
6459 }
6460 }
6461 argvlist[argc] = NULL;
6462
6463 #if !defined(HAVE_RTPSPAWN)
6464 if (mode == _OLD_P_OVERLAY)
6465 mode = _P_OVERLAY;
6466 #endif
6467
6468 if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
6469 Py_None) < 0) {
6470 free_string_array(argvlist, argc);
6471 return NULL;
6472 }
6473
6474 Py_BEGIN_ALLOW_THREADS
6475 _Py_BEGIN_SUPPRESS_IPH
6476 #ifdef HAVE_WSPAWNV
6477 spawnval = _wspawnv(mode, path->wide, argvlist);
6478 #elif defined(HAVE_RTPSPAWN)
6479 spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
6480 #else
6481 spawnval = _spawnv(mode, path->narrow, argvlist);
6482 #endif
6483 _Py_END_SUPPRESS_IPH
6484 Py_END_ALLOW_THREADS
6485
6486 free_string_array(argvlist, argc);
6487
6488 if (spawnval == -1)
6489 return posix_error();
6490 else
6491 return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6492 }
6493
6494 /*[clinic input]
6495 os.spawnve
6496
6497 mode: int
6498 Mode of process creation.
6499 path: path_t
6500 Path of executable file.
6501 argv: object
6502 Tuple or list of strings.
6503 env: object
6504 Dictionary of strings mapping to strings.
6505 /
6506
6507 Execute the program specified by path in a new process.
6508 [clinic start generated code]*/
6509
6510 static PyObject *
os_spawnve_impl(PyObject * module,int mode,path_t * path,PyObject * argv,PyObject * env)6511 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
6512 PyObject *env)
6513 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
6514 {
6515 EXECV_CHAR **argvlist;
6516 EXECV_CHAR **envlist;
6517 PyObject *res = NULL;
6518 Py_ssize_t argc, i, envc;
6519 intptr_t spawnval;
6520 PyObject *(*getitem)(PyObject *, Py_ssize_t);
6521 Py_ssize_t lastarg = 0;
6522
6523 /* spawnve has four arguments: (mode, path, argv, env), where
6524 argv is a list or tuple of strings and env is a dictionary
6525 like posix.environ. */
6526
6527 if (PyList_Check(argv)) {
6528 argc = PyList_Size(argv);
6529 getitem = PyList_GetItem;
6530 }
6531 else if (PyTuple_Check(argv)) {
6532 argc = PyTuple_Size(argv);
6533 getitem = PyTuple_GetItem;
6534 }
6535 else {
6536 PyErr_SetString(PyExc_TypeError,
6537 "spawnve() arg 2 must be a tuple or list");
6538 goto fail_0;
6539 }
6540 if (argc == 0) {
6541 PyErr_SetString(PyExc_ValueError,
6542 "spawnve() arg 2 cannot be empty");
6543 goto fail_0;
6544 }
6545 if (!PyMapping_Check(env)) {
6546 PyErr_SetString(PyExc_TypeError,
6547 "spawnve() arg 3 must be a mapping object");
6548 goto fail_0;
6549 }
6550
6551 argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6552 if (argvlist == NULL) {
6553 PyErr_NoMemory();
6554 goto fail_0;
6555 }
6556 for (i = 0; i < argc; i++) {
6557 if (!fsconvert_strdup((*getitem)(argv, i),
6558 &argvlist[i]))
6559 {
6560 lastarg = i;
6561 goto fail_1;
6562 }
6563 if (i == 0 && !argvlist[0][0]) {
6564 lastarg = i + 1;
6565 PyErr_SetString(
6566 PyExc_ValueError,
6567 "spawnv() arg 2 first element cannot be empty");
6568 goto fail_1;
6569 }
6570 }
6571 lastarg = argc;
6572 argvlist[argc] = NULL;
6573
6574 envlist = parse_envlist(env, &envc);
6575 if (envlist == NULL)
6576 goto fail_1;
6577
6578 #if !defined(HAVE_RTPSPAWN)
6579 if (mode == _OLD_P_OVERLAY)
6580 mode = _P_OVERLAY;
6581 #endif
6582
6583 if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6584 goto fail_2;
6585 }
6586
6587 Py_BEGIN_ALLOW_THREADS
6588 _Py_BEGIN_SUPPRESS_IPH
6589 #ifdef HAVE_WSPAWNV
6590 spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6591 #elif defined(HAVE_RTPSPAWN)
6592 spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6593 (const char **)envlist);
6594 #else
6595 spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6596 #endif
6597 _Py_END_SUPPRESS_IPH
6598 Py_END_ALLOW_THREADS
6599
6600 if (spawnval == -1)
6601 (void) posix_error();
6602 else
6603 res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6604
6605 fail_2:
6606 while (--envc >= 0) {
6607 PyMem_Free(envlist[envc]);
6608 }
6609 PyMem_Free(envlist);
6610 fail_1:
6611 free_string_array(argvlist, lastarg);
6612 fail_0:
6613 return res;
6614 }
6615
6616 #endif /* HAVE_SPAWNV */
6617
6618 #ifdef HAVE_FORK
6619
6620 /* Helper function to validate arguments.
6621 Returns 0 on success. non-zero on failure with a TypeError raised.
6622 If obj is non-NULL it must be callable. */
6623 static int
check_null_or_callable(PyObject * obj,const char * obj_name)6624 check_null_or_callable(PyObject *obj, const char* obj_name)
6625 {
6626 if (obj && !PyCallable_Check(obj)) {
6627 PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6628 obj_name, _PyType_Name(Py_TYPE(obj)));
6629 return -1;
6630 }
6631 return 0;
6632 }
6633
6634 /*[clinic input]
6635 os.register_at_fork
6636
6637 *
6638 before: object=NULL
6639 A callable to be called in the parent before the fork() syscall.
6640 after_in_child: object=NULL
6641 A callable to be called in the child after fork().
6642 after_in_parent: object=NULL
6643 A callable to be called in the parent after fork().
6644
6645 Register callables to be called when forking a new process.
6646
6647 'before' callbacks are called in reverse order.
6648 'after_in_child' and 'after_in_parent' callbacks are called in order.
6649
6650 [clinic start generated code]*/
6651
6652 static PyObject *
os_register_at_fork_impl(PyObject * module,PyObject * before,PyObject * after_in_child,PyObject * after_in_parent)6653 os_register_at_fork_impl(PyObject *module, PyObject *before,
6654 PyObject *after_in_child, PyObject *after_in_parent)
6655 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6656 {
6657 PyInterpreterState *interp;
6658
6659 if (!before && !after_in_child && !after_in_parent) {
6660 PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6661 return NULL;
6662 }
6663 if (check_null_or_callable(before, "before") ||
6664 check_null_or_callable(after_in_child, "after_in_child") ||
6665 check_null_or_callable(after_in_parent, "after_in_parent")) {
6666 return NULL;
6667 }
6668 interp = _PyInterpreterState_GET();
6669
6670 if (register_at_forker(&interp->before_forkers, before)) {
6671 return NULL;
6672 }
6673 if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6674 return NULL;
6675 }
6676 if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6677 return NULL;
6678 }
6679 Py_RETURN_NONE;
6680 }
6681 #endif /* HAVE_FORK */
6682
6683
6684 #ifdef HAVE_FORK1
6685 /*[clinic input]
6686 os.fork1
6687
6688 Fork a child process with a single multiplexed (i.e., not bound) thread.
6689
6690 Return 0 to child process and PID of child to parent process.
6691 [clinic start generated code]*/
6692
6693 static PyObject *
os_fork1_impl(PyObject * module)6694 os_fork1_impl(PyObject *module)
6695 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6696 {
6697 pid_t pid;
6698
6699 if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
6700 PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6701 return NULL;
6702 }
6703 PyOS_BeforeFork();
6704 pid = fork1();
6705 if (pid == 0) {
6706 /* child: this clobbers and resets the import lock. */
6707 PyOS_AfterFork_Child();
6708 } else {
6709 /* parent: release the import lock. */
6710 PyOS_AfterFork_Parent();
6711 }
6712 if (pid == -1)
6713 return posix_error();
6714 return PyLong_FromPid(pid);
6715 }
6716 #endif /* HAVE_FORK1 */
6717
6718
6719 #ifdef HAVE_FORK
6720 /*[clinic input]
6721 os.fork
6722
6723 Fork a child process.
6724
6725 Return 0 to child process and PID of child to parent process.
6726 [clinic start generated code]*/
6727
6728 static PyObject *
os_fork_impl(PyObject * module)6729 os_fork_impl(PyObject *module)
6730 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6731 {
6732 pid_t pid;
6733 PyInterpreterState *interp = _PyInterpreterState_GET();
6734 if (interp->config._isolated_interpreter) {
6735 PyErr_SetString(PyExc_RuntimeError,
6736 "fork not supported for isolated subinterpreters");
6737 return NULL;
6738 }
6739 if (PySys_Audit("os.fork", NULL) < 0) {
6740 return NULL;
6741 }
6742 PyOS_BeforeFork();
6743 pid = fork();
6744 if (pid == 0) {
6745 /* child: this clobbers and resets the import lock. */
6746 PyOS_AfterFork_Child();
6747 } else {
6748 /* parent: release the import lock. */
6749 PyOS_AfterFork_Parent();
6750 }
6751 if (pid == -1)
6752 return posix_error();
6753 return PyLong_FromPid(pid);
6754 }
6755 #endif /* HAVE_FORK */
6756
6757
6758 #ifdef HAVE_SCHED_H
6759 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6760 /*[clinic input]
6761 os.sched_get_priority_max
6762
6763 policy: int
6764
6765 Get the maximum scheduling priority for policy.
6766 [clinic start generated code]*/
6767
6768 static PyObject *
os_sched_get_priority_max_impl(PyObject * module,int policy)6769 os_sched_get_priority_max_impl(PyObject *module, int policy)
6770 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6771 {
6772 int max;
6773
6774 max = sched_get_priority_max(policy);
6775 if (max < 0)
6776 return posix_error();
6777 return PyLong_FromLong(max);
6778 }
6779
6780
6781 /*[clinic input]
6782 os.sched_get_priority_min
6783
6784 policy: int
6785
6786 Get the minimum scheduling priority for policy.
6787 [clinic start generated code]*/
6788
6789 static PyObject *
os_sched_get_priority_min_impl(PyObject * module,int policy)6790 os_sched_get_priority_min_impl(PyObject *module, int policy)
6791 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6792 {
6793 int min = sched_get_priority_min(policy);
6794 if (min < 0)
6795 return posix_error();
6796 return PyLong_FromLong(min);
6797 }
6798 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6799
6800
6801 #ifdef HAVE_SCHED_SETSCHEDULER
6802 /*[clinic input]
6803 os.sched_getscheduler
6804 pid: pid_t
6805 /
6806
6807 Get the scheduling policy for the process identified by pid.
6808
6809 Passing 0 for pid returns the scheduling policy for the calling process.
6810 [clinic start generated code]*/
6811
6812 static PyObject *
os_sched_getscheduler_impl(PyObject * module,pid_t pid)6813 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6814 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
6815 {
6816 int policy;
6817
6818 policy = sched_getscheduler(pid);
6819 if (policy < 0)
6820 return posix_error();
6821 return PyLong_FromLong(policy);
6822 }
6823 #endif /* HAVE_SCHED_SETSCHEDULER */
6824
6825
6826 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6827 /*[clinic input]
6828 class os.sched_param "PyObject *" "SchedParamType"
6829
6830 @classmethod
6831 os.sched_param.__new__
6832
6833 sched_priority: object
6834 A scheduling parameter.
6835
6836 Currently has only one field: sched_priority
6837 [clinic start generated code]*/
6838
6839 static PyObject *
os_sched_param_impl(PyTypeObject * type,PyObject * sched_priority)6840 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6841 /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
6842 {
6843 PyObject *res;
6844
6845 res = PyStructSequence_New(type);
6846 if (!res)
6847 return NULL;
6848 Py_INCREF(sched_priority);
6849 PyStructSequence_SET_ITEM(res, 0, sched_priority);
6850 return res;
6851 }
6852
6853 PyDoc_VAR(os_sched_param__doc__);
6854
6855 static PyStructSequence_Field sched_param_fields[] = {
6856 {"sched_priority", "the scheduling priority"},
6857 {0}
6858 };
6859
6860 static PyStructSequence_Desc sched_param_desc = {
6861 "sched_param", /* name */
6862 os_sched_param__doc__, /* doc */
6863 sched_param_fields,
6864 1
6865 };
6866
6867 static int
convert_sched_param(PyObject * module,PyObject * param,struct sched_param * res)6868 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
6869 {
6870 long priority;
6871
6872 if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
6873 PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
6874 return 0;
6875 }
6876 priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
6877 if (priority == -1 && PyErr_Occurred())
6878 return 0;
6879 if (priority > INT_MAX || priority < INT_MIN) {
6880 PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
6881 return 0;
6882 }
6883 res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
6884 return 1;
6885 }
6886 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
6887
6888
6889 #ifdef HAVE_SCHED_SETSCHEDULER
6890 /*[clinic input]
6891 os.sched_setscheduler
6892
6893 pid: pid_t
6894 policy: int
6895 param as param_obj: object
6896 /
6897
6898 Set the scheduling policy for the process identified by pid.
6899
6900 If pid is 0, the calling process is changed.
6901 param is an instance of sched_param.
6902 [clinic start generated code]*/
6903
6904 static PyObject *
os_sched_setscheduler_impl(PyObject * module,pid_t pid,int policy,PyObject * param_obj)6905 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
6906 PyObject *param_obj)
6907 /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
6908 {
6909 struct sched_param param;
6910 if (!convert_sched_param(module, param_obj, ¶m)) {
6911 return NULL;
6912 }
6913
6914 /*
6915 ** sched_setscheduler() returns 0 in Linux, but the previous
6916 ** scheduling policy under Solaris/Illumos, and others.
6917 ** On error, -1 is returned in all Operating Systems.
6918 */
6919 if (sched_setscheduler(pid, policy, ¶m) == -1)
6920 return posix_error();
6921 Py_RETURN_NONE;
6922 }
6923 #endif /* HAVE_SCHED_SETSCHEDULER*/
6924
6925
6926 #ifdef HAVE_SCHED_SETPARAM
6927 /*[clinic input]
6928 os.sched_getparam
6929 pid: pid_t
6930 /
6931
6932 Returns scheduling parameters for the process identified by pid.
6933
6934 If pid is 0, returns parameters for the calling process.
6935 Return value is an instance of sched_param.
6936 [clinic start generated code]*/
6937
6938 static PyObject *
os_sched_getparam_impl(PyObject * module,pid_t pid)6939 os_sched_getparam_impl(PyObject *module, pid_t pid)
6940 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
6941 {
6942 struct sched_param param;
6943 PyObject *result;
6944 PyObject *priority;
6945
6946 if (sched_getparam(pid, ¶m))
6947 return posix_error();
6948 PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
6949 result = PyStructSequence_New((PyTypeObject *)SchedParamType);
6950 if (!result)
6951 return NULL;
6952 priority = PyLong_FromLong(param.sched_priority);
6953 if (!priority) {
6954 Py_DECREF(result);
6955 return NULL;
6956 }
6957 PyStructSequence_SET_ITEM(result, 0, priority);
6958 return result;
6959 }
6960
6961
6962 /*[clinic input]
6963 os.sched_setparam
6964 pid: pid_t
6965 param as param_obj: object
6966 /
6967
6968 Set scheduling parameters for the process identified by pid.
6969
6970 If pid is 0, sets parameters for the calling process.
6971 param should be an instance of sched_param.
6972 [clinic start generated code]*/
6973
6974 static PyObject *
os_sched_setparam_impl(PyObject * module,pid_t pid,PyObject * param_obj)6975 os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
6976 /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
6977 {
6978 struct sched_param param;
6979 if (!convert_sched_param(module, param_obj, ¶m)) {
6980 return NULL;
6981 }
6982
6983 if (sched_setparam(pid, ¶m))
6984 return posix_error();
6985 Py_RETURN_NONE;
6986 }
6987 #endif /* HAVE_SCHED_SETPARAM */
6988
6989
6990 #ifdef HAVE_SCHED_RR_GET_INTERVAL
6991 /*[clinic input]
6992 os.sched_rr_get_interval -> double
6993 pid: pid_t
6994 /
6995
6996 Return the round-robin quantum for the process identified by pid, in seconds.
6997
6998 Value returned is a float.
6999 [clinic start generated code]*/
7000
7001 static double
os_sched_rr_get_interval_impl(PyObject * module,pid_t pid)7002 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
7003 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
7004 {
7005 struct timespec interval;
7006 if (sched_rr_get_interval(pid, &interval)) {
7007 posix_error();
7008 return -1.0;
7009 }
7010 #ifdef _Py_MEMORY_SANITIZER
7011 __msan_unpoison(&interval, sizeof(interval));
7012 #endif
7013 return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
7014 }
7015 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
7016
7017
7018 /*[clinic input]
7019 os.sched_yield
7020
7021 Voluntarily relinquish the CPU.
7022 [clinic start generated code]*/
7023
7024 static PyObject *
os_sched_yield_impl(PyObject * module)7025 os_sched_yield_impl(PyObject *module)
7026 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
7027 {
7028 if (sched_yield())
7029 return posix_error();
7030 Py_RETURN_NONE;
7031 }
7032
7033 #ifdef HAVE_SCHED_SETAFFINITY
7034 /* The minimum number of CPUs allocated in a cpu_set_t */
7035 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
7036
7037 /*[clinic input]
7038 os.sched_setaffinity
7039 pid: pid_t
7040 mask : object
7041 /
7042
7043 Set the CPU affinity of the process identified by pid to mask.
7044
7045 mask should be an iterable of integers identifying CPUs.
7046 [clinic start generated code]*/
7047
7048 static PyObject *
os_sched_setaffinity_impl(PyObject * module,pid_t pid,PyObject * mask)7049 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
7050 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
7051 {
7052 int ncpus;
7053 size_t setsize;
7054 cpu_set_t *cpu_set = NULL;
7055 PyObject *iterator = NULL, *item;
7056
7057 iterator = PyObject_GetIter(mask);
7058 if (iterator == NULL)
7059 return NULL;
7060
7061 ncpus = NCPUS_START;
7062 setsize = CPU_ALLOC_SIZE(ncpus);
7063 cpu_set = CPU_ALLOC(ncpus);
7064 if (cpu_set == NULL) {
7065 PyErr_NoMemory();
7066 goto error;
7067 }
7068 CPU_ZERO_S(setsize, cpu_set);
7069
7070 while ((item = PyIter_Next(iterator))) {
7071 long cpu;
7072 if (!PyLong_Check(item)) {
7073 PyErr_Format(PyExc_TypeError,
7074 "expected an iterator of ints, "
7075 "but iterator yielded %R",
7076 Py_TYPE(item));
7077 Py_DECREF(item);
7078 goto error;
7079 }
7080 cpu = PyLong_AsLong(item);
7081 Py_DECREF(item);
7082 if (cpu < 0) {
7083 if (!PyErr_Occurred())
7084 PyErr_SetString(PyExc_ValueError, "negative CPU number");
7085 goto error;
7086 }
7087 if (cpu > INT_MAX - 1) {
7088 PyErr_SetString(PyExc_OverflowError, "CPU number too large");
7089 goto error;
7090 }
7091 if (cpu >= ncpus) {
7092 /* Grow CPU mask to fit the CPU number */
7093 int newncpus = ncpus;
7094 cpu_set_t *newmask;
7095 size_t newsetsize;
7096 while (newncpus <= cpu) {
7097 if (newncpus > INT_MAX / 2)
7098 newncpus = cpu + 1;
7099 else
7100 newncpus = newncpus * 2;
7101 }
7102 newmask = CPU_ALLOC(newncpus);
7103 if (newmask == NULL) {
7104 PyErr_NoMemory();
7105 goto error;
7106 }
7107 newsetsize = CPU_ALLOC_SIZE(newncpus);
7108 CPU_ZERO_S(newsetsize, newmask);
7109 memcpy(newmask, cpu_set, setsize);
7110 CPU_FREE(cpu_set);
7111 setsize = newsetsize;
7112 cpu_set = newmask;
7113 ncpus = newncpus;
7114 }
7115 CPU_SET_S(cpu, setsize, cpu_set);
7116 }
7117 if (PyErr_Occurred()) {
7118 goto error;
7119 }
7120 Py_CLEAR(iterator);
7121
7122 if (sched_setaffinity(pid, setsize, cpu_set)) {
7123 posix_error();
7124 goto error;
7125 }
7126 CPU_FREE(cpu_set);
7127 Py_RETURN_NONE;
7128
7129 error:
7130 if (cpu_set)
7131 CPU_FREE(cpu_set);
7132 Py_XDECREF(iterator);
7133 return NULL;
7134 }
7135
7136
7137 /*[clinic input]
7138 os.sched_getaffinity
7139 pid: pid_t
7140 /
7141
7142 Return the affinity of the process identified by pid (or the current process if zero).
7143
7144 The affinity is returned as a set of CPU identifiers.
7145 [clinic start generated code]*/
7146
7147 static PyObject *
os_sched_getaffinity_impl(PyObject * module,pid_t pid)7148 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
7149 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
7150 {
7151 int cpu, ncpus, count;
7152 size_t setsize;
7153 cpu_set_t *mask = NULL;
7154 PyObject *res = NULL;
7155
7156 ncpus = NCPUS_START;
7157 while (1) {
7158 setsize = CPU_ALLOC_SIZE(ncpus);
7159 mask = CPU_ALLOC(ncpus);
7160 if (mask == NULL)
7161 return PyErr_NoMemory();
7162 if (sched_getaffinity(pid, setsize, mask) == 0)
7163 break;
7164 CPU_FREE(mask);
7165 if (errno != EINVAL)
7166 return posix_error();
7167 if (ncpus > INT_MAX / 2) {
7168 PyErr_SetString(PyExc_OverflowError, "could not allocate "
7169 "a large enough CPU set");
7170 return NULL;
7171 }
7172 ncpus = ncpus * 2;
7173 }
7174
7175 res = PySet_New(NULL);
7176 if (res == NULL)
7177 goto error;
7178 for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7179 if (CPU_ISSET_S(cpu, setsize, mask)) {
7180 PyObject *cpu_num = PyLong_FromLong(cpu);
7181 --count;
7182 if (cpu_num == NULL)
7183 goto error;
7184 if (PySet_Add(res, cpu_num)) {
7185 Py_DECREF(cpu_num);
7186 goto error;
7187 }
7188 Py_DECREF(cpu_num);
7189 }
7190 }
7191 CPU_FREE(mask);
7192 return res;
7193
7194 error:
7195 if (mask)
7196 CPU_FREE(mask);
7197 Py_XDECREF(res);
7198 return NULL;
7199 }
7200
7201 #endif /* HAVE_SCHED_SETAFFINITY */
7202
7203 #endif /* HAVE_SCHED_H */
7204
7205
7206 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
7207 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
7208 # define DEV_PTY_FILE "/dev/ptc"
7209 # define HAVE_DEV_PTMX
7210 #else
7211 # define DEV_PTY_FILE "/dev/ptmx"
7212 #endif
7213
7214 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
7215 #ifdef HAVE_PTY_H
7216 #include <pty.h>
7217 #else
7218 #ifdef HAVE_LIBUTIL_H
7219 #include <libutil.h>
7220 #else
7221 #ifdef HAVE_UTIL_H
7222 #include <util.h>
7223 #endif /* HAVE_UTIL_H */
7224 #endif /* HAVE_LIBUTIL_H */
7225 #endif /* HAVE_PTY_H */
7226 #ifdef HAVE_STROPTS_H
7227 #include <stropts.h>
7228 #endif
7229 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */
7230
7231
7232 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7233 /*[clinic input]
7234 os.openpty
7235
7236 Open a pseudo-terminal.
7237
7238 Return a tuple of (master_fd, slave_fd) containing open file descriptors
7239 for both the master and slave ends.
7240 [clinic start generated code]*/
7241
7242 static PyObject *
os_openpty_impl(PyObject * module)7243 os_openpty_impl(PyObject *module)
7244 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
7245 {
7246 int master_fd = -1, slave_fd = -1;
7247 #ifndef HAVE_OPENPTY
7248 char * slave_name;
7249 #endif
7250 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
7251 PyOS_sighandler_t sig_saved;
7252 #if defined(__sun) && defined(__SVR4)
7253 extern char *ptsname(int fildes);
7254 #endif
7255 #endif
7256
7257 #ifdef HAVE_OPENPTY
7258 if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
7259 goto posix_error;
7260
7261 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7262 goto error;
7263 if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
7264 goto error;
7265
7266 #elif defined(HAVE__GETPTY)
7267 slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
7268 if (slave_name == NULL)
7269 goto posix_error;
7270 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7271 goto error;
7272
7273 slave_fd = _Py_open(slave_name, O_RDWR);
7274 if (slave_fd < 0)
7275 goto error;
7276
7277 #else
7278 master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
7279 if (master_fd < 0)
7280 goto posix_error;
7281
7282 sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
7283
7284 /* change permission of slave */
7285 if (grantpt(master_fd) < 0) {
7286 PyOS_setsig(SIGCHLD, sig_saved);
7287 goto posix_error;
7288 }
7289
7290 /* unlock slave */
7291 if (unlockpt(master_fd) < 0) {
7292 PyOS_setsig(SIGCHLD, sig_saved);
7293 goto posix_error;
7294 }
7295
7296 PyOS_setsig(SIGCHLD, sig_saved);
7297
7298 slave_name = ptsname(master_fd); /* get name of slave */
7299 if (slave_name == NULL)
7300 goto posix_error;
7301
7302 slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
7303 if (slave_fd == -1)
7304 goto error;
7305
7306 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7307 goto posix_error;
7308
7309 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
7310 ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
7311 ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
7312 #ifndef __hpux
7313 ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
7314 #endif /* __hpux */
7315 #endif /* HAVE_CYGWIN */
7316 #endif /* HAVE_OPENPTY */
7317
7318 return Py_BuildValue("(ii)", master_fd, slave_fd);
7319
7320 posix_error:
7321 posix_error();
7322 error:
7323 if (master_fd != -1)
7324 close(master_fd);
7325 if (slave_fd != -1)
7326 close(slave_fd);
7327 return NULL;
7328 }
7329 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
7330
7331
7332 #ifdef HAVE_FORKPTY
7333 /*[clinic input]
7334 os.forkpty
7335
7336 Fork a new process with a new pseudo-terminal as controlling tty.
7337
7338 Returns a tuple of (pid, master_fd).
7339 Like fork(), return pid of 0 to the child process,
7340 and pid of child to the parent process.
7341 To both, return fd of newly opened pseudo-terminal.
7342 [clinic start generated code]*/
7343
7344 static PyObject *
os_forkpty_impl(PyObject * module)7345 os_forkpty_impl(PyObject *module)
7346 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
7347 {
7348 int master_fd = -1;
7349 pid_t pid;
7350
7351 if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
7352 PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
7353 return NULL;
7354 }
7355 if (PySys_Audit("os.forkpty", NULL) < 0) {
7356 return NULL;
7357 }
7358 PyOS_BeforeFork();
7359 pid = forkpty(&master_fd, NULL, NULL, NULL);
7360 if (pid == 0) {
7361 /* child: this clobbers and resets the import lock. */
7362 PyOS_AfterFork_Child();
7363 } else {
7364 /* parent: release the import lock. */
7365 PyOS_AfterFork_Parent();
7366 }
7367 if (pid == -1)
7368 return posix_error();
7369 return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
7370 }
7371 #endif /* HAVE_FORKPTY */
7372
7373
7374 #ifdef HAVE_GETEGID
7375 /*[clinic input]
7376 os.getegid
7377
7378 Return the current process's effective group id.
7379 [clinic start generated code]*/
7380
7381 static PyObject *
os_getegid_impl(PyObject * module)7382 os_getegid_impl(PyObject *module)
7383 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
7384 {
7385 return _PyLong_FromGid(getegid());
7386 }
7387 #endif /* HAVE_GETEGID */
7388
7389
7390 #ifdef HAVE_GETEUID
7391 /*[clinic input]
7392 os.geteuid
7393
7394 Return the current process's effective user id.
7395 [clinic start generated code]*/
7396
7397 static PyObject *
os_geteuid_impl(PyObject * module)7398 os_geteuid_impl(PyObject *module)
7399 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
7400 {
7401 return _PyLong_FromUid(geteuid());
7402 }
7403 #endif /* HAVE_GETEUID */
7404
7405
7406 #ifdef HAVE_GETGID
7407 /*[clinic input]
7408 os.getgid
7409
7410 Return the current process's group id.
7411 [clinic start generated code]*/
7412
7413 static PyObject *
os_getgid_impl(PyObject * module)7414 os_getgid_impl(PyObject *module)
7415 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
7416 {
7417 return _PyLong_FromGid(getgid());
7418 }
7419 #endif /* HAVE_GETGID */
7420
7421
7422 #ifdef HAVE_GETPID
7423 /*[clinic input]
7424 os.getpid
7425
7426 Return the current process id.
7427 [clinic start generated code]*/
7428
7429 static PyObject *
os_getpid_impl(PyObject * module)7430 os_getpid_impl(PyObject *module)
7431 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
7432 {
7433 return PyLong_FromPid(getpid());
7434 }
7435 #endif /* HAVE_GETPID */
7436
7437 #ifdef NGROUPS_MAX
7438 #define MAX_GROUPS NGROUPS_MAX
7439 #else
7440 /* defined to be 16 on Solaris7, so this should be a small number */
7441 #define MAX_GROUPS 64
7442 #endif
7443
7444 #ifdef HAVE_GETGROUPLIST
7445
7446 #ifdef __APPLE__
7447 /*[clinic input]
7448 os.getgrouplist
7449
7450 user: str
7451 username to lookup
7452 group as basegid: int
7453 base group id of the user
7454 /
7455
7456 Returns a list of groups to which a user belongs.
7457 [clinic start generated code]*/
7458
7459 static PyObject *
os_getgrouplist_impl(PyObject * module,const char * user,int basegid)7460 os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
7461 /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
7462 #else
7463 /*[clinic input]
7464 os.getgrouplist
7465
7466 user: str
7467 username to lookup
7468 group as basegid: gid_t
7469 base group id of the user
7470 /
7471
7472 Returns a list of groups to which a user belongs.
7473 [clinic start generated code]*/
7474
7475 static PyObject *
7476 os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
7477 /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
7478 #endif
7479 {
7480 int i, ngroups;
7481 PyObject *list;
7482 #ifdef __APPLE__
7483 int *groups;
7484 #else
7485 gid_t *groups;
7486 #endif
7487
7488 /*
7489 * NGROUPS_MAX is defined by POSIX.1 as the maximum
7490 * number of supplimental groups a users can belong to.
7491 * We have to increment it by one because
7492 * getgrouplist() returns both the supplemental groups
7493 * and the primary group, i.e. all of the groups the
7494 * user belongs to.
7495 */
7496 ngroups = 1 + MAX_GROUPS;
7497
7498 while (1) {
7499 #ifdef __APPLE__
7500 groups = PyMem_New(int, ngroups);
7501 #else
7502 groups = PyMem_New(gid_t, ngroups);
7503 #endif
7504 if (groups == NULL) {
7505 return PyErr_NoMemory();
7506 }
7507
7508 int old_ngroups = ngroups;
7509 if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
7510 /* Success */
7511 break;
7512 }
7513
7514 /* getgrouplist() fails if the group list is too small */
7515 PyMem_Free(groups);
7516
7517 if (ngroups > old_ngroups) {
7518 /* If the group list is too small, the glibc implementation of
7519 getgrouplist() sets ngroups to the total number of groups and
7520 returns -1. */
7521 }
7522 else {
7523 /* Double the group list size */
7524 if (ngroups > INT_MAX / 2) {
7525 return PyErr_NoMemory();
7526 }
7527 ngroups *= 2;
7528 }
7529
7530 /* Retry getgrouplist() with a larger group list */
7531 }
7532
7533 #ifdef _Py_MEMORY_SANITIZER
7534 /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
7535 __msan_unpoison(&ngroups, sizeof(ngroups));
7536 __msan_unpoison(groups, ngroups*sizeof(*groups));
7537 #endif
7538
7539 list = PyList_New(ngroups);
7540 if (list == NULL) {
7541 PyMem_Free(groups);
7542 return NULL;
7543 }
7544
7545 for (i = 0; i < ngroups; i++) {
7546 #ifdef __APPLE__
7547 PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7548 #else
7549 PyObject *o = _PyLong_FromGid(groups[i]);
7550 #endif
7551 if (o == NULL) {
7552 Py_DECREF(list);
7553 PyMem_Free(groups);
7554 return NULL;
7555 }
7556 PyList_SET_ITEM(list, i, o);
7557 }
7558
7559 PyMem_Free(groups);
7560
7561 return list;
7562 }
7563 #endif /* HAVE_GETGROUPLIST */
7564
7565
7566 #ifdef HAVE_GETGROUPS
7567 /*[clinic input]
7568 os.getgroups
7569
7570 Return list of supplemental group IDs for the process.
7571 [clinic start generated code]*/
7572
7573 static PyObject *
os_getgroups_impl(PyObject * module)7574 os_getgroups_impl(PyObject *module)
7575 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
7576 {
7577 PyObject *result = NULL;
7578 gid_t grouplist[MAX_GROUPS];
7579
7580 /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
7581 * This is a helper variable to store the intermediate result when
7582 * that happens.
7583 *
7584 * To keep the code readable the OSX behaviour is unconditional,
7585 * according to the POSIX spec this should be safe on all unix-y
7586 * systems.
7587 */
7588 gid_t* alt_grouplist = grouplist;
7589 int n;
7590
7591 #ifdef __APPLE__
7592 /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if
7593 * there are more groups than can fit in grouplist. Therefore, on OS X
7594 * always first call getgroups with length 0 to get the actual number
7595 * of groups.
7596 */
7597 n = getgroups(0, NULL);
7598 if (n < 0) {
7599 return posix_error();
7600 } else if (n <= MAX_GROUPS) {
7601 /* groups will fit in existing array */
7602 alt_grouplist = grouplist;
7603 } else {
7604 alt_grouplist = PyMem_New(gid_t, n);
7605 if (alt_grouplist == NULL) {
7606 return PyErr_NoMemory();
7607 }
7608 }
7609
7610 n = getgroups(n, alt_grouplist);
7611 if (n == -1) {
7612 if (alt_grouplist != grouplist) {
7613 PyMem_Free(alt_grouplist);
7614 }
7615 return posix_error();
7616 }
7617 #else
7618 n = getgroups(MAX_GROUPS, grouplist);
7619 if (n < 0) {
7620 if (errno == EINVAL) {
7621 n = getgroups(0, NULL);
7622 if (n == -1) {
7623 return posix_error();
7624 }
7625 if (n == 0) {
7626 /* Avoid malloc(0) */
7627 alt_grouplist = grouplist;
7628 } else {
7629 alt_grouplist = PyMem_New(gid_t, n);
7630 if (alt_grouplist == NULL) {
7631 return PyErr_NoMemory();
7632 }
7633 n = getgroups(n, alt_grouplist);
7634 if (n == -1) {
7635 PyMem_Free(alt_grouplist);
7636 return posix_error();
7637 }
7638 }
7639 } else {
7640 return posix_error();
7641 }
7642 }
7643 #endif
7644
7645 result = PyList_New(n);
7646 if (result != NULL) {
7647 int i;
7648 for (i = 0; i < n; ++i) {
7649 PyObject *o = _PyLong_FromGid(alt_grouplist[i]);
7650 if (o == NULL) {
7651 Py_DECREF(result);
7652 result = NULL;
7653 break;
7654 }
7655 PyList_SET_ITEM(result, i, o);
7656 }
7657 }
7658
7659 if (alt_grouplist != grouplist) {
7660 PyMem_Free(alt_grouplist);
7661 }
7662
7663 return result;
7664 }
7665 #endif /* HAVE_GETGROUPS */
7666
7667 #ifdef HAVE_INITGROUPS
7668 #ifdef __APPLE__
7669 /*[clinic input]
7670 os.initgroups
7671
7672 username as oname: FSConverter
7673 gid: int
7674 /
7675
7676 Initialize the group access list.
7677
7678 Call the system initgroups() to initialize the group access list with all of
7679 the groups of which the specified username is a member, plus the specified
7680 group id.
7681 [clinic start generated code]*/
7682
7683 static PyObject *
os_initgroups_impl(PyObject * module,PyObject * oname,int gid)7684 os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
7685 /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
7686 #else
7687 /*[clinic input]
7688 os.initgroups
7689
7690 username as oname: FSConverter
7691 gid: gid_t
7692 /
7693
7694 Initialize the group access list.
7695
7696 Call the system initgroups() to initialize the group access list with all of
7697 the groups of which the specified username is a member, plus the specified
7698 group id.
7699 [clinic start generated code]*/
7700
7701 static PyObject *
7702 os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
7703 /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
7704 #endif
7705 {
7706 const char *username = PyBytes_AS_STRING(oname);
7707
7708 if (initgroups(username, gid) == -1)
7709 return PyErr_SetFromErrno(PyExc_OSError);
7710
7711 Py_RETURN_NONE;
7712 }
7713 #endif /* HAVE_INITGROUPS */
7714
7715
7716 #ifdef HAVE_GETPGID
7717 /*[clinic input]
7718 os.getpgid
7719
7720 pid: pid_t
7721
7722 Call the system call getpgid(), and return the result.
7723 [clinic start generated code]*/
7724
7725 static PyObject *
os_getpgid_impl(PyObject * module,pid_t pid)7726 os_getpgid_impl(PyObject *module, pid_t pid)
7727 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7728 {
7729 pid_t pgid = getpgid(pid);
7730 if (pgid < 0)
7731 return posix_error();
7732 return PyLong_FromPid(pgid);
7733 }
7734 #endif /* HAVE_GETPGID */
7735
7736
7737 #ifdef HAVE_GETPGRP
7738 /*[clinic input]
7739 os.getpgrp
7740
7741 Return the current process group id.
7742 [clinic start generated code]*/
7743
7744 static PyObject *
os_getpgrp_impl(PyObject * module)7745 os_getpgrp_impl(PyObject *module)
7746 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7747 {
7748 #ifdef GETPGRP_HAVE_ARG
7749 return PyLong_FromPid(getpgrp(0));
7750 #else /* GETPGRP_HAVE_ARG */
7751 return PyLong_FromPid(getpgrp());
7752 #endif /* GETPGRP_HAVE_ARG */
7753 }
7754 #endif /* HAVE_GETPGRP */
7755
7756
7757 #ifdef HAVE_SETPGRP
7758 /*[clinic input]
7759 os.setpgrp
7760
7761 Make the current process the leader of its process group.
7762 [clinic start generated code]*/
7763
7764 static PyObject *
os_setpgrp_impl(PyObject * module)7765 os_setpgrp_impl(PyObject *module)
7766 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7767 {
7768 #ifdef SETPGRP_HAVE_ARG
7769 if (setpgrp(0, 0) < 0)
7770 #else /* SETPGRP_HAVE_ARG */
7771 if (setpgrp() < 0)
7772 #endif /* SETPGRP_HAVE_ARG */
7773 return posix_error();
7774 Py_RETURN_NONE;
7775 }
7776 #endif /* HAVE_SETPGRP */
7777
7778 #ifdef HAVE_GETPPID
7779
7780 #ifdef MS_WINDOWS
7781 #include <tlhelp32.h>
7782
7783 static PyObject*
win32_getppid()7784 win32_getppid()
7785 {
7786 HANDLE snapshot;
7787 pid_t mypid;
7788 PyObject* result = NULL;
7789 BOOL have_record;
7790 PROCESSENTRY32 pe;
7791
7792 mypid = getpid(); /* This function never fails */
7793
7794 snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7795 if (snapshot == INVALID_HANDLE_VALUE)
7796 return PyErr_SetFromWindowsErr(GetLastError());
7797
7798 pe.dwSize = sizeof(pe);
7799 have_record = Process32First(snapshot, &pe);
7800 while (have_record) {
7801 if (mypid == (pid_t)pe.th32ProcessID) {
7802 /* We could cache the ulong value in a static variable. */
7803 result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7804 break;
7805 }
7806
7807 have_record = Process32Next(snapshot, &pe);
7808 }
7809
7810 /* If our loop exits and our pid was not found (result will be NULL)
7811 * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7812 * error anyway, so let's raise it. */
7813 if (!result)
7814 result = PyErr_SetFromWindowsErr(GetLastError());
7815
7816 CloseHandle(snapshot);
7817
7818 return result;
7819 }
7820 #endif /*MS_WINDOWS*/
7821
7822
7823 /*[clinic input]
7824 os.getppid
7825
7826 Return the parent's process id.
7827
7828 If the parent process has already exited, Windows machines will still
7829 return its id; others systems will return the id of the 'init' process (1).
7830 [clinic start generated code]*/
7831
7832 static PyObject *
os_getppid_impl(PyObject * module)7833 os_getppid_impl(PyObject *module)
7834 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7835 {
7836 #ifdef MS_WINDOWS
7837 return win32_getppid();
7838 #else
7839 return PyLong_FromPid(getppid());
7840 #endif
7841 }
7842 #endif /* HAVE_GETPPID */
7843
7844
7845 #ifdef HAVE_GETLOGIN
7846 /*[clinic input]
7847 os.getlogin
7848
7849 Return the actual login name.
7850 [clinic start generated code]*/
7851
7852 static PyObject *
os_getlogin_impl(PyObject * module)7853 os_getlogin_impl(PyObject *module)
7854 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7855 {
7856 PyObject *result = NULL;
7857 #ifdef MS_WINDOWS
7858 wchar_t user_name[UNLEN + 1];
7859 DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7860
7861 if (GetUserNameW(user_name, &num_chars)) {
7862 /* num_chars is the number of unicode chars plus null terminator */
7863 result = PyUnicode_FromWideChar(user_name, num_chars - 1);
7864 }
7865 else
7866 result = PyErr_SetFromWindowsErr(GetLastError());
7867 #else
7868 char *name;
7869 int old_errno = errno;
7870
7871 errno = 0;
7872 name = getlogin();
7873 if (name == NULL) {
7874 if (errno)
7875 posix_error();
7876 else
7877 PyErr_SetString(PyExc_OSError, "unable to determine login name");
7878 }
7879 else
7880 result = PyUnicode_DecodeFSDefault(name);
7881 errno = old_errno;
7882 #endif
7883 return result;
7884 }
7885 #endif /* HAVE_GETLOGIN */
7886
7887
7888 #ifdef HAVE_GETUID
7889 /*[clinic input]
7890 os.getuid
7891
7892 Return the current process's user id.
7893 [clinic start generated code]*/
7894
7895 static PyObject *
os_getuid_impl(PyObject * module)7896 os_getuid_impl(PyObject *module)
7897 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7898 {
7899 return _PyLong_FromUid(getuid());
7900 }
7901 #endif /* HAVE_GETUID */
7902
7903
7904 #ifdef MS_WINDOWS
7905 #define HAVE_KILL
7906 #endif /* MS_WINDOWS */
7907
7908 #ifdef HAVE_KILL
7909 /*[clinic input]
7910 os.kill
7911
7912 pid: pid_t
7913 signal: Py_ssize_t
7914 /
7915
7916 Kill a process with a signal.
7917 [clinic start generated code]*/
7918
7919 static PyObject *
os_kill_impl(PyObject * module,pid_t pid,Py_ssize_t signal)7920 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
7921 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
7922 {
7923 if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
7924 return NULL;
7925 }
7926 #ifndef MS_WINDOWS
7927 if (kill(pid, (int)signal) == -1)
7928 return posix_error();
7929 Py_RETURN_NONE;
7930 #else /* !MS_WINDOWS */
7931 PyObject *result;
7932 DWORD sig = (DWORD)signal;
7933 DWORD err;
7934 HANDLE handle;
7935
7936 /* Console processes which share a common console can be sent CTRL+C or
7937 CTRL+BREAK events, provided they handle said events. */
7938 if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
7939 if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
7940 err = GetLastError();
7941 PyErr_SetFromWindowsErr(err);
7942 }
7943 else
7944 Py_RETURN_NONE;
7945 }
7946
7947 /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
7948 attempt to open and terminate the process. */
7949 handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
7950 if (handle == NULL) {
7951 err = GetLastError();
7952 return PyErr_SetFromWindowsErr(err);
7953 }
7954
7955 if (TerminateProcess(handle, sig) == 0) {
7956 err = GetLastError();
7957 result = PyErr_SetFromWindowsErr(err);
7958 } else {
7959 Py_INCREF(Py_None);
7960 result = Py_None;
7961 }
7962
7963 CloseHandle(handle);
7964 return result;
7965 #endif /* !MS_WINDOWS */
7966 }
7967 #endif /* HAVE_KILL */
7968
7969
7970 #ifdef HAVE_KILLPG
7971 /*[clinic input]
7972 os.killpg
7973
7974 pgid: pid_t
7975 signal: int
7976 /
7977
7978 Kill a process group with a signal.
7979 [clinic start generated code]*/
7980
7981 static PyObject *
os_killpg_impl(PyObject * module,pid_t pgid,int signal)7982 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
7983 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
7984 {
7985 if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
7986 return NULL;
7987 }
7988 /* XXX some man pages make the `pgid` parameter an int, others
7989 a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
7990 take the same type. Moreover, pid_t is always at least as wide as
7991 int (else compilation of this module fails), which is safe. */
7992 if (killpg(pgid, signal) == -1)
7993 return posix_error();
7994 Py_RETURN_NONE;
7995 }
7996 #endif /* HAVE_KILLPG */
7997
7998
7999 #ifdef HAVE_PLOCK
8000 #ifdef HAVE_SYS_LOCK_H
8001 #include <sys/lock.h>
8002 #endif
8003
8004 /*[clinic input]
8005 os.plock
8006 op: int
8007 /
8008
8009 Lock program segments into memory.");
8010 [clinic start generated code]*/
8011
8012 static PyObject *
os_plock_impl(PyObject * module,int op)8013 os_plock_impl(PyObject *module, int op)
8014 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
8015 {
8016 if (plock(op) == -1)
8017 return posix_error();
8018 Py_RETURN_NONE;
8019 }
8020 #endif /* HAVE_PLOCK */
8021
8022
8023 #ifdef HAVE_SETUID
8024 /*[clinic input]
8025 os.setuid
8026
8027 uid: uid_t
8028 /
8029
8030 Set the current process's user id.
8031 [clinic start generated code]*/
8032
8033 static PyObject *
os_setuid_impl(PyObject * module,uid_t uid)8034 os_setuid_impl(PyObject *module, uid_t uid)
8035 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
8036 {
8037 if (setuid(uid) < 0)
8038 return posix_error();
8039 Py_RETURN_NONE;
8040 }
8041 #endif /* HAVE_SETUID */
8042
8043
8044 #ifdef HAVE_SETEUID
8045 /*[clinic input]
8046 os.seteuid
8047
8048 euid: uid_t
8049 /
8050
8051 Set the current process's effective user id.
8052 [clinic start generated code]*/
8053
8054 static PyObject *
os_seteuid_impl(PyObject * module,uid_t euid)8055 os_seteuid_impl(PyObject *module, uid_t euid)
8056 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
8057 {
8058 if (seteuid(euid) < 0)
8059 return posix_error();
8060 Py_RETURN_NONE;
8061 }
8062 #endif /* HAVE_SETEUID */
8063
8064
8065 #ifdef HAVE_SETEGID
8066 /*[clinic input]
8067 os.setegid
8068
8069 egid: gid_t
8070 /
8071
8072 Set the current process's effective group id.
8073 [clinic start generated code]*/
8074
8075 static PyObject *
os_setegid_impl(PyObject * module,gid_t egid)8076 os_setegid_impl(PyObject *module, gid_t egid)
8077 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
8078 {
8079 if (setegid(egid) < 0)
8080 return posix_error();
8081 Py_RETURN_NONE;
8082 }
8083 #endif /* HAVE_SETEGID */
8084
8085
8086 #ifdef HAVE_SETREUID
8087 /*[clinic input]
8088 os.setreuid
8089
8090 ruid: uid_t
8091 euid: uid_t
8092 /
8093
8094 Set the current process's real and effective user ids.
8095 [clinic start generated code]*/
8096
8097 static PyObject *
os_setreuid_impl(PyObject * module,uid_t ruid,uid_t euid)8098 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
8099 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
8100 {
8101 if (setreuid(ruid, euid) < 0) {
8102 return posix_error();
8103 } else {
8104 Py_RETURN_NONE;
8105 }
8106 }
8107 #endif /* HAVE_SETREUID */
8108
8109
8110 #ifdef HAVE_SETREGID
8111 /*[clinic input]
8112 os.setregid
8113
8114 rgid: gid_t
8115 egid: gid_t
8116 /
8117
8118 Set the current process's real and effective group ids.
8119 [clinic start generated code]*/
8120
8121 static PyObject *
os_setregid_impl(PyObject * module,gid_t rgid,gid_t egid)8122 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
8123 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
8124 {
8125 if (setregid(rgid, egid) < 0)
8126 return posix_error();
8127 Py_RETURN_NONE;
8128 }
8129 #endif /* HAVE_SETREGID */
8130
8131
8132 #ifdef HAVE_SETGID
8133 /*[clinic input]
8134 os.setgid
8135 gid: gid_t
8136 /
8137
8138 Set the current process's group id.
8139 [clinic start generated code]*/
8140
8141 static PyObject *
os_setgid_impl(PyObject * module,gid_t gid)8142 os_setgid_impl(PyObject *module, gid_t gid)
8143 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
8144 {
8145 if (setgid(gid) < 0)
8146 return posix_error();
8147 Py_RETURN_NONE;
8148 }
8149 #endif /* HAVE_SETGID */
8150
8151
8152 #ifdef HAVE_SETGROUPS
8153 /*[clinic input]
8154 os.setgroups
8155
8156 groups: object
8157 /
8158
8159 Set the groups of the current process to list.
8160 [clinic start generated code]*/
8161
8162 static PyObject *
os_setgroups(PyObject * module,PyObject * groups)8163 os_setgroups(PyObject *module, PyObject *groups)
8164 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
8165 {
8166 Py_ssize_t i, len;
8167 gid_t grouplist[MAX_GROUPS];
8168
8169 if (!PySequence_Check(groups)) {
8170 PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
8171 return NULL;
8172 }
8173 len = PySequence_Size(groups);
8174 if (len < 0) {
8175 return NULL;
8176 }
8177 if (len > MAX_GROUPS) {
8178 PyErr_SetString(PyExc_ValueError, "too many groups");
8179 return NULL;
8180 }
8181 for(i = 0; i < len; i++) {
8182 PyObject *elem;
8183 elem = PySequence_GetItem(groups, i);
8184 if (!elem)
8185 return NULL;
8186 if (!PyLong_Check(elem)) {
8187 PyErr_SetString(PyExc_TypeError,
8188 "groups must be integers");
8189 Py_DECREF(elem);
8190 return NULL;
8191 } else {
8192 if (!_Py_Gid_Converter(elem, &grouplist[i])) {
8193 Py_DECREF(elem);
8194 return NULL;
8195 }
8196 }
8197 Py_DECREF(elem);
8198 }
8199
8200 if (setgroups(len, grouplist) < 0)
8201 return posix_error();
8202 Py_RETURN_NONE;
8203 }
8204 #endif /* HAVE_SETGROUPS */
8205
8206 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
8207 static PyObject *
wait_helper(PyObject * module,pid_t pid,int status,struct rusage * ru)8208 wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
8209 {
8210 PyObject *result;
8211 PyObject *struct_rusage;
8212
8213 if (pid == -1)
8214 return posix_error();
8215
8216 // If wait succeeded but no child was ready to report status, ru will not
8217 // have been populated.
8218 if (pid == 0) {
8219 memset(ru, 0, sizeof(*ru));
8220 }
8221
8222 PyObject *m = PyImport_ImportModuleNoBlock("resource");
8223 if (m == NULL)
8224 return NULL;
8225 struct_rusage = PyObject_GetAttr(m, get_posix_state(module)->struct_rusage);
8226 Py_DECREF(m);
8227 if (struct_rusage == NULL)
8228 return NULL;
8229
8230 /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
8231 result = PyStructSequence_New((PyTypeObject*) struct_rusage);
8232 Py_DECREF(struct_rusage);
8233 if (!result)
8234 return NULL;
8235
8236 #ifndef doubletime
8237 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
8238 #endif
8239
8240 PyStructSequence_SET_ITEM(result, 0,
8241 PyFloat_FromDouble(doubletime(ru->ru_utime)));
8242 PyStructSequence_SET_ITEM(result, 1,
8243 PyFloat_FromDouble(doubletime(ru->ru_stime)));
8244 #define SET_INT(result, index, value)\
8245 PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
8246 SET_INT(result, 2, ru->ru_maxrss);
8247 SET_INT(result, 3, ru->ru_ixrss);
8248 SET_INT(result, 4, ru->ru_idrss);
8249 SET_INT(result, 5, ru->ru_isrss);
8250 SET_INT(result, 6, ru->ru_minflt);
8251 SET_INT(result, 7, ru->ru_majflt);
8252 SET_INT(result, 8, ru->ru_nswap);
8253 SET_INT(result, 9, ru->ru_inblock);
8254 SET_INT(result, 10, ru->ru_oublock);
8255 SET_INT(result, 11, ru->ru_msgsnd);
8256 SET_INT(result, 12, ru->ru_msgrcv);
8257 SET_INT(result, 13, ru->ru_nsignals);
8258 SET_INT(result, 14, ru->ru_nvcsw);
8259 SET_INT(result, 15, ru->ru_nivcsw);
8260 #undef SET_INT
8261
8262 if (PyErr_Occurred()) {
8263 Py_DECREF(result);
8264 return NULL;
8265 }
8266
8267 return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
8268 }
8269 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
8270
8271
8272 #ifdef HAVE_WAIT3
8273 /*[clinic input]
8274 os.wait3
8275
8276 options: int
8277 Wait for completion of a child process.
8278
8279 Returns a tuple of information about the child process:
8280 (pid, status, rusage)
8281 [clinic start generated code]*/
8282
8283 static PyObject *
os_wait3_impl(PyObject * module,int options)8284 os_wait3_impl(PyObject *module, int options)
8285 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
8286 {
8287 pid_t pid;
8288 struct rusage ru;
8289 int async_err = 0;
8290 WAIT_TYPE status;
8291 WAIT_STATUS_INT(status) = 0;
8292
8293 do {
8294 Py_BEGIN_ALLOW_THREADS
8295 pid = wait3(&status, options, &ru);
8296 Py_END_ALLOW_THREADS
8297 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8298 if (pid < 0)
8299 return (!async_err) ? posix_error() : NULL;
8300
8301 return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
8302 }
8303 #endif /* HAVE_WAIT3 */
8304
8305
8306 #ifdef HAVE_WAIT4
8307 /*[clinic input]
8308
8309 os.wait4
8310
8311 pid: pid_t
8312 options: int
8313
8314 Wait for completion of a specific child process.
8315
8316 Returns a tuple of information about the child process:
8317 (pid, status, rusage)
8318 [clinic start generated code]*/
8319
8320 static PyObject *
os_wait4_impl(PyObject * module,pid_t pid,int options)8321 os_wait4_impl(PyObject *module, pid_t pid, int options)
8322 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
8323 {
8324 pid_t res;
8325 struct rusage ru;
8326 int async_err = 0;
8327 WAIT_TYPE status;
8328 WAIT_STATUS_INT(status) = 0;
8329
8330 do {
8331 Py_BEGIN_ALLOW_THREADS
8332 res = wait4(pid, &status, options, &ru);
8333 Py_END_ALLOW_THREADS
8334 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8335 if (res < 0)
8336 return (!async_err) ? posix_error() : NULL;
8337
8338 return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
8339 }
8340 #endif /* HAVE_WAIT4 */
8341
8342
8343 #if defined(HAVE_WAITID) && !defined(__APPLE__)
8344 /*[clinic input]
8345 os.waitid
8346
8347 idtype: idtype_t
8348 Must be one of be P_PID, P_PGID or P_ALL.
8349 id: id_t
8350 The id to wait on.
8351 options: int
8352 Constructed from the ORing of one or more of WEXITED, WSTOPPED
8353 or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
8354 /
8355
8356 Returns the result of waiting for a process or processes.
8357
8358 Returns either waitid_result or None if WNOHANG is specified and there are
8359 no children in a waitable state.
8360 [clinic start generated code]*/
8361
8362 static PyObject *
os_waitid_impl(PyObject * module,idtype_t idtype,id_t id,int options)8363 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
8364 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
8365 {
8366 PyObject *result;
8367 int res;
8368 int async_err = 0;
8369 siginfo_t si;
8370 si.si_pid = 0;
8371
8372 do {
8373 Py_BEGIN_ALLOW_THREADS
8374 res = waitid(idtype, id, &si, options);
8375 Py_END_ALLOW_THREADS
8376 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8377 if (res < 0)
8378 return (!async_err) ? posix_error() : NULL;
8379
8380 if (si.si_pid == 0)
8381 Py_RETURN_NONE;
8382
8383 PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
8384 result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
8385 if (!result)
8386 return NULL;
8387
8388 PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
8389 PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
8390 PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
8391 PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
8392 PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
8393 if (PyErr_Occurred()) {
8394 Py_DECREF(result);
8395 return NULL;
8396 }
8397
8398 return result;
8399 }
8400 #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
8401
8402
8403 #if defined(HAVE_WAITPID)
8404 /*[clinic input]
8405 os.waitpid
8406 pid: pid_t
8407 options: int
8408 /
8409
8410 Wait for completion of a given child process.
8411
8412 Returns a tuple of information regarding the child process:
8413 (pid, status)
8414
8415 The options argument is ignored on Windows.
8416 [clinic start generated code]*/
8417
8418 static PyObject *
os_waitpid_impl(PyObject * module,pid_t pid,int options)8419 os_waitpid_impl(PyObject *module, pid_t pid, int options)
8420 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
8421 {
8422 pid_t res;
8423 int async_err = 0;
8424 WAIT_TYPE status;
8425 WAIT_STATUS_INT(status) = 0;
8426
8427 do {
8428 Py_BEGIN_ALLOW_THREADS
8429 res = waitpid(pid, &status, options);
8430 Py_END_ALLOW_THREADS
8431 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8432 if (res < 0)
8433 return (!async_err) ? posix_error() : NULL;
8434
8435 return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
8436 }
8437 #elif defined(HAVE_CWAIT)
8438 /* MS C has a variant of waitpid() that's usable for most purposes. */
8439 /*[clinic input]
8440 os.waitpid
8441 pid: intptr_t
8442 options: int
8443 /
8444
8445 Wait for completion of a given process.
8446
8447 Returns a tuple of information regarding the process:
8448 (pid, status << 8)
8449
8450 The options argument is ignored on Windows.
8451 [clinic start generated code]*/
8452
8453 static PyObject *
os_waitpid_impl(PyObject * module,intptr_t pid,int options)8454 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
8455 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
8456 {
8457 int status;
8458 intptr_t res;
8459 int async_err = 0;
8460
8461 do {
8462 Py_BEGIN_ALLOW_THREADS
8463 _Py_BEGIN_SUPPRESS_IPH
8464 res = _cwait(&status, pid, options);
8465 _Py_END_SUPPRESS_IPH
8466 Py_END_ALLOW_THREADS
8467 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8468 if (res < 0)
8469 return (!async_err) ? posix_error() : NULL;
8470
8471 unsigned long long ustatus = (unsigned int)status;
8472
8473 /* shift the status left a byte so this is more like the POSIX waitpid */
8474 return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
8475 }
8476 #endif
8477
8478
8479 #ifdef HAVE_WAIT
8480 /*[clinic input]
8481 os.wait
8482
8483 Wait for completion of a child process.
8484
8485 Returns a tuple of information about the child process:
8486 (pid, status)
8487 [clinic start generated code]*/
8488
8489 static PyObject *
os_wait_impl(PyObject * module)8490 os_wait_impl(PyObject *module)
8491 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
8492 {
8493 pid_t pid;
8494 int async_err = 0;
8495 WAIT_TYPE status;
8496 WAIT_STATUS_INT(status) = 0;
8497
8498 do {
8499 Py_BEGIN_ALLOW_THREADS
8500 pid = wait(&status);
8501 Py_END_ALLOW_THREADS
8502 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8503 if (pid < 0)
8504 return (!async_err) ? posix_error() : NULL;
8505
8506 return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
8507 }
8508 #endif /* HAVE_WAIT */
8509
8510 #if defined(__linux__) && defined(__NR_pidfd_open)
8511 /*[clinic input]
8512 os.pidfd_open
8513 pid: pid_t
8514 flags: unsigned_int = 0
8515
8516 Return a file descriptor referring to the process *pid*.
8517
8518 The descriptor can be used to perform process management without races and
8519 signals.
8520 [clinic start generated code]*/
8521
8522 static PyObject *
os_pidfd_open_impl(PyObject * module,pid_t pid,unsigned int flags)8523 os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
8524 /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
8525 {
8526 int fd = syscall(__NR_pidfd_open, pid, flags);
8527 if (fd < 0) {
8528 return posix_error();
8529 }
8530 return PyLong_FromLong(fd);
8531 }
8532 #endif
8533
8534
8535 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
8536 /*[clinic input]
8537 os.readlink
8538
8539 path: path_t
8540 *
8541 dir_fd: dir_fd(requires='readlinkat') = None
8542
8543 Return a string representing the path to which the symbolic link points.
8544
8545 If dir_fd is not None, it should be a file descriptor open to a directory,
8546 and path should be relative; path will then be relative to that directory.
8547
8548 dir_fd may not be implemented on your platform. If it is unavailable,
8549 using it will raise a NotImplementedError.
8550 [clinic start generated code]*/
8551
8552 static PyObject *
os_readlink_impl(PyObject * module,path_t * path,int dir_fd)8553 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
8554 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
8555 {
8556 #if defined(HAVE_READLINK)
8557 char buffer[MAXPATHLEN+1];
8558 ssize_t length;
8559 #ifdef HAVE_READLINKAT
8560 int readlinkat_unavailable = 0;
8561 #endif
8562
8563 Py_BEGIN_ALLOW_THREADS
8564 #ifdef HAVE_READLINKAT
8565 if (dir_fd != DEFAULT_DIR_FD) {
8566 if (HAVE_READLINKAT_RUNTIME) {
8567 length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
8568 } else {
8569 readlinkat_unavailable = 1;
8570 }
8571 } else
8572 #endif
8573 length = readlink(path->narrow, buffer, MAXPATHLEN);
8574 Py_END_ALLOW_THREADS
8575
8576 #ifdef HAVE_READLINKAT
8577 if (readlinkat_unavailable) {
8578 argument_unavailable_error(NULL, "dir_fd");
8579 return NULL;
8580 }
8581 #endif
8582
8583 if (length < 0) {
8584 return path_error(path);
8585 }
8586 buffer[length] = '\0';
8587
8588 if (PyUnicode_Check(path->object))
8589 return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
8590 else
8591 return PyBytes_FromStringAndSize(buffer, length);
8592 #elif defined(MS_WINDOWS)
8593 DWORD n_bytes_returned;
8594 DWORD io_result = 0;
8595 HANDLE reparse_point_handle;
8596 char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
8597 _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
8598 PyObject *result = NULL;
8599
8600 /* First get a handle to the reparse point */
8601 Py_BEGIN_ALLOW_THREADS
8602 reparse_point_handle = CreateFileW(
8603 path->wide,
8604 0,
8605 0,
8606 0,
8607 OPEN_EXISTING,
8608 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
8609 0);
8610 if (reparse_point_handle != INVALID_HANDLE_VALUE) {
8611 /* New call DeviceIoControl to read the reparse point */
8612 io_result = DeviceIoControl(
8613 reparse_point_handle,
8614 FSCTL_GET_REPARSE_POINT,
8615 0, 0, /* in buffer */
8616 target_buffer, sizeof(target_buffer),
8617 &n_bytes_returned,
8618 0 /* we're not using OVERLAPPED_IO */
8619 );
8620 CloseHandle(reparse_point_handle);
8621 }
8622 Py_END_ALLOW_THREADS
8623
8624 if (io_result == 0) {
8625 return path_error(path);
8626 }
8627
8628 wchar_t *name = NULL;
8629 Py_ssize_t nameLen = 0;
8630 if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
8631 {
8632 name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
8633 rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
8634 nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8635 }
8636 else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
8637 {
8638 name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8639 rdb->MountPointReparseBuffer.SubstituteNameOffset);
8640 nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8641 }
8642 else
8643 {
8644 PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8645 }
8646 if (name) {
8647 if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8648 /* Our buffer is mutable, so this is okay */
8649 name[1] = L'\\';
8650 }
8651 result = PyUnicode_FromWideChar(name, nameLen);
8652 if (result && path->narrow) {
8653 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8654 }
8655 }
8656 return result;
8657 #endif
8658 }
8659 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8660
8661 #if defined(MS_WINDOWS)
8662
8663 /* Remove the last portion of the path - return 0 on success */
8664 static int
_dirnameW(WCHAR * path)8665 _dirnameW(WCHAR *path)
8666 {
8667 WCHAR *ptr;
8668 size_t length = wcsnlen_s(path, MAX_PATH);
8669 if (length == MAX_PATH) {
8670 return -1;
8671 }
8672
8673 /* walk the path from the end until a backslash is encountered */
8674 for(ptr = path + length; ptr != path; ptr--) {
8675 if (*ptr == L'\\' || *ptr == L'/') {
8676 break;
8677 }
8678 }
8679 *ptr = 0;
8680 return 0;
8681 }
8682
8683 #endif
8684
8685 #ifdef HAVE_SYMLINK
8686
8687 #if defined(MS_WINDOWS)
8688
8689 /* Is this path absolute? */
8690 static int
_is_absW(const WCHAR * path)8691 _is_absW(const WCHAR *path)
8692 {
8693 return path[0] == L'\\' || path[0] == L'/' ||
8694 (path[0] && path[1] == L':');
8695 }
8696
8697 /* join root and rest with a backslash - return 0 on success */
8698 static int
_joinW(WCHAR * dest_path,const WCHAR * root,const WCHAR * rest)8699 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8700 {
8701 if (_is_absW(rest)) {
8702 return wcscpy_s(dest_path, MAX_PATH, rest);
8703 }
8704
8705 if (wcscpy_s(dest_path, MAX_PATH, root)) {
8706 return -1;
8707 }
8708
8709 if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8710 return -1;
8711 }
8712
8713 return wcscat_s(dest_path, MAX_PATH, rest);
8714 }
8715
8716 /* Return True if the path at src relative to dest is a directory */
8717 static int
_check_dirW(LPCWSTR src,LPCWSTR dest)8718 _check_dirW(LPCWSTR src, LPCWSTR dest)
8719 {
8720 WIN32_FILE_ATTRIBUTE_DATA src_info;
8721 WCHAR dest_parent[MAX_PATH];
8722 WCHAR src_resolved[MAX_PATH] = L"";
8723
8724 /* dest_parent = os.path.dirname(dest) */
8725 if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8726 _dirnameW(dest_parent)) {
8727 return 0;
8728 }
8729 /* src_resolved = os.path.join(dest_parent, src) */
8730 if (_joinW(src_resolved, dest_parent, src)) {
8731 return 0;
8732 }
8733 return (
8734 GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8735 && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8736 );
8737 }
8738 #endif
8739
8740
8741 /*[clinic input]
8742 os.symlink
8743 src: path_t
8744 dst: path_t
8745 target_is_directory: bool = False
8746 *
8747 dir_fd: dir_fd(requires='symlinkat')=None
8748
8749 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8750
8751 Create a symbolic link pointing to src named dst.
8752
8753 target_is_directory is required on Windows if the target is to be
8754 interpreted as a directory. (On Windows, symlink requires
8755 Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8756 target_is_directory is ignored on non-Windows platforms.
8757
8758 If dir_fd is not None, it should be a file descriptor open to a directory,
8759 and path should be relative; path will then be relative to that directory.
8760 dir_fd may not be implemented on your platform.
8761 If it is unavailable, using it will raise a NotImplementedError.
8762
8763 [clinic start generated code]*/
8764
8765 static PyObject *
os_symlink_impl(PyObject * module,path_t * src,path_t * dst,int target_is_directory,int dir_fd)8766 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8767 int target_is_directory, int dir_fd)
8768 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8769 {
8770 #ifdef MS_WINDOWS
8771 DWORD result;
8772 DWORD flags = 0;
8773
8774 /* Assumed true, set to false if detected to not be available. */
8775 static int windows_has_symlink_unprivileged_flag = TRUE;
8776 #else
8777 int result;
8778 #ifdef HAVE_SYMLINKAT
8779 int symlinkat_unavailable = 0;
8780 #endif
8781 #endif
8782
8783 if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8784 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8785 return NULL;
8786 }
8787
8788 #ifdef MS_WINDOWS
8789
8790 if (windows_has_symlink_unprivileged_flag) {
8791 /* Allow non-admin symlinks if system allows it. */
8792 flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8793 }
8794
8795 Py_BEGIN_ALLOW_THREADS
8796 _Py_BEGIN_SUPPRESS_IPH
8797 /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8798 if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8799 flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8800 }
8801
8802 result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8803 _Py_END_SUPPRESS_IPH
8804 Py_END_ALLOW_THREADS
8805
8806 if (windows_has_symlink_unprivileged_flag && !result &&
8807 ERROR_INVALID_PARAMETER == GetLastError()) {
8808
8809 Py_BEGIN_ALLOW_THREADS
8810 _Py_BEGIN_SUPPRESS_IPH
8811 /* This error might be caused by
8812 SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8813 Try again, and update windows_has_symlink_unprivileged_flag if we
8814 are successful this time.
8815
8816 NOTE: There is a risk of a race condition here if there are other
8817 conditions than the flag causing ERROR_INVALID_PARAMETER, and
8818 another process (or thread) changes that condition in between our
8819 calls to CreateSymbolicLink.
8820 */
8821 flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8822 result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8823 _Py_END_SUPPRESS_IPH
8824 Py_END_ALLOW_THREADS
8825
8826 if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8827 windows_has_symlink_unprivileged_flag = FALSE;
8828 }
8829 }
8830
8831 if (!result)
8832 return path_error2(src, dst);
8833
8834 #else
8835
8836 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8837 PyErr_SetString(PyExc_ValueError,
8838 "symlink: src and dst must be the same type");
8839 return NULL;
8840 }
8841
8842 Py_BEGIN_ALLOW_THREADS
8843 #ifdef HAVE_SYMLINKAT
8844 if (dir_fd != DEFAULT_DIR_FD) {
8845 if (HAVE_SYMLINKAT_RUNTIME) {
8846 result = symlinkat(src->narrow, dir_fd, dst->narrow);
8847 } else {
8848 symlinkat_unavailable = 1;
8849 }
8850 } else
8851 #endif
8852 result = symlink(src->narrow, dst->narrow);
8853 Py_END_ALLOW_THREADS
8854
8855 #ifdef HAVE_SYMLINKAT
8856 if (symlinkat_unavailable) {
8857 argument_unavailable_error(NULL, "dir_fd");
8858 return NULL;
8859 }
8860 #endif
8861
8862 if (result)
8863 return path_error2(src, dst);
8864 #endif
8865
8866 Py_RETURN_NONE;
8867 }
8868 #endif /* HAVE_SYMLINK */
8869
8870
8871
8872
8873 static PyStructSequence_Field times_result_fields[] = {
8874 {"user", "user time"},
8875 {"system", "system time"},
8876 {"children_user", "user time of children"},
8877 {"children_system", "system time of children"},
8878 {"elapsed", "elapsed time since an arbitrary point in the past"},
8879 {NULL}
8880 };
8881
8882 PyDoc_STRVAR(times_result__doc__,
8883 "times_result: Result from os.times().\n\n\
8884 This object may be accessed either as a tuple of\n\
8885 (user, system, children_user, children_system, elapsed),\n\
8886 or via the attributes user, system, children_user, children_system,\n\
8887 and elapsed.\n\
8888 \n\
8889 See os.times for more information.");
8890
8891 static PyStructSequence_Desc times_result_desc = {
8892 "times_result", /* name */
8893 times_result__doc__, /* doc */
8894 times_result_fields,
8895 5
8896 };
8897
8898 #ifdef MS_WINDOWS
8899 #define HAVE_TIMES /* mandatory, for the method table */
8900 #endif
8901
8902 #ifdef HAVE_TIMES
8903
8904 static PyObject *
build_times_result(PyObject * module,double user,double system,double children_user,double children_system,double elapsed)8905 build_times_result(PyObject *module, double user, double system,
8906 double children_user, double children_system,
8907 double elapsed)
8908 {
8909 PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
8910 PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
8911 if (value == NULL)
8912 return NULL;
8913
8914 #define SET(i, field) \
8915 { \
8916 PyObject *o = PyFloat_FromDouble(field); \
8917 if (!o) { \
8918 Py_DECREF(value); \
8919 return NULL; \
8920 } \
8921 PyStructSequence_SET_ITEM(value, i, o); \
8922 } \
8923
8924 SET(0, user);
8925 SET(1, system);
8926 SET(2, children_user);
8927 SET(3, children_system);
8928 SET(4, elapsed);
8929
8930 #undef SET
8931
8932 return value;
8933 }
8934
8935
8936 #ifndef MS_WINDOWS
8937 #define NEED_TICKS_PER_SECOND
8938 static long ticks_per_second = -1;
8939 #endif /* MS_WINDOWS */
8940
8941 /*[clinic input]
8942 os.times
8943
8944 Return a collection containing process timing information.
8945
8946 The object returned behaves like a named tuple with these fields:
8947 (utime, stime, cutime, cstime, elapsed_time)
8948 All fields are floating point numbers.
8949 [clinic start generated code]*/
8950
8951 static PyObject *
os_times_impl(PyObject * module)8952 os_times_impl(PyObject *module)
8953 /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
8954 #ifdef MS_WINDOWS
8955 {
8956 FILETIME create, exit, kernel, user;
8957 HANDLE hProc;
8958 hProc = GetCurrentProcess();
8959 GetProcessTimes(hProc, &create, &exit, &kernel, &user);
8960 /* The fields of a FILETIME structure are the hi and lo part
8961 of a 64-bit value expressed in 100 nanosecond units.
8962 1e7 is one second in such units; 1e-7 the inverse.
8963 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
8964 */
8965 return build_times_result(module,
8966 (double)(user.dwHighDateTime*429.4967296 +
8967 user.dwLowDateTime*1e-7),
8968 (double)(kernel.dwHighDateTime*429.4967296 +
8969 kernel.dwLowDateTime*1e-7),
8970 (double)0,
8971 (double)0,
8972 (double)0);
8973 }
8974 #else /* MS_WINDOWS */
8975 {
8976
8977
8978 struct tms t;
8979 clock_t c;
8980 errno = 0;
8981 c = times(&t);
8982 if (c == (clock_t) -1)
8983 return posix_error();
8984 return build_times_result(module,
8985 (double)t.tms_utime / ticks_per_second,
8986 (double)t.tms_stime / ticks_per_second,
8987 (double)t.tms_cutime / ticks_per_second,
8988 (double)t.tms_cstime / ticks_per_second,
8989 (double)c / ticks_per_second);
8990 }
8991 #endif /* MS_WINDOWS */
8992 #endif /* HAVE_TIMES */
8993
8994
8995 #ifdef HAVE_GETSID
8996 /*[clinic input]
8997 os.getsid
8998
8999 pid: pid_t
9000 /
9001
9002 Call the system call getsid(pid) and return the result.
9003 [clinic start generated code]*/
9004
9005 static PyObject *
os_getsid_impl(PyObject * module,pid_t pid)9006 os_getsid_impl(PyObject *module, pid_t pid)
9007 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
9008 {
9009 int sid;
9010 sid = getsid(pid);
9011 if (sid < 0)
9012 return posix_error();
9013 return PyLong_FromLong((long)sid);
9014 }
9015 #endif /* HAVE_GETSID */
9016
9017
9018 #ifdef HAVE_SETSID
9019 /*[clinic input]
9020 os.setsid
9021
9022 Call the system call setsid().
9023 [clinic start generated code]*/
9024
9025 static PyObject *
os_setsid_impl(PyObject * module)9026 os_setsid_impl(PyObject *module)
9027 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
9028 {
9029 if (setsid() < 0)
9030 return posix_error();
9031 Py_RETURN_NONE;
9032 }
9033 #endif /* HAVE_SETSID */
9034
9035
9036 #ifdef HAVE_SETPGID
9037 /*[clinic input]
9038 os.setpgid
9039
9040 pid: pid_t
9041 pgrp: pid_t
9042 /
9043
9044 Call the system call setpgid(pid, pgrp).
9045 [clinic start generated code]*/
9046
9047 static PyObject *
os_setpgid_impl(PyObject * module,pid_t pid,pid_t pgrp)9048 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
9049 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
9050 {
9051 if (setpgid(pid, pgrp) < 0)
9052 return posix_error();
9053 Py_RETURN_NONE;
9054 }
9055 #endif /* HAVE_SETPGID */
9056
9057
9058 #ifdef HAVE_TCGETPGRP
9059 /*[clinic input]
9060 os.tcgetpgrp
9061
9062 fd: int
9063 /
9064
9065 Return the process group associated with the terminal specified by fd.
9066 [clinic start generated code]*/
9067
9068 static PyObject *
os_tcgetpgrp_impl(PyObject * module,int fd)9069 os_tcgetpgrp_impl(PyObject *module, int fd)
9070 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
9071 {
9072 pid_t pgid = tcgetpgrp(fd);
9073 if (pgid < 0)
9074 return posix_error();
9075 return PyLong_FromPid(pgid);
9076 }
9077 #endif /* HAVE_TCGETPGRP */
9078
9079
9080 #ifdef HAVE_TCSETPGRP
9081 /*[clinic input]
9082 os.tcsetpgrp
9083
9084 fd: int
9085 pgid: pid_t
9086 /
9087
9088 Set the process group associated with the terminal specified by fd.
9089 [clinic start generated code]*/
9090
9091 static PyObject *
os_tcsetpgrp_impl(PyObject * module,int fd,pid_t pgid)9092 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
9093 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
9094 {
9095 if (tcsetpgrp(fd, pgid) < 0)
9096 return posix_error();
9097 Py_RETURN_NONE;
9098 }
9099 #endif /* HAVE_TCSETPGRP */
9100
9101 /* Functions acting on file descriptors */
9102
9103 #ifdef O_CLOEXEC
9104 extern int _Py_open_cloexec_works;
9105 #endif
9106
9107
9108 /*[clinic input]
9109 os.open -> int
9110 path: path_t
9111 flags: int
9112 mode: int = 0o777
9113 *
9114 dir_fd: dir_fd(requires='openat') = None
9115
9116 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
9117
9118 Open a file for low level IO. Returns a file descriptor (integer).
9119
9120 If dir_fd is not None, it should be a file descriptor open to a directory,
9121 and path should be relative; path will then be relative to that directory.
9122 dir_fd may not be implemented on your platform.
9123 If it is unavailable, using it will raise a NotImplementedError.
9124 [clinic start generated code]*/
9125
9126 static int
os_open_impl(PyObject * module,path_t * path,int flags,int mode,int dir_fd)9127 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
9128 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
9129 {
9130 int fd;
9131 int async_err = 0;
9132 #ifdef HAVE_OPENAT
9133 int openat_unavailable = 0;
9134 #endif
9135
9136 #ifdef O_CLOEXEC
9137 int *atomic_flag_works = &_Py_open_cloexec_works;
9138 #elif !defined(MS_WINDOWS)
9139 int *atomic_flag_works = NULL;
9140 #endif
9141
9142 #ifdef MS_WINDOWS
9143 flags |= O_NOINHERIT;
9144 #elif defined(O_CLOEXEC)
9145 flags |= O_CLOEXEC;
9146 #endif
9147
9148 if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
9149 return -1;
9150 }
9151
9152 _Py_BEGIN_SUPPRESS_IPH
9153 do {
9154 Py_BEGIN_ALLOW_THREADS
9155 #ifdef MS_WINDOWS
9156 fd = _wopen(path->wide, flags, mode);
9157 #else
9158 #ifdef HAVE_OPENAT
9159 if (dir_fd != DEFAULT_DIR_FD) {
9160 if (HAVE_OPENAT_RUNTIME) {
9161 fd = openat(dir_fd, path->narrow, flags, mode);
9162
9163 } else {
9164 openat_unavailable = 1;
9165 fd = -1;
9166 }
9167 } else
9168 #endif /* HAVE_OPENAT */
9169 fd = open(path->narrow, flags, mode);
9170 #endif /* !MS_WINDOWS */
9171 Py_END_ALLOW_THREADS
9172 } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9173 _Py_END_SUPPRESS_IPH
9174
9175 #ifdef HAVE_OPENAT
9176 if (openat_unavailable) {
9177 argument_unavailable_error(NULL, "dir_fd");
9178 return -1;
9179 }
9180 #endif
9181
9182 if (fd < 0) {
9183 if (!async_err)
9184 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
9185 return -1;
9186 }
9187
9188 #ifndef MS_WINDOWS
9189 if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
9190 close(fd);
9191 return -1;
9192 }
9193 #endif
9194
9195 return fd;
9196 }
9197
9198
9199 /*[clinic input]
9200 os.close
9201
9202 fd: int
9203
9204 Close a file descriptor.
9205 [clinic start generated code]*/
9206
9207 static PyObject *
os_close_impl(PyObject * module,int fd)9208 os_close_impl(PyObject *module, int fd)
9209 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
9210 {
9211 int res;
9212 /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
9213 * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
9214 * for more details.
9215 */
9216 Py_BEGIN_ALLOW_THREADS
9217 _Py_BEGIN_SUPPRESS_IPH
9218 res = close(fd);
9219 _Py_END_SUPPRESS_IPH
9220 Py_END_ALLOW_THREADS
9221 if (res < 0)
9222 return posix_error();
9223 Py_RETURN_NONE;
9224 }
9225
9226 /*[clinic input]
9227 os.closerange
9228
9229 fd_low: int
9230 fd_high: int
9231 /
9232
9233 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
9234 [clinic start generated code]*/
9235
9236 static PyObject *
os_closerange_impl(PyObject * module,int fd_low,int fd_high)9237 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
9238 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
9239 {
9240 Py_BEGIN_ALLOW_THREADS
9241 _Py_closerange(fd_low, fd_high - 1);
9242 Py_END_ALLOW_THREADS
9243 Py_RETURN_NONE;
9244 }
9245
9246
9247 /*[clinic input]
9248 os.dup -> int
9249
9250 fd: int
9251 /
9252
9253 Return a duplicate of a file descriptor.
9254 [clinic start generated code]*/
9255
9256 static int
os_dup_impl(PyObject * module,int fd)9257 os_dup_impl(PyObject *module, int fd)
9258 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
9259 {
9260 return _Py_dup(fd);
9261 }
9262
9263
9264 /*[clinic input]
9265 os.dup2 -> int
9266 fd: int
9267 fd2: int
9268 inheritable: bool=True
9269
9270 Duplicate file descriptor.
9271 [clinic start generated code]*/
9272
9273 static int
os_dup2_impl(PyObject * module,int fd,int fd2,int inheritable)9274 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
9275 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
9276 {
9277 int res = 0;
9278 #if defined(HAVE_DUP3) && \
9279 !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
9280 /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
9281 static int dup3_works = -1;
9282 #endif
9283
9284 if (fd < 0 || fd2 < 0) {
9285 posix_error();
9286 return -1;
9287 }
9288
9289 /* dup2() can fail with EINTR if the target FD is already open, because it
9290 * then has to be closed. See os_close_impl() for why we don't handle EINTR
9291 * upon close(), and therefore below.
9292 */
9293 #ifdef MS_WINDOWS
9294 Py_BEGIN_ALLOW_THREADS
9295 _Py_BEGIN_SUPPRESS_IPH
9296 res = dup2(fd, fd2);
9297 _Py_END_SUPPRESS_IPH
9298 Py_END_ALLOW_THREADS
9299 if (res < 0) {
9300 posix_error();
9301 return -1;
9302 }
9303 res = fd2; // msvcrt dup2 returns 0 on success.
9304
9305 /* Character files like console cannot be make non-inheritable */
9306 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9307 close(fd2);
9308 return -1;
9309 }
9310
9311 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
9312 Py_BEGIN_ALLOW_THREADS
9313 if (!inheritable)
9314 res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
9315 else
9316 res = dup2(fd, fd2);
9317 Py_END_ALLOW_THREADS
9318 if (res < 0) {
9319 posix_error();
9320 return -1;
9321 }
9322
9323 #else
9324
9325 #ifdef HAVE_DUP3
9326 if (!inheritable && dup3_works != 0) {
9327 Py_BEGIN_ALLOW_THREADS
9328 res = dup3(fd, fd2, O_CLOEXEC);
9329 Py_END_ALLOW_THREADS
9330 if (res < 0) {
9331 if (dup3_works == -1)
9332 dup3_works = (errno != ENOSYS);
9333 if (dup3_works) {
9334 posix_error();
9335 return -1;
9336 }
9337 }
9338 }
9339
9340 if (inheritable || dup3_works == 0)
9341 {
9342 #endif
9343 Py_BEGIN_ALLOW_THREADS
9344 res = dup2(fd, fd2);
9345 Py_END_ALLOW_THREADS
9346 if (res < 0) {
9347 posix_error();
9348 return -1;
9349 }
9350
9351 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9352 close(fd2);
9353 return -1;
9354 }
9355 #ifdef HAVE_DUP3
9356 }
9357 #endif
9358
9359 #endif
9360
9361 return res;
9362 }
9363
9364
9365 #ifdef HAVE_LOCKF
9366 /*[clinic input]
9367 os.lockf
9368
9369 fd: int
9370 An open file descriptor.
9371 command: int
9372 One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
9373 length: Py_off_t
9374 The number of bytes to lock, starting at the current position.
9375 /
9376
9377 Apply, test or remove a POSIX lock on an open file descriptor.
9378
9379 [clinic start generated code]*/
9380
9381 static PyObject *
os_lockf_impl(PyObject * module,int fd,int command,Py_off_t length)9382 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
9383 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
9384 {
9385 int res;
9386
9387 if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
9388 return NULL;
9389 }
9390
9391 Py_BEGIN_ALLOW_THREADS
9392 res = lockf(fd, command, length);
9393 Py_END_ALLOW_THREADS
9394
9395 if (res < 0)
9396 return posix_error();
9397
9398 Py_RETURN_NONE;
9399 }
9400 #endif /* HAVE_LOCKF */
9401
9402
9403 /*[clinic input]
9404 os.lseek -> Py_off_t
9405
9406 fd: int
9407 position: Py_off_t
9408 how: int
9409 /
9410
9411 Set the position of a file descriptor. Return the new position.
9412
9413 Return the new cursor position in number of bytes
9414 relative to the beginning of the file.
9415 [clinic start generated code]*/
9416
9417 static Py_off_t
os_lseek_impl(PyObject * module,int fd,Py_off_t position,int how)9418 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
9419 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
9420 {
9421 Py_off_t result;
9422
9423 #ifdef SEEK_SET
9424 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
9425 switch (how) {
9426 case 0: how = SEEK_SET; break;
9427 case 1: how = SEEK_CUR; break;
9428 case 2: how = SEEK_END; break;
9429 }
9430 #endif /* SEEK_END */
9431
9432 Py_BEGIN_ALLOW_THREADS
9433 _Py_BEGIN_SUPPRESS_IPH
9434 #ifdef MS_WINDOWS
9435 result = _lseeki64(fd, position, how);
9436 #else
9437 result = lseek(fd, position, how);
9438 #endif
9439 _Py_END_SUPPRESS_IPH
9440 Py_END_ALLOW_THREADS
9441 if (result < 0)
9442 posix_error();
9443
9444 return result;
9445 }
9446
9447
9448 /*[clinic input]
9449 os.read
9450 fd: int
9451 length: Py_ssize_t
9452 /
9453
9454 Read from a file descriptor. Returns a bytes object.
9455 [clinic start generated code]*/
9456
9457 static PyObject *
os_read_impl(PyObject * module,int fd,Py_ssize_t length)9458 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
9459 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
9460 {
9461 Py_ssize_t n;
9462 PyObject *buffer;
9463
9464 if (length < 0) {
9465 errno = EINVAL;
9466 return posix_error();
9467 }
9468
9469 length = Py_MIN(length, _PY_READ_MAX);
9470
9471 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9472 if (buffer == NULL)
9473 return NULL;
9474
9475 n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
9476 if (n == -1) {
9477 Py_DECREF(buffer);
9478 return NULL;
9479 }
9480
9481 if (n != length)
9482 _PyBytes_Resize(&buffer, n);
9483
9484 return buffer;
9485 }
9486
9487 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
9488 || defined(__APPLE__))) \
9489 || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
9490 || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9491 static int
iov_setup(struct iovec ** iov,Py_buffer ** buf,PyObject * seq,Py_ssize_t cnt,int type)9492 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
9493 {
9494 Py_ssize_t i, j;
9495
9496 *iov = PyMem_New(struct iovec, cnt);
9497 if (*iov == NULL) {
9498 PyErr_NoMemory();
9499 return -1;
9500 }
9501
9502 *buf = PyMem_New(Py_buffer, cnt);
9503 if (*buf == NULL) {
9504 PyMem_Free(*iov);
9505 PyErr_NoMemory();
9506 return -1;
9507 }
9508
9509 for (i = 0; i < cnt; i++) {
9510 PyObject *item = PySequence_GetItem(seq, i);
9511 if (item == NULL)
9512 goto fail;
9513 if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
9514 Py_DECREF(item);
9515 goto fail;
9516 }
9517 Py_DECREF(item);
9518 (*iov)[i].iov_base = (*buf)[i].buf;
9519 (*iov)[i].iov_len = (*buf)[i].len;
9520 }
9521 return 0;
9522
9523 fail:
9524 PyMem_Free(*iov);
9525 for (j = 0; j < i; j++) {
9526 PyBuffer_Release(&(*buf)[j]);
9527 }
9528 PyMem_Free(*buf);
9529 return -1;
9530 }
9531
9532 static void
iov_cleanup(struct iovec * iov,Py_buffer * buf,int cnt)9533 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9534 {
9535 int i;
9536 PyMem_Free(iov);
9537 for (i = 0; i < cnt; i++) {
9538 PyBuffer_Release(&buf[i]);
9539 }
9540 PyMem_Free(buf);
9541 }
9542 #endif
9543
9544
9545 #ifdef HAVE_READV
9546 /*[clinic input]
9547 os.readv -> Py_ssize_t
9548
9549 fd: int
9550 buffers: object
9551 /
9552
9553 Read from a file descriptor fd into an iterable of buffers.
9554
9555 The buffers should be mutable buffers accepting bytes.
9556 readv will transfer data into each buffer until it is full
9557 and then move on to the next buffer in the sequence to hold
9558 the rest of the data.
9559
9560 readv returns the total number of bytes read,
9561 which may be less than the total capacity of all the buffers.
9562 [clinic start generated code]*/
9563
9564 static Py_ssize_t
os_readv_impl(PyObject * module,int fd,PyObject * buffers)9565 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9566 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9567 {
9568 Py_ssize_t cnt, n;
9569 int async_err = 0;
9570 struct iovec *iov;
9571 Py_buffer *buf;
9572
9573 if (!PySequence_Check(buffers)) {
9574 PyErr_SetString(PyExc_TypeError,
9575 "readv() arg 2 must be a sequence");
9576 return -1;
9577 }
9578
9579 cnt = PySequence_Size(buffers);
9580 if (cnt < 0)
9581 return -1;
9582
9583 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9584 return -1;
9585
9586 do {
9587 Py_BEGIN_ALLOW_THREADS
9588 n = readv(fd, iov, cnt);
9589 Py_END_ALLOW_THREADS
9590 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9591
9592 iov_cleanup(iov, buf, cnt);
9593 if (n < 0) {
9594 if (!async_err)
9595 posix_error();
9596 return -1;
9597 }
9598
9599 return n;
9600 }
9601 #endif /* HAVE_READV */
9602
9603
9604 #ifdef HAVE_PREAD
9605 /*[clinic input]
9606 os.pread
9607
9608 fd: int
9609 length: Py_ssize_t
9610 offset: Py_off_t
9611 /
9612
9613 Read a number of bytes from a file descriptor starting at a particular offset.
9614
9615 Read length bytes from file descriptor fd, starting at offset bytes from
9616 the beginning of the file. The file offset remains unchanged.
9617 [clinic start generated code]*/
9618
9619 static PyObject *
os_pread_impl(PyObject * module,int fd,Py_ssize_t length,Py_off_t offset)9620 os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
9621 /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
9622 {
9623 Py_ssize_t n;
9624 int async_err = 0;
9625 PyObject *buffer;
9626
9627 if (length < 0) {
9628 errno = EINVAL;
9629 return posix_error();
9630 }
9631 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9632 if (buffer == NULL)
9633 return NULL;
9634
9635 do {
9636 Py_BEGIN_ALLOW_THREADS
9637 _Py_BEGIN_SUPPRESS_IPH
9638 n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9639 _Py_END_SUPPRESS_IPH
9640 Py_END_ALLOW_THREADS
9641 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9642
9643 if (n < 0) {
9644 Py_DECREF(buffer);
9645 return (!async_err) ? posix_error() : NULL;
9646 }
9647 if (n != length)
9648 _PyBytes_Resize(&buffer, n);
9649 return buffer;
9650 }
9651 #endif /* HAVE_PREAD */
9652
9653 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9654 /*[clinic input]
9655 os.preadv -> Py_ssize_t
9656
9657 fd: int
9658 buffers: object
9659 offset: Py_off_t
9660 flags: int = 0
9661 /
9662
9663 Reads from a file descriptor into a number of mutable bytes-like objects.
9664
9665 Combines the functionality of readv() and pread(). As readv(), it will
9666 transfer data into each buffer until it is full and then move on to the next
9667 buffer in the sequence to hold the rest of the data. Its fourth argument,
9668 specifies the file offset at which the input operation is to be performed. It
9669 will return the total number of bytes read (which can be less than the total
9670 capacity of all the objects).
9671
9672 The flags argument contains a bitwise OR of zero or more of the following flags:
9673
9674 - RWF_HIPRI
9675 - RWF_NOWAIT
9676
9677 Using non-zero flags requires Linux 4.6 or newer.
9678 [clinic start generated code]*/
9679
9680 static Py_ssize_t
os_preadv_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9681 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9682 int flags)
9683 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9684 {
9685 Py_ssize_t cnt, n;
9686 int async_err = 0;
9687 struct iovec *iov;
9688 Py_buffer *buf;
9689
9690 if (!PySequence_Check(buffers)) {
9691 PyErr_SetString(PyExc_TypeError,
9692 "preadv2() arg 2 must be a sequence");
9693 return -1;
9694 }
9695
9696 cnt = PySequence_Size(buffers);
9697 if (cnt < 0) {
9698 return -1;
9699 }
9700
9701 #ifndef HAVE_PREADV2
9702 if(flags != 0) {
9703 argument_unavailable_error("preadv2", "flags");
9704 return -1;
9705 }
9706 #endif
9707
9708 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9709 return -1;
9710 }
9711 #ifdef HAVE_PREADV2
9712 do {
9713 Py_BEGIN_ALLOW_THREADS
9714 _Py_BEGIN_SUPPRESS_IPH
9715 n = preadv2(fd, iov, cnt, offset, flags);
9716 _Py_END_SUPPRESS_IPH
9717 Py_END_ALLOW_THREADS
9718 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9719 #else
9720 do {
9721 #ifdef __APPLE__
9722 /* This entire function will be removed from the module dict when the API
9723 * is not available.
9724 */
9725 #pragma clang diagnostic push
9726 #pragma clang diagnostic ignored "-Wunguarded-availability"
9727 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
9728 #endif
9729 Py_BEGIN_ALLOW_THREADS
9730 _Py_BEGIN_SUPPRESS_IPH
9731 n = preadv(fd, iov, cnt, offset);
9732 _Py_END_SUPPRESS_IPH
9733 Py_END_ALLOW_THREADS
9734 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9735
9736 #ifdef __APPLE__
9737 #pragma clang diagnostic pop
9738 #endif
9739
9740 #endif
9741
9742 iov_cleanup(iov, buf, cnt);
9743 if (n < 0) {
9744 if (!async_err) {
9745 posix_error();
9746 }
9747 return -1;
9748 }
9749
9750 return n;
9751 }
9752 #endif /* HAVE_PREADV */
9753
9754
9755 /*[clinic input]
9756 os.write -> Py_ssize_t
9757
9758 fd: int
9759 data: Py_buffer
9760 /
9761
9762 Write a bytes object to a file descriptor.
9763 [clinic start generated code]*/
9764
9765 static Py_ssize_t
os_write_impl(PyObject * module,int fd,Py_buffer * data)9766 os_write_impl(PyObject *module, int fd, Py_buffer *data)
9767 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9768 {
9769 return _Py_write(fd, data->buf, data->len);
9770 }
9771
9772 #ifdef HAVE_SENDFILE
9773 #ifdef __APPLE__
9774 /*[clinic input]
9775 os.sendfile
9776
9777 out_fd: int
9778 in_fd: int
9779 offset: Py_off_t
9780 count as sbytes: Py_off_t
9781 headers: object(c_default="NULL") = ()
9782 trailers: object(c_default="NULL") = ()
9783 flags: int = 0
9784
9785 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9786 [clinic start generated code]*/
9787
9788 static PyObject *
os_sendfile_impl(PyObject * module,int out_fd,int in_fd,Py_off_t offset,Py_off_t sbytes,PyObject * headers,PyObject * trailers,int flags)9789 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9790 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
9791 int flags)
9792 /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
9793 #elif defined(__FreeBSD__) || defined(__DragonFly__)
9794 /*[clinic input]
9795 os.sendfile
9796
9797 out_fd: int
9798 in_fd: int
9799 offset: Py_off_t
9800 count: Py_ssize_t
9801 headers: object(c_default="NULL") = ()
9802 trailers: object(c_default="NULL") = ()
9803 flags: int = 0
9804
9805 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9806 [clinic start generated code]*/
9807
9808 static PyObject *
9809 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9810 Py_ssize_t count, PyObject *headers, PyObject *trailers,
9811 int flags)
9812 /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
9813 #else
9814 /*[clinic input]
9815 os.sendfile
9816
9817 out_fd: int
9818 in_fd: int
9819 offset as offobj: object
9820 count: Py_ssize_t
9821
9822 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9823 [clinic start generated code]*/
9824
9825 static PyObject *
9826 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
9827 Py_ssize_t count)
9828 /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
9829 #endif
9830 {
9831 Py_ssize_t ret;
9832 int async_err = 0;
9833
9834 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9835 #ifndef __APPLE__
9836 off_t sbytes;
9837 #endif
9838 Py_buffer *hbuf, *tbuf;
9839 struct sf_hdtr sf;
9840
9841 sf.headers = NULL;
9842 sf.trailers = NULL;
9843
9844 if (headers != NULL) {
9845 if (!PySequence_Check(headers)) {
9846 PyErr_SetString(PyExc_TypeError,
9847 "sendfile() headers must be a sequence");
9848 return NULL;
9849 } else {
9850 Py_ssize_t i = PySequence_Size(headers);
9851 if (i < 0)
9852 return NULL;
9853 if (i > INT_MAX) {
9854 PyErr_SetString(PyExc_OverflowError,
9855 "sendfile() header is too large");
9856 return NULL;
9857 }
9858 if (i > 0) {
9859 sf.hdr_cnt = (int)i;
9860 if (iov_setup(&(sf.headers), &hbuf,
9861 headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9862 return NULL;
9863 #ifdef __APPLE__
9864 for (i = 0; i < sf.hdr_cnt; i++) {
9865 Py_ssize_t blen = sf.headers[i].iov_len;
9866 # define OFF_T_MAX 0x7fffffffffffffff
9867 if (sbytes >= OFF_T_MAX - blen) {
9868 PyErr_SetString(PyExc_OverflowError,
9869 "sendfile() header is too large");
9870 return NULL;
9871 }
9872 sbytes += blen;
9873 }
9874 #endif
9875 }
9876 }
9877 }
9878 if (trailers != NULL) {
9879 if (!PySequence_Check(trailers)) {
9880 PyErr_SetString(PyExc_TypeError,
9881 "sendfile() trailers must be a sequence");
9882 return NULL;
9883 } else {
9884 Py_ssize_t i = PySequence_Size(trailers);
9885 if (i < 0)
9886 return NULL;
9887 if (i > INT_MAX) {
9888 PyErr_SetString(PyExc_OverflowError,
9889 "sendfile() trailer is too large");
9890 return NULL;
9891 }
9892 if (i > 0) {
9893 sf.trl_cnt = (int)i;
9894 if (iov_setup(&(sf.trailers), &tbuf,
9895 trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
9896 return NULL;
9897 }
9898 }
9899 }
9900
9901 _Py_BEGIN_SUPPRESS_IPH
9902 do {
9903 Py_BEGIN_ALLOW_THREADS
9904 #ifdef __APPLE__
9905 ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
9906 #else
9907 ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
9908 #endif
9909 Py_END_ALLOW_THREADS
9910 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9911 _Py_END_SUPPRESS_IPH
9912
9913 if (sf.headers != NULL)
9914 iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
9915 if (sf.trailers != NULL)
9916 iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
9917
9918 if (ret < 0) {
9919 if ((errno == EAGAIN) || (errno == EBUSY)) {
9920 if (sbytes != 0) {
9921 // some data has been sent
9922 goto done;
9923 }
9924 else {
9925 // no data has been sent; upper application is supposed
9926 // to retry on EAGAIN or EBUSY
9927 return posix_error();
9928 }
9929 }
9930 return (!async_err) ? posix_error() : NULL;
9931 }
9932 goto done;
9933
9934 done:
9935 #if !defined(HAVE_LARGEFILE_SUPPORT)
9936 return Py_BuildValue("l", sbytes);
9937 #else
9938 return Py_BuildValue("L", sbytes);
9939 #endif
9940
9941 #else
9942 #ifdef __linux__
9943 if (offobj == Py_None) {
9944 do {
9945 Py_BEGIN_ALLOW_THREADS
9946 ret = sendfile(out_fd, in_fd, NULL, count);
9947 Py_END_ALLOW_THREADS
9948 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9949 if (ret < 0)
9950 return (!async_err) ? posix_error() : NULL;
9951 return Py_BuildValue("n", ret);
9952 }
9953 #endif
9954 off_t offset;
9955 if (!Py_off_t_converter(offobj, &offset))
9956 return NULL;
9957
9958 #if defined(__sun) && defined(__SVR4)
9959 // On Solaris, sendfile raises EINVAL rather than returning 0
9960 // when the offset is equal or bigger than the in_fd size.
9961 struct stat st;
9962
9963 do {
9964 Py_BEGIN_ALLOW_THREADS
9965 ret = fstat(in_fd, &st);
9966 Py_END_ALLOW_THREADS
9967 } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9968 if (ret < 0)
9969 return (!async_err) ? posix_error() : NULL;
9970
9971 if (offset >= st.st_size) {
9972 return Py_BuildValue("i", 0);
9973 }
9974
9975 // On illumos specifically sendfile() may perform a partial write but
9976 // return -1/an error (in one confirmed case the destination socket
9977 // had a 5 second timeout set and errno was EAGAIN) and it's on the client
9978 // code to check if the offset parameter was modified by sendfile().
9979 //
9980 // We need this variable to track said change.
9981 off_t original_offset = offset;
9982 #endif
9983
9984 do {
9985 Py_BEGIN_ALLOW_THREADS
9986 ret = sendfile(out_fd, in_fd, &offset, count);
9987 #if defined(__sun) && defined(__SVR4)
9988 // This handles illumos-specific sendfile() partial write behavior,
9989 // see a comment above for more details.
9990 if (ret < 0 && offset != original_offset) {
9991 ret = offset - original_offset;
9992 }
9993 #endif
9994 Py_END_ALLOW_THREADS
9995 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9996 if (ret < 0)
9997 return (!async_err) ? posix_error() : NULL;
9998 return Py_BuildValue("n", ret);
9999 #endif
10000 }
10001 #endif /* HAVE_SENDFILE */
10002
10003
10004 #if defined(__APPLE__)
10005 /*[clinic input]
10006 os._fcopyfile
10007
10008 in_fd: int
10009 out_fd: int
10010 flags: int
10011 /
10012
10013 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
10014 [clinic start generated code]*/
10015
10016 static PyObject *
os__fcopyfile_impl(PyObject * module,int in_fd,int out_fd,int flags)10017 os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
10018 /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
10019 {
10020 int ret;
10021
10022 Py_BEGIN_ALLOW_THREADS
10023 ret = fcopyfile(in_fd, out_fd, NULL, flags);
10024 Py_END_ALLOW_THREADS
10025 if (ret < 0)
10026 return posix_error();
10027 Py_RETURN_NONE;
10028 }
10029 #endif
10030
10031
10032 /*[clinic input]
10033 os.fstat
10034
10035 fd : int
10036
10037 Perform a stat system call on the given file descriptor.
10038
10039 Like stat(), but for an open file descriptor.
10040 Equivalent to os.stat(fd).
10041 [clinic start generated code]*/
10042
10043 static PyObject *
os_fstat_impl(PyObject * module,int fd)10044 os_fstat_impl(PyObject *module, int fd)
10045 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
10046 {
10047 STRUCT_STAT st;
10048 int res;
10049 int async_err = 0;
10050
10051 do {
10052 Py_BEGIN_ALLOW_THREADS
10053 res = FSTAT(fd, &st);
10054 Py_END_ALLOW_THREADS
10055 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10056 if (res != 0) {
10057 #ifdef MS_WINDOWS
10058 return PyErr_SetFromWindowsErr(0);
10059 #else
10060 return (!async_err) ? posix_error() : NULL;
10061 #endif
10062 }
10063
10064 return _pystat_fromstructstat(module, &st);
10065 }
10066
10067
10068 /*[clinic input]
10069 os.isatty -> bool
10070 fd: int
10071 /
10072
10073 Return True if the fd is connected to a terminal.
10074
10075 Return True if the file descriptor is an open file descriptor
10076 connected to the slave end of a terminal.
10077 [clinic start generated code]*/
10078
10079 static int
os_isatty_impl(PyObject * module,int fd)10080 os_isatty_impl(PyObject *module, int fd)
10081 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
10082 {
10083 int return_value;
10084 Py_BEGIN_ALLOW_THREADS
10085 _Py_BEGIN_SUPPRESS_IPH
10086 return_value = isatty(fd);
10087 _Py_END_SUPPRESS_IPH
10088 Py_END_ALLOW_THREADS
10089 return return_value;
10090 }
10091
10092
10093 #ifdef HAVE_PIPE
10094 /*[clinic input]
10095 os.pipe
10096
10097 Create a pipe.
10098
10099 Returns a tuple of two file descriptors:
10100 (read_fd, write_fd)
10101 [clinic start generated code]*/
10102
10103 static PyObject *
os_pipe_impl(PyObject * module)10104 os_pipe_impl(PyObject *module)
10105 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
10106 {
10107 int fds[2];
10108 #ifdef MS_WINDOWS
10109 HANDLE read, write;
10110 SECURITY_ATTRIBUTES attr;
10111 BOOL ok;
10112 #else
10113 int res;
10114 #endif
10115
10116 #ifdef MS_WINDOWS
10117 attr.nLength = sizeof(attr);
10118 attr.lpSecurityDescriptor = NULL;
10119 attr.bInheritHandle = FALSE;
10120
10121 Py_BEGIN_ALLOW_THREADS
10122 ok = CreatePipe(&read, &write, &attr, 0);
10123 if (ok) {
10124 fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY);
10125 fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY);
10126 if (fds[0] == -1 || fds[1] == -1) {
10127 CloseHandle(read);
10128 CloseHandle(write);
10129 ok = 0;
10130 }
10131 }
10132 Py_END_ALLOW_THREADS
10133
10134 if (!ok)
10135 return PyErr_SetFromWindowsErr(0);
10136 #else
10137
10138 #ifdef HAVE_PIPE2
10139 Py_BEGIN_ALLOW_THREADS
10140 res = pipe2(fds, O_CLOEXEC);
10141 Py_END_ALLOW_THREADS
10142
10143 if (res != 0 && errno == ENOSYS)
10144 {
10145 #endif
10146 Py_BEGIN_ALLOW_THREADS
10147 res = pipe(fds);
10148 Py_END_ALLOW_THREADS
10149
10150 if (res == 0) {
10151 if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
10152 close(fds[0]);
10153 close(fds[1]);
10154 return NULL;
10155 }
10156 if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
10157 close(fds[0]);
10158 close(fds[1]);
10159 return NULL;
10160 }
10161 }
10162 #ifdef HAVE_PIPE2
10163 }
10164 #endif
10165
10166 if (res != 0)
10167 return PyErr_SetFromErrno(PyExc_OSError);
10168 #endif /* !MS_WINDOWS */
10169 return Py_BuildValue("(ii)", fds[0], fds[1]);
10170 }
10171 #endif /* HAVE_PIPE */
10172
10173
10174 #ifdef HAVE_PIPE2
10175 /*[clinic input]
10176 os.pipe2
10177
10178 flags: int
10179 /
10180
10181 Create a pipe with flags set atomically.
10182
10183 Returns a tuple of two file descriptors:
10184 (read_fd, write_fd)
10185
10186 flags can be constructed by ORing together one or more of these values:
10187 O_NONBLOCK, O_CLOEXEC.
10188 [clinic start generated code]*/
10189
10190 static PyObject *
os_pipe2_impl(PyObject * module,int flags)10191 os_pipe2_impl(PyObject *module, int flags)
10192 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
10193 {
10194 int fds[2];
10195 int res;
10196
10197 res = pipe2(fds, flags);
10198 if (res != 0)
10199 return posix_error();
10200 return Py_BuildValue("(ii)", fds[0], fds[1]);
10201 }
10202 #endif /* HAVE_PIPE2 */
10203
10204
10205 #ifdef HAVE_WRITEV
10206 /*[clinic input]
10207 os.writev -> Py_ssize_t
10208 fd: int
10209 buffers: object
10210 /
10211
10212 Iterate over buffers, and write the contents of each to a file descriptor.
10213
10214 Returns the total number of bytes written.
10215 buffers must be a sequence of bytes-like objects.
10216 [clinic start generated code]*/
10217
10218 static Py_ssize_t
os_writev_impl(PyObject * module,int fd,PyObject * buffers)10219 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
10220 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
10221 {
10222 Py_ssize_t cnt;
10223 Py_ssize_t result;
10224 int async_err = 0;
10225 struct iovec *iov;
10226 Py_buffer *buf;
10227
10228 if (!PySequence_Check(buffers)) {
10229 PyErr_SetString(PyExc_TypeError,
10230 "writev() arg 2 must be a sequence");
10231 return -1;
10232 }
10233 cnt = PySequence_Size(buffers);
10234 if (cnt < 0)
10235 return -1;
10236
10237 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10238 return -1;
10239 }
10240
10241 do {
10242 Py_BEGIN_ALLOW_THREADS
10243 result = writev(fd, iov, cnt);
10244 Py_END_ALLOW_THREADS
10245 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10246
10247 iov_cleanup(iov, buf, cnt);
10248 if (result < 0 && !async_err)
10249 posix_error();
10250
10251 return result;
10252 }
10253 #endif /* HAVE_WRITEV */
10254
10255
10256 #ifdef HAVE_PWRITE
10257 /*[clinic input]
10258 os.pwrite -> Py_ssize_t
10259
10260 fd: int
10261 buffer: Py_buffer
10262 offset: Py_off_t
10263 /
10264
10265 Write bytes to a file descriptor starting at a particular offset.
10266
10267 Write buffer to fd, starting at offset bytes from the beginning of
10268 the file. Returns the number of bytes writte. Does not change the
10269 current file offset.
10270 [clinic start generated code]*/
10271
10272 static Py_ssize_t
os_pwrite_impl(PyObject * module,int fd,Py_buffer * buffer,Py_off_t offset)10273 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
10274 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
10275 {
10276 Py_ssize_t size;
10277 int async_err = 0;
10278
10279 do {
10280 Py_BEGIN_ALLOW_THREADS
10281 _Py_BEGIN_SUPPRESS_IPH
10282 size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
10283 _Py_END_SUPPRESS_IPH
10284 Py_END_ALLOW_THREADS
10285 } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10286
10287 if (size < 0 && !async_err)
10288 posix_error();
10289 return size;
10290 }
10291 #endif /* HAVE_PWRITE */
10292
10293 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
10294 /*[clinic input]
10295 os.pwritev -> Py_ssize_t
10296
10297 fd: int
10298 buffers: object
10299 offset: Py_off_t
10300 flags: int = 0
10301 /
10302
10303 Writes the contents of bytes-like objects to a file descriptor at a given offset.
10304
10305 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
10306 of bytes-like objects. Buffers are processed in array order. Entire contents of first
10307 buffer is written before proceeding to second, and so on. The operating system may
10308 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
10309 This function writes the contents of each object to the file descriptor and returns
10310 the total number of bytes written.
10311
10312 The flags argument contains a bitwise OR of zero or more of the following flags:
10313
10314 - RWF_DSYNC
10315 - RWF_SYNC
10316 - RWF_APPEND
10317
10318 Using non-zero flags requires Linux 4.7 or newer.
10319 [clinic start generated code]*/
10320
10321 static Py_ssize_t
os_pwritev_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)10322 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
10323 int flags)
10324 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
10325 {
10326 Py_ssize_t cnt;
10327 Py_ssize_t result;
10328 int async_err = 0;
10329 struct iovec *iov;
10330 Py_buffer *buf;
10331
10332 if (!PySequence_Check(buffers)) {
10333 PyErr_SetString(PyExc_TypeError,
10334 "pwritev() arg 2 must be a sequence");
10335 return -1;
10336 }
10337
10338 cnt = PySequence_Size(buffers);
10339 if (cnt < 0) {
10340 return -1;
10341 }
10342
10343 #ifndef HAVE_PWRITEV2
10344 if(flags != 0) {
10345 argument_unavailable_error("pwritev2", "flags");
10346 return -1;
10347 }
10348 #endif
10349
10350 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10351 return -1;
10352 }
10353 #ifdef HAVE_PWRITEV2
10354 do {
10355 Py_BEGIN_ALLOW_THREADS
10356 _Py_BEGIN_SUPPRESS_IPH
10357 result = pwritev2(fd, iov, cnt, offset, flags);
10358 _Py_END_SUPPRESS_IPH
10359 Py_END_ALLOW_THREADS
10360 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10361 #else
10362
10363 #ifdef __APPLE__
10364 /* This entire function will be removed from the module dict when the API
10365 * is not available.
10366 */
10367 #pragma clang diagnostic push
10368 #pragma clang diagnostic ignored "-Wunguarded-availability"
10369 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
10370 #endif
10371 do {
10372 Py_BEGIN_ALLOW_THREADS
10373 _Py_BEGIN_SUPPRESS_IPH
10374 result = pwritev(fd, iov, cnt, offset);
10375 _Py_END_SUPPRESS_IPH
10376 Py_END_ALLOW_THREADS
10377 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10378
10379 #ifdef __APPLE__
10380 #pragma clang diagnostic pop
10381 #endif
10382
10383 #endif
10384
10385 iov_cleanup(iov, buf, cnt);
10386 if (result < 0) {
10387 if (!async_err) {
10388 posix_error();
10389 }
10390 return -1;
10391 }
10392
10393 return result;
10394 }
10395 #endif /* HAVE_PWRITEV */
10396
10397 #ifdef HAVE_COPY_FILE_RANGE
10398 /*[clinic input]
10399
10400 os.copy_file_range
10401 src: int
10402 Source file descriptor.
10403 dst: int
10404 Destination file descriptor.
10405 count: Py_ssize_t
10406 Number of bytes to copy.
10407 offset_src: object = None
10408 Starting offset in src.
10409 offset_dst: object = None
10410 Starting offset in dst.
10411
10412 Copy count bytes from one file descriptor to another.
10413
10414 If offset_src is None, then src is read from the current position;
10415 respectively for offset_dst.
10416 [clinic start generated code]*/
10417
10418 static PyObject *
os_copy_file_range_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst)10419 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10420 PyObject *offset_src, PyObject *offset_dst)
10421 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
10422 {
10423 off_t offset_src_val, offset_dst_val;
10424 off_t *p_offset_src = NULL;
10425 off_t *p_offset_dst = NULL;
10426 Py_ssize_t ret;
10427 int async_err = 0;
10428 /* The flags argument is provided to allow
10429 * for future extensions and currently must be to 0. */
10430 int flags = 0;
10431
10432
10433 if (count < 0) {
10434 PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10435 return NULL;
10436 }
10437
10438 if (offset_src != Py_None) {
10439 if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10440 return NULL;
10441 }
10442 p_offset_src = &offset_src_val;
10443 }
10444
10445 if (offset_dst != Py_None) {
10446 if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10447 return NULL;
10448 }
10449 p_offset_dst = &offset_dst_val;
10450 }
10451
10452 do {
10453 Py_BEGIN_ALLOW_THREADS
10454 ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
10455 Py_END_ALLOW_THREADS
10456 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10457
10458 if (ret < 0) {
10459 return (!async_err) ? posix_error() : NULL;
10460 }
10461
10462 return PyLong_FromSsize_t(ret);
10463 }
10464 #endif /* HAVE_COPY_FILE_RANGE*/
10465
10466 #if (defined(HAVE_SPLICE) && !defined(_AIX))
10467 /*[clinic input]
10468
10469 os.splice
10470 src: int
10471 Source file descriptor.
10472 dst: int
10473 Destination file descriptor.
10474 count: Py_ssize_t
10475 Number of bytes to copy.
10476 offset_src: object = None
10477 Starting offset in src.
10478 offset_dst: object = None
10479 Starting offset in dst.
10480 flags: unsigned_int = 0
10481 Flags to modify the semantics of the call.
10482
10483 Transfer count bytes from one pipe to a descriptor or vice versa.
10484
10485 If offset_src is None, then src is read from the current position;
10486 respectively for offset_dst. The offset associated to the file
10487 descriptor that refers to a pipe must be None.
10488 [clinic start generated code]*/
10489
10490 static PyObject *
os_splice_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst,unsigned int flags)10491 os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10492 PyObject *offset_src, PyObject *offset_dst,
10493 unsigned int flags)
10494 /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
10495 {
10496 off_t offset_src_val, offset_dst_val;
10497 off_t *p_offset_src = NULL;
10498 off_t *p_offset_dst = NULL;
10499 Py_ssize_t ret;
10500 int async_err = 0;
10501
10502 if (count < 0) {
10503 PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10504 return NULL;
10505 }
10506
10507 if (offset_src != Py_None) {
10508 if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10509 return NULL;
10510 }
10511 p_offset_src = &offset_src_val;
10512 }
10513
10514 if (offset_dst != Py_None) {
10515 if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10516 return NULL;
10517 }
10518 p_offset_dst = &offset_dst_val;
10519 }
10520
10521 do {
10522 Py_BEGIN_ALLOW_THREADS
10523 ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
10524 Py_END_ALLOW_THREADS
10525 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10526
10527 if (ret < 0) {
10528 return (!async_err) ? posix_error() : NULL;
10529 }
10530
10531 return PyLong_FromSsize_t(ret);
10532 }
10533 #endif /* HAVE_SPLICE*/
10534
10535 #ifdef HAVE_MKFIFO
10536 /*[clinic input]
10537 os.mkfifo
10538
10539 path: path_t
10540 mode: int=0o666
10541 *
10542 dir_fd: dir_fd(requires='mkfifoat')=None
10543
10544 Create a "fifo" (a POSIX named pipe).
10545
10546 If dir_fd is not None, it should be a file descriptor open to a directory,
10547 and path should be relative; path will then be relative to that directory.
10548 dir_fd may not be implemented on your platform.
10549 If it is unavailable, using it will raise a NotImplementedError.
10550 [clinic start generated code]*/
10551
10552 static PyObject *
os_mkfifo_impl(PyObject * module,path_t * path,int mode,int dir_fd)10553 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
10554 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
10555 {
10556 int result;
10557 int async_err = 0;
10558
10559 do {
10560 Py_BEGIN_ALLOW_THREADS
10561 #ifdef HAVE_MKFIFOAT
10562 if (dir_fd != DEFAULT_DIR_FD)
10563 result = mkfifoat(dir_fd, path->narrow, mode);
10564 else
10565 #endif
10566 result = mkfifo(path->narrow, mode);
10567 Py_END_ALLOW_THREADS
10568 } while (result != 0 && errno == EINTR &&
10569 !(async_err = PyErr_CheckSignals()));
10570 if (result != 0)
10571 return (!async_err) ? posix_error() : NULL;
10572
10573 Py_RETURN_NONE;
10574 }
10575 #endif /* HAVE_MKFIFO */
10576
10577
10578 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
10579 /*[clinic input]
10580 os.mknod
10581
10582 path: path_t
10583 mode: int=0o600
10584 device: dev_t=0
10585 *
10586 dir_fd: dir_fd(requires='mknodat')=None
10587
10588 Create a node in the file system.
10589
10590 Create a node in the file system (file, device special file or named pipe)
10591 at path. mode specifies both the permissions to use and the
10592 type of node to be created, being combined (bitwise OR) with one of
10593 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,
10594 device defines the newly created device special file (probably using
10595 os.makedev()). Otherwise device is ignored.
10596
10597 If dir_fd is not None, it should be a file descriptor open to a directory,
10598 and path should be relative; path will then be relative to that directory.
10599 dir_fd may not be implemented on your platform.
10600 If it is unavailable, using it will raise a NotImplementedError.
10601 [clinic start generated code]*/
10602
10603 static PyObject *
os_mknod_impl(PyObject * module,path_t * path,int mode,dev_t device,int dir_fd)10604 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
10605 int dir_fd)
10606 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
10607 {
10608 int result;
10609 int async_err = 0;
10610
10611 do {
10612 Py_BEGIN_ALLOW_THREADS
10613 #ifdef HAVE_MKNODAT
10614 if (dir_fd != DEFAULT_DIR_FD)
10615 result = mknodat(dir_fd, path->narrow, mode, device);
10616 else
10617 #endif
10618 result = mknod(path->narrow, mode, device);
10619 Py_END_ALLOW_THREADS
10620 } while (result != 0 && errno == EINTR &&
10621 !(async_err = PyErr_CheckSignals()));
10622 if (result != 0)
10623 return (!async_err) ? posix_error() : NULL;
10624
10625 Py_RETURN_NONE;
10626 }
10627 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
10628
10629
10630 #ifdef HAVE_DEVICE_MACROS
10631 /*[clinic input]
10632 os.major -> unsigned_int
10633
10634 device: dev_t
10635 /
10636
10637 Extracts a device major number from a raw device number.
10638 [clinic start generated code]*/
10639
10640 static unsigned int
os_major_impl(PyObject * module,dev_t device)10641 os_major_impl(PyObject *module, dev_t device)
10642 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
10643 {
10644 return major(device);
10645 }
10646
10647
10648 /*[clinic input]
10649 os.minor -> unsigned_int
10650
10651 device: dev_t
10652 /
10653
10654 Extracts a device minor number from a raw device number.
10655 [clinic start generated code]*/
10656
10657 static unsigned int
os_minor_impl(PyObject * module,dev_t device)10658 os_minor_impl(PyObject *module, dev_t device)
10659 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10660 {
10661 return minor(device);
10662 }
10663
10664
10665 /*[clinic input]
10666 os.makedev -> dev_t
10667
10668 major: int
10669 minor: int
10670 /
10671
10672 Composes a raw device number from the major and minor device numbers.
10673 [clinic start generated code]*/
10674
10675 static dev_t
os_makedev_impl(PyObject * module,int major,int minor)10676 os_makedev_impl(PyObject *module, int major, int minor)
10677 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10678 {
10679 return makedev(major, minor);
10680 }
10681 #endif /* HAVE_DEVICE_MACROS */
10682
10683
10684 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10685 /*[clinic input]
10686 os.ftruncate
10687
10688 fd: int
10689 length: Py_off_t
10690 /
10691
10692 Truncate a file, specified by file descriptor, to a specific length.
10693 [clinic start generated code]*/
10694
10695 static PyObject *
os_ftruncate_impl(PyObject * module,int fd,Py_off_t length)10696 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10697 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10698 {
10699 int result;
10700 int async_err = 0;
10701
10702 if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10703 return NULL;
10704 }
10705
10706 do {
10707 Py_BEGIN_ALLOW_THREADS
10708 _Py_BEGIN_SUPPRESS_IPH
10709 #ifdef MS_WINDOWS
10710 result = _chsize_s(fd, length);
10711 #else
10712 result = ftruncate(fd, length);
10713 #endif
10714 _Py_END_SUPPRESS_IPH
10715 Py_END_ALLOW_THREADS
10716 } while (result != 0 && errno == EINTR &&
10717 !(async_err = PyErr_CheckSignals()));
10718 if (result != 0)
10719 return (!async_err) ? posix_error() : NULL;
10720 Py_RETURN_NONE;
10721 }
10722 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10723
10724
10725 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10726 /*[clinic input]
10727 os.truncate
10728 path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10729 length: Py_off_t
10730
10731 Truncate a file, specified by path, to a specific length.
10732
10733 On some platforms, path may also be specified as an open file descriptor.
10734 If this functionality is unavailable, using it raises an exception.
10735 [clinic start generated code]*/
10736
10737 static PyObject *
os_truncate_impl(PyObject * module,path_t * path,Py_off_t length)10738 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10739 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10740 {
10741 int result;
10742 #ifdef MS_WINDOWS
10743 int fd;
10744 #endif
10745
10746 if (path->fd != -1)
10747 return os_ftruncate_impl(module, path->fd, length);
10748
10749 if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10750 return NULL;
10751 }
10752
10753 Py_BEGIN_ALLOW_THREADS
10754 _Py_BEGIN_SUPPRESS_IPH
10755 #ifdef MS_WINDOWS
10756 fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10757 if (fd < 0)
10758 result = -1;
10759 else {
10760 result = _chsize_s(fd, length);
10761 close(fd);
10762 if (result < 0)
10763 errno = result;
10764 }
10765 #else
10766 result = truncate(path->narrow, length);
10767 #endif
10768 _Py_END_SUPPRESS_IPH
10769 Py_END_ALLOW_THREADS
10770 if (result < 0)
10771 return posix_path_error(path);
10772
10773 Py_RETURN_NONE;
10774 }
10775 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10776
10777
10778 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10779 and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10780 defined, which is the case in Python on AIX. AIX bug report:
10781 http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10782 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10783 # define POSIX_FADVISE_AIX_BUG
10784 #endif
10785
10786
10787 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10788 /*[clinic input]
10789 os.posix_fallocate
10790
10791 fd: int
10792 offset: Py_off_t
10793 length: Py_off_t
10794 /
10795
10796 Ensure a file has allocated at least a particular number of bytes on disk.
10797
10798 Ensure that the file specified by fd encompasses a range of bytes
10799 starting at offset bytes from the beginning and continuing for length bytes.
10800 [clinic start generated code]*/
10801
10802 static PyObject *
os_posix_fallocate_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length)10803 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10804 Py_off_t length)
10805 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10806 {
10807 int result;
10808 int async_err = 0;
10809
10810 do {
10811 Py_BEGIN_ALLOW_THREADS
10812 result = posix_fallocate(fd, offset, length);
10813 Py_END_ALLOW_THREADS
10814 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10815
10816 if (result == 0)
10817 Py_RETURN_NONE;
10818
10819 if (async_err)
10820 return NULL;
10821
10822 errno = result;
10823 return posix_error();
10824 }
10825 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
10826
10827
10828 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
10829 /*[clinic input]
10830 os.posix_fadvise
10831
10832 fd: int
10833 offset: Py_off_t
10834 length: Py_off_t
10835 advice: int
10836 /
10837
10838 Announce an intention to access data in a specific pattern.
10839
10840 Announce an intention to access data in a specific pattern, thus allowing
10841 the kernel to make optimizations.
10842 The advice applies to the region of the file specified by fd starting at
10843 offset and continuing for length bytes.
10844 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
10845 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
10846 POSIX_FADV_DONTNEED.
10847 [clinic start generated code]*/
10848
10849 static PyObject *
os_posix_fadvise_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length,int advice)10850 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
10851 Py_off_t length, int advice)
10852 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
10853 {
10854 int result;
10855 int async_err = 0;
10856
10857 do {
10858 Py_BEGIN_ALLOW_THREADS
10859 result = posix_fadvise(fd, offset, length, advice);
10860 Py_END_ALLOW_THREADS
10861 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10862
10863 if (result == 0)
10864 Py_RETURN_NONE;
10865
10866 if (async_err)
10867 return NULL;
10868
10869 errno = result;
10870 return posix_error();
10871 }
10872 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
10873
10874
10875 #ifdef MS_WINDOWS
10876 static PyObject*
win32_putenv(PyObject * name,PyObject * value)10877 win32_putenv(PyObject *name, PyObject *value)
10878 {
10879 /* Search from index 1 because on Windows starting '=' is allowed for
10880 defining hidden environment variables. */
10881 if (PyUnicode_GET_LENGTH(name) == 0 ||
10882 PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
10883 {
10884 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10885 return NULL;
10886 }
10887 PyObject *unicode;
10888 if (value != NULL) {
10889 unicode = PyUnicode_FromFormat("%U=%U", name, value);
10890 }
10891 else {
10892 unicode = PyUnicode_FromFormat("%U=", name);
10893 }
10894 if (unicode == NULL) {
10895 return NULL;
10896 }
10897
10898 Py_ssize_t size;
10899 /* PyUnicode_AsWideCharString() rejects embedded null characters */
10900 wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
10901 Py_DECREF(unicode);
10902
10903 if (env == NULL) {
10904 return NULL;
10905 }
10906 if (size > _MAX_ENV) {
10907 PyErr_Format(PyExc_ValueError,
10908 "the environment variable is longer than %u characters",
10909 _MAX_ENV);
10910 PyMem_Free(env);
10911 return NULL;
10912 }
10913
10914 /* _wputenv() and SetEnvironmentVariableW() update the environment in the
10915 Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
10916 and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
10917
10918 Prefer _wputenv() to be compatible with C libraries using CRT
10919 variables and CRT functions using these variables (ex: getenv()). */
10920 int err = _wputenv(env);
10921 PyMem_Free(env);
10922
10923 if (err) {
10924 posix_error();
10925 return NULL;
10926 }
10927
10928 Py_RETURN_NONE;
10929 }
10930 #endif
10931
10932
10933 #ifdef MS_WINDOWS
10934 /*[clinic input]
10935 os.putenv
10936
10937 name: unicode
10938 value: unicode
10939 /
10940
10941 Change or add an environment variable.
10942 [clinic start generated code]*/
10943
10944 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10945 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10946 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
10947 {
10948 if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10949 return NULL;
10950 }
10951 return win32_putenv(name, value);
10952 }
10953 #else
10954 /*[clinic input]
10955 os.putenv
10956
10957 name: FSConverter
10958 value: FSConverter
10959 /
10960
10961 Change or add an environment variable.
10962 [clinic start generated code]*/
10963
10964 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10965 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10966 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
10967 {
10968 const char *name_string = PyBytes_AS_STRING(name);
10969 const char *value_string = PyBytes_AS_STRING(value);
10970
10971 if (strchr(name_string, '=') != NULL) {
10972 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10973 return NULL;
10974 }
10975
10976 if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10977 return NULL;
10978 }
10979
10980 if (setenv(name_string, value_string, 1)) {
10981 return posix_error();
10982 }
10983 Py_RETURN_NONE;
10984 }
10985 #endif /* !defined(MS_WINDOWS) */
10986
10987
10988 #ifdef MS_WINDOWS
10989 /*[clinic input]
10990 os.unsetenv
10991 name: unicode
10992 /
10993
10994 Delete an environment variable.
10995 [clinic start generated code]*/
10996
10997 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)10998 os_unsetenv_impl(PyObject *module, PyObject *name)
10999 /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
11000 {
11001 if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11002 return NULL;
11003 }
11004 return win32_putenv(name, NULL);
11005 }
11006 #else
11007 /*[clinic input]
11008 os.unsetenv
11009 name: FSConverter
11010 /
11011
11012 Delete an environment variable.
11013 [clinic start generated code]*/
11014
11015 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)11016 os_unsetenv_impl(PyObject *module, PyObject *name)
11017 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
11018 {
11019 if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11020 return NULL;
11021 }
11022 #ifdef HAVE_BROKEN_UNSETENV
11023 unsetenv(PyBytes_AS_STRING(name));
11024 #else
11025 int err = unsetenv(PyBytes_AS_STRING(name));
11026 if (err) {
11027 return posix_error();
11028 }
11029 #endif
11030
11031 Py_RETURN_NONE;
11032 }
11033 #endif /* !MS_WINDOWS */
11034
11035
11036 /*[clinic input]
11037 os.strerror
11038
11039 code: int
11040 /
11041
11042 Translate an error code to a message string.
11043 [clinic start generated code]*/
11044
11045 static PyObject *
os_strerror_impl(PyObject * module,int code)11046 os_strerror_impl(PyObject *module, int code)
11047 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
11048 {
11049 char *message = strerror(code);
11050 if (message == NULL) {
11051 PyErr_SetString(PyExc_ValueError,
11052 "strerror() argument out of range");
11053 return NULL;
11054 }
11055 return PyUnicode_DecodeLocale(message, "surrogateescape");
11056 }
11057
11058
11059 #ifdef HAVE_SYS_WAIT_H
11060 #ifdef WCOREDUMP
11061 /*[clinic input]
11062 os.WCOREDUMP -> bool
11063
11064 status: int
11065 /
11066
11067 Return True if the process returning status was dumped to a core file.
11068 [clinic start generated code]*/
11069
11070 static int
os_WCOREDUMP_impl(PyObject * module,int status)11071 os_WCOREDUMP_impl(PyObject *module, int status)
11072 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
11073 {
11074 WAIT_TYPE wait_status;
11075 WAIT_STATUS_INT(wait_status) = status;
11076 return WCOREDUMP(wait_status);
11077 }
11078 #endif /* WCOREDUMP */
11079
11080
11081 #ifdef WIFCONTINUED
11082 /*[clinic input]
11083 os.WIFCONTINUED -> bool
11084
11085 status: int
11086
11087 Return True if a particular process was continued from a job control stop.
11088
11089 Return True if the process returning status was continued from a
11090 job control stop.
11091 [clinic start generated code]*/
11092
11093 static int
os_WIFCONTINUED_impl(PyObject * module,int status)11094 os_WIFCONTINUED_impl(PyObject *module, int status)
11095 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
11096 {
11097 WAIT_TYPE wait_status;
11098 WAIT_STATUS_INT(wait_status) = status;
11099 return WIFCONTINUED(wait_status);
11100 }
11101 #endif /* WIFCONTINUED */
11102
11103
11104 #ifdef WIFSTOPPED
11105 /*[clinic input]
11106 os.WIFSTOPPED -> bool
11107
11108 status: int
11109
11110 Return True if the process returning status was stopped.
11111 [clinic start generated code]*/
11112
11113 static int
os_WIFSTOPPED_impl(PyObject * module,int status)11114 os_WIFSTOPPED_impl(PyObject *module, int status)
11115 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
11116 {
11117 WAIT_TYPE wait_status;
11118 WAIT_STATUS_INT(wait_status) = status;
11119 return WIFSTOPPED(wait_status);
11120 }
11121 #endif /* WIFSTOPPED */
11122
11123
11124 #ifdef WIFSIGNALED
11125 /*[clinic input]
11126 os.WIFSIGNALED -> bool
11127
11128 status: int
11129
11130 Return True if the process returning status was terminated by a signal.
11131 [clinic start generated code]*/
11132
11133 static int
os_WIFSIGNALED_impl(PyObject * module,int status)11134 os_WIFSIGNALED_impl(PyObject *module, int status)
11135 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
11136 {
11137 WAIT_TYPE wait_status;
11138 WAIT_STATUS_INT(wait_status) = status;
11139 return WIFSIGNALED(wait_status);
11140 }
11141 #endif /* WIFSIGNALED */
11142
11143
11144 #ifdef WIFEXITED
11145 /*[clinic input]
11146 os.WIFEXITED -> bool
11147
11148 status: int
11149
11150 Return True if the process returning status exited via the exit() system call.
11151 [clinic start generated code]*/
11152
11153 static int
os_WIFEXITED_impl(PyObject * module,int status)11154 os_WIFEXITED_impl(PyObject *module, int status)
11155 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
11156 {
11157 WAIT_TYPE wait_status;
11158 WAIT_STATUS_INT(wait_status) = status;
11159 return WIFEXITED(wait_status);
11160 }
11161 #endif /* WIFEXITED */
11162
11163
11164 #ifdef WEXITSTATUS
11165 /*[clinic input]
11166 os.WEXITSTATUS -> int
11167
11168 status: int
11169
11170 Return the process return code from status.
11171 [clinic start generated code]*/
11172
11173 static int
os_WEXITSTATUS_impl(PyObject * module,int status)11174 os_WEXITSTATUS_impl(PyObject *module, int status)
11175 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
11176 {
11177 WAIT_TYPE wait_status;
11178 WAIT_STATUS_INT(wait_status) = status;
11179 return WEXITSTATUS(wait_status);
11180 }
11181 #endif /* WEXITSTATUS */
11182
11183
11184 #ifdef WTERMSIG
11185 /*[clinic input]
11186 os.WTERMSIG -> int
11187
11188 status: int
11189
11190 Return the signal that terminated the process that provided the status value.
11191 [clinic start generated code]*/
11192
11193 static int
os_WTERMSIG_impl(PyObject * module,int status)11194 os_WTERMSIG_impl(PyObject *module, int status)
11195 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
11196 {
11197 WAIT_TYPE wait_status;
11198 WAIT_STATUS_INT(wait_status) = status;
11199 return WTERMSIG(wait_status);
11200 }
11201 #endif /* WTERMSIG */
11202
11203
11204 #ifdef WSTOPSIG
11205 /*[clinic input]
11206 os.WSTOPSIG -> int
11207
11208 status: int
11209
11210 Return the signal that stopped the process that provided the status value.
11211 [clinic start generated code]*/
11212
11213 static int
os_WSTOPSIG_impl(PyObject * module,int status)11214 os_WSTOPSIG_impl(PyObject *module, int status)
11215 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
11216 {
11217 WAIT_TYPE wait_status;
11218 WAIT_STATUS_INT(wait_status) = status;
11219 return WSTOPSIG(wait_status);
11220 }
11221 #endif /* WSTOPSIG */
11222 #endif /* HAVE_SYS_WAIT_H */
11223
11224
11225 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
11226 #ifdef _SCO_DS
11227 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
11228 needed definitions in sys/statvfs.h */
11229 #define _SVID3
11230 #endif
11231 #include <sys/statvfs.h>
11232
11233 static PyObject*
_pystatvfs_fromstructstatvfs(PyObject * module,struct statvfs st)11234 _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
11235 PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
11236 PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
11237 if (v == NULL)
11238 return NULL;
11239
11240 #if !defined(HAVE_LARGEFILE_SUPPORT)
11241 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11242 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11243 PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
11244 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
11245 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
11246 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
11247 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
11248 PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
11249 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11250 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11251 #else
11252 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11253 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11254 PyStructSequence_SET_ITEM(v, 2,
11255 PyLong_FromLongLong((long long) st.f_blocks));
11256 PyStructSequence_SET_ITEM(v, 3,
11257 PyLong_FromLongLong((long long) st.f_bfree));
11258 PyStructSequence_SET_ITEM(v, 4,
11259 PyLong_FromLongLong((long long) st.f_bavail));
11260 PyStructSequence_SET_ITEM(v, 5,
11261 PyLong_FromLongLong((long long) st.f_files));
11262 PyStructSequence_SET_ITEM(v, 6,
11263 PyLong_FromLongLong((long long) st.f_ffree));
11264 PyStructSequence_SET_ITEM(v, 7,
11265 PyLong_FromLongLong((long long) st.f_favail));
11266 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11267 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11268 #endif
11269 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
11270 * (issue #32390). */
11271 #if defined(_AIX) && defined(_ALL_SOURCE)
11272 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
11273 #else
11274 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
11275 #endif
11276 if (PyErr_Occurred()) {
11277 Py_DECREF(v);
11278 return NULL;
11279 }
11280
11281 return v;
11282 }
11283
11284
11285 /*[clinic input]
11286 os.fstatvfs
11287 fd: int
11288 /
11289
11290 Perform an fstatvfs system call on the given fd.
11291
11292 Equivalent to statvfs(fd).
11293 [clinic start generated code]*/
11294
11295 static PyObject *
os_fstatvfs_impl(PyObject * module,int fd)11296 os_fstatvfs_impl(PyObject *module, int fd)
11297 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
11298 {
11299 int result;
11300 int async_err = 0;
11301 struct statvfs st;
11302
11303 do {
11304 Py_BEGIN_ALLOW_THREADS
11305 result = fstatvfs(fd, &st);
11306 Py_END_ALLOW_THREADS
11307 } while (result != 0 && errno == EINTR &&
11308 !(async_err = PyErr_CheckSignals()));
11309 if (result != 0)
11310 return (!async_err) ? posix_error() : NULL;
11311
11312 return _pystatvfs_fromstructstatvfs(module, st);
11313 }
11314 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
11315
11316
11317 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
11318 #include <sys/statvfs.h>
11319 /*[clinic input]
11320 os.statvfs
11321
11322 path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
11323
11324 Perform a statvfs system call on the given path.
11325
11326 path may always be specified as a string.
11327 On some platforms, path may also be specified as an open file descriptor.
11328 If this functionality is unavailable, using it raises an exception.
11329 [clinic start generated code]*/
11330
11331 static PyObject *
os_statvfs_impl(PyObject * module,path_t * path)11332 os_statvfs_impl(PyObject *module, path_t *path)
11333 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
11334 {
11335 int result;
11336 struct statvfs st;
11337
11338 Py_BEGIN_ALLOW_THREADS
11339 #ifdef HAVE_FSTATVFS
11340 if (path->fd != -1) {
11341 result = fstatvfs(path->fd, &st);
11342 }
11343 else
11344 #endif
11345 result = statvfs(path->narrow, &st);
11346 Py_END_ALLOW_THREADS
11347
11348 if (result) {
11349 return path_error(path);
11350 }
11351
11352 return _pystatvfs_fromstructstatvfs(module, st);
11353 }
11354 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
11355
11356
11357 #ifdef MS_WINDOWS
11358 /*[clinic input]
11359 os._getdiskusage
11360
11361 path: path_t
11362
11363 Return disk usage statistics about the given path as a (total, free) tuple.
11364 [clinic start generated code]*/
11365
11366 static PyObject *
os__getdiskusage_impl(PyObject * module,path_t * path)11367 os__getdiskusage_impl(PyObject *module, path_t *path)
11368 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
11369 {
11370 BOOL retval;
11371 ULARGE_INTEGER _, total, free;
11372 DWORD err = 0;
11373
11374 Py_BEGIN_ALLOW_THREADS
11375 retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
11376 Py_END_ALLOW_THREADS
11377 if (retval == 0) {
11378 if (GetLastError() == ERROR_DIRECTORY) {
11379 wchar_t *dir_path = NULL;
11380
11381 dir_path = PyMem_New(wchar_t, path->length + 1);
11382 if (dir_path == NULL) {
11383 return PyErr_NoMemory();
11384 }
11385
11386 wcscpy_s(dir_path, path->length + 1, path->wide);
11387
11388 if (_dirnameW(dir_path) != -1) {
11389 Py_BEGIN_ALLOW_THREADS
11390 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
11391 Py_END_ALLOW_THREADS
11392 }
11393 /* Record the last error in case it's modified by PyMem_Free. */
11394 err = GetLastError();
11395 PyMem_Free(dir_path);
11396 if (retval) {
11397 goto success;
11398 }
11399 }
11400 return PyErr_SetFromWindowsErr(err);
11401 }
11402
11403 success:
11404 return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
11405 }
11406 #endif /* MS_WINDOWS */
11407
11408
11409 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
11410 * It maps strings representing configuration variable names to
11411 * integer values, allowing those functions to be called with the
11412 * magic names instead of polluting the module's namespace with tons of
11413 * rarely-used constants. There are three separate tables that use
11414 * these definitions.
11415 *
11416 * This code is always included, even if none of the interfaces that
11417 * need it are included. The #if hackery needed to avoid it would be
11418 * sufficiently pervasive that it's not worth the loss of readability.
11419 */
11420 struct constdef {
11421 const char *name;
11422 int value;
11423 };
11424
11425 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)11426 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
11427 size_t tablesize)
11428 {
11429 if (PyLong_Check(arg)) {
11430 int value = _PyLong_AsInt(arg);
11431 if (value == -1 && PyErr_Occurred())
11432 return 0;
11433 *valuep = value;
11434 return 1;
11435 }
11436 else {
11437 /* look up the value in the table using a binary search */
11438 size_t lo = 0;
11439 size_t mid;
11440 size_t hi = tablesize;
11441 int cmp;
11442 const char *confname;
11443 if (!PyUnicode_Check(arg)) {
11444 PyErr_SetString(PyExc_TypeError,
11445 "configuration names must be strings or integers");
11446 return 0;
11447 }
11448 confname = PyUnicode_AsUTF8(arg);
11449 if (confname == NULL)
11450 return 0;
11451 while (lo < hi) {
11452 mid = (lo + hi) / 2;
11453 cmp = strcmp(confname, table[mid].name);
11454 if (cmp < 0)
11455 hi = mid;
11456 else if (cmp > 0)
11457 lo = mid + 1;
11458 else {
11459 *valuep = table[mid].value;
11460 return 1;
11461 }
11462 }
11463 PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
11464 return 0;
11465 }
11466 }
11467
11468
11469 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11470 static struct constdef posix_constants_pathconf[] = {
11471 #ifdef _PC_ABI_AIO_XFER_MAX
11472 {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
11473 #endif
11474 #ifdef _PC_ABI_ASYNC_IO
11475 {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
11476 #endif
11477 #ifdef _PC_ASYNC_IO
11478 {"PC_ASYNC_IO", _PC_ASYNC_IO},
11479 #endif
11480 #ifdef _PC_CHOWN_RESTRICTED
11481 {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
11482 #endif
11483 #ifdef _PC_FILESIZEBITS
11484 {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
11485 #endif
11486 #ifdef _PC_LAST
11487 {"PC_LAST", _PC_LAST},
11488 #endif
11489 #ifdef _PC_LINK_MAX
11490 {"PC_LINK_MAX", _PC_LINK_MAX},
11491 #endif
11492 #ifdef _PC_MAX_CANON
11493 {"PC_MAX_CANON", _PC_MAX_CANON},
11494 #endif
11495 #ifdef _PC_MAX_INPUT
11496 {"PC_MAX_INPUT", _PC_MAX_INPUT},
11497 #endif
11498 #ifdef _PC_NAME_MAX
11499 {"PC_NAME_MAX", _PC_NAME_MAX},
11500 #endif
11501 #ifdef _PC_NO_TRUNC
11502 {"PC_NO_TRUNC", _PC_NO_TRUNC},
11503 #endif
11504 #ifdef _PC_PATH_MAX
11505 {"PC_PATH_MAX", _PC_PATH_MAX},
11506 #endif
11507 #ifdef _PC_PIPE_BUF
11508 {"PC_PIPE_BUF", _PC_PIPE_BUF},
11509 #endif
11510 #ifdef _PC_PRIO_IO
11511 {"PC_PRIO_IO", _PC_PRIO_IO},
11512 #endif
11513 #ifdef _PC_SOCK_MAXBUF
11514 {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
11515 #endif
11516 #ifdef _PC_SYNC_IO
11517 {"PC_SYNC_IO", _PC_SYNC_IO},
11518 #endif
11519 #ifdef _PC_VDISABLE
11520 {"PC_VDISABLE", _PC_VDISABLE},
11521 #endif
11522 #ifdef _PC_ACL_ENABLED
11523 {"PC_ACL_ENABLED", _PC_ACL_ENABLED},
11524 #endif
11525 #ifdef _PC_MIN_HOLE_SIZE
11526 {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE},
11527 #endif
11528 #ifdef _PC_ALLOC_SIZE_MIN
11529 {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN},
11530 #endif
11531 #ifdef _PC_REC_INCR_XFER_SIZE
11532 {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE},
11533 #endif
11534 #ifdef _PC_REC_MAX_XFER_SIZE
11535 {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE},
11536 #endif
11537 #ifdef _PC_REC_MIN_XFER_SIZE
11538 {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE},
11539 #endif
11540 #ifdef _PC_REC_XFER_ALIGN
11541 {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN},
11542 #endif
11543 #ifdef _PC_SYMLINK_MAX
11544 {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX},
11545 #endif
11546 #ifdef _PC_XATTR_ENABLED
11547 {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED},
11548 #endif
11549 #ifdef _PC_XATTR_EXISTS
11550 {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
11551 #endif
11552 #ifdef _PC_TIMESTAMP_RESOLUTION
11553 {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
11554 #endif
11555 };
11556
11557 static int
conv_path_confname(PyObject * arg,int * valuep)11558 conv_path_confname(PyObject *arg, int *valuep)
11559 {
11560 return conv_confname(arg, valuep, posix_constants_pathconf,
11561 sizeof(posix_constants_pathconf)
11562 / sizeof(struct constdef));
11563 }
11564 #endif
11565
11566
11567 #ifdef HAVE_FPATHCONF
11568 /*[clinic input]
11569 os.fpathconf -> long
11570
11571 fd: fildes
11572 name: path_confname
11573 /
11574
11575 Return the configuration limit name for the file descriptor fd.
11576
11577 If there is no limit, return -1.
11578 [clinic start generated code]*/
11579
11580 static long
os_fpathconf_impl(PyObject * module,int fd,int name)11581 os_fpathconf_impl(PyObject *module, int fd, int name)
11582 /*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
11583 {
11584 long limit;
11585
11586 errno = 0;
11587 limit = fpathconf(fd, name);
11588 if (limit == -1 && errno != 0)
11589 posix_error();
11590
11591 return limit;
11592 }
11593 #endif /* HAVE_FPATHCONF */
11594
11595
11596 #ifdef HAVE_PATHCONF
11597 /*[clinic input]
11598 os.pathconf -> long
11599 path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
11600 name: path_confname
11601
11602 Return the configuration limit name for the file or directory path.
11603
11604 If there is no limit, return -1.
11605 On some platforms, path may also be specified as an open file descriptor.
11606 If this functionality is unavailable, using it raises an exception.
11607 [clinic start generated code]*/
11608
11609 static long
os_pathconf_impl(PyObject * module,path_t * path,int name)11610 os_pathconf_impl(PyObject *module, path_t *path, int name)
11611 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
11612 {
11613 long limit;
11614
11615 errno = 0;
11616 #ifdef HAVE_FPATHCONF
11617 if (path->fd != -1)
11618 limit = fpathconf(path->fd, name);
11619 else
11620 #endif
11621 limit = pathconf(path->narrow, name);
11622 if (limit == -1 && errno != 0) {
11623 if (errno == EINVAL)
11624 /* could be a path or name problem */
11625 posix_error();
11626 else
11627 path_error(path);
11628 }
11629
11630 return limit;
11631 }
11632 #endif /* HAVE_PATHCONF */
11633
11634 #ifdef HAVE_CONFSTR
11635 static struct constdef posix_constants_confstr[] = {
11636 #ifdef _CS_ARCHITECTURE
11637 {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
11638 #endif
11639 #ifdef _CS_GNU_LIBC_VERSION
11640 {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION},
11641 #endif
11642 #ifdef _CS_GNU_LIBPTHREAD_VERSION
11643 {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION},
11644 #endif
11645 #ifdef _CS_HOSTNAME
11646 {"CS_HOSTNAME", _CS_HOSTNAME},
11647 #endif
11648 #ifdef _CS_HW_PROVIDER
11649 {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
11650 #endif
11651 #ifdef _CS_HW_SERIAL
11652 {"CS_HW_SERIAL", _CS_HW_SERIAL},
11653 #endif
11654 #ifdef _CS_INITTAB_NAME
11655 {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11656 #endif
11657 #ifdef _CS_LFS64_CFLAGS
11658 {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11659 #endif
11660 #ifdef _CS_LFS64_LDFLAGS
11661 {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
11662 #endif
11663 #ifdef _CS_LFS64_LIBS
11664 {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
11665 #endif
11666 #ifdef _CS_LFS64_LINTFLAGS
11667 {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
11668 #endif
11669 #ifdef _CS_LFS_CFLAGS
11670 {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
11671 #endif
11672 #ifdef _CS_LFS_LDFLAGS
11673 {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
11674 #endif
11675 #ifdef _CS_LFS_LIBS
11676 {"CS_LFS_LIBS", _CS_LFS_LIBS},
11677 #endif
11678 #ifdef _CS_LFS_LINTFLAGS
11679 {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
11680 #endif
11681 #ifdef _CS_MACHINE
11682 {"CS_MACHINE", _CS_MACHINE},
11683 #endif
11684 #ifdef _CS_PATH
11685 {"CS_PATH", _CS_PATH},
11686 #endif
11687 #ifdef _CS_RELEASE
11688 {"CS_RELEASE", _CS_RELEASE},
11689 #endif
11690 #ifdef _CS_SRPC_DOMAIN
11691 {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
11692 #endif
11693 #ifdef _CS_SYSNAME
11694 {"CS_SYSNAME", _CS_SYSNAME},
11695 #endif
11696 #ifdef _CS_VERSION
11697 {"CS_VERSION", _CS_VERSION},
11698 #endif
11699 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11700 {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
11701 #endif
11702 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11703 {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
11704 #endif
11705 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11706 {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
11707 #endif
11708 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11709 {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11710 #endif
11711 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11712 {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11713 #endif
11714 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11715 {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11716 #endif
11717 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11718 {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
11719 #endif
11720 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11721 {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11722 #endif
11723 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11724 {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
11725 #endif
11726 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11727 {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
11728 #endif
11729 #ifdef _CS_XBS5_LP64_OFF64_LIBS
11730 {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11731 #endif
11732 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11733 {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
11734 #endif
11735 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11736 {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11737 #endif
11738 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11739 {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11740 #endif
11741 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11742 {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
11743 #endif
11744 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11745 {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11746 #endif
11747 #ifdef _MIPS_CS_AVAIL_PROCESSORS
11748 {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
11749 #endif
11750 #ifdef _MIPS_CS_BASE
11751 {"MIPS_CS_BASE", _MIPS_CS_BASE},
11752 #endif
11753 #ifdef _MIPS_CS_HOSTID
11754 {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
11755 #endif
11756 #ifdef _MIPS_CS_HW_NAME
11757 {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11758 #endif
11759 #ifdef _MIPS_CS_NUM_PROCESSORS
11760 {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
11761 #endif
11762 #ifdef _MIPS_CS_OSREL_MAJ
11763 {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
11764 #endif
11765 #ifdef _MIPS_CS_OSREL_MIN
11766 {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
11767 #endif
11768 #ifdef _MIPS_CS_OSREL_PATCH
11769 {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
11770 #endif
11771 #ifdef _MIPS_CS_OS_NAME
11772 {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11773 #endif
11774 #ifdef _MIPS_CS_OS_PROVIDER
11775 {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
11776 #endif
11777 #ifdef _MIPS_CS_PROCESSORS
11778 {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
11779 #endif
11780 #ifdef _MIPS_CS_SERIAL
11781 {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
11782 #endif
11783 #ifdef _MIPS_CS_VENDOR
11784 {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
11785 #endif
11786 };
11787
11788 static int
conv_confstr_confname(PyObject * arg,int * valuep)11789 conv_confstr_confname(PyObject *arg, int *valuep)
11790 {
11791 return conv_confname(arg, valuep, posix_constants_confstr,
11792 sizeof(posix_constants_confstr)
11793 / sizeof(struct constdef));
11794 }
11795
11796
11797 /*[clinic input]
11798 os.confstr
11799
11800 name: confstr_confname
11801 /
11802
11803 Return a string-valued system configuration variable.
11804 [clinic start generated code]*/
11805
11806 static PyObject *
os_confstr_impl(PyObject * module,int name)11807 os_confstr_impl(PyObject *module, int name)
11808 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11809 {
11810 PyObject *result = NULL;
11811 char buffer[255];
11812 size_t len;
11813
11814 errno = 0;
11815 len = confstr(name, buffer, sizeof(buffer));
11816 if (len == 0) {
11817 if (errno) {
11818 posix_error();
11819 return NULL;
11820 }
11821 else {
11822 Py_RETURN_NONE;
11823 }
11824 }
11825
11826 if (len >= sizeof(buffer)) {
11827 size_t len2;
11828 char *buf = PyMem_Malloc(len);
11829 if (buf == NULL)
11830 return PyErr_NoMemory();
11831 len2 = confstr(name, buf, len);
11832 assert(len == len2);
11833 result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11834 PyMem_Free(buf);
11835 }
11836 else
11837 result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11838 return result;
11839 }
11840 #endif /* HAVE_CONFSTR */
11841
11842
11843 #ifdef HAVE_SYSCONF
11844 static struct constdef posix_constants_sysconf[] = {
11845 #ifdef _SC_2_CHAR_TERM
11846 {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
11847 #endif
11848 #ifdef _SC_2_C_BIND
11849 {"SC_2_C_BIND", _SC_2_C_BIND},
11850 #endif
11851 #ifdef _SC_2_C_DEV
11852 {"SC_2_C_DEV", _SC_2_C_DEV},
11853 #endif
11854 #ifdef _SC_2_C_VERSION
11855 {"SC_2_C_VERSION", _SC_2_C_VERSION},
11856 #endif
11857 #ifdef _SC_2_FORT_DEV
11858 {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
11859 #endif
11860 #ifdef _SC_2_FORT_RUN
11861 {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
11862 #endif
11863 #ifdef _SC_2_LOCALEDEF
11864 {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
11865 #endif
11866 #ifdef _SC_2_SW_DEV
11867 {"SC_2_SW_DEV", _SC_2_SW_DEV},
11868 #endif
11869 #ifdef _SC_2_UPE
11870 {"SC_2_UPE", _SC_2_UPE},
11871 #endif
11872 #ifdef _SC_2_VERSION
11873 {"SC_2_VERSION", _SC_2_VERSION},
11874 #endif
11875 #ifdef _SC_ABI_ASYNCHRONOUS_IO
11876 {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
11877 #endif
11878 #ifdef _SC_ACL
11879 {"SC_ACL", _SC_ACL},
11880 #endif
11881 #ifdef _SC_AIO_LISTIO_MAX
11882 {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
11883 #endif
11884 #ifdef _SC_AIO_MAX
11885 {"SC_AIO_MAX", _SC_AIO_MAX},
11886 #endif
11887 #ifdef _SC_AIO_PRIO_DELTA_MAX
11888 {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
11889 #endif
11890 #ifdef _SC_ARG_MAX
11891 {"SC_ARG_MAX", _SC_ARG_MAX},
11892 #endif
11893 #ifdef _SC_ASYNCHRONOUS_IO
11894 {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
11895 #endif
11896 #ifdef _SC_ATEXIT_MAX
11897 {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
11898 #endif
11899 #ifdef _SC_AUDIT
11900 {"SC_AUDIT", _SC_AUDIT},
11901 #endif
11902 #ifdef _SC_AVPHYS_PAGES
11903 {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
11904 #endif
11905 #ifdef _SC_BC_BASE_MAX
11906 {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
11907 #endif
11908 #ifdef _SC_BC_DIM_MAX
11909 {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
11910 #endif
11911 #ifdef _SC_BC_SCALE_MAX
11912 {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
11913 #endif
11914 #ifdef _SC_BC_STRING_MAX
11915 {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
11916 #endif
11917 #ifdef _SC_CAP
11918 {"SC_CAP", _SC_CAP},
11919 #endif
11920 #ifdef _SC_CHARCLASS_NAME_MAX
11921 {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
11922 #endif
11923 #ifdef _SC_CHAR_BIT
11924 {"SC_CHAR_BIT", _SC_CHAR_BIT},
11925 #endif
11926 #ifdef _SC_CHAR_MAX
11927 {"SC_CHAR_MAX", _SC_CHAR_MAX},
11928 #endif
11929 #ifdef _SC_CHAR_MIN
11930 {"SC_CHAR_MIN", _SC_CHAR_MIN},
11931 #endif
11932 #ifdef _SC_CHILD_MAX
11933 {"SC_CHILD_MAX", _SC_CHILD_MAX},
11934 #endif
11935 #ifdef _SC_CLK_TCK
11936 {"SC_CLK_TCK", _SC_CLK_TCK},
11937 #endif
11938 #ifdef _SC_COHER_BLKSZ
11939 {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
11940 #endif
11941 #ifdef _SC_COLL_WEIGHTS_MAX
11942 {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
11943 #endif
11944 #ifdef _SC_DCACHE_ASSOC
11945 {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
11946 #endif
11947 #ifdef _SC_DCACHE_BLKSZ
11948 {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
11949 #endif
11950 #ifdef _SC_DCACHE_LINESZ
11951 {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
11952 #endif
11953 #ifdef _SC_DCACHE_SZ
11954 {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
11955 #endif
11956 #ifdef _SC_DCACHE_TBLKSZ
11957 {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
11958 #endif
11959 #ifdef _SC_DELAYTIMER_MAX
11960 {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
11961 #endif
11962 #ifdef _SC_EQUIV_CLASS_MAX
11963 {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
11964 #endif
11965 #ifdef _SC_EXPR_NEST_MAX
11966 {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
11967 #endif
11968 #ifdef _SC_FSYNC
11969 {"SC_FSYNC", _SC_FSYNC},
11970 #endif
11971 #ifdef _SC_GETGR_R_SIZE_MAX
11972 {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
11973 #endif
11974 #ifdef _SC_GETPW_R_SIZE_MAX
11975 {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
11976 #endif
11977 #ifdef _SC_ICACHE_ASSOC
11978 {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
11979 #endif
11980 #ifdef _SC_ICACHE_BLKSZ
11981 {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
11982 #endif
11983 #ifdef _SC_ICACHE_LINESZ
11984 {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
11985 #endif
11986 #ifdef _SC_ICACHE_SZ
11987 {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
11988 #endif
11989 #ifdef _SC_INF
11990 {"SC_INF", _SC_INF},
11991 #endif
11992 #ifdef _SC_INT_MAX
11993 {"SC_INT_MAX", _SC_INT_MAX},
11994 #endif
11995 #ifdef _SC_INT_MIN
11996 {"SC_INT_MIN", _SC_INT_MIN},
11997 #endif
11998 #ifdef _SC_IOV_MAX
11999 {"SC_IOV_MAX", _SC_IOV_MAX},
12000 #endif
12001 #ifdef _SC_IP_SECOPTS
12002 {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
12003 #endif
12004 #ifdef _SC_JOB_CONTROL
12005 {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
12006 #endif
12007 #ifdef _SC_KERN_POINTERS
12008 {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
12009 #endif
12010 #ifdef _SC_KERN_SIM
12011 {"SC_KERN_SIM", _SC_KERN_SIM},
12012 #endif
12013 #ifdef _SC_LINE_MAX
12014 {"SC_LINE_MAX", _SC_LINE_MAX},
12015 #endif
12016 #ifdef _SC_LOGIN_NAME_MAX
12017 {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
12018 #endif
12019 #ifdef _SC_LOGNAME_MAX
12020 {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
12021 #endif
12022 #ifdef _SC_LONG_BIT
12023 {"SC_LONG_BIT", _SC_LONG_BIT},
12024 #endif
12025 #ifdef _SC_MAC
12026 {"SC_MAC", _SC_MAC},
12027 #endif
12028 #ifdef _SC_MAPPED_FILES
12029 {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
12030 #endif
12031 #ifdef _SC_MAXPID
12032 {"SC_MAXPID", _SC_MAXPID},
12033 #endif
12034 #ifdef _SC_MB_LEN_MAX
12035 {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
12036 #endif
12037 #ifdef _SC_MEMLOCK
12038 {"SC_MEMLOCK", _SC_MEMLOCK},
12039 #endif
12040 #ifdef _SC_MEMLOCK_RANGE
12041 {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
12042 #endif
12043 #ifdef _SC_MEMORY_PROTECTION
12044 {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
12045 #endif
12046 #ifdef _SC_MESSAGE_PASSING
12047 {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
12048 #endif
12049 #ifdef _SC_MMAP_FIXED_ALIGNMENT
12050 {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
12051 #endif
12052 #ifdef _SC_MQ_OPEN_MAX
12053 {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
12054 #endif
12055 #ifdef _SC_MQ_PRIO_MAX
12056 {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},
12057 #endif
12058 #ifdef _SC_NACLS_MAX
12059 {"SC_NACLS_MAX", _SC_NACLS_MAX},
12060 #endif
12061 #ifdef _SC_NGROUPS_MAX
12062 {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX},
12063 #endif
12064 #ifdef _SC_NL_ARGMAX
12065 {"SC_NL_ARGMAX", _SC_NL_ARGMAX},
12066 #endif
12067 #ifdef _SC_NL_LANGMAX
12068 {"SC_NL_LANGMAX", _SC_NL_LANGMAX},
12069 #endif
12070 #ifdef _SC_NL_MSGMAX
12071 {"SC_NL_MSGMAX", _SC_NL_MSGMAX},
12072 #endif
12073 #ifdef _SC_NL_NMAX
12074 {"SC_NL_NMAX", _SC_NL_NMAX},
12075 #endif
12076 #ifdef _SC_NL_SETMAX
12077 {"SC_NL_SETMAX", _SC_NL_SETMAX},
12078 #endif
12079 #ifdef _SC_NL_TEXTMAX
12080 {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX},
12081 #endif
12082 #ifdef _SC_NPROCESSORS_CONF
12083 {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
12084 #endif
12085 #ifdef _SC_NPROCESSORS_ONLN
12086 {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
12087 #endif
12088 #ifdef _SC_NPROC_CONF
12089 {"SC_NPROC_CONF", _SC_NPROC_CONF},
12090 #endif
12091 #ifdef _SC_NPROC_ONLN
12092 {"SC_NPROC_ONLN", _SC_NPROC_ONLN},
12093 #endif
12094 #ifdef _SC_NZERO
12095 {"SC_NZERO", _SC_NZERO},
12096 #endif
12097 #ifdef _SC_OPEN_MAX
12098 {"SC_OPEN_MAX", _SC_OPEN_MAX},
12099 #endif
12100 #ifdef _SC_PAGESIZE
12101 {"SC_PAGESIZE", _SC_PAGESIZE},
12102 #endif
12103 #ifdef _SC_PAGE_SIZE
12104 {"SC_PAGE_SIZE", _SC_PAGE_SIZE},
12105 #endif
12106 #ifdef _SC_AIX_REALMEM
12107 {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
12108 #endif
12109 #ifdef _SC_PASS_MAX
12110 {"SC_PASS_MAX", _SC_PASS_MAX},
12111 #endif
12112 #ifdef _SC_PHYS_PAGES
12113 {"SC_PHYS_PAGES", _SC_PHYS_PAGES},
12114 #endif
12115 #ifdef _SC_PII
12116 {"SC_PII", _SC_PII},
12117 #endif
12118 #ifdef _SC_PII_INTERNET
12119 {"SC_PII_INTERNET", _SC_PII_INTERNET},
12120 #endif
12121 #ifdef _SC_PII_INTERNET_DGRAM
12122 {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM},
12123 #endif
12124 #ifdef _SC_PII_INTERNET_STREAM
12125 {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM},
12126 #endif
12127 #ifdef _SC_PII_OSI
12128 {"SC_PII_OSI", _SC_PII_OSI},
12129 #endif
12130 #ifdef _SC_PII_OSI_CLTS
12131 {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
12132 #endif
12133 #ifdef _SC_PII_OSI_COTS
12134 {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
12135 #endif
12136 #ifdef _SC_PII_OSI_M
12137 {"SC_PII_OSI_M", _SC_PII_OSI_M},
12138 #endif
12139 #ifdef _SC_PII_SOCKET
12140 {"SC_PII_SOCKET", _SC_PII_SOCKET},
12141 #endif
12142 #ifdef _SC_PII_XTI
12143 {"SC_PII_XTI", _SC_PII_XTI},
12144 #endif
12145 #ifdef _SC_POLL
12146 {"SC_POLL", _SC_POLL},
12147 #endif
12148 #ifdef _SC_PRIORITIZED_IO
12149 {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO},
12150 #endif
12151 #ifdef _SC_PRIORITY_SCHEDULING
12152 {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING},
12153 #endif
12154 #ifdef _SC_REALTIME_SIGNALS
12155 {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS},
12156 #endif
12157 #ifdef _SC_RE_DUP_MAX
12158 {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX},
12159 #endif
12160 #ifdef _SC_RTSIG_MAX
12161 {"SC_RTSIG_MAX", _SC_RTSIG_MAX},
12162 #endif
12163 #ifdef _SC_SAVED_IDS
12164 {"SC_SAVED_IDS", _SC_SAVED_IDS},
12165 #endif
12166 #ifdef _SC_SCHAR_MAX
12167 {"SC_SCHAR_MAX", _SC_SCHAR_MAX},
12168 #endif
12169 #ifdef _SC_SCHAR_MIN
12170 {"SC_SCHAR_MIN", _SC_SCHAR_MIN},
12171 #endif
12172 #ifdef _SC_SELECT
12173 {"SC_SELECT", _SC_SELECT},
12174 #endif
12175 #ifdef _SC_SEMAPHORES
12176 {"SC_SEMAPHORES", _SC_SEMAPHORES},
12177 #endif
12178 #ifdef _SC_SEM_NSEMS_MAX
12179 {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX},
12180 #endif
12181 #ifdef _SC_SEM_VALUE_MAX
12182 {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX},
12183 #endif
12184 #ifdef _SC_SHARED_MEMORY_OBJECTS
12185 {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS},
12186 #endif
12187 #ifdef _SC_SHRT_MAX
12188 {"SC_SHRT_MAX", _SC_SHRT_MAX},
12189 #endif
12190 #ifdef _SC_SHRT_MIN
12191 {"SC_SHRT_MIN", _SC_SHRT_MIN},
12192 #endif
12193 #ifdef _SC_SIGQUEUE_MAX
12194 {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
12195 #endif
12196 #ifdef _SC_SIGRT_MAX
12197 {"SC_SIGRT_MAX", _SC_SIGRT_MAX},
12198 #endif
12199 #ifdef _SC_SIGRT_MIN
12200 {"SC_SIGRT_MIN", _SC_SIGRT_MIN},
12201 #endif
12202 #ifdef _SC_SOFTPOWER
12203 {"SC_SOFTPOWER", _SC_SOFTPOWER},
12204 #endif
12205 #ifdef _SC_SPLIT_CACHE
12206 {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE},
12207 #endif
12208 #ifdef _SC_SSIZE_MAX
12209 {"SC_SSIZE_MAX", _SC_SSIZE_MAX},
12210 #endif
12211 #ifdef _SC_STACK_PROT
12212 {"SC_STACK_PROT", _SC_STACK_PROT},
12213 #endif
12214 #ifdef _SC_STREAM_MAX
12215 {"SC_STREAM_MAX", _SC_STREAM_MAX},
12216 #endif
12217 #ifdef _SC_SYNCHRONIZED_IO
12218 {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO},
12219 #endif
12220 #ifdef _SC_THREADS
12221 {"SC_THREADS", _SC_THREADS},
12222 #endif
12223 #ifdef _SC_THREAD_ATTR_STACKADDR
12224 {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR},
12225 #endif
12226 #ifdef _SC_THREAD_ATTR_STACKSIZE
12227 {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE},
12228 #endif
12229 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
12230 {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
12231 #endif
12232 #ifdef _SC_THREAD_KEYS_MAX
12233 {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
12234 #endif
12235 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
12236 {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING},
12237 #endif
12238 #ifdef _SC_THREAD_PRIO_INHERIT
12239 {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT},
12240 #endif
12241 #ifdef _SC_THREAD_PRIO_PROTECT
12242 {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT},
12243 #endif
12244 #ifdef _SC_THREAD_PROCESS_SHARED
12245 {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED},
12246 #endif
12247 #ifdef _SC_THREAD_SAFE_FUNCTIONS
12248 {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS},
12249 #endif
12250 #ifdef _SC_THREAD_STACK_MIN
12251 {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
12252 #endif
12253 #ifdef _SC_THREAD_THREADS_MAX
12254 {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
12255 #endif
12256 #ifdef _SC_TIMERS
12257 {"SC_TIMERS", _SC_TIMERS},
12258 #endif
12259 #ifdef _SC_TIMER_MAX
12260 {"SC_TIMER_MAX", _SC_TIMER_MAX},
12261 #endif
12262 #ifdef _SC_TTY_NAME_MAX
12263 {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
12264 #endif
12265 #ifdef _SC_TZNAME_MAX
12266 {"SC_TZNAME_MAX", _SC_TZNAME_MAX},
12267 #endif
12268 #ifdef _SC_T_IOV_MAX
12269 {"SC_T_IOV_MAX", _SC_T_IOV_MAX},
12270 #endif
12271 #ifdef _SC_UCHAR_MAX
12272 {"SC_UCHAR_MAX", _SC_UCHAR_MAX},
12273 #endif
12274 #ifdef _SC_UINT_MAX
12275 {"SC_UINT_MAX", _SC_UINT_MAX},
12276 #endif
12277 #ifdef _SC_UIO_MAXIOV
12278 {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV},
12279 #endif
12280 #ifdef _SC_ULONG_MAX
12281 {"SC_ULONG_MAX", _SC_ULONG_MAX},
12282 #endif
12283 #ifdef _SC_USHRT_MAX
12284 {"SC_USHRT_MAX", _SC_USHRT_MAX},
12285 #endif
12286 #ifdef _SC_VERSION
12287 {"SC_VERSION", _SC_VERSION},
12288 #endif
12289 #ifdef _SC_WORD_BIT
12290 {"SC_WORD_BIT", _SC_WORD_BIT},
12291 #endif
12292 #ifdef _SC_XBS5_ILP32_OFF32
12293 {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32},
12294 #endif
12295 #ifdef _SC_XBS5_ILP32_OFFBIG
12296 {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG},
12297 #endif
12298 #ifdef _SC_XBS5_LP64_OFF64
12299 {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64},
12300 #endif
12301 #ifdef _SC_XBS5_LPBIG_OFFBIG
12302 {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG},
12303 #endif
12304 #ifdef _SC_XOPEN_CRYPT
12305 {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT},
12306 #endif
12307 #ifdef _SC_XOPEN_ENH_I18N
12308 {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N},
12309 #endif
12310 #ifdef _SC_XOPEN_LEGACY
12311 {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
12312 #endif
12313 #ifdef _SC_XOPEN_REALTIME
12314 {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME},
12315 #endif
12316 #ifdef _SC_XOPEN_REALTIME_THREADS
12317 {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS},
12318 #endif
12319 #ifdef _SC_XOPEN_SHM
12320 {"SC_XOPEN_SHM", _SC_XOPEN_SHM},
12321 #endif
12322 #ifdef _SC_XOPEN_UNIX
12323 {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX},
12324 #endif
12325 #ifdef _SC_XOPEN_VERSION
12326 {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION},
12327 #endif
12328 #ifdef _SC_XOPEN_XCU_VERSION
12329 {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION},
12330 #endif
12331 #ifdef _SC_XOPEN_XPG2
12332 {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2},
12333 #endif
12334 #ifdef _SC_XOPEN_XPG3
12335 {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3},
12336 #endif
12337 #ifdef _SC_XOPEN_XPG4
12338 {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4},
12339 #endif
12340 };
12341
12342 static int
conv_sysconf_confname(PyObject * arg,int * valuep)12343 conv_sysconf_confname(PyObject *arg, int *valuep)
12344 {
12345 return conv_confname(arg, valuep, posix_constants_sysconf,
12346 sizeof(posix_constants_sysconf)
12347 / sizeof(struct constdef));
12348 }
12349
12350
12351 /*[clinic input]
12352 os.sysconf -> long
12353 name: sysconf_confname
12354 /
12355
12356 Return an integer-valued system configuration variable.
12357 [clinic start generated code]*/
12358
12359 static long
os_sysconf_impl(PyObject * module,int name)12360 os_sysconf_impl(PyObject *module, int name)
12361 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
12362 {
12363 long value;
12364
12365 errno = 0;
12366 value = sysconf(name);
12367 if (value == -1 && errno != 0)
12368 posix_error();
12369 return value;
12370 }
12371 #endif /* HAVE_SYSCONF */
12372
12373
12374 /* This code is used to ensure that the tables of configuration value names
12375 * are in sorted order as required by conv_confname(), and also to build
12376 * the exported dictionaries that are used to publish information about the
12377 * names available on the host platform.
12378 *
12379 * Sorting the table at runtime ensures that the table is properly ordered
12380 * when used, even for platforms we're not able to test on. It also makes
12381 * it easier to add additional entries to the tables.
12382 */
12383
12384 static int
cmp_constdefs(const void * v1,const void * v2)12385 cmp_constdefs(const void *v1, const void *v2)
12386 {
12387 const struct constdef *c1 =
12388 (const struct constdef *) v1;
12389 const struct constdef *c2 =
12390 (const struct constdef *) v2;
12391
12392 return strcmp(c1->name, c2->name);
12393 }
12394
12395 static int
setup_confname_table(struct constdef * table,size_t tablesize,const char * tablename,PyObject * module)12396 setup_confname_table(struct constdef *table, size_t tablesize,
12397 const char *tablename, PyObject *module)
12398 {
12399 PyObject *d = NULL;
12400 size_t i;
12401
12402 qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
12403 d = PyDict_New();
12404 if (d == NULL)
12405 return -1;
12406
12407 for (i=0; i < tablesize; ++i) {
12408 PyObject *o = PyLong_FromLong(table[i].value);
12409 if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
12410 Py_XDECREF(o);
12411 Py_DECREF(d);
12412 return -1;
12413 }
12414 Py_DECREF(o);
12415 }
12416 return PyModule_AddObject(module, tablename, d);
12417 }
12418
12419 /* Return -1 on failure, 0 on success. */
12420 static int
setup_confname_tables(PyObject * module)12421 setup_confname_tables(PyObject *module)
12422 {
12423 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12424 if (setup_confname_table(posix_constants_pathconf,
12425 sizeof(posix_constants_pathconf)
12426 / sizeof(struct constdef),
12427 "pathconf_names", module))
12428 return -1;
12429 #endif
12430 #ifdef HAVE_CONFSTR
12431 if (setup_confname_table(posix_constants_confstr,
12432 sizeof(posix_constants_confstr)
12433 / sizeof(struct constdef),
12434 "confstr_names", module))
12435 return -1;
12436 #endif
12437 #ifdef HAVE_SYSCONF
12438 if (setup_confname_table(posix_constants_sysconf,
12439 sizeof(posix_constants_sysconf)
12440 / sizeof(struct constdef),
12441 "sysconf_names", module))
12442 return -1;
12443 #endif
12444 return 0;
12445 }
12446
12447
12448 /*[clinic input]
12449 os.abort
12450
12451 Abort the interpreter immediately.
12452
12453 This function 'dumps core' or otherwise fails in the hardest way possible
12454 on the hosting operating system. This function never returns.
12455 [clinic start generated code]*/
12456
12457 static PyObject *
os_abort_impl(PyObject * module)12458 os_abort_impl(PyObject *module)
12459 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
12460 {
12461 abort();
12462 /*NOTREACHED*/
12463 #ifndef __clang__
12464 /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
12465 GCC emits a warning without "return NULL;" (compiler bug?), but Clang
12466 is smarter and emits a warning on the return. */
12467 Py_FatalError("abort() called from Python code didn't abort!");
12468 return NULL;
12469 #endif
12470 }
12471
12472 #ifdef MS_WINDOWS
12473 /* Grab ShellExecute dynamically from shell32 */
12474 static int has_ShellExecute = -1;
12475 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
12476 LPCWSTR, INT);
12477 static int
check_ShellExecute()12478 check_ShellExecute()
12479 {
12480 HINSTANCE hShell32;
12481
12482 /* only recheck */
12483 if (-1 == has_ShellExecute) {
12484 Py_BEGIN_ALLOW_THREADS
12485 /* Security note: this call is not vulnerable to "DLL hijacking".
12486 SHELL32 is part of "KnownDLLs" and so Windows always load
12487 the system SHELL32.DLL, even if there is another SHELL32.DLL
12488 in the DLL search path. */
12489 hShell32 = LoadLibraryW(L"SHELL32");
12490 if (hShell32) {
12491 *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
12492 "ShellExecuteW");
12493 has_ShellExecute = Py_ShellExecuteW != NULL;
12494 } else {
12495 has_ShellExecute = 0;
12496 }
12497 Py_END_ALLOW_THREADS
12498 }
12499 return has_ShellExecute;
12500 }
12501
12502
12503 /*[clinic input]
12504 os.startfile
12505 filepath: path_t
12506 operation: Py_UNICODE = NULL
12507 arguments: Py_UNICODE = NULL
12508 cwd: path_t(nullable=True) = None
12509 show_cmd: int = 1
12510
12511 Start a file with its associated application.
12512
12513 When "operation" is not specified or "open", this acts like
12514 double-clicking the file in Explorer, or giving the file name as an
12515 argument to the DOS "start" command: the file is opened with whatever
12516 application (if any) its extension is associated.
12517 When another "operation" is given, it specifies what should be done with
12518 the file. A typical operation is "print".
12519
12520 "arguments" is passed to the application, but should be omitted if the
12521 file is a document.
12522
12523 "cwd" is the working directory for the operation. If "filepath" is
12524 relative, it will be resolved against this directory. This argument
12525 should usually be an absolute path.
12526
12527 "show_cmd" can be used to override the recommended visibility option.
12528 See the Windows ShellExecute documentation for values.
12529
12530 startfile returns as soon as the associated application is launched.
12531 There is no option to wait for the application to close, and no way
12532 to retrieve the application's exit status.
12533
12534 The filepath is relative to the current directory. If you want to use
12535 an absolute path, make sure the first character is not a slash ("/");
12536 the underlying Win32 ShellExecute function doesn't work if it is.
12537 [clinic start generated code]*/
12538
12539 static PyObject *
os_startfile_impl(PyObject * module,path_t * filepath,const Py_UNICODE * operation,const Py_UNICODE * arguments,path_t * cwd,int show_cmd)12540 os_startfile_impl(PyObject *module, path_t *filepath,
12541 const Py_UNICODE *operation, const Py_UNICODE *arguments,
12542 path_t *cwd, int show_cmd)
12543 /*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/
12544 {
12545 HINSTANCE rc;
12546
12547 if(!check_ShellExecute()) {
12548 /* If the OS doesn't have ShellExecute, return a
12549 NotImplementedError. */
12550 return PyErr_Format(PyExc_NotImplementedError,
12551 "startfile not available on this platform");
12552 }
12553
12554 if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
12555 return NULL;
12556 }
12557 if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
12558 arguments, cwd->object ? cwd->object : Py_None,
12559 show_cmd) < 0) {
12560 return NULL;
12561 }
12562
12563 Py_BEGIN_ALLOW_THREADS
12564 rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
12565 arguments, cwd->wide, show_cmd);
12566 Py_END_ALLOW_THREADS
12567
12568 if (rc <= (HINSTANCE)32) {
12569 win32_error_object("startfile", filepath->object);
12570 return NULL;
12571 }
12572 Py_RETURN_NONE;
12573 }
12574 #endif /* MS_WINDOWS */
12575
12576
12577 #ifdef HAVE_GETLOADAVG
12578 /*[clinic input]
12579 os.getloadavg
12580
12581 Return average recent system load information.
12582
12583 Return the number of processes in the system run queue averaged over
12584 the last 1, 5, and 15 minutes as a tuple of three floats.
12585 Raises OSError if the load average was unobtainable.
12586 [clinic start generated code]*/
12587
12588 static PyObject *
os_getloadavg_impl(PyObject * module)12589 os_getloadavg_impl(PyObject *module)
12590 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
12591 {
12592 double loadavg[3];
12593 if (getloadavg(loadavg, 3)!=3) {
12594 PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
12595 return NULL;
12596 } else
12597 return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
12598 }
12599 #endif /* HAVE_GETLOADAVG */
12600
12601
12602 /*[clinic input]
12603 os.device_encoding
12604 fd: int
12605
12606 Return a string describing the encoding of a terminal's file descriptor.
12607
12608 The file descriptor must be attached to a terminal.
12609 If the device is not a terminal, return None.
12610 [clinic start generated code]*/
12611
12612 static PyObject *
os_device_encoding_impl(PyObject * module,int fd)12613 os_device_encoding_impl(PyObject *module, int fd)
12614 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
12615 {
12616 return _Py_device_encoding(fd);
12617 }
12618
12619
12620 #ifdef HAVE_SETRESUID
12621 /*[clinic input]
12622 os.setresuid
12623
12624 ruid: uid_t
12625 euid: uid_t
12626 suid: uid_t
12627 /
12628
12629 Set the current process's real, effective, and saved user ids.
12630 [clinic start generated code]*/
12631
12632 static PyObject *
os_setresuid_impl(PyObject * module,uid_t ruid,uid_t euid,uid_t suid)12633 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
12634 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
12635 {
12636 if (setresuid(ruid, euid, suid) < 0)
12637 return posix_error();
12638 Py_RETURN_NONE;
12639 }
12640 #endif /* HAVE_SETRESUID */
12641
12642
12643 #ifdef HAVE_SETRESGID
12644 /*[clinic input]
12645 os.setresgid
12646
12647 rgid: gid_t
12648 egid: gid_t
12649 sgid: gid_t
12650 /
12651
12652 Set the current process's real, effective, and saved group ids.
12653 [clinic start generated code]*/
12654
12655 static PyObject *
os_setresgid_impl(PyObject * module,gid_t rgid,gid_t egid,gid_t sgid)12656 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
12657 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
12658 {
12659 if (setresgid(rgid, egid, sgid) < 0)
12660 return posix_error();
12661 Py_RETURN_NONE;
12662 }
12663 #endif /* HAVE_SETRESGID */
12664
12665
12666 #ifdef HAVE_GETRESUID
12667 /*[clinic input]
12668 os.getresuid
12669
12670 Return a tuple of the current process's real, effective, and saved user ids.
12671 [clinic start generated code]*/
12672
12673 static PyObject *
os_getresuid_impl(PyObject * module)12674 os_getresuid_impl(PyObject *module)
12675 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12676 {
12677 uid_t ruid, euid, suid;
12678 if (getresuid(&ruid, &euid, &suid) < 0)
12679 return posix_error();
12680 return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12681 _PyLong_FromUid(euid),
12682 _PyLong_FromUid(suid));
12683 }
12684 #endif /* HAVE_GETRESUID */
12685
12686
12687 #ifdef HAVE_GETRESGID
12688 /*[clinic input]
12689 os.getresgid
12690
12691 Return a tuple of the current process's real, effective, and saved group ids.
12692 [clinic start generated code]*/
12693
12694 static PyObject *
os_getresgid_impl(PyObject * module)12695 os_getresgid_impl(PyObject *module)
12696 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12697 {
12698 gid_t rgid, egid, sgid;
12699 if (getresgid(&rgid, &egid, &sgid) < 0)
12700 return posix_error();
12701 return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12702 _PyLong_FromGid(egid),
12703 _PyLong_FromGid(sgid));
12704 }
12705 #endif /* HAVE_GETRESGID */
12706
12707
12708 #ifdef USE_XATTRS
12709 /*[clinic input]
12710 os.getxattr
12711
12712 path: path_t(allow_fd=True)
12713 attribute: path_t
12714 *
12715 follow_symlinks: bool = True
12716
12717 Return the value of extended attribute attribute on path.
12718
12719 path may be either a string, a path-like object, or an open file descriptor.
12720 If follow_symlinks is False, and the last element of the path is a symbolic
12721 link, getxattr will examine the symbolic link itself instead of the file
12722 the link points to.
12723
12724 [clinic start generated code]*/
12725
12726 static PyObject *
os_getxattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12727 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12728 int follow_symlinks)
12729 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12730 {
12731 Py_ssize_t i;
12732 PyObject *buffer = NULL;
12733
12734 if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12735 return NULL;
12736
12737 if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12738 return NULL;
12739 }
12740
12741 for (i = 0; ; i++) {
12742 void *ptr;
12743 ssize_t result;
12744 static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12745 Py_ssize_t buffer_size = buffer_sizes[i];
12746 if (!buffer_size) {
12747 path_error(path);
12748 return NULL;
12749 }
12750 buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12751 if (!buffer)
12752 return NULL;
12753 ptr = PyBytes_AS_STRING(buffer);
12754
12755 Py_BEGIN_ALLOW_THREADS;
12756 if (path->fd >= 0)
12757 result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12758 else if (follow_symlinks)
12759 result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12760 else
12761 result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12762 Py_END_ALLOW_THREADS;
12763
12764 if (result < 0) {
12765 Py_DECREF(buffer);
12766 if (errno == ERANGE)
12767 continue;
12768 path_error(path);
12769 return NULL;
12770 }
12771
12772 if (result != buffer_size) {
12773 /* Can only shrink. */
12774 _PyBytes_Resize(&buffer, result);
12775 }
12776 break;
12777 }
12778
12779 return buffer;
12780 }
12781
12782
12783 /*[clinic input]
12784 os.setxattr
12785
12786 path: path_t(allow_fd=True)
12787 attribute: path_t
12788 value: Py_buffer
12789 flags: int = 0
12790 *
12791 follow_symlinks: bool = True
12792
12793 Set extended attribute attribute on path to value.
12794
12795 path may be either a string, a path-like object, or an open file descriptor.
12796 If follow_symlinks is False, and the last element of the path is a symbolic
12797 link, setxattr will modify the symbolic link itself instead of the file
12798 the link points to.
12799
12800 [clinic start generated code]*/
12801
12802 static PyObject *
os_setxattr_impl(PyObject * module,path_t * path,path_t * attribute,Py_buffer * value,int flags,int follow_symlinks)12803 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12804 Py_buffer *value, int flags, int follow_symlinks)
12805 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12806 {
12807 ssize_t result;
12808
12809 if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12810 return NULL;
12811
12812 if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12813 value->buf, value->len, flags) < 0) {
12814 return NULL;
12815 }
12816
12817 Py_BEGIN_ALLOW_THREADS;
12818 if (path->fd > -1)
12819 result = fsetxattr(path->fd, attribute->narrow,
12820 value->buf, value->len, flags);
12821 else if (follow_symlinks)
12822 result = setxattr(path->narrow, attribute->narrow,
12823 value->buf, value->len, flags);
12824 else
12825 result = lsetxattr(path->narrow, attribute->narrow,
12826 value->buf, value->len, flags);
12827 Py_END_ALLOW_THREADS;
12828
12829 if (result) {
12830 path_error(path);
12831 return NULL;
12832 }
12833
12834 Py_RETURN_NONE;
12835 }
12836
12837
12838 /*[clinic input]
12839 os.removexattr
12840
12841 path: path_t(allow_fd=True)
12842 attribute: path_t
12843 *
12844 follow_symlinks: bool = True
12845
12846 Remove extended attribute attribute on path.
12847
12848 path may be either a string, a path-like object, or an open file descriptor.
12849 If follow_symlinks is False, and the last element of the path is a symbolic
12850 link, removexattr will modify the symbolic link itself instead of the file
12851 the link points to.
12852
12853 [clinic start generated code]*/
12854
12855 static PyObject *
os_removexattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12856 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
12857 int follow_symlinks)
12858 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
12859 {
12860 ssize_t result;
12861
12862 if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
12863 return NULL;
12864
12865 if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
12866 return NULL;
12867 }
12868
12869 Py_BEGIN_ALLOW_THREADS;
12870 if (path->fd > -1)
12871 result = fremovexattr(path->fd, attribute->narrow);
12872 else if (follow_symlinks)
12873 result = removexattr(path->narrow, attribute->narrow);
12874 else
12875 result = lremovexattr(path->narrow, attribute->narrow);
12876 Py_END_ALLOW_THREADS;
12877
12878 if (result) {
12879 return path_error(path);
12880 }
12881
12882 Py_RETURN_NONE;
12883 }
12884
12885
12886 /*[clinic input]
12887 os.listxattr
12888
12889 path: path_t(allow_fd=True, nullable=True) = None
12890 *
12891 follow_symlinks: bool = True
12892
12893 Return a list of extended attributes on path.
12894
12895 path may be either None, a string, a path-like object, or an open file descriptor.
12896 if path is None, listxattr will examine the current directory.
12897 If follow_symlinks is False, and the last element of the path is a symbolic
12898 link, listxattr will examine the symbolic link itself instead of the file
12899 the link points to.
12900 [clinic start generated code]*/
12901
12902 static PyObject *
os_listxattr_impl(PyObject * module,path_t * path,int follow_symlinks)12903 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
12904 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
12905 {
12906 Py_ssize_t i;
12907 PyObject *result = NULL;
12908 const char *name;
12909 char *buffer = NULL;
12910
12911 if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
12912 goto exit;
12913
12914 if (PySys_Audit("os.listxattr", "(O)",
12915 path->object ? path->object : Py_None) < 0) {
12916 return NULL;
12917 }
12918
12919 name = path->narrow ? path->narrow : ".";
12920
12921 for (i = 0; ; i++) {
12922 const char *start, *trace, *end;
12923 ssize_t length;
12924 static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
12925 Py_ssize_t buffer_size = buffer_sizes[i];
12926 if (!buffer_size) {
12927 /* ERANGE */
12928 path_error(path);
12929 break;
12930 }
12931 buffer = PyMem_Malloc(buffer_size);
12932 if (!buffer) {
12933 PyErr_NoMemory();
12934 break;
12935 }
12936
12937 Py_BEGIN_ALLOW_THREADS;
12938 if (path->fd > -1)
12939 length = flistxattr(path->fd, buffer, buffer_size);
12940 else if (follow_symlinks)
12941 length = listxattr(name, buffer, buffer_size);
12942 else
12943 length = llistxattr(name, buffer, buffer_size);
12944 Py_END_ALLOW_THREADS;
12945
12946 if (length < 0) {
12947 if (errno == ERANGE) {
12948 PyMem_Free(buffer);
12949 buffer = NULL;
12950 continue;
12951 }
12952 path_error(path);
12953 break;
12954 }
12955
12956 result = PyList_New(0);
12957 if (!result) {
12958 goto exit;
12959 }
12960
12961 end = buffer + length;
12962 for (trace = start = buffer; trace != end; trace++) {
12963 if (!*trace) {
12964 int error;
12965 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
12966 trace - start);
12967 if (!attribute) {
12968 Py_DECREF(result);
12969 result = NULL;
12970 goto exit;
12971 }
12972 error = PyList_Append(result, attribute);
12973 Py_DECREF(attribute);
12974 if (error) {
12975 Py_DECREF(result);
12976 result = NULL;
12977 goto exit;
12978 }
12979 start = trace + 1;
12980 }
12981 }
12982 break;
12983 }
12984 exit:
12985 if (buffer)
12986 PyMem_Free(buffer);
12987 return result;
12988 }
12989 #endif /* USE_XATTRS */
12990
12991
12992 /*[clinic input]
12993 os.urandom
12994
12995 size: Py_ssize_t
12996 /
12997
12998 Return a bytes object containing random bytes suitable for cryptographic use.
12999 [clinic start generated code]*/
13000
13001 static PyObject *
os_urandom_impl(PyObject * module,Py_ssize_t size)13002 os_urandom_impl(PyObject *module, Py_ssize_t size)
13003 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
13004 {
13005 PyObject *bytes;
13006 int result;
13007
13008 if (size < 0)
13009 return PyErr_Format(PyExc_ValueError,
13010 "negative argument not allowed");
13011 bytes = PyBytes_FromStringAndSize(NULL, size);
13012 if (bytes == NULL)
13013 return NULL;
13014
13015 result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
13016 if (result == -1) {
13017 Py_DECREF(bytes);
13018 return NULL;
13019 }
13020 return bytes;
13021 }
13022
13023 #ifdef HAVE_MEMFD_CREATE
13024 /*[clinic input]
13025 os.memfd_create
13026
13027 name: FSConverter
13028 flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
13029
13030 [clinic start generated code]*/
13031
13032 static PyObject *
os_memfd_create_impl(PyObject * module,PyObject * name,unsigned int flags)13033 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
13034 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
13035 {
13036 int fd;
13037 const char *bytes = PyBytes_AS_STRING(name);
13038 Py_BEGIN_ALLOW_THREADS
13039 fd = memfd_create(bytes, flags);
13040 Py_END_ALLOW_THREADS
13041 if (fd == -1) {
13042 return PyErr_SetFromErrno(PyExc_OSError);
13043 }
13044 return PyLong_FromLong(fd);
13045 }
13046 #endif
13047
13048 #ifdef HAVE_EVENTFD
13049 /*[clinic input]
13050 os.eventfd
13051
13052 initval: unsigned_int
13053 flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
13054
13055 Creates and returns an event notification file descriptor.
13056 [clinic start generated code]*/
13057
13058 static PyObject *
os_eventfd_impl(PyObject * module,unsigned int initval,int flags)13059 os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
13060 /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
13061
13062 {
13063 /* initval is limited to uint32_t, internal counter is uint64_t */
13064 int fd;
13065 Py_BEGIN_ALLOW_THREADS
13066 fd = eventfd(initval, flags);
13067 Py_END_ALLOW_THREADS
13068 if (fd == -1) {
13069 return PyErr_SetFromErrno(PyExc_OSError);
13070 }
13071 return PyLong_FromLong(fd);
13072 }
13073
13074 /*[clinic input]
13075 os.eventfd_read
13076
13077 fd: fildes
13078
13079 Read eventfd value
13080 [clinic start generated code]*/
13081
13082 static PyObject *
os_eventfd_read_impl(PyObject * module,int fd)13083 os_eventfd_read_impl(PyObject *module, int fd)
13084 /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
13085 {
13086 eventfd_t value;
13087 int result;
13088 Py_BEGIN_ALLOW_THREADS
13089 result = eventfd_read(fd, &value);
13090 Py_END_ALLOW_THREADS
13091 if (result == -1) {
13092 return PyErr_SetFromErrno(PyExc_OSError);
13093 }
13094 return PyLong_FromUnsignedLongLong(value);
13095 }
13096
13097 /*[clinic input]
13098 os.eventfd_write
13099
13100 fd: fildes
13101 value: unsigned_long_long
13102
13103 Write eventfd value.
13104 [clinic start generated code]*/
13105
13106 static PyObject *
os_eventfd_write_impl(PyObject * module,int fd,unsigned long long value)13107 os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
13108 /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
13109 {
13110 int result;
13111 Py_BEGIN_ALLOW_THREADS
13112 result = eventfd_write(fd, value);
13113 Py_END_ALLOW_THREADS
13114 if (result == -1) {
13115 return PyErr_SetFromErrno(PyExc_OSError);
13116 }
13117 Py_RETURN_NONE;
13118 }
13119 #endif /* HAVE_EVENTFD */
13120
13121 /* Terminal size querying */
13122
13123 PyDoc_STRVAR(TerminalSize_docstring,
13124 "A tuple of (columns, lines) for holding terminal window size");
13125
13126 static PyStructSequence_Field TerminalSize_fields[] = {
13127 {"columns", "width of the terminal window in characters"},
13128 {"lines", "height of the terminal window in characters"},
13129 {NULL, NULL}
13130 };
13131
13132 static PyStructSequence_Desc TerminalSize_desc = {
13133 "os.terminal_size",
13134 TerminalSize_docstring,
13135 TerminalSize_fields,
13136 2,
13137 };
13138
13139 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
13140 /*[clinic input]
13141 os.get_terminal_size
13142
13143 fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
13144 /
13145
13146 Return the size of the terminal window as (columns, lines).
13147
13148 The optional argument fd (default standard output) specifies
13149 which file descriptor should be queried.
13150
13151 If the file descriptor is not connected to a terminal, an OSError
13152 is thrown.
13153
13154 This function will only be defined if an implementation is
13155 available for this system.
13156
13157 shutil.get_terminal_size is the high-level function which should
13158 normally be used, os.get_terminal_size is the low-level implementation.
13159 [clinic start generated code]*/
13160
13161 static PyObject *
os_get_terminal_size_impl(PyObject * module,int fd)13162 os_get_terminal_size_impl(PyObject *module, int fd)
13163 /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
13164 {
13165 int columns, lines;
13166 PyObject *termsize;
13167
13168 /* Under some conditions stdout may not be connected and
13169 * fileno(stdout) may point to an invalid file descriptor. For example
13170 * GUI apps don't have valid standard streams by default.
13171 *
13172 * If this happens, and the optional fd argument is not present,
13173 * the ioctl below will fail returning EBADF. This is what we want.
13174 */
13175
13176 #ifdef TERMSIZE_USE_IOCTL
13177 {
13178 struct winsize w;
13179 if (ioctl(fd, TIOCGWINSZ, &w))
13180 return PyErr_SetFromErrno(PyExc_OSError);
13181 columns = w.ws_col;
13182 lines = w.ws_row;
13183 }
13184 #endif /* TERMSIZE_USE_IOCTL */
13185
13186 #ifdef TERMSIZE_USE_CONIO
13187 {
13188 DWORD nhandle;
13189 HANDLE handle;
13190 CONSOLE_SCREEN_BUFFER_INFO csbi;
13191 switch (fd) {
13192 case 0: nhandle = STD_INPUT_HANDLE;
13193 break;
13194 case 1: nhandle = STD_OUTPUT_HANDLE;
13195 break;
13196 case 2: nhandle = STD_ERROR_HANDLE;
13197 break;
13198 default:
13199 return PyErr_Format(PyExc_ValueError, "bad file descriptor");
13200 }
13201 handle = GetStdHandle(nhandle);
13202 if (handle == NULL)
13203 return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
13204 if (handle == INVALID_HANDLE_VALUE)
13205 return PyErr_SetFromWindowsErr(0);
13206
13207 if (!GetConsoleScreenBufferInfo(handle, &csbi))
13208 return PyErr_SetFromWindowsErr(0);
13209
13210 columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
13211 lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
13212 }
13213 #endif /* TERMSIZE_USE_CONIO */
13214
13215 PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
13216 termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
13217 if (termsize == NULL)
13218 return NULL;
13219 PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
13220 PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
13221 if (PyErr_Occurred()) {
13222 Py_DECREF(termsize);
13223 return NULL;
13224 }
13225 return termsize;
13226 }
13227 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
13228
13229
13230 /*[clinic input]
13231 os.cpu_count
13232
13233 Return the number of CPUs in the system; return None if indeterminable.
13234
13235 This number is not equivalent to the number of CPUs the current process can
13236 use. The number of usable CPUs can be obtained with
13237 ``len(os.sched_getaffinity(0))``
13238 [clinic start generated code]*/
13239
13240 static PyObject *
os_cpu_count_impl(PyObject * module)13241 os_cpu_count_impl(PyObject *module)
13242 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
13243 {
13244 int ncpu = 0;
13245 #ifdef MS_WINDOWS
13246 ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
13247 #elif defined(__hpux)
13248 ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
13249 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
13250 ncpu = sysconf(_SC_NPROCESSORS_ONLN);
13251 #elif defined(__VXWORKS__)
13252 ncpu = _Py_popcount32(vxCpuEnabledGet());
13253 #elif defined(__DragonFly__) || \
13254 defined(__OpenBSD__) || \
13255 defined(__FreeBSD__) || \
13256 defined(__NetBSD__) || \
13257 defined(__APPLE__)
13258 int mib[2];
13259 size_t len = sizeof(ncpu);
13260 mib[0] = CTL_HW;
13261 mib[1] = HW_NCPU;
13262 if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
13263 ncpu = 0;
13264 #endif
13265 if (ncpu >= 1)
13266 return PyLong_FromLong(ncpu);
13267 else
13268 Py_RETURN_NONE;
13269 }
13270
13271
13272 /*[clinic input]
13273 os.get_inheritable -> bool
13274
13275 fd: int
13276 /
13277
13278 Get the close-on-exe flag of the specified file descriptor.
13279 [clinic start generated code]*/
13280
13281 static int
os_get_inheritable_impl(PyObject * module,int fd)13282 os_get_inheritable_impl(PyObject *module, int fd)
13283 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
13284 {
13285 int return_value;
13286 _Py_BEGIN_SUPPRESS_IPH
13287 return_value = _Py_get_inheritable(fd);
13288 _Py_END_SUPPRESS_IPH
13289 return return_value;
13290 }
13291
13292
13293 /*[clinic input]
13294 os.set_inheritable
13295 fd: int
13296 inheritable: int
13297 /
13298
13299 Set the inheritable flag of the specified file descriptor.
13300 [clinic start generated code]*/
13301
13302 static PyObject *
os_set_inheritable_impl(PyObject * module,int fd,int inheritable)13303 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
13304 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
13305 {
13306 int result;
13307
13308 _Py_BEGIN_SUPPRESS_IPH
13309 result = _Py_set_inheritable(fd, inheritable, NULL);
13310 _Py_END_SUPPRESS_IPH
13311 if (result < 0)
13312 return NULL;
13313 Py_RETURN_NONE;
13314 }
13315
13316
13317 #ifdef MS_WINDOWS
13318 /*[clinic input]
13319 os.get_handle_inheritable -> bool
13320 handle: intptr_t
13321 /
13322
13323 Get the close-on-exe flag of the specified file descriptor.
13324 [clinic start generated code]*/
13325
13326 static int
os_get_handle_inheritable_impl(PyObject * module,intptr_t handle)13327 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
13328 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
13329 {
13330 DWORD flags;
13331
13332 if (!GetHandleInformation((HANDLE)handle, &flags)) {
13333 PyErr_SetFromWindowsErr(0);
13334 return -1;
13335 }
13336
13337 return flags & HANDLE_FLAG_INHERIT;
13338 }
13339
13340
13341 /*[clinic input]
13342 os.set_handle_inheritable
13343 handle: intptr_t
13344 inheritable: bool
13345 /
13346
13347 Set the inheritable flag of the specified handle.
13348 [clinic start generated code]*/
13349
13350 static PyObject *
os_set_handle_inheritable_impl(PyObject * module,intptr_t handle,int inheritable)13351 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
13352 int inheritable)
13353 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
13354 {
13355 DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
13356 if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
13357 PyErr_SetFromWindowsErr(0);
13358 return NULL;
13359 }
13360 Py_RETURN_NONE;
13361 }
13362 #endif /* MS_WINDOWS */
13363
13364 #ifndef MS_WINDOWS
13365 /*[clinic input]
13366 os.get_blocking -> bool
13367 fd: int
13368 /
13369
13370 Get the blocking mode of the file descriptor.
13371
13372 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
13373 [clinic start generated code]*/
13374
13375 static int
os_get_blocking_impl(PyObject * module,int fd)13376 os_get_blocking_impl(PyObject *module, int fd)
13377 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
13378 {
13379 int blocking;
13380
13381 _Py_BEGIN_SUPPRESS_IPH
13382 blocking = _Py_get_blocking(fd);
13383 _Py_END_SUPPRESS_IPH
13384 return blocking;
13385 }
13386
13387 /*[clinic input]
13388 os.set_blocking
13389 fd: int
13390 blocking: bool(accept={int})
13391 /
13392
13393 Set the blocking mode of the specified file descriptor.
13394
13395 Set the O_NONBLOCK flag if blocking is False,
13396 clear the O_NONBLOCK flag otherwise.
13397 [clinic start generated code]*/
13398
13399 static PyObject *
os_set_blocking_impl(PyObject * module,int fd,int blocking)13400 os_set_blocking_impl(PyObject *module, int fd, int blocking)
13401 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
13402 {
13403 int result;
13404
13405 _Py_BEGIN_SUPPRESS_IPH
13406 result = _Py_set_blocking(fd, blocking);
13407 _Py_END_SUPPRESS_IPH
13408 if (result < 0)
13409 return NULL;
13410 Py_RETURN_NONE;
13411 }
13412 #endif /* !MS_WINDOWS */
13413
13414
13415 /*[clinic input]
13416 class os.DirEntry "DirEntry *" "DirEntryType"
13417 [clinic start generated code]*/
13418 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
13419
13420 typedef struct {
13421 PyObject_HEAD
13422 PyObject *name;
13423 PyObject *path;
13424 PyObject *stat;
13425 PyObject *lstat;
13426 #ifdef MS_WINDOWS
13427 struct _Py_stat_struct win32_lstat;
13428 uint64_t win32_file_index;
13429 int got_file_index;
13430 #else /* POSIX */
13431 #ifdef HAVE_DIRENT_D_TYPE
13432 unsigned char d_type;
13433 #endif
13434 ino_t d_ino;
13435 int dir_fd;
13436 #endif
13437 } DirEntry;
13438
13439 static void
DirEntry_dealloc(DirEntry * entry)13440 DirEntry_dealloc(DirEntry *entry)
13441 {
13442 PyTypeObject *tp = Py_TYPE(entry);
13443 Py_XDECREF(entry->name);
13444 Py_XDECREF(entry->path);
13445 Py_XDECREF(entry->stat);
13446 Py_XDECREF(entry->lstat);
13447 freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13448 free_func(entry);
13449 Py_DECREF(tp);
13450 }
13451
13452 /* Forward reference */
13453 static int
13454 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13455 int follow_symlinks, unsigned short mode_bits);
13456
13457 /*[clinic input]
13458 os.DirEntry.is_symlink -> bool
13459 defining_class: defining_class
13460 /
13461
13462 Return True if the entry is a symbolic link; cached per entry.
13463 [clinic start generated code]*/
13464
13465 static int
os_DirEntry_is_symlink_impl(DirEntry * self,PyTypeObject * defining_class)13466 os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
13467 /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
13468 {
13469 #ifdef MS_WINDOWS
13470 return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13471 #elif defined(HAVE_DIRENT_D_TYPE)
13472 /* POSIX */
13473 if (self->d_type != DT_UNKNOWN)
13474 return self->d_type == DT_LNK;
13475 else
13476 return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13477 #else
13478 /* POSIX without d_type */
13479 return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13480 #endif
13481 }
13482
13483 static PyObject *
DirEntry_fetch_stat(PyObject * module,DirEntry * self,int follow_symlinks)13484 DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
13485 {
13486 int result;
13487 STRUCT_STAT st;
13488 PyObject *ub;
13489
13490 #ifdef MS_WINDOWS
13491 if (!PyUnicode_FSDecoder(self->path, &ub))
13492 return NULL;
13493 #if USE_UNICODE_WCHAR_CACHE
13494 _Py_COMP_DIAG_PUSH
13495 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13496 const wchar_t *path = PyUnicode_AsUnicode(ub);
13497 _Py_COMP_DIAG_POP
13498 #else /* USE_UNICODE_WCHAR_CACHE */
13499 wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
13500 Py_DECREF(ub);
13501 #endif /* USE_UNICODE_WCHAR_CACHE */
13502 #else /* POSIX */
13503 if (!PyUnicode_FSConverter(self->path, &ub))
13504 return NULL;
13505 const char *path = PyBytes_AS_STRING(ub);
13506 if (self->dir_fd != DEFAULT_DIR_FD) {
13507 #ifdef HAVE_FSTATAT
13508 if (HAVE_FSTATAT_RUNTIME) {
13509 Py_BEGIN_ALLOW_THREADS
13510 result = fstatat(self->dir_fd, path, &st,
13511 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
13512 Py_END_ALLOW_THREADS
13513 } else
13514
13515 #endif /* HAVE_FSTATAT */
13516 {
13517 Py_DECREF(ub);
13518 PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
13519 return NULL;
13520 }
13521 }
13522 else
13523 #endif
13524 {
13525 Py_BEGIN_ALLOW_THREADS
13526 if (follow_symlinks) {
13527 result = STAT(path, &st);
13528 }
13529 else {
13530 result = LSTAT(path, &st);
13531 }
13532 Py_END_ALLOW_THREADS
13533 }
13534 #if defined(MS_WINDOWS) && !USE_UNICODE_WCHAR_CACHE
13535 PyMem_Free(path);
13536 #else /* USE_UNICODE_WCHAR_CACHE */
13537 Py_DECREF(ub);
13538 #endif /* USE_UNICODE_WCHAR_CACHE */
13539
13540 if (result != 0)
13541 return path_object_error(self->path);
13542
13543 return _pystat_fromstructstat(module, &st);
13544 }
13545
13546 static PyObject *
DirEntry_get_lstat(PyTypeObject * defining_class,DirEntry * self)13547 DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
13548 {
13549 if (!self->lstat) {
13550 PyObject *module = PyType_GetModule(defining_class);
13551 #ifdef MS_WINDOWS
13552 self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
13553 #else /* POSIX */
13554 self->lstat = DirEntry_fetch_stat(module, self, 0);
13555 #endif
13556 }
13557 Py_XINCREF(self->lstat);
13558 return self->lstat;
13559 }
13560
13561 /*[clinic input]
13562 os.DirEntry.stat
13563 defining_class: defining_class
13564 /
13565 *
13566 follow_symlinks: bool = True
13567
13568 Return stat_result object for the entry; cached per entry.
13569 [clinic start generated code]*/
13570
13571 static PyObject *
os_DirEntry_stat_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13572 os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
13573 int follow_symlinks)
13574 /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
13575 {
13576 if (!follow_symlinks) {
13577 return DirEntry_get_lstat(defining_class, self);
13578 }
13579
13580 if (!self->stat) {
13581 int result = os_DirEntry_is_symlink_impl(self, defining_class);
13582 if (result == -1) {
13583 return NULL;
13584 }
13585 if (result) {
13586 PyObject *module = PyType_GetModule(defining_class);
13587 self->stat = DirEntry_fetch_stat(module, self, 1);
13588 }
13589 else {
13590 self->stat = DirEntry_get_lstat(defining_class, self);
13591 }
13592 }
13593
13594 Py_XINCREF(self->stat);
13595 return self->stat;
13596 }
13597
13598 /* Set exception and return -1 on error, 0 for False, 1 for True */
13599 static int
DirEntry_test_mode(PyTypeObject * defining_class,DirEntry * self,int follow_symlinks,unsigned short mode_bits)13600 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13601 int follow_symlinks, unsigned short mode_bits)
13602 {
13603 PyObject *stat = NULL;
13604 PyObject *st_mode = NULL;
13605 long mode;
13606 int result;
13607 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13608 int is_symlink;
13609 int need_stat;
13610 #endif
13611 #ifdef MS_WINDOWS
13612 unsigned long dir_bits;
13613 #endif
13614
13615 #ifdef MS_WINDOWS
13616 is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13617 need_stat = follow_symlinks && is_symlink;
13618 #elif defined(HAVE_DIRENT_D_TYPE)
13619 is_symlink = self->d_type == DT_LNK;
13620 need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
13621 #endif
13622
13623 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13624 if (need_stat) {
13625 #endif
13626 stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
13627 if (!stat) {
13628 if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
13629 /* If file doesn't exist (anymore), then return False
13630 (i.e., say it's not a file/directory) */
13631 PyErr_Clear();
13632 return 0;
13633 }
13634 goto error;
13635 }
13636 _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
13637 st_mode = PyObject_GetAttr(stat, state->st_mode);
13638 if (!st_mode)
13639 goto error;
13640
13641 mode = PyLong_AsLong(st_mode);
13642 if (mode == -1 && PyErr_Occurred())
13643 goto error;
13644 Py_CLEAR(st_mode);
13645 Py_CLEAR(stat);
13646 result = (mode & S_IFMT) == mode_bits;
13647 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13648 }
13649 else if (is_symlink) {
13650 assert(mode_bits != S_IFLNK);
13651 result = 0;
13652 }
13653 else {
13654 assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
13655 #ifdef MS_WINDOWS
13656 dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
13657 if (mode_bits == S_IFDIR)
13658 result = dir_bits != 0;
13659 else
13660 result = dir_bits == 0;
13661 #else /* POSIX */
13662 if (mode_bits == S_IFDIR)
13663 result = self->d_type == DT_DIR;
13664 else
13665 result = self->d_type == DT_REG;
13666 #endif
13667 }
13668 #endif
13669
13670 return result;
13671
13672 error:
13673 Py_XDECREF(st_mode);
13674 Py_XDECREF(stat);
13675 return -1;
13676 }
13677
13678 /*[clinic input]
13679 os.DirEntry.is_dir -> bool
13680 defining_class: defining_class
13681 /
13682 *
13683 follow_symlinks: bool = True
13684
13685 Return True if the entry is a directory; cached per entry.
13686 [clinic start generated code]*/
13687
13688 static int
os_DirEntry_is_dir_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13689 os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
13690 int follow_symlinks)
13691 /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
13692 {
13693 return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
13694 }
13695
13696 /*[clinic input]
13697 os.DirEntry.is_file -> bool
13698 defining_class: defining_class
13699 /
13700 *
13701 follow_symlinks: bool = True
13702
13703 Return True if the entry is a file; cached per entry.
13704 [clinic start generated code]*/
13705
13706 static int
os_DirEntry_is_file_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13707 os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
13708 int follow_symlinks)
13709 /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
13710 {
13711 return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
13712 }
13713
13714 /*[clinic input]
13715 os.DirEntry.inode
13716
13717 Return inode of the entry; cached per entry.
13718 [clinic start generated code]*/
13719
13720 static PyObject *
os_DirEntry_inode_impl(DirEntry * self)13721 os_DirEntry_inode_impl(DirEntry *self)
13722 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
13723 {
13724 #ifdef MS_WINDOWS
13725 if (!self->got_file_index) {
13726 PyObject *unicode;
13727 STRUCT_STAT stat;
13728 int result;
13729
13730 if (!PyUnicode_FSDecoder(self->path, &unicode))
13731 return NULL;
13732 #if USE_UNICODE_WCHAR_CACHE
13733 _Py_COMP_DIAG_PUSH
13734 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13735 const wchar_t *path = PyUnicode_AsUnicode(unicode);
13736 result = LSTAT(path, &stat);
13737 Py_DECREF(unicode);
13738 _Py_COMP_DIAG_POP
13739 #else /* USE_UNICODE_WCHAR_CACHE */
13740 wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
13741 Py_DECREF(unicode);
13742 result = LSTAT(path, &stat);
13743 PyMem_Free(path);
13744 #endif /* USE_UNICODE_WCHAR_CACHE */
13745
13746 if (result != 0)
13747 return path_object_error(self->path);
13748
13749 self->win32_file_index = stat.st_ino;
13750 self->got_file_index = 1;
13751 }
13752 Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->win32_file_index));
13753 return PyLong_FromUnsignedLongLong(self->win32_file_index);
13754 #else /* POSIX */
13755 Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->d_ino));
13756 return PyLong_FromUnsignedLongLong(self->d_ino);
13757 #endif
13758 }
13759
13760 static PyObject *
DirEntry_repr(DirEntry * self)13761 DirEntry_repr(DirEntry *self)
13762 {
13763 return PyUnicode_FromFormat("<DirEntry %R>", self->name);
13764 }
13765
13766 /*[clinic input]
13767 os.DirEntry.__fspath__
13768
13769 Returns the path for the entry.
13770 [clinic start generated code]*/
13771
13772 static PyObject *
os_DirEntry___fspath___impl(DirEntry * self)13773 os_DirEntry___fspath___impl(DirEntry *self)
13774 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
13775 {
13776 Py_INCREF(self->path);
13777 return self->path;
13778 }
13779
13780 static PyMemberDef DirEntry_members[] = {
13781 {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
13782 "the entry's base filename, relative to scandir() \"path\" argument"},
13783 {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
13784 "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
13785 {NULL}
13786 };
13787
13788 #include "clinic/posixmodule.c.h"
13789
13790 static PyMethodDef DirEntry_methods[] = {
13791 OS_DIRENTRY_IS_DIR_METHODDEF
13792 OS_DIRENTRY_IS_FILE_METHODDEF
13793 OS_DIRENTRY_IS_SYMLINK_METHODDEF
13794 OS_DIRENTRY_STAT_METHODDEF
13795 OS_DIRENTRY_INODE_METHODDEF
13796 OS_DIRENTRY___FSPATH___METHODDEF
13797 {"__class_getitem__", Py_GenericAlias,
13798 METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
13799 {NULL}
13800 };
13801
13802 static PyType_Slot DirEntryType_slots[] = {
13803 {Py_tp_dealloc, DirEntry_dealloc},
13804 {Py_tp_repr, DirEntry_repr},
13805 {Py_tp_methods, DirEntry_methods},
13806 {Py_tp_members, DirEntry_members},
13807 {0, 0},
13808 };
13809
13810 static PyType_Spec DirEntryType_spec = {
13811 MODNAME ".DirEntry",
13812 sizeof(DirEntry),
13813 0,
13814 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
13815 DirEntryType_slots
13816 };
13817
13818
13819 #ifdef MS_WINDOWS
13820
13821 static wchar_t *
join_path_filenameW(const wchar_t * path_wide,const wchar_t * filename)13822 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
13823 {
13824 Py_ssize_t path_len;
13825 Py_ssize_t size;
13826 wchar_t *result;
13827 wchar_t ch;
13828
13829 if (!path_wide) { /* Default arg: "." */
13830 path_wide = L".";
13831 path_len = 1;
13832 }
13833 else {
13834 path_len = wcslen(path_wide);
13835 }
13836
13837 /* The +1's are for the path separator and the NUL */
13838 size = path_len + 1 + wcslen(filename) + 1;
13839 result = PyMem_New(wchar_t, size);
13840 if (!result) {
13841 PyErr_NoMemory();
13842 return NULL;
13843 }
13844 wcscpy(result, path_wide);
13845 if (path_len > 0) {
13846 ch = result[path_len - 1];
13847 if (ch != SEP && ch != ALTSEP && ch != L':')
13848 result[path_len++] = SEP;
13849 wcscpy(result + path_len, filename);
13850 }
13851 return result;
13852 }
13853
13854 static PyObject *
DirEntry_from_find_data(PyObject * module,path_t * path,WIN32_FIND_DATAW * dataW)13855 DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
13856 {
13857 DirEntry *entry;
13858 BY_HANDLE_FILE_INFORMATION file_info;
13859 ULONG reparse_tag;
13860 wchar_t *joined_path;
13861
13862 PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13863 entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13864 if (!entry)
13865 return NULL;
13866 entry->name = NULL;
13867 entry->path = NULL;
13868 entry->stat = NULL;
13869 entry->lstat = NULL;
13870 entry->got_file_index = 0;
13871
13872 entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
13873 if (!entry->name)
13874 goto error;
13875 if (path->narrow) {
13876 Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
13877 if (!entry->name)
13878 goto error;
13879 }
13880
13881 joined_path = join_path_filenameW(path->wide, dataW->cFileName);
13882 if (!joined_path)
13883 goto error;
13884
13885 entry->path = PyUnicode_FromWideChar(joined_path, -1);
13886 PyMem_Free(joined_path);
13887 if (!entry->path)
13888 goto error;
13889 if (path->narrow) {
13890 Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
13891 if (!entry->path)
13892 goto error;
13893 }
13894
13895 find_data_to_file_info(dataW, &file_info, &reparse_tag);
13896 _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
13897
13898 return (PyObject *)entry;
13899
13900 error:
13901 Py_DECREF(entry);
13902 return NULL;
13903 }
13904
13905 #else /* POSIX */
13906
13907 static char *
join_path_filename(const char * path_narrow,const char * filename,Py_ssize_t filename_len)13908 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
13909 {
13910 Py_ssize_t path_len;
13911 Py_ssize_t size;
13912 char *result;
13913
13914 if (!path_narrow) { /* Default arg: "." */
13915 path_narrow = ".";
13916 path_len = 1;
13917 }
13918 else {
13919 path_len = strlen(path_narrow);
13920 }
13921
13922 if (filename_len == -1)
13923 filename_len = strlen(filename);
13924
13925 /* The +1's are for the path separator and the NUL */
13926 size = path_len + 1 + filename_len + 1;
13927 result = PyMem_New(char, size);
13928 if (!result) {
13929 PyErr_NoMemory();
13930 return NULL;
13931 }
13932 strcpy(result, path_narrow);
13933 if (path_len > 0 && result[path_len - 1] != '/')
13934 result[path_len++] = '/';
13935 strcpy(result + path_len, filename);
13936 return result;
13937 }
13938
13939 static PyObject *
DirEntry_from_posix_info(PyObject * module,path_t * path,const char * name,Py_ssize_t name_len,ino_t d_ino,unsigned char d_type)13940 DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
13941 Py_ssize_t name_len, ino_t d_ino
13942 #ifdef HAVE_DIRENT_D_TYPE
13943 , unsigned char d_type
13944 #endif
13945 )
13946 {
13947 DirEntry *entry;
13948 char *joined_path;
13949
13950 PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13951 entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13952 if (!entry)
13953 return NULL;
13954 entry->name = NULL;
13955 entry->path = NULL;
13956 entry->stat = NULL;
13957 entry->lstat = NULL;
13958
13959 if (path->fd != -1) {
13960 entry->dir_fd = path->fd;
13961 joined_path = NULL;
13962 }
13963 else {
13964 entry->dir_fd = DEFAULT_DIR_FD;
13965 joined_path = join_path_filename(path->narrow, name, name_len);
13966 if (!joined_path)
13967 goto error;
13968 }
13969
13970 if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
13971 entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
13972 if (joined_path)
13973 entry->path = PyUnicode_DecodeFSDefault(joined_path);
13974 }
13975 else {
13976 entry->name = PyBytes_FromStringAndSize(name, name_len);
13977 if (joined_path)
13978 entry->path = PyBytes_FromString(joined_path);
13979 }
13980 PyMem_Free(joined_path);
13981 if (!entry->name)
13982 goto error;
13983
13984 if (path->fd != -1) {
13985 entry->path = entry->name;
13986 Py_INCREF(entry->path);
13987 }
13988 else if (!entry->path)
13989 goto error;
13990
13991 #ifdef HAVE_DIRENT_D_TYPE
13992 entry->d_type = d_type;
13993 #endif
13994 entry->d_ino = d_ino;
13995
13996 return (PyObject *)entry;
13997
13998 error:
13999 Py_XDECREF(entry);
14000 return NULL;
14001 }
14002
14003 #endif
14004
14005
14006 typedef struct {
14007 PyObject_HEAD
14008 path_t path;
14009 #ifdef MS_WINDOWS
14010 HANDLE handle;
14011 WIN32_FIND_DATAW file_data;
14012 int first_time;
14013 #else /* POSIX */
14014 DIR *dirp;
14015 #endif
14016 #ifdef HAVE_FDOPENDIR
14017 int fd;
14018 #endif
14019 } ScandirIterator;
14020
14021 #ifdef MS_WINDOWS
14022
14023 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14024 ScandirIterator_is_closed(ScandirIterator *iterator)
14025 {
14026 return iterator->handle == INVALID_HANDLE_VALUE;
14027 }
14028
14029 static void
ScandirIterator_closedir(ScandirIterator * iterator)14030 ScandirIterator_closedir(ScandirIterator *iterator)
14031 {
14032 HANDLE handle = iterator->handle;
14033
14034 if (handle == INVALID_HANDLE_VALUE)
14035 return;
14036
14037 iterator->handle = INVALID_HANDLE_VALUE;
14038 Py_BEGIN_ALLOW_THREADS
14039 FindClose(handle);
14040 Py_END_ALLOW_THREADS
14041 }
14042
14043 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14044 ScandirIterator_iternext(ScandirIterator *iterator)
14045 {
14046 WIN32_FIND_DATAW *file_data = &iterator->file_data;
14047 BOOL success;
14048 PyObject *entry;
14049
14050 /* Happens if the iterator is iterated twice, or closed explicitly */
14051 if (iterator->handle == INVALID_HANDLE_VALUE)
14052 return NULL;
14053
14054 while (1) {
14055 if (!iterator->first_time) {
14056 Py_BEGIN_ALLOW_THREADS
14057 success = FindNextFileW(iterator->handle, file_data);
14058 Py_END_ALLOW_THREADS
14059 if (!success) {
14060 /* Error or no more files */
14061 if (GetLastError() != ERROR_NO_MORE_FILES)
14062 path_error(&iterator->path);
14063 break;
14064 }
14065 }
14066 iterator->first_time = 0;
14067
14068 /* Skip over . and .. */
14069 if (wcscmp(file_data->cFileName, L".") != 0 &&
14070 wcscmp(file_data->cFileName, L"..") != 0)
14071 {
14072 PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14073 entry = DirEntry_from_find_data(module, &iterator->path, file_data);
14074 if (!entry)
14075 break;
14076 return entry;
14077 }
14078
14079 /* Loop till we get a non-dot directory or finish iterating */
14080 }
14081
14082 /* Error or no more files */
14083 ScandirIterator_closedir(iterator);
14084 return NULL;
14085 }
14086
14087 #else /* POSIX */
14088
14089 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14090 ScandirIterator_is_closed(ScandirIterator *iterator)
14091 {
14092 return !iterator->dirp;
14093 }
14094
14095 static void
ScandirIterator_closedir(ScandirIterator * iterator)14096 ScandirIterator_closedir(ScandirIterator *iterator)
14097 {
14098 DIR *dirp = iterator->dirp;
14099
14100 if (!dirp)
14101 return;
14102
14103 iterator->dirp = NULL;
14104 Py_BEGIN_ALLOW_THREADS
14105 #ifdef HAVE_FDOPENDIR
14106 if (iterator->path.fd != -1)
14107 rewinddir(dirp);
14108 #endif
14109 closedir(dirp);
14110 Py_END_ALLOW_THREADS
14111 return;
14112 }
14113
14114 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14115 ScandirIterator_iternext(ScandirIterator *iterator)
14116 {
14117 struct dirent *direntp;
14118 Py_ssize_t name_len;
14119 int is_dot;
14120 PyObject *entry;
14121
14122 /* Happens if the iterator is iterated twice, or closed explicitly */
14123 if (!iterator->dirp)
14124 return NULL;
14125
14126 while (1) {
14127 errno = 0;
14128 Py_BEGIN_ALLOW_THREADS
14129 direntp = readdir(iterator->dirp);
14130 Py_END_ALLOW_THREADS
14131
14132 if (!direntp) {
14133 /* Error or no more files */
14134 if (errno != 0)
14135 path_error(&iterator->path);
14136 break;
14137 }
14138
14139 /* Skip over . and .. */
14140 name_len = NAMLEN(direntp);
14141 is_dot = direntp->d_name[0] == '.' &&
14142 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
14143 if (!is_dot) {
14144 PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14145 entry = DirEntry_from_posix_info(module,
14146 &iterator->path, direntp->d_name,
14147 name_len, direntp->d_ino
14148 #ifdef HAVE_DIRENT_D_TYPE
14149 , direntp->d_type
14150 #endif
14151 );
14152 if (!entry)
14153 break;
14154 return entry;
14155 }
14156
14157 /* Loop till we get a non-dot directory or finish iterating */
14158 }
14159
14160 /* Error or no more files */
14161 ScandirIterator_closedir(iterator);
14162 return NULL;
14163 }
14164
14165 #endif
14166
14167 static PyObject *
ScandirIterator_close(ScandirIterator * self,PyObject * args)14168 ScandirIterator_close(ScandirIterator *self, PyObject *args)
14169 {
14170 ScandirIterator_closedir(self);
14171 Py_RETURN_NONE;
14172 }
14173
14174 static PyObject *
ScandirIterator_enter(PyObject * self,PyObject * args)14175 ScandirIterator_enter(PyObject *self, PyObject *args)
14176 {
14177 Py_INCREF(self);
14178 return self;
14179 }
14180
14181 static PyObject *
ScandirIterator_exit(ScandirIterator * self,PyObject * args)14182 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
14183 {
14184 ScandirIterator_closedir(self);
14185 Py_RETURN_NONE;
14186 }
14187
14188 static void
ScandirIterator_finalize(ScandirIterator * iterator)14189 ScandirIterator_finalize(ScandirIterator *iterator)
14190 {
14191 PyObject *error_type, *error_value, *error_traceback;
14192
14193 /* Save the current exception, if any. */
14194 PyErr_Fetch(&error_type, &error_value, &error_traceback);
14195
14196 if (!ScandirIterator_is_closed(iterator)) {
14197 ScandirIterator_closedir(iterator);
14198
14199 if (PyErr_ResourceWarning((PyObject *)iterator, 1,
14200 "unclosed scandir iterator %R", iterator)) {
14201 /* Spurious errors can appear at shutdown */
14202 if (PyErr_ExceptionMatches(PyExc_Warning)) {
14203 PyErr_WriteUnraisable((PyObject *) iterator);
14204 }
14205 }
14206 }
14207
14208 path_cleanup(&iterator->path);
14209
14210 /* Restore the saved exception. */
14211 PyErr_Restore(error_type, error_value, error_traceback);
14212 }
14213
14214 static void
ScandirIterator_dealloc(ScandirIterator * iterator)14215 ScandirIterator_dealloc(ScandirIterator *iterator)
14216 {
14217 PyTypeObject *tp = Py_TYPE(iterator);
14218 if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
14219 return;
14220
14221 freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
14222 free_func(iterator);
14223 Py_DECREF(tp);
14224 }
14225
14226 static PyMethodDef ScandirIterator_methods[] = {
14227 {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
14228 {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
14229 {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
14230 {NULL}
14231 };
14232
14233 static PyType_Slot ScandirIteratorType_slots[] = {
14234 {Py_tp_dealloc, ScandirIterator_dealloc},
14235 {Py_tp_finalize, ScandirIterator_finalize},
14236 {Py_tp_iter, PyObject_SelfIter},
14237 {Py_tp_iternext, ScandirIterator_iternext},
14238 {Py_tp_methods, ScandirIterator_methods},
14239 {0, 0},
14240 };
14241
14242 static PyType_Spec ScandirIteratorType_spec = {
14243 MODNAME ".ScandirIterator",
14244 sizeof(ScandirIterator),
14245 0,
14246 // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
14247 // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
14248 (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
14249 | Py_TPFLAGS_DISALLOW_INSTANTIATION),
14250 ScandirIteratorType_slots
14251 };
14252
14253 /*[clinic input]
14254 os.scandir
14255
14256 path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
14257
14258 Return an iterator of DirEntry objects for given path.
14259
14260 path can be specified as either str, bytes, or a path-like object. If path
14261 is bytes, the names of yielded DirEntry objects will also be bytes; in
14262 all other circumstances they will be str.
14263
14264 If path is None, uses the path='.'.
14265 [clinic start generated code]*/
14266
14267 static PyObject *
os_scandir_impl(PyObject * module,path_t * path)14268 os_scandir_impl(PyObject *module, path_t *path)
14269 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
14270 {
14271 ScandirIterator *iterator;
14272 #ifdef MS_WINDOWS
14273 wchar_t *path_strW;
14274 #else
14275 const char *path_str;
14276 #ifdef HAVE_FDOPENDIR
14277 int fd = -1;
14278 #endif
14279 #endif
14280
14281 if (PySys_Audit("os.scandir", "O",
14282 path->object ? path->object : Py_None) < 0) {
14283 return NULL;
14284 }
14285
14286 PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
14287 iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
14288 if (!iterator)
14289 return NULL;
14290
14291 #ifdef MS_WINDOWS
14292 iterator->handle = INVALID_HANDLE_VALUE;
14293 #else
14294 iterator->dirp = NULL;
14295 #endif
14296
14297 /* Move the ownership to iterator->path */
14298 memcpy(&iterator->path, path, sizeof(path_t));
14299 memset(path, 0, sizeof(path_t));
14300
14301 #ifdef MS_WINDOWS
14302 iterator->first_time = 1;
14303
14304 path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
14305 if (!path_strW)
14306 goto error;
14307
14308 Py_BEGIN_ALLOW_THREADS
14309 iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
14310 Py_END_ALLOW_THREADS
14311
14312 PyMem_Free(path_strW);
14313
14314 if (iterator->handle == INVALID_HANDLE_VALUE) {
14315 path_error(&iterator->path);
14316 goto error;
14317 }
14318 #else /* POSIX */
14319 errno = 0;
14320 #ifdef HAVE_FDOPENDIR
14321 if (iterator->path.fd != -1) {
14322 if (HAVE_FDOPENDIR_RUNTIME) {
14323 /* closedir() closes the FD, so we duplicate it */
14324 fd = _Py_dup(iterator->path.fd);
14325 if (fd == -1)
14326 goto error;
14327
14328 Py_BEGIN_ALLOW_THREADS
14329 iterator->dirp = fdopendir(fd);
14330 Py_END_ALLOW_THREADS
14331 } else {
14332 PyErr_SetString(PyExc_TypeError,
14333 "scandir: path should be string, bytes, os.PathLike or None, not int");
14334 return NULL;
14335 }
14336 }
14337 else
14338 #endif
14339 {
14340 if (iterator->path.narrow)
14341 path_str = iterator->path.narrow;
14342 else
14343 path_str = ".";
14344
14345 Py_BEGIN_ALLOW_THREADS
14346 iterator->dirp = opendir(path_str);
14347 Py_END_ALLOW_THREADS
14348 }
14349
14350 if (!iterator->dirp) {
14351 path_error(&iterator->path);
14352 #ifdef HAVE_FDOPENDIR
14353 if (fd != -1) {
14354 Py_BEGIN_ALLOW_THREADS
14355 close(fd);
14356 Py_END_ALLOW_THREADS
14357 }
14358 #endif
14359 goto error;
14360 }
14361 #endif
14362
14363 return (PyObject *)iterator;
14364
14365 error:
14366 Py_DECREF(iterator);
14367 return NULL;
14368 }
14369
14370 /*
14371 Return the file system path representation of the object.
14372
14373 If the object is str or bytes, then allow it to pass through with
14374 an incremented refcount. If the object defines __fspath__(), then
14375 return the result of that method. All other types raise a TypeError.
14376 */
14377 PyObject *
PyOS_FSPath(PyObject * path)14378 PyOS_FSPath(PyObject *path)
14379 {
14380 /* For error message reasons, this function is manually inlined in
14381 path_converter(). */
14382 PyObject *func = NULL;
14383 PyObject *path_repr = NULL;
14384
14385 if (PyUnicode_Check(path) || PyBytes_Check(path)) {
14386 Py_INCREF(path);
14387 return path;
14388 }
14389
14390 func = _PyObject_LookupSpecial(path, &PyId___fspath__);
14391 if (NULL == func) {
14392 return PyErr_Format(PyExc_TypeError,
14393 "expected str, bytes or os.PathLike object, "
14394 "not %.200s",
14395 _PyType_Name(Py_TYPE(path)));
14396 }
14397
14398 path_repr = _PyObject_CallNoArgs(func);
14399 Py_DECREF(func);
14400 if (NULL == path_repr) {
14401 return NULL;
14402 }
14403
14404 if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
14405 PyErr_Format(PyExc_TypeError,
14406 "expected %.200s.__fspath__() to return str or bytes, "
14407 "not %.200s", _PyType_Name(Py_TYPE(path)),
14408 _PyType_Name(Py_TYPE(path_repr)));
14409 Py_DECREF(path_repr);
14410 return NULL;
14411 }
14412
14413 return path_repr;
14414 }
14415
14416 /*[clinic input]
14417 os.fspath
14418
14419 path: object
14420
14421 Return the file system path representation of the object.
14422
14423 If the object is str or bytes, then allow it to pass through as-is. If the
14424 object defines __fspath__(), then return the result of that method. All other
14425 types raise a TypeError.
14426 [clinic start generated code]*/
14427
14428 static PyObject *
os_fspath_impl(PyObject * module,PyObject * path)14429 os_fspath_impl(PyObject *module, PyObject *path)
14430 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
14431 {
14432 return PyOS_FSPath(path);
14433 }
14434
14435 #ifdef HAVE_GETRANDOM_SYSCALL
14436 /*[clinic input]
14437 os.getrandom
14438
14439 size: Py_ssize_t
14440 flags: int=0
14441
14442 Obtain a series of random bytes.
14443 [clinic start generated code]*/
14444
14445 static PyObject *
os_getrandom_impl(PyObject * module,Py_ssize_t size,int flags)14446 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
14447 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
14448 {
14449 PyObject *bytes;
14450 Py_ssize_t n;
14451
14452 if (size < 0) {
14453 errno = EINVAL;
14454 return posix_error();
14455 }
14456
14457 bytes = PyBytes_FromStringAndSize(NULL, size);
14458 if (bytes == NULL) {
14459 PyErr_NoMemory();
14460 return NULL;
14461 }
14462
14463 while (1) {
14464 n = syscall(SYS_getrandom,
14465 PyBytes_AS_STRING(bytes),
14466 PyBytes_GET_SIZE(bytes),
14467 flags);
14468 if (n < 0 && errno == EINTR) {
14469 if (PyErr_CheckSignals() < 0) {
14470 goto error;
14471 }
14472
14473 /* getrandom() was interrupted by a signal: retry */
14474 continue;
14475 }
14476 break;
14477 }
14478
14479 if (n < 0) {
14480 PyErr_SetFromErrno(PyExc_OSError);
14481 goto error;
14482 }
14483
14484 if (n != size) {
14485 _PyBytes_Resize(&bytes, n);
14486 }
14487
14488 return bytes;
14489
14490 error:
14491 Py_DECREF(bytes);
14492 return NULL;
14493 }
14494 #endif /* HAVE_GETRANDOM_SYSCALL */
14495
14496 #ifdef MS_WINDOWS
14497 /* bpo-36085: Helper functions for managing DLL search directories
14498 * on win32
14499 */
14500
14501 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
14502 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
14503
14504 /*[clinic input]
14505 os._add_dll_directory
14506
14507 path: path_t
14508
14509 Add a path to the DLL search path.
14510
14511 This search path is used when resolving dependencies for imported
14512 extension modules (the module itself is resolved through sys.path),
14513 and also by ctypes.
14514
14515 Returns an opaque value that may be passed to os.remove_dll_directory
14516 to remove this directory from the search path.
14517 [clinic start generated code]*/
14518
14519 static PyObject *
os__add_dll_directory_impl(PyObject * module,path_t * path)14520 os__add_dll_directory_impl(PyObject *module, path_t *path)
14521 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
14522 {
14523 HMODULE hKernel32;
14524 PAddDllDirectory AddDllDirectory;
14525 DLL_DIRECTORY_COOKIE cookie = 0;
14526 DWORD err = 0;
14527
14528 if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
14529 return NULL;
14530 }
14531
14532 /* For Windows 7, we have to load this. As this will be a fairly
14533 infrequent operation, just do it each time. Kernel32 is always
14534 loaded. */
14535 Py_BEGIN_ALLOW_THREADS
14536 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14537 !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
14538 hKernel32, "AddDllDirectory")) ||
14539 !(cookie = (*AddDllDirectory)(path->wide))) {
14540 err = GetLastError();
14541 }
14542 Py_END_ALLOW_THREADS
14543
14544 if (err) {
14545 return win32_error_object_err("add_dll_directory",
14546 path->object, err);
14547 }
14548
14549 return PyCapsule_New(cookie, "DLL directory cookie", NULL);
14550 }
14551
14552 /*[clinic input]
14553 os._remove_dll_directory
14554
14555 cookie: object
14556
14557 Removes a path from the DLL search path.
14558
14559 The parameter is an opaque value that was returned from
14560 os.add_dll_directory. You can only remove directories that you added
14561 yourself.
14562 [clinic start generated code]*/
14563
14564 static PyObject *
os__remove_dll_directory_impl(PyObject * module,PyObject * cookie)14565 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
14566 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
14567 {
14568 HMODULE hKernel32;
14569 PRemoveDllDirectory RemoveDllDirectory;
14570 DLL_DIRECTORY_COOKIE cookieValue;
14571 DWORD err = 0;
14572
14573 if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
14574 PyErr_SetString(PyExc_TypeError,
14575 "Provided cookie was not returned from os.add_dll_directory");
14576 return NULL;
14577 }
14578
14579 cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
14580 cookie, "DLL directory cookie");
14581
14582 /* For Windows 7, we have to load this. As this will be a fairly
14583 infrequent operation, just do it each time. Kernel32 is always
14584 loaded. */
14585 Py_BEGIN_ALLOW_THREADS
14586 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14587 !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
14588 hKernel32, "RemoveDllDirectory")) ||
14589 !(*RemoveDllDirectory)(cookieValue)) {
14590 err = GetLastError();
14591 }
14592 Py_END_ALLOW_THREADS
14593
14594 if (err) {
14595 return win32_error_object_err("remove_dll_directory",
14596 NULL, err);
14597 }
14598
14599 if (PyCapsule_SetName(cookie, NULL)) {
14600 return NULL;
14601 }
14602
14603 Py_RETURN_NONE;
14604 }
14605
14606 #endif
14607
14608
14609 /* Only check if WIFEXITED is available: expect that it comes
14610 with WEXITSTATUS, WIFSIGNALED, etc.
14611
14612 os.waitstatus_to_exitcode() is implemented in C and not in Python, so
14613 subprocess can safely call it during late Python finalization without
14614 risking that used os attributes were set to None by finalize_modules(). */
14615 #if defined(WIFEXITED) || defined(MS_WINDOWS)
14616 /*[clinic input]
14617 os.waitstatus_to_exitcode
14618
14619 status as status_obj: object
14620
14621 Convert a wait status to an exit code.
14622
14623 On Unix:
14624
14625 * If WIFEXITED(status) is true, return WEXITSTATUS(status).
14626 * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
14627 * Otherwise, raise a ValueError.
14628
14629 On Windows, return status shifted right by 8 bits.
14630
14631 On Unix, if the process is being traced or if waitpid() was called with
14632 WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
14633 This function must not be called if WIFSTOPPED(status) is true.
14634 [clinic start generated code]*/
14635
14636 static PyObject *
os_waitstatus_to_exitcode_impl(PyObject * module,PyObject * status_obj)14637 os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
14638 /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
14639 {
14640 #ifndef MS_WINDOWS
14641 int status = _PyLong_AsInt(status_obj);
14642 if (status == -1 && PyErr_Occurred()) {
14643 return NULL;
14644 }
14645
14646 WAIT_TYPE wait_status;
14647 WAIT_STATUS_INT(wait_status) = status;
14648 int exitcode;
14649 if (WIFEXITED(wait_status)) {
14650 exitcode = WEXITSTATUS(wait_status);
14651 /* Sanity check to provide warranty on the function behavior.
14652 It should not occur in practice */
14653 if (exitcode < 0) {
14654 PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
14655 return NULL;
14656 }
14657 }
14658 else if (WIFSIGNALED(wait_status)) {
14659 int signum = WTERMSIG(wait_status);
14660 /* Sanity check to provide warranty on the function behavior.
14661 It should not occurs in practice */
14662 if (signum <= 0) {
14663 PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
14664 return NULL;
14665 }
14666 exitcode = -signum;
14667 } else if (WIFSTOPPED(wait_status)) {
14668 /* Status only received if the process is being traced
14669 or if waitpid() was called with WUNTRACED option. */
14670 int signum = WSTOPSIG(wait_status);
14671 PyErr_Format(PyExc_ValueError,
14672 "process stopped by delivery of signal %i",
14673 signum);
14674 return NULL;
14675 }
14676 else {
14677 PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
14678 return NULL;
14679 }
14680 return PyLong_FromLong(exitcode);
14681 #else
14682 /* Windows implementation: see os.waitpid() implementation
14683 which uses _cwait(). */
14684 unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
14685 if (status == (unsigned long long)-1 && PyErr_Occurred()) {
14686 return NULL;
14687 }
14688
14689 unsigned long long exitcode = (status >> 8);
14690 /* ExitProcess() accepts an UINT type:
14691 reject exit code which doesn't fit in an UINT */
14692 if (exitcode > UINT_MAX) {
14693 PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
14694 return NULL;
14695 }
14696 return PyLong_FromUnsignedLong((unsigned long)exitcode);
14697 #endif
14698 }
14699 #endif
14700
14701
14702 static PyMethodDef posix_methods[] = {
14703
14704 OS_STAT_METHODDEF
14705 OS_ACCESS_METHODDEF
14706 OS_TTYNAME_METHODDEF
14707 OS_CHDIR_METHODDEF
14708 OS_CHFLAGS_METHODDEF
14709 OS_CHMOD_METHODDEF
14710 OS_FCHMOD_METHODDEF
14711 OS_LCHMOD_METHODDEF
14712 OS_CHOWN_METHODDEF
14713 OS_FCHOWN_METHODDEF
14714 OS_LCHOWN_METHODDEF
14715 OS_LCHFLAGS_METHODDEF
14716 OS_CHROOT_METHODDEF
14717 OS_CTERMID_METHODDEF
14718 OS_GETCWD_METHODDEF
14719 OS_GETCWDB_METHODDEF
14720 OS_LINK_METHODDEF
14721 OS_LISTDIR_METHODDEF
14722 OS_LSTAT_METHODDEF
14723 OS_MKDIR_METHODDEF
14724 OS_NICE_METHODDEF
14725 OS_GETPRIORITY_METHODDEF
14726 OS_SETPRIORITY_METHODDEF
14727 OS_POSIX_SPAWN_METHODDEF
14728 OS_POSIX_SPAWNP_METHODDEF
14729 OS_READLINK_METHODDEF
14730 OS_COPY_FILE_RANGE_METHODDEF
14731 OS_SPLICE_METHODDEF
14732 OS_RENAME_METHODDEF
14733 OS_REPLACE_METHODDEF
14734 OS_RMDIR_METHODDEF
14735 OS_SYMLINK_METHODDEF
14736 OS_SYSTEM_METHODDEF
14737 OS_UMASK_METHODDEF
14738 OS_UNAME_METHODDEF
14739 OS_UNLINK_METHODDEF
14740 OS_REMOVE_METHODDEF
14741 OS_UTIME_METHODDEF
14742 OS_TIMES_METHODDEF
14743 OS__EXIT_METHODDEF
14744 OS__FCOPYFILE_METHODDEF
14745 OS_EXECV_METHODDEF
14746 OS_EXECVE_METHODDEF
14747 OS_SPAWNV_METHODDEF
14748 OS_SPAWNVE_METHODDEF
14749 OS_FORK1_METHODDEF
14750 OS_FORK_METHODDEF
14751 OS_REGISTER_AT_FORK_METHODDEF
14752 OS_SCHED_GET_PRIORITY_MAX_METHODDEF
14753 OS_SCHED_GET_PRIORITY_MIN_METHODDEF
14754 OS_SCHED_GETPARAM_METHODDEF
14755 OS_SCHED_GETSCHEDULER_METHODDEF
14756 OS_SCHED_RR_GET_INTERVAL_METHODDEF
14757 OS_SCHED_SETPARAM_METHODDEF
14758 OS_SCHED_SETSCHEDULER_METHODDEF
14759 OS_SCHED_YIELD_METHODDEF
14760 OS_SCHED_SETAFFINITY_METHODDEF
14761 OS_SCHED_GETAFFINITY_METHODDEF
14762 OS_OPENPTY_METHODDEF
14763 OS_FORKPTY_METHODDEF
14764 OS_GETEGID_METHODDEF
14765 OS_GETEUID_METHODDEF
14766 OS_GETGID_METHODDEF
14767 OS_GETGROUPLIST_METHODDEF
14768 OS_GETGROUPS_METHODDEF
14769 OS_GETPID_METHODDEF
14770 OS_GETPGRP_METHODDEF
14771 OS_GETPPID_METHODDEF
14772 OS_GETUID_METHODDEF
14773 OS_GETLOGIN_METHODDEF
14774 OS_KILL_METHODDEF
14775 OS_KILLPG_METHODDEF
14776 OS_PLOCK_METHODDEF
14777 OS_STARTFILE_METHODDEF
14778 OS_SETUID_METHODDEF
14779 OS_SETEUID_METHODDEF
14780 OS_SETREUID_METHODDEF
14781 OS_SETGID_METHODDEF
14782 OS_SETEGID_METHODDEF
14783 OS_SETREGID_METHODDEF
14784 OS_SETGROUPS_METHODDEF
14785 OS_INITGROUPS_METHODDEF
14786 OS_GETPGID_METHODDEF
14787 OS_SETPGRP_METHODDEF
14788 OS_WAIT_METHODDEF
14789 OS_WAIT3_METHODDEF
14790 OS_WAIT4_METHODDEF
14791 OS_WAITID_METHODDEF
14792 OS_WAITPID_METHODDEF
14793 OS_PIDFD_OPEN_METHODDEF
14794 OS_GETSID_METHODDEF
14795 OS_SETSID_METHODDEF
14796 OS_SETPGID_METHODDEF
14797 OS_TCGETPGRP_METHODDEF
14798 OS_TCSETPGRP_METHODDEF
14799 OS_OPEN_METHODDEF
14800 OS_CLOSE_METHODDEF
14801 OS_CLOSERANGE_METHODDEF
14802 OS_DEVICE_ENCODING_METHODDEF
14803 OS_DUP_METHODDEF
14804 OS_DUP2_METHODDEF
14805 OS_LOCKF_METHODDEF
14806 OS_LSEEK_METHODDEF
14807 OS_READ_METHODDEF
14808 OS_READV_METHODDEF
14809 OS_PREAD_METHODDEF
14810 OS_PREADV_METHODDEF
14811 OS_WRITE_METHODDEF
14812 OS_WRITEV_METHODDEF
14813 OS_PWRITE_METHODDEF
14814 OS_PWRITEV_METHODDEF
14815 OS_SENDFILE_METHODDEF
14816 OS_FSTAT_METHODDEF
14817 OS_ISATTY_METHODDEF
14818 OS_PIPE_METHODDEF
14819 OS_PIPE2_METHODDEF
14820 OS_MKFIFO_METHODDEF
14821 OS_MKNOD_METHODDEF
14822 OS_MAJOR_METHODDEF
14823 OS_MINOR_METHODDEF
14824 OS_MAKEDEV_METHODDEF
14825 OS_FTRUNCATE_METHODDEF
14826 OS_TRUNCATE_METHODDEF
14827 OS_POSIX_FALLOCATE_METHODDEF
14828 OS_POSIX_FADVISE_METHODDEF
14829 OS_PUTENV_METHODDEF
14830 OS_UNSETENV_METHODDEF
14831 OS_STRERROR_METHODDEF
14832 OS_FCHDIR_METHODDEF
14833 OS_FSYNC_METHODDEF
14834 OS_SYNC_METHODDEF
14835 OS_FDATASYNC_METHODDEF
14836 OS_WCOREDUMP_METHODDEF
14837 OS_WIFCONTINUED_METHODDEF
14838 OS_WIFSTOPPED_METHODDEF
14839 OS_WIFSIGNALED_METHODDEF
14840 OS_WIFEXITED_METHODDEF
14841 OS_WEXITSTATUS_METHODDEF
14842 OS_WTERMSIG_METHODDEF
14843 OS_WSTOPSIG_METHODDEF
14844 OS_FSTATVFS_METHODDEF
14845 OS_STATVFS_METHODDEF
14846 OS_CONFSTR_METHODDEF
14847 OS_SYSCONF_METHODDEF
14848 OS_FPATHCONF_METHODDEF
14849 OS_PATHCONF_METHODDEF
14850 OS_ABORT_METHODDEF
14851 OS__GETFULLPATHNAME_METHODDEF
14852 OS__GETDISKUSAGE_METHODDEF
14853 OS__GETFINALPATHNAME_METHODDEF
14854 OS__GETVOLUMEPATHNAME_METHODDEF
14855 OS__PATH_SPLITROOT_METHODDEF
14856 OS__PATH_NORMPATH_METHODDEF
14857 OS_GETLOADAVG_METHODDEF
14858 OS_URANDOM_METHODDEF
14859 OS_SETRESUID_METHODDEF
14860 OS_SETRESGID_METHODDEF
14861 OS_GETRESUID_METHODDEF
14862 OS_GETRESGID_METHODDEF
14863
14864 OS_GETXATTR_METHODDEF
14865 OS_SETXATTR_METHODDEF
14866 OS_REMOVEXATTR_METHODDEF
14867 OS_LISTXATTR_METHODDEF
14868
14869 OS_GET_TERMINAL_SIZE_METHODDEF
14870 OS_CPU_COUNT_METHODDEF
14871 OS_GET_INHERITABLE_METHODDEF
14872 OS_SET_INHERITABLE_METHODDEF
14873 OS_GET_HANDLE_INHERITABLE_METHODDEF
14874 OS_SET_HANDLE_INHERITABLE_METHODDEF
14875 OS_GET_BLOCKING_METHODDEF
14876 OS_SET_BLOCKING_METHODDEF
14877 OS_SCANDIR_METHODDEF
14878 OS_FSPATH_METHODDEF
14879 OS_GETRANDOM_METHODDEF
14880 OS_MEMFD_CREATE_METHODDEF
14881 OS_EVENTFD_METHODDEF
14882 OS_EVENTFD_READ_METHODDEF
14883 OS_EVENTFD_WRITE_METHODDEF
14884 OS__ADD_DLL_DIRECTORY_METHODDEF
14885 OS__REMOVE_DLL_DIRECTORY_METHODDEF
14886 OS_WAITSTATUS_TO_EXITCODE_METHODDEF
14887 {NULL, NULL} /* Sentinel */
14888 };
14889
14890 static int
all_ins(PyObject * m)14891 all_ins(PyObject *m)
14892 {
14893 #ifdef F_OK
14894 if (PyModule_AddIntMacro(m, F_OK)) return -1;
14895 #endif
14896 #ifdef R_OK
14897 if (PyModule_AddIntMacro(m, R_OK)) return -1;
14898 #endif
14899 #ifdef W_OK
14900 if (PyModule_AddIntMacro(m, W_OK)) return -1;
14901 #endif
14902 #ifdef X_OK
14903 if (PyModule_AddIntMacro(m, X_OK)) return -1;
14904 #endif
14905 #ifdef NGROUPS_MAX
14906 if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
14907 #endif
14908 #ifdef TMP_MAX
14909 if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
14910 #endif
14911 #ifdef WCONTINUED
14912 if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
14913 #endif
14914 #ifdef WNOHANG
14915 if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
14916 #endif
14917 #ifdef WUNTRACED
14918 if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
14919 #endif
14920 #ifdef O_RDONLY
14921 if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
14922 #endif
14923 #ifdef O_WRONLY
14924 if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
14925 #endif
14926 #ifdef O_RDWR
14927 if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
14928 #endif
14929 #ifdef O_NDELAY
14930 if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
14931 #endif
14932 #ifdef O_NONBLOCK
14933 if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
14934 #endif
14935 #ifdef O_APPEND
14936 if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
14937 #endif
14938 #ifdef O_DSYNC
14939 if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
14940 #endif
14941 #ifdef O_RSYNC
14942 if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
14943 #endif
14944 #ifdef O_SYNC
14945 if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
14946 #endif
14947 #ifdef O_NOCTTY
14948 if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
14949 #endif
14950 #ifdef O_CREAT
14951 if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
14952 #endif
14953 #ifdef O_EXCL
14954 if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
14955 #endif
14956 #ifdef O_TRUNC
14957 if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
14958 #endif
14959 #ifdef O_BINARY
14960 if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
14961 #endif
14962 #ifdef O_TEXT
14963 if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
14964 #endif
14965 #ifdef O_XATTR
14966 if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
14967 #endif
14968 #ifdef O_LARGEFILE
14969 if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
14970 #endif
14971 #ifndef __GNU__
14972 #ifdef O_SHLOCK
14973 if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
14974 #endif
14975 #ifdef O_EXLOCK
14976 if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
14977 #endif
14978 #endif
14979 #ifdef O_EXEC
14980 if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
14981 #endif
14982 #ifdef O_SEARCH
14983 if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
14984 #endif
14985 #ifdef O_PATH
14986 if (PyModule_AddIntMacro(m, O_PATH)) return -1;
14987 #endif
14988 #ifdef O_TTY_INIT
14989 if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
14990 #endif
14991 #ifdef O_TMPFILE
14992 if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
14993 #endif
14994 #ifdef PRIO_PROCESS
14995 if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
14996 #endif
14997 #ifdef PRIO_PGRP
14998 if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
14999 #endif
15000 #ifdef PRIO_USER
15001 if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
15002 #endif
15003 #ifdef O_CLOEXEC
15004 if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
15005 #endif
15006 #ifdef O_ACCMODE
15007 if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
15008 #endif
15009 #ifdef O_EVTONLY
15010 if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
15011 #endif
15012 #ifdef O_FSYNC
15013 if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
15014 #endif
15015 #ifdef O_SYMLINK
15016 if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
15017 #endif
15018
15019 #ifdef SEEK_HOLE
15020 if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
15021 #endif
15022 #ifdef SEEK_DATA
15023 if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
15024 #endif
15025
15026 /* MS Windows */
15027 #ifdef O_NOINHERIT
15028 /* Don't inherit in child processes. */
15029 if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
15030 #endif
15031 #ifdef _O_SHORT_LIVED
15032 /* Optimize for short life (keep in memory). */
15033 /* MS forgot to define this one with a non-underscore form too. */
15034 if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
15035 #endif
15036 #ifdef O_TEMPORARY
15037 /* Automatically delete when last handle is closed. */
15038 if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
15039 #endif
15040 #ifdef O_RANDOM
15041 /* Optimize for random access. */
15042 if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
15043 #endif
15044 #ifdef O_SEQUENTIAL
15045 /* Optimize for sequential access. */
15046 if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
15047 #endif
15048
15049 /* GNU extensions. */
15050 #ifdef O_ASYNC
15051 /* Send a SIGIO signal whenever input or output
15052 becomes available on file descriptor */
15053 if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
15054 #endif
15055 #ifdef O_DIRECT
15056 /* Direct disk access. */
15057 if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
15058 #endif
15059 #ifdef O_DIRECTORY
15060 /* Must be a directory. */
15061 if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
15062 #endif
15063 #ifdef O_NOFOLLOW
15064 /* Do not follow links. */
15065 if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
15066 #endif
15067 #ifdef O_NOFOLLOW_ANY
15068 if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
15069 #endif
15070 #ifdef O_NOLINKS
15071 /* Fails if link count of the named file is greater than 1 */
15072 if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
15073 #endif
15074 #ifdef O_NOATIME
15075 /* Do not update the access time. */
15076 if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
15077 #endif
15078
15079 /* These come from sysexits.h */
15080 #ifdef EX_OK
15081 if (PyModule_AddIntMacro(m, EX_OK)) return -1;
15082 #endif /* EX_OK */
15083 #ifdef EX_USAGE
15084 if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
15085 #endif /* EX_USAGE */
15086 #ifdef EX_DATAERR
15087 if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
15088 #endif /* EX_DATAERR */
15089 #ifdef EX_NOINPUT
15090 if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
15091 #endif /* EX_NOINPUT */
15092 #ifdef EX_NOUSER
15093 if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
15094 #endif /* EX_NOUSER */
15095 #ifdef EX_NOHOST
15096 if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
15097 #endif /* EX_NOHOST */
15098 #ifdef EX_UNAVAILABLE
15099 if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
15100 #endif /* EX_UNAVAILABLE */
15101 #ifdef EX_SOFTWARE
15102 if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
15103 #endif /* EX_SOFTWARE */
15104 #ifdef EX_OSERR
15105 if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
15106 #endif /* EX_OSERR */
15107 #ifdef EX_OSFILE
15108 if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
15109 #endif /* EX_OSFILE */
15110 #ifdef EX_CANTCREAT
15111 if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
15112 #endif /* EX_CANTCREAT */
15113 #ifdef EX_IOERR
15114 if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
15115 #endif /* EX_IOERR */
15116 #ifdef EX_TEMPFAIL
15117 if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
15118 #endif /* EX_TEMPFAIL */
15119 #ifdef EX_PROTOCOL
15120 if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
15121 #endif /* EX_PROTOCOL */
15122 #ifdef EX_NOPERM
15123 if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
15124 #endif /* EX_NOPERM */
15125 #ifdef EX_CONFIG
15126 if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
15127 #endif /* EX_CONFIG */
15128 #ifdef EX_NOTFOUND
15129 if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
15130 #endif /* EX_NOTFOUND */
15131
15132 /* statvfs */
15133 #ifdef ST_RDONLY
15134 if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
15135 #endif /* ST_RDONLY */
15136 #ifdef ST_NOSUID
15137 if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
15138 #endif /* ST_NOSUID */
15139
15140 /* GNU extensions */
15141 #ifdef ST_NODEV
15142 if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
15143 #endif /* ST_NODEV */
15144 #ifdef ST_NOEXEC
15145 if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
15146 #endif /* ST_NOEXEC */
15147 #ifdef ST_SYNCHRONOUS
15148 if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
15149 #endif /* ST_SYNCHRONOUS */
15150 #ifdef ST_MANDLOCK
15151 if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
15152 #endif /* ST_MANDLOCK */
15153 #ifdef ST_WRITE
15154 if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
15155 #endif /* ST_WRITE */
15156 #ifdef ST_APPEND
15157 if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
15158 #endif /* ST_APPEND */
15159 #ifdef ST_NOATIME
15160 if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
15161 #endif /* ST_NOATIME */
15162 #ifdef ST_NODIRATIME
15163 if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
15164 #endif /* ST_NODIRATIME */
15165 #ifdef ST_RELATIME
15166 if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
15167 #endif /* ST_RELATIME */
15168
15169 /* FreeBSD sendfile() constants */
15170 #ifdef SF_NODISKIO
15171 if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
15172 #endif
15173 #ifdef SF_MNOWAIT
15174 if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
15175 #endif
15176 #ifdef SF_SYNC
15177 if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
15178 #endif
15179
15180 /* constants for posix_fadvise */
15181 #ifdef POSIX_FADV_NORMAL
15182 if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
15183 #endif
15184 #ifdef POSIX_FADV_SEQUENTIAL
15185 if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
15186 #endif
15187 #ifdef POSIX_FADV_RANDOM
15188 if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
15189 #endif
15190 #ifdef POSIX_FADV_NOREUSE
15191 if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
15192 #endif
15193 #ifdef POSIX_FADV_WILLNEED
15194 if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
15195 #endif
15196 #ifdef POSIX_FADV_DONTNEED
15197 if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
15198 #endif
15199
15200 /* constants for waitid */
15201 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
15202 if (PyModule_AddIntMacro(m, P_PID)) return -1;
15203 if (PyModule_AddIntMacro(m, P_PGID)) return -1;
15204 if (PyModule_AddIntMacro(m, P_ALL)) return -1;
15205 #ifdef P_PIDFD
15206 if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
15207 #endif
15208 #endif
15209 #ifdef WEXITED
15210 if (PyModule_AddIntMacro(m, WEXITED)) return -1;
15211 #endif
15212 #ifdef WNOWAIT
15213 if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
15214 #endif
15215 #ifdef WSTOPPED
15216 if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
15217 #endif
15218 #ifdef CLD_EXITED
15219 if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
15220 #endif
15221 #ifdef CLD_KILLED
15222 if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
15223 #endif
15224 #ifdef CLD_DUMPED
15225 if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
15226 #endif
15227 #ifdef CLD_TRAPPED
15228 if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
15229 #endif
15230 #ifdef CLD_STOPPED
15231 if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
15232 #endif
15233 #ifdef CLD_CONTINUED
15234 if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
15235 #endif
15236
15237 /* constants for lockf */
15238 #ifdef F_LOCK
15239 if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
15240 #endif
15241 #ifdef F_TLOCK
15242 if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
15243 #endif
15244 #ifdef F_ULOCK
15245 if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
15246 #endif
15247 #ifdef F_TEST
15248 if (PyModule_AddIntMacro(m, F_TEST)) return -1;
15249 #endif
15250
15251 #ifdef RWF_DSYNC
15252 if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
15253 #endif
15254 #ifdef RWF_HIPRI
15255 if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
15256 #endif
15257 #ifdef RWF_SYNC
15258 if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
15259 #endif
15260 #ifdef RWF_NOWAIT
15261 if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
15262 #endif
15263 #ifdef RWF_APPEND
15264 if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
15265 #endif
15266
15267 /* constants for splice */
15268 #if defined(HAVE_SPLICE) && defined(__linux__)
15269 if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
15270 if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
15271 if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
15272 #endif
15273
15274 /* constants for posix_spawn */
15275 #ifdef HAVE_POSIX_SPAWN
15276 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
15277 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
15278 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
15279 #endif
15280
15281 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
15282 if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
15283 if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
15284 if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
15285 #endif
15286 #ifdef HAVE_SPAWNV
15287 if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
15288 if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
15289 #endif
15290
15291 #ifdef HAVE_SCHED_H
15292 #ifdef SCHED_OTHER
15293 if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
15294 #endif
15295 #ifdef SCHED_FIFO
15296 if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
15297 #endif
15298 #ifdef SCHED_RR
15299 if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
15300 #endif
15301 #ifdef SCHED_SPORADIC
15302 if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
15303 #endif
15304 #ifdef SCHED_BATCH
15305 if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
15306 #endif
15307 #ifdef SCHED_IDLE
15308 if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
15309 #endif
15310 #ifdef SCHED_RESET_ON_FORK
15311 if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
15312 #endif
15313 #ifdef SCHED_SYS
15314 if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
15315 #endif
15316 #ifdef SCHED_IA
15317 if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
15318 #endif
15319 #ifdef SCHED_FSS
15320 if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
15321 #endif
15322 #ifdef SCHED_FX
15323 if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
15324 #endif
15325 #endif
15326
15327 #ifdef USE_XATTRS
15328 if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
15329 if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
15330 if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
15331 #endif
15332
15333 #if HAVE_DECL_RTLD_LAZY
15334 if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
15335 #endif
15336 #if HAVE_DECL_RTLD_NOW
15337 if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
15338 #endif
15339 #if HAVE_DECL_RTLD_GLOBAL
15340 if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
15341 #endif
15342 #if HAVE_DECL_RTLD_LOCAL
15343 if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
15344 #endif
15345 #if HAVE_DECL_RTLD_NODELETE
15346 if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
15347 #endif
15348 #if HAVE_DECL_RTLD_NOLOAD
15349 if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
15350 #endif
15351 #if HAVE_DECL_RTLD_DEEPBIND
15352 if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
15353 #endif
15354 #if HAVE_DECL_RTLD_MEMBER
15355 if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
15356 #endif
15357
15358 #ifdef HAVE_GETRANDOM_SYSCALL
15359 if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
15360 if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
15361 #endif
15362 #ifdef HAVE_MEMFD_CREATE
15363 if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
15364 if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
15365 #ifdef MFD_HUGETLB
15366 if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
15367 #endif
15368 #ifdef MFD_HUGE_SHIFT
15369 if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
15370 #endif
15371 #ifdef MFD_HUGE_MASK
15372 if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
15373 #endif
15374 #ifdef MFD_HUGE_64KB
15375 if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
15376 #endif
15377 #ifdef MFD_HUGE_512KB
15378 if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
15379 #endif
15380 #ifdef MFD_HUGE_1MB
15381 if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
15382 #endif
15383 #ifdef MFD_HUGE_2MB
15384 if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
15385 #endif
15386 #ifdef MFD_HUGE_8MB
15387 if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
15388 #endif
15389 #ifdef MFD_HUGE_16MB
15390 if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
15391 #endif
15392 #ifdef MFD_HUGE_32MB
15393 if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
15394 #endif
15395 #ifdef MFD_HUGE_256MB
15396 if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
15397 #endif
15398 #ifdef MFD_HUGE_512MB
15399 if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
15400 #endif
15401 #ifdef MFD_HUGE_1GB
15402 if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
15403 #endif
15404 #ifdef MFD_HUGE_2GB
15405 if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
15406 #endif
15407 #ifdef MFD_HUGE_16GB
15408 if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
15409 #endif
15410 #endif /* HAVE_MEMFD_CREATE */
15411
15412 #ifdef HAVE_EVENTFD
15413 if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
15414 if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
15415 if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
15416 #endif
15417
15418 #if defined(__APPLE__)
15419 if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
15420 #endif
15421
15422 #ifdef MS_WINDOWS
15423 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
15424 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
15425 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
15426 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
15427 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
15428 #endif
15429
15430 return 0;
15431 }
15432
15433
15434
15435 #define PROBE(name, test) \
15436 static int name(void) \
15437 { \
15438 if (test) { \
15439 return 1; \
15440 } else { \
15441 return 0; \
15442 } \
15443 }
15444
15445 #ifdef HAVE_FSTATAT
15446 PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
15447 #endif
15448
15449 #ifdef HAVE_FACCESSAT
15450 PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
15451 #endif
15452
15453 #ifdef HAVE_FCHMODAT
15454 PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
15455 #endif
15456
15457 #ifdef HAVE_FCHOWNAT
15458 PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
15459 #endif
15460
15461 #ifdef HAVE_LINKAT
15462 PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
15463 #endif
15464
15465 #ifdef HAVE_FDOPENDIR
15466 PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
15467 #endif
15468
15469 #ifdef HAVE_MKDIRAT
15470 PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
15471 #endif
15472
15473 #ifdef HAVE_RENAMEAT
15474 PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
15475 #endif
15476
15477 #ifdef HAVE_UNLINKAT
15478 PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
15479 #endif
15480
15481 #ifdef HAVE_OPENAT
15482 PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
15483 #endif
15484
15485 #ifdef HAVE_READLINKAT
15486 PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
15487 #endif
15488
15489 #ifdef HAVE_SYMLINKAT
15490 PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
15491 #endif
15492
15493 #ifdef HAVE_FUTIMENS
15494 PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
15495 #endif
15496
15497 #ifdef HAVE_UTIMENSAT
15498 PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
15499 #endif
15500
15501
15502
15503
15504 static const struct have_function {
15505 const char * const label;
15506 int (*probe)(void);
15507 } have_functions[] = {
15508
15509 #ifdef HAVE_EVENTFD
15510 {"HAVE_EVENTFD", NULL},
15511 #endif
15512
15513 #ifdef HAVE_FACCESSAT
15514 { "HAVE_FACCESSAT", probe_faccessat },
15515 #endif
15516
15517 #ifdef HAVE_FCHDIR
15518 { "HAVE_FCHDIR", NULL },
15519 #endif
15520
15521 #ifdef HAVE_FCHMOD
15522 { "HAVE_FCHMOD", NULL },
15523 #endif
15524
15525 #ifdef HAVE_FCHMODAT
15526 { "HAVE_FCHMODAT", probe_fchmodat },
15527 #endif
15528
15529 #ifdef HAVE_FCHOWN
15530 { "HAVE_FCHOWN", NULL },
15531 #endif
15532
15533 #ifdef HAVE_FCHOWNAT
15534 { "HAVE_FCHOWNAT", probe_fchownat },
15535 #endif
15536
15537 #ifdef HAVE_FEXECVE
15538 { "HAVE_FEXECVE", NULL },
15539 #endif
15540
15541 #ifdef HAVE_FDOPENDIR
15542 { "HAVE_FDOPENDIR", probe_fdopendir },
15543 #endif
15544
15545 #ifdef HAVE_FPATHCONF
15546 { "HAVE_FPATHCONF", NULL },
15547 #endif
15548
15549 #ifdef HAVE_FSTATAT
15550 { "HAVE_FSTATAT", probe_fstatat },
15551 #endif
15552
15553 #ifdef HAVE_FSTATVFS
15554 { "HAVE_FSTATVFS", NULL },
15555 #endif
15556
15557 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
15558 { "HAVE_FTRUNCATE", NULL },
15559 #endif
15560
15561 #ifdef HAVE_FUTIMENS
15562 { "HAVE_FUTIMENS", probe_futimens },
15563 #endif
15564
15565 #ifdef HAVE_FUTIMES
15566 { "HAVE_FUTIMES", NULL },
15567 #endif
15568
15569 #ifdef HAVE_FUTIMESAT
15570 { "HAVE_FUTIMESAT", NULL },
15571 #endif
15572
15573 #ifdef HAVE_LINKAT
15574 { "HAVE_LINKAT", probe_linkat },
15575 #endif
15576
15577 #ifdef HAVE_LCHFLAGS
15578 { "HAVE_LCHFLAGS", NULL },
15579 #endif
15580
15581 #ifdef HAVE_LCHMOD
15582 { "HAVE_LCHMOD", NULL },
15583 #endif
15584
15585 #ifdef HAVE_LCHOWN
15586 { "HAVE_LCHOWN", NULL },
15587 #endif
15588
15589 #ifdef HAVE_LSTAT
15590 { "HAVE_LSTAT", NULL },
15591 #endif
15592
15593 #ifdef HAVE_LUTIMES
15594 { "HAVE_LUTIMES", NULL },
15595 #endif
15596
15597 #ifdef HAVE_MEMFD_CREATE
15598 { "HAVE_MEMFD_CREATE", NULL },
15599 #endif
15600
15601 #ifdef HAVE_MKDIRAT
15602 { "HAVE_MKDIRAT", probe_mkdirat },
15603 #endif
15604
15605 #ifdef HAVE_MKFIFOAT
15606 { "HAVE_MKFIFOAT", NULL },
15607 #endif
15608
15609 #ifdef HAVE_MKNODAT
15610 { "HAVE_MKNODAT", NULL },
15611 #endif
15612
15613 #ifdef HAVE_OPENAT
15614 { "HAVE_OPENAT", probe_openat },
15615 #endif
15616
15617 #ifdef HAVE_READLINKAT
15618 { "HAVE_READLINKAT", probe_readlinkat },
15619 #endif
15620
15621 #ifdef HAVE_RENAMEAT
15622 { "HAVE_RENAMEAT", probe_renameat },
15623 #endif
15624
15625 #ifdef HAVE_SYMLINKAT
15626 { "HAVE_SYMLINKAT", probe_symlinkat },
15627 #endif
15628
15629 #ifdef HAVE_UNLINKAT
15630 { "HAVE_UNLINKAT", probe_unlinkat },
15631 #endif
15632
15633 #ifdef HAVE_UTIMENSAT
15634 { "HAVE_UTIMENSAT", probe_utimensat },
15635 #endif
15636
15637 #ifdef MS_WINDOWS
15638 { "MS_WINDOWS", NULL },
15639 #endif
15640
15641 { NULL, NULL }
15642 };
15643
15644
15645 static int
posixmodule_exec(PyObject * m)15646 posixmodule_exec(PyObject *m)
15647 {
15648 _posixstate *state = get_posix_state(m);
15649
15650 #if defined(HAVE_PWRITEV)
15651 if (HAVE_PWRITEV_RUNTIME) {} else {
15652 PyObject* dct = PyModule_GetDict(m);
15653
15654 if (dct == NULL) {
15655 return -1;
15656 }
15657
15658 if (PyDict_DelItemString(dct, "pwritev") == -1) {
15659 PyErr_Clear();
15660 }
15661 if (PyDict_DelItemString(dct, "preadv") == -1) {
15662 PyErr_Clear();
15663 }
15664 }
15665 #endif
15666
15667 /* Initialize environ dictionary */
15668 PyObject *v = convertenviron();
15669 Py_XINCREF(v);
15670 if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
15671 return -1;
15672 Py_DECREF(v);
15673
15674 if (all_ins(m))
15675 return -1;
15676
15677 if (setup_confname_tables(m))
15678 return -1;
15679
15680 Py_INCREF(PyExc_OSError);
15681 PyModule_AddObject(m, "error", PyExc_OSError);
15682
15683 #if defined(HAVE_WAITID) && !defined(__APPLE__)
15684 waitid_result_desc.name = MODNAME ".waitid_result";
15685 PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
15686 if (WaitidResultType == NULL) {
15687 return -1;
15688 }
15689 Py_INCREF(WaitidResultType);
15690 PyModule_AddObject(m, "waitid_result", WaitidResultType);
15691 state->WaitidResultType = WaitidResultType;
15692 #endif
15693
15694 stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
15695 stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
15696 stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
15697 stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
15698 PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
15699 if (StatResultType == NULL) {
15700 return -1;
15701 }
15702 Py_INCREF(StatResultType);
15703 PyModule_AddObject(m, "stat_result", StatResultType);
15704 state->StatResultType = StatResultType;
15705 structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15706 ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
15707
15708 statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
15709 PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
15710 if (StatVFSResultType == NULL) {
15711 return -1;
15712 }
15713 Py_INCREF(StatVFSResultType);
15714 PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
15715 state->StatVFSResultType = StatVFSResultType;
15716 #ifdef NEED_TICKS_PER_SECOND
15717 # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15718 ticks_per_second = sysconf(_SC_CLK_TCK);
15719 # elif defined(HZ)
15720 ticks_per_second = HZ;
15721 # else
15722 ticks_per_second = 60; /* magic fallback value; may be bogus */
15723 # endif
15724 #endif
15725
15726 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
15727 sched_param_desc.name = MODNAME ".sched_param";
15728 PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
15729 if (SchedParamType == NULL) {
15730 return -1;
15731 }
15732 Py_INCREF(SchedParamType);
15733 PyModule_AddObject(m, "sched_param", SchedParamType);
15734 state->SchedParamType = SchedParamType;
15735 ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
15736 #endif
15737
15738 /* initialize TerminalSize_info */
15739 PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
15740 if (TerminalSizeType == NULL) {
15741 return -1;
15742 }
15743 Py_INCREF(TerminalSizeType);
15744 PyModule_AddObject(m, "terminal_size", TerminalSizeType);
15745 state->TerminalSizeType = TerminalSizeType;
15746
15747 /* initialize scandir types */
15748 PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
15749 if (ScandirIteratorType == NULL) {
15750 return -1;
15751 }
15752 state->ScandirIteratorType = ScandirIteratorType;
15753
15754 PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
15755 if (DirEntryType == NULL) {
15756 return -1;
15757 }
15758 Py_INCREF(DirEntryType);
15759 PyModule_AddObject(m, "DirEntry", DirEntryType);
15760 state->DirEntryType = DirEntryType;
15761
15762 times_result_desc.name = MODNAME ".times_result";
15763 PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(×_result_desc);
15764 if (TimesResultType == NULL) {
15765 return -1;
15766 }
15767 Py_INCREF(TimesResultType);
15768 PyModule_AddObject(m, "times_result", TimesResultType);
15769 state->TimesResultType = TimesResultType;
15770
15771 PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
15772 if (UnameResultType == NULL) {
15773 return -1;
15774 }
15775 Py_INCREF(UnameResultType);
15776 PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
15777 state->UnameResultType = (PyObject *)UnameResultType;
15778
15779 if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
15780 return -1;
15781 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
15782 state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
15783 if (state->struct_rusage == NULL)
15784 return -1;
15785 #endif
15786 state->st_mode = PyUnicode_InternFromString("st_mode");
15787 if (state->st_mode == NULL)
15788 return -1;
15789
15790 /* suppress "function not used" warnings */
15791 {
15792 int ignored;
15793 fd_specified("", -1);
15794 follow_symlinks_specified("", 1);
15795 dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
15796 dir_fd_converter(Py_None, &ignored);
15797 dir_fd_unavailable(Py_None, &ignored);
15798 }
15799
15800 /*
15801 * provide list of locally available functions
15802 * so os.py can populate support_* lists
15803 */
15804 PyObject *list = PyList_New(0);
15805 if (!list) {
15806 return -1;
15807 }
15808 for (const struct have_function *trace = have_functions; trace->label; trace++) {
15809 PyObject *unicode;
15810 if (trace->probe && !trace->probe()) continue;
15811 unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
15812 if (!unicode)
15813 return -1;
15814 if (PyList_Append(list, unicode))
15815 return -1;
15816 Py_DECREF(unicode);
15817 }
15818
15819 PyModule_AddObject(m, "_have_functions", list);
15820
15821 return 0;
15822 }
15823
15824
15825 static PyModuleDef_Slot posixmodile_slots[] = {
15826 {Py_mod_exec, posixmodule_exec},
15827 {0, NULL}
15828 };
15829
15830 static struct PyModuleDef posixmodule = {
15831 PyModuleDef_HEAD_INIT,
15832 .m_name = MODNAME,
15833 .m_doc = posix__doc__,
15834 .m_size = sizeof(_posixstate),
15835 .m_methods = posix_methods,
15836 .m_slots = posixmodile_slots,
15837 .m_traverse = _posix_traverse,
15838 .m_clear = _posix_clear,
15839 .m_free = _posix_free,
15840 };
15841
15842 PyMODINIT_FUNC
INITFUNC(void)15843 INITFUNC(void)
15844 {
15845 return PyModuleDef_Init(&posixmodule);
15846 }
15847
15848 #ifdef __cplusplus
15849 }
15850 #endif
15851