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 "pycore_fileutils.h"
14 #include "pycore_moduleobject.h" // _PyModule_GetState()
15 #ifdef MS_WINDOWS
16 /* include <windows.h> early to avoid conflict with pycore_condvar.h:
17
18 #define WIN32_LEAN_AND_MEAN
19 #include <windows.h>
20
21 FSCTL_GET_REPARSE_POINT is not exported with WIN32_LEAN_AND_MEAN. */
22 # include <windows.h>
23 # include <pathcch.h>
24 #endif
25
26 #ifdef __VXWORKS__
27 # include "pycore_bitutils.h" // _Py_popcount32()
28 #endif
29 #include "pycore_ceval.h" // _PyEval_ReInitThreads()
30 #include "pycore_import.h" // _PyImport_ReInitLock()
31 #include "pycore_initconfig.h" // _PyStatus_EXCEPTION()
32 #include "pycore_pystate.h" // _PyInterpreterState_GET()
33 #include "structmember.h" // PyMemberDef
34 #ifndef MS_WINDOWS
35 # include "posixmodule.h"
36 #else
37 # include "winreparse.h"
38 #endif
39
40 /* On android API level 21, 'AT_EACCESS' is not declared although
41 * HAVE_FACCESSAT is defined. */
42 #ifdef __ANDROID__
43 # undef HAVE_FACCESSAT
44 #endif
45
46 #include <stdio.h> /* needed for ctermid() */
47
48 /*
49 * A number of APIs are available on macOS from a certain macOS version.
50 * To support building with a new SDK while deploying to older versions
51 * the availability test is split into two:
52 * - HAVE_<FUNCTION>: The configure check for compile time availability
53 * - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
54 *
55 * The latter is always true when not on macOS, or when using a compiler
56 * that does not support __has_builtin (older versions of Xcode).
57 *
58 * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
59 * if (HAVE_<FUNCTION>_RUNTIME) { ... }
60 *
61 * In mixing the test with other tests or using negations will result in compile
62 * errors.
63 */
64 #if defined(__APPLE__)
65
66 #if defined(__has_builtin)
67 #if __has_builtin(__builtin_available)
68 #define HAVE_BUILTIN_AVAILABLE 1
69 #endif
70 #endif
71
72 #ifdef HAVE_BUILTIN_AVAILABLE
73 # define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
74 # define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
75 # define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
76 # define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
77 # define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
78 # define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
79 # define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
80 # define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
81 # define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
82 # define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
83 # define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
84 # define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
85 # define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
86 # define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
87 # define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
88
89 # define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
90
91 #else /* Xcode 8 or earlier */
92
93 /* __builtin_available is not present in these compilers, but
94 * some of the symbols might be weak linked (10.10 SDK or later
95 * deploying on 10.9.
96 *
97 * Fall back to the older style of availability checking for
98 * symbols introduced in macOS 10.10.
99 */
100
101 # ifdef HAVE_FSTATAT
102 # define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
103 # endif
104
105 # ifdef HAVE_FACCESSAT
106 # define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
107 # endif
108
109 # ifdef HAVE_FCHMODAT
110 # define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
111 # endif
112
113 # ifdef HAVE_FCHOWNAT
114 # define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
115 # endif
116
117 # ifdef HAVE_LINKAT
118 # define HAVE_LINKAT_RUNTIME (linkat != NULL)
119 # endif
120
121 # ifdef HAVE_FDOPENDIR
122 # define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
123 # endif
124
125 # ifdef HAVE_MKDIRAT
126 # define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
127 # endif
128
129 # ifdef HAVE_RENAMEAT
130 # define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
131 # endif
132
133 # ifdef HAVE_UNLINKAT
134 # define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
135 # endif
136
137 # ifdef HAVE_OPENAT
138 # define HAVE_OPENAT_RUNTIME (openat != NULL)
139 # endif
140
141 # ifdef HAVE_READLINKAT
142 # define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
143 # endif
144
145 # ifdef HAVE_SYMLINKAT
146 # define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
147 # endif
148
149 #endif
150
151 #ifdef HAVE_FUTIMESAT
152 /* Some of the logic for weak linking depends on this assertion */
153 # error "HAVE_FUTIMESAT unexpectedly defined"
154 #endif
155
156 #else
157 # define HAVE_FSTATAT_RUNTIME 1
158 # define HAVE_FACCESSAT_RUNTIME 1
159 # define HAVE_FCHMODAT_RUNTIME 1
160 # define HAVE_FCHOWNAT_RUNTIME 1
161 # define HAVE_LINKAT_RUNTIME 1
162 # define HAVE_FDOPENDIR_RUNTIME 1
163 # define HAVE_MKDIRAT_RUNTIME 1
164 # define HAVE_RENAMEAT_RUNTIME 1
165 # define HAVE_UNLINKAT_RUNTIME 1
166 # define HAVE_OPENAT_RUNTIME 1
167 # define HAVE_READLINKAT_RUNTIME 1
168 # define HAVE_SYMLINKAT_RUNTIME 1
169 # define HAVE_FUTIMENS_RUNTIME 1
170 # define HAVE_UTIMENSAT_RUNTIME 1
171 # define HAVE_PWRITEV_RUNTIME 1
172 #endif
173
174
175 #ifdef __cplusplus
176 extern "C" {
177 #endif
178
179 PyDoc_STRVAR(posix__doc__,
180 "This module provides access to operating system functionality that is\n\
181 standardized by the C Standard and the POSIX standard (a thinly\n\
182 disguised Unix interface). Refer to the library manual and\n\
183 corresponding Unix manual entries for more information on calls.");
184
185
186 #ifdef HAVE_SYS_UIO_H
187 # include <sys/uio.h>
188 #endif
189
190 #ifdef HAVE_SYS_SYSMACROS_H
191 /* GNU C Library: major(), minor(), makedev() */
192 # include <sys/sysmacros.h>
193 #endif
194
195 #ifdef HAVE_SYS_TYPES_H
196 # include <sys/types.h>
197 #endif /* HAVE_SYS_TYPES_H */
198
199 #ifdef HAVE_SYS_STAT_H
200 # include <sys/stat.h>
201 #endif /* HAVE_SYS_STAT_H */
202
203 #ifdef HAVE_SYS_WAIT_H
204 # include <sys/wait.h> // WNOHANG
205 #endif
206 #ifdef HAVE_LINUX_WAIT_H
207 # include <linux/wait.h> // P_PIDFD
208 #endif
209
210 #ifdef HAVE_SIGNAL_H
211 # include <signal.h>
212 #endif
213
214 #ifdef HAVE_FCNTL_H
215 # include <fcntl.h>
216 #endif
217
218 #ifdef HAVE_GRP_H
219 # include <grp.h>
220 #endif
221
222 #ifdef HAVE_SYSEXITS_H
223 # include <sysexits.h>
224 #endif
225
226 #ifdef HAVE_SYS_LOADAVG_H
227 # include <sys/loadavg.h>
228 #endif
229
230 #ifdef HAVE_SYS_SENDFILE_H
231 # include <sys/sendfile.h>
232 #endif
233
234 #if defined(__APPLE__)
235 # include <copyfile.h>
236 #endif
237
238 #ifdef HAVE_SCHED_H
239 # include <sched.h>
240 #endif
241
242 #ifdef HAVE_COPY_FILE_RANGE
243 # include <unistd.h>
244 #endif
245
246 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
247 # undef HAVE_SCHED_SETAFFINITY
248 #endif
249
250 #if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
251 # define USE_XATTRS
252 #endif
253
254 #ifdef USE_XATTRS
255 # include <sys/xattr.h>
256 #endif
257
258 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
259 # ifdef HAVE_SYS_SOCKET_H
260 # include <sys/socket.h>
261 # endif
262 #endif
263
264 #ifdef HAVE_DLFCN_H
265 # include <dlfcn.h>
266 #endif
267
268 #ifdef __hpux
269 # include <sys/mpctl.h>
270 #endif
271
272 #if defined(__DragonFly__) || \
273 defined(__OpenBSD__) || \
274 defined(__FreeBSD__) || \
275 defined(__NetBSD__) || \
276 defined(__APPLE__)
277 # include <sys/sysctl.h>
278 #endif
279
280 #ifdef HAVE_LINUX_RANDOM_H
281 # include <linux/random.h>
282 #endif
283 #ifdef HAVE_GETRANDOM_SYSCALL
284 # include <sys/syscall.h>
285 #endif
286
287 #if defined(MS_WINDOWS)
288 # define TERMSIZE_USE_CONIO
289 #elif defined(HAVE_SYS_IOCTL_H)
290 # include <sys/ioctl.h>
291 # if defined(HAVE_TERMIOS_H)
292 # include <termios.h>
293 # endif
294 # if defined(TIOCGWINSZ)
295 # define TERMSIZE_USE_IOCTL
296 # endif
297 #endif /* MS_WINDOWS */
298
299 /* Various compilers have only certain posix functions */
300 /* XXX Gosh I wish these were all moved into pyconfig.h */
301 #if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */
302 # define HAVE_OPENDIR 1
303 # define HAVE_SYSTEM 1
304 # include <process.h>
305 #else
306 # ifdef _MSC_VER
307 /* Microsoft compiler */
308 # define HAVE_GETPPID 1
309 # define HAVE_GETLOGIN 1
310 # define HAVE_SPAWNV 1
311 # define HAVE_EXECV 1
312 # define HAVE_WSPAWNV 1
313 # define HAVE_WEXECV 1
314 # define HAVE_PIPE 1
315 # define HAVE_SYSTEM 1
316 # define HAVE_CWAIT 1
317 # define HAVE_FSYNC 1
318 # define fsync _commit
319 # else
320 /* Unix functions that the configure script doesn't check for */
321 # ifndef __VXWORKS__
322 # define HAVE_EXECV 1
323 # define HAVE_FORK 1
324 # if defined(__USLC__) && defined(__SCO_VERSION__) /* SCO UDK Compiler */
325 # define HAVE_FORK1 1
326 # endif
327 # endif
328 # define HAVE_GETEGID 1
329 # define HAVE_GETEUID 1
330 # define HAVE_GETGID 1
331 # define HAVE_GETPPID 1
332 # define HAVE_GETUID 1
333 # define HAVE_KILL 1
334 # define HAVE_OPENDIR 1
335 # define HAVE_PIPE 1
336 # define HAVE_SYSTEM 1
337 # define HAVE_WAIT 1
338 # define HAVE_TTYNAME 1
339 # endif /* _MSC_VER */
340 #endif /* ! __WATCOMC__ || __QNX__ */
341
342 _Py_IDENTIFIER(__fspath__);
343
344 /*[clinic input]
345 # one of the few times we lie about this name!
346 module os
347 [clinic start generated code]*/
348 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
349
350 #ifndef _MSC_VER
351
352 #if defined(__sgi)&&_COMPILER_VERSION>=700
353 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
354 (default) */
355 extern char *ctermid_r(char *);
356 #endif
357
358 #endif /* !_MSC_VER */
359
360 #if defined(__VXWORKS__)
361 # include <vxCpuLib.h>
362 # include <rtpLib.h>
363 # include <wait.h>
364 # include <taskLib.h>
365 # ifndef _P_WAIT
366 # define _P_WAIT 0
367 # define _P_NOWAIT 1
368 # define _P_NOWAITO 1
369 # endif
370 #endif /* __VXWORKS__ */
371
372 #ifdef HAVE_POSIX_SPAWN
373 # include <spawn.h>
374 #endif
375
376 #ifdef HAVE_UTIME_H
377 # include <utime.h>
378 #endif /* HAVE_UTIME_H */
379
380 #ifdef HAVE_SYS_UTIME_H
381 # include <sys/utime.h>
382 # define HAVE_UTIME_H /* pretend we do for the rest of this file */
383 #endif /* HAVE_SYS_UTIME_H */
384
385 #ifdef HAVE_SYS_TIMES_H
386 # include <sys/times.h>
387 #endif /* HAVE_SYS_TIMES_H */
388
389 #ifdef HAVE_SYS_PARAM_H
390 # include <sys/param.h>
391 #endif /* HAVE_SYS_PARAM_H */
392
393 #ifdef HAVE_SYS_UTSNAME_H
394 # include <sys/utsname.h>
395 #endif /* HAVE_SYS_UTSNAME_H */
396
397 #ifdef HAVE_DIRENT_H
398 # include <dirent.h>
399 # define NAMLEN(dirent) strlen((dirent)->d_name)
400 #else
401 # if defined(__WATCOMC__) && !defined(__QNX__)
402 # include <direct.h>
403 # define NAMLEN(dirent) strlen((dirent)->d_name)
404 # else
405 # define dirent direct
406 # define NAMLEN(dirent) (dirent)->d_namlen
407 # endif
408 # ifdef HAVE_SYS_NDIR_H
409 # include <sys/ndir.h>
410 # endif
411 # ifdef HAVE_SYS_DIR_H
412 # include <sys/dir.h>
413 # endif
414 # ifdef HAVE_NDIR_H
415 # include <ndir.h>
416 # endif
417 #endif
418
419 #ifdef _MSC_VER
420 # ifdef HAVE_DIRECT_H
421 # include <direct.h>
422 # endif
423 # ifdef HAVE_IO_H
424 # include <io.h>
425 # endif
426 # ifdef HAVE_PROCESS_H
427 # include <process.h>
428 # endif
429 # ifndef IO_REPARSE_TAG_SYMLINK
430 # define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
431 # endif
432 # ifndef IO_REPARSE_TAG_MOUNT_POINT
433 # define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
434 # endif
435 # include "osdefs.h" // SEP
436 # include <malloc.h>
437 # include <windows.h>
438 # include <shellapi.h> // ShellExecute()
439 # include <lmcons.h> // UNLEN
440 # define HAVE_SYMLINK
441 #endif /* _MSC_VER */
442
443 #ifndef MAXPATHLEN
444 # if defined(PATH_MAX) && PATH_MAX > 1024
445 # define MAXPATHLEN PATH_MAX
446 # else
447 # define MAXPATHLEN 1024
448 # endif
449 #endif /* MAXPATHLEN */
450
451 #ifdef UNION_WAIT
452 /* Emulate some macros on systems that have a union instead of macros */
453 # ifndef WIFEXITED
454 # define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
455 # endif
456 # ifndef WEXITSTATUS
457 # define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
458 # endif
459 # ifndef WTERMSIG
460 # define WTERMSIG(u_wait) ((u_wait).w_termsig)
461 # endif
462 # define WAIT_TYPE union wait
463 # define WAIT_STATUS_INT(s) (s.w_status)
464 #else
465 /* !UNION_WAIT */
466 # define WAIT_TYPE int
467 # define WAIT_STATUS_INT(s) (s)
468 #endif /* UNION_WAIT */
469
470 /* Don't use the "_r" form if we don't need it (also, won't have a
471 prototype for it, at least on Solaris -- maybe others as well?). */
472 #if defined(HAVE_CTERMID_R)
473 # define USE_CTERMID_R
474 #endif
475
476 /* choose the appropriate stat and fstat functions and return structs */
477 #undef STAT
478 #undef FSTAT
479 #undef STRUCT_STAT
480 #ifdef MS_WINDOWS
481 # define STAT win32_stat
482 # define LSTAT win32_lstat
483 # define FSTAT _Py_fstat_noraise
484 # define STRUCT_STAT struct _Py_stat_struct
485 #else
486 # define STAT stat
487 # define LSTAT lstat
488 # define FSTAT fstat
489 # define STRUCT_STAT struct stat
490 #endif
491
492 #if defined(MAJOR_IN_MKDEV)
493 # include <sys/mkdev.h>
494 #else
495 # if defined(MAJOR_IN_SYSMACROS)
496 # include <sys/sysmacros.h>
497 # endif
498 # if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
499 # include <sys/mkdev.h>
500 # endif
501 #endif
502
503 #ifdef MS_WINDOWS
504 # define INITFUNC PyInit_nt
505 # define MODNAME "nt"
506 #else
507 # define INITFUNC PyInit_posix
508 # define MODNAME "posix"
509 #endif
510
511 #if defined(__sun)
512 /* Something to implement in autoconf, not present in autoconf 2.69 */
513 # define HAVE_STRUCT_STAT_ST_FSTYPE 1
514 #endif
515
516 /* memfd_create is either defined in sys/mman.h or sys/memfd.h
517 * linux/memfd.h defines additional flags
518 */
519 #ifdef HAVE_SYS_MMAN_H
520 # include <sys/mman.h>
521 #endif
522 #ifdef HAVE_SYS_MEMFD_H
523 # include <sys/memfd.h>
524 #endif
525 #ifdef HAVE_LINUX_MEMFD_H
526 # include <linux/memfd.h>
527 #endif
528
529 /* eventfd() */
530 #ifdef HAVE_SYS_EVENTFD_H
531 # include <sys/eventfd.h>
532 #endif
533
534 #ifdef _Py_MEMORY_SANITIZER
535 # include <sanitizer/msan_interface.h>
536 #endif
537
538 #ifdef HAVE_FORK
539 static void
run_at_forkers(PyObject * lst,int reverse)540 run_at_forkers(PyObject *lst, int reverse)
541 {
542 Py_ssize_t i;
543 PyObject *cpy;
544
545 if (lst != NULL) {
546 assert(PyList_CheckExact(lst));
547
548 /* Use a list copy in case register_at_fork() is called from
549 * one of the callbacks.
550 */
551 cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
552 if (cpy == NULL)
553 PyErr_WriteUnraisable(lst);
554 else {
555 if (reverse)
556 PyList_Reverse(cpy);
557 for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
558 PyObject *func, *res;
559 func = PyList_GET_ITEM(cpy, i);
560 res = _PyObject_CallNoArg(func);
561 if (res == NULL)
562 PyErr_WriteUnraisable(func);
563 else
564 Py_DECREF(res);
565 }
566 Py_DECREF(cpy);
567 }
568 }
569 }
570
571 void
PyOS_BeforeFork(void)572 PyOS_BeforeFork(void)
573 {
574 run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1);
575
576 _PyImport_AcquireLock();
577 }
578
579 void
PyOS_AfterFork_Parent(void)580 PyOS_AfterFork_Parent(void)
581 {
582 if (_PyImport_ReleaseLock() <= 0)
583 Py_FatalError("failed releasing import lock after fork");
584
585 run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0);
586 }
587
588 void
PyOS_AfterFork_Child(void)589 PyOS_AfterFork_Child(void)
590 {
591 PyStatus status;
592 _PyRuntimeState *runtime = &_PyRuntime;
593
594 status = _PyGILState_Reinit(runtime);
595 if (_PyStatus_EXCEPTION(status)) {
596 goto fatal_error;
597 }
598
599 PyThreadState *tstate = _PyThreadState_GET();
600 _Py_EnsureTstateNotNULL(tstate);
601
602 status = _PyEval_ReInitThreads(tstate);
603 if (_PyStatus_EXCEPTION(status)) {
604 goto fatal_error;
605 }
606
607 status = _PyImport_ReInitLock();
608 if (_PyStatus_EXCEPTION(status)) {
609 goto fatal_error;
610 }
611
612 _PySignal_AfterFork();
613
614 status = _PyRuntimeState_ReInitThreads(runtime);
615 if (_PyStatus_EXCEPTION(status)) {
616 goto fatal_error;
617 }
618
619 status = _PyInterpreterState_DeleteExceptMain(runtime);
620 if (_PyStatus_EXCEPTION(status)) {
621 goto fatal_error;
622 }
623 assert(_PyThreadState_GET() == tstate);
624
625 run_at_forkers(tstate->interp->after_forkers_child, 0);
626 return;
627
628 fatal_error:
629 Py_ExitStatusException(status);
630 }
631
632 static int
register_at_forker(PyObject ** lst,PyObject * func)633 register_at_forker(PyObject **lst, PyObject *func)
634 {
635 if (func == NULL) /* nothing to register? do nothing. */
636 return 0;
637 if (*lst == NULL) {
638 *lst = PyList_New(0);
639 if (*lst == NULL)
640 return -1;
641 }
642 return PyList_Append(*lst, func);
643 }
644 #endif /* HAVE_FORK */
645
646
647 /* Legacy wrapper */
648 void
PyOS_AfterFork(void)649 PyOS_AfterFork(void)
650 {
651 #ifdef HAVE_FORK
652 PyOS_AfterFork_Child();
653 #endif
654 }
655
656
657 #ifdef MS_WINDOWS
658 /* defined in fileutils.c */
659 void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
660 void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
661 ULONG, struct _Py_stat_struct *);
662 #endif
663
664
665 #ifndef MS_WINDOWS
666 PyObject *
_PyLong_FromUid(uid_t uid)667 _PyLong_FromUid(uid_t uid)
668 {
669 if (uid == (uid_t)-1)
670 return PyLong_FromLong(-1);
671 return PyLong_FromUnsignedLong(uid);
672 }
673
674 PyObject *
_PyLong_FromGid(gid_t gid)675 _PyLong_FromGid(gid_t gid)
676 {
677 if (gid == (gid_t)-1)
678 return PyLong_FromLong(-1);
679 return PyLong_FromUnsignedLong(gid);
680 }
681
682 int
_Py_Uid_Converter(PyObject * obj,uid_t * p)683 _Py_Uid_Converter(PyObject *obj, uid_t *p)
684 {
685 uid_t uid;
686 PyObject *index;
687 int overflow;
688 long result;
689 unsigned long uresult;
690
691 index = _PyNumber_Index(obj);
692 if (index == NULL) {
693 PyErr_Format(PyExc_TypeError,
694 "uid should be integer, not %.200s",
695 _PyType_Name(Py_TYPE(obj)));
696 return 0;
697 }
698
699 /*
700 * Handling uid_t is complicated for two reasons:
701 * * Although uid_t is (always?) unsigned, it still
702 * accepts -1.
703 * * We don't know its size in advance--it may be
704 * bigger than an int, or it may be smaller than
705 * a long.
706 *
707 * So a bit of defensive programming is in order.
708 * Start with interpreting the value passed
709 * in as a signed long and see if it works.
710 */
711
712 result = PyLong_AsLongAndOverflow(index, &overflow);
713
714 if (!overflow) {
715 uid = (uid_t)result;
716
717 if (result == -1) {
718 if (PyErr_Occurred())
719 goto fail;
720 /* It's a legitimate -1, we're done. */
721 goto success;
722 }
723
724 /* Any other negative number is disallowed. */
725 if (result < 0)
726 goto underflow;
727
728 /* Ensure the value wasn't truncated. */
729 if (sizeof(uid_t) < sizeof(long) &&
730 (long)uid != result)
731 goto underflow;
732 goto success;
733 }
734
735 if (overflow < 0)
736 goto underflow;
737
738 /*
739 * Okay, the value overflowed a signed long. If it
740 * fits in an *unsigned* long, it may still be okay,
741 * as uid_t may be unsigned long on this platform.
742 */
743 uresult = PyLong_AsUnsignedLong(index);
744 if (PyErr_Occurred()) {
745 if (PyErr_ExceptionMatches(PyExc_OverflowError))
746 goto overflow;
747 goto fail;
748 }
749
750 uid = (uid_t)uresult;
751
752 /*
753 * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
754 * but this value would get interpreted as (uid_t)-1 by chown
755 * and its siblings. That's not what the user meant! So we
756 * throw an overflow exception instead. (We already
757 * handled a real -1 with PyLong_AsLongAndOverflow() above.)
758 */
759 if (uid == (uid_t)-1)
760 goto overflow;
761
762 /* Ensure the value wasn't truncated. */
763 if (sizeof(uid_t) < sizeof(long) &&
764 (unsigned long)uid != uresult)
765 goto overflow;
766 /* fallthrough */
767
768 success:
769 Py_DECREF(index);
770 *p = uid;
771 return 1;
772
773 underflow:
774 PyErr_SetString(PyExc_OverflowError,
775 "uid is less than minimum");
776 goto fail;
777
778 overflow:
779 PyErr_SetString(PyExc_OverflowError,
780 "uid is greater than maximum");
781 /* fallthrough */
782
783 fail:
784 Py_DECREF(index);
785 return 0;
786 }
787
788 int
_Py_Gid_Converter(PyObject * obj,gid_t * p)789 _Py_Gid_Converter(PyObject *obj, gid_t *p)
790 {
791 gid_t gid;
792 PyObject *index;
793 int overflow;
794 long result;
795 unsigned long uresult;
796
797 index = _PyNumber_Index(obj);
798 if (index == NULL) {
799 PyErr_Format(PyExc_TypeError,
800 "gid should be integer, not %.200s",
801 _PyType_Name(Py_TYPE(obj)));
802 return 0;
803 }
804
805 /*
806 * Handling gid_t is complicated for two reasons:
807 * * Although gid_t is (always?) unsigned, it still
808 * accepts -1.
809 * * We don't know its size in advance--it may be
810 * bigger than an int, or it may be smaller than
811 * a long.
812 *
813 * So a bit of defensive programming is in order.
814 * Start with interpreting the value passed
815 * in as a signed long and see if it works.
816 */
817
818 result = PyLong_AsLongAndOverflow(index, &overflow);
819
820 if (!overflow) {
821 gid = (gid_t)result;
822
823 if (result == -1) {
824 if (PyErr_Occurred())
825 goto fail;
826 /* It's a legitimate -1, we're done. */
827 goto success;
828 }
829
830 /* Any other negative number is disallowed. */
831 if (result < 0) {
832 goto underflow;
833 }
834
835 /* Ensure the value wasn't truncated. */
836 if (sizeof(gid_t) < sizeof(long) &&
837 (long)gid != result)
838 goto underflow;
839 goto success;
840 }
841
842 if (overflow < 0)
843 goto underflow;
844
845 /*
846 * Okay, the value overflowed a signed long. If it
847 * fits in an *unsigned* long, it may still be okay,
848 * as gid_t may be unsigned long on this platform.
849 */
850 uresult = PyLong_AsUnsignedLong(index);
851 if (PyErr_Occurred()) {
852 if (PyErr_ExceptionMatches(PyExc_OverflowError))
853 goto overflow;
854 goto fail;
855 }
856
857 gid = (gid_t)uresult;
858
859 /*
860 * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
861 * but this value would get interpreted as (gid_t)-1 by chown
862 * and its siblings. That's not what the user meant! So we
863 * throw an overflow exception instead. (We already
864 * handled a real -1 with PyLong_AsLongAndOverflow() above.)
865 */
866 if (gid == (gid_t)-1)
867 goto overflow;
868
869 /* Ensure the value wasn't truncated. */
870 if (sizeof(gid_t) < sizeof(long) &&
871 (unsigned long)gid != uresult)
872 goto overflow;
873 /* fallthrough */
874
875 success:
876 Py_DECREF(index);
877 *p = gid;
878 return 1;
879
880 underflow:
881 PyErr_SetString(PyExc_OverflowError,
882 "gid is less than minimum");
883 goto fail;
884
885 overflow:
886 PyErr_SetString(PyExc_OverflowError,
887 "gid is greater than maximum");
888 /* fallthrough */
889
890 fail:
891 Py_DECREF(index);
892 return 0;
893 }
894 #endif /* MS_WINDOWS */
895
896
897 #define _PyLong_FromDev PyLong_FromLongLong
898
899
900 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
901 static int
_Py_Dev_Converter(PyObject * obj,void * p)902 _Py_Dev_Converter(PyObject *obj, void *p)
903 {
904 *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
905 if (PyErr_Occurred())
906 return 0;
907 return 1;
908 }
909 #endif /* HAVE_MKNOD && HAVE_MAKEDEV */
910
911
912 #ifdef AT_FDCWD
913 /*
914 * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
915 * without the int cast, the value gets interpreted as uint (4291925331),
916 * which doesn't play nicely with all the initializer lines in this file that
917 * look like this:
918 * int dir_fd = DEFAULT_DIR_FD;
919 */
920 #define DEFAULT_DIR_FD (int)AT_FDCWD
921 #else
922 #define DEFAULT_DIR_FD (-100)
923 #endif
924
925 static int
_fd_converter(PyObject * o,int * p)926 _fd_converter(PyObject *o, int *p)
927 {
928 int overflow;
929 long long_value;
930
931 PyObject *index = _PyNumber_Index(o);
932 if (index == NULL) {
933 return 0;
934 }
935
936 assert(PyLong_Check(index));
937 long_value = PyLong_AsLongAndOverflow(index, &overflow);
938 Py_DECREF(index);
939 assert(!PyErr_Occurred());
940 if (overflow > 0 || long_value > INT_MAX) {
941 PyErr_SetString(PyExc_OverflowError,
942 "fd is greater than maximum");
943 return 0;
944 }
945 if (overflow < 0 || long_value < INT_MIN) {
946 PyErr_SetString(PyExc_OverflowError,
947 "fd is less than minimum");
948 return 0;
949 }
950
951 *p = (int)long_value;
952 return 1;
953 }
954
955 static int
dir_fd_converter(PyObject * o,void * p)956 dir_fd_converter(PyObject *o, void *p)
957 {
958 if (o == Py_None) {
959 *(int *)p = DEFAULT_DIR_FD;
960 return 1;
961 }
962 else if (PyIndex_Check(o)) {
963 return _fd_converter(o, (int *)p);
964 }
965 else {
966 PyErr_Format(PyExc_TypeError,
967 "argument should be integer or None, not %.200s",
968 _PyType_Name(Py_TYPE(o)));
969 return 0;
970 }
971 }
972
973 typedef struct {
974 PyObject *billion;
975 PyObject *DirEntryType;
976 PyObject *ScandirIteratorType;
977 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
978 PyObject *SchedParamType;
979 #endif
980 PyObject *StatResultType;
981 PyObject *StatVFSResultType;
982 PyObject *TerminalSizeType;
983 PyObject *TimesResultType;
984 PyObject *UnameResultType;
985 #if defined(HAVE_WAITID) && !defined(__APPLE__)
986 PyObject *WaitidResultType;
987 #endif
988 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
989 PyObject *struct_rusage;
990 #endif
991 PyObject *st_mode;
992 } _posixstate;
993
994
995 static inline _posixstate*
get_posix_state(PyObject * module)996 get_posix_state(PyObject *module)
997 {
998 void *state = _PyModule_GetState(module);
999 assert(state != NULL);
1000 return (_posixstate *)state;
1001 }
1002
1003 /*
1004 * A PyArg_ParseTuple "converter" function
1005 * that handles filesystem paths in the manner
1006 * preferred by the os module.
1007 *
1008 * path_converter accepts (Unicode) strings and their
1009 * subclasses, and bytes and their subclasses. What
1010 * it does with the argument depends on the platform:
1011 *
1012 * * On Windows, if we get a (Unicode) string we
1013 * extract the wchar_t * and return it; if we get
1014 * bytes we decode to wchar_t * and return that.
1015 *
1016 * * On all other platforms, strings are encoded
1017 * to bytes using PyUnicode_FSConverter, then we
1018 * extract the char * from the bytes object and
1019 * return that.
1020 *
1021 * path_converter also optionally accepts signed
1022 * integers (representing open file descriptors) instead
1023 * of path strings.
1024 *
1025 * Input fields:
1026 * path.nullable
1027 * If nonzero, the path is permitted to be None.
1028 * path.allow_fd
1029 * If nonzero, the path is permitted to be a file handle
1030 * (a signed int) instead of a string.
1031 * path.function_name
1032 * If non-NULL, path_converter will use that as the name
1033 * of the function in error messages.
1034 * (If path.function_name is NULL it omits the function name.)
1035 * path.argument_name
1036 * If non-NULL, path_converter will use that as the name
1037 * of the parameter in error messages.
1038 * (If path.argument_name is NULL it uses "path".)
1039 *
1040 * Output fields:
1041 * path.wide
1042 * Points to the path if it was expressed as Unicode
1043 * and was not encoded. (Only used on Windows.)
1044 * path.narrow
1045 * Points to the path if it was expressed as bytes,
1046 * or it was Unicode and was encoded to bytes. (On Windows,
1047 * is a non-zero integer if the path was expressed as bytes.
1048 * The type is deliberately incompatible to prevent misuse.)
1049 * path.fd
1050 * Contains a file descriptor if path.accept_fd was true
1051 * and the caller provided a signed integer instead of any
1052 * sort of string.
1053 *
1054 * WARNING: if your "path" parameter is optional, and is
1055 * unspecified, path_converter will never get called.
1056 * So if you set allow_fd, you *MUST* initialize path.fd = -1
1057 * yourself!
1058 * path.length
1059 * The length of the path in characters, if specified as
1060 * a string.
1061 * path.object
1062 * The original object passed in (if get a PathLike object,
1063 * the result of PyOS_FSPath() is treated as the original object).
1064 * Own a reference to the object.
1065 * path.cleanup
1066 * For internal use only. May point to a temporary object.
1067 * (Pay no attention to the man behind the curtain.)
1068 *
1069 * At most one of path.wide or path.narrow will be non-NULL.
1070 * If path was None and path.nullable was set,
1071 * or if path was an integer and path.allow_fd was set,
1072 * both path.wide and path.narrow will be NULL
1073 * and path.length will be 0.
1074 *
1075 * path_converter takes care to not write to the path_t
1076 * unless it's successful. However it must reset the
1077 * "cleanup" field each time it's called.
1078 *
1079 * Use as follows:
1080 * path_t path;
1081 * memset(&path, 0, sizeof(path));
1082 * PyArg_ParseTuple(args, "O&", path_converter, &path);
1083 * // ... use values from path ...
1084 * path_cleanup(&path);
1085 *
1086 * (Note that if PyArg_Parse fails you don't need to call
1087 * path_cleanup(). However it is safe to do so.)
1088 */
1089 typedef struct {
1090 const char *function_name;
1091 const char *argument_name;
1092 int nullable;
1093 int allow_fd;
1094 const wchar_t *wide;
1095 #ifdef MS_WINDOWS
1096 BOOL narrow;
1097 #else
1098 const char *narrow;
1099 #endif
1100 int fd;
1101 Py_ssize_t length;
1102 PyObject *object;
1103 PyObject *cleanup;
1104 } path_t;
1105
1106 #ifdef MS_WINDOWS
1107 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1108 {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
1109 #else
1110 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1111 {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
1112 #endif
1113
1114 static void
path_cleanup(path_t * path)1115 path_cleanup(path_t *path)
1116 {
1117 #if !USE_UNICODE_WCHAR_CACHE
1118 wchar_t *wide = (wchar_t *)path->wide;
1119 path->wide = NULL;
1120 PyMem_Free(wide);
1121 #endif /* USE_UNICODE_WCHAR_CACHE */
1122 Py_CLEAR(path->object);
1123 Py_CLEAR(path->cleanup);
1124 }
1125
1126 static int
path_converter(PyObject * o,void * p)1127 path_converter(PyObject *o, void *p)
1128 {
1129 path_t *path = (path_t *)p;
1130 PyObject *bytes = NULL;
1131 Py_ssize_t length = 0;
1132 int is_index, is_buffer, is_bytes, is_unicode;
1133 const char *narrow;
1134 #ifdef MS_WINDOWS
1135 PyObject *wo = NULL;
1136 wchar_t *wide = NULL;
1137 #endif
1138
1139 #define FORMAT_EXCEPTION(exc, fmt) \
1140 PyErr_Format(exc, "%s%s" fmt, \
1141 path->function_name ? path->function_name : "", \
1142 path->function_name ? ": " : "", \
1143 path->argument_name ? path->argument_name : "path")
1144
1145 /* Py_CLEANUP_SUPPORTED support */
1146 if (o == NULL) {
1147 path_cleanup(path);
1148 return 1;
1149 }
1150
1151 /* Ensure it's always safe to call path_cleanup(). */
1152 path->object = path->cleanup = NULL;
1153 /* path->object owns a reference to the original object */
1154 Py_INCREF(o);
1155
1156 if ((o == Py_None) && path->nullable) {
1157 path->wide = NULL;
1158 #ifdef MS_WINDOWS
1159 path->narrow = FALSE;
1160 #else
1161 path->narrow = NULL;
1162 #endif
1163 path->fd = -1;
1164 goto success_exit;
1165 }
1166
1167 /* Only call this here so that we don't treat the return value of
1168 os.fspath() as an fd or buffer. */
1169 is_index = path->allow_fd && PyIndex_Check(o);
1170 is_buffer = PyObject_CheckBuffer(o);
1171 is_bytes = PyBytes_Check(o);
1172 is_unicode = PyUnicode_Check(o);
1173
1174 if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
1175 /* Inline PyOS_FSPath() for better error messages. */
1176 PyObject *func, *res;
1177
1178 func = _PyObject_LookupSpecial(o, &PyId___fspath__);
1179 if (NULL == func) {
1180 goto error_format;
1181 }
1182 res = _PyObject_CallNoArg(func);
1183 Py_DECREF(func);
1184 if (NULL == res) {
1185 goto error_exit;
1186 }
1187 else if (PyUnicode_Check(res)) {
1188 is_unicode = 1;
1189 }
1190 else if (PyBytes_Check(res)) {
1191 is_bytes = 1;
1192 }
1193 else {
1194 PyErr_Format(PyExc_TypeError,
1195 "expected %.200s.__fspath__() to return str or bytes, "
1196 "not %.200s", _PyType_Name(Py_TYPE(o)),
1197 _PyType_Name(Py_TYPE(res)));
1198 Py_DECREF(res);
1199 goto error_exit;
1200 }
1201
1202 /* still owns a reference to the original object */
1203 Py_DECREF(o);
1204 o = res;
1205 }
1206
1207 if (is_unicode) {
1208 #ifdef MS_WINDOWS
1209 #if USE_UNICODE_WCHAR_CACHE
1210 _Py_COMP_DIAG_PUSH
1211 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1212 wide = PyUnicode_AsUnicodeAndSize(o, &length);
1213 _Py_COMP_DIAG_POP
1214 #else /* USE_UNICODE_WCHAR_CACHE */
1215 wide = PyUnicode_AsWideCharString(o, &length);
1216 #endif /* USE_UNICODE_WCHAR_CACHE */
1217 if (!wide) {
1218 goto error_exit;
1219 }
1220 if (length > 32767) {
1221 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1222 goto error_exit;
1223 }
1224 if (wcslen(wide) != length) {
1225 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1226 goto error_exit;
1227 }
1228
1229 path->wide = wide;
1230 path->narrow = FALSE;
1231 path->fd = -1;
1232 #if !USE_UNICODE_WCHAR_CACHE
1233 wide = NULL;
1234 #endif /* USE_UNICODE_WCHAR_CACHE */
1235 goto success_exit;
1236 #else
1237 if (!PyUnicode_FSConverter(o, &bytes)) {
1238 goto error_exit;
1239 }
1240 #endif
1241 }
1242 else if (is_bytes) {
1243 bytes = o;
1244 Py_INCREF(bytes);
1245 }
1246 else if (is_buffer) {
1247 /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1248 after removing support of non-bytes buffer objects. */
1249 if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
1250 "%s%s%s should be %s, not %.200s",
1251 path->function_name ? path->function_name : "",
1252 path->function_name ? ": " : "",
1253 path->argument_name ? path->argument_name : "path",
1254 path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1255 "integer or None" :
1256 path->allow_fd ? "string, bytes, os.PathLike or integer" :
1257 path->nullable ? "string, bytes, os.PathLike or None" :
1258 "string, bytes or os.PathLike",
1259 _PyType_Name(Py_TYPE(o)))) {
1260 goto error_exit;
1261 }
1262 bytes = PyBytes_FromObject(o);
1263 if (!bytes) {
1264 goto error_exit;
1265 }
1266 }
1267 else if (is_index) {
1268 if (!_fd_converter(o, &path->fd)) {
1269 goto error_exit;
1270 }
1271 path->wide = NULL;
1272 #ifdef MS_WINDOWS
1273 path->narrow = FALSE;
1274 #else
1275 path->narrow = NULL;
1276 #endif
1277 goto success_exit;
1278 }
1279 else {
1280 error_format:
1281 PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1282 path->function_name ? path->function_name : "",
1283 path->function_name ? ": " : "",
1284 path->argument_name ? path->argument_name : "path",
1285 path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1286 "integer or None" :
1287 path->allow_fd ? "string, bytes, os.PathLike or integer" :
1288 path->nullable ? "string, bytes, os.PathLike or None" :
1289 "string, bytes or os.PathLike",
1290 _PyType_Name(Py_TYPE(o)));
1291 goto error_exit;
1292 }
1293
1294 length = PyBytes_GET_SIZE(bytes);
1295 narrow = PyBytes_AS_STRING(bytes);
1296 if ((size_t)length != strlen(narrow)) {
1297 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1298 goto error_exit;
1299 }
1300
1301 #ifdef MS_WINDOWS
1302 wo = PyUnicode_DecodeFSDefaultAndSize(
1303 narrow,
1304 length
1305 );
1306 if (!wo) {
1307 goto error_exit;
1308 }
1309
1310 #if USE_UNICODE_WCHAR_CACHE
1311 _Py_COMP_DIAG_PUSH
1312 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1313 wide = PyUnicode_AsUnicodeAndSize(wo, &length);
1314 _Py_COMP_DIAG_POP
1315 #else /* USE_UNICODE_WCHAR_CACHE */
1316 wide = PyUnicode_AsWideCharString(wo, &length);
1317 Py_DECREF(wo);
1318 #endif /* USE_UNICODE_WCHAR_CACHE */
1319 if (!wide) {
1320 goto error_exit;
1321 }
1322 if (length > 32767) {
1323 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1324 goto error_exit;
1325 }
1326 if (wcslen(wide) != length) {
1327 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1328 goto error_exit;
1329 }
1330 path->wide = wide;
1331 path->narrow = TRUE;
1332 Py_DECREF(bytes);
1333 #if USE_UNICODE_WCHAR_CACHE
1334 path->cleanup = wo;
1335 #else /* USE_UNICODE_WCHAR_CACHE */
1336 wide = NULL;
1337 #endif /* USE_UNICODE_WCHAR_CACHE */
1338 #else
1339 path->wide = NULL;
1340 path->narrow = narrow;
1341 if (bytes == o) {
1342 /* Still a reference owned by path->object, don't have to
1343 worry about path->narrow is used after free. */
1344 Py_DECREF(bytes);
1345 }
1346 else {
1347 path->cleanup = bytes;
1348 }
1349 #endif
1350 path->fd = -1;
1351
1352 success_exit:
1353 path->length = length;
1354 path->object = o;
1355 return Py_CLEANUP_SUPPORTED;
1356
1357 error_exit:
1358 Py_XDECREF(o);
1359 Py_XDECREF(bytes);
1360 #ifdef MS_WINDOWS
1361 #if USE_UNICODE_WCHAR_CACHE
1362 Py_XDECREF(wo);
1363 #else /* USE_UNICODE_WCHAR_CACHE */
1364 PyMem_Free(wide);
1365 #endif /* USE_UNICODE_WCHAR_CACHE */
1366 #endif
1367 return 0;
1368 }
1369
1370 static void
argument_unavailable_error(const char * function_name,const char * argument_name)1371 argument_unavailable_error(const char *function_name, const char *argument_name)
1372 {
1373 PyErr_Format(PyExc_NotImplementedError,
1374 "%s%s%s unavailable on this platform",
1375 (function_name != NULL) ? function_name : "",
1376 (function_name != NULL) ? ": ": "",
1377 argument_name);
1378 }
1379
1380 static int
dir_fd_unavailable(PyObject * o,void * p)1381 dir_fd_unavailable(PyObject *o, void *p)
1382 {
1383 int dir_fd;
1384 if (!dir_fd_converter(o, &dir_fd))
1385 return 0;
1386 if (dir_fd != DEFAULT_DIR_FD) {
1387 argument_unavailable_error(NULL, "dir_fd");
1388 return 0;
1389 }
1390 *(int *)p = dir_fd;
1391 return 1;
1392 }
1393
1394 static int
fd_specified(const char * function_name,int fd)1395 fd_specified(const char *function_name, int fd)
1396 {
1397 if (fd == -1)
1398 return 0;
1399
1400 argument_unavailable_error(function_name, "fd");
1401 return 1;
1402 }
1403
1404 static int
follow_symlinks_specified(const char * function_name,int follow_symlinks)1405 follow_symlinks_specified(const char *function_name, int follow_symlinks)
1406 {
1407 if (follow_symlinks)
1408 return 0;
1409
1410 argument_unavailable_error(function_name, "follow_symlinks");
1411 return 1;
1412 }
1413
1414 static int
path_and_dir_fd_invalid(const char * function_name,path_t * path,int dir_fd)1415 path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1416 {
1417 if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1418 #ifndef MS_WINDOWS
1419 && !path->narrow
1420 #endif
1421 ) {
1422 PyErr_Format(PyExc_ValueError,
1423 "%s: can't specify dir_fd without matching path",
1424 function_name);
1425 return 1;
1426 }
1427 return 0;
1428 }
1429
1430 static int
dir_fd_and_fd_invalid(const char * function_name,int dir_fd,int fd)1431 dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1432 {
1433 if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1434 PyErr_Format(PyExc_ValueError,
1435 "%s: can't specify both dir_fd and fd",
1436 function_name);
1437 return 1;
1438 }
1439 return 0;
1440 }
1441
1442 static int
fd_and_follow_symlinks_invalid(const char * function_name,int fd,int follow_symlinks)1443 fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1444 int follow_symlinks)
1445 {
1446 if ((fd > 0) && (!follow_symlinks)) {
1447 PyErr_Format(PyExc_ValueError,
1448 "%s: cannot use fd and follow_symlinks together",
1449 function_name);
1450 return 1;
1451 }
1452 return 0;
1453 }
1454
1455 static int
dir_fd_and_follow_symlinks_invalid(const char * function_name,int dir_fd,int follow_symlinks)1456 dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1457 int follow_symlinks)
1458 {
1459 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1460 PyErr_Format(PyExc_ValueError,
1461 "%s: cannot use dir_fd and follow_symlinks together",
1462 function_name);
1463 return 1;
1464 }
1465 return 0;
1466 }
1467
1468 #ifdef MS_WINDOWS
1469 typedef long long Py_off_t;
1470 #else
1471 typedef off_t Py_off_t;
1472 #endif
1473
1474 static int
Py_off_t_converter(PyObject * arg,void * addr)1475 Py_off_t_converter(PyObject *arg, void *addr)
1476 {
1477 #ifdef HAVE_LARGEFILE_SUPPORT
1478 *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1479 #else
1480 *((Py_off_t *)addr) = PyLong_AsLong(arg);
1481 #endif
1482 if (PyErr_Occurred())
1483 return 0;
1484 return 1;
1485 }
1486
1487 static PyObject *
PyLong_FromPy_off_t(Py_off_t offset)1488 PyLong_FromPy_off_t(Py_off_t offset)
1489 {
1490 #ifdef HAVE_LARGEFILE_SUPPORT
1491 return PyLong_FromLongLong(offset);
1492 #else
1493 return PyLong_FromLong(offset);
1494 #endif
1495 }
1496
1497 #ifdef HAVE_SIGSET_T
1498 /* Convert an iterable of integers to a sigset.
1499 Return 1 on success, return 0 and raise an exception on error. */
1500 int
_Py_Sigset_Converter(PyObject * obj,void * addr)1501 _Py_Sigset_Converter(PyObject *obj, void *addr)
1502 {
1503 sigset_t *mask = (sigset_t *)addr;
1504 PyObject *iterator, *item;
1505 long signum;
1506 int overflow;
1507
1508 // The extra parens suppress the unreachable-code warning with clang on MacOS
1509 if (sigemptyset(mask) < (0)) {
1510 /* Probably only if mask == NULL. */
1511 PyErr_SetFromErrno(PyExc_OSError);
1512 return 0;
1513 }
1514
1515 iterator = PyObject_GetIter(obj);
1516 if (iterator == NULL) {
1517 return 0;
1518 }
1519
1520 while ((item = PyIter_Next(iterator)) != NULL) {
1521 signum = PyLong_AsLongAndOverflow(item, &overflow);
1522 Py_DECREF(item);
1523 if (signum <= 0 || signum >= NSIG) {
1524 if (overflow || signum != -1 || !PyErr_Occurred()) {
1525 PyErr_Format(PyExc_ValueError,
1526 "signal number %ld out of range", signum);
1527 }
1528 goto error;
1529 }
1530 if (sigaddset(mask, (int)signum)) {
1531 if (errno != EINVAL) {
1532 /* Probably impossible */
1533 PyErr_SetFromErrno(PyExc_OSError);
1534 goto error;
1535 }
1536 /* For backwards compatibility, allow idioms such as
1537 * `range(1, NSIG)` but warn about invalid signal numbers
1538 */
1539 const char msg[] =
1540 "invalid signal number %ld, please use valid_signals()";
1541 if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1542 goto error;
1543 }
1544 }
1545 }
1546 if (!PyErr_Occurred()) {
1547 Py_DECREF(iterator);
1548 return 1;
1549 }
1550
1551 error:
1552 Py_DECREF(iterator);
1553 return 0;
1554 }
1555 #endif /* HAVE_SIGSET_T */
1556
1557 #ifdef MS_WINDOWS
1558
1559 static int
win32_get_reparse_tag(HANDLE reparse_point_handle,ULONG * reparse_tag)1560 win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1561 {
1562 char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1563 _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1564 DWORD n_bytes_returned;
1565
1566 if (0 == DeviceIoControl(
1567 reparse_point_handle,
1568 FSCTL_GET_REPARSE_POINT,
1569 NULL, 0, /* in buffer */
1570 target_buffer, sizeof(target_buffer),
1571 &n_bytes_returned,
1572 NULL)) /* we're not using OVERLAPPED_IO */
1573 return FALSE;
1574
1575 if (reparse_tag)
1576 *reparse_tag = rdb->ReparseTag;
1577
1578 return TRUE;
1579 }
1580
1581 #endif /* MS_WINDOWS */
1582
1583 /* Return a dictionary corresponding to the POSIX environment table */
1584 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1585 /* On Darwin/MacOSX a shared library or framework has no access to
1586 ** environ directly, we must obtain it with _NSGetEnviron(). See also
1587 ** man environ(7).
1588 */
1589 #include <crt_externs.h>
1590 #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1591 extern char **environ;
1592 #endif /* !_MSC_VER */
1593
1594 static PyObject *
convertenviron(void)1595 convertenviron(void)
1596 {
1597 PyObject *d;
1598 #ifdef MS_WINDOWS
1599 wchar_t **e;
1600 #else
1601 char **e;
1602 #endif
1603
1604 d = PyDict_New();
1605 if (d == NULL)
1606 return NULL;
1607 #ifdef MS_WINDOWS
1608 /* _wenviron must be initialized in this way if the program is started
1609 through main() instead of wmain(). */
1610 _wgetenv(L"");
1611 e = _wenviron;
1612 #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1613 /* environ is not accessible as an extern in a shared object on OSX; use
1614 _NSGetEnviron to resolve it. The value changes if you add environment
1615 variables between calls to Py_Initialize, so don't cache the value. */
1616 e = *_NSGetEnviron();
1617 #else
1618 e = environ;
1619 #endif
1620 if (e == NULL)
1621 return d;
1622 for (; *e != NULL; e++) {
1623 PyObject *k;
1624 PyObject *v;
1625 #ifdef MS_WINDOWS
1626 const wchar_t *p = wcschr(*e, L'=');
1627 #else
1628 const char *p = strchr(*e, '=');
1629 #endif
1630 if (p == NULL)
1631 continue;
1632 #ifdef MS_WINDOWS
1633 k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1634 #else
1635 k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1636 #endif
1637 if (k == NULL) {
1638 Py_DECREF(d);
1639 return NULL;
1640 }
1641 #ifdef MS_WINDOWS
1642 v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1643 #else
1644 v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1645 #endif
1646 if (v == NULL) {
1647 Py_DECREF(k);
1648 Py_DECREF(d);
1649 return NULL;
1650 }
1651 if (PyDict_SetDefault(d, k, v) == NULL) {
1652 Py_DECREF(v);
1653 Py_DECREF(k);
1654 Py_DECREF(d);
1655 return NULL;
1656 }
1657 Py_DECREF(k);
1658 Py_DECREF(v);
1659 }
1660 return d;
1661 }
1662
1663 /* Set a POSIX-specific error from errno, and return NULL */
1664
1665 static PyObject *
posix_error(void)1666 posix_error(void)
1667 {
1668 return PyErr_SetFromErrno(PyExc_OSError);
1669 }
1670
1671 #ifdef MS_WINDOWS
1672 static PyObject *
win32_error(const char * function,const char * filename)1673 win32_error(const char* function, const char* filename)
1674 {
1675 /* XXX We should pass the function name along in the future.
1676 (winreg.c also wants to pass the function name.)
1677 This would however require an additional param to the
1678 Windows error object, which is non-trivial.
1679 */
1680 errno = GetLastError();
1681 if (filename)
1682 return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1683 else
1684 return PyErr_SetFromWindowsErr(errno);
1685 }
1686
1687 static PyObject *
win32_error_object_err(const char * function,PyObject * filename,DWORD err)1688 win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1689 {
1690 /* XXX - see win32_error for comments on 'function' */
1691 if (filename)
1692 return PyErr_SetExcFromWindowsErrWithFilenameObject(
1693 PyExc_OSError,
1694 err,
1695 filename);
1696 else
1697 return PyErr_SetFromWindowsErr(err);
1698 }
1699
1700 static PyObject *
win32_error_object(const char * function,PyObject * filename)1701 win32_error_object(const char* function, PyObject* filename)
1702 {
1703 errno = GetLastError();
1704 return win32_error_object_err(function, filename, errno);
1705 }
1706
1707 #endif /* MS_WINDOWS */
1708
1709 static PyObject *
posix_path_object_error(PyObject * path)1710 posix_path_object_error(PyObject *path)
1711 {
1712 return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1713 }
1714
1715 static PyObject *
path_object_error(PyObject * path)1716 path_object_error(PyObject *path)
1717 {
1718 #ifdef MS_WINDOWS
1719 return PyErr_SetExcFromWindowsErrWithFilenameObject(
1720 PyExc_OSError, 0, path);
1721 #else
1722 return posix_path_object_error(path);
1723 #endif
1724 }
1725
1726 static PyObject *
path_object_error2(PyObject * path,PyObject * path2)1727 path_object_error2(PyObject *path, PyObject *path2)
1728 {
1729 #ifdef MS_WINDOWS
1730 return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1731 PyExc_OSError, 0, path, path2);
1732 #else
1733 return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1734 #endif
1735 }
1736
1737 static PyObject *
path_error(path_t * path)1738 path_error(path_t *path)
1739 {
1740 return path_object_error(path->object);
1741 }
1742
1743 static PyObject *
posix_path_error(path_t * path)1744 posix_path_error(path_t *path)
1745 {
1746 return posix_path_object_error(path->object);
1747 }
1748
1749 static PyObject *
path_error2(path_t * path,path_t * path2)1750 path_error2(path_t *path, path_t *path2)
1751 {
1752 return path_object_error2(path->object, path2->object);
1753 }
1754
1755
1756 /* POSIX generic methods */
1757
1758 static PyObject *
posix_fildes_fd(int fd,int (* func)(int))1759 posix_fildes_fd(int fd, int (*func)(int))
1760 {
1761 int res;
1762 int async_err = 0;
1763
1764 do {
1765 Py_BEGIN_ALLOW_THREADS
1766 _Py_BEGIN_SUPPRESS_IPH
1767 res = (*func)(fd);
1768 _Py_END_SUPPRESS_IPH
1769 Py_END_ALLOW_THREADS
1770 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1771 if (res != 0)
1772 return (!async_err) ? posix_error() : NULL;
1773 Py_RETURN_NONE;
1774 }
1775
1776
1777 #ifdef MS_WINDOWS
1778 /* This is a reimplementation of the C library's chdir function,
1779 but one that produces Win32 errors instead of DOS error codes.
1780 chdir is essentially a wrapper around SetCurrentDirectory; however,
1781 it also needs to set "magic" environment variables indicating
1782 the per-drive current directory, which are of the form =<drive>: */
1783 static BOOL __stdcall
win32_wchdir(LPCWSTR path)1784 win32_wchdir(LPCWSTR path)
1785 {
1786 wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1787 int result;
1788 wchar_t env[4] = L"=x:";
1789
1790 if(!SetCurrentDirectoryW(path))
1791 return FALSE;
1792 result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1793 if (!result)
1794 return FALSE;
1795 if (result > Py_ARRAY_LENGTH(path_buf)) {
1796 new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1797 if (!new_path) {
1798 SetLastError(ERROR_OUTOFMEMORY);
1799 return FALSE;
1800 }
1801 result = GetCurrentDirectoryW(result, new_path);
1802 if (!result) {
1803 PyMem_RawFree(new_path);
1804 return FALSE;
1805 }
1806 }
1807 int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1808 wcsncmp(new_path, L"//", 2) == 0);
1809 if (!is_unc_like_path) {
1810 env[1] = new_path[0];
1811 result = SetEnvironmentVariableW(env, new_path);
1812 }
1813 if (new_path != path_buf)
1814 PyMem_RawFree(new_path);
1815 return result ? TRUE : FALSE;
1816 }
1817 #endif
1818
1819 #ifdef MS_WINDOWS
1820 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1821 - time stamps are restricted to second resolution
1822 - file modification times suffer from forth-and-back conversions between
1823 UTC and local time
1824 Therefore, we implement our own stat, based on the Win32 API directly.
1825 */
1826 #define HAVE_STAT_NSEC 1
1827 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1828 #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1829
1830 static void
find_data_to_file_info(WIN32_FIND_DATAW * pFileData,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1831 find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1832 BY_HANDLE_FILE_INFORMATION *info,
1833 ULONG *reparse_tag)
1834 {
1835 memset(info, 0, sizeof(*info));
1836 info->dwFileAttributes = pFileData->dwFileAttributes;
1837 info->ftCreationTime = pFileData->ftCreationTime;
1838 info->ftLastAccessTime = pFileData->ftLastAccessTime;
1839 info->ftLastWriteTime = pFileData->ftLastWriteTime;
1840 info->nFileSizeHigh = pFileData->nFileSizeHigh;
1841 info->nFileSizeLow = pFileData->nFileSizeLow;
1842 /* info->nNumberOfLinks = 1; */
1843 if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1844 *reparse_tag = pFileData->dwReserved0;
1845 else
1846 *reparse_tag = 0;
1847 }
1848
1849 static BOOL
attributes_from_dir(LPCWSTR pszFile,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1850 attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1851 {
1852 HANDLE hFindFile;
1853 WIN32_FIND_DATAW FileData;
1854 LPCWSTR filename = pszFile;
1855 size_t n = wcslen(pszFile);
1856 if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
1857 // cannot use PyMem_Malloc here because we do not hold the GIL
1858 filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
1859 wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
1860 while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
1861 ((LPWSTR)filename)[n] = L'\0';
1862 }
1863 if (!n || (n == 1 && filename[1] == L':')) {
1864 // Nothing left to query
1865 free((void *)filename);
1866 return FALSE;
1867 }
1868 }
1869 hFindFile = FindFirstFileW(filename, &FileData);
1870 if (pszFile != filename) {
1871 free((void *)filename);
1872 }
1873 if (hFindFile == INVALID_HANDLE_VALUE) {
1874 return FALSE;
1875 }
1876 FindClose(hFindFile);
1877 find_data_to_file_info(&FileData, info, reparse_tag);
1878 return TRUE;
1879 }
1880
1881 static int
win32_xstat_impl(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1882 win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1883 BOOL traverse)
1884 {
1885 HANDLE hFile;
1886 BY_HANDLE_FILE_INFORMATION fileInfo;
1887 FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1888 DWORD fileType, error;
1889 BOOL isUnhandledTag = FALSE;
1890 int retval = 0;
1891
1892 DWORD access = FILE_READ_ATTRIBUTES;
1893 DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1894 if (!traverse) {
1895 flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1896 }
1897
1898 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1899 if (hFile == INVALID_HANDLE_VALUE) {
1900 /* Either the path doesn't exist, or the caller lacks access. */
1901 error = GetLastError();
1902 switch (error) {
1903 case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */
1904 case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1905 /* Try reading the parent directory. */
1906 if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1907 /* Cannot read the parent directory. */
1908 SetLastError(error);
1909 return -1;
1910 }
1911 if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1912 if (traverse ||
1913 !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1914 /* The stat call has to traverse but cannot, so fail. */
1915 SetLastError(error);
1916 return -1;
1917 }
1918 }
1919 break;
1920
1921 case ERROR_INVALID_PARAMETER:
1922 /* \\.\con requires read or write access. */
1923 hFile = CreateFileW(path, access | GENERIC_READ,
1924 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1925 OPEN_EXISTING, flags, NULL);
1926 if (hFile == INVALID_HANDLE_VALUE) {
1927 SetLastError(error);
1928 return -1;
1929 }
1930 break;
1931
1932 case ERROR_CANT_ACCESS_FILE:
1933 /* bpo37834: open unhandled reparse points if traverse fails. */
1934 if (traverse) {
1935 traverse = FALSE;
1936 isUnhandledTag = TRUE;
1937 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1938 flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1939 }
1940 if (hFile == INVALID_HANDLE_VALUE) {
1941 SetLastError(error);
1942 return -1;
1943 }
1944 break;
1945
1946 default:
1947 return -1;
1948 }
1949 }
1950
1951 if (hFile != INVALID_HANDLE_VALUE) {
1952 /* Handle types other than files on disk. */
1953 fileType = GetFileType(hFile);
1954 if (fileType != FILE_TYPE_DISK) {
1955 if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1956 retval = -1;
1957 goto cleanup;
1958 }
1959 DWORD fileAttributes = GetFileAttributesW(path);
1960 memset(result, 0, sizeof(*result));
1961 if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1962 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1963 /* \\.\pipe\ or \\.\mailslot\ */
1964 result->st_mode = _S_IFDIR;
1965 } else if (fileType == FILE_TYPE_CHAR) {
1966 /* \\.\nul */
1967 result->st_mode = _S_IFCHR;
1968 } else if (fileType == FILE_TYPE_PIPE) {
1969 /* \\.\pipe\spam */
1970 result->st_mode = _S_IFIFO;
1971 }
1972 /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1973 goto cleanup;
1974 }
1975
1976 /* Query the reparse tag, and traverse a non-link. */
1977 if (!traverse) {
1978 if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
1979 &tagInfo, sizeof(tagInfo))) {
1980 /* Allow devices that do not support FileAttributeTagInfo. */
1981 switch (GetLastError()) {
1982 case ERROR_INVALID_PARAMETER:
1983 case ERROR_INVALID_FUNCTION:
1984 case ERROR_NOT_SUPPORTED:
1985 tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1986 tagInfo.ReparseTag = 0;
1987 break;
1988 default:
1989 retval = -1;
1990 goto cleanup;
1991 }
1992 } else if (tagInfo.FileAttributes &
1993 FILE_ATTRIBUTE_REPARSE_POINT) {
1994 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1995 if (isUnhandledTag) {
1996 /* Traversing previously failed for either this link
1997 or its target. */
1998 SetLastError(ERROR_CANT_ACCESS_FILE);
1999 retval = -1;
2000 goto cleanup;
2001 }
2002 /* Traverse a non-link, but not if traversing already failed
2003 for an unhandled tag. */
2004 } else if (!isUnhandledTag) {
2005 CloseHandle(hFile);
2006 return win32_xstat_impl(path, result, TRUE);
2007 }
2008 }
2009 }
2010
2011 if (!GetFileInformationByHandle(hFile, &fileInfo)) {
2012 switch (GetLastError()) {
2013 case ERROR_INVALID_PARAMETER:
2014 case ERROR_INVALID_FUNCTION:
2015 case ERROR_NOT_SUPPORTED:
2016 /* Volumes and physical disks are block devices, e.g.
2017 \\.\C: and \\.\PhysicalDrive0. */
2018 memset(result, 0, sizeof(*result));
2019 result->st_mode = 0x6000; /* S_IFBLK */
2020 goto cleanup;
2021 }
2022 retval = -1;
2023 goto cleanup;
2024 }
2025 }
2026
2027 _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
2028
2029 if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
2030 /* Fix the file execute permissions. This hack sets S_IEXEC if
2031 the filename has an extension that is commonly used by files
2032 that CreateProcessW can execute. A real implementation calls
2033 GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2034 AccessCheck to check for generic read, write, and execute
2035 access. */
2036 const wchar_t *fileExtension = wcsrchr(path, '.');
2037 if (fileExtension) {
2038 if (_wcsicmp(fileExtension, L".exe") == 0 ||
2039 _wcsicmp(fileExtension, L".bat") == 0 ||
2040 _wcsicmp(fileExtension, L".cmd") == 0 ||
2041 _wcsicmp(fileExtension, L".com") == 0) {
2042 result->st_mode |= 0111;
2043 }
2044 }
2045 }
2046
2047 cleanup:
2048 if (hFile != INVALID_HANDLE_VALUE) {
2049 /* Preserve last error if we are failing */
2050 error = retval ? GetLastError() : 0;
2051 if (!CloseHandle(hFile)) {
2052 retval = -1;
2053 } else if (retval) {
2054 /* Restore last error */
2055 SetLastError(error);
2056 }
2057 }
2058
2059 return retval;
2060 }
2061
2062 static int
win32_xstat(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)2063 win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2064 {
2065 /* Protocol violation: we explicitly clear errno, instead of
2066 setting it to a POSIX error. Callers should use GetLastError. */
2067 int code = win32_xstat_impl(path, result, traverse);
2068 errno = 0;
2069 return code;
2070 }
2071 /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2072
2073 In Posix, stat automatically traverses symlinks and returns the stat
2074 structure for the target. In Windows, the equivalent GetFileAttributes by
2075 default does not traverse symlinks and instead returns attributes for
2076 the symlink.
2077
2078 Instead, we will open the file (which *does* traverse symlinks by default)
2079 and GetFileInformationByHandle(). */
2080
2081 static int
win32_lstat(const wchar_t * path,struct _Py_stat_struct * result)2082 win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2083 {
2084 return win32_xstat(path, result, FALSE);
2085 }
2086
2087 static int
win32_stat(const wchar_t * path,struct _Py_stat_struct * result)2088 win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2089 {
2090 return win32_xstat(path, result, TRUE);
2091 }
2092
2093 #endif /* MS_WINDOWS */
2094
2095 PyDoc_STRVAR(stat_result__doc__,
2096 "stat_result: Result from stat, fstat, or lstat.\n\n\
2097 This object may be accessed either as a tuple of\n\
2098 (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2099 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2100 \n\
2101 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2102 or st_flags, they are available as attributes only.\n\
2103 \n\
2104 See os.stat for more information.");
2105
2106 static PyStructSequence_Field stat_result_fields[] = {
2107 {"st_mode", "protection bits"},
2108 {"st_ino", "inode"},
2109 {"st_dev", "device"},
2110 {"st_nlink", "number of hard links"},
2111 {"st_uid", "user ID of owner"},
2112 {"st_gid", "group ID of owner"},
2113 {"st_size", "total size, in bytes"},
2114 /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2115 {NULL, "integer time of last access"},
2116 {NULL, "integer time of last modification"},
2117 {NULL, "integer time of last change"},
2118 {"st_atime", "time of last access"},
2119 {"st_mtime", "time of last modification"},
2120 {"st_ctime", "time of last change"},
2121 {"st_atime_ns", "time of last access in nanoseconds"},
2122 {"st_mtime_ns", "time of last modification in nanoseconds"},
2123 {"st_ctime_ns", "time of last change in nanoseconds"},
2124 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2125 {"st_blksize", "blocksize for filesystem I/O"},
2126 #endif
2127 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2128 {"st_blocks", "number of blocks allocated"},
2129 #endif
2130 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2131 {"st_rdev", "device type (if inode device)"},
2132 #endif
2133 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2134 {"st_flags", "user defined flags for file"},
2135 #endif
2136 #ifdef HAVE_STRUCT_STAT_ST_GEN
2137 {"st_gen", "generation number"},
2138 #endif
2139 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2140 {"st_birthtime", "time of creation"},
2141 #endif
2142 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2143 {"st_file_attributes", "Windows file attribute bits"},
2144 #endif
2145 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2146 {"st_fstype", "Type of filesystem"},
2147 #endif
2148 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2149 {"st_reparse_tag", "Windows reparse tag"},
2150 #endif
2151 {0}
2152 };
2153
2154 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2155 #define ST_BLKSIZE_IDX 16
2156 #else
2157 #define ST_BLKSIZE_IDX 15
2158 #endif
2159
2160 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2161 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2162 #else
2163 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2164 #endif
2165
2166 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2167 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2168 #else
2169 #define ST_RDEV_IDX ST_BLOCKS_IDX
2170 #endif
2171
2172 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2173 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2174 #else
2175 #define ST_FLAGS_IDX ST_RDEV_IDX
2176 #endif
2177
2178 #ifdef HAVE_STRUCT_STAT_ST_GEN
2179 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
2180 #else
2181 #define ST_GEN_IDX ST_FLAGS_IDX
2182 #endif
2183
2184 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2185 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2186 #else
2187 #define ST_BIRTHTIME_IDX ST_GEN_IDX
2188 #endif
2189
2190 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2191 #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
2192 #else
2193 #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
2194 #endif
2195
2196 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2197 #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2198 #else
2199 #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2200 #endif
2201
2202 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2203 #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2204 #else
2205 #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2206 #endif
2207
2208 static PyStructSequence_Desc stat_result_desc = {
2209 "stat_result", /* name */
2210 stat_result__doc__, /* doc */
2211 stat_result_fields,
2212 10
2213 };
2214
2215 PyDoc_STRVAR(statvfs_result__doc__,
2216 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
2217 This object may be accessed either as a tuple of\n\
2218 (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2219 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2220 \n\
2221 See os.statvfs for more information.");
2222
2223 static PyStructSequence_Field statvfs_result_fields[] = {
2224 {"f_bsize", },
2225 {"f_frsize", },
2226 {"f_blocks", },
2227 {"f_bfree", },
2228 {"f_bavail", },
2229 {"f_files", },
2230 {"f_ffree", },
2231 {"f_favail", },
2232 {"f_flag", },
2233 {"f_namemax",},
2234 {"f_fsid", },
2235 {0}
2236 };
2237
2238 static PyStructSequence_Desc statvfs_result_desc = {
2239 "statvfs_result", /* name */
2240 statvfs_result__doc__, /* doc */
2241 statvfs_result_fields,
2242 10
2243 };
2244
2245 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2246 PyDoc_STRVAR(waitid_result__doc__,
2247 "waitid_result: Result from waitid.\n\n\
2248 This object may be accessed either as a tuple of\n\
2249 (si_pid, si_uid, si_signo, si_status, si_code),\n\
2250 or via the attributes si_pid, si_uid, and so on.\n\
2251 \n\
2252 See os.waitid for more information.");
2253
2254 static PyStructSequence_Field waitid_result_fields[] = {
2255 {"si_pid", },
2256 {"si_uid", },
2257 {"si_signo", },
2258 {"si_status", },
2259 {"si_code", },
2260 {0}
2261 };
2262
2263 static PyStructSequence_Desc waitid_result_desc = {
2264 "waitid_result", /* name */
2265 waitid_result__doc__, /* doc */
2266 waitid_result_fields,
2267 5
2268 };
2269 #endif
2270 static newfunc structseq_new;
2271
2272 static PyObject *
statresult_new(PyTypeObject * type,PyObject * args,PyObject * kwds)2273 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2274 {
2275 PyStructSequence *result;
2276 int i;
2277
2278 result = (PyStructSequence*)structseq_new(type, args, kwds);
2279 if (!result)
2280 return NULL;
2281 /* If we have been initialized from a tuple,
2282 st_?time might be set to None. Initialize it
2283 from the int slots. */
2284 for (i = 7; i <= 9; i++) {
2285 if (result->ob_item[i+3] == Py_None) {
2286 Py_DECREF(Py_None);
2287 Py_INCREF(result->ob_item[i]);
2288 result->ob_item[i+3] = result->ob_item[i];
2289 }
2290 }
2291 return (PyObject*)result;
2292 }
2293
2294 static int
_posix_clear(PyObject * module)2295 _posix_clear(PyObject *module)
2296 {
2297 _posixstate *state = get_posix_state(module);
2298 Py_CLEAR(state->billion);
2299 Py_CLEAR(state->DirEntryType);
2300 Py_CLEAR(state->ScandirIteratorType);
2301 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2302 Py_CLEAR(state->SchedParamType);
2303 #endif
2304 Py_CLEAR(state->StatResultType);
2305 Py_CLEAR(state->StatVFSResultType);
2306 Py_CLEAR(state->TerminalSizeType);
2307 Py_CLEAR(state->TimesResultType);
2308 Py_CLEAR(state->UnameResultType);
2309 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2310 Py_CLEAR(state->WaitidResultType);
2311 #endif
2312 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2313 Py_CLEAR(state->struct_rusage);
2314 #endif
2315 Py_CLEAR(state->st_mode);
2316 return 0;
2317 }
2318
2319 static int
_posix_traverse(PyObject * module,visitproc visit,void * arg)2320 _posix_traverse(PyObject *module, visitproc visit, void *arg)
2321 {
2322 _posixstate *state = get_posix_state(module);
2323 Py_VISIT(state->billion);
2324 Py_VISIT(state->DirEntryType);
2325 Py_VISIT(state->ScandirIteratorType);
2326 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2327 Py_VISIT(state->SchedParamType);
2328 #endif
2329 Py_VISIT(state->StatResultType);
2330 Py_VISIT(state->StatVFSResultType);
2331 Py_VISIT(state->TerminalSizeType);
2332 Py_VISIT(state->TimesResultType);
2333 Py_VISIT(state->UnameResultType);
2334 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2335 Py_VISIT(state->WaitidResultType);
2336 #endif
2337 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2338 Py_VISIT(state->struct_rusage);
2339 #endif
2340 Py_VISIT(state->st_mode);
2341 return 0;
2342 }
2343
2344 static void
_posix_free(void * module)2345 _posix_free(void *module)
2346 {
2347 _posix_clear((PyObject *)module);
2348 }
2349
2350 static void
fill_time(PyObject * module,PyObject * v,int index,time_t sec,unsigned long nsec)2351 fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)
2352 {
2353 PyObject *s = _PyLong_FromTime_t(sec);
2354 PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2355 PyObject *s_in_ns = NULL;
2356 PyObject *ns_total = NULL;
2357 PyObject *float_s = NULL;
2358
2359 if (!(s && ns_fractional))
2360 goto exit;
2361
2362 s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2363 if (!s_in_ns)
2364 goto exit;
2365
2366 ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2367 if (!ns_total)
2368 goto exit;
2369
2370 float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2371 if (!float_s) {
2372 goto exit;
2373 }
2374
2375 PyStructSequence_SET_ITEM(v, index, s);
2376 PyStructSequence_SET_ITEM(v, index+3, float_s);
2377 PyStructSequence_SET_ITEM(v, index+6, ns_total);
2378 s = NULL;
2379 float_s = NULL;
2380 ns_total = NULL;
2381 exit:
2382 Py_XDECREF(s);
2383 Py_XDECREF(ns_fractional);
2384 Py_XDECREF(s_in_ns);
2385 Py_XDECREF(ns_total);
2386 Py_XDECREF(float_s);
2387 }
2388
2389 /* pack a system stat C structure into the Python stat tuple
2390 (used by posix_stat() and posix_fstat()) */
2391 static PyObject*
_pystat_fromstructstat(PyObject * module,STRUCT_STAT * st)2392 _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2393 {
2394 unsigned long ansec, mnsec, cnsec;
2395 PyObject *StatResultType = get_posix_state(module)->StatResultType;
2396 PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2397 if (v == NULL)
2398 return NULL;
2399
2400 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2401 Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(st->st_ino));
2402 PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2403 #ifdef MS_WINDOWS
2404 PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
2405 #else
2406 PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2407 #endif
2408 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2409 #if defined(MS_WINDOWS)
2410 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2411 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2412 #else
2413 PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2414 PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2415 #endif
2416 Py_BUILD_ASSERT(sizeof(long long) >= sizeof(st->st_size));
2417 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2418
2419 #if defined(HAVE_STAT_TV_NSEC)
2420 ansec = st->st_atim.tv_nsec;
2421 mnsec = st->st_mtim.tv_nsec;
2422 cnsec = st->st_ctim.tv_nsec;
2423 #elif defined(HAVE_STAT_TV_NSEC2)
2424 ansec = st->st_atimespec.tv_nsec;
2425 mnsec = st->st_mtimespec.tv_nsec;
2426 cnsec = st->st_ctimespec.tv_nsec;
2427 #elif defined(HAVE_STAT_NSEC)
2428 ansec = st->st_atime_nsec;
2429 mnsec = st->st_mtime_nsec;
2430 cnsec = st->st_ctime_nsec;
2431 #else
2432 ansec = mnsec = cnsec = 0;
2433 #endif
2434 fill_time(module, v, 7, st->st_atime, ansec);
2435 fill_time(module, v, 8, st->st_mtime, mnsec);
2436 fill_time(module, v, 9, st->st_ctime, cnsec);
2437
2438 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2439 PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2440 PyLong_FromLong((long)st->st_blksize));
2441 #endif
2442 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2443 PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2444 PyLong_FromLong((long)st->st_blocks));
2445 #endif
2446 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2447 PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2448 PyLong_FromLong((long)st->st_rdev));
2449 #endif
2450 #ifdef HAVE_STRUCT_STAT_ST_GEN
2451 PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2452 PyLong_FromLong((long)st->st_gen));
2453 #endif
2454 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2455 {
2456 PyObject *val;
2457 unsigned long bsec,bnsec;
2458 bsec = (long)st->st_birthtime;
2459 #ifdef HAVE_STAT_TV_NSEC2
2460 bnsec = st->st_birthtimespec.tv_nsec;
2461 #else
2462 bnsec = 0;
2463 #endif
2464 val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2465 PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2466 val);
2467 }
2468 #endif
2469 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2470 PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2471 PyLong_FromLong((long)st->st_flags));
2472 #endif
2473 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2474 PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2475 PyLong_FromUnsignedLong(st->st_file_attributes));
2476 #endif
2477 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2478 PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2479 PyUnicode_FromString(st->st_fstype));
2480 #endif
2481 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2482 PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2483 PyLong_FromUnsignedLong(st->st_reparse_tag));
2484 #endif
2485
2486 if (PyErr_Occurred()) {
2487 Py_DECREF(v);
2488 return NULL;
2489 }
2490
2491 return v;
2492 }
2493
2494 /* POSIX methods */
2495
2496
2497 static PyObject *
posix_do_stat(PyObject * module,const char * function_name,path_t * path,int dir_fd,int follow_symlinks)2498 posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2499 int dir_fd, int follow_symlinks)
2500 {
2501 STRUCT_STAT st;
2502 int result;
2503
2504 #ifdef HAVE_FSTATAT
2505 int fstatat_unavailable = 0;
2506 #endif
2507
2508 #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2509 if (follow_symlinks_specified(function_name, follow_symlinks))
2510 return NULL;
2511 #endif
2512
2513 if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2514 dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2515 fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2516 return NULL;
2517
2518 Py_BEGIN_ALLOW_THREADS
2519 if (path->fd != -1)
2520 result = FSTAT(path->fd, &st);
2521 #ifdef MS_WINDOWS
2522 else if (follow_symlinks)
2523 result = win32_stat(path->wide, &st);
2524 else
2525 result = win32_lstat(path->wide, &st);
2526 #else
2527 else
2528 #if defined(HAVE_LSTAT)
2529 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2530 result = LSTAT(path->narrow, &st);
2531 else
2532 #endif /* HAVE_LSTAT */
2533 #ifdef HAVE_FSTATAT
2534 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2535 if (HAVE_FSTATAT_RUNTIME) {
2536 result = fstatat(dir_fd, path->narrow, &st,
2537 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2538
2539 } else {
2540 fstatat_unavailable = 1;
2541 }
2542 } else
2543 #endif /* HAVE_FSTATAT */
2544 result = STAT(path->narrow, &st);
2545 #endif /* MS_WINDOWS */
2546 Py_END_ALLOW_THREADS
2547
2548 #ifdef HAVE_FSTATAT
2549 if (fstatat_unavailable) {
2550 argument_unavailable_error("stat", "dir_fd");
2551 return NULL;
2552 }
2553 #endif
2554
2555 if (result != 0) {
2556 return path_error(path);
2557 }
2558
2559 return _pystat_fromstructstat(module, &st);
2560 }
2561
2562 /*[python input]
2563
2564 for s in """
2565
2566 FACCESSAT
2567 FCHMODAT
2568 FCHOWNAT
2569 FSTATAT
2570 LINKAT
2571 MKDIRAT
2572 MKFIFOAT
2573 MKNODAT
2574 OPENAT
2575 READLINKAT
2576 SYMLINKAT
2577 UNLINKAT
2578
2579 """.strip().split():
2580 s = s.strip()
2581 print("""
2582 #ifdef HAVE_{s}
2583 #define {s}_DIR_FD_CONVERTER dir_fd_converter
2584 #else
2585 #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2586 #endif
2587 """.rstrip().format(s=s))
2588
2589 for s in """
2590
2591 FCHDIR
2592 FCHMOD
2593 FCHOWN
2594 FDOPENDIR
2595 FEXECVE
2596 FPATHCONF
2597 FSTATVFS
2598 FTRUNCATE
2599
2600 """.strip().split():
2601 s = s.strip()
2602 print("""
2603 #ifdef HAVE_{s}
2604 #define PATH_HAVE_{s} 1
2605 #else
2606 #define PATH_HAVE_{s} 0
2607 #endif
2608
2609 """.rstrip().format(s=s))
2610 [python start generated code]*/
2611
2612 #ifdef HAVE_FACCESSAT
2613 #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2614 #else
2615 #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2616 #endif
2617
2618 #ifdef HAVE_FCHMODAT
2619 #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2620 #else
2621 #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2622 #endif
2623
2624 #ifdef HAVE_FCHOWNAT
2625 #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2626 #else
2627 #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2628 #endif
2629
2630 #ifdef HAVE_FSTATAT
2631 #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2632 #else
2633 #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2634 #endif
2635
2636 #ifdef HAVE_LINKAT
2637 #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2638 #else
2639 #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2640 #endif
2641
2642 #ifdef HAVE_MKDIRAT
2643 #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2644 #else
2645 #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2646 #endif
2647
2648 #ifdef HAVE_MKFIFOAT
2649 #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2650 #else
2651 #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2652 #endif
2653
2654 #ifdef HAVE_MKNODAT
2655 #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2656 #else
2657 #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2658 #endif
2659
2660 #ifdef HAVE_OPENAT
2661 #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2662 #else
2663 #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2664 #endif
2665
2666 #ifdef HAVE_READLINKAT
2667 #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2668 #else
2669 #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2670 #endif
2671
2672 #ifdef HAVE_SYMLINKAT
2673 #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2674 #else
2675 #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2676 #endif
2677
2678 #ifdef HAVE_UNLINKAT
2679 #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2680 #else
2681 #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2682 #endif
2683
2684 #ifdef HAVE_FCHDIR
2685 #define PATH_HAVE_FCHDIR 1
2686 #else
2687 #define PATH_HAVE_FCHDIR 0
2688 #endif
2689
2690 #ifdef HAVE_FCHMOD
2691 #define PATH_HAVE_FCHMOD 1
2692 #else
2693 #define PATH_HAVE_FCHMOD 0
2694 #endif
2695
2696 #ifdef HAVE_FCHOWN
2697 #define PATH_HAVE_FCHOWN 1
2698 #else
2699 #define PATH_HAVE_FCHOWN 0
2700 #endif
2701
2702 #ifdef HAVE_FDOPENDIR
2703 #define PATH_HAVE_FDOPENDIR 1
2704 #else
2705 #define PATH_HAVE_FDOPENDIR 0
2706 #endif
2707
2708 #ifdef HAVE_FEXECVE
2709 #define PATH_HAVE_FEXECVE 1
2710 #else
2711 #define PATH_HAVE_FEXECVE 0
2712 #endif
2713
2714 #ifdef HAVE_FPATHCONF
2715 #define PATH_HAVE_FPATHCONF 1
2716 #else
2717 #define PATH_HAVE_FPATHCONF 0
2718 #endif
2719
2720 #ifdef HAVE_FSTATVFS
2721 #define PATH_HAVE_FSTATVFS 1
2722 #else
2723 #define PATH_HAVE_FSTATVFS 0
2724 #endif
2725
2726 #ifdef HAVE_FTRUNCATE
2727 #define PATH_HAVE_FTRUNCATE 1
2728 #else
2729 #define PATH_HAVE_FTRUNCATE 0
2730 #endif
2731 /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2732
2733 #ifdef MS_WINDOWS
2734 #undef PATH_HAVE_FTRUNCATE
2735 #define PATH_HAVE_FTRUNCATE 1
2736 #endif
2737
2738 /*[python input]
2739
2740 class path_t_converter(CConverter):
2741
2742 type = "path_t"
2743 impl_by_reference = True
2744 parse_by_reference = True
2745
2746 converter = 'path_converter'
2747
2748 def converter_init(self, *, allow_fd=False, nullable=False):
2749 # right now path_t doesn't support default values.
2750 # to support a default value, you'll need to override initialize().
2751 if self.default not in (unspecified, None):
2752 fail("Can't specify a default to the path_t converter!")
2753
2754 if self.c_default not in (None, 'Py_None'):
2755 raise RuntimeError("Can't specify a c_default to the path_t converter!")
2756
2757 self.nullable = nullable
2758 self.allow_fd = allow_fd
2759
2760 def pre_render(self):
2761 def strify(value):
2762 if isinstance(value, str):
2763 return value
2764 return str(int(bool(value)))
2765
2766 # add self.py_name here when merging with posixmodule conversion
2767 self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2768 self.function.name,
2769 self.name,
2770 strify(self.nullable),
2771 strify(self.allow_fd),
2772 )
2773
2774 def cleanup(self):
2775 return "path_cleanup(&" + self.name + ");\n"
2776
2777
2778 class dir_fd_converter(CConverter):
2779 type = 'int'
2780
2781 def converter_init(self, requires=None):
2782 if self.default in (unspecified, None):
2783 self.c_default = 'DEFAULT_DIR_FD'
2784 if isinstance(requires, str):
2785 self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2786 else:
2787 self.converter = 'dir_fd_converter'
2788
2789 class uid_t_converter(CConverter):
2790 type = "uid_t"
2791 converter = '_Py_Uid_Converter'
2792
2793 class gid_t_converter(CConverter):
2794 type = "gid_t"
2795 converter = '_Py_Gid_Converter'
2796
2797 class dev_t_converter(CConverter):
2798 type = 'dev_t'
2799 converter = '_Py_Dev_Converter'
2800
2801 class dev_t_return_converter(unsigned_long_return_converter):
2802 type = 'dev_t'
2803 conversion_fn = '_PyLong_FromDev'
2804 unsigned_cast = '(dev_t)'
2805
2806 class FSConverter_converter(CConverter):
2807 type = 'PyObject *'
2808 converter = 'PyUnicode_FSConverter'
2809 def converter_init(self):
2810 if self.default is not unspecified:
2811 fail("FSConverter_converter does not support default values")
2812 self.c_default = 'NULL'
2813
2814 def cleanup(self):
2815 return "Py_XDECREF(" + self.name + ");\n"
2816
2817 class pid_t_converter(CConverter):
2818 type = 'pid_t'
2819 format_unit = '" _Py_PARSE_PID "'
2820
2821 class idtype_t_converter(int_converter):
2822 type = 'idtype_t'
2823
2824 class id_t_converter(CConverter):
2825 type = 'id_t'
2826 format_unit = '" _Py_PARSE_PID "'
2827
2828 class intptr_t_converter(CConverter):
2829 type = 'intptr_t'
2830 format_unit = '" _Py_PARSE_INTPTR "'
2831
2832 class Py_off_t_converter(CConverter):
2833 type = 'Py_off_t'
2834 converter = 'Py_off_t_converter'
2835
2836 class Py_off_t_return_converter(long_return_converter):
2837 type = 'Py_off_t'
2838 conversion_fn = 'PyLong_FromPy_off_t'
2839
2840 class path_confname_converter(CConverter):
2841 type="int"
2842 converter="conv_path_confname"
2843
2844 class confstr_confname_converter(path_confname_converter):
2845 converter='conv_confstr_confname'
2846
2847 class sysconf_confname_converter(path_confname_converter):
2848 converter="conv_sysconf_confname"
2849
2850 [python start generated code]*/
2851 /*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/
2852
2853 /*[clinic input]
2854
2855 os.stat
2856
2857 path : path_t(allow_fd=True)
2858 Path to be examined; can be string, bytes, a path-like object or
2859 open-file-descriptor int.
2860
2861 *
2862
2863 dir_fd : dir_fd(requires='fstatat') = None
2864 If not None, it should be a file descriptor open to a directory,
2865 and path should be a relative string; path will then be relative to
2866 that directory.
2867
2868 follow_symlinks: bool = True
2869 If False, and the last element of the path is a symbolic link,
2870 stat will examine the symbolic link itself instead of the file
2871 the link points to.
2872
2873 Perform a stat system call on the given path.
2874
2875 dir_fd and follow_symlinks may not be implemented
2876 on your platform. If they are unavailable, using them will raise a
2877 NotImplementedError.
2878
2879 It's an error to use dir_fd or follow_symlinks when specifying path as
2880 an open file descriptor.
2881
2882 [clinic start generated code]*/
2883
2884 static PyObject *
os_stat_impl(PyObject * module,path_t * path,int dir_fd,int follow_symlinks)2885 os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2886 /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2887 {
2888 return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
2889 }
2890
2891
2892 /*[clinic input]
2893 os.lstat
2894
2895 path : path_t
2896
2897 *
2898
2899 dir_fd : dir_fd(requires='fstatat') = None
2900
2901 Perform a stat system call on the given path, without following symbolic links.
2902
2903 Like stat(), but do not follow symbolic links.
2904 Equivalent to stat(path, follow_symlinks=False).
2905 [clinic start generated code]*/
2906
2907 static PyObject *
os_lstat_impl(PyObject * module,path_t * path,int dir_fd)2908 os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2909 /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2910 {
2911 int follow_symlinks = 0;
2912 return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
2913 }
2914
2915
2916 /*[clinic input]
2917 os.access -> bool
2918
2919 path: path_t
2920 Path to be tested; can be string, bytes, or a path-like object.
2921
2922 mode: int
2923 Operating-system mode bitfield. Can be F_OK to test existence,
2924 or the inclusive-OR of R_OK, W_OK, and X_OK.
2925
2926 *
2927
2928 dir_fd : dir_fd(requires='faccessat') = None
2929 If not None, it should be a file descriptor open to a directory,
2930 and path should be relative; path will then be relative to that
2931 directory.
2932
2933 effective_ids: bool = False
2934 If True, access will use the effective uid/gid instead of
2935 the real uid/gid.
2936
2937 follow_symlinks: bool = True
2938 If False, and the last element of the path is a symbolic link,
2939 access will examine the symbolic link itself instead of the file
2940 the link points to.
2941
2942 Use the real uid/gid to test for access to a path.
2943
2944 {parameters}
2945 dir_fd, effective_ids, and follow_symlinks may not be implemented
2946 on your platform. If they are unavailable, using them will raise a
2947 NotImplementedError.
2948
2949 Note that most operations will use the effective uid/gid, therefore this
2950 routine can be used in a suid/sgid environment to test if the invoking user
2951 has the specified access to the path.
2952
2953 [clinic start generated code]*/
2954
2955 static int
os_access_impl(PyObject * module,path_t * path,int mode,int dir_fd,int effective_ids,int follow_symlinks)2956 os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2957 int effective_ids, int follow_symlinks)
2958 /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
2959 {
2960 int return_value;
2961
2962 #ifdef MS_WINDOWS
2963 DWORD attr;
2964 #else
2965 int result;
2966 #endif
2967
2968 #ifdef HAVE_FACCESSAT
2969 int faccessat_unavailable = 0;
2970 #endif
2971
2972 #ifndef HAVE_FACCESSAT
2973 if (follow_symlinks_specified("access", follow_symlinks))
2974 return -1;
2975
2976 if (effective_ids) {
2977 argument_unavailable_error("access", "effective_ids");
2978 return -1;
2979 }
2980 #endif
2981
2982 #ifdef MS_WINDOWS
2983 Py_BEGIN_ALLOW_THREADS
2984 attr = GetFileAttributesW(path->wide);
2985 Py_END_ALLOW_THREADS
2986
2987 /*
2988 * Access is possible if
2989 * * we didn't get a -1, and
2990 * * write access wasn't requested,
2991 * * or the file isn't read-only,
2992 * * or it's a directory.
2993 * (Directories cannot be read-only on Windows.)
2994 */
2995 return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
2996 (!(mode & 2) ||
2997 !(attr & FILE_ATTRIBUTE_READONLY) ||
2998 (attr & FILE_ATTRIBUTE_DIRECTORY));
2999 #else
3000
3001 Py_BEGIN_ALLOW_THREADS
3002 #ifdef HAVE_FACCESSAT
3003 if ((dir_fd != DEFAULT_DIR_FD) ||
3004 effective_ids ||
3005 !follow_symlinks) {
3006
3007 if (HAVE_FACCESSAT_RUNTIME) {
3008 int flags = 0;
3009 if (!follow_symlinks)
3010 flags |= AT_SYMLINK_NOFOLLOW;
3011 if (effective_ids)
3012 flags |= AT_EACCESS;
3013 result = faccessat(dir_fd, path->narrow, mode, flags);
3014 } else {
3015 faccessat_unavailable = 1;
3016 }
3017 }
3018 else
3019 #endif
3020 result = access(path->narrow, mode);
3021 Py_END_ALLOW_THREADS
3022
3023 #ifdef HAVE_FACCESSAT
3024 if (faccessat_unavailable) {
3025 if (dir_fd != DEFAULT_DIR_FD) {
3026 argument_unavailable_error("access", "dir_fd");
3027 return -1;
3028 }
3029 if (follow_symlinks_specified("access", follow_symlinks))
3030 return -1;
3031
3032 if (effective_ids) {
3033 argument_unavailable_error("access", "effective_ids");
3034 return -1;
3035 }
3036 /* should be unreachable */
3037 return -1;
3038 }
3039 #endif
3040 return_value = !result;
3041 #endif
3042
3043 return return_value;
3044 }
3045
3046 #ifndef F_OK
3047 #define F_OK 0
3048 #endif
3049 #ifndef R_OK
3050 #define R_OK 4
3051 #endif
3052 #ifndef W_OK
3053 #define W_OK 2
3054 #endif
3055 #ifndef X_OK
3056 #define X_OK 1
3057 #endif
3058
3059
3060 #ifdef HAVE_TTYNAME
3061 /*[clinic input]
3062 os.ttyname
3063
3064 fd: int
3065 Integer file descriptor handle.
3066
3067 /
3068
3069 Return the name of the terminal device connected to 'fd'.
3070 [clinic start generated code]*/
3071
3072 static PyObject *
os_ttyname_impl(PyObject * module,int fd)3073 os_ttyname_impl(PyObject *module, int fd)
3074 /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3075 {
3076
3077 long size = sysconf(_SC_TTY_NAME_MAX);
3078 if (size == -1) {
3079 return posix_error();
3080 }
3081 char *buffer = (char *)PyMem_RawMalloc(size);
3082 if (buffer == NULL) {
3083 return PyErr_NoMemory();
3084 }
3085 int ret = ttyname_r(fd, buffer, size);
3086 if (ret != 0) {
3087 PyMem_RawFree(buffer);
3088 errno = ret;
3089 return posix_error();
3090 }
3091 PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3092 PyMem_RawFree(buffer);
3093 return res;
3094 }
3095 #endif
3096
3097 #ifdef HAVE_CTERMID
3098 /*[clinic input]
3099 os.ctermid
3100
3101 Return the name of the controlling terminal for this process.
3102 [clinic start generated code]*/
3103
3104 static PyObject *
os_ctermid_impl(PyObject * module)3105 os_ctermid_impl(PyObject *module)
3106 /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3107 {
3108 char *ret;
3109 char buffer[L_ctermid];
3110
3111 #ifdef USE_CTERMID_R
3112 ret = ctermid_r(buffer);
3113 #else
3114 ret = ctermid(buffer);
3115 #endif
3116 if (ret == NULL)
3117 return posix_error();
3118 return PyUnicode_DecodeFSDefault(buffer);
3119 }
3120 #endif /* HAVE_CTERMID */
3121
3122
3123 /*[clinic input]
3124 os.chdir
3125
3126 path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3127
3128 Change the current working directory to the specified path.
3129
3130 path may always be specified as a string.
3131 On some platforms, path may also be specified as an open file descriptor.
3132 If this functionality is unavailable, using it raises an exception.
3133 [clinic start generated code]*/
3134
3135 static PyObject *
os_chdir_impl(PyObject * module,path_t * path)3136 os_chdir_impl(PyObject *module, path_t *path)
3137 /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3138 {
3139 int result;
3140
3141 if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3142 return NULL;
3143 }
3144
3145 Py_BEGIN_ALLOW_THREADS
3146 #ifdef MS_WINDOWS
3147 /* on unix, success = 0, on windows, success = !0 */
3148 result = !win32_wchdir(path->wide);
3149 #else
3150 #ifdef HAVE_FCHDIR
3151 if (path->fd != -1)
3152 result = fchdir(path->fd);
3153 else
3154 #endif
3155 result = chdir(path->narrow);
3156 #endif
3157 Py_END_ALLOW_THREADS
3158
3159 if (result) {
3160 return path_error(path);
3161 }
3162
3163 Py_RETURN_NONE;
3164 }
3165
3166
3167 #ifdef HAVE_FCHDIR
3168 /*[clinic input]
3169 os.fchdir
3170
3171 fd: fildes
3172
3173 Change to the directory of the given file descriptor.
3174
3175 fd must be opened on a directory, not a file.
3176 Equivalent to os.chdir(fd).
3177
3178 [clinic start generated code]*/
3179
3180 static PyObject *
os_fchdir_impl(PyObject * module,int fd)3181 os_fchdir_impl(PyObject *module, int fd)
3182 /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3183 {
3184 if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3185 return NULL;
3186 }
3187 return posix_fildes_fd(fd, fchdir);
3188 }
3189 #endif /* HAVE_FCHDIR */
3190
3191
3192 /*[clinic input]
3193 os.chmod
3194
3195 path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3196 Path to be modified. May always be specified as a str, bytes, or a path-like object.
3197 On some platforms, path may also be specified as an open file descriptor.
3198 If this functionality is unavailable, using it raises an exception.
3199
3200 mode: int
3201 Operating-system mode bitfield.
3202
3203 *
3204
3205 dir_fd : dir_fd(requires='fchmodat') = None
3206 If not None, it should be a file descriptor open to a directory,
3207 and path should be relative; path will then be relative to that
3208 directory.
3209
3210 follow_symlinks: bool = True
3211 If False, and the last element of the path is a symbolic link,
3212 chmod will modify the symbolic link itself instead of the file
3213 the link points to.
3214
3215 Change the access permissions of a file.
3216
3217 It is an error to use dir_fd or follow_symlinks when specifying path as
3218 an open file descriptor.
3219 dir_fd and follow_symlinks may not be implemented on your platform.
3220 If they are unavailable, using them will raise a NotImplementedError.
3221
3222 [clinic start generated code]*/
3223
3224 static PyObject *
os_chmod_impl(PyObject * module,path_t * path,int mode,int dir_fd,int follow_symlinks)3225 os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3226 int follow_symlinks)
3227 /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
3228 {
3229 int result;
3230
3231 #ifdef MS_WINDOWS
3232 DWORD attr;
3233 #endif
3234
3235 #ifdef HAVE_FCHMODAT
3236 int fchmodat_nofollow_unsupported = 0;
3237 int fchmodat_unsupported = 0;
3238 #endif
3239
3240 #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
3241 if (follow_symlinks_specified("chmod", follow_symlinks))
3242 return NULL;
3243 #endif
3244
3245 if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3246 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3247 return NULL;
3248 }
3249
3250 #ifdef MS_WINDOWS
3251 Py_BEGIN_ALLOW_THREADS
3252 attr = GetFileAttributesW(path->wide);
3253 if (attr == INVALID_FILE_ATTRIBUTES)
3254 result = 0;
3255 else {
3256 if (mode & _S_IWRITE)
3257 attr &= ~FILE_ATTRIBUTE_READONLY;
3258 else
3259 attr |= FILE_ATTRIBUTE_READONLY;
3260 result = SetFileAttributesW(path->wide, attr);
3261 }
3262 Py_END_ALLOW_THREADS
3263
3264 if (!result) {
3265 return path_error(path);
3266 }
3267 #else /* MS_WINDOWS */
3268 Py_BEGIN_ALLOW_THREADS
3269 #ifdef HAVE_FCHMOD
3270 if (path->fd != -1)
3271 result = fchmod(path->fd, mode);
3272 else
3273 #endif /* HAVE_CHMOD */
3274 #ifdef HAVE_LCHMOD
3275 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3276 result = lchmod(path->narrow, mode);
3277 else
3278 #endif /* HAVE_LCHMOD */
3279 #ifdef HAVE_FCHMODAT
3280 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3281 if (HAVE_FCHMODAT_RUNTIME) {
3282 /*
3283 * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3284 * The documentation specifically shows how to use it,
3285 * and then says it isn't implemented yet.
3286 * (true on linux with glibc 2.15, and openindiana 3.x)
3287 *
3288 * Once it is supported, os.chmod will automatically
3289 * support dir_fd and follow_symlinks=False. (Hopefully.)
3290 * Until then, we need to be careful what exception we raise.
3291 */
3292 result = fchmodat(dir_fd, path->narrow, mode,
3293 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3294 /*
3295 * But wait! We can't throw the exception without allowing threads,
3296 * and we can't do that in this nested scope. (Macro trickery, sigh.)
3297 */
3298 fchmodat_nofollow_unsupported =
3299 result &&
3300 ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3301 !follow_symlinks;
3302 } else {
3303 fchmodat_unsupported = 1;
3304 fchmodat_nofollow_unsupported = 1;
3305
3306 result = -1;
3307 }
3308 }
3309 else
3310 #endif /* HAVE_FHCMODAT */
3311 result = chmod(path->narrow, mode);
3312 Py_END_ALLOW_THREADS
3313
3314 if (result) {
3315 #ifdef HAVE_FCHMODAT
3316 if (fchmodat_unsupported) {
3317 if (dir_fd != DEFAULT_DIR_FD) {
3318 argument_unavailable_error("chmod", "dir_fd");
3319 return NULL;
3320 }
3321 }
3322
3323 if (fchmodat_nofollow_unsupported) {
3324 if (dir_fd != DEFAULT_DIR_FD)
3325 dir_fd_and_follow_symlinks_invalid("chmod",
3326 dir_fd, follow_symlinks);
3327 else
3328 follow_symlinks_specified("chmod", follow_symlinks);
3329 return NULL;
3330 }
3331 else
3332 #endif /* HAVE_FCHMODAT */
3333 return path_error(path);
3334 }
3335 #endif /* MS_WINDOWS */
3336
3337 Py_RETURN_NONE;
3338 }
3339
3340
3341 #ifdef HAVE_FCHMOD
3342 /*[clinic input]
3343 os.fchmod
3344
3345 fd: int
3346 mode: int
3347
3348 Change the access permissions of the file given by file descriptor fd.
3349
3350 Equivalent to os.chmod(fd, mode).
3351 [clinic start generated code]*/
3352
3353 static PyObject *
os_fchmod_impl(PyObject * module,int fd,int mode)3354 os_fchmod_impl(PyObject *module, int fd, int mode)
3355 /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
3356 {
3357 int res;
3358 int async_err = 0;
3359
3360 if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3361 return NULL;
3362 }
3363
3364 do {
3365 Py_BEGIN_ALLOW_THREADS
3366 res = fchmod(fd, mode);
3367 Py_END_ALLOW_THREADS
3368 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3369 if (res != 0)
3370 return (!async_err) ? posix_error() : NULL;
3371
3372 Py_RETURN_NONE;
3373 }
3374 #endif /* HAVE_FCHMOD */
3375
3376
3377 #ifdef HAVE_LCHMOD
3378 /*[clinic input]
3379 os.lchmod
3380
3381 path: path_t
3382 mode: int
3383
3384 Change the access permissions of a file, without following symbolic links.
3385
3386 If path is a symlink, this affects the link itself rather than the target.
3387 Equivalent to chmod(path, mode, follow_symlinks=False)."
3388 [clinic start generated code]*/
3389
3390 static PyObject *
os_lchmod_impl(PyObject * module,path_t * path,int mode)3391 os_lchmod_impl(PyObject *module, path_t *path, int mode)
3392 /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3393 {
3394 int res;
3395 if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3396 return NULL;
3397 }
3398 Py_BEGIN_ALLOW_THREADS
3399 res = lchmod(path->narrow, mode);
3400 Py_END_ALLOW_THREADS
3401 if (res < 0) {
3402 path_error(path);
3403 return NULL;
3404 }
3405 Py_RETURN_NONE;
3406 }
3407 #endif /* HAVE_LCHMOD */
3408
3409
3410 #ifdef HAVE_CHFLAGS
3411 /*[clinic input]
3412 os.chflags
3413
3414 path: path_t
3415 flags: unsigned_long(bitwise=True)
3416 follow_symlinks: bool=True
3417
3418 Set file flags.
3419
3420 If follow_symlinks is False, and the last element of the path is a symbolic
3421 link, chflags will change flags on the symbolic link itself instead of the
3422 file the link points to.
3423 follow_symlinks may not be implemented on your platform. If it is
3424 unavailable, using it will raise a NotImplementedError.
3425
3426 [clinic start generated code]*/
3427
3428 static PyObject *
os_chflags_impl(PyObject * module,path_t * path,unsigned long flags,int follow_symlinks)3429 os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3430 int follow_symlinks)
3431 /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3432 {
3433 int result;
3434
3435 #ifndef HAVE_LCHFLAGS
3436 if (follow_symlinks_specified("chflags", follow_symlinks))
3437 return NULL;
3438 #endif
3439
3440 if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3441 return NULL;
3442 }
3443
3444 Py_BEGIN_ALLOW_THREADS
3445 #ifdef HAVE_LCHFLAGS
3446 if (!follow_symlinks)
3447 result = lchflags(path->narrow, flags);
3448 else
3449 #endif
3450 result = chflags(path->narrow, flags);
3451 Py_END_ALLOW_THREADS
3452
3453 if (result)
3454 return path_error(path);
3455
3456 Py_RETURN_NONE;
3457 }
3458 #endif /* HAVE_CHFLAGS */
3459
3460
3461 #ifdef HAVE_LCHFLAGS
3462 /*[clinic input]
3463 os.lchflags
3464
3465 path: path_t
3466 flags: unsigned_long(bitwise=True)
3467
3468 Set file flags.
3469
3470 This function will not follow symbolic links.
3471 Equivalent to chflags(path, flags, follow_symlinks=False).
3472 [clinic start generated code]*/
3473
3474 static PyObject *
os_lchflags_impl(PyObject * module,path_t * path,unsigned long flags)3475 os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3476 /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3477 {
3478 int res;
3479 if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3480 return NULL;
3481 }
3482 Py_BEGIN_ALLOW_THREADS
3483 res = lchflags(path->narrow, flags);
3484 Py_END_ALLOW_THREADS
3485 if (res < 0) {
3486 return path_error(path);
3487 }
3488 Py_RETURN_NONE;
3489 }
3490 #endif /* HAVE_LCHFLAGS */
3491
3492
3493 #ifdef HAVE_CHROOT
3494 /*[clinic input]
3495 os.chroot
3496 path: path_t
3497
3498 Change root directory to path.
3499
3500 [clinic start generated code]*/
3501
3502 static PyObject *
os_chroot_impl(PyObject * module,path_t * path)3503 os_chroot_impl(PyObject *module, path_t *path)
3504 /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3505 {
3506 int res;
3507 Py_BEGIN_ALLOW_THREADS
3508 res = chroot(path->narrow);
3509 Py_END_ALLOW_THREADS
3510 if (res < 0)
3511 return path_error(path);
3512 Py_RETURN_NONE;
3513 }
3514 #endif /* HAVE_CHROOT */
3515
3516
3517 #ifdef HAVE_FSYNC
3518 /*[clinic input]
3519 os.fsync
3520
3521 fd: fildes
3522
3523 Force write of fd to disk.
3524 [clinic start generated code]*/
3525
3526 static PyObject *
os_fsync_impl(PyObject * module,int fd)3527 os_fsync_impl(PyObject *module, int fd)
3528 /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3529 {
3530 return posix_fildes_fd(fd, fsync);
3531 }
3532 #endif /* HAVE_FSYNC */
3533
3534
3535 #ifdef HAVE_SYNC
3536 /*[clinic input]
3537 os.sync
3538
3539 Force write of everything to disk.
3540 [clinic start generated code]*/
3541
3542 static PyObject *
os_sync_impl(PyObject * module)3543 os_sync_impl(PyObject *module)
3544 /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3545 {
3546 Py_BEGIN_ALLOW_THREADS
3547 sync();
3548 Py_END_ALLOW_THREADS
3549 Py_RETURN_NONE;
3550 }
3551 #endif /* HAVE_SYNC */
3552
3553
3554 #ifdef HAVE_FDATASYNC
3555 #ifdef __hpux
3556 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3557 #endif
3558
3559 /*[clinic input]
3560 os.fdatasync
3561
3562 fd: fildes
3563
3564 Force write of fd to disk without forcing update of metadata.
3565 [clinic start generated code]*/
3566
3567 static PyObject *
os_fdatasync_impl(PyObject * module,int fd)3568 os_fdatasync_impl(PyObject *module, int fd)
3569 /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3570 {
3571 return posix_fildes_fd(fd, fdatasync);
3572 }
3573 #endif /* HAVE_FDATASYNC */
3574
3575
3576 #ifdef HAVE_CHOWN
3577 /*[clinic input]
3578 os.chown
3579
3580 path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3581 Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3582
3583 uid: uid_t
3584
3585 gid: gid_t
3586
3587 *
3588
3589 dir_fd : dir_fd(requires='fchownat') = None
3590 If not None, it should be a file descriptor open to a directory,
3591 and path should be relative; path will then be relative to that
3592 directory.
3593
3594 follow_symlinks: bool = True
3595 If False, and the last element of the path is a symbolic link,
3596 stat will examine the symbolic link itself instead of the file
3597 the link points to.
3598
3599 Change the owner and group id of path to the numeric uid and gid.\
3600
3601 path may always be specified as a string.
3602 On some platforms, path may also be specified as an open file descriptor.
3603 If this functionality is unavailable, using it raises an exception.
3604 If dir_fd is not None, it should be a file descriptor open to a directory,
3605 and path should be relative; path will then be relative to that directory.
3606 If follow_symlinks is False, and the last element of the path is a symbolic
3607 link, chown will modify the symbolic link itself instead of the file the
3608 link points to.
3609 It is an error to use dir_fd or follow_symlinks when specifying path as
3610 an open file descriptor.
3611 dir_fd and follow_symlinks may not be implemented on your platform.
3612 If they are unavailable, using them will raise a NotImplementedError.
3613
3614 [clinic start generated code]*/
3615
3616 static PyObject *
os_chown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid,int dir_fd,int follow_symlinks)3617 os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3618 int dir_fd, int follow_symlinks)
3619 /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3620 {
3621 int result;
3622
3623 #if defined(HAVE_FCHOWNAT)
3624 int fchownat_unsupported = 0;
3625 #endif
3626
3627 #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3628 if (follow_symlinks_specified("chown", follow_symlinks))
3629 return NULL;
3630 #endif
3631 if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3632 fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3633 return NULL;
3634
3635 if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3636 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3637 return NULL;
3638 }
3639
3640 Py_BEGIN_ALLOW_THREADS
3641 #ifdef HAVE_FCHOWN
3642 if (path->fd != -1)
3643 result = fchown(path->fd, uid, gid);
3644 else
3645 #endif
3646 #ifdef HAVE_LCHOWN
3647 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3648 result = lchown(path->narrow, uid, gid);
3649 else
3650 #endif
3651 #ifdef HAVE_FCHOWNAT
3652 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
3653 if (HAVE_FCHOWNAT_RUNTIME) {
3654 result = fchownat(dir_fd, path->narrow, uid, gid,
3655 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3656 } else {
3657 fchownat_unsupported = 1;
3658 }
3659 } else
3660 #endif
3661 result = chown(path->narrow, uid, gid);
3662 Py_END_ALLOW_THREADS
3663
3664 #ifdef HAVE_FCHOWNAT
3665 if (fchownat_unsupported) {
3666 /* This would be incorrect if the current platform
3667 * doesn't support lchown.
3668 */
3669 argument_unavailable_error(NULL, "dir_fd");
3670 return NULL;
3671 }
3672 #endif
3673
3674 if (result)
3675 return path_error(path);
3676
3677 Py_RETURN_NONE;
3678 }
3679 #endif /* HAVE_CHOWN */
3680
3681
3682 #ifdef HAVE_FCHOWN
3683 /*[clinic input]
3684 os.fchown
3685
3686 fd: int
3687 uid: uid_t
3688 gid: gid_t
3689
3690 Change the owner and group id of the file specified by file descriptor.
3691
3692 Equivalent to os.chown(fd, uid, gid).
3693
3694 [clinic start generated code]*/
3695
3696 static PyObject *
os_fchown_impl(PyObject * module,int fd,uid_t uid,gid_t gid)3697 os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3698 /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3699 {
3700 int res;
3701 int async_err = 0;
3702
3703 if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
3704 return NULL;
3705 }
3706
3707 do {
3708 Py_BEGIN_ALLOW_THREADS
3709 res = fchown(fd, uid, gid);
3710 Py_END_ALLOW_THREADS
3711 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3712 if (res != 0)
3713 return (!async_err) ? posix_error() : NULL;
3714
3715 Py_RETURN_NONE;
3716 }
3717 #endif /* HAVE_FCHOWN */
3718
3719
3720 #ifdef HAVE_LCHOWN
3721 /*[clinic input]
3722 os.lchown
3723
3724 path : path_t
3725 uid: uid_t
3726 gid: gid_t
3727
3728 Change the owner and group id of path to the numeric uid and gid.
3729
3730 This function will not follow symbolic links.
3731 Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3732 [clinic start generated code]*/
3733
3734 static PyObject *
os_lchown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid)3735 os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3736 /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3737 {
3738 int res;
3739 if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
3740 return NULL;
3741 }
3742 Py_BEGIN_ALLOW_THREADS
3743 res = lchown(path->narrow, uid, gid);
3744 Py_END_ALLOW_THREADS
3745 if (res < 0) {
3746 return path_error(path);
3747 }
3748 Py_RETURN_NONE;
3749 }
3750 #endif /* HAVE_LCHOWN */
3751
3752
3753 static PyObject *
posix_getcwd(int use_bytes)3754 posix_getcwd(int use_bytes)
3755 {
3756 #ifdef MS_WINDOWS
3757 wchar_t wbuf[MAXPATHLEN];
3758 wchar_t *wbuf2 = wbuf;
3759 DWORD len;
3760
3761 Py_BEGIN_ALLOW_THREADS
3762 len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3763 /* If the buffer is large enough, len does not include the
3764 terminating \0. If the buffer is too small, len includes
3765 the space needed for the terminator. */
3766 if (len >= Py_ARRAY_LENGTH(wbuf)) {
3767 if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3768 wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3769 }
3770 else {
3771 wbuf2 = NULL;
3772 }
3773 if (wbuf2) {
3774 len = GetCurrentDirectoryW(len, wbuf2);
3775 }
3776 }
3777 Py_END_ALLOW_THREADS
3778
3779 if (!wbuf2) {
3780 PyErr_NoMemory();
3781 return NULL;
3782 }
3783 if (!len) {
3784 if (wbuf2 != wbuf)
3785 PyMem_RawFree(wbuf2);
3786 return PyErr_SetFromWindowsErr(0);
3787 }
3788
3789 PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3790 if (wbuf2 != wbuf) {
3791 PyMem_RawFree(wbuf2);
3792 }
3793
3794 if (use_bytes) {
3795 if (resobj == NULL) {
3796 return NULL;
3797 }
3798 Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3799 }
3800
3801 return resobj;
3802 #else
3803 const size_t chunk = 1024;
3804
3805 char *buf = NULL;
3806 char *cwd = NULL;
3807 size_t buflen = 0;
3808
3809 Py_BEGIN_ALLOW_THREADS
3810 do {
3811 char *newbuf;
3812 if (buflen <= PY_SSIZE_T_MAX - chunk) {
3813 buflen += chunk;
3814 newbuf = PyMem_RawRealloc(buf, buflen);
3815 }
3816 else {
3817 newbuf = NULL;
3818 }
3819 if (newbuf == NULL) {
3820 PyMem_RawFree(buf);
3821 buf = NULL;
3822 break;
3823 }
3824 buf = newbuf;
3825
3826 cwd = getcwd(buf, buflen);
3827 } while (cwd == NULL && errno == ERANGE);
3828 Py_END_ALLOW_THREADS
3829
3830 if (buf == NULL) {
3831 return PyErr_NoMemory();
3832 }
3833 if (cwd == NULL) {
3834 PyMem_RawFree(buf);
3835 return posix_error();
3836 }
3837
3838 PyObject *obj;
3839 if (use_bytes) {
3840 obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3841 }
3842 else {
3843 obj = PyUnicode_DecodeFSDefault(buf);
3844 }
3845 PyMem_RawFree(buf);
3846
3847 return obj;
3848 #endif /* !MS_WINDOWS */
3849 }
3850
3851
3852 /*[clinic input]
3853 os.getcwd
3854
3855 Return a unicode string representing the current working directory.
3856 [clinic start generated code]*/
3857
3858 static PyObject *
os_getcwd_impl(PyObject * module)3859 os_getcwd_impl(PyObject *module)
3860 /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3861 {
3862 return posix_getcwd(0);
3863 }
3864
3865
3866 /*[clinic input]
3867 os.getcwdb
3868
3869 Return a bytes string representing the current working directory.
3870 [clinic start generated code]*/
3871
3872 static PyObject *
os_getcwdb_impl(PyObject * module)3873 os_getcwdb_impl(PyObject *module)
3874 /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3875 {
3876 return posix_getcwd(1);
3877 }
3878
3879
3880 #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3881 #define HAVE_LINK 1
3882 #endif
3883
3884 #ifdef HAVE_LINK
3885 /*[clinic input]
3886
3887 os.link
3888
3889 src : path_t
3890 dst : path_t
3891 *
3892 src_dir_fd : dir_fd = None
3893 dst_dir_fd : dir_fd = None
3894 follow_symlinks: bool = True
3895
3896 Create a hard link to a file.
3897
3898 If either src_dir_fd or dst_dir_fd is not None, it should be a file
3899 descriptor open to a directory, and the respective path string (src or dst)
3900 should be relative; the path will then be relative to that directory.
3901 If follow_symlinks is False, and the last element of src is a symbolic
3902 link, link will create a link to the symbolic link itself instead of the
3903 file the link points to.
3904 src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3905 platform. If they are unavailable, using them will raise a
3906 NotImplementedError.
3907 [clinic start generated code]*/
3908
3909 static PyObject *
os_link_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int follow_symlinks)3910 os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3911 int dst_dir_fd, int follow_symlinks)
3912 /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3913 {
3914 #ifdef MS_WINDOWS
3915 BOOL result = FALSE;
3916 #else
3917 int result;
3918 #endif
3919 #if defined(HAVE_LINKAT)
3920 int linkat_unavailable = 0;
3921 #endif
3922
3923 #ifndef HAVE_LINKAT
3924 if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3925 argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3926 return NULL;
3927 }
3928 #endif
3929
3930 #ifndef MS_WINDOWS
3931 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3932 PyErr_SetString(PyExc_NotImplementedError,
3933 "link: src and dst must be the same type");
3934 return NULL;
3935 }
3936 #endif
3937
3938 if (PySys_Audit("os.link", "OOii", src->object, dst->object,
3939 src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
3940 dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
3941 return NULL;
3942 }
3943
3944 #ifdef MS_WINDOWS
3945 Py_BEGIN_ALLOW_THREADS
3946 result = CreateHardLinkW(dst->wide, src->wide, NULL);
3947 Py_END_ALLOW_THREADS
3948
3949 if (!result)
3950 return path_error2(src, dst);
3951 #else
3952 Py_BEGIN_ALLOW_THREADS
3953 #ifdef HAVE_LINKAT
3954 if ((src_dir_fd != DEFAULT_DIR_FD) ||
3955 (dst_dir_fd != DEFAULT_DIR_FD) ||
3956 (!follow_symlinks)) {
3957
3958 if (HAVE_LINKAT_RUNTIME) {
3959
3960 result = linkat(src_dir_fd, src->narrow,
3961 dst_dir_fd, dst->narrow,
3962 follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3963
3964 }
3965 #ifdef __APPLE__
3966 else {
3967 if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
3968 /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
3969 result = link(src->narrow, dst->narrow);
3970 } else {
3971 linkat_unavailable = 1;
3972 }
3973 }
3974 #endif
3975 }
3976 else
3977 #endif /* HAVE_LINKAT */
3978 result = link(src->narrow, dst->narrow);
3979 Py_END_ALLOW_THREADS
3980
3981 #ifdef HAVE_LINKAT
3982 if (linkat_unavailable) {
3983 /* Either or both dir_fd arguments were specified */
3984 if (src_dir_fd != DEFAULT_DIR_FD) {
3985 argument_unavailable_error("link", "src_dir_fd");
3986 } else {
3987 argument_unavailable_error("link", "dst_dir_fd");
3988 }
3989 return NULL;
3990 }
3991 #endif
3992
3993 if (result)
3994 return path_error2(src, dst);
3995 #endif /* MS_WINDOWS */
3996
3997 Py_RETURN_NONE;
3998 }
3999 #endif
4000
4001
4002 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4003 static PyObject *
_listdir_windows_no_opendir(path_t * path,PyObject * list)4004 _listdir_windows_no_opendir(path_t *path, PyObject *list)
4005 {
4006 PyObject *v;
4007 HANDLE hFindFile = INVALID_HANDLE_VALUE;
4008 BOOL result;
4009 wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4010 /* only claim to have space for MAX_PATH */
4011 Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4012 wchar_t *wnamebuf = NULL;
4013
4014 WIN32_FIND_DATAW wFileData;
4015 const wchar_t *po_wchars;
4016
4017 if (!path->wide) { /* Default arg: "." */
4018 po_wchars = L".";
4019 len = 1;
4020 } else {
4021 po_wchars = path->wide;
4022 len = wcslen(path->wide);
4023 }
4024 /* The +5 is so we can append "\\*.*\0" */
4025 wnamebuf = PyMem_New(wchar_t, len + 5);
4026 if (!wnamebuf) {
4027 PyErr_NoMemory();
4028 goto exit;
4029 }
4030 wcscpy(wnamebuf, po_wchars);
4031 if (len > 0) {
4032 wchar_t wch = wnamebuf[len-1];
4033 if (wch != SEP && wch != ALTSEP && wch != L':')
4034 wnamebuf[len++] = SEP;
4035 wcscpy(wnamebuf + len, L"*.*");
4036 }
4037 if ((list = PyList_New(0)) == NULL) {
4038 goto exit;
4039 }
4040 Py_BEGIN_ALLOW_THREADS
4041 hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4042 Py_END_ALLOW_THREADS
4043 if (hFindFile == INVALID_HANDLE_VALUE) {
4044 int error = GetLastError();
4045 if (error == ERROR_FILE_NOT_FOUND)
4046 goto exit;
4047 Py_DECREF(list);
4048 list = path_error(path);
4049 goto exit;
4050 }
4051 do {
4052 /* Skip over . and .. */
4053 if (wcscmp(wFileData.cFileName, L".") != 0 &&
4054 wcscmp(wFileData.cFileName, L"..") != 0) {
4055 v = PyUnicode_FromWideChar(wFileData.cFileName,
4056 wcslen(wFileData.cFileName));
4057 if (path->narrow && v) {
4058 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4059 }
4060 if (v == NULL) {
4061 Py_DECREF(list);
4062 list = NULL;
4063 break;
4064 }
4065 if (PyList_Append(list, v) != 0) {
4066 Py_DECREF(v);
4067 Py_DECREF(list);
4068 list = NULL;
4069 break;
4070 }
4071 Py_DECREF(v);
4072 }
4073 Py_BEGIN_ALLOW_THREADS
4074 result = FindNextFileW(hFindFile, &wFileData);
4075 Py_END_ALLOW_THREADS
4076 /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4077 it got to the end of the directory. */
4078 if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4079 Py_DECREF(list);
4080 list = path_error(path);
4081 goto exit;
4082 }
4083 } while (result == TRUE);
4084
4085 exit:
4086 if (hFindFile != INVALID_HANDLE_VALUE) {
4087 if (FindClose(hFindFile) == FALSE) {
4088 if (list != NULL) {
4089 Py_DECREF(list);
4090 list = path_error(path);
4091 }
4092 }
4093 }
4094 PyMem_Free(wnamebuf);
4095
4096 return list;
4097 } /* end of _listdir_windows_no_opendir */
4098
4099 #else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4100
4101 static PyObject *
_posix_listdir(path_t * path,PyObject * list)4102 _posix_listdir(path_t *path, PyObject *list)
4103 {
4104 PyObject *v;
4105 DIR *dirp = NULL;
4106 struct dirent *ep;
4107 int return_str; /* if false, return bytes */
4108 #ifdef HAVE_FDOPENDIR
4109 int fd = -1;
4110 #endif
4111
4112 errno = 0;
4113 #ifdef HAVE_FDOPENDIR
4114 if (path->fd != -1) {
4115 if (HAVE_FDOPENDIR_RUNTIME) {
4116 /* closedir() closes the FD, so we duplicate it */
4117 fd = _Py_dup(path->fd);
4118 if (fd == -1)
4119 return NULL;
4120
4121 return_str = 1;
4122
4123 Py_BEGIN_ALLOW_THREADS
4124 dirp = fdopendir(fd);
4125 Py_END_ALLOW_THREADS
4126 } else {
4127 PyErr_SetString(PyExc_TypeError,
4128 "listdir: path should be string, bytes, os.PathLike or None, not int");
4129 return NULL;
4130 }
4131 }
4132 else
4133 #endif
4134 {
4135 const char *name;
4136 if (path->narrow) {
4137 name = path->narrow;
4138 /* only return bytes if they specified a bytes-like object */
4139 return_str = !PyObject_CheckBuffer(path->object);
4140 }
4141 else {
4142 name = ".";
4143 return_str = 1;
4144 }
4145
4146 Py_BEGIN_ALLOW_THREADS
4147 dirp = opendir(name);
4148 Py_END_ALLOW_THREADS
4149 }
4150
4151 if (dirp == NULL) {
4152 list = path_error(path);
4153 #ifdef HAVE_FDOPENDIR
4154 if (fd != -1) {
4155 Py_BEGIN_ALLOW_THREADS
4156 close(fd);
4157 Py_END_ALLOW_THREADS
4158 }
4159 #endif
4160 goto exit;
4161 }
4162 if ((list = PyList_New(0)) == NULL) {
4163 goto exit;
4164 }
4165 for (;;) {
4166 errno = 0;
4167 Py_BEGIN_ALLOW_THREADS
4168 ep = readdir(dirp);
4169 Py_END_ALLOW_THREADS
4170 if (ep == NULL) {
4171 if (errno == 0) {
4172 break;
4173 } else {
4174 Py_DECREF(list);
4175 list = path_error(path);
4176 goto exit;
4177 }
4178 }
4179 if (ep->d_name[0] == '.' &&
4180 (NAMLEN(ep) == 1 ||
4181 (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4182 continue;
4183 if (return_str)
4184 v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4185 else
4186 v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4187 if (v == NULL) {
4188 Py_CLEAR(list);
4189 break;
4190 }
4191 if (PyList_Append(list, v) != 0) {
4192 Py_DECREF(v);
4193 Py_CLEAR(list);
4194 break;
4195 }
4196 Py_DECREF(v);
4197 }
4198
4199 exit:
4200 if (dirp != NULL) {
4201 Py_BEGIN_ALLOW_THREADS
4202 #ifdef HAVE_FDOPENDIR
4203 if (fd > -1)
4204 rewinddir(dirp);
4205 #endif
4206 closedir(dirp);
4207 Py_END_ALLOW_THREADS
4208 }
4209
4210 return list;
4211 } /* end of _posix_listdir */
4212 #endif /* which OS */
4213
4214
4215 /*[clinic input]
4216 os.listdir
4217
4218 path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4219
4220 Return a list containing the names of the files in the directory.
4221
4222 path can be specified as either str, bytes, or a path-like object. If path is bytes,
4223 the filenames returned will also be bytes; in all other circumstances
4224 the filenames returned will be str.
4225 If path is None, uses the path='.'.
4226 On some platforms, path may also be specified as an open file descriptor;\
4227 the file descriptor must refer to a directory.
4228 If this functionality is unavailable, using it raises NotImplementedError.
4229
4230 The list is in arbitrary order. It does not include the special
4231 entries '.' and '..' even if they are present in the directory.
4232
4233
4234 [clinic start generated code]*/
4235
4236 static PyObject *
os_listdir_impl(PyObject * module,path_t * path)4237 os_listdir_impl(PyObject *module, path_t *path)
4238 /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4239 {
4240 if (PySys_Audit("os.listdir", "O",
4241 path->object ? path->object : Py_None) < 0) {
4242 return NULL;
4243 }
4244 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4245 return _listdir_windows_no_opendir(path, NULL);
4246 #else
4247 return _posix_listdir(path, NULL);
4248 #endif
4249 }
4250
4251 #ifdef MS_WINDOWS
4252 /* A helper function for abspath on win32 */
4253 /*[clinic input]
4254 os._getfullpathname
4255
4256 path: path_t
4257 /
4258
4259 [clinic start generated code]*/
4260
4261 static PyObject *
os__getfullpathname_impl(PyObject * module,path_t * path)4262 os__getfullpathname_impl(PyObject *module, path_t *path)
4263 /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
4264 {
4265 wchar_t *abspath;
4266
4267 /* _Py_abspath() is implemented with GetFullPathNameW() on Windows */
4268 if (_Py_abspath(path->wide, &abspath) < 0) {
4269 return win32_error_object("GetFullPathNameW", path->object);
4270 }
4271 if (abspath == NULL) {
4272 return PyErr_NoMemory();
4273 }
4274
4275 PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
4276 PyMem_RawFree(abspath);
4277 if (str == NULL) {
4278 return NULL;
4279 }
4280 if (path->narrow) {
4281 Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
4282 }
4283 return str;
4284 }
4285
4286
4287 /*[clinic input]
4288 os._getfinalpathname
4289
4290 path: path_t
4291 /
4292
4293 A helper function for samepath on windows.
4294 [clinic start generated code]*/
4295
4296 static PyObject *
os__getfinalpathname_impl(PyObject * module,path_t * path)4297 os__getfinalpathname_impl(PyObject *module, path_t *path)
4298 /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
4299 {
4300 HANDLE hFile;
4301 wchar_t buf[MAXPATHLEN], *target_path = buf;
4302 int buf_size = Py_ARRAY_LENGTH(buf);
4303 int result_length;
4304 PyObject *result;
4305
4306 Py_BEGIN_ALLOW_THREADS
4307 hFile = CreateFileW(
4308 path->wide,
4309 0, /* desired access */
4310 0, /* share mode */
4311 NULL, /* security attributes */
4312 OPEN_EXISTING,
4313 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
4314 FILE_FLAG_BACKUP_SEMANTICS,
4315 NULL);
4316 Py_END_ALLOW_THREADS
4317
4318 if (hFile == INVALID_HANDLE_VALUE) {
4319 return win32_error_object("CreateFileW", path->object);
4320 }
4321
4322 /* We have a good handle to the target, use it to determine the
4323 target path name. */
4324 while (1) {
4325 Py_BEGIN_ALLOW_THREADS
4326 result_length = GetFinalPathNameByHandleW(hFile, target_path,
4327 buf_size, VOLUME_NAME_DOS);
4328 Py_END_ALLOW_THREADS
4329
4330 if (!result_length) {
4331 result = win32_error_object("GetFinalPathNameByHandleW",
4332 path->object);
4333 goto cleanup;
4334 }
4335
4336 if (result_length < buf_size) {
4337 break;
4338 }
4339
4340 wchar_t *tmp;
4341 tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
4342 result_length * sizeof(*tmp));
4343 if (!tmp) {
4344 result = PyErr_NoMemory();
4345 goto cleanup;
4346 }
4347
4348 buf_size = result_length;
4349 target_path = tmp;
4350 }
4351
4352 result = PyUnicode_FromWideChar(target_path, result_length);
4353 if (result && path->narrow) {
4354 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4355 }
4356
4357 cleanup:
4358 if (target_path != buf) {
4359 PyMem_Free(target_path);
4360 }
4361 CloseHandle(hFile);
4362 return result;
4363 }
4364
4365
4366 /*[clinic input]
4367 os._getvolumepathname
4368
4369 path: path_t
4370
4371 A helper function for ismount on Win32.
4372 [clinic start generated code]*/
4373
4374 static PyObject *
os__getvolumepathname_impl(PyObject * module,path_t * path)4375 os__getvolumepathname_impl(PyObject *module, path_t *path)
4376 /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
4377 {
4378 PyObject *result;
4379 wchar_t *mountpath=NULL;
4380 size_t buflen;
4381 BOOL ret;
4382
4383 /* Volume path should be shorter than entire path */
4384 buflen = Py_MAX(path->length, MAX_PATH);
4385
4386 if (buflen > PY_DWORD_MAX) {
4387 PyErr_SetString(PyExc_OverflowError, "path too long");
4388 return NULL;
4389 }
4390
4391 mountpath = PyMem_New(wchar_t, buflen);
4392 if (mountpath == NULL)
4393 return PyErr_NoMemory();
4394
4395 Py_BEGIN_ALLOW_THREADS
4396 ret = GetVolumePathNameW(path->wide, mountpath,
4397 Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
4398 Py_END_ALLOW_THREADS
4399
4400 if (!ret) {
4401 result = win32_error_object("_getvolumepathname", path->object);
4402 goto exit;
4403 }
4404 result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
4405 if (path->narrow)
4406 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4407
4408 exit:
4409 PyMem_Free(mountpath);
4410 return result;
4411 }
4412
4413
4414 /*[clinic input]
4415 os._path_splitroot
4416
4417 path: path_t
4418
4419 Removes everything after the root on Win32.
4420 [clinic start generated code]*/
4421
4422 static PyObject *
os__path_splitroot_impl(PyObject * module,path_t * path)4423 os__path_splitroot_impl(PyObject *module, path_t *path)
4424 /*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/
4425 {
4426 wchar_t *buffer;
4427 wchar_t *end;
4428 PyObject *result = NULL;
4429 HRESULT ret;
4430
4431 buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
4432 if (!buffer) {
4433 return NULL;
4434 }
4435 wcscpy(buffer, path->wide);
4436 for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
4437 *p = L'\\';
4438 }
4439
4440 Py_BEGIN_ALLOW_THREADS
4441 ret = PathCchSkipRoot(buffer, &end);
4442 Py_END_ALLOW_THREADS
4443 if (FAILED(ret)) {
4444 result = Py_BuildValue("sO", "", path->object);
4445 } else if (end != buffer) {
4446 size_t rootLen = (size_t)(end - buffer);
4447 result = Py_BuildValue("NN",
4448 PyUnicode_FromWideChar(path->wide, rootLen),
4449 PyUnicode_FromWideChar(path->wide + rootLen, -1)
4450 );
4451 } else {
4452 result = Py_BuildValue("Os", path->object, "");
4453 }
4454 PyMem_Free(buffer);
4455
4456 return result;
4457 }
4458
4459
4460 #endif /* MS_WINDOWS */
4461
4462
4463 /*[clinic input]
4464 os.mkdir
4465
4466 path : path_t
4467
4468 mode: int = 0o777
4469
4470 *
4471
4472 dir_fd : dir_fd(requires='mkdirat') = None
4473
4474 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4475
4476 Create a directory.
4477
4478 If dir_fd is not None, it should be a file descriptor open to a directory,
4479 and path should be relative; path will then be relative to that directory.
4480 dir_fd may not be implemented on your platform.
4481 If it is unavailable, using it will raise a NotImplementedError.
4482
4483 The mode argument is ignored on Windows.
4484 [clinic start generated code]*/
4485
4486 static PyObject *
os_mkdir_impl(PyObject * module,path_t * path,int mode,int dir_fd)4487 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4488 /*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/
4489 {
4490 int result;
4491 #ifdef HAVE_MKDIRAT
4492 int mkdirat_unavailable = 0;
4493 #endif
4494
4495 if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4496 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4497 return NULL;
4498 }
4499
4500 #ifdef MS_WINDOWS
4501 Py_BEGIN_ALLOW_THREADS
4502 result = CreateDirectoryW(path->wide, NULL);
4503 Py_END_ALLOW_THREADS
4504
4505 if (!result)
4506 return path_error(path);
4507 #else
4508 Py_BEGIN_ALLOW_THREADS
4509 #if HAVE_MKDIRAT
4510 if (dir_fd != DEFAULT_DIR_FD) {
4511 if (HAVE_MKDIRAT_RUNTIME) {
4512 result = mkdirat(dir_fd, path->narrow, mode);
4513
4514 } else {
4515 mkdirat_unavailable = 1;
4516 }
4517 } else
4518 #endif
4519 #if defined(__WATCOMC__) && !defined(__QNX__)
4520 result = mkdir(path->narrow);
4521 #else
4522 result = mkdir(path->narrow, mode);
4523 #endif
4524 Py_END_ALLOW_THREADS
4525
4526 #if HAVE_MKDIRAT
4527 if (mkdirat_unavailable) {
4528 argument_unavailable_error(NULL, "dir_fd");
4529 return NULL;
4530 }
4531 #endif
4532
4533 if (result < 0)
4534 return path_error(path);
4535 #endif /* MS_WINDOWS */
4536 Py_RETURN_NONE;
4537 }
4538
4539
4540 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4541 #if defined(HAVE_SYS_RESOURCE_H)
4542 #include <sys/resource.h>
4543 #endif
4544
4545
4546 #ifdef HAVE_NICE
4547 /*[clinic input]
4548 os.nice
4549
4550 increment: int
4551 /
4552
4553 Add increment to the priority of process and return the new priority.
4554 [clinic start generated code]*/
4555
4556 static PyObject *
os_nice_impl(PyObject * module,int increment)4557 os_nice_impl(PyObject *module, int increment)
4558 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4559 {
4560 int value;
4561
4562 /* There are two flavours of 'nice': one that returns the new
4563 priority (as required by almost all standards out there) and the
4564 Linux/FreeBSD one, which returns '0' on success and advices
4565 the use of getpriority() to get the new priority.
4566
4567 If we are of the nice family that returns the new priority, we
4568 need to clear errno before the call, and check if errno is filled
4569 before calling posix_error() on a returnvalue of -1, because the
4570 -1 may be the actual new priority! */
4571
4572 errno = 0;
4573 value = nice(increment);
4574 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4575 if (value == 0)
4576 value = getpriority(PRIO_PROCESS, 0);
4577 #endif
4578 if (value == -1 && errno != 0)
4579 /* either nice() or getpriority() returned an error */
4580 return posix_error();
4581 return PyLong_FromLong((long) value);
4582 }
4583 #endif /* HAVE_NICE */
4584
4585
4586 #ifdef HAVE_GETPRIORITY
4587 /*[clinic input]
4588 os.getpriority
4589
4590 which: int
4591 who: int
4592
4593 Return program scheduling priority.
4594 [clinic start generated code]*/
4595
4596 static PyObject *
os_getpriority_impl(PyObject * module,int which,int who)4597 os_getpriority_impl(PyObject *module, int which, int who)
4598 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4599 {
4600 int retval;
4601
4602 errno = 0;
4603 retval = getpriority(which, who);
4604 if (errno != 0)
4605 return posix_error();
4606 return PyLong_FromLong((long)retval);
4607 }
4608 #endif /* HAVE_GETPRIORITY */
4609
4610
4611 #ifdef HAVE_SETPRIORITY
4612 /*[clinic input]
4613 os.setpriority
4614
4615 which: int
4616 who: int
4617 priority: int
4618
4619 Set program scheduling priority.
4620 [clinic start generated code]*/
4621
4622 static PyObject *
os_setpriority_impl(PyObject * module,int which,int who,int priority)4623 os_setpriority_impl(PyObject *module, int which, int who, int priority)
4624 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4625 {
4626 int retval;
4627
4628 retval = setpriority(which, who, priority);
4629 if (retval == -1)
4630 return posix_error();
4631 Py_RETURN_NONE;
4632 }
4633 #endif /* HAVE_SETPRIORITY */
4634
4635
4636 static PyObject *
internal_rename(path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int is_replace)4637 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4638 {
4639 const char *function_name = is_replace ? "replace" : "rename";
4640 int dir_fd_specified;
4641
4642 #ifdef HAVE_RENAMEAT
4643 int renameat_unavailable = 0;
4644 #endif
4645
4646 #ifdef MS_WINDOWS
4647 BOOL result;
4648 int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4649 #else
4650 int result;
4651 #endif
4652
4653 dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4654 (dst_dir_fd != DEFAULT_DIR_FD);
4655 #ifndef HAVE_RENAMEAT
4656 if (dir_fd_specified) {
4657 argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4658 return NULL;
4659 }
4660 #endif
4661
4662 if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
4663 src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4664 dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4665 return NULL;
4666 }
4667
4668 #ifdef MS_WINDOWS
4669 Py_BEGIN_ALLOW_THREADS
4670 result = MoveFileExW(src->wide, dst->wide, flags);
4671 Py_END_ALLOW_THREADS
4672
4673 if (!result)
4674 return path_error2(src, dst);
4675
4676 #else
4677 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4678 PyErr_Format(PyExc_ValueError,
4679 "%s: src and dst must be the same type", function_name);
4680 return NULL;
4681 }
4682
4683 Py_BEGIN_ALLOW_THREADS
4684 #ifdef HAVE_RENAMEAT
4685 if (dir_fd_specified) {
4686 if (HAVE_RENAMEAT_RUNTIME) {
4687 result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4688 } else {
4689 renameat_unavailable = 1;
4690 }
4691 } else
4692 #endif
4693 result = rename(src->narrow, dst->narrow);
4694 Py_END_ALLOW_THREADS
4695
4696
4697 #ifdef HAVE_RENAMEAT
4698 if (renameat_unavailable) {
4699 argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4700 return NULL;
4701 }
4702 #endif
4703
4704 if (result)
4705 return path_error2(src, dst);
4706 #endif
4707 Py_RETURN_NONE;
4708 }
4709
4710
4711 /*[clinic input]
4712 os.rename
4713
4714 src : path_t
4715 dst : path_t
4716 *
4717 src_dir_fd : dir_fd = None
4718 dst_dir_fd : dir_fd = None
4719
4720 Rename a file or directory.
4721
4722 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4723 descriptor open to a directory, and the respective path string (src or dst)
4724 should be relative; the path will then be relative to that directory.
4725 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4726 If they are unavailable, using them will raise a NotImplementedError.
4727 [clinic start generated code]*/
4728
4729 static PyObject *
os_rename_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4730 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4731 int dst_dir_fd)
4732 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4733 {
4734 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4735 }
4736
4737
4738 /*[clinic input]
4739 os.replace = os.rename
4740
4741 Rename a file or directory, overwriting the destination.
4742
4743 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4744 descriptor open to a directory, and the respective path string (src or dst)
4745 should be relative; the path will then be relative to that directory.
4746 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4747 If they are unavailable, using them will raise a NotImplementedError.
4748 [clinic start generated code]*/
4749
4750 static PyObject *
os_replace_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4751 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4752 int dst_dir_fd)
4753 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4754 {
4755 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4756 }
4757
4758
4759 /*[clinic input]
4760 os.rmdir
4761
4762 path: path_t
4763 *
4764 dir_fd: dir_fd(requires='unlinkat') = None
4765
4766 Remove a directory.
4767
4768 If dir_fd is not None, it should be a file descriptor open to a directory,
4769 and path should be relative; path will then be relative to that directory.
4770 dir_fd may not be implemented on your platform.
4771 If it is unavailable, using it will raise a NotImplementedError.
4772 [clinic start generated code]*/
4773
4774 static PyObject *
os_rmdir_impl(PyObject * module,path_t * path,int dir_fd)4775 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4776 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4777 {
4778 int result;
4779 #ifdef HAVE_UNLINKAT
4780 int unlinkat_unavailable = 0;
4781 #endif
4782
4783 if (PySys_Audit("os.rmdir", "Oi", path->object,
4784 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4785 return NULL;
4786 }
4787
4788 Py_BEGIN_ALLOW_THREADS
4789 #ifdef MS_WINDOWS
4790 /* Windows, success=1, UNIX, success=0 */
4791 result = !RemoveDirectoryW(path->wide);
4792 #else
4793 #ifdef HAVE_UNLINKAT
4794 if (dir_fd != DEFAULT_DIR_FD) {
4795 if (HAVE_UNLINKAT_RUNTIME) {
4796 result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4797 } else {
4798 unlinkat_unavailable = 1;
4799 result = -1;
4800 }
4801 } else
4802 #endif
4803 result = rmdir(path->narrow);
4804 #endif
4805 Py_END_ALLOW_THREADS
4806
4807 #ifdef HAVE_UNLINKAT
4808 if (unlinkat_unavailable) {
4809 argument_unavailable_error("rmdir", "dir_fd");
4810 return NULL;
4811 }
4812 #endif
4813
4814 if (result)
4815 return path_error(path);
4816
4817 Py_RETURN_NONE;
4818 }
4819
4820
4821 #ifdef HAVE_SYSTEM
4822 #ifdef MS_WINDOWS
4823 /*[clinic input]
4824 os.system -> long
4825
4826 command: Py_UNICODE
4827
4828 Execute the command in a subshell.
4829 [clinic start generated code]*/
4830
4831 static long
os_system_impl(PyObject * module,const Py_UNICODE * command)4832 os_system_impl(PyObject *module, const Py_UNICODE *command)
4833 /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4834 {
4835 long result;
4836
4837 if (PySys_Audit("os.system", "(u)", command) < 0) {
4838 return -1;
4839 }
4840
4841 Py_BEGIN_ALLOW_THREADS
4842 _Py_BEGIN_SUPPRESS_IPH
4843 result = _wsystem(command);
4844 _Py_END_SUPPRESS_IPH
4845 Py_END_ALLOW_THREADS
4846 return result;
4847 }
4848 #else /* MS_WINDOWS */
4849 /*[clinic input]
4850 os.system -> long
4851
4852 command: FSConverter
4853
4854 Execute the command in a subshell.
4855 [clinic start generated code]*/
4856
4857 static long
os_system_impl(PyObject * module,PyObject * command)4858 os_system_impl(PyObject *module, PyObject *command)
4859 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4860 {
4861 long result;
4862 const char *bytes = PyBytes_AsString(command);
4863
4864 if (PySys_Audit("os.system", "(O)", command) < 0) {
4865 return -1;
4866 }
4867
4868 Py_BEGIN_ALLOW_THREADS
4869 result = system(bytes);
4870 Py_END_ALLOW_THREADS
4871 return result;
4872 }
4873 #endif
4874 #endif /* HAVE_SYSTEM */
4875
4876
4877 /*[clinic input]
4878 os.umask
4879
4880 mask: int
4881 /
4882
4883 Set the current numeric umask and return the previous umask.
4884 [clinic start generated code]*/
4885
4886 static PyObject *
os_umask_impl(PyObject * module,int mask)4887 os_umask_impl(PyObject *module, int mask)
4888 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4889 {
4890 int i = (int)umask(mask);
4891 if (i < 0)
4892 return posix_error();
4893 return PyLong_FromLong((long)i);
4894 }
4895
4896 #ifdef MS_WINDOWS
4897
4898 /* override the default DeleteFileW behavior so that directory
4899 symlinks can be removed with this function, the same as with
4900 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)4901 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
4902 {
4903 WIN32_FILE_ATTRIBUTE_DATA info;
4904 WIN32_FIND_DATAW find_data;
4905 HANDLE find_data_handle;
4906 int is_directory = 0;
4907 int is_link = 0;
4908
4909 if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
4910 is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4911
4912 /* Get WIN32_FIND_DATA structure for the path to determine if
4913 it is a symlink */
4914 if(is_directory &&
4915 info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
4916 find_data_handle = FindFirstFileW(lpFileName, &find_data);
4917
4918 if(find_data_handle != INVALID_HANDLE_VALUE) {
4919 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
4920 IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
4921 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
4922 find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
4923 FindClose(find_data_handle);
4924 }
4925 }
4926 }
4927
4928 if (is_directory && is_link)
4929 return RemoveDirectoryW(lpFileName);
4930
4931 return DeleteFileW(lpFileName);
4932 }
4933 #endif /* MS_WINDOWS */
4934
4935
4936 /*[clinic input]
4937 os.unlink
4938
4939 path: path_t
4940 *
4941 dir_fd: dir_fd(requires='unlinkat')=None
4942
4943 Remove a file (same as remove()).
4944
4945 If dir_fd is not None, it should be a file descriptor open to a directory,
4946 and path should be relative; path will then be relative to that directory.
4947 dir_fd may not be implemented on your platform.
4948 If it is unavailable, using it will raise a NotImplementedError.
4949
4950 [clinic start generated code]*/
4951
4952 static PyObject *
os_unlink_impl(PyObject * module,path_t * path,int dir_fd)4953 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
4954 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
4955 {
4956 int result;
4957 #ifdef HAVE_UNLINKAT
4958 int unlinkat_unavailable = 0;
4959 #endif
4960
4961 if (PySys_Audit("os.remove", "Oi", path->object,
4962 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4963 return NULL;
4964 }
4965
4966 Py_BEGIN_ALLOW_THREADS
4967 _Py_BEGIN_SUPPRESS_IPH
4968 #ifdef MS_WINDOWS
4969 /* Windows, success=1, UNIX, success=0 */
4970 result = !Py_DeleteFileW(path->wide);
4971 #else
4972 #ifdef HAVE_UNLINKAT
4973 if (dir_fd != DEFAULT_DIR_FD) {
4974 if (HAVE_UNLINKAT_RUNTIME) {
4975
4976 result = unlinkat(dir_fd, path->narrow, 0);
4977 } else {
4978 unlinkat_unavailable = 1;
4979 }
4980 } else
4981 #endif /* HAVE_UNLINKAT */
4982 result = unlink(path->narrow);
4983 #endif
4984 _Py_END_SUPPRESS_IPH
4985 Py_END_ALLOW_THREADS
4986
4987 #ifdef HAVE_UNLINKAT
4988 if (unlinkat_unavailable) {
4989 argument_unavailable_error(NULL, "dir_fd");
4990 return NULL;
4991 }
4992 #endif
4993
4994 if (result)
4995 return path_error(path);
4996
4997 Py_RETURN_NONE;
4998 }
4999
5000
5001 /*[clinic input]
5002 os.remove = os.unlink
5003
5004 Remove a file (same as unlink()).
5005
5006 If dir_fd is not None, it should be a file descriptor open to a directory,
5007 and path should be relative; path will then be relative to that directory.
5008 dir_fd may not be implemented on your platform.
5009 If it is unavailable, using it will raise a NotImplementedError.
5010 [clinic start generated code]*/
5011
5012 static PyObject *
os_remove_impl(PyObject * module,path_t * path,int dir_fd)5013 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
5014 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
5015 {
5016 return os_unlink_impl(module, path, dir_fd);
5017 }
5018
5019
5020 static PyStructSequence_Field uname_result_fields[] = {
5021 {"sysname", "operating system name"},
5022 {"nodename", "name of machine on network (implementation-defined)"},
5023 {"release", "operating system release"},
5024 {"version", "operating system version"},
5025 {"machine", "hardware identifier"},
5026 {NULL}
5027 };
5028
5029 PyDoc_STRVAR(uname_result__doc__,
5030 "uname_result: Result from os.uname().\n\n\
5031 This object may be accessed either as a tuple of\n\
5032 (sysname, nodename, release, version, machine),\n\
5033 or via the attributes sysname, nodename, release, version, and machine.\n\
5034 \n\
5035 See os.uname for more information.");
5036
5037 static PyStructSequence_Desc uname_result_desc = {
5038 MODNAME ".uname_result", /* name */
5039 uname_result__doc__, /* doc */
5040 uname_result_fields,
5041 5
5042 };
5043
5044 #ifdef HAVE_UNAME
5045 /*[clinic input]
5046 os.uname
5047
5048 Return an object identifying the current operating system.
5049
5050 The object behaves like a named tuple with the following fields:
5051 (sysname, nodename, release, version, machine)
5052
5053 [clinic start generated code]*/
5054
5055 static PyObject *
os_uname_impl(PyObject * module)5056 os_uname_impl(PyObject *module)
5057 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
5058 {
5059 struct utsname u;
5060 int res;
5061 PyObject *value;
5062
5063 Py_BEGIN_ALLOW_THREADS
5064 res = uname(&u);
5065 Py_END_ALLOW_THREADS
5066 if (res < 0)
5067 return posix_error();
5068
5069 PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
5070 value = PyStructSequence_New((PyTypeObject *)UnameResultType);
5071 if (value == NULL)
5072 return NULL;
5073
5074 #define SET(i, field) \
5075 { \
5076 PyObject *o = PyUnicode_DecodeFSDefault(field); \
5077 if (!o) { \
5078 Py_DECREF(value); \
5079 return NULL; \
5080 } \
5081 PyStructSequence_SET_ITEM(value, i, o); \
5082 } \
5083
5084 SET(0, u.sysname);
5085 SET(1, u.nodename);
5086 SET(2, u.release);
5087 SET(3, u.version);
5088 SET(4, u.machine);
5089
5090 #undef SET
5091
5092 return value;
5093 }
5094 #endif /* HAVE_UNAME */
5095
5096
5097
5098 typedef struct {
5099 int now;
5100 time_t atime_s;
5101 long atime_ns;
5102 time_t mtime_s;
5103 long mtime_ns;
5104 } utime_t;
5105
5106 /*
5107 * these macros assume that "ut" is a pointer to a utime_t
5108 * they also intentionally leak the declaration of a pointer named "time"
5109 */
5110 #define UTIME_TO_TIMESPEC \
5111 struct timespec ts[2]; \
5112 struct timespec *time; \
5113 if (ut->now) \
5114 time = NULL; \
5115 else { \
5116 ts[0].tv_sec = ut->atime_s; \
5117 ts[0].tv_nsec = ut->atime_ns; \
5118 ts[1].tv_sec = ut->mtime_s; \
5119 ts[1].tv_nsec = ut->mtime_ns; \
5120 time = ts; \
5121 } \
5122
5123 #define UTIME_TO_TIMEVAL \
5124 struct timeval tv[2]; \
5125 struct timeval *time; \
5126 if (ut->now) \
5127 time = NULL; \
5128 else { \
5129 tv[0].tv_sec = ut->atime_s; \
5130 tv[0].tv_usec = ut->atime_ns / 1000; \
5131 tv[1].tv_sec = ut->mtime_s; \
5132 tv[1].tv_usec = ut->mtime_ns / 1000; \
5133 time = tv; \
5134 } \
5135
5136 #define UTIME_TO_UTIMBUF \
5137 struct utimbuf u; \
5138 struct utimbuf *time; \
5139 if (ut->now) \
5140 time = NULL; \
5141 else { \
5142 u.actime = ut->atime_s; \
5143 u.modtime = ut->mtime_s; \
5144 time = &u; \
5145 }
5146
5147 #define UTIME_TO_TIME_T \
5148 time_t timet[2]; \
5149 time_t *time; \
5150 if (ut->now) \
5151 time = NULL; \
5152 else { \
5153 timet[0] = ut->atime_s; \
5154 timet[1] = ut->mtime_s; \
5155 time = timet; \
5156 } \
5157
5158
5159 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5160
5161 static int
utime_dir_fd(utime_t * ut,int dir_fd,const char * path,int follow_symlinks)5162 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
5163 {
5164 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5165 if (HAVE_UTIMENSAT_RUNTIME) {
5166 int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5167 UTIME_TO_TIMESPEC;
5168 return utimensat(dir_fd, path, time, flags);
5169 } else {
5170 errno = ENOSYS;
5171 return -1;
5172 }
5173 #elif defined(HAVE_UTIMENSAT)
5174 int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5175 UTIME_TO_TIMESPEC;
5176 return utimensat(dir_fd, path, time, flags);
5177 #elif defined(HAVE_FUTIMESAT)
5178 UTIME_TO_TIMEVAL;
5179 /*
5180 * follow_symlinks will never be false here;
5181 * we only allow !follow_symlinks and dir_fd together
5182 * if we have utimensat()
5183 */
5184 assert(follow_symlinks);
5185 return futimesat(dir_fd, path, time);
5186 #endif
5187 }
5188
5189 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
5190 #else
5191 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
5192 #endif
5193
5194 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5195
5196 static int
utime_fd(utime_t * ut,int fd)5197 utime_fd(utime_t *ut, int fd)
5198 {
5199 #ifdef HAVE_FUTIMENS
5200
5201 if (HAVE_FUTIMENS_RUNTIME) {
5202
5203 UTIME_TO_TIMESPEC;
5204 return futimens(fd, time);
5205
5206 } else
5207 #ifndef HAVE_FUTIMES
5208 {
5209 /* Not sure if this can happen */
5210 PyErr_SetString(
5211 PyExc_RuntimeError,
5212 "neither futimens nor futimes are supported"
5213 " on this system");
5214 return -1;
5215 }
5216 #endif
5217
5218 #endif
5219 #ifdef HAVE_FUTIMES
5220 {
5221 UTIME_TO_TIMEVAL;
5222 return futimes(fd, time);
5223 }
5224 #endif
5225 }
5226
5227 #define PATH_UTIME_HAVE_FD 1
5228 #else
5229 #define PATH_UTIME_HAVE_FD 0
5230 #endif
5231
5232 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
5233 # define UTIME_HAVE_NOFOLLOW_SYMLINKS
5234 #endif
5235
5236 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5237
5238 static int
utime_nofollow_symlinks(utime_t * ut,const char * path)5239 utime_nofollow_symlinks(utime_t *ut, const char *path)
5240 {
5241 #ifdef HAVE_UTIMENSAT
5242 if (HAVE_UTIMENSAT_RUNTIME) {
5243 UTIME_TO_TIMESPEC;
5244 return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
5245 } else
5246 #ifndef HAVE_LUTIMES
5247 {
5248 /* Not sure if this can happen */
5249 PyErr_SetString(
5250 PyExc_RuntimeError,
5251 "neither utimensat nor lutimes are supported"
5252 " on this system");
5253 return -1;
5254 }
5255 #endif
5256 #endif
5257
5258 #ifdef HAVE_LUTIMES
5259 {
5260 UTIME_TO_TIMEVAL;
5261 return lutimes(path, time);
5262 }
5263 #endif
5264 }
5265
5266 #endif
5267
5268 #ifndef MS_WINDOWS
5269
5270 static int
utime_default(utime_t * ut,const char * path)5271 utime_default(utime_t *ut, const char *path)
5272 {
5273 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5274 if (HAVE_UTIMENSAT_RUNTIME) {
5275 UTIME_TO_TIMESPEC;
5276 return utimensat(DEFAULT_DIR_FD, path, time, 0);
5277 } else {
5278 UTIME_TO_TIMEVAL;
5279 return utimes(path, time);
5280 }
5281 #elif defined(HAVE_UTIMENSAT)
5282 UTIME_TO_TIMESPEC;
5283 return utimensat(DEFAULT_DIR_FD, path, time, 0);
5284 #elif defined(HAVE_UTIMES)
5285 UTIME_TO_TIMEVAL;
5286 return utimes(path, time);
5287 #elif defined(HAVE_UTIME_H)
5288 UTIME_TO_UTIMBUF;
5289 return utime(path, time);
5290 #else
5291 UTIME_TO_TIME_T;
5292 return utime(path, time);
5293 #endif
5294 }
5295
5296 #endif
5297
5298 static int
split_py_long_to_s_and_ns(PyObject * module,PyObject * py_long,time_t * s,long * ns)5299 split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5300 {
5301 int result = 0;
5302 PyObject *divmod;
5303 divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5304 if (!divmod)
5305 goto exit;
5306 if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
5307 PyErr_Format(PyExc_TypeError,
5308 "%.200s.__divmod__() must return a 2-tuple, not %.200s",
5309 _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
5310 goto exit;
5311 }
5312 *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5313 if ((*s == -1) && PyErr_Occurred())
5314 goto exit;
5315 *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5316 if ((*ns == -1) && PyErr_Occurred())
5317 goto exit;
5318
5319 result = 1;
5320 exit:
5321 Py_XDECREF(divmod);
5322 return result;
5323 }
5324
5325
5326 /*[clinic input]
5327 os.utime
5328
5329 path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
5330 times: object = None
5331 *
5332 ns: object = NULL
5333 dir_fd: dir_fd(requires='futimensat') = None
5334 follow_symlinks: bool=True
5335
5336 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
5337
5338 Set the access and modified time of path.
5339
5340 path may always be specified as a string.
5341 On some platforms, path may also be specified as an open file descriptor.
5342 If this functionality is unavailable, using it raises an exception.
5343
5344 If times is not None, it must be a tuple (atime, mtime);
5345 atime and mtime should be expressed as float seconds since the epoch.
5346 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
5347 atime_ns and mtime_ns should be expressed as integer nanoseconds
5348 since the epoch.
5349 If times is None and ns is unspecified, utime uses the current time.
5350 Specifying tuples for both times and ns is an error.
5351
5352 If dir_fd is not None, it should be a file descriptor open to a directory,
5353 and path should be relative; path will then be relative to that directory.
5354 If follow_symlinks is False, and the last element of the path is a symbolic
5355 link, utime will modify the symbolic link itself instead of the file the
5356 link points to.
5357 It is an error to use dir_fd or follow_symlinks when specifying path
5358 as an open file descriptor.
5359 dir_fd and follow_symlinks may not be available on your platform.
5360 If they are unavailable, using them will raise a NotImplementedError.
5361
5362 [clinic start generated code]*/
5363
5364 static PyObject *
os_utime_impl(PyObject * module,path_t * path,PyObject * times,PyObject * ns,int dir_fd,int follow_symlinks)5365 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
5366 int dir_fd, int follow_symlinks)
5367 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
5368 {
5369 #ifdef MS_WINDOWS
5370 HANDLE hFile;
5371 FILETIME atime, mtime;
5372 #else
5373 int result;
5374 #endif
5375
5376 utime_t utime;
5377
5378 memset(&utime, 0, sizeof(utime_t));
5379
5380 if (times != Py_None && ns) {
5381 PyErr_SetString(PyExc_ValueError,
5382 "utime: you may specify either 'times'"
5383 " or 'ns' but not both");
5384 return NULL;
5385 }
5386
5387 if (times != Py_None) {
5388 time_t a_sec, m_sec;
5389 long a_nsec, m_nsec;
5390 if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
5391 PyErr_SetString(PyExc_TypeError,
5392 "utime: 'times' must be either"
5393 " a tuple of two ints or None");
5394 return NULL;
5395 }
5396 utime.now = 0;
5397 if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
5398 &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
5399 _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
5400 &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
5401 return NULL;
5402 }
5403 utime.atime_s = a_sec;
5404 utime.atime_ns = a_nsec;
5405 utime.mtime_s = m_sec;
5406 utime.mtime_ns = m_nsec;
5407 }
5408 else if (ns) {
5409 if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
5410 PyErr_SetString(PyExc_TypeError,
5411 "utime: 'ns' must be a tuple of two ints");
5412 return NULL;
5413 }
5414 utime.now = 0;
5415 if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
5416 &utime.atime_s, &utime.atime_ns) ||
5417 !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
5418 &utime.mtime_s, &utime.mtime_ns)) {
5419 return NULL;
5420 }
5421 }
5422 else {
5423 /* times and ns are both None/unspecified. use "now". */
5424 utime.now = 1;
5425 }
5426
5427 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
5428 if (follow_symlinks_specified("utime", follow_symlinks))
5429 return NULL;
5430 #endif
5431
5432 if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
5433 dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
5434 fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
5435 return NULL;
5436
5437 #if !defined(HAVE_UTIMENSAT)
5438 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
5439 PyErr_SetString(PyExc_ValueError,
5440 "utime: cannot use dir_fd and follow_symlinks "
5441 "together on this platform");
5442 return NULL;
5443 }
5444 #endif
5445
5446 if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
5447 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5448 return NULL;
5449 }
5450
5451 #ifdef MS_WINDOWS
5452 Py_BEGIN_ALLOW_THREADS
5453 hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
5454 NULL, OPEN_EXISTING,
5455 FILE_FLAG_BACKUP_SEMANTICS, NULL);
5456 Py_END_ALLOW_THREADS
5457 if (hFile == INVALID_HANDLE_VALUE) {
5458 path_error(path);
5459 return NULL;
5460 }
5461
5462 if (utime.now) {
5463 GetSystemTimeAsFileTime(&mtime);
5464 atime = mtime;
5465 }
5466 else {
5467 _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
5468 _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
5469 }
5470 if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
5471 /* Avoid putting the file name into the error here,
5472 as that may confuse the user into believing that
5473 something is wrong with the file, when it also
5474 could be the time stamp that gives a problem. */
5475 PyErr_SetFromWindowsErr(0);
5476 CloseHandle(hFile);
5477 return NULL;
5478 }
5479 CloseHandle(hFile);
5480 #else /* MS_WINDOWS */
5481 Py_BEGIN_ALLOW_THREADS
5482
5483 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5484 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
5485 result = utime_nofollow_symlinks(&utime, path->narrow);
5486 else
5487 #endif
5488
5489 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5490 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
5491 result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
5492
5493 } else
5494 #endif
5495
5496 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5497 if (path->fd != -1)
5498 result = utime_fd(&utime, path->fd);
5499 else
5500 #endif
5501
5502 result = utime_default(&utime, path->narrow);
5503
5504 Py_END_ALLOW_THREADS
5505
5506 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5507 /* See utime_dir_fd implementation */
5508 if (result == -1 && errno == ENOSYS) {
5509 argument_unavailable_error(NULL, "dir_fd");
5510 return NULL;
5511 }
5512 #endif
5513
5514 if (result < 0) {
5515 /* see previous comment about not putting filename in error here */
5516 posix_error();
5517 return NULL;
5518 }
5519
5520 #endif /* MS_WINDOWS */
5521
5522 Py_RETURN_NONE;
5523 }
5524
5525 /* Process operations */
5526
5527
5528 /*[clinic input]
5529 os._exit
5530
5531 status: int
5532
5533 Exit to the system with specified status, without normal exit processing.
5534 [clinic start generated code]*/
5535
5536 static PyObject *
os__exit_impl(PyObject * module,int status)5537 os__exit_impl(PyObject *module, int status)
5538 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5539 {
5540 _exit(status);
5541 return NULL; /* Make gcc -Wall happy */
5542 }
5543
5544 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5545 #define EXECV_CHAR wchar_t
5546 #else
5547 #define EXECV_CHAR char
5548 #endif
5549
5550 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5551 static void
free_string_array(EXECV_CHAR ** array,Py_ssize_t count)5552 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5553 {
5554 Py_ssize_t i;
5555 for (i = 0; i < count; i++)
5556 PyMem_Free(array[i]);
5557 PyMem_Free(array);
5558 }
5559
5560 static int
fsconvert_strdup(PyObject * o,EXECV_CHAR ** out)5561 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5562 {
5563 Py_ssize_t size;
5564 PyObject *ub;
5565 int result = 0;
5566 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5567 if (!PyUnicode_FSDecoder(o, &ub))
5568 return 0;
5569 *out = PyUnicode_AsWideCharString(ub, &size);
5570 if (*out)
5571 result = 1;
5572 #else
5573 if (!PyUnicode_FSConverter(o, &ub))
5574 return 0;
5575 size = PyBytes_GET_SIZE(ub);
5576 *out = PyMem_Malloc(size + 1);
5577 if (*out) {
5578 memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5579 result = 1;
5580 } else
5581 PyErr_NoMemory();
5582 #endif
5583 Py_DECREF(ub);
5584 return result;
5585 }
5586 #endif
5587
5588 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5589 static EXECV_CHAR**
parse_envlist(PyObject * env,Py_ssize_t * envc_ptr)5590 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5591 {
5592 Py_ssize_t i, pos, envc;
5593 PyObject *keys=NULL, *vals=NULL;
5594 PyObject *key, *val, *key2, *val2, *keyval;
5595 EXECV_CHAR **envlist;
5596
5597 i = PyMapping_Size(env);
5598 if (i < 0)
5599 return NULL;
5600 envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5601 if (envlist == NULL) {
5602 PyErr_NoMemory();
5603 return NULL;
5604 }
5605 envc = 0;
5606 keys = PyMapping_Keys(env);
5607 if (!keys)
5608 goto error;
5609 vals = PyMapping_Values(env);
5610 if (!vals)
5611 goto error;
5612 if (!PyList_Check(keys) || !PyList_Check(vals)) {
5613 PyErr_Format(PyExc_TypeError,
5614 "env.keys() or env.values() is not a list");
5615 goto error;
5616 }
5617
5618 for (pos = 0; pos < i; pos++) {
5619 key = PyList_GetItem(keys, pos);
5620 val = PyList_GetItem(vals, pos);
5621 if (!key || !val)
5622 goto error;
5623
5624 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5625 if (!PyUnicode_FSDecoder(key, &key2))
5626 goto error;
5627 if (!PyUnicode_FSDecoder(val, &val2)) {
5628 Py_DECREF(key2);
5629 goto error;
5630 }
5631 /* Search from index 1 because on Windows starting '=' is allowed for
5632 defining hidden environment variables. */
5633 if (PyUnicode_GET_LENGTH(key2) == 0 ||
5634 PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5635 {
5636 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5637 Py_DECREF(key2);
5638 Py_DECREF(val2);
5639 goto error;
5640 }
5641 keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5642 #else
5643 if (!PyUnicode_FSConverter(key, &key2))
5644 goto error;
5645 if (!PyUnicode_FSConverter(val, &val2)) {
5646 Py_DECREF(key2);
5647 goto error;
5648 }
5649 if (PyBytes_GET_SIZE(key2) == 0 ||
5650 strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5651 {
5652 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5653 Py_DECREF(key2);
5654 Py_DECREF(val2);
5655 goto error;
5656 }
5657 keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5658 PyBytes_AS_STRING(val2));
5659 #endif
5660 Py_DECREF(key2);
5661 Py_DECREF(val2);
5662 if (!keyval)
5663 goto error;
5664
5665 if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5666 Py_DECREF(keyval);
5667 goto error;
5668 }
5669
5670 Py_DECREF(keyval);
5671 }
5672 Py_DECREF(vals);
5673 Py_DECREF(keys);
5674
5675 envlist[envc] = 0;
5676 *envc_ptr = envc;
5677 return envlist;
5678
5679 error:
5680 Py_XDECREF(keys);
5681 Py_XDECREF(vals);
5682 free_string_array(envlist, envc);
5683 return NULL;
5684 }
5685
5686 static EXECV_CHAR**
parse_arglist(PyObject * argv,Py_ssize_t * argc)5687 parse_arglist(PyObject* argv, Py_ssize_t *argc)
5688 {
5689 int i;
5690 EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5691 if (argvlist == NULL) {
5692 PyErr_NoMemory();
5693 return NULL;
5694 }
5695 for (i = 0; i < *argc; i++) {
5696 PyObject* item = PySequence_ITEM(argv, i);
5697 if (item == NULL)
5698 goto fail;
5699 if (!fsconvert_strdup(item, &argvlist[i])) {
5700 Py_DECREF(item);
5701 goto fail;
5702 }
5703 Py_DECREF(item);
5704 }
5705 argvlist[*argc] = NULL;
5706 return argvlist;
5707 fail:
5708 *argc = i;
5709 free_string_array(argvlist, *argc);
5710 return NULL;
5711 }
5712
5713 #endif
5714
5715
5716 #ifdef HAVE_EXECV
5717 /*[clinic input]
5718 os.execv
5719
5720 path: path_t
5721 Path of executable file.
5722 argv: object
5723 Tuple or list of strings.
5724 /
5725
5726 Execute an executable path with arguments, replacing current process.
5727 [clinic start generated code]*/
5728
5729 static PyObject *
os_execv_impl(PyObject * module,path_t * path,PyObject * argv)5730 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5731 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5732 {
5733 EXECV_CHAR **argvlist;
5734 Py_ssize_t argc;
5735
5736 /* execv has two arguments: (path, argv), where
5737 argv is a list or tuple of strings. */
5738
5739 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5740 PyErr_SetString(PyExc_TypeError,
5741 "execv() arg 2 must be a tuple or list");
5742 return NULL;
5743 }
5744 argc = PySequence_Size(argv);
5745 if (argc < 1) {
5746 PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5747 return NULL;
5748 }
5749
5750 argvlist = parse_arglist(argv, &argc);
5751 if (argvlist == NULL) {
5752 return NULL;
5753 }
5754 if (!argvlist[0][0]) {
5755 PyErr_SetString(PyExc_ValueError,
5756 "execv() arg 2 first element cannot be empty");
5757 free_string_array(argvlist, argc);
5758 return NULL;
5759 }
5760
5761 if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5762 free_string_array(argvlist, argc);
5763 return NULL;
5764 }
5765
5766 _Py_BEGIN_SUPPRESS_IPH
5767 #ifdef HAVE_WEXECV
5768 _wexecv(path->wide, argvlist);
5769 #else
5770 execv(path->narrow, argvlist);
5771 #endif
5772 _Py_END_SUPPRESS_IPH
5773
5774 /* If we get here it's definitely an error */
5775
5776 free_string_array(argvlist, argc);
5777 return posix_error();
5778 }
5779
5780
5781 /*[clinic input]
5782 os.execve
5783
5784 path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5785 Path of executable file.
5786 argv: object
5787 Tuple or list of strings.
5788 env: object
5789 Dictionary of strings mapping to strings.
5790
5791 Execute an executable path with arguments, replacing current process.
5792 [clinic start generated code]*/
5793
5794 static PyObject *
os_execve_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env)5795 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5796 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5797 {
5798 EXECV_CHAR **argvlist = NULL;
5799 EXECV_CHAR **envlist;
5800 Py_ssize_t argc, envc;
5801
5802 /* execve has three arguments: (path, argv, env), where
5803 argv is a list or tuple of strings and env is a dictionary
5804 like posix.environ. */
5805
5806 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5807 PyErr_SetString(PyExc_TypeError,
5808 "execve: argv must be a tuple or list");
5809 goto fail_0;
5810 }
5811 argc = PySequence_Size(argv);
5812 if (argc < 1) {
5813 PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5814 return NULL;
5815 }
5816
5817 if (!PyMapping_Check(env)) {
5818 PyErr_SetString(PyExc_TypeError,
5819 "execve: environment must be a mapping object");
5820 goto fail_0;
5821 }
5822
5823 argvlist = parse_arglist(argv, &argc);
5824 if (argvlist == NULL) {
5825 goto fail_0;
5826 }
5827 if (!argvlist[0][0]) {
5828 PyErr_SetString(PyExc_ValueError,
5829 "execve: argv first element cannot be empty");
5830 goto fail_0;
5831 }
5832
5833 envlist = parse_envlist(env, &envc);
5834 if (envlist == NULL)
5835 goto fail_0;
5836
5837 if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5838 goto fail_1;
5839 }
5840
5841 _Py_BEGIN_SUPPRESS_IPH
5842 #ifdef HAVE_FEXECVE
5843 if (path->fd > -1)
5844 fexecve(path->fd, argvlist, envlist);
5845 else
5846 #endif
5847 #ifdef HAVE_WEXECV
5848 _wexecve(path->wide, argvlist, envlist);
5849 #else
5850 execve(path->narrow, argvlist, envlist);
5851 #endif
5852 _Py_END_SUPPRESS_IPH
5853
5854 /* If we get here it's definitely an error */
5855
5856 posix_path_error(path);
5857 fail_1:
5858 free_string_array(envlist, envc);
5859 fail_0:
5860 if (argvlist)
5861 free_string_array(argvlist, argc);
5862 return NULL;
5863 }
5864
5865 #endif /* HAVE_EXECV */
5866
5867 #ifdef HAVE_POSIX_SPAWN
5868
5869 enum posix_spawn_file_actions_identifier {
5870 POSIX_SPAWN_OPEN,
5871 POSIX_SPAWN_CLOSE,
5872 POSIX_SPAWN_DUP2
5873 };
5874
5875 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
5876 static int
5877 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
5878 #endif
5879
5880 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)5881 parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
5882 int resetids, int setsid, PyObject *setsigmask,
5883 PyObject *setsigdef, PyObject *scheduler,
5884 posix_spawnattr_t *attrp)
5885 {
5886 long all_flags = 0;
5887
5888 errno = posix_spawnattr_init(attrp);
5889 if (errno) {
5890 posix_error();
5891 return -1;
5892 }
5893
5894 if (setpgroup) {
5895 pid_t pgid = PyLong_AsPid(setpgroup);
5896 if (pgid == (pid_t)-1 && PyErr_Occurred()) {
5897 goto fail;
5898 }
5899 errno = posix_spawnattr_setpgroup(attrp, pgid);
5900 if (errno) {
5901 posix_error();
5902 goto fail;
5903 }
5904 all_flags |= POSIX_SPAWN_SETPGROUP;
5905 }
5906
5907 if (resetids) {
5908 all_flags |= POSIX_SPAWN_RESETIDS;
5909 }
5910
5911 if (setsid) {
5912 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5913 if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
5914 #endif
5915 #ifdef POSIX_SPAWN_SETSID
5916 all_flags |= POSIX_SPAWN_SETSID;
5917 #elif defined(POSIX_SPAWN_SETSID_NP)
5918 all_flags |= POSIX_SPAWN_SETSID_NP;
5919 #else
5920 argument_unavailable_error(func_name, "setsid");
5921 return -1;
5922 #endif
5923
5924 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5925 } else {
5926 argument_unavailable_error(func_name, "setsid");
5927 return -1;
5928 }
5929 #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
5930
5931 }
5932
5933 #ifdef HAVE_SIGSET_T
5934 if (setsigmask) {
5935 sigset_t set;
5936 if (!_Py_Sigset_Converter(setsigmask, &set)) {
5937 goto fail;
5938 }
5939 errno = posix_spawnattr_setsigmask(attrp, &set);
5940 if (errno) {
5941 posix_error();
5942 goto fail;
5943 }
5944 all_flags |= POSIX_SPAWN_SETSIGMASK;
5945 }
5946
5947 if (setsigdef) {
5948 sigset_t set;
5949 if (!_Py_Sigset_Converter(setsigdef, &set)) {
5950 goto fail;
5951 }
5952 errno = posix_spawnattr_setsigdefault(attrp, &set);
5953 if (errno) {
5954 posix_error();
5955 goto fail;
5956 }
5957 all_flags |= POSIX_SPAWN_SETSIGDEF;
5958 }
5959 #else
5960 if (setsigmask || setsigdef) {
5961 PyErr_SetString(PyExc_NotImplementedError,
5962 "sigset is not supported on this platform");
5963 goto fail;
5964 }
5965 #endif
5966
5967 if (scheduler) {
5968 #ifdef POSIX_SPAWN_SETSCHEDULER
5969 PyObject *py_schedpolicy;
5970 PyObject *schedparam_obj;
5971 struct sched_param schedparam;
5972
5973 if (!PyArg_ParseTuple(scheduler, "OO"
5974 ";A scheduler tuple must have two elements",
5975 &py_schedpolicy, &schedparam_obj)) {
5976 goto fail;
5977 }
5978 if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
5979 goto fail;
5980 }
5981 if (py_schedpolicy != Py_None) {
5982 int schedpolicy = _PyLong_AsInt(py_schedpolicy);
5983
5984 if (schedpolicy == -1 && PyErr_Occurred()) {
5985 goto fail;
5986 }
5987 errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
5988 if (errno) {
5989 posix_error();
5990 goto fail;
5991 }
5992 all_flags |= POSIX_SPAWN_SETSCHEDULER;
5993 }
5994 errno = posix_spawnattr_setschedparam(attrp, &schedparam);
5995 if (errno) {
5996 posix_error();
5997 goto fail;
5998 }
5999 all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
6000 #else
6001 PyErr_SetString(PyExc_NotImplementedError,
6002 "The scheduler option is not supported in this system.");
6003 goto fail;
6004 #endif
6005 }
6006
6007 errno = posix_spawnattr_setflags(attrp, all_flags);
6008 if (errno) {
6009 posix_error();
6010 goto fail;
6011 }
6012
6013 return 0;
6014
6015 fail:
6016 (void)posix_spawnattr_destroy(attrp);
6017 return -1;
6018 }
6019
6020 static int
parse_file_actions(PyObject * file_actions,posix_spawn_file_actions_t * file_actionsp,PyObject * temp_buffer)6021 parse_file_actions(PyObject *file_actions,
6022 posix_spawn_file_actions_t *file_actionsp,
6023 PyObject *temp_buffer)
6024 {
6025 PyObject *seq;
6026 PyObject *file_action = NULL;
6027 PyObject *tag_obj;
6028
6029 seq = PySequence_Fast(file_actions,
6030 "file_actions must be a sequence or None");
6031 if (seq == NULL) {
6032 return -1;
6033 }
6034
6035 errno = posix_spawn_file_actions_init(file_actionsp);
6036 if (errno) {
6037 posix_error();
6038 Py_DECREF(seq);
6039 return -1;
6040 }
6041
6042 for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
6043 file_action = PySequence_Fast_GET_ITEM(seq, i);
6044 Py_INCREF(file_action);
6045 if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
6046 PyErr_SetString(PyExc_TypeError,
6047 "Each file_actions element must be a non-empty tuple");
6048 goto fail;
6049 }
6050 long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
6051 if (tag == -1 && PyErr_Occurred()) {
6052 goto fail;
6053 }
6054
6055 /* Populate the file_actions object */
6056 switch (tag) {
6057 case POSIX_SPAWN_OPEN: {
6058 int fd, oflag;
6059 PyObject *path;
6060 unsigned long mode;
6061 if (!PyArg_ParseTuple(file_action, "OiO&ik"
6062 ";A open file_action tuple must have 5 elements",
6063 &tag_obj, &fd, PyUnicode_FSConverter, &path,
6064 &oflag, &mode))
6065 {
6066 goto fail;
6067 }
6068 if (PyList_Append(temp_buffer, path)) {
6069 Py_DECREF(path);
6070 goto fail;
6071 }
6072 errno = posix_spawn_file_actions_addopen(file_actionsp,
6073 fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
6074 Py_DECREF(path);
6075 if (errno) {
6076 posix_error();
6077 goto fail;
6078 }
6079 break;
6080 }
6081 case POSIX_SPAWN_CLOSE: {
6082 int fd;
6083 if (!PyArg_ParseTuple(file_action, "Oi"
6084 ";A close file_action tuple must have 2 elements",
6085 &tag_obj, &fd))
6086 {
6087 goto fail;
6088 }
6089 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
6090 if (errno) {
6091 posix_error();
6092 goto fail;
6093 }
6094 break;
6095 }
6096 case POSIX_SPAWN_DUP2: {
6097 int fd1, fd2;
6098 if (!PyArg_ParseTuple(file_action, "Oii"
6099 ";A dup2 file_action tuple must have 3 elements",
6100 &tag_obj, &fd1, &fd2))
6101 {
6102 goto fail;
6103 }
6104 errno = posix_spawn_file_actions_adddup2(file_actionsp,
6105 fd1, fd2);
6106 if (errno) {
6107 posix_error();
6108 goto fail;
6109 }
6110 break;
6111 }
6112 default: {
6113 PyErr_SetString(PyExc_TypeError,
6114 "Unknown file_actions identifier");
6115 goto fail;
6116 }
6117 }
6118 Py_DECREF(file_action);
6119 }
6120
6121 Py_DECREF(seq);
6122 return 0;
6123
6124 fail:
6125 Py_DECREF(seq);
6126 Py_DECREF(file_action);
6127 (void)posix_spawn_file_actions_destroy(file_actionsp);
6128 return -1;
6129 }
6130
6131
6132 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)6133 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
6134 PyObject *env, PyObject *file_actions,
6135 PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
6136 PyObject *setsigdef, PyObject *scheduler)
6137 {
6138 const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
6139 EXECV_CHAR **argvlist = NULL;
6140 EXECV_CHAR **envlist = NULL;
6141 posix_spawn_file_actions_t file_actions_buf;
6142 posix_spawn_file_actions_t *file_actionsp = NULL;
6143 posix_spawnattr_t attr;
6144 posix_spawnattr_t *attrp = NULL;
6145 Py_ssize_t argc, envc;
6146 PyObject *result = NULL;
6147 PyObject *temp_buffer = NULL;
6148 pid_t pid;
6149 int err_code;
6150
6151 /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
6152 argv is a list or tuple of strings and env is a dictionary
6153 like posix.environ. */
6154
6155 if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6156 PyErr_Format(PyExc_TypeError,
6157 "%s: argv must be a tuple or list", func_name);
6158 goto exit;
6159 }
6160 argc = PySequence_Size(argv);
6161 if (argc < 1) {
6162 PyErr_Format(PyExc_ValueError,
6163 "%s: argv must not be empty", func_name);
6164 return NULL;
6165 }
6166
6167 if (!PyMapping_Check(env)) {
6168 PyErr_Format(PyExc_TypeError,
6169 "%s: environment must be a mapping object", func_name);
6170 goto exit;
6171 }
6172
6173 argvlist = parse_arglist(argv, &argc);
6174 if (argvlist == NULL) {
6175 goto exit;
6176 }
6177 if (!argvlist[0][0]) {
6178 PyErr_Format(PyExc_ValueError,
6179 "%s: argv first element cannot be empty", func_name);
6180 goto exit;
6181 }
6182
6183 envlist = parse_envlist(env, &envc);
6184 if (envlist == NULL) {
6185 goto exit;
6186 }
6187
6188 if (file_actions != NULL && file_actions != Py_None) {
6189 /* There is a bug in old versions of glibc that makes some of the
6190 * helper functions for manipulating file actions not copy the provided
6191 * buffers. The problem is that posix_spawn_file_actions_addopen does not
6192 * copy the value of path for some old versions of glibc (<2.20).
6193 * The use of temp_buffer here is a workaround that keeps the
6194 * python objects that own the buffers alive until posix_spawn gets called.
6195 * Check https://bugs.python.org/issue33630 and
6196 * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
6197 temp_buffer = PyList_New(0);
6198 if (!temp_buffer) {
6199 goto exit;
6200 }
6201 if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
6202 goto exit;
6203 }
6204 file_actionsp = &file_actions_buf;
6205 }
6206
6207 if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
6208 setsigmask, setsigdef, scheduler, &attr)) {
6209 goto exit;
6210 }
6211 attrp = &attr;
6212
6213 if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
6214 goto exit;
6215 }
6216
6217 _Py_BEGIN_SUPPRESS_IPH
6218 #ifdef HAVE_POSIX_SPAWNP
6219 if (use_posix_spawnp) {
6220 err_code = posix_spawnp(&pid, path->narrow,
6221 file_actionsp, attrp, argvlist, envlist);
6222 }
6223 else
6224 #endif /* HAVE_POSIX_SPAWNP */
6225 {
6226 err_code = posix_spawn(&pid, path->narrow,
6227 file_actionsp, attrp, argvlist, envlist);
6228 }
6229 _Py_END_SUPPRESS_IPH
6230
6231 if (err_code) {
6232 errno = err_code;
6233 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
6234 goto exit;
6235 }
6236 #ifdef _Py_MEMORY_SANITIZER
6237 __msan_unpoison(&pid, sizeof(pid));
6238 #endif
6239 result = PyLong_FromPid(pid);
6240
6241 exit:
6242 if (file_actionsp) {
6243 (void)posix_spawn_file_actions_destroy(file_actionsp);
6244 }
6245 if (attrp) {
6246 (void)posix_spawnattr_destroy(attrp);
6247 }
6248 if (envlist) {
6249 free_string_array(envlist, envc);
6250 }
6251 if (argvlist) {
6252 free_string_array(argvlist, argc);
6253 }
6254 Py_XDECREF(temp_buffer);
6255 return result;
6256 }
6257
6258
6259 /*[clinic input]
6260
6261 os.posix_spawn
6262 path: path_t
6263 Path of executable file.
6264 argv: object
6265 Tuple or list of strings.
6266 env: object
6267 Dictionary of strings mapping to strings.
6268 /
6269 *
6270 file_actions: object(c_default='NULL') = ()
6271 A sequence of file action tuples.
6272 setpgroup: object = NULL
6273 The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6274 resetids: bool(accept={int}) = False
6275 If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
6276 setsid: bool(accept={int}) = False
6277 If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6278 setsigmask: object(c_default='NULL') = ()
6279 The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6280 setsigdef: object(c_default='NULL') = ()
6281 The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6282 scheduler: object = NULL
6283 A tuple with the scheduler policy (optional) and parameters.
6284
6285 Execute the program specified by path in a new process.
6286 [clinic start generated code]*/
6287
6288 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)6289 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
6290 PyObject *env, PyObject *file_actions,
6291 PyObject *setpgroup, int resetids, int setsid,
6292 PyObject *setsigmask, PyObject *setsigdef,
6293 PyObject *scheduler)
6294 /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
6295 {
6296 return py_posix_spawn(0, module, path, argv, env, file_actions,
6297 setpgroup, resetids, setsid, setsigmask, setsigdef,
6298 scheduler);
6299 }
6300 #endif /* HAVE_POSIX_SPAWN */
6301
6302
6303
6304 #ifdef HAVE_POSIX_SPAWNP
6305 /*[clinic input]
6306
6307 os.posix_spawnp
6308 path: path_t
6309 Path of executable file.
6310 argv: object
6311 Tuple or list of strings.
6312 env: object
6313 Dictionary of strings mapping to strings.
6314 /
6315 *
6316 file_actions: object(c_default='NULL') = ()
6317 A sequence of file action tuples.
6318 setpgroup: object = NULL
6319 The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6320 resetids: bool(accept={int}) = False
6321 If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
6322 setsid: bool(accept={int}) = False
6323 If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6324 setsigmask: object(c_default='NULL') = ()
6325 The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6326 setsigdef: object(c_default='NULL') = ()
6327 The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6328 scheduler: object = NULL
6329 A tuple with the scheduler policy (optional) and parameters.
6330
6331 Execute the program specified by path in a new process.
6332 [clinic start generated code]*/
6333
6334 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)6335 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
6336 PyObject *env, PyObject *file_actions,
6337 PyObject *setpgroup, int resetids, int setsid,
6338 PyObject *setsigmask, PyObject *setsigdef,
6339 PyObject *scheduler)
6340 /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
6341 {
6342 return py_posix_spawn(1, module, path, argv, env, file_actions,
6343 setpgroup, resetids, setsid, setsigmask, setsigdef,
6344 scheduler);
6345 }
6346 #endif /* HAVE_POSIX_SPAWNP */
6347
6348 #ifdef HAVE_RTPSPAWN
6349 static intptr_t
_rtp_spawn(int mode,const char * rtpFileName,const char * argv[],const char * envp[])6350 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
6351 const char *envp[])
6352 {
6353 RTP_ID rtpid;
6354 int status;
6355 pid_t res;
6356 int async_err = 0;
6357
6358 /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
6359 uStackSize=0 cannot be used, the default stack size is too small for
6360 Python. */
6361 if (envp) {
6362 rtpid = rtpSpawn(rtpFileName, argv, envp,
6363 100, 0x1000000, 0, VX_FP_TASK);
6364 }
6365 else {
6366 rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
6367 100, 0x1000000, 0, VX_FP_TASK);
6368 }
6369 if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
6370 do {
6371 res = waitpid((pid_t)rtpid, &status, 0);
6372 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6373
6374 if (res < 0)
6375 return RTP_ID_ERROR;
6376 return ((intptr_t)status);
6377 }
6378 return ((intptr_t)rtpid);
6379 }
6380 #endif
6381
6382 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
6383 /*[clinic input]
6384 os.spawnv
6385
6386 mode: int
6387 Mode of process creation.
6388 path: path_t
6389 Path of executable file.
6390 argv: object
6391 Tuple or list of strings.
6392 /
6393
6394 Execute the program specified by path in a new process.
6395 [clinic start generated code]*/
6396
6397 static PyObject *
os_spawnv_impl(PyObject * module,int mode,path_t * path,PyObject * argv)6398 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
6399 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
6400 {
6401 EXECV_CHAR **argvlist;
6402 int i;
6403 Py_ssize_t argc;
6404 intptr_t spawnval;
6405 PyObject *(*getitem)(PyObject *, Py_ssize_t);
6406
6407 /* spawnv has three arguments: (mode, path, argv), where
6408 argv is a list or tuple of strings. */
6409
6410 if (PyList_Check(argv)) {
6411 argc = PyList_Size(argv);
6412 getitem = PyList_GetItem;
6413 }
6414 else if (PyTuple_Check(argv)) {
6415 argc = PyTuple_Size(argv);
6416 getitem = PyTuple_GetItem;
6417 }
6418 else {
6419 PyErr_SetString(PyExc_TypeError,
6420 "spawnv() arg 2 must be a tuple or list");
6421 return NULL;
6422 }
6423 if (argc == 0) {
6424 PyErr_SetString(PyExc_ValueError,
6425 "spawnv() arg 2 cannot be empty");
6426 return NULL;
6427 }
6428
6429 argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6430 if (argvlist == NULL) {
6431 return PyErr_NoMemory();
6432 }
6433 for (i = 0; i < argc; i++) {
6434 if (!fsconvert_strdup((*getitem)(argv, i),
6435 &argvlist[i])) {
6436 free_string_array(argvlist, i);
6437 PyErr_SetString(
6438 PyExc_TypeError,
6439 "spawnv() arg 2 must contain only strings");
6440 return NULL;
6441 }
6442 if (i == 0 && !argvlist[0][0]) {
6443 free_string_array(argvlist, i + 1);
6444 PyErr_SetString(
6445 PyExc_ValueError,
6446 "spawnv() arg 2 first element cannot be empty");
6447 return NULL;
6448 }
6449 }
6450 argvlist[argc] = NULL;
6451
6452 #if !defined(HAVE_RTPSPAWN)
6453 if (mode == _OLD_P_OVERLAY)
6454 mode = _P_OVERLAY;
6455 #endif
6456
6457 if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
6458 Py_None) < 0) {
6459 free_string_array(argvlist, argc);
6460 return NULL;
6461 }
6462
6463 Py_BEGIN_ALLOW_THREADS
6464 _Py_BEGIN_SUPPRESS_IPH
6465 #ifdef HAVE_WSPAWNV
6466 spawnval = _wspawnv(mode, path->wide, argvlist);
6467 #elif defined(HAVE_RTPSPAWN)
6468 spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
6469 #else
6470 spawnval = _spawnv(mode, path->narrow, argvlist);
6471 #endif
6472 _Py_END_SUPPRESS_IPH
6473 Py_END_ALLOW_THREADS
6474
6475 free_string_array(argvlist, argc);
6476
6477 if (spawnval == -1)
6478 return posix_error();
6479 else
6480 return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6481 }
6482
6483 /*[clinic input]
6484 os.spawnve
6485
6486 mode: int
6487 Mode of process creation.
6488 path: path_t
6489 Path of executable file.
6490 argv: object
6491 Tuple or list of strings.
6492 env: object
6493 Dictionary of strings mapping to strings.
6494 /
6495
6496 Execute the program specified by path in a new process.
6497 [clinic start generated code]*/
6498
6499 static PyObject *
os_spawnve_impl(PyObject * module,int mode,path_t * path,PyObject * argv,PyObject * env)6500 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
6501 PyObject *env)
6502 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
6503 {
6504 EXECV_CHAR **argvlist;
6505 EXECV_CHAR **envlist;
6506 PyObject *res = NULL;
6507 Py_ssize_t argc, i, envc;
6508 intptr_t spawnval;
6509 PyObject *(*getitem)(PyObject *, Py_ssize_t);
6510 Py_ssize_t lastarg = 0;
6511
6512 /* spawnve has four arguments: (mode, path, argv, env), where
6513 argv is a list or tuple of strings and env is a dictionary
6514 like posix.environ. */
6515
6516 if (PyList_Check(argv)) {
6517 argc = PyList_Size(argv);
6518 getitem = PyList_GetItem;
6519 }
6520 else if (PyTuple_Check(argv)) {
6521 argc = PyTuple_Size(argv);
6522 getitem = PyTuple_GetItem;
6523 }
6524 else {
6525 PyErr_SetString(PyExc_TypeError,
6526 "spawnve() arg 2 must be a tuple or list");
6527 goto fail_0;
6528 }
6529 if (argc == 0) {
6530 PyErr_SetString(PyExc_ValueError,
6531 "spawnve() arg 2 cannot be empty");
6532 goto fail_0;
6533 }
6534 if (!PyMapping_Check(env)) {
6535 PyErr_SetString(PyExc_TypeError,
6536 "spawnve() arg 3 must be a mapping object");
6537 goto fail_0;
6538 }
6539
6540 argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6541 if (argvlist == NULL) {
6542 PyErr_NoMemory();
6543 goto fail_0;
6544 }
6545 for (i = 0; i < argc; i++) {
6546 if (!fsconvert_strdup((*getitem)(argv, i),
6547 &argvlist[i]))
6548 {
6549 lastarg = i;
6550 goto fail_1;
6551 }
6552 if (i == 0 && !argvlist[0][0]) {
6553 lastarg = i + 1;
6554 PyErr_SetString(
6555 PyExc_ValueError,
6556 "spawnv() arg 2 first element cannot be empty");
6557 goto fail_1;
6558 }
6559 }
6560 lastarg = argc;
6561 argvlist[argc] = NULL;
6562
6563 envlist = parse_envlist(env, &envc);
6564 if (envlist == NULL)
6565 goto fail_1;
6566
6567 #if !defined(HAVE_RTPSPAWN)
6568 if (mode == _OLD_P_OVERLAY)
6569 mode = _P_OVERLAY;
6570 #endif
6571
6572 if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6573 goto fail_2;
6574 }
6575
6576 Py_BEGIN_ALLOW_THREADS
6577 _Py_BEGIN_SUPPRESS_IPH
6578 #ifdef HAVE_WSPAWNV
6579 spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6580 #elif defined(HAVE_RTPSPAWN)
6581 spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6582 (const char **)envlist);
6583 #else
6584 spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6585 #endif
6586 _Py_END_SUPPRESS_IPH
6587 Py_END_ALLOW_THREADS
6588
6589 if (spawnval == -1)
6590 (void) posix_error();
6591 else
6592 res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6593
6594 fail_2:
6595 while (--envc >= 0) {
6596 PyMem_Free(envlist[envc]);
6597 }
6598 PyMem_Free(envlist);
6599 fail_1:
6600 free_string_array(argvlist, lastarg);
6601 fail_0:
6602 return res;
6603 }
6604
6605 #endif /* HAVE_SPAWNV */
6606
6607 #ifdef HAVE_FORK
6608
6609 /* Helper function to validate arguments.
6610 Returns 0 on success. non-zero on failure with a TypeError raised.
6611 If obj is non-NULL it must be callable. */
6612 static int
check_null_or_callable(PyObject * obj,const char * obj_name)6613 check_null_or_callable(PyObject *obj, const char* obj_name)
6614 {
6615 if (obj && !PyCallable_Check(obj)) {
6616 PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6617 obj_name, _PyType_Name(Py_TYPE(obj)));
6618 return -1;
6619 }
6620 return 0;
6621 }
6622
6623 /*[clinic input]
6624 os.register_at_fork
6625
6626 *
6627 before: object=NULL
6628 A callable to be called in the parent before the fork() syscall.
6629 after_in_child: object=NULL
6630 A callable to be called in the child after fork().
6631 after_in_parent: object=NULL
6632 A callable to be called in the parent after fork().
6633
6634 Register callables to be called when forking a new process.
6635
6636 'before' callbacks are called in reverse order.
6637 'after_in_child' and 'after_in_parent' callbacks are called in order.
6638
6639 [clinic start generated code]*/
6640
6641 static PyObject *
os_register_at_fork_impl(PyObject * module,PyObject * before,PyObject * after_in_child,PyObject * after_in_parent)6642 os_register_at_fork_impl(PyObject *module, PyObject *before,
6643 PyObject *after_in_child, PyObject *after_in_parent)
6644 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6645 {
6646 PyInterpreterState *interp;
6647
6648 if (!before && !after_in_child && !after_in_parent) {
6649 PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6650 return NULL;
6651 }
6652 if (check_null_or_callable(before, "before") ||
6653 check_null_or_callable(after_in_child, "after_in_child") ||
6654 check_null_or_callable(after_in_parent, "after_in_parent")) {
6655 return NULL;
6656 }
6657 interp = _PyInterpreterState_GET();
6658
6659 if (register_at_forker(&interp->before_forkers, before)) {
6660 return NULL;
6661 }
6662 if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6663 return NULL;
6664 }
6665 if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6666 return NULL;
6667 }
6668 Py_RETURN_NONE;
6669 }
6670 #endif /* HAVE_FORK */
6671
6672
6673 #ifdef HAVE_FORK1
6674 /*[clinic input]
6675 os.fork1
6676
6677 Fork a child process with a single multiplexed (i.e., not bound) thread.
6678
6679 Return 0 to child process and PID of child to parent process.
6680 [clinic start generated code]*/
6681
6682 static PyObject *
os_fork1_impl(PyObject * module)6683 os_fork1_impl(PyObject *module)
6684 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6685 {
6686 pid_t pid;
6687
6688 if (_PyInterpreterState_GET() != PyInterpreterState_Main()) {
6689 PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6690 return NULL;
6691 }
6692 PyOS_BeforeFork();
6693 pid = fork1();
6694 if (pid == 0) {
6695 /* child: this clobbers and resets the import lock. */
6696 PyOS_AfterFork_Child();
6697 } else {
6698 /* parent: release the import lock. */
6699 PyOS_AfterFork_Parent();
6700 }
6701 if (pid == -1)
6702 return posix_error();
6703 return PyLong_FromPid(pid);
6704 }
6705 #endif /* HAVE_FORK1 */
6706
6707
6708 #ifdef HAVE_FORK
6709 /*[clinic input]
6710 os.fork
6711
6712 Fork a child process.
6713
6714 Return 0 to child process and PID of child to parent process.
6715 [clinic start generated code]*/
6716
6717 static PyObject *
os_fork_impl(PyObject * module)6718 os_fork_impl(PyObject *module)
6719 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6720 {
6721 pid_t pid;
6722 PyInterpreterState *interp = _PyInterpreterState_GET();
6723 if (interp->config._isolated_interpreter) {
6724 PyErr_SetString(PyExc_RuntimeError,
6725 "fork not supported for isolated subinterpreters");
6726 return NULL;
6727 }
6728 if (PySys_Audit("os.fork", NULL) < 0) {
6729 return NULL;
6730 }
6731 PyOS_BeforeFork();
6732 pid = fork();
6733 if (pid == 0) {
6734 /* child: this clobbers and resets the import lock. */
6735 PyOS_AfterFork_Child();
6736 } else {
6737 /* parent: release the import lock. */
6738 PyOS_AfterFork_Parent();
6739 }
6740 if (pid == -1)
6741 return posix_error();
6742 return PyLong_FromPid(pid);
6743 }
6744 #endif /* HAVE_FORK */
6745
6746
6747 #ifdef HAVE_SCHED_H
6748 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6749 /*[clinic input]
6750 os.sched_get_priority_max
6751
6752 policy: int
6753
6754 Get the maximum scheduling priority for policy.
6755 [clinic start generated code]*/
6756
6757 static PyObject *
os_sched_get_priority_max_impl(PyObject * module,int policy)6758 os_sched_get_priority_max_impl(PyObject *module, int policy)
6759 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6760 {
6761 int max;
6762
6763 max = sched_get_priority_max(policy);
6764 if (max < 0)
6765 return posix_error();
6766 return PyLong_FromLong(max);
6767 }
6768
6769
6770 /*[clinic input]
6771 os.sched_get_priority_min
6772
6773 policy: int
6774
6775 Get the minimum scheduling priority for policy.
6776 [clinic start generated code]*/
6777
6778 static PyObject *
os_sched_get_priority_min_impl(PyObject * module,int policy)6779 os_sched_get_priority_min_impl(PyObject *module, int policy)
6780 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6781 {
6782 int min = sched_get_priority_min(policy);
6783 if (min < 0)
6784 return posix_error();
6785 return PyLong_FromLong(min);
6786 }
6787 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6788
6789
6790 #ifdef HAVE_SCHED_SETSCHEDULER
6791 /*[clinic input]
6792 os.sched_getscheduler
6793 pid: pid_t
6794 /
6795
6796 Get the scheduling policy for the process identified by pid.
6797
6798 Passing 0 for pid returns the scheduling policy for the calling process.
6799 [clinic start generated code]*/
6800
6801 static PyObject *
os_sched_getscheduler_impl(PyObject * module,pid_t pid)6802 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6803 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
6804 {
6805 int policy;
6806
6807 policy = sched_getscheduler(pid);
6808 if (policy < 0)
6809 return posix_error();
6810 return PyLong_FromLong(policy);
6811 }
6812 #endif /* HAVE_SCHED_SETSCHEDULER */
6813
6814
6815 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6816 /*[clinic input]
6817 class os.sched_param "PyObject *" "SchedParamType"
6818
6819 @classmethod
6820 os.sched_param.__new__
6821
6822 sched_priority: object
6823 A scheduling parameter.
6824
6825 Currently has only one field: sched_priority
6826 [clinic start generated code]*/
6827
6828 static PyObject *
os_sched_param_impl(PyTypeObject * type,PyObject * sched_priority)6829 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6830 /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
6831 {
6832 PyObject *res;
6833
6834 res = PyStructSequence_New(type);
6835 if (!res)
6836 return NULL;
6837 Py_INCREF(sched_priority);
6838 PyStructSequence_SET_ITEM(res, 0, sched_priority);
6839 return res;
6840 }
6841
6842 PyDoc_VAR(os_sched_param__doc__);
6843
6844 static PyStructSequence_Field sched_param_fields[] = {
6845 {"sched_priority", "the scheduling priority"},
6846 {0}
6847 };
6848
6849 static PyStructSequence_Desc sched_param_desc = {
6850 "sched_param", /* name */
6851 os_sched_param__doc__, /* doc */
6852 sched_param_fields,
6853 1
6854 };
6855
6856 static int
convert_sched_param(PyObject * module,PyObject * param,struct sched_param * res)6857 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
6858 {
6859 long priority;
6860
6861 if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
6862 PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
6863 return 0;
6864 }
6865 priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
6866 if (priority == -1 && PyErr_Occurred())
6867 return 0;
6868 if (priority > INT_MAX || priority < INT_MIN) {
6869 PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
6870 return 0;
6871 }
6872 res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
6873 return 1;
6874 }
6875 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
6876
6877
6878 #ifdef HAVE_SCHED_SETSCHEDULER
6879 /*[clinic input]
6880 os.sched_setscheduler
6881
6882 pid: pid_t
6883 policy: int
6884 param as param_obj: object
6885 /
6886
6887 Set the scheduling policy for the process identified by pid.
6888
6889 If pid is 0, the calling process is changed.
6890 param is an instance of sched_param.
6891 [clinic start generated code]*/
6892
6893 static PyObject *
os_sched_setscheduler_impl(PyObject * module,pid_t pid,int policy,PyObject * param_obj)6894 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
6895 PyObject *param_obj)
6896 /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
6897 {
6898 struct sched_param param;
6899 if (!convert_sched_param(module, param_obj, ¶m)) {
6900 return NULL;
6901 }
6902
6903 /*
6904 ** sched_setscheduler() returns 0 in Linux, but the previous
6905 ** scheduling policy under Solaris/Illumos, and others.
6906 ** On error, -1 is returned in all Operating Systems.
6907 */
6908 if (sched_setscheduler(pid, policy, ¶m) == -1)
6909 return posix_error();
6910 Py_RETURN_NONE;
6911 }
6912 #endif /* HAVE_SCHED_SETSCHEDULER*/
6913
6914
6915 #ifdef HAVE_SCHED_SETPARAM
6916 /*[clinic input]
6917 os.sched_getparam
6918 pid: pid_t
6919 /
6920
6921 Returns scheduling parameters for the process identified by pid.
6922
6923 If pid is 0, returns parameters for the calling process.
6924 Return value is an instance of sched_param.
6925 [clinic start generated code]*/
6926
6927 static PyObject *
os_sched_getparam_impl(PyObject * module,pid_t pid)6928 os_sched_getparam_impl(PyObject *module, pid_t pid)
6929 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
6930 {
6931 struct sched_param param;
6932 PyObject *result;
6933 PyObject *priority;
6934
6935 if (sched_getparam(pid, ¶m))
6936 return posix_error();
6937 PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
6938 result = PyStructSequence_New((PyTypeObject *)SchedParamType);
6939 if (!result)
6940 return NULL;
6941 priority = PyLong_FromLong(param.sched_priority);
6942 if (!priority) {
6943 Py_DECREF(result);
6944 return NULL;
6945 }
6946 PyStructSequence_SET_ITEM(result, 0, priority);
6947 return result;
6948 }
6949
6950
6951 /*[clinic input]
6952 os.sched_setparam
6953 pid: pid_t
6954 param as param_obj: object
6955 /
6956
6957 Set scheduling parameters for the process identified by pid.
6958
6959 If pid is 0, sets parameters for the calling process.
6960 param should be an instance of sched_param.
6961 [clinic start generated code]*/
6962
6963 static PyObject *
os_sched_setparam_impl(PyObject * module,pid_t pid,PyObject * param_obj)6964 os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
6965 /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
6966 {
6967 struct sched_param param;
6968 if (!convert_sched_param(module, param_obj, ¶m)) {
6969 return NULL;
6970 }
6971
6972 if (sched_setparam(pid, ¶m))
6973 return posix_error();
6974 Py_RETURN_NONE;
6975 }
6976 #endif /* HAVE_SCHED_SETPARAM */
6977
6978
6979 #ifdef HAVE_SCHED_RR_GET_INTERVAL
6980 /*[clinic input]
6981 os.sched_rr_get_interval -> double
6982 pid: pid_t
6983 /
6984
6985 Return the round-robin quantum for the process identified by pid, in seconds.
6986
6987 Value returned is a float.
6988 [clinic start generated code]*/
6989
6990 static double
os_sched_rr_get_interval_impl(PyObject * module,pid_t pid)6991 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
6992 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
6993 {
6994 struct timespec interval;
6995 if (sched_rr_get_interval(pid, &interval)) {
6996 posix_error();
6997 return -1.0;
6998 }
6999 #ifdef _Py_MEMORY_SANITIZER
7000 __msan_unpoison(&interval, sizeof(interval));
7001 #endif
7002 return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
7003 }
7004 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
7005
7006
7007 /*[clinic input]
7008 os.sched_yield
7009
7010 Voluntarily relinquish the CPU.
7011 [clinic start generated code]*/
7012
7013 static PyObject *
os_sched_yield_impl(PyObject * module)7014 os_sched_yield_impl(PyObject *module)
7015 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
7016 {
7017 if (sched_yield())
7018 return posix_error();
7019 Py_RETURN_NONE;
7020 }
7021
7022 #ifdef HAVE_SCHED_SETAFFINITY
7023 /* The minimum number of CPUs allocated in a cpu_set_t */
7024 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
7025
7026 /*[clinic input]
7027 os.sched_setaffinity
7028 pid: pid_t
7029 mask : object
7030 /
7031
7032 Set the CPU affinity of the process identified by pid to mask.
7033
7034 mask should be an iterable of integers identifying CPUs.
7035 [clinic start generated code]*/
7036
7037 static PyObject *
os_sched_setaffinity_impl(PyObject * module,pid_t pid,PyObject * mask)7038 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
7039 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
7040 {
7041 int ncpus;
7042 size_t setsize;
7043 cpu_set_t *cpu_set = NULL;
7044 PyObject *iterator = NULL, *item;
7045
7046 iterator = PyObject_GetIter(mask);
7047 if (iterator == NULL)
7048 return NULL;
7049
7050 ncpus = NCPUS_START;
7051 setsize = CPU_ALLOC_SIZE(ncpus);
7052 cpu_set = CPU_ALLOC(ncpus);
7053 if (cpu_set == NULL) {
7054 PyErr_NoMemory();
7055 goto error;
7056 }
7057 CPU_ZERO_S(setsize, cpu_set);
7058
7059 while ((item = PyIter_Next(iterator))) {
7060 long cpu;
7061 if (!PyLong_Check(item)) {
7062 PyErr_Format(PyExc_TypeError,
7063 "expected an iterator of ints, "
7064 "but iterator yielded %R",
7065 Py_TYPE(item));
7066 Py_DECREF(item);
7067 goto error;
7068 }
7069 cpu = PyLong_AsLong(item);
7070 Py_DECREF(item);
7071 if (cpu < 0) {
7072 if (!PyErr_Occurred())
7073 PyErr_SetString(PyExc_ValueError, "negative CPU number");
7074 goto error;
7075 }
7076 if (cpu > INT_MAX - 1) {
7077 PyErr_SetString(PyExc_OverflowError, "CPU number too large");
7078 goto error;
7079 }
7080 if (cpu >= ncpus) {
7081 /* Grow CPU mask to fit the CPU number */
7082 int newncpus = ncpus;
7083 cpu_set_t *newmask;
7084 size_t newsetsize;
7085 while (newncpus <= cpu) {
7086 if (newncpus > INT_MAX / 2)
7087 newncpus = cpu + 1;
7088 else
7089 newncpus = newncpus * 2;
7090 }
7091 newmask = CPU_ALLOC(newncpus);
7092 if (newmask == NULL) {
7093 PyErr_NoMemory();
7094 goto error;
7095 }
7096 newsetsize = CPU_ALLOC_SIZE(newncpus);
7097 CPU_ZERO_S(newsetsize, newmask);
7098 memcpy(newmask, cpu_set, setsize);
7099 CPU_FREE(cpu_set);
7100 setsize = newsetsize;
7101 cpu_set = newmask;
7102 ncpus = newncpus;
7103 }
7104 CPU_SET_S(cpu, setsize, cpu_set);
7105 }
7106 if (PyErr_Occurred()) {
7107 goto error;
7108 }
7109 Py_CLEAR(iterator);
7110
7111 if (sched_setaffinity(pid, setsize, cpu_set)) {
7112 posix_error();
7113 goto error;
7114 }
7115 CPU_FREE(cpu_set);
7116 Py_RETURN_NONE;
7117
7118 error:
7119 if (cpu_set)
7120 CPU_FREE(cpu_set);
7121 Py_XDECREF(iterator);
7122 return NULL;
7123 }
7124
7125
7126 /*[clinic input]
7127 os.sched_getaffinity
7128 pid: pid_t
7129 /
7130
7131 Return the affinity of the process identified by pid (or the current process if zero).
7132
7133 The affinity is returned as a set of CPU identifiers.
7134 [clinic start generated code]*/
7135
7136 static PyObject *
os_sched_getaffinity_impl(PyObject * module,pid_t pid)7137 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
7138 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
7139 {
7140 int cpu, ncpus, count;
7141 size_t setsize;
7142 cpu_set_t *mask = NULL;
7143 PyObject *res = NULL;
7144
7145 ncpus = NCPUS_START;
7146 while (1) {
7147 setsize = CPU_ALLOC_SIZE(ncpus);
7148 mask = CPU_ALLOC(ncpus);
7149 if (mask == NULL)
7150 return PyErr_NoMemory();
7151 if (sched_getaffinity(pid, setsize, mask) == 0)
7152 break;
7153 CPU_FREE(mask);
7154 if (errno != EINVAL)
7155 return posix_error();
7156 if (ncpus > INT_MAX / 2) {
7157 PyErr_SetString(PyExc_OverflowError, "could not allocate "
7158 "a large enough CPU set");
7159 return NULL;
7160 }
7161 ncpus = ncpus * 2;
7162 }
7163
7164 res = PySet_New(NULL);
7165 if (res == NULL)
7166 goto error;
7167 for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7168 if (CPU_ISSET_S(cpu, setsize, mask)) {
7169 PyObject *cpu_num = PyLong_FromLong(cpu);
7170 --count;
7171 if (cpu_num == NULL)
7172 goto error;
7173 if (PySet_Add(res, cpu_num)) {
7174 Py_DECREF(cpu_num);
7175 goto error;
7176 }
7177 Py_DECREF(cpu_num);
7178 }
7179 }
7180 CPU_FREE(mask);
7181 return res;
7182
7183 error:
7184 if (mask)
7185 CPU_FREE(mask);
7186 Py_XDECREF(res);
7187 return NULL;
7188 }
7189
7190 #endif /* HAVE_SCHED_SETAFFINITY */
7191
7192 #endif /* HAVE_SCHED_H */
7193
7194
7195 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
7196 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
7197 # define DEV_PTY_FILE "/dev/ptc"
7198 # define HAVE_DEV_PTMX
7199 #else
7200 # define DEV_PTY_FILE "/dev/ptmx"
7201 #endif
7202
7203 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
7204 #ifdef HAVE_PTY_H
7205 #include <pty.h>
7206 #else
7207 #ifdef HAVE_LIBUTIL_H
7208 #include <libutil.h>
7209 #else
7210 #ifdef HAVE_UTIL_H
7211 #include <util.h>
7212 #endif /* HAVE_UTIL_H */
7213 #endif /* HAVE_LIBUTIL_H */
7214 #endif /* HAVE_PTY_H */
7215 #ifdef HAVE_STROPTS_H
7216 #include <stropts.h>
7217 #endif
7218 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */
7219
7220
7221 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7222 /*[clinic input]
7223 os.openpty
7224
7225 Open a pseudo-terminal.
7226
7227 Return a tuple of (master_fd, slave_fd) containing open file descriptors
7228 for both the master and slave ends.
7229 [clinic start generated code]*/
7230
7231 static PyObject *
os_openpty_impl(PyObject * module)7232 os_openpty_impl(PyObject *module)
7233 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
7234 {
7235 int master_fd = -1, slave_fd = -1;
7236 #ifndef HAVE_OPENPTY
7237 char * slave_name;
7238 #endif
7239 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
7240 PyOS_sighandler_t sig_saved;
7241 #if defined(__sun) && defined(__SVR4)
7242 extern char *ptsname(int fildes);
7243 #endif
7244 #endif
7245
7246 #ifdef HAVE_OPENPTY
7247 if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
7248 goto posix_error;
7249
7250 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7251 goto error;
7252 if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
7253 goto error;
7254
7255 #elif defined(HAVE__GETPTY)
7256 slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
7257 if (slave_name == NULL)
7258 goto posix_error;
7259 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7260 goto error;
7261
7262 slave_fd = _Py_open(slave_name, O_RDWR);
7263 if (slave_fd < 0)
7264 goto error;
7265
7266 #else
7267 master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
7268 if (master_fd < 0)
7269 goto posix_error;
7270
7271 sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
7272
7273 /* change permission of slave */
7274 if (grantpt(master_fd) < 0) {
7275 PyOS_setsig(SIGCHLD, sig_saved);
7276 goto posix_error;
7277 }
7278
7279 /* unlock slave */
7280 if (unlockpt(master_fd) < 0) {
7281 PyOS_setsig(SIGCHLD, sig_saved);
7282 goto posix_error;
7283 }
7284
7285 PyOS_setsig(SIGCHLD, sig_saved);
7286
7287 slave_name = ptsname(master_fd); /* get name of slave */
7288 if (slave_name == NULL)
7289 goto posix_error;
7290
7291 slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
7292 if (slave_fd == -1)
7293 goto error;
7294
7295 if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7296 goto posix_error;
7297
7298 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
7299 ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
7300 ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
7301 #ifndef __hpux
7302 ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
7303 #endif /* __hpux */
7304 #endif /* HAVE_CYGWIN */
7305 #endif /* HAVE_OPENPTY */
7306
7307 return Py_BuildValue("(ii)", master_fd, slave_fd);
7308
7309 posix_error:
7310 posix_error();
7311 error:
7312 if (master_fd != -1)
7313 close(master_fd);
7314 if (slave_fd != -1)
7315 close(slave_fd);
7316 return NULL;
7317 }
7318 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
7319
7320
7321 #ifdef HAVE_FORKPTY
7322 /*[clinic input]
7323 os.forkpty
7324
7325 Fork a new process with a new pseudo-terminal as controlling tty.
7326
7327 Returns a tuple of (pid, master_fd).
7328 Like fork(), return pid of 0 to the child process,
7329 and pid of child to the parent process.
7330 To both, return fd of newly opened pseudo-terminal.
7331 [clinic start generated code]*/
7332
7333 static PyObject *
os_forkpty_impl(PyObject * module)7334 os_forkpty_impl(PyObject *module)
7335 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
7336 {
7337 int master_fd = -1;
7338 pid_t pid;
7339
7340 if (_PyInterpreterState_GET() != PyInterpreterState_Main()) {
7341 PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
7342 return NULL;
7343 }
7344 if (PySys_Audit("os.forkpty", NULL) < 0) {
7345 return NULL;
7346 }
7347 PyOS_BeforeFork();
7348 pid = forkpty(&master_fd, NULL, NULL, NULL);
7349 if (pid == 0) {
7350 /* child: this clobbers and resets the import lock. */
7351 PyOS_AfterFork_Child();
7352 } else {
7353 /* parent: release the import lock. */
7354 PyOS_AfterFork_Parent();
7355 }
7356 if (pid == -1)
7357 return posix_error();
7358 return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
7359 }
7360 #endif /* HAVE_FORKPTY */
7361
7362
7363 #ifdef HAVE_GETEGID
7364 /*[clinic input]
7365 os.getegid
7366
7367 Return the current process's effective group id.
7368 [clinic start generated code]*/
7369
7370 static PyObject *
os_getegid_impl(PyObject * module)7371 os_getegid_impl(PyObject *module)
7372 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
7373 {
7374 return _PyLong_FromGid(getegid());
7375 }
7376 #endif /* HAVE_GETEGID */
7377
7378
7379 #ifdef HAVE_GETEUID
7380 /*[clinic input]
7381 os.geteuid
7382
7383 Return the current process's effective user id.
7384 [clinic start generated code]*/
7385
7386 static PyObject *
os_geteuid_impl(PyObject * module)7387 os_geteuid_impl(PyObject *module)
7388 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
7389 {
7390 return _PyLong_FromUid(geteuid());
7391 }
7392 #endif /* HAVE_GETEUID */
7393
7394
7395 #ifdef HAVE_GETGID
7396 /*[clinic input]
7397 os.getgid
7398
7399 Return the current process's group id.
7400 [clinic start generated code]*/
7401
7402 static PyObject *
os_getgid_impl(PyObject * module)7403 os_getgid_impl(PyObject *module)
7404 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
7405 {
7406 return _PyLong_FromGid(getgid());
7407 }
7408 #endif /* HAVE_GETGID */
7409
7410
7411 #ifdef HAVE_GETPID
7412 /*[clinic input]
7413 os.getpid
7414
7415 Return the current process id.
7416 [clinic start generated code]*/
7417
7418 static PyObject *
os_getpid_impl(PyObject * module)7419 os_getpid_impl(PyObject *module)
7420 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
7421 {
7422 return PyLong_FromPid(getpid());
7423 }
7424 #endif /* HAVE_GETPID */
7425
7426 #ifdef NGROUPS_MAX
7427 #define MAX_GROUPS NGROUPS_MAX
7428 #else
7429 /* defined to be 16 on Solaris7, so this should be a small number */
7430 #define MAX_GROUPS 64
7431 #endif
7432
7433 #ifdef HAVE_GETGROUPLIST
7434
7435 #ifdef __APPLE__
7436 /*[clinic input]
7437 os.getgrouplist
7438
7439 user: str
7440 username to lookup
7441 group as basegid: int
7442 base group id of the user
7443 /
7444
7445 Returns a list of groups to which a user belongs.
7446 [clinic start generated code]*/
7447
7448 static PyObject *
os_getgrouplist_impl(PyObject * module,const char * user,int basegid)7449 os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
7450 /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
7451 #else
7452 /*[clinic input]
7453 os.getgrouplist
7454
7455 user: str
7456 username to lookup
7457 group as basegid: gid_t
7458 base group id of the user
7459 /
7460
7461 Returns a list of groups to which a user belongs.
7462 [clinic start generated code]*/
7463
7464 static PyObject *
7465 os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
7466 /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
7467 #endif
7468 {
7469 int i, ngroups;
7470 PyObject *list;
7471 #ifdef __APPLE__
7472 int *groups;
7473 #else
7474 gid_t *groups;
7475 #endif
7476
7477 /*
7478 * NGROUPS_MAX is defined by POSIX.1 as the maximum
7479 * number of supplimental groups a users can belong to.
7480 * We have to increment it by one because
7481 * getgrouplist() returns both the supplemental groups
7482 * and the primary group, i.e. all of the groups the
7483 * user belongs to.
7484 */
7485 ngroups = 1 + MAX_GROUPS;
7486
7487 while (1) {
7488 #ifdef __APPLE__
7489 groups = PyMem_New(int, ngroups);
7490 #else
7491 groups = PyMem_New(gid_t, ngroups);
7492 #endif
7493 if (groups == NULL) {
7494 return PyErr_NoMemory();
7495 }
7496
7497 int old_ngroups = ngroups;
7498 if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
7499 /* Success */
7500 break;
7501 }
7502
7503 /* getgrouplist() fails if the group list is too small */
7504 PyMem_Free(groups);
7505
7506 if (ngroups > old_ngroups) {
7507 /* If the group list is too small, the glibc implementation of
7508 getgrouplist() sets ngroups to the total number of groups and
7509 returns -1. */
7510 }
7511 else {
7512 /* Double the group list size */
7513 if (ngroups > INT_MAX / 2) {
7514 return PyErr_NoMemory();
7515 }
7516 ngroups *= 2;
7517 }
7518
7519 /* Retry getgrouplist() with a larger group list */
7520 }
7521
7522 #ifdef _Py_MEMORY_SANITIZER
7523 /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
7524 __msan_unpoison(&ngroups, sizeof(ngroups));
7525 __msan_unpoison(groups, ngroups*sizeof(*groups));
7526 #endif
7527
7528 list = PyList_New(ngroups);
7529 if (list == NULL) {
7530 PyMem_Free(groups);
7531 return NULL;
7532 }
7533
7534 for (i = 0; i < ngroups; i++) {
7535 #ifdef __APPLE__
7536 PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7537 #else
7538 PyObject *o = _PyLong_FromGid(groups[i]);
7539 #endif
7540 if (o == NULL) {
7541 Py_DECREF(list);
7542 PyMem_Free(groups);
7543 return NULL;
7544 }
7545 PyList_SET_ITEM(list, i, o);
7546 }
7547
7548 PyMem_Free(groups);
7549
7550 return list;
7551 }
7552 #endif /* HAVE_GETGROUPLIST */
7553
7554
7555 #ifdef HAVE_GETGROUPS
7556 /*[clinic input]
7557 os.getgroups
7558
7559 Return list of supplemental group IDs for the process.
7560 [clinic start generated code]*/
7561
7562 static PyObject *
os_getgroups_impl(PyObject * module)7563 os_getgroups_impl(PyObject *module)
7564 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
7565 {
7566 PyObject *result = NULL;
7567 gid_t grouplist[MAX_GROUPS];
7568
7569 /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
7570 * This is a helper variable to store the intermediate result when
7571 * that happens.
7572 *
7573 * To keep the code readable the OSX behaviour is unconditional,
7574 * according to the POSIX spec this should be safe on all unix-y
7575 * systems.
7576 */
7577 gid_t* alt_grouplist = grouplist;
7578 int n;
7579
7580 #ifdef __APPLE__
7581 /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if
7582 * there are more groups than can fit in grouplist. Therefore, on OS X
7583 * always first call getgroups with length 0 to get the actual number
7584 * of groups.
7585 */
7586 n = getgroups(0, NULL);
7587 if (n < 0) {
7588 return posix_error();
7589 } else if (n <= MAX_GROUPS) {
7590 /* groups will fit in existing array */
7591 alt_grouplist = grouplist;
7592 } else {
7593 alt_grouplist = PyMem_New(gid_t, n);
7594 if (alt_grouplist == NULL) {
7595 return PyErr_NoMemory();
7596 }
7597 }
7598
7599 n = getgroups(n, alt_grouplist);
7600 if (n == -1) {
7601 if (alt_grouplist != grouplist) {
7602 PyMem_Free(alt_grouplist);
7603 }
7604 return posix_error();
7605 }
7606 #else
7607 n = getgroups(MAX_GROUPS, grouplist);
7608 if (n < 0) {
7609 if (errno == EINVAL) {
7610 n = getgroups(0, NULL);
7611 if (n == -1) {
7612 return posix_error();
7613 }
7614 if (n == 0) {
7615 /* Avoid malloc(0) */
7616 alt_grouplist = grouplist;
7617 } else {
7618 alt_grouplist = PyMem_New(gid_t, n);
7619 if (alt_grouplist == NULL) {
7620 return PyErr_NoMemory();
7621 }
7622 n = getgroups(n, alt_grouplist);
7623 if (n == -1) {
7624 PyMem_Free(alt_grouplist);
7625 return posix_error();
7626 }
7627 }
7628 } else {
7629 return posix_error();
7630 }
7631 }
7632 #endif
7633
7634 result = PyList_New(n);
7635 if (result != NULL) {
7636 int i;
7637 for (i = 0; i < n; ++i) {
7638 PyObject *o = _PyLong_FromGid(alt_grouplist[i]);
7639 if (o == NULL) {
7640 Py_DECREF(result);
7641 result = NULL;
7642 break;
7643 }
7644 PyList_SET_ITEM(result, i, o);
7645 }
7646 }
7647
7648 if (alt_grouplist != grouplist) {
7649 PyMem_Free(alt_grouplist);
7650 }
7651
7652 return result;
7653 }
7654 #endif /* HAVE_GETGROUPS */
7655
7656 #ifdef HAVE_INITGROUPS
7657 #ifdef __APPLE__
7658 /*[clinic input]
7659 os.initgroups
7660
7661 username as oname: FSConverter
7662 gid: int
7663 /
7664
7665 Initialize the group access list.
7666
7667 Call the system initgroups() to initialize the group access list with all of
7668 the groups of which the specified username is a member, plus the specified
7669 group id.
7670 [clinic start generated code]*/
7671
7672 static PyObject *
os_initgroups_impl(PyObject * module,PyObject * oname,int gid)7673 os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
7674 /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
7675 #else
7676 /*[clinic input]
7677 os.initgroups
7678
7679 username as oname: FSConverter
7680 gid: gid_t
7681 /
7682
7683 Initialize the group access list.
7684
7685 Call the system initgroups() to initialize the group access list with all of
7686 the groups of which the specified username is a member, plus the specified
7687 group id.
7688 [clinic start generated code]*/
7689
7690 static PyObject *
7691 os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
7692 /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
7693 #endif
7694 {
7695 const char *username = PyBytes_AS_STRING(oname);
7696
7697 if (initgroups(username, gid) == -1)
7698 return PyErr_SetFromErrno(PyExc_OSError);
7699
7700 Py_RETURN_NONE;
7701 }
7702 #endif /* HAVE_INITGROUPS */
7703
7704
7705 #ifdef HAVE_GETPGID
7706 /*[clinic input]
7707 os.getpgid
7708
7709 pid: pid_t
7710
7711 Call the system call getpgid(), and return the result.
7712 [clinic start generated code]*/
7713
7714 static PyObject *
os_getpgid_impl(PyObject * module,pid_t pid)7715 os_getpgid_impl(PyObject *module, pid_t pid)
7716 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7717 {
7718 pid_t pgid = getpgid(pid);
7719 if (pgid < 0)
7720 return posix_error();
7721 return PyLong_FromPid(pgid);
7722 }
7723 #endif /* HAVE_GETPGID */
7724
7725
7726 #ifdef HAVE_GETPGRP
7727 /*[clinic input]
7728 os.getpgrp
7729
7730 Return the current process group id.
7731 [clinic start generated code]*/
7732
7733 static PyObject *
os_getpgrp_impl(PyObject * module)7734 os_getpgrp_impl(PyObject *module)
7735 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7736 {
7737 #ifdef GETPGRP_HAVE_ARG
7738 return PyLong_FromPid(getpgrp(0));
7739 #else /* GETPGRP_HAVE_ARG */
7740 return PyLong_FromPid(getpgrp());
7741 #endif /* GETPGRP_HAVE_ARG */
7742 }
7743 #endif /* HAVE_GETPGRP */
7744
7745
7746 #ifdef HAVE_SETPGRP
7747 /*[clinic input]
7748 os.setpgrp
7749
7750 Make the current process the leader of its process group.
7751 [clinic start generated code]*/
7752
7753 static PyObject *
os_setpgrp_impl(PyObject * module)7754 os_setpgrp_impl(PyObject *module)
7755 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7756 {
7757 #ifdef SETPGRP_HAVE_ARG
7758 if (setpgrp(0, 0) < 0)
7759 #else /* SETPGRP_HAVE_ARG */
7760 if (setpgrp() < 0)
7761 #endif /* SETPGRP_HAVE_ARG */
7762 return posix_error();
7763 Py_RETURN_NONE;
7764 }
7765 #endif /* HAVE_SETPGRP */
7766
7767 #ifdef HAVE_GETPPID
7768
7769 #ifdef MS_WINDOWS
7770 #include <tlhelp32.h>
7771
7772 static PyObject*
win32_getppid()7773 win32_getppid()
7774 {
7775 HANDLE snapshot;
7776 pid_t mypid;
7777 PyObject* result = NULL;
7778 BOOL have_record;
7779 PROCESSENTRY32 pe;
7780
7781 mypid = getpid(); /* This function never fails */
7782
7783 snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7784 if (snapshot == INVALID_HANDLE_VALUE)
7785 return PyErr_SetFromWindowsErr(GetLastError());
7786
7787 pe.dwSize = sizeof(pe);
7788 have_record = Process32First(snapshot, &pe);
7789 while (have_record) {
7790 if (mypid == (pid_t)pe.th32ProcessID) {
7791 /* We could cache the ulong value in a static variable. */
7792 result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7793 break;
7794 }
7795
7796 have_record = Process32Next(snapshot, &pe);
7797 }
7798
7799 /* If our loop exits and our pid was not found (result will be NULL)
7800 * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7801 * error anyway, so let's raise it. */
7802 if (!result)
7803 result = PyErr_SetFromWindowsErr(GetLastError());
7804
7805 CloseHandle(snapshot);
7806
7807 return result;
7808 }
7809 #endif /*MS_WINDOWS*/
7810
7811
7812 /*[clinic input]
7813 os.getppid
7814
7815 Return the parent's process id.
7816
7817 If the parent process has already exited, Windows machines will still
7818 return its id; others systems will return the id of the 'init' process (1).
7819 [clinic start generated code]*/
7820
7821 static PyObject *
os_getppid_impl(PyObject * module)7822 os_getppid_impl(PyObject *module)
7823 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7824 {
7825 #ifdef MS_WINDOWS
7826 return win32_getppid();
7827 #else
7828 return PyLong_FromPid(getppid());
7829 #endif
7830 }
7831 #endif /* HAVE_GETPPID */
7832
7833
7834 #ifdef HAVE_GETLOGIN
7835 /*[clinic input]
7836 os.getlogin
7837
7838 Return the actual login name.
7839 [clinic start generated code]*/
7840
7841 static PyObject *
os_getlogin_impl(PyObject * module)7842 os_getlogin_impl(PyObject *module)
7843 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7844 {
7845 PyObject *result = NULL;
7846 #ifdef MS_WINDOWS
7847 wchar_t user_name[UNLEN + 1];
7848 DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7849
7850 if (GetUserNameW(user_name, &num_chars)) {
7851 /* num_chars is the number of unicode chars plus null terminator */
7852 result = PyUnicode_FromWideChar(user_name, num_chars - 1);
7853 }
7854 else
7855 result = PyErr_SetFromWindowsErr(GetLastError());
7856 #else
7857 char *name;
7858 int old_errno = errno;
7859
7860 errno = 0;
7861 name = getlogin();
7862 if (name == NULL) {
7863 if (errno)
7864 posix_error();
7865 else
7866 PyErr_SetString(PyExc_OSError, "unable to determine login name");
7867 }
7868 else
7869 result = PyUnicode_DecodeFSDefault(name);
7870 errno = old_errno;
7871 #endif
7872 return result;
7873 }
7874 #endif /* HAVE_GETLOGIN */
7875
7876
7877 #ifdef HAVE_GETUID
7878 /*[clinic input]
7879 os.getuid
7880
7881 Return the current process's user id.
7882 [clinic start generated code]*/
7883
7884 static PyObject *
os_getuid_impl(PyObject * module)7885 os_getuid_impl(PyObject *module)
7886 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7887 {
7888 return _PyLong_FromUid(getuid());
7889 }
7890 #endif /* HAVE_GETUID */
7891
7892
7893 #ifdef MS_WINDOWS
7894 #define HAVE_KILL
7895 #endif /* MS_WINDOWS */
7896
7897 #ifdef HAVE_KILL
7898 /*[clinic input]
7899 os.kill
7900
7901 pid: pid_t
7902 signal: Py_ssize_t
7903 /
7904
7905 Kill a process with a signal.
7906 [clinic start generated code]*/
7907
7908 static PyObject *
os_kill_impl(PyObject * module,pid_t pid,Py_ssize_t signal)7909 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
7910 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
7911 {
7912 if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
7913 return NULL;
7914 }
7915 #ifndef MS_WINDOWS
7916 if (kill(pid, (int)signal) == -1)
7917 return posix_error();
7918 Py_RETURN_NONE;
7919 #else /* !MS_WINDOWS */
7920 PyObject *result;
7921 DWORD sig = (DWORD)signal;
7922 DWORD err;
7923 HANDLE handle;
7924
7925 /* Console processes which share a common console can be sent CTRL+C or
7926 CTRL+BREAK events, provided they handle said events. */
7927 if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
7928 if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
7929 err = GetLastError();
7930 PyErr_SetFromWindowsErr(err);
7931 }
7932 else
7933 Py_RETURN_NONE;
7934 }
7935
7936 /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
7937 attempt to open and terminate the process. */
7938 handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
7939 if (handle == NULL) {
7940 err = GetLastError();
7941 return PyErr_SetFromWindowsErr(err);
7942 }
7943
7944 if (TerminateProcess(handle, sig) == 0) {
7945 err = GetLastError();
7946 result = PyErr_SetFromWindowsErr(err);
7947 } else {
7948 Py_INCREF(Py_None);
7949 result = Py_None;
7950 }
7951
7952 CloseHandle(handle);
7953 return result;
7954 #endif /* !MS_WINDOWS */
7955 }
7956 #endif /* HAVE_KILL */
7957
7958
7959 #ifdef HAVE_KILLPG
7960 /*[clinic input]
7961 os.killpg
7962
7963 pgid: pid_t
7964 signal: int
7965 /
7966
7967 Kill a process group with a signal.
7968 [clinic start generated code]*/
7969
7970 static PyObject *
os_killpg_impl(PyObject * module,pid_t pgid,int signal)7971 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
7972 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
7973 {
7974 if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
7975 return NULL;
7976 }
7977 /* XXX some man pages make the `pgid` parameter an int, others
7978 a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
7979 take the same type. Moreover, pid_t is always at least as wide as
7980 int (else compilation of this module fails), which is safe. */
7981 if (killpg(pgid, signal) == -1)
7982 return posix_error();
7983 Py_RETURN_NONE;
7984 }
7985 #endif /* HAVE_KILLPG */
7986
7987
7988 #ifdef HAVE_PLOCK
7989 #ifdef HAVE_SYS_LOCK_H
7990 #include <sys/lock.h>
7991 #endif
7992
7993 /*[clinic input]
7994 os.plock
7995 op: int
7996 /
7997
7998 Lock program segments into memory.");
7999 [clinic start generated code]*/
8000
8001 static PyObject *
os_plock_impl(PyObject * module,int op)8002 os_plock_impl(PyObject *module, int op)
8003 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
8004 {
8005 if (plock(op) == -1)
8006 return posix_error();
8007 Py_RETURN_NONE;
8008 }
8009 #endif /* HAVE_PLOCK */
8010
8011
8012 #ifdef HAVE_SETUID
8013 /*[clinic input]
8014 os.setuid
8015
8016 uid: uid_t
8017 /
8018
8019 Set the current process's user id.
8020 [clinic start generated code]*/
8021
8022 static PyObject *
os_setuid_impl(PyObject * module,uid_t uid)8023 os_setuid_impl(PyObject *module, uid_t uid)
8024 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
8025 {
8026 if (setuid(uid) < 0)
8027 return posix_error();
8028 Py_RETURN_NONE;
8029 }
8030 #endif /* HAVE_SETUID */
8031
8032
8033 #ifdef HAVE_SETEUID
8034 /*[clinic input]
8035 os.seteuid
8036
8037 euid: uid_t
8038 /
8039
8040 Set the current process's effective user id.
8041 [clinic start generated code]*/
8042
8043 static PyObject *
os_seteuid_impl(PyObject * module,uid_t euid)8044 os_seteuid_impl(PyObject *module, uid_t euid)
8045 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
8046 {
8047 if (seteuid(euid) < 0)
8048 return posix_error();
8049 Py_RETURN_NONE;
8050 }
8051 #endif /* HAVE_SETEUID */
8052
8053
8054 #ifdef HAVE_SETEGID
8055 /*[clinic input]
8056 os.setegid
8057
8058 egid: gid_t
8059 /
8060
8061 Set the current process's effective group id.
8062 [clinic start generated code]*/
8063
8064 static PyObject *
os_setegid_impl(PyObject * module,gid_t egid)8065 os_setegid_impl(PyObject *module, gid_t egid)
8066 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
8067 {
8068 if (setegid(egid) < 0)
8069 return posix_error();
8070 Py_RETURN_NONE;
8071 }
8072 #endif /* HAVE_SETEGID */
8073
8074
8075 #ifdef HAVE_SETREUID
8076 /*[clinic input]
8077 os.setreuid
8078
8079 ruid: uid_t
8080 euid: uid_t
8081 /
8082
8083 Set the current process's real and effective user ids.
8084 [clinic start generated code]*/
8085
8086 static PyObject *
os_setreuid_impl(PyObject * module,uid_t ruid,uid_t euid)8087 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
8088 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
8089 {
8090 if (setreuid(ruid, euid) < 0) {
8091 return posix_error();
8092 } else {
8093 Py_RETURN_NONE;
8094 }
8095 }
8096 #endif /* HAVE_SETREUID */
8097
8098
8099 #ifdef HAVE_SETREGID
8100 /*[clinic input]
8101 os.setregid
8102
8103 rgid: gid_t
8104 egid: gid_t
8105 /
8106
8107 Set the current process's real and effective group ids.
8108 [clinic start generated code]*/
8109
8110 static PyObject *
os_setregid_impl(PyObject * module,gid_t rgid,gid_t egid)8111 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
8112 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
8113 {
8114 if (setregid(rgid, egid) < 0)
8115 return posix_error();
8116 Py_RETURN_NONE;
8117 }
8118 #endif /* HAVE_SETREGID */
8119
8120
8121 #ifdef HAVE_SETGID
8122 /*[clinic input]
8123 os.setgid
8124 gid: gid_t
8125 /
8126
8127 Set the current process's group id.
8128 [clinic start generated code]*/
8129
8130 static PyObject *
os_setgid_impl(PyObject * module,gid_t gid)8131 os_setgid_impl(PyObject *module, gid_t gid)
8132 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
8133 {
8134 if (setgid(gid) < 0)
8135 return posix_error();
8136 Py_RETURN_NONE;
8137 }
8138 #endif /* HAVE_SETGID */
8139
8140
8141 #ifdef HAVE_SETGROUPS
8142 /*[clinic input]
8143 os.setgroups
8144
8145 groups: object
8146 /
8147
8148 Set the groups of the current process to list.
8149 [clinic start generated code]*/
8150
8151 static PyObject *
os_setgroups(PyObject * module,PyObject * groups)8152 os_setgroups(PyObject *module, PyObject *groups)
8153 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
8154 {
8155 Py_ssize_t i, len;
8156 gid_t grouplist[MAX_GROUPS];
8157
8158 if (!PySequence_Check(groups)) {
8159 PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
8160 return NULL;
8161 }
8162 len = PySequence_Size(groups);
8163 if (len < 0) {
8164 return NULL;
8165 }
8166 if (len > MAX_GROUPS) {
8167 PyErr_SetString(PyExc_ValueError, "too many groups");
8168 return NULL;
8169 }
8170 for(i = 0; i < len; i++) {
8171 PyObject *elem;
8172 elem = PySequence_GetItem(groups, i);
8173 if (!elem)
8174 return NULL;
8175 if (!PyLong_Check(elem)) {
8176 PyErr_SetString(PyExc_TypeError,
8177 "groups must be integers");
8178 Py_DECREF(elem);
8179 return NULL;
8180 } else {
8181 if (!_Py_Gid_Converter(elem, &grouplist[i])) {
8182 Py_DECREF(elem);
8183 return NULL;
8184 }
8185 }
8186 Py_DECREF(elem);
8187 }
8188
8189 if (setgroups(len, grouplist) < 0)
8190 return posix_error();
8191 Py_RETURN_NONE;
8192 }
8193 #endif /* HAVE_SETGROUPS */
8194
8195 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
8196 static PyObject *
wait_helper(PyObject * module,pid_t pid,int status,struct rusage * ru)8197 wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
8198 {
8199 PyObject *result;
8200 PyObject *struct_rusage;
8201
8202 if (pid == -1)
8203 return posix_error();
8204
8205 // If wait succeeded but no child was ready to report status, ru will not
8206 // have been populated.
8207 if (pid == 0) {
8208 memset(ru, 0, sizeof(*ru));
8209 }
8210
8211 PyObject *m = PyImport_ImportModuleNoBlock("resource");
8212 if (m == NULL)
8213 return NULL;
8214 struct_rusage = PyObject_GetAttr(m, get_posix_state(module)->struct_rusage);
8215 Py_DECREF(m);
8216 if (struct_rusage == NULL)
8217 return NULL;
8218
8219 /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
8220 result = PyStructSequence_New((PyTypeObject*) struct_rusage);
8221 Py_DECREF(struct_rusage);
8222 if (!result)
8223 return NULL;
8224
8225 #ifndef doubletime
8226 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
8227 #endif
8228
8229 PyStructSequence_SET_ITEM(result, 0,
8230 PyFloat_FromDouble(doubletime(ru->ru_utime)));
8231 PyStructSequence_SET_ITEM(result, 1,
8232 PyFloat_FromDouble(doubletime(ru->ru_stime)));
8233 #define SET_INT(result, index, value)\
8234 PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
8235 SET_INT(result, 2, ru->ru_maxrss);
8236 SET_INT(result, 3, ru->ru_ixrss);
8237 SET_INT(result, 4, ru->ru_idrss);
8238 SET_INT(result, 5, ru->ru_isrss);
8239 SET_INT(result, 6, ru->ru_minflt);
8240 SET_INT(result, 7, ru->ru_majflt);
8241 SET_INT(result, 8, ru->ru_nswap);
8242 SET_INT(result, 9, ru->ru_inblock);
8243 SET_INT(result, 10, ru->ru_oublock);
8244 SET_INT(result, 11, ru->ru_msgsnd);
8245 SET_INT(result, 12, ru->ru_msgrcv);
8246 SET_INT(result, 13, ru->ru_nsignals);
8247 SET_INT(result, 14, ru->ru_nvcsw);
8248 SET_INT(result, 15, ru->ru_nivcsw);
8249 #undef SET_INT
8250
8251 if (PyErr_Occurred()) {
8252 Py_DECREF(result);
8253 return NULL;
8254 }
8255
8256 return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
8257 }
8258 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
8259
8260
8261 #ifdef HAVE_WAIT3
8262 /*[clinic input]
8263 os.wait3
8264
8265 options: int
8266 Wait for completion of a child process.
8267
8268 Returns a tuple of information about the child process:
8269 (pid, status, rusage)
8270 [clinic start generated code]*/
8271
8272 static PyObject *
os_wait3_impl(PyObject * module,int options)8273 os_wait3_impl(PyObject *module, int options)
8274 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
8275 {
8276 pid_t pid;
8277 struct rusage ru;
8278 int async_err = 0;
8279 WAIT_TYPE status;
8280 WAIT_STATUS_INT(status) = 0;
8281
8282 do {
8283 Py_BEGIN_ALLOW_THREADS
8284 pid = wait3(&status, options, &ru);
8285 Py_END_ALLOW_THREADS
8286 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8287 if (pid < 0)
8288 return (!async_err) ? posix_error() : NULL;
8289
8290 return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
8291 }
8292 #endif /* HAVE_WAIT3 */
8293
8294
8295 #ifdef HAVE_WAIT4
8296 /*[clinic input]
8297
8298 os.wait4
8299
8300 pid: pid_t
8301 options: int
8302
8303 Wait for completion of a specific child process.
8304
8305 Returns a tuple of information about the child process:
8306 (pid, status, rusage)
8307 [clinic start generated code]*/
8308
8309 static PyObject *
os_wait4_impl(PyObject * module,pid_t pid,int options)8310 os_wait4_impl(PyObject *module, pid_t pid, int options)
8311 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
8312 {
8313 pid_t res;
8314 struct rusage ru;
8315 int async_err = 0;
8316 WAIT_TYPE status;
8317 WAIT_STATUS_INT(status) = 0;
8318
8319 do {
8320 Py_BEGIN_ALLOW_THREADS
8321 res = wait4(pid, &status, options, &ru);
8322 Py_END_ALLOW_THREADS
8323 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8324 if (res < 0)
8325 return (!async_err) ? posix_error() : NULL;
8326
8327 return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
8328 }
8329 #endif /* HAVE_WAIT4 */
8330
8331
8332 #if defined(HAVE_WAITID) && !defined(__APPLE__)
8333 /*[clinic input]
8334 os.waitid
8335
8336 idtype: idtype_t
8337 Must be one of be P_PID, P_PGID or P_ALL.
8338 id: id_t
8339 The id to wait on.
8340 options: int
8341 Constructed from the ORing of one or more of WEXITED, WSTOPPED
8342 or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
8343 /
8344
8345 Returns the result of waiting for a process or processes.
8346
8347 Returns either waitid_result or None if WNOHANG is specified and there are
8348 no children in a waitable state.
8349 [clinic start generated code]*/
8350
8351 static PyObject *
os_waitid_impl(PyObject * module,idtype_t idtype,id_t id,int options)8352 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
8353 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
8354 {
8355 PyObject *result;
8356 int res;
8357 int async_err = 0;
8358 siginfo_t si;
8359 si.si_pid = 0;
8360
8361 do {
8362 Py_BEGIN_ALLOW_THREADS
8363 res = waitid(idtype, id, &si, options);
8364 Py_END_ALLOW_THREADS
8365 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8366 if (res < 0)
8367 return (!async_err) ? posix_error() : NULL;
8368
8369 if (si.si_pid == 0)
8370 Py_RETURN_NONE;
8371
8372 PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
8373 result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
8374 if (!result)
8375 return NULL;
8376
8377 PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
8378 PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
8379 PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
8380 PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
8381 PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
8382 if (PyErr_Occurred()) {
8383 Py_DECREF(result);
8384 return NULL;
8385 }
8386
8387 return result;
8388 }
8389 #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
8390
8391
8392 #if defined(HAVE_WAITPID)
8393 /*[clinic input]
8394 os.waitpid
8395 pid: pid_t
8396 options: int
8397 /
8398
8399 Wait for completion of a given child process.
8400
8401 Returns a tuple of information regarding the child process:
8402 (pid, status)
8403
8404 The options argument is ignored on Windows.
8405 [clinic start generated code]*/
8406
8407 static PyObject *
os_waitpid_impl(PyObject * module,pid_t pid,int options)8408 os_waitpid_impl(PyObject *module, pid_t pid, int options)
8409 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
8410 {
8411 pid_t res;
8412 int async_err = 0;
8413 WAIT_TYPE status;
8414 WAIT_STATUS_INT(status) = 0;
8415
8416 do {
8417 Py_BEGIN_ALLOW_THREADS
8418 res = waitpid(pid, &status, options);
8419 Py_END_ALLOW_THREADS
8420 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8421 if (res < 0)
8422 return (!async_err) ? posix_error() : NULL;
8423
8424 return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
8425 }
8426 #elif defined(HAVE_CWAIT)
8427 /* MS C has a variant of waitpid() that's usable for most purposes. */
8428 /*[clinic input]
8429 os.waitpid
8430 pid: intptr_t
8431 options: int
8432 /
8433
8434 Wait for completion of a given process.
8435
8436 Returns a tuple of information regarding the process:
8437 (pid, status << 8)
8438
8439 The options argument is ignored on Windows.
8440 [clinic start generated code]*/
8441
8442 static PyObject *
os_waitpid_impl(PyObject * module,intptr_t pid,int options)8443 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
8444 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
8445 {
8446 int status;
8447 intptr_t res;
8448 int async_err = 0;
8449
8450 do {
8451 Py_BEGIN_ALLOW_THREADS
8452 _Py_BEGIN_SUPPRESS_IPH
8453 res = _cwait(&status, pid, options);
8454 _Py_END_SUPPRESS_IPH
8455 Py_END_ALLOW_THREADS
8456 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8457 if (res < 0)
8458 return (!async_err) ? posix_error() : NULL;
8459
8460 unsigned long long ustatus = (unsigned int)status;
8461
8462 /* shift the status left a byte so this is more like the POSIX waitpid */
8463 return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
8464 }
8465 #endif
8466
8467
8468 #ifdef HAVE_WAIT
8469 /*[clinic input]
8470 os.wait
8471
8472 Wait for completion of a child process.
8473
8474 Returns a tuple of information about the child process:
8475 (pid, status)
8476 [clinic start generated code]*/
8477
8478 static PyObject *
os_wait_impl(PyObject * module)8479 os_wait_impl(PyObject *module)
8480 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
8481 {
8482 pid_t pid;
8483 int async_err = 0;
8484 WAIT_TYPE status;
8485 WAIT_STATUS_INT(status) = 0;
8486
8487 do {
8488 Py_BEGIN_ALLOW_THREADS
8489 pid = wait(&status);
8490 Py_END_ALLOW_THREADS
8491 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8492 if (pid < 0)
8493 return (!async_err) ? posix_error() : NULL;
8494
8495 return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
8496 }
8497 #endif /* HAVE_WAIT */
8498
8499 #if defined(__linux__) && defined(__NR_pidfd_open)
8500 /*[clinic input]
8501 os.pidfd_open
8502 pid: pid_t
8503 flags: unsigned_int = 0
8504
8505 Return a file descriptor referring to the process *pid*.
8506
8507 The descriptor can be used to perform process management without races and
8508 signals.
8509 [clinic start generated code]*/
8510
8511 static PyObject *
os_pidfd_open_impl(PyObject * module,pid_t pid,unsigned int flags)8512 os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
8513 /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
8514 {
8515 int fd = syscall(__NR_pidfd_open, pid, flags);
8516 if (fd < 0) {
8517 return posix_error();
8518 }
8519 return PyLong_FromLong(fd);
8520 }
8521 #endif
8522
8523
8524 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
8525 /*[clinic input]
8526 os.readlink
8527
8528 path: path_t
8529 *
8530 dir_fd: dir_fd(requires='readlinkat') = None
8531
8532 Return a string representing the path to which the symbolic link points.
8533
8534 If dir_fd is not None, it should be a file descriptor open to a directory,
8535 and path should be relative; path will then be relative to that directory.
8536
8537 dir_fd may not be implemented on your platform. If it is unavailable,
8538 using it will raise a NotImplementedError.
8539 [clinic start generated code]*/
8540
8541 static PyObject *
os_readlink_impl(PyObject * module,path_t * path,int dir_fd)8542 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
8543 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
8544 {
8545 #if defined(HAVE_READLINK)
8546 char buffer[MAXPATHLEN+1];
8547 ssize_t length;
8548 #ifdef HAVE_READLINKAT
8549 int readlinkat_unavailable = 0;
8550 #endif
8551
8552 Py_BEGIN_ALLOW_THREADS
8553 #ifdef HAVE_READLINKAT
8554 if (dir_fd != DEFAULT_DIR_FD) {
8555 if (HAVE_READLINKAT_RUNTIME) {
8556 length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
8557 } else {
8558 readlinkat_unavailable = 1;
8559 }
8560 } else
8561 #endif
8562 length = readlink(path->narrow, buffer, MAXPATHLEN);
8563 Py_END_ALLOW_THREADS
8564
8565 #ifdef HAVE_READLINKAT
8566 if (readlinkat_unavailable) {
8567 argument_unavailable_error(NULL, "dir_fd");
8568 return NULL;
8569 }
8570 #endif
8571
8572 if (length < 0) {
8573 return path_error(path);
8574 }
8575 buffer[length] = '\0';
8576
8577 if (PyUnicode_Check(path->object))
8578 return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
8579 else
8580 return PyBytes_FromStringAndSize(buffer, length);
8581 #elif defined(MS_WINDOWS)
8582 DWORD n_bytes_returned;
8583 DWORD io_result = 0;
8584 HANDLE reparse_point_handle;
8585 char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
8586 _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
8587 PyObject *result = NULL;
8588
8589 /* First get a handle to the reparse point */
8590 Py_BEGIN_ALLOW_THREADS
8591 reparse_point_handle = CreateFileW(
8592 path->wide,
8593 0,
8594 0,
8595 0,
8596 OPEN_EXISTING,
8597 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
8598 0);
8599 if (reparse_point_handle != INVALID_HANDLE_VALUE) {
8600 /* New call DeviceIoControl to read the reparse point */
8601 io_result = DeviceIoControl(
8602 reparse_point_handle,
8603 FSCTL_GET_REPARSE_POINT,
8604 0, 0, /* in buffer */
8605 target_buffer, sizeof(target_buffer),
8606 &n_bytes_returned,
8607 0 /* we're not using OVERLAPPED_IO */
8608 );
8609 CloseHandle(reparse_point_handle);
8610 }
8611 Py_END_ALLOW_THREADS
8612
8613 if (io_result == 0) {
8614 return path_error(path);
8615 }
8616
8617 wchar_t *name = NULL;
8618 Py_ssize_t nameLen = 0;
8619 if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
8620 {
8621 name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
8622 rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
8623 nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8624 }
8625 else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
8626 {
8627 name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8628 rdb->MountPointReparseBuffer.SubstituteNameOffset);
8629 nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8630 }
8631 else
8632 {
8633 PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8634 }
8635 if (name) {
8636 if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8637 /* Our buffer is mutable, so this is okay */
8638 name[1] = L'\\';
8639 }
8640 result = PyUnicode_FromWideChar(name, nameLen);
8641 if (result && path->narrow) {
8642 Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8643 }
8644 }
8645 return result;
8646 #endif
8647 }
8648 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8649
8650 #if defined(MS_WINDOWS)
8651
8652 /* Remove the last portion of the path - return 0 on success */
8653 static int
_dirnameW(WCHAR * path)8654 _dirnameW(WCHAR *path)
8655 {
8656 WCHAR *ptr;
8657 size_t length = wcsnlen_s(path, MAX_PATH);
8658 if (length == MAX_PATH) {
8659 return -1;
8660 }
8661
8662 /* walk the path from the end until a backslash is encountered */
8663 for(ptr = path + length; ptr != path; ptr--) {
8664 if (*ptr == L'\\' || *ptr == L'/') {
8665 break;
8666 }
8667 }
8668 *ptr = 0;
8669 return 0;
8670 }
8671
8672 #endif
8673
8674 #ifdef HAVE_SYMLINK
8675
8676 #if defined(MS_WINDOWS)
8677
8678 /* Is this path absolute? */
8679 static int
_is_absW(const WCHAR * path)8680 _is_absW(const WCHAR *path)
8681 {
8682 return path[0] == L'\\' || path[0] == L'/' ||
8683 (path[0] && path[1] == L':');
8684 }
8685
8686 /* join root and rest with a backslash - return 0 on success */
8687 static int
_joinW(WCHAR * dest_path,const WCHAR * root,const WCHAR * rest)8688 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8689 {
8690 if (_is_absW(rest)) {
8691 return wcscpy_s(dest_path, MAX_PATH, rest);
8692 }
8693
8694 if (wcscpy_s(dest_path, MAX_PATH, root)) {
8695 return -1;
8696 }
8697
8698 if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8699 return -1;
8700 }
8701
8702 return wcscat_s(dest_path, MAX_PATH, rest);
8703 }
8704
8705 /* Return True if the path at src relative to dest is a directory */
8706 static int
_check_dirW(LPCWSTR src,LPCWSTR dest)8707 _check_dirW(LPCWSTR src, LPCWSTR dest)
8708 {
8709 WIN32_FILE_ATTRIBUTE_DATA src_info;
8710 WCHAR dest_parent[MAX_PATH];
8711 WCHAR src_resolved[MAX_PATH] = L"";
8712
8713 /* dest_parent = os.path.dirname(dest) */
8714 if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8715 _dirnameW(dest_parent)) {
8716 return 0;
8717 }
8718 /* src_resolved = os.path.join(dest_parent, src) */
8719 if (_joinW(src_resolved, dest_parent, src)) {
8720 return 0;
8721 }
8722 return (
8723 GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8724 && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8725 );
8726 }
8727 #endif
8728
8729
8730 /*[clinic input]
8731 os.symlink
8732 src: path_t
8733 dst: path_t
8734 target_is_directory: bool = False
8735 *
8736 dir_fd: dir_fd(requires='symlinkat')=None
8737
8738 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8739
8740 Create a symbolic link pointing to src named dst.
8741
8742 target_is_directory is required on Windows if the target is to be
8743 interpreted as a directory. (On Windows, symlink requires
8744 Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8745 target_is_directory is ignored on non-Windows platforms.
8746
8747 If dir_fd is not None, it should be a file descriptor open to a directory,
8748 and path should be relative; path will then be relative to that directory.
8749 dir_fd may not be implemented on your platform.
8750 If it is unavailable, using it will raise a NotImplementedError.
8751
8752 [clinic start generated code]*/
8753
8754 static PyObject *
os_symlink_impl(PyObject * module,path_t * src,path_t * dst,int target_is_directory,int dir_fd)8755 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8756 int target_is_directory, int dir_fd)
8757 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8758 {
8759 #ifdef MS_WINDOWS
8760 DWORD result;
8761 DWORD flags = 0;
8762
8763 /* Assumed true, set to false if detected to not be available. */
8764 static int windows_has_symlink_unprivileged_flag = TRUE;
8765 #else
8766 int result;
8767 #ifdef HAVE_SYMLINKAT
8768 int symlinkat_unavailable = 0;
8769 #endif
8770 #endif
8771
8772 if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8773 dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8774 return NULL;
8775 }
8776
8777 #ifdef MS_WINDOWS
8778
8779 if (windows_has_symlink_unprivileged_flag) {
8780 /* Allow non-admin symlinks if system allows it. */
8781 flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8782 }
8783
8784 Py_BEGIN_ALLOW_THREADS
8785 _Py_BEGIN_SUPPRESS_IPH
8786 /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8787 if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8788 flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8789 }
8790
8791 result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8792 _Py_END_SUPPRESS_IPH
8793 Py_END_ALLOW_THREADS
8794
8795 if (windows_has_symlink_unprivileged_flag && !result &&
8796 ERROR_INVALID_PARAMETER == GetLastError()) {
8797
8798 Py_BEGIN_ALLOW_THREADS
8799 _Py_BEGIN_SUPPRESS_IPH
8800 /* This error might be caused by
8801 SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8802 Try again, and update windows_has_symlink_unprivileged_flag if we
8803 are successful this time.
8804
8805 NOTE: There is a risk of a race condition here if there are other
8806 conditions than the flag causing ERROR_INVALID_PARAMETER, and
8807 another process (or thread) changes that condition in between our
8808 calls to CreateSymbolicLink.
8809 */
8810 flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8811 result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8812 _Py_END_SUPPRESS_IPH
8813 Py_END_ALLOW_THREADS
8814
8815 if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8816 windows_has_symlink_unprivileged_flag = FALSE;
8817 }
8818 }
8819
8820 if (!result)
8821 return path_error2(src, dst);
8822
8823 #else
8824
8825 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8826 PyErr_SetString(PyExc_ValueError,
8827 "symlink: src and dst must be the same type");
8828 return NULL;
8829 }
8830
8831 Py_BEGIN_ALLOW_THREADS
8832 #ifdef HAVE_SYMLINKAT
8833 if (dir_fd != DEFAULT_DIR_FD) {
8834 if (HAVE_SYMLINKAT_RUNTIME) {
8835 result = symlinkat(src->narrow, dir_fd, dst->narrow);
8836 } else {
8837 symlinkat_unavailable = 1;
8838 }
8839 } else
8840 #endif
8841 result = symlink(src->narrow, dst->narrow);
8842 Py_END_ALLOW_THREADS
8843
8844 #ifdef HAVE_SYMLINKAT
8845 if (symlinkat_unavailable) {
8846 argument_unavailable_error(NULL, "dir_fd");
8847 return NULL;
8848 }
8849 #endif
8850
8851 if (result)
8852 return path_error2(src, dst);
8853 #endif
8854
8855 Py_RETURN_NONE;
8856 }
8857 #endif /* HAVE_SYMLINK */
8858
8859
8860
8861
8862 static PyStructSequence_Field times_result_fields[] = {
8863 {"user", "user time"},
8864 {"system", "system time"},
8865 {"children_user", "user time of children"},
8866 {"children_system", "system time of children"},
8867 {"elapsed", "elapsed time since an arbitrary point in the past"},
8868 {NULL}
8869 };
8870
8871 PyDoc_STRVAR(times_result__doc__,
8872 "times_result: Result from os.times().\n\n\
8873 This object may be accessed either as a tuple of\n\
8874 (user, system, children_user, children_system, elapsed),\n\
8875 or via the attributes user, system, children_user, children_system,\n\
8876 and elapsed.\n\
8877 \n\
8878 See os.times for more information.");
8879
8880 static PyStructSequence_Desc times_result_desc = {
8881 "times_result", /* name */
8882 times_result__doc__, /* doc */
8883 times_result_fields,
8884 5
8885 };
8886
8887 #ifdef MS_WINDOWS
8888 #define HAVE_TIMES /* mandatory, for the method table */
8889 #endif
8890
8891 #ifdef HAVE_TIMES
8892
8893 static PyObject *
build_times_result(PyObject * module,double user,double system,double children_user,double children_system,double elapsed)8894 build_times_result(PyObject *module, double user, double system,
8895 double children_user, double children_system,
8896 double elapsed)
8897 {
8898 PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
8899 PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
8900 if (value == NULL)
8901 return NULL;
8902
8903 #define SET(i, field) \
8904 { \
8905 PyObject *o = PyFloat_FromDouble(field); \
8906 if (!o) { \
8907 Py_DECREF(value); \
8908 return NULL; \
8909 } \
8910 PyStructSequence_SET_ITEM(value, i, o); \
8911 } \
8912
8913 SET(0, user);
8914 SET(1, system);
8915 SET(2, children_user);
8916 SET(3, children_system);
8917 SET(4, elapsed);
8918
8919 #undef SET
8920
8921 return value;
8922 }
8923
8924
8925 #ifndef MS_WINDOWS
8926 #define NEED_TICKS_PER_SECOND
8927 static long ticks_per_second = -1;
8928 #endif /* MS_WINDOWS */
8929
8930 /*[clinic input]
8931 os.times
8932
8933 Return a collection containing process timing information.
8934
8935 The object returned behaves like a named tuple with these fields:
8936 (utime, stime, cutime, cstime, elapsed_time)
8937 All fields are floating point numbers.
8938 [clinic start generated code]*/
8939
8940 static PyObject *
os_times_impl(PyObject * module)8941 os_times_impl(PyObject *module)
8942 /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
8943 #ifdef MS_WINDOWS
8944 {
8945 FILETIME create, exit, kernel, user;
8946 HANDLE hProc;
8947 hProc = GetCurrentProcess();
8948 GetProcessTimes(hProc, &create, &exit, &kernel, &user);
8949 /* The fields of a FILETIME structure are the hi and lo part
8950 of a 64-bit value expressed in 100 nanosecond units.
8951 1e7 is one second in such units; 1e-7 the inverse.
8952 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
8953 */
8954 return build_times_result(module,
8955 (double)(user.dwHighDateTime*429.4967296 +
8956 user.dwLowDateTime*1e-7),
8957 (double)(kernel.dwHighDateTime*429.4967296 +
8958 kernel.dwLowDateTime*1e-7),
8959 (double)0,
8960 (double)0,
8961 (double)0);
8962 }
8963 #else /* MS_WINDOWS */
8964 {
8965
8966
8967 struct tms t;
8968 clock_t c;
8969 errno = 0;
8970 c = times(&t);
8971 if (c == (clock_t) -1)
8972 return posix_error();
8973 return build_times_result(module,
8974 (double)t.tms_utime / ticks_per_second,
8975 (double)t.tms_stime / ticks_per_second,
8976 (double)t.tms_cutime / ticks_per_second,
8977 (double)t.tms_cstime / ticks_per_second,
8978 (double)c / ticks_per_second);
8979 }
8980 #endif /* MS_WINDOWS */
8981 #endif /* HAVE_TIMES */
8982
8983
8984 #ifdef HAVE_GETSID
8985 /*[clinic input]
8986 os.getsid
8987
8988 pid: pid_t
8989 /
8990
8991 Call the system call getsid(pid) and return the result.
8992 [clinic start generated code]*/
8993
8994 static PyObject *
os_getsid_impl(PyObject * module,pid_t pid)8995 os_getsid_impl(PyObject *module, pid_t pid)
8996 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
8997 {
8998 int sid;
8999 sid = getsid(pid);
9000 if (sid < 0)
9001 return posix_error();
9002 return PyLong_FromLong((long)sid);
9003 }
9004 #endif /* HAVE_GETSID */
9005
9006
9007 #ifdef HAVE_SETSID
9008 /*[clinic input]
9009 os.setsid
9010
9011 Call the system call setsid().
9012 [clinic start generated code]*/
9013
9014 static PyObject *
os_setsid_impl(PyObject * module)9015 os_setsid_impl(PyObject *module)
9016 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
9017 {
9018 if (setsid() < 0)
9019 return posix_error();
9020 Py_RETURN_NONE;
9021 }
9022 #endif /* HAVE_SETSID */
9023
9024
9025 #ifdef HAVE_SETPGID
9026 /*[clinic input]
9027 os.setpgid
9028
9029 pid: pid_t
9030 pgrp: pid_t
9031 /
9032
9033 Call the system call setpgid(pid, pgrp).
9034 [clinic start generated code]*/
9035
9036 static PyObject *
os_setpgid_impl(PyObject * module,pid_t pid,pid_t pgrp)9037 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
9038 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
9039 {
9040 if (setpgid(pid, pgrp) < 0)
9041 return posix_error();
9042 Py_RETURN_NONE;
9043 }
9044 #endif /* HAVE_SETPGID */
9045
9046
9047 #ifdef HAVE_TCGETPGRP
9048 /*[clinic input]
9049 os.tcgetpgrp
9050
9051 fd: int
9052 /
9053
9054 Return the process group associated with the terminal specified by fd.
9055 [clinic start generated code]*/
9056
9057 static PyObject *
os_tcgetpgrp_impl(PyObject * module,int fd)9058 os_tcgetpgrp_impl(PyObject *module, int fd)
9059 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
9060 {
9061 pid_t pgid = tcgetpgrp(fd);
9062 if (pgid < 0)
9063 return posix_error();
9064 return PyLong_FromPid(pgid);
9065 }
9066 #endif /* HAVE_TCGETPGRP */
9067
9068
9069 #ifdef HAVE_TCSETPGRP
9070 /*[clinic input]
9071 os.tcsetpgrp
9072
9073 fd: int
9074 pgid: pid_t
9075 /
9076
9077 Set the process group associated with the terminal specified by fd.
9078 [clinic start generated code]*/
9079
9080 static PyObject *
os_tcsetpgrp_impl(PyObject * module,int fd,pid_t pgid)9081 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
9082 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
9083 {
9084 if (tcsetpgrp(fd, pgid) < 0)
9085 return posix_error();
9086 Py_RETURN_NONE;
9087 }
9088 #endif /* HAVE_TCSETPGRP */
9089
9090 /* Functions acting on file descriptors */
9091
9092 #ifdef O_CLOEXEC
9093 extern int _Py_open_cloexec_works;
9094 #endif
9095
9096
9097 /*[clinic input]
9098 os.open -> int
9099 path: path_t
9100 flags: int
9101 mode: int = 0o777
9102 *
9103 dir_fd: dir_fd(requires='openat') = None
9104
9105 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
9106
9107 Open a file for low level IO. Returns a file descriptor (integer).
9108
9109 If dir_fd is not None, it should be a file descriptor open to a directory,
9110 and path should be relative; path will then be relative to that directory.
9111 dir_fd may not be implemented on your platform.
9112 If it is unavailable, using it will raise a NotImplementedError.
9113 [clinic start generated code]*/
9114
9115 static int
os_open_impl(PyObject * module,path_t * path,int flags,int mode,int dir_fd)9116 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
9117 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
9118 {
9119 int fd;
9120 int async_err = 0;
9121 #ifdef HAVE_OPENAT
9122 int openat_unavailable = 0;
9123 #endif
9124
9125 #ifdef O_CLOEXEC
9126 int *atomic_flag_works = &_Py_open_cloexec_works;
9127 #elif !defined(MS_WINDOWS)
9128 int *atomic_flag_works = NULL;
9129 #endif
9130
9131 #ifdef MS_WINDOWS
9132 flags |= O_NOINHERIT;
9133 #elif defined(O_CLOEXEC)
9134 flags |= O_CLOEXEC;
9135 #endif
9136
9137 if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
9138 return -1;
9139 }
9140
9141 _Py_BEGIN_SUPPRESS_IPH
9142 do {
9143 Py_BEGIN_ALLOW_THREADS
9144 #ifdef MS_WINDOWS
9145 fd = _wopen(path->wide, flags, mode);
9146 #else
9147 #ifdef HAVE_OPENAT
9148 if (dir_fd != DEFAULT_DIR_FD) {
9149 if (HAVE_OPENAT_RUNTIME) {
9150 fd = openat(dir_fd, path->narrow, flags, mode);
9151
9152 } else {
9153 openat_unavailable = 1;
9154 fd = -1;
9155 }
9156 } else
9157 #endif /* HAVE_OPENAT */
9158 fd = open(path->narrow, flags, mode);
9159 #endif /* !MS_WINDOWS */
9160 Py_END_ALLOW_THREADS
9161 } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9162 _Py_END_SUPPRESS_IPH
9163
9164 #ifdef HAVE_OPENAT
9165 if (openat_unavailable) {
9166 argument_unavailable_error(NULL, "dir_fd");
9167 return -1;
9168 }
9169 #endif
9170
9171 if (fd < 0) {
9172 if (!async_err)
9173 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
9174 return -1;
9175 }
9176
9177 #ifndef MS_WINDOWS
9178 if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
9179 close(fd);
9180 return -1;
9181 }
9182 #endif
9183
9184 return fd;
9185 }
9186
9187
9188 /*[clinic input]
9189 os.close
9190
9191 fd: int
9192
9193 Close a file descriptor.
9194 [clinic start generated code]*/
9195
9196 static PyObject *
os_close_impl(PyObject * module,int fd)9197 os_close_impl(PyObject *module, int fd)
9198 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
9199 {
9200 int res;
9201 /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
9202 * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
9203 * for more details.
9204 */
9205 Py_BEGIN_ALLOW_THREADS
9206 _Py_BEGIN_SUPPRESS_IPH
9207 res = close(fd);
9208 _Py_END_SUPPRESS_IPH
9209 Py_END_ALLOW_THREADS
9210 if (res < 0)
9211 return posix_error();
9212 Py_RETURN_NONE;
9213 }
9214
9215 /*[clinic input]
9216 os.closerange
9217
9218 fd_low: int
9219 fd_high: int
9220 /
9221
9222 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
9223 [clinic start generated code]*/
9224
9225 static PyObject *
os_closerange_impl(PyObject * module,int fd_low,int fd_high)9226 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
9227 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
9228 {
9229 Py_BEGIN_ALLOW_THREADS
9230 _Py_closerange(fd_low, fd_high - 1);
9231 Py_END_ALLOW_THREADS
9232 Py_RETURN_NONE;
9233 }
9234
9235
9236 /*[clinic input]
9237 os.dup -> int
9238
9239 fd: int
9240 /
9241
9242 Return a duplicate of a file descriptor.
9243 [clinic start generated code]*/
9244
9245 static int
os_dup_impl(PyObject * module,int fd)9246 os_dup_impl(PyObject *module, int fd)
9247 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
9248 {
9249 return _Py_dup(fd);
9250 }
9251
9252
9253 /*[clinic input]
9254 os.dup2 -> int
9255 fd: int
9256 fd2: int
9257 inheritable: bool=True
9258
9259 Duplicate file descriptor.
9260 [clinic start generated code]*/
9261
9262 static int
os_dup2_impl(PyObject * module,int fd,int fd2,int inheritable)9263 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
9264 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
9265 {
9266 int res = 0;
9267 #if defined(HAVE_DUP3) && \
9268 !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
9269 /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
9270 static int dup3_works = -1;
9271 #endif
9272
9273 if (fd < 0 || fd2 < 0) {
9274 posix_error();
9275 return -1;
9276 }
9277
9278 /* dup2() can fail with EINTR if the target FD is already open, because it
9279 * then has to be closed. See os_close_impl() for why we don't handle EINTR
9280 * upon close(), and therefore below.
9281 */
9282 #ifdef MS_WINDOWS
9283 Py_BEGIN_ALLOW_THREADS
9284 _Py_BEGIN_SUPPRESS_IPH
9285 res = dup2(fd, fd2);
9286 _Py_END_SUPPRESS_IPH
9287 Py_END_ALLOW_THREADS
9288 if (res < 0) {
9289 posix_error();
9290 return -1;
9291 }
9292 res = fd2; // msvcrt dup2 returns 0 on success.
9293
9294 /* Character files like console cannot be make non-inheritable */
9295 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9296 close(fd2);
9297 return -1;
9298 }
9299
9300 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
9301 Py_BEGIN_ALLOW_THREADS
9302 if (!inheritable)
9303 res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
9304 else
9305 res = dup2(fd, fd2);
9306 Py_END_ALLOW_THREADS
9307 if (res < 0) {
9308 posix_error();
9309 return -1;
9310 }
9311
9312 #else
9313
9314 #ifdef HAVE_DUP3
9315 if (!inheritable && dup3_works != 0) {
9316 Py_BEGIN_ALLOW_THREADS
9317 res = dup3(fd, fd2, O_CLOEXEC);
9318 Py_END_ALLOW_THREADS
9319 if (res < 0) {
9320 if (dup3_works == -1)
9321 dup3_works = (errno != ENOSYS);
9322 if (dup3_works) {
9323 posix_error();
9324 return -1;
9325 }
9326 }
9327 }
9328
9329 if (inheritable || dup3_works == 0)
9330 {
9331 #endif
9332 Py_BEGIN_ALLOW_THREADS
9333 res = dup2(fd, fd2);
9334 Py_END_ALLOW_THREADS
9335 if (res < 0) {
9336 posix_error();
9337 return -1;
9338 }
9339
9340 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9341 close(fd2);
9342 return -1;
9343 }
9344 #ifdef HAVE_DUP3
9345 }
9346 #endif
9347
9348 #endif
9349
9350 return res;
9351 }
9352
9353
9354 #ifdef HAVE_LOCKF
9355 /*[clinic input]
9356 os.lockf
9357
9358 fd: int
9359 An open file descriptor.
9360 command: int
9361 One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
9362 length: Py_off_t
9363 The number of bytes to lock, starting at the current position.
9364 /
9365
9366 Apply, test or remove a POSIX lock on an open file descriptor.
9367
9368 [clinic start generated code]*/
9369
9370 static PyObject *
os_lockf_impl(PyObject * module,int fd,int command,Py_off_t length)9371 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
9372 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
9373 {
9374 int res;
9375
9376 if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
9377 return NULL;
9378 }
9379
9380 Py_BEGIN_ALLOW_THREADS
9381 res = lockf(fd, command, length);
9382 Py_END_ALLOW_THREADS
9383
9384 if (res < 0)
9385 return posix_error();
9386
9387 Py_RETURN_NONE;
9388 }
9389 #endif /* HAVE_LOCKF */
9390
9391
9392 /*[clinic input]
9393 os.lseek -> Py_off_t
9394
9395 fd: int
9396 position: Py_off_t
9397 how: int
9398 /
9399
9400 Set the position of a file descriptor. Return the new position.
9401
9402 Return the new cursor position in number of bytes
9403 relative to the beginning of the file.
9404 [clinic start generated code]*/
9405
9406 static Py_off_t
os_lseek_impl(PyObject * module,int fd,Py_off_t position,int how)9407 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
9408 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
9409 {
9410 Py_off_t result;
9411
9412 #ifdef SEEK_SET
9413 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
9414 switch (how) {
9415 case 0: how = SEEK_SET; break;
9416 case 1: how = SEEK_CUR; break;
9417 case 2: how = SEEK_END; break;
9418 }
9419 #endif /* SEEK_END */
9420
9421 Py_BEGIN_ALLOW_THREADS
9422 _Py_BEGIN_SUPPRESS_IPH
9423 #ifdef MS_WINDOWS
9424 result = _lseeki64(fd, position, how);
9425 #else
9426 result = lseek(fd, position, how);
9427 #endif
9428 _Py_END_SUPPRESS_IPH
9429 Py_END_ALLOW_THREADS
9430 if (result < 0)
9431 posix_error();
9432
9433 return result;
9434 }
9435
9436
9437 /*[clinic input]
9438 os.read
9439 fd: int
9440 length: Py_ssize_t
9441 /
9442
9443 Read from a file descriptor. Returns a bytes object.
9444 [clinic start generated code]*/
9445
9446 static PyObject *
os_read_impl(PyObject * module,int fd,Py_ssize_t length)9447 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
9448 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
9449 {
9450 Py_ssize_t n;
9451 PyObject *buffer;
9452
9453 if (length < 0) {
9454 errno = EINVAL;
9455 return posix_error();
9456 }
9457
9458 length = Py_MIN(length, _PY_READ_MAX);
9459
9460 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9461 if (buffer == NULL)
9462 return NULL;
9463
9464 n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
9465 if (n == -1) {
9466 Py_DECREF(buffer);
9467 return NULL;
9468 }
9469
9470 if (n != length)
9471 _PyBytes_Resize(&buffer, n);
9472
9473 return buffer;
9474 }
9475
9476 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
9477 || defined(__APPLE__))) \
9478 || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
9479 || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9480 static int
iov_setup(struct iovec ** iov,Py_buffer ** buf,PyObject * seq,Py_ssize_t cnt,int type)9481 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
9482 {
9483 Py_ssize_t i, j;
9484
9485 *iov = PyMem_New(struct iovec, cnt);
9486 if (*iov == NULL) {
9487 PyErr_NoMemory();
9488 return -1;
9489 }
9490
9491 *buf = PyMem_New(Py_buffer, cnt);
9492 if (*buf == NULL) {
9493 PyMem_Free(*iov);
9494 PyErr_NoMemory();
9495 return -1;
9496 }
9497
9498 for (i = 0; i < cnt; i++) {
9499 PyObject *item = PySequence_GetItem(seq, i);
9500 if (item == NULL)
9501 goto fail;
9502 if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
9503 Py_DECREF(item);
9504 goto fail;
9505 }
9506 Py_DECREF(item);
9507 (*iov)[i].iov_base = (*buf)[i].buf;
9508 (*iov)[i].iov_len = (*buf)[i].len;
9509 }
9510 return 0;
9511
9512 fail:
9513 PyMem_Free(*iov);
9514 for (j = 0; j < i; j++) {
9515 PyBuffer_Release(&(*buf)[j]);
9516 }
9517 PyMem_Free(*buf);
9518 return -1;
9519 }
9520
9521 static void
iov_cleanup(struct iovec * iov,Py_buffer * buf,int cnt)9522 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9523 {
9524 int i;
9525 PyMem_Free(iov);
9526 for (i = 0; i < cnt; i++) {
9527 PyBuffer_Release(&buf[i]);
9528 }
9529 PyMem_Free(buf);
9530 }
9531 #endif
9532
9533
9534 #ifdef HAVE_READV
9535 /*[clinic input]
9536 os.readv -> Py_ssize_t
9537
9538 fd: int
9539 buffers: object
9540 /
9541
9542 Read from a file descriptor fd into an iterable of buffers.
9543
9544 The buffers should be mutable buffers accepting bytes.
9545 readv will transfer data into each buffer until it is full
9546 and then move on to the next buffer in the sequence to hold
9547 the rest of the data.
9548
9549 readv returns the total number of bytes read,
9550 which may be less than the total capacity of all the buffers.
9551 [clinic start generated code]*/
9552
9553 static Py_ssize_t
os_readv_impl(PyObject * module,int fd,PyObject * buffers)9554 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9555 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9556 {
9557 Py_ssize_t cnt, n;
9558 int async_err = 0;
9559 struct iovec *iov;
9560 Py_buffer *buf;
9561
9562 if (!PySequence_Check(buffers)) {
9563 PyErr_SetString(PyExc_TypeError,
9564 "readv() arg 2 must be a sequence");
9565 return -1;
9566 }
9567
9568 cnt = PySequence_Size(buffers);
9569 if (cnt < 0)
9570 return -1;
9571
9572 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9573 return -1;
9574
9575 do {
9576 Py_BEGIN_ALLOW_THREADS
9577 n = readv(fd, iov, cnt);
9578 Py_END_ALLOW_THREADS
9579 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9580
9581 iov_cleanup(iov, buf, cnt);
9582 if (n < 0) {
9583 if (!async_err)
9584 posix_error();
9585 return -1;
9586 }
9587
9588 return n;
9589 }
9590 #endif /* HAVE_READV */
9591
9592
9593 #ifdef HAVE_PREAD
9594 /*[clinic input]
9595 os.pread
9596
9597 fd: int
9598 length: Py_ssize_t
9599 offset: Py_off_t
9600 /
9601
9602 Read a number of bytes from a file descriptor starting at a particular offset.
9603
9604 Read length bytes from file descriptor fd, starting at offset bytes from
9605 the beginning of the file. The file offset remains unchanged.
9606 [clinic start generated code]*/
9607
9608 static PyObject *
os_pread_impl(PyObject * module,int fd,Py_ssize_t length,Py_off_t offset)9609 os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
9610 /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
9611 {
9612 Py_ssize_t n;
9613 int async_err = 0;
9614 PyObject *buffer;
9615
9616 if (length < 0) {
9617 errno = EINVAL;
9618 return posix_error();
9619 }
9620 buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9621 if (buffer == NULL)
9622 return NULL;
9623
9624 do {
9625 Py_BEGIN_ALLOW_THREADS
9626 _Py_BEGIN_SUPPRESS_IPH
9627 n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9628 _Py_END_SUPPRESS_IPH
9629 Py_END_ALLOW_THREADS
9630 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9631
9632 if (n < 0) {
9633 Py_DECREF(buffer);
9634 return (!async_err) ? posix_error() : NULL;
9635 }
9636 if (n != length)
9637 _PyBytes_Resize(&buffer, n);
9638 return buffer;
9639 }
9640 #endif /* HAVE_PREAD */
9641
9642 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9643 /*[clinic input]
9644 os.preadv -> Py_ssize_t
9645
9646 fd: int
9647 buffers: object
9648 offset: Py_off_t
9649 flags: int = 0
9650 /
9651
9652 Reads from a file descriptor into a number of mutable bytes-like objects.
9653
9654 Combines the functionality of readv() and pread(). As readv(), it will
9655 transfer data into each buffer until it is full and then move on to the next
9656 buffer in the sequence to hold the rest of the data. Its fourth argument,
9657 specifies the file offset at which the input operation is to be performed. It
9658 will return the total number of bytes read (which can be less than the total
9659 capacity of all the objects).
9660
9661 The flags argument contains a bitwise OR of zero or more of the following flags:
9662
9663 - RWF_HIPRI
9664 - RWF_NOWAIT
9665
9666 Using non-zero flags requires Linux 4.6 or newer.
9667 [clinic start generated code]*/
9668
9669 static Py_ssize_t
os_preadv_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9670 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9671 int flags)
9672 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9673 {
9674 Py_ssize_t cnt, n;
9675 int async_err = 0;
9676 struct iovec *iov;
9677 Py_buffer *buf;
9678
9679 if (!PySequence_Check(buffers)) {
9680 PyErr_SetString(PyExc_TypeError,
9681 "preadv2() arg 2 must be a sequence");
9682 return -1;
9683 }
9684
9685 cnt = PySequence_Size(buffers);
9686 if (cnt < 0) {
9687 return -1;
9688 }
9689
9690 #ifndef HAVE_PREADV2
9691 if(flags != 0) {
9692 argument_unavailable_error("preadv2", "flags");
9693 return -1;
9694 }
9695 #endif
9696
9697 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9698 return -1;
9699 }
9700 #ifdef HAVE_PREADV2
9701 do {
9702 Py_BEGIN_ALLOW_THREADS
9703 _Py_BEGIN_SUPPRESS_IPH
9704 n = preadv2(fd, iov, cnt, offset, flags);
9705 _Py_END_SUPPRESS_IPH
9706 Py_END_ALLOW_THREADS
9707 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9708 #else
9709 do {
9710 #ifdef __APPLE__
9711 /* This entire function will be removed from the module dict when the API
9712 * is not available.
9713 */
9714 #pragma clang diagnostic push
9715 #pragma clang diagnostic ignored "-Wunguarded-availability"
9716 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
9717 #endif
9718 Py_BEGIN_ALLOW_THREADS
9719 _Py_BEGIN_SUPPRESS_IPH
9720 n = preadv(fd, iov, cnt, offset);
9721 _Py_END_SUPPRESS_IPH
9722 Py_END_ALLOW_THREADS
9723 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9724
9725 #ifdef __APPLE__
9726 #pragma clang diagnostic pop
9727 #endif
9728
9729 #endif
9730
9731 iov_cleanup(iov, buf, cnt);
9732 if (n < 0) {
9733 if (!async_err) {
9734 posix_error();
9735 }
9736 return -1;
9737 }
9738
9739 return n;
9740 }
9741 #endif /* HAVE_PREADV */
9742
9743
9744 /*[clinic input]
9745 os.write -> Py_ssize_t
9746
9747 fd: int
9748 data: Py_buffer
9749 /
9750
9751 Write a bytes object to a file descriptor.
9752 [clinic start generated code]*/
9753
9754 static Py_ssize_t
os_write_impl(PyObject * module,int fd,Py_buffer * data)9755 os_write_impl(PyObject *module, int fd, Py_buffer *data)
9756 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9757 {
9758 return _Py_write(fd, data->buf, data->len);
9759 }
9760
9761 #ifdef HAVE_SENDFILE
9762 #ifdef __APPLE__
9763 /*[clinic input]
9764 os.sendfile
9765
9766 out_fd: int
9767 in_fd: int
9768 offset: Py_off_t
9769 count as sbytes: Py_off_t
9770 headers: object(c_default="NULL") = ()
9771 trailers: object(c_default="NULL") = ()
9772 flags: int = 0
9773
9774 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9775 [clinic start generated code]*/
9776
9777 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)9778 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9779 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
9780 int flags)
9781 /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
9782 #elif defined(__FreeBSD__) || defined(__DragonFly__)
9783 /*[clinic input]
9784 os.sendfile
9785
9786 out_fd: int
9787 in_fd: int
9788 offset: Py_off_t
9789 count: Py_ssize_t
9790 headers: object(c_default="NULL") = ()
9791 trailers: object(c_default="NULL") = ()
9792 flags: int = 0
9793
9794 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9795 [clinic start generated code]*/
9796
9797 static PyObject *
9798 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9799 Py_ssize_t count, PyObject *headers, PyObject *trailers,
9800 int flags)
9801 /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
9802 #else
9803 /*[clinic input]
9804 os.sendfile
9805
9806 out_fd: int
9807 in_fd: int
9808 offset as offobj: object
9809 count: Py_ssize_t
9810
9811 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9812 [clinic start generated code]*/
9813
9814 static PyObject *
9815 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
9816 Py_ssize_t count)
9817 /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
9818 #endif
9819 {
9820 Py_ssize_t ret;
9821 int async_err = 0;
9822
9823 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9824 #ifndef __APPLE__
9825 off_t sbytes;
9826 #endif
9827 Py_buffer *hbuf, *tbuf;
9828 struct sf_hdtr sf;
9829
9830 sf.headers = NULL;
9831 sf.trailers = NULL;
9832
9833 if (headers != NULL) {
9834 if (!PySequence_Check(headers)) {
9835 PyErr_SetString(PyExc_TypeError,
9836 "sendfile() headers must be a sequence");
9837 return NULL;
9838 } else {
9839 Py_ssize_t i = PySequence_Size(headers);
9840 if (i < 0)
9841 return NULL;
9842 if (i > INT_MAX) {
9843 PyErr_SetString(PyExc_OverflowError,
9844 "sendfile() header is too large");
9845 return NULL;
9846 }
9847 if (i > 0) {
9848 sf.hdr_cnt = (int)i;
9849 if (iov_setup(&(sf.headers), &hbuf,
9850 headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9851 return NULL;
9852 #ifdef __APPLE__
9853 for (i = 0; i < sf.hdr_cnt; i++) {
9854 Py_ssize_t blen = sf.headers[i].iov_len;
9855 # define OFF_T_MAX 0x7fffffffffffffff
9856 if (sbytes >= OFF_T_MAX - blen) {
9857 PyErr_SetString(PyExc_OverflowError,
9858 "sendfile() header is too large");
9859 return NULL;
9860 }
9861 sbytes += blen;
9862 }
9863 #endif
9864 }
9865 }
9866 }
9867 if (trailers != NULL) {
9868 if (!PySequence_Check(trailers)) {
9869 PyErr_SetString(PyExc_TypeError,
9870 "sendfile() trailers must be a sequence");
9871 return NULL;
9872 } else {
9873 Py_ssize_t i = PySequence_Size(trailers);
9874 if (i < 0)
9875 return NULL;
9876 if (i > INT_MAX) {
9877 PyErr_SetString(PyExc_OverflowError,
9878 "sendfile() trailer is too large");
9879 return NULL;
9880 }
9881 if (i > 0) {
9882 sf.trl_cnt = (int)i;
9883 if (iov_setup(&(sf.trailers), &tbuf,
9884 trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
9885 return NULL;
9886 }
9887 }
9888 }
9889
9890 _Py_BEGIN_SUPPRESS_IPH
9891 do {
9892 Py_BEGIN_ALLOW_THREADS
9893 #ifdef __APPLE__
9894 ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
9895 #else
9896 ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
9897 #endif
9898 Py_END_ALLOW_THREADS
9899 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9900 _Py_END_SUPPRESS_IPH
9901
9902 if (sf.headers != NULL)
9903 iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
9904 if (sf.trailers != NULL)
9905 iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
9906
9907 if (ret < 0) {
9908 if ((errno == EAGAIN) || (errno == EBUSY)) {
9909 if (sbytes != 0) {
9910 // some data has been sent
9911 goto done;
9912 }
9913 else {
9914 // no data has been sent; upper application is supposed
9915 // to retry on EAGAIN or EBUSY
9916 return posix_error();
9917 }
9918 }
9919 return (!async_err) ? posix_error() : NULL;
9920 }
9921 goto done;
9922
9923 done:
9924 #if !defined(HAVE_LARGEFILE_SUPPORT)
9925 return Py_BuildValue("l", sbytes);
9926 #else
9927 return Py_BuildValue("L", sbytes);
9928 #endif
9929
9930 #else
9931 #ifdef __linux__
9932 if (offobj == Py_None) {
9933 do {
9934 Py_BEGIN_ALLOW_THREADS
9935 ret = sendfile(out_fd, in_fd, NULL, count);
9936 Py_END_ALLOW_THREADS
9937 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9938 if (ret < 0)
9939 return (!async_err) ? posix_error() : NULL;
9940 return Py_BuildValue("n", ret);
9941 }
9942 #endif
9943 off_t offset;
9944 if (!Py_off_t_converter(offobj, &offset))
9945 return NULL;
9946
9947 #if defined(__sun) && defined(__SVR4)
9948 // On Solaris, sendfile raises EINVAL rather than returning 0
9949 // when the offset is equal or bigger than the in_fd size.
9950 struct stat st;
9951
9952 do {
9953 Py_BEGIN_ALLOW_THREADS
9954 ret = fstat(in_fd, &st);
9955 Py_END_ALLOW_THREADS
9956 } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9957 if (ret < 0)
9958 return (!async_err) ? posix_error() : NULL;
9959
9960 if (offset >= st.st_size) {
9961 return Py_BuildValue("i", 0);
9962 }
9963
9964 // On illumos specifically sendfile() may perform a partial write but
9965 // return -1/an error (in one confirmed case the destination socket
9966 // had a 5 second timeout set and errno was EAGAIN) and it's on the client
9967 // code to check if the offset parameter was modified by sendfile().
9968 //
9969 // We need this variable to track said change.
9970 off_t original_offset = offset;
9971 #endif
9972
9973 do {
9974 Py_BEGIN_ALLOW_THREADS
9975 ret = sendfile(out_fd, in_fd, &offset, count);
9976 #if defined(__sun) && defined(__SVR4)
9977 // This handles illumos-specific sendfile() partial write behavior,
9978 // see a comment above for more details.
9979 if (ret < 0 && offset != original_offset) {
9980 ret = offset - original_offset;
9981 }
9982 #endif
9983 Py_END_ALLOW_THREADS
9984 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9985 if (ret < 0)
9986 return (!async_err) ? posix_error() : NULL;
9987 return Py_BuildValue("n", ret);
9988 #endif
9989 }
9990 #endif /* HAVE_SENDFILE */
9991
9992
9993 #if defined(__APPLE__)
9994 /*[clinic input]
9995 os._fcopyfile
9996
9997 in_fd: int
9998 out_fd: int
9999 flags: int
10000 /
10001
10002 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
10003 [clinic start generated code]*/
10004
10005 static PyObject *
os__fcopyfile_impl(PyObject * module,int in_fd,int out_fd,int flags)10006 os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
10007 /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
10008 {
10009 int ret;
10010
10011 Py_BEGIN_ALLOW_THREADS
10012 ret = fcopyfile(in_fd, out_fd, NULL, flags);
10013 Py_END_ALLOW_THREADS
10014 if (ret < 0)
10015 return posix_error();
10016 Py_RETURN_NONE;
10017 }
10018 #endif
10019
10020
10021 /*[clinic input]
10022 os.fstat
10023
10024 fd : int
10025
10026 Perform a stat system call on the given file descriptor.
10027
10028 Like stat(), but for an open file descriptor.
10029 Equivalent to os.stat(fd).
10030 [clinic start generated code]*/
10031
10032 static PyObject *
os_fstat_impl(PyObject * module,int fd)10033 os_fstat_impl(PyObject *module, int fd)
10034 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
10035 {
10036 STRUCT_STAT st;
10037 int res;
10038 int async_err = 0;
10039
10040 do {
10041 Py_BEGIN_ALLOW_THREADS
10042 res = FSTAT(fd, &st);
10043 Py_END_ALLOW_THREADS
10044 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10045 if (res != 0) {
10046 #ifdef MS_WINDOWS
10047 return PyErr_SetFromWindowsErr(0);
10048 #else
10049 return (!async_err) ? posix_error() : NULL;
10050 #endif
10051 }
10052
10053 return _pystat_fromstructstat(module, &st);
10054 }
10055
10056
10057 /*[clinic input]
10058 os.isatty -> bool
10059 fd: int
10060 /
10061
10062 Return True if the fd is connected to a terminal.
10063
10064 Return True if the file descriptor is an open file descriptor
10065 connected to the slave end of a terminal.
10066 [clinic start generated code]*/
10067
10068 static int
os_isatty_impl(PyObject * module,int fd)10069 os_isatty_impl(PyObject *module, int fd)
10070 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
10071 {
10072 int return_value;
10073 Py_BEGIN_ALLOW_THREADS
10074 _Py_BEGIN_SUPPRESS_IPH
10075 return_value = isatty(fd);
10076 _Py_END_SUPPRESS_IPH
10077 Py_END_ALLOW_THREADS
10078 return return_value;
10079 }
10080
10081
10082 #ifdef HAVE_PIPE
10083 /*[clinic input]
10084 os.pipe
10085
10086 Create a pipe.
10087
10088 Returns a tuple of two file descriptors:
10089 (read_fd, write_fd)
10090 [clinic start generated code]*/
10091
10092 static PyObject *
os_pipe_impl(PyObject * module)10093 os_pipe_impl(PyObject *module)
10094 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
10095 {
10096 int fds[2];
10097 #ifdef MS_WINDOWS
10098 HANDLE read, write;
10099 SECURITY_ATTRIBUTES attr;
10100 BOOL ok;
10101 #else
10102 int res;
10103 #endif
10104
10105 #ifdef MS_WINDOWS
10106 attr.nLength = sizeof(attr);
10107 attr.lpSecurityDescriptor = NULL;
10108 attr.bInheritHandle = FALSE;
10109
10110 Py_BEGIN_ALLOW_THREADS
10111 ok = CreatePipe(&read, &write, &attr, 0);
10112 if (ok) {
10113 fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY);
10114 fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY);
10115 if (fds[0] == -1 || fds[1] == -1) {
10116 CloseHandle(read);
10117 CloseHandle(write);
10118 ok = 0;
10119 }
10120 }
10121 Py_END_ALLOW_THREADS
10122
10123 if (!ok)
10124 return PyErr_SetFromWindowsErr(0);
10125 #else
10126
10127 #ifdef HAVE_PIPE2
10128 Py_BEGIN_ALLOW_THREADS
10129 res = pipe2(fds, O_CLOEXEC);
10130 Py_END_ALLOW_THREADS
10131
10132 if (res != 0 && errno == ENOSYS)
10133 {
10134 #endif
10135 Py_BEGIN_ALLOW_THREADS
10136 res = pipe(fds);
10137 Py_END_ALLOW_THREADS
10138
10139 if (res == 0) {
10140 if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
10141 close(fds[0]);
10142 close(fds[1]);
10143 return NULL;
10144 }
10145 if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
10146 close(fds[0]);
10147 close(fds[1]);
10148 return NULL;
10149 }
10150 }
10151 #ifdef HAVE_PIPE2
10152 }
10153 #endif
10154
10155 if (res != 0)
10156 return PyErr_SetFromErrno(PyExc_OSError);
10157 #endif /* !MS_WINDOWS */
10158 return Py_BuildValue("(ii)", fds[0], fds[1]);
10159 }
10160 #endif /* HAVE_PIPE */
10161
10162
10163 #ifdef HAVE_PIPE2
10164 /*[clinic input]
10165 os.pipe2
10166
10167 flags: int
10168 /
10169
10170 Create a pipe with flags set atomically.
10171
10172 Returns a tuple of two file descriptors:
10173 (read_fd, write_fd)
10174
10175 flags can be constructed by ORing together one or more of these values:
10176 O_NONBLOCK, O_CLOEXEC.
10177 [clinic start generated code]*/
10178
10179 static PyObject *
os_pipe2_impl(PyObject * module,int flags)10180 os_pipe2_impl(PyObject *module, int flags)
10181 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
10182 {
10183 int fds[2];
10184 int res;
10185
10186 res = pipe2(fds, flags);
10187 if (res != 0)
10188 return posix_error();
10189 return Py_BuildValue("(ii)", fds[0], fds[1]);
10190 }
10191 #endif /* HAVE_PIPE2 */
10192
10193
10194 #ifdef HAVE_WRITEV
10195 /*[clinic input]
10196 os.writev -> Py_ssize_t
10197 fd: int
10198 buffers: object
10199 /
10200
10201 Iterate over buffers, and write the contents of each to a file descriptor.
10202
10203 Returns the total number of bytes written.
10204 buffers must be a sequence of bytes-like objects.
10205 [clinic start generated code]*/
10206
10207 static Py_ssize_t
os_writev_impl(PyObject * module,int fd,PyObject * buffers)10208 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
10209 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
10210 {
10211 Py_ssize_t cnt;
10212 Py_ssize_t result;
10213 int async_err = 0;
10214 struct iovec *iov;
10215 Py_buffer *buf;
10216
10217 if (!PySequence_Check(buffers)) {
10218 PyErr_SetString(PyExc_TypeError,
10219 "writev() arg 2 must be a sequence");
10220 return -1;
10221 }
10222 cnt = PySequence_Size(buffers);
10223 if (cnt < 0)
10224 return -1;
10225
10226 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10227 return -1;
10228 }
10229
10230 do {
10231 Py_BEGIN_ALLOW_THREADS
10232 result = writev(fd, iov, cnt);
10233 Py_END_ALLOW_THREADS
10234 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10235
10236 iov_cleanup(iov, buf, cnt);
10237 if (result < 0 && !async_err)
10238 posix_error();
10239
10240 return result;
10241 }
10242 #endif /* HAVE_WRITEV */
10243
10244
10245 #ifdef HAVE_PWRITE
10246 /*[clinic input]
10247 os.pwrite -> Py_ssize_t
10248
10249 fd: int
10250 buffer: Py_buffer
10251 offset: Py_off_t
10252 /
10253
10254 Write bytes to a file descriptor starting at a particular offset.
10255
10256 Write buffer to fd, starting at offset bytes from the beginning of
10257 the file. Returns the number of bytes writte. Does not change the
10258 current file offset.
10259 [clinic start generated code]*/
10260
10261 static Py_ssize_t
os_pwrite_impl(PyObject * module,int fd,Py_buffer * buffer,Py_off_t offset)10262 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
10263 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
10264 {
10265 Py_ssize_t size;
10266 int async_err = 0;
10267
10268 do {
10269 Py_BEGIN_ALLOW_THREADS
10270 _Py_BEGIN_SUPPRESS_IPH
10271 size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
10272 _Py_END_SUPPRESS_IPH
10273 Py_END_ALLOW_THREADS
10274 } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10275
10276 if (size < 0 && !async_err)
10277 posix_error();
10278 return size;
10279 }
10280 #endif /* HAVE_PWRITE */
10281
10282 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
10283 /*[clinic input]
10284 os.pwritev -> Py_ssize_t
10285
10286 fd: int
10287 buffers: object
10288 offset: Py_off_t
10289 flags: int = 0
10290 /
10291
10292 Writes the contents of bytes-like objects to a file descriptor at a given offset.
10293
10294 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
10295 of bytes-like objects. Buffers are processed in array order. Entire contents of first
10296 buffer is written before proceeding to second, and so on. The operating system may
10297 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
10298 This function writes the contents of each object to the file descriptor and returns
10299 the total number of bytes written.
10300
10301 The flags argument contains a bitwise OR of zero or more of the following flags:
10302
10303 - RWF_DSYNC
10304 - RWF_SYNC
10305 - RWF_APPEND
10306
10307 Using non-zero flags requires Linux 4.7 or newer.
10308 [clinic start generated code]*/
10309
10310 static Py_ssize_t
os_pwritev_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)10311 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
10312 int flags)
10313 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
10314 {
10315 Py_ssize_t cnt;
10316 Py_ssize_t result;
10317 int async_err = 0;
10318 struct iovec *iov;
10319 Py_buffer *buf;
10320
10321 if (!PySequence_Check(buffers)) {
10322 PyErr_SetString(PyExc_TypeError,
10323 "pwritev() arg 2 must be a sequence");
10324 return -1;
10325 }
10326
10327 cnt = PySequence_Size(buffers);
10328 if (cnt < 0) {
10329 return -1;
10330 }
10331
10332 #ifndef HAVE_PWRITEV2
10333 if(flags != 0) {
10334 argument_unavailable_error("pwritev2", "flags");
10335 return -1;
10336 }
10337 #endif
10338
10339 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10340 return -1;
10341 }
10342 #ifdef HAVE_PWRITEV2
10343 do {
10344 Py_BEGIN_ALLOW_THREADS
10345 _Py_BEGIN_SUPPRESS_IPH
10346 result = pwritev2(fd, iov, cnt, offset, flags);
10347 _Py_END_SUPPRESS_IPH
10348 Py_END_ALLOW_THREADS
10349 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10350 #else
10351
10352 #ifdef __APPLE__
10353 /* This entire function will be removed from the module dict when the API
10354 * is not available.
10355 */
10356 #pragma clang diagnostic push
10357 #pragma clang diagnostic ignored "-Wunguarded-availability"
10358 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
10359 #endif
10360 do {
10361 Py_BEGIN_ALLOW_THREADS
10362 _Py_BEGIN_SUPPRESS_IPH
10363 result = pwritev(fd, iov, cnt, offset);
10364 _Py_END_SUPPRESS_IPH
10365 Py_END_ALLOW_THREADS
10366 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10367
10368 #ifdef __APPLE__
10369 #pragma clang diagnostic pop
10370 #endif
10371
10372 #endif
10373
10374 iov_cleanup(iov, buf, cnt);
10375 if (result < 0) {
10376 if (!async_err) {
10377 posix_error();
10378 }
10379 return -1;
10380 }
10381
10382 return result;
10383 }
10384 #endif /* HAVE_PWRITEV */
10385
10386 #ifdef HAVE_COPY_FILE_RANGE
10387 /*[clinic input]
10388
10389 os.copy_file_range
10390 src: int
10391 Source file descriptor.
10392 dst: int
10393 Destination file descriptor.
10394 count: Py_ssize_t
10395 Number of bytes to copy.
10396 offset_src: object = None
10397 Starting offset in src.
10398 offset_dst: object = None
10399 Starting offset in dst.
10400
10401 Copy count bytes from one file descriptor to another.
10402
10403 If offset_src is None, then src is read from the current position;
10404 respectively for offset_dst.
10405 [clinic start generated code]*/
10406
10407 static PyObject *
os_copy_file_range_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst)10408 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10409 PyObject *offset_src, PyObject *offset_dst)
10410 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
10411 {
10412 off_t offset_src_val, offset_dst_val;
10413 off_t *p_offset_src = NULL;
10414 off_t *p_offset_dst = NULL;
10415 Py_ssize_t ret;
10416 int async_err = 0;
10417 /* The flags argument is provided to allow
10418 * for future extensions and currently must be to 0. */
10419 int flags = 0;
10420
10421
10422 if (count < 0) {
10423 PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10424 return NULL;
10425 }
10426
10427 if (offset_src != Py_None) {
10428 if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10429 return NULL;
10430 }
10431 p_offset_src = &offset_src_val;
10432 }
10433
10434 if (offset_dst != Py_None) {
10435 if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10436 return NULL;
10437 }
10438 p_offset_dst = &offset_dst_val;
10439 }
10440
10441 do {
10442 Py_BEGIN_ALLOW_THREADS
10443 ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
10444 Py_END_ALLOW_THREADS
10445 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10446
10447 if (ret < 0) {
10448 return (!async_err) ? posix_error() : NULL;
10449 }
10450
10451 return PyLong_FromSsize_t(ret);
10452 }
10453 #endif /* HAVE_COPY_FILE_RANGE*/
10454
10455 #if (defined(HAVE_SPLICE) && !defined(_AIX))
10456 /*[clinic input]
10457
10458 os.splice
10459 src: int
10460 Source file descriptor.
10461 dst: int
10462 Destination file descriptor.
10463 count: Py_ssize_t
10464 Number of bytes to copy.
10465 offset_src: object = None
10466 Starting offset in src.
10467 offset_dst: object = None
10468 Starting offset in dst.
10469 flags: unsigned_int = 0
10470 Flags to modify the semantics of the call.
10471
10472 Transfer count bytes from one pipe to a descriptor or vice versa.
10473
10474 If offset_src is None, then src is read from the current position;
10475 respectively for offset_dst. The offset associated to the file
10476 descriptor that refers to a pipe must be None.
10477 [clinic start generated code]*/
10478
10479 static PyObject *
os_splice_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst,unsigned int flags)10480 os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10481 PyObject *offset_src, PyObject *offset_dst,
10482 unsigned int flags)
10483 /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
10484 {
10485 off_t offset_src_val, offset_dst_val;
10486 off_t *p_offset_src = NULL;
10487 off_t *p_offset_dst = NULL;
10488 Py_ssize_t ret;
10489 int async_err = 0;
10490
10491 if (count < 0) {
10492 PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10493 return NULL;
10494 }
10495
10496 if (offset_src != Py_None) {
10497 if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10498 return NULL;
10499 }
10500 p_offset_src = &offset_src_val;
10501 }
10502
10503 if (offset_dst != Py_None) {
10504 if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10505 return NULL;
10506 }
10507 p_offset_dst = &offset_dst_val;
10508 }
10509
10510 do {
10511 Py_BEGIN_ALLOW_THREADS
10512 ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
10513 Py_END_ALLOW_THREADS
10514 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10515
10516 if (ret < 0) {
10517 return (!async_err) ? posix_error() : NULL;
10518 }
10519
10520 return PyLong_FromSsize_t(ret);
10521 }
10522 #endif /* HAVE_SPLICE*/
10523
10524 #ifdef HAVE_MKFIFO
10525 /*[clinic input]
10526 os.mkfifo
10527
10528 path: path_t
10529 mode: int=0o666
10530 *
10531 dir_fd: dir_fd(requires='mkfifoat')=None
10532
10533 Create a "fifo" (a POSIX named pipe).
10534
10535 If dir_fd is not None, it should be a file descriptor open to a directory,
10536 and path should be relative; path will then be relative to that directory.
10537 dir_fd may not be implemented on your platform.
10538 If it is unavailable, using it will raise a NotImplementedError.
10539 [clinic start generated code]*/
10540
10541 static PyObject *
os_mkfifo_impl(PyObject * module,path_t * path,int mode,int dir_fd)10542 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
10543 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
10544 {
10545 int result;
10546 int async_err = 0;
10547
10548 do {
10549 Py_BEGIN_ALLOW_THREADS
10550 #ifdef HAVE_MKFIFOAT
10551 if (dir_fd != DEFAULT_DIR_FD)
10552 result = mkfifoat(dir_fd, path->narrow, mode);
10553 else
10554 #endif
10555 result = mkfifo(path->narrow, mode);
10556 Py_END_ALLOW_THREADS
10557 } while (result != 0 && errno == EINTR &&
10558 !(async_err = PyErr_CheckSignals()));
10559 if (result != 0)
10560 return (!async_err) ? posix_error() : NULL;
10561
10562 Py_RETURN_NONE;
10563 }
10564 #endif /* HAVE_MKFIFO */
10565
10566
10567 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
10568 /*[clinic input]
10569 os.mknod
10570
10571 path: path_t
10572 mode: int=0o600
10573 device: dev_t=0
10574 *
10575 dir_fd: dir_fd(requires='mknodat')=None
10576
10577 Create a node in the file system.
10578
10579 Create a node in the file system (file, device special file or named pipe)
10580 at path. mode specifies both the permissions to use and the
10581 type of node to be created, being combined (bitwise OR) with one of
10582 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,
10583 device defines the newly created device special file (probably using
10584 os.makedev()). Otherwise device is ignored.
10585
10586 If dir_fd is not None, it should be a file descriptor open to a directory,
10587 and path should be relative; path will then be relative to that directory.
10588 dir_fd may not be implemented on your platform.
10589 If it is unavailable, using it will raise a NotImplementedError.
10590 [clinic start generated code]*/
10591
10592 static PyObject *
os_mknod_impl(PyObject * module,path_t * path,int mode,dev_t device,int dir_fd)10593 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
10594 int dir_fd)
10595 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
10596 {
10597 int result;
10598 int async_err = 0;
10599
10600 do {
10601 Py_BEGIN_ALLOW_THREADS
10602 #ifdef HAVE_MKNODAT
10603 if (dir_fd != DEFAULT_DIR_FD)
10604 result = mknodat(dir_fd, path->narrow, mode, device);
10605 else
10606 #endif
10607 result = mknod(path->narrow, mode, device);
10608 Py_END_ALLOW_THREADS
10609 } while (result != 0 && errno == EINTR &&
10610 !(async_err = PyErr_CheckSignals()));
10611 if (result != 0)
10612 return (!async_err) ? posix_error() : NULL;
10613
10614 Py_RETURN_NONE;
10615 }
10616 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
10617
10618
10619 #ifdef HAVE_DEVICE_MACROS
10620 /*[clinic input]
10621 os.major -> unsigned_int
10622
10623 device: dev_t
10624 /
10625
10626 Extracts a device major number from a raw device number.
10627 [clinic start generated code]*/
10628
10629 static unsigned int
os_major_impl(PyObject * module,dev_t device)10630 os_major_impl(PyObject *module, dev_t device)
10631 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
10632 {
10633 return major(device);
10634 }
10635
10636
10637 /*[clinic input]
10638 os.minor -> unsigned_int
10639
10640 device: dev_t
10641 /
10642
10643 Extracts a device minor number from a raw device number.
10644 [clinic start generated code]*/
10645
10646 static unsigned int
os_minor_impl(PyObject * module,dev_t device)10647 os_minor_impl(PyObject *module, dev_t device)
10648 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10649 {
10650 return minor(device);
10651 }
10652
10653
10654 /*[clinic input]
10655 os.makedev -> dev_t
10656
10657 major: int
10658 minor: int
10659 /
10660
10661 Composes a raw device number from the major and minor device numbers.
10662 [clinic start generated code]*/
10663
10664 static dev_t
os_makedev_impl(PyObject * module,int major,int minor)10665 os_makedev_impl(PyObject *module, int major, int minor)
10666 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10667 {
10668 return makedev(major, minor);
10669 }
10670 #endif /* HAVE_DEVICE_MACROS */
10671
10672
10673 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10674 /*[clinic input]
10675 os.ftruncate
10676
10677 fd: int
10678 length: Py_off_t
10679 /
10680
10681 Truncate a file, specified by file descriptor, to a specific length.
10682 [clinic start generated code]*/
10683
10684 static PyObject *
os_ftruncate_impl(PyObject * module,int fd,Py_off_t length)10685 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10686 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10687 {
10688 int result;
10689 int async_err = 0;
10690
10691 if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10692 return NULL;
10693 }
10694
10695 do {
10696 Py_BEGIN_ALLOW_THREADS
10697 _Py_BEGIN_SUPPRESS_IPH
10698 #ifdef MS_WINDOWS
10699 result = _chsize_s(fd, length);
10700 #else
10701 result = ftruncate(fd, length);
10702 #endif
10703 _Py_END_SUPPRESS_IPH
10704 Py_END_ALLOW_THREADS
10705 } while (result != 0 && errno == EINTR &&
10706 !(async_err = PyErr_CheckSignals()));
10707 if (result != 0)
10708 return (!async_err) ? posix_error() : NULL;
10709 Py_RETURN_NONE;
10710 }
10711 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10712
10713
10714 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10715 /*[clinic input]
10716 os.truncate
10717 path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10718 length: Py_off_t
10719
10720 Truncate a file, specified by path, to a specific length.
10721
10722 On some platforms, path may also be specified as an open file descriptor.
10723 If this functionality is unavailable, using it raises an exception.
10724 [clinic start generated code]*/
10725
10726 static PyObject *
os_truncate_impl(PyObject * module,path_t * path,Py_off_t length)10727 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10728 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10729 {
10730 int result;
10731 #ifdef MS_WINDOWS
10732 int fd;
10733 #endif
10734
10735 if (path->fd != -1)
10736 return os_ftruncate_impl(module, path->fd, length);
10737
10738 if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10739 return NULL;
10740 }
10741
10742 Py_BEGIN_ALLOW_THREADS
10743 _Py_BEGIN_SUPPRESS_IPH
10744 #ifdef MS_WINDOWS
10745 fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10746 if (fd < 0)
10747 result = -1;
10748 else {
10749 result = _chsize_s(fd, length);
10750 close(fd);
10751 if (result < 0)
10752 errno = result;
10753 }
10754 #else
10755 result = truncate(path->narrow, length);
10756 #endif
10757 _Py_END_SUPPRESS_IPH
10758 Py_END_ALLOW_THREADS
10759 if (result < 0)
10760 return posix_path_error(path);
10761
10762 Py_RETURN_NONE;
10763 }
10764 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10765
10766
10767 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10768 and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10769 defined, which is the case in Python on AIX. AIX bug report:
10770 http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10771 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10772 # define POSIX_FADVISE_AIX_BUG
10773 #endif
10774
10775
10776 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10777 /*[clinic input]
10778 os.posix_fallocate
10779
10780 fd: int
10781 offset: Py_off_t
10782 length: Py_off_t
10783 /
10784
10785 Ensure a file has allocated at least a particular number of bytes on disk.
10786
10787 Ensure that the file specified by fd encompasses a range of bytes
10788 starting at offset bytes from the beginning and continuing for length bytes.
10789 [clinic start generated code]*/
10790
10791 static PyObject *
os_posix_fallocate_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length)10792 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10793 Py_off_t length)
10794 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10795 {
10796 int result;
10797 int async_err = 0;
10798
10799 do {
10800 Py_BEGIN_ALLOW_THREADS
10801 result = posix_fallocate(fd, offset, length);
10802 Py_END_ALLOW_THREADS
10803 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10804
10805 if (result == 0)
10806 Py_RETURN_NONE;
10807
10808 if (async_err)
10809 return NULL;
10810
10811 errno = result;
10812 return posix_error();
10813 }
10814 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
10815
10816
10817 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
10818 /*[clinic input]
10819 os.posix_fadvise
10820
10821 fd: int
10822 offset: Py_off_t
10823 length: Py_off_t
10824 advice: int
10825 /
10826
10827 Announce an intention to access data in a specific pattern.
10828
10829 Announce an intention to access data in a specific pattern, thus allowing
10830 the kernel to make optimizations.
10831 The advice applies to the region of the file specified by fd starting at
10832 offset and continuing for length bytes.
10833 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
10834 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
10835 POSIX_FADV_DONTNEED.
10836 [clinic start generated code]*/
10837
10838 static PyObject *
os_posix_fadvise_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length,int advice)10839 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
10840 Py_off_t length, int advice)
10841 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
10842 {
10843 int result;
10844 int async_err = 0;
10845
10846 do {
10847 Py_BEGIN_ALLOW_THREADS
10848 result = posix_fadvise(fd, offset, length, advice);
10849 Py_END_ALLOW_THREADS
10850 } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10851
10852 if (result == 0)
10853 Py_RETURN_NONE;
10854
10855 if (async_err)
10856 return NULL;
10857
10858 errno = result;
10859 return posix_error();
10860 }
10861 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
10862
10863
10864 #ifdef MS_WINDOWS
10865 static PyObject*
win32_putenv(PyObject * name,PyObject * value)10866 win32_putenv(PyObject *name, PyObject *value)
10867 {
10868 /* Search from index 1 because on Windows starting '=' is allowed for
10869 defining hidden environment variables. */
10870 if (PyUnicode_GET_LENGTH(name) == 0 ||
10871 PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
10872 {
10873 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10874 return NULL;
10875 }
10876 PyObject *unicode;
10877 if (value != NULL) {
10878 unicode = PyUnicode_FromFormat("%U=%U", name, value);
10879 }
10880 else {
10881 unicode = PyUnicode_FromFormat("%U=", name);
10882 }
10883 if (unicode == NULL) {
10884 return NULL;
10885 }
10886
10887 Py_ssize_t size;
10888 /* PyUnicode_AsWideCharString() rejects embedded null characters */
10889 wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
10890 Py_DECREF(unicode);
10891
10892 if (env == NULL) {
10893 return NULL;
10894 }
10895 if (size > _MAX_ENV) {
10896 PyErr_Format(PyExc_ValueError,
10897 "the environment variable is longer than %u characters",
10898 _MAX_ENV);
10899 PyMem_Free(env);
10900 return NULL;
10901 }
10902
10903 /* _wputenv() and SetEnvironmentVariableW() update the environment in the
10904 Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
10905 and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
10906
10907 Prefer _wputenv() to be compatible with C libraries using CRT
10908 variables and CRT functions using these variables (ex: getenv()). */
10909 int err = _wputenv(env);
10910 PyMem_Free(env);
10911
10912 if (err) {
10913 posix_error();
10914 return NULL;
10915 }
10916
10917 Py_RETURN_NONE;
10918 }
10919 #endif
10920
10921
10922 #ifdef MS_WINDOWS
10923 /*[clinic input]
10924 os.putenv
10925
10926 name: unicode
10927 value: unicode
10928 /
10929
10930 Change or add an environment variable.
10931 [clinic start generated code]*/
10932
10933 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10934 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10935 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
10936 {
10937 if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10938 return NULL;
10939 }
10940 return win32_putenv(name, value);
10941 }
10942 #else
10943 /*[clinic input]
10944 os.putenv
10945
10946 name: FSConverter
10947 value: FSConverter
10948 /
10949
10950 Change or add an environment variable.
10951 [clinic start generated code]*/
10952
10953 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10954 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10955 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
10956 {
10957 const char *name_string = PyBytes_AS_STRING(name);
10958 const char *value_string = PyBytes_AS_STRING(value);
10959
10960 if (strchr(name_string, '=') != NULL) {
10961 PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10962 return NULL;
10963 }
10964
10965 if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10966 return NULL;
10967 }
10968
10969 if (setenv(name_string, value_string, 1)) {
10970 return posix_error();
10971 }
10972 Py_RETURN_NONE;
10973 }
10974 #endif /* !defined(MS_WINDOWS) */
10975
10976
10977 #ifdef MS_WINDOWS
10978 /*[clinic input]
10979 os.unsetenv
10980 name: unicode
10981 /
10982
10983 Delete an environment variable.
10984 [clinic start generated code]*/
10985
10986 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)10987 os_unsetenv_impl(PyObject *module, PyObject *name)
10988 /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
10989 {
10990 if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
10991 return NULL;
10992 }
10993 return win32_putenv(name, NULL);
10994 }
10995 #else
10996 /*[clinic input]
10997 os.unsetenv
10998 name: FSConverter
10999 /
11000
11001 Delete an environment variable.
11002 [clinic start generated code]*/
11003
11004 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)11005 os_unsetenv_impl(PyObject *module, PyObject *name)
11006 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
11007 {
11008 if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11009 return NULL;
11010 }
11011 #ifdef HAVE_BROKEN_UNSETENV
11012 unsetenv(PyBytes_AS_STRING(name));
11013 #else
11014 int err = unsetenv(PyBytes_AS_STRING(name));
11015 if (err) {
11016 return posix_error();
11017 }
11018 #endif
11019
11020 Py_RETURN_NONE;
11021 }
11022 #endif /* !MS_WINDOWS */
11023
11024
11025 /*[clinic input]
11026 os.strerror
11027
11028 code: int
11029 /
11030
11031 Translate an error code to a message string.
11032 [clinic start generated code]*/
11033
11034 static PyObject *
os_strerror_impl(PyObject * module,int code)11035 os_strerror_impl(PyObject *module, int code)
11036 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
11037 {
11038 char *message = strerror(code);
11039 if (message == NULL) {
11040 PyErr_SetString(PyExc_ValueError,
11041 "strerror() argument out of range");
11042 return NULL;
11043 }
11044 return PyUnicode_DecodeLocale(message, "surrogateescape");
11045 }
11046
11047
11048 #ifdef HAVE_SYS_WAIT_H
11049 #ifdef WCOREDUMP
11050 /*[clinic input]
11051 os.WCOREDUMP -> bool
11052
11053 status: int
11054 /
11055
11056 Return True if the process returning status was dumped to a core file.
11057 [clinic start generated code]*/
11058
11059 static int
os_WCOREDUMP_impl(PyObject * module,int status)11060 os_WCOREDUMP_impl(PyObject *module, int status)
11061 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
11062 {
11063 WAIT_TYPE wait_status;
11064 WAIT_STATUS_INT(wait_status) = status;
11065 return WCOREDUMP(wait_status);
11066 }
11067 #endif /* WCOREDUMP */
11068
11069
11070 #ifdef WIFCONTINUED
11071 /*[clinic input]
11072 os.WIFCONTINUED -> bool
11073
11074 status: int
11075
11076 Return True if a particular process was continued from a job control stop.
11077
11078 Return True if the process returning status was continued from a
11079 job control stop.
11080 [clinic start generated code]*/
11081
11082 static int
os_WIFCONTINUED_impl(PyObject * module,int status)11083 os_WIFCONTINUED_impl(PyObject *module, int status)
11084 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
11085 {
11086 WAIT_TYPE wait_status;
11087 WAIT_STATUS_INT(wait_status) = status;
11088 return WIFCONTINUED(wait_status);
11089 }
11090 #endif /* WIFCONTINUED */
11091
11092
11093 #ifdef WIFSTOPPED
11094 /*[clinic input]
11095 os.WIFSTOPPED -> bool
11096
11097 status: int
11098
11099 Return True if the process returning status was stopped.
11100 [clinic start generated code]*/
11101
11102 static int
os_WIFSTOPPED_impl(PyObject * module,int status)11103 os_WIFSTOPPED_impl(PyObject *module, int status)
11104 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
11105 {
11106 WAIT_TYPE wait_status;
11107 WAIT_STATUS_INT(wait_status) = status;
11108 return WIFSTOPPED(wait_status);
11109 }
11110 #endif /* WIFSTOPPED */
11111
11112
11113 #ifdef WIFSIGNALED
11114 /*[clinic input]
11115 os.WIFSIGNALED -> bool
11116
11117 status: int
11118
11119 Return True if the process returning status was terminated by a signal.
11120 [clinic start generated code]*/
11121
11122 static int
os_WIFSIGNALED_impl(PyObject * module,int status)11123 os_WIFSIGNALED_impl(PyObject *module, int status)
11124 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
11125 {
11126 WAIT_TYPE wait_status;
11127 WAIT_STATUS_INT(wait_status) = status;
11128 return WIFSIGNALED(wait_status);
11129 }
11130 #endif /* WIFSIGNALED */
11131
11132
11133 #ifdef WIFEXITED
11134 /*[clinic input]
11135 os.WIFEXITED -> bool
11136
11137 status: int
11138
11139 Return True if the process returning status exited via the exit() system call.
11140 [clinic start generated code]*/
11141
11142 static int
os_WIFEXITED_impl(PyObject * module,int status)11143 os_WIFEXITED_impl(PyObject *module, int status)
11144 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
11145 {
11146 WAIT_TYPE wait_status;
11147 WAIT_STATUS_INT(wait_status) = status;
11148 return WIFEXITED(wait_status);
11149 }
11150 #endif /* WIFEXITED */
11151
11152
11153 #ifdef WEXITSTATUS
11154 /*[clinic input]
11155 os.WEXITSTATUS -> int
11156
11157 status: int
11158
11159 Return the process return code from status.
11160 [clinic start generated code]*/
11161
11162 static int
os_WEXITSTATUS_impl(PyObject * module,int status)11163 os_WEXITSTATUS_impl(PyObject *module, int status)
11164 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
11165 {
11166 WAIT_TYPE wait_status;
11167 WAIT_STATUS_INT(wait_status) = status;
11168 return WEXITSTATUS(wait_status);
11169 }
11170 #endif /* WEXITSTATUS */
11171
11172
11173 #ifdef WTERMSIG
11174 /*[clinic input]
11175 os.WTERMSIG -> int
11176
11177 status: int
11178
11179 Return the signal that terminated the process that provided the status value.
11180 [clinic start generated code]*/
11181
11182 static int
os_WTERMSIG_impl(PyObject * module,int status)11183 os_WTERMSIG_impl(PyObject *module, int status)
11184 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
11185 {
11186 WAIT_TYPE wait_status;
11187 WAIT_STATUS_INT(wait_status) = status;
11188 return WTERMSIG(wait_status);
11189 }
11190 #endif /* WTERMSIG */
11191
11192
11193 #ifdef WSTOPSIG
11194 /*[clinic input]
11195 os.WSTOPSIG -> int
11196
11197 status: int
11198
11199 Return the signal that stopped the process that provided the status value.
11200 [clinic start generated code]*/
11201
11202 static int
os_WSTOPSIG_impl(PyObject * module,int status)11203 os_WSTOPSIG_impl(PyObject *module, int status)
11204 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
11205 {
11206 WAIT_TYPE wait_status;
11207 WAIT_STATUS_INT(wait_status) = status;
11208 return WSTOPSIG(wait_status);
11209 }
11210 #endif /* WSTOPSIG */
11211 #endif /* HAVE_SYS_WAIT_H */
11212
11213
11214 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
11215 #ifdef _SCO_DS
11216 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
11217 needed definitions in sys/statvfs.h */
11218 #define _SVID3
11219 #endif
11220 #include <sys/statvfs.h>
11221
11222 static PyObject*
_pystatvfs_fromstructstatvfs(PyObject * module,struct statvfs st)11223 _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
11224 PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
11225 PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
11226 if (v == NULL)
11227 return NULL;
11228
11229 #if !defined(HAVE_LARGEFILE_SUPPORT)
11230 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11231 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11232 PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
11233 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
11234 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
11235 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
11236 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
11237 PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
11238 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11239 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11240 #else
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,
11244 PyLong_FromLongLong((long long) st.f_blocks));
11245 PyStructSequence_SET_ITEM(v, 3,
11246 PyLong_FromLongLong((long long) st.f_bfree));
11247 PyStructSequence_SET_ITEM(v, 4,
11248 PyLong_FromLongLong((long long) st.f_bavail));
11249 PyStructSequence_SET_ITEM(v, 5,
11250 PyLong_FromLongLong((long long) st.f_files));
11251 PyStructSequence_SET_ITEM(v, 6,
11252 PyLong_FromLongLong((long long) st.f_ffree));
11253 PyStructSequence_SET_ITEM(v, 7,
11254 PyLong_FromLongLong((long long) st.f_favail));
11255 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11256 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11257 #endif
11258 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
11259 * (issue #32390). */
11260 #if defined(_AIX) && defined(_ALL_SOURCE)
11261 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
11262 #else
11263 PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
11264 #endif
11265 if (PyErr_Occurred()) {
11266 Py_DECREF(v);
11267 return NULL;
11268 }
11269
11270 return v;
11271 }
11272
11273
11274 /*[clinic input]
11275 os.fstatvfs
11276 fd: int
11277 /
11278
11279 Perform an fstatvfs system call on the given fd.
11280
11281 Equivalent to statvfs(fd).
11282 [clinic start generated code]*/
11283
11284 static PyObject *
os_fstatvfs_impl(PyObject * module,int fd)11285 os_fstatvfs_impl(PyObject *module, int fd)
11286 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
11287 {
11288 int result;
11289 int async_err = 0;
11290 struct statvfs st;
11291
11292 do {
11293 Py_BEGIN_ALLOW_THREADS
11294 result = fstatvfs(fd, &st);
11295 Py_END_ALLOW_THREADS
11296 } while (result != 0 && errno == EINTR &&
11297 !(async_err = PyErr_CheckSignals()));
11298 if (result != 0)
11299 return (!async_err) ? posix_error() : NULL;
11300
11301 return _pystatvfs_fromstructstatvfs(module, st);
11302 }
11303 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
11304
11305
11306 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
11307 #include <sys/statvfs.h>
11308 /*[clinic input]
11309 os.statvfs
11310
11311 path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
11312
11313 Perform a statvfs system call on the given path.
11314
11315 path may always be specified as a string.
11316 On some platforms, path may also be specified as an open file descriptor.
11317 If this functionality is unavailable, using it raises an exception.
11318 [clinic start generated code]*/
11319
11320 static PyObject *
os_statvfs_impl(PyObject * module,path_t * path)11321 os_statvfs_impl(PyObject *module, path_t *path)
11322 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
11323 {
11324 int result;
11325 struct statvfs st;
11326
11327 Py_BEGIN_ALLOW_THREADS
11328 #ifdef HAVE_FSTATVFS
11329 if (path->fd != -1) {
11330 result = fstatvfs(path->fd, &st);
11331 }
11332 else
11333 #endif
11334 result = statvfs(path->narrow, &st);
11335 Py_END_ALLOW_THREADS
11336
11337 if (result) {
11338 return path_error(path);
11339 }
11340
11341 return _pystatvfs_fromstructstatvfs(module, st);
11342 }
11343 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
11344
11345
11346 #ifdef MS_WINDOWS
11347 /*[clinic input]
11348 os._getdiskusage
11349
11350 path: path_t
11351
11352 Return disk usage statistics about the given path as a (total, free) tuple.
11353 [clinic start generated code]*/
11354
11355 static PyObject *
os__getdiskusage_impl(PyObject * module,path_t * path)11356 os__getdiskusage_impl(PyObject *module, path_t *path)
11357 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
11358 {
11359 BOOL retval;
11360 ULARGE_INTEGER _, total, free;
11361 DWORD err = 0;
11362
11363 Py_BEGIN_ALLOW_THREADS
11364 retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
11365 Py_END_ALLOW_THREADS
11366 if (retval == 0) {
11367 if (GetLastError() == ERROR_DIRECTORY) {
11368 wchar_t *dir_path = NULL;
11369
11370 dir_path = PyMem_New(wchar_t, path->length + 1);
11371 if (dir_path == NULL) {
11372 return PyErr_NoMemory();
11373 }
11374
11375 wcscpy_s(dir_path, path->length + 1, path->wide);
11376
11377 if (_dirnameW(dir_path) != -1) {
11378 Py_BEGIN_ALLOW_THREADS
11379 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
11380 Py_END_ALLOW_THREADS
11381 }
11382 /* Record the last error in case it's modified by PyMem_Free. */
11383 err = GetLastError();
11384 PyMem_Free(dir_path);
11385 if (retval) {
11386 goto success;
11387 }
11388 }
11389 return PyErr_SetFromWindowsErr(err);
11390 }
11391
11392 success:
11393 return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
11394 }
11395 #endif /* MS_WINDOWS */
11396
11397
11398 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
11399 * It maps strings representing configuration variable names to
11400 * integer values, allowing those functions to be called with the
11401 * magic names instead of polluting the module's namespace with tons of
11402 * rarely-used constants. There are three separate tables that use
11403 * these definitions.
11404 *
11405 * This code is always included, even if none of the interfaces that
11406 * need it are included. The #if hackery needed to avoid it would be
11407 * sufficiently pervasive that it's not worth the loss of readability.
11408 */
11409 struct constdef {
11410 const char *name;
11411 int value;
11412 };
11413
11414 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)11415 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
11416 size_t tablesize)
11417 {
11418 if (PyLong_Check(arg)) {
11419 int value = _PyLong_AsInt(arg);
11420 if (value == -1 && PyErr_Occurred())
11421 return 0;
11422 *valuep = value;
11423 return 1;
11424 }
11425 else {
11426 /* look up the value in the table using a binary search */
11427 size_t lo = 0;
11428 size_t mid;
11429 size_t hi = tablesize;
11430 int cmp;
11431 const char *confname;
11432 if (!PyUnicode_Check(arg)) {
11433 PyErr_SetString(PyExc_TypeError,
11434 "configuration names must be strings or integers");
11435 return 0;
11436 }
11437 confname = PyUnicode_AsUTF8(arg);
11438 if (confname == NULL)
11439 return 0;
11440 while (lo < hi) {
11441 mid = (lo + hi) / 2;
11442 cmp = strcmp(confname, table[mid].name);
11443 if (cmp < 0)
11444 hi = mid;
11445 else if (cmp > 0)
11446 lo = mid + 1;
11447 else {
11448 *valuep = table[mid].value;
11449 return 1;
11450 }
11451 }
11452 PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
11453 return 0;
11454 }
11455 }
11456
11457
11458 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11459 static struct constdef posix_constants_pathconf[] = {
11460 #ifdef _PC_ABI_AIO_XFER_MAX
11461 {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
11462 #endif
11463 #ifdef _PC_ABI_ASYNC_IO
11464 {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
11465 #endif
11466 #ifdef _PC_ASYNC_IO
11467 {"PC_ASYNC_IO", _PC_ASYNC_IO},
11468 #endif
11469 #ifdef _PC_CHOWN_RESTRICTED
11470 {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
11471 #endif
11472 #ifdef _PC_FILESIZEBITS
11473 {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
11474 #endif
11475 #ifdef _PC_LAST
11476 {"PC_LAST", _PC_LAST},
11477 #endif
11478 #ifdef _PC_LINK_MAX
11479 {"PC_LINK_MAX", _PC_LINK_MAX},
11480 #endif
11481 #ifdef _PC_MAX_CANON
11482 {"PC_MAX_CANON", _PC_MAX_CANON},
11483 #endif
11484 #ifdef _PC_MAX_INPUT
11485 {"PC_MAX_INPUT", _PC_MAX_INPUT},
11486 #endif
11487 #ifdef _PC_NAME_MAX
11488 {"PC_NAME_MAX", _PC_NAME_MAX},
11489 #endif
11490 #ifdef _PC_NO_TRUNC
11491 {"PC_NO_TRUNC", _PC_NO_TRUNC},
11492 #endif
11493 #ifdef _PC_PATH_MAX
11494 {"PC_PATH_MAX", _PC_PATH_MAX},
11495 #endif
11496 #ifdef _PC_PIPE_BUF
11497 {"PC_PIPE_BUF", _PC_PIPE_BUF},
11498 #endif
11499 #ifdef _PC_PRIO_IO
11500 {"PC_PRIO_IO", _PC_PRIO_IO},
11501 #endif
11502 #ifdef _PC_SOCK_MAXBUF
11503 {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
11504 #endif
11505 #ifdef _PC_SYNC_IO
11506 {"PC_SYNC_IO", _PC_SYNC_IO},
11507 #endif
11508 #ifdef _PC_VDISABLE
11509 {"PC_VDISABLE", _PC_VDISABLE},
11510 #endif
11511 #ifdef _PC_ACL_ENABLED
11512 {"PC_ACL_ENABLED", _PC_ACL_ENABLED},
11513 #endif
11514 #ifdef _PC_MIN_HOLE_SIZE
11515 {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE},
11516 #endif
11517 #ifdef _PC_ALLOC_SIZE_MIN
11518 {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN},
11519 #endif
11520 #ifdef _PC_REC_INCR_XFER_SIZE
11521 {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE},
11522 #endif
11523 #ifdef _PC_REC_MAX_XFER_SIZE
11524 {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE},
11525 #endif
11526 #ifdef _PC_REC_MIN_XFER_SIZE
11527 {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE},
11528 #endif
11529 #ifdef _PC_REC_XFER_ALIGN
11530 {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN},
11531 #endif
11532 #ifdef _PC_SYMLINK_MAX
11533 {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX},
11534 #endif
11535 #ifdef _PC_XATTR_ENABLED
11536 {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED},
11537 #endif
11538 #ifdef _PC_XATTR_EXISTS
11539 {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
11540 #endif
11541 #ifdef _PC_TIMESTAMP_RESOLUTION
11542 {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
11543 #endif
11544 };
11545
11546 static int
conv_path_confname(PyObject * arg,int * valuep)11547 conv_path_confname(PyObject *arg, int *valuep)
11548 {
11549 return conv_confname(arg, valuep, posix_constants_pathconf,
11550 sizeof(posix_constants_pathconf)
11551 / sizeof(struct constdef));
11552 }
11553 #endif
11554
11555
11556 #ifdef HAVE_FPATHCONF
11557 /*[clinic input]
11558 os.fpathconf -> long
11559
11560 fd: fildes
11561 name: path_confname
11562 /
11563
11564 Return the configuration limit name for the file descriptor fd.
11565
11566 If there is no limit, return -1.
11567 [clinic start generated code]*/
11568
11569 static long
os_fpathconf_impl(PyObject * module,int fd,int name)11570 os_fpathconf_impl(PyObject *module, int fd, int name)
11571 /*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
11572 {
11573 long limit;
11574
11575 errno = 0;
11576 limit = fpathconf(fd, name);
11577 if (limit == -1 && errno != 0)
11578 posix_error();
11579
11580 return limit;
11581 }
11582 #endif /* HAVE_FPATHCONF */
11583
11584
11585 #ifdef HAVE_PATHCONF
11586 /*[clinic input]
11587 os.pathconf -> long
11588 path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
11589 name: path_confname
11590
11591 Return the configuration limit name for the file or directory path.
11592
11593 If there is no limit, return -1.
11594 On some platforms, path may also be specified as an open file descriptor.
11595 If this functionality is unavailable, using it raises an exception.
11596 [clinic start generated code]*/
11597
11598 static long
os_pathconf_impl(PyObject * module,path_t * path,int name)11599 os_pathconf_impl(PyObject *module, path_t *path, int name)
11600 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
11601 {
11602 long limit;
11603
11604 errno = 0;
11605 #ifdef HAVE_FPATHCONF
11606 if (path->fd != -1)
11607 limit = fpathconf(path->fd, name);
11608 else
11609 #endif
11610 limit = pathconf(path->narrow, name);
11611 if (limit == -1 && errno != 0) {
11612 if (errno == EINVAL)
11613 /* could be a path or name problem */
11614 posix_error();
11615 else
11616 path_error(path);
11617 }
11618
11619 return limit;
11620 }
11621 #endif /* HAVE_PATHCONF */
11622
11623 #ifdef HAVE_CONFSTR
11624 static struct constdef posix_constants_confstr[] = {
11625 #ifdef _CS_ARCHITECTURE
11626 {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
11627 #endif
11628 #ifdef _CS_GNU_LIBC_VERSION
11629 {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION},
11630 #endif
11631 #ifdef _CS_GNU_LIBPTHREAD_VERSION
11632 {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION},
11633 #endif
11634 #ifdef _CS_HOSTNAME
11635 {"CS_HOSTNAME", _CS_HOSTNAME},
11636 #endif
11637 #ifdef _CS_HW_PROVIDER
11638 {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
11639 #endif
11640 #ifdef _CS_HW_SERIAL
11641 {"CS_HW_SERIAL", _CS_HW_SERIAL},
11642 #endif
11643 #ifdef _CS_INITTAB_NAME
11644 {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11645 #endif
11646 #ifdef _CS_LFS64_CFLAGS
11647 {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11648 #endif
11649 #ifdef _CS_LFS64_LDFLAGS
11650 {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
11651 #endif
11652 #ifdef _CS_LFS64_LIBS
11653 {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
11654 #endif
11655 #ifdef _CS_LFS64_LINTFLAGS
11656 {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
11657 #endif
11658 #ifdef _CS_LFS_CFLAGS
11659 {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
11660 #endif
11661 #ifdef _CS_LFS_LDFLAGS
11662 {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
11663 #endif
11664 #ifdef _CS_LFS_LIBS
11665 {"CS_LFS_LIBS", _CS_LFS_LIBS},
11666 #endif
11667 #ifdef _CS_LFS_LINTFLAGS
11668 {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
11669 #endif
11670 #ifdef _CS_MACHINE
11671 {"CS_MACHINE", _CS_MACHINE},
11672 #endif
11673 #ifdef _CS_PATH
11674 {"CS_PATH", _CS_PATH},
11675 #endif
11676 #ifdef _CS_RELEASE
11677 {"CS_RELEASE", _CS_RELEASE},
11678 #endif
11679 #ifdef _CS_SRPC_DOMAIN
11680 {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
11681 #endif
11682 #ifdef _CS_SYSNAME
11683 {"CS_SYSNAME", _CS_SYSNAME},
11684 #endif
11685 #ifdef _CS_VERSION
11686 {"CS_VERSION", _CS_VERSION},
11687 #endif
11688 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11689 {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
11690 #endif
11691 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11692 {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
11693 #endif
11694 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11695 {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
11696 #endif
11697 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11698 {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11699 #endif
11700 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11701 {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11702 #endif
11703 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11704 {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11705 #endif
11706 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11707 {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
11708 #endif
11709 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11710 {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11711 #endif
11712 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11713 {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
11714 #endif
11715 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11716 {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
11717 #endif
11718 #ifdef _CS_XBS5_LP64_OFF64_LIBS
11719 {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11720 #endif
11721 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11722 {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
11723 #endif
11724 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11725 {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11726 #endif
11727 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11728 {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11729 #endif
11730 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11731 {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
11732 #endif
11733 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11734 {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11735 #endif
11736 #ifdef _MIPS_CS_AVAIL_PROCESSORS
11737 {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
11738 #endif
11739 #ifdef _MIPS_CS_BASE
11740 {"MIPS_CS_BASE", _MIPS_CS_BASE},
11741 #endif
11742 #ifdef _MIPS_CS_HOSTID
11743 {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
11744 #endif
11745 #ifdef _MIPS_CS_HW_NAME
11746 {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11747 #endif
11748 #ifdef _MIPS_CS_NUM_PROCESSORS
11749 {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
11750 #endif
11751 #ifdef _MIPS_CS_OSREL_MAJ
11752 {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
11753 #endif
11754 #ifdef _MIPS_CS_OSREL_MIN
11755 {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
11756 #endif
11757 #ifdef _MIPS_CS_OSREL_PATCH
11758 {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
11759 #endif
11760 #ifdef _MIPS_CS_OS_NAME
11761 {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11762 #endif
11763 #ifdef _MIPS_CS_OS_PROVIDER
11764 {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
11765 #endif
11766 #ifdef _MIPS_CS_PROCESSORS
11767 {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
11768 #endif
11769 #ifdef _MIPS_CS_SERIAL
11770 {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
11771 #endif
11772 #ifdef _MIPS_CS_VENDOR
11773 {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
11774 #endif
11775 };
11776
11777 static int
conv_confstr_confname(PyObject * arg,int * valuep)11778 conv_confstr_confname(PyObject *arg, int *valuep)
11779 {
11780 return conv_confname(arg, valuep, posix_constants_confstr,
11781 sizeof(posix_constants_confstr)
11782 / sizeof(struct constdef));
11783 }
11784
11785
11786 /*[clinic input]
11787 os.confstr
11788
11789 name: confstr_confname
11790 /
11791
11792 Return a string-valued system configuration variable.
11793 [clinic start generated code]*/
11794
11795 static PyObject *
os_confstr_impl(PyObject * module,int name)11796 os_confstr_impl(PyObject *module, int name)
11797 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11798 {
11799 PyObject *result = NULL;
11800 char buffer[255];
11801 size_t len;
11802
11803 errno = 0;
11804 len = confstr(name, buffer, sizeof(buffer));
11805 if (len == 0) {
11806 if (errno) {
11807 posix_error();
11808 return NULL;
11809 }
11810 else {
11811 Py_RETURN_NONE;
11812 }
11813 }
11814
11815 if (len >= sizeof(buffer)) {
11816 size_t len2;
11817 char *buf = PyMem_Malloc(len);
11818 if (buf == NULL)
11819 return PyErr_NoMemory();
11820 len2 = confstr(name, buf, len);
11821 assert(len == len2);
11822 result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11823 PyMem_Free(buf);
11824 }
11825 else
11826 result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11827 return result;
11828 }
11829 #endif /* HAVE_CONFSTR */
11830
11831
11832 #ifdef HAVE_SYSCONF
11833 static struct constdef posix_constants_sysconf[] = {
11834 #ifdef _SC_2_CHAR_TERM
11835 {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
11836 #endif
11837 #ifdef _SC_2_C_BIND
11838 {"SC_2_C_BIND", _SC_2_C_BIND},
11839 #endif
11840 #ifdef _SC_2_C_DEV
11841 {"SC_2_C_DEV", _SC_2_C_DEV},
11842 #endif
11843 #ifdef _SC_2_C_VERSION
11844 {"SC_2_C_VERSION", _SC_2_C_VERSION},
11845 #endif
11846 #ifdef _SC_2_FORT_DEV
11847 {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
11848 #endif
11849 #ifdef _SC_2_FORT_RUN
11850 {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
11851 #endif
11852 #ifdef _SC_2_LOCALEDEF
11853 {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
11854 #endif
11855 #ifdef _SC_2_SW_DEV
11856 {"SC_2_SW_DEV", _SC_2_SW_DEV},
11857 #endif
11858 #ifdef _SC_2_UPE
11859 {"SC_2_UPE", _SC_2_UPE},
11860 #endif
11861 #ifdef _SC_2_VERSION
11862 {"SC_2_VERSION", _SC_2_VERSION},
11863 #endif
11864 #ifdef _SC_ABI_ASYNCHRONOUS_IO
11865 {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
11866 #endif
11867 #ifdef _SC_ACL
11868 {"SC_ACL", _SC_ACL},
11869 #endif
11870 #ifdef _SC_AIO_LISTIO_MAX
11871 {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
11872 #endif
11873 #ifdef _SC_AIO_MAX
11874 {"SC_AIO_MAX", _SC_AIO_MAX},
11875 #endif
11876 #ifdef _SC_AIO_PRIO_DELTA_MAX
11877 {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
11878 #endif
11879 #ifdef _SC_ARG_MAX
11880 {"SC_ARG_MAX", _SC_ARG_MAX},
11881 #endif
11882 #ifdef _SC_ASYNCHRONOUS_IO
11883 {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
11884 #endif
11885 #ifdef _SC_ATEXIT_MAX
11886 {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
11887 #endif
11888 #ifdef _SC_AUDIT
11889 {"SC_AUDIT", _SC_AUDIT},
11890 #endif
11891 #ifdef _SC_AVPHYS_PAGES
11892 {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
11893 #endif
11894 #ifdef _SC_BC_BASE_MAX
11895 {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
11896 #endif
11897 #ifdef _SC_BC_DIM_MAX
11898 {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
11899 #endif
11900 #ifdef _SC_BC_SCALE_MAX
11901 {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
11902 #endif
11903 #ifdef _SC_BC_STRING_MAX
11904 {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
11905 #endif
11906 #ifdef _SC_CAP
11907 {"SC_CAP", _SC_CAP},
11908 #endif
11909 #ifdef _SC_CHARCLASS_NAME_MAX
11910 {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
11911 #endif
11912 #ifdef _SC_CHAR_BIT
11913 {"SC_CHAR_BIT", _SC_CHAR_BIT},
11914 #endif
11915 #ifdef _SC_CHAR_MAX
11916 {"SC_CHAR_MAX", _SC_CHAR_MAX},
11917 #endif
11918 #ifdef _SC_CHAR_MIN
11919 {"SC_CHAR_MIN", _SC_CHAR_MIN},
11920 #endif
11921 #ifdef _SC_CHILD_MAX
11922 {"SC_CHILD_MAX", _SC_CHILD_MAX},
11923 #endif
11924 #ifdef _SC_CLK_TCK
11925 {"SC_CLK_TCK", _SC_CLK_TCK},
11926 #endif
11927 #ifdef _SC_COHER_BLKSZ
11928 {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
11929 #endif
11930 #ifdef _SC_COLL_WEIGHTS_MAX
11931 {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
11932 #endif
11933 #ifdef _SC_DCACHE_ASSOC
11934 {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
11935 #endif
11936 #ifdef _SC_DCACHE_BLKSZ
11937 {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
11938 #endif
11939 #ifdef _SC_DCACHE_LINESZ
11940 {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
11941 #endif
11942 #ifdef _SC_DCACHE_SZ
11943 {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
11944 #endif
11945 #ifdef _SC_DCACHE_TBLKSZ
11946 {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
11947 #endif
11948 #ifdef _SC_DELAYTIMER_MAX
11949 {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
11950 #endif
11951 #ifdef _SC_EQUIV_CLASS_MAX
11952 {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
11953 #endif
11954 #ifdef _SC_EXPR_NEST_MAX
11955 {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
11956 #endif
11957 #ifdef _SC_FSYNC
11958 {"SC_FSYNC", _SC_FSYNC},
11959 #endif
11960 #ifdef _SC_GETGR_R_SIZE_MAX
11961 {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
11962 #endif
11963 #ifdef _SC_GETPW_R_SIZE_MAX
11964 {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
11965 #endif
11966 #ifdef _SC_ICACHE_ASSOC
11967 {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
11968 #endif
11969 #ifdef _SC_ICACHE_BLKSZ
11970 {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
11971 #endif
11972 #ifdef _SC_ICACHE_LINESZ
11973 {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
11974 #endif
11975 #ifdef _SC_ICACHE_SZ
11976 {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
11977 #endif
11978 #ifdef _SC_INF
11979 {"SC_INF", _SC_INF},
11980 #endif
11981 #ifdef _SC_INT_MAX
11982 {"SC_INT_MAX", _SC_INT_MAX},
11983 #endif
11984 #ifdef _SC_INT_MIN
11985 {"SC_INT_MIN", _SC_INT_MIN},
11986 #endif
11987 #ifdef _SC_IOV_MAX
11988 {"SC_IOV_MAX", _SC_IOV_MAX},
11989 #endif
11990 #ifdef _SC_IP_SECOPTS
11991 {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
11992 #endif
11993 #ifdef _SC_JOB_CONTROL
11994 {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
11995 #endif
11996 #ifdef _SC_KERN_POINTERS
11997 {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
11998 #endif
11999 #ifdef _SC_KERN_SIM
12000 {"SC_KERN_SIM", _SC_KERN_SIM},
12001 #endif
12002 #ifdef _SC_LINE_MAX
12003 {"SC_LINE_MAX", _SC_LINE_MAX},
12004 #endif
12005 #ifdef _SC_LOGIN_NAME_MAX
12006 {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
12007 #endif
12008 #ifdef _SC_LOGNAME_MAX
12009 {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
12010 #endif
12011 #ifdef _SC_LONG_BIT
12012 {"SC_LONG_BIT", _SC_LONG_BIT},
12013 #endif
12014 #ifdef _SC_MAC
12015 {"SC_MAC", _SC_MAC},
12016 #endif
12017 #ifdef _SC_MAPPED_FILES
12018 {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
12019 #endif
12020 #ifdef _SC_MAXPID
12021 {"SC_MAXPID", _SC_MAXPID},
12022 #endif
12023 #ifdef _SC_MB_LEN_MAX
12024 {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
12025 #endif
12026 #ifdef _SC_MEMLOCK
12027 {"SC_MEMLOCK", _SC_MEMLOCK},
12028 #endif
12029 #ifdef _SC_MEMLOCK_RANGE
12030 {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
12031 #endif
12032 #ifdef _SC_MEMORY_PROTECTION
12033 {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
12034 #endif
12035 #ifdef _SC_MESSAGE_PASSING
12036 {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
12037 #endif
12038 #ifdef _SC_MMAP_FIXED_ALIGNMENT
12039 {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
12040 #endif
12041 #ifdef _SC_MQ_OPEN_MAX
12042 {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
12043 #endif
12044 #ifdef _SC_MQ_PRIO_MAX
12045 {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},
12046 #endif
12047 #ifdef _SC_NACLS_MAX
12048 {"SC_NACLS_MAX", _SC_NACLS_MAX},
12049 #endif
12050 #ifdef _SC_NGROUPS_MAX
12051 {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX},
12052 #endif
12053 #ifdef _SC_NL_ARGMAX
12054 {"SC_NL_ARGMAX", _SC_NL_ARGMAX},
12055 #endif
12056 #ifdef _SC_NL_LANGMAX
12057 {"SC_NL_LANGMAX", _SC_NL_LANGMAX},
12058 #endif
12059 #ifdef _SC_NL_MSGMAX
12060 {"SC_NL_MSGMAX", _SC_NL_MSGMAX},
12061 #endif
12062 #ifdef _SC_NL_NMAX
12063 {"SC_NL_NMAX", _SC_NL_NMAX},
12064 #endif
12065 #ifdef _SC_NL_SETMAX
12066 {"SC_NL_SETMAX", _SC_NL_SETMAX},
12067 #endif
12068 #ifdef _SC_NL_TEXTMAX
12069 {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX},
12070 #endif
12071 #ifdef _SC_NPROCESSORS_CONF
12072 {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
12073 #endif
12074 #ifdef _SC_NPROCESSORS_ONLN
12075 {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
12076 #endif
12077 #ifdef _SC_NPROC_CONF
12078 {"SC_NPROC_CONF", _SC_NPROC_CONF},
12079 #endif
12080 #ifdef _SC_NPROC_ONLN
12081 {"SC_NPROC_ONLN", _SC_NPROC_ONLN},
12082 #endif
12083 #ifdef _SC_NZERO
12084 {"SC_NZERO", _SC_NZERO},
12085 #endif
12086 #ifdef _SC_OPEN_MAX
12087 {"SC_OPEN_MAX", _SC_OPEN_MAX},
12088 #endif
12089 #ifdef _SC_PAGESIZE
12090 {"SC_PAGESIZE", _SC_PAGESIZE},
12091 #endif
12092 #ifdef _SC_PAGE_SIZE
12093 {"SC_PAGE_SIZE", _SC_PAGE_SIZE},
12094 #endif
12095 #ifdef _SC_AIX_REALMEM
12096 {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
12097 #endif
12098 #ifdef _SC_PASS_MAX
12099 {"SC_PASS_MAX", _SC_PASS_MAX},
12100 #endif
12101 #ifdef _SC_PHYS_PAGES
12102 {"SC_PHYS_PAGES", _SC_PHYS_PAGES},
12103 #endif
12104 #ifdef _SC_PII
12105 {"SC_PII", _SC_PII},
12106 #endif
12107 #ifdef _SC_PII_INTERNET
12108 {"SC_PII_INTERNET", _SC_PII_INTERNET},
12109 #endif
12110 #ifdef _SC_PII_INTERNET_DGRAM
12111 {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM},
12112 #endif
12113 #ifdef _SC_PII_INTERNET_STREAM
12114 {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM},
12115 #endif
12116 #ifdef _SC_PII_OSI
12117 {"SC_PII_OSI", _SC_PII_OSI},
12118 #endif
12119 #ifdef _SC_PII_OSI_CLTS
12120 {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
12121 #endif
12122 #ifdef _SC_PII_OSI_COTS
12123 {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
12124 #endif
12125 #ifdef _SC_PII_OSI_M
12126 {"SC_PII_OSI_M", _SC_PII_OSI_M},
12127 #endif
12128 #ifdef _SC_PII_SOCKET
12129 {"SC_PII_SOCKET", _SC_PII_SOCKET},
12130 #endif
12131 #ifdef _SC_PII_XTI
12132 {"SC_PII_XTI", _SC_PII_XTI},
12133 #endif
12134 #ifdef _SC_POLL
12135 {"SC_POLL", _SC_POLL},
12136 #endif
12137 #ifdef _SC_PRIORITIZED_IO
12138 {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO},
12139 #endif
12140 #ifdef _SC_PRIORITY_SCHEDULING
12141 {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING},
12142 #endif
12143 #ifdef _SC_REALTIME_SIGNALS
12144 {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS},
12145 #endif
12146 #ifdef _SC_RE_DUP_MAX
12147 {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX},
12148 #endif
12149 #ifdef _SC_RTSIG_MAX
12150 {"SC_RTSIG_MAX", _SC_RTSIG_MAX},
12151 #endif
12152 #ifdef _SC_SAVED_IDS
12153 {"SC_SAVED_IDS", _SC_SAVED_IDS},
12154 #endif
12155 #ifdef _SC_SCHAR_MAX
12156 {"SC_SCHAR_MAX", _SC_SCHAR_MAX},
12157 #endif
12158 #ifdef _SC_SCHAR_MIN
12159 {"SC_SCHAR_MIN", _SC_SCHAR_MIN},
12160 #endif
12161 #ifdef _SC_SELECT
12162 {"SC_SELECT", _SC_SELECT},
12163 #endif
12164 #ifdef _SC_SEMAPHORES
12165 {"SC_SEMAPHORES", _SC_SEMAPHORES},
12166 #endif
12167 #ifdef _SC_SEM_NSEMS_MAX
12168 {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX},
12169 #endif
12170 #ifdef _SC_SEM_VALUE_MAX
12171 {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX},
12172 #endif
12173 #ifdef _SC_SHARED_MEMORY_OBJECTS
12174 {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS},
12175 #endif
12176 #ifdef _SC_SHRT_MAX
12177 {"SC_SHRT_MAX", _SC_SHRT_MAX},
12178 #endif
12179 #ifdef _SC_SHRT_MIN
12180 {"SC_SHRT_MIN", _SC_SHRT_MIN},
12181 #endif
12182 #ifdef _SC_SIGQUEUE_MAX
12183 {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
12184 #endif
12185 #ifdef _SC_SIGRT_MAX
12186 {"SC_SIGRT_MAX", _SC_SIGRT_MAX},
12187 #endif
12188 #ifdef _SC_SIGRT_MIN
12189 {"SC_SIGRT_MIN", _SC_SIGRT_MIN},
12190 #endif
12191 #ifdef _SC_SOFTPOWER
12192 {"SC_SOFTPOWER", _SC_SOFTPOWER},
12193 #endif
12194 #ifdef _SC_SPLIT_CACHE
12195 {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE},
12196 #endif
12197 #ifdef _SC_SSIZE_MAX
12198 {"SC_SSIZE_MAX", _SC_SSIZE_MAX},
12199 #endif
12200 #ifdef _SC_STACK_PROT
12201 {"SC_STACK_PROT", _SC_STACK_PROT},
12202 #endif
12203 #ifdef _SC_STREAM_MAX
12204 {"SC_STREAM_MAX", _SC_STREAM_MAX},
12205 #endif
12206 #ifdef _SC_SYNCHRONIZED_IO
12207 {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO},
12208 #endif
12209 #ifdef _SC_THREADS
12210 {"SC_THREADS", _SC_THREADS},
12211 #endif
12212 #ifdef _SC_THREAD_ATTR_STACKADDR
12213 {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR},
12214 #endif
12215 #ifdef _SC_THREAD_ATTR_STACKSIZE
12216 {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE},
12217 #endif
12218 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
12219 {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
12220 #endif
12221 #ifdef _SC_THREAD_KEYS_MAX
12222 {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
12223 #endif
12224 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
12225 {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING},
12226 #endif
12227 #ifdef _SC_THREAD_PRIO_INHERIT
12228 {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT},
12229 #endif
12230 #ifdef _SC_THREAD_PRIO_PROTECT
12231 {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT},
12232 #endif
12233 #ifdef _SC_THREAD_PROCESS_SHARED
12234 {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED},
12235 #endif
12236 #ifdef _SC_THREAD_SAFE_FUNCTIONS
12237 {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS},
12238 #endif
12239 #ifdef _SC_THREAD_STACK_MIN
12240 {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
12241 #endif
12242 #ifdef _SC_THREAD_THREADS_MAX
12243 {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
12244 #endif
12245 #ifdef _SC_TIMERS
12246 {"SC_TIMERS", _SC_TIMERS},
12247 #endif
12248 #ifdef _SC_TIMER_MAX
12249 {"SC_TIMER_MAX", _SC_TIMER_MAX},
12250 #endif
12251 #ifdef _SC_TTY_NAME_MAX
12252 {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
12253 #endif
12254 #ifdef _SC_TZNAME_MAX
12255 {"SC_TZNAME_MAX", _SC_TZNAME_MAX},
12256 #endif
12257 #ifdef _SC_T_IOV_MAX
12258 {"SC_T_IOV_MAX", _SC_T_IOV_MAX},
12259 #endif
12260 #ifdef _SC_UCHAR_MAX
12261 {"SC_UCHAR_MAX", _SC_UCHAR_MAX},
12262 #endif
12263 #ifdef _SC_UINT_MAX
12264 {"SC_UINT_MAX", _SC_UINT_MAX},
12265 #endif
12266 #ifdef _SC_UIO_MAXIOV
12267 {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV},
12268 #endif
12269 #ifdef _SC_ULONG_MAX
12270 {"SC_ULONG_MAX", _SC_ULONG_MAX},
12271 #endif
12272 #ifdef _SC_USHRT_MAX
12273 {"SC_USHRT_MAX", _SC_USHRT_MAX},
12274 #endif
12275 #ifdef _SC_VERSION
12276 {"SC_VERSION", _SC_VERSION},
12277 #endif
12278 #ifdef _SC_WORD_BIT
12279 {"SC_WORD_BIT", _SC_WORD_BIT},
12280 #endif
12281 #ifdef _SC_XBS5_ILP32_OFF32
12282 {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32},
12283 #endif
12284 #ifdef _SC_XBS5_ILP32_OFFBIG
12285 {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG},
12286 #endif
12287 #ifdef _SC_XBS5_LP64_OFF64
12288 {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64},
12289 #endif
12290 #ifdef _SC_XBS5_LPBIG_OFFBIG
12291 {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG},
12292 #endif
12293 #ifdef _SC_XOPEN_CRYPT
12294 {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT},
12295 #endif
12296 #ifdef _SC_XOPEN_ENH_I18N
12297 {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N},
12298 #endif
12299 #ifdef _SC_XOPEN_LEGACY
12300 {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
12301 #endif
12302 #ifdef _SC_XOPEN_REALTIME
12303 {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME},
12304 #endif
12305 #ifdef _SC_XOPEN_REALTIME_THREADS
12306 {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS},
12307 #endif
12308 #ifdef _SC_XOPEN_SHM
12309 {"SC_XOPEN_SHM", _SC_XOPEN_SHM},
12310 #endif
12311 #ifdef _SC_XOPEN_UNIX
12312 {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX},
12313 #endif
12314 #ifdef _SC_XOPEN_VERSION
12315 {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION},
12316 #endif
12317 #ifdef _SC_XOPEN_XCU_VERSION
12318 {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION},
12319 #endif
12320 #ifdef _SC_XOPEN_XPG2
12321 {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2},
12322 #endif
12323 #ifdef _SC_XOPEN_XPG3
12324 {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3},
12325 #endif
12326 #ifdef _SC_XOPEN_XPG4
12327 {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4},
12328 #endif
12329 };
12330
12331 static int
conv_sysconf_confname(PyObject * arg,int * valuep)12332 conv_sysconf_confname(PyObject *arg, int *valuep)
12333 {
12334 return conv_confname(arg, valuep, posix_constants_sysconf,
12335 sizeof(posix_constants_sysconf)
12336 / sizeof(struct constdef));
12337 }
12338
12339
12340 /*[clinic input]
12341 os.sysconf -> long
12342 name: sysconf_confname
12343 /
12344
12345 Return an integer-valued system configuration variable.
12346 [clinic start generated code]*/
12347
12348 static long
os_sysconf_impl(PyObject * module,int name)12349 os_sysconf_impl(PyObject *module, int name)
12350 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
12351 {
12352 long value;
12353
12354 errno = 0;
12355 value = sysconf(name);
12356 if (value == -1 && errno != 0)
12357 posix_error();
12358 return value;
12359 }
12360 #endif /* HAVE_SYSCONF */
12361
12362
12363 /* This code is used to ensure that the tables of configuration value names
12364 * are in sorted order as required by conv_confname(), and also to build
12365 * the exported dictionaries that are used to publish information about the
12366 * names available on the host platform.
12367 *
12368 * Sorting the table at runtime ensures that the table is properly ordered
12369 * when used, even for platforms we're not able to test on. It also makes
12370 * it easier to add additional entries to the tables.
12371 */
12372
12373 static int
cmp_constdefs(const void * v1,const void * v2)12374 cmp_constdefs(const void *v1, const void *v2)
12375 {
12376 const struct constdef *c1 =
12377 (const struct constdef *) v1;
12378 const struct constdef *c2 =
12379 (const struct constdef *) v2;
12380
12381 return strcmp(c1->name, c2->name);
12382 }
12383
12384 static int
setup_confname_table(struct constdef * table,size_t tablesize,const char * tablename,PyObject * module)12385 setup_confname_table(struct constdef *table, size_t tablesize,
12386 const char *tablename, PyObject *module)
12387 {
12388 PyObject *d = NULL;
12389 size_t i;
12390
12391 qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
12392 d = PyDict_New();
12393 if (d == NULL)
12394 return -1;
12395
12396 for (i=0; i < tablesize; ++i) {
12397 PyObject *o = PyLong_FromLong(table[i].value);
12398 if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
12399 Py_XDECREF(o);
12400 Py_DECREF(d);
12401 return -1;
12402 }
12403 Py_DECREF(o);
12404 }
12405 return PyModule_AddObject(module, tablename, d);
12406 }
12407
12408 /* Return -1 on failure, 0 on success. */
12409 static int
setup_confname_tables(PyObject * module)12410 setup_confname_tables(PyObject *module)
12411 {
12412 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12413 if (setup_confname_table(posix_constants_pathconf,
12414 sizeof(posix_constants_pathconf)
12415 / sizeof(struct constdef),
12416 "pathconf_names", module))
12417 return -1;
12418 #endif
12419 #ifdef HAVE_CONFSTR
12420 if (setup_confname_table(posix_constants_confstr,
12421 sizeof(posix_constants_confstr)
12422 / sizeof(struct constdef),
12423 "confstr_names", module))
12424 return -1;
12425 #endif
12426 #ifdef HAVE_SYSCONF
12427 if (setup_confname_table(posix_constants_sysconf,
12428 sizeof(posix_constants_sysconf)
12429 / sizeof(struct constdef),
12430 "sysconf_names", module))
12431 return -1;
12432 #endif
12433 return 0;
12434 }
12435
12436
12437 /*[clinic input]
12438 os.abort
12439
12440 Abort the interpreter immediately.
12441
12442 This function 'dumps core' or otherwise fails in the hardest way possible
12443 on the hosting operating system. This function never returns.
12444 [clinic start generated code]*/
12445
12446 static PyObject *
os_abort_impl(PyObject * module)12447 os_abort_impl(PyObject *module)
12448 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
12449 {
12450 abort();
12451 /*NOTREACHED*/
12452 #ifndef __clang__
12453 /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
12454 GCC emits a warning without "return NULL;" (compiler bug?), but Clang
12455 is smarter and emits a warning on the return. */
12456 Py_FatalError("abort() called from Python code didn't abort!");
12457 return NULL;
12458 #endif
12459 }
12460
12461 #ifdef MS_WINDOWS
12462 /* Grab ShellExecute dynamically from shell32 */
12463 static int has_ShellExecute = -1;
12464 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
12465 LPCWSTR, INT);
12466 static int
check_ShellExecute()12467 check_ShellExecute()
12468 {
12469 HINSTANCE hShell32;
12470
12471 /* only recheck */
12472 if (-1 == has_ShellExecute) {
12473 Py_BEGIN_ALLOW_THREADS
12474 /* Security note: this call is not vulnerable to "DLL hijacking".
12475 SHELL32 is part of "KnownDLLs" and so Windows always load
12476 the system SHELL32.DLL, even if there is another SHELL32.DLL
12477 in the DLL search path. */
12478 hShell32 = LoadLibraryW(L"SHELL32");
12479 if (hShell32) {
12480 *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
12481 "ShellExecuteW");
12482 has_ShellExecute = Py_ShellExecuteW != NULL;
12483 } else {
12484 has_ShellExecute = 0;
12485 }
12486 Py_END_ALLOW_THREADS
12487 }
12488 return has_ShellExecute;
12489 }
12490
12491
12492 /*[clinic input]
12493 os.startfile
12494 filepath: path_t
12495 operation: Py_UNICODE = NULL
12496 arguments: Py_UNICODE = NULL
12497 cwd: path_t(nullable=True) = None
12498 show_cmd: int = 1
12499
12500 Start a file with its associated application.
12501
12502 When "operation" is not specified or "open", this acts like
12503 double-clicking the file in Explorer, or giving the file name as an
12504 argument to the DOS "start" command: the file is opened with whatever
12505 application (if any) its extension is associated.
12506 When another "operation" is given, it specifies what should be done with
12507 the file. A typical operation is "print".
12508
12509 "arguments" is passed to the application, but should be omitted if the
12510 file is a document.
12511
12512 "cwd" is the working directory for the operation. If "filepath" is
12513 relative, it will be resolved against this directory. This argument
12514 should usually be an absolute path.
12515
12516 "show_cmd" can be used to override the recommended visibility option.
12517 See the Windows ShellExecute documentation for values.
12518
12519 startfile returns as soon as the associated application is launched.
12520 There is no option to wait for the application to close, and no way
12521 to retrieve the application's exit status.
12522
12523 The filepath is relative to the current directory. If you want to use
12524 an absolute path, make sure the first character is not a slash ("/");
12525 the underlying Win32 ShellExecute function doesn't work if it is.
12526 [clinic start generated code]*/
12527
12528 static PyObject *
os_startfile_impl(PyObject * module,path_t * filepath,const Py_UNICODE * operation,const Py_UNICODE * arguments,path_t * cwd,int show_cmd)12529 os_startfile_impl(PyObject *module, path_t *filepath,
12530 const Py_UNICODE *operation, const Py_UNICODE *arguments,
12531 path_t *cwd, int show_cmd)
12532 /*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/
12533 {
12534 HINSTANCE rc;
12535
12536 if(!check_ShellExecute()) {
12537 /* If the OS doesn't have ShellExecute, return a
12538 NotImplementedError. */
12539 return PyErr_Format(PyExc_NotImplementedError,
12540 "startfile not available on this platform");
12541 }
12542
12543 if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
12544 return NULL;
12545 }
12546 if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
12547 arguments, cwd->object ? cwd->object : Py_None,
12548 show_cmd) < 0) {
12549 return NULL;
12550 }
12551
12552 Py_BEGIN_ALLOW_THREADS
12553 rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
12554 arguments, cwd->wide, show_cmd);
12555 Py_END_ALLOW_THREADS
12556
12557 if (rc <= (HINSTANCE)32) {
12558 win32_error_object("startfile", filepath->object);
12559 return NULL;
12560 }
12561 Py_RETURN_NONE;
12562 }
12563 #endif /* MS_WINDOWS */
12564
12565
12566 #ifdef HAVE_GETLOADAVG
12567 /*[clinic input]
12568 os.getloadavg
12569
12570 Return average recent system load information.
12571
12572 Return the number of processes in the system run queue averaged over
12573 the last 1, 5, and 15 minutes as a tuple of three floats.
12574 Raises OSError if the load average was unobtainable.
12575 [clinic start generated code]*/
12576
12577 static PyObject *
os_getloadavg_impl(PyObject * module)12578 os_getloadavg_impl(PyObject *module)
12579 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
12580 {
12581 double loadavg[3];
12582 if (getloadavg(loadavg, 3)!=3) {
12583 PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
12584 return NULL;
12585 } else
12586 return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
12587 }
12588 #endif /* HAVE_GETLOADAVG */
12589
12590
12591 /*[clinic input]
12592 os.device_encoding
12593 fd: int
12594
12595 Return a string describing the encoding of a terminal's file descriptor.
12596
12597 The file descriptor must be attached to a terminal.
12598 If the device is not a terminal, return None.
12599 [clinic start generated code]*/
12600
12601 static PyObject *
os_device_encoding_impl(PyObject * module,int fd)12602 os_device_encoding_impl(PyObject *module, int fd)
12603 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
12604 {
12605 return _Py_device_encoding(fd);
12606 }
12607
12608
12609 #ifdef HAVE_SETRESUID
12610 /*[clinic input]
12611 os.setresuid
12612
12613 ruid: uid_t
12614 euid: uid_t
12615 suid: uid_t
12616 /
12617
12618 Set the current process's real, effective, and saved user ids.
12619 [clinic start generated code]*/
12620
12621 static PyObject *
os_setresuid_impl(PyObject * module,uid_t ruid,uid_t euid,uid_t suid)12622 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
12623 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
12624 {
12625 if (setresuid(ruid, euid, suid) < 0)
12626 return posix_error();
12627 Py_RETURN_NONE;
12628 }
12629 #endif /* HAVE_SETRESUID */
12630
12631
12632 #ifdef HAVE_SETRESGID
12633 /*[clinic input]
12634 os.setresgid
12635
12636 rgid: gid_t
12637 egid: gid_t
12638 sgid: gid_t
12639 /
12640
12641 Set the current process's real, effective, and saved group ids.
12642 [clinic start generated code]*/
12643
12644 static PyObject *
os_setresgid_impl(PyObject * module,gid_t rgid,gid_t egid,gid_t sgid)12645 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
12646 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
12647 {
12648 if (setresgid(rgid, egid, sgid) < 0)
12649 return posix_error();
12650 Py_RETURN_NONE;
12651 }
12652 #endif /* HAVE_SETRESGID */
12653
12654
12655 #ifdef HAVE_GETRESUID
12656 /*[clinic input]
12657 os.getresuid
12658
12659 Return a tuple of the current process's real, effective, and saved user ids.
12660 [clinic start generated code]*/
12661
12662 static PyObject *
os_getresuid_impl(PyObject * module)12663 os_getresuid_impl(PyObject *module)
12664 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12665 {
12666 uid_t ruid, euid, suid;
12667 if (getresuid(&ruid, &euid, &suid) < 0)
12668 return posix_error();
12669 return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12670 _PyLong_FromUid(euid),
12671 _PyLong_FromUid(suid));
12672 }
12673 #endif /* HAVE_GETRESUID */
12674
12675
12676 #ifdef HAVE_GETRESGID
12677 /*[clinic input]
12678 os.getresgid
12679
12680 Return a tuple of the current process's real, effective, and saved group ids.
12681 [clinic start generated code]*/
12682
12683 static PyObject *
os_getresgid_impl(PyObject * module)12684 os_getresgid_impl(PyObject *module)
12685 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12686 {
12687 gid_t rgid, egid, sgid;
12688 if (getresgid(&rgid, &egid, &sgid) < 0)
12689 return posix_error();
12690 return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12691 _PyLong_FromGid(egid),
12692 _PyLong_FromGid(sgid));
12693 }
12694 #endif /* HAVE_GETRESGID */
12695
12696
12697 #ifdef USE_XATTRS
12698 /*[clinic input]
12699 os.getxattr
12700
12701 path: path_t(allow_fd=True)
12702 attribute: path_t
12703 *
12704 follow_symlinks: bool = True
12705
12706 Return the value of extended attribute attribute on path.
12707
12708 path may be either a string, a path-like object, or an open file descriptor.
12709 If follow_symlinks is False, and the last element of the path is a symbolic
12710 link, getxattr will examine the symbolic link itself instead of the file
12711 the link points to.
12712
12713 [clinic start generated code]*/
12714
12715 static PyObject *
os_getxattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12716 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12717 int follow_symlinks)
12718 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12719 {
12720 Py_ssize_t i;
12721 PyObject *buffer = NULL;
12722
12723 if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12724 return NULL;
12725
12726 if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12727 return NULL;
12728 }
12729
12730 for (i = 0; ; i++) {
12731 void *ptr;
12732 ssize_t result;
12733 static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12734 Py_ssize_t buffer_size = buffer_sizes[i];
12735 if (!buffer_size) {
12736 path_error(path);
12737 return NULL;
12738 }
12739 buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12740 if (!buffer)
12741 return NULL;
12742 ptr = PyBytes_AS_STRING(buffer);
12743
12744 Py_BEGIN_ALLOW_THREADS;
12745 if (path->fd >= 0)
12746 result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12747 else if (follow_symlinks)
12748 result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12749 else
12750 result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12751 Py_END_ALLOW_THREADS;
12752
12753 if (result < 0) {
12754 Py_DECREF(buffer);
12755 if (errno == ERANGE)
12756 continue;
12757 path_error(path);
12758 return NULL;
12759 }
12760
12761 if (result != buffer_size) {
12762 /* Can only shrink. */
12763 _PyBytes_Resize(&buffer, result);
12764 }
12765 break;
12766 }
12767
12768 return buffer;
12769 }
12770
12771
12772 /*[clinic input]
12773 os.setxattr
12774
12775 path: path_t(allow_fd=True)
12776 attribute: path_t
12777 value: Py_buffer
12778 flags: int = 0
12779 *
12780 follow_symlinks: bool = True
12781
12782 Set extended attribute attribute on path to value.
12783
12784 path may be either a string, a path-like object, or an open file descriptor.
12785 If follow_symlinks is False, and the last element of the path is a symbolic
12786 link, setxattr will modify the symbolic link itself instead of the file
12787 the link points to.
12788
12789 [clinic start generated code]*/
12790
12791 static PyObject *
os_setxattr_impl(PyObject * module,path_t * path,path_t * attribute,Py_buffer * value,int flags,int follow_symlinks)12792 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12793 Py_buffer *value, int flags, int follow_symlinks)
12794 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12795 {
12796 ssize_t result;
12797
12798 if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12799 return NULL;
12800
12801 if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12802 value->buf, value->len, flags) < 0) {
12803 return NULL;
12804 }
12805
12806 Py_BEGIN_ALLOW_THREADS;
12807 if (path->fd > -1)
12808 result = fsetxattr(path->fd, attribute->narrow,
12809 value->buf, value->len, flags);
12810 else if (follow_symlinks)
12811 result = setxattr(path->narrow, attribute->narrow,
12812 value->buf, value->len, flags);
12813 else
12814 result = lsetxattr(path->narrow, attribute->narrow,
12815 value->buf, value->len, flags);
12816 Py_END_ALLOW_THREADS;
12817
12818 if (result) {
12819 path_error(path);
12820 return NULL;
12821 }
12822
12823 Py_RETURN_NONE;
12824 }
12825
12826
12827 /*[clinic input]
12828 os.removexattr
12829
12830 path: path_t(allow_fd=True)
12831 attribute: path_t
12832 *
12833 follow_symlinks: bool = True
12834
12835 Remove extended attribute attribute on path.
12836
12837 path may be either a string, a path-like object, or an open file descriptor.
12838 If follow_symlinks is False, and the last element of the path is a symbolic
12839 link, removexattr will modify the symbolic link itself instead of the file
12840 the link points to.
12841
12842 [clinic start generated code]*/
12843
12844 static PyObject *
os_removexattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12845 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
12846 int follow_symlinks)
12847 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
12848 {
12849 ssize_t result;
12850
12851 if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
12852 return NULL;
12853
12854 if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
12855 return NULL;
12856 }
12857
12858 Py_BEGIN_ALLOW_THREADS;
12859 if (path->fd > -1)
12860 result = fremovexattr(path->fd, attribute->narrow);
12861 else if (follow_symlinks)
12862 result = removexattr(path->narrow, attribute->narrow);
12863 else
12864 result = lremovexattr(path->narrow, attribute->narrow);
12865 Py_END_ALLOW_THREADS;
12866
12867 if (result) {
12868 return path_error(path);
12869 }
12870
12871 Py_RETURN_NONE;
12872 }
12873
12874
12875 /*[clinic input]
12876 os.listxattr
12877
12878 path: path_t(allow_fd=True, nullable=True) = None
12879 *
12880 follow_symlinks: bool = True
12881
12882 Return a list of extended attributes on path.
12883
12884 path may be either None, a string, a path-like object, or an open file descriptor.
12885 if path is None, listxattr will examine the current directory.
12886 If follow_symlinks is False, and the last element of the path is a symbolic
12887 link, listxattr will examine the symbolic link itself instead of the file
12888 the link points to.
12889 [clinic start generated code]*/
12890
12891 static PyObject *
os_listxattr_impl(PyObject * module,path_t * path,int follow_symlinks)12892 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
12893 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
12894 {
12895 Py_ssize_t i;
12896 PyObject *result = NULL;
12897 const char *name;
12898 char *buffer = NULL;
12899
12900 if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
12901 goto exit;
12902
12903 if (PySys_Audit("os.listxattr", "(O)",
12904 path->object ? path->object : Py_None) < 0) {
12905 return NULL;
12906 }
12907
12908 name = path->narrow ? path->narrow : ".";
12909
12910 for (i = 0; ; i++) {
12911 const char *start, *trace, *end;
12912 ssize_t length;
12913 static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
12914 Py_ssize_t buffer_size = buffer_sizes[i];
12915 if (!buffer_size) {
12916 /* ERANGE */
12917 path_error(path);
12918 break;
12919 }
12920 buffer = PyMem_Malloc(buffer_size);
12921 if (!buffer) {
12922 PyErr_NoMemory();
12923 break;
12924 }
12925
12926 Py_BEGIN_ALLOW_THREADS;
12927 if (path->fd > -1)
12928 length = flistxattr(path->fd, buffer, buffer_size);
12929 else if (follow_symlinks)
12930 length = listxattr(name, buffer, buffer_size);
12931 else
12932 length = llistxattr(name, buffer, buffer_size);
12933 Py_END_ALLOW_THREADS;
12934
12935 if (length < 0) {
12936 if (errno == ERANGE) {
12937 PyMem_Free(buffer);
12938 buffer = NULL;
12939 continue;
12940 }
12941 path_error(path);
12942 break;
12943 }
12944
12945 result = PyList_New(0);
12946 if (!result) {
12947 goto exit;
12948 }
12949
12950 end = buffer + length;
12951 for (trace = start = buffer; trace != end; trace++) {
12952 if (!*trace) {
12953 int error;
12954 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
12955 trace - start);
12956 if (!attribute) {
12957 Py_DECREF(result);
12958 result = NULL;
12959 goto exit;
12960 }
12961 error = PyList_Append(result, attribute);
12962 Py_DECREF(attribute);
12963 if (error) {
12964 Py_DECREF(result);
12965 result = NULL;
12966 goto exit;
12967 }
12968 start = trace + 1;
12969 }
12970 }
12971 break;
12972 }
12973 exit:
12974 if (buffer)
12975 PyMem_Free(buffer);
12976 return result;
12977 }
12978 #endif /* USE_XATTRS */
12979
12980
12981 /*[clinic input]
12982 os.urandom
12983
12984 size: Py_ssize_t
12985 /
12986
12987 Return a bytes object containing random bytes suitable for cryptographic use.
12988 [clinic start generated code]*/
12989
12990 static PyObject *
os_urandom_impl(PyObject * module,Py_ssize_t size)12991 os_urandom_impl(PyObject *module, Py_ssize_t size)
12992 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
12993 {
12994 PyObject *bytes;
12995 int result;
12996
12997 if (size < 0)
12998 return PyErr_Format(PyExc_ValueError,
12999 "negative argument not allowed");
13000 bytes = PyBytes_FromStringAndSize(NULL, size);
13001 if (bytes == NULL)
13002 return NULL;
13003
13004 result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
13005 if (result == -1) {
13006 Py_DECREF(bytes);
13007 return NULL;
13008 }
13009 return bytes;
13010 }
13011
13012 #ifdef HAVE_MEMFD_CREATE
13013 /*[clinic input]
13014 os.memfd_create
13015
13016 name: FSConverter
13017 flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
13018
13019 [clinic start generated code]*/
13020
13021 static PyObject *
os_memfd_create_impl(PyObject * module,PyObject * name,unsigned int flags)13022 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
13023 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
13024 {
13025 int fd;
13026 const char *bytes = PyBytes_AS_STRING(name);
13027 Py_BEGIN_ALLOW_THREADS
13028 fd = memfd_create(bytes, flags);
13029 Py_END_ALLOW_THREADS
13030 if (fd == -1) {
13031 return PyErr_SetFromErrno(PyExc_OSError);
13032 }
13033 return PyLong_FromLong(fd);
13034 }
13035 #endif
13036
13037 #ifdef HAVE_EVENTFD
13038 /*[clinic input]
13039 os.eventfd
13040
13041 initval: unsigned_int
13042 flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
13043
13044 Creates and returns an event notification file descriptor.
13045 [clinic start generated code]*/
13046
13047 static PyObject *
os_eventfd_impl(PyObject * module,unsigned int initval,int flags)13048 os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
13049 /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
13050
13051 {
13052 /* initval is limited to uint32_t, internal counter is uint64_t */
13053 int fd;
13054 Py_BEGIN_ALLOW_THREADS
13055 fd = eventfd(initval, flags);
13056 Py_END_ALLOW_THREADS
13057 if (fd == -1) {
13058 return PyErr_SetFromErrno(PyExc_OSError);
13059 }
13060 return PyLong_FromLong(fd);
13061 }
13062
13063 /*[clinic input]
13064 os.eventfd_read
13065
13066 fd: fildes
13067
13068 Read eventfd value
13069 [clinic start generated code]*/
13070
13071 static PyObject *
os_eventfd_read_impl(PyObject * module,int fd)13072 os_eventfd_read_impl(PyObject *module, int fd)
13073 /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
13074 {
13075 eventfd_t value;
13076 int result;
13077 Py_BEGIN_ALLOW_THREADS
13078 result = eventfd_read(fd, &value);
13079 Py_END_ALLOW_THREADS
13080 if (result == -1) {
13081 return PyErr_SetFromErrno(PyExc_OSError);
13082 }
13083 return PyLong_FromUnsignedLongLong(value);
13084 }
13085
13086 /*[clinic input]
13087 os.eventfd_write
13088
13089 fd: fildes
13090 value: unsigned_long_long
13091
13092 Write eventfd value.
13093 [clinic start generated code]*/
13094
13095 static PyObject *
os_eventfd_write_impl(PyObject * module,int fd,unsigned long long value)13096 os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
13097 /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
13098 {
13099 int result;
13100 Py_BEGIN_ALLOW_THREADS
13101 result = eventfd_write(fd, value);
13102 Py_END_ALLOW_THREADS
13103 if (result == -1) {
13104 return PyErr_SetFromErrno(PyExc_OSError);
13105 }
13106 Py_RETURN_NONE;
13107 }
13108 #endif /* HAVE_EVENTFD */
13109
13110 /* Terminal size querying */
13111
13112 PyDoc_STRVAR(TerminalSize_docstring,
13113 "A tuple of (columns, lines) for holding terminal window size");
13114
13115 static PyStructSequence_Field TerminalSize_fields[] = {
13116 {"columns", "width of the terminal window in characters"},
13117 {"lines", "height of the terminal window in characters"},
13118 {NULL, NULL}
13119 };
13120
13121 static PyStructSequence_Desc TerminalSize_desc = {
13122 "os.terminal_size",
13123 TerminalSize_docstring,
13124 TerminalSize_fields,
13125 2,
13126 };
13127
13128 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
13129 /*[clinic input]
13130 os.get_terminal_size
13131
13132 fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
13133 /
13134
13135 Return the size of the terminal window as (columns, lines).
13136
13137 The optional argument fd (default standard output) specifies
13138 which file descriptor should be queried.
13139
13140 If the file descriptor is not connected to a terminal, an OSError
13141 is thrown.
13142
13143 This function will only be defined if an implementation is
13144 available for this system.
13145
13146 shutil.get_terminal_size is the high-level function which should
13147 normally be used, os.get_terminal_size is the low-level implementation.
13148 [clinic start generated code]*/
13149
13150 static PyObject *
os_get_terminal_size_impl(PyObject * module,int fd)13151 os_get_terminal_size_impl(PyObject *module, int fd)
13152 /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
13153 {
13154 int columns, lines;
13155 PyObject *termsize;
13156
13157 /* Under some conditions stdout may not be connected and
13158 * fileno(stdout) may point to an invalid file descriptor. For example
13159 * GUI apps don't have valid standard streams by default.
13160 *
13161 * If this happens, and the optional fd argument is not present,
13162 * the ioctl below will fail returning EBADF. This is what we want.
13163 */
13164
13165 #ifdef TERMSIZE_USE_IOCTL
13166 {
13167 struct winsize w;
13168 if (ioctl(fd, TIOCGWINSZ, &w))
13169 return PyErr_SetFromErrno(PyExc_OSError);
13170 columns = w.ws_col;
13171 lines = w.ws_row;
13172 }
13173 #endif /* TERMSIZE_USE_IOCTL */
13174
13175 #ifdef TERMSIZE_USE_CONIO
13176 {
13177 DWORD nhandle;
13178 HANDLE handle;
13179 CONSOLE_SCREEN_BUFFER_INFO csbi;
13180 switch (fd) {
13181 case 0: nhandle = STD_INPUT_HANDLE;
13182 break;
13183 case 1: nhandle = STD_OUTPUT_HANDLE;
13184 break;
13185 case 2: nhandle = STD_ERROR_HANDLE;
13186 break;
13187 default:
13188 return PyErr_Format(PyExc_ValueError, "bad file descriptor");
13189 }
13190 handle = GetStdHandle(nhandle);
13191 if (handle == NULL)
13192 return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
13193 if (handle == INVALID_HANDLE_VALUE)
13194 return PyErr_SetFromWindowsErr(0);
13195
13196 if (!GetConsoleScreenBufferInfo(handle, &csbi))
13197 return PyErr_SetFromWindowsErr(0);
13198
13199 columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
13200 lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
13201 }
13202 #endif /* TERMSIZE_USE_CONIO */
13203
13204 PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
13205 termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
13206 if (termsize == NULL)
13207 return NULL;
13208 PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
13209 PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
13210 if (PyErr_Occurred()) {
13211 Py_DECREF(termsize);
13212 return NULL;
13213 }
13214 return termsize;
13215 }
13216 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
13217
13218
13219 /*[clinic input]
13220 os.cpu_count
13221
13222 Return the number of CPUs in the system; return None if indeterminable.
13223
13224 This number is not equivalent to the number of CPUs the current process can
13225 use. The number of usable CPUs can be obtained with
13226 ``len(os.sched_getaffinity(0))``
13227 [clinic start generated code]*/
13228
13229 static PyObject *
os_cpu_count_impl(PyObject * module)13230 os_cpu_count_impl(PyObject *module)
13231 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
13232 {
13233 int ncpu = 0;
13234 #ifdef MS_WINDOWS
13235 ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
13236 #elif defined(__hpux)
13237 ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
13238 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
13239 ncpu = sysconf(_SC_NPROCESSORS_ONLN);
13240 #elif defined(__VXWORKS__)
13241 ncpu = _Py_popcount32(vxCpuEnabledGet());
13242 #elif defined(__DragonFly__) || \
13243 defined(__OpenBSD__) || \
13244 defined(__FreeBSD__) || \
13245 defined(__NetBSD__) || \
13246 defined(__APPLE__)
13247 int mib[2];
13248 size_t len = sizeof(ncpu);
13249 mib[0] = CTL_HW;
13250 mib[1] = HW_NCPU;
13251 if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
13252 ncpu = 0;
13253 #endif
13254 if (ncpu >= 1)
13255 return PyLong_FromLong(ncpu);
13256 else
13257 Py_RETURN_NONE;
13258 }
13259
13260
13261 /*[clinic input]
13262 os.get_inheritable -> bool
13263
13264 fd: int
13265 /
13266
13267 Get the close-on-exe flag of the specified file descriptor.
13268 [clinic start generated code]*/
13269
13270 static int
os_get_inheritable_impl(PyObject * module,int fd)13271 os_get_inheritable_impl(PyObject *module, int fd)
13272 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
13273 {
13274 int return_value;
13275 _Py_BEGIN_SUPPRESS_IPH
13276 return_value = _Py_get_inheritable(fd);
13277 _Py_END_SUPPRESS_IPH
13278 return return_value;
13279 }
13280
13281
13282 /*[clinic input]
13283 os.set_inheritable
13284 fd: int
13285 inheritable: int
13286 /
13287
13288 Set the inheritable flag of the specified file descriptor.
13289 [clinic start generated code]*/
13290
13291 static PyObject *
os_set_inheritable_impl(PyObject * module,int fd,int inheritable)13292 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
13293 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
13294 {
13295 int result;
13296
13297 _Py_BEGIN_SUPPRESS_IPH
13298 result = _Py_set_inheritable(fd, inheritable, NULL);
13299 _Py_END_SUPPRESS_IPH
13300 if (result < 0)
13301 return NULL;
13302 Py_RETURN_NONE;
13303 }
13304
13305
13306 #ifdef MS_WINDOWS
13307 /*[clinic input]
13308 os.get_handle_inheritable -> bool
13309 handle: intptr_t
13310 /
13311
13312 Get the close-on-exe flag of the specified file descriptor.
13313 [clinic start generated code]*/
13314
13315 static int
os_get_handle_inheritable_impl(PyObject * module,intptr_t handle)13316 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
13317 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
13318 {
13319 DWORD flags;
13320
13321 if (!GetHandleInformation((HANDLE)handle, &flags)) {
13322 PyErr_SetFromWindowsErr(0);
13323 return -1;
13324 }
13325
13326 return flags & HANDLE_FLAG_INHERIT;
13327 }
13328
13329
13330 /*[clinic input]
13331 os.set_handle_inheritable
13332 handle: intptr_t
13333 inheritable: bool
13334 /
13335
13336 Set the inheritable flag of the specified handle.
13337 [clinic start generated code]*/
13338
13339 static PyObject *
os_set_handle_inheritable_impl(PyObject * module,intptr_t handle,int inheritable)13340 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
13341 int inheritable)
13342 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
13343 {
13344 DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
13345 if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
13346 PyErr_SetFromWindowsErr(0);
13347 return NULL;
13348 }
13349 Py_RETURN_NONE;
13350 }
13351 #endif /* MS_WINDOWS */
13352
13353 #ifndef MS_WINDOWS
13354 /*[clinic input]
13355 os.get_blocking -> bool
13356 fd: int
13357 /
13358
13359 Get the blocking mode of the file descriptor.
13360
13361 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
13362 [clinic start generated code]*/
13363
13364 static int
os_get_blocking_impl(PyObject * module,int fd)13365 os_get_blocking_impl(PyObject *module, int fd)
13366 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
13367 {
13368 int blocking;
13369
13370 _Py_BEGIN_SUPPRESS_IPH
13371 blocking = _Py_get_blocking(fd);
13372 _Py_END_SUPPRESS_IPH
13373 return blocking;
13374 }
13375
13376 /*[clinic input]
13377 os.set_blocking
13378 fd: int
13379 blocking: bool(accept={int})
13380 /
13381
13382 Set the blocking mode of the specified file descriptor.
13383
13384 Set the O_NONBLOCK flag if blocking is False,
13385 clear the O_NONBLOCK flag otherwise.
13386 [clinic start generated code]*/
13387
13388 static PyObject *
os_set_blocking_impl(PyObject * module,int fd,int blocking)13389 os_set_blocking_impl(PyObject *module, int fd, int blocking)
13390 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
13391 {
13392 int result;
13393
13394 _Py_BEGIN_SUPPRESS_IPH
13395 result = _Py_set_blocking(fd, blocking);
13396 _Py_END_SUPPRESS_IPH
13397 if (result < 0)
13398 return NULL;
13399 Py_RETURN_NONE;
13400 }
13401 #endif /* !MS_WINDOWS */
13402
13403
13404 /*[clinic input]
13405 class os.DirEntry "DirEntry *" "DirEntryType"
13406 [clinic start generated code]*/
13407 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
13408
13409 typedef struct {
13410 PyObject_HEAD
13411 PyObject *name;
13412 PyObject *path;
13413 PyObject *stat;
13414 PyObject *lstat;
13415 #ifdef MS_WINDOWS
13416 struct _Py_stat_struct win32_lstat;
13417 uint64_t win32_file_index;
13418 int got_file_index;
13419 #else /* POSIX */
13420 #ifdef HAVE_DIRENT_D_TYPE
13421 unsigned char d_type;
13422 #endif
13423 ino_t d_ino;
13424 int dir_fd;
13425 #endif
13426 } DirEntry;
13427
13428 static void
DirEntry_dealloc(DirEntry * entry)13429 DirEntry_dealloc(DirEntry *entry)
13430 {
13431 PyTypeObject *tp = Py_TYPE(entry);
13432 Py_XDECREF(entry->name);
13433 Py_XDECREF(entry->path);
13434 Py_XDECREF(entry->stat);
13435 Py_XDECREF(entry->lstat);
13436 freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13437 free_func(entry);
13438 Py_DECREF(tp);
13439 }
13440
13441 /* Forward reference */
13442 static int
13443 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13444 int follow_symlinks, unsigned short mode_bits);
13445
13446 /*[clinic input]
13447 os.DirEntry.is_symlink -> bool
13448 defining_class: defining_class
13449 /
13450
13451 Return True if the entry is a symbolic link; cached per entry.
13452 [clinic start generated code]*/
13453
13454 static int
os_DirEntry_is_symlink_impl(DirEntry * self,PyTypeObject * defining_class)13455 os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
13456 /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
13457 {
13458 #ifdef MS_WINDOWS
13459 return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13460 #elif defined(HAVE_DIRENT_D_TYPE)
13461 /* POSIX */
13462 if (self->d_type != DT_UNKNOWN)
13463 return self->d_type == DT_LNK;
13464 else
13465 return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13466 #else
13467 /* POSIX without d_type */
13468 return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13469 #endif
13470 }
13471
13472 static PyObject *
DirEntry_fetch_stat(PyObject * module,DirEntry * self,int follow_symlinks)13473 DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
13474 {
13475 int result;
13476 STRUCT_STAT st;
13477 PyObject *ub;
13478
13479 #ifdef MS_WINDOWS
13480 if (!PyUnicode_FSDecoder(self->path, &ub))
13481 return NULL;
13482 #if USE_UNICODE_WCHAR_CACHE
13483 _Py_COMP_DIAG_PUSH
13484 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13485 const wchar_t *path = PyUnicode_AsUnicode(ub);
13486 _Py_COMP_DIAG_POP
13487 #else /* USE_UNICODE_WCHAR_CACHE */
13488 wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
13489 Py_DECREF(ub);
13490 #endif /* USE_UNICODE_WCHAR_CACHE */
13491 #else /* POSIX */
13492 if (!PyUnicode_FSConverter(self->path, &ub))
13493 return NULL;
13494 const char *path = PyBytes_AS_STRING(ub);
13495 if (self->dir_fd != DEFAULT_DIR_FD) {
13496 #ifdef HAVE_FSTATAT
13497 if (HAVE_FSTATAT_RUNTIME) {
13498 result = fstatat(self->dir_fd, path, &st,
13499 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
13500 } else
13501
13502 #endif /* HAVE_FSTATAT */
13503 {
13504 Py_DECREF(ub);
13505 PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
13506 return NULL;
13507 }
13508 }
13509 else
13510 #endif
13511 {
13512 if (follow_symlinks)
13513 result = STAT(path, &st);
13514 else
13515 result = LSTAT(path, &st);
13516 }
13517 #if defined(MS_WINDOWS) && !USE_UNICODE_WCHAR_CACHE
13518 PyMem_Free(path);
13519 #else /* USE_UNICODE_WCHAR_CACHE */
13520 Py_DECREF(ub);
13521 #endif /* USE_UNICODE_WCHAR_CACHE */
13522
13523 if (result != 0)
13524 return path_object_error(self->path);
13525
13526 return _pystat_fromstructstat(module, &st);
13527 }
13528
13529 static PyObject *
DirEntry_get_lstat(PyTypeObject * defining_class,DirEntry * self)13530 DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
13531 {
13532 if (!self->lstat) {
13533 PyObject *module = PyType_GetModule(defining_class);
13534 #ifdef MS_WINDOWS
13535 self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
13536 #else /* POSIX */
13537 self->lstat = DirEntry_fetch_stat(module, self, 0);
13538 #endif
13539 }
13540 Py_XINCREF(self->lstat);
13541 return self->lstat;
13542 }
13543
13544 /*[clinic input]
13545 os.DirEntry.stat
13546 defining_class: defining_class
13547 /
13548 *
13549 follow_symlinks: bool = True
13550
13551 Return stat_result object for the entry; cached per entry.
13552 [clinic start generated code]*/
13553
13554 static PyObject *
os_DirEntry_stat_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13555 os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
13556 int follow_symlinks)
13557 /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
13558 {
13559 if (!follow_symlinks) {
13560 return DirEntry_get_lstat(defining_class, self);
13561 }
13562
13563 if (!self->stat) {
13564 int result = os_DirEntry_is_symlink_impl(self, defining_class);
13565 if (result == -1) {
13566 return NULL;
13567 }
13568 if (result) {
13569 PyObject *module = PyType_GetModule(defining_class);
13570 self->stat = DirEntry_fetch_stat(module, self, 1);
13571 }
13572 else {
13573 self->stat = DirEntry_get_lstat(defining_class, self);
13574 }
13575 }
13576
13577 Py_XINCREF(self->stat);
13578 return self->stat;
13579 }
13580
13581 /* Set exception and return -1 on error, 0 for False, 1 for True */
13582 static int
DirEntry_test_mode(PyTypeObject * defining_class,DirEntry * self,int follow_symlinks,unsigned short mode_bits)13583 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13584 int follow_symlinks, unsigned short mode_bits)
13585 {
13586 PyObject *stat = NULL;
13587 PyObject *st_mode = NULL;
13588 long mode;
13589 int result;
13590 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13591 int is_symlink;
13592 int need_stat;
13593 #endif
13594 #ifdef MS_WINDOWS
13595 unsigned long dir_bits;
13596 #endif
13597
13598 #ifdef MS_WINDOWS
13599 is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13600 need_stat = follow_symlinks && is_symlink;
13601 #elif defined(HAVE_DIRENT_D_TYPE)
13602 is_symlink = self->d_type == DT_LNK;
13603 need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
13604 #endif
13605
13606 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13607 if (need_stat) {
13608 #endif
13609 stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
13610 if (!stat) {
13611 if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
13612 /* If file doesn't exist (anymore), then return False
13613 (i.e., say it's not a file/directory) */
13614 PyErr_Clear();
13615 return 0;
13616 }
13617 goto error;
13618 }
13619 _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
13620 st_mode = PyObject_GetAttr(stat, state->st_mode);
13621 if (!st_mode)
13622 goto error;
13623
13624 mode = PyLong_AsLong(st_mode);
13625 if (mode == -1 && PyErr_Occurred())
13626 goto error;
13627 Py_CLEAR(st_mode);
13628 Py_CLEAR(stat);
13629 result = (mode & S_IFMT) == mode_bits;
13630 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13631 }
13632 else if (is_symlink) {
13633 assert(mode_bits != S_IFLNK);
13634 result = 0;
13635 }
13636 else {
13637 assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
13638 #ifdef MS_WINDOWS
13639 dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
13640 if (mode_bits == S_IFDIR)
13641 result = dir_bits != 0;
13642 else
13643 result = dir_bits == 0;
13644 #else /* POSIX */
13645 if (mode_bits == S_IFDIR)
13646 result = self->d_type == DT_DIR;
13647 else
13648 result = self->d_type == DT_REG;
13649 #endif
13650 }
13651 #endif
13652
13653 return result;
13654
13655 error:
13656 Py_XDECREF(st_mode);
13657 Py_XDECREF(stat);
13658 return -1;
13659 }
13660
13661 /*[clinic input]
13662 os.DirEntry.is_dir -> bool
13663 defining_class: defining_class
13664 /
13665 *
13666 follow_symlinks: bool = True
13667
13668 Return True if the entry is a directory; cached per entry.
13669 [clinic start generated code]*/
13670
13671 static int
os_DirEntry_is_dir_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13672 os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
13673 int follow_symlinks)
13674 /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
13675 {
13676 return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
13677 }
13678
13679 /*[clinic input]
13680 os.DirEntry.is_file -> bool
13681 defining_class: defining_class
13682 /
13683 *
13684 follow_symlinks: bool = True
13685
13686 Return True if the entry is a file; cached per entry.
13687 [clinic start generated code]*/
13688
13689 static int
os_DirEntry_is_file_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13690 os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
13691 int follow_symlinks)
13692 /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
13693 {
13694 return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
13695 }
13696
13697 /*[clinic input]
13698 os.DirEntry.inode
13699
13700 Return inode of the entry; cached per entry.
13701 [clinic start generated code]*/
13702
13703 static PyObject *
os_DirEntry_inode_impl(DirEntry * self)13704 os_DirEntry_inode_impl(DirEntry *self)
13705 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
13706 {
13707 #ifdef MS_WINDOWS
13708 if (!self->got_file_index) {
13709 PyObject *unicode;
13710 STRUCT_STAT stat;
13711 int result;
13712
13713 if (!PyUnicode_FSDecoder(self->path, &unicode))
13714 return NULL;
13715 #if USE_UNICODE_WCHAR_CACHE
13716 _Py_COMP_DIAG_PUSH
13717 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13718 const wchar_t *path = PyUnicode_AsUnicode(unicode);
13719 result = LSTAT(path, &stat);
13720 Py_DECREF(unicode);
13721 _Py_COMP_DIAG_POP
13722 #else /* USE_UNICODE_WCHAR_CACHE */
13723 wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
13724 Py_DECREF(unicode);
13725 result = LSTAT(path, &stat);
13726 PyMem_Free(path);
13727 #endif /* USE_UNICODE_WCHAR_CACHE */
13728
13729 if (result != 0)
13730 return path_object_error(self->path);
13731
13732 self->win32_file_index = stat.st_ino;
13733 self->got_file_index = 1;
13734 }
13735 Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->win32_file_index));
13736 return PyLong_FromUnsignedLongLong(self->win32_file_index);
13737 #else /* POSIX */
13738 Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->d_ino));
13739 return PyLong_FromUnsignedLongLong(self->d_ino);
13740 #endif
13741 }
13742
13743 static PyObject *
DirEntry_repr(DirEntry * self)13744 DirEntry_repr(DirEntry *self)
13745 {
13746 return PyUnicode_FromFormat("<DirEntry %R>", self->name);
13747 }
13748
13749 /*[clinic input]
13750 os.DirEntry.__fspath__
13751
13752 Returns the path for the entry.
13753 [clinic start generated code]*/
13754
13755 static PyObject *
os_DirEntry___fspath___impl(DirEntry * self)13756 os_DirEntry___fspath___impl(DirEntry *self)
13757 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
13758 {
13759 Py_INCREF(self->path);
13760 return self->path;
13761 }
13762
13763 static PyMemberDef DirEntry_members[] = {
13764 {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
13765 "the entry's base filename, relative to scandir() \"path\" argument"},
13766 {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
13767 "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
13768 {NULL}
13769 };
13770
13771 #include "clinic/posixmodule.c.h"
13772
13773 static PyMethodDef DirEntry_methods[] = {
13774 OS_DIRENTRY_IS_DIR_METHODDEF
13775 OS_DIRENTRY_IS_FILE_METHODDEF
13776 OS_DIRENTRY_IS_SYMLINK_METHODDEF
13777 OS_DIRENTRY_STAT_METHODDEF
13778 OS_DIRENTRY_INODE_METHODDEF
13779 OS_DIRENTRY___FSPATH___METHODDEF
13780 {"__class_getitem__", (PyCFunction)Py_GenericAlias,
13781 METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
13782 {NULL}
13783 };
13784
13785 static PyType_Slot DirEntryType_slots[] = {
13786 {Py_tp_dealloc, DirEntry_dealloc},
13787 {Py_tp_repr, DirEntry_repr},
13788 {Py_tp_methods, DirEntry_methods},
13789 {Py_tp_members, DirEntry_members},
13790 {0, 0},
13791 };
13792
13793 static PyType_Spec DirEntryType_spec = {
13794 MODNAME ".DirEntry",
13795 sizeof(DirEntry),
13796 0,
13797 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
13798 DirEntryType_slots
13799 };
13800
13801
13802 #ifdef MS_WINDOWS
13803
13804 static wchar_t *
join_path_filenameW(const wchar_t * path_wide,const wchar_t * filename)13805 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
13806 {
13807 Py_ssize_t path_len;
13808 Py_ssize_t size;
13809 wchar_t *result;
13810 wchar_t ch;
13811
13812 if (!path_wide) { /* Default arg: "." */
13813 path_wide = L".";
13814 path_len = 1;
13815 }
13816 else {
13817 path_len = wcslen(path_wide);
13818 }
13819
13820 /* The +1's are for the path separator and the NUL */
13821 size = path_len + 1 + wcslen(filename) + 1;
13822 result = PyMem_New(wchar_t, size);
13823 if (!result) {
13824 PyErr_NoMemory();
13825 return NULL;
13826 }
13827 wcscpy(result, path_wide);
13828 if (path_len > 0) {
13829 ch = result[path_len - 1];
13830 if (ch != SEP && ch != ALTSEP && ch != L':')
13831 result[path_len++] = SEP;
13832 wcscpy(result + path_len, filename);
13833 }
13834 return result;
13835 }
13836
13837 static PyObject *
DirEntry_from_find_data(PyObject * module,path_t * path,WIN32_FIND_DATAW * dataW)13838 DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
13839 {
13840 DirEntry *entry;
13841 BY_HANDLE_FILE_INFORMATION file_info;
13842 ULONG reparse_tag;
13843 wchar_t *joined_path;
13844
13845 PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13846 entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13847 if (!entry)
13848 return NULL;
13849 entry->name = NULL;
13850 entry->path = NULL;
13851 entry->stat = NULL;
13852 entry->lstat = NULL;
13853 entry->got_file_index = 0;
13854
13855 entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
13856 if (!entry->name)
13857 goto error;
13858 if (path->narrow) {
13859 Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
13860 if (!entry->name)
13861 goto error;
13862 }
13863
13864 joined_path = join_path_filenameW(path->wide, dataW->cFileName);
13865 if (!joined_path)
13866 goto error;
13867
13868 entry->path = PyUnicode_FromWideChar(joined_path, -1);
13869 PyMem_Free(joined_path);
13870 if (!entry->path)
13871 goto error;
13872 if (path->narrow) {
13873 Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
13874 if (!entry->path)
13875 goto error;
13876 }
13877
13878 find_data_to_file_info(dataW, &file_info, &reparse_tag);
13879 _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
13880
13881 return (PyObject *)entry;
13882
13883 error:
13884 Py_DECREF(entry);
13885 return NULL;
13886 }
13887
13888 #else /* POSIX */
13889
13890 static char *
join_path_filename(const char * path_narrow,const char * filename,Py_ssize_t filename_len)13891 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
13892 {
13893 Py_ssize_t path_len;
13894 Py_ssize_t size;
13895 char *result;
13896
13897 if (!path_narrow) { /* Default arg: "." */
13898 path_narrow = ".";
13899 path_len = 1;
13900 }
13901 else {
13902 path_len = strlen(path_narrow);
13903 }
13904
13905 if (filename_len == -1)
13906 filename_len = strlen(filename);
13907
13908 /* The +1's are for the path separator and the NUL */
13909 size = path_len + 1 + filename_len + 1;
13910 result = PyMem_New(char, size);
13911 if (!result) {
13912 PyErr_NoMemory();
13913 return NULL;
13914 }
13915 strcpy(result, path_narrow);
13916 if (path_len > 0 && result[path_len - 1] != '/')
13917 result[path_len++] = '/';
13918 strcpy(result + path_len, filename);
13919 return result;
13920 }
13921
13922 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)13923 DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
13924 Py_ssize_t name_len, ino_t d_ino
13925 #ifdef HAVE_DIRENT_D_TYPE
13926 , unsigned char d_type
13927 #endif
13928 )
13929 {
13930 DirEntry *entry;
13931 char *joined_path;
13932
13933 PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13934 entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13935 if (!entry)
13936 return NULL;
13937 entry->name = NULL;
13938 entry->path = NULL;
13939 entry->stat = NULL;
13940 entry->lstat = NULL;
13941
13942 if (path->fd != -1) {
13943 entry->dir_fd = path->fd;
13944 joined_path = NULL;
13945 }
13946 else {
13947 entry->dir_fd = DEFAULT_DIR_FD;
13948 joined_path = join_path_filename(path->narrow, name, name_len);
13949 if (!joined_path)
13950 goto error;
13951 }
13952
13953 if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
13954 entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
13955 if (joined_path)
13956 entry->path = PyUnicode_DecodeFSDefault(joined_path);
13957 }
13958 else {
13959 entry->name = PyBytes_FromStringAndSize(name, name_len);
13960 if (joined_path)
13961 entry->path = PyBytes_FromString(joined_path);
13962 }
13963 PyMem_Free(joined_path);
13964 if (!entry->name)
13965 goto error;
13966
13967 if (path->fd != -1) {
13968 entry->path = entry->name;
13969 Py_INCREF(entry->path);
13970 }
13971 else if (!entry->path)
13972 goto error;
13973
13974 #ifdef HAVE_DIRENT_D_TYPE
13975 entry->d_type = d_type;
13976 #endif
13977 entry->d_ino = d_ino;
13978
13979 return (PyObject *)entry;
13980
13981 error:
13982 Py_XDECREF(entry);
13983 return NULL;
13984 }
13985
13986 #endif
13987
13988
13989 typedef struct {
13990 PyObject_HEAD
13991 path_t path;
13992 #ifdef MS_WINDOWS
13993 HANDLE handle;
13994 WIN32_FIND_DATAW file_data;
13995 int first_time;
13996 #else /* POSIX */
13997 DIR *dirp;
13998 #endif
13999 #ifdef HAVE_FDOPENDIR
14000 int fd;
14001 #endif
14002 } ScandirIterator;
14003
14004 #ifdef MS_WINDOWS
14005
14006 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14007 ScandirIterator_is_closed(ScandirIterator *iterator)
14008 {
14009 return iterator->handle == INVALID_HANDLE_VALUE;
14010 }
14011
14012 static void
ScandirIterator_closedir(ScandirIterator * iterator)14013 ScandirIterator_closedir(ScandirIterator *iterator)
14014 {
14015 HANDLE handle = iterator->handle;
14016
14017 if (handle == INVALID_HANDLE_VALUE)
14018 return;
14019
14020 iterator->handle = INVALID_HANDLE_VALUE;
14021 Py_BEGIN_ALLOW_THREADS
14022 FindClose(handle);
14023 Py_END_ALLOW_THREADS
14024 }
14025
14026 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14027 ScandirIterator_iternext(ScandirIterator *iterator)
14028 {
14029 WIN32_FIND_DATAW *file_data = &iterator->file_data;
14030 BOOL success;
14031 PyObject *entry;
14032
14033 /* Happens if the iterator is iterated twice, or closed explicitly */
14034 if (iterator->handle == INVALID_HANDLE_VALUE)
14035 return NULL;
14036
14037 while (1) {
14038 if (!iterator->first_time) {
14039 Py_BEGIN_ALLOW_THREADS
14040 success = FindNextFileW(iterator->handle, file_data);
14041 Py_END_ALLOW_THREADS
14042 if (!success) {
14043 /* Error or no more files */
14044 if (GetLastError() != ERROR_NO_MORE_FILES)
14045 path_error(&iterator->path);
14046 break;
14047 }
14048 }
14049 iterator->first_time = 0;
14050
14051 /* Skip over . and .. */
14052 if (wcscmp(file_data->cFileName, L".") != 0 &&
14053 wcscmp(file_data->cFileName, L"..") != 0)
14054 {
14055 PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14056 entry = DirEntry_from_find_data(module, &iterator->path, file_data);
14057 if (!entry)
14058 break;
14059 return entry;
14060 }
14061
14062 /* Loop till we get a non-dot directory or finish iterating */
14063 }
14064
14065 /* Error or no more files */
14066 ScandirIterator_closedir(iterator);
14067 return NULL;
14068 }
14069
14070 #else /* POSIX */
14071
14072 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14073 ScandirIterator_is_closed(ScandirIterator *iterator)
14074 {
14075 return !iterator->dirp;
14076 }
14077
14078 static void
ScandirIterator_closedir(ScandirIterator * iterator)14079 ScandirIterator_closedir(ScandirIterator *iterator)
14080 {
14081 DIR *dirp = iterator->dirp;
14082
14083 if (!dirp)
14084 return;
14085
14086 iterator->dirp = NULL;
14087 Py_BEGIN_ALLOW_THREADS
14088 #ifdef HAVE_FDOPENDIR
14089 if (iterator->path.fd != -1)
14090 rewinddir(dirp);
14091 #endif
14092 closedir(dirp);
14093 Py_END_ALLOW_THREADS
14094 return;
14095 }
14096
14097 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14098 ScandirIterator_iternext(ScandirIterator *iterator)
14099 {
14100 struct dirent *direntp;
14101 Py_ssize_t name_len;
14102 int is_dot;
14103 PyObject *entry;
14104
14105 /* Happens if the iterator is iterated twice, or closed explicitly */
14106 if (!iterator->dirp)
14107 return NULL;
14108
14109 while (1) {
14110 errno = 0;
14111 Py_BEGIN_ALLOW_THREADS
14112 direntp = readdir(iterator->dirp);
14113 Py_END_ALLOW_THREADS
14114
14115 if (!direntp) {
14116 /* Error or no more files */
14117 if (errno != 0)
14118 path_error(&iterator->path);
14119 break;
14120 }
14121
14122 /* Skip over . and .. */
14123 name_len = NAMLEN(direntp);
14124 is_dot = direntp->d_name[0] == '.' &&
14125 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
14126 if (!is_dot) {
14127 PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14128 entry = DirEntry_from_posix_info(module,
14129 &iterator->path, direntp->d_name,
14130 name_len, direntp->d_ino
14131 #ifdef HAVE_DIRENT_D_TYPE
14132 , direntp->d_type
14133 #endif
14134 );
14135 if (!entry)
14136 break;
14137 return entry;
14138 }
14139
14140 /* Loop till we get a non-dot directory or finish iterating */
14141 }
14142
14143 /* Error or no more files */
14144 ScandirIterator_closedir(iterator);
14145 return NULL;
14146 }
14147
14148 #endif
14149
14150 static PyObject *
ScandirIterator_close(ScandirIterator * self,PyObject * args)14151 ScandirIterator_close(ScandirIterator *self, PyObject *args)
14152 {
14153 ScandirIterator_closedir(self);
14154 Py_RETURN_NONE;
14155 }
14156
14157 static PyObject *
ScandirIterator_enter(PyObject * self,PyObject * args)14158 ScandirIterator_enter(PyObject *self, PyObject *args)
14159 {
14160 Py_INCREF(self);
14161 return self;
14162 }
14163
14164 static PyObject *
ScandirIterator_exit(ScandirIterator * self,PyObject * args)14165 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
14166 {
14167 ScandirIterator_closedir(self);
14168 Py_RETURN_NONE;
14169 }
14170
14171 static void
ScandirIterator_finalize(ScandirIterator * iterator)14172 ScandirIterator_finalize(ScandirIterator *iterator)
14173 {
14174 PyObject *error_type, *error_value, *error_traceback;
14175
14176 /* Save the current exception, if any. */
14177 PyErr_Fetch(&error_type, &error_value, &error_traceback);
14178
14179 if (!ScandirIterator_is_closed(iterator)) {
14180 ScandirIterator_closedir(iterator);
14181
14182 if (PyErr_ResourceWarning((PyObject *)iterator, 1,
14183 "unclosed scandir iterator %R", iterator)) {
14184 /* Spurious errors can appear at shutdown */
14185 if (PyErr_ExceptionMatches(PyExc_Warning)) {
14186 PyErr_WriteUnraisable((PyObject *) iterator);
14187 }
14188 }
14189 }
14190
14191 path_cleanup(&iterator->path);
14192
14193 /* Restore the saved exception. */
14194 PyErr_Restore(error_type, error_value, error_traceback);
14195 }
14196
14197 static void
ScandirIterator_dealloc(ScandirIterator * iterator)14198 ScandirIterator_dealloc(ScandirIterator *iterator)
14199 {
14200 PyTypeObject *tp = Py_TYPE(iterator);
14201 if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
14202 return;
14203
14204 freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
14205 free_func(iterator);
14206 Py_DECREF(tp);
14207 }
14208
14209 static PyMethodDef ScandirIterator_methods[] = {
14210 {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
14211 {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
14212 {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
14213 {NULL}
14214 };
14215
14216 static PyType_Slot ScandirIteratorType_slots[] = {
14217 {Py_tp_dealloc, ScandirIterator_dealloc},
14218 {Py_tp_finalize, ScandirIterator_finalize},
14219 {Py_tp_iter, PyObject_SelfIter},
14220 {Py_tp_iternext, ScandirIterator_iternext},
14221 {Py_tp_methods, ScandirIterator_methods},
14222 {0, 0},
14223 };
14224
14225 static PyType_Spec ScandirIteratorType_spec = {
14226 MODNAME ".ScandirIterator",
14227 sizeof(ScandirIterator),
14228 0,
14229 // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
14230 // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
14231 (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
14232 | Py_TPFLAGS_DISALLOW_INSTANTIATION),
14233 ScandirIteratorType_slots
14234 };
14235
14236 /*[clinic input]
14237 os.scandir
14238
14239 path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
14240
14241 Return an iterator of DirEntry objects for given path.
14242
14243 path can be specified as either str, bytes, or a path-like object. If path
14244 is bytes, the names of yielded DirEntry objects will also be bytes; in
14245 all other circumstances they will be str.
14246
14247 If path is None, uses the path='.'.
14248 [clinic start generated code]*/
14249
14250 static PyObject *
os_scandir_impl(PyObject * module,path_t * path)14251 os_scandir_impl(PyObject *module, path_t *path)
14252 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
14253 {
14254 ScandirIterator *iterator;
14255 #ifdef MS_WINDOWS
14256 wchar_t *path_strW;
14257 #else
14258 const char *path_str;
14259 #ifdef HAVE_FDOPENDIR
14260 int fd = -1;
14261 #endif
14262 #endif
14263
14264 if (PySys_Audit("os.scandir", "O",
14265 path->object ? path->object : Py_None) < 0) {
14266 return NULL;
14267 }
14268
14269 PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
14270 iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
14271 if (!iterator)
14272 return NULL;
14273
14274 #ifdef MS_WINDOWS
14275 iterator->handle = INVALID_HANDLE_VALUE;
14276 #else
14277 iterator->dirp = NULL;
14278 #endif
14279
14280 /* Move the ownership to iterator->path */
14281 memcpy(&iterator->path, path, sizeof(path_t));
14282 memset(path, 0, sizeof(path_t));
14283
14284 #ifdef MS_WINDOWS
14285 iterator->first_time = 1;
14286
14287 path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
14288 if (!path_strW)
14289 goto error;
14290
14291 Py_BEGIN_ALLOW_THREADS
14292 iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
14293 Py_END_ALLOW_THREADS
14294
14295 PyMem_Free(path_strW);
14296
14297 if (iterator->handle == INVALID_HANDLE_VALUE) {
14298 path_error(&iterator->path);
14299 goto error;
14300 }
14301 #else /* POSIX */
14302 errno = 0;
14303 #ifdef HAVE_FDOPENDIR
14304 if (iterator->path.fd != -1) {
14305 if (HAVE_FDOPENDIR_RUNTIME) {
14306 /* closedir() closes the FD, so we duplicate it */
14307 fd = _Py_dup(iterator->path.fd);
14308 if (fd == -1)
14309 goto error;
14310
14311 Py_BEGIN_ALLOW_THREADS
14312 iterator->dirp = fdopendir(fd);
14313 Py_END_ALLOW_THREADS
14314 } else {
14315 PyErr_SetString(PyExc_TypeError,
14316 "scandir: path should be string, bytes, os.PathLike or None, not int");
14317 return NULL;
14318 }
14319 }
14320 else
14321 #endif
14322 {
14323 if (iterator->path.narrow)
14324 path_str = iterator->path.narrow;
14325 else
14326 path_str = ".";
14327
14328 Py_BEGIN_ALLOW_THREADS
14329 iterator->dirp = opendir(path_str);
14330 Py_END_ALLOW_THREADS
14331 }
14332
14333 if (!iterator->dirp) {
14334 path_error(&iterator->path);
14335 #ifdef HAVE_FDOPENDIR
14336 if (fd != -1) {
14337 Py_BEGIN_ALLOW_THREADS
14338 close(fd);
14339 Py_END_ALLOW_THREADS
14340 }
14341 #endif
14342 goto error;
14343 }
14344 #endif
14345
14346 return (PyObject *)iterator;
14347
14348 error:
14349 Py_DECREF(iterator);
14350 return NULL;
14351 }
14352
14353 /*
14354 Return the file system path representation of the object.
14355
14356 If the object is str or bytes, then allow it to pass through with
14357 an incremented refcount. If the object defines __fspath__(), then
14358 return the result of that method. All other types raise a TypeError.
14359 */
14360 PyObject *
PyOS_FSPath(PyObject * path)14361 PyOS_FSPath(PyObject *path)
14362 {
14363 /* For error message reasons, this function is manually inlined in
14364 path_converter(). */
14365 PyObject *func = NULL;
14366 PyObject *path_repr = NULL;
14367
14368 if (PyUnicode_Check(path) || PyBytes_Check(path)) {
14369 Py_INCREF(path);
14370 return path;
14371 }
14372
14373 func = _PyObject_LookupSpecial(path, &PyId___fspath__);
14374 if (NULL == func) {
14375 return PyErr_Format(PyExc_TypeError,
14376 "expected str, bytes or os.PathLike object, "
14377 "not %.200s",
14378 _PyType_Name(Py_TYPE(path)));
14379 }
14380
14381 path_repr = _PyObject_CallNoArg(func);
14382 Py_DECREF(func);
14383 if (NULL == path_repr) {
14384 return NULL;
14385 }
14386
14387 if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
14388 PyErr_Format(PyExc_TypeError,
14389 "expected %.200s.__fspath__() to return str or bytes, "
14390 "not %.200s", _PyType_Name(Py_TYPE(path)),
14391 _PyType_Name(Py_TYPE(path_repr)));
14392 Py_DECREF(path_repr);
14393 return NULL;
14394 }
14395
14396 return path_repr;
14397 }
14398
14399 /*[clinic input]
14400 os.fspath
14401
14402 path: object
14403
14404 Return the file system path representation of the object.
14405
14406 If the object is str or bytes, then allow it to pass through as-is. If the
14407 object defines __fspath__(), then return the result of that method. All other
14408 types raise a TypeError.
14409 [clinic start generated code]*/
14410
14411 static PyObject *
os_fspath_impl(PyObject * module,PyObject * path)14412 os_fspath_impl(PyObject *module, PyObject *path)
14413 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
14414 {
14415 return PyOS_FSPath(path);
14416 }
14417
14418 #ifdef HAVE_GETRANDOM_SYSCALL
14419 /*[clinic input]
14420 os.getrandom
14421
14422 size: Py_ssize_t
14423 flags: int=0
14424
14425 Obtain a series of random bytes.
14426 [clinic start generated code]*/
14427
14428 static PyObject *
os_getrandom_impl(PyObject * module,Py_ssize_t size,int flags)14429 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
14430 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
14431 {
14432 PyObject *bytes;
14433 Py_ssize_t n;
14434
14435 if (size < 0) {
14436 errno = EINVAL;
14437 return posix_error();
14438 }
14439
14440 bytes = PyBytes_FromStringAndSize(NULL, size);
14441 if (bytes == NULL) {
14442 PyErr_NoMemory();
14443 return NULL;
14444 }
14445
14446 while (1) {
14447 n = syscall(SYS_getrandom,
14448 PyBytes_AS_STRING(bytes),
14449 PyBytes_GET_SIZE(bytes),
14450 flags);
14451 if (n < 0 && errno == EINTR) {
14452 if (PyErr_CheckSignals() < 0) {
14453 goto error;
14454 }
14455
14456 /* getrandom() was interrupted by a signal: retry */
14457 continue;
14458 }
14459 break;
14460 }
14461
14462 if (n < 0) {
14463 PyErr_SetFromErrno(PyExc_OSError);
14464 goto error;
14465 }
14466
14467 if (n != size) {
14468 _PyBytes_Resize(&bytes, n);
14469 }
14470
14471 return bytes;
14472
14473 error:
14474 Py_DECREF(bytes);
14475 return NULL;
14476 }
14477 #endif /* HAVE_GETRANDOM_SYSCALL */
14478
14479 #ifdef MS_WINDOWS
14480 /* bpo-36085: Helper functions for managing DLL search directories
14481 * on win32
14482 */
14483
14484 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
14485 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
14486
14487 /*[clinic input]
14488 os._add_dll_directory
14489
14490 path: path_t
14491
14492 Add a path to the DLL search path.
14493
14494 This search path is used when resolving dependencies for imported
14495 extension modules (the module itself is resolved through sys.path),
14496 and also by ctypes.
14497
14498 Returns an opaque value that may be passed to os.remove_dll_directory
14499 to remove this directory from the search path.
14500 [clinic start generated code]*/
14501
14502 static PyObject *
os__add_dll_directory_impl(PyObject * module,path_t * path)14503 os__add_dll_directory_impl(PyObject *module, path_t *path)
14504 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
14505 {
14506 HMODULE hKernel32;
14507 PAddDllDirectory AddDllDirectory;
14508 DLL_DIRECTORY_COOKIE cookie = 0;
14509 DWORD err = 0;
14510
14511 if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
14512 return NULL;
14513 }
14514
14515 /* For Windows 7, we have to load this. As this will be a fairly
14516 infrequent operation, just do it each time. Kernel32 is always
14517 loaded. */
14518 Py_BEGIN_ALLOW_THREADS
14519 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14520 !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
14521 hKernel32, "AddDllDirectory")) ||
14522 !(cookie = (*AddDllDirectory)(path->wide))) {
14523 err = GetLastError();
14524 }
14525 Py_END_ALLOW_THREADS
14526
14527 if (err) {
14528 return win32_error_object_err("add_dll_directory",
14529 path->object, err);
14530 }
14531
14532 return PyCapsule_New(cookie, "DLL directory cookie", NULL);
14533 }
14534
14535 /*[clinic input]
14536 os._remove_dll_directory
14537
14538 cookie: object
14539
14540 Removes a path from the DLL search path.
14541
14542 The parameter is an opaque value that was returned from
14543 os.add_dll_directory. You can only remove directories that you added
14544 yourself.
14545 [clinic start generated code]*/
14546
14547 static PyObject *
os__remove_dll_directory_impl(PyObject * module,PyObject * cookie)14548 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
14549 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
14550 {
14551 HMODULE hKernel32;
14552 PRemoveDllDirectory RemoveDllDirectory;
14553 DLL_DIRECTORY_COOKIE cookieValue;
14554 DWORD err = 0;
14555
14556 if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
14557 PyErr_SetString(PyExc_TypeError,
14558 "Provided cookie was not returned from os.add_dll_directory");
14559 return NULL;
14560 }
14561
14562 cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
14563 cookie, "DLL directory cookie");
14564
14565 /* For Windows 7, we have to load this. As this will be a fairly
14566 infrequent operation, just do it each time. Kernel32 is always
14567 loaded. */
14568 Py_BEGIN_ALLOW_THREADS
14569 if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14570 !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
14571 hKernel32, "RemoveDllDirectory")) ||
14572 !(*RemoveDllDirectory)(cookieValue)) {
14573 err = GetLastError();
14574 }
14575 Py_END_ALLOW_THREADS
14576
14577 if (err) {
14578 return win32_error_object_err("remove_dll_directory",
14579 NULL, err);
14580 }
14581
14582 if (PyCapsule_SetName(cookie, NULL)) {
14583 return NULL;
14584 }
14585
14586 Py_RETURN_NONE;
14587 }
14588
14589 #endif
14590
14591
14592 /* Only check if WIFEXITED is available: expect that it comes
14593 with WEXITSTATUS, WIFSIGNALED, etc.
14594
14595 os.waitstatus_to_exitcode() is implemented in C and not in Python, so
14596 subprocess can safely call it during late Python finalization without
14597 risking that used os attributes were set to None by finalize_modules(). */
14598 #if defined(WIFEXITED) || defined(MS_WINDOWS)
14599 /*[clinic input]
14600 os.waitstatus_to_exitcode
14601
14602 status as status_obj: object
14603
14604 Convert a wait status to an exit code.
14605
14606 On Unix:
14607
14608 * If WIFEXITED(status) is true, return WEXITSTATUS(status).
14609 * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
14610 * Otherwise, raise a ValueError.
14611
14612 On Windows, return status shifted right by 8 bits.
14613
14614 On Unix, if the process is being traced or if waitpid() was called with
14615 WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
14616 This function must not be called if WIFSTOPPED(status) is true.
14617 [clinic start generated code]*/
14618
14619 static PyObject *
os_waitstatus_to_exitcode_impl(PyObject * module,PyObject * status_obj)14620 os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
14621 /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
14622 {
14623 #ifndef MS_WINDOWS
14624 int status = _PyLong_AsInt(status_obj);
14625 if (status == -1 && PyErr_Occurred()) {
14626 return NULL;
14627 }
14628
14629 WAIT_TYPE wait_status;
14630 WAIT_STATUS_INT(wait_status) = status;
14631 int exitcode;
14632 if (WIFEXITED(wait_status)) {
14633 exitcode = WEXITSTATUS(wait_status);
14634 /* Sanity check to provide warranty on the function behavior.
14635 It should not occur in practice */
14636 if (exitcode < 0) {
14637 PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
14638 return NULL;
14639 }
14640 }
14641 else if (WIFSIGNALED(wait_status)) {
14642 int signum = WTERMSIG(wait_status);
14643 /* Sanity check to provide warranty on the function behavior.
14644 It should not occurs in practice */
14645 if (signum <= 0) {
14646 PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
14647 return NULL;
14648 }
14649 exitcode = -signum;
14650 } else if (WIFSTOPPED(wait_status)) {
14651 /* Status only received if the process is being traced
14652 or if waitpid() was called with WUNTRACED option. */
14653 int signum = WSTOPSIG(wait_status);
14654 PyErr_Format(PyExc_ValueError,
14655 "process stopped by delivery of signal %i",
14656 signum);
14657 return NULL;
14658 }
14659 else {
14660 PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
14661 return NULL;
14662 }
14663 return PyLong_FromLong(exitcode);
14664 #else
14665 /* Windows implementation: see os.waitpid() implementation
14666 which uses _cwait(). */
14667 unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
14668 if (status == (unsigned long long)-1 && PyErr_Occurred()) {
14669 return NULL;
14670 }
14671
14672 unsigned long long exitcode = (status >> 8);
14673 /* ExitProcess() accepts an UINT type:
14674 reject exit code which doesn't fit in an UINT */
14675 if (exitcode > UINT_MAX) {
14676 PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
14677 return NULL;
14678 }
14679 return PyLong_FromUnsignedLong((unsigned long)exitcode);
14680 #endif
14681 }
14682 #endif
14683
14684
14685 static PyMethodDef posix_methods[] = {
14686
14687 OS_STAT_METHODDEF
14688 OS_ACCESS_METHODDEF
14689 OS_TTYNAME_METHODDEF
14690 OS_CHDIR_METHODDEF
14691 OS_CHFLAGS_METHODDEF
14692 OS_CHMOD_METHODDEF
14693 OS_FCHMOD_METHODDEF
14694 OS_LCHMOD_METHODDEF
14695 OS_CHOWN_METHODDEF
14696 OS_FCHOWN_METHODDEF
14697 OS_LCHOWN_METHODDEF
14698 OS_LCHFLAGS_METHODDEF
14699 OS_CHROOT_METHODDEF
14700 OS_CTERMID_METHODDEF
14701 OS_GETCWD_METHODDEF
14702 OS_GETCWDB_METHODDEF
14703 OS_LINK_METHODDEF
14704 OS_LISTDIR_METHODDEF
14705 OS_LSTAT_METHODDEF
14706 OS_MKDIR_METHODDEF
14707 OS_NICE_METHODDEF
14708 OS_GETPRIORITY_METHODDEF
14709 OS_SETPRIORITY_METHODDEF
14710 OS_POSIX_SPAWN_METHODDEF
14711 OS_POSIX_SPAWNP_METHODDEF
14712 OS_READLINK_METHODDEF
14713 OS_COPY_FILE_RANGE_METHODDEF
14714 OS_SPLICE_METHODDEF
14715 OS_RENAME_METHODDEF
14716 OS_REPLACE_METHODDEF
14717 OS_RMDIR_METHODDEF
14718 OS_SYMLINK_METHODDEF
14719 OS_SYSTEM_METHODDEF
14720 OS_UMASK_METHODDEF
14721 OS_UNAME_METHODDEF
14722 OS_UNLINK_METHODDEF
14723 OS_REMOVE_METHODDEF
14724 OS_UTIME_METHODDEF
14725 OS_TIMES_METHODDEF
14726 OS__EXIT_METHODDEF
14727 OS__FCOPYFILE_METHODDEF
14728 OS_EXECV_METHODDEF
14729 OS_EXECVE_METHODDEF
14730 OS_SPAWNV_METHODDEF
14731 OS_SPAWNVE_METHODDEF
14732 OS_FORK1_METHODDEF
14733 OS_FORK_METHODDEF
14734 OS_REGISTER_AT_FORK_METHODDEF
14735 OS_SCHED_GET_PRIORITY_MAX_METHODDEF
14736 OS_SCHED_GET_PRIORITY_MIN_METHODDEF
14737 OS_SCHED_GETPARAM_METHODDEF
14738 OS_SCHED_GETSCHEDULER_METHODDEF
14739 OS_SCHED_RR_GET_INTERVAL_METHODDEF
14740 OS_SCHED_SETPARAM_METHODDEF
14741 OS_SCHED_SETSCHEDULER_METHODDEF
14742 OS_SCHED_YIELD_METHODDEF
14743 OS_SCHED_SETAFFINITY_METHODDEF
14744 OS_SCHED_GETAFFINITY_METHODDEF
14745 OS_OPENPTY_METHODDEF
14746 OS_FORKPTY_METHODDEF
14747 OS_GETEGID_METHODDEF
14748 OS_GETEUID_METHODDEF
14749 OS_GETGID_METHODDEF
14750 OS_GETGROUPLIST_METHODDEF
14751 OS_GETGROUPS_METHODDEF
14752 OS_GETPID_METHODDEF
14753 OS_GETPGRP_METHODDEF
14754 OS_GETPPID_METHODDEF
14755 OS_GETUID_METHODDEF
14756 OS_GETLOGIN_METHODDEF
14757 OS_KILL_METHODDEF
14758 OS_KILLPG_METHODDEF
14759 OS_PLOCK_METHODDEF
14760 OS_STARTFILE_METHODDEF
14761 OS_SETUID_METHODDEF
14762 OS_SETEUID_METHODDEF
14763 OS_SETREUID_METHODDEF
14764 OS_SETGID_METHODDEF
14765 OS_SETEGID_METHODDEF
14766 OS_SETREGID_METHODDEF
14767 OS_SETGROUPS_METHODDEF
14768 OS_INITGROUPS_METHODDEF
14769 OS_GETPGID_METHODDEF
14770 OS_SETPGRP_METHODDEF
14771 OS_WAIT_METHODDEF
14772 OS_WAIT3_METHODDEF
14773 OS_WAIT4_METHODDEF
14774 OS_WAITID_METHODDEF
14775 OS_WAITPID_METHODDEF
14776 OS_PIDFD_OPEN_METHODDEF
14777 OS_GETSID_METHODDEF
14778 OS_SETSID_METHODDEF
14779 OS_SETPGID_METHODDEF
14780 OS_TCGETPGRP_METHODDEF
14781 OS_TCSETPGRP_METHODDEF
14782 OS_OPEN_METHODDEF
14783 OS_CLOSE_METHODDEF
14784 OS_CLOSERANGE_METHODDEF
14785 OS_DEVICE_ENCODING_METHODDEF
14786 OS_DUP_METHODDEF
14787 OS_DUP2_METHODDEF
14788 OS_LOCKF_METHODDEF
14789 OS_LSEEK_METHODDEF
14790 OS_READ_METHODDEF
14791 OS_READV_METHODDEF
14792 OS_PREAD_METHODDEF
14793 OS_PREADV_METHODDEF
14794 OS_WRITE_METHODDEF
14795 OS_WRITEV_METHODDEF
14796 OS_PWRITE_METHODDEF
14797 OS_PWRITEV_METHODDEF
14798 OS_SENDFILE_METHODDEF
14799 OS_FSTAT_METHODDEF
14800 OS_ISATTY_METHODDEF
14801 OS_PIPE_METHODDEF
14802 OS_PIPE2_METHODDEF
14803 OS_MKFIFO_METHODDEF
14804 OS_MKNOD_METHODDEF
14805 OS_MAJOR_METHODDEF
14806 OS_MINOR_METHODDEF
14807 OS_MAKEDEV_METHODDEF
14808 OS_FTRUNCATE_METHODDEF
14809 OS_TRUNCATE_METHODDEF
14810 OS_POSIX_FALLOCATE_METHODDEF
14811 OS_POSIX_FADVISE_METHODDEF
14812 OS_PUTENV_METHODDEF
14813 OS_UNSETENV_METHODDEF
14814 OS_STRERROR_METHODDEF
14815 OS_FCHDIR_METHODDEF
14816 OS_FSYNC_METHODDEF
14817 OS_SYNC_METHODDEF
14818 OS_FDATASYNC_METHODDEF
14819 OS_WCOREDUMP_METHODDEF
14820 OS_WIFCONTINUED_METHODDEF
14821 OS_WIFSTOPPED_METHODDEF
14822 OS_WIFSIGNALED_METHODDEF
14823 OS_WIFEXITED_METHODDEF
14824 OS_WEXITSTATUS_METHODDEF
14825 OS_WTERMSIG_METHODDEF
14826 OS_WSTOPSIG_METHODDEF
14827 OS_FSTATVFS_METHODDEF
14828 OS_STATVFS_METHODDEF
14829 OS_CONFSTR_METHODDEF
14830 OS_SYSCONF_METHODDEF
14831 OS_FPATHCONF_METHODDEF
14832 OS_PATHCONF_METHODDEF
14833 OS_ABORT_METHODDEF
14834 OS__GETFULLPATHNAME_METHODDEF
14835 OS__GETDISKUSAGE_METHODDEF
14836 OS__GETFINALPATHNAME_METHODDEF
14837 OS__GETVOLUMEPATHNAME_METHODDEF
14838 OS__PATH_SPLITROOT_METHODDEF
14839 OS_GETLOADAVG_METHODDEF
14840 OS_URANDOM_METHODDEF
14841 OS_SETRESUID_METHODDEF
14842 OS_SETRESGID_METHODDEF
14843 OS_GETRESUID_METHODDEF
14844 OS_GETRESGID_METHODDEF
14845
14846 OS_GETXATTR_METHODDEF
14847 OS_SETXATTR_METHODDEF
14848 OS_REMOVEXATTR_METHODDEF
14849 OS_LISTXATTR_METHODDEF
14850
14851 OS_GET_TERMINAL_SIZE_METHODDEF
14852 OS_CPU_COUNT_METHODDEF
14853 OS_GET_INHERITABLE_METHODDEF
14854 OS_SET_INHERITABLE_METHODDEF
14855 OS_GET_HANDLE_INHERITABLE_METHODDEF
14856 OS_SET_HANDLE_INHERITABLE_METHODDEF
14857 OS_GET_BLOCKING_METHODDEF
14858 OS_SET_BLOCKING_METHODDEF
14859 OS_SCANDIR_METHODDEF
14860 OS_FSPATH_METHODDEF
14861 OS_GETRANDOM_METHODDEF
14862 OS_MEMFD_CREATE_METHODDEF
14863 OS_EVENTFD_METHODDEF
14864 OS_EVENTFD_READ_METHODDEF
14865 OS_EVENTFD_WRITE_METHODDEF
14866 OS__ADD_DLL_DIRECTORY_METHODDEF
14867 OS__REMOVE_DLL_DIRECTORY_METHODDEF
14868 OS_WAITSTATUS_TO_EXITCODE_METHODDEF
14869 {NULL, NULL} /* Sentinel */
14870 };
14871
14872 static int
all_ins(PyObject * m)14873 all_ins(PyObject *m)
14874 {
14875 #ifdef F_OK
14876 if (PyModule_AddIntMacro(m, F_OK)) return -1;
14877 #endif
14878 #ifdef R_OK
14879 if (PyModule_AddIntMacro(m, R_OK)) return -1;
14880 #endif
14881 #ifdef W_OK
14882 if (PyModule_AddIntMacro(m, W_OK)) return -1;
14883 #endif
14884 #ifdef X_OK
14885 if (PyModule_AddIntMacro(m, X_OK)) return -1;
14886 #endif
14887 #ifdef NGROUPS_MAX
14888 if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
14889 #endif
14890 #ifdef TMP_MAX
14891 if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
14892 #endif
14893 #ifdef WCONTINUED
14894 if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
14895 #endif
14896 #ifdef WNOHANG
14897 if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
14898 #endif
14899 #ifdef WUNTRACED
14900 if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
14901 #endif
14902 #ifdef O_RDONLY
14903 if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
14904 #endif
14905 #ifdef O_WRONLY
14906 if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
14907 #endif
14908 #ifdef O_RDWR
14909 if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
14910 #endif
14911 #ifdef O_NDELAY
14912 if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
14913 #endif
14914 #ifdef O_NONBLOCK
14915 if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
14916 #endif
14917 #ifdef O_APPEND
14918 if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
14919 #endif
14920 #ifdef O_DSYNC
14921 if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
14922 #endif
14923 #ifdef O_RSYNC
14924 if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
14925 #endif
14926 #ifdef O_SYNC
14927 if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
14928 #endif
14929 #ifdef O_NOCTTY
14930 if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
14931 #endif
14932 #ifdef O_CREAT
14933 if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
14934 #endif
14935 #ifdef O_EXCL
14936 if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
14937 #endif
14938 #ifdef O_TRUNC
14939 if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
14940 #endif
14941 #ifdef O_BINARY
14942 if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
14943 #endif
14944 #ifdef O_TEXT
14945 if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
14946 #endif
14947 #ifdef O_XATTR
14948 if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
14949 #endif
14950 #ifdef O_LARGEFILE
14951 if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
14952 #endif
14953 #ifndef __GNU__
14954 #ifdef O_SHLOCK
14955 if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
14956 #endif
14957 #ifdef O_EXLOCK
14958 if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
14959 #endif
14960 #endif
14961 #ifdef O_EXEC
14962 if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
14963 #endif
14964 #ifdef O_SEARCH
14965 if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
14966 #endif
14967 #ifdef O_PATH
14968 if (PyModule_AddIntMacro(m, O_PATH)) return -1;
14969 #endif
14970 #ifdef O_TTY_INIT
14971 if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
14972 #endif
14973 #ifdef O_TMPFILE
14974 if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
14975 #endif
14976 #ifdef PRIO_PROCESS
14977 if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
14978 #endif
14979 #ifdef PRIO_PGRP
14980 if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
14981 #endif
14982 #ifdef PRIO_USER
14983 if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
14984 #endif
14985 #ifdef O_CLOEXEC
14986 if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
14987 #endif
14988 #ifdef O_ACCMODE
14989 if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
14990 #endif
14991 #ifdef O_EVTONLY
14992 if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
14993 #endif
14994 #ifdef O_FSYNC
14995 if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
14996 #endif
14997 #ifdef O_SYMLINK
14998 if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
14999 #endif
15000
15001 #ifdef SEEK_HOLE
15002 if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
15003 #endif
15004 #ifdef SEEK_DATA
15005 if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
15006 #endif
15007
15008 /* MS Windows */
15009 #ifdef O_NOINHERIT
15010 /* Don't inherit in child processes. */
15011 if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
15012 #endif
15013 #ifdef _O_SHORT_LIVED
15014 /* Optimize for short life (keep in memory). */
15015 /* MS forgot to define this one with a non-underscore form too. */
15016 if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
15017 #endif
15018 #ifdef O_TEMPORARY
15019 /* Automatically delete when last handle is closed. */
15020 if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
15021 #endif
15022 #ifdef O_RANDOM
15023 /* Optimize for random access. */
15024 if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
15025 #endif
15026 #ifdef O_SEQUENTIAL
15027 /* Optimize for sequential access. */
15028 if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
15029 #endif
15030
15031 /* GNU extensions. */
15032 #ifdef O_ASYNC
15033 /* Send a SIGIO signal whenever input or output
15034 becomes available on file descriptor */
15035 if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
15036 #endif
15037 #ifdef O_DIRECT
15038 /* Direct disk access. */
15039 if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
15040 #endif
15041 #ifdef O_DIRECTORY
15042 /* Must be a directory. */
15043 if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
15044 #endif
15045 #ifdef O_NOFOLLOW
15046 /* Do not follow links. */
15047 if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
15048 #endif
15049 #ifdef O_NOFOLLOW_ANY
15050 if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
15051 #endif
15052 #ifdef O_NOLINKS
15053 /* Fails if link count of the named file is greater than 1 */
15054 if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
15055 #endif
15056 #ifdef O_NOATIME
15057 /* Do not update the access time. */
15058 if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
15059 #endif
15060
15061 /* These come from sysexits.h */
15062 #ifdef EX_OK
15063 if (PyModule_AddIntMacro(m, EX_OK)) return -1;
15064 #endif /* EX_OK */
15065 #ifdef EX_USAGE
15066 if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
15067 #endif /* EX_USAGE */
15068 #ifdef EX_DATAERR
15069 if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
15070 #endif /* EX_DATAERR */
15071 #ifdef EX_NOINPUT
15072 if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
15073 #endif /* EX_NOINPUT */
15074 #ifdef EX_NOUSER
15075 if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
15076 #endif /* EX_NOUSER */
15077 #ifdef EX_NOHOST
15078 if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
15079 #endif /* EX_NOHOST */
15080 #ifdef EX_UNAVAILABLE
15081 if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
15082 #endif /* EX_UNAVAILABLE */
15083 #ifdef EX_SOFTWARE
15084 if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
15085 #endif /* EX_SOFTWARE */
15086 #ifdef EX_OSERR
15087 if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
15088 #endif /* EX_OSERR */
15089 #ifdef EX_OSFILE
15090 if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
15091 #endif /* EX_OSFILE */
15092 #ifdef EX_CANTCREAT
15093 if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
15094 #endif /* EX_CANTCREAT */
15095 #ifdef EX_IOERR
15096 if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
15097 #endif /* EX_IOERR */
15098 #ifdef EX_TEMPFAIL
15099 if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
15100 #endif /* EX_TEMPFAIL */
15101 #ifdef EX_PROTOCOL
15102 if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
15103 #endif /* EX_PROTOCOL */
15104 #ifdef EX_NOPERM
15105 if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
15106 #endif /* EX_NOPERM */
15107 #ifdef EX_CONFIG
15108 if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
15109 #endif /* EX_CONFIG */
15110 #ifdef EX_NOTFOUND
15111 if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
15112 #endif /* EX_NOTFOUND */
15113
15114 /* statvfs */
15115 #ifdef ST_RDONLY
15116 if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
15117 #endif /* ST_RDONLY */
15118 #ifdef ST_NOSUID
15119 if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
15120 #endif /* ST_NOSUID */
15121
15122 /* GNU extensions */
15123 #ifdef ST_NODEV
15124 if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
15125 #endif /* ST_NODEV */
15126 #ifdef ST_NOEXEC
15127 if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
15128 #endif /* ST_NOEXEC */
15129 #ifdef ST_SYNCHRONOUS
15130 if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
15131 #endif /* ST_SYNCHRONOUS */
15132 #ifdef ST_MANDLOCK
15133 if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
15134 #endif /* ST_MANDLOCK */
15135 #ifdef ST_WRITE
15136 if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
15137 #endif /* ST_WRITE */
15138 #ifdef ST_APPEND
15139 if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
15140 #endif /* ST_APPEND */
15141 #ifdef ST_NOATIME
15142 if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
15143 #endif /* ST_NOATIME */
15144 #ifdef ST_NODIRATIME
15145 if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
15146 #endif /* ST_NODIRATIME */
15147 #ifdef ST_RELATIME
15148 if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
15149 #endif /* ST_RELATIME */
15150
15151 /* FreeBSD sendfile() constants */
15152 #ifdef SF_NODISKIO
15153 if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
15154 #endif
15155 #ifdef SF_MNOWAIT
15156 if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
15157 #endif
15158 #ifdef SF_SYNC
15159 if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
15160 #endif
15161
15162 /* constants for posix_fadvise */
15163 #ifdef POSIX_FADV_NORMAL
15164 if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
15165 #endif
15166 #ifdef POSIX_FADV_SEQUENTIAL
15167 if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
15168 #endif
15169 #ifdef POSIX_FADV_RANDOM
15170 if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
15171 #endif
15172 #ifdef POSIX_FADV_NOREUSE
15173 if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
15174 #endif
15175 #ifdef POSIX_FADV_WILLNEED
15176 if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
15177 #endif
15178 #ifdef POSIX_FADV_DONTNEED
15179 if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
15180 #endif
15181
15182 /* constants for waitid */
15183 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
15184 if (PyModule_AddIntMacro(m, P_PID)) return -1;
15185 if (PyModule_AddIntMacro(m, P_PGID)) return -1;
15186 if (PyModule_AddIntMacro(m, P_ALL)) return -1;
15187 #ifdef P_PIDFD
15188 if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
15189 #endif
15190 #endif
15191 #ifdef WEXITED
15192 if (PyModule_AddIntMacro(m, WEXITED)) return -1;
15193 #endif
15194 #ifdef WNOWAIT
15195 if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
15196 #endif
15197 #ifdef WSTOPPED
15198 if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
15199 #endif
15200 #ifdef CLD_EXITED
15201 if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
15202 #endif
15203 #ifdef CLD_KILLED
15204 if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
15205 #endif
15206 #ifdef CLD_DUMPED
15207 if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
15208 #endif
15209 #ifdef CLD_TRAPPED
15210 if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
15211 #endif
15212 #ifdef CLD_STOPPED
15213 if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
15214 #endif
15215 #ifdef CLD_CONTINUED
15216 if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
15217 #endif
15218
15219 /* constants for lockf */
15220 #ifdef F_LOCK
15221 if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
15222 #endif
15223 #ifdef F_TLOCK
15224 if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
15225 #endif
15226 #ifdef F_ULOCK
15227 if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
15228 #endif
15229 #ifdef F_TEST
15230 if (PyModule_AddIntMacro(m, F_TEST)) return -1;
15231 #endif
15232
15233 #ifdef RWF_DSYNC
15234 if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
15235 #endif
15236 #ifdef RWF_HIPRI
15237 if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
15238 #endif
15239 #ifdef RWF_SYNC
15240 if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
15241 #endif
15242 #ifdef RWF_NOWAIT
15243 if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
15244 #endif
15245 #ifdef RWF_APPEND
15246 if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
15247 #endif
15248
15249 /* constants for splice */
15250 #if defined(HAVE_SPLICE) && defined(__linux__)
15251 if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
15252 if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
15253 if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
15254 #endif
15255
15256 /* constants for posix_spawn */
15257 #ifdef HAVE_POSIX_SPAWN
15258 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
15259 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
15260 if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
15261 #endif
15262
15263 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
15264 if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
15265 if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
15266 if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
15267 #endif
15268 #ifdef HAVE_SPAWNV
15269 if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
15270 if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
15271 #endif
15272
15273 #ifdef HAVE_SCHED_H
15274 #ifdef SCHED_OTHER
15275 if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
15276 #endif
15277 #ifdef SCHED_FIFO
15278 if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
15279 #endif
15280 #ifdef SCHED_RR
15281 if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
15282 #endif
15283 #ifdef SCHED_SPORADIC
15284 if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
15285 #endif
15286 #ifdef SCHED_BATCH
15287 if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
15288 #endif
15289 #ifdef SCHED_IDLE
15290 if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
15291 #endif
15292 #ifdef SCHED_RESET_ON_FORK
15293 if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
15294 #endif
15295 #ifdef SCHED_SYS
15296 if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
15297 #endif
15298 #ifdef SCHED_IA
15299 if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
15300 #endif
15301 #ifdef SCHED_FSS
15302 if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
15303 #endif
15304 #ifdef SCHED_FX
15305 if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
15306 #endif
15307 #endif
15308
15309 #ifdef USE_XATTRS
15310 if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
15311 if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
15312 if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
15313 #endif
15314
15315 #if HAVE_DECL_RTLD_LAZY
15316 if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
15317 #endif
15318 #if HAVE_DECL_RTLD_NOW
15319 if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
15320 #endif
15321 #if HAVE_DECL_RTLD_GLOBAL
15322 if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
15323 #endif
15324 #if HAVE_DECL_RTLD_LOCAL
15325 if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
15326 #endif
15327 #if HAVE_DECL_RTLD_NODELETE
15328 if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
15329 #endif
15330 #if HAVE_DECL_RTLD_NOLOAD
15331 if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
15332 #endif
15333 #if HAVE_DECL_RTLD_DEEPBIND
15334 if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
15335 #endif
15336 #if HAVE_DECL_RTLD_MEMBER
15337 if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
15338 #endif
15339
15340 #ifdef HAVE_GETRANDOM_SYSCALL
15341 if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
15342 if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
15343 #endif
15344 #ifdef HAVE_MEMFD_CREATE
15345 if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
15346 if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
15347 #ifdef MFD_HUGETLB
15348 if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
15349 #endif
15350 #ifdef MFD_HUGE_SHIFT
15351 if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
15352 #endif
15353 #ifdef MFD_HUGE_MASK
15354 if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
15355 #endif
15356 #ifdef MFD_HUGE_64KB
15357 if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
15358 #endif
15359 #ifdef MFD_HUGE_512KB
15360 if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
15361 #endif
15362 #ifdef MFD_HUGE_1MB
15363 if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
15364 #endif
15365 #ifdef MFD_HUGE_2MB
15366 if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
15367 #endif
15368 #ifdef MFD_HUGE_8MB
15369 if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
15370 #endif
15371 #ifdef MFD_HUGE_16MB
15372 if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
15373 #endif
15374 #ifdef MFD_HUGE_32MB
15375 if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
15376 #endif
15377 #ifdef MFD_HUGE_256MB
15378 if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
15379 #endif
15380 #ifdef MFD_HUGE_512MB
15381 if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
15382 #endif
15383 #ifdef MFD_HUGE_1GB
15384 if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
15385 #endif
15386 #ifdef MFD_HUGE_2GB
15387 if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
15388 #endif
15389 #ifdef MFD_HUGE_16GB
15390 if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
15391 #endif
15392 #endif /* HAVE_MEMFD_CREATE */
15393
15394 #ifdef HAVE_EVENTFD
15395 if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
15396 if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
15397 if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
15398 #endif
15399
15400 #if defined(__APPLE__)
15401 if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
15402 #endif
15403
15404 #ifdef MS_WINDOWS
15405 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
15406 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
15407 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
15408 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
15409 if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
15410 #endif
15411
15412 return 0;
15413 }
15414
15415
15416
15417 #define PROBE(name, test) \
15418 static int name(void) \
15419 { \
15420 if (test) { \
15421 return 1; \
15422 } else { \
15423 return 0; \
15424 } \
15425 }
15426
15427 #ifdef HAVE_FSTATAT
15428 PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
15429 #endif
15430
15431 #ifdef HAVE_FACCESSAT
15432 PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
15433 #endif
15434
15435 #ifdef HAVE_FCHMODAT
15436 PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
15437 #endif
15438
15439 #ifdef HAVE_FCHOWNAT
15440 PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
15441 #endif
15442
15443 #ifdef HAVE_LINKAT
15444 PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
15445 #endif
15446
15447 #ifdef HAVE_FDOPENDIR
15448 PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
15449 #endif
15450
15451 #ifdef HAVE_MKDIRAT
15452 PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
15453 #endif
15454
15455 #ifdef HAVE_RENAMEAT
15456 PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
15457 #endif
15458
15459 #ifdef HAVE_UNLINKAT
15460 PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
15461 #endif
15462
15463 #ifdef HAVE_OPENAT
15464 PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
15465 #endif
15466
15467 #ifdef HAVE_READLINKAT
15468 PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
15469 #endif
15470
15471 #ifdef HAVE_SYMLINKAT
15472 PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
15473 #endif
15474
15475 #ifdef HAVE_FUTIMENS
15476 PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
15477 #endif
15478
15479 #ifdef HAVE_UTIMENSAT
15480 PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
15481 #endif
15482
15483
15484
15485
15486 static const struct have_function {
15487 const char * const label;
15488 int (*probe)(void);
15489 } have_functions[] = {
15490
15491 #ifdef HAVE_EVENTFD
15492 {"HAVE_EVENTFD", NULL},
15493 #endif
15494
15495 #ifdef HAVE_FACCESSAT
15496 { "HAVE_FACCESSAT", probe_faccessat },
15497 #endif
15498
15499 #ifdef HAVE_FCHDIR
15500 { "HAVE_FCHDIR", NULL },
15501 #endif
15502
15503 #ifdef HAVE_FCHMOD
15504 { "HAVE_FCHMOD", NULL },
15505 #endif
15506
15507 #ifdef HAVE_FCHMODAT
15508 { "HAVE_FCHMODAT", probe_fchmodat },
15509 #endif
15510
15511 #ifdef HAVE_FCHOWN
15512 { "HAVE_FCHOWN", NULL },
15513 #endif
15514
15515 #ifdef HAVE_FCHOWNAT
15516 { "HAVE_FCHOWNAT", probe_fchownat },
15517 #endif
15518
15519 #ifdef HAVE_FEXECVE
15520 { "HAVE_FEXECVE", NULL },
15521 #endif
15522
15523 #ifdef HAVE_FDOPENDIR
15524 { "HAVE_FDOPENDIR", probe_fdopendir },
15525 #endif
15526
15527 #ifdef HAVE_FPATHCONF
15528 { "HAVE_FPATHCONF", NULL },
15529 #endif
15530
15531 #ifdef HAVE_FSTATAT
15532 { "HAVE_FSTATAT", probe_fstatat },
15533 #endif
15534
15535 #ifdef HAVE_FSTATVFS
15536 { "HAVE_FSTATVFS", NULL },
15537 #endif
15538
15539 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
15540 { "HAVE_FTRUNCATE", NULL },
15541 #endif
15542
15543 #ifdef HAVE_FUTIMENS
15544 { "HAVE_FUTIMENS", probe_futimens },
15545 #endif
15546
15547 #ifdef HAVE_FUTIMES
15548 { "HAVE_FUTIMES", NULL },
15549 #endif
15550
15551 #ifdef HAVE_FUTIMESAT
15552 { "HAVE_FUTIMESAT", NULL },
15553 #endif
15554
15555 #ifdef HAVE_LINKAT
15556 { "HAVE_LINKAT", probe_linkat },
15557 #endif
15558
15559 #ifdef HAVE_LCHFLAGS
15560 { "HAVE_LCHFLAGS", NULL },
15561 #endif
15562
15563 #ifdef HAVE_LCHMOD
15564 { "HAVE_LCHMOD", NULL },
15565 #endif
15566
15567 #ifdef HAVE_LCHOWN
15568 { "HAVE_LCHOWN", NULL },
15569 #endif
15570
15571 #ifdef HAVE_LSTAT
15572 { "HAVE_LSTAT", NULL },
15573 #endif
15574
15575 #ifdef HAVE_LUTIMES
15576 { "HAVE_LUTIMES", NULL },
15577 #endif
15578
15579 #ifdef HAVE_MEMFD_CREATE
15580 { "HAVE_MEMFD_CREATE", NULL },
15581 #endif
15582
15583 #ifdef HAVE_MKDIRAT
15584 { "HAVE_MKDIRAT", probe_mkdirat },
15585 #endif
15586
15587 #ifdef HAVE_MKFIFOAT
15588 { "HAVE_MKFIFOAT", NULL },
15589 #endif
15590
15591 #ifdef HAVE_MKNODAT
15592 { "HAVE_MKNODAT", NULL },
15593 #endif
15594
15595 #ifdef HAVE_OPENAT
15596 { "HAVE_OPENAT", probe_openat },
15597 #endif
15598
15599 #ifdef HAVE_READLINKAT
15600 { "HAVE_READLINKAT", probe_readlinkat },
15601 #endif
15602
15603 #ifdef HAVE_RENAMEAT
15604 { "HAVE_RENAMEAT", probe_renameat },
15605 #endif
15606
15607 #ifdef HAVE_SYMLINKAT
15608 { "HAVE_SYMLINKAT", probe_symlinkat },
15609 #endif
15610
15611 #ifdef HAVE_UNLINKAT
15612 { "HAVE_UNLINKAT", probe_unlinkat },
15613 #endif
15614
15615 #ifdef HAVE_UTIMENSAT
15616 { "HAVE_UTIMENSAT", probe_utimensat },
15617 #endif
15618
15619 #ifdef MS_WINDOWS
15620 { "MS_WINDOWS", NULL },
15621 #endif
15622
15623 { NULL, NULL }
15624 };
15625
15626
15627 static int
posixmodule_exec(PyObject * m)15628 posixmodule_exec(PyObject *m)
15629 {
15630 _posixstate *state = get_posix_state(m);
15631
15632 #if defined(HAVE_PWRITEV)
15633 if (HAVE_PWRITEV_RUNTIME) {} else {
15634 PyObject* dct = PyModule_GetDict(m);
15635
15636 if (dct == NULL) {
15637 return -1;
15638 }
15639
15640 if (PyDict_DelItemString(dct, "pwritev") == -1) {
15641 PyErr_Clear();
15642 }
15643 if (PyDict_DelItemString(dct, "preadv") == -1) {
15644 PyErr_Clear();
15645 }
15646 }
15647 #endif
15648
15649 /* Initialize environ dictionary */
15650 PyObject *v = convertenviron();
15651 Py_XINCREF(v);
15652 if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
15653 return -1;
15654 Py_DECREF(v);
15655
15656 if (all_ins(m))
15657 return -1;
15658
15659 if (setup_confname_tables(m))
15660 return -1;
15661
15662 Py_INCREF(PyExc_OSError);
15663 PyModule_AddObject(m, "error", PyExc_OSError);
15664
15665 #if defined(HAVE_WAITID) && !defined(__APPLE__)
15666 waitid_result_desc.name = MODNAME ".waitid_result";
15667 PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
15668 if (WaitidResultType == NULL) {
15669 return -1;
15670 }
15671 Py_INCREF(WaitidResultType);
15672 PyModule_AddObject(m, "waitid_result", WaitidResultType);
15673 state->WaitidResultType = WaitidResultType;
15674 #endif
15675
15676 stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
15677 stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
15678 stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
15679 stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
15680 PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
15681 if (StatResultType == NULL) {
15682 return -1;
15683 }
15684 Py_INCREF(StatResultType);
15685 PyModule_AddObject(m, "stat_result", StatResultType);
15686 state->StatResultType = StatResultType;
15687 structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15688 ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
15689
15690 statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
15691 PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
15692 if (StatVFSResultType == NULL) {
15693 return -1;
15694 }
15695 Py_INCREF(StatVFSResultType);
15696 PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
15697 state->StatVFSResultType = StatVFSResultType;
15698 #ifdef NEED_TICKS_PER_SECOND
15699 # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15700 ticks_per_second = sysconf(_SC_CLK_TCK);
15701 # elif defined(HZ)
15702 ticks_per_second = HZ;
15703 # else
15704 ticks_per_second = 60; /* magic fallback value; may be bogus */
15705 # endif
15706 #endif
15707
15708 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
15709 sched_param_desc.name = MODNAME ".sched_param";
15710 PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
15711 if (SchedParamType == NULL) {
15712 return -1;
15713 }
15714 Py_INCREF(SchedParamType);
15715 PyModule_AddObject(m, "sched_param", SchedParamType);
15716 state->SchedParamType = SchedParamType;
15717 ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
15718 #endif
15719
15720 /* initialize TerminalSize_info */
15721 PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
15722 if (TerminalSizeType == NULL) {
15723 return -1;
15724 }
15725 Py_INCREF(TerminalSizeType);
15726 PyModule_AddObject(m, "terminal_size", TerminalSizeType);
15727 state->TerminalSizeType = TerminalSizeType;
15728
15729 /* initialize scandir types */
15730 PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
15731 if (ScandirIteratorType == NULL) {
15732 return -1;
15733 }
15734 state->ScandirIteratorType = ScandirIteratorType;
15735
15736 PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
15737 if (DirEntryType == NULL) {
15738 return -1;
15739 }
15740 Py_INCREF(DirEntryType);
15741 PyModule_AddObject(m, "DirEntry", DirEntryType);
15742 state->DirEntryType = DirEntryType;
15743
15744 times_result_desc.name = MODNAME ".times_result";
15745 PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(×_result_desc);
15746 if (TimesResultType == NULL) {
15747 return -1;
15748 }
15749 Py_INCREF(TimesResultType);
15750 PyModule_AddObject(m, "times_result", TimesResultType);
15751 state->TimesResultType = TimesResultType;
15752
15753 PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
15754 if (UnameResultType == NULL) {
15755 return -1;
15756 }
15757 Py_INCREF(UnameResultType);
15758 PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
15759 state->UnameResultType = (PyObject *)UnameResultType;
15760
15761 if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
15762 return -1;
15763 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
15764 state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
15765 if (state->struct_rusage == NULL)
15766 return -1;
15767 #endif
15768 state->st_mode = PyUnicode_InternFromString("st_mode");
15769 if (state->st_mode == NULL)
15770 return -1;
15771
15772 /* suppress "function not used" warnings */
15773 {
15774 int ignored;
15775 fd_specified("", -1);
15776 follow_symlinks_specified("", 1);
15777 dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
15778 dir_fd_converter(Py_None, &ignored);
15779 dir_fd_unavailable(Py_None, &ignored);
15780 }
15781
15782 /*
15783 * provide list of locally available functions
15784 * so os.py can populate support_* lists
15785 */
15786 PyObject *list = PyList_New(0);
15787 if (!list) {
15788 return -1;
15789 }
15790 for (const struct have_function *trace = have_functions; trace->label; trace++) {
15791 PyObject *unicode;
15792 if (trace->probe && !trace->probe()) continue;
15793 unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
15794 if (!unicode)
15795 return -1;
15796 if (PyList_Append(list, unicode))
15797 return -1;
15798 Py_DECREF(unicode);
15799 }
15800
15801 PyModule_AddObject(m, "_have_functions", list);
15802
15803 return 0;
15804 }
15805
15806
15807 static PyModuleDef_Slot posixmodile_slots[] = {
15808 {Py_mod_exec, posixmodule_exec},
15809 {0, NULL}
15810 };
15811
15812 static struct PyModuleDef posixmodule = {
15813 PyModuleDef_HEAD_INIT,
15814 .m_name = MODNAME,
15815 .m_doc = posix__doc__,
15816 .m_size = sizeof(_posixstate),
15817 .m_methods = posix_methods,
15818 .m_slots = posixmodile_slots,
15819 .m_traverse = _posix_traverse,
15820 .m_clear = _posix_clear,
15821 .m_free = _posix_free,
15822 };
15823
15824 PyMODINIT_FUNC
INITFUNC(void)15825 INITFUNC(void)
15826 {
15827 return PyModuleDef_Init(&posixmodule);
15828 }
15829
15830 #ifdef __cplusplus
15831 }
15832 #endif
15833