• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "Python.h"
11 
12 #ifdef __VXWORKS__
13 #  include "pycore_bitutils.h"    // _Py_popcount32()
14 #endif
15 #include "pycore_abstract.h"      // _PyNumber_Index()
16 #include "pycore_call.h"          // _PyObject_CallNoArgs()
17 #include "pycore_ceval.h"         // _PyEval_ReInitThreads()
18 #include "pycore_fileutils.h"     // _Py_closerange()
19 #include "pycore_initconfig.h"    // _PyStatus_EXCEPTION()
20 #include "pycore_long.h"          // _PyLong_IsNegative()
21 #include "pycore_moduleobject.h"  // _PyModule_GetState()
22 #include "pycore_object.h"        // _PyObject_LookupSpecial()
23 #include "pycore_pylifecycle.h"   // _PyOS_URandom()
24 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
25 #include "pycore_signal.h"        // Py_NSIG
26 #include "pycore_time.h"          // _PyLong_FromTime_t()
27 #include "pycore_typeobject.h"    // _PyType_AddMethod()
28 
29 #ifdef HAVE_UNISTD_H
30 #  include <unistd.h>             // symlink()
31 #endif
32 
33 #ifdef MS_WINDOWS
34 #  include <windows.h>
35 #  if !defined(MS_WINDOWS_GAMES) || defined(MS_WINDOWS_DESKTOP)
36 #    include <pathcch.h>
37 #  endif
38 #  include <winioctl.h>
39 #  include <lmcons.h>             // UNLEN
40 #  include "osdefs.h"             // SEP
41 #  include <aclapi.h>             // SetEntriesInAcl
42 #  include <sddl.h>               // SDDL_REVISION_1
43 #  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
44 #    define HAVE_SYMLINK
45 #  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
46 #endif
47 
48 #ifndef MS_WINDOWS
49 #  include "posixmodule.h"
50 #else
51 #  include "pycore_fileutils_windows.h"
52 #  include "winreparse.h"
53 #endif
54 
55 #if !defined(EX_OK) && defined(EXIT_SUCCESS)
56 #  define EX_OK EXIT_SUCCESS
57 #endif
58 
59 #ifdef __APPLE__
60  /* Needed for the implementation of os.statvfs */
61 #  include <sys/param.h>
62 #  include <sys/mount.h>
63 #endif
64 
65 /* On android API level 21, 'AT_EACCESS' is not declared although
66  * HAVE_FACCESSAT is defined. */
67 #ifdef __ANDROID__
68 #  undef HAVE_FACCESSAT
69 #endif
70 
71 #include <stdio.h>                // ctermid()
72 #include <stdlib.h>               // system()
73 #ifdef HAVE_SYS_TIME_H
74 #  include <sys/time.h>           // futimes()
75 #endif
76 
77 
78 // SGI apparently needs this forward declaration
79 #ifdef HAVE__GETPTY
80 #  include <sys/types.h>          // mode_t
81    extern char * _getpty(int *, int, mode_t, int);
82 #endif
83 
84 
85 /*
86  * A number of APIs are available on macOS from a certain macOS version.
87  * To support building with a new SDK while deploying to older versions
88  * the availability test is split into two:
89  *   - HAVE_<FUNCTION>:  The configure check for compile time availability
90  *   - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
91  *
92  * The latter is always true when not on macOS, or when using a compiler
93  * that does not support __has_builtin (older versions of Xcode).
94  *
95  * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
96  *    if (HAVE_<FUNCTION>_RUNTIME) { ... }
97  *
98  * In mixing the test with other tests or using negations will result in compile
99  * errors.
100  */
101 #if defined(__APPLE__)
102 
103 #include <mach/mach.h>
104 
105 #if defined(__has_builtin)
106 #if __has_builtin(__builtin_available)
107 #define HAVE_BUILTIN_AVAILABLE 1
108 #endif
109 #endif
110 
111 #ifdef HAVE_BUILTIN_AVAILABLE
112 #  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
113 #  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
114 #  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
115 #  define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
116 #  define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
117 #  define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
118 #  define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
119 #  define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
120 #  define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
121 #  define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
122 #  define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
123 #  define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
124 #  define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
125 #  define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
126 #  define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
127 #  define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
128 #  define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
129 #  define HAVE_PTSNAME_R_RUNTIME __builtin_available(macOS 10.13.4, iOS 11.3, tvOS 11.3, watchOS 4.3, *)
130 
131 #  define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
132 
133 #else /* Xcode 8 or earlier */
134 
135    /* __builtin_available is not present in these compilers, but
136     * some of the symbols might be weak linked (10.10 SDK or later
137     * deploying on 10.9.
138     *
139     * Fall back to the older style of availability checking for
140     * symbols introduced in macOS 10.10.
141     */
142 
143 #  ifdef HAVE_FSTATAT
144 #    define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
145 #  endif
146 
147 #  ifdef HAVE_FACCESSAT
148 #    define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
149 #  endif
150 
151 #  ifdef HAVE_FCHMODAT
152 #    define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
153 #  endif
154 
155 #  ifdef HAVE_FCHOWNAT
156 #    define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
157 #  endif
158 
159 #  ifdef HAVE_LINKAT
160 #    define HAVE_LINKAT_RUNTIME (linkat != NULL)
161 #  endif
162 
163 #  ifdef HAVE_FDOPENDIR
164 #    define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
165 #  endif
166 
167 #  ifdef HAVE_MKDIRAT
168 #    define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
169 #  endif
170 
171 #  ifdef HAVE_RENAMEAT
172 #    define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
173 #  endif
174 
175 #  ifdef HAVE_UNLINKAT
176 #    define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
177 #  endif
178 
179 #  ifdef HAVE_OPENAT
180 #    define HAVE_OPENAT_RUNTIME (openat != NULL)
181 #  endif
182 
183 #  ifdef HAVE_READLINKAT
184 #    define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
185 #  endif
186 
187 #  ifdef HAVE_SYMLINKAT
188 #    define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
189 #  endif
190 
191 #  ifdef HAVE_UTIMENSAT
192 #    define HAVE_UTIMENSAT_RUNTIME (utimensat != NULL)
193 #  endif
194 
195 #  ifdef HAVE_FUTIMENS
196 #    define HAVE_FUTIMENS_RUNTIME (futimens != NULL)
197 #  endif
198 
199 #  ifdef HAVE_PWRITEV
200 #    define HAVE_PWRITEV_RUNTIME (pwritev != NULL)
201 #  endif
202 
203 #  ifdef HAVE_MKFIFOAT
204 #    define HAVE_MKFIFOAT_RUNTIME (mkfifoat != NULL)
205 #  endif
206 
207 #  ifdef HAVE_MKNODAT
208 #    define HAVE_MKNODAT_RUNTIME (mknodat != NULL)
209 #  endif
210 
211 #  ifdef HAVE_PTSNAME_R
212 #    define HAVE_PTSNAME_R_RUNTIME (ptsname_r != NULL)
213 #  endif
214 
215 #endif
216 
217 #ifdef HAVE_FUTIMESAT
218 /* Some of the logic for weak linking depends on this assertion */
219 # error "HAVE_FUTIMESAT unexpectedly defined"
220 #endif
221 
222 #else
223 #  define HAVE_FSTATAT_RUNTIME 1
224 #  define HAVE_FACCESSAT_RUNTIME 1
225 #  define HAVE_FCHMODAT_RUNTIME 1
226 #  define HAVE_FCHOWNAT_RUNTIME 1
227 #  define HAVE_LINKAT_RUNTIME 1
228 #  define HAVE_FDOPENDIR_RUNTIME 1
229 #  define HAVE_MKDIRAT_RUNTIME 1
230 #  define HAVE_RENAMEAT_RUNTIME 1
231 #  define HAVE_UNLINKAT_RUNTIME 1
232 #  define HAVE_OPENAT_RUNTIME 1
233 #  define HAVE_READLINKAT_RUNTIME 1
234 #  define HAVE_SYMLINKAT_RUNTIME 1
235 #  define HAVE_FUTIMENS_RUNTIME 1
236 #  define HAVE_UTIMENSAT_RUNTIME 1
237 #  define HAVE_PWRITEV_RUNTIME 1
238 #  define HAVE_MKFIFOAT_RUNTIME 1
239 #  define HAVE_MKNODAT_RUNTIME 1
240 #  define HAVE_PTSNAME_R_RUNTIME 1
241 #endif
242 
243 
244 PyDoc_STRVAR(posix__doc__,
245 "This module provides access to operating system functionality that is\n\
246 standardized by the C Standard and the POSIX standard (a thinly\n\
247 disguised Unix interface).  Refer to the library manual and\n\
248 corresponding Unix manual entries for more information on calls.");
249 
250 
251 #ifdef HAVE_SYS_UIO_H
252 #  include <sys/uio.h>
253 #endif
254 
255 #ifdef HAVE_SYS_TYPES_H
256 /* Should be included before <sys/sysmacros.h> on HP-UX v3 */
257 #  include <sys/types.h>
258 #endif /* HAVE_SYS_TYPES_H */
259 
260 #ifdef HAVE_SYS_SYSMACROS_H
261 /* GNU C Library: major(), minor(), makedev() */
262 #  include <sys/sysmacros.h>
263 #endif
264 
265 #ifdef HAVE_SYS_STAT_H
266 #  include <sys/stat.h>
267 #endif /* HAVE_SYS_STAT_H */
268 
269 #ifdef HAVE_SYS_WAIT_H
270 #  include <sys/wait.h>           // WNOHANG
271 #endif
272 #ifdef HAVE_LINUX_WAIT_H
273 #  include <linux/wait.h>         // P_PIDFD
274 #endif
275 
276 #ifdef HAVE_SIGNAL_H
277 #  include <signal.h>
278 #endif
279 
280 #ifdef HAVE_FCNTL_H
281 #  include <fcntl.h>
282 #endif
283 
284 #ifdef HAVE_GRP_H
285 #  include <grp.h>
286 #endif
287 
288 #ifdef HAVE_SYSEXITS_H
289 #  include <sysexits.h>
290 #endif
291 
292 #ifdef HAVE_SYS_LOADAVG_H
293 #  include <sys/loadavg.h>
294 #endif
295 
296 #ifdef HAVE_SYS_SENDFILE_H
297 #  include <sys/sendfile.h>
298 #endif
299 
300 #if defined(__APPLE__)
301 #  include <copyfile.h>
302 #endif
303 
304 #ifdef HAVE_SCHED_H
305 #  include <sched.h>
306 #endif
307 
308 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
309 #  undef HAVE_SCHED_SETAFFINITY
310 #endif
311 
312 #if defined(HAVE_SYS_XATTR_H)
313 #  if defined(HAVE_LINUX_LIMITS_H) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
314 #    define USE_XATTRS
315 #    include <linux/limits.h>  // Needed for XATTR_SIZE_MAX on musl libc.
316 #  endif
317 #  if defined(__CYGWIN__)
318 #    define USE_XATTRS
319 #    include <cygwin/limits.h>  // Needed for XATTR_SIZE_MAX and XATTR_LIST_MAX.
320 #  endif
321 #endif
322 
323 #ifdef USE_XATTRS
324 #  include <sys/xattr.h>
325 #endif
326 
327 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
328 #  ifdef HAVE_SYS_SOCKET_H
329 #    include <sys/socket.h>
330 #  endif
331 #endif
332 
333 #ifdef HAVE_DLFCN_H
334 #  include <dlfcn.h>
335 #endif
336 
337 #ifdef __hpux
338 #  include <sys/mpctl.h>
339 #endif
340 
341 #if defined(__DragonFly__) || \
342     defined(__OpenBSD__)   || \
343     defined(__FreeBSD__)   || \
344     defined(__NetBSD__)    || \
345     defined(__APPLE__)
346 #  include <sys/sysctl.h>
347 #endif
348 
349 #ifdef HAVE_LINUX_RANDOM_H
350 #  include <linux/random.h>
351 #endif
352 #ifdef HAVE_GETRANDOM_SYSCALL
353 #  include <sys/syscall.h>
354 #endif
355 
356 #ifdef HAVE_WINDOWS_CONSOLE_IO
357 #  define TERMSIZE_USE_CONIO
358 #elif defined(HAVE_SYS_IOCTL_H)
359 #  include <sys/ioctl.h>
360 #  if defined(HAVE_TERMIOS_H)
361 #    include <termios.h>
362 #  endif
363 #  if defined(TIOCGWINSZ)
364 #    define TERMSIZE_USE_IOCTL
365 #  endif
366 #endif /* HAVE_WINDOWS_CONSOLE_IO */
367 
368 /* Various compilers have only certain posix functions */
369 /* XXX Gosh I wish these were all moved into pyconfig.h */
370 #if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
371 #  define HAVE_OPENDIR    1
372 #  define HAVE_SYSTEM     1
373 #  include <process.h>
374 #elif defined( _MSC_VER)
375   /* Microsoft compiler */
376 #  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
377 #    define HAVE_GETPPID    1
378 #  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_APP | MS_WINDOWS_SYSTEM */
379 #  if defined(MS_WINDOWS_DESKTOP)
380 #    define HAVE_GETLOGIN   1
381 #  endif /* MS_WINDOWS_DESKTOP */
382 #  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
383 #    define HAVE_SPAWNV     1
384 #    define HAVE_EXECV      1
385 #    define HAVE_WSPAWNV    1
386 #    define HAVE_WEXECV     1
387 #    define HAVE_SYSTEM     1
388 #    define HAVE_CWAIT      1
389 #  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
390 #  define HAVE_PIPE       1
391 #  define HAVE_FSYNC      1
392 #  define fsync _commit
393 #endif  /* ! __WATCOMC__ || __QNX__ */
394 
395 /*[clinic input]
396 # one of the few times we lie about this name!
397 module os
398 [clinic start generated code]*/
399 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
400 
401 #ifndef _MSC_VER
402 
403 #if defined(__sgi)&&_COMPILER_VERSION>=700
404 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
405    (default) */
406 extern char        *ctermid_r(char *);
407 #endif
408 
409 #endif /* !_MSC_VER */
410 
411 #if defined(__VXWORKS__)
412 #  include <vxCpuLib.h>
413 #  include <rtpLib.h>
414 #  include <wait.h>
415 #  include <taskLib.h>
416 #  ifndef _P_WAIT
417 #    define _P_WAIT          0
418 #    define _P_NOWAIT        1
419 #    define _P_NOWAITO       1
420 #  endif
421 #endif /* __VXWORKS__ */
422 
423 #ifdef HAVE_POSIX_SPAWN
424 #  include <spawn.h>
425 #endif
426 
427 #ifdef HAVE_UTIME_H
428 #  include <utime.h>
429 #endif /* HAVE_UTIME_H */
430 
431 #ifdef HAVE_SYS_UTIME_H
432 #  include <sys/utime.h>
433 #  define HAVE_UTIME_H /* pretend we do for the rest of this file */
434 #endif /* HAVE_SYS_UTIME_H */
435 
436 #ifdef HAVE_SYS_TIMES_H
437 #  include <sys/times.h>
438 #endif /* HAVE_SYS_TIMES_H */
439 
440 #ifdef HAVE_SYS_PARAM_H
441 #  include <sys/param.h>
442 #endif /* HAVE_SYS_PARAM_H */
443 
444 #ifdef HAVE_SYS_UTSNAME_H
445 #  include <sys/utsname.h>
446 #endif /* HAVE_SYS_UTSNAME_H */
447 
448 #ifdef HAVE_DIRENT_H
449 #  include <dirent.h>
450 #  define NAMLEN(dirent) strlen((dirent)->d_name)
451 #else
452 #  if defined(__WATCOMC__) && !defined(__QNX__)
453 #    include <direct.h>
454 #    define NAMLEN(dirent) strlen((dirent)->d_name)
455 #  else
456 #    define dirent direct
457 #    define NAMLEN(dirent) (dirent)->d_namlen
458 #  endif
459 #  ifdef HAVE_SYS_NDIR_H
460 #    include <sys/ndir.h>
461 #  endif
462 #  ifdef HAVE_SYS_DIR_H
463 #    include <sys/dir.h>
464 #  endif
465 #  ifdef HAVE_NDIR_H
466 #    include <ndir.h>
467 #  endif
468 #endif
469 
470 #ifdef _MSC_VER
471 #  ifdef HAVE_DIRECT_H
472 #    include <direct.h>
473 #  endif
474 #  ifdef HAVE_IO_H
475 #    include <io.h>
476 #  endif
477 #  ifdef HAVE_PROCESS_H
478 #    include <process.h>
479 #  endif
480 #  include <malloc.h>
481 #endif /* _MSC_VER */
482 
483 #ifndef MAXPATHLEN
484 #  if defined(PATH_MAX) && PATH_MAX > 1024
485 #    define MAXPATHLEN PATH_MAX
486 #  else
487 #    define MAXPATHLEN 1024
488 #  endif
489 #endif /* MAXPATHLEN */
490 
491 #ifdef UNION_WAIT
492    /* Emulate some macros on systems that have a union instead of macros */
493 #  ifndef WIFEXITED
494 #    define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
495 #  endif
496 #  ifndef WEXITSTATUS
497 #    define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
498 #  endif
499 #  ifndef WTERMSIG
500 #    define WTERMSIG(u_wait) ((u_wait).w_termsig)
501 #  endif
502 #  define WAIT_TYPE union wait
503 #  define WAIT_STATUS_INT(s) (s.w_status)
504 #else
505    /* !UNION_WAIT */
506 #  define WAIT_TYPE int
507 #  define WAIT_STATUS_INT(s) (s)
508 #endif /* UNION_WAIT */
509 
510 /* Don't use the "_r" form if we don't need it (also, won't have a
511    prototype for it, at least on Solaris -- maybe others as well?). */
512 #if defined(HAVE_CTERMID_R)
513 #  define USE_CTERMID_R
514 #endif
515 
516 /* choose the appropriate stat and fstat functions and return structs */
517 #undef STAT
518 #undef FSTAT
519 #undef STRUCT_STAT
520 #ifdef MS_WINDOWS
521 #  define STAT win32_stat
522 #  define LSTAT win32_lstat
523 #  define FSTAT _Py_fstat_noraise
524 #  define STRUCT_STAT struct _Py_stat_struct
525 #else
526 #  define STAT stat
527 #  define LSTAT lstat
528 #  define FSTAT fstat
529 #  define STRUCT_STAT struct stat
530 #endif
531 
532 #if defined(MAJOR_IN_MKDEV)
533 #  include <sys/mkdev.h>
534 #else
535 #  if defined(MAJOR_IN_SYSMACROS)
536 #    include <sys/sysmacros.h>
537 #  endif
538 #  if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
539 #    include <sys/mkdev.h>
540 #  endif
541 #endif
542 
543 #ifdef MS_WINDOWS
544 #  define INITFUNC PyInit_nt
545 #  define MODNAME "nt"
546 #  define MODNAME_OBJ &_Py_ID(nt)
547 #else
548 #  define INITFUNC PyInit_posix
549 #  define MODNAME "posix"
550 #  define MODNAME_OBJ &_Py_ID(posix)
551 #endif
552 
553 #if defined(__sun)
554 /* Something to implement in autoconf, not present in autoconf 2.69 */
555 #  define HAVE_STRUCT_STAT_ST_FSTYPE 1
556 #endif
557 
558 /* memfd_create is either defined in sys/mman.h or sys/memfd.h
559  * linux/memfd.h defines additional flags
560  */
561 #ifdef HAVE_SYS_MMAN_H
562 #  include <sys/mman.h>
563 #endif
564 #ifdef HAVE_SYS_MEMFD_H
565 #  include <sys/memfd.h>
566 #endif
567 #ifdef HAVE_LINUX_MEMFD_H
568 #  include <linux/memfd.h>
569 #endif
570 
571 /* eventfd() */
572 #ifdef HAVE_SYS_EVENTFD_H
573 #  include <sys/eventfd.h>
574 #endif
575 
576 /* timerfd_create() */
577 #ifdef HAVE_SYS_TIMERFD_H
578 #  include <sys/timerfd.h>
579 #endif
580 
581 #ifdef _Py_MEMORY_SANITIZER
582 #  include <sanitizer/msan_interface.h>
583 #endif
584 
585 #ifdef HAVE_FORK
586 static void
run_at_forkers(PyObject * lst,int reverse)587 run_at_forkers(PyObject *lst, int reverse)
588 {
589     Py_ssize_t i;
590     PyObject *cpy;
591 
592     if (lst != NULL) {
593         assert(PyList_CheckExact(lst));
594 
595         /* Use a list copy in case register_at_fork() is called from
596          * one of the callbacks.
597          */
598         cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
599         if (cpy == NULL)
600             PyErr_WriteUnraisable(lst);
601         else {
602             if (reverse)
603                 PyList_Reverse(cpy);
604             for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
605                 PyObject *func, *res;
606                 func = PyList_GET_ITEM(cpy, i);
607                 res = _PyObject_CallNoArgs(func);
608                 if (res == NULL)
609                     PyErr_WriteUnraisable(func);
610                 else
611                     Py_DECREF(res);
612             }
613             Py_DECREF(cpy);
614         }
615     }
616 }
617 
618 void
PyOS_BeforeFork(void)619 PyOS_BeforeFork(void)
620 {
621     PyInterpreterState *interp = _PyInterpreterState_GET();
622     run_at_forkers(interp->before_forkers, 1);
623 
624     _PyImport_AcquireLock(interp);
625     _PyEval_StopTheWorldAll(&_PyRuntime);
626     HEAD_LOCK(&_PyRuntime);
627 }
628 
629 void
PyOS_AfterFork_Parent(void)630 PyOS_AfterFork_Parent(void)
631 {
632     HEAD_UNLOCK(&_PyRuntime);
633     _PyEval_StartTheWorldAll(&_PyRuntime);
634 
635     PyInterpreterState *interp = _PyInterpreterState_GET();
636     _PyImport_ReleaseLock(interp);
637     run_at_forkers(interp->after_forkers_parent, 0);
638 }
639 
640 void
PyOS_AfterFork_Child(void)641 PyOS_AfterFork_Child(void)
642 {
643     PyStatus status;
644     _PyRuntimeState *runtime = &_PyRuntime;
645 
646     // re-creates runtime->interpreters.mutex (HEAD_UNLOCK)
647     status = _PyRuntimeState_ReInitThreads(runtime);
648     if (_PyStatus_EXCEPTION(status)) {
649         goto fatal_error;
650     }
651 
652     PyThreadState *tstate = _PyThreadState_GET();
653     _Py_EnsureTstateNotNULL(tstate);
654 
655     assert(tstate->thread_id == PyThread_get_thread_ident());
656 #ifdef PY_HAVE_THREAD_NATIVE_ID
657     tstate->native_thread_id = PyThread_get_thread_native_id();
658 #endif
659 
660 #ifdef Py_GIL_DISABLED
661     _Py_brc_after_fork(tstate->interp);
662     _Py_qsbr_after_fork((_PyThreadStateImpl *)tstate);
663 #endif
664 
665     // Ideally we could guarantee tstate is running main.
666     _PyInterpreterState_ReinitRunningMain(tstate);
667 
668     status = _PyEval_ReInitThreads(tstate);
669     if (_PyStatus_EXCEPTION(status)) {
670         goto fatal_error;
671     }
672 
673     // Remove the dead thread states. We "start the world" once we are the only
674     // thread state left to undo the stop the world call in `PyOS_BeforeFork`.
675     // That needs to happen before `_PyThreadState_DeleteList`, because that
676     // may call destructors.
677     PyThreadState *list = _PyThreadState_RemoveExcept(tstate);
678     _PyEval_StartTheWorldAll(&_PyRuntime);
679     _PyThreadState_DeleteList(list);
680 
681     _PyImport_ReInitLock(tstate->interp);
682     _PyImport_ReleaseLock(tstate->interp);
683 
684     _PySignal_AfterFork();
685 
686     status = _PyInterpreterState_DeleteExceptMain(runtime);
687     if (_PyStatus_EXCEPTION(status)) {
688         goto fatal_error;
689     }
690     assert(_PyThreadState_GET() == tstate);
691 
692     status = _PyPerfTrampoline_AfterFork_Child();
693     if (_PyStatus_EXCEPTION(status)) {
694         goto fatal_error;
695     }
696 
697     run_at_forkers(tstate->interp->after_forkers_child, 0);
698     return;
699 
700 fatal_error:
701     Py_ExitStatusException(status);
702 }
703 
704 static int
register_at_forker(PyObject ** lst,PyObject * func)705 register_at_forker(PyObject **lst, PyObject *func)
706 {
707     if (func == NULL)  /* nothing to register? do nothing. */
708         return 0;
709     if (*lst == NULL) {
710         *lst = PyList_New(0);
711         if (*lst == NULL)
712             return -1;
713     }
714     return PyList_Append(*lst, func);
715 }
716 #endif  /* HAVE_FORK */
717 
718 
719 /* Legacy wrapper */
720 void
PyOS_AfterFork(void)721 PyOS_AfterFork(void)
722 {
723 #ifdef HAVE_FORK
724     PyOS_AfterFork_Child();
725 #endif
726 }
727 
728 
729 #ifdef MS_WINDOWS
730 /* defined in fileutils.c */
731 void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
732 void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, ULONG,
733                                 FILE_BASIC_INFO *, FILE_ID_INFO *,
734                                 struct _Py_stat_struct *);
735 void _Py_stat_basic_info_to_stat(FILE_STAT_BASIC_INFORMATION *,
736                                  struct _Py_stat_struct *);
737 #endif
738 
739 
740 #ifndef MS_WINDOWS
741 PyObject *
_PyLong_FromUid(uid_t uid)742 _PyLong_FromUid(uid_t uid)
743 {
744     if (uid == (uid_t)-1)
745         return PyLong_FromLong(-1);
746     return PyLong_FromUnsignedLong(uid);
747 }
748 
749 PyObject *
_PyLong_FromGid(gid_t gid)750 _PyLong_FromGid(gid_t gid)
751 {
752     if (gid == (gid_t)-1)
753         return PyLong_FromLong(-1);
754     return PyLong_FromUnsignedLong(gid);
755 }
756 
757 int
_Py_Uid_Converter(PyObject * obj,uid_t * p)758 _Py_Uid_Converter(PyObject *obj, uid_t *p)
759 {
760     uid_t uid;
761     PyObject *index;
762     int overflow;
763     long result;
764     unsigned long uresult;
765 
766     index = _PyNumber_Index(obj);
767     if (index == NULL) {
768         PyErr_Format(PyExc_TypeError,
769                      "uid should be integer, not %.200s",
770                      _PyType_Name(Py_TYPE(obj)));
771         return 0;
772     }
773 
774     /*
775      * Handling uid_t is complicated for two reasons:
776      *  * Although uid_t is (always?) unsigned, it still
777      *    accepts -1.
778      *  * We don't know its size in advance--it may be
779      *    bigger than an int, or it may be smaller than
780      *    a long.
781      *
782      * So a bit of defensive programming is in order.
783      * Start with interpreting the value passed
784      * in as a signed long and see if it works.
785      */
786 
787     result = PyLong_AsLongAndOverflow(index, &overflow);
788 
789     if (!overflow) {
790         uid = (uid_t)result;
791 
792         if (result == -1) {
793             if (PyErr_Occurred())
794                 goto fail;
795             /* It's a legitimate -1, we're done. */
796             goto success;
797         }
798 
799         /* Any other negative number is disallowed. */
800         if (result < 0)
801             goto underflow;
802 
803         /* Ensure the value wasn't truncated. */
804         if (sizeof(uid_t) < sizeof(long) &&
805             (long)uid != result)
806             goto underflow;
807         goto success;
808     }
809 
810     if (overflow < 0)
811         goto underflow;
812 
813     /*
814      * Okay, the value overflowed a signed long.  If it
815      * fits in an *unsigned* long, it may still be okay,
816      * as uid_t may be unsigned long on this platform.
817      */
818     uresult = PyLong_AsUnsignedLong(index);
819     if (PyErr_Occurred()) {
820         if (PyErr_ExceptionMatches(PyExc_OverflowError))
821             goto overflow;
822         goto fail;
823     }
824 
825     uid = (uid_t)uresult;
826 
827     /*
828      * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
829      * but this value would get interpreted as (uid_t)-1  by chown
830      * and its siblings.   That's not what the user meant!  So we
831      * throw an overflow exception instead.   (We already
832      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
833      */
834     if (uid == (uid_t)-1)
835         goto overflow;
836 
837     /* Ensure the value wasn't truncated. */
838     if (sizeof(uid_t) < sizeof(long) &&
839         (unsigned long)uid != uresult)
840         goto overflow;
841     /* fallthrough */
842 
843 success:
844     Py_DECREF(index);
845     *p = uid;
846     return 1;
847 
848 underflow:
849     PyErr_SetString(PyExc_OverflowError,
850                     "uid is less than minimum");
851     goto fail;
852 
853 overflow:
854     PyErr_SetString(PyExc_OverflowError,
855                     "uid is greater than maximum");
856     /* fallthrough */
857 
858 fail:
859     Py_DECREF(index);
860     return 0;
861 }
862 
863 int
_Py_Gid_Converter(PyObject * obj,gid_t * p)864 _Py_Gid_Converter(PyObject *obj, gid_t *p)
865 {
866     gid_t gid;
867     PyObject *index;
868     int overflow;
869     long result;
870     unsigned long uresult;
871 
872     index = _PyNumber_Index(obj);
873     if (index == NULL) {
874         PyErr_Format(PyExc_TypeError,
875                      "gid should be integer, not %.200s",
876                      _PyType_Name(Py_TYPE(obj)));
877         return 0;
878     }
879 
880     /*
881      * Handling gid_t is complicated for two reasons:
882      *  * Although gid_t is (always?) unsigned, it still
883      *    accepts -1.
884      *  * We don't know its size in advance--it may be
885      *    bigger than an int, or it may be smaller than
886      *    a long.
887      *
888      * So a bit of defensive programming is in order.
889      * Start with interpreting the value passed
890      * in as a signed long and see if it works.
891      */
892 
893     result = PyLong_AsLongAndOverflow(index, &overflow);
894 
895     if (!overflow) {
896         gid = (gid_t)result;
897 
898         if (result == -1) {
899             if (PyErr_Occurred())
900                 goto fail;
901             /* It's a legitimate -1, we're done. */
902             goto success;
903         }
904 
905         /* Any other negative number is disallowed. */
906         if (result < 0) {
907             goto underflow;
908         }
909 
910         /* Ensure the value wasn't truncated. */
911         if (sizeof(gid_t) < sizeof(long) &&
912             (long)gid != result)
913             goto underflow;
914         goto success;
915     }
916 
917     if (overflow < 0)
918         goto underflow;
919 
920     /*
921      * Okay, the value overflowed a signed long.  If it
922      * fits in an *unsigned* long, it may still be okay,
923      * as gid_t may be unsigned long on this platform.
924      */
925     uresult = PyLong_AsUnsignedLong(index);
926     if (PyErr_Occurred()) {
927         if (PyErr_ExceptionMatches(PyExc_OverflowError))
928             goto overflow;
929         goto fail;
930     }
931 
932     gid = (gid_t)uresult;
933 
934     /*
935      * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
936      * but this value would get interpreted as (gid_t)-1  by chown
937      * and its siblings.   That's not what the user meant!  So we
938      * throw an overflow exception instead.   (We already
939      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
940      */
941     if (gid == (gid_t)-1)
942         goto overflow;
943 
944     /* Ensure the value wasn't truncated. */
945     if (sizeof(gid_t) < sizeof(long) &&
946         (unsigned long)gid != uresult)
947         goto overflow;
948     /* fallthrough */
949 
950 success:
951     Py_DECREF(index);
952     *p = gid;
953     return 1;
954 
955 underflow:
956     PyErr_SetString(PyExc_OverflowError,
957                     "gid is less than minimum");
958     goto fail;
959 
960 overflow:
961     PyErr_SetString(PyExc_OverflowError,
962                     "gid is greater than maximum");
963     /* fallthrough */
964 
965 fail:
966     Py_DECREF(index);
967     return 0;
968 }
969 #endif /* MS_WINDOWS */
970 
971 
972 static PyObject *
_PyLong_FromDev(dev_t dev)973 _PyLong_FromDev(dev_t dev)
974 {
975 #ifdef NODEV
976     if (dev == NODEV) {
977         return PyLong_FromLongLong((long long)dev);
978     }
979 #endif
980     return PyLong_FromUnsignedLongLong((unsigned long long)dev);
981 }
982 
983 
984 #if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
985 static int
_Py_Dev_Converter(PyObject * obj,void * p)986 _Py_Dev_Converter(PyObject *obj, void *p)
987 {
988 #ifdef NODEV
989     if (PyLong_Check(obj) && _PyLong_IsNegative((PyLongObject *)obj)) {
990         int overflow;
991         long long result = PyLong_AsLongLongAndOverflow(obj, &overflow);
992         if (result == -1 && PyErr_Occurred()) {
993             return 0;
994         }
995         if (!overflow && result == (long long)NODEV) {
996             *((dev_t *)p) = NODEV;
997             return 1;
998         }
999     }
1000 #endif
1001 
1002     unsigned long long result = PyLong_AsUnsignedLongLong(obj);
1003     if (result == (unsigned long long)-1 && PyErr_Occurred()) {
1004         return 0;
1005     }
1006     if ((unsigned long long)(dev_t)result != result) {
1007         PyErr_SetString(PyExc_OverflowError,
1008                         "Python int too large to convert to C dev_t");
1009         return 0;
1010     }
1011     *((dev_t *)p) = (dev_t)result;
1012     return 1;
1013 }
1014 #endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
1015 
1016 
1017 #ifdef AT_FDCWD
1018 /*
1019  * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
1020  * without the int cast, the value gets interpreted as uint (4291925331),
1021  * which doesn't play nicely with all the initializer lines in this file that
1022  * look like this:
1023  *      int dir_fd = DEFAULT_DIR_FD;
1024  */
1025 #define DEFAULT_DIR_FD (int)AT_FDCWD
1026 #else
1027 #define DEFAULT_DIR_FD (-100)
1028 #endif
1029 
1030 static int
_fd_converter(PyObject * o,int * p)1031 _fd_converter(PyObject *o, int *p)
1032 {
1033     int overflow;
1034     long long_value;
1035 
1036     if (PyBool_Check(o)) {
1037         if (PyErr_WarnEx(PyExc_RuntimeWarning,
1038                 "bool is used as a file descriptor", 1))
1039         {
1040             return 0;
1041         }
1042     }
1043     PyObject *index = _PyNumber_Index(o);
1044     if (index == NULL) {
1045         return 0;
1046     }
1047 
1048     assert(PyLong_Check(index));
1049     long_value = PyLong_AsLongAndOverflow(index, &overflow);
1050     Py_DECREF(index);
1051     assert(!PyErr_Occurred());
1052     if (overflow > 0 || long_value > INT_MAX) {
1053         PyErr_SetString(PyExc_OverflowError,
1054                         "fd is greater than maximum");
1055         return 0;
1056     }
1057     if (overflow < 0 || long_value < INT_MIN) {
1058         PyErr_SetString(PyExc_OverflowError,
1059                         "fd is less than minimum");
1060         return 0;
1061     }
1062 
1063     *p = (int)long_value;
1064     return 1;
1065 }
1066 
1067 static int
dir_fd_converter(PyObject * o,void * p)1068 dir_fd_converter(PyObject *o, void *p)
1069 {
1070     if (o == Py_None) {
1071         *(int *)p = DEFAULT_DIR_FD;
1072         return 1;
1073     }
1074     else if (PyIndex_Check(o)) {
1075         return _fd_converter(o, (int *)p);
1076     }
1077     else {
1078         PyErr_Format(PyExc_TypeError,
1079                      "argument should be integer or None, not %.200s",
1080                      _PyType_Name(Py_TYPE(o)));
1081         return 0;
1082     }
1083 }
1084 
1085 typedef struct {
1086     PyObject *billion;
1087     PyObject *DirEntryType;
1088     PyObject *ScandirIteratorType;
1089 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
1090     PyObject *SchedParamType;
1091 #endif
1092     newfunc statresult_new_orig;
1093     PyObject *StatResultType;
1094     PyObject *StatVFSResultType;
1095     PyObject *TerminalSizeType;
1096     PyObject *TimesResultType;
1097     PyObject *UnameResultType;
1098 #if defined(HAVE_WAITID)
1099     PyObject *WaitidResultType;
1100 #endif
1101 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
1102     PyObject *struct_rusage;
1103 #endif
1104     PyObject *st_mode;
1105 #ifndef MS_WINDOWS
1106     // times() clock frequency in hertz; used by os.times()
1107     long ticks_per_second;
1108 #endif
1109 } _posixstate;
1110 
1111 
1112 static inline _posixstate*
get_posix_state(PyObject * module)1113 get_posix_state(PyObject *module)
1114 {
1115     void *state = _PyModule_GetState(module);
1116     assert(state != NULL);
1117     return (_posixstate *)state;
1118 }
1119 
1120 /*
1121  * A PyArg_ParseTuple "converter" function
1122  * that handles filesystem paths in the manner
1123  * preferred by the os module.
1124  *
1125  * path_converter accepts (Unicode) strings and their
1126  * subclasses, and bytes and their subclasses.  What
1127  * it does with the argument depends on path.make_wide:
1128  *
1129  *   * If path.make_wide is nonzero, if we get a (Unicode)
1130  *     string we extract the wchar_t * and return it; if we
1131  *     get bytes we decode to wchar_t * and return that.
1132  *
1133  *   * If path.make_wide is zero, if we get bytes we extract
1134  *     the char_t * and return it; if we get a (Unicode)
1135  *     string we encode to char_t * and return that.
1136  *
1137  * path_converter also optionally accepts signed
1138  * integers (representing open file descriptors) instead
1139  * of path strings.
1140  *
1141  * Input fields:
1142  *   path.nullable
1143  *     If nonzero, the path is permitted to be None.
1144  *   path.nonstrict
1145  *     If nonzero, the path is permitted to contain
1146  *     embedded null characters and have any length.
1147  *   path.make_wide
1148  *     If nonzero, the converter always uses wide, decoding if necessary, else
1149  *     it always uses narrow, encoding if necessary. The default value is
1150  *     nonzero on Windows, else zero.
1151  *   path.suppress_value_error
1152  *     If nonzero, raising ValueError is suppressed.
1153  *   path.allow_fd
1154  *     If nonzero, the path is permitted to be a file handle
1155  *     (a signed int) instead of a string.
1156  *   path.function_name
1157  *     If non-NULL, path_converter will use that as the name
1158  *     of the function in error messages.
1159  *     (If path.function_name is NULL it omits the function name.)
1160  *   path.argument_name
1161  *     If non-NULL, path_converter will use that as the name
1162  *     of the parameter in error messages.
1163  *     (If path.argument_name is NULL it uses "path".)
1164  *
1165  * Output fields:
1166  *   path.wide
1167  *     Points to the path if it was expressed as Unicode
1168  *     or if it was bytes and decoded to Unicode.
1169  *   path.narrow
1170  *     Points to the path if it was expressed as bytes,
1171  *     or if it was Unicode and encoded to bytes.
1172  *   path.fd
1173  *     Contains a file descriptor if path.accept_fd was true
1174  *     and the caller provided a signed integer instead of any
1175  *     sort of string.
1176  *
1177  *     WARNING: if your "path" parameter is optional, and is
1178  *     unspecified, path_converter will never get called.
1179  *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1180  *     yourself!
1181  *   path.value_error
1182  *     If nonzero, then suppress_value_error was specified and a ValueError
1183  *     occurred.
1184  *   path.length
1185  *     The length of the path in characters, if specified as
1186  *     a string.
1187  *   path.object
1188  *     The original object passed in (if get a PathLike object,
1189  *     the result of PyOS_FSPath() is treated as the original object).
1190  *     Own a reference to the object.
1191  *   path.cleanup
1192  *     For internal use only.  May point to a temporary object.
1193  *     (Pay no attention to the man behind the curtain.)
1194  *
1195  *   At most one of path.wide or path.narrow will be non-NULL.
1196  *   If path was None and path.nullable was set,
1197  *     or if path was an integer and path.allow_fd was set,
1198  *     both path.wide and path.narrow will be NULL
1199  *     and path.length will be 0.
1200  *
1201  *   path_converter takes care to not write to the path_t
1202  *   unless it's successful.  However it must reset the
1203  *   "cleanup" field each time it's called.
1204  *
1205  * Use as follows:
1206  *      path_t path;
1207  *      memset(&path, 0, sizeof(path));
1208  *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1209  *      // ... use values from path ...
1210  *      path_cleanup(&path);
1211  *
1212  * (Note that if PyArg_Parse fails you don't need to call
1213  * path_cleanup().  However it is safe to do so.)
1214  */
1215 typedef struct {
1216     // Input fields
1217     const char *function_name;
1218     const char *argument_name;
1219     int nullable;
1220     int nonstrict;
1221     int make_wide;
1222     int suppress_value_error;
1223     int allow_fd;
1224     // Output fields
1225     const wchar_t *wide;
1226     const char *narrow;
1227     int fd;
1228     int value_error;
1229     Py_ssize_t length;
1230     PyObject *object;
1231     PyObject *cleanup;
1232 } path_t;
1233 
1234 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \
1235                           make_wide, suppress_value_error, allow_fd) \
1236     {function_name, argument_name, nullable, nonstrict, make_wide, \
1237      suppress_value_error, allow_fd, NULL, NULL, -1, 0, 0, NULL, NULL}
1238 #ifdef MS_WINDOWS
1239 #define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1240                             nonstrict, suppress_value_error, allow_fd) \
1241     PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 1, \
1242                       suppress_value_error, allow_fd)
1243 #else
1244 #define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1245                             nonstrict, suppress_value_error, allow_fd) \
1246     PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1247                       suppress_value_error, allow_fd)
1248 #endif
1249 
1250 static void
path_cleanup(path_t * path)1251 path_cleanup(path_t *path)
1252 {
1253     wchar_t *wide = (wchar_t *)path->wide;
1254     path->wide = NULL;
1255     PyMem_Free(wide);
1256     Py_CLEAR(path->object);
1257     Py_CLEAR(path->cleanup);
1258 }
1259 
1260 static int
path_converter(PyObject * o,void * p)1261 path_converter(PyObject *o, void *p)
1262 {
1263     path_t *path = (path_t *)p;
1264     PyObject *bytes = NULL;
1265     Py_ssize_t length = 0;
1266     int is_index, is_bytes, is_unicode;
1267     const char *narrow;
1268     PyObject *wo = NULL;
1269     wchar_t *wide = NULL;
1270 
1271 #define FORMAT_EXCEPTION(exc, fmt) \
1272     PyErr_Format(exc, "%s%s" fmt, \
1273         path->function_name ? path->function_name : "", \
1274         path->function_name ? ": "                : "", \
1275         path->argument_name ? path->argument_name : "path")
1276 
1277     /* Py_CLEANUP_SUPPORTED support */
1278     if (o == NULL) {
1279         path_cleanup(path);
1280         return 1;
1281     }
1282 
1283     /* Ensure it's always safe to call path_cleanup(). */
1284     path->object = path->cleanup = NULL;
1285     /* path->object owns a reference to the original object */
1286     Py_INCREF(o);
1287 
1288     if ((o == Py_None) && path->nullable) {
1289         path->wide = NULL;
1290         path->narrow = NULL;
1291         path->fd = -1;
1292         goto success_exit;
1293     }
1294 
1295     /* Only call this here so that we don't treat the return value of
1296        os.fspath() as an fd or buffer. */
1297     is_index = path->allow_fd && PyIndex_Check(o);
1298     is_bytes = PyBytes_Check(o);
1299     is_unicode = PyUnicode_Check(o);
1300 
1301     if (!is_index && !is_unicode && !is_bytes) {
1302         /* Inline PyOS_FSPath() for better error messages. */
1303         PyObject *func, *res;
1304 
1305         func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1306         if ((NULL == func) || (func == Py_None)) {
1307             goto error_format;
1308         }
1309         res = _PyObject_CallNoArgs(func);
1310         Py_DECREF(func);
1311         if (NULL == res) {
1312             goto error_exit;
1313         }
1314         else if (PyUnicode_Check(res)) {
1315             is_unicode = 1;
1316         }
1317         else if (PyBytes_Check(res)) {
1318             is_bytes = 1;
1319         }
1320         else {
1321             PyErr_Format(PyExc_TypeError,
1322                  "expected %.200s.__fspath__() to return str or bytes, "
1323                  "not %.200s", _PyType_Name(Py_TYPE(o)),
1324                  _PyType_Name(Py_TYPE(res)));
1325             Py_DECREF(res);
1326             goto error_exit;
1327         }
1328 
1329         /* still owns a reference to the original object */
1330         Py_SETREF(o, res);
1331     }
1332 
1333     if (is_unicode) {
1334         if (path->make_wide) {
1335             wide = PyUnicode_AsWideCharString(o, &length);
1336             if (!wide) {
1337                 goto error_exit;
1338             }
1339 #ifdef MS_WINDOWS
1340             if (!path->nonstrict && length > 32767) {
1341                 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1342                 goto error_exit;
1343             }
1344 #endif
1345             if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1346                 FORMAT_EXCEPTION(PyExc_ValueError,
1347                                  "embedded null character in %s");
1348                 goto error_exit;
1349             }
1350 
1351             path->wide = wide;
1352             path->narrow = NULL;
1353             path->fd = -1;
1354             wide = NULL;
1355             goto success_exit;
1356         }
1357         bytes = PyUnicode_EncodeFSDefault(o);
1358         if (!bytes) {
1359             goto error_exit;
1360         }
1361     }
1362     else if (is_bytes) {
1363         bytes = Py_NewRef(o);
1364     }
1365     else if (is_index) {
1366         if (!_fd_converter(o, &path->fd)) {
1367             goto error_exit;
1368         }
1369         path->wide = NULL;
1370         path->narrow = NULL;
1371         goto success_exit;
1372     }
1373     else {
1374  error_format:
1375         PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1376             path->function_name ? path->function_name : "",
1377             path->function_name ? ": "                : "",
1378             path->argument_name ? path->argument_name : "path",
1379             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1380                                                "integer or None" :
1381             path->allow_fd ? "string, bytes, os.PathLike or integer" :
1382             path->nullable ? "string, bytes, os.PathLike or None" :
1383                              "string, bytes or os.PathLike",
1384             _PyType_Name(Py_TYPE(o)));
1385         goto error_exit;
1386     }
1387 
1388     length = PyBytes_GET_SIZE(bytes);
1389     narrow = PyBytes_AS_STRING(bytes);
1390     if (!path->nonstrict && strlen(narrow) != (size_t)length) {
1391         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1392         goto error_exit;
1393     }
1394 
1395     if (path->make_wide) {
1396         wo = PyUnicode_DecodeFSDefaultAndSize(narrow, length);
1397         if (!wo) {
1398             goto error_exit;
1399         }
1400 
1401         wide = PyUnicode_AsWideCharString(wo, &length);
1402         Py_DECREF(wo);
1403         if (!wide) {
1404             goto error_exit;
1405         }
1406 #ifdef MS_WINDOWS
1407         if (!path->nonstrict && length > 32767) {
1408             FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1409             goto error_exit;
1410         }
1411 #endif
1412         if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1413             FORMAT_EXCEPTION(PyExc_ValueError,
1414                              "embedded null character in %s");
1415             goto error_exit;
1416         }
1417         path->wide = wide;
1418         path->narrow = NULL;
1419         Py_DECREF(bytes);
1420         wide = NULL;
1421     }
1422     else {
1423         path->wide = NULL;
1424         path->narrow = narrow;
1425         if (bytes == o) {
1426             /* Still a reference owned by path->object, don't have to
1427             worry about path->narrow is used after free. */
1428             Py_DECREF(bytes);
1429         }
1430         else {
1431             path->cleanup = bytes;
1432         }
1433     }
1434     path->fd = -1;
1435 
1436  success_exit:
1437     path->value_error = 0;
1438     path->length = length;
1439     path->object = o;
1440     return Py_CLEANUP_SUPPORTED;
1441 
1442  error_exit:
1443     Py_XDECREF(o);
1444     Py_XDECREF(bytes);
1445     PyMem_Free(wide);
1446     if (!path->suppress_value_error ||
1447         !PyErr_ExceptionMatches(PyExc_ValueError))
1448     {
1449         return 0;
1450     }
1451     PyErr_Clear();
1452     path->wide = NULL;
1453     path->narrow = NULL;
1454     path->fd = -1;
1455     path->value_error = 1;
1456     path->length = 0;
1457     path->object = NULL;
1458     return Py_CLEANUP_SUPPORTED;
1459 }
1460 
1461 static void
argument_unavailable_error(const char * function_name,const char * argument_name)1462 argument_unavailable_error(const char *function_name, const char *argument_name)
1463 {
1464     PyErr_Format(PyExc_NotImplementedError,
1465         "%s%s%s unavailable on this platform",
1466         (function_name != NULL) ? function_name : "",
1467         (function_name != NULL) ? ": ": "",
1468         argument_name);
1469 }
1470 
1471 static int
dir_fd_unavailable(PyObject * o,void * p)1472 dir_fd_unavailable(PyObject *o, void *p)
1473 {
1474     int dir_fd;
1475     if (!dir_fd_converter(o, &dir_fd))
1476         return 0;
1477     if (dir_fd != DEFAULT_DIR_FD) {
1478         argument_unavailable_error(NULL, "dir_fd");
1479         return 0;
1480     }
1481     *(int *)p = dir_fd;
1482     return 1;
1483 }
1484 
1485 static int
fd_specified(const char * function_name,int fd)1486 fd_specified(const char *function_name, int fd)
1487 {
1488     if (fd == -1)
1489         return 0;
1490 
1491     argument_unavailable_error(function_name, "fd");
1492     return 1;
1493 }
1494 
1495 static int
follow_symlinks_specified(const char * function_name,int follow_symlinks)1496 follow_symlinks_specified(const char *function_name, int follow_symlinks)
1497 {
1498     if (follow_symlinks)
1499         return 0;
1500 
1501     argument_unavailable_error(function_name, "follow_symlinks");
1502     return 1;
1503 }
1504 
1505 static int
path_and_dir_fd_invalid(const char * function_name,path_t * path,int dir_fd)1506 path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1507 {
1508     if (!path->wide && (dir_fd != DEFAULT_DIR_FD) && !path->narrow) {
1509         PyErr_Format(PyExc_ValueError,
1510                      "%s: can't specify dir_fd without matching path",
1511                      function_name);
1512         return 1;
1513     }
1514     return 0;
1515 }
1516 
1517 static int
dir_fd_and_fd_invalid(const char * function_name,int dir_fd,int fd)1518 dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1519 {
1520     if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1521         PyErr_Format(PyExc_ValueError,
1522                      "%s: can't specify both dir_fd and fd",
1523                      function_name);
1524         return 1;
1525     }
1526     return 0;
1527 }
1528 
1529 static int
fd_and_follow_symlinks_invalid(const char * function_name,int fd,int follow_symlinks)1530 fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1531                                int follow_symlinks)
1532 {
1533     if ((fd > 0) && (!follow_symlinks)) {
1534         PyErr_Format(PyExc_ValueError,
1535                      "%s: cannot use fd and follow_symlinks together",
1536                      function_name);
1537         return 1;
1538     }
1539     return 0;
1540 }
1541 
1542 static int
dir_fd_and_follow_symlinks_invalid(const char * function_name,int dir_fd,int follow_symlinks)1543 dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1544                                    int follow_symlinks)
1545 {
1546     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1547         PyErr_Format(PyExc_ValueError,
1548                      "%s: cannot use dir_fd and follow_symlinks together",
1549                      function_name);
1550         return 1;
1551     }
1552     return 0;
1553 }
1554 
1555 #ifdef MS_WINDOWS
1556     typedef long long Py_off_t;
1557 #else
1558     typedef off_t Py_off_t;
1559 #endif
1560 
1561 static int
Py_off_t_converter(PyObject * arg,void * addr)1562 Py_off_t_converter(PyObject *arg, void *addr)
1563 {
1564 #ifdef HAVE_LARGEFILE_SUPPORT
1565     *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1566 #else
1567     *((Py_off_t *)addr) = PyLong_AsLong(arg);
1568 #endif
1569     if (PyErr_Occurred())
1570         return 0;
1571     return 1;
1572 }
1573 
1574 static PyObject *
PyLong_FromPy_off_t(Py_off_t offset)1575 PyLong_FromPy_off_t(Py_off_t offset)
1576 {
1577 #ifdef HAVE_LARGEFILE_SUPPORT
1578     return PyLong_FromLongLong(offset);
1579 #else
1580     return PyLong_FromLong(offset);
1581 #endif
1582 }
1583 
1584 #ifdef HAVE_SIGSET_T
1585 /* Convert an iterable of integers to a sigset.
1586    Return 1 on success, return 0 and raise an exception on error. */
1587 int
_Py_Sigset_Converter(PyObject * obj,void * addr)1588 _Py_Sigset_Converter(PyObject *obj, void *addr)
1589 {
1590     sigset_t *mask = (sigset_t *)addr;
1591     PyObject *iterator, *item;
1592     long signum;
1593     int overflow;
1594 
1595     // The extra parens suppress the unreachable-code warning with clang on MacOS
1596     if (sigemptyset(mask) < (0)) {
1597         /* Probably only if mask == NULL. */
1598         PyErr_SetFromErrno(PyExc_OSError);
1599         return 0;
1600     }
1601 
1602     iterator = PyObject_GetIter(obj);
1603     if (iterator == NULL) {
1604         return 0;
1605     }
1606 
1607     while ((item = PyIter_Next(iterator)) != NULL) {
1608         signum = PyLong_AsLongAndOverflow(item, &overflow);
1609         Py_DECREF(item);
1610         if (signum <= 0 || signum >= Py_NSIG) {
1611             if (overflow || signum != -1 || !PyErr_Occurred()) {
1612                 PyErr_Format(PyExc_ValueError,
1613                              "signal number %ld out of range [1; %i]",
1614                              signum, Py_NSIG - 1);
1615             }
1616             goto error;
1617         }
1618         if (sigaddset(mask, (int)signum)) {
1619             if (errno != EINVAL) {
1620                 /* Probably impossible */
1621                 PyErr_SetFromErrno(PyExc_OSError);
1622                 goto error;
1623             }
1624             /* For backwards compatibility, allow idioms such as
1625              * `range(1, NSIG)` but warn about invalid signal numbers
1626              */
1627             const char msg[] =
1628                 "invalid signal number %ld, please use valid_signals()";
1629             if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1630                 goto error;
1631             }
1632         }
1633     }
1634     if (!PyErr_Occurred()) {
1635         Py_DECREF(iterator);
1636         return 1;
1637     }
1638 
1639 error:
1640     Py_DECREF(iterator);
1641     return 0;
1642 }
1643 #endif /* HAVE_SIGSET_T */
1644 
1645 /* Return a dictionary corresponding to the POSIX environment table */
1646 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1647 /* On Darwin/MacOSX a shared library or framework has no access to
1648 ** environ directly, we must obtain it with _NSGetEnviron(). See also
1649 ** man environ(7).
1650 */
1651 #include <crt_externs.h>
1652 #define USE_DARWIN_NS_GET_ENVIRON 1
1653 #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1654 extern char **environ;
1655 #endif /* !_MSC_VER */
1656 
1657 static PyObject *
convertenviron(void)1658 convertenviron(void)
1659 {
1660     PyObject *d;
1661 #ifdef MS_WINDOWS
1662     wchar_t **e;
1663 #else
1664     char **e;
1665 #endif
1666 
1667     d = PyDict_New();
1668     if (d == NULL)
1669         return NULL;
1670 #ifdef MS_WINDOWS
1671     /* _wenviron must be initialized in this way if the program is started
1672        through main() instead of wmain(). */
1673     (void)_wgetenv(L"");
1674     e = _wenviron;
1675 #elif defined(USE_DARWIN_NS_GET_ENVIRON)
1676     /* environ is not accessible as an extern in a shared object on OSX; use
1677        _NSGetEnviron to resolve it. The value changes if you add environment
1678        variables between calls to Py_Initialize, so don't cache the value. */
1679     e = *_NSGetEnviron();
1680 #else
1681     e = environ;
1682 #endif
1683     if (e == NULL)
1684         return d;
1685     for (; *e != NULL; e++) {
1686         PyObject *k;
1687         PyObject *v;
1688 #ifdef MS_WINDOWS
1689         const wchar_t *p = wcschr(*e, L'=');
1690 #else
1691         const char *p = strchr(*e, '=');
1692 #endif
1693         if (p == NULL)
1694             continue;
1695 #ifdef MS_WINDOWS
1696         k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1697 #else
1698         k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1699 #endif
1700         if (k == NULL) {
1701             Py_DECREF(d);
1702             return NULL;
1703         }
1704 #ifdef MS_WINDOWS
1705         v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1706 #else
1707         v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1708 #endif
1709         if (v == NULL) {
1710             Py_DECREF(k);
1711             Py_DECREF(d);
1712             return NULL;
1713         }
1714         if (PyDict_SetDefaultRef(d, k, v, NULL) < 0) {
1715             Py_DECREF(v);
1716             Py_DECREF(k);
1717             Py_DECREF(d);
1718             return NULL;
1719         }
1720         Py_DECREF(k);
1721         Py_DECREF(v);
1722     }
1723     return d;
1724 }
1725 
1726 /* Set a POSIX-specific error from errno, and return NULL */
1727 
1728 static PyObject *
posix_error(void)1729 posix_error(void)
1730 {
1731     return PyErr_SetFromErrno(PyExc_OSError);
1732 }
1733 
1734 #ifdef MS_WINDOWS
1735 static PyObject *
win32_error(const char * function,const char * filename)1736 win32_error(const char* function, const char* filename)
1737 {
1738     /* XXX We should pass the function name along in the future.
1739        (winreg.c also wants to pass the function name.)
1740        This would however require an additional param to the
1741        Windows error object, which is non-trivial.
1742     */
1743     errno = GetLastError();
1744     if (filename)
1745         return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1746     else
1747         return PyErr_SetFromWindowsErr(errno);
1748 }
1749 
1750 static PyObject *
win32_error_object_err(const char * function,PyObject * filename,DWORD err)1751 win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1752 {
1753     /* XXX - see win32_error for comments on 'function' */
1754     if (filename)
1755         return PyErr_SetExcFromWindowsErrWithFilenameObject(
1756                     PyExc_OSError,
1757                     err,
1758                     filename);
1759     else
1760         return PyErr_SetFromWindowsErr(err);
1761 }
1762 
1763 static PyObject *
win32_error_object(const char * function,PyObject * filename)1764 win32_error_object(const char* function, PyObject* filename)
1765 {
1766     errno = GetLastError();
1767     return win32_error_object_err(function, filename, errno);
1768 }
1769 
1770 #endif /* MS_WINDOWS */
1771 
1772 static PyObject *
posix_path_object_error(PyObject * path)1773 posix_path_object_error(PyObject *path)
1774 {
1775     return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1776 }
1777 
1778 static PyObject *
path_object_error(PyObject * path)1779 path_object_error(PyObject *path)
1780 {
1781 #ifdef MS_WINDOWS
1782     return PyErr_SetExcFromWindowsErrWithFilenameObject(
1783                 PyExc_OSError, 0, path);
1784 #else
1785     return posix_path_object_error(path);
1786 #endif
1787 }
1788 
1789 static PyObject *
path_object_error2(PyObject * path,PyObject * path2)1790 path_object_error2(PyObject *path, PyObject *path2)
1791 {
1792 #ifdef MS_WINDOWS
1793     return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1794                 PyExc_OSError, 0, path, path2);
1795 #else
1796     return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1797 #endif
1798 }
1799 
1800 static PyObject *
path_error(path_t * path)1801 path_error(path_t *path)
1802 {
1803     return path_object_error(path->object);
1804 }
1805 
1806 static PyObject *
posix_path_error(path_t * path)1807 posix_path_error(path_t *path)
1808 {
1809     return posix_path_object_error(path->object);
1810 }
1811 
1812 static PyObject *
path_error2(path_t * path,path_t * path2)1813 path_error2(path_t *path, path_t *path2)
1814 {
1815     return path_object_error2(path->object, path2->object);
1816 }
1817 
1818 
1819 /* POSIX generic methods */
1820 
1821 static PyObject *
posix_fildes_fd(int fd,int (* func)(int))1822 posix_fildes_fd(int fd, int (*func)(int))
1823 {
1824     int res;
1825     int async_err = 0;
1826 
1827     do {
1828         Py_BEGIN_ALLOW_THREADS
1829         _Py_BEGIN_SUPPRESS_IPH
1830         res = (*func)(fd);
1831         _Py_END_SUPPRESS_IPH
1832         Py_END_ALLOW_THREADS
1833     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1834     if (res != 0)
1835         return (!async_err) ? posix_error() : NULL;
1836     Py_RETURN_NONE;
1837 }
1838 
1839 
1840 #ifdef MS_WINDOWS
1841 /* This is a reimplementation of the C library's chdir function,
1842    but one that produces Win32 errors instead of DOS error codes.
1843    chdir is essentially a wrapper around SetCurrentDirectory; however,
1844    it also needs to set "magic" environment variables indicating
1845    the per-drive current directory, which are of the form =<drive>: */
1846 static BOOL __stdcall
win32_wchdir(LPCWSTR path)1847 win32_wchdir(LPCWSTR path)
1848 {
1849     wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1850     int result;
1851     wchar_t env[4] = L"=x:";
1852 
1853     if(!SetCurrentDirectoryW(path))
1854         return FALSE;
1855     result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1856     if (!result)
1857         return FALSE;
1858     if (result > Py_ARRAY_LENGTH(path_buf)) {
1859         new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1860         if (!new_path) {
1861             SetLastError(ERROR_OUTOFMEMORY);
1862             return FALSE;
1863         }
1864         result = GetCurrentDirectoryW(result, new_path);
1865         if (!result) {
1866             PyMem_RawFree(new_path);
1867             return FALSE;
1868         }
1869     }
1870     int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1871                             wcsncmp(new_path, L"//", 2) == 0);
1872     if (!is_unc_like_path) {
1873         env[1] = new_path[0];
1874         result = SetEnvironmentVariableW(env, new_path);
1875     }
1876     if (new_path != path_buf)
1877         PyMem_RawFree(new_path);
1878     return result ? TRUE : FALSE;
1879 }
1880 #endif
1881 
1882 #ifdef MS_WINDOWS
1883 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1884    - time stamps are restricted to second resolution
1885    - file modification times suffer from forth-and-back conversions between
1886      UTC and local time
1887    Therefore, we implement our own stat, based on the Win32 API directly.
1888 */
1889 #define HAVE_STAT_NSEC 1
1890 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1891 #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1892 
1893 static void
find_data_to_file_info(WIN32_FIND_DATAW * pFileData,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1894 find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1895                        BY_HANDLE_FILE_INFORMATION *info,
1896                        ULONG *reparse_tag)
1897 {
1898     memset(info, 0, sizeof(*info));
1899     info->dwFileAttributes = pFileData->dwFileAttributes;
1900     info->ftCreationTime   = pFileData->ftCreationTime;
1901     info->ftLastAccessTime = pFileData->ftLastAccessTime;
1902     info->ftLastWriteTime  = pFileData->ftLastWriteTime;
1903     info->nFileSizeHigh    = pFileData->nFileSizeHigh;
1904     info->nFileSizeLow     = pFileData->nFileSizeLow;
1905 /*  info->nNumberOfLinks   = 1; */
1906     if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1907         *reparse_tag = pFileData->dwReserved0;
1908     else
1909         *reparse_tag = 0;
1910 }
1911 
1912 static BOOL
attributes_from_dir(LPCWSTR pszFile,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1913 attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1914 {
1915     HANDLE hFindFile;
1916     WIN32_FIND_DATAW FileData;
1917     LPCWSTR filename = pszFile;
1918     size_t n = wcslen(pszFile);
1919     if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
1920         // cannot use PyMem_Malloc here because we do not hold the GIL
1921         filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
1922         if(!filename) {
1923             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1924             return FALSE;
1925         }
1926         wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
1927         while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
1928             ((LPWSTR)filename)[n] = L'\0';
1929         }
1930         if (!n || (n == 1 && filename[1] == L':')) {
1931             // Nothing left to query
1932             free((void *)filename);
1933             return FALSE;
1934         }
1935     }
1936     hFindFile = FindFirstFileW(filename, &FileData);
1937     if (pszFile != filename) {
1938         free((void *)filename);
1939     }
1940     if (hFindFile == INVALID_HANDLE_VALUE) {
1941         return FALSE;
1942     }
1943     FindClose(hFindFile);
1944     find_data_to_file_info(&FileData, info, reparse_tag);
1945     return TRUE;
1946 }
1947 
1948 
1949 static void
update_st_mode_from_path(const wchar_t * path,DWORD attr,struct _Py_stat_struct * result)1950 update_st_mode_from_path(const wchar_t *path, DWORD attr,
1951                          struct _Py_stat_struct *result)
1952 {
1953     if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
1954         /* Fix the file execute permissions. This hack sets S_IEXEC if
1955            the filename has an extension that is commonly used by files
1956            that CreateProcessW can execute. A real implementation calls
1957            GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
1958            AccessCheck to check for generic read, write, and execute
1959            access. */
1960         const wchar_t *fileExtension = wcsrchr(path, '.');
1961         if (fileExtension) {
1962             if (_wcsicmp(fileExtension, L".exe") == 0 ||
1963                 _wcsicmp(fileExtension, L".bat") == 0 ||
1964                 _wcsicmp(fileExtension, L".cmd") == 0 ||
1965                 _wcsicmp(fileExtension, L".com") == 0) {
1966                 result->st_mode |= 0111;
1967             }
1968         }
1969     }
1970 }
1971 
1972 
1973 static int
win32_xstat_slow_impl(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1974 win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
1975                       BOOL traverse)
1976 {
1977     HANDLE hFile;
1978     BY_HANDLE_FILE_INFORMATION fileInfo;
1979     FILE_BASIC_INFO basicInfo;
1980     FILE_BASIC_INFO *pBasicInfo = NULL;
1981     FILE_ID_INFO idInfo;
1982     FILE_ID_INFO *pIdInfo = NULL;
1983     FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1984     DWORD fileType, error;
1985     BOOL isUnhandledTag = FALSE;
1986     int retval = 0;
1987 
1988     DWORD access = FILE_READ_ATTRIBUTES;
1989     DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1990     if (!traverse) {
1991         flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1992     }
1993 
1994     hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1995     if (hFile == INVALID_HANDLE_VALUE) {
1996         /* Either the path doesn't exist, or the caller lacks access. */
1997         error = GetLastError();
1998         switch (error) {
1999         case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
2000         case ERROR_SHARING_VIOLATION: /* It's a paging file. */
2001             /* Try reading the parent directory. */
2002             if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
2003                 /* Cannot read the parent directory. */
2004                 switch (GetLastError()) {
2005                 case ERROR_FILE_NOT_FOUND: /* File cannot be found */
2006                 case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
2007                 case ERROR_NOT_READY: /* Drive exists but unavailable */
2008                 case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
2009                     break;
2010                 /* Restore the error from CreateFileW(). */
2011                 default:
2012                     SetLastError(error);
2013                 }
2014 
2015                 return -1;
2016             }
2017             if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
2018                 if (traverse ||
2019                     !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2020                     /* The stat call has to traverse but cannot, so fail. */
2021                     SetLastError(error);
2022                     return -1;
2023                 }
2024             }
2025             break;
2026 
2027         case ERROR_INVALID_PARAMETER:
2028             /* \\.\con requires read or write access. */
2029             hFile = CreateFileW(path, access | GENERIC_READ,
2030                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2031                         OPEN_EXISTING, flags, NULL);
2032             if (hFile == INVALID_HANDLE_VALUE) {
2033                 SetLastError(error);
2034                 return -1;
2035             }
2036             break;
2037 
2038         case ERROR_CANT_ACCESS_FILE:
2039             /* bpo37834: open unhandled reparse points if traverse fails. */
2040             if (traverse) {
2041                 traverse = FALSE;
2042                 isUnhandledTag = TRUE;
2043                 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
2044                             flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
2045             }
2046             if (hFile == INVALID_HANDLE_VALUE) {
2047                 SetLastError(error);
2048                 return -1;
2049             }
2050             break;
2051 
2052         default:
2053             return -1;
2054         }
2055     }
2056 
2057     if (hFile != INVALID_HANDLE_VALUE) {
2058         /* Handle types other than files on disk. */
2059         fileType = GetFileType(hFile);
2060         if (fileType != FILE_TYPE_DISK) {
2061             if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
2062                 retval = -1;
2063                 goto cleanup;
2064             }
2065             DWORD fileAttributes = GetFileAttributesW(path);
2066             memset(result, 0, sizeof(*result));
2067             if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
2068                 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2069                 /* \\.\pipe\ or \\.\mailslot\ */
2070                 result->st_mode = _S_IFDIR;
2071             } else if (fileType == FILE_TYPE_CHAR) {
2072                 /* \\.\nul */
2073                 result->st_mode = _S_IFCHR;
2074             } else if (fileType == FILE_TYPE_PIPE) {
2075                 /* \\.\pipe\spam */
2076                 result->st_mode = _S_IFIFO;
2077             }
2078             /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
2079             goto cleanup;
2080         }
2081 
2082         /* Query the reparse tag, and traverse a non-link. */
2083         if (!traverse) {
2084             if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
2085                     &tagInfo, sizeof(tagInfo))) {
2086                 /* Allow devices that do not support FileAttributeTagInfo. */
2087                 switch (GetLastError()) {
2088                 case ERROR_INVALID_PARAMETER:
2089                 case ERROR_INVALID_FUNCTION:
2090                 case ERROR_NOT_SUPPORTED:
2091                     tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2092                     tagInfo.ReparseTag = 0;
2093                     break;
2094                 default:
2095                     retval = -1;
2096                     goto cleanup;
2097                 }
2098             } else if (tagInfo.FileAttributes &
2099                          FILE_ATTRIBUTE_REPARSE_POINT) {
2100                 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2101                     if (isUnhandledTag) {
2102                         /* Traversing previously failed for either this link
2103                            or its target. */
2104                         SetLastError(ERROR_CANT_ACCESS_FILE);
2105                         retval = -1;
2106                         goto cleanup;
2107                     }
2108                 /* Traverse a non-link, but not if traversing already failed
2109                    for an unhandled tag. */
2110                 } else if (!isUnhandledTag) {
2111                     CloseHandle(hFile);
2112                     return win32_xstat_slow_impl(path, result, TRUE);
2113                 }
2114             }
2115         }
2116 
2117         if (!GetFileInformationByHandle(hFile, &fileInfo) ||
2118             !GetFileInformationByHandleEx(hFile, FileBasicInfo,
2119                                           &basicInfo, sizeof(basicInfo))) {
2120             switch (GetLastError()) {
2121             case ERROR_INVALID_PARAMETER:
2122             case ERROR_INVALID_FUNCTION:
2123             case ERROR_NOT_SUPPORTED:
2124                 /* Volumes and physical disks are block devices, e.g.
2125                    \\.\C: and \\.\PhysicalDrive0. */
2126                 memset(result, 0, sizeof(*result));
2127                 result->st_mode = 0x6000; /* S_IFBLK */
2128                 goto cleanup;
2129             }
2130             retval = -1;
2131             goto cleanup;
2132         }
2133 
2134         /* Successfully got FileBasicInfo, so we'll pass it along */
2135         pBasicInfo = &basicInfo;
2136 
2137         if (GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
2138             /* Successfully got FileIdInfo, so pass it along */
2139             pIdInfo = &idInfo;
2140         }
2141     }
2142 
2143     _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, pBasicInfo, pIdInfo, result);
2144     update_st_mode_from_path(path, fileInfo.dwFileAttributes, result);
2145 
2146 cleanup:
2147     if (hFile != INVALID_HANDLE_VALUE) {
2148         /* Preserve last error if we are failing */
2149         error = retval ? GetLastError() : 0;
2150         if (!CloseHandle(hFile)) {
2151             retval = -1;
2152         } else if (retval) {
2153             /* Restore last error */
2154             SetLastError(error);
2155         }
2156     }
2157 
2158     return retval;
2159 }
2160 
2161 static int
win32_xstat_impl(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)2162 win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
2163                  BOOL traverse)
2164 {
2165     FILE_STAT_BASIC_INFORMATION statInfo;
2166     if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo,
2167                                      &statInfo, sizeof(statInfo))) {
2168         if (// Cannot use fast path for reparse points ...
2169             !(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2170             // ... unless it's a name surrogate (symlink) and we're not following
2171             || (!traverse && IsReparseTagNameSurrogate(statInfo.ReparseTag))
2172         ) {
2173             _Py_stat_basic_info_to_stat(&statInfo, result);
2174             update_st_mode_from_path(path, statInfo.FileAttributes, result);
2175             return 0;
2176         }
2177     } else {
2178         switch(GetLastError()) {
2179         case ERROR_FILE_NOT_FOUND:
2180         case ERROR_PATH_NOT_FOUND:
2181         case ERROR_NOT_READY:
2182         case ERROR_BAD_NET_NAME:
2183             /* These errors aren't worth retrying with the slow path */
2184             return -1;
2185         case ERROR_NOT_SUPPORTED:
2186             /* indicates the API couldn't be loaded */
2187             break;
2188         }
2189     }
2190 
2191     return win32_xstat_slow_impl(path, result, traverse);
2192 }
2193 
2194 static int
win32_xstat(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)2195 win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2196 {
2197     /* Protocol violation: we explicitly clear errno, instead of
2198        setting it to a POSIX error. Callers should use GetLastError. */
2199     int code = win32_xstat_impl(path, result, traverse);
2200     errno = 0;
2201 
2202     /* ctime is only deprecated from 3.12, so we copy birthtime across */
2203     result->st_ctime = result->st_birthtime;
2204     result->st_ctime_nsec = result->st_birthtime_nsec;
2205     return code;
2206 }
2207 /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2208 
2209    In Posix, stat automatically traverses symlinks and returns the stat
2210    structure for the target.  In Windows, the equivalent GetFileAttributes by
2211    default does not traverse symlinks and instead returns attributes for
2212    the symlink.
2213 
2214    Instead, we will open the file (which *does* traverse symlinks by default)
2215    and GetFileInformationByHandle(). */
2216 
2217 static int
win32_lstat(const wchar_t * path,struct _Py_stat_struct * result)2218 win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2219 {
2220     return win32_xstat(path, result, FALSE);
2221 }
2222 
2223 static int
win32_stat(const wchar_t * path,struct _Py_stat_struct * result)2224 win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2225 {
2226     return win32_xstat(path, result, TRUE);
2227 }
2228 
2229 #endif /* MS_WINDOWS */
2230 
2231 PyDoc_STRVAR(stat_result__doc__,
2232 "stat_result: Result from stat, fstat, or lstat.\n\n\
2233 This object may be accessed either as a tuple of\n\
2234   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2235 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2236 \n\
2237 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2238 or st_flags, they are available as attributes only.\n\
2239 \n\
2240 See os.stat for more information.");
2241 
2242 static PyStructSequence_Field stat_result_fields[] = {
2243     {"st_mode",    "protection bits"},
2244     {"st_ino",     "inode"},
2245     {"st_dev",     "device"},
2246     {"st_nlink",   "number of hard links"},
2247     {"st_uid",     "user ID of owner"},
2248     {"st_gid",     "group ID of owner"},
2249     {"st_size",    "total size, in bytes"},
2250     /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2251     {NULL,   "integer time of last access"},
2252     {NULL,   "integer time of last modification"},
2253     {NULL,   "integer time of last change"},
2254     {"st_atime",   "time of last access"},
2255     {"st_mtime",   "time of last modification"},
2256     {"st_ctime",   "time of last change"},
2257     {"st_atime_ns",   "time of last access in nanoseconds"},
2258     {"st_mtime_ns",   "time of last modification in nanoseconds"},
2259     {"st_ctime_ns",   "time of last change in nanoseconds"},
2260 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2261     {"st_blksize", "blocksize for filesystem I/O"},
2262 #endif
2263 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2264     {"st_blocks",  "number of blocks allocated"},
2265 #endif
2266 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2267     {"st_rdev",    "device type (if inode device)"},
2268 #endif
2269 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2270     {"st_flags",   "user defined flags for file"},
2271 #endif
2272 #ifdef HAVE_STRUCT_STAT_ST_GEN
2273     {"st_gen",    "generation number"},
2274 #endif
2275 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2276     {"st_birthtime",   "time of creation"},
2277 #endif
2278 #ifdef MS_WINDOWS
2279     {"st_birthtime_ns", "time of creation in nanoseconds"},
2280 #endif
2281 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2282     {"st_file_attributes", "Windows file attribute bits"},
2283 #endif
2284 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2285     {"st_fstype",  "Type of filesystem"},
2286 #endif
2287 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2288     {"st_reparse_tag", "Windows reparse tag"},
2289 #endif
2290     {0}
2291 };
2292 
2293 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2294 #define ST_BLKSIZE_IDX 16
2295 #else
2296 #define ST_BLKSIZE_IDX 15
2297 #endif
2298 
2299 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2300 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2301 #else
2302 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2303 #endif
2304 
2305 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2306 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2307 #else
2308 #define ST_RDEV_IDX ST_BLOCKS_IDX
2309 #endif
2310 
2311 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2312 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2313 #else
2314 #define ST_FLAGS_IDX ST_RDEV_IDX
2315 #endif
2316 
2317 #ifdef HAVE_STRUCT_STAT_ST_GEN
2318 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
2319 #else
2320 #define ST_GEN_IDX ST_FLAGS_IDX
2321 #endif
2322 
2323 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2324 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2325 #else
2326 #define ST_BIRTHTIME_IDX ST_GEN_IDX
2327 #endif
2328 
2329 #ifdef MS_WINDOWS
2330 #define ST_BIRTHTIME_NS_IDX (ST_BIRTHTIME_IDX+1)
2331 #else
2332 #define ST_BIRTHTIME_NS_IDX ST_BIRTHTIME_IDX
2333 #endif
2334 
2335 #if defined(HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES) || defined(MS_WINDOWS)
2336 #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_NS_IDX+1)
2337 #else
2338 #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_NS_IDX
2339 #endif
2340 
2341 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2342 #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2343 #else
2344 #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2345 #endif
2346 
2347 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2348 #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2349 #else
2350 #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2351 #endif
2352 
2353 static PyStructSequence_Desc stat_result_desc = {
2354     "stat_result", /* name */
2355     stat_result__doc__, /* doc */
2356     stat_result_fields,
2357     10
2358 };
2359 
2360 PyDoc_STRVAR(statvfs_result__doc__,
2361 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
2362 This object may be accessed either as a tuple of\n\
2363   (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2364 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2365 \n\
2366 See os.statvfs for more information.");
2367 
2368 static PyStructSequence_Field statvfs_result_fields[] = {
2369     {"f_bsize",  },
2370     {"f_frsize", },
2371     {"f_blocks", },
2372     {"f_bfree",  },
2373     {"f_bavail", },
2374     {"f_files",  },
2375     {"f_ffree",  },
2376     {"f_favail", },
2377     {"f_flag",   },
2378     {"f_namemax",},
2379     {"f_fsid",   },
2380     {0}
2381 };
2382 
2383 static PyStructSequence_Desc statvfs_result_desc = {
2384     "statvfs_result", /* name */
2385     statvfs_result__doc__, /* doc */
2386     statvfs_result_fields,
2387     10
2388 };
2389 
2390 #if defined(HAVE_WAITID)
2391 PyDoc_STRVAR(waitid_result__doc__,
2392 "waitid_result: Result from waitid.\n\n\
2393 This object may be accessed either as a tuple of\n\
2394   (si_pid, si_uid, si_signo, si_status, si_code),\n\
2395 or via the attributes si_pid, si_uid, and so on.\n\
2396 \n\
2397 See os.waitid for more information.");
2398 
2399 static PyStructSequence_Field waitid_result_fields[] = {
2400     {"si_pid",  },
2401     {"si_uid", },
2402     {"si_signo", },
2403     {"si_status",  },
2404     {"si_code", },
2405     {0}
2406 };
2407 
2408 static PyStructSequence_Desc waitid_result_desc = {
2409     "waitid_result", /* name */
2410     waitid_result__doc__, /* doc */
2411     waitid_result_fields,
2412     5
2413 };
2414 #endif
2415 
2416 static PyObject *
statresult_new(PyTypeObject * type,PyObject * args,PyObject * kwds)2417 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2418 {
2419     PyStructSequence *result;
2420     int i;
2421 
2422     // ht_module doesn't get set in PyStructSequence_NewType(),
2423     // so we can't use PyType_GetModule().
2424     PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
2425     if (mod == NULL) {
2426         return NULL;
2427     }
2428     _posixstate *state = get_posix_state(mod);
2429     Py_DECREF(mod);
2430     if (state == NULL) {
2431         return NULL;
2432     }
2433 #define structseq_new state->statresult_new_orig
2434 
2435     result = (PyStructSequence*)structseq_new(type, args, kwds);
2436     if (!result)
2437         return NULL;
2438     /* If we have been initialized from a tuple,
2439        st_?time might be set to None. Initialize it
2440        from the int slots.  */
2441     for (i = 7; i <= 9; i++) {
2442         if (result->ob_item[i+3] == Py_None) {
2443             Py_DECREF(Py_None);
2444             result->ob_item[i+3] = Py_NewRef(result->ob_item[i]);
2445         }
2446     }
2447     return (PyObject*)result;
2448 }
2449 
2450 static int
_posix_clear(PyObject * module)2451 _posix_clear(PyObject *module)
2452 {
2453     _posixstate *state = get_posix_state(module);
2454     Py_CLEAR(state->billion);
2455     Py_CLEAR(state->DirEntryType);
2456     Py_CLEAR(state->ScandirIteratorType);
2457 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2458     Py_CLEAR(state->SchedParamType);
2459 #endif
2460     Py_CLEAR(state->StatResultType);
2461     Py_CLEAR(state->StatVFSResultType);
2462     Py_CLEAR(state->TerminalSizeType);
2463     Py_CLEAR(state->TimesResultType);
2464     Py_CLEAR(state->UnameResultType);
2465 #if defined(HAVE_WAITID)
2466     Py_CLEAR(state->WaitidResultType);
2467 #endif
2468 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2469     Py_CLEAR(state->struct_rusage);
2470 #endif
2471     Py_CLEAR(state->st_mode);
2472     return 0;
2473 }
2474 
2475 static int
_posix_traverse(PyObject * module,visitproc visit,void * arg)2476 _posix_traverse(PyObject *module, visitproc visit, void *arg)
2477 {
2478     _posixstate *state = get_posix_state(module);
2479     Py_VISIT(state->billion);
2480     Py_VISIT(state->DirEntryType);
2481     Py_VISIT(state->ScandirIteratorType);
2482 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2483     Py_VISIT(state->SchedParamType);
2484 #endif
2485     Py_VISIT(state->StatResultType);
2486     Py_VISIT(state->StatVFSResultType);
2487     Py_VISIT(state->TerminalSizeType);
2488     Py_VISIT(state->TimesResultType);
2489     Py_VISIT(state->UnameResultType);
2490 #if defined(HAVE_WAITID)
2491     Py_VISIT(state->WaitidResultType);
2492 #endif
2493 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2494     Py_VISIT(state->struct_rusage);
2495 #endif
2496     Py_VISIT(state->st_mode);
2497     return 0;
2498 }
2499 
2500 static void
_posix_free(void * module)2501 _posix_free(void *module)
2502 {
2503    _posix_clear((PyObject *)module);
2504 }
2505 
2506 static int
fill_time(PyObject * module,PyObject * v,int s_index,int f_index,int ns_index,time_t sec,unsigned long nsec)2507 fill_time(PyObject *module, PyObject *v, int s_index, int f_index, int ns_index, time_t sec, unsigned long nsec)
2508 {
2509     assert(!PyErr_Occurred());
2510 
2511     int res = -1;
2512     PyObject *s_in_ns = NULL;
2513     PyObject *ns_total = NULL;
2514     PyObject *float_s = NULL;
2515 
2516     PyObject *s = _PyLong_FromTime_t(sec);
2517     PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2518     if (!(s && ns_fractional)) {
2519         goto exit;
2520     }
2521 
2522     s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2523     if (!s_in_ns) {
2524         goto exit;
2525     }
2526 
2527     ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2528     if (!ns_total)
2529         goto exit;
2530 
2531     float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2532     if (!float_s) {
2533         goto exit;
2534     }
2535 
2536     if (s_index >= 0) {
2537         PyStructSequence_SET_ITEM(v, s_index, s);
2538         s = NULL;
2539     }
2540     if (f_index >= 0) {
2541         PyStructSequence_SET_ITEM(v, f_index, float_s);
2542         float_s = NULL;
2543     }
2544     if (ns_index >= 0) {
2545         PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2546         ns_total = NULL;
2547     }
2548 
2549     assert(!PyErr_Occurred());
2550     res = 0;
2551 
2552 exit:
2553     Py_XDECREF(s);
2554     Py_XDECREF(ns_fractional);
2555     Py_XDECREF(s_in_ns);
2556     Py_XDECREF(ns_total);
2557     Py_XDECREF(float_s);
2558     return res;
2559 }
2560 
2561 #ifdef MS_WINDOWS
2562 static PyObject*
_pystat_l128_from_l64_l64(uint64_t low,uint64_t high)2563 _pystat_l128_from_l64_l64(uint64_t low, uint64_t high)
2564 {
2565     PyObject *o_low = PyLong_FromUnsignedLongLong(low);
2566     if (!o_low || !high) {
2567         return o_low;
2568     }
2569     PyObject *o_high = PyLong_FromUnsignedLongLong(high);
2570     PyObject *l64 = o_high ? PyLong_FromLong(64) : NULL;
2571     if (!l64) {
2572         Py_XDECREF(o_high);
2573         Py_DECREF(o_low);
2574         return NULL;
2575     }
2576     Py_SETREF(o_high, PyNumber_Lshift(o_high, l64));
2577     Py_DECREF(l64);
2578     if (!o_high) {
2579         Py_DECREF(o_low);
2580         return NULL;
2581     }
2582     Py_SETREF(o_low, PyNumber_Add(o_low, o_high));
2583     Py_DECREF(o_high);
2584     return o_low;
2585 }
2586 #endif
2587 
2588 /* pack a system stat C structure into the Python stat tuple
2589    (used by posix_stat() and posix_fstat()) */
2590 static PyObject*
_pystat_fromstructstat(PyObject * module,STRUCT_STAT * st)2591 _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2592 {
2593     assert(!PyErr_Occurred());
2594 
2595     PyObject *StatResultType = get_posix_state(module)->StatResultType;
2596     PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2597     if (v == NULL) {
2598         return NULL;
2599     }
2600 
2601 #define SET_ITEM(pos, expr) \
2602     do { \
2603         PyObject *obj = (expr); \
2604         if (obj == NULL) { \
2605             goto error; \
2606         } \
2607         PyStructSequence_SET_ITEM(v, (pos), obj); \
2608     } while (0)
2609 
2610     SET_ITEM(0, PyLong_FromLong((long)st->st_mode));
2611 #ifdef MS_WINDOWS
2612     SET_ITEM(1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high));
2613     SET_ITEM(2, PyLong_FromUnsignedLongLong(st->st_dev));
2614 #else
2615     static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2616                   "stat.st_ino is larger than unsigned long long");
2617     SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2618     SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2619 #endif
2620     SET_ITEM(3, PyLong_FromLong((long)st->st_nlink));
2621 #if defined(MS_WINDOWS)
2622     SET_ITEM(4, PyLong_FromLong(0));
2623     SET_ITEM(5, PyLong_FromLong(0));
2624 #else
2625     SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2626     SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2627 #endif
2628     static_assert(sizeof(long long) >= sizeof(st->st_size),
2629                   "stat.st_size is larger than long long");
2630     SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2631 
2632     // Set st_atime, st_mtime and st_ctime
2633     unsigned long ansec, mnsec, cnsec;
2634 #if defined(HAVE_STAT_TV_NSEC)
2635     ansec = st->st_atim.tv_nsec;
2636     mnsec = st->st_mtim.tv_nsec;
2637     cnsec = st->st_ctim.tv_nsec;
2638 #elif defined(HAVE_STAT_TV_NSEC2)
2639     ansec = st->st_atimespec.tv_nsec;
2640     mnsec = st->st_mtimespec.tv_nsec;
2641     cnsec = st->st_ctimespec.tv_nsec;
2642 #elif defined(HAVE_STAT_NSEC)
2643     ansec = st->st_atime_nsec;
2644     mnsec = st->st_mtime_nsec;
2645     cnsec = st->st_ctime_nsec;
2646 #else
2647     ansec = mnsec = cnsec = 0;
2648 #endif
2649     if (fill_time(module, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2650         goto error;
2651     }
2652     if (fill_time(module, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2653         goto error;
2654     }
2655     if (fill_time(module, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2656         goto error;
2657     }
2658 
2659 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2660     SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2661 #endif
2662 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2663     SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2664 #endif
2665 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2666     SET_ITEM(ST_RDEV_IDX, PyLong_FromLong((long)st->st_rdev));
2667 #endif
2668 #ifdef HAVE_STRUCT_STAT_ST_GEN
2669     SET_ITEM(ST_GEN_IDX, PyLong_FromLong((long)st->st_gen));
2670 #endif
2671 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
2672     {
2673       unsigned long bsec, bnsec;
2674       bsec = (long)st->st_birthtime;
2675 #ifdef HAVE_STAT_TV_NSEC2
2676       bnsec = st->st_birthtimespec.tv_nsec;
2677 #else
2678       bnsec = 0;
2679 #endif
2680       SET_ITEM(ST_BIRTHTIME_IDX, PyFloat_FromDouble(bsec + bnsec * 1e-9));
2681     }
2682 #elif defined(MS_WINDOWS)
2683     if (fill_time(module, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX,
2684                   st->st_birthtime, st->st_birthtime_nsec) < 0) {
2685         goto error;
2686     }
2687 #endif
2688 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2689     SET_ITEM(ST_FLAGS_IDX, PyLong_FromLong((long)st->st_flags));
2690 #endif
2691 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2692     SET_ITEM(ST_FILE_ATTRIBUTES_IDX,
2693              PyLong_FromUnsignedLong(st->st_file_attributes));
2694 #endif
2695 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2696    SET_ITEM(ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype));
2697 #endif
2698 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2699     SET_ITEM(ST_REPARSE_TAG_IDX, PyLong_FromUnsignedLong(st->st_reparse_tag));
2700 #endif
2701 
2702     assert(!PyErr_Occurred());
2703     return v;
2704 
2705 error:
2706     Py_DECREF(v);
2707     return NULL;
2708 
2709 #undef SET_ITEM
2710 }
2711 
2712 /* POSIX methods */
2713 
2714 
2715 static PyObject *
posix_do_stat(PyObject * module,const char * function_name,path_t * path,int dir_fd,int follow_symlinks)2716 posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2717               int dir_fd, int follow_symlinks)
2718 {
2719     STRUCT_STAT st;
2720     int result;
2721 
2722 #ifdef HAVE_FSTATAT
2723     int fstatat_unavailable = 0;
2724 #endif
2725 
2726 #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2727     if (follow_symlinks_specified(function_name, follow_symlinks))
2728         return NULL;
2729 #endif
2730 
2731     if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2732         dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2733         fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2734         return NULL;
2735 
2736     Py_BEGIN_ALLOW_THREADS
2737     if (path->fd != -1)
2738         result = FSTAT(path->fd, &st);
2739 #ifdef MS_WINDOWS
2740     else if (follow_symlinks)
2741         result = win32_stat(path->wide, &st);
2742     else
2743         result = win32_lstat(path->wide, &st);
2744 #else
2745     else
2746 #if defined(HAVE_LSTAT)
2747     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2748         result = LSTAT(path->narrow, &st);
2749     else
2750 #endif /* HAVE_LSTAT */
2751 #ifdef HAVE_FSTATAT
2752     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2753         if (HAVE_FSTATAT_RUNTIME) {
2754             result = fstatat(dir_fd, path->narrow, &st,
2755                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2756 
2757         } else {
2758             fstatat_unavailable = 1;
2759         }
2760     } else
2761 #endif /* HAVE_FSTATAT */
2762         result = STAT(path->narrow, &st);
2763 #endif /* MS_WINDOWS */
2764     Py_END_ALLOW_THREADS
2765 
2766 #ifdef HAVE_FSTATAT
2767     if (fstatat_unavailable) {
2768         argument_unavailable_error("stat", "dir_fd");
2769         return NULL;
2770     }
2771 #endif
2772 
2773     if (result != 0) {
2774         return path_error(path);
2775     }
2776 
2777     return _pystat_fromstructstat(module, &st);
2778 }
2779 
2780 /*[python input]
2781 
2782 for s in """
2783 
2784 FACCESSAT
2785 FCHMODAT
2786 FCHOWNAT
2787 FSTATAT
2788 LINKAT
2789 MKDIRAT
2790 MKFIFOAT
2791 MKNODAT
2792 OPENAT
2793 READLINKAT
2794 SYMLINKAT
2795 UNLINKAT
2796 
2797 """.strip().split():
2798     s = s.strip()
2799     print("""
2800 #ifdef HAVE_{s}
2801     #define {s}_DIR_FD_CONVERTER dir_fd_converter
2802 #else
2803     #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2804 #endif
2805 """.rstrip().format(s=s))
2806 
2807 for s in """
2808 
2809 FCHDIR
2810 FCHMOD
2811 FCHOWN
2812 FDOPENDIR
2813 FEXECVE
2814 FPATHCONF
2815 FSTATVFS
2816 FTRUNCATE
2817 
2818 """.strip().split():
2819     s = s.strip()
2820     print("""
2821 #ifdef HAVE_{s}
2822     #define PATH_HAVE_{s} 1
2823 #else
2824     #define PATH_HAVE_{s} 0
2825 #endif
2826 
2827 """.rstrip().format(s=s))
2828 [python start generated code]*/
2829 
2830 #ifdef HAVE_FACCESSAT
2831     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2832 #else
2833     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2834 #endif
2835 
2836 #ifdef HAVE_FCHMODAT
2837     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2838 #else
2839     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2840 #endif
2841 
2842 #ifdef HAVE_FCHOWNAT
2843     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2844 #else
2845     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2846 #endif
2847 
2848 #ifdef HAVE_FSTATAT
2849     #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2850 #else
2851     #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2852 #endif
2853 
2854 #ifdef HAVE_LINKAT
2855     #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2856 #else
2857     #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2858 #endif
2859 
2860 #ifdef HAVE_MKDIRAT
2861     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2862 #else
2863     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2864 #endif
2865 
2866 #ifdef HAVE_MKFIFOAT
2867     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2868 #else
2869     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2870 #endif
2871 
2872 #ifdef HAVE_MKNODAT
2873     #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2874 #else
2875     #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2876 #endif
2877 
2878 #ifdef HAVE_OPENAT
2879     #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2880 #else
2881     #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2882 #endif
2883 
2884 #ifdef HAVE_READLINKAT
2885     #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2886 #else
2887     #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2888 #endif
2889 
2890 #ifdef HAVE_SYMLINKAT
2891     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2892 #else
2893     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2894 #endif
2895 
2896 #ifdef HAVE_UNLINKAT
2897     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2898 #else
2899     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2900 #endif
2901 
2902 #ifdef HAVE_FCHDIR
2903     #define PATH_HAVE_FCHDIR 1
2904 #else
2905     #define PATH_HAVE_FCHDIR 0
2906 #endif
2907 
2908 #ifdef HAVE_FCHMOD
2909     #define PATH_HAVE_FCHMOD 1
2910 #else
2911     #define PATH_HAVE_FCHMOD 0
2912 #endif
2913 
2914 #ifdef HAVE_FCHOWN
2915     #define PATH_HAVE_FCHOWN 1
2916 #else
2917     #define PATH_HAVE_FCHOWN 0
2918 #endif
2919 
2920 #ifdef HAVE_FDOPENDIR
2921     #define PATH_HAVE_FDOPENDIR 1
2922 #else
2923     #define PATH_HAVE_FDOPENDIR 0
2924 #endif
2925 
2926 #ifdef HAVE_FEXECVE
2927     #define PATH_HAVE_FEXECVE 1
2928 #else
2929     #define PATH_HAVE_FEXECVE 0
2930 #endif
2931 
2932 #ifdef HAVE_FPATHCONF
2933     #define PATH_HAVE_FPATHCONF 1
2934 #else
2935     #define PATH_HAVE_FPATHCONF 0
2936 #endif
2937 
2938 #ifdef HAVE_FSTATVFS
2939     #define PATH_HAVE_FSTATVFS 1
2940 #else
2941     #define PATH_HAVE_FSTATVFS 0
2942 #endif
2943 
2944 #ifdef HAVE_FTRUNCATE
2945     #define PATH_HAVE_FTRUNCATE 1
2946 #else
2947     #define PATH_HAVE_FTRUNCATE 0
2948 #endif
2949 /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2950 
2951 #ifdef MS_WINDOWS
2952     #undef PATH_HAVE_FTRUNCATE
2953     #define PATH_HAVE_FTRUNCATE 1
2954     #undef PATH_HAVE_FCHMOD
2955     #define PATH_HAVE_FCHMOD 1
2956 #endif
2957 
2958 /*[python input]
2959 
2960 class path_t_converter(CConverter):
2961 
2962     type = "path_t"
2963     impl_by_reference = True
2964     parse_by_reference = True
2965 
2966     converter = 'path_converter'
2967 
2968     def converter_init(self, *, allow_fd=False, make_wide=None,
2969                        nonstrict=False, nullable=False,
2970                        suppress_value_error=False):
2971         # right now path_t doesn't support default values.
2972         # to support a default value, you'll need to override initialize().
2973         if self.default not in (unspecified, None):
2974             fail("Can't specify a default to the path_t converter!")
2975 
2976         if self.c_default not in (None, 'Py_None'):
2977             raise RuntimeError("Can't specify a c_default to the path_t converter!")
2978 
2979         self.nullable = nullable
2980         self.nonstrict = nonstrict
2981         self.make_wide = make_wide
2982         self.suppress_value_error = suppress_value_error
2983         self.allow_fd = allow_fd
2984 
2985     def pre_render(self):
2986         def strify(value):
2987             if isinstance(value, str):
2988                 return value
2989             return str(int(bool(value)))
2990 
2991         # add self.py_name here when merging with posixmodule conversion
2992         if self.make_wide is None:
2993             self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {}, {})'.format(
2994                 self.function.name,
2995                 self.name,
2996                 strify(self.nullable),
2997                 strify(self.nonstrict),
2998                 strify(self.suppress_value_error),
2999                 strify(self.allow_fd),
3000             )
3001         else:
3002             self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {}, {})'.format(
3003                 self.function.name,
3004                 self.name,
3005                 strify(self.nullable),
3006                 strify(self.nonstrict),
3007                 strify(self.make_wide),
3008                 strify(self.suppress_value_error),
3009                 strify(self.allow_fd),
3010             )
3011 
3012     def cleanup(self):
3013         return "path_cleanup(&" + self.name + ");\n"
3014 
3015 
3016 class dir_fd_converter(CConverter):
3017     type = 'int'
3018 
3019     def converter_init(self, requires=None):
3020         if self.default in (unspecified, None):
3021             self.c_default = 'DEFAULT_DIR_FD'
3022         if isinstance(requires, str):
3023             self.converter = requires.upper() + '_DIR_FD_CONVERTER'
3024         else:
3025             self.converter = 'dir_fd_converter'
3026 
3027 class uid_t_converter(CConverter):
3028     type = "uid_t"
3029     converter = '_Py_Uid_Converter'
3030 
3031 class gid_t_converter(CConverter):
3032     type = "gid_t"
3033     converter = '_Py_Gid_Converter'
3034 
3035 class dev_t_converter(CConverter):
3036     type = 'dev_t'
3037     converter = '_Py_Dev_Converter'
3038 
3039 class dev_t_return_converter(unsigned_long_return_converter):
3040     type = 'dev_t'
3041     conversion_fn = '_PyLong_FromDev'
3042     unsigned_cast = '(dev_t)'
3043 
3044 class FSConverter_converter(CConverter):
3045     type = 'PyObject *'
3046     converter = 'PyUnicode_FSConverter'
3047     def converter_init(self):
3048         if self.default is not unspecified:
3049             fail("FSConverter_converter does not support default values")
3050         self.c_default = 'NULL'
3051 
3052     def cleanup(self):
3053         return "Py_XDECREF(" + self.name + ");\n"
3054 
3055 class pid_t_converter(CConverter):
3056     type = 'pid_t'
3057     format_unit = '" _Py_PARSE_PID "'
3058 
3059 class idtype_t_converter(int_converter):
3060     type = 'idtype_t'
3061 
3062 class id_t_converter(CConverter):
3063     type = 'id_t'
3064     format_unit = '" _Py_PARSE_PID "'
3065 
3066 class intptr_t_converter(CConverter):
3067     type = 'intptr_t'
3068     format_unit = '" _Py_PARSE_INTPTR "'
3069 
3070 class Py_off_t_converter(CConverter):
3071     type = 'Py_off_t'
3072     converter = 'Py_off_t_converter'
3073 
3074 class Py_off_t_return_converter(long_return_converter):
3075     type = 'Py_off_t'
3076     conversion_fn = 'PyLong_FromPy_off_t'
3077 
3078 class path_confname_converter(CConverter):
3079     type="int"
3080     converter="conv_path_confname"
3081 
3082 class confstr_confname_converter(path_confname_converter):
3083     converter='conv_confstr_confname'
3084 
3085 class sysconf_confname_converter(path_confname_converter):
3086     converter="conv_sysconf_confname"
3087 
3088 [python start generated code]*/
3089 /*[python end generated code: output=da39a3ee5e6b4b0d input=577cb476e5d64960]*/
3090 
3091 /*[clinic input]
3092 
3093 os.stat
3094 
3095     path : path_t(allow_fd=True)
3096         Path to be examined; can be string, bytes, a path-like object or
3097         open-file-descriptor int.
3098 
3099     *
3100 
3101     dir_fd : dir_fd(requires='fstatat') = None
3102         If not None, it should be a file descriptor open to a directory,
3103         and path should be a relative string; path will then be relative to
3104         that directory.
3105 
3106     follow_symlinks: bool = True
3107         If False, and the last element of the path is a symbolic link,
3108         stat will examine the symbolic link itself instead of the file
3109         the link points to.
3110 
3111 Perform a stat system call on the given path.
3112 
3113 dir_fd and follow_symlinks may not be implemented
3114   on your platform.  If they are unavailable, using them will raise a
3115   NotImplementedError.
3116 
3117 It's an error to use dir_fd or follow_symlinks when specifying path as
3118   an open file descriptor.
3119 
3120 [clinic start generated code]*/
3121 
3122 static PyObject *
os_stat_impl(PyObject * module,path_t * path,int dir_fd,int follow_symlinks)3123 os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
3124 /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
3125 {
3126     return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3127 }
3128 
3129 
3130 /*[clinic input]
3131 os.lstat
3132 
3133     path : path_t
3134 
3135     *
3136 
3137     dir_fd : dir_fd(requires='fstatat') = None
3138 
3139 Perform a stat system call on the given path, without following symbolic links.
3140 
3141 Like stat(), but do not follow symbolic links.
3142 Equivalent to stat(path, follow_symlinks=False).
3143 [clinic start generated code]*/
3144 
3145 static PyObject *
os_lstat_impl(PyObject * module,path_t * path,int dir_fd)3146 os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
3147 /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
3148 {
3149     int follow_symlinks = 0;
3150     return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3151 }
3152 
3153 
3154 /*[clinic input]
3155 os.access -> bool
3156 
3157     path: path_t
3158         Path to be tested; can be string, bytes, or a path-like object.
3159 
3160     mode: int
3161         Operating-system mode bitfield.  Can be F_OK to test existence,
3162         or the inclusive-OR of R_OK, W_OK, and X_OK.
3163 
3164     *
3165 
3166     dir_fd : dir_fd(requires='faccessat') = None
3167         If not None, it should be a file descriptor open to a directory,
3168         and path should be relative; path will then be relative to that
3169         directory.
3170 
3171     effective_ids: bool = False
3172         If True, access will use the effective uid/gid instead of
3173         the real uid/gid.
3174 
3175     follow_symlinks: bool = True
3176         If False, and the last element of the path is a symbolic link,
3177         access will examine the symbolic link itself instead of the file
3178         the link points to.
3179 
3180 Use the real uid/gid to test for access to a path.
3181 
3182 {parameters}
3183 dir_fd, effective_ids, and follow_symlinks may not be implemented
3184   on your platform.  If they are unavailable, using them will raise a
3185   NotImplementedError.
3186 
3187 Note that most operations will use the effective uid/gid, therefore this
3188   routine can be used in a suid/sgid environment to test if the invoking user
3189   has the specified access to the path.
3190 
3191 [clinic start generated code]*/
3192 
3193 static int
os_access_impl(PyObject * module,path_t * path,int mode,int dir_fd,int effective_ids,int follow_symlinks)3194 os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3195                int effective_ids, int follow_symlinks)
3196 /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
3197 {
3198     int return_value;
3199 
3200 #ifdef MS_WINDOWS
3201     DWORD attr;
3202 #else
3203     int result;
3204 #endif
3205 
3206 #ifdef HAVE_FACCESSAT
3207     int faccessat_unavailable = 0;
3208 #endif
3209 
3210 #ifndef HAVE_FACCESSAT
3211     if (follow_symlinks_specified("access", follow_symlinks))
3212         return -1;
3213 
3214     if (effective_ids) {
3215         argument_unavailable_error("access", "effective_ids");
3216         return -1;
3217     }
3218 #endif
3219 
3220 #ifdef MS_WINDOWS
3221     Py_BEGIN_ALLOW_THREADS
3222     attr = GetFileAttributesW(path->wide);
3223     Py_END_ALLOW_THREADS
3224 
3225     /*
3226      * Access is possible if
3227      *   * we didn't get a -1, and
3228      *     * write access wasn't requested,
3229      *     * or the file isn't read-only,
3230      *     * or it's a directory.
3231      * (Directories cannot be read-only on Windows.)
3232     */
3233     return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3234             (!(mode & 2) ||
3235             !(attr & FILE_ATTRIBUTE_READONLY) ||
3236             (attr & FILE_ATTRIBUTE_DIRECTORY));
3237 #else
3238 
3239     Py_BEGIN_ALLOW_THREADS
3240 #ifdef HAVE_FACCESSAT
3241     if ((dir_fd != DEFAULT_DIR_FD) ||
3242         effective_ids ||
3243         !follow_symlinks) {
3244 
3245         if (HAVE_FACCESSAT_RUNTIME) {
3246             int flags = 0;
3247             if (!follow_symlinks)
3248                 flags |= AT_SYMLINK_NOFOLLOW;
3249             if (effective_ids)
3250                 flags |= AT_EACCESS;
3251             result = faccessat(dir_fd, path->narrow, mode, flags);
3252         } else {
3253             faccessat_unavailable = 1;
3254         }
3255     }
3256     else
3257 #endif
3258         result = access(path->narrow, mode);
3259     Py_END_ALLOW_THREADS
3260 
3261 #ifdef HAVE_FACCESSAT
3262     if (faccessat_unavailable) {
3263         if (dir_fd != DEFAULT_DIR_FD) {
3264             argument_unavailable_error("access", "dir_fd");
3265             return -1;
3266         }
3267         if (follow_symlinks_specified("access", follow_symlinks))
3268             return -1;
3269 
3270         if (effective_ids) {
3271             argument_unavailable_error("access", "effective_ids");
3272             return -1;
3273         }
3274         /* should be unreachable */
3275         return -1;
3276     }
3277 #endif
3278     return_value = !result;
3279 #endif
3280 
3281     return return_value;
3282 }
3283 
3284 #ifndef F_OK
3285 #define F_OK 0
3286 #endif
3287 #ifndef R_OK
3288 #define R_OK 4
3289 #endif
3290 #ifndef W_OK
3291 #define W_OK 2
3292 #endif
3293 #ifndef X_OK
3294 #define X_OK 1
3295 #endif
3296 
3297 
3298 #ifdef HAVE_TTYNAME
3299 /*[clinic input]
3300 os.ttyname
3301 
3302     fd: int
3303         Integer file descriptor handle.
3304 
3305     /
3306 
3307 Return the name of the terminal device connected to 'fd'.
3308 [clinic start generated code]*/
3309 
3310 static PyObject *
os_ttyname_impl(PyObject * module,int fd)3311 os_ttyname_impl(PyObject *module, int fd)
3312 /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3313 {
3314 
3315     long size = sysconf(_SC_TTY_NAME_MAX);
3316     if (size == -1) {
3317         return posix_error();
3318     }
3319     char *buffer = (char *)PyMem_RawMalloc(size);
3320     if (buffer == NULL) {
3321         return PyErr_NoMemory();
3322     }
3323     int ret = ttyname_r(fd, buffer, size);
3324     if (ret != 0) {
3325         PyMem_RawFree(buffer);
3326         errno = ret;
3327         return posix_error();
3328     }
3329     PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3330     PyMem_RawFree(buffer);
3331     return res;
3332 }
3333 #endif
3334 
3335 #ifdef HAVE_CTERMID
3336 /*[clinic input]
3337 os.ctermid
3338 
3339 Return the name of the controlling terminal for this process.
3340 [clinic start generated code]*/
3341 
3342 static PyObject *
os_ctermid_impl(PyObject * module)3343 os_ctermid_impl(PyObject *module)
3344 /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3345 {
3346     char *ret;
3347     char buffer[L_ctermid];
3348 
3349 #ifdef USE_CTERMID_R
3350     ret = ctermid_r(buffer);
3351 #else
3352     ret = ctermid(buffer);
3353 #endif
3354     if (ret == NULL)
3355         return posix_error();
3356     return PyUnicode_DecodeFSDefault(buffer);
3357 }
3358 #endif /* HAVE_CTERMID */
3359 
3360 
3361 /*[clinic input]
3362 os.chdir
3363 
3364     path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3365 
3366 Change the current working directory to the specified path.
3367 
3368 path may always be specified as a string.
3369 On some platforms, path may also be specified as an open file descriptor.
3370   If this functionality is unavailable, using it raises an exception.
3371 [clinic start generated code]*/
3372 
3373 static PyObject *
os_chdir_impl(PyObject * module,path_t * path)3374 os_chdir_impl(PyObject *module, path_t *path)
3375 /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3376 {
3377     int result;
3378 
3379     if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3380         return NULL;
3381     }
3382 
3383     Py_BEGIN_ALLOW_THREADS
3384 #ifdef MS_WINDOWS
3385     /* on unix, success = 0, on windows, success = !0 */
3386     result = !win32_wchdir(path->wide);
3387 #else
3388 #ifdef HAVE_FCHDIR
3389     if (path->fd != -1)
3390         result = fchdir(path->fd);
3391     else
3392 #endif
3393         result = chdir(path->narrow);
3394 #endif
3395     Py_END_ALLOW_THREADS
3396 
3397     if (result) {
3398         return path_error(path);
3399     }
3400 
3401     Py_RETURN_NONE;
3402 }
3403 
3404 
3405 #ifdef HAVE_FCHDIR
3406 /*[clinic input]
3407 os.fchdir
3408 
3409     fd: fildes
3410 
3411 Change to the directory of the given file descriptor.
3412 
3413 fd must be opened on a directory, not a file.
3414 Equivalent to os.chdir(fd).
3415 
3416 [clinic start generated code]*/
3417 
3418 static PyObject *
os_fchdir_impl(PyObject * module,int fd)3419 os_fchdir_impl(PyObject *module, int fd)
3420 /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3421 {
3422     if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3423         return NULL;
3424     }
3425     return posix_fildes_fd(fd, fchdir);
3426 }
3427 #endif /* HAVE_FCHDIR */
3428 
3429 #ifdef MS_WINDOWS
3430 # define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0
3431 #else
3432 # define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1
3433 #endif
3434 
3435 #ifdef MS_WINDOWS
3436 static int
win32_lchmod(LPCWSTR path,int mode)3437 win32_lchmod(LPCWSTR path, int mode)
3438 {
3439     DWORD attr = GetFileAttributesW(path);
3440     if (attr == INVALID_FILE_ATTRIBUTES) {
3441         return 0;
3442     }
3443     if (mode & _S_IWRITE) {
3444         attr &= ~FILE_ATTRIBUTE_READONLY;
3445     }
3446     else {
3447         attr |= FILE_ATTRIBUTE_READONLY;
3448     }
3449     return SetFileAttributesW(path, attr);
3450 }
3451 
3452 static int
win32_hchmod(HANDLE hfile,int mode)3453 win32_hchmod(HANDLE hfile, int mode)
3454 {
3455     FILE_BASIC_INFO info;
3456     if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
3457                                       &info, sizeof(info)))
3458     {
3459         return 0;
3460     }
3461     if (mode & _S_IWRITE) {
3462         info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
3463     }
3464     else {
3465         info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
3466     }
3467     return SetFileInformationByHandle(hfile, FileBasicInfo,
3468                                       &info, sizeof(info));
3469 }
3470 
3471 static int
win32_fchmod(int fd,int mode)3472 win32_fchmod(int fd, int mode)
3473 {
3474     HANDLE hfile = _Py_get_osfhandle_noraise(fd);
3475     if (hfile == INVALID_HANDLE_VALUE) {
3476         SetLastError(ERROR_INVALID_HANDLE);
3477         return 0;
3478     }
3479     return win32_hchmod(hfile, mode);
3480 }
3481 
3482 #endif /* MS_WINDOWS */
3483 
3484 /*[clinic input]
3485 os.chmod
3486 
3487     path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3488         Path to be modified.  May always be specified as a str, bytes, or a path-like object.
3489         On some platforms, path may also be specified as an open file descriptor.
3490         If this functionality is unavailable, using it raises an exception.
3491 
3492     mode: int
3493         Operating-system mode bitfield.
3494         Be careful when using number literals for *mode*. The conventional UNIX notation for
3495         numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
3496         Python.
3497 
3498     *
3499 
3500     dir_fd : dir_fd(requires='fchmodat') = None
3501         If not None, it should be a file descriptor open to a directory,
3502         and path should be relative; path will then be relative to that
3503         directory.
3504 
3505     follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
3506                           py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
3507         If False, and the last element of the path is a symbolic link,
3508         chmod will modify the symbolic link itself instead of the file
3509         the link points to.
3510 
3511 Change the access permissions of a file.
3512 
3513 It is an error to use dir_fd or follow_symlinks when specifying path as
3514   an open file descriptor.
3515 dir_fd and follow_symlinks may not be implemented on your platform.
3516   If they are unavailable, using them will raise a NotImplementedError.
3517 
3518 [clinic start generated code]*/
3519 
3520 static PyObject *
os_chmod_impl(PyObject * module,path_t * path,int mode,int dir_fd,int follow_symlinks)3521 os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3522               int follow_symlinks)
3523 /*[clinic end generated code: output=5cf6a94915cc7bff input=fcf115d174b9f3d8]*/
3524 {
3525     int result;
3526 
3527 #ifdef HAVE_FCHMODAT
3528     int fchmodat_nofollow_unsupported = 0;
3529     int fchmodat_unsupported = 0;
3530 #endif
3531 
3532 #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
3533     if (follow_symlinks_specified("chmod", follow_symlinks))
3534         return NULL;
3535 #endif
3536 
3537     if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3538                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3539         return NULL;
3540     }
3541 
3542 #ifdef MS_WINDOWS
3543     result = 0;
3544     Py_BEGIN_ALLOW_THREADS
3545     if (path->fd != -1) {
3546         result = win32_fchmod(path->fd, mode);
3547     }
3548     else if (follow_symlinks) {
3549         HANDLE hfile = CreateFileW(path->wide,
3550                                    FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
3551                                    0, NULL,
3552                                    OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
3553         if (hfile != INVALID_HANDLE_VALUE) {
3554             result = win32_hchmod(hfile, mode);
3555             (void)CloseHandle(hfile);
3556         }
3557     }
3558     else {
3559         result = win32_lchmod(path->wide, mode);
3560     }
3561     Py_END_ALLOW_THREADS
3562     if (!result) {
3563         return path_error(path);
3564     }
3565 #else /* MS_WINDOWS */
3566     Py_BEGIN_ALLOW_THREADS
3567 #ifdef HAVE_FCHMOD
3568     if (path->fd != -1)
3569         result = fchmod(path->fd, mode);
3570     else
3571 #endif /* HAVE_CHMOD */
3572 #ifdef HAVE_LCHMOD
3573     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3574         result = lchmod(path->narrow, mode);
3575     else
3576 #endif /* HAVE_LCHMOD */
3577 #ifdef HAVE_FCHMODAT
3578     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3579         if (HAVE_FCHMODAT_RUNTIME) {
3580             /*
3581              * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3582              * The documentation specifically shows how to use it,
3583              * and then says it isn't implemented yet.
3584              * (true on linux with glibc 2.15, and openindiana 3.x)
3585              *
3586              * Once it is supported, os.chmod will automatically
3587              * support dir_fd and follow_symlinks=False.  (Hopefully.)
3588              * Until then, we need to be careful what exception we raise.
3589              */
3590             result = fchmodat(dir_fd, path->narrow, mode,
3591                               follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3592             /*
3593              * But wait!  We can't throw the exception without allowing threads,
3594              * and we can't do that in this nested scope.  (Macro trickery, sigh.)
3595              */
3596             fchmodat_nofollow_unsupported =
3597                              result &&
3598                              ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3599                              !follow_symlinks;
3600         } else {
3601             fchmodat_unsupported = 1;
3602             fchmodat_nofollow_unsupported = 1;
3603 
3604             result = -1;
3605         }
3606     }
3607     else
3608 #endif /* HAVE_FHCMODAT */
3609     {
3610 #ifdef HAVE_CHMOD
3611         result = chmod(path->narrow, mode);
3612 #elif defined(__wasi__)
3613         // WASI SDK 15.0 does not support chmod.
3614         // Ignore missing syscall for now.
3615         result = 0;
3616 #else
3617         result = -1;
3618         errno = ENOSYS;
3619 #endif
3620     }
3621     Py_END_ALLOW_THREADS
3622 
3623     if (result) {
3624 #ifdef HAVE_FCHMODAT
3625         if (fchmodat_unsupported) {
3626             if (dir_fd != DEFAULT_DIR_FD) {
3627                 argument_unavailable_error("chmod", "dir_fd");
3628                 return NULL;
3629             }
3630         }
3631 
3632         if (fchmodat_nofollow_unsupported) {
3633             if (dir_fd != DEFAULT_DIR_FD)
3634                 dir_fd_and_follow_symlinks_invalid("chmod",
3635                                                    dir_fd, follow_symlinks);
3636             else
3637                 follow_symlinks_specified("chmod", follow_symlinks);
3638             return NULL;
3639         }
3640         else
3641 #endif /* HAVE_FCHMODAT */
3642         return path_error(path);
3643     }
3644 #endif /* MS_WINDOWS */
3645 
3646     Py_RETURN_NONE;
3647 }
3648 
3649 
3650 #if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
3651 /*[clinic input]
3652 os.fchmod
3653 
3654     fd: int
3655         The file descriptor of the file to be modified.
3656     mode: int
3657         Operating-system mode bitfield.
3658         Be careful when using number literals for *mode*. The conventional UNIX notation for
3659         numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in
3660         Python.
3661 
3662 Change the access permissions of the file given by file descriptor fd.
3663 
3664 Equivalent to os.chmod(fd, mode).
3665 [clinic start generated code]*/
3666 
3667 static PyObject *
os_fchmod_impl(PyObject * module,int fd,int mode)3668 os_fchmod_impl(PyObject *module, int fd, int mode)
3669 /*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/
3670 {
3671     int res;
3672 
3673     if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3674         return NULL;
3675     }
3676 
3677 #ifdef MS_WINDOWS
3678     res = 0;
3679     Py_BEGIN_ALLOW_THREADS
3680     res = win32_fchmod(fd, mode);
3681     Py_END_ALLOW_THREADS
3682     if (!res) {
3683         return PyErr_SetFromWindowsErr(0);
3684     }
3685 #else /* MS_WINDOWS */
3686     int async_err = 0;
3687     do {
3688         Py_BEGIN_ALLOW_THREADS
3689         res = fchmod(fd, mode);
3690         Py_END_ALLOW_THREADS
3691     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3692     if (res != 0)
3693         return (!async_err) ? posix_error() : NULL;
3694 #endif /* MS_WINDOWS */
3695 
3696     Py_RETURN_NONE;
3697 }
3698 #endif /* HAVE_FCHMOD || MS_WINDOWS */
3699 
3700 
3701 #if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
3702 /*[clinic input]
3703 os.lchmod
3704 
3705     path: path_t
3706     mode: int
3707 
3708 Change the access permissions of a file, without following symbolic links.
3709 
3710 If path is a symlink, this affects the link itself rather than the target.
3711 Equivalent to chmod(path, mode, follow_symlinks=False)."
3712 [clinic start generated code]*/
3713 
3714 static PyObject *
os_lchmod_impl(PyObject * module,path_t * path,int mode)3715 os_lchmod_impl(PyObject *module, path_t *path, int mode)
3716 /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3717 {
3718     int res;
3719     if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3720         return NULL;
3721     }
3722 #ifdef MS_WINDOWS
3723     Py_BEGIN_ALLOW_THREADS
3724     res = win32_lchmod(path->wide, mode);
3725     Py_END_ALLOW_THREADS
3726     if (!res) {
3727         path_error(path);
3728         return NULL;
3729     }
3730 #else /* MS_WINDOWS */
3731     Py_BEGIN_ALLOW_THREADS
3732     res = lchmod(path->narrow, mode);
3733     Py_END_ALLOW_THREADS
3734     if (res < 0) {
3735         path_error(path);
3736         return NULL;
3737     }
3738 #endif /* MS_WINDOWS */
3739     Py_RETURN_NONE;
3740 }
3741 #endif /* HAVE_LCHMOD || MS_WINDOWS */
3742 
3743 
3744 #ifdef HAVE_CHFLAGS
3745 /*[clinic input]
3746 os.chflags
3747 
3748     path: path_t
3749     flags: unsigned_long(bitwise=True)
3750     follow_symlinks: bool=True
3751 
3752 Set file flags.
3753 
3754 If follow_symlinks is False, and the last element of the path is a symbolic
3755   link, chflags will change flags on the symbolic link itself instead of the
3756   file the link points to.
3757 follow_symlinks may not be implemented on your platform.  If it is
3758 unavailable, using it will raise a NotImplementedError.
3759 
3760 [clinic start generated code]*/
3761 
3762 static PyObject *
os_chflags_impl(PyObject * module,path_t * path,unsigned long flags,int follow_symlinks)3763 os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3764                 int follow_symlinks)
3765 /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3766 {
3767     int result;
3768 
3769 #ifndef HAVE_LCHFLAGS
3770     if (follow_symlinks_specified("chflags", follow_symlinks))
3771         return NULL;
3772 #endif
3773 
3774     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3775         return NULL;
3776     }
3777 
3778     Py_BEGIN_ALLOW_THREADS
3779 #ifdef HAVE_LCHFLAGS
3780     if (!follow_symlinks)
3781         result = lchflags(path->narrow, flags);
3782     else
3783 #endif
3784         result = chflags(path->narrow, flags);
3785     Py_END_ALLOW_THREADS
3786 
3787     if (result)
3788         return path_error(path);
3789 
3790     Py_RETURN_NONE;
3791 }
3792 #endif /* HAVE_CHFLAGS */
3793 
3794 
3795 #ifdef HAVE_LCHFLAGS
3796 /*[clinic input]
3797 os.lchflags
3798 
3799     path: path_t
3800     flags: unsigned_long(bitwise=True)
3801 
3802 Set file flags.
3803 
3804 This function will not follow symbolic links.
3805 Equivalent to chflags(path, flags, follow_symlinks=False).
3806 [clinic start generated code]*/
3807 
3808 static PyObject *
os_lchflags_impl(PyObject * module,path_t * path,unsigned long flags)3809 os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3810 /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3811 {
3812     int res;
3813     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3814         return NULL;
3815     }
3816     Py_BEGIN_ALLOW_THREADS
3817     res = lchflags(path->narrow, flags);
3818     Py_END_ALLOW_THREADS
3819     if (res < 0) {
3820         return path_error(path);
3821     }
3822     Py_RETURN_NONE;
3823 }
3824 #endif /* HAVE_LCHFLAGS */
3825 
3826 
3827 #ifdef HAVE_CHROOT
3828 /*[clinic input]
3829 os.chroot
3830     path: path_t
3831 
3832 Change root directory to path.
3833 
3834 [clinic start generated code]*/
3835 
3836 static PyObject *
os_chroot_impl(PyObject * module,path_t * path)3837 os_chroot_impl(PyObject *module, path_t *path)
3838 /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3839 {
3840     int res;
3841     Py_BEGIN_ALLOW_THREADS
3842     res = chroot(path->narrow);
3843     Py_END_ALLOW_THREADS
3844     if (res < 0)
3845         return path_error(path);
3846     Py_RETURN_NONE;
3847 }
3848 #endif /* HAVE_CHROOT */
3849 
3850 
3851 #ifdef HAVE_FSYNC
3852 /*[clinic input]
3853 os.fsync
3854 
3855     fd: fildes
3856 
3857 Force write of fd to disk.
3858 [clinic start generated code]*/
3859 
3860 static PyObject *
os_fsync_impl(PyObject * module,int fd)3861 os_fsync_impl(PyObject *module, int fd)
3862 /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3863 {
3864     return posix_fildes_fd(fd, fsync);
3865 }
3866 #endif /* HAVE_FSYNC */
3867 
3868 
3869 #ifdef HAVE_SYNC
3870 /*[clinic input]
3871 os.sync
3872 
3873 Force write of everything to disk.
3874 [clinic start generated code]*/
3875 
3876 static PyObject *
os_sync_impl(PyObject * module)3877 os_sync_impl(PyObject *module)
3878 /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3879 {
3880     Py_BEGIN_ALLOW_THREADS
3881     sync();
3882     Py_END_ALLOW_THREADS
3883     Py_RETURN_NONE;
3884 }
3885 #endif /* HAVE_SYNC */
3886 
3887 
3888 #ifdef HAVE_FDATASYNC
3889 #ifdef __hpux
3890 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3891 #endif
3892 
3893 /*[clinic input]
3894 os.fdatasync
3895 
3896     fd: fildes
3897 
3898 Force write of fd to disk without forcing update of metadata.
3899 [clinic start generated code]*/
3900 
3901 static PyObject *
os_fdatasync_impl(PyObject * module,int fd)3902 os_fdatasync_impl(PyObject *module, int fd)
3903 /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3904 {
3905     return posix_fildes_fd(fd, fdatasync);
3906 }
3907 #endif /* HAVE_FDATASYNC */
3908 
3909 
3910 #ifdef HAVE_CHOWN
3911 /*[clinic input]
3912 os.chown
3913 
3914     path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3915         Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3916 
3917     uid: uid_t
3918 
3919     gid: gid_t
3920 
3921     *
3922 
3923     dir_fd : dir_fd(requires='fchownat') = None
3924         If not None, it should be a file descriptor open to a directory,
3925         and path should be relative; path will then be relative to that
3926         directory.
3927 
3928     follow_symlinks: bool = True
3929         If False, and the last element of the path is a symbolic link,
3930         stat will examine the symbolic link itself instead of the file
3931         the link points to.
3932 
3933 Change the owner and group id of path to the numeric uid and gid.\
3934 
3935 path may always be specified as a string.
3936 On some platforms, path may also be specified as an open file descriptor.
3937   If this functionality is unavailable, using it raises an exception.
3938 If dir_fd is not None, it should be a file descriptor open to a directory,
3939   and path should be relative; path will then be relative to that directory.
3940 If follow_symlinks is False, and the last element of the path is a symbolic
3941   link, chown will modify the symbolic link itself instead of the file the
3942   link points to.
3943 It is an error to use dir_fd or follow_symlinks when specifying path as
3944   an open file descriptor.
3945 dir_fd and follow_symlinks may not be implemented on your platform.
3946   If they are unavailable, using them will raise a NotImplementedError.
3947 
3948 [clinic start generated code]*/
3949 
3950 static PyObject *
os_chown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid,int dir_fd,int follow_symlinks)3951 os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3952               int dir_fd, int follow_symlinks)
3953 /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3954 {
3955     int result;
3956 
3957 #if defined(HAVE_FCHOWNAT)
3958     int fchownat_unsupported = 0;
3959 #endif
3960 
3961 #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3962     if (follow_symlinks_specified("chown", follow_symlinks))
3963         return NULL;
3964 #endif
3965     if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3966         fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3967         return NULL;
3968 
3969     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3970                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3971         return NULL;
3972     }
3973 
3974     Py_BEGIN_ALLOW_THREADS
3975 #ifdef HAVE_FCHOWN
3976     if (path->fd != -1)
3977         result = fchown(path->fd, uid, gid);
3978     else
3979 #endif
3980 #ifdef HAVE_LCHOWN
3981     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3982         result = lchown(path->narrow, uid, gid);
3983     else
3984 #endif
3985 #ifdef HAVE_FCHOWNAT
3986     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
3987       if (HAVE_FCHOWNAT_RUNTIME) {
3988         result = fchownat(dir_fd, path->narrow, uid, gid,
3989                           follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3990       } else {
3991          fchownat_unsupported = 1;
3992       }
3993     } else
3994 #endif
3995         result = chown(path->narrow, uid, gid);
3996     Py_END_ALLOW_THREADS
3997 
3998 #ifdef HAVE_FCHOWNAT
3999     if (fchownat_unsupported) {
4000         /* This would be incorrect if the current platform
4001          * doesn't support lchown.
4002          */
4003         argument_unavailable_error(NULL, "dir_fd");
4004         return NULL;
4005     }
4006 #endif
4007 
4008     if (result)
4009         return path_error(path);
4010 
4011     Py_RETURN_NONE;
4012 }
4013 #endif /* HAVE_CHOWN */
4014 
4015 
4016 #ifdef HAVE_FCHOWN
4017 /*[clinic input]
4018 os.fchown
4019 
4020     fd: int
4021     uid: uid_t
4022     gid: gid_t
4023 
4024 Change the owner and group id of the file specified by file descriptor.
4025 
4026 Equivalent to os.chown(fd, uid, gid).
4027 
4028 [clinic start generated code]*/
4029 
4030 static PyObject *
os_fchown_impl(PyObject * module,int fd,uid_t uid,gid_t gid)4031 os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4032 /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4033 {
4034     int res;
4035     int async_err = 0;
4036 
4037     if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4038         return NULL;
4039     }
4040 
4041     do {
4042         Py_BEGIN_ALLOW_THREADS
4043         res = fchown(fd, uid, gid);
4044         Py_END_ALLOW_THREADS
4045     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4046     if (res != 0)
4047         return (!async_err) ? posix_error() : NULL;
4048 
4049     Py_RETURN_NONE;
4050 }
4051 #endif /* HAVE_FCHOWN */
4052 
4053 
4054 #ifdef HAVE_LCHOWN
4055 /*[clinic input]
4056 os.lchown
4057 
4058     path : path_t
4059     uid: uid_t
4060     gid: gid_t
4061 
4062 Change the owner and group id of path to the numeric uid and gid.
4063 
4064 This function will not follow symbolic links.
4065 Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4066 [clinic start generated code]*/
4067 
4068 static PyObject *
os_lchown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid)4069 os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4070 /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4071 {
4072     int res;
4073     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4074         return NULL;
4075     }
4076     Py_BEGIN_ALLOW_THREADS
4077     res = lchown(path->narrow, uid, gid);
4078     Py_END_ALLOW_THREADS
4079     if (res < 0) {
4080         return path_error(path);
4081     }
4082     Py_RETURN_NONE;
4083 }
4084 #endif /* HAVE_LCHOWN */
4085 
4086 
4087 static PyObject *
posix_getcwd(int use_bytes)4088 posix_getcwd(int use_bytes)
4089 {
4090 #ifdef MS_WINDOWS
4091     wchar_t wbuf[MAXPATHLEN];
4092     wchar_t *wbuf2 = wbuf;
4093     DWORD len;
4094 
4095     Py_BEGIN_ALLOW_THREADS
4096     len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4097     /* If the buffer is large enough, len does not include the
4098        terminating \0. If the buffer is too small, len includes
4099        the space needed for the terminator. */
4100     if (len >= Py_ARRAY_LENGTH(wbuf)) {
4101         if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4102             wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4103         }
4104         else {
4105             wbuf2 = NULL;
4106         }
4107         if (wbuf2) {
4108             len = GetCurrentDirectoryW(len, wbuf2);
4109         }
4110     }
4111     Py_END_ALLOW_THREADS
4112 
4113     if (!wbuf2) {
4114         PyErr_NoMemory();
4115         return NULL;
4116     }
4117     if (!len) {
4118         PyErr_SetFromWindowsErr(0);
4119         if (wbuf2 != wbuf)
4120             PyMem_RawFree(wbuf2);
4121         return NULL;
4122     }
4123 
4124     PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4125     if (wbuf2 != wbuf) {
4126         PyMem_RawFree(wbuf2);
4127     }
4128 
4129     if (use_bytes) {
4130         if (resobj == NULL) {
4131             return NULL;
4132         }
4133         Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4134     }
4135 
4136     return resobj;
4137 #else
4138     const size_t chunk = 1024;
4139 
4140     char *buf = NULL;
4141     char *cwd = NULL;
4142     size_t buflen = 0;
4143 
4144     Py_BEGIN_ALLOW_THREADS
4145     do {
4146         char *newbuf;
4147         if (buflen <= PY_SSIZE_T_MAX - chunk) {
4148             buflen += chunk;
4149             newbuf = PyMem_RawRealloc(buf, buflen);
4150         }
4151         else {
4152             newbuf = NULL;
4153         }
4154         if (newbuf == NULL) {
4155             PyMem_RawFree(buf);
4156             buf = NULL;
4157             break;
4158         }
4159         buf = newbuf;
4160 
4161         cwd = getcwd(buf, buflen);
4162     } while (cwd == NULL && errno == ERANGE);
4163     Py_END_ALLOW_THREADS
4164 
4165     if (buf == NULL) {
4166         return PyErr_NoMemory();
4167     }
4168     if (cwd == NULL) {
4169         posix_error();
4170         PyMem_RawFree(buf);
4171         return NULL;
4172     }
4173 
4174     PyObject *obj;
4175     if (use_bytes) {
4176         obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4177     }
4178     else {
4179         obj = PyUnicode_DecodeFSDefault(buf);
4180     }
4181 #ifdef __linux__
4182     if (buf[0] != '/') {
4183         /*
4184          * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4185          * relative pathname starting with '(unreachable)'. We detect this
4186          * and fail with ENOENT, matching newer glibc behaviour.
4187          */
4188         errno = ENOENT;
4189         path_object_error(obj);
4190         PyMem_RawFree(buf);
4191         return NULL;
4192     }
4193 #endif
4194     assert(buf[0] == '/');
4195     PyMem_RawFree(buf);
4196 
4197     return obj;
4198 #endif   /* !MS_WINDOWS */
4199 }
4200 
4201 
4202 /*[clinic input]
4203 os.getcwd
4204 
4205 Return a unicode string representing the current working directory.
4206 [clinic start generated code]*/
4207 
4208 static PyObject *
os_getcwd_impl(PyObject * module)4209 os_getcwd_impl(PyObject *module)
4210 /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4211 {
4212     return posix_getcwd(0);
4213 }
4214 
4215 
4216 /*[clinic input]
4217 os.getcwdb
4218 
4219 Return a bytes string representing the current working directory.
4220 [clinic start generated code]*/
4221 
4222 static PyObject *
os_getcwdb_impl(PyObject * module)4223 os_getcwdb_impl(PyObject *module)
4224 /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4225 {
4226     return posix_getcwd(1);
4227 }
4228 
4229 
4230 #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4231 #define HAVE_LINK 1
4232 #endif
4233 
4234 #ifdef HAVE_LINK
4235 /*[clinic input]
4236 
4237 os.link
4238 
4239     src : path_t
4240     dst : path_t
4241     *
4242     src_dir_fd : dir_fd = None
4243     dst_dir_fd : dir_fd = None
4244     follow_symlinks: bool = True
4245 
4246 Create a hard link to a file.
4247 
4248 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4249   descriptor open to a directory, and the respective path string (src or dst)
4250   should be relative; the path will then be relative to that directory.
4251 If follow_symlinks is False, and the last element of src is a symbolic
4252   link, link will create a link to the symbolic link itself instead of the
4253   file the link points to.
4254 src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
4255   platform.  If they are unavailable, using them will raise a
4256   NotImplementedError.
4257 [clinic start generated code]*/
4258 
4259 static PyObject *
os_link_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int follow_symlinks)4260 os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4261              int dst_dir_fd, int follow_symlinks)
4262 /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
4263 {
4264 #ifdef MS_WINDOWS
4265     BOOL result = FALSE;
4266 #else
4267     int result;
4268 #endif
4269 #if defined(HAVE_LINKAT)
4270     int linkat_unavailable = 0;
4271 #endif
4272 
4273 #ifndef HAVE_LINKAT
4274     if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4275         argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4276         return NULL;
4277     }
4278 #endif
4279 
4280 #ifndef MS_WINDOWS
4281     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4282         PyErr_SetString(PyExc_NotImplementedError,
4283                         "link: src and dst must be the same type");
4284         return NULL;
4285     }
4286 #endif
4287 
4288     if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4289                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4290                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4291         return NULL;
4292     }
4293 
4294 #ifdef MS_WINDOWS
4295     Py_BEGIN_ALLOW_THREADS
4296     result = CreateHardLinkW(dst->wide, src->wide, NULL);
4297     Py_END_ALLOW_THREADS
4298 
4299     if (!result)
4300         return path_error2(src, dst);
4301 #else
4302     Py_BEGIN_ALLOW_THREADS
4303 #ifdef HAVE_LINKAT
4304     if ((src_dir_fd != DEFAULT_DIR_FD) ||
4305         (dst_dir_fd != DEFAULT_DIR_FD) ||
4306         (!follow_symlinks)) {
4307 
4308         if (HAVE_LINKAT_RUNTIME) {
4309 
4310             result = linkat(src_dir_fd, src->narrow,
4311                 dst_dir_fd, dst->narrow,
4312                 follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4313 
4314         }
4315 #ifdef __APPLE__
4316         else {
4317             if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
4318                 /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
4319                 result = link(src->narrow, dst->narrow);
4320             } else {
4321                 linkat_unavailable = 1;
4322             }
4323         }
4324 #endif
4325     }
4326     else
4327 #endif /* HAVE_LINKAT */
4328         result = link(src->narrow, dst->narrow);
4329     Py_END_ALLOW_THREADS
4330 
4331 #ifdef HAVE_LINKAT
4332     if (linkat_unavailable) {
4333         /* Either or both dir_fd arguments were specified */
4334         if (src_dir_fd  != DEFAULT_DIR_FD) {
4335             argument_unavailable_error("link", "src_dir_fd");
4336         } else {
4337             argument_unavailable_error("link", "dst_dir_fd");
4338         }
4339         return NULL;
4340     }
4341 #endif
4342 
4343     if (result)
4344         return path_error2(src, dst);
4345 #endif /* MS_WINDOWS */
4346 
4347     Py_RETURN_NONE;
4348 }
4349 #endif
4350 
4351 
4352 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4353 static PyObject *
_listdir_windows_no_opendir(path_t * path,PyObject * list)4354 _listdir_windows_no_opendir(path_t *path, PyObject *list)
4355 {
4356     PyObject *v;
4357     HANDLE hFindFile = INVALID_HANDLE_VALUE;
4358     BOOL result, return_bytes;
4359     wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4360     /* only claim to have space for MAX_PATH */
4361     Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4362     wchar_t *wnamebuf = NULL;
4363 
4364     WIN32_FIND_DATAW wFileData;
4365     const wchar_t *po_wchars;
4366 
4367     if (!path->wide) { /* Default arg: "." */
4368         po_wchars = L".";
4369         len = 1;
4370         return_bytes = 0;
4371     } else {
4372         po_wchars = path->wide;
4373         len = wcslen(path->wide);
4374         return_bytes = PyBytes_Check(path->object);
4375     }
4376     /* The +5 is so we can append "\\*.*\0" */
4377     wnamebuf = PyMem_New(wchar_t, len + 5);
4378     if (!wnamebuf) {
4379         PyErr_NoMemory();
4380         goto exit;
4381     }
4382     wcscpy(wnamebuf, po_wchars);
4383     if (len > 0) {
4384         wchar_t wch = wnamebuf[len-1];
4385         if (wch != SEP && wch != ALTSEP && wch != L':')
4386             wnamebuf[len++] = SEP;
4387         wcscpy(wnamebuf + len, L"*.*");
4388     }
4389     if ((list = PyList_New(0)) == NULL) {
4390         goto exit;
4391     }
4392     Py_BEGIN_ALLOW_THREADS
4393     hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4394     Py_END_ALLOW_THREADS
4395     if (hFindFile == INVALID_HANDLE_VALUE) {
4396         int error = GetLastError();
4397         if (error == ERROR_FILE_NOT_FOUND)
4398             goto exit;
4399         path_error(path);
4400         Py_CLEAR(list);
4401         goto exit;
4402     }
4403     do {
4404         /* Skip over . and .. */
4405         if (wcscmp(wFileData.cFileName, L".") != 0 &&
4406             wcscmp(wFileData.cFileName, L"..") != 0) {
4407             v = PyUnicode_FromWideChar(wFileData.cFileName,
4408                                        wcslen(wFileData.cFileName));
4409             if (return_bytes && v) {
4410                 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4411             }
4412             if (v == NULL) {
4413                 Py_CLEAR(list);
4414                 break;
4415             }
4416             if (PyList_Append(list, v) != 0) {
4417                 Py_DECREF(v);
4418                 Py_CLEAR(list);
4419                 break;
4420             }
4421             Py_DECREF(v);
4422         }
4423         Py_BEGIN_ALLOW_THREADS
4424         result = FindNextFileW(hFindFile, &wFileData);
4425         Py_END_ALLOW_THREADS
4426         /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4427            it got to the end of the directory. */
4428         if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4429             path_error(path);
4430             Py_CLEAR(list);
4431             goto exit;
4432         }
4433     } while (result == TRUE);
4434 
4435 exit:
4436     if (hFindFile != INVALID_HANDLE_VALUE) {
4437         if (FindClose(hFindFile) == FALSE) {
4438             if (list != NULL) {
4439                 path_error(path);
4440                 Py_CLEAR(list);
4441             }
4442         }
4443     }
4444     PyMem_Free(wnamebuf);
4445 
4446     return list;
4447 }  /* end of _listdir_windows_no_opendir */
4448 
4449 #else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4450 
4451 static PyObject *
_posix_listdir(path_t * path,PyObject * list)4452 _posix_listdir(path_t *path, PyObject *list)
4453 {
4454     PyObject *v;
4455     DIR *dirp = NULL;
4456     struct dirent *ep;
4457     int return_str; /* if false, return bytes */
4458 #ifdef HAVE_FDOPENDIR
4459     int fd = -1;
4460 #endif
4461 
4462     errno = 0;
4463 #ifdef HAVE_FDOPENDIR
4464     if (path->fd != -1) {
4465       if (HAVE_FDOPENDIR_RUNTIME) {
4466         /* closedir() closes the FD, so we duplicate it */
4467         fd = _Py_dup(path->fd);
4468         if (fd == -1)
4469             return NULL;
4470 
4471         return_str = 1;
4472 
4473         Py_BEGIN_ALLOW_THREADS
4474         dirp = fdopendir(fd);
4475         Py_END_ALLOW_THREADS
4476       } else {
4477         PyErr_SetString(PyExc_TypeError,
4478             "listdir: path should be string, bytes, os.PathLike or None, not int");
4479         return NULL;
4480       }
4481     }
4482     else
4483 #endif
4484     {
4485         const char *name;
4486         if (path->narrow) {
4487             name = path->narrow;
4488             /* only return bytes if they specified a bytes object */
4489             return_str = !PyBytes_Check(path->object);
4490         }
4491         else {
4492             name = ".";
4493             return_str = 1;
4494         }
4495 
4496         Py_BEGIN_ALLOW_THREADS
4497         dirp = opendir(name);
4498         Py_END_ALLOW_THREADS
4499     }
4500 
4501     if (dirp == NULL) {
4502         path_error(path);
4503         list = NULL;
4504 #ifdef HAVE_FDOPENDIR
4505         if (fd != -1) {
4506             Py_BEGIN_ALLOW_THREADS
4507             close(fd);
4508             Py_END_ALLOW_THREADS
4509         }
4510 #endif
4511         goto exit;
4512     }
4513     if ((list = PyList_New(0)) == NULL) {
4514         goto exit;
4515     }
4516     for (;;) {
4517         errno = 0;
4518         Py_BEGIN_ALLOW_THREADS
4519         ep = readdir(dirp);
4520         Py_END_ALLOW_THREADS
4521         if (ep == NULL) {
4522             if (errno == 0) {
4523                 break;
4524             } else {
4525                 path_error(path);
4526                 Py_CLEAR(list);
4527                 goto exit;
4528             }
4529         }
4530         if (ep->d_name[0] == '.' &&
4531             (NAMLEN(ep) == 1 ||
4532              (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4533             continue;
4534         if (return_str)
4535             v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4536         else
4537             v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4538         if (v == NULL) {
4539             Py_CLEAR(list);
4540             break;
4541         }
4542         if (PyList_Append(list, v) != 0) {
4543             Py_DECREF(v);
4544             Py_CLEAR(list);
4545             break;
4546         }
4547         Py_DECREF(v);
4548     }
4549 
4550 exit:
4551     if (dirp != NULL) {
4552         Py_BEGIN_ALLOW_THREADS
4553 #ifdef HAVE_FDOPENDIR
4554         if (fd > -1)
4555             rewinddir(dirp);
4556 #endif
4557         closedir(dirp);
4558         Py_END_ALLOW_THREADS
4559     }
4560 
4561     return list;
4562 }  /* end of _posix_listdir */
4563 #endif  /* which OS */
4564 
4565 
4566 /*[clinic input]
4567 os.listdir
4568 
4569     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4570 
4571 Return a list containing the names of the files in the directory.
4572 
4573 path can be specified as either str, bytes, or a path-like object.  If path is bytes,
4574   the filenames returned will also be bytes; in all other circumstances
4575   the filenames returned will be str.
4576 If path is None, uses the path='.'.
4577 On some platforms, path may also be specified as an open file descriptor;\
4578   the file descriptor must refer to a directory.
4579   If this functionality is unavailable, using it raises NotImplementedError.
4580 
4581 The list is in arbitrary order.  It does not include the special
4582 entries '.' and '..' even if they are present in the directory.
4583 
4584 
4585 [clinic start generated code]*/
4586 
4587 static PyObject *
os_listdir_impl(PyObject * module,path_t * path)4588 os_listdir_impl(PyObject *module, path_t *path)
4589 /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4590 {
4591     if (PySys_Audit("os.listdir", "O",
4592                     path->object ? path->object : Py_None) < 0) {
4593         return NULL;
4594     }
4595 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4596     return _listdir_windows_no_opendir(path, NULL);
4597 #else
4598     return _posix_listdir(path, NULL);
4599 #endif
4600 }
4601 
4602 
4603 #ifdef MS_WINDOWS
4604 
4605 /*[clinic input]
4606 os.listdrives
4607 
4608 Return a list containing the names of drives in the system.
4609 
4610 A drive name typically looks like 'C:\\'.
4611 
4612 [clinic start generated code]*/
4613 
4614 static PyObject *
os_listdrives_impl(PyObject * module)4615 os_listdrives_impl(PyObject *module)
4616 /*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
4617 {
4618     /* Number of possible drives is limited, so 256 should always be enough.
4619        On the day when it is not, listmounts() will have to be used. */
4620     wchar_t buffer[256];
4621     DWORD buflen = Py_ARRAY_LENGTH(buffer);
4622     PyObject *result = NULL;
4623     if (PySys_Audit("os.listdrives", NULL) < 0) {
4624         return NULL;
4625     }
4626 
4627     Py_BEGIN_ALLOW_THREADS;
4628     buflen = GetLogicalDriveStringsW(buflen, buffer);
4629     Py_END_ALLOW_THREADS;
4630 
4631     if (!buflen) {
4632         PyErr_SetFromWindowsErr(0);
4633         return NULL;
4634     } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
4635         PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
4636         return NULL;
4637     }
4638 
4639     /* buflen includes a null terminator, so remove it */
4640     PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
4641     if (str) {
4642         PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
4643         if (nullchar) {
4644             result = PyUnicode_Split(str, nullchar, -1);
4645             Py_DECREF(nullchar);
4646         }
4647         Py_DECREF(str);
4648     }
4649     return result;
4650 }
4651 
4652 /*[clinic input]
4653 os.listvolumes
4654 
4655 Return a list containing the volumes in the system.
4656 
4657 Volumes are typically represented as a GUID path.
4658 
4659 [clinic start generated code]*/
4660 
4661 static PyObject *
os_listvolumes_impl(PyObject * module)4662 os_listvolumes_impl(PyObject *module)
4663 /*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
4664 {
4665     PyObject *result = PyList_New(0);
4666     HANDLE find = INVALID_HANDLE_VALUE;
4667     wchar_t buffer[MAX_PATH + 1];
4668     if (!result) {
4669         return NULL;
4670     }
4671     if (PySys_Audit("os.listvolumes", NULL) < 0) {
4672         Py_DECREF(result);
4673         return NULL;
4674     }
4675 
4676     int err = 0;
4677     Py_BEGIN_ALLOW_THREADS;
4678     find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
4679     if (find == INVALID_HANDLE_VALUE) {
4680         err = GetLastError();
4681     }
4682     Py_END_ALLOW_THREADS;
4683 
4684     while (!err) {
4685         PyObject *s = PyUnicode_FromWideChar(buffer, -1);
4686         if (!s || PyList_Append(result, s) < 0) {
4687             Py_XDECREF(s);
4688             Py_CLEAR(result);
4689             break;
4690         }
4691         Py_DECREF(s);
4692 
4693         Py_BEGIN_ALLOW_THREADS;
4694         if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
4695             err = GetLastError();
4696         }
4697         Py_END_ALLOW_THREADS;
4698     }
4699 
4700     if (find != INVALID_HANDLE_VALUE) {
4701         Py_BEGIN_ALLOW_THREADS;
4702         FindVolumeClose(find);
4703         Py_END_ALLOW_THREADS;
4704     }
4705     if (err && err != ERROR_NO_MORE_FILES) {
4706         PyErr_SetFromWindowsErr(err);
4707         Py_XDECREF(result);
4708         result = NULL;
4709     }
4710     return result;
4711 }
4712 
4713 
4714 /*[clinic input]
4715 os.listmounts
4716 
4717     volume: path_t
4718 
4719 Return a list containing mount points for a particular volume.
4720 
4721 'volume' should be a GUID path as returned from os.listvolumes.
4722 
4723 [clinic start generated code]*/
4724 
4725 static PyObject *
os_listmounts_impl(PyObject * module,path_t * volume)4726 os_listmounts_impl(PyObject *module, path_t *volume)
4727 /*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
4728 {
4729     wchar_t default_buffer[MAX_PATH + 1];
4730     DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
4731     LPWSTR buffer = default_buffer;
4732     DWORD attributes;
4733     PyObject *str = NULL;
4734     PyObject *nullchar = NULL;
4735     PyObject *result = NULL;
4736 
4737     /* Ensure we have a valid volume path before continuing */
4738     Py_BEGIN_ALLOW_THREADS
4739     attributes = GetFileAttributesW(volume->wide);
4740     Py_END_ALLOW_THREADS
4741     if (attributes == INVALID_FILE_ATTRIBUTES &&
4742         GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
4743     {
4744         return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
4745     }
4746 
4747     if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
4748         return NULL;
4749     }
4750 
4751     while (1) {
4752         BOOL success;
4753         Py_BEGIN_ALLOW_THREADS
4754         success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
4755                                                    buflen, &buflen);
4756         Py_END_ALLOW_THREADS
4757         if (success) {
4758             break;
4759         }
4760         if (GetLastError() != ERROR_MORE_DATA) {
4761             PyErr_SetFromWindowsErr(0);
4762             goto exit;
4763         }
4764         if (buffer != default_buffer) {
4765             PyMem_Free((void *)buffer);
4766         }
4767         buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
4768         if (!buffer) {
4769             PyErr_NoMemory();
4770             goto exit;
4771         }
4772     }
4773     if (buflen < 2) {
4774         result = PyList_New(0);
4775         goto exit;
4776     }
4777     // buflen includes two null terminators, one for the last string
4778     // and one for the array of strings.
4779     str = PyUnicode_FromWideChar(buffer, buflen - 2);
4780     nullchar = PyUnicode_FromStringAndSize("\0", 1);
4781     if (str && nullchar) {
4782         result = PyUnicode_Split(str, nullchar, -1);
4783     }
4784 exit:
4785     if (buffer != default_buffer) {
4786         PyMem_Free(buffer);
4787     }
4788     Py_XDECREF(nullchar);
4789     Py_XDECREF(str);
4790     return result;
4791 }
4792 
4793 
4794 /*[clinic input]
4795 os._path_isdevdrive
4796 
4797     path: path_t
4798 
4799 Determines whether the specified path is on a Windows Dev Drive.
4800 
4801 [clinic start generated code]*/
4802 
4803 static PyObject *
os__path_isdevdrive_impl(PyObject * module,path_t * path)4804 os__path_isdevdrive_impl(PyObject *module, path_t *path)
4805 /*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
4806 {
4807 #ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
4808     /* This flag will be documented at
4809        https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
4810        after release, and will be available in the latest WinSDK.
4811        We include the flag to avoid a specific version dependency
4812        on the latest WinSDK. */
4813     const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
4814 #endif
4815     int err = 0;
4816     PyObject *r = NULL;
4817     wchar_t volume[MAX_PATH];
4818 
4819     Py_BEGIN_ALLOW_THREADS
4820     if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
4821         /* invalid path of some kind */
4822         /* Note that this also includes the case where a volume is mounted
4823            in a path longer than 260 characters. This is likely to be rare
4824            and problematic for other reasons, so a (soft) failure in this
4825            check seems okay. */
4826         err = GetLastError();
4827     } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
4828         /* only care about local dev drives */
4829         r = Py_False;
4830     } else {
4831         HANDLE hVolume = CreateFileW(
4832             volume,
4833             FILE_READ_ATTRIBUTES,
4834             FILE_SHARE_READ | FILE_SHARE_WRITE,
4835             NULL,
4836             OPEN_EXISTING,
4837             FILE_FLAG_BACKUP_SEMANTICS,
4838             NULL
4839         );
4840         if (hVolume == INVALID_HANDLE_VALUE) {
4841             err = GetLastError();
4842         } else {
4843             FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
4844             volumeState.Version = 1;
4845             volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
4846             if (!DeviceIoControl(
4847                 hVolume,
4848                 FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
4849                 &volumeState,
4850                 sizeof(volumeState),
4851                 &volumeState,
4852                 sizeof(volumeState),
4853                 NULL,
4854                 NULL
4855             )) {
4856                 err = GetLastError();
4857             }
4858             CloseHandle(hVolume);
4859             if (err == ERROR_INVALID_PARAMETER) {
4860                 /* not supported on this platform */
4861                 r = Py_False;
4862             } else if (!err) {
4863                 r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
4864                     ? Py_True : Py_False;
4865             }
4866         }
4867     }
4868     Py_END_ALLOW_THREADS
4869 
4870     if (err) {
4871         PyErr_SetFromWindowsErr(err);
4872         return NULL;
4873     }
4874 
4875     if (r) {
4876         return Py_NewRef(r);
4877     }
4878 
4879     return NULL;
4880 }
4881 
4882 
4883 int
_PyOS_getfullpathname(const wchar_t * path,wchar_t ** abspath_p)4884 _PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
4885 {
4886     wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
4887     DWORD result;
4888 
4889     result = GetFullPathNameW(path,
4890                               Py_ARRAY_LENGTH(woutbuf), woutbuf,
4891                               NULL);
4892     if (!result) {
4893         return -1;
4894     }
4895 
4896     if (result >= Py_ARRAY_LENGTH(woutbuf)) {
4897         if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4898             woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
4899         }
4900         else {
4901             woutbufp = NULL;
4902         }
4903         if (!woutbufp) {
4904             *abspath_p = NULL;
4905             return 0;
4906         }
4907 
4908         result = GetFullPathNameW(path, result, woutbufp, NULL);
4909         if (!result) {
4910             PyMem_RawFree(woutbufp);
4911             return -1;
4912         }
4913     }
4914 
4915     if (woutbufp != woutbuf) {
4916         *abspath_p = woutbufp;
4917         return 0;
4918     }
4919 
4920     *abspath_p = _PyMem_RawWcsdup(woutbufp);
4921     return 0;
4922 }
4923 
4924 
4925 /* A helper function for abspath on win32 */
4926 /*[clinic input]
4927 os._getfullpathname
4928 
4929     path: path_t
4930     /
4931 
4932 [clinic start generated code]*/
4933 
4934 static PyObject *
os__getfullpathname_impl(PyObject * module,path_t * path)4935 os__getfullpathname_impl(PyObject *module, path_t *path)
4936 /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
4937 {
4938     wchar_t *abspath;
4939 
4940     if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
4941         return win32_error_object("GetFullPathNameW", path->object);
4942     }
4943     if (abspath == NULL) {
4944         return PyErr_NoMemory();
4945     }
4946 
4947     PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
4948     PyMem_RawFree(abspath);
4949     if (str == NULL) {
4950         return NULL;
4951     }
4952     if (PyBytes_Check(path->object)) {
4953         Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
4954     }
4955     return str;
4956 }
4957 
4958 
4959 /*[clinic input]
4960 os._getfinalpathname
4961 
4962     path: path_t
4963     /
4964 
4965 A helper function for samepath on windows.
4966 [clinic start generated code]*/
4967 
4968 static PyObject *
os__getfinalpathname_impl(PyObject * module,path_t * path)4969 os__getfinalpathname_impl(PyObject *module, path_t *path)
4970 /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
4971 {
4972     HANDLE hFile;
4973     wchar_t buf[MAXPATHLEN], *target_path = buf;
4974     int buf_size = Py_ARRAY_LENGTH(buf);
4975     int result_length;
4976     PyObject *result;
4977 
4978     Py_BEGIN_ALLOW_THREADS
4979     hFile = CreateFileW(
4980         path->wide,
4981         0, /* desired access */
4982         0, /* share mode */
4983         NULL, /* security attributes */
4984         OPEN_EXISTING,
4985         /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
4986         FILE_FLAG_BACKUP_SEMANTICS,
4987         NULL);
4988     Py_END_ALLOW_THREADS
4989 
4990     if (hFile == INVALID_HANDLE_VALUE) {
4991         return win32_error_object("CreateFileW", path->object);
4992     }
4993 
4994     /* We have a good handle to the target, use it to determine the
4995        target path name. */
4996     while (1) {
4997         Py_BEGIN_ALLOW_THREADS
4998         result_length = GetFinalPathNameByHandleW(hFile, target_path,
4999                                                   buf_size, VOLUME_NAME_DOS);
5000         Py_END_ALLOW_THREADS
5001 
5002         if (!result_length) {
5003             result = win32_error_object("GetFinalPathNameByHandleW",
5004                                          path->object);
5005             goto cleanup;
5006         }
5007 
5008         if (result_length < buf_size) {
5009             break;
5010         }
5011 
5012         wchar_t *tmp;
5013         tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5014                             result_length * sizeof(*tmp));
5015         if (!tmp) {
5016             result = PyErr_NoMemory();
5017             goto cleanup;
5018         }
5019 
5020         buf_size = result_length;
5021         target_path = tmp;
5022     }
5023 
5024     result = PyUnicode_FromWideChar(target_path, result_length);
5025     if (result && PyBytes_Check(path->object)) {
5026         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5027     }
5028 
5029 cleanup:
5030     if (target_path != buf) {
5031         PyMem_Free(target_path);
5032     }
5033     CloseHandle(hFile);
5034     return result;
5035 }
5036 
5037 /*[clinic input]
5038 os._findfirstfile
5039     path: path_t
5040     /
5041 A function to get the real file name without accessing the file in Windows.
5042 [clinic start generated code]*/
5043 
5044 static PyObject *
os__findfirstfile_impl(PyObject * module,path_t * path)5045 os__findfirstfile_impl(PyObject *module, path_t *path)
5046 /*[clinic end generated code: output=106dd3f0779c83dd input=0734dff70f60e1a8]*/
5047 {
5048     PyObject *result;
5049     HANDLE hFindFile;
5050     WIN32_FIND_DATAW wFileData;
5051     WCHAR *wRealFileName;
5052 
5053     Py_BEGIN_ALLOW_THREADS
5054     hFindFile = FindFirstFileW(path->wide, &wFileData);
5055     Py_END_ALLOW_THREADS
5056 
5057     if (hFindFile == INVALID_HANDLE_VALUE) {
5058         path_error(path);
5059         return NULL;
5060     }
5061 
5062     wRealFileName = wFileData.cFileName;
5063     result = PyUnicode_FromWideChar(wRealFileName, wcslen(wRealFileName));
5064     FindClose(hFindFile);
5065     return result;
5066 }
5067 
5068 
5069 /*[clinic input]
5070 os._getvolumepathname
5071 
5072     path: path_t
5073 
5074 A helper function for ismount on Win32.
5075 [clinic start generated code]*/
5076 
5077 static PyObject *
os__getvolumepathname_impl(PyObject * module,path_t * path)5078 os__getvolumepathname_impl(PyObject *module, path_t *path)
5079 /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5080 {
5081     PyObject *result;
5082     wchar_t *mountpath=NULL;
5083     size_t buflen;
5084     BOOL ret;
5085 
5086     /* Volume path should be shorter than entire path */
5087     buflen = Py_MAX(path->length, MAX_PATH);
5088 
5089     if (buflen > PY_DWORD_MAX) {
5090         PyErr_SetString(PyExc_OverflowError, "path too long");
5091         return NULL;
5092     }
5093 
5094     mountpath = PyMem_New(wchar_t, buflen);
5095     if (mountpath == NULL)
5096         return PyErr_NoMemory();
5097 
5098     Py_BEGIN_ALLOW_THREADS
5099     ret = GetVolumePathNameW(path->wide, mountpath,
5100                              Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5101     Py_END_ALLOW_THREADS
5102 
5103     if (!ret) {
5104         result = win32_error_object("_getvolumepathname", path->object);
5105         goto exit;
5106     }
5107     result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
5108     if (PyBytes_Check(path->object))
5109         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5110 
5111 exit:
5112     PyMem_Free(mountpath);
5113     return result;
5114 }
5115 
5116 
5117 /*[clinic input]
5118 os._path_splitroot
5119 
5120     path: path_t
5121 
5122 Removes everything after the root on Win32.
5123 [clinic start generated code]*/
5124 
5125 static PyObject *
os__path_splitroot_impl(PyObject * module,path_t * path)5126 os__path_splitroot_impl(PyObject *module, path_t *path)
5127 /*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/
5128 {
5129     wchar_t *buffer;
5130     wchar_t *end;
5131     PyObject *result = NULL;
5132     HRESULT ret;
5133 
5134     buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5135     if (!buffer) {
5136         return NULL;
5137     }
5138     wcscpy(buffer, path->wide);
5139     for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5140         *p = L'\\';
5141     }
5142 
5143     Py_BEGIN_ALLOW_THREADS
5144     ret = PathCchSkipRoot(buffer, &end);
5145     Py_END_ALLOW_THREADS
5146     if (FAILED(ret)) {
5147         result = Py_BuildValue("sO", "", path->object);
5148     } else if (end != buffer) {
5149         size_t rootLen = (size_t)(end - buffer);
5150         result = Py_BuildValue("NN",
5151             PyUnicode_FromWideChar(path->wide, rootLen),
5152             PyUnicode_FromWideChar(path->wide + rootLen, -1)
5153         );
5154     } else {
5155         result = Py_BuildValue("Os", path->object, "");
5156     }
5157     PyMem_Free(buffer);
5158 
5159     return result;
5160 }
5161 
5162 
5163 #define PY_IFREG  1 // Regular file
5164 #define PY_IFDIR  2 // Directory
5165 #define PY_IFLNK  4 // Symlink
5166 #define PY_IFMNT  8 // Mount Point (junction)
5167 #define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5168 #define PY_IFRRP 32 // Regular Reparse Point
5169 
5170 static inline BOOL
_testInfo(DWORD attributes,DWORD reparseTag,BOOL diskDevice,int testedType)5171 _testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5172 {
5173     switch (testedType) {
5174     case PY_IFREG:
5175         return diskDevice && attributes &&
5176                !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5177     case PY_IFDIR:
5178         return attributes & FILE_ATTRIBUTE_DIRECTORY;
5179     case PY_IFLNK:
5180         return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5181                reparseTag == IO_REPARSE_TAG_SYMLINK;
5182     case PY_IFMNT:
5183         return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5184                reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5185     case PY_IFLRP:
5186         return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5187                IsReparseTagNameSurrogate(reparseTag);
5188     case PY_IFRRP:
5189         return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5190                reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5191     }
5192 
5193     return FALSE;
5194 }
5195 
5196 static BOOL
_testFileTypeByHandle(HANDLE hfile,int testedType,BOOL diskOnly)5197 _testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5198 {
5199     assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5200            testedType == PY_IFLNK || testedType == PY_IFMNT ||
5201            testedType == PY_IFLRP || testedType == PY_IFRRP);
5202 
5203     BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5204     if (diskOnly && !diskDevice) {
5205         return FALSE;
5206     }
5207     if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5208         FILE_ATTRIBUTE_TAG_INFO info;
5209         return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5210                                             sizeof(info)) &&
5211                _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5212                          testedType);
5213     }
5214     FILE_BASIC_INFO info;
5215     return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5216                                         sizeof(info)) &&
5217            _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5218 }
5219 
5220 static BOOL
_testFileTypeByName(LPCWSTR path,int testedType)5221 _testFileTypeByName(LPCWSTR path, int testedType)
5222 {
5223     assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5224            testedType == PY_IFLNK || testedType == PY_IFMNT ||
5225            testedType == PY_IFLRP || testedType == PY_IFRRP);
5226 
5227     FILE_STAT_BASIC_INFORMATION info;
5228     if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5229                                      sizeof(info)))
5230     {
5231         BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5232                           info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5233                           info.DeviceType == FILE_DEVICE_CD_ROM;
5234         BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5235                                 diskDevice, testedType);
5236         if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5237             !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5238         {
5239             return result;
5240         }
5241     }
5242     else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5243                 GetLastError()))
5244     {
5245         return FALSE;
5246     }
5247 
5248     DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5249     if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5250         flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5251     }
5252     HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5253                                OPEN_EXISTING, flags, NULL);
5254     if (hfile != INVALID_HANDLE_VALUE) {
5255         BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5256         CloseHandle(hfile);
5257         return result;
5258     }
5259 
5260     switch (GetLastError()) {
5261     case ERROR_ACCESS_DENIED:
5262     case ERROR_SHARING_VIOLATION:
5263     case ERROR_CANT_ACCESS_FILE:
5264     case ERROR_INVALID_PARAMETER:
5265         int rc;
5266         STRUCT_STAT st;
5267         if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5268             rc = STAT(path, &st);
5269         }
5270         else {
5271             // PY_IFRRP is not generally supported in this case, except for
5272             // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5273             rc = LSTAT(path, &st);
5274         }
5275         if (!rc) {
5276             return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5277                              st.st_mode & S_IFREG, testedType);
5278         }
5279     }
5280 
5281     return FALSE;
5282 }
5283 
5284 
5285 static BOOL
_testFileExistsByName(LPCWSTR path,BOOL followLinks)5286 _testFileExistsByName(LPCWSTR path, BOOL followLinks)
5287 {
5288     FILE_STAT_BASIC_INFORMATION info;
5289     if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5290                                      sizeof(info)))
5291     {
5292         if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5293             !followLinks && IsReparseTagNameSurrogate(info.ReparseTag))
5294         {
5295             return TRUE;
5296         }
5297     }
5298     else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5299                     GetLastError()))
5300     {
5301         return FALSE;
5302     }
5303 
5304     DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5305     if (!followLinks) {
5306         flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5307     }
5308     HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5309                                OPEN_EXISTING, flags, NULL);
5310     if (hfile != INVALID_HANDLE_VALUE) {
5311         if (followLinks) {
5312             CloseHandle(hfile);
5313             return TRUE;
5314         }
5315         // Regular Reparse Points (PY_IFRRP) have to be traversed.
5316         BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5317         CloseHandle(hfile);
5318         if (!result) {
5319             return TRUE;
5320         }
5321         hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5322                             FILE_FLAG_BACKUP_SEMANTICS, NULL);
5323         if (hfile != INVALID_HANDLE_VALUE) {
5324             CloseHandle(hfile);
5325             return TRUE;
5326         }
5327     }
5328 
5329     switch (GetLastError()) {
5330     case ERROR_ACCESS_DENIED:
5331     case ERROR_SHARING_VIOLATION:
5332     case ERROR_CANT_ACCESS_FILE:
5333     case ERROR_INVALID_PARAMETER:
5334         STRUCT_STAT _st;
5335         return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5336     }
5337 
5338     return FALSE;
5339 }
5340 
5341 
5342 static BOOL
_testFileExists(path_t * path,BOOL followLinks)5343 _testFileExists(path_t *path, BOOL followLinks)
5344 {
5345     BOOL result = FALSE;
5346     if (path->value_error) {
5347         return FALSE;
5348     }
5349 
5350     Py_BEGIN_ALLOW_THREADS
5351     if (path->fd != -1) {
5352         HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5353         if (hfile != INVALID_HANDLE_VALUE) {
5354             if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5355                 result = TRUE;
5356             }
5357         }
5358     }
5359     else if (path->wide) {
5360         result = _testFileExistsByName(path->wide, followLinks);
5361     }
5362     Py_END_ALLOW_THREADS
5363 
5364     return result;
5365 }
5366 
5367 
5368 static BOOL
_testFileType(path_t * path,int testedType)5369 _testFileType(path_t *path, int testedType)
5370 {
5371     BOOL result = FALSE;
5372     if (path->value_error) {
5373         return FALSE;
5374     }
5375 
5376     Py_BEGIN_ALLOW_THREADS
5377     if (path->fd != -1) {
5378         HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5379         if (hfile != INVALID_HANDLE_VALUE) {
5380             result = _testFileTypeByHandle(hfile, testedType, TRUE);
5381         }
5382     }
5383     else if (path->wide) {
5384         result = _testFileTypeByName(path->wide, testedType);
5385     }
5386     Py_END_ALLOW_THREADS
5387 
5388     return result;
5389 }
5390 
5391 
5392 /*[clinic input]
5393 os._path_exists -> bool
5394 
5395     path: path_t(allow_fd=True, suppress_value_error=True)
5396 
5397 Test whether a path exists.  Returns False for broken symbolic links.
5398 
5399 [clinic start generated code]*/
5400 
5401 static int
os__path_exists_impl(PyObject * module,path_t * path)5402 os__path_exists_impl(PyObject *module, path_t *path)
5403 /*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5404 {
5405     return _testFileExists(path, TRUE);
5406 }
5407 
5408 
5409 /*[clinic input]
5410 os._path_lexists -> bool
5411 
5412     path: path_t(allow_fd=True, suppress_value_error=True)
5413 
5414 Test whether a path exists.  Returns True for broken symbolic links.
5415 
5416 [clinic start generated code]*/
5417 
5418 static int
os__path_lexists_impl(PyObject * module,path_t * path)5419 os__path_lexists_impl(PyObject *module, path_t *path)
5420 /*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5421 {
5422     return _testFileExists(path, FALSE);
5423 }
5424 
5425 
5426 /*[clinic input]
5427 os._path_isdir -> bool
5428 
5429     s as path: path_t(allow_fd=True, suppress_value_error=True)
5430 
5431 Return true if the pathname refers to an existing directory.
5432 
5433 [clinic start generated code]*/
5434 
5435 static int
os__path_isdir_impl(PyObject * module,path_t * path)5436 os__path_isdir_impl(PyObject *module, path_t *path)
5437 /*[clinic end generated code: output=d5786196f9e2fa7a input=132a3b5301aecf79]*/
5438 {
5439     return _testFileType(path, PY_IFDIR);
5440 }
5441 
5442 
5443 /*[clinic input]
5444 os._path_isfile -> bool
5445 
5446     path: path_t(allow_fd=True, suppress_value_error=True)
5447 
5448 Test whether a path is a regular file
5449 
5450 [clinic start generated code]*/
5451 
5452 static int
os__path_isfile_impl(PyObject * module,path_t * path)5453 os__path_isfile_impl(PyObject *module, path_t *path)
5454 /*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
5455 {
5456     return _testFileType(path, PY_IFREG);
5457 }
5458 
5459 
5460 /*[clinic input]
5461 os._path_islink -> bool
5462 
5463     path: path_t(allow_fd=True, suppress_value_error=True)
5464 
5465 Test whether a path is a symbolic link
5466 
5467 [clinic start generated code]*/
5468 
5469 static int
os__path_islink_impl(PyObject * module,path_t * path)5470 os__path_islink_impl(PyObject *module, path_t *path)
5471 /*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
5472 {
5473     return _testFileType(path, PY_IFLNK);
5474 }
5475 
5476 
5477 /*[clinic input]
5478 os._path_isjunction -> bool
5479 
5480     path: path_t(allow_fd=True, suppress_value_error=True)
5481 
5482 Test whether a path is a junction
5483 
5484 [clinic start generated code]*/
5485 
5486 static int
os__path_isjunction_impl(PyObject * module,path_t * path)5487 os__path_isjunction_impl(PyObject *module, path_t *path)
5488 /*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
5489 {
5490     return _testFileType(path, PY_IFMNT);
5491 }
5492 
5493 #undef PY_IFREG
5494 #undef PY_IFDIR
5495 #undef PY_IFLNK
5496 #undef PY_IFMNT
5497 #undef PY_IFLRP
5498 #undef PY_IFRRP
5499 
5500 #endif /* MS_WINDOWS */
5501 
5502 
5503 /*[clinic input]
5504 os._path_splitroot_ex
5505 
5506     p as path: path_t(make_wide=True, nonstrict=True)
5507 
5508 Split a pathname into drive, root and tail.
5509 
5510 The tail contains anything after the root.
5511 [clinic start generated code]*/
5512 
5513 static PyObject *
os__path_splitroot_ex_impl(PyObject * module,path_t * path)5514 os__path_splitroot_ex_impl(PyObject *module, path_t *path)
5515 /*[clinic end generated code: output=4b0072b6cdf4b611 input=4556b615c7cc13f2]*/
5516 {
5517     Py_ssize_t drvsize, rootsize;
5518     PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
5519 
5520     const wchar_t *buffer = path->wide;
5521     _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
5522     drv = PyUnicode_FromWideChar(buffer, drvsize);
5523     if (drv == NULL) {
5524         goto exit;
5525     }
5526     root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
5527     if (root == NULL) {
5528         goto exit;
5529     }
5530     tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
5531                                   path->length - drvsize - rootsize);
5532     if (tail == NULL) {
5533         goto exit;
5534     }
5535     if (PyBytes_Check(path->object)) {
5536         Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
5537         if (drv == NULL) {
5538             goto exit;
5539         }
5540         Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
5541         if (root == NULL) {
5542             goto exit;
5543         }
5544         Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
5545         if (tail == NULL) {
5546             goto exit;
5547         }
5548     }
5549     result = PyTuple_Pack(3, drv, root, tail);
5550 exit:
5551     Py_XDECREF(drv);
5552     Py_XDECREF(root);
5553     Py_XDECREF(tail);
5554     return result;
5555 }
5556 
5557 
5558 /*[clinic input]
5559 os._path_normpath
5560 
5561     path: path_t(make_wide=True, nonstrict=True)
5562 
5563 Normalize path, eliminating double slashes, etc.
5564 [clinic start generated code]*/
5565 
5566 static PyObject *
os__path_normpath_impl(PyObject * module,path_t * path)5567 os__path_normpath_impl(PyObject *module, path_t *path)
5568 /*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
5569 {
5570     PyObject *result;
5571     Py_ssize_t norm_len;
5572     wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
5573                                                path->length, &norm_len);
5574     if (!norm_len) {
5575         result = PyUnicode_FromOrdinal('.');
5576     }
5577     else {
5578         result = PyUnicode_FromWideChar(norm_path, norm_len);
5579     }
5580     if (PyBytes_Check(path->object)) {
5581         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5582     }
5583     return result;
5584 }
5585 
5586 /*[clinic input]
5587 os.mkdir
5588 
5589     path : path_t
5590 
5591     mode: int = 0o777
5592 
5593     *
5594 
5595     dir_fd : dir_fd(requires='mkdirat') = None
5596 
5597 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
5598 
5599 Create a directory.
5600 
5601 If dir_fd is not None, it should be a file descriptor open to a directory,
5602   and path should be relative; path will then be relative to that directory.
5603 dir_fd may not be implemented on your platform.
5604   If it is unavailable, using it will raise a NotImplementedError.
5605 
5606 The mode argument is ignored on Windows. Where it is used, the current umask
5607 value is first masked out.
5608 [clinic start generated code]*/
5609 
5610 static PyObject *
os_mkdir_impl(PyObject * module,path_t * path,int mode,int dir_fd)5611 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
5612 /*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
5613 {
5614     int result;
5615 #ifdef MS_WINDOWS
5616     int error = 0;
5617     int pathError = 0;
5618     SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
5619     SECURITY_ATTRIBUTES *pSecAttr = NULL;
5620 #endif
5621 #ifdef HAVE_MKDIRAT
5622     int mkdirat_unavailable = 0;
5623 #endif
5624 
5625     if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
5626                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5627         return NULL;
5628     }
5629 
5630 #ifdef MS_WINDOWS
5631     Py_BEGIN_ALLOW_THREADS
5632     if (mode == 0700 /* 0o700 */) {
5633         ULONG sdSize;
5634         pSecAttr = &secAttr;
5635         // Set a discretionary ACL (D) that is protected (P) and includes
5636         // inheritable (OICI) entries that allow (A) full control (FA) to
5637         // SYSTEM (SY), Administrators (BA), and the owner (OW).
5638         if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
5639             L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
5640             SDDL_REVISION_1,
5641             &secAttr.lpSecurityDescriptor,
5642             &sdSize
5643         )) {
5644             error = GetLastError();
5645         }
5646     }
5647     if (!error) {
5648         result = CreateDirectoryW(path->wide, pSecAttr);
5649         if (secAttr.lpSecurityDescriptor &&
5650             // uncommonly, LocalFree returns non-zero on error, but still uses
5651             // GetLastError() to see what the error code is
5652             LocalFree(secAttr.lpSecurityDescriptor)) {
5653             error = GetLastError();
5654         }
5655     }
5656     Py_END_ALLOW_THREADS
5657 
5658     if (error) {
5659         return PyErr_SetFromWindowsErr(error);
5660     }
5661     if (!result) {
5662         return path_error(path);
5663     }
5664 #else
5665     Py_BEGIN_ALLOW_THREADS
5666 #if HAVE_MKDIRAT
5667     if (dir_fd != DEFAULT_DIR_FD) {
5668       if (HAVE_MKDIRAT_RUNTIME) {
5669         result = mkdirat(dir_fd, path->narrow, mode);
5670 
5671       } else {
5672         mkdirat_unavailable = 1;
5673       }
5674     } else
5675 #endif
5676 #if defined(__WATCOMC__) && !defined(__QNX__)
5677         result = mkdir(path->narrow);
5678 #else
5679         result = mkdir(path->narrow, mode);
5680 #endif
5681     Py_END_ALLOW_THREADS
5682 
5683 #if HAVE_MKDIRAT
5684     if (mkdirat_unavailable) {
5685         argument_unavailable_error(NULL, "dir_fd");
5686         return NULL;
5687     }
5688 #endif
5689 
5690     if (result < 0)
5691         return path_error(path);
5692 #endif /* MS_WINDOWS */
5693     Py_RETURN_NONE;
5694 }
5695 
5696 
5697 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
5698 #if defined(HAVE_SYS_RESOURCE_H)
5699 #include <sys/resource.h>
5700 #endif
5701 
5702 
5703 #ifdef HAVE_NICE
5704 /*[clinic input]
5705 os.nice
5706 
5707     increment: int
5708     /
5709 
5710 Add increment to the priority of process and return the new priority.
5711 [clinic start generated code]*/
5712 
5713 static PyObject *
os_nice_impl(PyObject * module,int increment)5714 os_nice_impl(PyObject *module, int increment)
5715 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
5716 {
5717     int value;
5718 
5719     /* There are two flavours of 'nice': one that returns the new
5720        priority (as required by almost all standards out there) and the
5721        Linux/FreeBSD one, which returns '0' on success and advices
5722        the use of getpriority() to get the new priority.
5723 
5724        If we are of the nice family that returns the new priority, we
5725        need to clear errno before the call, and check if errno is filled
5726        before calling posix_error() on a returnvalue of -1, because the
5727        -1 may be the actual new priority! */
5728 
5729     errno = 0;
5730     value = nice(increment);
5731 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
5732     if (value == 0)
5733         value = getpriority(PRIO_PROCESS, 0);
5734 #endif
5735     if (value == -1 && errno != 0)
5736         /* either nice() or getpriority() returned an error */
5737         return posix_error();
5738     return PyLong_FromLong((long) value);
5739 }
5740 #endif /* HAVE_NICE */
5741 
5742 
5743 #ifdef HAVE_GETPRIORITY
5744 /*[clinic input]
5745 os.getpriority
5746 
5747     which: int
5748     who: int
5749 
5750 Return program scheduling priority.
5751 [clinic start generated code]*/
5752 
5753 static PyObject *
os_getpriority_impl(PyObject * module,int which,int who)5754 os_getpriority_impl(PyObject *module, int which, int who)
5755 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
5756 {
5757     int retval;
5758 
5759     errno = 0;
5760     retval = getpriority(which, who);
5761     if (errno != 0)
5762         return posix_error();
5763     return PyLong_FromLong((long)retval);
5764 }
5765 #endif /* HAVE_GETPRIORITY */
5766 
5767 
5768 #ifdef HAVE_SETPRIORITY
5769 /*[clinic input]
5770 os.setpriority
5771 
5772     which: int
5773     who: int
5774     priority: int
5775 
5776 Set program scheduling priority.
5777 [clinic start generated code]*/
5778 
5779 static PyObject *
os_setpriority_impl(PyObject * module,int which,int who,int priority)5780 os_setpriority_impl(PyObject *module, int which, int who, int priority)
5781 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
5782 {
5783     int retval;
5784 
5785     retval = setpriority(which, who, priority);
5786     if (retval == -1)
5787         return posix_error();
5788     Py_RETURN_NONE;
5789 }
5790 #endif /* HAVE_SETPRIORITY */
5791 
5792 
5793 static PyObject *
internal_rename(path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int is_replace)5794 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
5795 {
5796     const char *function_name = is_replace ? "replace" : "rename";
5797     int dir_fd_specified;
5798 
5799 #ifdef HAVE_RENAMEAT
5800     int renameat_unavailable = 0;
5801 #endif
5802 
5803 #ifdef MS_WINDOWS
5804     BOOL result;
5805     int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
5806 #else
5807     int result;
5808 #endif
5809 
5810     dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
5811                        (dst_dir_fd != DEFAULT_DIR_FD);
5812 #ifndef HAVE_RENAMEAT
5813     if (dir_fd_specified) {
5814         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
5815         return NULL;
5816     }
5817 #endif
5818 
5819     if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
5820                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
5821                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
5822         return NULL;
5823     }
5824 
5825 #ifdef MS_WINDOWS
5826     Py_BEGIN_ALLOW_THREADS
5827     result = MoveFileExW(src->wide, dst->wide, flags);
5828     Py_END_ALLOW_THREADS
5829 
5830     if (!result)
5831         return path_error2(src, dst);
5832 
5833 #else
5834     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
5835         PyErr_Format(PyExc_ValueError,
5836                      "%s: src and dst must be the same type", function_name);
5837         return NULL;
5838     }
5839 
5840     Py_BEGIN_ALLOW_THREADS
5841 #ifdef HAVE_RENAMEAT
5842     if (dir_fd_specified) {
5843         if (HAVE_RENAMEAT_RUNTIME) {
5844             result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
5845         } else {
5846             renameat_unavailable = 1;
5847         }
5848     } else
5849 #endif
5850     result = rename(src->narrow, dst->narrow);
5851     Py_END_ALLOW_THREADS
5852 
5853 
5854 #ifdef HAVE_RENAMEAT
5855     if (renameat_unavailable) {
5856         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
5857         return NULL;
5858     }
5859 #endif
5860 
5861     if (result)
5862         return path_error2(src, dst);
5863 #endif
5864     Py_RETURN_NONE;
5865 }
5866 
5867 
5868 /*[clinic input]
5869 os.rename
5870 
5871     src : path_t
5872     dst : path_t
5873     *
5874     src_dir_fd : dir_fd = None
5875     dst_dir_fd : dir_fd = None
5876 
5877 Rename a file or directory.
5878 
5879 If either src_dir_fd or dst_dir_fd is not None, it should be a file
5880   descriptor open to a directory, and the respective path string (src or dst)
5881   should be relative; the path will then be relative to that directory.
5882 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
5883   If they are unavailable, using them will raise a NotImplementedError.
5884 [clinic start generated code]*/
5885 
5886 static PyObject *
os_rename_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)5887 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
5888                int dst_dir_fd)
5889 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
5890 {
5891     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
5892 }
5893 
5894 
5895 /*[clinic input]
5896 os.replace = os.rename
5897 
5898 Rename a file or directory, overwriting the destination.
5899 
5900 If either src_dir_fd or dst_dir_fd is not None, it should be a file
5901   descriptor open to a directory, and the respective path string (src or dst)
5902   should be relative; the path will then be relative to that directory.
5903 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
5904   If they are unavailable, using them will raise a NotImplementedError.
5905 [clinic start generated code]*/
5906 
5907 static PyObject *
os_replace_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)5908 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
5909                 int dst_dir_fd)
5910 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
5911 {
5912     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
5913 }
5914 
5915 
5916 /*[clinic input]
5917 os.rmdir
5918 
5919     path: path_t
5920     *
5921     dir_fd: dir_fd(requires='unlinkat') = None
5922 
5923 Remove a directory.
5924 
5925 If dir_fd is not None, it should be a file descriptor open to a directory,
5926   and path should be relative; path will then be relative to that directory.
5927 dir_fd may not be implemented on your platform.
5928   If it is unavailable, using it will raise a NotImplementedError.
5929 [clinic start generated code]*/
5930 
5931 static PyObject *
os_rmdir_impl(PyObject * module,path_t * path,int dir_fd)5932 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
5933 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
5934 {
5935     int result;
5936 #ifdef HAVE_UNLINKAT
5937     int unlinkat_unavailable = 0;
5938 #endif
5939 
5940     if (PySys_Audit("os.rmdir", "Oi", path->object,
5941                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5942         return NULL;
5943     }
5944 
5945     Py_BEGIN_ALLOW_THREADS
5946 #ifdef MS_WINDOWS
5947     /* Windows, success=1, UNIX, success=0 */
5948     result = !RemoveDirectoryW(path->wide);
5949 #else
5950 #ifdef HAVE_UNLINKAT
5951     if (dir_fd != DEFAULT_DIR_FD) {
5952       if (HAVE_UNLINKAT_RUNTIME) {
5953         result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
5954       } else {
5955         unlinkat_unavailable = 1;
5956         result = -1;
5957       }
5958     } else
5959 #endif
5960         result = rmdir(path->narrow);
5961 #endif
5962     Py_END_ALLOW_THREADS
5963 
5964 #ifdef HAVE_UNLINKAT
5965     if (unlinkat_unavailable) {
5966         argument_unavailable_error("rmdir", "dir_fd");
5967         return NULL;
5968     }
5969 #endif
5970 
5971     if (result)
5972         return path_error(path);
5973 
5974     Py_RETURN_NONE;
5975 }
5976 
5977 
5978 #ifdef HAVE_SYSTEM
5979 #ifdef MS_WINDOWS
5980 /*[clinic input]
5981 os.system -> long
5982 
5983     command: Py_UNICODE
5984 
5985 Execute the command in a subshell.
5986 [clinic start generated code]*/
5987 
5988 static long
os_system_impl(PyObject * module,const wchar_t * command)5989 os_system_impl(PyObject *module, const wchar_t *command)
5990 /*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
5991 {
5992     long result;
5993 
5994     if (PySys_Audit("os.system", "(u)", command) < 0) {
5995         return -1;
5996     }
5997 
5998     Py_BEGIN_ALLOW_THREADS
5999     _Py_BEGIN_SUPPRESS_IPH
6000     result = _wsystem(command);
6001     _Py_END_SUPPRESS_IPH
6002     Py_END_ALLOW_THREADS
6003     return result;
6004 }
6005 #else /* MS_WINDOWS */
6006 /*[clinic input]
6007 os.system -> long
6008 
6009     command: FSConverter
6010 
6011 Execute the command in a subshell.
6012 [clinic start generated code]*/
6013 
6014 static long
os_system_impl(PyObject * module,PyObject * command)6015 os_system_impl(PyObject *module, PyObject *command)
6016 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
6017 {
6018     long result;
6019     const char *bytes = PyBytes_AsString(command);
6020 
6021     if (PySys_Audit("os.system", "(O)", command) < 0) {
6022         return -1;
6023     }
6024 
6025     Py_BEGIN_ALLOW_THREADS
6026     result = system(bytes);
6027     Py_END_ALLOW_THREADS
6028     return result;
6029 }
6030 #endif
6031 #endif /* HAVE_SYSTEM */
6032 
6033 
6034 #ifdef HAVE_UMASK
6035 /*[clinic input]
6036 os.umask
6037 
6038     mask: int
6039     /
6040 
6041 Set the current numeric umask and return the previous umask.
6042 [clinic start generated code]*/
6043 
6044 static PyObject *
os_umask_impl(PyObject * module,int mask)6045 os_umask_impl(PyObject *module, int mask)
6046 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6047 {
6048     int i = (int)umask(mask);
6049     if (i < 0)
6050         return posix_error();
6051     return PyLong_FromLong((long)i);
6052 }
6053 #endif
6054 
6055 #ifdef MS_WINDOWS
6056 
6057 /* override the default DeleteFileW behavior so that directory
6058 symlinks can be removed with this function, the same as with
6059 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)6060 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6061 {
6062     WIN32_FILE_ATTRIBUTE_DATA info;
6063     WIN32_FIND_DATAW find_data;
6064     HANDLE find_data_handle;
6065     int is_directory = 0;
6066     int is_link = 0;
6067 
6068     if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6069         is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6070 
6071         /* Get WIN32_FIND_DATA structure for the path to determine if
6072            it is a symlink */
6073         if(is_directory &&
6074            info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6075             find_data_handle = FindFirstFileW(lpFileName, &find_data);
6076 
6077             if(find_data_handle != INVALID_HANDLE_VALUE) {
6078                 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6079                    IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6080                 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6081                           find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6082                 FindClose(find_data_handle);
6083             }
6084         }
6085     }
6086 
6087     if (is_directory && is_link)
6088         return RemoveDirectoryW(lpFileName);
6089 
6090     return DeleteFileW(lpFileName);
6091 }
6092 #endif /* MS_WINDOWS */
6093 
6094 
6095 /*[clinic input]
6096 os.unlink
6097 
6098     path: path_t
6099     *
6100     dir_fd: dir_fd(requires='unlinkat')=None
6101 
6102 Remove a file (same as remove()).
6103 
6104 If dir_fd is not None, it should be a file descriptor open to a directory,
6105   and path should be relative; path will then be relative to that directory.
6106 dir_fd may not be implemented on your platform.
6107   If it is unavailable, using it will raise a NotImplementedError.
6108 
6109 [clinic start generated code]*/
6110 
6111 static PyObject *
os_unlink_impl(PyObject * module,path_t * path,int dir_fd)6112 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6113 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
6114 {
6115     int result;
6116 #ifdef HAVE_UNLINKAT
6117     int unlinkat_unavailable = 0;
6118 #endif
6119 
6120     if (PySys_Audit("os.remove", "Oi", path->object,
6121                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6122         return NULL;
6123     }
6124 
6125     Py_BEGIN_ALLOW_THREADS
6126     _Py_BEGIN_SUPPRESS_IPH
6127 #ifdef MS_WINDOWS
6128     /* Windows, success=1, UNIX, success=0 */
6129     result = !Py_DeleteFileW(path->wide);
6130 #else
6131 #ifdef HAVE_UNLINKAT
6132     if (dir_fd != DEFAULT_DIR_FD) {
6133       if (HAVE_UNLINKAT_RUNTIME) {
6134 
6135         result = unlinkat(dir_fd, path->narrow, 0);
6136       } else {
6137         unlinkat_unavailable = 1;
6138       }
6139     } else
6140 #endif /* HAVE_UNLINKAT */
6141         result = unlink(path->narrow);
6142 #endif
6143     _Py_END_SUPPRESS_IPH
6144     Py_END_ALLOW_THREADS
6145 
6146 #ifdef HAVE_UNLINKAT
6147     if (unlinkat_unavailable) {
6148         argument_unavailable_error(NULL, "dir_fd");
6149         return NULL;
6150     }
6151 #endif
6152 
6153     if (result)
6154         return path_error(path);
6155 
6156     Py_RETURN_NONE;
6157 }
6158 
6159 
6160 /*[clinic input]
6161 os.remove = os.unlink
6162 
6163 Remove a file (same as unlink()).
6164 
6165 If dir_fd is not None, it should be a file descriptor open to a directory,
6166   and path should be relative; path will then be relative to that directory.
6167 dir_fd may not be implemented on your platform.
6168   If it is unavailable, using it will raise a NotImplementedError.
6169 [clinic start generated code]*/
6170 
6171 static PyObject *
os_remove_impl(PyObject * module,path_t * path,int dir_fd)6172 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
6173 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
6174 {
6175     return os_unlink_impl(module, path, dir_fd);
6176 }
6177 
6178 
6179 static PyStructSequence_Field uname_result_fields[] = {
6180     {"sysname",    "operating system name"},
6181     {"nodename",   "name of machine on network (implementation-defined)"},
6182     {"release",    "operating system release"},
6183     {"version",    "operating system version"},
6184     {"machine",    "hardware identifier"},
6185     {NULL}
6186 };
6187 
6188 PyDoc_STRVAR(uname_result__doc__,
6189 "uname_result: Result from os.uname().\n\n\
6190 This object may be accessed either as a tuple of\n\
6191   (sysname, nodename, release, version, machine),\n\
6192 or via the attributes sysname, nodename, release, version, and machine.\n\
6193 \n\
6194 See os.uname for more information.");
6195 
6196 static PyStructSequence_Desc uname_result_desc = {
6197     MODNAME ".uname_result", /* name */
6198     uname_result__doc__, /* doc */
6199     uname_result_fields,
6200     5
6201 };
6202 
6203 #ifdef HAVE_UNAME
6204 /*[clinic input]
6205 os.uname
6206 
6207 Return an object identifying the current operating system.
6208 
6209 The object behaves like a named tuple with the following fields:
6210   (sysname, nodename, release, version, machine)
6211 
6212 [clinic start generated code]*/
6213 
6214 static PyObject *
os_uname_impl(PyObject * module)6215 os_uname_impl(PyObject *module)
6216 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
6217 {
6218     struct utsname u;
6219     int res;
6220     PyObject *value;
6221 
6222     Py_BEGIN_ALLOW_THREADS
6223     res = uname(&u);
6224     Py_END_ALLOW_THREADS
6225     if (res < 0)
6226         return posix_error();
6227 
6228     PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
6229     value = PyStructSequence_New((PyTypeObject *)UnameResultType);
6230     if (value == NULL)
6231         return NULL;
6232 
6233 #define SET(i, field) \
6234     { \
6235     PyObject *o = PyUnicode_DecodeFSDefault(field); \
6236     if (!o) { \
6237         Py_DECREF(value); \
6238         return NULL; \
6239     } \
6240     PyStructSequence_SET_ITEM(value, i, o); \
6241     } \
6242 
6243     SET(0, u.sysname);
6244     SET(1, u.nodename);
6245     SET(2, u.release);
6246     SET(3, u.version);
6247     SET(4, u.machine);
6248 
6249 #undef SET
6250 
6251     return value;
6252 }
6253 #endif /* HAVE_UNAME */
6254 
6255 
6256 
6257 typedef struct {
6258     int    now;
6259     time_t atime_s;
6260     long   atime_ns;
6261     time_t mtime_s;
6262     long   mtime_ns;
6263 } utime_t;
6264 
6265 /*
6266  * these macros assume that "ut" is a pointer to a utime_t
6267  * they also intentionally leak the declaration of a pointer named "time"
6268  */
6269 #define UTIME_TO_TIMESPEC \
6270     struct timespec ts[2]; \
6271     struct timespec *time; \
6272     if (ut->now) \
6273         time = NULL; \
6274     else { \
6275         ts[0].tv_sec = ut->atime_s; \
6276         ts[0].tv_nsec = ut->atime_ns; \
6277         ts[1].tv_sec = ut->mtime_s; \
6278         ts[1].tv_nsec = ut->mtime_ns; \
6279         time = ts; \
6280     } \
6281 
6282 #define UTIME_TO_TIMEVAL \
6283     struct timeval tv[2]; \
6284     struct timeval *time; \
6285     if (ut->now) \
6286         time = NULL; \
6287     else { \
6288         tv[0].tv_sec = ut->atime_s; \
6289         tv[0].tv_usec = ut->atime_ns / 1000; \
6290         tv[1].tv_sec = ut->mtime_s; \
6291         tv[1].tv_usec = ut->mtime_ns / 1000; \
6292         time = tv; \
6293     } \
6294 
6295 #define UTIME_TO_UTIMBUF \
6296     struct utimbuf u; \
6297     struct utimbuf *time; \
6298     if (ut->now) \
6299         time = NULL; \
6300     else { \
6301         u.actime = ut->atime_s; \
6302         u.modtime = ut->mtime_s; \
6303         time = &u; \
6304     }
6305 
6306 #define UTIME_TO_TIME_T \
6307     time_t timet[2]; \
6308     time_t *time; \
6309     if (ut->now) \
6310         time = NULL; \
6311     else { \
6312         timet[0] = ut->atime_s; \
6313         timet[1] = ut->mtime_s; \
6314         time = timet; \
6315     } \
6316 
6317 
6318 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6319 
6320 static int
utime_dir_fd(utime_t * ut,int dir_fd,const char * path,int follow_symlinks)6321 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
6322 {
6323 #if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
6324     if (HAVE_UTIMENSAT_RUNTIME) {
6325         int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6326         UTIME_TO_TIMESPEC;
6327         return utimensat(dir_fd, path, time, flags);
6328     }  else {
6329         errno = ENOSYS;
6330         return -1;
6331     }
6332 #elif defined(HAVE_UTIMENSAT)
6333     int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6334     UTIME_TO_TIMESPEC;
6335     return utimensat(dir_fd, path, time, flags);
6336 #elif defined(HAVE_FUTIMESAT)
6337     UTIME_TO_TIMEVAL;
6338     /*
6339      * follow_symlinks will never be false here;
6340      * we only allow !follow_symlinks and dir_fd together
6341      * if we have utimensat()
6342      */
6343     assert(follow_symlinks);
6344     return futimesat(dir_fd, path, time);
6345 #endif
6346 }
6347 
6348     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
6349 #else
6350     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
6351 #endif
6352 
6353 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6354 
6355 static int
utime_fd(utime_t * ut,int fd)6356 utime_fd(utime_t *ut, int fd)
6357 {
6358 #ifdef HAVE_FUTIMENS
6359 
6360     if (HAVE_FUTIMENS_RUNTIME) {
6361 
6362     UTIME_TO_TIMESPEC;
6363     return futimens(fd, time);
6364 
6365     } else
6366 #ifndef HAVE_FUTIMES
6367     {
6368         /* Not sure if this can happen */
6369         PyErr_SetString(
6370             PyExc_RuntimeError,
6371             "neither futimens nor futimes are supported"
6372             " on this system");
6373         return -1;
6374     }
6375 #endif
6376 
6377 #endif
6378 #ifdef HAVE_FUTIMES
6379     {
6380     UTIME_TO_TIMEVAL;
6381     return futimes(fd, time);
6382     }
6383 #endif
6384 }
6385 
6386     #define PATH_UTIME_HAVE_FD 1
6387 #else
6388     #define PATH_UTIME_HAVE_FD 0
6389 #endif
6390 
6391 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
6392 #  define UTIME_HAVE_NOFOLLOW_SYMLINKS
6393 #endif
6394 
6395 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6396 
6397 static int
utime_nofollow_symlinks(utime_t * ut,const char * path)6398 utime_nofollow_symlinks(utime_t *ut, const char *path)
6399 {
6400 #ifdef HAVE_UTIMENSAT
6401     if (HAVE_UTIMENSAT_RUNTIME) {
6402         UTIME_TO_TIMESPEC;
6403         return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
6404     } else
6405 #ifndef HAVE_LUTIMES
6406     {
6407         /* Not sure if this can happen */
6408         PyErr_SetString(
6409             PyExc_RuntimeError,
6410             "neither utimensat nor lutimes are supported"
6411             " on this system");
6412         return -1;
6413     }
6414 #endif
6415 #endif
6416 
6417 #ifdef HAVE_LUTIMES
6418     {
6419     UTIME_TO_TIMEVAL;
6420     return lutimes(path, time);
6421     }
6422 #endif
6423 }
6424 
6425 #endif
6426 
6427 #ifndef MS_WINDOWS
6428 
6429 static int
utime_default(utime_t * ut,const char * path)6430 utime_default(utime_t *ut, const char *path)
6431 {
6432 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6433     if (HAVE_UTIMENSAT_RUNTIME) {
6434         UTIME_TO_TIMESPEC;
6435         return utimensat(DEFAULT_DIR_FD, path, time, 0);
6436     } else {
6437         UTIME_TO_TIMEVAL;
6438         return utimes(path, time);
6439     }
6440 #elif defined(HAVE_UTIMENSAT)
6441     UTIME_TO_TIMESPEC;
6442     return utimensat(DEFAULT_DIR_FD, path, time, 0);
6443 #elif defined(HAVE_UTIMES)
6444     UTIME_TO_TIMEVAL;
6445     return utimes(path, time);
6446 #elif defined(HAVE_UTIME_H)
6447     UTIME_TO_UTIMBUF;
6448     return utime(path, time);
6449 #else
6450     UTIME_TO_TIME_T;
6451     return utime(path, time);
6452 #endif
6453 }
6454 
6455 #endif
6456 
6457 static int
split_py_long_to_s_and_ns(PyObject * module,PyObject * py_long,time_t * s,long * ns)6458 split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
6459 {
6460     int result = 0;
6461     PyObject *divmod;
6462     divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
6463     if (!divmod)
6464         goto exit;
6465     if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
6466         PyErr_Format(PyExc_TypeError,
6467                      "%.200s.__divmod__() must return a 2-tuple, not %.200s",
6468                      _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
6469         goto exit;
6470     }
6471     *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
6472     if ((*s == -1) && PyErr_Occurred())
6473         goto exit;
6474     *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
6475     if ((*ns == -1) && PyErr_Occurred())
6476         goto exit;
6477 
6478     result = 1;
6479 exit:
6480     Py_XDECREF(divmod);
6481     return result;
6482 }
6483 
6484 
6485 /*[clinic input]
6486 os.utime
6487 
6488     path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
6489     times: object = None
6490     *
6491     ns: object = NULL
6492     dir_fd: dir_fd(requires='futimensat') = None
6493     follow_symlinks: bool=True
6494 
6495 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
6496 
6497 Set the access and modified time of path.
6498 
6499 path may always be specified as a string.
6500 On some platforms, path may also be specified as an open file descriptor.
6501   If this functionality is unavailable, using it raises an exception.
6502 
6503 If times is not None, it must be a tuple (atime, mtime);
6504     atime and mtime should be expressed as float seconds since the epoch.
6505 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
6506     atime_ns and mtime_ns should be expressed as integer nanoseconds
6507     since the epoch.
6508 If times is None and ns is unspecified, utime uses the current time.
6509 Specifying tuples for both times and ns is an error.
6510 
6511 If dir_fd is not None, it should be a file descriptor open to a directory,
6512   and path should be relative; path will then be relative to that directory.
6513 If follow_symlinks is False, and the last element of the path is a symbolic
6514   link, utime will modify the symbolic link itself instead of the file the
6515   link points to.
6516 It is an error to use dir_fd or follow_symlinks when specifying path
6517   as an open file descriptor.
6518 dir_fd and follow_symlinks may not be available on your platform.
6519   If they are unavailable, using them will raise a NotImplementedError.
6520 
6521 [clinic start generated code]*/
6522 
6523 static PyObject *
os_utime_impl(PyObject * module,path_t * path,PyObject * times,PyObject * ns,int dir_fd,int follow_symlinks)6524 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
6525               int dir_fd, int follow_symlinks)
6526 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
6527 {
6528 #ifdef MS_WINDOWS
6529     HANDLE hFile;
6530     FILETIME atime, mtime;
6531 #else
6532     int result;
6533 #endif
6534 
6535     utime_t utime;
6536 
6537     memset(&utime, 0, sizeof(utime_t));
6538 
6539     if (times != Py_None && ns) {
6540         PyErr_SetString(PyExc_ValueError,
6541                      "utime: you may specify either 'times'"
6542                      " or 'ns' but not both");
6543         return NULL;
6544     }
6545 
6546     if (times != Py_None) {
6547         time_t a_sec, m_sec;
6548         long a_nsec, m_nsec;
6549         if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
6550             PyErr_SetString(PyExc_TypeError,
6551                          "utime: 'times' must be either"
6552                          " a tuple of two ints or None");
6553             return NULL;
6554         }
6555         utime.now = 0;
6556         if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
6557                                      &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
6558             _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
6559                                      &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
6560             return NULL;
6561         }
6562         utime.atime_s = a_sec;
6563         utime.atime_ns = a_nsec;
6564         utime.mtime_s = m_sec;
6565         utime.mtime_ns = m_nsec;
6566     }
6567     else if (ns) {
6568         if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
6569             PyErr_SetString(PyExc_TypeError,
6570                          "utime: 'ns' must be a tuple of two ints");
6571             return NULL;
6572         }
6573         utime.now = 0;
6574         if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
6575                                       &utime.atime_s, &utime.atime_ns) ||
6576             !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
6577                                        &utime.mtime_s, &utime.mtime_ns)) {
6578             return NULL;
6579         }
6580     }
6581     else {
6582         /* times and ns are both None/unspecified. use "now". */
6583         utime.now = 1;
6584     }
6585 
6586 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
6587     if (follow_symlinks_specified("utime", follow_symlinks))
6588         return NULL;
6589 #endif
6590 
6591     if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
6592         dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
6593         fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
6594         return NULL;
6595 
6596 #if !defined(HAVE_UTIMENSAT)
6597     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
6598         PyErr_SetString(PyExc_ValueError,
6599                      "utime: cannot use dir_fd and follow_symlinks "
6600                      "together on this platform");
6601         return NULL;
6602     }
6603 #endif
6604 
6605     if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
6606                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6607         return NULL;
6608     }
6609 
6610 #ifdef MS_WINDOWS
6611     Py_BEGIN_ALLOW_THREADS
6612     hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
6613                         NULL, OPEN_EXISTING,
6614                         FILE_FLAG_BACKUP_SEMANTICS, NULL);
6615     Py_END_ALLOW_THREADS
6616     if (hFile == INVALID_HANDLE_VALUE) {
6617         path_error(path);
6618         return NULL;
6619     }
6620 
6621     if (utime.now) {
6622         GetSystemTimeAsFileTime(&mtime);
6623         atime = mtime;
6624     }
6625     else {
6626         _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
6627         _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
6628     }
6629     if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
6630         path_error(path);
6631         CloseHandle(hFile);
6632         return NULL;
6633     }
6634     CloseHandle(hFile);
6635 #else /* MS_WINDOWS */
6636     Py_BEGIN_ALLOW_THREADS
6637 
6638 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6639     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
6640         result = utime_nofollow_symlinks(&utime, path->narrow);
6641     else
6642 #endif
6643 
6644 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6645     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
6646         result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
6647 
6648     } else
6649 #endif
6650 
6651 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6652     if (path->fd != -1)
6653         result = utime_fd(&utime, path->fd);
6654     else
6655 #endif
6656 
6657     result = utime_default(&utime, path->narrow);
6658 
6659     Py_END_ALLOW_THREADS
6660 
6661 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
6662     /* See utime_dir_fd implementation */
6663     if (result == -1 && errno == ENOSYS) {
6664         argument_unavailable_error(NULL, "dir_fd");
6665         return NULL;
6666     }
6667 #endif
6668 
6669     if (result < 0) {
6670         path_error(path);
6671         return NULL;
6672     }
6673 
6674 #endif /* MS_WINDOWS */
6675 
6676     Py_RETURN_NONE;
6677 }
6678 
6679 /* Process operations */
6680 
6681 
6682 /*[clinic input]
6683 os._exit
6684 
6685     status: int
6686 
6687 Exit to the system with specified status, without normal exit processing.
6688 [clinic start generated code]*/
6689 
6690 static PyObject *
os__exit_impl(PyObject * module,int status)6691 os__exit_impl(PyObject *module, int status)
6692 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
6693 {
6694     _exit(status);
6695     return NULL; /* Make gcc -Wall happy */
6696 }
6697 
6698 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
6699 #define EXECV_CHAR wchar_t
6700 #else
6701 #define EXECV_CHAR char
6702 #endif
6703 
6704 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
6705 static void
free_string_array(EXECV_CHAR ** array,Py_ssize_t count)6706 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
6707 {
6708     Py_ssize_t i;
6709     for (i = 0; i < count; i++)
6710         PyMem_Free(array[i]);
6711     PyMem_Free(array);
6712 }
6713 
6714 static int
fsconvert_strdup(PyObject * o,EXECV_CHAR ** out)6715 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
6716 {
6717     Py_ssize_t size;
6718     PyObject *ub;
6719     int result = 0;
6720 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
6721     if (!PyUnicode_FSDecoder(o, &ub))
6722         return 0;
6723     *out = PyUnicode_AsWideCharString(ub, &size);
6724     if (*out)
6725         result = 1;
6726 #else
6727     if (!PyUnicode_FSConverter(o, &ub))
6728         return 0;
6729     size = PyBytes_GET_SIZE(ub);
6730     *out = PyMem_Malloc(size + 1);
6731     if (*out) {
6732         memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
6733         result = 1;
6734     } else
6735         PyErr_NoMemory();
6736 #endif
6737     Py_DECREF(ub);
6738     return result;
6739 }
6740 #endif
6741 
6742 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
6743 static EXECV_CHAR**
parse_envlist(PyObject * env,Py_ssize_t * envc_ptr)6744 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
6745 {
6746     Py_ssize_t i, pos, envc;
6747     PyObject *keys=NULL, *vals=NULL;
6748     PyObject *key2, *val2, *keyval;
6749     EXECV_CHAR **envlist;
6750 
6751     i = PyMapping_Size(env);
6752     if (i < 0)
6753         return NULL;
6754     envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
6755     if (envlist == NULL) {
6756         PyErr_NoMemory();
6757         return NULL;
6758     }
6759     envc = 0;
6760     keys = PyMapping_Keys(env);
6761     if (!keys)
6762         goto error;
6763     vals = PyMapping_Values(env);
6764     if (!vals)
6765         goto error;
6766     if (!PyList_Check(keys) || !PyList_Check(vals)) {
6767         PyErr_Format(PyExc_TypeError,
6768                      "env.keys() or env.values() is not a list");
6769         goto error;
6770     }
6771 
6772     for (pos = 0; pos < i; pos++) {
6773         PyObject *key = PyList_GetItem(keys, pos);  // Borrowed ref.
6774         if (key == NULL) {
6775             goto error;
6776         }
6777         PyObject *val = PyList_GetItem(vals, pos);  // Borrowed ref.
6778         if (val == NULL) {
6779             goto error;
6780         }
6781 
6782 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
6783         if (!PyUnicode_FSDecoder(key, &key2))
6784             goto error;
6785         if (!PyUnicode_FSDecoder(val, &val2)) {
6786             Py_DECREF(key2);
6787             goto error;
6788         }
6789         /* Search from index 1 because on Windows starting '=' is allowed for
6790            defining hidden environment variables. */
6791         if (PyUnicode_GET_LENGTH(key2) == 0 ||
6792             PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
6793         {
6794             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
6795             Py_DECREF(key2);
6796             Py_DECREF(val2);
6797             goto error;
6798         }
6799         keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
6800 #else
6801         if (!PyUnicode_FSConverter(key, &key2))
6802             goto error;
6803         if (!PyUnicode_FSConverter(val, &val2)) {
6804             Py_DECREF(key2);
6805             goto error;
6806         }
6807         if (PyBytes_GET_SIZE(key2) == 0 ||
6808             strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
6809         {
6810             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
6811             Py_DECREF(key2);
6812             Py_DECREF(val2);
6813             goto error;
6814         }
6815         keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
6816                                              PyBytes_AS_STRING(val2));
6817 #endif
6818         Py_DECREF(key2);
6819         Py_DECREF(val2);
6820         if (!keyval)
6821             goto error;
6822 
6823         if (!fsconvert_strdup(keyval, &envlist[envc++])) {
6824             Py_DECREF(keyval);
6825             goto error;
6826         }
6827 
6828         Py_DECREF(keyval);
6829     }
6830     Py_DECREF(vals);
6831     Py_DECREF(keys);
6832 
6833     envlist[envc] = 0;
6834     *envc_ptr = envc;
6835     return envlist;
6836 
6837 error:
6838     Py_XDECREF(keys);
6839     Py_XDECREF(vals);
6840     free_string_array(envlist, envc);
6841     return NULL;
6842 }
6843 
6844 static EXECV_CHAR**
parse_arglist(PyObject * argv,Py_ssize_t * argc)6845 parse_arglist(PyObject* argv, Py_ssize_t *argc)
6846 {
6847     int i;
6848     EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
6849     if (argvlist == NULL) {
6850         PyErr_NoMemory();
6851         return NULL;
6852     }
6853     for (i = 0; i < *argc; i++) {
6854         PyObject* item = PySequence_ITEM(argv, i);
6855         if (item == NULL)
6856             goto fail;
6857         if (!fsconvert_strdup(item, &argvlist[i])) {
6858             Py_DECREF(item);
6859             goto fail;
6860         }
6861         Py_DECREF(item);
6862     }
6863     argvlist[*argc] = NULL;
6864     return argvlist;
6865 fail:
6866     *argc = i;
6867     free_string_array(argvlist, *argc);
6868     return NULL;
6869 }
6870 
6871 #endif
6872 
6873 
6874 #ifdef HAVE_EXECV
6875 /*[clinic input]
6876 os.execv
6877 
6878     path: path_t
6879         Path of executable file.
6880     argv: object
6881         Tuple or list of strings.
6882     /
6883 
6884 Execute an executable path with arguments, replacing current process.
6885 [clinic start generated code]*/
6886 
6887 static PyObject *
os_execv_impl(PyObject * module,path_t * path,PyObject * argv)6888 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
6889 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
6890 {
6891     EXECV_CHAR **argvlist;
6892     Py_ssize_t argc;
6893 
6894     PyInterpreterState *interp = _PyInterpreterState_GET();
6895     if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
6896         PyErr_SetString(PyExc_RuntimeError,
6897                         "exec not supported for isolated subinterpreters");
6898         return NULL;
6899     }
6900 
6901     /* execv has two arguments: (path, argv), where
6902        argv is a list or tuple of strings. */
6903 
6904     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6905         PyErr_SetString(PyExc_TypeError,
6906                         "execv() arg 2 must be a tuple or list");
6907         return NULL;
6908     }
6909     argc = PySequence_Size(argv);
6910     if (argc < 1) {
6911         PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
6912         return NULL;
6913     }
6914 
6915     argvlist = parse_arglist(argv, &argc);
6916     if (argvlist == NULL) {
6917         return NULL;
6918     }
6919     if (!argvlist[0][0]) {
6920         PyErr_SetString(PyExc_ValueError,
6921             "execv() arg 2 first element cannot be empty");
6922         free_string_array(argvlist, argc);
6923         return NULL;
6924     }
6925 
6926     if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
6927         free_string_array(argvlist, argc);
6928         return NULL;
6929     }
6930 
6931     _Py_BEGIN_SUPPRESS_IPH
6932 #ifdef HAVE_WEXECV
6933     _wexecv(path->wide, argvlist);
6934 #else
6935     execv(path->narrow, argvlist);
6936 #endif
6937     _Py_END_SUPPRESS_IPH
6938 
6939     /* If we get here it's definitely an error */
6940 
6941     posix_error();
6942     free_string_array(argvlist, argc);
6943     return NULL;
6944 }
6945 
6946 
6947 /*[clinic input]
6948 os.execve
6949 
6950     path: path_t(allow_fd='PATH_HAVE_FEXECVE')
6951         Path of executable file.
6952     argv: object
6953         Tuple or list of strings.
6954     env: object
6955         Dictionary of strings mapping to strings.
6956 
6957 Execute an executable path with arguments, replacing current process.
6958 [clinic start generated code]*/
6959 
6960 static PyObject *
os_execve_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env)6961 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
6962 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
6963 {
6964     EXECV_CHAR **argvlist = NULL;
6965     EXECV_CHAR **envlist;
6966     Py_ssize_t argc, envc;
6967 
6968     PyInterpreterState *interp = _PyInterpreterState_GET();
6969     if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
6970         PyErr_SetString(PyExc_RuntimeError,
6971                         "exec not supported for isolated subinterpreters");
6972         return NULL;
6973     }
6974 
6975     /* execve has three arguments: (path, argv, env), where
6976        argv is a list or tuple of strings and env is a dictionary
6977        like posix.environ. */
6978 
6979     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6980         PyErr_SetString(PyExc_TypeError,
6981                         "execve: argv must be a tuple or list");
6982         goto fail_0;
6983     }
6984     argc = PySequence_Size(argv);
6985     if (argc < 1) {
6986         PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
6987         return NULL;
6988     }
6989 
6990     if (!PyMapping_Check(env)) {
6991         PyErr_SetString(PyExc_TypeError,
6992                         "execve: environment must be a mapping object");
6993         goto fail_0;
6994     }
6995 
6996     argvlist = parse_arglist(argv, &argc);
6997     if (argvlist == NULL) {
6998         goto fail_0;
6999     }
7000     if (!argvlist[0][0]) {
7001         PyErr_SetString(PyExc_ValueError,
7002             "execve: argv first element cannot be empty");
7003         goto fail_0;
7004     }
7005 
7006     envlist = parse_envlist(env, &envc);
7007     if (envlist == NULL)
7008         goto fail_0;
7009 
7010     if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
7011         goto fail_1;
7012     }
7013 
7014     _Py_BEGIN_SUPPRESS_IPH
7015 #ifdef HAVE_FEXECVE
7016     if (path->fd > -1)
7017         fexecve(path->fd, argvlist, envlist);
7018     else
7019 #endif
7020 #ifdef HAVE_WEXECV
7021         _wexecve(path->wide, argvlist, envlist);
7022 #else
7023         execve(path->narrow, argvlist, envlist);
7024 #endif
7025     _Py_END_SUPPRESS_IPH
7026 
7027     /* If we get here it's definitely an error */
7028 
7029     posix_path_error(path);
7030   fail_1:
7031     free_string_array(envlist, envc);
7032   fail_0:
7033     if (argvlist)
7034         free_string_array(argvlist, argc);
7035     return NULL;
7036 }
7037 
7038 #endif /* HAVE_EXECV */
7039 
7040 #ifdef HAVE_POSIX_SPAWN
7041 
7042 enum posix_spawn_file_actions_identifier {
7043     POSIX_SPAWN_OPEN,
7044     POSIX_SPAWN_CLOSE,
7045     POSIX_SPAWN_DUP2
7046 #ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7047     ,POSIX_SPAWN_CLOSEFROM
7048 #endif
7049 };
7050 
7051 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7052 static int
7053 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
7054 #endif
7055 
7056 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)7057 parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
7058                         int resetids, int setsid, PyObject *setsigmask,
7059                         PyObject *setsigdef, PyObject *scheduler,
7060                         posix_spawnattr_t *attrp)
7061 {
7062     long all_flags = 0;
7063 
7064     errno = posix_spawnattr_init(attrp);
7065     if (errno) {
7066         posix_error();
7067         return -1;
7068     }
7069 
7070     if (setpgroup) {
7071         pid_t pgid = PyLong_AsPid(setpgroup);
7072         if (pgid == (pid_t)-1 && PyErr_Occurred()) {
7073             goto fail;
7074         }
7075         errno = posix_spawnattr_setpgroup(attrp, pgid);
7076         if (errno) {
7077             posix_error();
7078             goto fail;
7079         }
7080         all_flags |= POSIX_SPAWN_SETPGROUP;
7081     }
7082 
7083     if (resetids) {
7084         all_flags |= POSIX_SPAWN_RESETIDS;
7085     }
7086 
7087     if (setsid) {
7088 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7089         if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
7090 #endif
7091 #ifdef POSIX_SPAWN_SETSID
7092         all_flags |= POSIX_SPAWN_SETSID;
7093 #elif defined(POSIX_SPAWN_SETSID_NP)
7094         all_flags |= POSIX_SPAWN_SETSID_NP;
7095 #else
7096         argument_unavailable_error(func_name, "setsid");
7097         return -1;
7098 #endif
7099 
7100 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7101         } else {
7102             argument_unavailable_error(func_name, "setsid");
7103             return -1;
7104         }
7105 #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
7106 
7107     }
7108 
7109 #ifdef HAVE_SIGSET_T
7110    if (setsigmask) {
7111         sigset_t set;
7112         if (!_Py_Sigset_Converter(setsigmask, &set)) {
7113             goto fail;
7114         }
7115         errno = posix_spawnattr_setsigmask(attrp, &set);
7116         if (errno) {
7117             posix_error();
7118             goto fail;
7119         }
7120         all_flags |= POSIX_SPAWN_SETSIGMASK;
7121     }
7122 
7123     if (setsigdef) {
7124         sigset_t set;
7125         if (!_Py_Sigset_Converter(setsigdef, &set)) {
7126             goto fail;
7127         }
7128         errno = posix_spawnattr_setsigdefault(attrp, &set);
7129         if (errno) {
7130             posix_error();
7131             goto fail;
7132         }
7133         all_flags |= POSIX_SPAWN_SETSIGDEF;
7134     }
7135 #else
7136     if (setsigmask || setsigdef) {
7137         PyErr_SetString(PyExc_NotImplementedError,
7138                         "sigset is not supported on this platform");
7139         goto fail;
7140     }
7141 #endif
7142 
7143     if (scheduler) {
7144 #ifdef POSIX_SPAWN_SETSCHEDULER
7145         PyObject *py_schedpolicy;
7146         PyObject *schedparam_obj;
7147         struct sched_param schedparam;
7148 
7149         if (!PyArg_ParseTuple(scheduler, "OO"
7150                         ";A scheduler tuple must have two elements",
7151                         &py_schedpolicy, &schedparam_obj)) {
7152             goto fail;
7153         }
7154         if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
7155             goto fail;
7156         }
7157         if (py_schedpolicy != Py_None) {
7158             int schedpolicy = PyLong_AsInt(py_schedpolicy);
7159 
7160             if (schedpolicy == -1 && PyErr_Occurred()) {
7161                 goto fail;
7162             }
7163             errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
7164             if (errno) {
7165                 posix_error();
7166                 goto fail;
7167             }
7168             all_flags |= POSIX_SPAWN_SETSCHEDULER;
7169         }
7170         errno = posix_spawnattr_setschedparam(attrp, &schedparam);
7171         if (errno) {
7172             posix_error();
7173             goto fail;
7174         }
7175         all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
7176 #else
7177         PyErr_SetString(PyExc_NotImplementedError,
7178                 "The scheduler option is not supported in this system.");
7179         goto fail;
7180 #endif
7181     }
7182 
7183     errno = posix_spawnattr_setflags(attrp, all_flags);
7184     if (errno) {
7185         posix_error();
7186         goto fail;
7187     }
7188 
7189     return 0;
7190 
7191 fail:
7192     (void)posix_spawnattr_destroy(attrp);
7193     return -1;
7194 }
7195 
7196 static int
parse_file_actions(PyObject * file_actions,posix_spawn_file_actions_t * file_actionsp,PyObject * temp_buffer)7197 parse_file_actions(PyObject *file_actions,
7198                    posix_spawn_file_actions_t *file_actionsp,
7199                    PyObject *temp_buffer)
7200 {
7201     PyObject *seq;
7202     PyObject *file_action = NULL;
7203     PyObject *tag_obj;
7204 
7205     seq = PySequence_Fast(file_actions,
7206                           "file_actions must be a sequence or None");
7207     if (seq == NULL) {
7208         return -1;
7209     }
7210 
7211     errno = posix_spawn_file_actions_init(file_actionsp);
7212     if (errno) {
7213         posix_error();
7214         Py_DECREF(seq);
7215         return -1;
7216     }
7217 
7218     for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
7219         file_action = PySequence_Fast_GET_ITEM(seq, i);
7220         Py_INCREF(file_action);
7221         if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
7222             PyErr_SetString(PyExc_TypeError,
7223                 "Each file_actions element must be a non-empty tuple");
7224             goto fail;
7225         }
7226         long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
7227         if (tag == -1 && PyErr_Occurred()) {
7228             goto fail;
7229         }
7230 
7231         /* Populate the file_actions object */
7232         switch (tag) {
7233             case POSIX_SPAWN_OPEN: {
7234                 int fd, oflag;
7235                 PyObject *path;
7236                 unsigned long mode;
7237                 if (!PyArg_ParseTuple(file_action, "OiO&ik"
7238                         ";A open file_action tuple must have 5 elements",
7239                         &tag_obj, &fd, PyUnicode_FSConverter, &path,
7240                         &oflag, &mode))
7241                 {
7242                     goto fail;
7243                 }
7244                 if (PyList_Append(temp_buffer, path)) {
7245                     Py_DECREF(path);
7246                     goto fail;
7247                 }
7248                 errno = posix_spawn_file_actions_addopen(file_actionsp,
7249                         fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
7250                 if (errno) {
7251                     posix_error();
7252                     Py_DECREF(path);
7253                     goto fail;
7254                 }
7255                 Py_DECREF(path);
7256                 break;
7257             }
7258             case POSIX_SPAWN_CLOSE: {
7259                 int fd;
7260                 if (!PyArg_ParseTuple(file_action, "Oi"
7261                         ";A close file_action tuple must have 2 elements",
7262                         &tag_obj, &fd))
7263                 {
7264                     goto fail;
7265                 }
7266                 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
7267                 if (errno) {
7268                     posix_error();
7269                     goto fail;
7270                 }
7271                 break;
7272             }
7273             case POSIX_SPAWN_DUP2: {
7274                 int fd1, fd2;
7275                 if (!PyArg_ParseTuple(file_action, "Oii"
7276                         ";A dup2 file_action tuple must have 3 elements",
7277                         &tag_obj, &fd1, &fd2))
7278                 {
7279                     goto fail;
7280                 }
7281                 errno = posix_spawn_file_actions_adddup2(file_actionsp,
7282                                                          fd1, fd2);
7283                 if (errno) {
7284                     posix_error();
7285                     goto fail;
7286                 }
7287                 break;
7288             }
7289 #ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7290             case POSIX_SPAWN_CLOSEFROM: {
7291                 int fd;
7292                 if (!PyArg_ParseTuple(file_action, "Oi"
7293                         ";A closefrom file_action tuple must have 2 elements",
7294                         &tag_obj, &fd))
7295                 {
7296                     goto fail;
7297                 }
7298                 errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
7299                                                                  fd);
7300                 if (errno) {
7301                     posix_error();
7302                     goto fail;
7303                 }
7304                 break;
7305             }
7306 #endif
7307             default: {
7308                 PyErr_SetString(PyExc_TypeError,
7309                                 "Unknown file_actions identifier");
7310                 goto fail;
7311             }
7312         }
7313         Py_DECREF(file_action);
7314     }
7315 
7316     Py_DECREF(seq);
7317     return 0;
7318 
7319 fail:
7320     Py_DECREF(seq);
7321     Py_DECREF(file_action);
7322     (void)posix_spawn_file_actions_destroy(file_actionsp);
7323     return -1;
7324 }
7325 
7326 
7327 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)7328 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
7329                PyObject *env, PyObject *file_actions,
7330                PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
7331                PyObject *setsigdef, PyObject *scheduler)
7332 {
7333     const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
7334     EXECV_CHAR **argvlist = NULL;
7335     EXECV_CHAR **envlist = NULL;
7336     posix_spawn_file_actions_t file_actions_buf;
7337     posix_spawn_file_actions_t *file_actionsp = NULL;
7338     posix_spawnattr_t attr;
7339     posix_spawnattr_t *attrp = NULL;
7340     Py_ssize_t argc, envc;
7341     PyObject *result = NULL;
7342     PyObject *temp_buffer = NULL;
7343     pid_t pid;
7344     int err_code;
7345 
7346     /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
7347        argv is a list or tuple of strings and env is a dictionary
7348        like posix.environ. */
7349 
7350     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7351         PyErr_Format(PyExc_TypeError,
7352                      "%s: argv must be a tuple or list", func_name);
7353         goto exit;
7354     }
7355     argc = PySequence_Size(argv);
7356     if (argc < 1) {
7357         PyErr_Format(PyExc_ValueError,
7358                      "%s: argv must not be empty", func_name);
7359         return NULL;
7360     }
7361 
7362     if (!PyMapping_Check(env) && env != Py_None) {
7363         PyErr_Format(PyExc_TypeError,
7364                      "%s: environment must be a mapping object or None", func_name);
7365         goto exit;
7366     }
7367 
7368     argvlist = parse_arglist(argv, &argc);
7369     if (argvlist == NULL) {
7370         goto exit;
7371     }
7372     if (!argvlist[0][0]) {
7373         PyErr_Format(PyExc_ValueError,
7374                      "%s: argv first element cannot be empty", func_name);
7375         goto exit;
7376     }
7377 
7378 #ifdef USE_DARWIN_NS_GET_ENVIRON
7379     // There is no environ global in this situation.
7380     char **environ = NULL;
7381 #endif
7382 
7383     if (env == Py_None) {
7384 #ifdef USE_DARWIN_NS_GET_ENVIRON
7385         environ = *_NSGetEnviron();
7386 #endif
7387         envlist = environ;
7388     } else {
7389         envlist = parse_envlist(env, &envc);
7390         if (envlist == NULL) {
7391             goto exit;
7392         }
7393     }
7394 
7395     if (file_actions != NULL && file_actions != Py_None) {
7396         /* There is a bug in old versions of glibc that makes some of the
7397          * helper functions for manipulating file actions not copy the provided
7398          * buffers. The problem is that posix_spawn_file_actions_addopen does not
7399          * copy the value of path for some old versions of glibc (<2.20).
7400          * The use of temp_buffer here is a workaround that keeps the
7401          * python objects that own the buffers alive until posix_spawn gets called.
7402          * Check https://bugs.python.org/issue33630 and
7403          * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
7404         temp_buffer = PyList_New(0);
7405         if (!temp_buffer) {
7406             goto exit;
7407         }
7408         if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
7409             goto exit;
7410         }
7411         file_actionsp = &file_actions_buf;
7412     }
7413 
7414     if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
7415                                 setsigmask, setsigdef, scheduler, &attr)) {
7416         goto exit;
7417     }
7418     attrp = &attr;
7419 
7420     if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
7421         goto exit;
7422     }
7423 
7424     _Py_BEGIN_SUPPRESS_IPH
7425 #ifdef HAVE_POSIX_SPAWNP
7426     if (use_posix_spawnp) {
7427         err_code = posix_spawnp(&pid, path->narrow,
7428                                 file_actionsp, attrp, argvlist, envlist);
7429     }
7430     else
7431 #endif /* HAVE_POSIX_SPAWNP */
7432     {
7433         err_code = posix_spawn(&pid, path->narrow,
7434                                file_actionsp, attrp, argvlist, envlist);
7435     }
7436     _Py_END_SUPPRESS_IPH
7437 
7438     if (err_code) {
7439         errno = err_code;
7440         PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
7441         goto exit;
7442     }
7443 #ifdef _Py_MEMORY_SANITIZER
7444     __msan_unpoison(&pid, sizeof(pid));
7445 #endif
7446     result = PyLong_FromPid(pid);
7447 
7448 exit:
7449     if (file_actionsp) {
7450         (void)posix_spawn_file_actions_destroy(file_actionsp);
7451     }
7452     if (attrp) {
7453         (void)posix_spawnattr_destroy(attrp);
7454     }
7455     if (envlist && envlist != environ) {
7456         free_string_array(envlist, envc);
7457     }
7458     if (argvlist) {
7459         free_string_array(argvlist, argc);
7460     }
7461     Py_XDECREF(temp_buffer);
7462     return result;
7463 }
7464 
7465 
7466 /*[clinic input]
7467 
7468 os.posix_spawn
7469     path: path_t
7470         Path of executable file.
7471     argv: object
7472         Tuple or list of strings.
7473     env: object
7474         Dictionary of strings mapping to strings.
7475     /
7476     *
7477     file_actions: object(c_default='NULL') = ()
7478         A sequence of file action tuples.
7479     setpgroup: object = NULL
7480         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
7481     resetids: bool = False
7482         If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
7483     setsid: bool = False
7484         If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
7485     setsigmask: object(c_default='NULL') = ()
7486         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
7487     setsigdef: object(c_default='NULL') = ()
7488         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
7489     scheduler: object = NULL
7490         A tuple with the scheduler policy (optional) and parameters.
7491 
7492 Execute the program specified by path in a new process.
7493 [clinic start generated code]*/
7494 
7495 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)7496 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
7497                     PyObject *env, PyObject *file_actions,
7498                     PyObject *setpgroup, int resetids, int setsid,
7499                     PyObject *setsigmask, PyObject *setsigdef,
7500                     PyObject *scheduler)
7501 /*[clinic end generated code: output=14a1098c566bc675 input=808aed1090d84e33]*/
7502 {
7503     return py_posix_spawn(0, module, path, argv, env, file_actions,
7504                           setpgroup, resetids, setsid, setsigmask, setsigdef,
7505                           scheduler);
7506 }
7507  #endif /* HAVE_POSIX_SPAWN */
7508 
7509 
7510 
7511 #ifdef HAVE_POSIX_SPAWNP
7512 /*[clinic input]
7513 
7514 os.posix_spawnp
7515     path: path_t
7516         Path of executable file.
7517     argv: object
7518         Tuple or list of strings.
7519     env: object
7520         Dictionary of strings mapping to strings.
7521     /
7522     *
7523     file_actions: object(c_default='NULL') = ()
7524         A sequence of file action tuples.
7525     setpgroup: object = NULL
7526         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
7527     resetids: bool = False
7528         If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
7529     setsid: bool = False
7530         If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
7531     setsigmask: object(c_default='NULL') = ()
7532         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
7533     setsigdef: object(c_default='NULL') = ()
7534         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
7535     scheduler: object = NULL
7536         A tuple with the scheduler policy (optional) and parameters.
7537 
7538 Execute the program specified by path in a new process.
7539 [clinic start generated code]*/
7540 
7541 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)7542 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
7543                      PyObject *env, PyObject *file_actions,
7544                      PyObject *setpgroup, int resetids, int setsid,
7545                      PyObject *setsigmask, PyObject *setsigdef,
7546                      PyObject *scheduler)
7547 /*[clinic end generated code: output=7b9aaefe3031238d input=9e89e616116752a1]*/
7548 {
7549     return py_posix_spawn(1, module, path, argv, env, file_actions,
7550                           setpgroup, resetids, setsid, setsigmask, setsigdef,
7551                           scheduler);
7552 }
7553 #endif /* HAVE_POSIX_SPAWNP */
7554 
7555 #ifdef HAVE_RTPSPAWN
7556 static intptr_t
_rtp_spawn(int mode,const char * rtpFileName,const char * argv[],const char * envp[])7557 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
7558                const char  *envp[])
7559 {
7560      RTP_ID rtpid;
7561      int status;
7562      pid_t res;
7563      int async_err = 0;
7564 
7565      /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
7566         uStackSize=0 cannot be used, the default stack size is too small for
7567         Python. */
7568      if (envp) {
7569          rtpid = rtpSpawn(rtpFileName, argv, envp,
7570                           100, 0x1000000, 0, VX_FP_TASK);
7571      }
7572      else {
7573          rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
7574                           100, 0x1000000, 0, VX_FP_TASK);
7575      }
7576      if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
7577          do {
7578              res = waitpid((pid_t)rtpid, &status, 0);
7579          } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
7580 
7581          if (res < 0)
7582              return RTP_ID_ERROR;
7583          return ((intptr_t)status);
7584      }
7585      return ((intptr_t)rtpid);
7586 }
7587 #endif
7588 
7589 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
7590 /*[clinic input]
7591 os.spawnv
7592 
7593     mode: int
7594         Mode of process creation.
7595     path: path_t
7596         Path of executable file.
7597     argv: object
7598         Tuple or list of strings.
7599     /
7600 
7601 Execute the program specified by path in a new process.
7602 [clinic start generated code]*/
7603 
7604 static PyObject *
os_spawnv_impl(PyObject * module,int mode,path_t * path,PyObject * argv)7605 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
7606 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
7607 {
7608     EXECV_CHAR **argvlist;
7609     int i;
7610     Py_ssize_t argc;
7611     intptr_t spawnval;
7612     PyObject *(*getitem)(PyObject *, Py_ssize_t);
7613 
7614     /* spawnv has three arguments: (mode, path, argv), where
7615        argv is a list or tuple of strings. */
7616 
7617     if (PyList_Check(argv)) {
7618         argc = PyList_Size(argv);
7619         getitem = PyList_GetItem;
7620     }
7621     else if (PyTuple_Check(argv)) {
7622         argc = PyTuple_Size(argv);
7623         getitem = PyTuple_GetItem;
7624     }
7625     else {
7626         PyErr_SetString(PyExc_TypeError,
7627                         "spawnv() arg 2 must be a tuple or list");
7628         return NULL;
7629     }
7630     if (argc == 0) {
7631         PyErr_SetString(PyExc_ValueError,
7632             "spawnv() arg 2 cannot be empty");
7633         return NULL;
7634     }
7635 
7636     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
7637     if (argvlist == NULL) {
7638         return PyErr_NoMemory();
7639     }
7640     for (i = 0; i < argc; i++) {
7641         if (!fsconvert_strdup((*getitem)(argv, i),
7642                               &argvlist[i])) {
7643             free_string_array(argvlist, i);
7644             PyErr_SetString(
7645                 PyExc_TypeError,
7646                 "spawnv() arg 2 must contain only strings");
7647             return NULL;
7648         }
7649         if (i == 0 && !argvlist[0][0]) {
7650             free_string_array(argvlist, i + 1);
7651             PyErr_SetString(
7652                 PyExc_ValueError,
7653                 "spawnv() arg 2 first element cannot be empty");
7654             return NULL;
7655         }
7656     }
7657     argvlist[argc] = NULL;
7658 
7659 #if !defined(HAVE_RTPSPAWN)
7660     if (mode == _OLD_P_OVERLAY)
7661         mode = _P_OVERLAY;
7662 #endif
7663 
7664     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
7665                     Py_None) < 0) {
7666         free_string_array(argvlist, argc);
7667         return NULL;
7668     }
7669 
7670     Py_BEGIN_ALLOW_THREADS
7671     _Py_BEGIN_SUPPRESS_IPH
7672 #ifdef HAVE_WSPAWNV
7673     spawnval = _wspawnv(mode, path->wide, argvlist);
7674 #elif defined(HAVE_RTPSPAWN)
7675     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
7676 #else
7677     spawnval = _spawnv(mode, path->narrow, argvlist);
7678 #endif
7679     _Py_END_SUPPRESS_IPH
7680     Py_END_ALLOW_THREADS
7681 
7682     int saved_errno = errno;
7683     free_string_array(argvlist, argc);
7684 
7685     if (spawnval == -1) {
7686         errno = saved_errno;
7687         posix_error();
7688         return NULL;
7689     }
7690     return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
7691 }
7692 
7693 /*[clinic input]
7694 os.spawnve
7695 
7696     mode: int
7697         Mode of process creation.
7698     path: path_t
7699         Path of executable file.
7700     argv: object
7701         Tuple or list of strings.
7702     env: object
7703         Dictionary of strings mapping to strings.
7704     /
7705 
7706 Execute the program specified by path in a new process.
7707 [clinic start generated code]*/
7708 
7709 static PyObject *
os_spawnve_impl(PyObject * module,int mode,path_t * path,PyObject * argv,PyObject * env)7710 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
7711                 PyObject *env)
7712 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
7713 {
7714     EXECV_CHAR **argvlist;
7715     EXECV_CHAR **envlist;
7716     PyObject *res = NULL;
7717     Py_ssize_t argc, i, envc;
7718     intptr_t spawnval;
7719     PyObject *(*getitem)(PyObject *, Py_ssize_t);
7720     Py_ssize_t lastarg = 0;
7721 
7722     /* spawnve has four arguments: (mode, path, argv, env), where
7723        argv is a list or tuple of strings and env is a dictionary
7724        like posix.environ. */
7725 
7726     if (PyList_Check(argv)) {
7727         argc = PyList_Size(argv);
7728         getitem = PyList_GetItem;
7729     }
7730     else if (PyTuple_Check(argv)) {
7731         argc = PyTuple_Size(argv);
7732         getitem = PyTuple_GetItem;
7733     }
7734     else {
7735         PyErr_SetString(PyExc_TypeError,
7736                         "spawnve() arg 2 must be a tuple or list");
7737         goto fail_0;
7738     }
7739     if (argc == 0) {
7740         PyErr_SetString(PyExc_ValueError,
7741             "spawnve() arg 2 cannot be empty");
7742         goto fail_0;
7743     }
7744     if (!PyMapping_Check(env)) {
7745         PyErr_SetString(PyExc_TypeError,
7746                         "spawnve() arg 3 must be a mapping object");
7747         goto fail_0;
7748     }
7749 
7750     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
7751     if (argvlist == NULL) {
7752         PyErr_NoMemory();
7753         goto fail_0;
7754     }
7755     for (i = 0; i < argc; i++) {
7756         if (!fsconvert_strdup((*getitem)(argv, i),
7757                               &argvlist[i]))
7758         {
7759             lastarg = i;
7760             goto fail_1;
7761         }
7762         if (i == 0 && !argvlist[0][0]) {
7763             lastarg = i + 1;
7764             PyErr_SetString(
7765                 PyExc_ValueError,
7766                 "spawnv() arg 2 first element cannot be empty");
7767             goto fail_1;
7768         }
7769     }
7770     lastarg = argc;
7771     argvlist[argc] = NULL;
7772 
7773     envlist = parse_envlist(env, &envc);
7774     if (envlist == NULL)
7775         goto fail_1;
7776 
7777 #if !defined(HAVE_RTPSPAWN)
7778     if (mode == _OLD_P_OVERLAY)
7779         mode = _P_OVERLAY;
7780 #endif
7781 
7782     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
7783         goto fail_2;
7784     }
7785 
7786     Py_BEGIN_ALLOW_THREADS
7787     _Py_BEGIN_SUPPRESS_IPH
7788 #ifdef HAVE_WSPAWNV
7789     spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
7790 #elif defined(HAVE_RTPSPAWN)
7791     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
7792                            (const char **)envlist);
7793 #else
7794     spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
7795 #endif
7796     _Py_END_SUPPRESS_IPH
7797     Py_END_ALLOW_THREADS
7798 
7799     if (spawnval == -1)
7800         (void) posix_error();
7801     else
7802         res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
7803 
7804   fail_2:
7805     while (--envc >= 0) {
7806         PyMem_Free(envlist[envc]);
7807     }
7808     PyMem_Free(envlist);
7809   fail_1:
7810     free_string_array(argvlist, lastarg);
7811   fail_0:
7812     return res;
7813 }
7814 
7815 #endif /* HAVE_SPAWNV */
7816 
7817 #ifdef HAVE_FORK
7818 
7819 /* Helper function to validate arguments.
7820    Returns 0 on success.  non-zero on failure with a TypeError raised.
7821    If obj is non-NULL it must be callable.  */
7822 static int
check_null_or_callable(PyObject * obj,const char * obj_name)7823 check_null_or_callable(PyObject *obj, const char* obj_name)
7824 {
7825     if (obj && !PyCallable_Check(obj)) {
7826         PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
7827                      obj_name, _PyType_Name(Py_TYPE(obj)));
7828         return -1;
7829     }
7830     return 0;
7831 }
7832 
7833 /*[clinic input]
7834 os.register_at_fork
7835 
7836     *
7837     before: object=NULL
7838         A callable to be called in the parent before the fork() syscall.
7839     after_in_child: object=NULL
7840         A callable to be called in the child after fork().
7841     after_in_parent: object=NULL
7842         A callable to be called in the parent after fork().
7843 
7844 Register callables to be called when forking a new process.
7845 
7846 'before' callbacks are called in reverse order.
7847 'after_in_child' and 'after_in_parent' callbacks are called in order.
7848 
7849 [clinic start generated code]*/
7850 
7851 static PyObject *
os_register_at_fork_impl(PyObject * module,PyObject * before,PyObject * after_in_child,PyObject * after_in_parent)7852 os_register_at_fork_impl(PyObject *module, PyObject *before,
7853                          PyObject *after_in_child, PyObject *after_in_parent)
7854 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
7855 {
7856     PyInterpreterState *interp;
7857 
7858     if (!before && !after_in_child && !after_in_parent) {
7859         PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
7860         return NULL;
7861     }
7862     if (check_null_or_callable(before, "before") ||
7863         check_null_or_callable(after_in_child, "after_in_child") ||
7864         check_null_or_callable(after_in_parent, "after_in_parent")) {
7865         return NULL;
7866     }
7867     interp = _PyInterpreterState_GET();
7868 
7869     if (register_at_forker(&interp->before_forkers, before)) {
7870         return NULL;
7871     }
7872     if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
7873         return NULL;
7874     }
7875     if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
7876         return NULL;
7877     }
7878     Py_RETURN_NONE;
7879 }
7880 #endif /* HAVE_FORK */
7881 
7882 #if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
7883 // Common code to raise a warning if we detect there is more than one thread
7884 // running in the process. Best effort, silent if unable to count threads.
7885 // Constraint: Quick. Never overcounts. Never leaves an error set.
7886 //
7887 // This should only be called from the parent process after
7888 // PyOS_AfterFork_Parent().
7889 static void
warn_about_fork_with_threads(const char * name)7890 warn_about_fork_with_threads(const char* name)
7891 {
7892     // It's not safe to issue the warning while the world is stopped, because
7893     // other threads might be holding locks that we need, which would deadlock.
7894     assert(!_PyRuntime.stoptheworld.world_stopped);
7895 
7896     // TODO: Consider making an `os` module API to return the current number
7897     // of threads in the process. That'd presumably use this platform code but
7898     // raise an error rather than using the inaccurate fallback.
7899     Py_ssize_t num_python_threads = 0;
7900 #if defined(__APPLE__) && defined(HAVE_GETPID)
7901     mach_port_t macos_self = mach_task_self();
7902     mach_port_t macos_task;
7903     if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
7904         thread_array_t macos_threads;
7905         mach_msg_type_number_t macos_n_threads;
7906         if (task_threads(macos_task, &macos_threads,
7907                          &macos_n_threads) == KERN_SUCCESS) {
7908             num_python_threads = macos_n_threads;
7909         }
7910     }
7911 #elif defined(__linux__)
7912     // Linux /proc/self/stat 20th field is the number of threads.
7913     FILE* proc_stat = fopen("/proc/self/stat", "r");
7914     if (proc_stat) {
7915         size_t n;
7916         // Size chosen arbitrarily. ~60% more bytes than a 20th column index
7917         // observed on the author's workstation.
7918         char stat_line[160];
7919         n = fread(&stat_line, 1, 159, proc_stat);
7920         stat_line[n] = '\0';
7921         fclose(proc_stat);
7922 
7923         char *saveptr = NULL;
7924         char *field = strtok_r(stat_line, " ", &saveptr);
7925         unsigned int idx;
7926         for (idx = 19; idx && field; --idx) {
7927             field = strtok_r(NULL, " ", &saveptr);
7928         }
7929         if (idx == 0 && field) {  // found the 20th field
7930             num_python_threads = atoi(field);  // 0 on error
7931         }
7932     }
7933 #endif
7934     if (num_python_threads <= 0) {
7935         // Fall back to just the number our threading module knows about.
7936         // An incomplete view of the world, but better than nothing.
7937         PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
7938         if (!threading) {
7939             PyErr_Clear();
7940             return;
7941         }
7942         PyObject *threading_active =
7943                 PyObject_GetAttr(threading, &_Py_ID(_active));
7944         if (!threading_active) {
7945             PyErr_Clear();
7946             Py_DECREF(threading);
7947             return;
7948         }
7949         PyObject *threading_limbo =
7950                 PyObject_GetAttr(threading, &_Py_ID(_limbo));
7951         if (!threading_limbo) {
7952             PyErr_Clear();
7953             Py_DECREF(threading);
7954             Py_DECREF(threading_active);
7955             return;
7956         }
7957         Py_DECREF(threading);
7958         // Duplicating what threading.active_count() does but without holding
7959         // threading._active_limbo_lock so our count could be inaccurate if
7960         // these dicts are mid-update from another thread.  Not a big deal.
7961         // Worst case if someone replaced threading._active or threading._limbo
7962         // with non-dicts, we get -1 from *Length() below and undercount.
7963         // Nobody should, but we're best effort so we clear errors and move on.
7964         num_python_threads = (PyMapping_Length(threading_active)
7965                               + PyMapping_Length(threading_limbo));
7966         PyErr_Clear();
7967         Py_DECREF(threading_active);
7968         Py_DECREF(threading_limbo);
7969     }
7970     if (num_python_threads > 1) {
7971         PyErr_WarnFormat(
7972                 PyExc_DeprecationWarning, 1,
7973 #ifdef HAVE_GETPID
7974                 "This process (pid=%d) is multi-threaded, "
7975 #else
7976                 "This process is multi-threaded, "
7977 #endif
7978                 "use of %s() may lead to deadlocks in the child.",
7979 #ifdef HAVE_GETPID
7980                 getpid(),
7981 #endif
7982                 name);
7983         PyErr_Clear();
7984     }
7985 }
7986 #endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
7987 
7988 #ifdef HAVE_FORK1
7989 /*[clinic input]
7990 os.fork1
7991 
7992 Fork a child process with a single multiplexed (i.e., not bound) thread.
7993 
7994 Return 0 to child process and PID of child to parent process.
7995 [clinic start generated code]*/
7996 
7997 static PyObject *
os_fork1_impl(PyObject * module)7998 os_fork1_impl(PyObject *module)
7999 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8000 {
8001     pid_t pid;
8002 
8003     PyInterpreterState *interp = _PyInterpreterState_GET();
8004     if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8005         PyErr_SetString(PyExc_PythonFinalizationError,
8006                         "can't fork at interpreter shutdown");
8007         return NULL;
8008     }
8009     if (!_Py_IsMainInterpreter(interp)) {
8010         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8011         return NULL;
8012     }
8013     PyOS_BeforeFork();
8014     pid = fork1();
8015     int saved_errno = errno;
8016     if (pid == 0) {
8017         /* child: this clobbers and resets the import lock. */
8018         PyOS_AfterFork_Child();
8019     } else {
8020         /* parent: release the import lock. */
8021         PyOS_AfterFork_Parent();
8022         // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8023         warn_about_fork_with_threads("fork1");
8024     }
8025     if (pid == -1) {
8026         errno = saved_errno;
8027         return posix_error();
8028     }
8029     return PyLong_FromPid(pid);
8030 }
8031 #endif /* HAVE_FORK1 */
8032 
8033 
8034 #ifdef HAVE_FORK
8035 /*[clinic input]
8036 os.fork
8037 
8038 Fork a child process.
8039 
8040 Return 0 to child process and PID of child to parent process.
8041 [clinic start generated code]*/
8042 
8043 static PyObject *
os_fork_impl(PyObject * module)8044 os_fork_impl(PyObject *module)
8045 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8046 {
8047     pid_t pid;
8048     PyInterpreterState *interp = _PyInterpreterState_GET();
8049     if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8050         PyErr_SetString(PyExc_PythonFinalizationError,
8051                         "can't fork at interpreter shutdown");
8052         return NULL;
8053     }
8054     if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8055         PyErr_SetString(PyExc_RuntimeError,
8056                         "fork not supported for isolated subinterpreters");
8057         return NULL;
8058     }
8059     if (PySys_Audit("os.fork", NULL) < 0) {
8060         return NULL;
8061     }
8062     PyOS_BeforeFork();
8063     pid = fork();
8064     int saved_errno = errno;
8065     if (pid == 0) {
8066         /* child: this clobbers and resets the import lock. */
8067         PyOS_AfterFork_Child();
8068     } else {
8069         /* parent: release the import lock. */
8070         PyOS_AfterFork_Parent();
8071         // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8072         warn_about_fork_with_threads("fork");
8073     }
8074     if (pid == -1) {
8075         errno = saved_errno;
8076         return posix_error();
8077     }
8078     return PyLong_FromPid(pid);
8079 }
8080 #endif /* HAVE_FORK */
8081 
8082 
8083 #ifdef HAVE_SCHED_H
8084 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
8085 /*[clinic input]
8086 os.sched_get_priority_max
8087 
8088     policy: int
8089 
8090 Get the maximum scheduling priority for policy.
8091 [clinic start generated code]*/
8092 
8093 static PyObject *
os_sched_get_priority_max_impl(PyObject * module,int policy)8094 os_sched_get_priority_max_impl(PyObject *module, int policy)
8095 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8096 {
8097     int max;
8098 
8099     max = sched_get_priority_max(policy);
8100     if (max < 0)
8101         return posix_error();
8102     return PyLong_FromLong(max);
8103 }
8104 
8105 
8106 /*[clinic input]
8107 os.sched_get_priority_min
8108 
8109     policy: int
8110 
8111 Get the minimum scheduling priority for policy.
8112 [clinic start generated code]*/
8113 
8114 static PyObject *
os_sched_get_priority_min_impl(PyObject * module,int policy)8115 os_sched_get_priority_min_impl(PyObject *module, int policy)
8116 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8117 {
8118     int min = sched_get_priority_min(policy);
8119     if (min < 0)
8120         return posix_error();
8121     return PyLong_FromLong(min);
8122 }
8123 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8124 
8125 
8126 #ifdef HAVE_SCHED_SETSCHEDULER
8127 /*[clinic input]
8128 os.sched_getscheduler
8129     pid: pid_t
8130     /
8131 
8132 Get the scheduling policy for the process identified by pid.
8133 
8134 Passing 0 for pid returns the scheduling policy for the calling process.
8135 [clinic start generated code]*/
8136 
8137 static PyObject *
os_sched_getscheduler_impl(PyObject * module,pid_t pid)8138 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8139 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8140 {
8141     int policy;
8142 
8143     policy = sched_getscheduler(pid);
8144     if (policy < 0)
8145         return posix_error();
8146     return PyLong_FromLong(policy);
8147 }
8148 #endif /* HAVE_SCHED_SETSCHEDULER */
8149 
8150 
8151 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8152 /*[clinic input]
8153 class os.sched_param "PyObject *" "SchedParamType"
8154 
8155 @classmethod
8156 os.sched_param.__new__
8157 
8158     sched_priority: object
8159         A scheduling parameter.
8160 
8161 Currently has only one field: sched_priority
8162 [clinic start generated code]*/
8163 
8164 static PyObject *
os_sched_param_impl(PyTypeObject * type,PyObject * sched_priority)8165 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8166 /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8167 {
8168     PyObject *res;
8169 
8170     res = PyStructSequence_New(type);
8171     if (!res)
8172         return NULL;
8173     PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8174     return res;
8175 }
8176 
8177 static PyObject *
os_sched_param_reduce(PyObject * self,PyObject * Py_UNUSED (ignored))8178 os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
8179 {
8180     return Py_BuildValue("(O(N))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8181 }
8182 
8183 static PyMethodDef os_sched_param_reduce_method = {
8184     "__reduce__", (PyCFunction)os_sched_param_reduce, METH_NOARGS|METH_COEXIST, NULL,
8185 };
8186 
8187 PyDoc_VAR(os_sched_param__doc__);
8188 
8189 static PyStructSequence_Field sched_param_fields[] = {
8190     {"sched_priority", "the scheduling priority"},
8191     {0}
8192 };
8193 
8194 static PyStructSequence_Desc sched_param_desc = {
8195     "sched_param", /* name */
8196     os_sched_param__doc__, /* doc */
8197     sched_param_fields,
8198     1
8199 };
8200 
8201 static int
convert_sched_param(PyObject * module,PyObject * param,struct sched_param * res)8202 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8203 {
8204     long priority;
8205 
8206     if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8207         PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8208         return 0;
8209     }
8210     priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8211     if (priority == -1 && PyErr_Occurred())
8212         return 0;
8213     if (priority > INT_MAX || priority < INT_MIN) {
8214         PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8215         return 0;
8216     }
8217     res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8218     return 1;
8219 }
8220 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8221 
8222 
8223 #ifdef HAVE_SCHED_SETSCHEDULER
8224 /*[clinic input]
8225 os.sched_setscheduler
8226 
8227     pid: pid_t
8228     policy: int
8229     param as param_obj: object
8230     /
8231 
8232 Set the scheduling policy for the process identified by pid.
8233 
8234 If pid is 0, the calling process is changed.
8235 param is an instance of sched_param.
8236 [clinic start generated code]*/
8237 
8238 static PyObject *
os_sched_setscheduler_impl(PyObject * module,pid_t pid,int policy,PyObject * param_obj)8239 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8240                            PyObject *param_obj)
8241 /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8242 {
8243     struct sched_param param;
8244     if (!convert_sched_param(module, param_obj, &param)) {
8245         return NULL;
8246     }
8247 
8248     /*
8249     ** sched_setscheduler() returns 0 in Linux, but the previous
8250     ** scheduling policy under Solaris/Illumos, and others.
8251     ** On error, -1 is returned in all Operating Systems.
8252     */
8253     if (sched_setscheduler(pid, policy, &param) == -1)
8254         return posix_error();
8255     Py_RETURN_NONE;
8256 }
8257 #endif  /* HAVE_SCHED_SETSCHEDULER*/
8258 
8259 
8260 #ifdef HAVE_SCHED_SETPARAM
8261 /*[clinic input]
8262 os.sched_getparam
8263     pid: pid_t
8264     /
8265 
8266 Returns scheduling parameters for the process identified by pid.
8267 
8268 If pid is 0, returns parameters for the calling process.
8269 Return value is an instance of sched_param.
8270 [clinic start generated code]*/
8271 
8272 static PyObject *
os_sched_getparam_impl(PyObject * module,pid_t pid)8273 os_sched_getparam_impl(PyObject *module, pid_t pid)
8274 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8275 {
8276     struct sched_param param;
8277     PyObject *result;
8278     PyObject *priority;
8279 
8280     if (sched_getparam(pid, &param))
8281         return posix_error();
8282     PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8283     result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8284     if (!result)
8285         return NULL;
8286     priority = PyLong_FromLong(param.sched_priority);
8287     if (!priority) {
8288         Py_DECREF(result);
8289         return NULL;
8290     }
8291     PyStructSequence_SET_ITEM(result, 0, priority);
8292     return result;
8293 }
8294 
8295 
8296 /*[clinic input]
8297 os.sched_setparam
8298     pid: pid_t
8299     param as param_obj: object
8300     /
8301 
8302 Set scheduling parameters for the process identified by pid.
8303 
8304 If pid is 0, sets parameters for the calling process.
8305 param should be an instance of sched_param.
8306 [clinic start generated code]*/
8307 
8308 static PyObject *
os_sched_setparam_impl(PyObject * module,pid_t pid,PyObject * param_obj)8309 os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8310 /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8311 {
8312     struct sched_param param;
8313     if (!convert_sched_param(module, param_obj, &param)) {
8314         return NULL;
8315     }
8316 
8317     if (sched_setparam(pid, &param))
8318         return posix_error();
8319     Py_RETURN_NONE;
8320 }
8321 #endif /* HAVE_SCHED_SETPARAM */
8322 
8323 
8324 #ifdef HAVE_SCHED_RR_GET_INTERVAL
8325 /*[clinic input]
8326 os.sched_rr_get_interval -> double
8327     pid: pid_t
8328     /
8329 
8330 Return the round-robin quantum for the process identified by pid, in seconds.
8331 
8332 Value returned is a float.
8333 [clinic start generated code]*/
8334 
8335 static double
os_sched_rr_get_interval_impl(PyObject * module,pid_t pid)8336 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8337 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
8338 {
8339     struct timespec interval;
8340     if (sched_rr_get_interval(pid, &interval)) {
8341         posix_error();
8342         return -1.0;
8343     }
8344 #ifdef _Py_MEMORY_SANITIZER
8345     __msan_unpoison(&interval, sizeof(interval));
8346 #endif
8347     return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8348 }
8349 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
8350 
8351 
8352 /*[clinic input]
8353 os.sched_yield
8354 
8355 Voluntarily relinquish the CPU.
8356 [clinic start generated code]*/
8357 
8358 static PyObject *
os_sched_yield_impl(PyObject * module)8359 os_sched_yield_impl(PyObject *module)
8360 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8361 {
8362     int result;
8363     Py_BEGIN_ALLOW_THREADS
8364     result = sched_yield();
8365     Py_END_ALLOW_THREADS
8366     if (result < 0) {
8367         return posix_error();
8368     }
8369     Py_RETURN_NONE;
8370 }
8371 
8372 #ifdef HAVE_SCHED_SETAFFINITY
8373 /* The minimum number of CPUs allocated in a cpu_set_t */
8374 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
8375 
8376 /*[clinic input]
8377 os.sched_setaffinity
8378     pid: pid_t
8379     mask : object
8380     /
8381 
8382 Set the CPU affinity of the process identified by pid to mask.
8383 
8384 mask should be an iterable of integers identifying CPUs.
8385 [clinic start generated code]*/
8386 
8387 static PyObject *
os_sched_setaffinity_impl(PyObject * module,pid_t pid,PyObject * mask)8388 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
8389 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
8390 {
8391     int ncpus;
8392     size_t setsize;
8393     cpu_set_t *cpu_set = NULL;
8394     PyObject *iterator = NULL, *item;
8395 
8396     iterator = PyObject_GetIter(mask);
8397     if (iterator == NULL)
8398         return NULL;
8399 
8400     ncpus = NCPUS_START;
8401     setsize = CPU_ALLOC_SIZE(ncpus);
8402     cpu_set = CPU_ALLOC(ncpus);
8403     if (cpu_set == NULL) {
8404         PyErr_NoMemory();
8405         goto error;
8406     }
8407     CPU_ZERO_S(setsize, cpu_set);
8408 
8409     while ((item = PyIter_Next(iterator))) {
8410         long cpu;
8411         if (!PyLong_Check(item)) {
8412             PyErr_Format(PyExc_TypeError,
8413                         "expected an iterator of ints, "
8414                         "but iterator yielded %R",
8415                         Py_TYPE(item));
8416             Py_DECREF(item);
8417             goto error;
8418         }
8419         cpu = PyLong_AsLong(item);
8420         Py_DECREF(item);
8421         if (cpu < 0) {
8422             if (!PyErr_Occurred())
8423                 PyErr_SetString(PyExc_ValueError, "negative CPU number");
8424             goto error;
8425         }
8426         if (cpu > INT_MAX - 1) {
8427             PyErr_SetString(PyExc_OverflowError, "CPU number too large");
8428             goto error;
8429         }
8430         if (cpu >= ncpus) {
8431             /* Grow CPU mask to fit the CPU number */
8432             int newncpus = ncpus;
8433             cpu_set_t *newmask;
8434             size_t newsetsize;
8435             while (newncpus <= cpu) {
8436                 if (newncpus > INT_MAX / 2)
8437                     newncpus = cpu + 1;
8438                 else
8439                     newncpus = newncpus * 2;
8440             }
8441             newmask = CPU_ALLOC(newncpus);
8442             if (newmask == NULL) {
8443                 PyErr_NoMemory();
8444                 goto error;
8445             }
8446             newsetsize = CPU_ALLOC_SIZE(newncpus);
8447             CPU_ZERO_S(newsetsize, newmask);
8448             memcpy(newmask, cpu_set, setsize);
8449             CPU_FREE(cpu_set);
8450             setsize = newsetsize;
8451             cpu_set = newmask;
8452             ncpus = newncpus;
8453         }
8454         CPU_SET_S(cpu, setsize, cpu_set);
8455     }
8456     if (PyErr_Occurred()) {
8457         goto error;
8458     }
8459     Py_CLEAR(iterator);
8460 
8461     if (sched_setaffinity(pid, setsize, cpu_set)) {
8462         posix_error();
8463         goto error;
8464     }
8465     CPU_FREE(cpu_set);
8466     Py_RETURN_NONE;
8467 
8468 error:
8469     if (cpu_set)
8470         CPU_FREE(cpu_set);
8471     Py_XDECREF(iterator);
8472     return NULL;
8473 }
8474 
8475 
8476 /*[clinic input]
8477 os.sched_getaffinity
8478     pid: pid_t
8479     /
8480 
8481 Return the affinity of the process identified by pid (or the current process if zero).
8482 
8483 The affinity is returned as a set of CPU identifiers.
8484 [clinic start generated code]*/
8485 
8486 static PyObject *
os_sched_getaffinity_impl(PyObject * module,pid_t pid)8487 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
8488 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
8489 {
8490     int ncpus = NCPUS_START;
8491     size_t setsize;
8492     cpu_set_t *mask;
8493 
8494     while (1) {
8495         setsize = CPU_ALLOC_SIZE(ncpus);
8496         mask = CPU_ALLOC(ncpus);
8497         if (mask == NULL) {
8498             return PyErr_NoMemory();
8499         }
8500         if (sched_getaffinity(pid, setsize, mask) == 0) {
8501             break;
8502         }
8503         CPU_FREE(mask);
8504         if (errno != EINVAL) {
8505             return posix_error();
8506         }
8507         if (ncpus > INT_MAX / 2) {
8508             PyErr_SetString(PyExc_OverflowError,
8509                             "could not allocate a large enough CPU set");
8510             return NULL;
8511         }
8512         ncpus *= 2;
8513     }
8514 
8515     PyObject *res = PySet_New(NULL);
8516     if (res == NULL) {
8517         goto error;
8518     }
8519 
8520     int cpu = 0;
8521     int count = CPU_COUNT_S(setsize, mask);
8522     for (; count; cpu++) {
8523         if (CPU_ISSET_S(cpu, setsize, mask)) {
8524             PyObject *cpu_num = PyLong_FromLong(cpu);
8525             --count;
8526             if (cpu_num == NULL) {
8527                 goto error;
8528             }
8529             if (PySet_Add(res, cpu_num)) {
8530                 Py_DECREF(cpu_num);
8531                 goto error;
8532             }
8533             Py_DECREF(cpu_num);
8534         }
8535     }
8536     CPU_FREE(mask);
8537     return res;
8538 
8539 error:
8540     if (mask) {
8541         CPU_FREE(mask);
8542     }
8543     Py_XDECREF(res);
8544     return NULL;
8545 }
8546 #endif /* HAVE_SCHED_SETAFFINITY */
8547 
8548 #endif /* HAVE_SCHED_H */
8549 
8550 
8551 #ifdef HAVE_POSIX_OPENPT
8552 /*[clinic input]
8553 os.posix_openpt -> int
8554 
8555     oflag: int
8556     /
8557 
8558 Open and return a file descriptor for a master pseudo-terminal device.
8559 
8560 Performs a posix_openpt() C function call. The oflag argument is used to
8561 set file status flags and file access modes as specified in the manual page
8562 of posix_openpt() of your system.
8563 [clinic start generated code]*/
8564 
8565 static int
os_posix_openpt_impl(PyObject * module,int oflag)8566 os_posix_openpt_impl(PyObject *module, int oflag)
8567 /*[clinic end generated code: output=ee0bc2624305fc79 input=0de33d0e29693caa]*/
8568 {
8569     int fd;
8570 
8571 #if defined(O_CLOEXEC)
8572     oflag |= O_CLOEXEC;
8573 #endif
8574 
8575     fd = posix_openpt(oflag);
8576     if (fd == -1) {
8577         posix_error();
8578         return -1;
8579     }
8580 
8581     // Just in case, likely a no-op given O_CLOEXEC above.
8582     if (_Py_set_inheritable(fd, 0, NULL) < 0) {
8583         close(fd);
8584         return -1;
8585     }
8586 
8587     return fd;
8588 }
8589 #endif /* HAVE_POSIX_OPENPT */
8590 
8591 #ifdef HAVE_GRANTPT
8592 /*[clinic input]
8593 os.grantpt
8594 
8595     fd: fildes
8596         File descriptor of a master pseudo-terminal device.
8597     /
8598 
8599 Grant access to the slave pseudo-terminal device.
8600 
8601 Performs a grantpt() C function call.
8602 [clinic start generated code]*/
8603 
8604 static PyObject *
os_grantpt_impl(PyObject * module,int fd)8605 os_grantpt_impl(PyObject *module, int fd)
8606 /*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
8607 {
8608     int ret;
8609     int saved_errno;
8610     PyOS_sighandler_t sig_saved;
8611 
8612     sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
8613 
8614     ret = grantpt(fd);
8615     if (ret == -1)
8616         saved_errno = errno;
8617 
8618     PyOS_setsig(SIGCHLD, sig_saved);
8619 
8620     if (ret == -1) {
8621         errno = saved_errno;
8622         return posix_error();
8623     }
8624 
8625     Py_RETURN_NONE;
8626 }
8627 #endif /* HAVE_GRANTPT */
8628 
8629 #ifdef HAVE_UNLOCKPT
8630 /*[clinic input]
8631 os.unlockpt
8632 
8633     fd: fildes
8634         File descriptor of a master pseudo-terminal device.
8635     /
8636 
8637 Unlock a pseudo-terminal master/slave pair.
8638 
8639 Performs an unlockpt() C function call.
8640 [clinic start generated code]*/
8641 
8642 static PyObject *
os_unlockpt_impl(PyObject * module,int fd)8643 os_unlockpt_impl(PyObject *module, int fd)
8644 /*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
8645 {
8646     if (unlockpt(fd) == -1)
8647         return posix_error();
8648 
8649     Py_RETURN_NONE;
8650 }
8651 #endif /* HAVE_UNLOCKPT */
8652 
8653 #if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
8654 static PyObject *
py_ptsname(int fd)8655 py_ptsname(int fd)
8656 {
8657     // POSIX manpage: Upon failure, ptsname() shall return a null pointer
8658     // and may set errno. Always initialize errno to avoid undefined behavior.
8659     errno = 0;
8660     char *name = ptsname(fd);
8661     if (name == NULL) {
8662         return posix_error();
8663     }
8664     return PyUnicode_DecodeFSDefault(name);
8665 }
8666 
8667 /*[clinic input]
8668 os.ptsname
8669 
8670     fd: fildes
8671         File descriptor of a master pseudo-terminal device.
8672     /
8673 
8674 Return the name of the slave pseudo-terminal device.
8675 
8676 If the ptsname_r() C function is available, it is called;
8677 otherwise, performs a ptsname() C function call.
8678 [clinic start generated code]*/
8679 
8680 static PyObject *
os_ptsname_impl(PyObject * module,int fd)8681 os_ptsname_impl(PyObject *module, int fd)
8682 /*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
8683 {
8684 #ifdef HAVE_PTSNAME_R
8685     int ret;
8686     char name[MAXPATHLEN+1];
8687 
8688     if (HAVE_PTSNAME_R_RUNTIME) {
8689         ret = ptsname_r(fd, name, sizeof(name));
8690     }
8691     else {
8692         // fallback to ptsname() if ptsname_r() is not available in runtime.
8693         return py_ptsname(fd);
8694     }
8695     if (ret != 0) {
8696         errno = ret;
8697         return posix_error();
8698     }
8699 
8700     return PyUnicode_DecodeFSDefault(name);
8701 #else
8702     return py_ptsname(fd);
8703 #endif /* HAVE_PTSNAME_R */
8704 }
8705 #endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
8706 
8707 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
8708 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
8709 #  define DEV_PTY_FILE "/dev/ptc"
8710 #  define HAVE_DEV_PTMX
8711 #else
8712 #  define DEV_PTY_FILE "/dev/ptmx"
8713 #endif
8714 
8715 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
8716 #ifdef HAVE_PTY_H
8717 #include <pty.h>
8718 #ifdef HAVE_UTMP_H
8719 #include <utmp.h>
8720 #endif /* HAVE_UTMP_H */
8721 #elif defined(HAVE_LIBUTIL_H)
8722 #include <libutil.h>
8723 #elif defined(HAVE_UTIL_H)
8724 #include <util.h>
8725 #endif /* HAVE_PTY_H */
8726 #ifdef HAVE_STROPTS_H
8727 #include <stropts.h>
8728 #endif
8729 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
8730 
8731 
8732 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
8733 /*[clinic input]
8734 os.openpty
8735 
8736 Open a pseudo-terminal.
8737 
8738 Return a tuple of (master_fd, slave_fd) containing open file descriptors
8739 for both the master and slave ends.
8740 [clinic start generated code]*/
8741 
8742 static PyObject *
os_openpty_impl(PyObject * module)8743 os_openpty_impl(PyObject *module)
8744 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
8745 {
8746     int master_fd = -1, slave_fd = -1;
8747 #ifndef HAVE_OPENPTY
8748     char * slave_name;
8749 #endif
8750 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
8751     PyOS_sighandler_t sig_saved;
8752 #if defined(__sun) && defined(__SVR4)
8753     extern char *ptsname(int fildes);
8754 #endif
8755 #endif
8756 
8757 #ifdef HAVE_OPENPTY
8758     if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
8759         goto posix_error;
8760 
8761     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
8762         goto error;
8763     if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
8764         goto error;
8765 
8766 #elif defined(HAVE__GETPTY)
8767     slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
8768     if (slave_name == NULL)
8769         goto posix_error;
8770     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
8771         goto error;
8772 
8773     slave_fd = _Py_open(slave_name, O_RDWR);
8774     if (slave_fd < 0)
8775         goto error;
8776 
8777 #else
8778     master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
8779     if (master_fd < 0)
8780         goto posix_error;
8781 
8782     sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
8783 
8784     /* change permission of slave */
8785     if (grantpt(master_fd) < 0) {
8786         int saved_errno = errno;
8787         PyOS_setsig(SIGCHLD, sig_saved);
8788         errno = saved_errno;
8789         goto posix_error;
8790     }
8791 
8792     /* unlock slave */
8793     if (unlockpt(master_fd) < 0) {
8794         int saved_errno = errno;
8795         PyOS_setsig(SIGCHLD, sig_saved);
8796         errno = saved_errno;
8797         goto posix_error;
8798     }
8799 
8800     PyOS_setsig(SIGCHLD, sig_saved);
8801 
8802     slave_name = ptsname(master_fd); /* get name of slave */
8803     if (slave_name == NULL)
8804         goto posix_error;
8805 
8806     slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
8807     if (slave_fd == -1)
8808         goto error;
8809 
8810     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
8811         goto posix_error;
8812 
8813 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
8814     ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
8815     ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
8816 #ifndef __hpux
8817     ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
8818 #endif /* __hpux */
8819 #endif /* HAVE_CYGWIN */
8820 #endif /* HAVE_OPENPTY */
8821 
8822     return Py_BuildValue("(ii)", master_fd, slave_fd);
8823 
8824 posix_error:
8825     posix_error();
8826 error:
8827     if (master_fd != -1)
8828         close(master_fd);
8829     if (slave_fd != -1)
8830         close(slave_fd);
8831     return NULL;
8832 }
8833 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
8834 
8835 
8836 #if defined(HAVE_SETSID) && defined(TIOCSCTTY)
8837 #define HAVE_FALLBACK_LOGIN_TTY 1
8838 #endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
8839 
8840 #if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
8841 /*[clinic input]
8842 os.login_tty
8843 
8844     fd: fildes
8845     /
8846 
8847 Prepare the tty of which fd is a file descriptor for a new login session.
8848 
8849 Make the calling process a session leader; make the tty the
8850 controlling tty, the stdin, the stdout, and the stderr of the
8851 calling process; close fd.
8852 [clinic start generated code]*/
8853 
8854 static PyObject *
os_login_tty_impl(PyObject * module,int fd)8855 os_login_tty_impl(PyObject *module, int fd)
8856 /*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
8857 {
8858 #ifdef HAVE_LOGIN_TTY
8859     if (login_tty(fd) == -1) {
8860         return posix_error();
8861     }
8862 #else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
8863     /* Establish a new session. */
8864     if (setsid() == -1) {
8865         return posix_error();
8866     }
8867 
8868     /* The tty becomes the controlling terminal. */
8869     if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
8870         return posix_error();
8871     }
8872 
8873     /* The tty becomes stdin/stdout/stderr */
8874     if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
8875         return posix_error();
8876     }
8877     if (fd > 2) {
8878         close(fd);
8879     }
8880 #endif /* HAVE_LOGIN_TTY */
8881     Py_RETURN_NONE;
8882 }
8883 #endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
8884 
8885 
8886 #ifdef HAVE_FORKPTY
8887 /*[clinic input]
8888 os.forkpty
8889 
8890 Fork a new process with a new pseudo-terminal as controlling tty.
8891 
8892 Returns a tuple of (pid, master_fd).
8893 Like fork(), return pid of 0 to the child process,
8894 and pid of child to the parent process.
8895 To both, return fd of newly opened pseudo-terminal.
8896 [clinic start generated code]*/
8897 
8898 static PyObject *
os_forkpty_impl(PyObject * module)8899 os_forkpty_impl(PyObject *module)
8900 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
8901 {
8902     int master_fd = -1;
8903     pid_t pid;
8904 
8905     PyInterpreterState *interp = _PyInterpreterState_GET();
8906     if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8907         PyErr_SetString(PyExc_PythonFinalizationError,
8908                         "can't fork at interpreter shutdown");
8909         return NULL;
8910     }
8911     if (!_Py_IsMainInterpreter(interp)) {
8912         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8913         return NULL;
8914     }
8915     if (PySys_Audit("os.forkpty", NULL) < 0) {
8916         return NULL;
8917     }
8918     PyOS_BeforeFork();
8919     pid = forkpty(&master_fd, NULL, NULL, NULL);
8920     if (pid == 0) {
8921         /* child: this clobbers and resets the import lock. */
8922         PyOS_AfterFork_Child();
8923     } else {
8924         /* parent: release the import lock. */
8925         PyOS_AfterFork_Parent();
8926         // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8927         warn_about_fork_with_threads("forkpty");
8928     }
8929     if (pid == -1) {
8930         return posix_error();
8931     }
8932     return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
8933 }
8934 #endif /* HAVE_FORKPTY */
8935 
8936 
8937 #ifdef HAVE_GETEGID
8938 /*[clinic input]
8939 os.getegid
8940 
8941 Return the current process's effective group id.
8942 [clinic start generated code]*/
8943 
8944 static PyObject *
os_getegid_impl(PyObject * module)8945 os_getegid_impl(PyObject *module)
8946 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
8947 {
8948     return _PyLong_FromGid(getegid());
8949 }
8950 #endif /* HAVE_GETEGID */
8951 
8952 
8953 #ifdef HAVE_GETEUID
8954 /*[clinic input]
8955 os.geteuid
8956 
8957 Return the current process's effective user id.
8958 [clinic start generated code]*/
8959 
8960 static PyObject *
os_geteuid_impl(PyObject * module)8961 os_geteuid_impl(PyObject *module)
8962 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
8963 {
8964     return _PyLong_FromUid(geteuid());
8965 }
8966 #endif /* HAVE_GETEUID */
8967 
8968 
8969 #ifdef HAVE_GETGID
8970 /*[clinic input]
8971 os.getgid
8972 
8973 Return the current process's group id.
8974 [clinic start generated code]*/
8975 
8976 static PyObject *
os_getgid_impl(PyObject * module)8977 os_getgid_impl(PyObject *module)
8978 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
8979 {
8980     return _PyLong_FromGid(getgid());
8981 }
8982 #endif /* HAVE_GETGID */
8983 
8984 
8985 #if defined(HAVE_GETPID)
8986 /*[clinic input]
8987 os.getpid
8988 
8989 Return the current process id.
8990 [clinic start generated code]*/
8991 
8992 static PyObject *
os_getpid_impl(PyObject * module)8993 os_getpid_impl(PyObject *module)
8994 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
8995 {
8996 #if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
8997     return PyLong_FromPid(getpid());
8998 #else
8999     return PyLong_FromUnsignedLong(GetCurrentProcessId());
9000 #endif
9001 }
9002 #endif /* defined(HAVE_GETPID) */
9003 
9004 #ifdef NGROUPS_MAX
9005 #define MAX_GROUPS NGROUPS_MAX
9006 #else
9007     /* defined to be 16 on Solaris7, so this should be a small number */
9008 #define MAX_GROUPS 64
9009 #endif
9010 
9011 #ifdef HAVE_GETGROUPLIST
9012 
9013 #ifdef __APPLE__
9014 /*[clinic input]
9015 os.getgrouplist
9016 
9017     user: str
9018         username to lookup
9019     group as basegid: int
9020         base group id of the user
9021     /
9022 
9023 Returns a list of groups to which a user belongs.
9024 [clinic start generated code]*/
9025 
9026 static PyObject *
os_getgrouplist_impl(PyObject * module,const char * user,int basegid)9027 os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9028 /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9029 #else
9030 /*[clinic input]
9031 os.getgrouplist
9032 
9033     user: str
9034         username to lookup
9035     group as basegid: gid_t
9036         base group id of the user
9037     /
9038 
9039 Returns a list of groups to which a user belongs.
9040 [clinic start generated code]*/
9041 
9042 static PyObject *
9043 os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
9044 /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9045 #endif
9046 {
9047     int i, ngroups;
9048     PyObject *list;
9049 #ifdef __APPLE__
9050     int *groups;
9051 #else
9052     gid_t *groups;
9053 #endif
9054 
9055     /*
9056      * NGROUPS_MAX is defined by POSIX.1 as the maximum
9057      * number of supplimental groups a users can belong to.
9058      * We have to increment it by one because
9059      * getgrouplist() returns both the supplemental groups
9060      * and the primary group, i.e. all of the groups the
9061      * user belongs to.
9062      */
9063     ngroups = 1 + MAX_GROUPS;
9064 
9065     while (1) {
9066 #ifdef __APPLE__
9067         groups = PyMem_New(int, ngroups);
9068 #else
9069         groups = PyMem_New(gid_t, ngroups);
9070 #endif
9071         if (groups == NULL) {
9072             return PyErr_NoMemory();
9073         }
9074 
9075         int old_ngroups = ngroups;
9076         if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9077             /* Success */
9078             break;
9079         }
9080 
9081         /* getgrouplist() fails if the group list is too small */
9082         PyMem_Free(groups);
9083 
9084         if (ngroups > old_ngroups) {
9085             /* If the group list is too small, the glibc implementation of
9086                getgrouplist() sets ngroups to the total number of groups and
9087                returns -1. */
9088         }
9089         else {
9090             /* Double the group list size */
9091             if (ngroups > INT_MAX / 2) {
9092                 return PyErr_NoMemory();
9093             }
9094             ngroups *= 2;
9095         }
9096 
9097         /* Retry getgrouplist() with a larger group list */
9098     }
9099 
9100 #ifdef _Py_MEMORY_SANITIZER
9101     /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9102     __msan_unpoison(&ngroups, sizeof(ngroups));
9103     __msan_unpoison(groups, ngroups*sizeof(*groups));
9104 #endif
9105 
9106     list = PyList_New(ngroups);
9107     if (list == NULL) {
9108         PyMem_Free(groups);
9109         return NULL;
9110     }
9111 
9112     for (i = 0; i < ngroups; i++) {
9113 #ifdef __APPLE__
9114         PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9115 #else
9116         PyObject *o = _PyLong_FromGid(groups[i]);
9117 #endif
9118         if (o == NULL) {
9119             Py_DECREF(list);
9120             PyMem_Free(groups);
9121             return NULL;
9122         }
9123         PyList_SET_ITEM(list, i, o);
9124     }
9125 
9126     PyMem_Free(groups);
9127 
9128     return list;
9129 }
9130 #endif /* HAVE_GETGROUPLIST */
9131 
9132 
9133 #ifdef HAVE_GETGROUPS
9134 /*[clinic input]
9135 os.getgroups
9136 
9137 Return list of supplemental group IDs for the process.
9138 [clinic start generated code]*/
9139 
9140 static PyObject *
os_getgroups_impl(PyObject * module)9141 os_getgroups_impl(PyObject *module)
9142 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9143 {
9144     // Call getgroups with length 0 to get the actual number of groups
9145     int n = getgroups(0, NULL);
9146     if (n < 0) {
9147         return posix_error();
9148     }
9149 
9150     if (n == 0) {
9151         return PyList_New(0);
9152     }
9153 
9154     gid_t *grouplist = PyMem_New(gid_t, n);
9155     if (grouplist == NULL) {
9156         return PyErr_NoMemory();
9157     }
9158 
9159     n = getgroups(n, grouplist);
9160     if (n == -1) {
9161         posix_error();
9162         PyMem_Free(grouplist);
9163         return NULL;
9164     }
9165 
9166     PyObject *result = PyList_New(n);
9167     if (result == NULL) {
9168         goto error;
9169     }
9170 
9171     for (int i = 0; i < n; ++i) {
9172         PyObject *group = _PyLong_FromGid(grouplist[i]);
9173         if (group == NULL) {
9174             goto error;
9175         }
9176         PyList_SET_ITEM(result, i, group);
9177     }
9178     PyMem_Free(grouplist);
9179 
9180     return result;
9181 
9182 error:
9183     PyMem_Free(grouplist);
9184     Py_XDECREF(result);
9185     return NULL;
9186 }
9187 #endif /* HAVE_GETGROUPS */
9188 
9189 #ifdef HAVE_INITGROUPS
9190 #ifdef __APPLE__
9191 /*[clinic input]
9192 os.initgroups
9193 
9194     username as oname: FSConverter
9195     gid: int
9196     /
9197 
9198 Initialize the group access list.
9199 
9200 Call the system initgroups() to initialize the group access list with all of
9201 the groups of which the specified username is a member, plus the specified
9202 group id.
9203 [clinic start generated code]*/
9204 
9205 static PyObject *
os_initgroups_impl(PyObject * module,PyObject * oname,int gid)9206 os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9207 /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
9208 #else
9209 /*[clinic input]
9210 os.initgroups
9211 
9212     username as oname: FSConverter
9213     gid: gid_t
9214     /
9215 
9216 Initialize the group access list.
9217 
9218 Call the system initgroups() to initialize the group access list with all of
9219 the groups of which the specified username is a member, plus the specified
9220 group id.
9221 [clinic start generated code]*/
9222 
9223 static PyObject *
9224 os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
9225 /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
9226 #endif
9227 {
9228     const char *username = PyBytes_AS_STRING(oname);
9229 
9230     if (initgroups(username, gid) == -1)
9231         return PyErr_SetFromErrno(PyExc_OSError);
9232 
9233     Py_RETURN_NONE;
9234 }
9235 #endif /* HAVE_INITGROUPS */
9236 
9237 
9238 #ifdef HAVE_GETPGID
9239 /*[clinic input]
9240 os.getpgid
9241 
9242     pid: pid_t
9243 
9244 Call the system call getpgid(), and return the result.
9245 [clinic start generated code]*/
9246 
9247 static PyObject *
os_getpgid_impl(PyObject * module,pid_t pid)9248 os_getpgid_impl(PyObject *module, pid_t pid)
9249 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9250 {
9251     pid_t pgid = getpgid(pid);
9252     if (pgid < 0)
9253         return posix_error();
9254     return PyLong_FromPid(pgid);
9255 }
9256 #endif /* HAVE_GETPGID */
9257 
9258 
9259 #ifdef HAVE_GETPGRP
9260 /*[clinic input]
9261 os.getpgrp
9262 
9263 Return the current process group id.
9264 [clinic start generated code]*/
9265 
9266 static PyObject *
os_getpgrp_impl(PyObject * module)9267 os_getpgrp_impl(PyObject *module)
9268 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9269 {
9270 #ifdef GETPGRP_HAVE_ARG
9271     return PyLong_FromPid(getpgrp(0));
9272 #else /* GETPGRP_HAVE_ARG */
9273     return PyLong_FromPid(getpgrp());
9274 #endif /* GETPGRP_HAVE_ARG */
9275 }
9276 #endif /* HAVE_GETPGRP */
9277 
9278 
9279 #ifdef HAVE_SETPGRP
9280 /*[clinic input]
9281 os.setpgrp
9282 
9283 Make the current process the leader of its process group.
9284 [clinic start generated code]*/
9285 
9286 static PyObject *
os_setpgrp_impl(PyObject * module)9287 os_setpgrp_impl(PyObject *module)
9288 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9289 {
9290 #ifdef SETPGRP_HAVE_ARG
9291     if (setpgrp(0, 0) < 0)
9292 #else /* SETPGRP_HAVE_ARG */
9293     if (setpgrp() < 0)
9294 #endif /* SETPGRP_HAVE_ARG */
9295         return posix_error();
9296     Py_RETURN_NONE;
9297 }
9298 #endif /* HAVE_SETPGRP */
9299 
9300 #ifdef HAVE_GETPPID
9301 
9302 #ifdef MS_WINDOWS
9303 #include <winternl.h>
9304 #include <ProcessSnapshot.h>
9305 
9306 // The structure definition in winternl.h may be incomplete.
9307 // This structure is the full version from the MSDN documentation.
9308 typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9309     NTSTATUS ExitStatus;
9310     PVOID PebBaseAddress;
9311     ULONG_PTR AffinityMask;
9312     LONG BasePriority;
9313     ULONG_PTR UniqueProcessId;
9314     ULONG_PTR InheritedFromUniqueProcessId;
9315 } PROCESS_BASIC_INFORMATION_FULL;
9316 
9317 typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9318     IN    HANDLE           ProcessHandle,
9319     IN    PROCESSINFOCLASS ProcessInformationClass,
9320     OUT   PVOID            ProcessInformation,
9321     IN    ULONG            ProcessInformationLength,
9322     OUT   PULONG           ReturnLength OPTIONAL);
9323 
9324 // This function returns the process ID of the parent process.
9325 // Returns 0 on failure.
9326 static ULONG
win32_getppid_fast(void)9327 win32_getppid_fast(void)
9328 {
9329     NTSTATUS status;
9330     HMODULE ntdll;
9331     PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
9332     PROCESS_BASIC_INFORMATION_FULL basic_information;
9333     static ULONG cached_ppid = 0;
9334 
9335     if (cached_ppid) {
9336         // No need to query the kernel again.
9337         return cached_ppid;
9338     }
9339 
9340     ntdll = GetModuleHandleW(L"ntdll.dll");
9341     if (!ntdll) {
9342         return 0;
9343     }
9344 
9345     pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
9346     if (!pNtQueryInformationProcess) {
9347         return 0;
9348     }
9349 
9350     status = pNtQueryInformationProcess(GetCurrentProcess(),
9351                                         ProcessBasicInformation,
9352                                         &basic_information,
9353                                         sizeof(basic_information),
9354                                         NULL);
9355 
9356     if (!NT_SUCCESS(status)) {
9357         return 0;
9358     }
9359 
9360     // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
9361     // The check covers values which exceed the 32-bit range (if running on x64) as well as
9362     // zero and (ULONG) -1.
9363 
9364     if (basic_information.InheritedFromUniqueProcessId == 0 ||
9365         basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
9366     {
9367         return 0;
9368     }
9369 
9370     // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
9371     // structure member contains a ULONG_PTR which represents the process ID of our parent
9372     // process. This process ID will be correctly returned even if the parent process has
9373     // exited or been terminated.
9374 
9375     cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
9376     return cached_ppid;
9377 }
9378 
9379 static PyObject*
win32_getppid(void)9380 win32_getppid(void)
9381 {
9382     DWORD error;
9383     PyObject* result = NULL;
9384     HANDLE process = GetCurrentProcess();
9385     HPSS snapshot = NULL;
9386     ULONG pid;
9387 
9388     pid = win32_getppid_fast();
9389     if (pid != 0) {
9390         return PyLong_FromUnsignedLong(pid);
9391     }
9392 
9393     // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
9394 
9395     error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
9396     if (error != ERROR_SUCCESS) {
9397         return PyErr_SetFromWindowsErr(error);
9398     }
9399 
9400     PSS_PROCESS_INFORMATION info;
9401     error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
9402                              sizeof(info));
9403     if (error == ERROR_SUCCESS) {
9404         result = PyLong_FromUnsignedLong(info.ParentProcessId);
9405     }
9406     else {
9407         result = PyErr_SetFromWindowsErr(error);
9408     }
9409 
9410     PssFreeSnapshot(process, snapshot);
9411     return result;
9412 }
9413 #endif /*MS_WINDOWS*/
9414 
9415 
9416 /*[clinic input]
9417 os.getppid
9418 
9419 Return the parent's process id.
9420 
9421 If the parent process has already exited, Windows machines will still
9422 return its id; others systems will return the id of the 'init' process (1).
9423 [clinic start generated code]*/
9424 
9425 static PyObject *
os_getppid_impl(PyObject * module)9426 os_getppid_impl(PyObject *module)
9427 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
9428 {
9429 #ifdef MS_WINDOWS
9430     return win32_getppid();
9431 #else
9432     return PyLong_FromPid(getppid());
9433 #endif
9434 }
9435 #endif /* HAVE_GETPPID */
9436 
9437 
9438 #ifdef HAVE_GETLOGIN
9439 /*[clinic input]
9440 os.getlogin
9441 
9442 Return the actual login name.
9443 [clinic start generated code]*/
9444 
9445 static PyObject *
os_getlogin_impl(PyObject * module)9446 os_getlogin_impl(PyObject *module)
9447 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
9448 {
9449     PyObject *result = NULL;
9450 #ifdef MS_WINDOWS
9451     wchar_t user_name[UNLEN + 1];
9452     DWORD num_chars = Py_ARRAY_LENGTH(user_name);
9453 
9454     if (GetUserNameW(user_name, &num_chars)) {
9455         /* num_chars is the number of unicode chars plus null terminator */
9456         result = PyUnicode_FromWideChar(user_name, num_chars - 1);
9457     }
9458     else
9459         result = PyErr_SetFromWindowsErr(GetLastError());
9460 #else
9461     char *name;
9462     int old_errno = errno;
9463 
9464     errno = 0;
9465     name = getlogin();
9466     if (name == NULL) {
9467         if (errno)
9468             posix_error();
9469         else
9470             PyErr_SetString(PyExc_OSError, "unable to determine login name");
9471     }
9472     else
9473         result = PyUnicode_DecodeFSDefault(name);
9474     errno = old_errno;
9475 #endif
9476     return result;
9477 }
9478 #endif /* HAVE_GETLOGIN */
9479 
9480 
9481 #ifdef HAVE_GETUID
9482 /*[clinic input]
9483 os.getuid
9484 
9485 Return the current process's user id.
9486 [clinic start generated code]*/
9487 
9488 static PyObject *
os_getuid_impl(PyObject * module)9489 os_getuid_impl(PyObject *module)
9490 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
9491 {
9492     return _PyLong_FromUid(getuid());
9493 }
9494 #endif /* HAVE_GETUID */
9495 
9496 
9497 #ifdef MS_WINDOWS
9498 #define HAVE_KILL
9499 #endif /* MS_WINDOWS */
9500 
9501 #ifdef HAVE_KILL
9502 /*[clinic input]
9503 os.kill
9504 
9505     pid: pid_t
9506     signal: Py_ssize_t
9507     /
9508 
9509 Kill a process with a signal.
9510 [clinic start generated code]*/
9511 
9512 static PyObject *
os_kill_impl(PyObject * module,pid_t pid,Py_ssize_t signal)9513 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
9514 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
9515 {
9516     if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
9517         return NULL;
9518     }
9519 #ifndef MS_WINDOWS
9520     if (kill(pid, (int)signal) == -1) {
9521         return posix_error();
9522     }
9523 
9524     // Check immediately if the signal was sent to the current process.
9525     // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
9526     // is cheap.
9527     if (PyErr_CheckSignals()) {
9528         return NULL;
9529     }
9530 
9531     Py_RETURN_NONE;
9532 #else /* !MS_WINDOWS */
9533     PyObject *result;
9534     DWORD sig = (DWORD)signal;
9535     DWORD err;
9536     HANDLE handle;
9537 
9538 #ifdef HAVE_WINDOWS_CONSOLE_IO
9539     /* Console processes which share a common console can be sent CTRL+C or
9540        CTRL+BREAK events, provided they handle said events. */
9541     if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
9542         if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
9543             err = GetLastError();
9544             PyErr_SetFromWindowsErr(err);
9545         }
9546         else {
9547             Py_RETURN_NONE;
9548         }
9549     }
9550 #endif /* HAVE_WINDOWS_CONSOLE_IO */
9551 
9552     /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
9553        attempt to open and terminate the process. */
9554     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
9555     if (handle == NULL) {
9556         err = GetLastError();
9557         return PyErr_SetFromWindowsErr(err);
9558     }
9559 
9560     if (TerminateProcess(handle, sig) == 0) {
9561         err = GetLastError();
9562         result = PyErr_SetFromWindowsErr(err);
9563     } else {
9564         result = Py_NewRef(Py_None);
9565     }
9566 
9567     CloseHandle(handle);
9568     return result;
9569 #endif /* !MS_WINDOWS */
9570 }
9571 #endif /* HAVE_KILL */
9572 
9573 
9574 #ifdef HAVE_KILLPG
9575 /*[clinic input]
9576 os.killpg
9577 
9578     pgid: pid_t
9579     signal: int
9580     /
9581 
9582 Kill a process group with a signal.
9583 [clinic start generated code]*/
9584 
9585 static PyObject *
os_killpg_impl(PyObject * module,pid_t pgid,int signal)9586 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
9587 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
9588 {
9589     if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
9590         return NULL;
9591     }
9592     /* XXX some man pages make the `pgid` parameter an int, others
9593        a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
9594        take the same type. Moreover, pid_t is always at least as wide as
9595        int (else compilation of this module fails), which is safe. */
9596     if (killpg(pgid, signal) == -1)
9597         return posix_error();
9598     Py_RETURN_NONE;
9599 }
9600 #endif /* HAVE_KILLPG */
9601 
9602 
9603 #ifdef HAVE_PLOCK
9604 #ifdef HAVE_SYS_LOCK_H
9605 #include <sys/lock.h>
9606 #endif
9607 
9608 /*[clinic input]
9609 os.plock
9610     op: int
9611     /
9612 
9613 Lock program segments into memory.");
9614 [clinic start generated code]*/
9615 
9616 static PyObject *
os_plock_impl(PyObject * module,int op)9617 os_plock_impl(PyObject *module, int op)
9618 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
9619 {
9620     if (plock(op) == -1)
9621         return posix_error();
9622     Py_RETURN_NONE;
9623 }
9624 #endif /* HAVE_PLOCK */
9625 
9626 
9627 #ifdef HAVE_SETUID
9628 /*[clinic input]
9629 os.setuid
9630 
9631     uid: uid_t
9632     /
9633 
9634 Set the current process's user id.
9635 [clinic start generated code]*/
9636 
9637 static PyObject *
os_setuid_impl(PyObject * module,uid_t uid)9638 os_setuid_impl(PyObject *module, uid_t uid)
9639 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
9640 {
9641     if (setuid(uid) < 0)
9642         return posix_error();
9643     Py_RETURN_NONE;
9644 }
9645 #endif /* HAVE_SETUID */
9646 
9647 
9648 #ifdef HAVE_SETEUID
9649 /*[clinic input]
9650 os.seteuid
9651 
9652     euid: uid_t
9653     /
9654 
9655 Set the current process's effective user id.
9656 [clinic start generated code]*/
9657 
9658 static PyObject *
os_seteuid_impl(PyObject * module,uid_t euid)9659 os_seteuid_impl(PyObject *module, uid_t euid)
9660 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
9661 {
9662     if (seteuid(euid) < 0)
9663         return posix_error();
9664     Py_RETURN_NONE;
9665 }
9666 #endif /* HAVE_SETEUID */
9667 
9668 
9669 #ifdef HAVE_SETEGID
9670 /*[clinic input]
9671 os.setegid
9672 
9673     egid: gid_t
9674     /
9675 
9676 Set the current process's effective group id.
9677 [clinic start generated code]*/
9678 
9679 static PyObject *
os_setegid_impl(PyObject * module,gid_t egid)9680 os_setegid_impl(PyObject *module, gid_t egid)
9681 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
9682 {
9683     if (setegid(egid) < 0)
9684         return posix_error();
9685     Py_RETURN_NONE;
9686 }
9687 #endif /* HAVE_SETEGID */
9688 
9689 
9690 #ifdef HAVE_SETREUID
9691 /*[clinic input]
9692 os.setreuid
9693 
9694     ruid: uid_t
9695     euid: uid_t
9696     /
9697 
9698 Set the current process's real and effective user ids.
9699 [clinic start generated code]*/
9700 
9701 static PyObject *
os_setreuid_impl(PyObject * module,uid_t ruid,uid_t euid)9702 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
9703 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
9704 {
9705     if (setreuid(ruid, euid) < 0) {
9706         return posix_error();
9707     } else {
9708         Py_RETURN_NONE;
9709     }
9710 }
9711 #endif /* HAVE_SETREUID */
9712 
9713 
9714 #ifdef HAVE_SETREGID
9715 /*[clinic input]
9716 os.setregid
9717 
9718     rgid: gid_t
9719     egid: gid_t
9720     /
9721 
9722 Set the current process's real and effective group ids.
9723 [clinic start generated code]*/
9724 
9725 static PyObject *
os_setregid_impl(PyObject * module,gid_t rgid,gid_t egid)9726 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
9727 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
9728 {
9729     if (setregid(rgid, egid) < 0)
9730         return posix_error();
9731     Py_RETURN_NONE;
9732 }
9733 #endif /* HAVE_SETREGID */
9734 
9735 
9736 #ifdef HAVE_SETGID
9737 /*[clinic input]
9738 os.setgid
9739     gid: gid_t
9740     /
9741 
9742 Set the current process's group id.
9743 [clinic start generated code]*/
9744 
9745 static PyObject *
os_setgid_impl(PyObject * module,gid_t gid)9746 os_setgid_impl(PyObject *module, gid_t gid)
9747 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
9748 {
9749     if (setgid(gid) < 0)
9750         return posix_error();
9751     Py_RETURN_NONE;
9752 }
9753 #endif /* HAVE_SETGID */
9754 
9755 
9756 #ifdef HAVE_SETGROUPS
9757 /*[clinic input]
9758 os.setgroups
9759 
9760     groups: object
9761     /
9762 
9763 Set the groups of the current process to list.
9764 [clinic start generated code]*/
9765 
9766 static PyObject *
os_setgroups(PyObject * module,PyObject * groups)9767 os_setgroups(PyObject *module, PyObject *groups)
9768 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
9769 {
9770     if (!PySequence_Check(groups)) {
9771         PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
9772         return NULL;
9773     }
9774     Py_ssize_t len = PySequence_Size(groups);
9775     if (len < 0) {
9776         return NULL;
9777     }
9778     if (len > MAX_GROUPS) {
9779         PyErr_SetString(PyExc_ValueError, "too many groups");
9780         return NULL;
9781     }
9782 
9783     gid_t *grouplist = PyMem_New(gid_t, len);
9784     if (grouplist == NULL) {
9785         PyErr_NoMemory();
9786         return NULL;
9787     }
9788     for (Py_ssize_t i = 0; i < len; i++) {
9789         PyObject *elem;
9790         elem = PySequence_GetItem(groups, i);
9791         if (!elem) {
9792             PyMem_Free(grouplist);
9793             return NULL;
9794         }
9795         if (!PyLong_Check(elem)) {
9796             PyErr_SetString(PyExc_TypeError,
9797                             "groups must be integers");
9798             Py_DECREF(elem);
9799             PyMem_Free(grouplist);
9800             return NULL;
9801         } else {
9802             if (!_Py_Gid_Converter(elem, &grouplist[i])) {
9803                 Py_DECREF(elem);
9804                 PyMem_Free(grouplist);
9805                 return NULL;
9806             }
9807         }
9808         Py_DECREF(elem);
9809     }
9810 
9811     if (setgroups(len, grouplist) < 0) {
9812         posix_error();
9813         PyMem_Free(grouplist);
9814         return NULL;
9815     }
9816     PyMem_Free(grouplist);
9817     Py_RETURN_NONE;
9818 }
9819 #endif /* HAVE_SETGROUPS */
9820 
9821 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
9822 static PyObject *
wait_helper(PyObject * module,pid_t pid,int status,struct rusage * ru)9823 wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
9824 {
9825     PyObject *result;
9826     PyObject *struct_rusage;
9827 
9828     if (pid == -1)
9829         return posix_error();
9830 
9831     // If wait succeeded but no child was ready to report status, ru will not
9832     // have been populated.
9833     if (pid == 0) {
9834         memset(ru, 0, sizeof(*ru));
9835     }
9836 
9837     struct_rusage = _PyImport_GetModuleAttrString("resource", "struct_rusage");
9838     if (struct_rusage == NULL)
9839         return NULL;
9840 
9841     /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
9842     result = PyStructSequence_New((PyTypeObject*) struct_rusage);
9843     Py_DECREF(struct_rusage);
9844     if (!result)
9845         return NULL;
9846 
9847     int pos = 0;
9848 
9849 #ifndef doubletime
9850 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
9851 #endif
9852 
9853 #define SET_RESULT(CALL)                                     \
9854     do {                                                     \
9855         PyObject *item = (CALL);                             \
9856         if (item == NULL) {                                  \
9857             Py_DECREF(result);                               \
9858             return NULL;                                     \
9859         }                                                    \
9860         PyStructSequence_SET_ITEM(result, pos++, item);      \
9861     } while(0)
9862 
9863     SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
9864     SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
9865     SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
9866     SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
9867     SET_RESULT(PyLong_FromLong(ru->ru_idrss));
9868     SET_RESULT(PyLong_FromLong(ru->ru_isrss));
9869     SET_RESULT(PyLong_FromLong(ru->ru_minflt));
9870     SET_RESULT(PyLong_FromLong(ru->ru_majflt));
9871     SET_RESULT(PyLong_FromLong(ru->ru_nswap));
9872     SET_RESULT(PyLong_FromLong(ru->ru_inblock));
9873     SET_RESULT(PyLong_FromLong(ru->ru_oublock));
9874     SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
9875     SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
9876     SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
9877     SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
9878     SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
9879 #undef SET_RESULT
9880 
9881     return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
9882 }
9883 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
9884 
9885 
9886 #ifdef HAVE_WAIT3
9887 /*[clinic input]
9888 os.wait3
9889 
9890     options: int
9891 Wait for completion of a child process.
9892 
9893 Returns a tuple of information about the child process:
9894   (pid, status, rusage)
9895 [clinic start generated code]*/
9896 
9897 static PyObject *
os_wait3_impl(PyObject * module,int options)9898 os_wait3_impl(PyObject *module, int options)
9899 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
9900 {
9901     pid_t pid;
9902     struct rusage ru;
9903     int async_err = 0;
9904     WAIT_TYPE status;
9905     WAIT_STATUS_INT(status) = 0;
9906 
9907     do {
9908         Py_BEGIN_ALLOW_THREADS
9909         pid = wait3(&status, options, &ru);
9910         Py_END_ALLOW_THREADS
9911     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9912     if (pid < 0)
9913         return (!async_err) ? posix_error() : NULL;
9914 
9915     return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
9916 }
9917 #endif /* HAVE_WAIT3 */
9918 
9919 
9920 #ifdef HAVE_WAIT4
9921 /*[clinic input]
9922 
9923 os.wait4
9924 
9925     pid: pid_t
9926     options: int
9927 
9928 Wait for completion of a specific child process.
9929 
9930 Returns a tuple of information about the child process:
9931   (pid, status, rusage)
9932 [clinic start generated code]*/
9933 
9934 static PyObject *
os_wait4_impl(PyObject * module,pid_t pid,int options)9935 os_wait4_impl(PyObject *module, pid_t pid, int options)
9936 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
9937 {
9938     pid_t res;
9939     struct rusage ru;
9940     int async_err = 0;
9941     WAIT_TYPE status;
9942     WAIT_STATUS_INT(status) = 0;
9943 
9944     do {
9945         Py_BEGIN_ALLOW_THREADS
9946         res = wait4(pid, &status, options, &ru);
9947         Py_END_ALLOW_THREADS
9948     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9949     if (res < 0)
9950         return (!async_err) ? posix_error() : NULL;
9951 
9952     return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
9953 }
9954 #endif /* HAVE_WAIT4 */
9955 
9956 
9957 #if defined(HAVE_WAITID)
9958 /*[clinic input]
9959 os.waitid
9960 
9961     idtype: idtype_t
9962         Must be one of be P_PID, P_PGID or P_ALL.
9963     id: id_t
9964         The id to wait on.
9965     options: int
9966         Constructed from the ORing of one or more of WEXITED, WSTOPPED
9967         or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
9968     /
9969 
9970 Returns the result of waiting for a process or processes.
9971 
9972 Returns either waitid_result or None if WNOHANG is specified and there are
9973 no children in a waitable state.
9974 [clinic start generated code]*/
9975 
9976 static PyObject *
os_waitid_impl(PyObject * module,idtype_t idtype,id_t id,int options)9977 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
9978 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
9979 {
9980     PyObject *result;
9981     int res;
9982     int async_err = 0;
9983     siginfo_t si;
9984     si.si_pid = 0;
9985 
9986     do {
9987         Py_BEGIN_ALLOW_THREADS
9988         res = waitid(idtype, id, &si, options);
9989         Py_END_ALLOW_THREADS
9990     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9991     if (res < 0)
9992         return (!async_err) ? posix_error() : NULL;
9993 
9994     if (si.si_pid == 0)
9995         Py_RETURN_NONE;
9996 
9997     PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
9998     result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
9999     if (!result)
10000         return NULL;
10001 
10002     int pos = 0;
10003 
10004 #define SET_RESULT(CALL)                                     \
10005     do {                                                     \
10006         PyObject *item = (CALL);                             \
10007         if (item == NULL) {                                  \
10008             Py_DECREF(result);                               \
10009             return NULL;                                     \
10010         }                                                    \
10011         PyStructSequence_SET_ITEM(result, pos++, item);      \
10012     } while(0)
10013 
10014     SET_RESULT(PyLong_FromPid(si.si_pid));
10015     SET_RESULT(_PyLong_FromUid(si.si_uid));
10016     SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10017     SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10018     SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10019 
10020 #undef SET_RESULT
10021 
10022     return result;
10023 }
10024 #endif /* defined(HAVE_WAITID) */
10025 
10026 
10027 #if defined(HAVE_WAITPID)
10028 /*[clinic input]
10029 os.waitpid
10030     pid: pid_t
10031     options: int
10032     /
10033 
10034 Wait for completion of a given child process.
10035 
10036 Returns a tuple of information regarding the child process:
10037     (pid, status)
10038 
10039 The options argument is ignored on Windows.
10040 [clinic start generated code]*/
10041 
10042 static PyObject *
os_waitpid_impl(PyObject * module,pid_t pid,int options)10043 os_waitpid_impl(PyObject *module, pid_t pid, int options)
10044 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10045 {
10046     pid_t res;
10047     int async_err = 0;
10048     WAIT_TYPE status;
10049     WAIT_STATUS_INT(status) = 0;
10050 
10051     do {
10052         Py_BEGIN_ALLOW_THREADS
10053         res = waitpid(pid, &status, options);
10054         Py_END_ALLOW_THREADS
10055     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10056     if (res < 0)
10057         return (!async_err) ? posix_error() : NULL;
10058 
10059     return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10060 }
10061 #elif defined(HAVE_CWAIT)
10062 /* MS C has a variant of waitpid() that's usable for most purposes. */
10063 /*[clinic input]
10064 os.waitpid
10065     pid: intptr_t
10066     options: int
10067     /
10068 
10069 Wait for completion of a given process.
10070 
10071 Returns a tuple of information regarding the process:
10072     (pid, status << 8)
10073 
10074 The options argument is ignored on Windows.
10075 [clinic start generated code]*/
10076 
10077 static PyObject *
os_waitpid_impl(PyObject * module,intptr_t pid,int options)10078 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10079 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10080 {
10081     int status;
10082     intptr_t res;
10083     int async_err = 0;
10084 
10085     do {
10086         Py_BEGIN_ALLOW_THREADS
10087         _Py_BEGIN_SUPPRESS_IPH
10088         res = _cwait(&status, pid, options);
10089         _Py_END_SUPPRESS_IPH
10090         Py_END_ALLOW_THREADS
10091     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10092     if (res < 0)
10093         return (!async_err) ? posix_error() : NULL;
10094 
10095     unsigned long long ustatus = (unsigned int)status;
10096 
10097     /* shift the status left a byte so this is more like the POSIX waitpid */
10098     return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10099 }
10100 #endif
10101 
10102 
10103 #ifdef HAVE_WAIT
10104 /*[clinic input]
10105 os.wait
10106 
10107 Wait for completion of a child process.
10108 
10109 Returns a tuple of information about the child process:
10110     (pid, status)
10111 [clinic start generated code]*/
10112 
10113 static PyObject *
os_wait_impl(PyObject * module)10114 os_wait_impl(PyObject *module)
10115 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10116 {
10117     pid_t pid;
10118     int async_err = 0;
10119     WAIT_TYPE status;
10120     WAIT_STATUS_INT(status) = 0;
10121 
10122     do {
10123         Py_BEGIN_ALLOW_THREADS
10124         pid = wait(&status);
10125         Py_END_ALLOW_THREADS
10126     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10127     if (pid < 0)
10128         return (!async_err) ? posix_error() : NULL;
10129 
10130     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10131 }
10132 #endif /* HAVE_WAIT */
10133 
10134 
10135 // This system call always crashes on older Android versions.
10136 #if defined(__linux__) && defined(__NR_pidfd_open) && \
10137     !(defined(__ANDROID__) && __ANDROID_API__ < 31)
10138 /*[clinic input]
10139 os.pidfd_open
10140   pid: pid_t
10141   flags: unsigned_int = 0
10142 
10143 Return a file descriptor referring to the process *pid*.
10144 
10145 The descriptor can be used to perform process management without races and
10146 signals.
10147 [clinic start generated code]*/
10148 
10149 static PyObject *
os_pidfd_open_impl(PyObject * module,pid_t pid,unsigned int flags)10150 os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10151 /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
10152 {
10153     int fd = syscall(__NR_pidfd_open, pid, flags);
10154     if (fd < 0) {
10155         return posix_error();
10156     }
10157     return PyLong_FromLong(fd);
10158 }
10159 #endif
10160 
10161 
10162 #ifdef HAVE_SETNS
10163 /*[clinic input]
10164 os.setns
10165   fd: fildes
10166     A file descriptor to a namespace.
10167   nstype: int = 0
10168     Type of namespace.
10169 
10170 Move the calling thread into different namespaces.
10171 [clinic start generated code]*/
10172 
10173 static PyObject *
os_setns_impl(PyObject * module,int fd,int nstype)10174 os_setns_impl(PyObject *module, int fd, int nstype)
10175 /*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10176 {
10177     int res;
10178 
10179     Py_BEGIN_ALLOW_THREADS
10180     res = setns(fd, nstype);
10181     Py_END_ALLOW_THREADS
10182 
10183     if (res != 0) {
10184         return posix_error();
10185     }
10186 
10187     Py_RETURN_NONE;
10188 }
10189 #endif
10190 
10191 
10192 #ifdef HAVE_UNSHARE
10193 /*[clinic input]
10194 os.unshare
10195   flags: int
10196     Namespaces to be unshared.
10197 
10198 Disassociate parts of a process (or thread) execution context.
10199 [clinic start generated code]*/
10200 
10201 static PyObject *
os_unshare_impl(PyObject * module,int flags)10202 os_unshare_impl(PyObject *module, int flags)
10203 /*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10204 {
10205     int res;
10206 
10207     Py_BEGIN_ALLOW_THREADS
10208     res = unshare(flags);
10209     Py_END_ALLOW_THREADS
10210 
10211     if (res != 0) {
10212         return posix_error();
10213     }
10214 
10215     Py_RETURN_NONE;
10216 }
10217 #endif
10218 
10219 
10220 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10221 /*[clinic input]
10222 os.readlink
10223 
10224     path: path_t
10225     *
10226     dir_fd: dir_fd(requires='readlinkat') = None
10227 
10228 Return a string representing the path to which the symbolic link points.
10229 
10230 If dir_fd is not None, it should be a file descriptor open to a directory,
10231 and path should be relative; path will then be relative to that directory.
10232 
10233 dir_fd may not be implemented on your platform.  If it is unavailable,
10234 using it will raise a NotImplementedError.
10235 [clinic start generated code]*/
10236 
10237 static PyObject *
os_readlink_impl(PyObject * module,path_t * path,int dir_fd)10238 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
10239 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
10240 {
10241 #if defined(HAVE_READLINK)
10242     char buffer[MAXPATHLEN+1];
10243     ssize_t length;
10244 #ifdef HAVE_READLINKAT
10245     int readlinkat_unavailable = 0;
10246 #endif
10247 
10248     Py_BEGIN_ALLOW_THREADS
10249 #ifdef HAVE_READLINKAT
10250     if (dir_fd != DEFAULT_DIR_FD) {
10251         if (HAVE_READLINKAT_RUNTIME) {
10252             length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
10253         } else {
10254             readlinkat_unavailable = 1;
10255         }
10256     } else
10257 #endif
10258         length = readlink(path->narrow, buffer, MAXPATHLEN);
10259     Py_END_ALLOW_THREADS
10260 
10261 #ifdef HAVE_READLINKAT
10262     if (readlinkat_unavailable) {
10263         argument_unavailable_error(NULL, "dir_fd");
10264         return NULL;
10265     }
10266 #endif
10267 
10268     if (length < 0) {
10269         return path_error(path);
10270     }
10271     buffer[length] = '\0';
10272 
10273     if (PyUnicode_Check(path->object))
10274         return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
10275     else
10276         return PyBytes_FromStringAndSize(buffer, length);
10277 #elif defined(MS_WINDOWS)
10278     DWORD n_bytes_returned;
10279     DWORD io_result = 0;
10280     HANDLE reparse_point_handle;
10281     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
10282     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
10283     PyObject *result = NULL;
10284 
10285     /* First get a handle to the reparse point */
10286     Py_BEGIN_ALLOW_THREADS
10287     reparse_point_handle = CreateFileW(
10288         path->wide,
10289         0,
10290         0,
10291         0,
10292         OPEN_EXISTING,
10293         FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
10294         0);
10295     if (reparse_point_handle != INVALID_HANDLE_VALUE) {
10296         /* New call DeviceIoControl to read the reparse point */
10297         io_result = DeviceIoControl(
10298             reparse_point_handle,
10299             FSCTL_GET_REPARSE_POINT,
10300             0, 0, /* in buffer */
10301             target_buffer, sizeof(target_buffer),
10302             &n_bytes_returned,
10303             0 /* we're not using OVERLAPPED_IO */
10304             );
10305         CloseHandle(reparse_point_handle);
10306     }
10307     Py_END_ALLOW_THREADS
10308 
10309     if (io_result == 0) {
10310         return path_error(path);
10311     }
10312 
10313     wchar_t *name = NULL;
10314     Py_ssize_t nameLen = 0;
10315     if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
10316     {
10317         name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
10318                            rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
10319         nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10320     }
10321     else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
10322     {
10323         name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
10324                            rdb->MountPointReparseBuffer.SubstituteNameOffset);
10325         nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
10326     }
10327     else
10328     {
10329         PyErr_SetString(PyExc_ValueError, "not a symbolic link");
10330     }
10331     if (name) {
10332         if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
10333             /* Our buffer is mutable, so this is okay */
10334             name[1] = L'\\';
10335         }
10336         result = PyUnicode_FromWideChar(name, nameLen);
10337         if (result && PyBytes_Check(path->object)) {
10338             Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
10339         }
10340     }
10341     return result;
10342 #endif
10343 }
10344 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
10345 
10346 #if defined(MS_WINDOWS)
10347 
10348 /* Remove the last portion of the path - return 0 on success */
10349 static int
_dirnameW(WCHAR * path)10350 _dirnameW(WCHAR *path)
10351 {
10352     WCHAR *ptr;
10353     size_t length = wcsnlen_s(path, MAX_PATH);
10354     if (length == MAX_PATH) {
10355         return -1;
10356     }
10357 
10358     /* walk the path from the end until a backslash is encountered */
10359     for(ptr = path + length; ptr != path; ptr--) {
10360         if (*ptr == L'\\' || *ptr == L'/') {
10361             break;
10362         }
10363     }
10364     *ptr = 0;
10365     return 0;
10366 }
10367 
10368 #endif
10369 
10370 #ifdef HAVE_SYMLINK
10371 
10372 #if defined(MS_WINDOWS)
10373 
10374 /* Is this path absolute? */
10375 static int
_is_absW(const WCHAR * path)10376 _is_absW(const WCHAR *path)
10377 {
10378     return path[0] == L'\\' || path[0] == L'/' ||
10379         (path[0] && path[1] == L':');
10380 }
10381 
10382 /* join root and rest with a backslash - return 0 on success */
10383 static int
_joinW(WCHAR * dest_path,const WCHAR * root,const WCHAR * rest)10384 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
10385 {
10386     if (_is_absW(rest)) {
10387         return wcscpy_s(dest_path, MAX_PATH, rest);
10388     }
10389 
10390     if (wcscpy_s(dest_path, MAX_PATH, root)) {
10391         return -1;
10392     }
10393 
10394     if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
10395         return -1;
10396     }
10397 
10398     return wcscat_s(dest_path, MAX_PATH, rest);
10399 }
10400 
10401 /* Return True if the path at src relative to dest is a directory */
10402 static int
_check_dirW(LPCWSTR src,LPCWSTR dest)10403 _check_dirW(LPCWSTR src, LPCWSTR dest)
10404 {
10405     WIN32_FILE_ATTRIBUTE_DATA src_info;
10406     WCHAR dest_parent[MAX_PATH];
10407     WCHAR src_resolved[MAX_PATH] = L"";
10408 
10409     /* dest_parent = os.path.dirname(dest) */
10410     if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
10411         _dirnameW(dest_parent)) {
10412         return 0;
10413     }
10414     /* src_resolved = os.path.join(dest_parent, src) */
10415     if (_joinW(src_resolved, dest_parent, src)) {
10416         return 0;
10417     }
10418     return (
10419         GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
10420         && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
10421     );
10422 }
10423 #endif
10424 
10425 
10426 /*[clinic input]
10427 os.symlink
10428     src: path_t
10429     dst: path_t
10430     target_is_directory: bool = False
10431     *
10432     dir_fd: dir_fd(requires='symlinkat')=None
10433 
10434 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
10435 
10436 Create a symbolic link pointing to src named dst.
10437 
10438 target_is_directory is required on Windows if the target is to be
10439   interpreted as a directory.  (On Windows, symlink requires
10440   Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
10441   target_is_directory is ignored on non-Windows platforms.
10442 
10443 If dir_fd is not None, it should be a file descriptor open to a directory,
10444   and path should be relative; path will then be relative to that directory.
10445 dir_fd may not be implemented on your platform.
10446   If it is unavailable, using it will raise a NotImplementedError.
10447 
10448 [clinic start generated code]*/
10449 
10450 static PyObject *
os_symlink_impl(PyObject * module,path_t * src,path_t * dst,int target_is_directory,int dir_fd)10451 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
10452                 int target_is_directory, int dir_fd)
10453 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
10454 {
10455 #ifdef MS_WINDOWS
10456     DWORD result;
10457     DWORD flags = 0;
10458 
10459     /* Assumed true, set to false if detected to not be available. */
10460     static int windows_has_symlink_unprivileged_flag = TRUE;
10461 #else
10462     int result;
10463 #ifdef HAVE_SYMLINKAT
10464     int symlinkat_unavailable = 0;
10465 #endif
10466 #endif
10467 
10468     if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
10469                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
10470         return NULL;
10471     }
10472 
10473 #ifdef MS_WINDOWS
10474 
10475     if (windows_has_symlink_unprivileged_flag) {
10476         /* Allow non-admin symlinks if system allows it. */
10477         flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
10478     }
10479 
10480     Py_BEGIN_ALLOW_THREADS
10481     _Py_BEGIN_SUPPRESS_IPH
10482     /* if src is a directory, ensure flags==1 (target_is_directory bit) */
10483     if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
10484         flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
10485     }
10486 
10487     result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
10488     _Py_END_SUPPRESS_IPH
10489     Py_END_ALLOW_THREADS
10490 
10491     if (windows_has_symlink_unprivileged_flag && !result &&
10492         ERROR_INVALID_PARAMETER == GetLastError()) {
10493 
10494         Py_BEGIN_ALLOW_THREADS
10495         _Py_BEGIN_SUPPRESS_IPH
10496         /* This error might be caused by
10497         SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
10498         Try again, and update windows_has_symlink_unprivileged_flag if we
10499         are successful this time.
10500 
10501         NOTE: There is a risk of a race condition here if there are other
10502         conditions than the flag causing ERROR_INVALID_PARAMETER, and
10503         another process (or thread) changes that condition in between our
10504         calls to CreateSymbolicLink.
10505         */
10506         flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
10507         result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
10508         _Py_END_SUPPRESS_IPH
10509         Py_END_ALLOW_THREADS
10510 
10511         if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
10512             windows_has_symlink_unprivileged_flag = FALSE;
10513         }
10514     }
10515 
10516     if (!result)
10517         return path_error2(src, dst);
10518 
10519 #else
10520 
10521     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
10522         PyErr_SetString(PyExc_ValueError,
10523             "symlink: src and dst must be the same type");
10524         return NULL;
10525     }
10526 
10527     Py_BEGIN_ALLOW_THREADS
10528 #ifdef HAVE_SYMLINKAT
10529     if (dir_fd != DEFAULT_DIR_FD) {
10530         if (HAVE_SYMLINKAT_RUNTIME) {
10531             result = symlinkat(src->narrow, dir_fd, dst->narrow);
10532         } else {
10533             symlinkat_unavailable = 1;
10534         }
10535     } else
10536 #endif
10537         result = symlink(src->narrow, dst->narrow);
10538     Py_END_ALLOW_THREADS
10539 
10540 #ifdef HAVE_SYMLINKAT
10541     if (symlinkat_unavailable) {
10542           argument_unavailable_error(NULL, "dir_fd");
10543           return NULL;
10544     }
10545 #endif
10546 
10547     if (result)
10548         return path_error2(src, dst);
10549 #endif
10550 
10551     Py_RETURN_NONE;
10552 }
10553 #endif /* HAVE_SYMLINK */
10554 
10555 
10556 static PyStructSequence_Field times_result_fields[] = {
10557     {"user",    "user time"},
10558     {"system",   "system time"},
10559     {"children_user",    "user time of children"},
10560     {"children_system",    "system time of children"},
10561     {"elapsed",    "elapsed time since an arbitrary point in the past"},
10562     {NULL}
10563 };
10564 
10565 PyDoc_STRVAR(times_result__doc__,
10566 "times_result: Result from os.times().\n\n\
10567 This object may be accessed either as a tuple of\n\
10568   (user, system, children_user, children_system, elapsed),\n\
10569 or via the attributes user, system, children_user, children_system,\n\
10570 and elapsed.\n\
10571 \n\
10572 See os.times for more information.");
10573 
10574 static PyStructSequence_Desc times_result_desc = {
10575     "times_result", /* name */
10576     times_result__doc__, /* doc */
10577     times_result_fields,
10578     5
10579 };
10580 
10581 static PyObject *
build_times_result(PyObject * module,double user,double system,double children_user,double children_system,double elapsed)10582 build_times_result(PyObject *module, double user, double system,
10583     double children_user, double children_system,
10584     double elapsed)
10585 {
10586     PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
10587     PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
10588     if (value == NULL)
10589         return NULL;
10590 
10591 #define SET(i, field) \
10592     { \
10593     PyObject *o = PyFloat_FromDouble(field); \
10594     if (!o) { \
10595         Py_DECREF(value); \
10596         return NULL; \
10597     } \
10598     PyStructSequence_SET_ITEM(value, i, o); \
10599     } \
10600 
10601     SET(0, user);
10602     SET(1, system);
10603     SET(2, children_user);
10604     SET(3, children_system);
10605     SET(4, elapsed);
10606 
10607 #undef SET
10608 
10609     return value;
10610 }
10611 
10612 
10613 /*[clinic input]
10614 os.times
10615 
10616 Return a collection containing process timing information.
10617 
10618 The object returned behaves like a named tuple with these fields:
10619   (utime, stime, cutime, cstime, elapsed_time)
10620 All fields are floating-point numbers.
10621 [clinic start generated code]*/
10622 
10623 static PyObject *
os_times_impl(PyObject * module)10624 os_times_impl(PyObject *module)
10625 /*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
10626 {
10627 #ifdef MS_WINDOWS
10628     FILETIME create, exit, kernel, user;
10629     HANDLE hProc;
10630     hProc = GetCurrentProcess();
10631     GetProcessTimes(hProc, &create, &exit, &kernel, &user);
10632     /* The fields of a FILETIME structure are the hi and lo part
10633        of a 64-bit value expressed in 100 nanosecond units.
10634        1e7 is one second in such units; 1e-7 the inverse.
10635        429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
10636     */
10637     return build_times_result(module,
10638         (double)(user.dwHighDateTime*429.4967296 +
10639                  user.dwLowDateTime*1e-7),
10640         (double)(kernel.dwHighDateTime*429.4967296 +
10641                  kernel.dwLowDateTime*1e-7),
10642         (double)0,
10643         (double)0,
10644         (double)0);
10645 #else /* MS_WINDOWS */
10646     _posixstate *state = get_posix_state(module);
10647     long ticks_per_second = state->ticks_per_second;
10648 
10649     struct tms process;
10650     clock_t elapsed;
10651     errno = 0;
10652     elapsed = times(&process);
10653     if (elapsed == (clock_t) -1) {
10654         return posix_error();
10655     }
10656 
10657     return build_times_result(module,
10658         (double)process.tms_utime / ticks_per_second,
10659         (double)process.tms_stime / ticks_per_second,
10660         (double)process.tms_cutime / ticks_per_second,
10661         (double)process.tms_cstime / ticks_per_second,
10662         (double)elapsed / ticks_per_second);
10663 #endif /* MS_WINDOWS */
10664 }
10665 
10666 
10667 #if defined(HAVE_TIMERFD_CREATE)
10668 #define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
10669 #define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
10670 #define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
10671 
10672 static PyObject *
build_itimerspec(const struct itimerspec * curr_value)10673 build_itimerspec(const struct itimerspec* curr_value)
10674 {
10675     double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
10676                                                           curr_value->it_value.tv_nsec);
10677     PyObject *value = PyFloat_FromDouble(_value);
10678     if (value == NULL) {
10679         return NULL;
10680     }
10681     double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
10682                                                    curr_value->it_interval.tv_nsec);
10683     PyObject *interval = PyFloat_FromDouble(_interval);
10684     if (interval == NULL) {
10685         Py_DECREF(value);
10686         return NULL;
10687     }
10688     PyObject *tuple = PyTuple_Pack(2, value, interval);
10689     Py_DECREF(interval);
10690     Py_DECREF(value);
10691     return tuple;
10692 }
10693 
10694 static PyObject *
build_itimerspec_ns(const struct itimerspec * curr_value)10695 build_itimerspec_ns(const struct itimerspec* curr_value)
10696 {
10697     PyTime_t value, interval;
10698     if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
10699         return NULL;
10700     }
10701     if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
10702         return NULL;
10703     }
10704     return Py_BuildValue("LL", value, interval);
10705 }
10706 
10707 /*[clinic input]
10708 os.timerfd_create
10709 
10710     clockid: int
10711         A valid clock ID constant as timer file descriptor.
10712 
10713         time.CLOCK_REALTIME
10714         time.CLOCK_MONOTONIC
10715         time.CLOCK_BOOTTIME
10716     /
10717     *
10718     flags: int = 0
10719         0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
10720 
10721         os.TFD_NONBLOCK
10722             If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
10723             If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
10724 
10725         os.TFD_CLOEXEC
10726             If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
10727 
10728 Create and return a timer file descriptor.
10729 [clinic start generated code]*/
10730 
10731 static PyObject *
os_timerfd_create_impl(PyObject * module,int clockid,int flags)10732 os_timerfd_create_impl(PyObject *module, int clockid, int flags)
10733 /*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
10734 
10735 {
10736     int fd;
10737     Py_BEGIN_ALLOW_THREADS
10738     flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
10739     fd = timerfd_create(clockid, flags);
10740     Py_END_ALLOW_THREADS
10741     if (fd == -1) {
10742         return PyErr_SetFromErrno(PyExc_OSError);
10743     }
10744     return PyLong_FromLong(fd);
10745 }
10746 
10747 /*[clinic input]
10748 os.timerfd_settime
10749 
10750     fd: fildes
10751         A timer file descriptor.
10752     /
10753     *
10754     flags: int = 0
10755         0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
10756     initial as initial_double: double = 0.0
10757         The initial expiration time, in seconds.
10758     interval as interval_double: double = 0.0
10759         The timer's interval, in seconds.
10760 
10761 Alter a timer file descriptor's internal timer in seconds.
10762 [clinic start generated code]*/
10763 
10764 static PyObject *
os_timerfd_settime_impl(PyObject * module,int fd,int flags,double initial_double,double interval_double)10765 os_timerfd_settime_impl(PyObject *module, int fd, int flags,
10766                         double initial_double, double interval_double)
10767 /*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
10768 {
10769     PyTime_t initial, interval;
10770     if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
10771                                   &initial) < 0) {
10772         return NULL;
10773     }
10774     if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
10775                                   &interval) < 0) {
10776         return NULL;
10777     }
10778 
10779     struct itimerspec new_value, old_value;
10780     if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
10781         PyErr_SetString(PyExc_ValueError, "invalid initial value");
10782         return NULL;
10783     }
10784     if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
10785         PyErr_SetString(PyExc_ValueError, "invalid interval value");
10786         return NULL;
10787     }
10788 
10789     int result;
10790     Py_BEGIN_ALLOW_THREADS
10791     result = timerfd_settime(fd, flags, &new_value, &old_value);
10792     Py_END_ALLOW_THREADS
10793     if (result == -1) {
10794         return PyErr_SetFromErrno(PyExc_OSError);
10795     }
10796     return build_itimerspec(&old_value);
10797 }
10798 
10799 
10800 /*[clinic input]
10801 os.timerfd_settime_ns
10802 
10803     fd: fildes
10804         A timer file descriptor.
10805     /
10806     *
10807     flags: int = 0
10808         0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
10809     initial: long_long = 0
10810         initial expiration timing in seconds.
10811     interval: long_long = 0
10812         interval for the timer in seconds.
10813 
10814 Alter a timer file descriptor's internal timer in nanoseconds.
10815 [clinic start generated code]*/
10816 
10817 static PyObject *
os_timerfd_settime_ns_impl(PyObject * module,int fd,int flags,long long initial,long long interval)10818 os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
10819                            long long initial, long long interval)
10820 /*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/
10821 {
10822     struct itimerspec new_value;
10823     struct itimerspec old_value;
10824     int result;
10825     if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
10826         PyErr_SetString(PyExc_ValueError, "invalid initial value");
10827         return NULL;
10828     }
10829     if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
10830         PyErr_SetString(PyExc_ValueError, "invalid interval value");
10831         return NULL;
10832     }
10833     Py_BEGIN_ALLOW_THREADS
10834     result = timerfd_settime(fd, flags, &new_value, &old_value);
10835     Py_END_ALLOW_THREADS
10836     if (result == -1) {
10837         return PyErr_SetFromErrno(PyExc_OSError);
10838     }
10839     return build_itimerspec_ns(&old_value);
10840 }
10841 
10842 /*[clinic input]
10843 os.timerfd_gettime
10844 
10845     fd: fildes
10846         A timer file descriptor.
10847     /
10848 
10849 Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds.
10850 [clinic start generated code]*/
10851 
10852 static PyObject *
os_timerfd_gettime_impl(PyObject * module,int fd)10853 os_timerfd_gettime_impl(PyObject *module, int fd)
10854 /*[clinic end generated code: output=ec5a94a66cfe6ab4 input=8148e3430870da1c]*/
10855 {
10856     struct itimerspec curr_value;
10857     int result;
10858     Py_BEGIN_ALLOW_THREADS
10859     result = timerfd_gettime(fd, &curr_value);
10860     Py_END_ALLOW_THREADS
10861     if (result == -1) {
10862         return PyErr_SetFromErrno(PyExc_OSError);
10863     }
10864     return build_itimerspec(&curr_value);
10865 }
10866 
10867 
10868 /*[clinic input]
10869 os.timerfd_gettime_ns
10870 
10871     fd: fildes
10872         A timer file descriptor.
10873     /
10874 
10875 Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds.
10876 [clinic start generated code]*/
10877 
10878 static PyObject *
os_timerfd_gettime_ns_impl(PyObject * module,int fd)10879 os_timerfd_gettime_ns_impl(PyObject *module, int fd)
10880 /*[clinic end generated code: output=580633a4465f39fe input=a825443e4c6b40ac]*/
10881 {
10882     struct itimerspec curr_value;
10883     int result;
10884     Py_BEGIN_ALLOW_THREADS
10885     result = timerfd_gettime(fd, &curr_value);
10886     Py_END_ALLOW_THREADS
10887     if (result == -1) {
10888         return PyErr_SetFromErrno(PyExc_OSError);
10889     }
10890     return build_itimerspec_ns(&curr_value);
10891 }
10892 
10893 #undef ONE_SECOND_IN_NS
10894 #undef EXTRACT_NSEC
10895 
10896 #endif  /* HAVE_TIMERFD_CREATE */
10897 
10898 #ifdef HAVE_GETSID
10899 /*[clinic input]
10900 os.getsid
10901 
10902     pid: pid_t
10903     /
10904 
10905 Call the system call getsid(pid) and return the result.
10906 [clinic start generated code]*/
10907 
10908 static PyObject *
os_getsid_impl(PyObject * module,pid_t pid)10909 os_getsid_impl(PyObject *module, pid_t pid)
10910 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
10911 {
10912     int sid;
10913     sid = getsid(pid);
10914     if (sid < 0)
10915         return posix_error();
10916     return PyLong_FromLong((long)sid);
10917 }
10918 #endif /* HAVE_GETSID */
10919 
10920 
10921 #ifdef HAVE_SETSID
10922 /*[clinic input]
10923 os.setsid
10924 
10925 Call the system call setsid().
10926 [clinic start generated code]*/
10927 
10928 static PyObject *
os_setsid_impl(PyObject * module)10929 os_setsid_impl(PyObject *module)
10930 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
10931 {
10932     if (setsid() < 0)
10933         return posix_error();
10934     Py_RETURN_NONE;
10935 }
10936 #endif /* HAVE_SETSID */
10937 
10938 
10939 #ifdef HAVE_SETPGID
10940 /*[clinic input]
10941 os.setpgid
10942 
10943     pid: pid_t
10944     pgrp: pid_t
10945     /
10946 
10947 Call the system call setpgid(pid, pgrp).
10948 [clinic start generated code]*/
10949 
10950 static PyObject *
os_setpgid_impl(PyObject * module,pid_t pid,pid_t pgrp)10951 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
10952 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
10953 {
10954     if (setpgid(pid, pgrp) < 0)
10955         return posix_error();
10956     Py_RETURN_NONE;
10957 }
10958 #endif /* HAVE_SETPGID */
10959 
10960 
10961 #ifdef HAVE_TCGETPGRP
10962 /*[clinic input]
10963 os.tcgetpgrp
10964 
10965     fd: int
10966     /
10967 
10968 Return the process group associated with the terminal specified by fd.
10969 [clinic start generated code]*/
10970 
10971 static PyObject *
os_tcgetpgrp_impl(PyObject * module,int fd)10972 os_tcgetpgrp_impl(PyObject *module, int fd)
10973 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
10974 {
10975     pid_t pgid = tcgetpgrp(fd);
10976     if (pgid < 0)
10977         return posix_error();
10978     return PyLong_FromPid(pgid);
10979 }
10980 #endif /* HAVE_TCGETPGRP */
10981 
10982 
10983 #ifdef HAVE_TCSETPGRP
10984 /*[clinic input]
10985 os.tcsetpgrp
10986 
10987     fd: int
10988     pgid: pid_t
10989     /
10990 
10991 Set the process group associated with the terminal specified by fd.
10992 [clinic start generated code]*/
10993 
10994 static PyObject *
os_tcsetpgrp_impl(PyObject * module,int fd,pid_t pgid)10995 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
10996 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
10997 {
10998     if (tcsetpgrp(fd, pgid) < 0)
10999         return posix_error();
11000     Py_RETURN_NONE;
11001 }
11002 #endif /* HAVE_TCSETPGRP */
11003 
11004 /* Functions acting on file descriptors */
11005 
11006 #ifdef O_CLOEXEC
11007 extern int _Py_open_cloexec_works;
11008 #endif
11009 
11010 
11011 /*[clinic input]
11012 os.open -> int
11013     path: path_t
11014     flags: int
11015     mode: int = 0o777
11016     *
11017     dir_fd: dir_fd(requires='openat') = None
11018 
11019 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
11020 
11021 Open a file for low level IO.  Returns a file descriptor (integer).
11022 
11023 If dir_fd is not None, it should be a file descriptor open to a directory,
11024   and path should be relative; path will then be relative to that directory.
11025 dir_fd may not be implemented on your platform.
11026   If it is unavailable, using it will raise a NotImplementedError.
11027 [clinic start generated code]*/
11028 
11029 static int
os_open_impl(PyObject * module,path_t * path,int flags,int mode,int dir_fd)11030 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11031 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
11032 {
11033     int fd;
11034     int async_err = 0;
11035 #ifdef HAVE_OPENAT
11036     int openat_unavailable = 0;
11037 #endif
11038 
11039 #ifdef O_CLOEXEC
11040     int *atomic_flag_works = &_Py_open_cloexec_works;
11041 #elif !defined(MS_WINDOWS)
11042     int *atomic_flag_works = NULL;
11043 #endif
11044 
11045 #ifdef MS_WINDOWS
11046     flags |= O_NOINHERIT;
11047 #elif defined(O_CLOEXEC)
11048     flags |= O_CLOEXEC;
11049 #endif
11050 
11051     if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11052         return -1;
11053     }
11054 
11055     _Py_BEGIN_SUPPRESS_IPH
11056     do {
11057         Py_BEGIN_ALLOW_THREADS
11058 #ifdef MS_WINDOWS
11059         fd = _wopen(path->wide, flags, mode);
11060 #else
11061 #ifdef HAVE_OPENAT
11062         if (dir_fd != DEFAULT_DIR_FD) {
11063             if (HAVE_OPENAT_RUNTIME) {
11064                 fd = openat(dir_fd, path->narrow, flags, mode);
11065 
11066             } else {
11067                 openat_unavailable = 1;
11068                 fd = -1;
11069             }
11070         } else
11071 #endif /* HAVE_OPENAT */
11072             fd = open(path->narrow, flags, mode);
11073 #endif /* !MS_WINDOWS */
11074         Py_END_ALLOW_THREADS
11075     } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11076     _Py_END_SUPPRESS_IPH
11077 
11078 #ifdef HAVE_OPENAT
11079     if (openat_unavailable) {
11080         argument_unavailable_error(NULL, "dir_fd");
11081         return -1;
11082     }
11083 #endif
11084 
11085     if (fd < 0) {
11086         if (!async_err)
11087             PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11088         return -1;
11089     }
11090 
11091 #ifndef MS_WINDOWS
11092     if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11093         close(fd);
11094         return -1;
11095     }
11096 #endif
11097 
11098     return fd;
11099 }
11100 
11101 
11102 /*[clinic input]
11103 os.close
11104 
11105     fd: int
11106 
11107 Close a file descriptor.
11108 [clinic start generated code]*/
11109 
11110 static PyObject *
os_close_impl(PyObject * module,int fd)11111 os_close_impl(PyObject *module, int fd)
11112 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11113 {
11114     int res;
11115     /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11116      * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11117      * for more details.
11118      */
11119     Py_BEGIN_ALLOW_THREADS
11120     _Py_BEGIN_SUPPRESS_IPH
11121     res = close(fd);
11122     _Py_END_SUPPRESS_IPH
11123     Py_END_ALLOW_THREADS
11124     if (res < 0)
11125         return posix_error();
11126     Py_RETURN_NONE;
11127 }
11128 
11129 /*[clinic input]
11130 os.closerange
11131 
11132     fd_low: int
11133     fd_high: int
11134     /
11135 
11136 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11137 [clinic start generated code]*/
11138 
11139 static PyObject *
os_closerange_impl(PyObject * module,int fd_low,int fd_high)11140 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11141 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11142 {
11143     Py_BEGIN_ALLOW_THREADS
11144     _Py_closerange(fd_low, fd_high - 1);
11145     Py_END_ALLOW_THREADS
11146     Py_RETURN_NONE;
11147 }
11148 
11149 
11150 /*[clinic input]
11151 os.dup -> int
11152 
11153     fd: int
11154     /
11155 
11156 Return a duplicate of a file descriptor.
11157 [clinic start generated code]*/
11158 
11159 static int
os_dup_impl(PyObject * module,int fd)11160 os_dup_impl(PyObject *module, int fd)
11161 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11162 {
11163     return _Py_dup(fd);
11164 }
11165 
11166 // dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11167 // dup2.c provides working dup2() if and only if F_DUPFD is available.
11168 #if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11169 /*[clinic input]
11170 os.dup2 -> int
11171     fd: int
11172     fd2: int
11173     inheritable: bool=True
11174 
11175 Duplicate file descriptor.
11176 [clinic start generated code]*/
11177 
11178 static int
os_dup2_impl(PyObject * module,int fd,int fd2,int inheritable)11179 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11180 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11181 {
11182     int res = 0;
11183 #if defined(HAVE_DUP3) && \
11184     !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
11185     /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
11186     static int dup3_works = -1;
11187 #endif
11188 
11189     /* dup2() can fail with EINTR if the target FD is already open, because it
11190      * then has to be closed. See os_close_impl() for why we don't handle EINTR
11191      * upon close(), and therefore below.
11192      */
11193 #ifdef MS_WINDOWS
11194     Py_BEGIN_ALLOW_THREADS
11195     _Py_BEGIN_SUPPRESS_IPH
11196     res = dup2(fd, fd2);
11197     _Py_END_SUPPRESS_IPH
11198     Py_END_ALLOW_THREADS
11199     if (res < 0) {
11200         posix_error();
11201         return -1;
11202     }
11203     res = fd2; // msvcrt dup2 returns 0 on success.
11204 
11205     /* Character files like console cannot be make non-inheritable */
11206     if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11207         close(fd2);
11208         return -1;
11209     }
11210 
11211 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
11212     Py_BEGIN_ALLOW_THREADS
11213     if (!inheritable)
11214         res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
11215     else
11216         res = dup2(fd, fd2);
11217     Py_END_ALLOW_THREADS
11218     if (res < 0) {
11219         posix_error();
11220         return -1;
11221     }
11222 
11223 #else
11224 
11225 #ifdef HAVE_DUP3
11226     if (!inheritable && dup3_works != 0) {
11227         Py_BEGIN_ALLOW_THREADS
11228         res = dup3(fd, fd2, O_CLOEXEC);
11229         Py_END_ALLOW_THREADS
11230         if (res < 0) {
11231             if (dup3_works == -1)
11232                 dup3_works = (errno != ENOSYS);
11233             if (dup3_works) {
11234                 posix_error();
11235                 return -1;
11236             }
11237         }
11238     }
11239 
11240     if (inheritable || dup3_works == 0)
11241     {
11242 #endif
11243         Py_BEGIN_ALLOW_THREADS
11244         res = dup2(fd, fd2);
11245         Py_END_ALLOW_THREADS
11246         if (res < 0) {
11247             posix_error();
11248             return -1;
11249         }
11250 
11251         if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
11252             close(fd2);
11253             return -1;
11254         }
11255 #ifdef HAVE_DUP3
11256     }
11257 #endif
11258 
11259 #endif
11260 
11261     return res;
11262 }
11263 #endif
11264 
11265 
11266 #ifdef HAVE_LOCKF
11267 /*[clinic input]
11268 os.lockf
11269 
11270     fd: int
11271         An open file descriptor.
11272     command: int
11273         One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
11274     length: Py_off_t
11275         The number of bytes to lock, starting at the current position.
11276     /
11277 
11278 Apply, test or remove a POSIX lock on an open file descriptor.
11279 
11280 [clinic start generated code]*/
11281 
11282 static PyObject *
os_lockf_impl(PyObject * module,int fd,int command,Py_off_t length)11283 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
11284 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
11285 {
11286     int res;
11287 
11288     if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
11289         return NULL;
11290     }
11291 
11292     Py_BEGIN_ALLOW_THREADS
11293     res = lockf(fd, command, length);
11294     Py_END_ALLOW_THREADS
11295 
11296     if (res < 0)
11297         return posix_error();
11298 
11299     Py_RETURN_NONE;
11300 }
11301 #endif /* HAVE_LOCKF */
11302 
11303 
11304 /*[clinic input]
11305 os.lseek -> Py_off_t
11306 
11307     fd: int
11308         An open file descriptor, as returned by os.open().
11309     position: Py_off_t
11310         Position, interpreted relative to 'whence'.
11311     whence as how: int
11312         The relative position to seek from. Valid values are:
11313         - SEEK_SET: seek from the start of the file.
11314         - SEEK_CUR: seek from the current file position.
11315         - SEEK_END: seek from the end of the file.
11316     /
11317 
11318 Set the position of a file descriptor.  Return the new position.
11319 
11320 The return value is the number of bytes relative to the beginning of the file.
11321 [clinic start generated code]*/
11322 
11323 static Py_off_t
os_lseek_impl(PyObject * module,int fd,Py_off_t position,int how)11324 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
11325 /*[clinic end generated code: output=971e1efb6b30bd2f input=f096e754c5367504]*/
11326 {
11327     Py_off_t result;
11328 
11329 #ifdef SEEK_SET
11330     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
11331     switch (how) {
11332         case 0: how = SEEK_SET; break;
11333         case 1: how = SEEK_CUR; break;
11334         case 2: how = SEEK_END; break;
11335     }
11336 #endif /* SEEK_END */
11337 
11338     Py_BEGIN_ALLOW_THREADS
11339     _Py_BEGIN_SUPPRESS_IPH
11340 #ifdef MS_WINDOWS
11341     result = _lseeki64(fd, position, how);
11342 #else
11343     result = lseek(fd, position, how);
11344 #endif
11345     _Py_END_SUPPRESS_IPH
11346     Py_END_ALLOW_THREADS
11347     if (result < 0)
11348         posix_error();
11349 
11350     return result;
11351 }
11352 
11353 
11354 /*[clinic input]
11355 os.read
11356     fd: int
11357     length: Py_ssize_t
11358     /
11359 
11360 Read from a file descriptor.  Returns a bytes object.
11361 [clinic start generated code]*/
11362 
11363 static PyObject *
os_read_impl(PyObject * module,int fd,Py_ssize_t length)11364 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
11365 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
11366 {
11367     Py_ssize_t n;
11368     PyObject *buffer;
11369 
11370     if (length < 0) {
11371         errno = EINVAL;
11372         return posix_error();
11373     }
11374 
11375     length = Py_MIN(length, _PY_READ_MAX);
11376 
11377     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
11378     if (buffer == NULL)
11379         return NULL;
11380 
11381     n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
11382     if (n == -1) {
11383         Py_DECREF(buffer);
11384         return NULL;
11385     }
11386 
11387     if (n != length)
11388         _PyBytes_Resize(&buffer, n);
11389 
11390     return buffer;
11391 }
11392 
11393 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
11394                                 || defined(__APPLE__))) \
11395     || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
11396     || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
11397 static int
iov_setup(struct iovec ** iov,Py_buffer ** buf,PyObject * seq,Py_ssize_t cnt,int type)11398 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
11399 {
11400     Py_ssize_t i, j;
11401 
11402     *iov = PyMem_New(struct iovec, cnt);
11403     if (*iov == NULL) {
11404         PyErr_NoMemory();
11405         return -1;
11406     }
11407 
11408     *buf = PyMem_New(Py_buffer, cnt);
11409     if (*buf == NULL) {
11410         PyMem_Free(*iov);
11411         PyErr_NoMemory();
11412         return -1;
11413     }
11414 
11415     for (i = 0; i < cnt; i++) {
11416         PyObject *item = PySequence_GetItem(seq, i);
11417         if (item == NULL)
11418             goto fail;
11419         if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
11420             Py_DECREF(item);
11421             goto fail;
11422         }
11423         Py_DECREF(item);
11424         (*iov)[i].iov_base = (*buf)[i].buf;
11425         (*iov)[i].iov_len = (*buf)[i].len;
11426     }
11427     return 0;
11428 
11429 fail:
11430     PyMem_Free(*iov);
11431     for (j = 0; j < i; j++) {
11432         PyBuffer_Release(&(*buf)[j]);
11433     }
11434     PyMem_Free(*buf);
11435     return -1;
11436 }
11437 
11438 static void
iov_cleanup(struct iovec * iov,Py_buffer * buf,int cnt)11439 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
11440 {
11441     int i;
11442     PyMem_Free(iov);
11443     for (i = 0; i < cnt; i++) {
11444         PyBuffer_Release(&buf[i]);
11445     }
11446     PyMem_Free(buf);
11447 }
11448 #endif
11449 
11450 
11451 #ifdef HAVE_READV
11452 /*[clinic input]
11453 os.readv -> Py_ssize_t
11454 
11455     fd: int
11456     buffers: object
11457     /
11458 
11459 Read from a file descriptor fd into an iterable of buffers.
11460 
11461 The buffers should be mutable buffers accepting bytes.
11462 readv will transfer data into each buffer until it is full
11463 and then move on to the next buffer in the sequence to hold
11464 the rest of the data.
11465 
11466 readv returns the total number of bytes read,
11467 which may be less than the total capacity of all the buffers.
11468 [clinic start generated code]*/
11469 
11470 static Py_ssize_t
os_readv_impl(PyObject * module,int fd,PyObject * buffers)11471 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
11472 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
11473 {
11474     Py_ssize_t cnt, n;
11475     int async_err = 0;
11476     struct iovec *iov;
11477     Py_buffer *buf;
11478 
11479     if (!PySequence_Check(buffers)) {
11480         PyErr_SetString(PyExc_TypeError,
11481             "readv() arg 2 must be a sequence");
11482         return -1;
11483     }
11484 
11485     cnt = PySequence_Size(buffers);
11486     if (cnt < 0)
11487         return -1;
11488 
11489     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
11490         return -1;
11491 
11492     do {
11493         Py_BEGIN_ALLOW_THREADS
11494         n = readv(fd, iov, cnt);
11495         Py_END_ALLOW_THREADS
11496     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11497 
11498     int saved_errno = errno;
11499     iov_cleanup(iov, buf, cnt);
11500     if (n < 0) {
11501         if (!async_err) {
11502             errno = saved_errno;
11503             posix_error();
11504         }
11505         return -1;
11506     }
11507 
11508     return n;
11509 }
11510 #endif /* HAVE_READV */
11511 
11512 
11513 #ifdef HAVE_PREAD
11514 /*[clinic input]
11515 os.pread
11516 
11517     fd: int
11518     length: Py_ssize_t
11519     offset: Py_off_t
11520     /
11521 
11522 Read a number of bytes from a file descriptor starting at a particular offset.
11523 
11524 Read length bytes from file descriptor fd, starting at offset bytes from
11525 the beginning of the file.  The file offset remains unchanged.
11526 [clinic start generated code]*/
11527 
11528 static PyObject *
os_pread_impl(PyObject * module,int fd,Py_ssize_t length,Py_off_t offset)11529 os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
11530 /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
11531 {
11532     Py_ssize_t n;
11533     int async_err = 0;
11534     PyObject *buffer;
11535 
11536     if (length < 0) {
11537         errno = EINVAL;
11538         return posix_error();
11539     }
11540     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
11541     if (buffer == NULL)
11542         return NULL;
11543 
11544     do {
11545         Py_BEGIN_ALLOW_THREADS
11546         _Py_BEGIN_SUPPRESS_IPH
11547         n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
11548         _Py_END_SUPPRESS_IPH
11549         Py_END_ALLOW_THREADS
11550     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11551 
11552     if (n < 0) {
11553         if (!async_err) {
11554             posix_error();
11555         }
11556         Py_DECREF(buffer);
11557         return NULL;
11558     }
11559     if (n != length)
11560         _PyBytes_Resize(&buffer, n);
11561     return buffer;
11562 }
11563 #endif /* HAVE_PREAD */
11564 
11565 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
11566 /*[clinic input]
11567 os.preadv -> Py_ssize_t
11568 
11569     fd: int
11570     buffers: object
11571     offset: Py_off_t
11572     flags: int = 0
11573     /
11574 
11575 Reads from a file descriptor into a number of mutable bytes-like objects.
11576 
11577 Combines the functionality of readv() and pread(). As readv(), it will
11578 transfer data into each buffer until it is full and then move on to the next
11579 buffer in the sequence to hold the rest of the data. Its fourth argument,
11580 specifies the file offset at which the input operation is to be performed. It
11581 will return the total number of bytes read (which can be less than the total
11582 capacity of all the objects).
11583 
11584 The flags argument contains a bitwise OR of zero or more of the following flags:
11585 
11586 - RWF_HIPRI
11587 - RWF_NOWAIT
11588 
11589 Using non-zero flags requires Linux 4.6 or newer.
11590 [clinic start generated code]*/
11591 
11592 static Py_ssize_t
os_preadv_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)11593 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
11594                int flags)
11595 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
11596 {
11597     Py_ssize_t cnt, n;
11598     int async_err = 0;
11599     struct iovec *iov;
11600     Py_buffer *buf;
11601 
11602     if (!PySequence_Check(buffers)) {
11603         PyErr_SetString(PyExc_TypeError,
11604             "preadv2() arg 2 must be a sequence");
11605         return -1;
11606     }
11607 
11608     cnt = PySequence_Size(buffers);
11609     if (cnt < 0) {
11610         return -1;
11611     }
11612 
11613 #ifndef HAVE_PREADV2
11614     if(flags != 0) {
11615         argument_unavailable_error("preadv2", "flags");
11616         return -1;
11617     }
11618 #endif
11619 
11620     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
11621         return -1;
11622     }
11623 #ifdef HAVE_PREADV2
11624     do {
11625         Py_BEGIN_ALLOW_THREADS
11626         _Py_BEGIN_SUPPRESS_IPH
11627         n = preadv2(fd, iov, cnt, offset, flags);
11628         _Py_END_SUPPRESS_IPH
11629         Py_END_ALLOW_THREADS
11630     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11631 #else
11632     do {
11633 #if defined(__APPLE__) && defined(__clang__)
11634 /* This entire function will be removed from the module dict when the API
11635  * is not available.
11636  */
11637 #pragma clang diagnostic push
11638 #pragma clang diagnostic ignored "-Wunguarded-availability"
11639 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
11640 #endif
11641         Py_BEGIN_ALLOW_THREADS
11642         _Py_BEGIN_SUPPRESS_IPH
11643         n = preadv(fd, iov, cnt, offset);
11644         _Py_END_SUPPRESS_IPH
11645         Py_END_ALLOW_THREADS
11646     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11647 
11648 #if defined(__APPLE__) && defined(__clang__)
11649 #pragma clang diagnostic pop
11650 #endif
11651 
11652 #endif
11653 
11654     int saved_errno = errno;
11655     iov_cleanup(iov, buf, cnt);
11656     if (n < 0) {
11657         if (!async_err) {
11658             errno = saved_errno;
11659             posix_error();
11660         }
11661         return -1;
11662     }
11663 
11664     return n;
11665 }
11666 #endif /* HAVE_PREADV */
11667 
11668 
11669 /*[clinic input]
11670 os.write -> Py_ssize_t
11671 
11672     fd: int
11673     data: Py_buffer
11674     /
11675 
11676 Write a bytes object to a file descriptor.
11677 [clinic start generated code]*/
11678 
11679 static Py_ssize_t
os_write_impl(PyObject * module,int fd,Py_buffer * data)11680 os_write_impl(PyObject *module, int fd, Py_buffer *data)
11681 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
11682 {
11683     return _Py_write(fd, data->buf, data->len);
11684 }
11685 
11686 #ifdef HAVE_SENDFILE
11687 #ifdef __APPLE__
11688 /*[clinic input]
11689 os.sendfile
11690 
11691     out_fd: int
11692     in_fd: int
11693     offset: Py_off_t
11694     count as sbytes: Py_off_t
11695     headers: object(c_default="NULL") = ()
11696     trailers: object(c_default="NULL") = ()
11697     flags: int = 0
11698 
11699 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
11700 [clinic start generated code]*/
11701 
11702 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)11703 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
11704                  Py_off_t sbytes, PyObject *headers, PyObject *trailers,
11705                  int flags)
11706 /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
11707 #elif defined(__FreeBSD__) || defined(__DragonFly__)
11708 /*[clinic input]
11709 os.sendfile
11710 
11711     out_fd: int
11712     in_fd: int
11713     offset: Py_off_t
11714     count: Py_ssize_t
11715     headers: object(c_default="NULL") = ()
11716     trailers: object(c_default="NULL") = ()
11717     flags: int = 0
11718 
11719 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
11720 [clinic start generated code]*/
11721 
11722 static PyObject *
11723 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
11724                  Py_ssize_t count, PyObject *headers, PyObject *trailers,
11725                  int flags)
11726 /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
11727 #else
11728 /*[clinic input]
11729 os.sendfile
11730 
11731     out_fd: int
11732     in_fd: int
11733     offset as offobj: object
11734     count: Py_ssize_t
11735 
11736 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
11737 [clinic start generated code]*/
11738 
11739 static PyObject *
11740 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
11741                  Py_ssize_t count)
11742 /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
11743 #endif
11744 {
11745     Py_ssize_t ret;
11746     int async_err = 0;
11747 
11748 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
11749 #ifndef __APPLE__
11750     off_t sbytes;
11751 #endif
11752     Py_buffer *hbuf, *tbuf;
11753     struct sf_hdtr sf;
11754 
11755     sf.headers = NULL;
11756     sf.trailers = NULL;
11757 
11758     if (headers != NULL) {
11759         if (!PySequence_Check(headers)) {
11760             PyErr_SetString(PyExc_TypeError,
11761                 "sendfile() headers must be a sequence");
11762             return NULL;
11763         } else {
11764             Py_ssize_t i = PySequence_Size(headers);
11765             if (i < 0)
11766                 return NULL;
11767             if (i > INT_MAX) {
11768                 PyErr_SetString(PyExc_OverflowError,
11769                     "sendfile() header is too large");
11770                 return NULL;
11771             }
11772             if (i > 0) {
11773                 sf.hdr_cnt = (int)i;
11774                 if (iov_setup(&(sf.headers), &hbuf,
11775                               headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
11776                     return NULL;
11777 #ifdef __APPLE__
11778                 for (i = 0; i < sf.hdr_cnt; i++) {
11779                     Py_ssize_t blen = sf.headers[i].iov_len;
11780 # define OFF_T_MAX 0x7fffffffffffffff
11781                     if (sbytes >= OFF_T_MAX - blen) {
11782                         PyErr_SetString(PyExc_OverflowError,
11783                             "sendfile() header is too large");
11784                         return NULL;
11785                     }
11786                     sbytes += blen;
11787                 }
11788 #endif
11789             }
11790         }
11791     }
11792     if (trailers != NULL) {
11793         if (!PySequence_Check(trailers)) {
11794             PyErr_SetString(PyExc_TypeError,
11795                 "sendfile() trailers must be a sequence");
11796             return NULL;
11797         } else {
11798             Py_ssize_t i = PySequence_Size(trailers);
11799             if (i < 0)
11800                 return NULL;
11801             if (i > INT_MAX) {
11802                 PyErr_SetString(PyExc_OverflowError,
11803                     "sendfile() trailer is too large");
11804                 return NULL;
11805             }
11806             if (i > 0) {
11807                 sf.trl_cnt = (int)i;
11808                 if (iov_setup(&(sf.trailers), &tbuf,
11809                               trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
11810                     return NULL;
11811             }
11812         }
11813     }
11814 
11815     _Py_BEGIN_SUPPRESS_IPH
11816     do {
11817         Py_BEGIN_ALLOW_THREADS
11818 #ifdef __APPLE__
11819         ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
11820 #else
11821         ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
11822 #endif
11823         Py_END_ALLOW_THREADS
11824     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11825     _Py_END_SUPPRESS_IPH
11826 
11827     int saved_errno = errno;
11828     if (sf.headers != NULL)
11829         iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
11830     if (sf.trailers != NULL)
11831         iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
11832 
11833     if (ret < 0) {
11834         if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
11835             if (sbytes != 0) {
11836                 // some data has been sent
11837                 goto done;
11838             }
11839             // no data has been sent; upper application is supposed
11840             // to retry on EAGAIN or EBUSY
11841         }
11842         if (!async_err) {
11843             errno = saved_errno;
11844             posix_error();
11845         }
11846         return NULL;
11847     }
11848     goto done;
11849 
11850 done:
11851     #if !defined(HAVE_LARGEFILE_SUPPORT)
11852         return PyLong_FromLong(sbytes);
11853     #else
11854         return PyLong_FromLongLong(sbytes);
11855     #endif
11856 
11857 #else
11858 #ifdef __linux__
11859     if (offobj == Py_None) {
11860         do {
11861             Py_BEGIN_ALLOW_THREADS
11862             ret = sendfile(out_fd, in_fd, NULL, count);
11863             Py_END_ALLOW_THREADS
11864         } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11865         if (ret < 0)
11866             return (!async_err) ? posix_error() : NULL;
11867         return PyLong_FromSsize_t(ret);
11868     }
11869 #endif
11870     off_t offset;
11871     if (!Py_off_t_converter(offobj, &offset))
11872         return NULL;
11873 
11874 #if defined(__sun) && defined(__SVR4)
11875     // On Solaris, sendfile raises EINVAL rather than returning 0
11876     // when the offset is equal or bigger than the in_fd size.
11877     struct stat st;
11878 
11879     do {
11880         Py_BEGIN_ALLOW_THREADS
11881         ret = fstat(in_fd, &st);
11882         Py_END_ALLOW_THREADS
11883     } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11884     if (ret < 0)
11885         return (!async_err) ? posix_error() : NULL;
11886 
11887     if (offset >= st.st_size) {
11888         return PyLong_FromLong(0);
11889     }
11890 
11891     // On illumos specifically sendfile() may perform a partial write but
11892     // return -1/an error (in one confirmed case the destination socket
11893     // had a 5 second timeout set and errno was EAGAIN) and it's on the client
11894     // code to check if the offset parameter was modified by sendfile().
11895     //
11896     // We need this variable to track said change.
11897     off_t original_offset = offset;
11898 #endif
11899 
11900     do {
11901         Py_BEGIN_ALLOW_THREADS
11902         ret = sendfile(out_fd, in_fd, &offset, count);
11903 #if defined(__sun) && defined(__SVR4)
11904         // This handles illumos-specific sendfile() partial write behavior,
11905         // see a comment above for more details.
11906         if (ret < 0 && offset != original_offset) {
11907             ret = offset - original_offset;
11908         }
11909 #endif
11910         Py_END_ALLOW_THREADS
11911     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11912     if (ret < 0)
11913         return (!async_err) ? posix_error() : NULL;
11914     return PyLong_FromSsize_t(ret);
11915 #endif
11916 }
11917 #endif /* HAVE_SENDFILE */
11918 
11919 
11920 #if defined(__APPLE__)
11921 /*[clinic input]
11922 os._fcopyfile
11923 
11924     in_fd: int
11925     out_fd: int
11926     flags: int
11927     /
11928 
11929 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
11930 [clinic start generated code]*/
11931 
11932 static PyObject *
os__fcopyfile_impl(PyObject * module,int in_fd,int out_fd,int flags)11933 os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
11934 /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
11935 {
11936     int ret;
11937 
11938     Py_BEGIN_ALLOW_THREADS
11939     ret = fcopyfile(in_fd, out_fd, NULL, flags);
11940     Py_END_ALLOW_THREADS
11941     if (ret < 0)
11942         return posix_error();
11943     Py_RETURN_NONE;
11944 }
11945 #endif
11946 
11947 
11948 /*[clinic input]
11949 os.fstat
11950 
11951     fd : int
11952 
11953 Perform a stat system call on the given file descriptor.
11954 
11955 Like stat(), but for an open file descriptor.
11956 Equivalent to os.stat(fd).
11957 [clinic start generated code]*/
11958 
11959 static PyObject *
os_fstat_impl(PyObject * module,int fd)11960 os_fstat_impl(PyObject *module, int fd)
11961 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
11962 {
11963     STRUCT_STAT st;
11964     int res;
11965     int async_err = 0;
11966 
11967     do {
11968         Py_BEGIN_ALLOW_THREADS
11969         res = FSTAT(fd, &st);
11970         Py_END_ALLOW_THREADS
11971     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11972     if (res != 0) {
11973 #ifdef MS_WINDOWS
11974         return PyErr_SetFromWindowsErr(0);
11975 #else
11976         return (!async_err) ? posix_error() : NULL;
11977 #endif
11978     }
11979 
11980     return _pystat_fromstructstat(module, &st);
11981 }
11982 
11983 
11984 /*[clinic input]
11985 os.isatty -> bool
11986     fd: int
11987     /
11988 
11989 Return True if the fd is connected to a terminal.
11990 
11991 Return True if the file descriptor is an open file descriptor
11992 connected to the slave end of a terminal.
11993 [clinic start generated code]*/
11994 
11995 static int
os_isatty_impl(PyObject * module,int fd)11996 os_isatty_impl(PyObject *module, int fd)
11997 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
11998 {
11999     int return_value;
12000     Py_BEGIN_ALLOW_THREADS
12001     _Py_BEGIN_SUPPRESS_IPH
12002     return_value = isatty(fd);
12003     _Py_END_SUPPRESS_IPH
12004     Py_END_ALLOW_THREADS
12005     return return_value;
12006 }
12007 
12008 
12009 #ifdef HAVE_PIPE
12010 /*[clinic input]
12011 os.pipe
12012 
12013 Create a pipe.
12014 
12015 Returns a tuple of two file descriptors:
12016   (read_fd, write_fd)
12017 [clinic start generated code]*/
12018 
12019 static PyObject *
os_pipe_impl(PyObject * module)12020 os_pipe_impl(PyObject *module)
12021 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12022 {
12023     int fds[2];
12024 #ifdef MS_WINDOWS
12025     HANDLE read, write;
12026     SECURITY_ATTRIBUTES attr;
12027     BOOL ok;
12028 #else
12029     int res;
12030 #endif
12031 
12032 #ifdef MS_WINDOWS
12033     attr.nLength = sizeof(attr);
12034     attr.lpSecurityDescriptor = NULL;
12035     attr.bInheritHandle = FALSE;
12036 
12037     Py_BEGIN_ALLOW_THREADS
12038     ok = CreatePipe(&read, &write, &attr, 0);
12039     if (ok) {
12040         fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12041         fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12042         if (fds[0] == -1 || fds[1] == -1) {
12043             CloseHandle(read);
12044             CloseHandle(write);
12045             ok = 0;
12046         }
12047     }
12048     Py_END_ALLOW_THREADS
12049 
12050     if (!ok)
12051         return PyErr_SetFromWindowsErr(0);
12052 #else
12053 
12054 #ifdef HAVE_PIPE2
12055     Py_BEGIN_ALLOW_THREADS
12056     res = pipe2(fds, O_CLOEXEC);
12057     Py_END_ALLOW_THREADS
12058 
12059     if (res != 0 && errno == ENOSYS)
12060     {
12061 #endif
12062         Py_BEGIN_ALLOW_THREADS
12063         res = pipe(fds);
12064         Py_END_ALLOW_THREADS
12065 
12066         if (res == 0) {
12067             if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12068                 close(fds[0]);
12069                 close(fds[1]);
12070                 return NULL;
12071             }
12072             if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12073                 close(fds[0]);
12074                 close(fds[1]);
12075                 return NULL;
12076             }
12077         }
12078 #ifdef HAVE_PIPE2
12079     }
12080 #endif
12081 
12082     if (res != 0)
12083         return PyErr_SetFromErrno(PyExc_OSError);
12084 #endif /* !MS_WINDOWS */
12085     return Py_BuildValue("(ii)", fds[0], fds[1]);
12086 }
12087 #endif  /* HAVE_PIPE */
12088 
12089 
12090 #ifdef HAVE_PIPE2
12091 /*[clinic input]
12092 os.pipe2
12093 
12094     flags: int
12095     /
12096 
12097 Create a pipe with flags set atomically.
12098 
12099 Returns a tuple of two file descriptors:
12100   (read_fd, write_fd)
12101 
12102 flags can be constructed by ORing together one or more of these values:
12103 O_NONBLOCK, O_CLOEXEC.
12104 [clinic start generated code]*/
12105 
12106 static PyObject *
os_pipe2_impl(PyObject * module,int flags)12107 os_pipe2_impl(PyObject *module, int flags)
12108 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
12109 {
12110     int fds[2];
12111     int res;
12112 
12113     res = pipe2(fds, flags);
12114     if (res != 0)
12115         return posix_error();
12116     return Py_BuildValue("(ii)", fds[0], fds[1]);
12117 }
12118 #endif /* HAVE_PIPE2 */
12119 
12120 
12121 #ifdef HAVE_WRITEV
12122 /*[clinic input]
12123 os.writev -> Py_ssize_t
12124     fd: int
12125     buffers: object
12126     /
12127 
12128 Iterate over buffers, and write the contents of each to a file descriptor.
12129 
12130 Returns the total number of bytes written.
12131 buffers must be a sequence of bytes-like objects.
12132 [clinic start generated code]*/
12133 
12134 static Py_ssize_t
os_writev_impl(PyObject * module,int fd,PyObject * buffers)12135 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
12136 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
12137 {
12138     Py_ssize_t cnt;
12139     Py_ssize_t result;
12140     int async_err = 0;
12141     struct iovec *iov;
12142     Py_buffer *buf;
12143 
12144     if (!PySequence_Check(buffers)) {
12145         PyErr_SetString(PyExc_TypeError,
12146             "writev() arg 2 must be a sequence");
12147         return -1;
12148     }
12149     cnt = PySequence_Size(buffers);
12150     if (cnt < 0)
12151         return -1;
12152 
12153     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12154         return -1;
12155     }
12156 
12157     do {
12158         Py_BEGIN_ALLOW_THREADS
12159         result = writev(fd, iov, cnt);
12160         Py_END_ALLOW_THREADS
12161     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12162 
12163     if (result < 0 && !async_err)
12164         posix_error();
12165 
12166     iov_cleanup(iov, buf, cnt);
12167     return result;
12168 }
12169 #endif /* HAVE_WRITEV */
12170 
12171 
12172 #ifdef HAVE_PWRITE
12173 /*[clinic input]
12174 os.pwrite -> Py_ssize_t
12175 
12176     fd: int
12177     buffer: Py_buffer
12178     offset: Py_off_t
12179     /
12180 
12181 Write bytes to a file descriptor starting at a particular offset.
12182 
12183 Write buffer to fd, starting at offset bytes from the beginning of
12184 the file.  Returns the number of bytes written.  Does not change the
12185 current file offset.
12186 [clinic start generated code]*/
12187 
12188 static Py_ssize_t
os_pwrite_impl(PyObject * module,int fd,Py_buffer * buffer,Py_off_t offset)12189 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
12190 /*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
12191 {
12192     Py_ssize_t size;
12193     int async_err = 0;
12194 
12195     do {
12196         Py_BEGIN_ALLOW_THREADS
12197         _Py_BEGIN_SUPPRESS_IPH
12198         size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
12199         _Py_END_SUPPRESS_IPH
12200         Py_END_ALLOW_THREADS
12201     } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12202 
12203     if (size < 0 && !async_err)
12204         posix_error();
12205     return size;
12206 }
12207 #endif /* HAVE_PWRITE */
12208 
12209 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12210 /*[clinic input]
12211 os.pwritev -> Py_ssize_t
12212 
12213     fd: int
12214     buffers: object
12215     offset: Py_off_t
12216     flags: int = 0
12217     /
12218 
12219 Writes the contents of bytes-like objects to a file descriptor at a given offset.
12220 
12221 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
12222 of bytes-like objects. Buffers are processed in array order. Entire contents of first
12223 buffer is written before proceeding to second, and so on. The operating system may
12224 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
12225 This function writes the contents of each object to the file descriptor and returns
12226 the total number of bytes written.
12227 
12228 The flags argument contains a bitwise OR of zero or more of the following flags:
12229 
12230 - RWF_DSYNC
12231 - RWF_SYNC
12232 - RWF_APPEND
12233 
12234 Using non-zero flags requires Linux 4.7 or newer.
12235 [clinic start generated code]*/
12236 
12237 static Py_ssize_t
os_pwritev_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)12238 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12239                 int flags)
12240 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
12241 {
12242     Py_ssize_t cnt;
12243     Py_ssize_t result;
12244     int async_err = 0;
12245     struct iovec *iov;
12246     Py_buffer *buf;
12247 
12248     if (!PySequence_Check(buffers)) {
12249         PyErr_SetString(PyExc_TypeError,
12250             "pwritev() arg 2 must be a sequence");
12251         return -1;
12252     }
12253 
12254     cnt = PySequence_Size(buffers);
12255     if (cnt < 0) {
12256         return -1;
12257     }
12258 
12259 #ifndef HAVE_PWRITEV2
12260     if(flags != 0) {
12261         argument_unavailable_error("pwritev2", "flags");
12262         return -1;
12263     }
12264 #endif
12265 
12266     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
12267         return -1;
12268     }
12269 #ifdef HAVE_PWRITEV2
12270     do {
12271         Py_BEGIN_ALLOW_THREADS
12272         _Py_BEGIN_SUPPRESS_IPH
12273         result = pwritev2(fd, iov, cnt, offset, flags);
12274         _Py_END_SUPPRESS_IPH
12275         Py_END_ALLOW_THREADS
12276     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12277 #else
12278 
12279 #if defined(__APPLE__) && defined(__clang__)
12280 /* This entire function will be removed from the module dict when the API
12281  * is not available.
12282  */
12283 #pragma clang diagnostic push
12284 #pragma clang diagnostic ignored "-Wunguarded-availability"
12285 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
12286 #endif
12287     do {
12288         Py_BEGIN_ALLOW_THREADS
12289         _Py_BEGIN_SUPPRESS_IPH
12290         result = pwritev(fd, iov, cnt, offset);
12291         _Py_END_SUPPRESS_IPH
12292         Py_END_ALLOW_THREADS
12293     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12294 
12295 #if defined(__APPLE__) && defined(__clang__)
12296 #pragma clang diagnostic pop
12297 #endif
12298 
12299 #endif
12300 
12301     if (result < 0) {
12302         if (!async_err) {
12303             posix_error();
12304         }
12305         result = -1;
12306     }
12307     iov_cleanup(iov, buf, cnt);
12308 
12309     return result;
12310 }
12311 #endif /* HAVE_PWRITEV */
12312 
12313 #ifdef HAVE_COPY_FILE_RANGE
12314 /*[clinic input]
12315 
12316 os.copy_file_range
12317     src: int
12318         Source file descriptor.
12319     dst: int
12320         Destination file descriptor.
12321     count: Py_ssize_t
12322         Number of bytes to copy.
12323     offset_src: object = None
12324         Starting offset in src.
12325     offset_dst: object = None
12326         Starting offset in dst.
12327 
12328 Copy count bytes from one file descriptor to another.
12329 
12330 If offset_src is None, then src is read from the current position;
12331 respectively for offset_dst.
12332 [clinic start generated code]*/
12333 
12334 static PyObject *
os_copy_file_range_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst)12335 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12336                         PyObject *offset_src, PyObject *offset_dst)
12337 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
12338 {
12339     off_t offset_src_val, offset_dst_val;
12340     off_t *p_offset_src = NULL;
12341     off_t *p_offset_dst = NULL;
12342     Py_ssize_t ret;
12343     int async_err = 0;
12344     /* The flags argument is provided to allow
12345      * for future extensions and currently must be to 0. */
12346     int flags = 0;
12347 
12348 
12349     if (count < 0) {
12350         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
12351         return NULL;
12352     }
12353 
12354     if (offset_src != Py_None) {
12355         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
12356             return NULL;
12357         }
12358         p_offset_src = &offset_src_val;
12359     }
12360 
12361     if (offset_dst != Py_None) {
12362         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
12363             return NULL;
12364         }
12365         p_offset_dst = &offset_dst_val;
12366     }
12367 
12368     do {
12369         Py_BEGIN_ALLOW_THREADS
12370         ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
12371         Py_END_ALLOW_THREADS
12372     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12373 
12374     if (ret < 0) {
12375         return (!async_err) ? posix_error() : NULL;
12376     }
12377 
12378     return PyLong_FromSsize_t(ret);
12379 }
12380 #endif /* HAVE_COPY_FILE_RANGE*/
12381 
12382 #if (defined(HAVE_SPLICE) && !defined(_AIX))
12383 /*[clinic input]
12384 
12385 os.splice
12386     src: int
12387         Source file descriptor.
12388     dst: int
12389         Destination file descriptor.
12390     count: Py_ssize_t
12391         Number of bytes to copy.
12392     offset_src: object = None
12393         Starting offset in src.
12394     offset_dst: object = None
12395         Starting offset in dst.
12396     flags: unsigned_int = 0
12397         Flags to modify the semantics of the call.
12398 
12399 Transfer count bytes from one pipe to a descriptor or vice versa.
12400 
12401 If offset_src is None, then src is read from the current position;
12402 respectively for offset_dst. The offset associated to the file
12403 descriptor that refers to a pipe must be None.
12404 [clinic start generated code]*/
12405 
12406 static PyObject *
os_splice_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst,unsigned int flags)12407 os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
12408                PyObject *offset_src, PyObject *offset_dst,
12409                unsigned int flags)
12410 /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
12411 {
12412     off_t offset_src_val, offset_dst_val;
12413     off_t *p_offset_src = NULL;
12414     off_t *p_offset_dst = NULL;
12415     Py_ssize_t ret;
12416     int async_err = 0;
12417 
12418     if (count < 0) {
12419         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
12420         return NULL;
12421     }
12422 
12423     if (offset_src != Py_None) {
12424         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
12425             return NULL;
12426         }
12427         p_offset_src = &offset_src_val;
12428     }
12429 
12430     if (offset_dst != Py_None) {
12431         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
12432             return NULL;
12433         }
12434         p_offset_dst = &offset_dst_val;
12435     }
12436 
12437     do {
12438         Py_BEGIN_ALLOW_THREADS
12439         ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
12440         Py_END_ALLOW_THREADS
12441     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12442 
12443     if (ret < 0) {
12444         return (!async_err) ? posix_error() : NULL;
12445     }
12446 
12447     return PyLong_FromSsize_t(ret);
12448 }
12449 #endif /* HAVE_SPLICE*/
12450 
12451 #ifdef HAVE_MKFIFO
12452 /*[clinic input]
12453 os.mkfifo
12454 
12455     path: path_t
12456     mode: int=0o666
12457     *
12458     dir_fd: dir_fd(requires='mkfifoat')=None
12459 
12460 Create a "fifo" (a POSIX named pipe).
12461 
12462 If dir_fd is not None, it should be a file descriptor open to a directory,
12463   and path should be relative; path will then be relative to that directory.
12464 dir_fd may not be implemented on your platform.
12465   If it is unavailable, using it will raise a NotImplementedError.
12466 [clinic start generated code]*/
12467 
12468 static PyObject *
os_mkfifo_impl(PyObject * module,path_t * path,int mode,int dir_fd)12469 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
12470 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
12471 {
12472     int result;
12473     int async_err = 0;
12474 #ifdef HAVE_MKFIFOAT
12475     int mkfifoat_unavailable = 0;
12476 #endif
12477 
12478     do {
12479         Py_BEGIN_ALLOW_THREADS
12480 #ifdef HAVE_MKFIFOAT
12481         if (dir_fd != DEFAULT_DIR_FD) {
12482             if (HAVE_MKFIFOAT_RUNTIME) {
12483                 result = mkfifoat(dir_fd, path->narrow, mode);
12484 
12485             } else {
12486                 mkfifoat_unavailable = 1;
12487                 result = 0;
12488             }
12489         } else
12490 #endif
12491             result = mkfifo(path->narrow, mode);
12492         Py_END_ALLOW_THREADS
12493     } while (result != 0 && errno == EINTR &&
12494              !(async_err = PyErr_CheckSignals()));
12495 
12496 #ifdef HAVE_MKFIFOAT
12497     if (mkfifoat_unavailable) {
12498         argument_unavailable_error(NULL, "dir_fd");
12499         return NULL;
12500     }
12501 #endif
12502 
12503     if (result != 0)
12504         return (!async_err) ? posix_error() : NULL;
12505 
12506     Py_RETURN_NONE;
12507 }
12508 #endif /* HAVE_MKFIFO */
12509 
12510 
12511 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
12512 /*[clinic input]
12513 os.mknod
12514 
12515     path: path_t
12516     mode: int=0o600
12517     device: dev_t=0
12518     *
12519     dir_fd: dir_fd(requires='mknodat')=None
12520 
12521 Create a node in the file system.
12522 
12523 Create a node in the file system (file, device special file or named pipe)
12524 at path.  mode specifies both the permissions to use and the
12525 type of node to be created, being combined (bitwise OR) with one of
12526 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
12527 device defines the newly created device special file (probably using
12528 os.makedev()).  Otherwise device is ignored.
12529 
12530 If dir_fd is not None, it should be a file descriptor open to a directory,
12531   and path should be relative; path will then be relative to that directory.
12532 dir_fd may not be implemented on your platform.
12533   If it is unavailable, using it will raise a NotImplementedError.
12534 [clinic start generated code]*/
12535 
12536 static PyObject *
os_mknod_impl(PyObject * module,path_t * path,int mode,dev_t device,int dir_fd)12537 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
12538               int dir_fd)
12539 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
12540 {
12541     int result;
12542     int async_err = 0;
12543 #ifdef HAVE_MKNODAT
12544     int mknodat_unavailable = 0;
12545 #endif
12546 
12547     do {
12548         Py_BEGIN_ALLOW_THREADS
12549 #ifdef HAVE_MKNODAT
12550         if (dir_fd != DEFAULT_DIR_FD) {
12551             if (HAVE_MKNODAT_RUNTIME) {
12552                 result = mknodat(dir_fd, path->narrow, mode, device);
12553 
12554             } else {
12555                 mknodat_unavailable = 1;
12556                 result = 0;
12557             }
12558         } else
12559 #endif
12560             result = mknod(path->narrow, mode, device);
12561         Py_END_ALLOW_THREADS
12562     } while (result != 0 && errno == EINTR &&
12563              !(async_err = PyErr_CheckSignals()));
12564 #ifdef HAVE_MKNODAT
12565     if (mknodat_unavailable) {
12566         argument_unavailable_error(NULL, "dir_fd");
12567         return NULL;
12568     }
12569 #endif
12570     if (result != 0)
12571         return (!async_err) ? posix_error() : NULL;
12572 
12573     Py_RETURN_NONE;
12574 }
12575 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
12576 
12577 
12578 #ifdef HAVE_DEVICE_MACROS
12579 static PyObject *
major_minor_conv(unsigned int value)12580 major_minor_conv(unsigned int value)
12581 {
12582 #ifdef NODEV
12583     if (value == (unsigned int)NODEV) {
12584         return PyLong_FromLong((int)NODEV);
12585     }
12586 #endif
12587     return PyLong_FromUnsignedLong(value);
12588 }
12589 
12590 static int
major_minor_check(dev_t value)12591 major_minor_check(dev_t value)
12592 {
12593 #ifdef NODEV
12594     if (value == NODEV) {
12595         return 1;
12596     }
12597 #endif
12598     return (dev_t)(unsigned int)value == value;
12599 }
12600 
12601 /*[clinic input]
12602 os.major
12603 
12604     device: dev_t
12605     /
12606 
12607 Extracts a device major number from a raw device number.
12608 [clinic start generated code]*/
12609 
12610 static PyObject *
os_major_impl(PyObject * module,dev_t device)12611 os_major_impl(PyObject *module, dev_t device)
12612 /*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
12613 {
12614     return major_minor_conv(major(device));
12615 }
12616 
12617 
12618 /*[clinic input]
12619 os.minor
12620 
12621     device: dev_t
12622     /
12623 
12624 Extracts a device minor number from a raw device number.
12625 [clinic start generated code]*/
12626 
12627 static PyObject *
os_minor_impl(PyObject * module,dev_t device)12628 os_minor_impl(PyObject *module, dev_t device)
12629 /*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
12630 {
12631     return major_minor_conv(minor(device));
12632 }
12633 
12634 
12635 /*[clinic input]
12636 os.makedev -> dev_t
12637 
12638     major: dev_t
12639     minor: dev_t
12640     /
12641 
12642 Composes a raw device number from the major and minor device numbers.
12643 [clinic start generated code]*/
12644 
12645 static dev_t
os_makedev_impl(PyObject * module,dev_t major,dev_t minor)12646 os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
12647 /*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
12648 {
12649     if (!major_minor_check(major) || !major_minor_check(minor)) {
12650         PyErr_SetString(PyExc_OverflowError,
12651                         "Python int too large to convert to C unsigned int");
12652         return (dev_t)-1;
12653     }
12654     return makedev(major, minor);
12655 }
12656 #endif /* HAVE_DEVICE_MACROS */
12657 
12658 
12659 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
12660 /*[clinic input]
12661 os.ftruncate
12662 
12663     fd: int
12664     length: Py_off_t
12665     /
12666 
12667 Truncate a file, specified by file descriptor, to a specific length.
12668 [clinic start generated code]*/
12669 
12670 static PyObject *
os_ftruncate_impl(PyObject * module,int fd,Py_off_t length)12671 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
12672 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
12673 {
12674     int result;
12675     int async_err = 0;
12676 
12677     if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
12678         return NULL;
12679     }
12680 
12681     do {
12682         Py_BEGIN_ALLOW_THREADS
12683         _Py_BEGIN_SUPPRESS_IPH
12684 #ifdef MS_WINDOWS
12685         result = _chsize_s(fd, length);
12686 #else
12687         result = ftruncate(fd, length);
12688 #endif
12689         _Py_END_SUPPRESS_IPH
12690         Py_END_ALLOW_THREADS
12691     } while (result != 0 && errno == EINTR &&
12692              !(async_err = PyErr_CheckSignals()));
12693     if (result != 0)
12694         return (!async_err) ? posix_error() : NULL;
12695     Py_RETURN_NONE;
12696 }
12697 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
12698 
12699 
12700 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
12701 /*[clinic input]
12702 os.truncate
12703     path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
12704     length: Py_off_t
12705 
12706 Truncate a file, specified by path, to a specific length.
12707 
12708 On some platforms, path may also be specified as an open file descriptor.
12709   If this functionality is unavailable, using it raises an exception.
12710 [clinic start generated code]*/
12711 
12712 static PyObject *
os_truncate_impl(PyObject * module,path_t * path,Py_off_t length)12713 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
12714 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
12715 {
12716     int result;
12717 #ifdef MS_WINDOWS
12718     int fd;
12719 #endif
12720 
12721     if (path->fd != -1)
12722         return os_ftruncate_impl(module, path->fd, length);
12723 
12724     if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
12725         return NULL;
12726     }
12727 
12728     Py_BEGIN_ALLOW_THREADS
12729     _Py_BEGIN_SUPPRESS_IPH
12730 #ifdef MS_WINDOWS
12731     fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
12732     if (fd < 0)
12733         result = -1;
12734     else {
12735         result = _chsize_s(fd, length);
12736         close(fd);
12737         if (result < 0)
12738             errno = result;
12739     }
12740 #else
12741     result = truncate(path->narrow, length);
12742 #endif
12743     _Py_END_SUPPRESS_IPH
12744     Py_END_ALLOW_THREADS
12745     if (result < 0)
12746         return posix_path_error(path);
12747 
12748     Py_RETURN_NONE;
12749 }
12750 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
12751 
12752 
12753 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
12754    and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
12755    defined, which is the case in Python on AIX. AIX bug report:
12756    http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
12757 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
12758 #  define POSIX_FADVISE_AIX_BUG
12759 #endif
12760 
12761 
12762 /* GH-111804: Due to posix_fallocate() not having consistent semantics across
12763    OSs, support was dropped in WASI preview2. */
12764 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && \
12765     !defined(__wasi__)
12766 /*[clinic input]
12767 os.posix_fallocate
12768 
12769     fd: int
12770     offset: Py_off_t
12771     length: Py_off_t
12772     /
12773 
12774 Ensure a file has allocated at least a particular number of bytes on disk.
12775 
12776 Ensure that the file specified by fd encompasses a range of bytes
12777 starting at offset bytes from the beginning and continuing for length bytes.
12778 [clinic start generated code]*/
12779 
12780 static PyObject *
os_posix_fallocate_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length)12781 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
12782                         Py_off_t length)
12783 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
12784 {
12785     int result;
12786     int async_err = 0;
12787 
12788     do {
12789         Py_BEGIN_ALLOW_THREADS
12790         result = posix_fallocate(fd, offset, length);
12791         Py_END_ALLOW_THREADS
12792     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
12793 
12794     if (result == 0)
12795         Py_RETURN_NONE;
12796 
12797     if (async_err)
12798         return NULL;
12799 
12800     errno = result;
12801     return posix_error();
12802 }
12803 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG && !defined(__wasi__) */
12804 
12805 
12806 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
12807 /*[clinic input]
12808 os.posix_fadvise
12809 
12810     fd: int
12811     offset: Py_off_t
12812     length: Py_off_t
12813     advice: int
12814     /
12815 
12816 Announce an intention to access data in a specific pattern.
12817 
12818 Announce an intention to access data in a specific pattern, thus allowing
12819 the kernel to make optimizations.
12820 The advice applies to the region of the file specified by fd starting at
12821 offset and continuing for length bytes.
12822 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
12823 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
12824 POSIX_FADV_DONTNEED.
12825 [clinic start generated code]*/
12826 
12827 static PyObject *
os_posix_fadvise_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length,int advice)12828 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
12829                       Py_off_t length, int advice)
12830 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
12831 {
12832     int result;
12833     int async_err = 0;
12834 
12835     do {
12836         Py_BEGIN_ALLOW_THREADS
12837         result = posix_fadvise(fd, offset, length, advice);
12838         Py_END_ALLOW_THREADS
12839     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
12840 
12841     if (result == 0)
12842         Py_RETURN_NONE;
12843 
12844     if (async_err)
12845         return NULL;
12846 
12847     errno = result;
12848     return posix_error();
12849 }
12850 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
12851 
12852 
12853 #ifdef MS_WINDOWS
12854 static PyObject*
win32_putenv(PyObject * name,PyObject * value)12855 win32_putenv(PyObject *name, PyObject *value)
12856 {
12857     /* Search from index 1 because on Windows starting '=' is allowed for
12858        defining hidden environment variables. */
12859     if (PyUnicode_GET_LENGTH(name) == 0 ||
12860         PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
12861     {
12862         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
12863         return NULL;
12864     }
12865     PyObject *unicode;
12866     if (value != NULL) {
12867         unicode = PyUnicode_FromFormat("%U=%U", name, value);
12868     }
12869     else {
12870         unicode = PyUnicode_FromFormat("%U=", name);
12871     }
12872     if (unicode == NULL) {
12873         return NULL;
12874     }
12875 
12876     Py_ssize_t size;
12877     wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
12878     Py_DECREF(unicode);
12879 
12880     if (env == NULL) {
12881         return NULL;
12882     }
12883     if (size > _MAX_ENV) {
12884         PyErr_Format(PyExc_ValueError,
12885                      "the environment variable is longer than %u characters",
12886                      _MAX_ENV);
12887         PyMem_Free(env);
12888         return NULL;
12889     }
12890     if (wcslen(env) != (size_t)size) {
12891         PyErr_SetString(PyExc_ValueError,
12892                         "embedded null character");
12893         PyMem_Free(env);
12894         return NULL;
12895     }
12896 
12897     /* _wputenv() and SetEnvironmentVariableW() update the environment in the
12898        Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
12899        and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
12900 
12901        Prefer _wputenv() to be compatible with C libraries using CRT
12902        variables and CRT functions using these variables (ex: getenv()). */
12903     int err = _wputenv(env);
12904 
12905     if (err) {
12906         posix_error();
12907         PyMem_Free(env);
12908         return NULL;
12909     }
12910     PyMem_Free(env);
12911 
12912     Py_RETURN_NONE;
12913 }
12914 #endif
12915 
12916 
12917 #ifdef MS_WINDOWS
12918 /*[clinic input]
12919 os.putenv
12920 
12921     name: unicode
12922     value: unicode
12923     /
12924 
12925 Change or add an environment variable.
12926 [clinic start generated code]*/
12927 
12928 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)12929 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
12930 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
12931 {
12932     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
12933         return NULL;
12934     }
12935     return win32_putenv(name, value);
12936 }
12937 #else
12938 /*[clinic input]
12939 os.putenv
12940 
12941     name: FSConverter
12942     value: FSConverter
12943     /
12944 
12945 Change or add an environment variable.
12946 [clinic start generated code]*/
12947 
12948 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)12949 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
12950 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
12951 {
12952     const char *name_string = PyBytes_AS_STRING(name);
12953     const char *value_string = PyBytes_AS_STRING(value);
12954 
12955     if (strchr(name_string, '=') != NULL) {
12956         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
12957         return NULL;
12958     }
12959 
12960     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
12961         return NULL;
12962     }
12963 
12964     if (setenv(name_string, value_string, 1)) {
12965         return posix_error();
12966     }
12967     Py_RETURN_NONE;
12968 }
12969 #endif  /* !defined(MS_WINDOWS) */
12970 
12971 
12972 #ifdef MS_WINDOWS
12973 /*[clinic input]
12974 os.unsetenv
12975     name: unicode
12976     /
12977 
12978 Delete an environment variable.
12979 [clinic start generated code]*/
12980 
12981 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)12982 os_unsetenv_impl(PyObject *module, PyObject *name)
12983 /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
12984 {
12985     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
12986         return NULL;
12987     }
12988     return win32_putenv(name, NULL);
12989 }
12990 #else
12991 /*[clinic input]
12992 os.unsetenv
12993     name: FSConverter
12994     /
12995 
12996 Delete an environment variable.
12997 [clinic start generated code]*/
12998 
12999 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)13000 os_unsetenv_impl(PyObject *module, PyObject *name)
13001 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
13002 {
13003     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13004         return NULL;
13005     }
13006 #ifdef HAVE_BROKEN_UNSETENV
13007     unsetenv(PyBytes_AS_STRING(name));
13008 #else
13009     int err = unsetenv(PyBytes_AS_STRING(name));
13010     if (err) {
13011         return posix_error();
13012     }
13013 #endif
13014 
13015     Py_RETURN_NONE;
13016 }
13017 #endif /* !MS_WINDOWS */
13018 
13019 
13020 /*[clinic input]
13021 os.strerror
13022 
13023     code: int
13024     /
13025 
13026 Translate an error code to a message string.
13027 [clinic start generated code]*/
13028 
13029 static PyObject *
os_strerror_impl(PyObject * module,int code)13030 os_strerror_impl(PyObject *module, int code)
13031 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13032 {
13033     char *message = strerror(code);
13034     if (message == NULL) {
13035         PyErr_SetString(PyExc_ValueError,
13036                         "strerror() argument out of range");
13037         return NULL;
13038     }
13039     return PyUnicode_DecodeLocale(message, "surrogateescape");
13040 }
13041 
13042 
13043 #ifdef HAVE_SYS_WAIT_H
13044 #ifdef WCOREDUMP
13045 /*[clinic input]
13046 os.WCOREDUMP -> bool
13047 
13048     status: int
13049     /
13050 
13051 Return True if the process returning status was dumped to a core file.
13052 [clinic start generated code]*/
13053 
13054 static int
os_WCOREDUMP_impl(PyObject * module,int status)13055 os_WCOREDUMP_impl(PyObject *module, int status)
13056 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13057 {
13058     WAIT_TYPE wait_status;
13059     WAIT_STATUS_INT(wait_status) = status;
13060     return WCOREDUMP(wait_status);
13061 }
13062 #endif /* WCOREDUMP */
13063 
13064 
13065 #ifdef WIFCONTINUED
13066 /*[clinic input]
13067 os.WIFCONTINUED -> bool
13068 
13069     status: int
13070 
13071 Return True if a particular process was continued from a job control stop.
13072 
13073 Return True if the process returning status was continued from a
13074 job control stop.
13075 [clinic start generated code]*/
13076 
13077 static int
os_WIFCONTINUED_impl(PyObject * module,int status)13078 os_WIFCONTINUED_impl(PyObject *module, int status)
13079 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
13080 {
13081     WAIT_TYPE wait_status;
13082     WAIT_STATUS_INT(wait_status) = status;
13083     return WIFCONTINUED(wait_status);
13084 }
13085 #endif /* WIFCONTINUED */
13086 
13087 
13088 #ifdef WIFSTOPPED
13089 /*[clinic input]
13090 os.WIFSTOPPED -> bool
13091 
13092     status: int
13093 
13094 Return True if the process returning status was stopped.
13095 [clinic start generated code]*/
13096 
13097 static int
os_WIFSTOPPED_impl(PyObject * module,int status)13098 os_WIFSTOPPED_impl(PyObject *module, int status)
13099 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
13100 {
13101     WAIT_TYPE wait_status;
13102     WAIT_STATUS_INT(wait_status) = status;
13103     return WIFSTOPPED(wait_status);
13104 }
13105 #endif /* WIFSTOPPED */
13106 
13107 
13108 #ifdef WIFSIGNALED
13109 /*[clinic input]
13110 os.WIFSIGNALED -> bool
13111 
13112     status: int
13113 
13114 Return True if the process returning status was terminated by a signal.
13115 [clinic start generated code]*/
13116 
13117 static int
os_WIFSIGNALED_impl(PyObject * module,int status)13118 os_WIFSIGNALED_impl(PyObject *module, int status)
13119 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
13120 {
13121     WAIT_TYPE wait_status;
13122     WAIT_STATUS_INT(wait_status) = status;
13123     return WIFSIGNALED(wait_status);
13124 }
13125 #endif /* WIFSIGNALED */
13126 
13127 
13128 #ifdef WIFEXITED
13129 /*[clinic input]
13130 os.WIFEXITED -> bool
13131 
13132     status: int
13133 
13134 Return True if the process returning status exited via the exit() system call.
13135 [clinic start generated code]*/
13136 
13137 static int
os_WIFEXITED_impl(PyObject * module,int status)13138 os_WIFEXITED_impl(PyObject *module, int status)
13139 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
13140 {
13141     WAIT_TYPE wait_status;
13142     WAIT_STATUS_INT(wait_status) = status;
13143     return WIFEXITED(wait_status);
13144 }
13145 #endif /* WIFEXITED */
13146 
13147 
13148 #ifdef WEXITSTATUS
13149 /*[clinic input]
13150 os.WEXITSTATUS -> int
13151 
13152     status: int
13153 
13154 Return the process return code from status.
13155 [clinic start generated code]*/
13156 
13157 static int
os_WEXITSTATUS_impl(PyObject * module,int status)13158 os_WEXITSTATUS_impl(PyObject *module, int status)
13159 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
13160 {
13161     WAIT_TYPE wait_status;
13162     WAIT_STATUS_INT(wait_status) = status;
13163     return WEXITSTATUS(wait_status);
13164 }
13165 #endif /* WEXITSTATUS */
13166 
13167 
13168 #ifdef WTERMSIG
13169 /*[clinic input]
13170 os.WTERMSIG -> int
13171 
13172     status: int
13173 
13174 Return the signal that terminated the process that provided the status value.
13175 [clinic start generated code]*/
13176 
13177 static int
os_WTERMSIG_impl(PyObject * module,int status)13178 os_WTERMSIG_impl(PyObject *module, int status)
13179 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
13180 {
13181     WAIT_TYPE wait_status;
13182     WAIT_STATUS_INT(wait_status) = status;
13183     return WTERMSIG(wait_status);
13184 }
13185 #endif /* WTERMSIG */
13186 
13187 
13188 #ifdef WSTOPSIG
13189 /*[clinic input]
13190 os.WSTOPSIG -> int
13191 
13192     status: int
13193 
13194 Return the signal that stopped the process that provided the status value.
13195 [clinic start generated code]*/
13196 
13197 static int
os_WSTOPSIG_impl(PyObject * module,int status)13198 os_WSTOPSIG_impl(PyObject *module, int status)
13199 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
13200 {
13201     WAIT_TYPE wait_status;
13202     WAIT_STATUS_INT(wait_status) = status;
13203     return WSTOPSIG(wait_status);
13204 }
13205 #endif /* WSTOPSIG */
13206 #endif /* HAVE_SYS_WAIT_H */
13207 
13208 
13209 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
13210 #ifdef _SCO_DS
13211 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
13212    needed definitions in sys/statvfs.h */
13213 #define _SVID3
13214 #endif
13215 #include <sys/statvfs.h>
13216 
13217 #ifdef __APPLE__
13218 /* On macOS struct statvfs uses 32-bit integers for block counts,
13219  * resulting in overflow when filesystems are larger than 4TB. Therefore
13220  * os.statvfs is implemented in terms of statfs(2).
13221  */
13222 
13223 static PyObject*
_pystatvfs_fromstructstatfs(PyObject * module,struct statfs st)13224 _pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
13225     PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13226     PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13227     if (v == NULL) {
13228         return NULL;
13229     }
13230 
13231     long flags = 0;
13232     if (st.f_flags & MNT_RDONLY) {
13233         flags |= ST_RDONLY;
13234     }
13235     if (st.f_flags & MNT_NOSUID) {
13236         flags |= ST_NOSUID;
13237     }
13238 
13239     _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
13240 
13241 #define SET_ITEM(SEQ, INDEX, EXPR)                       \
13242     do {                                                 \
13243         PyObject *obj = (EXPR);                          \
13244         if (obj == NULL) {                               \
13245             Py_DECREF((SEQ));                            \
13246             return NULL;                                 \
13247         }                                                \
13248         PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
13249     } while (0)
13250 
13251     SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
13252     SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
13253     SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
13254     SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
13255     SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
13256     SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
13257     SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
13258     SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
13259     SET_ITEM(v, 8, PyLong_FromLong((long) flags));
13260 
13261     SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
13262     SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13263 
13264 #undef SET_ITEM
13265 
13266     return v;
13267 }
13268 
13269 #else
13270 
13271 
13272 
13273 static PyObject*
_pystatvfs_fromstructstatvfs(PyObject * module,struct statvfs st)13274 _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
13275     PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
13276     PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
13277     if (v == NULL)
13278         return NULL;
13279 
13280     int pos = 0;
13281 
13282 #define SET_RESULT(CALL)                                     \
13283     do {                                                     \
13284         PyObject *item = (CALL);                             \
13285         if (item == NULL) {                                  \
13286             Py_DECREF(v);                                    \
13287             return NULL;                                     \
13288         }                                                    \
13289         PyStructSequence_SET_ITEM(v, pos++, item);           \
13290     } while(0)
13291 
13292 #if !defined(HAVE_LARGEFILE_SUPPORT)
13293     SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13294     SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13295     SET_RESULT(PyLong_FromLong((long) st.f_blocks));
13296     SET_RESULT(PyLong_FromLong((long) st.f_bfree));
13297     SET_RESULT(PyLong_FromLong((long) st.f_bavail));
13298     SET_RESULT(PyLong_FromLong((long) st.f_files));
13299     SET_RESULT(PyLong_FromLong((long) st.f_ffree));
13300     SET_RESULT(PyLong_FromLong((long) st.f_favail));
13301     SET_RESULT(PyLong_FromLong((long) st.f_flag));
13302     SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13303 #else
13304     SET_RESULT(PyLong_FromLong((long) st.f_bsize));
13305     SET_RESULT(PyLong_FromLong((long) st.f_frsize));
13306     SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
13307     SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
13308     SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
13309     SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
13310     SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
13311     SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
13312     SET_RESULT(PyLong_FromLong((long) st.f_flag));
13313     SET_RESULT(PyLong_FromLong((long) st.f_namemax));
13314 #endif
13315 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
13316  * (issue #32390). */
13317 #if defined(_AIX) && defined(_ALL_SOURCE)
13318     SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
13319 #else
13320     SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
13321 #endif
13322 
13323 #undef SET_RESULT
13324 
13325     return v;
13326 }
13327 
13328 #endif
13329 
13330 
13331 /*[clinic input]
13332 os.fstatvfs
13333     fd: int
13334     /
13335 
13336 Perform an fstatvfs system call on the given fd.
13337 
13338 Equivalent to statvfs(fd).
13339 [clinic start generated code]*/
13340 
13341 static PyObject *
os_fstatvfs_impl(PyObject * module,int fd)13342 os_fstatvfs_impl(PyObject *module, int fd)
13343 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
13344 {
13345     int result;
13346     int async_err = 0;
13347 #ifdef __APPLE__
13348     struct statfs st;
13349     /* On macOS os.fstatvfs is implemented using fstatfs(2) because
13350      * the former uses 32-bit values for block counts.
13351      */
13352     do {
13353         Py_BEGIN_ALLOW_THREADS
13354         result = fstatfs(fd, &st);
13355         Py_END_ALLOW_THREADS
13356     } while (result != 0 && errno == EINTR &&
13357              !(async_err = PyErr_CheckSignals()));
13358     if (result != 0)
13359         return (!async_err) ? posix_error() : NULL;
13360 
13361     return _pystatvfs_fromstructstatfs(module, st);
13362 #else
13363     struct statvfs st;
13364 
13365     do {
13366         Py_BEGIN_ALLOW_THREADS
13367         result = fstatvfs(fd, &st);
13368         Py_END_ALLOW_THREADS
13369     } while (result != 0 && errno == EINTR &&
13370              !(async_err = PyErr_CheckSignals()));
13371     if (result != 0)
13372         return (!async_err) ? posix_error() : NULL;
13373 
13374     return _pystatvfs_fromstructstatvfs(module, st);
13375 #endif
13376 }
13377 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
13378 
13379 
13380 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
13381 #include <sys/statvfs.h>
13382 /*[clinic input]
13383 os.statvfs
13384 
13385     path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
13386 
13387 Perform a statvfs system call on the given path.
13388 
13389 path may always be specified as a string.
13390 On some platforms, path may also be specified as an open file descriptor.
13391   If this functionality is unavailable, using it raises an exception.
13392 [clinic start generated code]*/
13393 
13394 static PyObject *
os_statvfs_impl(PyObject * module,path_t * path)13395 os_statvfs_impl(PyObject *module, path_t *path)
13396 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
13397 {
13398     int result;
13399 
13400 #ifdef __APPLE__
13401     /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
13402      * the former uses 32-bit values for block counts.
13403      */
13404     struct statfs st;
13405 
13406     Py_BEGIN_ALLOW_THREADS
13407     if (path->fd != -1) {
13408         result = fstatfs(path->fd, &st);
13409     }
13410     else
13411         result = statfs(path->narrow, &st);
13412     Py_END_ALLOW_THREADS
13413 
13414     if (result) {
13415         return path_error(path);
13416     }
13417 
13418     return _pystatvfs_fromstructstatfs(module, st);
13419 
13420 #else
13421     struct statvfs st;
13422 
13423     Py_BEGIN_ALLOW_THREADS
13424 #ifdef HAVE_FSTATVFS
13425     if (path->fd != -1) {
13426         result = fstatvfs(path->fd, &st);
13427     }
13428     else
13429 #endif
13430         result = statvfs(path->narrow, &st);
13431     Py_END_ALLOW_THREADS
13432 
13433     if (result) {
13434         return path_error(path);
13435     }
13436 
13437     return _pystatvfs_fromstructstatvfs(module, st);
13438 #endif
13439 }
13440 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
13441 
13442 
13443 #ifdef MS_WINDOWS
13444 /*[clinic input]
13445 os._getdiskusage
13446 
13447     path: path_t
13448 
13449 Return disk usage statistics about the given path as a (total, free) tuple.
13450 [clinic start generated code]*/
13451 
13452 static PyObject *
os__getdiskusage_impl(PyObject * module,path_t * path)13453 os__getdiskusage_impl(PyObject *module, path_t *path)
13454 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
13455 {
13456     BOOL retval;
13457     ULARGE_INTEGER _, total, free;
13458     DWORD err = 0;
13459 
13460     Py_BEGIN_ALLOW_THREADS
13461     retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
13462     Py_END_ALLOW_THREADS
13463     if (retval == 0) {
13464         if (GetLastError() == ERROR_DIRECTORY) {
13465             wchar_t *dir_path = NULL;
13466 
13467             dir_path = PyMem_New(wchar_t, path->length + 1);
13468             if (dir_path == NULL) {
13469                 return PyErr_NoMemory();
13470             }
13471 
13472             wcscpy_s(dir_path, path->length + 1, path->wide);
13473 
13474             if (_dirnameW(dir_path) != -1) {
13475                 Py_BEGIN_ALLOW_THREADS
13476                 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
13477                 Py_END_ALLOW_THREADS
13478             }
13479             /* Record the last error in case it's modified by PyMem_Free. */
13480             err = GetLastError();
13481             PyMem_Free(dir_path);
13482             if (retval) {
13483                 goto success;
13484             }
13485         }
13486         return PyErr_SetFromWindowsErr(err);
13487     }
13488 
13489 success:
13490     return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
13491 }
13492 #endif /* MS_WINDOWS */
13493 
13494 
13495 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
13496  * It maps strings representing configuration variable names to
13497  * integer values, allowing those functions to be called with the
13498  * magic names instead of polluting the module's namespace with tons of
13499  * rarely-used constants.  There are three separate tables that use
13500  * these definitions.
13501  *
13502  * This code is always included, even if none of the interfaces that
13503  * need it are included.  The #if hackery needed to avoid it would be
13504  * sufficiently pervasive that it's not worth the loss of readability.
13505  */
13506 struct constdef {
13507     const char *name;
13508     int value;
13509 };
13510 
13511 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)13512 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
13513               size_t tablesize)
13514 {
13515     if (PyLong_Check(arg)) {
13516         int value = PyLong_AsInt(arg);
13517         if (value == -1 && PyErr_Occurred())
13518             return 0;
13519         *valuep = value;
13520         return 1;
13521     }
13522     else {
13523         /* look up the value in the table using a binary search */
13524         size_t lo = 0;
13525         size_t mid;
13526         size_t hi = tablesize;
13527         int cmp;
13528         const char *confname;
13529         if (!PyUnicode_Check(arg)) {
13530             PyErr_SetString(PyExc_TypeError,
13531                 "configuration names must be strings or integers");
13532             return 0;
13533         }
13534         confname = PyUnicode_AsUTF8(arg);
13535         if (confname == NULL)
13536             return 0;
13537         while (lo < hi) {
13538             mid = (lo + hi) / 2;
13539             cmp = strcmp(confname, table[mid].name);
13540             if (cmp < 0)
13541                 hi = mid;
13542             else if (cmp > 0)
13543                 lo = mid + 1;
13544             else {
13545                 *valuep = table[mid].value;
13546                 return 1;
13547             }
13548         }
13549         PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
13550         return 0;
13551     }
13552 }
13553 
13554 
13555 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
13556 static struct constdef  posix_constants_pathconf[] = {
13557 #ifdef _PC_ABI_AIO_XFER_MAX
13558     {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
13559 #endif
13560 #ifdef _PC_ABI_ASYNC_IO
13561     {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
13562 #endif
13563 #ifdef _PC_ASYNC_IO
13564     {"PC_ASYNC_IO",     _PC_ASYNC_IO},
13565 #endif
13566 #ifdef _PC_CHOWN_RESTRICTED
13567     {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
13568 #endif
13569 #ifdef _PC_FILESIZEBITS
13570     {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
13571 #endif
13572 #ifdef _PC_LAST
13573     {"PC_LAST", _PC_LAST},
13574 #endif
13575 #ifdef _PC_LINK_MAX
13576     {"PC_LINK_MAX",     _PC_LINK_MAX},
13577 #endif
13578 #ifdef _PC_MAX_CANON
13579     {"PC_MAX_CANON",    _PC_MAX_CANON},
13580 #endif
13581 #ifdef _PC_MAX_INPUT
13582     {"PC_MAX_INPUT",    _PC_MAX_INPUT},
13583 #endif
13584 #ifdef _PC_NAME_MAX
13585     {"PC_NAME_MAX",     _PC_NAME_MAX},
13586 #endif
13587 #ifdef _PC_NO_TRUNC
13588     {"PC_NO_TRUNC",     _PC_NO_TRUNC},
13589 #endif
13590 #ifdef _PC_PATH_MAX
13591     {"PC_PATH_MAX",     _PC_PATH_MAX},
13592 #endif
13593 #ifdef _PC_PIPE_BUF
13594     {"PC_PIPE_BUF",     _PC_PIPE_BUF},
13595 #endif
13596 #ifdef _PC_PRIO_IO
13597     {"PC_PRIO_IO",      _PC_PRIO_IO},
13598 #endif
13599 #ifdef _PC_SOCK_MAXBUF
13600     {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
13601 #endif
13602 #ifdef _PC_SYNC_IO
13603     {"PC_SYNC_IO",      _PC_SYNC_IO},
13604 #endif
13605 #ifdef _PC_VDISABLE
13606     {"PC_VDISABLE",     _PC_VDISABLE},
13607 #endif
13608 #ifdef _PC_ACL_ENABLED
13609     {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
13610 #endif
13611 #ifdef _PC_MIN_HOLE_SIZE
13612     {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
13613 #endif
13614 #ifdef _PC_ALLOC_SIZE_MIN
13615     {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
13616 #endif
13617 #ifdef _PC_REC_INCR_XFER_SIZE
13618     {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
13619 #endif
13620 #ifdef _PC_REC_MAX_XFER_SIZE
13621     {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
13622 #endif
13623 #ifdef _PC_REC_MIN_XFER_SIZE
13624     {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
13625 #endif
13626 #ifdef _PC_REC_XFER_ALIGN
13627     {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
13628 #endif
13629 #ifdef _PC_SYMLINK_MAX
13630     {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
13631 #endif
13632 #ifdef _PC_XATTR_ENABLED
13633     {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
13634 #endif
13635 #ifdef _PC_XATTR_EXISTS
13636     {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
13637 #endif
13638 #ifdef _PC_TIMESTAMP_RESOLUTION
13639     {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
13640 #endif
13641 };
13642 
13643 static int
conv_path_confname(PyObject * arg,int * valuep)13644 conv_path_confname(PyObject *arg, int *valuep)
13645 {
13646     return conv_confname(arg, valuep, posix_constants_pathconf,
13647                          sizeof(posix_constants_pathconf)
13648                            / sizeof(struct constdef));
13649 }
13650 #endif
13651 
13652 
13653 #ifdef HAVE_FPATHCONF
13654 /*[clinic input]
13655 os.fpathconf -> long
13656 
13657     fd: fildes
13658     name: path_confname
13659     /
13660 
13661 Return the configuration limit name for the file descriptor fd.
13662 
13663 If there is no limit, return -1.
13664 [clinic start generated code]*/
13665 
13666 static long
os_fpathconf_impl(PyObject * module,int fd,int name)13667 os_fpathconf_impl(PyObject *module, int fd, int name)
13668 /*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
13669 {
13670     long limit;
13671 
13672     errno = 0;
13673     limit = fpathconf(fd, name);
13674     if (limit == -1 && errno != 0)
13675         posix_error();
13676 
13677     return limit;
13678 }
13679 #endif /* HAVE_FPATHCONF */
13680 
13681 
13682 #ifdef HAVE_PATHCONF
13683 /*[clinic input]
13684 os.pathconf -> long
13685     path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
13686     name: path_confname
13687 
13688 Return the configuration limit name for the file or directory path.
13689 
13690 If there is no limit, return -1.
13691 On some platforms, path may also be specified as an open file descriptor.
13692   If this functionality is unavailable, using it raises an exception.
13693 [clinic start generated code]*/
13694 
13695 static long
os_pathconf_impl(PyObject * module,path_t * path,int name)13696 os_pathconf_impl(PyObject *module, path_t *path, int name)
13697 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
13698 {
13699     long limit;
13700 
13701     errno = 0;
13702 #ifdef HAVE_FPATHCONF
13703     if (path->fd != -1)
13704         limit = fpathconf(path->fd, name);
13705     else
13706 #endif
13707         limit = pathconf(path->narrow, name);
13708     if (limit == -1 && errno != 0) {
13709         if (errno == EINVAL)
13710             /* could be a path or name problem */
13711             posix_error();
13712         else
13713             path_error(path);
13714     }
13715 
13716     return limit;
13717 }
13718 #endif /* HAVE_PATHCONF */
13719 
13720 #ifdef HAVE_CONFSTR
13721 static struct constdef posix_constants_confstr[] = {
13722 #ifdef _CS_ARCHITECTURE
13723     {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
13724 #endif
13725 #ifdef _CS_GNU_LIBC_VERSION
13726     {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
13727 #endif
13728 #ifdef _CS_GNU_LIBPTHREAD_VERSION
13729     {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
13730 #endif
13731 #ifdef _CS_HOSTNAME
13732     {"CS_HOSTNAME",     _CS_HOSTNAME},
13733 #endif
13734 #ifdef _CS_HW_PROVIDER
13735     {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
13736 #endif
13737 #ifdef _CS_HW_SERIAL
13738     {"CS_HW_SERIAL",    _CS_HW_SERIAL},
13739 #endif
13740 #ifdef _CS_INITTAB_NAME
13741     {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
13742 #endif
13743 #ifdef _CS_LFS64_CFLAGS
13744     {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
13745 #endif
13746 #ifdef _CS_LFS64_LDFLAGS
13747     {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
13748 #endif
13749 #ifdef _CS_LFS64_LIBS
13750     {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
13751 #endif
13752 #ifdef _CS_LFS64_LINTFLAGS
13753     {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
13754 #endif
13755 #ifdef _CS_LFS_CFLAGS
13756     {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
13757 #endif
13758 #ifdef _CS_LFS_LDFLAGS
13759     {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
13760 #endif
13761 #ifdef _CS_LFS_LIBS
13762     {"CS_LFS_LIBS",     _CS_LFS_LIBS},
13763 #endif
13764 #ifdef _CS_LFS_LINTFLAGS
13765     {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
13766 #endif
13767 #ifdef _CS_MACHINE
13768     {"CS_MACHINE",      _CS_MACHINE},
13769 #endif
13770 #ifdef _CS_PATH
13771     {"CS_PATH", _CS_PATH},
13772 #endif
13773 #ifdef _CS_RELEASE
13774     {"CS_RELEASE",      _CS_RELEASE},
13775 #endif
13776 #ifdef _CS_SRPC_DOMAIN
13777     {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
13778 #endif
13779 #ifdef _CS_SYSNAME
13780     {"CS_SYSNAME",      _CS_SYSNAME},
13781 #endif
13782 #ifdef _CS_VERSION
13783     {"CS_VERSION",      _CS_VERSION},
13784 #endif
13785 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
13786     {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
13787 #endif
13788 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
13789     {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
13790 #endif
13791 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
13792     {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
13793 #endif
13794 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
13795     {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
13796 #endif
13797 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
13798     {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
13799 #endif
13800 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
13801     {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
13802 #endif
13803 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
13804     {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
13805 #endif
13806 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
13807     {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
13808 #endif
13809 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
13810     {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
13811 #endif
13812 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
13813     {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
13814 #endif
13815 #ifdef _CS_XBS5_LP64_OFF64_LIBS
13816     {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
13817 #endif
13818 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
13819     {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
13820 #endif
13821 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
13822     {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
13823 #endif
13824 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
13825     {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
13826 #endif
13827 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
13828     {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
13829 #endif
13830 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
13831     {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
13832 #endif
13833 #ifdef _MIPS_CS_AVAIL_PROCESSORS
13834     {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
13835 #endif
13836 #ifdef _MIPS_CS_BASE
13837     {"MIPS_CS_BASE",    _MIPS_CS_BASE},
13838 #endif
13839 #ifdef _MIPS_CS_HOSTID
13840     {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
13841 #endif
13842 #ifdef _MIPS_CS_HW_NAME
13843     {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
13844 #endif
13845 #ifdef _MIPS_CS_NUM_PROCESSORS
13846     {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
13847 #endif
13848 #ifdef _MIPS_CS_OSREL_MAJ
13849     {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
13850 #endif
13851 #ifdef _MIPS_CS_OSREL_MIN
13852     {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
13853 #endif
13854 #ifdef _MIPS_CS_OSREL_PATCH
13855     {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
13856 #endif
13857 #ifdef _MIPS_CS_OS_NAME
13858     {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
13859 #endif
13860 #ifdef _MIPS_CS_OS_PROVIDER
13861     {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
13862 #endif
13863 #ifdef _MIPS_CS_PROCESSORS
13864     {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
13865 #endif
13866 #ifdef _MIPS_CS_SERIAL
13867     {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
13868 #endif
13869 #ifdef _MIPS_CS_VENDOR
13870     {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
13871 #endif
13872 };
13873 
13874 static int
conv_confstr_confname(PyObject * arg,int * valuep)13875 conv_confstr_confname(PyObject *arg, int *valuep)
13876 {
13877     return conv_confname(arg, valuep, posix_constants_confstr,
13878                          sizeof(posix_constants_confstr)
13879                            / sizeof(struct constdef));
13880 }
13881 
13882 
13883 /*[clinic input]
13884 os.confstr
13885 
13886     name: confstr_confname
13887     /
13888 
13889 Return a string-valued system configuration variable.
13890 [clinic start generated code]*/
13891 
13892 static PyObject *
os_confstr_impl(PyObject * module,int name)13893 os_confstr_impl(PyObject *module, int name)
13894 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
13895 {
13896     PyObject *result = NULL;
13897     char buffer[255];
13898     size_t len;
13899 
13900     errno = 0;
13901     len = confstr(name, buffer, sizeof(buffer));
13902     if (len == 0) {
13903         if (errno) {
13904             posix_error();
13905             return NULL;
13906         }
13907         else {
13908             Py_RETURN_NONE;
13909         }
13910     }
13911 
13912     if (len >= sizeof(buffer)) {
13913         size_t len2;
13914         char *buf = PyMem_Malloc(len);
13915         if (buf == NULL)
13916             return PyErr_NoMemory();
13917         len2 = confstr(name, buf, len);
13918         assert(len == len2);
13919         result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
13920         PyMem_Free(buf);
13921     }
13922     else
13923         result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
13924     return result;
13925 }
13926 #endif /* HAVE_CONFSTR */
13927 
13928 
13929 #ifdef HAVE_SYSCONF
13930 static struct constdef posix_constants_sysconf[] = {
13931 #ifdef _SC_2_CHAR_TERM
13932     {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
13933 #endif
13934 #ifdef _SC_2_C_BIND
13935     {"SC_2_C_BIND",     _SC_2_C_BIND},
13936 #endif
13937 #ifdef _SC_2_C_DEV
13938     {"SC_2_C_DEV",      _SC_2_C_DEV},
13939 #endif
13940 #ifdef _SC_2_C_VERSION
13941     {"SC_2_C_VERSION",  _SC_2_C_VERSION},
13942 #endif
13943 #ifdef _SC_2_FORT_DEV
13944     {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
13945 #endif
13946 #ifdef _SC_2_FORT_RUN
13947     {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
13948 #endif
13949 #ifdef _SC_2_LOCALEDEF
13950     {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
13951 #endif
13952 #ifdef _SC_2_SW_DEV
13953     {"SC_2_SW_DEV",     _SC_2_SW_DEV},
13954 #endif
13955 #ifdef _SC_2_UPE
13956     {"SC_2_UPE",        _SC_2_UPE},
13957 #endif
13958 #ifdef _SC_2_VERSION
13959     {"SC_2_VERSION",    _SC_2_VERSION},
13960 #endif
13961 #ifdef _SC_ABI_ASYNCHRONOUS_IO
13962     {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
13963 #endif
13964 #ifdef _SC_ACL
13965     {"SC_ACL",  _SC_ACL},
13966 #endif
13967 #ifdef _SC_AIO_LISTIO_MAX
13968     {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
13969 #endif
13970 #ifdef _SC_AIO_MAX
13971     {"SC_AIO_MAX",      _SC_AIO_MAX},
13972 #endif
13973 #ifdef _SC_AIO_PRIO_DELTA_MAX
13974     {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
13975 #endif
13976 #ifdef _SC_ARG_MAX
13977     {"SC_ARG_MAX",      _SC_ARG_MAX},
13978 #endif
13979 #ifdef _SC_ASYNCHRONOUS_IO
13980     {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
13981 #endif
13982 #ifdef _SC_ATEXIT_MAX
13983     {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
13984 #endif
13985 #ifdef _SC_AUDIT
13986     {"SC_AUDIT",        _SC_AUDIT},
13987 #endif
13988 #ifdef _SC_AVPHYS_PAGES
13989     {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
13990 #endif
13991 #ifdef _SC_BC_BASE_MAX
13992     {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
13993 #endif
13994 #ifdef _SC_BC_DIM_MAX
13995     {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
13996 #endif
13997 #ifdef _SC_BC_SCALE_MAX
13998     {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
13999 #endif
14000 #ifdef _SC_BC_STRING_MAX
14001     {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14002 #endif
14003 #ifdef _SC_CAP
14004     {"SC_CAP",  _SC_CAP},
14005 #endif
14006 #ifdef _SC_CHARCLASS_NAME_MAX
14007     {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14008 #endif
14009 #ifdef _SC_CHAR_BIT
14010     {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14011 #endif
14012 #ifdef _SC_CHAR_MAX
14013     {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14014 #endif
14015 #ifdef _SC_CHAR_MIN
14016     {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14017 #endif
14018 #ifdef _SC_CHILD_MAX
14019     {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14020 #endif
14021 #ifdef _SC_CLK_TCK
14022     {"SC_CLK_TCK",      _SC_CLK_TCK},
14023 #endif
14024 #ifdef _SC_COHER_BLKSZ
14025     {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14026 #endif
14027 #ifdef _SC_COLL_WEIGHTS_MAX
14028     {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14029 #endif
14030 #ifdef _SC_DCACHE_ASSOC
14031     {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14032 #endif
14033 #ifdef _SC_DCACHE_BLKSZ
14034     {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14035 #endif
14036 #ifdef _SC_DCACHE_LINESZ
14037     {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14038 #endif
14039 #ifdef _SC_DCACHE_SZ
14040     {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14041 #endif
14042 #ifdef _SC_DCACHE_TBLKSZ
14043     {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14044 #endif
14045 #ifdef _SC_DELAYTIMER_MAX
14046     {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14047 #endif
14048 #ifdef _SC_EQUIV_CLASS_MAX
14049     {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14050 #endif
14051 #ifdef _SC_EXPR_NEST_MAX
14052     {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14053 #endif
14054 #ifdef _SC_FSYNC
14055     {"SC_FSYNC",        _SC_FSYNC},
14056 #endif
14057 #ifdef _SC_GETGR_R_SIZE_MAX
14058     {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14059 #endif
14060 #ifdef _SC_GETPW_R_SIZE_MAX
14061     {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14062 #endif
14063 #ifdef _SC_ICACHE_ASSOC
14064     {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14065 #endif
14066 #ifdef _SC_ICACHE_BLKSZ
14067     {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14068 #endif
14069 #ifdef _SC_ICACHE_LINESZ
14070     {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14071 #endif
14072 #ifdef _SC_ICACHE_SZ
14073     {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14074 #endif
14075 #ifdef _SC_INF
14076     {"SC_INF",  _SC_INF},
14077 #endif
14078 #ifdef _SC_INT_MAX
14079     {"SC_INT_MAX",      _SC_INT_MAX},
14080 #endif
14081 #ifdef _SC_INT_MIN
14082     {"SC_INT_MIN",      _SC_INT_MIN},
14083 #endif
14084 #ifdef _SC_IOV_MAX
14085     {"SC_IOV_MAX",      _SC_IOV_MAX},
14086 #endif
14087 #ifdef _SC_IP_SECOPTS
14088     {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
14089 #endif
14090 #ifdef _SC_JOB_CONTROL
14091     {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
14092 #endif
14093 #ifdef _SC_KERN_POINTERS
14094     {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
14095 #endif
14096 #ifdef _SC_KERN_SIM
14097     {"SC_KERN_SIM",     _SC_KERN_SIM},
14098 #endif
14099 #ifdef _SC_LINE_MAX
14100     {"SC_LINE_MAX",     _SC_LINE_MAX},
14101 #endif
14102 #ifdef _SC_LOGIN_NAME_MAX
14103     {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
14104 #endif
14105 #ifdef _SC_LOGNAME_MAX
14106     {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
14107 #endif
14108 #ifdef _SC_LONG_BIT
14109     {"SC_LONG_BIT",     _SC_LONG_BIT},
14110 #endif
14111 #ifdef _SC_MAC
14112     {"SC_MAC",  _SC_MAC},
14113 #endif
14114 #ifdef _SC_MAPPED_FILES
14115     {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
14116 #endif
14117 #ifdef _SC_MAXPID
14118     {"SC_MAXPID",       _SC_MAXPID},
14119 #endif
14120 #ifdef _SC_MB_LEN_MAX
14121     {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
14122 #endif
14123 #ifdef _SC_MEMLOCK
14124     {"SC_MEMLOCK",      _SC_MEMLOCK},
14125 #endif
14126 #ifdef _SC_MEMLOCK_RANGE
14127     {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
14128 #endif
14129 #ifdef _SC_MEMORY_PROTECTION
14130     {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
14131 #endif
14132 #ifdef _SC_MESSAGE_PASSING
14133     {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
14134 #endif
14135 #ifdef _SC_MMAP_FIXED_ALIGNMENT
14136     {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
14137 #endif
14138 #ifdef _SC_MQ_OPEN_MAX
14139     {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
14140 #endif
14141 #ifdef _SC_MQ_PRIO_MAX
14142     {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
14143 #endif
14144 #ifdef _SC_NACLS_MAX
14145     {"SC_NACLS_MAX",    _SC_NACLS_MAX},
14146 #endif
14147 #ifdef _SC_NGROUPS_MAX
14148     {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
14149 #endif
14150 #ifdef _SC_NL_ARGMAX
14151     {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
14152 #endif
14153 #ifdef _SC_NL_LANGMAX
14154     {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
14155 #endif
14156 #ifdef _SC_NL_MSGMAX
14157     {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
14158 #endif
14159 #ifdef _SC_NL_NMAX
14160     {"SC_NL_NMAX",      _SC_NL_NMAX},
14161 #endif
14162 #ifdef _SC_NL_SETMAX
14163     {"SC_NL_SETMAX",    _SC_NL_SETMAX},
14164 #endif
14165 #ifdef _SC_NL_TEXTMAX
14166     {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
14167 #endif
14168 #ifdef _SC_NPROCESSORS_CONF
14169     {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
14170 #endif
14171 #ifdef _SC_NPROCESSORS_ONLN
14172     {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
14173 #endif
14174 #ifdef _SC_NPROC_CONF
14175     {"SC_NPROC_CONF",   _SC_NPROC_CONF},
14176 #endif
14177 #ifdef _SC_NPROC_ONLN
14178     {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
14179 #endif
14180 #ifdef _SC_NZERO
14181     {"SC_NZERO",        _SC_NZERO},
14182 #endif
14183 #ifdef _SC_OPEN_MAX
14184     {"SC_OPEN_MAX",     _SC_OPEN_MAX},
14185 #endif
14186 #ifdef _SC_PAGESIZE
14187     {"SC_PAGESIZE",     _SC_PAGESIZE},
14188 #endif
14189 #ifdef _SC_PAGE_SIZE
14190     {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
14191 #endif
14192 #ifdef _SC_AIX_REALMEM
14193     {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
14194 #endif
14195 #ifdef _SC_PASS_MAX
14196     {"SC_PASS_MAX",     _SC_PASS_MAX},
14197 #endif
14198 #ifdef _SC_PHYS_PAGES
14199     {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
14200 #endif
14201 #ifdef _SC_PII
14202     {"SC_PII",  _SC_PII},
14203 #endif
14204 #ifdef _SC_PII_INTERNET
14205     {"SC_PII_INTERNET", _SC_PII_INTERNET},
14206 #endif
14207 #ifdef _SC_PII_INTERNET_DGRAM
14208     {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
14209 #endif
14210 #ifdef _SC_PII_INTERNET_STREAM
14211     {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
14212 #endif
14213 #ifdef _SC_PII_OSI
14214     {"SC_PII_OSI",      _SC_PII_OSI},
14215 #endif
14216 #ifdef _SC_PII_OSI_CLTS
14217     {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
14218 #endif
14219 #ifdef _SC_PII_OSI_COTS
14220     {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
14221 #endif
14222 #ifdef _SC_PII_OSI_M
14223     {"SC_PII_OSI_M",    _SC_PII_OSI_M},
14224 #endif
14225 #ifdef _SC_PII_SOCKET
14226     {"SC_PII_SOCKET",   _SC_PII_SOCKET},
14227 #endif
14228 #ifdef _SC_PII_XTI
14229     {"SC_PII_XTI",      _SC_PII_XTI},
14230 #endif
14231 #ifdef _SC_POLL
14232     {"SC_POLL", _SC_POLL},
14233 #endif
14234 #ifdef _SC_PRIORITIZED_IO
14235     {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
14236 #endif
14237 #ifdef _SC_PRIORITY_SCHEDULING
14238     {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
14239 #endif
14240 #ifdef _SC_REALTIME_SIGNALS
14241     {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
14242 #endif
14243 #ifdef _SC_RE_DUP_MAX
14244     {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
14245 #endif
14246 #ifdef _SC_RTSIG_MAX
14247     {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
14248 #endif
14249 #ifdef _SC_SAVED_IDS
14250     {"SC_SAVED_IDS",    _SC_SAVED_IDS},
14251 #endif
14252 #ifdef _SC_SCHAR_MAX
14253     {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
14254 #endif
14255 #ifdef _SC_SCHAR_MIN
14256     {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
14257 #endif
14258 #ifdef _SC_SELECT
14259     {"SC_SELECT",       _SC_SELECT},
14260 #endif
14261 #ifdef _SC_SEMAPHORES
14262     {"SC_SEMAPHORES",   _SC_SEMAPHORES},
14263 #endif
14264 #ifdef _SC_SEM_NSEMS_MAX
14265     {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
14266 #endif
14267 #ifdef _SC_SEM_VALUE_MAX
14268     {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
14269 #endif
14270 #ifdef _SC_SHARED_MEMORY_OBJECTS
14271     {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
14272 #endif
14273 #ifdef _SC_SHRT_MAX
14274     {"SC_SHRT_MAX",     _SC_SHRT_MAX},
14275 #endif
14276 #ifdef _SC_SHRT_MIN
14277     {"SC_SHRT_MIN",     _SC_SHRT_MIN},
14278 #endif
14279 #ifdef _SC_SIGQUEUE_MAX
14280     {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
14281 #endif
14282 #ifdef _SC_SIGRT_MAX
14283     {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
14284 #endif
14285 #ifdef _SC_SIGRT_MIN
14286     {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
14287 #endif
14288 #ifdef _SC_SOFTPOWER
14289     {"SC_SOFTPOWER",    _SC_SOFTPOWER},
14290 #endif
14291 #ifdef _SC_SPLIT_CACHE
14292     {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
14293 #endif
14294 #ifdef _SC_SSIZE_MAX
14295     {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
14296 #endif
14297 #ifdef _SC_STACK_PROT
14298     {"SC_STACK_PROT",   _SC_STACK_PROT},
14299 #endif
14300 #ifdef _SC_STREAM_MAX
14301     {"SC_STREAM_MAX",   _SC_STREAM_MAX},
14302 #endif
14303 #ifdef _SC_SYNCHRONIZED_IO
14304     {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
14305 #endif
14306 #ifdef _SC_THREADS
14307     {"SC_THREADS",      _SC_THREADS},
14308 #endif
14309 #ifdef _SC_THREAD_ATTR_STACKADDR
14310     {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
14311 #endif
14312 #ifdef _SC_THREAD_ATTR_STACKSIZE
14313     {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
14314 #endif
14315 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
14316     {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
14317 #endif
14318 #ifdef _SC_THREAD_KEYS_MAX
14319     {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
14320 #endif
14321 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
14322     {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
14323 #endif
14324 #ifdef _SC_THREAD_PRIO_INHERIT
14325     {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
14326 #endif
14327 #ifdef _SC_THREAD_PRIO_PROTECT
14328     {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
14329 #endif
14330 #ifdef _SC_THREAD_PROCESS_SHARED
14331     {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
14332 #endif
14333 #ifdef _SC_THREAD_SAFE_FUNCTIONS
14334     {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
14335 #endif
14336 #ifdef _SC_THREAD_STACK_MIN
14337     {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
14338 #endif
14339 #ifdef _SC_THREAD_THREADS_MAX
14340     {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
14341 #endif
14342 #ifdef _SC_TIMERS
14343     {"SC_TIMERS",       _SC_TIMERS},
14344 #endif
14345 #ifdef _SC_TIMER_MAX
14346     {"SC_TIMER_MAX",    _SC_TIMER_MAX},
14347 #endif
14348 #ifdef _SC_TTY_NAME_MAX
14349     {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
14350 #endif
14351 #ifdef _SC_TZNAME_MAX
14352     {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
14353 #endif
14354 #ifdef _SC_T_IOV_MAX
14355     {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
14356 #endif
14357 #ifdef _SC_UCHAR_MAX
14358     {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
14359 #endif
14360 #ifdef _SC_UINT_MAX
14361     {"SC_UINT_MAX",     _SC_UINT_MAX},
14362 #endif
14363 #ifdef _SC_UIO_MAXIOV
14364     {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
14365 #endif
14366 #ifdef _SC_ULONG_MAX
14367     {"SC_ULONG_MAX",    _SC_ULONG_MAX},
14368 #endif
14369 #ifdef _SC_USHRT_MAX
14370     {"SC_USHRT_MAX",    _SC_USHRT_MAX},
14371 #endif
14372 #ifdef _SC_VERSION
14373     {"SC_VERSION",      _SC_VERSION},
14374 #endif
14375 #ifdef _SC_WORD_BIT
14376     {"SC_WORD_BIT",     _SC_WORD_BIT},
14377 #endif
14378 #ifdef _SC_XBS5_ILP32_OFF32
14379     {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
14380 #endif
14381 #ifdef _SC_XBS5_ILP32_OFFBIG
14382     {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
14383 #endif
14384 #ifdef _SC_XBS5_LP64_OFF64
14385     {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
14386 #endif
14387 #ifdef _SC_XBS5_LPBIG_OFFBIG
14388     {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
14389 #endif
14390 #ifdef _SC_XOPEN_CRYPT
14391     {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
14392 #endif
14393 #ifdef _SC_XOPEN_ENH_I18N
14394     {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
14395 #endif
14396 #ifdef _SC_XOPEN_LEGACY
14397     {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
14398 #endif
14399 #ifdef _SC_XOPEN_REALTIME
14400     {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
14401 #endif
14402 #ifdef _SC_XOPEN_REALTIME_THREADS
14403     {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
14404 #endif
14405 #ifdef _SC_XOPEN_SHM
14406     {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
14407 #endif
14408 #ifdef _SC_XOPEN_UNIX
14409     {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
14410 #endif
14411 #ifdef _SC_XOPEN_VERSION
14412     {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
14413 #endif
14414 #ifdef _SC_XOPEN_XCU_VERSION
14415     {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
14416 #endif
14417 #ifdef _SC_XOPEN_XPG2
14418     {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
14419 #endif
14420 #ifdef _SC_XOPEN_XPG3
14421     {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
14422 #endif
14423 #ifdef _SC_XOPEN_XPG4
14424     {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
14425 #endif
14426 #ifdef _SC_MINSIGSTKSZ
14427     {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
14428 #endif
14429 };
14430 
14431 static int
conv_sysconf_confname(PyObject * arg,int * valuep)14432 conv_sysconf_confname(PyObject *arg, int *valuep)
14433 {
14434     return conv_confname(arg, valuep, posix_constants_sysconf,
14435                          sizeof(posix_constants_sysconf)
14436                            / sizeof(struct constdef));
14437 }
14438 
14439 
14440 /*[clinic input]
14441 os.sysconf -> long
14442     name: sysconf_confname
14443     /
14444 
14445 Return an integer-valued system configuration variable.
14446 [clinic start generated code]*/
14447 
14448 static long
os_sysconf_impl(PyObject * module,int name)14449 os_sysconf_impl(PyObject *module, int name)
14450 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
14451 {
14452     long value;
14453 
14454     errno = 0;
14455     value = sysconf(name);
14456     if (value == -1 && errno != 0)
14457         posix_error();
14458     return value;
14459 }
14460 #endif /* HAVE_SYSCONF */
14461 
14462 
14463 /* This code is used to ensure that the tables of configuration value names
14464  * are in sorted order as required by conv_confname(), and also to build
14465  * the exported dictionaries that are used to publish information about the
14466  * names available on the host platform.
14467  *
14468  * Sorting the table at runtime ensures that the table is properly ordered
14469  * when used, even for platforms we're not able to test on.  It also makes
14470  * it easier to add additional entries to the tables.
14471  */
14472 
14473 static int
cmp_constdefs(const void * v1,const void * v2)14474 cmp_constdefs(const void *v1,  const void *v2)
14475 {
14476     const struct constdef *c1 =
14477     (const struct constdef *) v1;
14478     const struct constdef *c2 =
14479     (const struct constdef *) v2;
14480 
14481     return strcmp(c1->name, c2->name);
14482 }
14483 
14484 static int
setup_confname_table(struct constdef * table,size_t tablesize,const char * tablename,PyObject * module)14485 setup_confname_table(struct constdef *table, size_t tablesize,
14486                      const char *tablename, PyObject *module)
14487 {
14488     PyObject *d = NULL;
14489     size_t i;
14490 
14491     qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
14492     d = PyDict_New();
14493     if (d == NULL)
14494         return -1;
14495 
14496     for (i=0; i < tablesize; ++i) {
14497         PyObject *o = PyLong_FromLong(table[i].value);
14498         if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
14499             Py_XDECREF(o);
14500             Py_DECREF(d);
14501             return -1;
14502         }
14503         Py_DECREF(o);
14504     }
14505     return PyModule_Add(module, tablename, d);
14506 }
14507 
14508 /* Return -1 on failure, 0 on success. */
14509 static int
setup_confname_tables(PyObject * module)14510 setup_confname_tables(PyObject *module)
14511 {
14512 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14513     if (setup_confname_table(posix_constants_pathconf,
14514                              sizeof(posix_constants_pathconf)
14515                                / sizeof(struct constdef),
14516                              "pathconf_names", module))
14517         return -1;
14518 #endif
14519 #ifdef HAVE_CONFSTR
14520     if (setup_confname_table(posix_constants_confstr,
14521                              sizeof(posix_constants_confstr)
14522                                / sizeof(struct constdef),
14523                              "confstr_names", module))
14524         return -1;
14525 #endif
14526 #ifdef HAVE_SYSCONF
14527     if (setup_confname_table(posix_constants_sysconf,
14528                              sizeof(posix_constants_sysconf)
14529                                / sizeof(struct constdef),
14530                              "sysconf_names", module))
14531         return -1;
14532 #endif
14533     return 0;
14534 }
14535 
14536 
14537 /*[clinic input]
14538 os.abort
14539 
14540 Abort the interpreter immediately.
14541 
14542 This function 'dumps core' or otherwise fails in the hardest way possible
14543 on the hosting operating system.  This function never returns.
14544 [clinic start generated code]*/
14545 
14546 static PyObject *
os_abort_impl(PyObject * module)14547 os_abort_impl(PyObject *module)
14548 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
14549 {
14550     abort();
14551     /*NOTREACHED*/
14552 #ifndef __clang__
14553     /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
14554        GCC emits a warning without "return NULL;" (compiler bug?), but Clang
14555        is smarter and emits a warning on the return. */
14556     Py_FatalError("abort() called from Python code didn't abort!");
14557     return NULL;
14558 #endif
14559 }
14560 
14561 #ifdef MS_WINDOWS
14562 /* Grab ShellExecute dynamically from shell32 */
14563 static int has_ShellExecute = -1;
14564 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
14565                                               LPCWSTR, INT);
14566 static int
check_ShellExecute(void)14567 check_ShellExecute(void)
14568 {
14569     HINSTANCE hShell32;
14570 
14571     /* only recheck */
14572     if (-1 == has_ShellExecute) {
14573         Py_BEGIN_ALLOW_THREADS
14574         /* Security note: this call is not vulnerable to "DLL hijacking".
14575            SHELL32 is part of "KnownDLLs" and so Windows always load
14576            the system SHELL32.DLL, even if there is another SHELL32.DLL
14577            in the DLL search path. */
14578         hShell32 = LoadLibraryW(L"SHELL32");
14579         if (hShell32) {
14580             *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
14581                                             "ShellExecuteW");
14582             has_ShellExecute = Py_ShellExecuteW != NULL;
14583         } else {
14584             has_ShellExecute = 0;
14585         }
14586         Py_END_ALLOW_THREADS
14587     }
14588     return has_ShellExecute;
14589 }
14590 
14591 
14592 /*[clinic input]
14593 os.startfile
14594     filepath: path_t
14595     operation: Py_UNICODE = NULL
14596     arguments: Py_UNICODE = NULL
14597     cwd: path_t(nullable=True) = None
14598     show_cmd: int = 1
14599 
14600 Start a file with its associated application.
14601 
14602 When "operation" is not specified or "open", this acts like
14603 double-clicking the file in Explorer, or giving the file name as an
14604 argument to the DOS "start" command: the file is opened with whatever
14605 application (if any) its extension is associated.
14606 When another "operation" is given, it specifies what should be done with
14607 the file.  A typical operation is "print".
14608 
14609 "arguments" is passed to the application, but should be omitted if the
14610 file is a document.
14611 
14612 "cwd" is the working directory for the operation. If "filepath" is
14613 relative, it will be resolved against this directory. This argument
14614 should usually be an absolute path.
14615 
14616 "show_cmd" can be used to override the recommended visibility option.
14617 See the Windows ShellExecute documentation for values.
14618 
14619 startfile returns as soon as the associated application is launched.
14620 There is no option to wait for the application to close, and no way
14621 to retrieve the application's exit status.
14622 
14623 The filepath is relative to the current directory.  If you want to use
14624 an absolute path, make sure the first character is not a slash ("/");
14625 the underlying Win32 ShellExecute function doesn't work if it is.
14626 [clinic start generated code]*/
14627 
14628 static PyObject *
os_startfile_impl(PyObject * module,path_t * filepath,const wchar_t * operation,const wchar_t * arguments,path_t * cwd,int show_cmd)14629 os_startfile_impl(PyObject *module, path_t *filepath,
14630                   const wchar_t *operation, const wchar_t *arguments,
14631                   path_t *cwd, int show_cmd)
14632 /*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
14633 {
14634     HINSTANCE rc;
14635 
14636     if(!check_ShellExecute()) {
14637         /* If the OS doesn't have ShellExecute, return a
14638            NotImplementedError. */
14639         return PyErr_Format(PyExc_NotImplementedError,
14640             "startfile not available on this platform");
14641     }
14642 
14643     if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
14644         return NULL;
14645     }
14646     if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
14647                     arguments, cwd->object ? cwd->object : Py_None,
14648                     show_cmd) < 0) {
14649         return NULL;
14650     }
14651 
14652     Py_BEGIN_ALLOW_THREADS
14653     rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
14654                           arguments, cwd->wide, show_cmd);
14655     Py_END_ALLOW_THREADS
14656 
14657     if (rc <= (HINSTANCE)32) {
14658         win32_error_object("startfile", filepath->object);
14659         return NULL;
14660     }
14661     Py_RETURN_NONE;
14662 }
14663 #endif /* MS_WINDOWS */
14664 
14665 
14666 #ifdef HAVE_GETLOADAVG
14667 /*[clinic input]
14668 os.getloadavg
14669 
14670 Return average recent system load information.
14671 
14672 Return the number of processes in the system run queue averaged over
14673 the last 1, 5, and 15 minutes as a tuple of three floats.
14674 Raises OSError if the load average was unobtainable.
14675 [clinic start generated code]*/
14676 
14677 static PyObject *
os_getloadavg_impl(PyObject * module)14678 os_getloadavg_impl(PyObject *module)
14679 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
14680 {
14681     double loadavg[3];
14682     if (getloadavg(loadavg, 3)!=3) {
14683         PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
14684         return NULL;
14685     } else
14686         return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
14687 }
14688 #endif /* HAVE_GETLOADAVG */
14689 
14690 
14691 /*[clinic input]
14692 os.device_encoding
14693     fd: int
14694 
14695 Return a string describing the encoding of a terminal's file descriptor.
14696 
14697 The file descriptor must be attached to a terminal.
14698 If the device is not a terminal, return None.
14699 [clinic start generated code]*/
14700 
14701 static PyObject *
os_device_encoding_impl(PyObject * module,int fd)14702 os_device_encoding_impl(PyObject *module, int fd)
14703 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
14704 {
14705     return _Py_device_encoding(fd);
14706 }
14707 
14708 
14709 #ifdef HAVE_SETRESUID
14710 /*[clinic input]
14711 os.setresuid
14712 
14713     ruid: uid_t
14714     euid: uid_t
14715     suid: uid_t
14716     /
14717 
14718 Set the current process's real, effective, and saved user ids.
14719 [clinic start generated code]*/
14720 
14721 static PyObject *
os_setresuid_impl(PyObject * module,uid_t ruid,uid_t euid,uid_t suid)14722 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
14723 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
14724 {
14725     if (setresuid(ruid, euid, suid) < 0)
14726         return posix_error();
14727     Py_RETURN_NONE;
14728 }
14729 #endif /* HAVE_SETRESUID */
14730 
14731 
14732 #ifdef HAVE_SETRESGID
14733 /*[clinic input]
14734 os.setresgid
14735 
14736     rgid: gid_t
14737     egid: gid_t
14738     sgid: gid_t
14739     /
14740 
14741 Set the current process's real, effective, and saved group ids.
14742 [clinic start generated code]*/
14743 
14744 static PyObject *
os_setresgid_impl(PyObject * module,gid_t rgid,gid_t egid,gid_t sgid)14745 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
14746 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
14747 {
14748     if (setresgid(rgid, egid, sgid) < 0)
14749         return posix_error();
14750     Py_RETURN_NONE;
14751 }
14752 #endif /* HAVE_SETRESGID */
14753 
14754 
14755 #ifdef HAVE_GETRESUID
14756 /*[clinic input]
14757 os.getresuid
14758 
14759 Return a tuple of the current process's real, effective, and saved user ids.
14760 [clinic start generated code]*/
14761 
14762 static PyObject *
os_getresuid_impl(PyObject * module)14763 os_getresuid_impl(PyObject *module)
14764 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
14765 {
14766     uid_t ruid, euid, suid;
14767     if (getresuid(&ruid, &euid, &suid) < 0)
14768         return posix_error();
14769     return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
14770                                   _PyLong_FromUid(euid),
14771                                   _PyLong_FromUid(suid));
14772 }
14773 #endif /* HAVE_GETRESUID */
14774 
14775 
14776 #ifdef HAVE_GETRESGID
14777 /*[clinic input]
14778 os.getresgid
14779 
14780 Return a tuple of the current process's real, effective, and saved group ids.
14781 [clinic start generated code]*/
14782 
14783 static PyObject *
os_getresgid_impl(PyObject * module)14784 os_getresgid_impl(PyObject *module)
14785 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
14786 {
14787     gid_t rgid, egid, sgid;
14788     if (getresgid(&rgid, &egid, &sgid) < 0)
14789         return posix_error();
14790     return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
14791                                   _PyLong_FromGid(egid),
14792                                   _PyLong_FromGid(sgid));
14793 }
14794 #endif /* HAVE_GETRESGID */
14795 
14796 
14797 #ifdef USE_XATTRS
14798 /*[clinic input]
14799 os.getxattr
14800 
14801     path: path_t(allow_fd=True)
14802     attribute: path_t
14803     *
14804     follow_symlinks: bool = True
14805 
14806 Return the value of extended attribute attribute on path.
14807 
14808 path may be either a string, a path-like object, or an open file descriptor.
14809 If follow_symlinks is False, and the last element of the path is a symbolic
14810   link, getxattr will examine the symbolic link itself instead of the file
14811   the link points to.
14812 
14813 [clinic start generated code]*/
14814 
14815 static PyObject *
os_getxattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)14816 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
14817                  int follow_symlinks)
14818 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
14819 {
14820     Py_ssize_t i;
14821     PyObject *buffer = NULL;
14822 
14823     if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
14824         return NULL;
14825 
14826     if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
14827         return NULL;
14828     }
14829 
14830     for (i = 0; ; i++) {
14831         void *ptr;
14832         ssize_t result;
14833         static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
14834         Py_ssize_t buffer_size = buffer_sizes[i];
14835         if (!buffer_size) {
14836             path_error(path);
14837             return NULL;
14838         }
14839         buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
14840         if (!buffer)
14841             return NULL;
14842         ptr = PyBytes_AS_STRING(buffer);
14843 
14844         Py_BEGIN_ALLOW_THREADS;
14845         if (path->fd >= 0)
14846             result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
14847         else if (follow_symlinks)
14848             result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
14849         else
14850             result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
14851         Py_END_ALLOW_THREADS;
14852 
14853         if (result < 0) {
14854             if (errno == ERANGE) {
14855                 Py_DECREF(buffer);
14856                 continue;
14857             }
14858             path_error(path);
14859             Py_DECREF(buffer);
14860             return NULL;
14861         }
14862 
14863         if (result != buffer_size) {
14864             /* Can only shrink. */
14865             _PyBytes_Resize(&buffer, result);
14866         }
14867         break;
14868     }
14869 
14870     return buffer;
14871 }
14872 
14873 
14874 /*[clinic input]
14875 os.setxattr
14876 
14877     path: path_t(allow_fd=True)
14878     attribute: path_t
14879     value: Py_buffer
14880     flags: int = 0
14881     *
14882     follow_symlinks: bool = True
14883 
14884 Set extended attribute attribute on path to value.
14885 
14886 path may be either a string, a path-like object,  or an open file descriptor.
14887 If follow_symlinks is False, and the last element of the path is a symbolic
14888   link, setxattr will modify the symbolic link itself instead of the file
14889   the link points to.
14890 
14891 [clinic start generated code]*/
14892 
14893 static PyObject *
os_setxattr_impl(PyObject * module,path_t * path,path_t * attribute,Py_buffer * value,int flags,int follow_symlinks)14894 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
14895                  Py_buffer *value, int flags, int follow_symlinks)
14896 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
14897 {
14898     ssize_t result;
14899 
14900     if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
14901         return NULL;
14902 
14903     if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
14904                     value->buf, value->len, flags) < 0) {
14905         return NULL;
14906     }
14907 
14908     Py_BEGIN_ALLOW_THREADS;
14909     if (path->fd > -1)
14910         result = fsetxattr(path->fd, attribute->narrow,
14911                            value->buf, value->len, flags);
14912     else if (follow_symlinks)
14913         result = setxattr(path->narrow, attribute->narrow,
14914                            value->buf, value->len, flags);
14915     else
14916         result = lsetxattr(path->narrow, attribute->narrow,
14917                            value->buf, value->len, flags);
14918     Py_END_ALLOW_THREADS;
14919 
14920     if (result) {
14921         path_error(path);
14922         return NULL;
14923     }
14924 
14925     Py_RETURN_NONE;
14926 }
14927 
14928 
14929 /*[clinic input]
14930 os.removexattr
14931 
14932     path: path_t(allow_fd=True)
14933     attribute: path_t
14934     *
14935     follow_symlinks: bool = True
14936 
14937 Remove extended attribute attribute on path.
14938 
14939 path may be either a string, a path-like object, or an open file descriptor.
14940 If follow_symlinks is False, and the last element of the path is a symbolic
14941   link, removexattr will modify the symbolic link itself instead of the file
14942   the link points to.
14943 
14944 [clinic start generated code]*/
14945 
14946 static PyObject *
os_removexattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)14947 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
14948                     int follow_symlinks)
14949 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
14950 {
14951     ssize_t result;
14952 
14953     if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
14954         return NULL;
14955 
14956     if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
14957         return NULL;
14958     }
14959 
14960     Py_BEGIN_ALLOW_THREADS;
14961     if (path->fd > -1)
14962         result = fremovexattr(path->fd, attribute->narrow);
14963     else if (follow_symlinks)
14964         result = removexattr(path->narrow, attribute->narrow);
14965     else
14966         result = lremovexattr(path->narrow, attribute->narrow);
14967     Py_END_ALLOW_THREADS;
14968 
14969     if (result) {
14970         return path_error(path);
14971     }
14972 
14973     Py_RETURN_NONE;
14974 }
14975 
14976 
14977 /*[clinic input]
14978 os.listxattr
14979 
14980     path: path_t(allow_fd=True, nullable=True) = None
14981     *
14982     follow_symlinks: bool = True
14983 
14984 Return a list of extended attributes on path.
14985 
14986 path may be either None, a string, a path-like object, or an open file descriptor.
14987 if path is None, listxattr will examine the current directory.
14988 If follow_symlinks is False, and the last element of the path is a symbolic
14989   link, listxattr will examine the symbolic link itself instead of the file
14990   the link points to.
14991 [clinic start generated code]*/
14992 
14993 static PyObject *
os_listxattr_impl(PyObject * module,path_t * path,int follow_symlinks)14994 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
14995 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
14996 {
14997     Py_ssize_t i;
14998     PyObject *result = NULL;
14999     const char *name;
15000     char *buffer = NULL;
15001 
15002     if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
15003         goto exit;
15004 
15005     if (PySys_Audit("os.listxattr", "(O)",
15006                     path->object ? path->object : Py_None) < 0) {
15007         return NULL;
15008     }
15009 
15010     name = path->narrow ? path->narrow : ".";
15011 
15012     for (i = 0; ; i++) {
15013         const char *start, *trace, *end;
15014         ssize_t length;
15015         static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15016         Py_ssize_t buffer_size = buffer_sizes[i];
15017         if (!buffer_size) {
15018             /* ERANGE */
15019             path_error(path);
15020             break;
15021         }
15022         buffer = PyMem_Malloc(buffer_size);
15023         if (!buffer) {
15024             PyErr_NoMemory();
15025             break;
15026         }
15027 
15028         Py_BEGIN_ALLOW_THREADS;
15029         if (path->fd > -1)
15030             length = flistxattr(path->fd, buffer, buffer_size);
15031         else if (follow_symlinks)
15032             length = listxattr(name, buffer, buffer_size);
15033         else
15034             length = llistxattr(name, buffer, buffer_size);
15035         Py_END_ALLOW_THREADS;
15036 
15037         if (length < 0) {
15038             if (errno == ERANGE) {
15039                 PyMem_Free(buffer);
15040                 buffer = NULL;
15041                 continue;
15042             }
15043             path_error(path);
15044             break;
15045         }
15046 
15047         result = PyList_New(0);
15048         if (!result) {
15049             goto exit;
15050         }
15051 
15052         end = buffer + length;
15053         for (trace = start = buffer; trace != end; trace++) {
15054             if (!*trace) {
15055                 int error;
15056                 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15057                                                                  trace - start);
15058                 if (!attribute) {
15059                     Py_SETREF(result, NULL);
15060                     goto exit;
15061                 }
15062                 error = PyList_Append(result, attribute);
15063                 Py_DECREF(attribute);
15064                 if (error) {
15065                     Py_SETREF(result, NULL);
15066                     goto exit;
15067                 }
15068                 start = trace + 1;
15069             }
15070         }
15071     break;
15072     }
15073 exit:
15074     if (buffer)
15075         PyMem_Free(buffer);
15076     return result;
15077 }
15078 #endif /* USE_XATTRS */
15079 
15080 
15081 /*[clinic input]
15082 os.urandom
15083 
15084     size: Py_ssize_t
15085     /
15086 
15087 Return a bytes object containing random bytes suitable for cryptographic use.
15088 [clinic start generated code]*/
15089 
15090 static PyObject *
os_urandom_impl(PyObject * module,Py_ssize_t size)15091 os_urandom_impl(PyObject *module, Py_ssize_t size)
15092 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
15093 {
15094     PyObject *bytes;
15095     int result;
15096 
15097     if (size < 0)
15098         return PyErr_Format(PyExc_ValueError,
15099                             "negative argument not allowed");
15100     bytes = PyBytes_FromStringAndSize(NULL, size);
15101     if (bytes == NULL)
15102         return NULL;
15103 
15104     result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
15105     if (result == -1) {
15106         Py_DECREF(bytes);
15107         return NULL;
15108     }
15109     return bytes;
15110 }
15111 
15112 #ifdef HAVE_MEMFD_CREATE
15113 /*[clinic input]
15114 os.memfd_create
15115 
15116     name: FSConverter
15117     flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
15118 
15119 [clinic start generated code]*/
15120 
15121 static PyObject *
os_memfd_create_impl(PyObject * module,PyObject * name,unsigned int flags)15122 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
15123 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
15124 {
15125     int fd;
15126     const char *bytes = PyBytes_AS_STRING(name);
15127     Py_BEGIN_ALLOW_THREADS
15128     fd = memfd_create(bytes, flags);
15129     Py_END_ALLOW_THREADS
15130     if (fd == -1) {
15131         return PyErr_SetFromErrno(PyExc_OSError);
15132     }
15133     return PyLong_FromLong(fd);
15134 }
15135 #endif
15136 
15137 #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15138 /*[clinic input]
15139 os.eventfd
15140 
15141     initval: unsigned_int
15142     flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
15143 
15144 Creates and returns an event notification file descriptor.
15145 [clinic start generated code]*/
15146 
15147 static PyObject *
os_eventfd_impl(PyObject * module,unsigned int initval,int flags)15148 os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
15149 /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
15150 
15151 {
15152     /* initval is limited to uint32_t, internal counter is uint64_t */
15153     int fd;
15154     Py_BEGIN_ALLOW_THREADS
15155     fd = eventfd(initval, flags);
15156     Py_END_ALLOW_THREADS
15157     if (fd == -1) {
15158         return PyErr_SetFromErrno(PyExc_OSError);
15159     }
15160     return PyLong_FromLong(fd);
15161 }
15162 
15163 /*[clinic input]
15164 os.eventfd_read
15165 
15166     fd: fildes
15167 
15168 Read eventfd value
15169 [clinic start generated code]*/
15170 
15171 static PyObject *
os_eventfd_read_impl(PyObject * module,int fd)15172 os_eventfd_read_impl(PyObject *module, int fd)
15173 /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
15174 {
15175     eventfd_t value;
15176     int result;
15177     Py_BEGIN_ALLOW_THREADS
15178     result = eventfd_read(fd, &value);
15179     Py_END_ALLOW_THREADS
15180     if (result == -1) {
15181         return PyErr_SetFromErrno(PyExc_OSError);
15182     }
15183     return PyLong_FromUnsignedLongLong(value);
15184 }
15185 
15186 /*[clinic input]
15187 os.eventfd_write
15188 
15189     fd: fildes
15190     value: unsigned_long_long
15191 
15192 Write eventfd value.
15193 [clinic start generated code]*/
15194 
15195 static PyObject *
os_eventfd_write_impl(PyObject * module,int fd,unsigned long long value)15196 os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
15197 /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
15198 {
15199     int result;
15200     Py_BEGIN_ALLOW_THREADS
15201     result = eventfd_write(fd, value);
15202     Py_END_ALLOW_THREADS
15203     if (result == -1) {
15204         return PyErr_SetFromErrno(PyExc_OSError);
15205     }
15206     Py_RETURN_NONE;
15207 }
15208 #endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15209 
15210 /* Terminal size querying */
15211 
15212 PyDoc_STRVAR(TerminalSize_docstring,
15213     "A tuple of (columns, lines) for holding terminal window size");
15214 
15215 static PyStructSequence_Field TerminalSize_fields[] = {
15216     {"columns", "width of the terminal window in characters"},
15217     {"lines", "height of the terminal window in characters"},
15218     {NULL, NULL}
15219 };
15220 
15221 static PyStructSequence_Desc TerminalSize_desc = {
15222     "os.terminal_size",
15223     TerminalSize_docstring,
15224     TerminalSize_fields,
15225     2,
15226 };
15227 
15228 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
15229 /*[clinic input]
15230 os.get_terminal_size
15231 
15232     fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
15233     /
15234 
15235 Return the size of the terminal window as (columns, lines).
15236 
15237 The optional argument fd (default standard output) specifies
15238 which file descriptor should be queried.
15239 
15240 If the file descriptor is not connected to a terminal, an OSError
15241 is thrown.
15242 
15243 This function will only be defined if an implementation is
15244 available for this system.
15245 
15246 shutil.get_terminal_size is the high-level function which should
15247 normally be used, os.get_terminal_size is the low-level implementation.
15248 [clinic start generated code]*/
15249 
15250 static PyObject *
os_get_terminal_size_impl(PyObject * module,int fd)15251 os_get_terminal_size_impl(PyObject *module, int fd)
15252 /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
15253 {
15254     int columns, lines;
15255     PyObject *termsize;
15256 
15257     /* Under some conditions stdout may not be connected and
15258      * fileno(stdout) may point to an invalid file descriptor. For example
15259      * GUI apps don't have valid standard streams by default.
15260      *
15261      * If this happens, and the optional fd argument is not present,
15262      * the ioctl below will fail returning EBADF. This is what we want.
15263      */
15264 
15265 #ifdef TERMSIZE_USE_IOCTL
15266     {
15267         struct winsize w;
15268         if (ioctl(fd, TIOCGWINSZ, &w))
15269             return PyErr_SetFromErrno(PyExc_OSError);
15270         columns = w.ws_col;
15271         lines = w.ws_row;
15272     }
15273 #endif /* TERMSIZE_USE_IOCTL */
15274 
15275 #ifdef TERMSIZE_USE_CONIO
15276     {
15277         HANDLE handle;
15278         CONSOLE_SCREEN_BUFFER_INFO csbi;
15279         handle = _Py_get_osfhandle(fd);
15280         if (handle == INVALID_HANDLE_VALUE)
15281             return NULL;
15282 
15283         if (!GetConsoleScreenBufferInfo(handle, &csbi))
15284             return PyErr_SetFromWindowsErr(0);
15285 
15286         columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
15287         lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
15288     }
15289 #endif /* TERMSIZE_USE_CONIO */
15290 
15291     PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
15292     termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
15293     if (termsize == NULL)
15294         return NULL;
15295 
15296     int pos = 0;
15297 
15298 #define SET_TERMSIZE(CALL)                                   \
15299     do {                                                     \
15300         PyObject *item = (CALL);                             \
15301         if (item == NULL) {                                  \
15302             Py_DECREF(termsize);                             \
15303             return NULL;                                     \
15304         }                                                    \
15305         PyStructSequence_SET_ITEM(termsize, pos++, item);    \
15306     } while(0)
15307 
15308     SET_TERMSIZE(PyLong_FromLong(columns));
15309     SET_TERMSIZE(PyLong_FromLong(lines));
15310 #undef SET_TERMSIZE
15311 
15312     return termsize;
15313 }
15314 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
15315 
15316 /*[clinic input]
15317 os.cpu_count
15318 
15319 Return the number of logical CPUs in the system.
15320 
15321 Return None if indeterminable.
15322 [clinic start generated code]*/
15323 
15324 static PyObject *
os_cpu_count_impl(PyObject * module)15325 os_cpu_count_impl(PyObject *module)
15326 /*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
15327 {
15328     const PyConfig *config = _Py_GetConfig();
15329     if (config->cpu_count > 0) {
15330         return PyLong_FromLong(config->cpu_count);
15331     }
15332 
15333     int ncpu = 0;
15334 #ifdef MS_WINDOWS
15335 # ifdef MS_WINDOWS_DESKTOP
15336     ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
15337 # else
15338     ncpu = 0;
15339 # endif
15340 
15341 #elif defined(__hpux)
15342     ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
15343 
15344 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
15345     ncpu = sysconf(_SC_NPROCESSORS_ONLN);
15346 
15347 #elif defined(__VXWORKS__)
15348     ncpu = _Py_popcount32(vxCpuEnabledGet());
15349 
15350 #elif defined(__DragonFly__) || \
15351       defined(__OpenBSD__)   || \
15352       defined(__FreeBSD__)   || \
15353       defined(__NetBSD__)    || \
15354       defined(__APPLE__)
15355     ncpu = 0;
15356     size_t len = sizeof(ncpu);
15357     int mib[2] = {CTL_HW, HW_NCPU};
15358     if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
15359         ncpu = 0;
15360     }
15361 #endif
15362 
15363     if (ncpu < 1) {
15364         Py_RETURN_NONE;
15365     }
15366     return PyLong_FromLong(ncpu);
15367 }
15368 
15369 
15370 /*[clinic input]
15371 os.get_inheritable -> bool
15372 
15373     fd: int
15374     /
15375 
15376 Get the close-on-exe flag of the specified file descriptor.
15377 [clinic start generated code]*/
15378 
15379 static int
os_get_inheritable_impl(PyObject * module,int fd)15380 os_get_inheritable_impl(PyObject *module, int fd)
15381 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
15382 {
15383     int return_value;
15384     _Py_BEGIN_SUPPRESS_IPH
15385     return_value = _Py_get_inheritable(fd);
15386     _Py_END_SUPPRESS_IPH
15387     return return_value;
15388 }
15389 
15390 
15391 /*[clinic input]
15392 os.set_inheritable
15393     fd: int
15394     inheritable: int
15395     /
15396 
15397 Set the inheritable flag of the specified file descriptor.
15398 [clinic start generated code]*/
15399 
15400 static PyObject *
os_set_inheritable_impl(PyObject * module,int fd,int inheritable)15401 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
15402 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
15403 {
15404     int result;
15405 
15406     _Py_BEGIN_SUPPRESS_IPH
15407     result = _Py_set_inheritable(fd, inheritable, NULL);
15408     _Py_END_SUPPRESS_IPH
15409     if (result < 0)
15410         return NULL;
15411     Py_RETURN_NONE;
15412 }
15413 
15414 
15415 #ifdef MS_WINDOWS
15416 #ifndef HANDLE_FLAG_INHERIT
15417 #define HANDLE_FLAG_INHERIT 0x00000001
15418 #endif
15419 
15420 /*[clinic input]
15421 os.get_handle_inheritable -> bool
15422     handle: intptr_t
15423     /
15424 
15425 Get the close-on-exe flag of the specified file descriptor.
15426 [clinic start generated code]*/
15427 
15428 static int
os_get_handle_inheritable_impl(PyObject * module,intptr_t handle)15429 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
15430 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
15431 {
15432     DWORD flags;
15433 
15434     if (!GetHandleInformation((HANDLE)handle, &flags)) {
15435         PyErr_SetFromWindowsErr(0);
15436         return -1;
15437     }
15438 
15439     return flags & HANDLE_FLAG_INHERIT;
15440 }
15441 
15442 
15443 /*[clinic input]
15444 os.set_handle_inheritable
15445     handle: intptr_t
15446     inheritable: bool
15447     /
15448 
15449 Set the inheritable flag of the specified handle.
15450 [clinic start generated code]*/
15451 
15452 static PyObject *
os_set_handle_inheritable_impl(PyObject * module,intptr_t handle,int inheritable)15453 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
15454                                int inheritable)
15455 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
15456 {
15457     DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
15458     if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
15459         PyErr_SetFromWindowsErr(0);
15460         return NULL;
15461     }
15462     Py_RETURN_NONE;
15463 }
15464 #endif /* MS_WINDOWS */
15465 
15466 /*[clinic input]
15467 os.get_blocking -> bool
15468     fd: int
15469     /
15470 
15471 Get the blocking mode of the file descriptor.
15472 
15473 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
15474 [clinic start generated code]*/
15475 
15476 static int
os_get_blocking_impl(PyObject * module,int fd)15477 os_get_blocking_impl(PyObject *module, int fd)
15478 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
15479 {
15480     int blocking;
15481 
15482     _Py_BEGIN_SUPPRESS_IPH
15483     blocking = _Py_get_blocking(fd);
15484     _Py_END_SUPPRESS_IPH
15485     return blocking;
15486 }
15487 
15488 /*[clinic input]
15489 os.set_blocking
15490     fd: int
15491     blocking: bool
15492     /
15493 
15494 Set the blocking mode of the specified file descriptor.
15495 
15496 Set the O_NONBLOCK flag if blocking is False,
15497 clear the O_NONBLOCK flag otherwise.
15498 [clinic start generated code]*/
15499 
15500 static PyObject *
os_set_blocking_impl(PyObject * module,int fd,int blocking)15501 os_set_blocking_impl(PyObject *module, int fd, int blocking)
15502 /*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
15503 {
15504     int result;
15505 
15506     _Py_BEGIN_SUPPRESS_IPH
15507     result = _Py_set_blocking(fd, blocking);
15508     _Py_END_SUPPRESS_IPH
15509     if (result < 0)
15510         return NULL;
15511     Py_RETURN_NONE;
15512 }
15513 
15514 
15515 /*[clinic input]
15516 class os.DirEntry "DirEntry *" "DirEntryType"
15517 [clinic start generated code]*/
15518 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
15519 
15520 typedef struct {
15521     PyObject_HEAD
15522     PyObject *name;
15523     PyObject *path;
15524     PyObject *stat;
15525     PyObject *lstat;
15526 #ifdef MS_WINDOWS
15527     struct _Py_stat_struct win32_lstat;
15528     uint64_t win32_file_index;
15529     uint64_t win32_file_index_high;
15530     int got_file_index;
15531 #else /* POSIX */
15532 #ifdef HAVE_DIRENT_D_TYPE
15533     unsigned char d_type;
15534 #endif
15535     ino_t d_ino;
15536     int dir_fd;
15537 #endif
15538 } DirEntry;
15539 
15540 static void
DirEntry_dealloc(DirEntry * entry)15541 DirEntry_dealloc(DirEntry *entry)
15542 {
15543     PyTypeObject *tp = Py_TYPE(entry);
15544     Py_XDECREF(entry->name);
15545     Py_XDECREF(entry->path);
15546     Py_XDECREF(entry->stat);
15547     Py_XDECREF(entry->lstat);
15548     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
15549     free_func(entry);
15550     Py_DECREF(tp);
15551 }
15552 
15553 /* Forward reference */
15554 static int
15555 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
15556                    int follow_symlinks, unsigned short mode_bits);
15557 
15558 /*[clinic input]
15559 os.DirEntry.is_symlink -> bool
15560     defining_class: defining_class
15561     /
15562 
15563 Return True if the entry is a symbolic link; cached per entry.
15564 [clinic start generated code]*/
15565 
15566 static int
os_DirEntry_is_symlink_impl(DirEntry * self,PyTypeObject * defining_class)15567 os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
15568 /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
15569 {
15570 #ifdef MS_WINDOWS
15571     return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
15572 #elif defined(HAVE_DIRENT_D_TYPE)
15573     /* POSIX */
15574     if (self->d_type != DT_UNKNOWN)
15575         return self->d_type == DT_LNK;
15576     else
15577         return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
15578 #else
15579     /* POSIX without d_type */
15580     return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
15581 #endif
15582 }
15583 
15584 /*[clinic input]
15585 os.DirEntry.is_junction -> bool
15586 
15587 Return True if the entry is a junction; cached per entry.
15588 [clinic start generated code]*/
15589 
15590 static int
os_DirEntry_is_junction_impl(DirEntry * self)15591 os_DirEntry_is_junction_impl(DirEntry *self)
15592 /*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
15593 {
15594 #ifdef MS_WINDOWS
15595     return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
15596 #else
15597     return 0;
15598 #endif
15599 }
15600 
15601 static PyObject *
DirEntry_fetch_stat(PyObject * module,DirEntry * self,int follow_symlinks)15602 DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
15603 {
15604     int result;
15605     STRUCT_STAT st;
15606     PyObject *ub;
15607 
15608 #ifdef MS_WINDOWS
15609     if (!PyUnicode_FSDecoder(self->path, &ub))
15610         return NULL;
15611     wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
15612     Py_DECREF(ub);
15613 #else /* POSIX */
15614     if (!PyUnicode_FSConverter(self->path, &ub))
15615         return NULL;
15616     const char *path = PyBytes_AS_STRING(ub);
15617     if (self->dir_fd != DEFAULT_DIR_FD) {
15618 #ifdef HAVE_FSTATAT
15619       if (HAVE_FSTATAT_RUNTIME) {
15620         Py_BEGIN_ALLOW_THREADS
15621         result = fstatat(self->dir_fd, path, &st,
15622                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
15623         Py_END_ALLOW_THREADS
15624       } else
15625 
15626 #endif /* HAVE_FSTATAT */
15627       {
15628         Py_DECREF(ub);
15629         PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
15630         return NULL;
15631       }
15632     }
15633     else
15634 #endif
15635     {
15636         Py_BEGIN_ALLOW_THREADS
15637         if (follow_symlinks) {
15638             result = STAT(path, &st);
15639         }
15640         else {
15641             result = LSTAT(path, &st);
15642         }
15643         Py_END_ALLOW_THREADS
15644     }
15645 
15646     int saved_errno = errno;
15647 #if defined(MS_WINDOWS)
15648     PyMem_Free(path);
15649 #else
15650     Py_DECREF(ub);
15651 #endif
15652 
15653     if (result != 0) {
15654         errno = saved_errno;
15655         path_object_error(self->path);
15656         return NULL;
15657     }
15658 
15659     return _pystat_fromstructstat(module, &st);
15660 }
15661 
15662 static PyObject *
DirEntry_get_lstat(PyTypeObject * defining_class,DirEntry * self)15663 DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
15664 {
15665     if (!self->lstat) {
15666         PyObject *module = PyType_GetModule(defining_class);
15667 #ifdef MS_WINDOWS
15668         self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
15669 #else /* POSIX */
15670         self->lstat = DirEntry_fetch_stat(module, self, 0);
15671 #endif
15672     }
15673     return Py_XNewRef(self->lstat);
15674 }
15675 
15676 /*[clinic input]
15677 os.DirEntry.stat
15678     defining_class: defining_class
15679     /
15680     *
15681     follow_symlinks: bool = True
15682 
15683 Return stat_result object for the entry; cached per entry.
15684 [clinic start generated code]*/
15685 
15686 static PyObject *
os_DirEntry_stat_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)15687 os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
15688                       int follow_symlinks)
15689 /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
15690 {
15691     if (!follow_symlinks) {
15692         return DirEntry_get_lstat(defining_class, self);
15693     }
15694 
15695     if (!self->stat) {
15696         int result = os_DirEntry_is_symlink_impl(self, defining_class);
15697         if (result == -1) {
15698             return NULL;
15699         }
15700         if (result) {
15701             PyObject *module = PyType_GetModule(defining_class);
15702             self->stat = DirEntry_fetch_stat(module, self, 1);
15703         }
15704         else {
15705             self->stat = DirEntry_get_lstat(defining_class, self);
15706         }
15707     }
15708 
15709     return Py_XNewRef(self->stat);
15710 }
15711 
15712 /* Set exception and return -1 on error, 0 for False, 1 for True */
15713 static int
DirEntry_test_mode(PyTypeObject * defining_class,DirEntry * self,int follow_symlinks,unsigned short mode_bits)15714 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
15715                    int follow_symlinks, unsigned short mode_bits)
15716 {
15717     PyObject *stat = NULL;
15718     PyObject *st_mode = NULL;
15719     long mode;
15720     int result;
15721 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
15722     int is_symlink;
15723     int need_stat;
15724 #endif
15725 #ifdef MS_WINDOWS
15726     unsigned long dir_bits;
15727 #endif
15728 
15729 #ifdef MS_WINDOWS
15730     is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
15731     need_stat = follow_symlinks && is_symlink;
15732 #elif defined(HAVE_DIRENT_D_TYPE)
15733     is_symlink = self->d_type == DT_LNK;
15734     need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
15735 #endif
15736 
15737 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
15738     if (need_stat) {
15739 #endif
15740         stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
15741         if (!stat) {
15742             if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
15743                 /* If file doesn't exist (anymore), then return False
15744                    (i.e., say it's not a file/directory) */
15745                 PyErr_Clear();
15746                 return 0;
15747             }
15748             goto error;
15749         }
15750         _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
15751         st_mode = PyObject_GetAttr(stat, state->st_mode);
15752         if (!st_mode)
15753             goto error;
15754 
15755         mode = PyLong_AsLong(st_mode);
15756         if (mode == -1 && PyErr_Occurred())
15757             goto error;
15758         Py_CLEAR(st_mode);
15759         Py_CLEAR(stat);
15760         result = (mode & S_IFMT) == mode_bits;
15761 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
15762     }
15763     else if (is_symlink) {
15764         assert(mode_bits != S_IFLNK);
15765         result = 0;
15766     }
15767     else {
15768         assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
15769 #ifdef MS_WINDOWS
15770         dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
15771         if (mode_bits == S_IFDIR)
15772             result = dir_bits != 0;
15773         else
15774             result = dir_bits == 0;
15775 #else /* POSIX */
15776         if (mode_bits == S_IFDIR)
15777             result = self->d_type == DT_DIR;
15778         else
15779             result = self->d_type == DT_REG;
15780 #endif
15781     }
15782 #endif
15783 
15784     return result;
15785 
15786 error:
15787     Py_XDECREF(st_mode);
15788     Py_XDECREF(stat);
15789     return -1;
15790 }
15791 
15792 /*[clinic input]
15793 os.DirEntry.is_dir -> bool
15794     defining_class: defining_class
15795     /
15796     *
15797     follow_symlinks: bool = True
15798 
15799 Return True if the entry is a directory; cached per entry.
15800 [clinic start generated code]*/
15801 
15802 static int
os_DirEntry_is_dir_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)15803 os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
15804                         int follow_symlinks)
15805 /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
15806 {
15807     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
15808 }
15809 
15810 /*[clinic input]
15811 os.DirEntry.is_file -> bool
15812     defining_class: defining_class
15813     /
15814     *
15815     follow_symlinks: bool = True
15816 
15817 Return True if the entry is a file; cached per entry.
15818 [clinic start generated code]*/
15819 
15820 static int
os_DirEntry_is_file_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)15821 os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
15822                          int follow_symlinks)
15823 /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
15824 {
15825     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
15826 }
15827 
15828 /*[clinic input]
15829 os.DirEntry.inode
15830 
15831 Return inode of the entry; cached per entry.
15832 [clinic start generated code]*/
15833 
15834 static PyObject *
os_DirEntry_inode_impl(DirEntry * self)15835 os_DirEntry_inode_impl(DirEntry *self)
15836 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
15837 {
15838 #ifdef MS_WINDOWS
15839     if (!self->got_file_index) {
15840         PyObject *unicode;
15841         STRUCT_STAT stat;
15842         int result;
15843 
15844         if (!PyUnicode_FSDecoder(self->path, &unicode))
15845             return NULL;
15846         wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
15847         Py_DECREF(unicode);
15848         result = LSTAT(path, &stat);
15849 
15850         int saved_errno = errno;
15851         PyMem_Free(path);
15852 
15853         if (result != 0) {
15854             errno = saved_errno;
15855             return path_object_error(self->path);
15856         }
15857 
15858         self->win32_file_index = stat.st_ino;
15859         self->win32_file_index_high = stat.st_ino_high;
15860         self->got_file_index = 1;
15861     }
15862     return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
15863 #else /* POSIX */
15864     static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
15865                   "DirEntry.d_ino is larger than unsigned long long");
15866     return PyLong_FromUnsignedLongLong(self->d_ino);
15867 #endif
15868 }
15869 
15870 static PyObject *
DirEntry_repr(DirEntry * self)15871 DirEntry_repr(DirEntry *self)
15872 {
15873     return PyUnicode_FromFormat("<DirEntry %R>", self->name);
15874 }
15875 
15876 /*[clinic input]
15877 os.DirEntry.__fspath__
15878 
15879 Returns the path for the entry.
15880 [clinic start generated code]*/
15881 
15882 static PyObject *
os_DirEntry___fspath___impl(DirEntry * self)15883 os_DirEntry___fspath___impl(DirEntry *self)
15884 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
15885 {
15886     return Py_NewRef(self->path);
15887 }
15888 
15889 static PyMemberDef DirEntry_members[] = {
15890     {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
15891      "the entry's base filename, relative to scandir() \"path\" argument"},
15892     {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
15893      "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
15894     {NULL}
15895 };
15896 
15897 #include "clinic/posixmodule.c.h"
15898 
15899 static PyMethodDef DirEntry_methods[] = {
15900     OS_DIRENTRY_IS_DIR_METHODDEF
15901     OS_DIRENTRY_IS_FILE_METHODDEF
15902     OS_DIRENTRY_IS_SYMLINK_METHODDEF
15903     OS_DIRENTRY_IS_JUNCTION_METHODDEF
15904     OS_DIRENTRY_STAT_METHODDEF
15905     OS_DIRENTRY_INODE_METHODDEF
15906     OS_DIRENTRY___FSPATH___METHODDEF
15907     {"__class_getitem__",       Py_GenericAlias,
15908     METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
15909     {NULL}
15910 };
15911 
15912 static PyType_Slot DirEntryType_slots[] = {
15913     {Py_tp_dealloc, DirEntry_dealloc},
15914     {Py_tp_repr, DirEntry_repr},
15915     {Py_tp_methods, DirEntry_methods},
15916     {Py_tp_members, DirEntry_members},
15917     {0, 0},
15918 };
15919 
15920 static PyType_Spec DirEntryType_spec = {
15921     MODNAME ".DirEntry",
15922     sizeof(DirEntry),
15923     0,
15924     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
15925     DirEntryType_slots
15926 };
15927 
15928 
15929 #ifdef MS_WINDOWS
15930 
15931 static wchar_t *
join_path_filenameW(const wchar_t * path_wide,const wchar_t * filename)15932 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
15933 {
15934     Py_ssize_t path_len;
15935     Py_ssize_t size;
15936     wchar_t *result;
15937     wchar_t ch;
15938 
15939     if (!path_wide) { /* Default arg: "." */
15940         path_wide = L".";
15941         path_len = 1;
15942     }
15943     else {
15944         path_len = wcslen(path_wide);
15945     }
15946 
15947     /* The +1's are for the path separator and the NUL */
15948     size = path_len + 1 + wcslen(filename) + 1;
15949     result = PyMem_New(wchar_t, size);
15950     if (!result) {
15951         PyErr_NoMemory();
15952         return NULL;
15953     }
15954     wcscpy(result, path_wide);
15955     if (path_len > 0) {
15956         ch = result[path_len - 1];
15957         if (ch != SEP && ch != ALTSEP && ch != L':')
15958             result[path_len++] = SEP;
15959         wcscpy(result + path_len, filename);
15960     }
15961     return result;
15962 }
15963 
15964 static PyObject *
DirEntry_from_find_data(PyObject * module,path_t * path,WIN32_FIND_DATAW * dataW)15965 DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
15966 {
15967     DirEntry *entry;
15968     BY_HANDLE_FILE_INFORMATION file_info;
15969     ULONG reparse_tag;
15970     wchar_t *joined_path;
15971 
15972     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
15973     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
15974     if (!entry)
15975         return NULL;
15976     entry->name = NULL;
15977     entry->path = NULL;
15978     entry->stat = NULL;
15979     entry->lstat = NULL;
15980     entry->got_file_index = 0;
15981 
15982     entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
15983     if (!entry->name)
15984         goto error;
15985     int return_bytes = path->wide && PyBytes_Check(path->object);
15986     if (return_bytes) {
15987         Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
15988         if (!entry->name)
15989             goto error;
15990     }
15991 
15992     joined_path = join_path_filenameW(path->wide, dataW->cFileName);
15993     if (!joined_path)
15994         goto error;
15995 
15996     entry->path = PyUnicode_FromWideChar(joined_path, -1);
15997     PyMem_Free(joined_path);
15998     if (!entry->path)
15999         goto error;
16000     if (return_bytes) {
16001         Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16002         if (!entry->path)
16003             goto error;
16004     }
16005 
16006     find_data_to_file_info(dataW, &file_info, &reparse_tag);
16007     _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
16008 
16009     /* ctime is only deprecated from 3.12, so we copy birthtime across */
16010     entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16011     entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16012 
16013     return (PyObject *)entry;
16014 
16015 error:
16016     Py_DECREF(entry);
16017     return NULL;
16018 }
16019 
16020 #else /* POSIX */
16021 
16022 static char *
join_path_filename(const char * path_narrow,const char * filename,Py_ssize_t filename_len)16023 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16024 {
16025     Py_ssize_t path_len;
16026     Py_ssize_t size;
16027     char *result;
16028 
16029     if (!path_narrow) { /* Default arg: "." */
16030         path_narrow = ".";
16031         path_len = 1;
16032     }
16033     else {
16034         path_len = strlen(path_narrow);
16035     }
16036 
16037     if (filename_len == -1)
16038         filename_len = strlen(filename);
16039 
16040     /* The +1's are for the path separator and the NUL */
16041     size = path_len + 1 + filename_len + 1;
16042     result = PyMem_New(char, size);
16043     if (!result) {
16044         PyErr_NoMemory();
16045         return NULL;
16046     }
16047     strcpy(result, path_narrow);
16048     if (path_len > 0 && result[path_len - 1] != '/')
16049         result[path_len++] = '/';
16050     strcpy(result + path_len, filename);
16051     return result;
16052 }
16053 
16054 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)16055 DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
16056                          Py_ssize_t name_len, ino_t d_ino
16057 #ifdef HAVE_DIRENT_D_TYPE
16058                          , unsigned char d_type
16059 #endif
16060                          )
16061 {
16062     DirEntry *entry;
16063     char *joined_path;
16064 
16065     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16066     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16067     if (!entry)
16068         return NULL;
16069     entry->name = NULL;
16070     entry->path = NULL;
16071     entry->stat = NULL;
16072     entry->lstat = NULL;
16073 
16074     if (path->fd != -1) {
16075         entry->dir_fd = path->fd;
16076         joined_path = NULL;
16077     }
16078     else {
16079         entry->dir_fd = DEFAULT_DIR_FD;
16080         joined_path = join_path_filename(path->narrow, name, name_len);
16081         if (!joined_path)
16082             goto error;
16083     }
16084 
16085     if (!path->narrow || !PyBytes_Check(path->object)) {
16086         entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
16087         if (joined_path)
16088             entry->path = PyUnicode_DecodeFSDefault(joined_path);
16089     }
16090     else {
16091         entry->name = PyBytes_FromStringAndSize(name, name_len);
16092         if (joined_path)
16093             entry->path = PyBytes_FromString(joined_path);
16094     }
16095     PyMem_Free(joined_path);
16096     if (!entry->name)
16097         goto error;
16098 
16099     if (path->fd != -1) {
16100         entry->path = Py_NewRef(entry->name);
16101     }
16102     else if (!entry->path)
16103         goto error;
16104 
16105 #ifdef HAVE_DIRENT_D_TYPE
16106     entry->d_type = d_type;
16107 #endif
16108     entry->d_ino = d_ino;
16109 
16110     return (PyObject *)entry;
16111 
16112 error:
16113     Py_XDECREF(entry);
16114     return NULL;
16115 }
16116 
16117 #endif
16118 
16119 
16120 typedef struct {
16121     PyObject_HEAD
16122     path_t path;
16123 #ifdef MS_WINDOWS
16124     HANDLE handle;
16125     WIN32_FIND_DATAW file_data;
16126     int first_time;
16127 #else /* POSIX */
16128     DIR *dirp;
16129 #endif
16130 #ifdef HAVE_FDOPENDIR
16131     int fd;
16132 #endif
16133 } ScandirIterator;
16134 
16135 #ifdef MS_WINDOWS
16136 
16137 static int
ScandirIterator_is_closed(ScandirIterator * iterator)16138 ScandirIterator_is_closed(ScandirIterator *iterator)
16139 {
16140     return iterator->handle == INVALID_HANDLE_VALUE;
16141 }
16142 
16143 static void
ScandirIterator_closedir(ScandirIterator * iterator)16144 ScandirIterator_closedir(ScandirIterator *iterator)
16145 {
16146     HANDLE handle = iterator->handle;
16147 
16148     if (handle == INVALID_HANDLE_VALUE)
16149         return;
16150 
16151     iterator->handle = INVALID_HANDLE_VALUE;
16152     Py_BEGIN_ALLOW_THREADS
16153     FindClose(handle);
16154     Py_END_ALLOW_THREADS
16155 }
16156 
16157 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)16158 ScandirIterator_iternext(ScandirIterator *iterator)
16159 {
16160     WIN32_FIND_DATAW *file_data = &iterator->file_data;
16161     BOOL success;
16162     PyObject *entry;
16163 
16164     /* Happens if the iterator is iterated twice, or closed explicitly */
16165     if (iterator->handle == INVALID_HANDLE_VALUE)
16166         return NULL;
16167 
16168     while (1) {
16169         if (!iterator->first_time) {
16170             Py_BEGIN_ALLOW_THREADS
16171             success = FindNextFileW(iterator->handle, file_data);
16172             Py_END_ALLOW_THREADS
16173             if (!success) {
16174                 /* Error or no more files */
16175                 if (GetLastError() != ERROR_NO_MORE_FILES)
16176                     path_error(&iterator->path);
16177                 break;
16178             }
16179         }
16180         iterator->first_time = 0;
16181 
16182         /* Skip over . and .. */
16183         if (wcscmp(file_data->cFileName, L".") != 0 &&
16184             wcscmp(file_data->cFileName, L"..") != 0)
16185         {
16186             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16187             entry = DirEntry_from_find_data(module, &iterator->path, file_data);
16188             if (!entry)
16189                 break;
16190             return entry;
16191         }
16192 
16193         /* Loop till we get a non-dot directory or finish iterating */
16194     }
16195 
16196     /* Error or no more files */
16197     ScandirIterator_closedir(iterator);
16198     return NULL;
16199 }
16200 
16201 #else /* POSIX */
16202 
16203 static int
ScandirIterator_is_closed(ScandirIterator * iterator)16204 ScandirIterator_is_closed(ScandirIterator *iterator)
16205 {
16206     return !iterator->dirp;
16207 }
16208 
16209 static void
ScandirIterator_closedir(ScandirIterator * iterator)16210 ScandirIterator_closedir(ScandirIterator *iterator)
16211 {
16212     DIR *dirp = iterator->dirp;
16213 
16214     if (!dirp)
16215         return;
16216 
16217     iterator->dirp = NULL;
16218     Py_BEGIN_ALLOW_THREADS
16219 #ifdef HAVE_FDOPENDIR
16220     if (iterator->path.fd != -1)
16221         rewinddir(dirp);
16222 #endif
16223     closedir(dirp);
16224     Py_END_ALLOW_THREADS
16225     return;
16226 }
16227 
16228 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)16229 ScandirIterator_iternext(ScandirIterator *iterator)
16230 {
16231     struct dirent *direntp;
16232     Py_ssize_t name_len;
16233     int is_dot;
16234     PyObject *entry;
16235 
16236     /* Happens if the iterator is iterated twice, or closed explicitly */
16237     if (!iterator->dirp)
16238         return NULL;
16239 
16240     while (1) {
16241         errno = 0;
16242         Py_BEGIN_ALLOW_THREADS
16243         direntp = readdir(iterator->dirp);
16244         Py_END_ALLOW_THREADS
16245 
16246         if (!direntp) {
16247             /* Error or no more files */
16248             if (errno != 0)
16249                 path_error(&iterator->path);
16250             break;
16251         }
16252 
16253         /* Skip over . and .. */
16254         name_len = NAMLEN(direntp);
16255         is_dot = direntp->d_name[0] == '.' &&
16256                  (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
16257         if (!is_dot) {
16258             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
16259             entry = DirEntry_from_posix_info(module,
16260                                              &iterator->path, direntp->d_name,
16261                                              name_len, direntp->d_ino
16262 #ifdef HAVE_DIRENT_D_TYPE
16263                                              , direntp->d_type
16264 #endif
16265                                             );
16266             if (!entry)
16267                 break;
16268             return entry;
16269         }
16270 
16271         /* Loop till we get a non-dot directory or finish iterating */
16272     }
16273 
16274     /* Error or no more files */
16275     ScandirIterator_closedir(iterator);
16276     return NULL;
16277 }
16278 
16279 #endif
16280 
16281 static PyObject *
ScandirIterator_close(ScandirIterator * self,PyObject * args)16282 ScandirIterator_close(ScandirIterator *self, PyObject *args)
16283 {
16284     ScandirIterator_closedir(self);
16285     Py_RETURN_NONE;
16286 }
16287 
16288 static PyObject *
ScandirIterator_enter(PyObject * self,PyObject * args)16289 ScandirIterator_enter(PyObject *self, PyObject *args)
16290 {
16291     return Py_NewRef(self);
16292 }
16293 
16294 static PyObject *
ScandirIterator_exit(ScandirIterator * self,PyObject * args)16295 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
16296 {
16297     ScandirIterator_closedir(self);
16298     Py_RETURN_NONE;
16299 }
16300 
16301 static void
ScandirIterator_finalize(ScandirIterator * iterator)16302 ScandirIterator_finalize(ScandirIterator *iterator)
16303 {
16304 
16305     /* Save the current exception, if any. */
16306     PyObject *exc = PyErr_GetRaisedException();
16307 
16308     if (!ScandirIterator_is_closed(iterator)) {
16309         ScandirIterator_closedir(iterator);
16310 
16311         if (PyErr_ResourceWarning((PyObject *)iterator, 1,
16312                                   "unclosed scandir iterator %R", iterator)) {
16313             /* Spurious errors can appear at shutdown */
16314             if (PyErr_ExceptionMatches(PyExc_Warning)) {
16315                 PyErr_WriteUnraisable((PyObject *) iterator);
16316             }
16317         }
16318     }
16319 
16320     path_cleanup(&iterator->path);
16321 
16322     /* Restore the saved exception. */
16323     PyErr_SetRaisedException(exc);
16324 }
16325 
16326 static void
ScandirIterator_dealloc(ScandirIterator * iterator)16327 ScandirIterator_dealloc(ScandirIterator *iterator)
16328 {
16329     PyTypeObject *tp = Py_TYPE(iterator);
16330     if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
16331         return;
16332 
16333     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16334     free_func(iterator);
16335     Py_DECREF(tp);
16336 }
16337 
16338 static PyMethodDef ScandirIterator_methods[] = {
16339     {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
16340     {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
16341     {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
16342     {NULL}
16343 };
16344 
16345 static PyType_Slot ScandirIteratorType_slots[] = {
16346     {Py_tp_dealloc, ScandirIterator_dealloc},
16347     {Py_tp_finalize, ScandirIterator_finalize},
16348     {Py_tp_iter, PyObject_SelfIter},
16349     {Py_tp_iternext, ScandirIterator_iternext},
16350     {Py_tp_methods, ScandirIterator_methods},
16351     {0, 0},
16352 };
16353 
16354 static PyType_Spec ScandirIteratorType_spec = {
16355     MODNAME ".ScandirIterator",
16356     sizeof(ScandirIterator),
16357     0,
16358     // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
16359     // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
16360     (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
16361         | Py_TPFLAGS_DISALLOW_INSTANTIATION),
16362     ScandirIteratorType_slots
16363 };
16364 
16365 /*[clinic input]
16366 os.scandir
16367 
16368     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
16369 
16370 Return an iterator of DirEntry objects for given path.
16371 
16372 path can be specified as either str, bytes, or a path-like object.  If path
16373 is bytes, the names of yielded DirEntry objects will also be bytes; in
16374 all other circumstances they will be str.
16375 
16376 If path is None, uses the path='.'.
16377 [clinic start generated code]*/
16378 
16379 static PyObject *
os_scandir_impl(PyObject * module,path_t * path)16380 os_scandir_impl(PyObject *module, path_t *path)
16381 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
16382 {
16383     ScandirIterator *iterator;
16384 #ifdef MS_WINDOWS
16385     wchar_t *path_strW;
16386 #else
16387     const char *path_str;
16388 #ifdef HAVE_FDOPENDIR
16389     int fd = -1;
16390 #endif
16391 #endif
16392 
16393     if (PySys_Audit("os.scandir", "O",
16394                     path->object ? path->object : Py_None) < 0) {
16395         return NULL;
16396     }
16397 
16398     PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
16399     iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
16400     if (!iterator)
16401         return NULL;
16402 
16403 #ifdef MS_WINDOWS
16404     iterator->handle = INVALID_HANDLE_VALUE;
16405 #else
16406     iterator->dirp = NULL;
16407 #endif
16408 
16409     /* Move the ownership to iterator->path */
16410     memcpy(&iterator->path, path, sizeof(path_t));
16411     memset(path, 0, sizeof(path_t));
16412 
16413 #ifdef MS_WINDOWS
16414     iterator->first_time = 1;
16415 
16416     path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
16417     if (!path_strW)
16418         goto error;
16419 
16420     Py_BEGIN_ALLOW_THREADS
16421     iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
16422     Py_END_ALLOW_THREADS
16423 
16424     if (iterator->handle == INVALID_HANDLE_VALUE) {
16425         path_error(&iterator->path);
16426         PyMem_Free(path_strW);
16427         goto error;
16428     }
16429     PyMem_Free(path_strW);
16430 #else /* POSIX */
16431     errno = 0;
16432 #ifdef HAVE_FDOPENDIR
16433     if (iterator->path.fd != -1) {
16434       if (HAVE_FDOPENDIR_RUNTIME) {
16435         /* closedir() closes the FD, so we duplicate it */
16436         fd = _Py_dup(iterator->path.fd);
16437         if (fd == -1)
16438             goto error;
16439 
16440         Py_BEGIN_ALLOW_THREADS
16441         iterator->dirp = fdopendir(fd);
16442         Py_END_ALLOW_THREADS
16443       } else {
16444         PyErr_SetString(PyExc_TypeError,
16445             "scandir: path should be string, bytes, os.PathLike or None, not int");
16446         return NULL;
16447       }
16448     }
16449     else
16450 #endif
16451     {
16452         if (iterator->path.narrow)
16453             path_str = iterator->path.narrow;
16454         else
16455             path_str = ".";
16456 
16457         Py_BEGIN_ALLOW_THREADS
16458         iterator->dirp = opendir(path_str);
16459         Py_END_ALLOW_THREADS
16460     }
16461 
16462     if (!iterator->dirp) {
16463         path_error(&iterator->path);
16464 #ifdef HAVE_FDOPENDIR
16465         if (fd != -1) {
16466             Py_BEGIN_ALLOW_THREADS
16467             close(fd);
16468             Py_END_ALLOW_THREADS
16469         }
16470 #endif
16471         goto error;
16472     }
16473 #endif
16474 
16475     return (PyObject *)iterator;
16476 
16477 error:
16478     Py_DECREF(iterator);
16479     return NULL;
16480 }
16481 
16482 /*
16483     Return the file system path representation of the object.
16484 
16485     If the object is str or bytes, then allow it to pass through with
16486     an incremented refcount. If the object defines __fspath__(), then
16487     return the result of that method. All other types raise a TypeError.
16488 */
16489 PyObject *
PyOS_FSPath(PyObject * path)16490 PyOS_FSPath(PyObject *path)
16491 {
16492     /* For error message reasons, this function is manually inlined in
16493        path_converter(). */
16494     PyObject *func = NULL;
16495     PyObject *path_repr = NULL;
16496 
16497     if (PyUnicode_Check(path) || PyBytes_Check(path)) {
16498         return Py_NewRef(path);
16499     }
16500 
16501     func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
16502     if ((NULL == func) || (func == Py_None)) {
16503         return PyErr_Format(PyExc_TypeError,
16504                             "expected str, bytes or os.PathLike object, "
16505                             "not %.200s",
16506                             _PyType_Name(Py_TYPE(path)));
16507     }
16508 
16509     path_repr = _PyObject_CallNoArgs(func);
16510     Py_DECREF(func);
16511     if (NULL == path_repr) {
16512         return NULL;
16513     }
16514 
16515     if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
16516         PyErr_Format(PyExc_TypeError,
16517                      "expected %.200s.__fspath__() to return str or bytes, "
16518                      "not %.200s", _PyType_Name(Py_TYPE(path)),
16519                      _PyType_Name(Py_TYPE(path_repr)));
16520         Py_DECREF(path_repr);
16521         return NULL;
16522     }
16523 
16524     return path_repr;
16525 }
16526 
16527 /*[clinic input]
16528 os.fspath
16529 
16530     path: object
16531 
16532 Return the file system path representation of the object.
16533 
16534 If the object is str or bytes, then allow it to pass through as-is. If the
16535 object defines __fspath__(), then return the result of that method. All other
16536 types raise a TypeError.
16537 [clinic start generated code]*/
16538 
16539 static PyObject *
os_fspath_impl(PyObject * module,PyObject * path)16540 os_fspath_impl(PyObject *module, PyObject *path)
16541 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
16542 {
16543     return PyOS_FSPath(path);
16544 }
16545 
16546 #ifdef HAVE_GETRANDOM_SYSCALL
16547 /*[clinic input]
16548 os.getrandom
16549 
16550     size: Py_ssize_t
16551     flags: int=0
16552 
16553 Obtain a series of random bytes.
16554 [clinic start generated code]*/
16555 
16556 static PyObject *
os_getrandom_impl(PyObject * module,Py_ssize_t size,int flags)16557 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
16558 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
16559 {
16560     PyObject *bytes;
16561     Py_ssize_t n;
16562 
16563     if (size < 0) {
16564         errno = EINVAL;
16565         return posix_error();
16566     }
16567 
16568     bytes = PyBytes_FromStringAndSize(NULL, size);
16569     if (bytes == NULL) {
16570         PyErr_NoMemory();
16571         return NULL;
16572     }
16573 
16574     while (1) {
16575         n = syscall(SYS_getrandom,
16576                     PyBytes_AS_STRING(bytes),
16577                     PyBytes_GET_SIZE(bytes),
16578                     flags);
16579         if (n < 0 && errno == EINTR) {
16580             if (PyErr_CheckSignals() < 0) {
16581                 goto error;
16582             }
16583 
16584             /* getrandom() was interrupted by a signal: retry */
16585             continue;
16586         }
16587         break;
16588     }
16589 
16590     if (n < 0) {
16591         PyErr_SetFromErrno(PyExc_OSError);
16592         goto error;
16593     }
16594 
16595     if (n != size) {
16596         _PyBytes_Resize(&bytes, n);
16597     }
16598 
16599     return bytes;
16600 
16601 error:
16602     Py_DECREF(bytes);
16603     return NULL;
16604 }
16605 #endif   /* HAVE_GETRANDOM_SYSCALL */
16606 
16607 #if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
16608 
16609 /* bpo-36085: Helper functions for managing DLL search directories
16610  * on win32
16611  */
16612 
16613 /*[clinic input]
16614 os._add_dll_directory
16615 
16616     path: path_t
16617 
16618 Add a path to the DLL search path.
16619 
16620 This search path is used when resolving dependencies for imported
16621 extension modules (the module itself is resolved through sys.path),
16622 and also by ctypes.
16623 
16624 Returns an opaque value that may be passed to os.remove_dll_directory
16625 to remove this directory from the search path.
16626 [clinic start generated code]*/
16627 
16628 static PyObject *
os__add_dll_directory_impl(PyObject * module,path_t * path)16629 os__add_dll_directory_impl(PyObject *module, path_t *path)
16630 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
16631 {
16632     DLL_DIRECTORY_COOKIE cookie = 0;
16633     DWORD err = 0;
16634 
16635     if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
16636         return NULL;
16637     }
16638 
16639     Py_BEGIN_ALLOW_THREADS
16640     if (!(cookie = AddDllDirectory(path->wide))) {
16641         err = GetLastError();
16642     }
16643     Py_END_ALLOW_THREADS
16644 
16645     if (err) {
16646         return win32_error_object_err("add_dll_directory",
16647                                       path->object, err);
16648     }
16649 
16650     return PyCapsule_New(cookie, "DLL directory cookie", NULL);
16651 }
16652 
16653 /*[clinic input]
16654 os._remove_dll_directory
16655 
16656     cookie: object
16657 
16658 Removes a path from the DLL search path.
16659 
16660 The parameter is an opaque value that was returned from
16661 os.add_dll_directory. You can only remove directories that you added
16662 yourself.
16663 [clinic start generated code]*/
16664 
16665 static PyObject *
os__remove_dll_directory_impl(PyObject * module,PyObject * cookie)16666 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
16667 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
16668 {
16669     DLL_DIRECTORY_COOKIE cookieValue;
16670     DWORD err = 0;
16671 
16672     if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
16673         PyErr_SetString(PyExc_TypeError,
16674             "Provided cookie was not returned from os.add_dll_directory");
16675         return NULL;
16676     }
16677 
16678     cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
16679         cookie, "DLL directory cookie");
16680 
16681     Py_BEGIN_ALLOW_THREADS
16682     if (!RemoveDllDirectory(cookieValue)) {
16683         err = GetLastError();
16684     }
16685     Py_END_ALLOW_THREADS
16686 
16687     if (err) {
16688         return win32_error_object_err("remove_dll_directory",
16689                                       NULL, err);
16690     }
16691 
16692     if (PyCapsule_SetName(cookie, NULL)) {
16693         return NULL;
16694     }
16695 
16696     Py_RETURN_NONE;
16697 }
16698 
16699 #endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
16700 
16701 
16702 /* Only check if WIFEXITED is available: expect that it comes
16703    with WEXITSTATUS, WIFSIGNALED, etc.
16704 
16705    os.waitstatus_to_exitcode() is implemented in C and not in Python, so
16706    subprocess can safely call it during late Python finalization without
16707    risking that used os attributes were set to None by finalize_modules(). */
16708 #if defined(WIFEXITED) || defined(MS_WINDOWS)
16709 /*[clinic input]
16710 os.waitstatus_to_exitcode
16711 
16712     status as status_obj: object
16713 
16714 Convert a wait status to an exit code.
16715 
16716 On Unix:
16717 
16718 * If WIFEXITED(status) is true, return WEXITSTATUS(status).
16719 * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
16720 * Otherwise, raise a ValueError.
16721 
16722 On Windows, return status shifted right by 8 bits.
16723 
16724 On Unix, if the process is being traced or if waitpid() was called with
16725 WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
16726 This function must not be called if WIFSTOPPED(status) is true.
16727 [clinic start generated code]*/
16728 
16729 static PyObject *
os_waitstatus_to_exitcode_impl(PyObject * module,PyObject * status_obj)16730 os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
16731 /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
16732 {
16733 #ifndef MS_WINDOWS
16734     int status = PyLong_AsInt(status_obj);
16735     if (status == -1 && PyErr_Occurred()) {
16736         return NULL;
16737     }
16738 
16739     WAIT_TYPE wait_status;
16740     WAIT_STATUS_INT(wait_status) = status;
16741     int exitcode;
16742     if (WIFEXITED(wait_status)) {
16743         exitcode = WEXITSTATUS(wait_status);
16744         /* Sanity check to provide warranty on the function behavior.
16745            It should not occur in practice */
16746         if (exitcode < 0) {
16747             PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
16748             return NULL;
16749         }
16750     }
16751     else if (WIFSIGNALED(wait_status)) {
16752         int signum = WTERMSIG(wait_status);
16753         /* Sanity check to provide warranty on the function behavior.
16754            It should not occurs in practice */
16755         if (signum <= 0) {
16756             PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
16757             return NULL;
16758         }
16759         exitcode = -signum;
16760     } else if (WIFSTOPPED(wait_status)) {
16761         /* Status only received if the process is being traced
16762            or if waitpid() was called with WUNTRACED option. */
16763         int signum = WSTOPSIG(wait_status);
16764         PyErr_Format(PyExc_ValueError,
16765                      "process stopped by delivery of signal %i",
16766                      signum);
16767         return NULL;
16768     }
16769     else {
16770         PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
16771         return NULL;
16772     }
16773     return PyLong_FromLong(exitcode);
16774 #else
16775     /* Windows implementation: see os.waitpid() implementation
16776        which uses _cwait(). */
16777     unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
16778     if (status == (unsigned long long)-1 && PyErr_Occurred()) {
16779         return NULL;
16780     }
16781 
16782     unsigned long long exitcode = (status >> 8);
16783     /* ExitProcess() accepts an UINT type:
16784        reject exit code which doesn't fit in an UINT */
16785     if (exitcode > UINT_MAX) {
16786         PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
16787         return NULL;
16788     }
16789     return PyLong_FromUnsignedLong((unsigned long)exitcode);
16790 #endif
16791 }
16792 #endif
16793 
16794 #if defined(MS_WINDOWS)
16795 /*[clinic input]
16796 os._supports_virtual_terminal
16797 
16798 Checks if virtual terminal is supported in windows
16799 [clinic start generated code]*/
16800 
16801 static PyObject *
os__supports_virtual_terminal_impl(PyObject * module)16802 os__supports_virtual_terminal_impl(PyObject *module)
16803 /*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
16804 {
16805     DWORD mode = 0;
16806     HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
16807     if (!GetConsoleMode(handle, &mode)) {
16808         Py_RETURN_FALSE;
16809     }
16810     return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
16811 }
16812 #endif
16813 
16814 /*[clinic input]
16815 os._inputhook
16816 
16817 Calls PyOS_CallInputHook droppong the GIL first
16818 [clinic start generated code]*/
16819 
16820 static PyObject *
os__inputhook_impl(PyObject * module)16821 os__inputhook_impl(PyObject *module)
16822 /*[clinic end generated code: output=525aca4ef3c6149f input=fc531701930d064f]*/
16823 {
16824      int result = 0;
16825      if (PyOS_InputHook) {
16826          Py_BEGIN_ALLOW_THREADS;
16827          result = PyOS_InputHook();
16828          Py_END_ALLOW_THREADS;
16829      }
16830      return PyLong_FromLong(result);
16831 }
16832 
16833 /*[clinic input]
16834 os._is_inputhook_installed
16835 
16836 Checks if PyOS_CallInputHook is set
16837 [clinic start generated code]*/
16838 
16839 static PyObject *
os__is_inputhook_installed_impl(PyObject * module)16840 os__is_inputhook_installed_impl(PyObject *module)
16841 /*[clinic end generated code: output=3b3eab4f672c689a input=ff177c9938dd76d8]*/
16842 {
16843     return PyBool_FromLong(PyOS_InputHook != NULL);
16844 }
16845 
16846 static PyMethodDef posix_methods[] = {
16847 
16848     OS_STAT_METHODDEF
16849     OS_ACCESS_METHODDEF
16850     OS_TTYNAME_METHODDEF
16851     OS_CHDIR_METHODDEF
16852     OS_CHFLAGS_METHODDEF
16853     OS_CHMOD_METHODDEF
16854     OS_FCHMOD_METHODDEF
16855     OS_LCHMOD_METHODDEF
16856     OS_CHOWN_METHODDEF
16857     OS_FCHOWN_METHODDEF
16858     OS_LCHOWN_METHODDEF
16859     OS_LCHFLAGS_METHODDEF
16860     OS_CHROOT_METHODDEF
16861     OS_CTERMID_METHODDEF
16862     OS_GETCWD_METHODDEF
16863     OS_GETCWDB_METHODDEF
16864     OS_LINK_METHODDEF
16865     OS_LISTDIR_METHODDEF
16866     OS_LISTDRIVES_METHODDEF
16867     OS_LISTMOUNTS_METHODDEF
16868     OS_LISTVOLUMES_METHODDEF
16869     OS_LSTAT_METHODDEF
16870     OS_MKDIR_METHODDEF
16871     OS_NICE_METHODDEF
16872     OS_GETPRIORITY_METHODDEF
16873     OS_SETPRIORITY_METHODDEF
16874     OS_POSIX_SPAWN_METHODDEF
16875     OS_POSIX_SPAWNP_METHODDEF
16876     OS_READLINK_METHODDEF
16877     OS_COPY_FILE_RANGE_METHODDEF
16878     OS_SPLICE_METHODDEF
16879     OS_RENAME_METHODDEF
16880     OS_REPLACE_METHODDEF
16881     OS_RMDIR_METHODDEF
16882     OS_SYMLINK_METHODDEF
16883     OS_SYSTEM_METHODDEF
16884     OS_UMASK_METHODDEF
16885     OS_UNAME_METHODDEF
16886     OS_UNLINK_METHODDEF
16887     OS_REMOVE_METHODDEF
16888     OS_UTIME_METHODDEF
16889     OS_TIMES_METHODDEF
16890     OS__EXIT_METHODDEF
16891     OS__FCOPYFILE_METHODDEF
16892     OS_EXECV_METHODDEF
16893     OS_EXECVE_METHODDEF
16894     OS_SPAWNV_METHODDEF
16895     OS_SPAWNVE_METHODDEF
16896     OS_FORK1_METHODDEF
16897     OS_FORK_METHODDEF
16898     OS_REGISTER_AT_FORK_METHODDEF
16899     OS_SCHED_GET_PRIORITY_MAX_METHODDEF
16900     OS_SCHED_GET_PRIORITY_MIN_METHODDEF
16901     OS_SCHED_GETPARAM_METHODDEF
16902     OS_SCHED_GETSCHEDULER_METHODDEF
16903     OS_SCHED_RR_GET_INTERVAL_METHODDEF
16904     OS_SCHED_SETPARAM_METHODDEF
16905     OS_SCHED_SETSCHEDULER_METHODDEF
16906     OS_SCHED_YIELD_METHODDEF
16907     OS_SCHED_SETAFFINITY_METHODDEF
16908     OS_SCHED_GETAFFINITY_METHODDEF
16909     OS_POSIX_OPENPT_METHODDEF
16910     OS_GRANTPT_METHODDEF
16911     OS_UNLOCKPT_METHODDEF
16912     OS_PTSNAME_METHODDEF
16913     OS_OPENPTY_METHODDEF
16914     OS_LOGIN_TTY_METHODDEF
16915     OS_FORKPTY_METHODDEF
16916     OS_GETEGID_METHODDEF
16917     OS_GETEUID_METHODDEF
16918     OS_GETGID_METHODDEF
16919     OS_GETGROUPLIST_METHODDEF
16920     OS_GETGROUPS_METHODDEF
16921     OS_GETPID_METHODDEF
16922     OS_GETPGRP_METHODDEF
16923     OS_GETPPID_METHODDEF
16924     OS_GETUID_METHODDEF
16925     OS_GETLOGIN_METHODDEF
16926     OS_KILL_METHODDEF
16927     OS_KILLPG_METHODDEF
16928     OS_PLOCK_METHODDEF
16929     OS_STARTFILE_METHODDEF
16930     OS_SETUID_METHODDEF
16931     OS_SETEUID_METHODDEF
16932     OS_SETREUID_METHODDEF
16933     OS_SETGID_METHODDEF
16934     OS_SETEGID_METHODDEF
16935     OS_SETREGID_METHODDEF
16936     OS_SETGROUPS_METHODDEF
16937     OS_INITGROUPS_METHODDEF
16938     OS_GETPGID_METHODDEF
16939     OS_SETPGRP_METHODDEF
16940     OS_WAIT_METHODDEF
16941     OS_WAIT3_METHODDEF
16942     OS_WAIT4_METHODDEF
16943     OS_WAITID_METHODDEF
16944     OS_WAITPID_METHODDEF
16945     OS_PIDFD_OPEN_METHODDEF
16946     OS_GETSID_METHODDEF
16947     OS_SETSID_METHODDEF
16948     OS_SETPGID_METHODDEF
16949     OS_TCGETPGRP_METHODDEF
16950     OS_TCSETPGRP_METHODDEF
16951     OS_OPEN_METHODDEF
16952     OS_CLOSE_METHODDEF
16953     OS_CLOSERANGE_METHODDEF
16954     OS_DEVICE_ENCODING_METHODDEF
16955     OS_DUP_METHODDEF
16956     OS_DUP2_METHODDEF
16957     OS_LOCKF_METHODDEF
16958     OS_LSEEK_METHODDEF
16959     OS_READ_METHODDEF
16960     OS_READV_METHODDEF
16961     OS_PREAD_METHODDEF
16962     OS_PREADV_METHODDEF
16963     OS_WRITE_METHODDEF
16964     OS_WRITEV_METHODDEF
16965     OS_PWRITE_METHODDEF
16966     OS_PWRITEV_METHODDEF
16967     OS_SENDFILE_METHODDEF
16968     OS_FSTAT_METHODDEF
16969     OS_ISATTY_METHODDEF
16970     OS_PIPE_METHODDEF
16971     OS_PIPE2_METHODDEF
16972     OS_MKFIFO_METHODDEF
16973     OS_MKNOD_METHODDEF
16974     OS_MAJOR_METHODDEF
16975     OS_MINOR_METHODDEF
16976     OS_MAKEDEV_METHODDEF
16977     OS_FTRUNCATE_METHODDEF
16978     OS_TRUNCATE_METHODDEF
16979     OS_POSIX_FALLOCATE_METHODDEF
16980     OS_POSIX_FADVISE_METHODDEF
16981     OS_PUTENV_METHODDEF
16982     OS_UNSETENV_METHODDEF
16983     OS_STRERROR_METHODDEF
16984     OS_FCHDIR_METHODDEF
16985     OS_FSYNC_METHODDEF
16986     OS_SYNC_METHODDEF
16987     OS_FDATASYNC_METHODDEF
16988     OS_WCOREDUMP_METHODDEF
16989     OS_WIFCONTINUED_METHODDEF
16990     OS_WIFSTOPPED_METHODDEF
16991     OS_WIFSIGNALED_METHODDEF
16992     OS_WIFEXITED_METHODDEF
16993     OS_WEXITSTATUS_METHODDEF
16994     OS_WTERMSIG_METHODDEF
16995     OS_WSTOPSIG_METHODDEF
16996     OS_FSTATVFS_METHODDEF
16997     OS_STATVFS_METHODDEF
16998     OS_CONFSTR_METHODDEF
16999     OS_SYSCONF_METHODDEF
17000     OS_FPATHCONF_METHODDEF
17001     OS_PATHCONF_METHODDEF
17002     OS_ABORT_METHODDEF
17003     OS__GETFULLPATHNAME_METHODDEF
17004     OS__GETDISKUSAGE_METHODDEF
17005     OS__GETFINALPATHNAME_METHODDEF
17006     OS__FINDFIRSTFILE_METHODDEF
17007     OS__GETVOLUMEPATHNAME_METHODDEF
17008     OS__PATH_SPLITROOT_METHODDEF
17009     OS__PATH_SPLITROOT_EX_METHODDEF
17010     OS__PATH_NORMPATH_METHODDEF
17011     OS_GETLOADAVG_METHODDEF
17012     OS_URANDOM_METHODDEF
17013     OS_SETRESUID_METHODDEF
17014     OS_SETRESGID_METHODDEF
17015     OS_GETRESUID_METHODDEF
17016     OS_GETRESGID_METHODDEF
17017 
17018     OS_GETXATTR_METHODDEF
17019     OS_SETXATTR_METHODDEF
17020     OS_REMOVEXATTR_METHODDEF
17021     OS_LISTXATTR_METHODDEF
17022 
17023     OS_GET_TERMINAL_SIZE_METHODDEF
17024     OS_CPU_COUNT_METHODDEF
17025     OS_GET_INHERITABLE_METHODDEF
17026     OS_SET_INHERITABLE_METHODDEF
17027     OS_GET_HANDLE_INHERITABLE_METHODDEF
17028     OS_SET_HANDLE_INHERITABLE_METHODDEF
17029     OS_GET_BLOCKING_METHODDEF
17030     OS_SET_BLOCKING_METHODDEF
17031     OS_SCANDIR_METHODDEF
17032     OS_FSPATH_METHODDEF
17033     OS_GETRANDOM_METHODDEF
17034     OS_MEMFD_CREATE_METHODDEF
17035     OS_EVENTFD_METHODDEF
17036     OS_EVENTFD_READ_METHODDEF
17037     OS_EVENTFD_WRITE_METHODDEF
17038     OS__ADD_DLL_DIRECTORY_METHODDEF
17039     OS__REMOVE_DLL_DIRECTORY_METHODDEF
17040     OS_WAITSTATUS_TO_EXITCODE_METHODDEF
17041     OS_SETNS_METHODDEF
17042     OS_UNSHARE_METHODDEF
17043     OS_TIMERFD_CREATE_METHODDEF
17044     OS_TIMERFD_SETTIME_METHODDEF
17045     OS_TIMERFD_SETTIME_NS_METHODDEF
17046     OS_TIMERFD_GETTIME_METHODDEF
17047     OS_TIMERFD_GETTIME_NS_METHODDEF
17048 
17049     OS__PATH_ISDEVDRIVE_METHODDEF
17050     OS__PATH_ISDIR_METHODDEF
17051     OS__PATH_ISFILE_METHODDEF
17052     OS__PATH_ISLINK_METHODDEF
17053     OS__PATH_ISJUNCTION_METHODDEF
17054     OS__PATH_EXISTS_METHODDEF
17055     OS__PATH_LEXISTS_METHODDEF
17056 
17057     OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
17058     OS__INPUTHOOK_METHODDEF
17059     OS__IS_INPUTHOOK_INSTALLED_METHODDEF
17060     {NULL,              NULL}            /* Sentinel */
17061 };
17062 
17063 static int
all_ins(PyObject * m)17064 all_ins(PyObject *m)
17065 {
17066 #ifdef F_OK
17067     if (PyModule_AddIntMacro(m, F_OK)) return -1;
17068 #endif
17069 #ifdef R_OK
17070     if (PyModule_AddIntMacro(m, R_OK)) return -1;
17071 #endif
17072 #ifdef W_OK
17073     if (PyModule_AddIntMacro(m, W_OK)) return -1;
17074 #endif
17075 #ifdef X_OK
17076     if (PyModule_AddIntMacro(m, X_OK)) return -1;
17077 #endif
17078 #ifdef NGROUPS_MAX
17079     if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
17080 #endif
17081 #ifdef TMP_MAX
17082     if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
17083 #endif
17084 #ifdef WCONTINUED
17085     if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
17086 #endif
17087 #ifdef WNOHANG
17088     if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
17089 #endif
17090 #ifdef WUNTRACED
17091     if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
17092 #endif
17093 #ifdef O_RDONLY
17094     if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
17095 #endif
17096 #ifdef O_WRONLY
17097     if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
17098 #endif
17099 #ifdef O_RDWR
17100     if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
17101 #endif
17102 #ifdef O_NDELAY
17103     if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
17104 #endif
17105 #ifdef O_NONBLOCK
17106     if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
17107 #endif
17108 #ifdef O_APPEND
17109     if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
17110 #endif
17111 #ifdef O_DSYNC
17112     if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
17113 #endif
17114 #ifdef O_RSYNC
17115     if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
17116 #endif
17117 #ifdef O_SYNC
17118     if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
17119 #endif
17120 #ifdef O_NOCTTY
17121     if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
17122 #endif
17123 #ifdef O_CREAT
17124     if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
17125 #endif
17126 #ifdef O_EXCL
17127     if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
17128 #endif
17129 #ifdef O_TRUNC
17130     if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
17131 #endif
17132 #ifdef O_BINARY
17133     if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
17134 #endif
17135 #ifdef O_TEXT
17136     if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
17137 #endif
17138 #ifdef O_XATTR
17139     if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
17140 #endif
17141 #ifdef O_LARGEFILE
17142     if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
17143 #endif
17144 #ifndef __GNU__
17145 #ifdef O_SHLOCK
17146     if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
17147 #endif
17148 #ifdef O_EXLOCK
17149     if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
17150 #endif
17151 #endif
17152 #ifdef O_EXEC
17153     if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
17154 #endif
17155 #ifdef O_SEARCH
17156     if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
17157 #endif
17158 #ifdef O_PATH
17159     if (PyModule_AddIntMacro(m, O_PATH)) return -1;
17160 #endif
17161 #ifdef O_TTY_INIT
17162     if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
17163 #endif
17164 #ifdef O_TMPFILE
17165     if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
17166 #endif
17167 #ifdef PRIO_PROCESS
17168     if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
17169 #endif
17170 #ifdef PRIO_PGRP
17171     if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
17172 #endif
17173 #ifdef PRIO_USER
17174     if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
17175 #endif
17176 #ifdef PRIO_DARWIN_THREAD
17177     if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
17178 #endif
17179 #ifdef PRIO_DARWIN_PROCESS
17180     if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
17181 #endif
17182 #ifdef PRIO_DARWIN_BG
17183     if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
17184 #endif
17185 #ifdef PRIO_DARWIN_NONUI
17186     if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
17187 #endif
17188 #ifdef O_CLOEXEC
17189     if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
17190 #endif
17191 #ifdef O_ACCMODE
17192     if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
17193 #endif
17194 #ifdef O_EVTONLY
17195     if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
17196 #endif
17197 #ifdef O_FSYNC
17198     if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
17199 #endif
17200 #ifdef O_SYMLINK
17201     if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
17202 #endif
17203 
17204 #ifdef SEEK_HOLE
17205     if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
17206 #endif
17207 #ifdef SEEK_DATA
17208     if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
17209 #endif
17210 
17211 /* MS Windows */
17212 #ifdef O_NOINHERIT
17213     /* Don't inherit in child processes. */
17214     if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
17215 #endif
17216 #ifdef _O_SHORT_LIVED
17217     /* Optimize for short life (keep in memory). */
17218     /* MS forgot to define this one with a non-underscore form too. */
17219     if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
17220 #endif
17221 #ifdef O_TEMPORARY
17222     /* Automatically delete when last handle is closed. */
17223     if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
17224 #endif
17225 #ifdef O_RANDOM
17226     /* Optimize for random access. */
17227     if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
17228 #endif
17229 #ifdef O_SEQUENTIAL
17230     /* Optimize for sequential access. */
17231     if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
17232 #endif
17233 
17234 /* GNU extensions. */
17235 #ifdef O_ASYNC
17236     /* Send a SIGIO signal whenever input or output
17237        becomes available on file descriptor */
17238     if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
17239 #endif
17240 #ifdef O_DIRECT
17241     /* Direct disk access. */
17242     if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
17243 #endif
17244 #ifdef O_DIRECTORY
17245     /* Must be a directory.      */
17246     if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
17247 #endif
17248 #ifdef O_NOFOLLOW
17249     /* Do not follow links.      */
17250     if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
17251 #endif
17252 #ifdef O_NOFOLLOW_ANY
17253     if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
17254 #endif
17255 #ifdef O_NOLINKS
17256     /* Fails if link count of the named file is greater than 1 */
17257     if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
17258 #endif
17259 #ifdef O_NOATIME
17260     /* Do not update the access time. */
17261     if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
17262 #endif
17263 
17264     /* These come from sysexits.h */
17265 #ifdef EX_OK
17266     if (PyModule_AddIntMacro(m, EX_OK)) return -1;
17267 #endif /* EX_OK */
17268 #ifdef EX_USAGE
17269     if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
17270 #endif /* EX_USAGE */
17271 #ifdef EX_DATAERR
17272     if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
17273 #endif /* EX_DATAERR */
17274 #ifdef EX_NOINPUT
17275     if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
17276 #endif /* EX_NOINPUT */
17277 #ifdef EX_NOUSER
17278     if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
17279 #endif /* EX_NOUSER */
17280 #ifdef EX_NOHOST
17281     if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
17282 #endif /* EX_NOHOST */
17283 #ifdef EX_UNAVAILABLE
17284     if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
17285 #endif /* EX_UNAVAILABLE */
17286 #ifdef EX_SOFTWARE
17287     if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
17288 #endif /* EX_SOFTWARE */
17289 #ifdef EX_OSERR
17290     if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
17291 #endif /* EX_OSERR */
17292 #ifdef EX_OSFILE
17293     if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
17294 #endif /* EX_OSFILE */
17295 #ifdef EX_CANTCREAT
17296     if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
17297 #endif /* EX_CANTCREAT */
17298 #ifdef EX_IOERR
17299     if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
17300 #endif /* EX_IOERR */
17301 #ifdef EX_TEMPFAIL
17302     if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
17303 #endif /* EX_TEMPFAIL */
17304 #ifdef EX_PROTOCOL
17305     if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
17306 #endif /* EX_PROTOCOL */
17307 #ifdef EX_NOPERM
17308     if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
17309 #endif /* EX_NOPERM */
17310 #ifdef EX_CONFIG
17311     if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
17312 #endif /* EX_CONFIG */
17313 #ifdef EX_NOTFOUND
17314     if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
17315 #endif /* EX_NOTFOUND */
17316 
17317     /* statvfs */
17318 #ifdef ST_RDONLY
17319     if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
17320 #endif /* ST_RDONLY */
17321 #ifdef ST_NOSUID
17322     if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
17323 #endif /* ST_NOSUID */
17324 
17325        /* GNU extensions */
17326 #ifdef ST_NODEV
17327     if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
17328 #endif /* ST_NODEV */
17329 #ifdef ST_NOEXEC
17330     if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
17331 #endif /* ST_NOEXEC */
17332 #ifdef ST_SYNCHRONOUS
17333     if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
17334 #endif /* ST_SYNCHRONOUS */
17335 #ifdef ST_MANDLOCK
17336     if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
17337 #endif /* ST_MANDLOCK */
17338 #ifdef ST_WRITE
17339     if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
17340 #endif /* ST_WRITE */
17341 #ifdef ST_APPEND
17342     if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
17343 #endif /* ST_APPEND */
17344 #ifdef ST_NOATIME
17345     if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
17346 #endif /* ST_NOATIME */
17347 #ifdef ST_NODIRATIME
17348     if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
17349 #endif /* ST_NODIRATIME */
17350 #ifdef ST_RELATIME
17351     if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
17352 #endif /* ST_RELATIME */
17353 
17354     /* FreeBSD sendfile() constants */
17355 #ifdef SF_NODISKIO
17356     if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
17357 #endif
17358     /* is obsolete since the 11.x release */
17359 #ifdef SF_MNOWAIT
17360     if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
17361 #endif
17362 #ifdef SF_SYNC
17363     if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
17364 #endif
17365 #ifdef SF_NOCACHE
17366     if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
17367 #endif
17368 
17369 #ifdef TFD_NONBLOCK
17370     if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
17371 #endif
17372 #ifdef TFD_CLOEXEC
17373     if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
17374 #endif
17375 #ifdef TFD_TIMER_ABSTIME
17376     if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
17377 #endif
17378 #ifdef TFD_TIMER_CANCEL_ON_SET
17379     if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
17380 #endif
17381 
17382     /* constants for posix_fadvise */
17383 #ifdef POSIX_FADV_NORMAL
17384     if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
17385 #endif
17386 #ifdef POSIX_FADV_SEQUENTIAL
17387     if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
17388 #endif
17389 #ifdef POSIX_FADV_RANDOM
17390     if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
17391 #endif
17392 #ifdef POSIX_FADV_NOREUSE
17393     if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
17394 #endif
17395 #ifdef POSIX_FADV_WILLNEED
17396     if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
17397 #endif
17398 #ifdef POSIX_FADV_DONTNEED
17399     if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
17400 #endif
17401 
17402     /* constants for waitid */
17403 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
17404     if (PyModule_AddIntMacro(m, P_PID)) return -1;
17405     if (PyModule_AddIntMacro(m, P_PGID)) return -1;
17406     if (PyModule_AddIntMacro(m, P_ALL)) return -1;
17407 #ifdef P_PIDFD
17408     if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
17409 #endif
17410 #ifdef PIDFD_NONBLOCK
17411     if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
17412 #endif
17413 #endif
17414 #ifdef WEXITED
17415     if (PyModule_AddIntMacro(m, WEXITED)) return -1;
17416 #endif
17417 #ifdef WNOWAIT
17418     if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
17419 #endif
17420 #ifdef WSTOPPED
17421     if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
17422 #endif
17423 #ifdef CLD_EXITED
17424     if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
17425 #endif
17426 #ifdef CLD_KILLED
17427     if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
17428 #endif
17429 #ifdef CLD_DUMPED
17430     if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
17431 #endif
17432 #ifdef CLD_TRAPPED
17433     if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
17434 #endif
17435 #ifdef CLD_STOPPED
17436     if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
17437 #endif
17438 #ifdef CLD_CONTINUED
17439     if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
17440 #endif
17441 
17442     /* constants for lockf */
17443 #ifdef F_LOCK
17444     if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
17445 #endif
17446 #ifdef F_TLOCK
17447     if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
17448 #endif
17449 #ifdef F_ULOCK
17450     if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
17451 #endif
17452 #ifdef F_TEST
17453     if (PyModule_AddIntMacro(m, F_TEST)) return -1;
17454 #endif
17455 
17456 #ifdef RWF_DSYNC
17457     if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
17458 #endif
17459 #ifdef RWF_HIPRI
17460     if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
17461 #endif
17462 #ifdef RWF_SYNC
17463     if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
17464 #endif
17465 #ifdef RWF_NOWAIT
17466     if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
17467 #endif
17468 #ifdef RWF_APPEND
17469     if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
17470 #endif
17471 
17472 /* constants for splice */
17473 #if defined(HAVE_SPLICE) && defined(__linux__)
17474     if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
17475     if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
17476     if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
17477 #endif
17478 
17479 /* constants for posix_spawn */
17480 #ifdef HAVE_POSIX_SPAWN
17481     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
17482     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
17483     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
17484 #ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
17485     if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
17486 #endif
17487 #endif
17488 
17489 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
17490     if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
17491     if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
17492     if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
17493 #endif
17494 #ifdef HAVE_SPAWNV
17495     if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
17496     if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
17497 #endif
17498 
17499 #ifdef HAVE_SCHED_H
17500 #ifdef SCHED_OTHER
17501     if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
17502 #endif
17503 #ifdef SCHED_FIFO
17504     if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
17505 #endif
17506 #ifdef SCHED_RR
17507     if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
17508 #endif
17509 #ifdef SCHED_SPORADIC
17510     if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
17511 #endif
17512 #ifdef SCHED_BATCH
17513     if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
17514 #endif
17515 #ifdef SCHED_IDLE
17516     if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
17517 #endif
17518 #ifdef SCHED_RESET_ON_FORK
17519     if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
17520 #endif
17521 #ifdef SCHED_SYS
17522     if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
17523 #endif
17524 #ifdef SCHED_IA
17525     if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
17526 #endif
17527 #ifdef SCHED_FSS
17528     if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
17529 #endif
17530 #ifdef SCHED_FX
17531     if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
17532 #endif
17533 
17534 /* constants for namespaces */
17535 #if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
17536 #ifdef CLONE_FS
17537     if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
17538 #endif
17539 #ifdef CLONE_FILES
17540     if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
17541 #endif
17542 #ifdef CLONE_NEWNS
17543     if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
17544 #endif
17545 #ifdef CLONE_NEWCGROUP
17546     if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
17547 #endif
17548 #ifdef CLONE_NEWUTS
17549     if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
17550 #endif
17551 #ifdef CLONE_NEWIPC
17552     if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
17553 #endif
17554 #ifdef CLONE_NEWUSER
17555     if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
17556 #endif
17557 #ifdef CLONE_NEWPID
17558     if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
17559 #endif
17560 #ifdef CLONE_NEWNET
17561     if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
17562 #endif
17563 #ifdef CLONE_NEWTIME
17564     if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
17565 #endif
17566 #ifdef CLONE_SYSVSEM
17567     if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
17568 #endif
17569 #ifdef CLONE_THREAD
17570     if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
17571 #endif
17572 #ifdef CLONE_SIGHAND
17573     if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
17574 #endif
17575 #ifdef CLONE_VM
17576     if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
17577 #endif
17578 #endif
17579 
17580 #endif
17581 
17582 #ifdef USE_XATTRS
17583     if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
17584     if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
17585     if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
17586 #endif
17587 
17588 #if HAVE_DECL_RTLD_LAZY
17589     if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
17590 #endif
17591 #if HAVE_DECL_RTLD_NOW
17592     if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
17593 #endif
17594 #if HAVE_DECL_RTLD_GLOBAL
17595     if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
17596 #endif
17597 #if HAVE_DECL_RTLD_LOCAL
17598     if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
17599 #endif
17600 #if HAVE_DECL_RTLD_NODELETE
17601     if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
17602 #endif
17603 #if HAVE_DECL_RTLD_NOLOAD
17604     if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
17605 #endif
17606 #if HAVE_DECL_RTLD_DEEPBIND
17607     if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
17608 #endif
17609 #if HAVE_DECL_RTLD_MEMBER
17610     if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
17611 #endif
17612 
17613 #ifdef HAVE_GETRANDOM_SYSCALL
17614     if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
17615     if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
17616 #endif
17617 #ifdef HAVE_MEMFD_CREATE
17618     if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
17619     if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
17620 #ifdef MFD_HUGETLB
17621     if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
17622 #endif
17623 #ifdef MFD_HUGE_SHIFT
17624     if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
17625 #endif
17626 #ifdef MFD_HUGE_MASK
17627     if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
17628 #endif
17629 #ifdef MFD_HUGE_64KB
17630     if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
17631 #endif
17632 #ifdef MFD_HUGE_512KB
17633     if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
17634 #endif
17635 #ifdef MFD_HUGE_1MB
17636     if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
17637 #endif
17638 #ifdef MFD_HUGE_2MB
17639     if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
17640 #endif
17641 #ifdef MFD_HUGE_8MB
17642     if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
17643 #endif
17644 #ifdef MFD_HUGE_16MB
17645     if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
17646 #endif
17647 #ifdef MFD_HUGE_32MB
17648     if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
17649 #endif
17650 #ifdef MFD_HUGE_256MB
17651     if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
17652 #endif
17653 #ifdef MFD_HUGE_512MB
17654     if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
17655 #endif
17656 #ifdef MFD_HUGE_1GB
17657     if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
17658 #endif
17659 #ifdef MFD_HUGE_2GB
17660     if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
17661 #endif
17662 #ifdef MFD_HUGE_16GB
17663     if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
17664 #endif
17665 #endif /* HAVE_MEMFD_CREATE */
17666 
17667 #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
17668     if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
17669 #ifdef EFD_NONBLOCK
17670     if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
17671 #endif
17672 #ifdef EFD_SEMAPHORE
17673     if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
17674 #endif
17675 #endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
17676 
17677 #if defined(__APPLE__)
17678     if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
17679     if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
17680     if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
17681     if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
17682 #endif
17683 
17684 #ifdef MS_WINDOWS
17685     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
17686     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
17687     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
17688     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
17689     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
17690 #endif
17691 
17692     return 0;
17693 }
17694 
17695 
17696 
17697 #define PROBE(name, test) \
17698    static int name(void)  \
17699    {                      \
17700       if (test) {        \
17701           return 1;       \
17702       } else {            \
17703           return 0;       \
17704       }                   \
17705    }
17706 
17707 #ifdef HAVE_FSTATAT
17708 PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
17709 #endif
17710 
17711 #ifdef HAVE_FACCESSAT
17712 PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
17713 #endif
17714 
17715 #ifdef HAVE_FCHMODAT
17716 PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
17717 #endif
17718 
17719 #ifdef HAVE_FCHOWNAT
17720 PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
17721 #endif
17722 
17723 #ifdef HAVE_LINKAT
17724 PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
17725 #endif
17726 
17727 #ifdef HAVE_FDOPENDIR
17728 PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
17729 #endif
17730 
17731 #ifdef HAVE_MKDIRAT
17732 PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
17733 #endif
17734 
17735 #ifdef HAVE_MKFIFOAT
17736 PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
17737 #endif
17738 
17739 #ifdef HAVE_MKNODAT
17740 PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
17741 #endif
17742 
17743 #ifdef HAVE_RENAMEAT
17744 PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
17745 #endif
17746 
17747 #ifdef HAVE_UNLINKAT
17748 PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
17749 #endif
17750 
17751 #ifdef HAVE_OPENAT
17752 PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
17753 #endif
17754 
17755 #ifdef HAVE_READLINKAT
17756 PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
17757 #endif
17758 
17759 #ifdef HAVE_SYMLINKAT
17760 PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
17761 #endif
17762 
17763 #ifdef HAVE_FUTIMENS
17764 PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
17765 #endif
17766 
17767 #ifdef HAVE_UTIMENSAT
17768 PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
17769 #endif
17770 
17771 #ifdef HAVE_PTSNAME_R
17772 PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
17773 #endif
17774 
17775 
17776 
17777 static const struct have_function {
17778     const char * const label;
17779     int (*probe)(void);
17780 } have_functions[] = {
17781 
17782 #ifdef HAVE_EVENTFD
17783     {"HAVE_EVENTFD", NULL},
17784 #endif
17785 
17786 #ifdef HAVE_TIMERFD_CREATE
17787     {"HAVE_TIMERFD_CREATE", NULL},
17788 #endif
17789 
17790 #ifdef HAVE_FACCESSAT
17791     { "HAVE_FACCESSAT", probe_faccessat },
17792 #endif
17793 
17794 #ifdef HAVE_FCHDIR
17795     { "HAVE_FCHDIR", NULL },
17796 #endif
17797 
17798 #ifdef HAVE_FCHMOD
17799     { "HAVE_FCHMOD", NULL },
17800 #endif
17801 
17802 #ifdef HAVE_FCHMODAT
17803     { "HAVE_FCHMODAT", probe_fchmodat },
17804 #endif
17805 
17806 #ifdef HAVE_FCHOWN
17807     { "HAVE_FCHOWN", NULL },
17808 #endif
17809 
17810 #ifdef HAVE_FCHOWNAT
17811     { "HAVE_FCHOWNAT", probe_fchownat },
17812 #endif
17813 
17814 #ifdef HAVE_FEXECVE
17815     { "HAVE_FEXECVE", NULL },
17816 #endif
17817 
17818 #ifdef HAVE_FDOPENDIR
17819     { "HAVE_FDOPENDIR", probe_fdopendir },
17820 #endif
17821 
17822 #ifdef HAVE_FPATHCONF
17823     { "HAVE_FPATHCONF", NULL },
17824 #endif
17825 
17826 #ifdef HAVE_FSTATAT
17827     { "HAVE_FSTATAT", probe_fstatat },
17828 #endif
17829 
17830 #ifdef HAVE_FSTATVFS
17831     { "HAVE_FSTATVFS", NULL },
17832 #endif
17833 
17834 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
17835     { "HAVE_FTRUNCATE", NULL },
17836 #endif
17837 
17838 #ifdef HAVE_FUTIMENS
17839     { "HAVE_FUTIMENS", probe_futimens },
17840 #endif
17841 
17842 #ifdef HAVE_FUTIMES
17843     { "HAVE_FUTIMES", NULL },
17844 #endif
17845 
17846 #ifdef HAVE_FUTIMESAT
17847     { "HAVE_FUTIMESAT", NULL },
17848 #endif
17849 
17850 #ifdef HAVE_LINKAT
17851     { "HAVE_LINKAT", probe_linkat },
17852 #endif
17853 
17854 #ifdef HAVE_LCHFLAGS
17855     { "HAVE_LCHFLAGS", NULL },
17856 #endif
17857 
17858 #ifdef HAVE_LCHMOD
17859     { "HAVE_LCHMOD", NULL },
17860 #endif
17861 
17862 #ifdef HAVE_LCHOWN
17863     { "HAVE_LCHOWN", NULL },
17864 #endif
17865 
17866 #ifdef HAVE_LSTAT
17867     { "HAVE_LSTAT", NULL },
17868 #endif
17869 
17870 #ifdef HAVE_LUTIMES
17871     { "HAVE_LUTIMES", NULL },
17872 #endif
17873 
17874 #ifdef HAVE_MEMFD_CREATE
17875     { "HAVE_MEMFD_CREATE", NULL },
17876 #endif
17877 
17878 #ifdef HAVE_MKDIRAT
17879     { "HAVE_MKDIRAT", probe_mkdirat },
17880 #endif
17881 
17882 #ifdef HAVE_MKFIFOAT
17883     { "HAVE_MKFIFOAT", probe_mkfifoat },
17884 #endif
17885 
17886 #ifdef HAVE_MKNODAT
17887     { "HAVE_MKNODAT", probe_mknodat },
17888 #endif
17889 
17890 #ifdef HAVE_OPENAT
17891     { "HAVE_OPENAT", probe_openat },
17892 #endif
17893 
17894 #ifdef HAVE_READLINKAT
17895     { "HAVE_READLINKAT", probe_readlinkat },
17896 #endif
17897 
17898 #ifdef HAVE_RENAMEAT
17899     { "HAVE_RENAMEAT", probe_renameat },
17900 #endif
17901 
17902 #ifdef HAVE_SYMLINKAT
17903     { "HAVE_SYMLINKAT", probe_symlinkat },
17904 #endif
17905 
17906 #ifdef HAVE_UNLINKAT
17907     { "HAVE_UNLINKAT", probe_unlinkat },
17908 #endif
17909 
17910 #ifdef HAVE_UTIMENSAT
17911     { "HAVE_UTIMENSAT", probe_utimensat },
17912 #endif
17913 
17914 #ifdef HAVE_PTSNAME_R
17915     { "HAVE_PTSNAME_R", probe_ptsname_r },
17916 #endif
17917 
17918 #ifdef MS_WINDOWS
17919     { "MS_WINDOWS", NULL },
17920 #endif
17921 
17922     { NULL, NULL }
17923 };
17924 
17925 
17926 static int
posixmodule_exec(PyObject * m)17927 posixmodule_exec(PyObject *m)
17928 {
17929     _posixstate *state = get_posix_state(m);
17930 
17931 #if defined(HAVE_PWRITEV)
17932     if (HAVE_PWRITEV_RUNTIME) {} else {
17933         PyObject* dct = PyModule_GetDict(m);
17934 
17935         if (dct == NULL) {
17936             return -1;
17937         }
17938 
17939         if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
17940             return -1;
17941         }
17942         if (PyDict_PopString(dct, "preadv", NULL) < 0) {
17943             return -1;
17944         }
17945     }
17946 #endif
17947 
17948     /* Initialize environ dictionary */
17949     if (PyModule_Add(m, "environ", convertenviron()) != 0) {
17950         return -1;
17951     }
17952 
17953     if (all_ins(m))
17954         return -1;
17955 
17956     if (setup_confname_tables(m))
17957         return -1;
17958 
17959     if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
17960         return -1;
17961     }
17962 
17963 #if defined(HAVE_WAITID)
17964     waitid_result_desc.name = MODNAME ".waitid_result";
17965     state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
17966     if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
17967         return -1;
17968     }
17969 #endif
17970 
17971     stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
17972     stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
17973     stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
17974     stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
17975     state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
17976     if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
17977         return -1;
17978     }
17979     state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
17980     ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
17981 
17982     statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
17983     state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
17984     if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
17985         return -1;
17986     }
17987 
17988 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
17989     sched_param_desc.name = MODNAME ".sched_param";
17990     state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
17991     if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
17992         return -1;
17993     }
17994     ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
17995     if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
17996                           &os_sched_param_reduce_method) < 0)
17997     {
17998         return -1;
17999     }
18000     PyType_Modified((PyTypeObject *)state->SchedParamType);
18001 #endif
18002 
18003     /* initialize TerminalSize_info */
18004     state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
18005     if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
18006         return -1;
18007     }
18008 
18009     /* initialize scandir types */
18010     PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
18011     if (ScandirIteratorType == NULL) {
18012         return -1;
18013     }
18014     state->ScandirIteratorType = ScandirIteratorType;
18015 
18016     state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
18017     if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
18018         return -1;
18019     }
18020 
18021     times_result_desc.name = MODNAME ".times_result";
18022     state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
18023     if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
18024         return -1;
18025     }
18026 
18027     state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
18028     if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
18029         return -1;
18030     }
18031 
18032     if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
18033         return -1;
18034 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
18035     state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
18036     if (state->struct_rusage == NULL)
18037         return -1;
18038 #endif
18039     state->st_mode = PyUnicode_InternFromString("st_mode");
18040     if (state->st_mode == NULL)
18041         return -1;
18042 
18043     /* suppress "function not used" warnings */
18044     {
18045     int ignored;
18046     fd_specified("", -1);
18047     follow_symlinks_specified("", 1);
18048     dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
18049     dir_fd_converter(Py_None, &ignored);
18050     dir_fd_unavailable(Py_None, &ignored);
18051     }
18052 
18053     /*
18054      * provide list of locally available functions
18055      * so os.py can populate support_* lists
18056      */
18057     PyObject *list = PyList_New(0);
18058     if (!list) {
18059         return -1;
18060     }
18061     for (const struct have_function *trace = have_functions; trace->label; trace++) {
18062         PyObject *unicode;
18063         if (trace->probe && !trace->probe()) continue;
18064         unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
18065         if (!unicode)
18066             return -1;
18067         if (PyList_Append(list, unicode))
18068             return -1;
18069         Py_DECREF(unicode);
18070     }
18071 
18072 #ifndef MS_WINDOWS
18073     if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
18074         PyErr_SetString(PyExc_RuntimeError,
18075                         "cannot read ticks_per_second");
18076         return -1;
18077     }
18078     assert(state->ticks_per_second >= 1);
18079 #endif
18080 
18081     return PyModule_Add(m, "_have_functions", list);
18082 }
18083 
18084 
18085 static PyModuleDef_Slot posixmodile_slots[] = {
18086     {Py_mod_exec, posixmodule_exec},
18087     {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
18088     {Py_mod_gil, Py_MOD_GIL_NOT_USED},
18089     {0, NULL}
18090 };
18091 
18092 static struct PyModuleDef posixmodule = {
18093     PyModuleDef_HEAD_INIT,
18094     .m_name = MODNAME,
18095     .m_doc = posix__doc__,
18096     .m_size = sizeof(_posixstate),
18097     .m_methods = posix_methods,
18098     .m_slots = posixmodile_slots,
18099     .m_traverse = _posix_traverse,
18100     .m_clear = _posix_clear,
18101     .m_free = _posix_free,
18102 };
18103 
18104 PyMODINIT_FUNC
INITFUNC(void)18105 INITFUNC(void)
18106 {
18107     return PyModuleDef_Init(&posixmodule);
18108 }
18109