Coverage Report

Created: 2026-10-17 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Modules/posixmodule.c
Line
Count
Source
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
// --- Python includes ------------------------------------------------------
11
12
#include "Python.h"
13
14
#ifdef __VXWORKS__
15
#  include "pycore_bitutils.h"    // _Py_popcount32()
16
#endif
17
#include "pycore_abstract.h"      // _PyNumber_Index()
18
#include "pycore_call.h"          // _PyObject_CallNoArgs()
19
#include "pycore_ceval.h"         // _PyEval_ReInitThreads()
20
#include "pycore_fileutils.h"     // _Py_closerange()
21
#include "pycore_import.h"        // _PyImport_AcquireLock()
22
#include "pycore_initconfig.h"    // _PyStatus_EXCEPTION()
23
#include "pycore_jit_unwind.h"    // _Py_jit_debug_mutex
24
#include "pycore_lock.h"          // PyMutex_LockFast()
25
#include "pycore_long.h"          // _PyLong_IsNegative()
26
#include "pycore_moduleobject.h"  // _PyModule_GetState()
27
#include "pycore_object.h"        // _PyObject_LookupSpecial()
28
#include "pycore_pylifecycle.h"   // _PyOS_URandom()
29
#include "pycore_pystate.h"       // _PyInterpreterState_GET()
30
#include "pycore_signal.h"        // Py_NSIG
31
#include "pycore_time.h"          // _PyLong_FromTime_t()
32
#include "pycore_tuple.h"         // _PyTuple_FromPairSteal
33
#include "pycore_typeobject.h"    // _PyType_AddMethod()
34
#include "pycore_warnings.h"      // _PyWarnings_AfterFork()
35
36
#ifndef MS_WINDOWS
37
#  include "posixmodule.h"        // _PyLong_FromUid()
38
#else
39
#  include "pycore_fileutils_windows.h" // _Py_GetFileInformationByName()
40
#  include "osdefs.h"             // SEP
41
#  include "winreparse.h"         // _Py_REPARSE_DATA_BUFFER
42
#endif
43
44
45
// --- System includes ------------------------------------------------------
46
47
#include <stddef.h>               // offsetof()
48
#include <stdio.h>                // ctermid()
49
#include <stdlib.h>               // system()
50
51
#ifdef HAVE_UNISTD_H
52
#  include <unistd.h>             // symlink()
53
#endif
54
55
#ifdef __APPLE__
56
   /* Needed for the implementation of os.statvfs */
57
#  include <sys/param.h>
58
#  include <sys/mount.h>
59
#endif
60
61
#ifdef HAVE_SYS_TIME_H
62
#  include <sys/time.h>           // futimes()
63
#endif
64
65
#ifdef HAVE_SYS_PIDFD_H
66
#  include <sys/pidfd.h>          // PIDFD_NONBLOCK
67
#endif
68
69
#ifdef __EMSCRIPTEN__
70
#  include "emscripten.h"         // emscripten_debugger()
71
#endif
72
73
#ifdef HAVE_SYS_RANDOM_H
74
#  include <sys/random.h>         // getrandom()
75
#endif
76
77
#ifdef HAVE_SYS_UIO_H
78
#  include <sys/uio.h>
79
#endif
80
81
#ifdef HAVE_SYS_TYPES_H
82
   /* Should be included before <sys/sysmacros.h> on HP-UX v3 */
83
#  include <sys/types.h>
84
#endif
85
#ifdef HAVE_SYS_SYSMACROS_H
86
   /* GNU C Library: major(), minor(), makedev() */
87
#  include <sys/sysmacros.h>
88
#endif
89
90
#ifdef HAVE_SYS_STAT_H
91
#  include <sys/stat.h>
92
#endif
93
94
#ifdef HAVE_SYS_WAIT_H
95
#  include <sys/wait.h>           // WNOHANG
96
#endif
97
98
#ifdef HAVE_LINUX_WAIT_H
99
#  include <linux/wait.h>         // P_PIDFD
100
#endif
101
102
#ifdef HAVE_SIGNAL_H
103
#  include <signal.h>
104
#endif
105
106
#ifdef HAVE_FCNTL_H
107
#  include <fcntl.h>              // fcntl()
108
#endif
109
110
#ifdef HAVE_GRP_H
111
#  include <grp.h>                // setgroups()
112
#endif
113
114
#ifdef HAVE_SYSEXITS_H
115
#  include <sysexits.h>           // EX_OK
116
#endif
117
118
#ifdef HAVE_SYS_LOADAVG_H
119
#  include <sys/loadavg.h>        // getloadavg()
120
#endif
121
122
#ifdef HAVE_SYS_SENDFILE_H
123
#  include <sys/sendfile.h>       // sendfile()
124
#endif
125
126
#if defined(__APPLE__)
127
#  include <copyfile.h>           // fcopyfile()
128
#endif
129
130
#ifdef HAVE_SCHED_H
131
#  include <sched.h>              // sched_setscheduler()
132
#endif
133
#ifdef HAVE_LINUX_SCHED_H
134
#  include <linux/sched.h>        // SCHED_IDLE, SCHED_RR
135
#endif
136
137
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
138
#  ifdef HAVE_SYS_SOCKET_H
139
#    include <sys/socket.h>
140
#  endif
141
#endif
142
143
#ifdef HAVE_DLFCN_H
144
#  include <dlfcn.h>
145
#endif
146
147
#ifdef __hpux
148
#  include <sys/mpctl.h>
149
#endif
150
151
#if defined(__DragonFly__) || \
152
    defined(__OpenBSD__)   || \
153
    defined(__FreeBSD__)   || \
154
    defined(__NetBSD__)    || \
155
    defined(__APPLE__)
156
#  include <sys/sysctl.h>
157
#endif
158
159
#ifdef HAVE_LINUX_RANDOM_H
160
#  include <linux/random.h>       // GRND_RANDOM
161
#endif
162
#ifdef HAVE_SYS_SYSCALL_H
163
#  include <sys/syscall.h>        // syscall(), __NR_xxx syscall numbers
164
#endif
165
#if !defined(SYS_getrandom) && defined(__NR_getrandom)
166
#  define SYS_getrandom __NR_getrandom
167
#endif
168
169
#ifdef HAVE_POSIX_SPAWN
170
#  include <spawn.h>              // posix_spawn()
171
#endif
172
173
#ifdef HAVE_UTIME_H
174
#  include <utime.h>              // utime()
175
#endif
176
177
#ifdef HAVE_SYS_UTIME_H
178
#  include <sys/utime.h>
179
#  define HAVE_UTIME_H /* pretend we do for the rest of this file */
180
#endif
181
182
#ifdef HAVE_SYS_TIMES_H
183
#  include <sys/times.h>          // times()
184
#endif
185
186
#ifdef HAVE_SYS_PARAM_H
187
#  include <sys/param.h>
188
#endif
189
190
#ifdef HAVE_SYS_UTSNAME_H
191
#  include <sys/utsname.h>        // uname()
192
#endif
193
194
/* memfd_create is either defined in sys/mman.h or sys/memfd.h
195
 * linux/memfd.h defines additional flags
196
 */
197
#ifdef HAVE_SYS_MMAN_H
198
#  include <sys/mman.h>           // memfd_create()
199
#endif
200
#ifdef HAVE_SYS_MEMFD_H
201
#  include <sys/memfd.h>          // memfd_create()
202
#endif
203
#ifdef HAVE_LINUX_MEMFD_H
204
#  include <linux/memfd.h>        // memfd_create(), MFD_CLOEXEC
205
#endif
206
207
#ifdef HAVE_SYS_EVENTFD_H
208
#  include <sys/eventfd.h>        // eventfd()
209
#endif
210
211
#ifdef HAVE_SYS_TIMERFD_H
212
#  include <sys/timerfd.h>        // timerfd_create()
213
#endif
214
215
#ifdef _Py_MEMORY_SANITIZER
216
#  include <sanitizer/msan_interface.h> // __msan_unpoison()
217
#endif
218
219
220
// --- More complex system includes -----------------------------------------
221
222
#ifdef MS_WINDOWS
223
#  include <windows.h>
224
#  if !defined(MS_WINDOWS_GAMES) || defined(MS_WINDOWS_DESKTOP)
225
#    include <pathcch.h>          // PathCchSkipRoot()
226
#  endif
227
#  include <aclapi.h>             // SetEntriesInAcl
228
#  include <lmcons.h>             // UNLEN
229
#  include <sddl.h>               // SDDL_REVISION_1
230
#  include <winioctl.h>           // FSCTL_GET_REPARSE_POINT
231
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
232
#    define HAVE_SYMLINK
233
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
234
#endif
235
236
237
#ifdef _MSC_VER
238
#  ifdef HAVE_DIRECT_H
239
#    include <direct.h>
240
#  endif
241
#  ifdef HAVE_IO_H
242
#    include <io.h>
243
#  endif
244
#  ifdef HAVE_PROCESS_H
245
#    include <process.h>          // getpid(), _cwait()
246
#  endif
247
#  include <malloc.h>
248
#endif /* _MSC_VER */
249
250
251
#ifdef HAVE__GETPTY
252
#  include <sys/types.h>          // mode_t
253
   // SGI apparently needs this forward declaration
254
   extern char * _getpty(int *, int, mode_t, int);
255
#endif
256
257
258
#if defined(HAVE_SYS_XATTR_H)
259
#  if defined(HAVE_LINUX_LIMITS_H) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
260
#    define USE_XATTRS
261
#    include <linux/limits.h>  // Needed for XATTR_SIZE_MAX on musl libc.
262
#  endif
263
#  if defined(__CYGWIN__)
264
#    define USE_XATTRS
265
#    include <cygwin/limits.h>  // Needed for XATTR_SIZE_MAX and XATTR_LIST_MAX.
266
#  endif
267
#endif
268
#ifdef USE_XATTRS
269
#  include <sys/xattr.h>          // fgetxattr()
270
#endif
271
272
273
#ifdef HAVE_WINDOWS_CONSOLE_IO
274
#  define TERMSIZE_USE_CONIO
275
#elif defined(HAVE_SYS_IOCTL_H)
276
#  include <sys/ioctl.h>          // ioctl(), TIOCGWINSZ
277
#  if defined(HAVE_TERMIOS_H)
278
#    include <termios.h>
279
#  endif
280
#  if defined(TIOCGWINSZ)
281
#    define TERMSIZE_USE_IOCTL
282
#  endif
283
#endif
284
285
286
/* Various compilers have only certain posix functions */
287
/* XXX Gosh I wish these were all moved into pyconfig.h */
288
#if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
289
#  define HAVE_OPENDIR    1
290
#  define HAVE_SYSTEM     1
291
#  include <process.h>
292
#elif defined( _MSC_VER)
293
  /* Microsoft compiler */
294
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
295
#    define HAVE_GETPPID    1
296
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_APP | MS_WINDOWS_SYSTEM */
297
#  if defined(MS_WINDOWS_DESKTOP)
298
#    define HAVE_GETLOGIN   1
299
#  endif /* MS_WINDOWS_DESKTOP */
300
#  if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
301
#    define HAVE_SPAWNV     1
302
#    define HAVE_EXECV      1
303
#    define HAVE_WSPAWNV    1
304
#    define HAVE_WEXECV     1
305
#    define HAVE_SYSTEM     1
306
#    define HAVE_CWAIT      1
307
#  endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */
308
#  define HAVE_PIPE       1
309
#  define HAVE_FSYNC      1
310
#  define fsync _commit
311
#endif
312
313
314
#if !defined(_MSC_VER) && defined(__sgi) && _COMPILER_VERSION>=700
315
/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
316
   (default) */
317
extern char *ctermid_r(char *);
318
#endif
319
320
321
#if defined(__VXWORKS__)
322
#  include <vxCpuLib.h>
323
#  include <rtpLib.h>
324
#  include <wait.h>
325
#  include <taskLib.h>
326
#  ifndef _P_WAIT
327
#    define _P_WAIT          0
328
#    define _P_NOWAIT        1
329
#    define _P_NOWAITO       1
330
#  endif
331
#endif /* __VXWORKS__ */
332
333
334
#ifdef HAVE_DIRENT_H
335
#  include <dirent.h>             // opendir()
336
310k
#  define NAMLEN(dirent) strlen((dirent)->d_name)
337
#else
338
#  if defined(__WATCOMC__) && !defined(__QNX__)
339
#    include <direct.h>
340
#    define NAMLEN(dirent) strlen((dirent)->d_name)
341
#  else
342
#    define dirent direct
343
#    define NAMLEN(dirent) (dirent)->d_namlen
344
#  endif
345
#  ifdef HAVE_SYS_NDIR_H
346
#    include <sys/ndir.h>
347
#  endif
348
#  ifdef HAVE_SYS_DIR_H
349
#    include <sys/dir.h>
350
#  endif
351
#  ifdef HAVE_NDIR_H
352
#    include <ndir.h>
353
#  endif
354
#endif
355
356
357
#if defined(MAJOR_IN_MKDEV)
358
#  include <sys/mkdev.h>
359
#else
360
#  if defined(MAJOR_IN_SYSMACROS)
361
#    include <sys/sysmacros.h>
362
#  endif
363
#  if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
364
#    include <sys/mkdev.h>
365
#  endif
366
#endif
367
368
369
// --- Macros ---------------------------------------------------------------
370
371
#ifndef MAXPATHLEN
372
#  if defined(PATH_MAX) && PATH_MAX > 1024
373
#    define MAXPATHLEN PATH_MAX
374
#  else
375
#    define MAXPATHLEN 1024
376
#  endif
377
#endif /* MAXPATHLEN */
378
379
380
#ifdef UNION_WAIT
381
   /* Emulate some macros on systems that have a union instead of macros */
382
#  ifndef WIFEXITED
383
#    define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
384
#  endif
385
#  ifndef WEXITSTATUS
386
#    define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
387
#  endif
388
#  ifndef WTERMSIG
389
#    define WTERMSIG(u_wait) ((u_wait).w_termsig)
390
#  endif
391
#  define WAIT_TYPE union wait
392
#  define WAIT_STATUS_INT(s) (s.w_status)
393
#else
394
   /* !UNION_WAIT */
395
0
#  define WAIT_TYPE int
396
0
#  define WAIT_STATUS_INT(s) (s)
397
#endif /* UNION_WAIT */
398
399
400
/* Don't use the "_r" form if we don't need it (also, won't have a
401
   prototype for it, at least on Solaris -- maybe others as well?). */
402
#if defined(HAVE_CTERMID_R)
403
#  define USE_CTERMID_R
404
#endif
405
406
407
/* choose the appropriate stat and fstat functions and return structs */
408
#undef STAT
409
#undef FSTAT
410
#undef STRUCT_STAT
411
#ifdef MS_WINDOWS
412
#  define STAT win32_stat
413
#  define LSTAT win32_lstat
414
#  define FSTAT _Py_fstat_noraise
415
#  define STRUCT_STAT struct _Py_stat_struct
416
#else
417
233k
#  define STAT stat
418
11.2k
#  define LSTAT lstat
419
91.0k
#  define FSTAT fstat
420
422k
#  define STRUCT_STAT struct stat
421
#endif
422
423
#ifdef HAVE_STATX
424
/* until we can assume glibc 2.28 at runtime, we must weakly link */
425
#  pragma weak statx
426
static const unsigned int _Py_STATX_KNOWN = (STATX_BASIC_STATS | STATX_BTIME
427
#ifdef STATX_MNT_ID
428
                                             | STATX_MNT_ID
429
#endif
430
#ifdef STATX_DIOALIGN
431
                                             | STATX_DIOALIGN
432
#endif
433
#ifdef STATX_MNT_ID_UNIQUE
434
                                             | STATX_MNT_ID_UNIQUE
435
#endif
436
#ifdef STATX_SUBVOL
437
                                             | STATX_SUBVOL
438
#endif
439
#ifdef STATX_WRITE_ATOMIC
440
                                             | STATX_WRITE_ATOMIC
441
#endif
442
#ifdef STATX_DIO_READ_ALIGN
443
                                             | STATX_DIO_READ_ALIGN
444
#endif
445
                                            );
446
#endif /* HAVE_STATX */
447
448
449
#if !defined(EX_OK) && defined(EXIT_SUCCESS)
450
#  define EX_OK EXIT_SUCCESS
451
#endif
452
453
#if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
454
#  undef HAVE_SCHED_SETAFFINITY
455
#endif
456
457
/* On android API level 21, 'AT_EACCESS' is not declared although
458
 * HAVE_FACCESSAT is defined. */
459
#ifdef __ANDROID__
460
#  undef HAVE_FACCESSAT
461
#endif
462
463
#if defined(__sun)
464
/* Something to implement in autoconf, not present in autoconf 2.69 */
465
#  define HAVE_STRUCT_STAT_ST_FSTYPE 1
466
#endif
467
468
469
// --- Apple __builtin_available() macros -----------------------------------
470
471
/*
472
 * A number of APIs are available on macOS from a certain macOS version.
473
 * To support building with a new SDK while deploying to older versions
474
 * the availability test is split into two:
475
 *   - HAVE_<FUNCTION>:  The configure check for compile time availability
476
 *   - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
477
 *
478
 * The latter is always true when not on macOS, or when using a compiler
479
 * that does not support __has_builtin (older versions of Xcode).
480
 *
481
 * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
482
 *    if (HAVE_<FUNCTION>_RUNTIME) { ... }
483
 *
484
 * In mixing the test with other tests or using negations will result in compile
485
 * errors.
486
 */
487
#if defined(__APPLE__)
488
489
#include <mach/mach.h>
490
491
#if defined(__has_builtin)
492
#if __has_builtin(__builtin_available)
493
#define HAVE_BUILTIN_AVAILABLE 1
494
#endif
495
#endif
496
497
#ifdef HAVE_BUILTIN_AVAILABLE
498
#  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
499
#  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
500
#  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
501
#  define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
502
#  define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
503
#  define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
504
#  define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
505
#  define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
506
#  define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
507
#  define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
508
#  define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
509
#  define HAVE_FREADLINK_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, *)
510
#  define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
511
#  define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
512
#  define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
513
#  define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
514
#  define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
515
#  define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
516
#  define HAVE_PTSNAME_R_RUNTIME __builtin_available(macOS 10.13.4, iOS 11.3, tvOS 11.3, watchOS 4.3, *)
517
#  define HAVE_DUP3_RUNTIME __builtin_available(macOS 27.0, iOS 27.0, tvOS 27.0, watchOS 27.0, visionOS 27.0, *)
518
#  define HAVE_PIPE2_RUNTIME __builtin_available(macOS 27.0, iOS 27.0, tvOS 27.0, watchOS 27.0, visionOS 27.0, *)
519
520
#  define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
521
522
#else /* Xcode 8 or earlier */
523
524
   /* __builtin_available is not present in these compilers, but
525
    * some of the symbols might be weak linked (10.10 SDK or later
526
    * deploying on 10.9.
527
    *
528
    * Fall back to the older style of availability checking for
529
    * symbols introduced in macOS 10.10.
530
    */
531
532
#  ifdef HAVE_FSTATAT
533
#    define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
534
#  endif
535
536
#  ifdef HAVE_FACCESSAT
537
#    define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
538
#  endif
539
540
#  ifdef HAVE_FCHMODAT
541
#    define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
542
#  endif
543
544
#  ifdef HAVE_FCHOWNAT
545
#    define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
546
#  endif
547
548
#  ifdef HAVE_LINKAT
549
#    define HAVE_LINKAT_RUNTIME (linkat != NULL)
550
#  endif
551
552
#  ifdef HAVE_FDOPENDIR
553
#    define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
554
#  endif
555
556
#  ifdef HAVE_MKDIRAT
557
#    define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
558
#  endif
559
560
#  ifdef HAVE_RENAMEAT
561
#    define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
562
#  endif
563
564
#  ifdef HAVE_UNLINKAT
565
#    define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
566
#  endif
567
568
#  ifdef HAVE_OPENAT
569
#    define HAVE_OPENAT_RUNTIME (openat != NULL)
570
#  endif
571
572
#  ifdef HAVE_READLINKAT
573
#    define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
574
#  endif
575
576
#  ifdef _Py_HAVE_FREADLINK
577
#    define HAVE_FREADLINK_RUNTIME (freadlink != NULL)
578
#  endif
579
580
#  ifdef HAVE_SYMLINKAT
581
#    define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
582
#  endif
583
584
#  ifdef HAVE_UTIMENSAT
585
#    define HAVE_UTIMENSAT_RUNTIME (utimensat != NULL)
586
#  endif
587
588
#  ifdef HAVE_FUTIMENS
589
#    define HAVE_FUTIMENS_RUNTIME (futimens != NULL)
590
#  endif
591
592
#  ifdef HAVE_PWRITEV
593
#    define HAVE_PWRITEV_RUNTIME (pwritev != NULL)
594
#  endif
595
596
#  ifdef HAVE_MKFIFOAT
597
#    define HAVE_MKFIFOAT_RUNTIME (mkfifoat != NULL)
598
#  endif
599
600
#  ifdef HAVE_MKNODAT
601
#    define HAVE_MKNODAT_RUNTIME (mknodat != NULL)
602
#  endif
603
604
#  ifdef HAVE_PTSNAME_R
605
#    define HAVE_PTSNAME_R_RUNTIME (ptsname_r != NULL)
606
#  endif
607
608
#  ifdef HAVE_DUP3
609
#    define HAVE_DUP3_RUNTIME (dup3 != NULL)
610
#  endif
611
612
#  ifdef HAVE_PIPE2
613
#    define HAVE_PIPE2_RUNTIME (pipe2 != NULL)
614
#  endif
615
616
#endif
617
618
#ifdef HAVE_FUTIMESAT
619
/* Some of the logic for weak linking depends on this assertion */
620
# error "HAVE_FUTIMESAT unexpectedly defined"
621
#endif
622
623
#else
624
86.9k
#  define HAVE_FSTATAT_RUNTIME 1
625
0
#  define HAVE_FACCESSAT_RUNTIME 1
626
0
#  define HAVE_FCHMODAT_RUNTIME 1
627
0
#  define HAVE_FCHOWNAT_RUNTIME 1
628
#ifdef __wasi__
629
#  define HAVE_LINKAT_RUNTIME 0
630
# else
631
0
#  define HAVE_LINKAT_RUNTIME 1
632
# endif
633
91.0k
#  define HAVE_FDOPENDIR_RUNTIME 1
634
0
#  define HAVE_MKDIRAT_RUNTIME 1
635
0
#  define HAVE_RENAMEAT_RUNTIME 1
636
105k
#  define HAVE_UNLINKAT_RUNTIME 1
637
86.9k
#  define HAVE_OPENAT_RUNTIME 1
638
0
#  define HAVE_READLINKAT_RUNTIME 1
639
0
#  define HAVE_SYMLINKAT_RUNTIME 1
640
0
#  define HAVE_FUTIMENS_RUNTIME 1
641
0
#  define HAVE_UTIMENSAT_RUNTIME 1
642
37
#  define HAVE_PWRITEV_RUNTIME 1
643
0
#  define HAVE_MKFIFOAT_RUNTIME 1
644
0
#  define HAVE_MKNODAT_RUNTIME 1
645
0
#  define HAVE_PTSNAME_R_RUNTIME 1
646
0
#  define HAVE_DUP3_RUNTIME 1
647
37
#  define HAVE_PIPE2_RUNTIME 1
648
#  define HAVE_FREADLINK_RUNTIME 1
649
#endif
650
651
652
// --- os module ------------------------------------------------------------
653
654
#ifdef MS_WINDOWS
655
#  define INITFUNC PyInit_nt
656
#  define MODNAME "nt"
657
#  define MODNAME_OBJ &_Py_ID(nt)
658
#else
659
#  define INITFUNC PyInit_posix
660
#  define MODNAME "posix"
661
0
#  define MODNAME_OBJ &_Py_ID(posix)
662
#endif
663
664
/*[clinic input]
665
# one of the few times we lie about this name!
666
module os
667
[clinic start generated code]*/
668
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
669
670
PyDoc_STRVAR(posix__doc__,
671
"This module provides access to operating system functionality that is\n\
672
standardized by the C Standard and the POSIX standard (a thinly\n\
673
disguised Unix interface).  Refer to the library manual and\n\
674
corresponding Unix manual entries for more information on calls.");
675
676
677
// --- Functions ------------------------------------------------------------
678
679
#ifdef HAVE_FORK
680
static void
681
run_at_forkers(PyObject *lst, int reverse)
682
0
{
683
0
    Py_ssize_t i;
684
0
    PyObject *cpy;
685
686
0
    if (lst != NULL) {
687
0
        assert(PyList_CheckExact(lst));
688
689
        /* Use a list copy in case register_at_fork() is called from
690
         * one of the callbacks.
691
         */
692
0
        cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
693
0
        if (cpy == NULL) {
694
0
            PyErr_FormatUnraisable("Exception ignored in atfork callback "
695
0
                                   "while copying list %R", lst);
696
0
        }
697
0
        else {
698
0
            if (reverse)
699
0
                PyList_Reverse(cpy);
700
0
            for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
701
0
                PyObject *func, *res;
702
0
                func = PyList_GET_ITEM(cpy, i);
703
0
                res = _PyObject_CallNoArgs(func);
704
0
                if (res == NULL) {
705
0
                    PyErr_FormatUnraisable("Exception ignored "
706
0
                                           "in atfork callback %R", func);
707
0
                }
708
0
                else {
709
0
                    Py_DECREF(res);
710
0
                }
711
0
            }
712
0
            Py_DECREF(cpy);
713
0
        }
714
0
    }
715
0
}
716
717
void
718
PyOS_BeforeFork(void)
719
0
{
720
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
721
0
    run_at_forkers(interp->before_forkers, 1);
722
723
0
    _PyImport_AcquireLock(interp);
724
0
    _PyEval_StopTheWorldAll(&_PyRuntime);
725
0
    HEAD_LOCK(&_PyRuntime);
726
0
    _PyWarnings_BeforeFork(interp);
727
0
}
728
729
void
730
PyOS_AfterFork_Parent(void)
731
0
{
732
0
    HEAD_UNLOCK(&_PyRuntime);
733
0
    _PyEval_StartTheWorldAll(&_PyRuntime);
734
735
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
736
0
    _PyImport_ReleaseLock(interp);
737
0
    run_at_forkers(interp->after_forkers_parent, 0);
738
0
}
739
740
static void
741
reset_remotedebug_data(PyThreadState *tstate)
742
0
{
743
0
    tstate->remote_debugger_support.debugger_pending_call = 0;
744
0
    memset(tstate->remote_debugger_support.debugger_script_path, 0,
745
0
           _Py_MAX_SCRIPT_PATH_SIZE);
746
0
}
747
748
static void
749
reset_asyncio_state(_PyThreadStateImpl *tstate)
750
0
{
751
0
    llist_init(&tstate->asyncio_tasks_head);
752
0
    tstate->asyncio_running_loop = NULL;
753
0
    tstate->asyncio_running_task = NULL;
754
0
}
755
756
757
void
758
PyOS_AfterFork_Child(void)
759
0
{
760
0
    PyStatus status;
761
0
    _PyRuntimeState *runtime = &_PyRuntime;
762
763
    // re-creates runtime->interpreters.mutex (HEAD_UNLOCK)
764
0
    status = _PyRuntimeState_ReInitThreads(runtime);
765
0
    if (_PyStatus_EXCEPTION(status)) {
766
0
        goto fatal_error;
767
0
    }
768
769
0
    PyThreadState *tstate = _PyThreadState_GET();
770
0
    _Py_EnsureTstateNotNULL(tstate);
771
772
0
    assert(tstate->thread_id == PyThread_get_thread_ident());
773
0
#ifdef PY_HAVE_THREAD_NATIVE_ID
774
0
    tstate->native_thread_id = PyThread_get_thread_native_id();
775
0
#endif
776
777
#ifdef Py_GIL_DISABLED
778
    _Py_brc_after_fork(tstate->interp);
779
    _Py_qsbr_after_fork((_PyThreadStateImpl *)tstate);
780
#endif
781
782
    // Ideally we could guarantee tstate is running main.
783
0
    _PyInterpreterState_ReinitRunningMain(tstate);
784
785
0
    status = _PyEval_ReInitThreads(tstate);
786
0
    if (_PyStatus_EXCEPTION(status)) {
787
0
        goto fatal_error;
788
0
    }
789
790
#if defined(PY_HAVE_JIT_GDB_UNWIND)
791
    // The child can inherit this mutex locked if another thread held it at
792
    // fork(), but the child itself cannot be inside gdb_jit_register_code().
793
    // Reinitialize it before any executor cleanup can unregister JIT code.
794
    _Py_jit_debug_mutex = (PyMutex){0};
795
#endif
796
797
    // Thread-state cleanup can run finalizers that issue warnings.
798
0
    _PyWarnings_AfterFork(tstate->interp);
799
800
0
    reset_remotedebug_data(tstate);
801
802
0
    reset_asyncio_state((_PyThreadStateImpl *)tstate);
803
804
    // Remove the dead thread states. We "start the world" once we are the only
805
    // thread state left to undo the stop the world call in `PyOS_BeforeFork`.
806
    // That needs to happen before `_PyThreadState_DeleteList`, because that
807
    // may call destructors.
808
0
    PyThreadState *list = _PyThreadState_RemoveExcept(tstate);
809
0
    _PyEval_StartTheWorldAll(&_PyRuntime);
810
0
    _PyThreadState_DeleteList(list, /*is_after_fork=*/1);
811
812
0
    _PyImport_ReInitLock(tstate->interp);
813
0
    _PyImport_ReleaseLock(tstate->interp);
814
815
0
    _PySignal_AfterFork();
816
817
0
    status = _PyInterpreterState_DeleteExceptMain(runtime);
818
0
    if (_PyStatus_EXCEPTION(status)) {
819
0
        goto fatal_error;
820
0
    }
821
0
    assert(_PyThreadState_GET() == tstate);
822
823
0
    status = _PyPerfTrampoline_AfterFork_Child();
824
0
    if (_PyStatus_EXCEPTION(status)) {
825
0
        goto fatal_error;
826
0
    }
827
828
0
    run_at_forkers(tstate->interp->after_forkers_child, 0);
829
0
    return;
830
831
0
fatal_error:
832
0
    Py_ExitStatusException(status);
833
0
}
834
835
static int
836
register_at_forker(PyObject **lst, PyObject *func)
837
60
{
838
60
    if (func == NULL)  /* nothing to register? do nothing. */
839
40
        return 0;
840
20
    if (*lst == NULL) {
841
10
        *lst = PyList_New(0);
842
10
        if (*lst == NULL)
843
0
            return -1;
844
10
    }
845
20
    return PyList_Append(*lst, func);
846
20
}
847
#endif  /* HAVE_FORK */
848
849
850
/* Legacy wrapper */
851
void
852
PyOS_AfterFork(void)
853
0
{
854
0
#ifdef HAVE_FORK
855
0
    PyOS_AfterFork_Child();
856
0
#endif
857
0
}
858
859
860
#ifdef MS_WINDOWS
861
/* defined in fileutils.c */
862
void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
863
void _Py_attribute_data_to_stat(FILE_STANDARD_INFO*, ULONG,
864
                                FILE_BASIC_INFO*, FILE_ID_INFO*,
865
                                struct _Py_stat_struct*);
866
void _Py_stat_basic_info_to_stat(FILE_STAT_BASIC_INFORMATION *,
867
                                 struct _Py_stat_struct *);
868
#endif
869
870
871
#ifndef MS_WINDOWS
872
PyObject *
873
_PyLong_FromUid(uid_t uid)
874
242k
{
875
242k
    if (uid == (uid_t)-1)
876
0
        return PyLong_FromLong(-1);
877
242k
    return PyLong_FromUnsignedLong(uid);
878
242k
}
879
880
PyObject *
881
_PyLong_FromGid(gid_t gid)
882
242k
{
883
242k
    if (gid == (gid_t)-1)
884
0
        return PyLong_FromLong(-1);
885
242k
    return PyLong_FromUnsignedLong(gid);
886
242k
}
887
888
int
889
_Py_Uid_Converter(PyObject *obj, uid_t *p)
890
0
{
891
0
    uid_t uid;
892
0
    PyObject *index;
893
0
    int overflow;
894
0
    long result;
895
0
    unsigned long uresult;
896
897
0
    index = _PyNumber_Index(obj);
898
0
    if (index == NULL) {
899
0
        PyErr_Format(PyExc_TypeError,
900
0
                     "uid should be integer, not %.200s",
901
0
                     _PyType_Name(Py_TYPE(obj)));
902
0
        return 0;
903
0
    }
904
905
    /*
906
     * Handling uid_t is complicated for two reasons:
907
     *  * Although uid_t is (always?) unsigned, it still
908
     *    accepts -1.
909
     *  * We don't know its size in advance--it may be
910
     *    bigger than an int, or it may be smaller than
911
     *    a long.
912
     *
913
     * So a bit of defensive programming is in order.
914
     * Start with interpreting the value passed
915
     * in as a signed long and see if it works.
916
     */
917
918
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
919
920
0
    if (!overflow) {
921
0
        uid = (uid_t)result;
922
923
0
        if (result == -1) {
924
0
            if (PyErr_Occurred())
925
0
                goto fail;
926
            /* It's a legitimate -1, we're done. */
927
0
            goto success;
928
0
        }
929
930
        /* Any other negative number is disallowed. */
931
0
        if (result < 0)
932
0
            goto underflow;
933
934
        /* Ensure the value wasn't truncated. */
935
0
        if (sizeof(uid_t) < sizeof(long) &&
936
0
            (long)uid != result)
937
0
            goto underflow;
938
0
        goto success;
939
0
    }
940
941
0
    if (overflow < 0)
942
0
        goto underflow;
943
944
    /*
945
     * Okay, the value overflowed a signed long.  If it
946
     * fits in an *unsigned* long, it may still be okay,
947
     * as uid_t may be unsigned long on this platform.
948
     */
949
0
    uresult = PyLong_AsUnsignedLong(index);
950
0
    if (PyErr_Occurred()) {
951
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
952
0
            goto overflow;
953
0
        goto fail;
954
0
    }
955
956
0
    uid = (uid_t)uresult;
957
958
    /*
959
     * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
960
     * but this value would get interpreted as (uid_t)-1  by chown
961
     * and its siblings.   That's not what the user meant!  So we
962
     * throw an overflow exception instead.   (We already
963
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
964
     */
965
0
    if (uid == (uid_t)-1)
966
0
        goto overflow;
967
968
    /* Ensure the value wasn't truncated. */
969
0
    if (sizeof(uid_t) < sizeof(long) &&
970
0
        (unsigned long)uid != uresult)
971
0
        goto overflow;
972
    /* fallthrough */
973
974
0
success:
975
0
    Py_DECREF(index);
976
0
    *p = uid;
977
0
    return 1;
978
979
0
underflow:
980
0
    PyErr_SetString(PyExc_OverflowError,
981
0
                    "uid is less than minimum");
982
0
    goto fail;
983
984
0
overflow:
985
0
    PyErr_SetString(PyExc_OverflowError,
986
0
                    "uid is greater than maximum");
987
    /* fallthrough */
988
989
0
fail:
990
0
    Py_DECREF(index);
991
0
    return 0;
992
0
}
993
994
int
995
_Py_Gid_Converter(PyObject *obj, gid_t *p)
996
0
{
997
0
    gid_t gid;
998
0
    PyObject *index;
999
0
    int overflow;
1000
0
    long result;
1001
0
    unsigned long uresult;
1002
1003
0
    index = _PyNumber_Index(obj);
1004
0
    if (index == NULL) {
1005
0
        PyErr_Format(PyExc_TypeError,
1006
0
                     "gid should be integer, not %.200s",
1007
0
                     _PyType_Name(Py_TYPE(obj)));
1008
0
        return 0;
1009
0
    }
1010
1011
    /*
1012
     * Handling gid_t is complicated for two reasons:
1013
     *  * Although gid_t is (always?) unsigned, it still
1014
     *    accepts -1.
1015
     *  * We don't know its size in advance--it may be
1016
     *    bigger than an int, or it may be smaller than
1017
     *    a long.
1018
     *
1019
     * So a bit of defensive programming is in order.
1020
     * Start with interpreting the value passed
1021
     * in as a signed long and see if it works.
1022
     */
1023
1024
0
    result = PyLong_AsLongAndOverflow(index, &overflow);
1025
1026
0
    if (!overflow) {
1027
0
        gid = (gid_t)result;
1028
1029
0
        if (result == -1) {
1030
0
            if (PyErr_Occurred())
1031
0
                goto fail;
1032
            /* It's a legitimate -1, we're done. */
1033
0
            goto success;
1034
0
        }
1035
1036
        /* Any other negative number is disallowed. */
1037
0
        if (result < 0) {
1038
0
            goto underflow;
1039
0
        }
1040
1041
        /* Ensure the value wasn't truncated. */
1042
0
        if (sizeof(gid_t) < sizeof(long) &&
1043
0
            (long)gid != result)
1044
0
            goto underflow;
1045
0
        goto success;
1046
0
    }
1047
1048
0
    if (overflow < 0)
1049
0
        goto underflow;
1050
1051
    /*
1052
     * Okay, the value overflowed a signed long.  If it
1053
     * fits in an *unsigned* long, it may still be okay,
1054
     * as gid_t may be unsigned long on this platform.
1055
     */
1056
0
    uresult = PyLong_AsUnsignedLong(index);
1057
0
    if (PyErr_Occurred()) {
1058
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError))
1059
0
            goto overflow;
1060
0
        goto fail;
1061
0
    }
1062
1063
0
    gid = (gid_t)uresult;
1064
1065
    /*
1066
     * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
1067
     * but this value would get interpreted as (gid_t)-1  by chown
1068
     * and its siblings.   That's not what the user meant!  So we
1069
     * throw an overflow exception instead.   (We already
1070
     * handled a real -1 with PyLong_AsLongAndOverflow() above.)
1071
     */
1072
0
    if (gid == (gid_t)-1)
1073
0
        goto overflow;
1074
1075
    /* Ensure the value wasn't truncated. */
1076
0
    if (sizeof(gid_t) < sizeof(long) &&
1077
0
        (unsigned long)gid != uresult)
1078
0
        goto overflow;
1079
    /* fallthrough */
1080
1081
0
success:
1082
0
    Py_DECREF(index);
1083
0
    *p = gid;
1084
0
    return 1;
1085
1086
0
underflow:
1087
0
    PyErr_SetString(PyExc_OverflowError,
1088
0
                    "gid is less than minimum");
1089
0
    goto fail;
1090
1091
0
overflow:
1092
0
    PyErr_SetString(PyExc_OverflowError,
1093
0
                    "gid is greater than maximum");
1094
    /* fallthrough */
1095
1096
0
fail:
1097
0
    Py_DECREF(index);
1098
0
    return 0;
1099
0
}
1100
#endif /* MS_WINDOWS */
1101
1102
1103
static PyObject *
1104
_PyLong_FromDev(dev_t dev)
1105
485k
{
1106
485k
#ifdef NODEV
1107
485k
    if (dev == NODEV) {
1108
37
        return PyLong_FromLongLong((long long)dev);
1109
37
    }
1110
485k
#endif
1111
485k
    return PyLong_FromUnsignedLongLong((unsigned long long)dev);
1112
485k
}
1113
1114
1115
#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
1116
static int
1117
_Py_Dev_Converter(PyObject *obj, void *p)
1118
0
{
1119
0
    if (!PyLong_Check(obj)) {
1120
0
        obj = _PyNumber_Index(obj);
1121
0
        if (obj == NULL) {
1122
0
            return 0;
1123
0
        }
1124
0
    }
1125
0
    else {
1126
0
        Py_INCREF(obj);
1127
0
    }
1128
0
    assert(PyLong_Check(obj));
1129
0
#ifdef NODEV
1130
0
    if (_PyLong_IsNegative((PyLongObject *)obj)) {
1131
0
        int overflow;
1132
0
        long long result = PyLong_AsLongLongAndOverflow(obj, &overflow);
1133
0
        if (result == -1 && PyErr_Occurred()) {
1134
0
            Py_DECREF(obj);
1135
0
            return 0;
1136
0
        }
1137
0
        if (!overflow && result == (long long)NODEV) {
1138
0
            *((dev_t *)p) = NODEV;
1139
0
            Py_DECREF(obj);
1140
0
            return 1;
1141
0
        }
1142
0
    }
1143
0
#endif
1144
1145
0
    unsigned long long result = PyLong_AsUnsignedLongLong(obj);
1146
0
    Py_DECREF(obj);
1147
0
    if (result == (unsigned long long)-1 && PyErr_Occurred()) {
1148
0
        return 0;
1149
0
    }
1150
0
    if ((unsigned long long)(dev_t)result != result) {
1151
0
        PyErr_SetString(PyExc_OverflowError,
1152
0
                        "Python int too large to convert to C dev_t");
1153
0
        return 0;
1154
0
    }
1155
0
    *((dev_t *)p) = (dev_t)result;
1156
0
    return 1;
1157
0
}
1158
#endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
1159
1160
1161
#ifdef AT_FDCWD
1162
/*
1163
 * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
1164
 * without the int cast, the value gets interpreted as uint (4291925331),
1165
 * which doesn't play nicely with all the initializer lines in this file that
1166
 * look like this:
1167
 *      int dir_fd = DEFAULT_DIR_FD;
1168
 */
1169
1.86M
#define DEFAULT_DIR_FD (int)AT_FDCWD
1170
#else
1171
#define DEFAULT_DIR_FD (-100)
1172
#endif
1173
1174
static int
1175
_fd_converter(PyObject *o, int *p)
1176
283k
{
1177
283k
    int overflow;
1178
283k
    long long_value;
1179
1180
283k
    if (PyBool_Check(o)) {
1181
0
        if (PyErr_WarnEx(PyExc_RuntimeWarning,
1182
0
                "bool is used as a file descriptor", 1))
1183
0
        {
1184
0
            return 0;
1185
0
        }
1186
0
    }
1187
283k
    PyObject *index = _PyNumber_Index(o);
1188
283k
    if (index == NULL) {
1189
0
        return 0;
1190
0
    }
1191
1192
283k
    assert(PyLong_Check(index));
1193
283k
    long_value = PyLong_AsLongAndOverflow(index, &overflow);
1194
283k
    Py_DECREF(index);
1195
283k
    assert(!PyErr_Occurred());
1196
283k
    if (overflow > 0 || long_value > INT_MAX) {
1197
0
        PyErr_SetString(PyExc_OverflowError,
1198
0
                        "fd is greater than maximum");
1199
0
        return 0;
1200
0
    }
1201
283k
    if (overflow < 0 || long_value < INT_MIN) {
1202
0
        PyErr_SetString(PyExc_OverflowError,
1203
0
                        "fd is less than minimum");
1204
0
        return 0;
1205
0
    }
1206
1207
283k
    *p = (int)long_value;
1208
283k
    return 1;
1209
283k
}
1210
1211
static int
1212
dir_fd_converter(PyObject *o, void *p)
1213
208k
{
1214
208k
    if (o == Py_None) {
1215
16.5k
        *(int *)p = DEFAULT_DIR_FD;
1216
16.5k
        return 1;
1217
16.5k
    }
1218
192k
    else if (PyIndex_Check(o)) {
1219
192k
        return _fd_converter(o, (int *)p);
1220
192k
    }
1221
0
    else {
1222
0
        PyErr_Format(PyExc_TypeError,
1223
0
                     "argument should be integer or None, not %.200s",
1224
0
                     _PyType_Name(Py_TYPE(o)));
1225
0
        return 0;
1226
0
    }
1227
208k
}
1228
1229
typedef struct {
1230
    PyObject *billion;
1231
    PyObject *DirEntryType;
1232
    PyObject *ScandirIteratorType;
1233
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
1234
    PyObject *SchedParamType;
1235
#endif
1236
    newfunc statresult_new_orig;
1237
    PyObject *StatResultType;
1238
#ifdef HAVE_STATX
1239
    PyObject *StatxResultType;
1240
#endif
1241
    PyObject *StatVFSResultType;
1242
    PyObject *TerminalSizeType;
1243
    PyObject *TimesResultType;
1244
    PyObject *UnameResultType;
1245
#if defined(HAVE_WAITID)
1246
    PyObject *WaitidResultType;
1247
#endif
1248
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
1249
    PyObject *struct_rusage;
1250
#endif
1251
    PyObject *st_mode;
1252
#ifndef MS_WINDOWS
1253
    // times() clock frequency in hertz; used by os.times()
1254
    long ticks_per_second;
1255
#endif
1256
} _posixstate;
1257
1258
1259
static inline _posixstate*
1260
get_posix_state(PyObject *module)
1261
440k
{
1262
440k
    void *state = _PyModule_GetState(module);
1263
440k
    assert(state != NULL);
1264
440k
    return (_posixstate *)state;
1265
440k
}
1266
1267
/*
1268
 * A PyArg_ParseTuple "converter" function
1269
 * that handles filesystem paths in the manner
1270
 * preferred by the os module.
1271
 *
1272
 * path_converter accepts (Unicode) strings and their
1273
 * subclasses, and bytes and their subclasses.  What
1274
 * it does with the argument depends on path.make_wide:
1275
 *
1276
 *   * If path.make_wide is nonzero, if we get a (Unicode)
1277
 *     string we extract the wchar_t * and return it; if we
1278
 *     get bytes we decode to wchar_t * and return that.
1279
 *
1280
 *   * If path.make_wide is zero, if we get bytes we extract
1281
 *     the char_t * and return it; if we get a (Unicode)
1282
 *     string we encode to char_t * and return that.
1283
 *
1284
 * path_converter also optionally accepts signed
1285
 * integers (representing open file descriptors) instead
1286
 * of path strings.
1287
 *
1288
 * Input fields:
1289
 *   path.nullable
1290
 *     If nonzero, the path is permitted to be None.
1291
 *   path.nonstrict
1292
 *     If nonzero, the path is permitted to contain
1293
 *     embedded null characters and have any length.
1294
 *   path.make_wide
1295
 *     If nonzero, the converter always uses wide, decoding if necessary, else
1296
 *     it always uses narrow, encoding if necessary. The default value is
1297
 *     nonzero on Windows, else zero.
1298
 *   path.suppress_value_error
1299
 *     If nonzero, raising ValueError is suppressed.
1300
 *   path.allow_fd
1301
 *     If nonzero, the path is permitted to be a file handle
1302
 *     (a signed int) instead of a string.
1303
 *   path.function_name
1304
 *     If non-NULL, path_converter will use that as the name
1305
 *     of the function in error messages.
1306
 *     (If path.function_name is NULL it omits the function name.)
1307
 *   path.argument_name
1308
 *     If non-NULL, path_converter will use that as the name
1309
 *     of the parameter in error messages.
1310
 *     (If path.argument_name is NULL it uses "path".)
1311
 *
1312
 * Output fields:
1313
 *   path.wide
1314
 *     Points to the path if it was expressed as Unicode
1315
 *     or if it was bytes and decoded to Unicode.
1316
 *   path.narrow
1317
 *     Points to the path if it was expressed as bytes,
1318
 *     or if it was Unicode and encoded to bytes.
1319
 *   path.fd
1320
 *     Contains a file descriptor if path.accept_fd was true
1321
 *     and the caller provided a signed integer instead of any
1322
 *     sort of string.
1323
 *   path.is_fd
1324
 *     True if path was provided as a file descriptor.
1325
 *
1326
 *     WARNING: if your "path" parameter is optional, and is
1327
 *     unspecified, path_converter will never get called.
1328
 *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1329
 *     yourself!
1330
 *   path.value_error
1331
 *     If nonzero, then suppress_value_error was specified and a ValueError
1332
 *     occurred.
1333
 *   path.length
1334
 *     The length of the path in characters, if specified as
1335
 *     a string.
1336
 *   path.object
1337
 *     The original object passed in (if get a PathLike object,
1338
 *     the result of PyOS_FSPath() is treated as the original object).
1339
 *     Own a reference to the object.
1340
 *   path.cleanup
1341
 *     For internal use only.  May point to a temporary object.
1342
 *     (Pay no attention to the man behind the curtain.)
1343
 *
1344
 *   At most one of path.wide or path.narrow will be non-NULL.
1345
 *   If path was None and path.nullable was set,
1346
 *     or if path was an integer and path.allow_fd was set,
1347
 *     both path.wide and path.narrow will be NULL
1348
 *     and path.length will be 0.
1349
 *
1350
 *   path_converter takes care to not write to the path_t
1351
 *   unless it's successful.  However it must reset the
1352
 *   "cleanup" field each time it's called.
1353
 *
1354
 * Use as follows:
1355
 *      path_t path;
1356
 *      memset(&path, 0, sizeof(path));
1357
 *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1358
 *      // ... use values from path ...
1359
 *      path_cleanup(&path);
1360
 *
1361
 * (Note that if PyArg_Parse fails you don't need to call
1362
 * path_cleanup().  However it is safe to do so.)
1363
 */
1364
typedef struct {
1365
    // Input fields
1366
    const char *function_name;
1367
    const char *argument_name;
1368
    int nullable;
1369
    int nonstrict;
1370
    int make_wide;
1371
    int suppress_value_error;
1372
    int allow_fd;
1373
    // Output fields
1374
    const wchar_t *wide;
1375
    const char *narrow;
1376
    int fd;
1377
    bool is_fd;
1378
    int value_error;
1379
    Py_ssize_t length;
1380
    PyObject *object;
1381
    PyObject *cleanup;
1382
} path_t;
1383
1384
#define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \
1385
                          make_wide, suppress_value_error, allow_fd) \
1386
788k
    {function_name, argument_name, nullable, nonstrict, make_wide, \
1387
788k
     suppress_value_error, allow_fd, NULL, NULL, -1, false, 0, 0, NULL, NULL}
1388
#ifdef MS_WINDOWS
1389
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1390
                            nonstrict, suppress_value_error, allow_fd) \
1391
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 1, \
1392
                      suppress_value_error, allow_fd)
1393
#else
1394
#define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \
1395
                            nonstrict, suppress_value_error, allow_fd) \
1396
628k
    PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, 0, \
1397
628k
                      suppress_value_error, allow_fd)
1398
#endif
1399
1400
static void
1401
path_cleanup(path_t *path)
1402
879k
{
1403
879k
    wchar_t *wide = (wchar_t *)path->wide;
1404
879k
    path->wide = NULL;
1405
879k
    PyMem_Free(wide);
1406
879k
    Py_CLEAR(path->object);
1407
879k
    Py_CLEAR(path->cleanup);
1408
879k
}
1409
1410
static int
1411
path_converter(PyObject *o, void *p)
1412
788k
{
1413
788k
    path_t *path = (path_t *)p;
1414
788k
    PyObject *bytes = NULL;
1415
788k
    Py_ssize_t length = 0;
1416
788k
    int is_index, is_bytes, is_unicode;
1417
788k
    const char *narrow;
1418
788k
    PyObject *wo = NULL;
1419
788k
    wchar_t *wide = NULL;
1420
1421
788k
#define FORMAT_EXCEPTION(exc, fmt) \
1422
788k
    PyErr_Format(exc, "%s%s" fmt, \
1423
0
        path->function_name ? path->function_name : "", \
1424
0
        path->function_name ? ": "                : "", \
1425
0
        path->argument_name ? path->argument_name : "path")
1426
1427
    /* Py_CLEANUP_SUPPORTED support */
1428
788k
    if (o == NULL) {
1429
0
        path_cleanup(path);
1430
0
        return 1;
1431
0
    }
1432
1433
    /* Ensure it's always safe to call path_cleanup(). */
1434
788k
    path->object = path->cleanup = NULL;
1435
    /* path->object owns a reference to the original object */
1436
788k
    Py_INCREF(o);
1437
1438
788k
    if ((o == Py_None) && path->nullable) {
1439
0
        path->wide = NULL;
1440
0
        path->narrow = NULL;
1441
0
        path->fd = -1;
1442
0
        goto success_exit;
1443
0
    }
1444
1445
    /* Only call this here so that we don't treat the return value of
1446
       os.fspath() as an fd or buffer. */
1447
788k
    is_index = path->allow_fd && PyIndex_Check(o);
1448
788k
    is_bytes = PyBytes_Check(o);
1449
788k
    is_unicode = PyUnicode_Check(o);
1450
1451
788k
    if (!is_index && !is_unicode && !is_bytes) {
1452
        /* Inline PyOS_FSPath() for better error messages. */
1453
17
        PyObject *func, *res;
1454
1455
17
        func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1456
17
        if ((NULL == func) || (func == Py_None)) {
1457
0
            goto error_format;
1458
0
        }
1459
17
        res = _PyObject_CallNoArgs(func);
1460
17
        Py_DECREF(func);
1461
17
        if (NULL == res) {
1462
0
            goto error_exit;
1463
0
        }
1464
17
        else if (PyUnicode_Check(res)) {
1465
17
            is_unicode = 1;
1466
17
        }
1467
0
        else if (PyBytes_Check(res)) {
1468
0
            is_bytes = 1;
1469
0
        }
1470
0
        else {
1471
0
            PyErr_Format(PyExc_TypeError,
1472
0
                 "expected %.200s.__fspath__() to return str or bytes, "
1473
0
                 "not %.200s", _PyType_Name(Py_TYPE(o)),
1474
0
                 _PyType_Name(Py_TYPE(res)));
1475
0
            Py_DECREF(res);
1476
0
            goto error_exit;
1477
0
        }
1478
1479
        /* still owns a reference to the original object */
1480
17
        Py_SETREF(o, res);
1481
17
    }
1482
1483
788k
    if (is_unicode) {
1484
697k
        if (path->make_wide) {
1485
159k
            wide = PyUnicode_AsWideCharString(o, &length);
1486
159k
            if (!wide) {
1487
0
                goto error_exit;
1488
0
            }
1489
#ifdef MS_WINDOWS
1490
            if (!path->nonstrict && length > 32767) {
1491
                FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1492
                goto error_exit;
1493
            }
1494
#endif
1495
159k
            if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1496
0
                FORMAT_EXCEPTION(PyExc_ValueError,
1497
0
                                 "embedded null character in %s");
1498
0
                goto error_exit;
1499
0
            }
1500
1501
159k
            path->wide = wide;
1502
159k
            path->narrow = NULL;
1503
159k
            path->fd = -1;
1504
159k
            wide = NULL;
1505
159k
            goto success_exit;
1506
159k
        }
1507
537k
        bytes = PyUnicode_EncodeFSDefault(o);
1508
537k
        if (!bytes) {
1509
0
            goto error_exit;
1510
0
        }
1511
537k
    }
1512
91.0k
    else if (is_bytes) {
1513
0
        bytes = Py_NewRef(o);
1514
0
    }
1515
91.0k
    else if (is_index) {
1516
91.0k
        if (!_fd_converter(o, &path->fd)) {
1517
0
            goto error_exit;
1518
0
        }
1519
91.0k
        path->wide = NULL;
1520
91.0k
        path->narrow = NULL;
1521
91.0k
        path->is_fd = true;
1522
91.0k
        goto success_exit;
1523
91.0k
    }
1524
0
    else {
1525
0
 error_format:
1526
0
        PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1527
0
            path->function_name ? path->function_name : "",
1528
0
            path->function_name ? ": "                : "",
1529
0
            path->argument_name ? path->argument_name : "path",
1530
0
            path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1531
0
                                               "integer or None" :
1532
0
            path->allow_fd ? "string, bytes, os.PathLike or integer" :
1533
0
            path->nullable ? "string, bytes, os.PathLike or None" :
1534
0
                             "string, bytes or os.PathLike",
1535
0
            _PyType_Name(Py_TYPE(o)));
1536
0
        goto error_exit;
1537
0
    }
1538
1539
537k
    length = PyBytes_GET_SIZE(bytes);
1540
537k
    narrow = PyBytes_AS_STRING(bytes);
1541
537k
    if (!path->nonstrict && strlen(narrow) != (size_t)length) {
1542
0
        FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1543
0
        goto error_exit;
1544
0
    }
1545
1546
537k
    if (path->make_wide) {
1547
0
        wo = PyUnicode_DecodeFSDefaultAndSize(narrow, length);
1548
0
        if (!wo) {
1549
0
            goto error_exit;
1550
0
        }
1551
1552
0
        wide = PyUnicode_AsWideCharString(wo, &length);
1553
0
        Py_DECREF(wo);
1554
0
        if (!wide) {
1555
0
            goto error_exit;
1556
0
        }
1557
#ifdef MS_WINDOWS
1558
        if (!path->nonstrict && length > 32767) {
1559
            FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1560
            goto error_exit;
1561
        }
1562
#endif
1563
0
        if (!path->nonstrict && wcslen(wide) != (size_t)length) {
1564
0
            FORMAT_EXCEPTION(PyExc_ValueError,
1565
0
                             "embedded null character in %s");
1566
0
            goto error_exit;
1567
0
        }
1568
0
        path->wide = wide;
1569
0
        path->narrow = NULL;
1570
0
        Py_DECREF(bytes);
1571
0
        wide = NULL;
1572
0
    }
1573
537k
    else {
1574
537k
        path->wide = NULL;
1575
537k
        path->narrow = narrow;
1576
537k
        if (bytes == o) {
1577
            /* Still a reference owned by path->object, don't have to
1578
            worry about path->narrow is used after free. */
1579
0
            Py_DECREF(bytes);
1580
0
        }
1581
537k
        else {
1582
537k
            path->cleanup = bytes;
1583
537k
        }
1584
537k
    }
1585
537k
    path->fd = -1;
1586
1587
788k
 success_exit:
1588
788k
    path->value_error = 0;
1589
788k
    path->length = length;
1590
788k
    path->object = o;
1591
788k
    return Py_CLEANUP_SUPPORTED;
1592
1593
0
 error_exit:
1594
0
    Py_XDECREF(o);
1595
0
    Py_XDECREF(bytes);
1596
0
    PyMem_Free(wide);
1597
0
    if (!path->suppress_value_error ||
1598
0
        !PyErr_ExceptionMatches(PyExc_ValueError))
1599
0
    {
1600
0
        return 0;
1601
0
    }
1602
0
    PyErr_Clear();
1603
0
    path->wide = NULL;
1604
0
    path->narrow = NULL;
1605
0
    path->fd = -1;
1606
0
    path->value_error = 1;
1607
0
    path->length = 0;
1608
0
    path->object = NULL;
1609
0
    return Py_CLEANUP_SUPPORTED;
1610
0
}
1611
1612
static void
1613
argument_unavailable_error(const char *function_name, const char *argument_name)
1614
0
{
1615
0
    PyErr_Format(PyExc_NotImplementedError,
1616
0
        "%s%s%s unavailable on this platform",
1617
0
        (function_name != NULL) ? function_name : "",
1618
0
        (function_name != NULL) ? ": ": "",
1619
0
        argument_name);
1620
0
}
1621
1622
static int
1623
dir_fd_unavailable(PyObject *o, void *p)
1624
37
{
1625
37
    int dir_fd;
1626
37
    if (!dir_fd_converter(o, &dir_fd))
1627
0
        return 0;
1628
37
    if (dir_fd != DEFAULT_DIR_FD) {
1629
0
        argument_unavailable_error(NULL, "dir_fd");
1630
0
        return 0;
1631
0
    }
1632
37
    *(int *)p = dir_fd;
1633
37
    return 1;
1634
37
}
1635
1636
static int
1637
fd_specified(const char *function_name, int fd)
1638
37
{
1639
37
    if (fd == -1)
1640
37
        return 0;
1641
1642
0
    argument_unavailable_error(function_name, "fd");
1643
0
    return 1;
1644
37
}
1645
1646
static int
1647
follow_symlinks_specified(const char *function_name, int follow_symlinks)
1648
37
{
1649
37
    if (follow_symlinks)
1650
37
        return 0;
1651
1652
0
    argument_unavailable_error(function_name, "follow_symlinks");
1653
0
    return 1;
1654
37
}
1655
1656
static int
1657
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1658
244k
{
1659
244k
    if (!path->wide && (dir_fd != DEFAULT_DIR_FD) && !path->narrow) {
1660
0
        PyErr_Format(PyExc_ValueError,
1661
0
                     "%s: can't specify dir_fd without matching path",
1662
0
                     function_name);
1663
0
        return 1;
1664
0
    }
1665
244k
    return 0;
1666
244k
}
1667
1668
static int
1669
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1670
244k
{
1671
244k
    if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1672
0
        PyErr_Format(PyExc_ValueError,
1673
0
                     "%s: can't specify both dir_fd and fd",
1674
0
                     function_name);
1675
0
        return 1;
1676
0
    }
1677
244k
    return 0;
1678
244k
}
1679
1680
static int
1681
fd_and_follow_symlinks_invalid(const char *function_name, int is_fd,
1682
                               int follow_symlinks)
1683
244k
{
1684
244k
    if (is_fd && (!follow_symlinks)) {
1685
0
        PyErr_Format(PyExc_ValueError,
1686
0
                     "%s: cannot use fd and follow_symlinks together",
1687
0
                     function_name);
1688
0
        return 1;
1689
0
    }
1690
244k
    return 0;
1691
244k
}
1692
1693
static int
1694
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1695
                                   int follow_symlinks)
1696
37
{
1697
37
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1698
0
        PyErr_Format(PyExc_ValueError,
1699
0
                     "%s: cannot use dir_fd and follow_symlinks together",
1700
0
                     function_name);
1701
0
        return 1;
1702
0
    }
1703
37
    return 0;
1704
37
}
1705
1706
#if defined(HAVE_WAITID)
1707
static int
1708
idtype_t_converter(PyObject *arg, void *addr)
1709
0
{
1710
0
    int value = PyLong_AsInt(arg);
1711
0
    if (value == -1 && PyErr_Occurred()) {
1712
0
        return 0;
1713
0
    }
1714
0
    *((idtype_t *)addr) = (idtype_t)(value);
1715
0
    return 1;
1716
0
}
1717
#endif
1718
1719
static PyObject *
1720
PyLong_FromPy_off_t(Py_off_t offset)
1721
0
{
1722
#ifdef HAVE_LARGEFILE_SUPPORT
1723
    return PyLong_FromLongLong(offset);
1724
#else
1725
0
    return PyLong_FromLong(offset);
1726
0
#endif
1727
0
}
1728
1729
#ifdef HAVE_SIGSET_T
1730
/* Convert an iterable of integers to a sigset.
1731
   Return 1 on success, return 0 and raise an exception on error. */
1732
int
1733
_Py_Sigset_Converter(PyObject *obj, void *addr)
1734
0
{
1735
0
    sigset_t *mask = (sigset_t *)addr;
1736
0
    PyObject *iterator, *item;
1737
0
    long signum;
1738
0
    int overflow;
1739
1740
    // The extra parens suppress the unreachable-code warning with clang on MacOS
1741
0
    if (sigemptyset(mask) < (0)) {
1742
        /* Probably only if mask == NULL. */
1743
0
        PyErr_SetFromErrno(PyExc_OSError);
1744
0
        return 0;
1745
0
    }
1746
1747
0
    iterator = PyObject_GetIter(obj);
1748
0
    if (iterator == NULL) {
1749
0
        return 0;
1750
0
    }
1751
1752
0
    while ((item = PyIter_Next(iterator)) != NULL) {
1753
0
        signum = PyLong_AsLongAndOverflow(item, &overflow);
1754
0
        Py_DECREF(item);
1755
0
        if (signum <= 0 || signum >= Py_NSIG) {
1756
0
            if (overflow || signum != -1 || !PyErr_Occurred()) {
1757
0
                PyErr_Format(PyExc_ValueError,
1758
0
                             "signal number %ld out of range [1; %i]",
1759
0
                             signum, Py_NSIG - 1);
1760
0
            }
1761
0
            goto error;
1762
0
        }
1763
0
        if (sigaddset(mask, (int)signum)) {
1764
0
            if (errno != EINVAL) {
1765
                /* Probably impossible */
1766
0
                PyErr_SetFromErrno(PyExc_OSError);
1767
0
                goto error;
1768
0
            }
1769
            /* For backwards compatibility, allow idioms such as
1770
             * `range(1, NSIG)` but warn about invalid signal numbers
1771
             */
1772
0
            const char msg[] =
1773
0
                "invalid signal number %ld, please use valid_signals()";
1774
0
            if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1775
0
                goto error;
1776
0
            }
1777
0
        }
1778
0
    }
1779
0
    if (!PyErr_Occurred()) {
1780
0
        Py_DECREF(iterator);
1781
0
        return 1;
1782
0
    }
1783
1784
0
error:
1785
0
    Py_DECREF(iterator);
1786
0
    return 0;
1787
0
}
1788
#endif /* HAVE_SIGSET_T */
1789
1790
/* Return a dictionary corresponding to the POSIX environment table */
1791
#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1792
/* On Darwin/MacOSX a shared library or framework has no access to
1793
** environ directly, we must obtain it with _NSGetEnviron(). See also
1794
** man environ(7).
1795
*/
1796
#include <crt_externs.h>
1797
#define USE_DARWIN_NS_GET_ENVIRON 1
1798
#elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1799
extern char **environ;
1800
#endif /* !_MSC_VER */
1801
1802
static PyObject *
1803
convertenviron(void)
1804
37
{
1805
37
    PyObject *d;
1806
#ifdef MS_WINDOWS
1807
    wchar_t **e;
1808
#else
1809
37
    char **e;
1810
37
#endif
1811
1812
37
    d = PyDict_New();
1813
37
    if (d == NULL)
1814
0
        return NULL;
1815
#ifdef MS_WINDOWS
1816
    /* _wenviron must be initialized in this way if the program is started
1817
       through main() instead of wmain(). */
1818
    (void)_wgetenv(L"");
1819
    e = _wenviron;
1820
#elif defined(USE_DARWIN_NS_GET_ENVIRON)
1821
    /* environ is not accessible as an extern in a shared object on OSX; use
1822
       _NSGetEnviron to resolve it. The value changes if you add environment
1823
       variables between calls to Py_Initialize, so don't cache the value. */
1824
    e = *_NSGetEnviron();
1825
#else
1826
37
    e = environ;
1827
37
#endif
1828
37
    if (e == NULL)
1829
0
        return d;
1830
1.29k
    for (; *e != NULL; e++) {
1831
1.25k
        PyObject *k;
1832
1.25k
        PyObject *v;
1833
#ifdef MS_WINDOWS
1834
        const wchar_t *p = wcschr(*e, L'=');
1835
#else
1836
1.25k
        const char *p = strchr(*e, '=');
1837
1.25k
#endif
1838
1.25k
        if (p == NULL)
1839
0
            continue;
1840
#ifdef MS_WINDOWS
1841
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1842
#else
1843
1.25k
        k = PyBytes_FromStringAndSize(*e, (Py_ssize_t)(p-*e));
1844
1.25k
#endif
1845
1.25k
        if (k == NULL) {
1846
0
            Py_DECREF(d);
1847
0
            return NULL;
1848
0
        }
1849
#ifdef MS_WINDOWS
1850
        v = PyUnicode_FromWideChar(p+1, -1);
1851
#else
1852
1.25k
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1853
1.25k
#endif
1854
1.25k
        if (v == NULL) {
1855
0
            Py_DECREF(k);
1856
0
            Py_DECREF(d);
1857
0
            return NULL;
1858
0
        }
1859
1.25k
        if (PyDict_SetDefaultRef(d, k, v, NULL) < 0) {
1860
0
            Py_DECREF(v);
1861
0
            Py_DECREF(k);
1862
0
            Py_DECREF(d);
1863
0
            return NULL;
1864
0
        }
1865
1.25k
        Py_DECREF(k);
1866
1.25k
        Py_DECREF(v);
1867
1.25k
    }
1868
37
    return d;
1869
37
}
1870
1871
/* Set a POSIX-specific error from errno, and return NULL */
1872
1873
static PyObject *
1874
posix_error(void)
1875
0
{
1876
0
    return PyErr_SetFromErrno(PyExc_OSError);
1877
0
}
1878
1879
#ifdef MS_WINDOWS
1880
static PyObject *
1881
win32_error(const char* function, const char* filename)
1882
{
1883
    /* XXX We should pass the function name along in the future.
1884
       (winreg.c also wants to pass the function name.)
1885
       This would however require an additional param to the
1886
       Windows error object, which is non-trivial.
1887
    */
1888
    errno = GetLastError();
1889
    if (filename)
1890
        return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1891
    else
1892
        return PyErr_SetFromWindowsErr(errno);
1893
}
1894
1895
static PyObject *
1896
win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1897
{
1898
    /* XXX - see win32_error for comments on 'function' */
1899
    if (filename)
1900
        return PyErr_SetExcFromWindowsErrWithFilenameObject(
1901
                    PyExc_OSError,
1902
                    err,
1903
                    filename);
1904
    else
1905
        return PyErr_SetFromWindowsErr(err);
1906
}
1907
1908
static PyObject *
1909
win32_error_object(const char* function, PyObject* filename)
1910
{
1911
    errno = GetLastError();
1912
    return win32_error_object_err(function, filename, errno);
1913
}
1914
1915
#endif /* MS_WINDOWS */
1916
1917
static PyObject *
1918
posix_path_object_error(PyObject *path)
1919
180k
{
1920
180k
    return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1921
180k
}
1922
1923
static PyObject *
1924
path_object_error(PyObject *path)
1925
180k
{
1926
#ifdef MS_WINDOWS
1927
    return PyErr_SetExcFromWindowsErrWithFilenameObject(
1928
                PyExc_OSError, 0, path);
1929
#else
1930
180k
    return posix_path_object_error(path);
1931
180k
#endif
1932
180k
}
1933
1934
static PyObject *
1935
path_object_error2(PyObject *path, PyObject *path2)
1936
0
{
1937
#ifdef MS_WINDOWS
1938
    return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1939
                PyExc_OSError, 0, path, path2);
1940
#else
1941
0
    return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1942
0
#endif
1943
0
}
1944
1945
static PyObject *
1946
path_error(path_t *path)
1947
180k
{
1948
180k
    return path_object_error(path->object);
1949
180k
}
1950
1951
static PyObject *
1952
posix_path_error(path_t *path)
1953
0
{
1954
0
    return posix_path_object_error(path->object);
1955
0
}
1956
1957
static PyObject *
1958
path_error2(path_t *path, path_t *path2)
1959
0
{
1960
0
    return path_object_error2(path->object, path2->object);
1961
0
}
1962
1963
1964
/* POSIX generic methods */
1965
1966
static PyObject *
1967
posix_fildes_fd(int fd, int (*func)(int))
1968
0
{
1969
0
    int res;
1970
0
    int async_err = 0;
1971
1972
0
    do {
1973
0
        Py_BEGIN_ALLOW_THREADS
1974
0
        _Py_BEGIN_SUPPRESS_IPH
1975
0
        res = (*func)(fd);
1976
0
        _Py_END_SUPPRESS_IPH
1977
0
        Py_END_ALLOW_THREADS
1978
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1979
0
    if (res != 0)
1980
0
        return (!async_err) ? posix_error() : NULL;
1981
0
    Py_RETURN_NONE;
1982
0
}
1983
1984
1985
#ifdef MS_WINDOWS
1986
/* This is a reimplementation of the C library's chdir function,
1987
   but one that produces Win32 errors instead of DOS error codes.
1988
   chdir is essentially a wrapper around SetCurrentDirectory; however,
1989
   it also needs to set "magic" environment variables indicating
1990
   the per-drive current directory, which are of the form =<drive>: */
1991
static BOOL __stdcall
1992
win32_wchdir(LPCWSTR path)
1993
{
1994
    wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1995
    int result;
1996
    wchar_t env[4] = L"=x:";
1997
1998
    if(!SetCurrentDirectoryW(path))
1999
        return FALSE;
2000
    result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
2001
    if (!result)
2002
        return FALSE;
2003
    if (result > Py_ARRAY_LENGTH(path_buf)) {
2004
        new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
2005
        if (!new_path) {
2006
            SetLastError(ERROR_OUTOFMEMORY);
2007
            return FALSE;
2008
        }
2009
        result = GetCurrentDirectoryW(result, new_path);
2010
        if (!result) {
2011
            PyMem_RawFree(new_path);
2012
            return FALSE;
2013
        }
2014
    }
2015
    int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
2016
                            wcsncmp(new_path, L"//", 2) == 0);
2017
    if (!is_unc_like_path) {
2018
        env[1] = new_path[0];
2019
        result = SetEnvironmentVariableW(env, new_path);
2020
    }
2021
    if (new_path != path_buf)
2022
        PyMem_RawFree(new_path);
2023
    return result ? TRUE : FALSE;
2024
}
2025
#endif
2026
2027
#ifdef MS_WINDOWS
2028
/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
2029
   - time stamps are restricted to second resolution
2030
   - file modification times suffer from forth-and-back conversions between
2031
     UTC and local time
2032
   Therefore, we implement our own stat, based on the Win32 API directly.
2033
*/
2034
#define HAVE_STAT_NSEC 1
2035
#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
2036
#define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
2037
2038
/* The \\?\ prefix disables the path normalization, in particular
2039
   stripping of trailing dots and spaces. */
2040
static int
2041
is_extended_path(const wchar_t *path)
2042
{
2043
    return wcsncmp(path, L"\\\\?\\", 4) == 0;
2044
}
2045
2046
static void
2047
find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
2048
                       FILE_BASIC_INFO* basic_info,
2049
                       FILE_STANDARD_INFO* standard_info,
2050
                       ULONG *reparse_tag)
2051
{
2052
    memset(basic_info, 0, sizeof(*basic_info));
2053
    memset(standard_info, 0, sizeof(*standard_info));
2054
2055
    basic_info->FileAttributes = pFileData->dwFileAttributes;
2056
    basic_info->CreationTime.HighPart = pFileData->ftCreationTime.dwHighDateTime;
2057
    basic_info->CreationTime.LowPart = pFileData->ftCreationTime.dwLowDateTime;
2058
    basic_info->LastAccessTime.HighPart = pFileData->ftLastAccessTime.dwHighDateTime;
2059
    basic_info->LastAccessTime.LowPart = pFileData->ftLastAccessTime.dwLowDateTime;
2060
    basic_info->LastWriteTime.HighPart = pFileData->ftLastWriteTime.dwHighDateTime;
2061
    basic_info->LastWriteTime.LowPart = pFileData->ftLastWriteTime.dwLowDateTime;
2062
    standard_info->EndOfFile.HighPart = pFileData->nFileSizeHigh;
2063
    standard_info->EndOfFile.LowPart = pFileData->nFileSizeLow;
2064
2065
    if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2066
        *reparse_tag = pFileData->dwReserved0;
2067
    else
2068
        *reparse_tag = 0;
2069
}
2070
2071
static BOOL
2072
attributes_from_dir(LPCWSTR pszFile, FILE_BASIC_INFO* basic_info, FILE_STANDARD_INFO* standard_info, ULONG* reparse_tag)
2073
{
2074
    HANDLE hFindFile;
2075
    WIN32_FIND_DATAW FileData;
2076
    LPCWSTR filename = pszFile;
2077
    size_t n = wcslen(pszFile);
2078
    if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
2079
        // cannot use PyMem_Malloc here because we do not hold the GIL
2080
        filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
2081
        if(!filename) {
2082
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2083
            return FALSE;
2084
        }
2085
        wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
2086
        while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
2087
            ((LPWSTR)filename)[n] = L'\0';
2088
        }
2089
        if (!n || (n == 1 && filename[1] == L':')) {
2090
            // Nothing left to query
2091
            free((void *)filename);
2092
            return FALSE;
2093
        }
2094
    }
2095
    hFindFile = FindFirstFileW(filename, &FileData);
2096
    if (pszFile != filename) {
2097
        free((void *)filename);
2098
    }
2099
    if (hFindFile == INVALID_HANDLE_VALUE) {
2100
        return FALSE;
2101
    }
2102
    FindClose(hFindFile);
2103
    find_data_to_file_info(&FileData, basic_info, standard_info, reparse_tag);
2104
    return TRUE;
2105
}
2106
2107
2108
static void
2109
update_st_mode_from_path(const wchar_t *path, DWORD attr,
2110
                         struct _Py_stat_struct *result)
2111
{
2112
    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
2113
        /* Fix the file execute permissions. This hack sets S_IEXEC if
2114
           the filename has an extension that is commonly used by files
2115
           that CreateProcessW can execute. A real implementation calls
2116
           GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2117
           AccessCheck to check for generic read, write, and execute
2118
           access. */
2119
        size_t len = wcslen(path);
2120
        if (!is_extended_path(path)) {
2121
            /* Trailing dots and spaces are stripped from the last component
2122
               of the path. */
2123
            while (len > 0 && (path[len - 1] == L'.' || path[len - 1] == L' ')) {
2124
                len--;
2125
            }
2126
        }
2127
        if (len >= 4) {
2128
            const wchar_t *fileExtension = path + len - 4;
2129
            if (_wcsnicmp(fileExtension, L".exe", 4) == 0 ||
2130
                _wcsnicmp(fileExtension, L".bat", 4) == 0 ||
2131
                _wcsnicmp(fileExtension, L".cmd", 4) == 0 ||
2132
                _wcsnicmp(fileExtension, L".com", 4) == 0) {
2133
                result->st_mode |= 0111;
2134
            }
2135
        }
2136
    }
2137
}
2138
2139
2140
static int
2141
win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
2142
                      BOOL traverse)
2143
{
2144
    HANDLE hFile;
2145
    FILE_STANDARD_INFO standardInfo = {0};
2146
    FILE_BASIC_INFO basicInfo = {0};
2147
    FILE_ID_INFO idInfo = {0};
2148
    FILE_ID_INFO *pIdInfo = NULL;
2149
    FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
2150
    DWORD fileType, error;
2151
    BOOL isUnhandledTag = FALSE;
2152
    int retval = 0;
2153
2154
    DWORD access = FILE_READ_ATTRIBUTES;
2155
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
2156
    if (!traverse) {
2157
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
2158
    }
2159
2160
    hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
2161
    if (hFile == INVALID_HANDLE_VALUE) {
2162
        /* Either the path doesn't exist, or the caller lacks access. */
2163
        error = GetLastError();
2164
        switch (error) {
2165
        case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
2166
        case ERROR_SHARING_VIOLATION: /* It's a paging file. */
2167
            /* Try reading the parent directory. */
2168
            if (!attributes_from_dir(path, &basicInfo, &standardInfo, &tagInfo.ReparseTag)) {
2169
                /* Cannot read the parent directory. */
2170
                switch (GetLastError()) {
2171
                case ERROR_FILE_NOT_FOUND: /* File cannot be found */
2172
                case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
2173
                case ERROR_NOT_READY: /* Drive exists but unavailable */
2174
                case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
2175
                    break;
2176
                /* Restore the error from CreateFileW(). */
2177
                default:
2178
                    SetLastError(error);
2179
                }
2180
2181
                return -1;
2182
            }
2183
            if (basicInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
2184
                if (traverse ||
2185
                    !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2186
                    /* The stat call has to traverse but cannot, so fail. */
2187
                    SetLastError(error);
2188
                    return -1;
2189
                }
2190
            }
2191
            break;
2192
2193
        case ERROR_INVALID_PARAMETER:
2194
            /* \\.\con requires read or write access. */
2195
            hFile = CreateFileW(path, access | GENERIC_READ,
2196
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2197
                        OPEN_EXISTING, flags, NULL);
2198
            if (hFile == INVALID_HANDLE_VALUE) {
2199
                SetLastError(error);
2200
                return -1;
2201
            }
2202
            break;
2203
2204
        case ERROR_CANT_ACCESS_FILE:
2205
            /* bpo37834: open unhandled reparse points if traverse fails. */
2206
            if (traverse) {
2207
                traverse = FALSE;
2208
                isUnhandledTag = TRUE;
2209
                hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
2210
                            flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
2211
            }
2212
            if (hFile == INVALID_HANDLE_VALUE) {
2213
                SetLastError(error);
2214
                return -1;
2215
            }
2216
            break;
2217
2218
        default:
2219
            return -1;
2220
        }
2221
    }
2222
2223
    if (hFile != INVALID_HANDLE_VALUE) {
2224
        /* Handle types other than files on disk. */
2225
        fileType = GetFileType(hFile);
2226
        if (fileType != FILE_TYPE_DISK) {
2227
            if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
2228
                retval = -1;
2229
                goto cleanup;
2230
            }
2231
            DWORD fileAttributes = GetFileAttributesW(path);
2232
            memset(result, 0, sizeof(*result));
2233
            if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
2234
                fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2235
                /* \\.\pipe\ or \\.\mailslot\ */
2236
                result->st_mode = _S_IFDIR;
2237
            } else if (fileType == FILE_TYPE_CHAR) {
2238
                /* \\.\nul */
2239
                result->st_mode = _S_IFCHR;
2240
            } else if (fileType == FILE_TYPE_PIPE) {
2241
                /* \\.\pipe\spam */
2242
                result->st_mode = _S_IFIFO;
2243
            }
2244
            /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
2245
            goto cleanup;
2246
        }
2247
2248
        /* Query the reparse tag, and traverse a non-link. */
2249
        if (!traverse) {
2250
            if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
2251
                    &tagInfo, sizeof(tagInfo))) {
2252
                /* Allow devices that do not support FileAttributeTagInfo. */
2253
                switch (GetLastError()) {
2254
                case ERROR_INVALID_PARAMETER:
2255
                case ERROR_INVALID_FUNCTION:
2256
                case ERROR_NOT_SUPPORTED:
2257
                    tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2258
                    tagInfo.ReparseTag = 0;
2259
                    break;
2260
                default:
2261
                    retval = -1;
2262
                    goto cleanup;
2263
                }
2264
            } else if (tagInfo.FileAttributes &
2265
                         FILE_ATTRIBUTE_REPARSE_POINT) {
2266
                if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2267
                    if (isUnhandledTag) {
2268
                        /* Traversing previously failed for either this link
2269
                           or its target. */
2270
                        SetLastError(ERROR_CANT_ACCESS_FILE);
2271
                        retval = -1;
2272
                        goto cleanup;
2273
                    }
2274
                /* Traverse a non-link, but not if traversing already failed
2275
                   for an unhandled tag. */
2276
                } else if (!isUnhandledTag) {
2277
                    CloseHandle(hFile);
2278
                    return win32_xstat_slow_impl(path, result, TRUE);
2279
                }
2280
            }
2281
        }
2282
2283
        if (!GetFileInformationByHandleEx(hFile, FileStandardInfo, &standardInfo, sizeof(standardInfo)) ||
2284
            !GetFileInformationByHandleEx(hFile, FileBasicInfo, &basicInfo, sizeof(basicInfo))) {
2285
            switch (GetLastError()) {
2286
            case ERROR_INVALID_PARAMETER:
2287
            case ERROR_INVALID_FUNCTION:
2288
            case ERROR_NOT_SUPPORTED:
2289
                /* Volumes and physical disks are block devices, e.g.
2290
                   \\.\C: and \\.\PhysicalDrive0. */
2291
                memset(result, 0, sizeof(*result));
2292
                result->st_mode = 0x6000; /* S_IFBLK */
2293
                goto cleanup;
2294
            }
2295
            retval = -1;
2296
            goto cleanup;
2297
        }
2298
2299
        if (GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
2300
            /* Successfully got FileIdInfo, so pass it along */
2301
            pIdInfo = &idInfo;
2302
        }
2303
    }
2304
2305
    _Py_attribute_data_to_stat(&standardInfo, tagInfo.ReparseTag, &basicInfo, pIdInfo, result);
2306
    update_st_mode_from_path(path, basicInfo.FileAttributes, result);
2307
2308
cleanup:
2309
    if (hFile != INVALID_HANDLE_VALUE) {
2310
        /* Preserve last error if we are failing */
2311
        error = retval ? GetLastError() : 0;
2312
        if (!CloseHandle(hFile)) {
2313
            retval = -1;
2314
        } else if (retval) {
2315
            /* Restore last error */
2316
            SetLastError(error);
2317
        }
2318
    }
2319
2320
    return retval;
2321
}
2322
2323
static int
2324
win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
2325
                 BOOL traverse)
2326
{
2327
    FILE_STAT_BASIC_INFORMATION statInfo;
2328
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo,
2329
                                     &statInfo, sizeof(statInfo))) {
2330
        if (// Cannot use fast path for reparse points ...
2331
            !(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
2332
            // ... unless it's a name surrogate (symlink) and we're not following
2333
            || (!traverse && IsReparseTagNameSurrogate(statInfo.ReparseTag))
2334
        ) {
2335
            _Py_stat_basic_info_to_stat(&statInfo, result);
2336
            update_st_mode_from_path(path, statInfo.FileAttributes, result);
2337
            return 0;
2338
        }
2339
    } else {
2340
        switch(GetLastError()) {
2341
        case ERROR_FILE_NOT_FOUND:
2342
        case ERROR_PATH_NOT_FOUND:
2343
        case ERROR_NOT_READY:
2344
        case ERROR_BAD_NET_NAME:
2345
            /* These errors aren't worth retrying with the slow path */
2346
            return -1;
2347
        case ERROR_NOT_SUPPORTED:
2348
            /* indicates the API couldn't be loaded */
2349
            break;
2350
        }
2351
    }
2352
2353
    return win32_xstat_slow_impl(path, result, traverse);
2354
}
2355
2356
static int
2357
win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2358
{
2359
    /* Protocol violation: we explicitly clear errno, instead of
2360
       setting it to a POSIX error. Callers should use GetLastError. */
2361
    int code = win32_xstat_impl(path, result, traverse);
2362
    errno = 0;
2363
2364
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
2365
    result->st_ctime = result->st_birthtime;
2366
    result->st_ctime_nsec = result->st_birthtime_nsec;
2367
    return code;
2368
}
2369
/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2370
2371
   In Posix, stat automatically traverses symlinks and returns the stat
2372
   structure for the target.  In Windows, the equivalent GetFileAttributes by
2373
   default does not traverse symlinks and instead returns attributes for
2374
   the symlink.
2375
2376
   Instead, we will open the file (which *does* traverse symlinks by default)
2377
   and GetFileInformationByHandle(). */
2378
2379
static int
2380
win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2381
{
2382
    return win32_xstat(path, result, FALSE);
2383
}
2384
2385
static int
2386
win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2387
{
2388
    return win32_xstat(path, result, TRUE);
2389
}
2390
2391
#endif /* MS_WINDOWS */
2392
2393
PyDoc_STRVAR(stat_result__doc__,
2394
"stat_result: Result from stat, fstat, or lstat.\n\n\
2395
This object may be accessed either as a tuple of\n\
2396
  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2397
or via the attributes st_mode, st_ino, st_dev, st_nlink, and so on.\n\
2398
\n\
2399
Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2400
or st_flags, they are available as attributes only.\n\
2401
\n\
2402
See os.stat for more information.");
2403
2404
static PyStructSequence_Field stat_result_fields[] = {
2405
    {"st_mode",    "protection bits"},
2406
    {"st_ino",     "inode"},
2407
    {"st_dev",     "device"},
2408
    {"st_nlink",   "number of hard links"},
2409
    {"st_uid",     "user ID of owner"},
2410
    {"st_gid",     "group ID of owner"},
2411
    {"st_size",    "total size, in bytes"},
2412
    /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2413
    {NULL,   "integer time of last access"},
2414
    {NULL,   "integer time of last modification"},
2415
    {NULL,   "integer time of last change"},
2416
    {"st_atime",   "time of last access"},
2417
    {"st_mtime",   "time of last modification"},
2418
    {"st_ctime",   "time of last change"},
2419
    {"st_atime_ns",   "time of last access in nanoseconds"},
2420
    {"st_mtime_ns",   "time of last modification in nanoseconds"},
2421
    {"st_ctime_ns",   "time of last change in nanoseconds"},
2422
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2423
    {"st_blksize", "blocksize for filesystem I/O"},
2424
#endif
2425
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2426
    {"st_blocks",  "number of blocks allocated"},
2427
#endif
2428
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2429
    {"st_rdev",    "device type (if inode device)"},
2430
#endif
2431
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2432
    {"st_flags",   "user defined flags for file"},
2433
#endif
2434
#ifdef HAVE_STRUCT_STAT_ST_GEN
2435
    {"st_gen",    "generation number"},
2436
#endif
2437
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2438
    {"st_birthtime",   "time of creation"},
2439
#endif
2440
#ifdef MS_WINDOWS
2441
    {"st_birthtime_ns", "time of creation in nanoseconds"},
2442
#endif
2443
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2444
    {"st_file_attributes", "Windows file attribute bits"},
2445
#endif
2446
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2447
    {"st_fstype",  "Type of filesystem"},
2448
#endif
2449
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2450
    {"st_reparse_tag", "Windows reparse tag"},
2451
#endif
2452
    {0}
2453
};
2454
2455
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2456
#define ST_BLKSIZE_IDX 16
2457
#else
2458
#define ST_BLKSIZE_IDX 15
2459
#endif
2460
2461
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2462
#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2463
#else
2464
#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2465
#endif
2466
2467
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2468
#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2469
#else
2470
#define ST_RDEV_IDX ST_BLOCKS_IDX
2471
#endif
2472
2473
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2474
#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2475
#else
2476
#define ST_FLAGS_IDX ST_RDEV_IDX
2477
#endif
2478
2479
#ifdef HAVE_STRUCT_STAT_ST_GEN
2480
#define ST_GEN_IDX (ST_FLAGS_IDX+1)
2481
#else
2482
#define ST_GEN_IDX ST_FLAGS_IDX
2483
#endif
2484
2485
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS)
2486
#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2487
#else
2488
#define ST_BIRTHTIME_IDX ST_GEN_IDX
2489
#endif
2490
2491
#ifdef MS_WINDOWS
2492
#define ST_BIRTHTIME_NS_IDX (ST_BIRTHTIME_IDX+1)
2493
#else
2494
#define ST_BIRTHTIME_NS_IDX ST_BIRTHTIME_IDX
2495
#endif
2496
2497
#if defined(HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES) || defined(MS_WINDOWS)
2498
#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_NS_IDX+1)
2499
#else
2500
#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_NS_IDX
2501
#endif
2502
2503
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2504
#define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2505
#else
2506
#define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2507
#endif
2508
2509
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2510
#define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2511
#else
2512
#define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2513
#endif
2514
2515
static PyStructSequence_Desc stat_result_desc = {
2516
    "os.stat_result", /* name; see issue gh-63408 */
2517
    stat_result__doc__, /* doc */
2518
    stat_result_fields,
2519
    10
2520
};
2521
2522
PyDoc_STRVAR(statvfs_result__doc__,
2523
"statvfs_result: Result from statvfs or fstatvfs.\n\n\
2524
This object may be accessed either as a tuple of\n\
2525
  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2526
or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2527
\n\
2528
See os.statvfs for more information.");
2529
2530
static PyStructSequence_Field statvfs_result_fields[] = {
2531
    {"f_bsize",  },
2532
    {"f_frsize", },
2533
    {"f_blocks", },
2534
    {"f_bfree",  },
2535
    {"f_bavail", },
2536
    {"f_files",  },
2537
    {"f_ffree",  },
2538
    {"f_favail", },
2539
    {"f_flag",   },
2540
    {"f_namemax",},
2541
    {"f_fsid",   },
2542
    {0}
2543
};
2544
2545
static PyStructSequence_Desc statvfs_result_desc = {
2546
    "os.statvfs_result", /* name; see issue gh-63408 */
2547
    statvfs_result__doc__, /* doc */
2548
    statvfs_result_fields,
2549
    10
2550
};
2551
2552
#if defined(HAVE_WAITID)
2553
PyDoc_STRVAR(waitid_result__doc__,
2554
"waitid_result: Result from waitid.\n\n\
2555
This object may be accessed either as a tuple of\n\
2556
  (si_pid, si_uid, si_signo, si_status, si_code),\n\
2557
or via the attributes si_pid, si_uid, and so on.\n\
2558
\n\
2559
See os.waitid for more information.");
2560
2561
static PyStructSequence_Field waitid_result_fields[] = {
2562
    {"si_pid",  },
2563
    {"si_uid", },
2564
    {"si_signo", },
2565
    {"si_status",  },
2566
    {"si_code", },
2567
    {0}
2568
};
2569
2570
static PyStructSequence_Desc waitid_result_desc = {
2571
    MODNAME ".waitid_result", /* name */
2572
    waitid_result__doc__, /* doc */
2573
    waitid_result_fields,
2574
    5
2575
};
2576
#endif
2577
2578
static PyObject *
2579
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2580
0
{
2581
0
    PyStructSequence *result;
2582
0
    int i;
2583
2584
    // ht_module doesn't get set in PyStructSequence_NewType(),
2585
    // so we can't use PyType_GetModule().
2586
0
    PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
2587
0
    if (mod == NULL) {
2588
0
        return NULL;
2589
0
    }
2590
0
    _posixstate *state = get_posix_state(mod);
2591
0
    Py_DECREF(mod);
2592
0
    if (state == NULL) {
2593
0
        return NULL;
2594
0
    }
2595
0
#define structseq_new state->statresult_new_orig
2596
2597
0
    result = (PyStructSequence*)structseq_new(type, args, kwds);
2598
0
    if (!result)
2599
0
        return NULL;
2600
    /* If we have been initialized from a tuple,
2601
       st_?time might be set to None. Initialize it
2602
       from the int slots.  */
2603
0
    for (i = 7; i <= 9; i++) {
2604
0
        if (result->ob_item[i+3] == Py_None) {
2605
0
            Py_DECREF(Py_None);
2606
0
            result->ob_item[i+3] = Py_NewRef(result->ob_item[i]);
2607
0
        }
2608
0
    }
2609
0
    return (PyObject*)result;
2610
0
}
2611
2612
static int
2613
_posix_clear(PyObject *module)
2614
0
{
2615
0
    _posixstate *state = get_posix_state(module);
2616
0
    Py_CLEAR(state->billion);
2617
0
    Py_CLEAR(state->DirEntryType);
2618
0
    Py_CLEAR(state->ScandirIteratorType);
2619
0
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2620
0
    Py_CLEAR(state->SchedParamType);
2621
0
#endif
2622
0
    Py_CLEAR(state->StatResultType);
2623
0
#ifdef HAVE_STATX
2624
0
    Py_CLEAR(state->StatxResultType);
2625
0
#endif
2626
0
    Py_CLEAR(state->StatVFSResultType);
2627
0
    Py_CLEAR(state->TerminalSizeType);
2628
0
    Py_CLEAR(state->TimesResultType);
2629
0
    Py_CLEAR(state->UnameResultType);
2630
0
#if defined(HAVE_WAITID)
2631
0
    Py_CLEAR(state->WaitidResultType);
2632
0
#endif
2633
0
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2634
0
    Py_CLEAR(state->struct_rusage);
2635
0
#endif
2636
0
    Py_CLEAR(state->st_mode);
2637
0
    return 0;
2638
0
}
2639
2640
static int
2641
_posix_traverse(PyObject *module, visitproc visit, void *arg)
2642
1.61k
{
2643
1.61k
    _posixstate *state = get_posix_state(module);
2644
1.61k
    Py_VISIT(state->billion);
2645
1.61k
    Py_VISIT(state->DirEntryType);
2646
1.61k
    Py_VISIT(state->ScandirIteratorType);
2647
1.61k
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2648
1.61k
    Py_VISIT(state->SchedParamType);
2649
1.61k
#endif
2650
1.61k
    Py_VISIT(state->StatResultType);
2651
1.61k
#ifdef HAVE_STATX
2652
1.61k
    Py_VISIT(state->StatxResultType);
2653
1.61k
#endif
2654
1.61k
    Py_VISIT(state->StatVFSResultType);
2655
1.61k
    Py_VISIT(state->TerminalSizeType);
2656
1.61k
    Py_VISIT(state->TimesResultType);
2657
1.61k
    Py_VISIT(state->UnameResultType);
2658
1.61k
#if defined(HAVE_WAITID)
2659
1.61k
    Py_VISIT(state->WaitidResultType);
2660
1.61k
#endif
2661
1.61k
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2662
1.61k
    Py_VISIT(state->struct_rusage);
2663
1.61k
#endif
2664
1.61k
    Py_VISIT(state->st_mode);
2665
1.61k
    return 0;
2666
1.61k
}
2667
2668
static void
2669
_posix_free(void *module)
2670
0
{
2671
0
   _posix_clear((PyObject *)module);
2672
0
}
2673
2674
2675
2.18M
#define SEC_TO_NS (1000000000LL)
2676
static PyObject *
2677
stat_nanosecond_timestamp(_posixstate *state, time_t sec, unsigned long nsec)
2678
727k
{
2679
#if SIZEOF_TIME_T == 4
2680
    return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2681
#else
2682
    /* 1677-09-21 00:12:44 to 2262-04-11 23:47:15 UTC inclusive */
2683
727k
    if ((LLONG_MIN/SEC_TO_NS) <= sec && sec <= (LLONG_MAX/SEC_TO_NS - 1)) {
2684
727k
        return PyLong_FromLongLong(sec * SEC_TO_NS + nsec);
2685
727k
    }
2686
0
    else
2687
0
    {
2688
0
        PyObject *ns_total = NULL;
2689
0
        PyObject *s_in_ns = NULL;
2690
0
        PyObject *s = _PyLong_FromTime_t(sec);
2691
0
        PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2692
0
        if (s == NULL || ns_fractional == NULL) {
2693
0
            goto exit;
2694
0
        }
2695
2696
0
        s_in_ns = PyNumber_Multiply(s, state->billion);
2697
0
        if (s_in_ns == NULL) {
2698
0
            goto exit;
2699
0
        }
2700
2701
0
        ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2702
2703
0
    exit:
2704
0
        Py_XDECREF(s);
2705
0
        Py_XDECREF(ns_fractional);
2706
0
        Py_XDECREF(s_in_ns);
2707
0
        return ns_total;
2708
0
    }
2709
727k
#endif
2710
727k
}
2711
2712
static int
2713
fill_time(_posixstate *state, PyObject *v, int s_index, int f_index,
2714
          int ns_index, time_t sec, unsigned long nsec)
2715
727k
{
2716
727k
    assert(!PyErr_Occurred());
2717
727k
    assert(nsec < SEC_TO_NS);
2718
2719
727k
    if (s_index >= 0) {
2720
727k
        PyObject *s = _PyLong_FromTime_t(sec);
2721
727k
        if (s == NULL) {
2722
0
            return -1;
2723
0
        }
2724
727k
        PyStructSequence_SET_ITEM(v, s_index, s);
2725
727k
    }
2726
2727
727k
    if (f_index >= 0) {
2728
727k
        PyObject *float_s = PyFloat_FromDouble((double)sec + 1e-9 * nsec);
2729
727k
        if (float_s == NULL) {
2730
0
            return -1;
2731
0
        }
2732
727k
        PyStructSequence_SET_ITEM(v, f_index, float_s);
2733
727k
    }
2734
2735
727k
    if (ns_index >= 0) {
2736
727k
        PyObject *ns_total = stat_nanosecond_timestamp(state, sec, nsec);
2737
727k
        if (ns_total == NULL) {
2738
0
            return -1;
2739
0
        }
2740
727k
        PyStructSequence_SET_ITEM(v, ns_index, ns_total);
2741
727k
    }
2742
2743
727k
    assert(!PyErr_Occurred());
2744
727k
    return 0;
2745
727k
}
2746
#undef SEC_TO_NS
2747
2748
#ifdef MS_WINDOWS
2749
static PyObject*
2750
_pystat_l128_from_l64_l64(uint64_t low, uint64_t high)
2751
{
2752
    PyObject *o_low = PyLong_FromUnsignedLongLong(low);
2753
    if (!o_low || !high) {
2754
        return o_low;
2755
    }
2756
    PyObject *o_high = PyLong_FromUnsignedLongLong(high);
2757
    PyObject *l64 = o_high ? PyLong_FromLong(64) : NULL;
2758
    if (!l64) {
2759
        Py_XDECREF(o_high);
2760
        Py_DECREF(o_low);
2761
        return NULL;
2762
    }
2763
    Py_SETREF(o_high, PyNumber_Lshift(o_high, l64));
2764
    Py_DECREF(l64);
2765
    if (!o_high) {
2766
        Py_DECREF(o_low);
2767
        return NULL;
2768
    }
2769
    Py_SETREF(o_low, PyNumber_Add(o_low, o_high));
2770
    Py_DECREF(o_high);
2771
    return o_low;
2772
}
2773
#endif
2774
2775
/* pack a system stat C structure into the Python stat tuple
2776
   (used by posix_stat() and posix_fstat()) */
2777
static PyObject*
2778
_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2779
242k
{
2780
242k
    assert(!PyErr_Occurred());
2781
2782
242k
    _posixstate *state = get_posix_state(module);
2783
242k
    PyObject *StatResultType = state->StatResultType;
2784
242k
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2785
242k
    if (v == NULL) {
2786
0
        return NULL;
2787
0
    }
2788
2789
242k
#define SET_ITEM(pos, expr) \
2790
2.42M
    do { \
2791
2.42M
        PyObject *obj = (expr); \
2792
2.42M
        if (obj == NULL) { \
2793
0
            goto error; \
2794
0
        } \
2795
2.42M
        PyStructSequence_SET_ITEM(v, (pos), obj); \
2796
2.42M
    } while (0)
2797
2798
242k
    SET_ITEM(0, PyLong_FromLong((long)st->st_mode));
2799
#ifdef MS_WINDOWS
2800
    SET_ITEM(1, _pystat_l128_from_l64_l64(st->st_ino, st->st_ino_high));
2801
    SET_ITEM(2, PyLong_FromUnsignedLongLong(st->st_dev));
2802
#else
2803
242k
    static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2804
242k
                  "stat.st_ino is larger than unsigned long long");
2805
242k
    SET_ITEM(1, PyLong_FromUnsignedLongLong(st->st_ino));
2806
242k
    SET_ITEM(2, _PyLong_FromDev(st->st_dev));
2807
242k
#endif
2808
242k
    SET_ITEM(3, PyLong_FromLong((long)st->st_nlink));
2809
#if defined(MS_WINDOWS)
2810
    SET_ITEM(4, PyLong_FromLong(0));
2811
    SET_ITEM(5, PyLong_FromLong(0));
2812
#else
2813
242k
    SET_ITEM(4, _PyLong_FromUid(st->st_uid));
2814
242k
    SET_ITEM(5, _PyLong_FromGid(st->st_gid));
2815
242k
#endif
2816
242k
    static_assert(sizeof(long long) >= sizeof(st->st_size),
2817
242k
                  "stat.st_size is larger than long long");
2818
242k
    SET_ITEM(6, PyLong_FromLongLong(st->st_size));
2819
2820
    // Set st_atime, st_mtime and st_ctime
2821
242k
    unsigned long ansec, mnsec, cnsec;
2822
242k
#if defined(HAVE_STAT_TV_NSEC)
2823
242k
    ansec = st->st_atim.tv_nsec;
2824
242k
    mnsec = st->st_mtim.tv_nsec;
2825
242k
    cnsec = st->st_ctim.tv_nsec;
2826
#elif defined(HAVE_STAT_TV_NSEC2)
2827
    ansec = st->st_atimespec.tv_nsec;
2828
    mnsec = st->st_mtimespec.tv_nsec;
2829
    cnsec = st->st_ctimespec.tv_nsec;
2830
#elif defined(HAVE_STAT_NSEC)
2831
    ansec = st->st_atime_nsec;
2832
    mnsec = st->st_mtime_nsec;
2833
    cnsec = st->st_ctime_nsec;
2834
#else
2835
    ansec = mnsec = cnsec = 0;
2836
#endif
2837
242k
    if (fill_time(state, v, 7, 10, 13, st->st_atime, ansec) < 0) {
2838
0
        goto error;
2839
0
    }
2840
242k
    if (fill_time(state, v, 8, 11, 14, st->st_mtime, mnsec) < 0) {
2841
0
        goto error;
2842
0
    }
2843
242k
    if (fill_time(state, v, 9, 12, 15, st->st_ctime, cnsec) < 0) {
2844
0
        goto error;
2845
0
    }
2846
2847
242k
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2848
242k
    SET_ITEM(ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize));
2849
242k
#endif
2850
242k
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2851
242k
    SET_ITEM(ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks));
2852
242k
#endif
2853
242k
#ifdef HAVE_STRUCT_STAT_ST_RDEV
2854
242k
    SET_ITEM(ST_RDEV_IDX, _PyLong_FromDev(st->st_rdev));
2855
242k
#endif
2856
#ifdef HAVE_STRUCT_STAT_ST_GEN
2857
    SET_ITEM(ST_GEN_IDX, PyLong_FromLong((long)st->st_gen));
2858
#endif
2859
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
2860
    {
2861
      unsigned long bsec, bnsec;
2862
      bsec = (long)st->st_birthtime;
2863
#ifdef HAVE_STAT_TV_NSEC2
2864
      bnsec = st->st_birthtimespec.tv_nsec;
2865
#else
2866
      bnsec = 0;
2867
#endif
2868
      SET_ITEM(ST_BIRTHTIME_IDX, PyFloat_FromDouble(bsec + bnsec * 1e-9));
2869
    }
2870
#elif defined(MS_WINDOWS)
2871
    if (fill_time(state, v, -1, ST_BIRTHTIME_IDX, ST_BIRTHTIME_NS_IDX,
2872
                  st->st_birthtime, st->st_birthtime_nsec) < 0) {
2873
        goto error;
2874
    }
2875
#endif
2876
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
2877
    SET_ITEM(ST_FLAGS_IDX, PyLong_FromLong((long)st->st_flags));
2878
#endif
2879
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2880
    SET_ITEM(ST_FILE_ATTRIBUTES_IDX,
2881
             PyLong_FromUnsignedLong(st->st_file_attributes));
2882
#endif
2883
#ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2884
   SET_ITEM(ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype));
2885
#endif
2886
#ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2887
    SET_ITEM(ST_REPARSE_TAG_IDX, PyLong_FromUnsignedLong(st->st_reparse_tag));
2888
#endif
2889
2890
242k
    assert(!PyErr_Occurred());
2891
242k
    return v;
2892
2893
0
error:
2894
0
    Py_DECREF(v);
2895
0
    return NULL;
2896
2897
242k
#undef SET_ITEM
2898
242k
}
2899
2900
/* POSIX methods */
2901
2902
2903
static PyObject *
2904
posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2905
              int dir_fd, int follow_symlinks)
2906
244k
{
2907
244k
    STRUCT_STAT st;
2908
244k
    int result;
2909
2910
244k
#ifdef HAVE_FSTATAT
2911
244k
    int fstatat_unavailable = 0;
2912
244k
#endif
2913
2914
#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2915
    if (follow_symlinks_specified(function_name, follow_symlinks))
2916
        return NULL;
2917
#endif
2918
2919
244k
    if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2920
244k
        dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2921
244k
        fd_and_follow_symlinks_invalid("stat", path->is_fd, follow_symlinks))
2922
0
        return NULL;
2923
2924
244k
    Py_BEGIN_ALLOW_THREADS
2925
244k
    if (path->is_fd) {
2926
0
        result = FSTAT(path->fd, &st);
2927
0
    }
2928
#ifdef MS_WINDOWS
2929
    else if (follow_symlinks)
2930
        result = win32_stat(path->wide, &st);
2931
    else
2932
        result = win32_lstat(path->wide, &st);
2933
#else
2934
244k
    else
2935
244k
#if defined(HAVE_LSTAT)
2936
244k
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2937
11.2k
        result = LSTAT(path->narrow, &st);
2938
233k
    else
2939
233k
#endif /* HAVE_LSTAT */
2940
233k
#ifdef HAVE_FSTATAT
2941
233k
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2942
0
        if (HAVE_FSTATAT_RUNTIME) {
2943
0
            result = fstatat(dir_fd, path->narrow, &st,
2944
0
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2945
2946
0
        } else {
2947
0
            fstatat_unavailable = 1;
2948
0
        }
2949
0
    } else
2950
233k
#endif /* HAVE_FSTATAT */
2951
233k
        result = STAT(path->narrow, &st);
2952
244k
#endif /* MS_WINDOWS */
2953
244k
    Py_END_ALLOW_THREADS
2954
2955
244k
#ifdef HAVE_FSTATAT
2956
244k
    if (fstatat_unavailable) {
2957
0
        argument_unavailable_error("stat", "dir_fd");
2958
0
        return NULL;
2959
0
    }
2960
244k
#endif
2961
2962
244k
    if (result != 0) {
2963
179k
        return path_error(path);
2964
179k
    }
2965
2966
64.5k
    return _pystat_fromstructstat(module, &st);
2967
244k
}
2968
2969
/*[python input]
2970
2971
for s in """
2972
2973
FACCESSAT
2974
FCHMODAT
2975
FCHOWNAT
2976
FSTATAT
2977
LINKAT
2978
MKDIRAT
2979
MKFIFOAT
2980
MKNODAT
2981
OPENAT
2982
READLINKAT
2983
SYMLINKAT
2984
UNLINKAT
2985
2986
""".strip().split():
2987
    s = s.strip()
2988
    print("""
2989
#ifdef HAVE_{s}
2990
    #define {s}_DIR_FD_CONVERTER dir_fd_converter
2991
#else
2992
    #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2993
#endif
2994
""".rstrip().format(s=s))
2995
2996
for s in """
2997
2998
FCHDIR
2999
FCHMOD
3000
FCHOWN
3001
FDOPENDIR
3002
FEXECVE
3003
FPATHCONF
3004
FSTATVFS
3005
FTRUNCATE
3006
3007
""".strip().split():
3008
    s = s.strip()
3009
    print("""
3010
#ifdef HAVE_{s}
3011
    #define PATH_HAVE_{s} 1
3012
#else
3013
    #define PATH_HAVE_{s} 0
3014
#endif
3015
3016
""".rstrip().format(s=s))
3017
[python start generated code]*/
3018
3019
#ifdef HAVE_FACCESSAT
3020
0
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
3021
#else
3022
    #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
3023
#endif
3024
3025
#ifdef HAVE_FCHMODAT
3026
0
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
3027
#else
3028
    #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
3029
#endif
3030
3031
#ifdef HAVE_FCHOWNAT
3032
0
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
3033
#else
3034
    #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
3035
#endif
3036
3037
#ifdef HAVE_FSTATAT
3038
8.21k
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
3039
#else
3040
    #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
3041
#endif
3042
3043
#ifdef HAVE_LINKAT
3044
    #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
3045
#else
3046
    #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3047
#endif
3048
3049
#ifdef HAVE_MKDIRAT
3050
0
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
3051
#else
3052
    #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
3053
#endif
3054
3055
#ifdef HAVE_MKFIFOAT
3056
0
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
3057
#else
3058
    #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
3059
#endif
3060
3061
#ifdef HAVE_MKNODAT
3062
0
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
3063
#else
3064
    #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
3065
#endif
3066
3067
#ifdef HAVE_OPENAT
3068
91.0k
    #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
3069
#else
3070
    #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
3071
#endif
3072
3073
#ifdef HAVE_READLINKAT
3074
0
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
3075
#else
3076
    #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3077
#endif
3078
3079
#ifdef HAVE_SYMLINKAT
3080
0
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
3081
#else
3082
    #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3083
#endif
3084
3085
#ifdef HAVE_UNLINKAT
3086
109k
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
3087
#else
3088
    #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
3089
#endif
3090
3091
#ifdef HAVE_FCHDIR
3092
    #define PATH_HAVE_FCHDIR 1
3093
#else
3094
    #define PATH_HAVE_FCHDIR 0
3095
#endif
3096
3097
#ifdef HAVE_FCHMOD
3098
    #define PATH_HAVE_FCHMOD 1
3099
#else
3100
    #define PATH_HAVE_FCHMOD 0
3101
#endif
3102
3103
#ifdef HAVE_FCHOWN
3104
    #define PATH_HAVE_FCHOWN 1
3105
#else
3106
    #define PATH_HAVE_FCHOWN 0
3107
#endif
3108
3109
#ifdef HAVE_FDOPENDIR
3110
    #define PATH_HAVE_FDOPENDIR 1
3111
#else
3112
    #define PATH_HAVE_FDOPENDIR 0
3113
#endif
3114
3115
#ifdef HAVE_FEXECVE
3116
    #define PATH_HAVE_FEXECVE 1
3117
#else
3118
    #define PATH_HAVE_FEXECVE 0
3119
#endif
3120
3121
#ifdef HAVE_FPATHCONF
3122
    #define PATH_HAVE_FPATHCONF 1
3123
#else
3124
    #define PATH_HAVE_FPATHCONF 0
3125
#endif
3126
3127
#ifdef HAVE_FSTATVFS
3128
    #define PATH_HAVE_FSTATVFS 1
3129
#else
3130
    #define PATH_HAVE_FSTATVFS 0
3131
#endif
3132
3133
#ifdef HAVE_FTRUNCATE
3134
    #define PATH_HAVE_FTRUNCATE 1
3135
#else
3136
    #define PATH_HAVE_FTRUNCATE 0
3137
#endif
3138
/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
3139
3140
#ifdef MS_WINDOWS
3141
    #undef PATH_HAVE_FTRUNCATE
3142
    #define PATH_HAVE_FTRUNCATE 1
3143
    #undef PATH_HAVE_FCHMOD
3144
    #define PATH_HAVE_FCHMOD 1
3145
#endif
3146
3147
/*[python input]
3148
3149
class path_t_converter(CConverter):
3150
3151
    type = "path_t"
3152
    impl_by_reference = True
3153
    parse_by_reference = True
3154
    default_type = ()
3155
    c_init_default = "<placeholder>"  # overridden in pre_render()
3156
3157
    converter = 'path_converter'
3158
3159
    def converter_init(self, *, allow_fd=False, make_wide=None,
3160
                       nonstrict=False, nullable=False,
3161
                       suppress_value_error=False):
3162
3163
        self.nullable = nullable
3164
        self.nonstrict = nonstrict
3165
        self.make_wide = make_wide
3166
        self.suppress_value_error = suppress_value_error
3167
        self.allow_fd = allow_fd
3168
        if nullable:
3169
            self.default_type = NoneType
3170
3171
    def pre_render(self):
3172
        def strify(value):
3173
            if isinstance(value, str):
3174
                return value
3175
            return str(int(bool(value)))
3176
3177
        # add self.py_name here when merging with posixmodule conversion
3178
        if self.make_wide is None:
3179
            self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {}, {})'.format(
3180
                self.function.name,
3181
                self.name,
3182
                strify(self.nullable),
3183
                strify(self.nonstrict),
3184
                strify(self.suppress_value_error),
3185
                strify(self.allow_fd),
3186
            )
3187
        else:
3188
            self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {}, {})'.format(
3189
                self.function.name,
3190
                self.name,
3191
                strify(self.nullable),
3192
                strify(self.nonstrict),
3193
                strify(self.make_wide),
3194
                strify(self.suppress_value_error),
3195
                strify(self.allow_fd),
3196
            )
3197
3198
    def cleanup(self):
3199
        return "path_cleanup(&" + self.name + ");\n"
3200
3201
3202
class dir_fd_converter(CConverter):
3203
    type = 'int'
3204
    default_type = NoneType
3205
    c_init_default = 'DEFAULT_DIR_FD'
3206
3207
    def converter_init(self, requires=None):
3208
        if self.default in (unspecified, None):
3209
            self.c_default = 'DEFAULT_DIR_FD'
3210
        if isinstance(requires, str):
3211
            self.converter = requires.upper() + '_DIR_FD_CONVERTER'
3212
        else:
3213
            self.converter = 'dir_fd_converter'
3214
3215
    def c_default_init(self):
3216
        self.c_default = 'DEFAULT_DIR_FD'
3217
3218
class dev_t_converter(CConverter):
3219
    type = 'dev_t'
3220
    converter = '_Py_Dev_Converter'
3221
3222
class dev_t_return_converter(unsigned_long_return_converter):
3223
    type = 'dev_t'
3224
    conversion_fn = '_PyLong_FromDev'
3225
    unsigned_cast = '(dev_t)'
3226
3227
class idtype_t_converter(CConverter):
3228
    type = 'idtype_t'
3229
    converter = 'idtype_t_converter'
3230
3231
class id_t_converter(CConverter):
3232
    type = 'id_t'
3233
    format_unit = '" _Py_PARSE_PID "'
3234
3235
    def parse_arg(self, argname, displayname, *, limited_capi):
3236
        return self.format_code("""
3237
            {paramname} = (id_t)PyLong_AsPid({argname});
3238
            if ({paramname} == (id_t)(-1) && PyErr_Occurred()) {{{{
3239
                goto exit;
3240
            }}}}
3241
            """, argname=argname)
3242
3243
class intptr_t_converter(CConverter):
3244
    type = 'intptr_t'
3245
    format_unit = '" _Py_PARSE_INTPTR "'
3246
3247
    def parse_arg(self, argname, displayname, *, limited_capi):
3248
        return self.format_code("""
3249
            {paramname} = (intptr_t)PyLong_AsVoidPtr({argname});
3250
            if (!{paramname} && PyErr_Occurred()) {{{{
3251
                goto exit;
3252
            }}}}
3253
            """, argname=argname)
3254
3255
class Py_off_t_return_converter(long_return_converter):
3256
    type = 'Py_off_t'
3257
    conversion_fn = 'PyLong_FromPy_off_t'
3258
3259
class confname_converter(CConverter):
3260
    type="int"
3261
    converter="conv_confname"
3262
3263
    def converter_init(self, *, table):
3264
        self.table = table
3265
3266
    def parse_arg(self, argname, displayname, *, limited_capi):
3267
        return self.format_code("""
3268
            if (!{converter}(module, {argname}, &{paramname}, "{table}")) {{{{
3269
                goto exit;
3270
            }}}}
3271
        """, argname=argname, converter=self.converter, table=self.table)
3272
3273
[python start generated code]*/
3274
/*[python end generated code: output=da39a3ee5e6b4b0d input=7ceccf55bb600f61]*/
3275
3276
/*[clinic input]
3277
3278
os.stat
3279
3280
    path : path_t(allow_fd=True)
3281
        Path to be examined; can be string, bytes, a path-like object or
3282
        open-file-descriptor int.
3283
3284
    *
3285
3286
    dir_fd : dir_fd(requires='fstatat') = None
3287
        If not None, it should be a file descriptor open to a directory,
3288
        and path should be a relative string; path will then be relative to
3289
        that directory.
3290
3291
    follow_symlinks: bool = True
3292
        If False, and the last element of the path is a symbolic link,
3293
        stat will examine the symbolic link itself instead of the file
3294
        the link points to.
3295
3296
Perform a stat system call on the given path.
3297
3298
dir_fd and follow_symlinks may not be implemented
3299
  on your platform.  If they are unavailable, using them will raise a
3300
  NotImplementedError.
3301
3302
It's an error to use dir_fd or follow_symlinks when specifying path as
3303
  an open file descriptor.
3304
3305
[clinic start generated code]*/
3306
3307
static PyObject *
3308
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
3309
/*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
3310
233k
{
3311
233k
    return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
3312
233k
}
3313
3314
3315
/*[clinic input]
3316
@permit_long_summary
3317
os.lstat
3318
3319
    path : path_t
3320
3321
    *
3322
3323
    dir_fd : dir_fd(requires='fstatat') = None
3324
3325
Perform a stat system call on the given path, without following symbolic links.
3326
3327
Like stat(), but do not follow symbolic links.
3328
Equivalent to stat(path, follow_symlinks=False).
3329
[clinic start generated code]*/
3330
3331
static PyObject *
3332
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
3333
/*[clinic end generated code: output=ef82a5d35ce8ab37 input=024102124f88e743]*/
3334
11.2k
{
3335
11.2k
    int follow_symlinks = 0;
3336
11.2k
    return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
3337
11.2k
}
3338
3339
3340
#ifdef HAVE_STATX
3341
typedef struct {
3342
    PyObject_HEAD
3343
    dev_t rdev, dev;
3344
    struct statx stx;
3345
} Py_statx_result;
3346
3347
0
#define Py_statx_result_CAST(op) _Py_CAST(Py_statx_result*, (op))
3348
3349
#define M(attr, type, offset, doc) \
3350
    {attr, type, offset, Py_READONLY, PyDoc_STR(doc)}
3351
#define MM(attr, type, member, doc) \
3352
    M(#attr, type, offsetof(Py_statx_result, stx.stx_##member), doc)
3353
#define MX(attr, type, member, doc) \
3354
    M(#attr, type, offsetof(Py_statx_result, member), doc)
3355
3356
static PyMemberDef pystatx_result_members[] = {
3357
    MM(stx_mask, Py_T_UINT, mask, "member validity mask"),
3358
    MM(stx_blksize, Py_T_UINT, blksize, "blocksize for filesystem I/O"),
3359
    MM(stx_attributes, Py_T_ULONGLONG, attributes, "Linux inode attribute bits"),
3360
    MM(stx_attributes_mask, Py_T_ULONGLONG, attributes_mask,
3361
        "Mask of supported bits in stx_attributes"),
3362
    MM(stx_rdev_major, Py_T_UINT, rdev_major, "represented device major number"),
3363
    MM(stx_rdev_minor, Py_T_UINT, rdev_minor, "represented device minor number"),
3364
    MX(stx_rdev, Py_T_ULONGLONG, rdev, "device type (if inode device)"),
3365
    MM(stx_dev_major, Py_T_UINT, dev_major, "containing device major number"),
3366
    MM(stx_dev_minor, Py_T_UINT, dev_minor, "containing device minor number"),
3367
    MX(stx_dev, Py_T_ULONGLONG, dev, "device"),
3368
    {NULL},
3369
};
3370
3371
#undef MX
3372
#undef MM
3373
#undef M
3374
3375
3376
#define STATX_GET_UINT(ATTR, MASK) \
3377
    static PyObject* \
3378
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3379
0
    { \
3380
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3381
0
        if (!(self->stx.stx_mask & MASK)) { \
3382
0
            Py_RETURN_NONE; \
3383
0
        } \
3384
0
        unsigned long value = self->stx.ATTR; \
3385
0
        return PyLong_FromUnsignedLong(value); \
3386
0
    }
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_nlink
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_uid
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_gid
3387
3388
STATX_GET_UINT(stx_uid, STATX_UID)
3389
STATX_GET_UINT(stx_gid, STATX_GID)
3390
STATX_GET_UINT(stx_nlink, STATX_NLINK)
3391
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3392
STATX_GET_UINT(stx_dio_mem_align, STATX_DIOALIGN)
3393
STATX_GET_UINT(stx_dio_offset_align, STATX_DIOALIGN)
3394
#endif
3395
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3396
STATX_GET_UINT(stx_dio_read_offset_align, STATX_DIO_READ_ALIGN)
3397
#endif
3398
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3399
STATX_GET_UINT(stx_atomic_write_unit_min, STATX_WRITE_ATOMIC)
3400
STATX_GET_UINT(stx_atomic_write_unit_max, STATX_WRITE_ATOMIC)
3401
STATX_GET_UINT(stx_atomic_write_segments_max, STATX_WRITE_ATOMIC)
3402
#endif
3403
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3404
STATX_GET_UINT(stx_atomic_write_unit_max_opt, STATX_WRITE_ATOMIC)
3405
#endif
3406
3407
3408
static PyObject*
3409
pystatx_result_get_stx_mode(PyObject *op, void *Py_UNUSED(context))
3410
0
{
3411
0
    Py_statx_result *self = Py_statx_result_CAST(op);
3412
0
    if (!(self->stx.stx_mask & (STATX_TYPE | STATX_MODE))) {
3413
0
        Py_RETURN_NONE;
3414
0
    }
3415
0
    return PyLong_FromUnsignedLong(self->stx.stx_mode);
3416
0
}
3417
3418
3419
#define STATX_GET_ULONGLONG(ATTR, MASK) \
3420
    static PyObject* \
3421
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3422
0
    { \
3423
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3424
0
        if (!(self->stx.stx_mask & MASK)) { \
3425
0
            Py_RETURN_NONE; \
3426
0
        } \
3427
0
        unsigned long long value = self->stx.ATTR; \
3428
0
        return PyLong_FromUnsignedLongLong(value); \
3429
0
    }
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_ino
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_size
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_blocks
3430
3431
STATX_GET_ULONGLONG(stx_blocks, STATX_BLOCKS)
3432
STATX_GET_ULONGLONG(stx_ino, STATX_INO)
3433
STATX_GET_ULONGLONG(stx_size, STATX_SIZE)
3434
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3435
STATX_GET_ULONGLONG(stx_mnt_id, STATX_MNT_ID)
3436
#endif
3437
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3438
STATX_GET_ULONGLONG(stx_subvol, STATX_SUBVOL)
3439
#endif
3440
3441
3442
#define STATX_GET_DOUBLE(ATTR, MASK) \
3443
    static PyObject* \
3444
    pystatx_result_get_##ATTR(PyObject *op, void *Py_UNUSED(context)) \
3445
0
    { \
3446
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3447
0
        if (!(self->stx.stx_mask & MASK)) { \
3448
0
            Py_RETURN_NONE; \
3449
0
        } \
3450
0
        struct statx_timestamp *ts = &self->stx.ATTR; \
3451
0
        double sec = ((double)ts->tv_sec + ts->tv_nsec * 1e-9); \
3452
0
        return PyFloat_FromDouble(sec); \
3453
0
    }
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_atime
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_btime
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_ctime
Unexecuted instantiation: posixmodule.c:pystatx_result_get_stx_mtime
3454
3455
STATX_GET_DOUBLE(stx_atime, STATX_ATIME)
3456
STATX_GET_DOUBLE(stx_btime, STATX_BTIME)
3457
STATX_GET_DOUBLE(stx_ctime, STATX_CTIME)
3458
STATX_GET_DOUBLE(stx_mtime, STATX_MTIME)
3459
3460
#define STATX_GET_NSEC(ATTR, MEMBER, MASK) \
3461
    static PyObject* \
3462
    pystatx_result_get_##ATTR(PyObject *op, void *context) \
3463
0
    { \
3464
0
        Py_statx_result *self = Py_statx_result_CAST(op); \
3465
0
        if (!(self->stx.stx_mask & MASK)) { \
3466
0
            Py_RETURN_NONE; \
3467
0
        } \
3468
0
        struct statx_timestamp *ts = &self->stx.MEMBER; \
3469
0
        _posixstate *state = PyType_GetModuleState(Py_TYPE(op)); \
3470
0
        assert(state != NULL); \
3471
0
        return stat_nanosecond_timestamp(state, ts->tv_sec, ts->tv_nsec); \
3472
0
    }
3473
3474
0
STATX_GET_NSEC(stx_atime_ns, stx_atime, STATX_ATIME)
3475
0
STATX_GET_NSEC(stx_btime_ns, stx_btime, STATX_BTIME)
3476
0
STATX_GET_NSEC(stx_ctime_ns, stx_ctime, STATX_CTIME)
3477
0
STATX_GET_NSEC(stx_mtime_ns, stx_mtime, STATX_MTIME)
3478
3479
#define G(attr, doc) \
3480
    {#attr, pystatx_result_get_##attr, NULL, PyDoc_STR(doc), NULL}
3481
3482
static PyGetSetDef pystatx_result_getset[] = {
3483
    G(stx_mode, "protection bits"),
3484
    G(stx_nlink, "number of hard links"),
3485
    G(stx_uid, "user ID of owner"),
3486
    G(stx_gid, "group ID of owner"),
3487
    G(stx_ino, "inode"),
3488
    G(stx_size, "total size, in bytes"),
3489
    G(stx_blocks, "number of blocks allocated"),
3490
    G(stx_atime, "time of last access"),
3491
    G(stx_atime_ns, "time of last access in nanoseconds"),
3492
    G(stx_btime, "time of creation"),
3493
    G(stx_btime_ns, "time of creation in nanoseconds"),
3494
    G(stx_ctime, "time of last change"),
3495
    G(stx_ctime_ns, "time of last change in nanoseconds"),
3496
    G(stx_mtime, "time of last modification"),
3497
    G(stx_mtime_ns, "time of last modification in nanoseconds"),
3498
#if defined(STATX_MNT_ID) && defined(HAVE_STRUCT_STATX_STX_MNT_ID)
3499
    G(stx_mnt_id, "mount ID"),
3500
#endif
3501
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
3502
    G(stx_dio_mem_align, "direct I/O memory buffer alignment"),
3503
    G(stx_dio_offset_align, "direct I/O file offset alignment"),
3504
#endif
3505
#if defined(STATX_SUBVOL) && defined(HAVE_STRUCT_STATX_STX_SUBVOL)
3506
    G(stx_subvol, "subvolume ID"),
3507
#endif
3508
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MIN
3509
    G(stx_atomic_write_unit_min,
3510
      "minimum size for direct I/O with torn-write protection"),
3511
    G(stx_atomic_write_unit_max,
3512
        "maximum size for direct I/O with torn-write protection"),
3513
    G(stx_atomic_write_segments_max,
3514
        "maximum iovecs for direct I/O with torn-write protection"),
3515
#endif
3516
#ifdef HAVE_STRUCT_STATX_STX_DIO_READ_OFFSET_ALIGN
3517
    G(stx_dio_read_offset_align, "direct I/O file offset alignment for reads"),
3518
#endif
3519
#ifdef HAVE_STRUCT_STATX_STX_ATOMIC_WRITE_UNIT_MAX_OPT
3520
    G(stx_atomic_write_unit_max_opt,
3521
        "maximum optimized size for direct I/O with torn-write protection"),
3522
#endif
3523
    {NULL},
3524
};
3525
3526
#undef G
3527
3528
static PyObject *
3529
pystatx_result_repr(PyObject *op)
3530
0
{
3531
0
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
3532
0
    if (writer == NULL) {
3533
0
        return NULL;
3534
0
    }
3535
0
#define WRITE_ASCII(s) \
3536
0
    do { \
3537
0
        if (PyUnicodeWriter_WriteASCII(writer, s, strlen(s)) < 0) { \
3538
0
            goto error; \
3539
0
        } \
3540
0
    } while (0)
3541
3542
0
    WRITE_ASCII("os.statx_result(");
3543
3544
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_members) - 1; ++i) {
3545
0
        if (i > 0) {
3546
0
            WRITE_ASCII(", ");
3547
0
        }
3548
3549
0
        PyMemberDef *d = &pystatx_result_members[i];
3550
0
        WRITE_ASCII(d->name);
3551
0
        WRITE_ASCII("=");
3552
3553
0
        PyObject *o = PyMember_GetOne((const char *)op, d);
3554
0
        if (o == NULL) {
3555
0
            goto error;
3556
0
        }
3557
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3558
0
            Py_DECREF(o);
3559
0
            goto error;
3560
0
        }
3561
0
        Py_DECREF(o);
3562
0
    }
3563
3564
0
    for (size_t i = 0; i < Py_ARRAY_LENGTH(pystatx_result_getset) - 1; ++i) {
3565
0
        PyGetSetDef *d = &pystatx_result_getset[i];
3566
0
        PyObject *o = d->get(op, d->closure);
3567
0
        if (o == NULL) {
3568
0
            goto error;
3569
0
        }
3570
0
        if (o == Py_None) {
3571
0
            continue;
3572
0
        }
3573
3574
0
        WRITE_ASCII(", ");
3575
0
        WRITE_ASCII(d->name);
3576
0
        WRITE_ASCII("=");
3577
0
        if (PyUnicodeWriter_WriteRepr(writer, o) < 0) {
3578
0
            Py_DECREF(o);
3579
0
            goto error;
3580
0
        }
3581
0
        Py_DECREF(o);
3582
0
    }
3583
3584
0
    WRITE_ASCII(")");
3585
0
    return PyUnicodeWriter_Finish(writer);
3586
0
#undef WRITE_ASCII
3587
3588
0
error:
3589
0
    PyUnicodeWriter_Discard(writer);
3590
0
    return NULL;
3591
0
}
3592
3593
static int
3594
pystatx_result_traverse(PyObject *self, visitproc visit, void *arg)
3595
0
{
3596
0
    Py_VISIT(Py_TYPE(self));
3597
0
    return 0;
3598
0
}
3599
3600
static void
3601
pystatx_result_dealloc(PyObject *op)
3602
0
{
3603
0
    Py_statx_result *self = (Py_statx_result *) op;
3604
0
    PyTypeObject *tp = Py_TYPE(self);
3605
0
    PyObject_GC_UnTrack(self);
3606
0
    tp->tp_free(self);
3607
0
    Py_DECREF(tp);
3608
0
}
3609
3610
static PyType_Slot pystatx_result_slots[] = {
3611
    {Py_tp_repr, pystatx_result_repr},
3612
    {Py_tp_traverse, pystatx_result_traverse},
3613
    {Py_tp_dealloc, pystatx_result_dealloc},
3614
    {Py_tp_members, pystatx_result_members},
3615
    {Py_tp_getset, pystatx_result_getset},
3616
    {0, NULL},
3617
};
3618
3619
static PyType_Spec pystatx_result_spec = {
3620
    .name = "os.statx_result",
3621
    .basicsize = sizeof(Py_statx_result),
3622
    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_HAVE_GC |
3623
             Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION,
3624
    .slots = pystatx_result_slots,
3625
};
3626
3627
/*[clinic input]
3628
3629
os.statx
3630
3631
    path : path_t(allow_fd=True)
3632
        Path to be examined; can be string, bytes, a path-like object or
3633
        open-file-descriptor int.
3634
3635
    mask: unsigned_int(bitwise=True)
3636
        A bitmask of STATX_* constants defining the requested information.
3637
3638
    *
3639
3640
    flags: int = 0
3641
        A bitmask of AT_NO_AUTOMOUNT and/or AT_STATX_* flags.
3642
3643
    dir_fd : dir_fd = None
3644
        If not None, it should be a file descriptor open to a directory,
3645
        and path should be a relative string; path will then be relative to
3646
        that directory.
3647
3648
    follow_symlinks: bool = True
3649
        If False, and the last element of the path is a symbolic link,
3650
        statx will examine the symbolic link itself instead of the file
3651
        the link points to.
3652
3653
Perform a statx system call on the given path.
3654
3655
It's an error to use dir_fd or follow_symlinks when specifying path as
3656
  an open file descriptor.
3657
3658
[clinic start generated code]*/
3659
3660
static PyObject *
3661
os_statx_impl(PyObject *module, path_t *path, unsigned int mask, int flags,
3662
              int dir_fd, int follow_symlinks)
3663
/*[clinic end generated code: output=e3765979ac6fe15b input=f0116380c5dc4f2f]*/
3664
0
{
3665
0
    if (path_and_dir_fd_invalid("statx", path, dir_fd) ||
3666
0
        dir_fd_and_fd_invalid("statx", dir_fd, path->fd) ||
3667
0
        fd_and_follow_symlinks_invalid("statx", path->is_fd, follow_symlinks)) {
3668
0
        return NULL;
3669
0
    }
3670
3671
    /* reject flags covered by kwargs, but allow unknown flags that may be
3672
       future AT_STATX_* extensions */
3673
0
    if (flags & (AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW)) {
3674
0
        PyErr_Format(PyExc_ValueError,
3675
0
                     "use follow_symlinks kwarg instead of AT_SYMLINK_* flag");
3676
0
        return NULL;
3677
0
    }
3678
0
    if (flags & AT_EMPTY_PATH) {
3679
0
        PyErr_Format(PyExc_ValueError,
3680
0
                     "use dir_fd kwarg instead of AT_EMPTY_PATH flag");
3681
0
        return NULL;
3682
0
    }
3683
3684
    /* Future bits may refer to members beyond the current size of struct
3685
       statx, so we need to mask them off to prevent memory corruption. */
3686
0
    mask &= _Py_STATX_KNOWN;
3687
3688
0
    _posixstate *state = get_posix_state(module);
3689
0
    PyTypeObject *tp = (PyTypeObject *)state->StatxResultType;
3690
0
    Py_statx_result *v = (Py_statx_result *)tp->tp_alloc(tp, 0);
3691
0
    if (v == NULL) {
3692
0
        return NULL;
3693
0
    }
3694
3695
0
    int result;
3696
0
    Py_BEGIN_ALLOW_THREADS
3697
0
    if (path->is_fd) {
3698
0
        result = statx(path->fd, "", flags | AT_EMPTY_PATH, mask, &v->stx);
3699
0
    }
3700
0
    else {
3701
0
        result = statx(dir_fd, path->narrow, flags, mask, &v->stx);
3702
0
    }
3703
0
    Py_END_ALLOW_THREADS
3704
3705
0
    if (result != 0) {
3706
0
        Py_DECREF(v);
3707
0
        return path_error(path);
3708
0
    }
3709
3710
0
    v->rdev = makedev(v->stx.stx_rdev_major, v->stx.stx_rdev_minor);
3711
0
    v->dev = makedev(v->stx.stx_dev_major, v->stx.stx_dev_minor);
3712
3713
0
    assert(!PyErr_Occurred());
3714
0
    return (PyObject *)v;
3715
0
}
3716
#endif /* HAVE_STATX */
3717
3718
3719
/*[clinic input]
3720
os.access -> bool
3721
3722
    path: path_t
3723
        Path to be tested; can be string, bytes, or a path-like object.
3724
3725
    mode: int
3726
        Operating-system mode bitfield.  Can be F_OK to test existence,
3727
        or the inclusive-OR of R_OK, W_OK, and X_OK.
3728
3729
    *
3730
3731
    dir_fd : dir_fd(requires='faccessat') = None
3732
        If not None, it should be a file descriptor open to a directory,
3733
        and path should be relative; path will then be relative to that
3734
        directory.
3735
3736
    effective_ids: bool = False
3737
        If True, access will use the effective uid/gid instead of
3738
        the real uid/gid.
3739
3740
    follow_symlinks: bool = True
3741
        If False, and the last element of the path is a symbolic link,
3742
        access will examine the symbolic link itself instead of the file
3743
        the link points to.
3744
3745
Use the real uid/gid to test for access to a path.
3746
3747
{parameters}
3748
dir_fd, effective_ids, and follow_symlinks may not be implemented
3749
  on your platform.  If they are unavailable, using them will raise a
3750
  NotImplementedError.
3751
3752
Note that most operations will use the effective uid/gid, therefore this
3753
  routine can be used in a suid/sgid environment to test if the invoking
3754
  user has the specified access to the path.
3755
3756
[clinic start generated code]*/
3757
3758
static int
3759
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3760
               int effective_ids, int follow_symlinks)
3761
/*[clinic end generated code: output=cf84158bc90b1a77 input=c33565f7584b99e4]*/
3762
0
{
3763
0
    int return_value;
3764
3765
#ifdef MS_WINDOWS
3766
    DWORD attr;
3767
#else
3768
0
    int result;
3769
0
#endif
3770
3771
0
#ifdef HAVE_FACCESSAT
3772
0
    int faccessat_unavailable = 0;
3773
0
#endif
3774
3775
#ifndef HAVE_FACCESSAT
3776
    if (follow_symlinks_specified("access", follow_symlinks))
3777
        return -1;
3778
3779
    if (effective_ids) {
3780
        argument_unavailable_error("access", "effective_ids");
3781
        return -1;
3782
    }
3783
#endif
3784
3785
#ifdef MS_WINDOWS
3786
    Py_BEGIN_ALLOW_THREADS
3787
    attr = GetFileAttributesW(path->wide);
3788
    Py_END_ALLOW_THREADS
3789
3790
    /*
3791
     * Access is possible if
3792
     *   * we didn't get a -1, and
3793
     *     * write access wasn't requested,
3794
     *     * or the file isn't read-only,
3795
     *     * or it's a directory.
3796
     * (Directories cannot be read-only on Windows.)
3797
    */
3798
    return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3799
            (!(mode & 2) ||
3800
            !(attr & FILE_ATTRIBUTE_READONLY) ||
3801
            (attr & FILE_ATTRIBUTE_DIRECTORY));
3802
#else
3803
3804
0
    Py_BEGIN_ALLOW_THREADS
3805
0
#ifdef HAVE_FACCESSAT
3806
0
    if ((dir_fd != DEFAULT_DIR_FD) ||
3807
0
        effective_ids ||
3808
0
        !follow_symlinks) {
3809
3810
0
        if (HAVE_FACCESSAT_RUNTIME) {
3811
0
            int flags = 0;
3812
0
            if (!follow_symlinks)
3813
0
                flags |= AT_SYMLINK_NOFOLLOW;
3814
0
            if (effective_ids)
3815
0
                flags |= AT_EACCESS;
3816
0
            result = faccessat(dir_fd, path->narrow, mode, flags);
3817
0
        } else {
3818
0
            faccessat_unavailable = 1;
3819
0
        }
3820
0
    }
3821
0
    else
3822
0
#endif
3823
0
        result = access(path->narrow, mode);
3824
0
    Py_END_ALLOW_THREADS
3825
3826
0
#ifdef HAVE_FACCESSAT
3827
0
    if (faccessat_unavailable) {
3828
0
        if (dir_fd != DEFAULT_DIR_FD) {
3829
0
            argument_unavailable_error("access", "dir_fd");
3830
0
            return -1;
3831
0
        }
3832
0
        if (follow_symlinks_specified("access", follow_symlinks))
3833
0
            return -1;
3834
3835
0
        if (effective_ids) {
3836
0
            argument_unavailable_error("access", "effective_ids");
3837
0
            return -1;
3838
0
        }
3839
        /* should be unreachable */
3840
0
        return -1;
3841
0
    }
3842
0
#endif
3843
0
    return_value = !result;
3844
0
#endif
3845
3846
0
    return return_value;
3847
0
}
3848
3849
#ifndef F_OK
3850
#define F_OK 0
3851
#endif
3852
#ifndef R_OK
3853
#define R_OK 4
3854
#endif
3855
#ifndef W_OK
3856
#define W_OK 2
3857
#endif
3858
#ifndef X_OK
3859
#define X_OK 1
3860
#endif
3861
3862
3863
#ifdef HAVE_TTYNAME_R
3864
/*[clinic input]
3865
os.ttyname
3866
3867
    fd: int
3868
        Integer file descriptor handle.
3869
3870
    /
3871
3872
Return the name of the terminal device connected to 'fd'.
3873
[clinic start generated code]*/
3874
3875
static PyObject *
3876
os_ttyname_impl(PyObject *module, int fd)
3877
/*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3878
0
{
3879
3880
0
    long size = sysconf(_SC_TTY_NAME_MAX);
3881
0
    if (size == -1) {
3882
0
        return posix_error();
3883
0
    }
3884
0
    char *buffer = (char *)PyMem_RawMalloc(size);
3885
0
    if (buffer == NULL) {
3886
0
        return PyErr_NoMemory();
3887
0
    }
3888
0
    int ret = ttyname_r(fd, buffer, size);
3889
0
    if (ret != 0) {
3890
0
        PyMem_RawFree(buffer);
3891
0
        errno = ret;
3892
0
        return posix_error();
3893
0
    }
3894
0
    PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3895
0
    PyMem_RawFree(buffer);
3896
0
    return res;
3897
0
}
3898
#endif
3899
3900
#ifdef HAVE_CTERMID
3901
/*[clinic input]
3902
os.ctermid
3903
3904
Return the name of the controlling terminal for this process.
3905
[clinic start generated code]*/
3906
3907
static PyObject *
3908
os_ctermid_impl(PyObject *module)
3909
/*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3910
0
{
3911
0
    char *ret;
3912
0
    char buffer[L_ctermid];
3913
3914
#ifdef USE_CTERMID_R
3915
    ret = ctermid_r(buffer);
3916
#else
3917
0
    ret = ctermid(buffer);
3918
0
#endif
3919
0
    if (ret == NULL)
3920
0
        return posix_error();
3921
0
    return PyUnicode_DecodeFSDefault(buffer);
3922
0
}
3923
#endif /* HAVE_CTERMID */
3924
3925
3926
/*[clinic input]
3927
os.chdir
3928
3929
    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3930
3931
Change the current working directory to the specified path.
3932
3933
path may always be specified as a string.  On some platforms, path may
3934
also be specified as an open file descriptor.  If this functionality is
3935
unavailable, using it raises an exception.
3936
[clinic start generated code]*/
3937
3938
static PyObject *
3939
os_chdir_impl(PyObject *module, path_t *path)
3940
/*[clinic end generated code: output=3be6400eee26eaae input=64673c342e4369f1]*/
3941
0
{
3942
0
    int result;
3943
3944
0
    if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3945
0
        return NULL;
3946
0
    }
3947
3948
0
    Py_BEGIN_ALLOW_THREADS
3949
#ifdef MS_WINDOWS
3950
    /* on unix, success = 0, on windows, success = !0 */
3951
    result = !win32_wchdir(path->wide);
3952
#else
3953
0
#ifdef HAVE_FCHDIR
3954
0
    if (path->is_fd)
3955
0
        result = fchdir(path->fd);
3956
0
    else
3957
0
#endif
3958
0
        result = chdir(path->narrow);
3959
0
#endif
3960
0
    Py_END_ALLOW_THREADS
3961
3962
0
    if (result) {
3963
0
        return path_error(path);
3964
0
    }
3965
3966
0
    Py_RETURN_NONE;
3967
0
}
3968
3969
3970
#ifdef HAVE_FCHDIR
3971
/*[clinic input]
3972
os.fchdir
3973
3974
    fd: fildes
3975
3976
Change to the directory of the given file descriptor.
3977
3978
fd must be opened on a directory, not a file.
3979
Equivalent to os.chdir(fd).
3980
3981
[clinic start generated code]*/
3982
3983
static PyObject *
3984
os_fchdir_impl(PyObject *module, int fd)
3985
/*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3986
0
{
3987
0
    if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3988
0
        return NULL;
3989
0
    }
3990
0
    return posix_fildes_fd(fd, fchdir);
3991
0
}
3992
#endif /* HAVE_FCHDIR */
3993
3994
#ifdef MS_WINDOWS
3995
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 0
3996
#else
3997
0
# define CHMOD_DEFAULT_FOLLOW_SYMLINKS 1
3998
#endif
3999
4000
#ifdef MS_WINDOWS
4001
static int
4002
win32_lchmod(LPCWSTR path, int mode)
4003
{
4004
    DWORD attr = GetFileAttributesW(path);
4005
    if (attr == INVALID_FILE_ATTRIBUTES) {
4006
        return 0;
4007
    }
4008
    if (mode & _S_IWRITE) {
4009
        attr &= ~FILE_ATTRIBUTE_READONLY;
4010
    }
4011
    else {
4012
        attr |= FILE_ATTRIBUTE_READONLY;
4013
    }
4014
    return SetFileAttributesW(path, attr);
4015
}
4016
4017
static int
4018
win32_hchmod(HANDLE hfile, int mode)
4019
{
4020
    FILE_BASIC_INFO info;
4021
    if (!GetFileInformationByHandleEx(hfile, FileBasicInfo,
4022
                                      &info, sizeof(info)))
4023
    {
4024
        return 0;
4025
    }
4026
    if (mode & _S_IWRITE) {
4027
        info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
4028
    }
4029
    else {
4030
        info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
4031
    }
4032
    return SetFileInformationByHandle(hfile, FileBasicInfo,
4033
                                      &info, sizeof(info));
4034
}
4035
4036
static int
4037
win32_fchmod(int fd, int mode)
4038
{
4039
    HANDLE hfile = _Py_get_osfhandle_noraise(fd);
4040
    if (hfile == INVALID_HANDLE_VALUE) {
4041
        SetLastError(ERROR_INVALID_HANDLE);
4042
        return 0;
4043
    }
4044
    return win32_hchmod(hfile, mode);
4045
}
4046
4047
#endif /* MS_WINDOWS */
4048
4049
/*[clinic input]
4050
os.chmod
4051
4052
    path: path_t(allow_fd='PATH_HAVE_FCHMOD')
4053
        Path to be modified.  May always be specified as a str, bytes, or
4054
        a path-like object.  On some platforms, path may also be specified
4055
        as an open file descriptor.  If this functionality is unavailable,
4056
        using it raises an exception.
4057
4058
    mode: int
4059
        Operating-system mode bitfield.
4060
        Be careful when using number literals for *mode*. The conventional
4061
        UNIX notation for numeric modes uses an octal base, which needs to
4062
        be indicated with a ``0o`` prefix in Python.
4063
4064
    *
4065
4066
    dir_fd : dir_fd(requires='fchmodat') = None
4067
        If not None, it should be a file descriptor open to a directory,
4068
        and path should be relative; path will then be relative to that
4069
        directory.
4070
4071
    follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \
4072
                          py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS
4073
        If False, and the last element of the path is a symbolic link,
4074
        chmod will modify the symbolic link itself instead of the file
4075
        the link points to.
4076
4077
Change the access permissions of a file.
4078
4079
It is an error to use dir_fd or follow_symlinks when specifying path as
4080
  an open file descriptor.
4081
dir_fd and follow_symlinks may not be implemented on your platform.
4082
  If they are unavailable, using them will raise a NotImplementedError.
4083
4084
[clinic start generated code]*/
4085
4086
static PyObject *
4087
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
4088
              int follow_symlinks)
4089
/*[clinic end generated code: output=5cf6a94915cc7bff input=7b6e2eeadd8bf199]*/
4090
0
{
4091
0
    int result;
4092
4093
0
#ifdef HAVE_FCHMODAT
4094
0
    int fchmodat_nofollow_unsupported = 0;
4095
0
    int fchmodat_unsupported = 0;
4096
0
#endif
4097
4098
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD) || defined(MS_WINDOWS))
4099
    if (follow_symlinks_specified("chmod", follow_symlinks))
4100
        return NULL;
4101
#endif
4102
4103
0
    if (PySys_Audit("os.chmod", "Oii", path->object, mode,
4104
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4105
0
        return NULL;
4106
0
    }
4107
4108
#ifdef MS_WINDOWS
4109
    result = 0;
4110
    Py_BEGIN_ALLOW_THREADS
4111
    if (path->is_fd) {
4112
        result = win32_fchmod(path->fd, mode);
4113
    }
4114
    else if (follow_symlinks) {
4115
        HANDLE hfile = CreateFileW(path->wide,
4116
                                   FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
4117
                                   0, NULL,
4118
                                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
4119
        if (hfile != INVALID_HANDLE_VALUE) {
4120
            result = win32_hchmod(hfile, mode);
4121
            (void)CloseHandle(hfile);
4122
        }
4123
    }
4124
    else {
4125
        result = win32_lchmod(path->wide, mode);
4126
    }
4127
    Py_END_ALLOW_THREADS
4128
    if (!result) {
4129
        return path_error(path);
4130
    }
4131
#else /* MS_WINDOWS */
4132
0
    Py_BEGIN_ALLOW_THREADS
4133
0
#ifdef HAVE_FCHMOD
4134
0
    if (path->is_fd) {
4135
0
        result = fchmod(path->fd, mode);
4136
0
    }
4137
0
    else
4138
0
#endif /* HAVE_CHMOD */
4139
#ifdef HAVE_LCHMOD
4140
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4141
        result = lchmod(path->narrow, mode);
4142
    else
4143
#endif /* HAVE_LCHMOD */
4144
0
#ifdef HAVE_FCHMODAT
4145
0
    if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
4146
0
        if (HAVE_FCHMODAT_RUNTIME) {
4147
            /*
4148
             * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
4149
             * The documentation specifically shows how to use it,
4150
             * and then says it isn't implemented yet.
4151
             * (true on linux with glibc 2.15, and openindiana 3.x)
4152
             *
4153
             * Once it is supported, os.chmod will automatically
4154
             * support dir_fd and follow_symlinks=False.  (Hopefully.)
4155
             * Until then, we need to be careful what exception we raise.
4156
             */
4157
0
            result = fchmodat(dir_fd, path->narrow, mode,
4158
0
                              follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4159
            /*
4160
             * But wait!  We can't throw the exception without allowing threads,
4161
             * and we can't do that in this nested scope.  (Macro trickery, sigh.)
4162
             */
4163
0
            fchmodat_nofollow_unsupported =
4164
0
                             result &&
4165
0
                             ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
4166
0
                             !follow_symlinks;
4167
0
        } else {
4168
0
            fchmodat_unsupported = 1;
4169
0
            fchmodat_nofollow_unsupported = 1;
4170
4171
0
            result = -1;
4172
0
        }
4173
0
    }
4174
0
    else
4175
0
#endif /* HAVE_FHCMODAT */
4176
0
    {
4177
0
#ifdef HAVE_CHMOD
4178
0
        result = chmod(path->narrow, mode);
4179
#elif defined(__wasi__)
4180
        // WASI SDK 15.0 does not support chmod.
4181
        // Ignore missing syscall for now.
4182
        result = 0;
4183
#else
4184
        result = -1;
4185
        errno = ENOSYS;
4186
#endif
4187
0
    }
4188
0
    Py_END_ALLOW_THREADS
4189
4190
0
    if (result) {
4191
0
#ifdef HAVE_FCHMODAT
4192
0
        if (fchmodat_unsupported) {
4193
0
            if (dir_fd != DEFAULT_DIR_FD) {
4194
0
                argument_unavailable_error("chmod", "dir_fd");
4195
0
                return NULL;
4196
0
            }
4197
0
        }
4198
4199
0
        if (fchmodat_nofollow_unsupported) {
4200
0
            if (dir_fd != DEFAULT_DIR_FD)
4201
0
                dir_fd_and_follow_symlinks_invalid("chmod",
4202
0
                                                   dir_fd, follow_symlinks);
4203
0
            else
4204
0
                follow_symlinks_specified("chmod", follow_symlinks);
4205
0
            return NULL;
4206
0
        }
4207
0
        else
4208
0
#endif /* HAVE_FCHMODAT */
4209
0
        return path_error(path);
4210
0
    }
4211
0
#endif /* MS_WINDOWS */
4212
4213
0
    Py_RETURN_NONE;
4214
0
}
4215
4216
4217
#if defined(HAVE_FCHMOD) || defined(MS_WINDOWS)
4218
/*[clinic input]
4219
os.fchmod
4220
4221
    fd: int
4222
        The file descriptor of the file to be modified.
4223
    mode: int
4224
        Operating-system mode bitfield.
4225
        Be careful when using number literals for *mode*.  The conventional
4226
        UNIX notation for numeric modes uses an octal base, which needs to
4227
        be indicated with a ``0o`` prefix in Python.
4228
4229
Change the access permissions of the file given by file descriptor fd.
4230
4231
Equivalent to os.chmod(fd, mode).
4232
[clinic start generated code]*/
4233
4234
static PyObject *
4235
os_fchmod_impl(PyObject *module, int fd, int mode)
4236
/*[clinic end generated code: output=afd9bc05b4e426b3 input=d24331f9fdc17f49]*/
4237
0
{
4238
0
    int res;
4239
4240
0
    if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
4241
0
        return NULL;
4242
0
    }
4243
4244
#ifdef MS_WINDOWS
4245
    res = 0;
4246
    Py_BEGIN_ALLOW_THREADS
4247
    res = win32_fchmod(fd, mode);
4248
    Py_END_ALLOW_THREADS
4249
    if (!res) {
4250
        return PyErr_SetFromWindowsErr(0);
4251
    }
4252
#else /* MS_WINDOWS */
4253
0
    int async_err = 0;
4254
0
    do {
4255
0
        Py_BEGIN_ALLOW_THREADS
4256
0
        res = fchmod(fd, mode);
4257
0
        Py_END_ALLOW_THREADS
4258
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4259
0
    if (res != 0)
4260
0
        return (!async_err) ? posix_error() : NULL;
4261
0
#endif /* MS_WINDOWS */
4262
4263
0
    Py_RETURN_NONE;
4264
0
}
4265
#endif /* HAVE_FCHMOD || MS_WINDOWS */
4266
4267
4268
#if defined(HAVE_LCHMOD) || defined(MS_WINDOWS)
4269
/*[clinic input]
4270
@permit_long_summary
4271
os.lchmod
4272
4273
    path: path_t
4274
    mode: int
4275
4276
Change the access permissions of a file, without following symbolic links.
4277
4278
If path is a symlink, this affects the link itself rather than the
4279
target.  Equivalent to chmod(path, mode, follow_symlinks=False).
4280
[clinic start generated code]*/
4281
4282
static PyObject *
4283
os_lchmod_impl(PyObject *module, path_t *path, int mode)
4284
/*[clinic end generated code: output=082344022b51a1d5 input=13110fb62911b015]*/
4285
{
4286
    int res;
4287
    if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
4288
        return NULL;
4289
    }
4290
#ifdef MS_WINDOWS
4291
    Py_BEGIN_ALLOW_THREADS
4292
    res = win32_lchmod(path->wide, mode);
4293
    Py_END_ALLOW_THREADS
4294
    if (!res) {
4295
        path_error(path);
4296
        return NULL;
4297
    }
4298
#else /* MS_WINDOWS */
4299
    Py_BEGIN_ALLOW_THREADS
4300
    res = lchmod(path->narrow, mode);
4301
    Py_END_ALLOW_THREADS
4302
    if (res < 0) {
4303
        path_error(path);
4304
        return NULL;
4305
    }
4306
#endif /* MS_WINDOWS */
4307
    Py_RETURN_NONE;
4308
}
4309
#endif /* HAVE_LCHMOD || MS_WINDOWS */
4310
4311
4312
#ifdef HAVE_CHFLAGS
4313
/*[clinic input]
4314
os.chflags
4315
4316
    path: path_t
4317
    flags: unsigned_long(bitwise=True)
4318
    follow_symlinks: bool=True
4319
4320
Set file flags.
4321
4322
If follow_symlinks is False, and the last element of the path is
4323
a symbolic link, chflags() will change flags on the symbolic link itself
4324
instead of the file the link points to.
4325
follow_symlinks may not be implemented on your platform.  If it is
4326
unavailable, using it will raise a NotImplementedError.
4327
4328
[clinic start generated code]*/
4329
4330
static PyObject *
4331
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
4332
                int follow_symlinks)
4333
/*[clinic end generated code: output=85571c6737661ce9 input=31391927707be1de]*/
4334
{
4335
    int result;
4336
4337
#ifndef HAVE_LCHFLAGS
4338
    if (follow_symlinks_specified("chflags", follow_symlinks))
4339
        return NULL;
4340
#endif
4341
4342
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4343
        return NULL;
4344
    }
4345
4346
    Py_BEGIN_ALLOW_THREADS
4347
#ifdef HAVE_LCHFLAGS
4348
    if (!follow_symlinks)
4349
        result = lchflags(path->narrow, flags);
4350
    else
4351
#endif
4352
        result = chflags(path->narrow, flags);
4353
    Py_END_ALLOW_THREADS
4354
4355
    if (result)
4356
        return path_error(path);
4357
4358
    Py_RETURN_NONE;
4359
}
4360
#endif /* HAVE_CHFLAGS */
4361
4362
4363
#ifdef HAVE_LCHFLAGS
4364
/*[clinic input]
4365
os.lchflags
4366
4367
    path: path_t
4368
    flags: unsigned_long(bitwise=True)
4369
4370
Set file flags.
4371
4372
This function will not follow symbolic links.
4373
Equivalent to chflags(path, flags, follow_symlinks=False).
4374
[clinic start generated code]*/
4375
4376
static PyObject *
4377
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
4378
/*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
4379
{
4380
    int res;
4381
    if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
4382
        return NULL;
4383
    }
4384
    Py_BEGIN_ALLOW_THREADS
4385
    res = lchflags(path->narrow, flags);
4386
    Py_END_ALLOW_THREADS
4387
    if (res < 0) {
4388
        return path_error(path);
4389
    }
4390
    Py_RETURN_NONE;
4391
}
4392
#endif /* HAVE_LCHFLAGS */
4393
4394
4395
#ifdef HAVE_CHROOT
4396
/*[clinic input]
4397
os.chroot
4398
    path: path_t
4399
4400
Change root directory to path.
4401
4402
[clinic start generated code]*/
4403
4404
static PyObject *
4405
os_chroot_impl(PyObject *module, path_t *path)
4406
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
4407
0
{
4408
#ifdef __ANDROID__
4409
    // On Android, calling this function as a non-root user leads to a process crash
4410
    // rather than returning a permission error.
4411
    if (getuid() != 0) {
4412
        errno = EPERM;
4413
        return path_error(path);
4414
    }
4415
#endif
4416
0
    int res;
4417
0
    Py_BEGIN_ALLOW_THREADS
4418
0
    res = chroot(path->narrow);
4419
0
    Py_END_ALLOW_THREADS
4420
0
    if (res < 0)
4421
0
        return path_error(path);
4422
0
    Py_RETURN_NONE;
4423
0
}
4424
#endif /* HAVE_CHROOT */
4425
4426
4427
#ifdef HAVE_FSYNC
4428
/*[clinic input]
4429
os.fsync
4430
4431
    fd: fildes
4432
4433
Force write of fd to disk.
4434
[clinic start generated code]*/
4435
4436
static PyObject *
4437
os_fsync_impl(PyObject *module, int fd)
4438
/*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
4439
0
{
4440
0
    return posix_fildes_fd(fd, fsync);
4441
0
}
4442
#endif /* HAVE_FSYNC */
4443
4444
4445
#ifdef HAVE_SYNC
4446
/*[clinic input]
4447
os.sync
4448
4449
Force write of everything to disk.
4450
[clinic start generated code]*/
4451
4452
static PyObject *
4453
os_sync_impl(PyObject *module)
4454
/*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
4455
0
{
4456
0
    Py_BEGIN_ALLOW_THREADS
4457
0
    sync();
4458
0
    Py_END_ALLOW_THREADS
4459
0
    Py_RETURN_NONE;
4460
0
}
4461
#endif /* HAVE_SYNC */
4462
4463
4464
#ifdef HAVE_FDATASYNC
4465
#ifdef __hpux
4466
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
4467
#endif
4468
4469
/*[clinic input]
4470
os.fdatasync
4471
4472
    fd: fildes
4473
4474
Force write of fd to disk without forcing update of metadata.
4475
[clinic start generated code]*/
4476
4477
static PyObject *
4478
os_fdatasync_impl(PyObject *module, int fd)
4479
/*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
4480
0
{
4481
0
    return posix_fildes_fd(fd, fdatasync);
4482
0
}
4483
#endif /* HAVE_FDATASYNC */
4484
4485
4486
#ifdef HAVE_CHOWN
4487
/*[clinic input]
4488
os.chown
4489
4490
    path : path_t(allow_fd='PATH_HAVE_FCHOWN')
4491
        Path to be examined; can be string, bytes, a path-like object, or
4492
        open-file-descriptor int.
4493
4494
    uid: uid_t
4495
4496
    gid: gid_t
4497
4498
    *
4499
4500
    dir_fd: dir_fd(requires='fchownat') = None
4501
        If not None, it should be a file descriptor open to a directory,
4502
        and path should be relative; path will then be relative to that
4503
        directory.
4504
4505
    follow_symlinks: bool = True
4506
        If False, and the last element of the path is a symbolic link,
4507
        stat will examine the symbolic link itself instead of the file
4508
        the link points to.
4509
4510
Change the owner and group id of path to the numeric uid and gid.
4511
4512
path may always be specified as a string.  On some platforms, path may
4513
also be specified as an open file descriptor.  If this functionality is
4514
unavailable, using it raises an exception.
4515
If dir_fd is not None, it should be a file descriptor open to
4516
a directory, and path should be relative; path will then be relative to
4517
that directory.
4518
If follow_symlinks is False, and the last element of the path is
4519
a symbolic link, chown will modify the symbolic link itself instead of
4520
the file the link points to.
4521
It is an error to use dir_fd or follow_symlinks when specifying path as
4522
an open file descriptor.
4523
dir_fd and follow_symlinks may not be implemented on your platform.  If
4524
they are unavailable, using them will raise a NotImplementedError.
4525
4526
[clinic start generated code]*/
4527
4528
static PyObject *
4529
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
4530
              int dir_fd, int follow_symlinks)
4531
/*[clinic end generated code: output=4beadab0db5f70cd input=509c91b7a0e72f52]*/
4532
0
{
4533
0
    int result;
4534
4535
0
#if defined(HAVE_FCHOWNAT)
4536
0
    int fchownat_unsupported = 0;
4537
0
#endif
4538
4539
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
4540
    if (follow_symlinks_specified("chown", follow_symlinks))
4541
        return NULL;
4542
#endif
4543
0
    if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
4544
0
        fd_and_follow_symlinks_invalid("chown", path->is_fd, follow_symlinks))
4545
0
        return NULL;
4546
4547
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
4548
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4549
0
        return NULL;
4550
0
    }
4551
4552
0
    Py_BEGIN_ALLOW_THREADS
4553
0
#ifdef HAVE_FCHOWN
4554
0
    if (path->is_fd)
4555
0
        result = fchown(path->fd, uid, gid);
4556
0
    else
4557
0
#endif
4558
0
#ifdef HAVE_LCHOWN
4559
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4560
0
        result = lchown(path->narrow, uid, gid);
4561
0
    else
4562
0
#endif
4563
0
#ifdef HAVE_FCHOWNAT
4564
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
4565
0
      if (HAVE_FCHOWNAT_RUNTIME) {
4566
0
        result = fchownat(dir_fd, path->narrow, uid, gid,
4567
0
                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
4568
0
      } else {
4569
0
         fchownat_unsupported = 1;
4570
0
      }
4571
0
    } else
4572
0
#endif
4573
0
        result = chown(path->narrow, uid, gid);
4574
0
    Py_END_ALLOW_THREADS
4575
4576
0
#ifdef HAVE_FCHOWNAT
4577
0
    if (fchownat_unsupported) {
4578
        /* This would be incorrect if the current platform
4579
         * doesn't support lchown.
4580
         */
4581
0
        argument_unavailable_error(NULL, "dir_fd");
4582
0
        return NULL;
4583
0
    }
4584
0
#endif
4585
4586
0
    if (result)
4587
0
        return path_error(path);
4588
4589
0
    Py_RETURN_NONE;
4590
0
}
4591
#endif /* HAVE_CHOWN */
4592
4593
4594
#ifdef HAVE_FCHOWN
4595
/*[clinic input]
4596
os.fchown
4597
4598
    fd: int
4599
    uid: uid_t
4600
    gid: gid_t
4601
4602
Change the owner and group id of the file specified by file descriptor.
4603
4604
Equivalent to os.chown(fd, uid, gid).
4605
4606
[clinic start generated code]*/
4607
4608
static PyObject *
4609
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
4610
/*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
4611
0
{
4612
0
    int res;
4613
0
    int async_err = 0;
4614
4615
0
    if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
4616
0
        return NULL;
4617
0
    }
4618
4619
0
    do {
4620
0
        Py_BEGIN_ALLOW_THREADS
4621
0
        res = fchown(fd, uid, gid);
4622
0
        Py_END_ALLOW_THREADS
4623
0
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
4624
0
    if (res != 0)
4625
0
        return (!async_err) ? posix_error() : NULL;
4626
4627
0
    Py_RETURN_NONE;
4628
0
}
4629
#endif /* HAVE_FCHOWN */
4630
4631
4632
#ifdef HAVE_LCHOWN
4633
/*[clinic input]
4634
os.lchown
4635
4636
    path : path_t
4637
    uid: uid_t
4638
    gid: gid_t
4639
4640
Change the owner and group id of path to the numeric uid and gid.
4641
4642
This function will not follow symbolic links.
4643
Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
4644
[clinic start generated code]*/
4645
4646
static PyObject *
4647
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
4648
/*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
4649
0
{
4650
0
    int res;
4651
0
    if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
4652
0
        return NULL;
4653
0
    }
4654
0
    Py_BEGIN_ALLOW_THREADS
4655
0
    res = lchown(path->narrow, uid, gid);
4656
0
    Py_END_ALLOW_THREADS
4657
0
    if (res < 0) {
4658
0
        return path_error(path);
4659
0
    }
4660
0
    Py_RETURN_NONE;
4661
0
}
4662
#endif /* HAVE_LCHOWN */
4663
4664
4665
static PyObject *
4666
posix_getcwd(int use_bytes)
4667
8
{
4668
#ifdef MS_WINDOWS
4669
    wchar_t wbuf[MAXPATHLEN];
4670
    wchar_t *wbuf2 = wbuf;
4671
    DWORD len;
4672
4673
    Py_BEGIN_ALLOW_THREADS
4674
    len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
4675
    /* If the buffer is large enough, len does not include the
4676
       terminating \0. If the buffer is too small, len includes
4677
       the space needed for the terminator. */
4678
    if (len >= Py_ARRAY_LENGTH(wbuf)) {
4679
        if ((Py_ssize_t)len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4680
            wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
4681
        }
4682
        else {
4683
            wbuf2 = NULL;
4684
        }
4685
        if (wbuf2) {
4686
            len = GetCurrentDirectoryW(len, wbuf2);
4687
        }
4688
    }
4689
    Py_END_ALLOW_THREADS
4690
4691
    if (!wbuf2) {
4692
        PyErr_NoMemory();
4693
        return NULL;
4694
    }
4695
    if (!len) {
4696
        PyErr_SetFromWindowsErr(0);
4697
        if (wbuf2 != wbuf)
4698
            PyMem_RawFree(wbuf2);
4699
        return NULL;
4700
    }
4701
4702
    PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
4703
    if (wbuf2 != wbuf) {
4704
        PyMem_RawFree(wbuf2);
4705
    }
4706
4707
    if (use_bytes) {
4708
        if (resobj == NULL) {
4709
            return NULL;
4710
        }
4711
        Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
4712
    }
4713
4714
    return resobj;
4715
#else
4716
8
    const size_t chunk = 1024;
4717
4718
8
    char *buf = NULL;
4719
8
    char *cwd = NULL;
4720
8
    size_t buflen = 0;
4721
4722
8
    Py_BEGIN_ALLOW_THREADS
4723
8
    do {
4724
8
        char *newbuf;
4725
8
        if (buflen <= PY_SSIZE_T_MAX - chunk) {
4726
8
            buflen += chunk;
4727
8
            newbuf = PyMem_RawRealloc(buf, buflen);
4728
8
        }
4729
0
        else {
4730
0
            newbuf = NULL;
4731
0
        }
4732
8
        if (newbuf == NULL) {
4733
0
            PyMem_RawFree(buf);
4734
0
            buf = NULL;
4735
0
            break;
4736
0
        }
4737
8
        buf = newbuf;
4738
4739
8
        cwd = getcwd(buf, buflen);
4740
8
    } while (cwd == NULL && errno == ERANGE);
4741
8
    Py_END_ALLOW_THREADS
4742
4743
8
    if (buf == NULL) {
4744
0
        return PyErr_NoMemory();
4745
0
    }
4746
8
    if (cwd == NULL) {
4747
0
        posix_error();
4748
0
        PyMem_RawFree(buf);
4749
0
        return NULL;
4750
0
    }
4751
4752
8
    PyObject *obj;
4753
8
    if (use_bytes) {
4754
0
        obj = PyBytes_FromStringAndSize(buf, strlen(buf));
4755
0
    }
4756
8
    else {
4757
8
        obj = PyUnicode_DecodeFSDefault(buf);
4758
8
    }
4759
8
#ifdef __linux__
4760
8
    if (buf[0] != '/') {
4761
        /*
4762
         * On Linux >= 2.6.36 with glibc < 2.27, getcwd() can return a
4763
         * relative pathname starting with '(unreachable)'. We detect this
4764
         * and fail with ENOENT, matching newer glibc behaviour.
4765
         */
4766
0
        errno = ENOENT;
4767
0
        path_object_error(obj);
4768
0
        PyMem_RawFree(buf);
4769
0
        return NULL;
4770
0
    }
4771
8
#endif
4772
8
    assert(buf[0] == '/');
4773
8
    PyMem_RawFree(buf);
4774
4775
8
    return obj;
4776
8
#endif   /* !MS_WINDOWS */
4777
8
}
4778
4779
4780
/*[clinic input]
4781
os.getcwd
4782
4783
Return a unicode string representing the current working directory.
4784
[clinic start generated code]*/
4785
4786
static PyObject *
4787
os_getcwd_impl(PyObject *module)
4788
/*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
4789
8
{
4790
8
    return posix_getcwd(0);
4791
8
}
4792
4793
4794
/*[clinic input]
4795
os.getcwdb
4796
4797
Return a bytes string representing the current working directory.
4798
[clinic start generated code]*/
4799
4800
static PyObject *
4801
os_getcwdb_impl(PyObject *module)
4802
/*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
4803
0
{
4804
0
    return posix_getcwd(1);
4805
0
}
4806
4807
4808
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
4809
#define HAVE_LINK 1
4810
#endif
4811
4812
#ifdef HAVE_LINK
4813
/*[clinic input]
4814
4815
os.link
4816
4817
    src : path_t
4818
    dst : path_t
4819
    *
4820
    src_dir_fd : dir_fd = None
4821
    dst_dir_fd : dir_fd = None
4822
    follow_symlinks: bool(c_default="-1", py_default="(os.name != 'nt')") = PLACEHOLDER
4823
4824
Create a hard link to a file.
4825
4826
If either src_dir_fd or dst_dir_fd is not None, it should be a file
4827
descriptor open to a directory, and the respective path string (src or
4828
dst) should be relative; the path will then be relative to that
4829
directory.
4830
If follow_symlinks is False, and the last element of src is a symbolic
4831
link, link will create a link to the symbolic link itself instead of the
4832
file the link points to.
4833
src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on
4834
your platform.  If they are unavailable, using them will raise
4835
a NotImplementedError.
4836
[clinic start generated code]*/
4837
4838
static PyObject *
4839
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4840
             int dst_dir_fd, int follow_symlinks)
4841
/*[clinic end generated code: output=7f00f6007fd5269a input=a28e6866fbd20a01]*/
4842
0
{
4843
#ifdef MS_WINDOWS
4844
    BOOL result = FALSE;
4845
#else
4846
0
    int result;
4847
0
#endif
4848
4849
0
#ifdef HAVE_LINKAT
4850
0
    if (HAVE_LINKAT_RUNTIME) {
4851
0
        if (follow_symlinks < 0) {
4852
0
            follow_symlinks = 1;
4853
0
        }
4854
0
    }
4855
0
    else
4856
0
#endif
4857
0
    {
4858
0
        if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
4859
0
            argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
4860
0
            return NULL;
4861
0
        }
4862
/* See issue 85527: link() on Linux works like linkat without AT_SYMLINK_FOLLOW,
4863
   but on Mac it works like linkat *with* AT_SYMLINK_FOLLOW. */
4864
0
#if defined(MS_WINDOWS) || defined(__linux__)
4865
0
        if (follow_symlinks == 1) {
4866
0
            argument_unavailable_error("link", "follow_symlinks=True");
4867
0
            return NULL;
4868
0
        }
4869
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || (defined(__sun) && defined(__SVR4))
4870
        if (follow_symlinks == 0) {
4871
            argument_unavailable_error("link", "follow_symlinks=False");
4872
            return NULL;
4873
        }
4874
#else
4875
        if (follow_symlinks >= 0) {
4876
            argument_unavailable_error("link", "follow_symlinks");
4877
            return NULL;
4878
        }
4879
#endif
4880
0
    }
4881
4882
0
    if (PySys_Audit("os.link", "OOii", src->object, dst->object,
4883
0
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4884
0
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4885
0
        return NULL;
4886
0
    }
4887
4888
#ifdef MS_WINDOWS
4889
    Py_BEGIN_ALLOW_THREADS
4890
    result = CreateHardLinkW(dst->wide, src->wide, NULL);
4891
    Py_END_ALLOW_THREADS
4892
4893
    if (!result)
4894
        return path_error2(src, dst);
4895
#else
4896
0
    Py_BEGIN_ALLOW_THREADS
4897
0
#ifdef HAVE_LINKAT
4898
0
    if (HAVE_LINKAT_RUNTIME) {
4899
0
        result = linkat(src_dir_fd, src->narrow,
4900
0
            dst_dir_fd, dst->narrow,
4901
0
            follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
4902
0
    }
4903
0
    else
4904
0
#endif
4905
0
    {
4906
        /* linkat not available */
4907
0
        result = link(src->narrow, dst->narrow);
4908
0
    }
4909
0
    Py_END_ALLOW_THREADS
4910
4911
0
    if (result)
4912
0
        return path_error2(src, dst);
4913
0
#endif /* MS_WINDOWS */
4914
4915
0
    Py_RETURN_NONE;
4916
0
}
4917
#endif
4918
4919
4920
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4921
static wchar_t *
4922
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename,
4923
                    int normalize);
4924
4925
static PyObject *
4926
_listdir_windows_no_opendir(path_t *path, PyObject *list)
4927
{
4928
    PyObject *v;
4929
    HANDLE hFindFile = INVALID_HANDLE_VALUE;
4930
    BOOL result, return_bytes;
4931
    wchar_t *wnamebuf = NULL;
4932
4933
    WIN32_FIND_DATAW wFileData;
4934
    const wchar_t *po_wchars;
4935
4936
    if (!path->wide) { /* Default arg: "." */
4937
        po_wchars = L".";
4938
        return_bytes = 0;
4939
    } else {
4940
        po_wchars = path->wide;
4941
        return_bytes = PyBytes_Check(path->object);
4942
    }
4943
4944
    wnamebuf = join_path_filenameW(po_wchars, L"*.*", 1);
4945
    if (wnamebuf == NULL) {
4946
        goto exit;
4947
    }
4948
4949
    if ((list = PyList_New(0)) == NULL) {
4950
        goto exit;
4951
    }
4952
    Py_BEGIN_ALLOW_THREADS
4953
    hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4954
    Py_END_ALLOW_THREADS
4955
    if (hFindFile == INVALID_HANDLE_VALUE) {
4956
        int error = GetLastError();
4957
        if (error == ERROR_FILE_NOT_FOUND)
4958
            goto exit;
4959
        path_error(path);
4960
        Py_CLEAR(list);
4961
        goto exit;
4962
    }
4963
    do {
4964
        /* Skip over . and .. */
4965
        if (wcscmp(wFileData.cFileName, L".") != 0 &&
4966
            wcscmp(wFileData.cFileName, L"..") != 0) {
4967
            v = PyUnicode_FromWideChar(wFileData.cFileName,
4968
                                       wcslen(wFileData.cFileName));
4969
            if (return_bytes && v) {
4970
                Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4971
            }
4972
            if (v == NULL) {
4973
                Py_CLEAR(list);
4974
                break;
4975
            }
4976
            if (PyList_Append(list, v) != 0) {
4977
                Py_DECREF(v);
4978
                Py_CLEAR(list);
4979
                break;
4980
            }
4981
            Py_DECREF(v);
4982
        }
4983
        Py_BEGIN_ALLOW_THREADS
4984
        result = FindNextFileW(hFindFile, &wFileData);
4985
        Py_END_ALLOW_THREADS
4986
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4987
           it got to the end of the directory. */
4988
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4989
            path_error(path);
4990
            Py_CLEAR(list);
4991
            goto exit;
4992
        }
4993
    } while (result == TRUE);
4994
4995
exit:
4996
    if (hFindFile != INVALID_HANDLE_VALUE) {
4997
        if (FindClose(hFindFile) == FALSE) {
4998
            if (list != NULL) {
4999
                path_error(path);
5000
                Py_CLEAR(list);
5001
            }
5002
        }
5003
    }
5004
    PyMem_Free(wnamebuf);
5005
5006
    return list;
5007
}  /* end of _listdir_windows_no_opendir */
5008
5009
#else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
5010
5011
static PyObject *
5012
_posix_listdir(path_t *path, PyObject *list)
5013
407
{
5014
407
    PyObject *v;
5015
407
    DIR *dirp = NULL;
5016
407
    struct dirent *ep;
5017
407
    int return_str; /* if false, return bytes */
5018
407
#ifdef HAVE_FDOPENDIR
5019
407
    int fd = -1;
5020
407
#endif
5021
5022
407
    errno = 0;
5023
407
#ifdef HAVE_FDOPENDIR
5024
407
    if (path->is_fd) {
5025
0
      if (HAVE_FDOPENDIR_RUNTIME) {
5026
        /* closedir() closes the FD, so we duplicate it */
5027
0
        fd = _Py_dup(path->fd);
5028
0
        if (fd == -1)
5029
0
            return NULL;
5030
5031
0
        return_str = 1;
5032
5033
0
        Py_BEGIN_ALLOW_THREADS
5034
0
        dirp = fdopendir(fd);
5035
0
        Py_END_ALLOW_THREADS
5036
0
      } else {
5037
0
        PyErr_SetString(PyExc_TypeError,
5038
0
            "listdir: path should be string, bytes, os.PathLike or None, not int");
5039
0
        return NULL;
5040
0
      }
5041
0
    }
5042
407
    else
5043
407
#endif
5044
407
    {
5045
407
        const char *name;
5046
407
        if (path->narrow) {
5047
407
            name = path->narrow;
5048
            /* only return bytes if they specified a bytes object */
5049
407
            return_str = !PyBytes_Check(path->object);
5050
407
        }
5051
0
        else {
5052
0
            name = ".";
5053
0
            return_str = 1;
5054
0
        }
5055
5056
407
        Py_BEGIN_ALLOW_THREADS
5057
407
        dirp = opendir(name);
5058
407
        Py_END_ALLOW_THREADS
5059
407
    }
5060
5061
407
    if (dirp == NULL) {
5062
4
        path_error(path);
5063
4
        list = NULL;
5064
4
#ifdef HAVE_FDOPENDIR
5065
4
        if (fd != -1) {
5066
0
            Py_BEGIN_ALLOW_THREADS
5067
0
            close(fd);
5068
0
            Py_END_ALLOW_THREADS
5069
0
        }
5070
4
#endif
5071
4
        goto exit;
5072
4
    }
5073
403
    if ((list = PyList_New(0)) == NULL) {
5074
0
        goto exit;
5075
0
    }
5076
23.3k
    for (;;) {
5077
23.3k
        errno = 0;
5078
23.3k
        Py_BEGIN_ALLOW_THREADS
5079
23.3k
        ep = readdir(dirp);
5080
23.3k
        Py_END_ALLOW_THREADS
5081
23.3k
        if (ep == NULL) {
5082
403
            if (errno == 0) {
5083
403
                break;
5084
403
            } else {
5085
0
                path_error(path);
5086
0
                Py_CLEAR(list);
5087
0
                goto exit;
5088
0
            }
5089
403
        }
5090
22.9k
        if (ep->d_name[0] == '.' &&
5091
841
            (NAMLEN(ep) == 1 ||
5092
438
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
5093
806
            continue;
5094
22.1k
        if (return_str)
5095
22.1k
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
5096
0
        else
5097
0
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
5098
22.1k
        if (v == NULL) {
5099
0
            Py_CLEAR(list);
5100
0
            break;
5101
0
        }
5102
22.1k
        if (PyList_Append(list, v) != 0) {
5103
0
            Py_DECREF(v);
5104
0
            Py_CLEAR(list);
5105
0
            break;
5106
0
        }
5107
22.1k
        Py_DECREF(v);
5108
22.1k
    }
5109
5110
407
exit:
5111
407
    if (dirp != NULL) {
5112
403
        Py_BEGIN_ALLOW_THREADS
5113
403
#ifdef HAVE_FDOPENDIR
5114
403
        if (fd > -1)
5115
0
            rewinddir(dirp);
5116
403
#endif
5117
403
        closedir(dirp);
5118
403
        Py_END_ALLOW_THREADS
5119
403
    }
5120
5121
407
    return list;
5122
403
}  /* end of _posix_listdir */
5123
#endif  /* which OS */
5124
5125
5126
/*[clinic input]
5127
os.listdir
5128
5129
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
5130
5131
Return a list containing the names of the files in the directory.
5132
5133
path can be specified as either str, bytes, or a path-like object.  If
5134
path is bytes, the filenames returned will also be bytes; in all other
5135
circumstances the filenames returned will be str.
5136
If path is None, uses the path='.'.
5137
On some platforms, path may also be specified as an open file
5138
descriptor; the file descriptor must refer to a directory.  If this
5139
functionality is unavailable, using it raises NotImplementedError.
5140
5141
The list is in arbitrary order.  It does not include the special
5142
entries '.' and '..' even if they are present in the directory.
5143
5144
[clinic start generated code]*/
5145
5146
static PyObject *
5147
os_listdir_impl(PyObject *module, path_t *path)
5148
/*[clinic end generated code: output=293045673fcd1a75 input=4eefe7c6a42ec9b2]*/
5149
407
{
5150
407
    if (PySys_Audit("os.listdir", "O",
5151
407
                    path->object ? path->object : Py_None) < 0) {
5152
0
        return NULL;
5153
0
    }
5154
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
5155
    return _listdir_windows_no_opendir(path, NULL);
5156
#else
5157
407
    return _posix_listdir(path, NULL);
5158
407
#endif
5159
407
}
5160
5161
5162
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5163
5164
/*[clinic input]
5165
os.listdrives
5166
5167
Return a list containing the names of drives in the system.
5168
5169
A drive name typically looks like 'C:\\'.
5170
5171
[clinic start generated code]*/
5172
5173
static PyObject *
5174
os_listdrives_impl(PyObject *module)
5175
/*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/
5176
{
5177
    /* Number of possible drives is limited, so 256 should always be enough.
5178
       On the day when it is not, listmounts() will have to be used. */
5179
    wchar_t buffer[256];
5180
    DWORD buflen = Py_ARRAY_LENGTH(buffer);
5181
    PyObject *result = NULL;
5182
    if (PySys_Audit("os.listdrives", NULL) < 0) {
5183
        return NULL;
5184
    }
5185
5186
    Py_BEGIN_ALLOW_THREADS;
5187
    buflen = GetLogicalDriveStringsW(buflen, buffer);
5188
    Py_END_ALLOW_THREADS;
5189
5190
    if (!buflen) {
5191
        PyErr_SetFromWindowsErr(0);
5192
        return NULL;
5193
    } else if (buflen >= Py_ARRAY_LENGTH(buffer)) {
5194
        PyErr_SetFromWindowsErr(ERROR_MORE_DATA);
5195
        return NULL;
5196
    }
5197
5198
    /* buflen includes a null terminator, so remove it */
5199
    PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1);
5200
    if (str) {
5201
        PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1);
5202
        if (nullchar) {
5203
            result = PyUnicode_Split(str, nullchar, -1);
5204
            Py_DECREF(nullchar);
5205
        }
5206
        Py_DECREF(str);
5207
    }
5208
    return result;
5209
}
5210
5211
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5212
5213
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5214
5215
/*[clinic input]
5216
os.listvolumes
5217
5218
Return a list containing the volumes in the system.
5219
5220
Volumes are typically represented as a GUID path.
5221
5222
[clinic start generated code]*/
5223
5224
static PyObject *
5225
os_listvolumes_impl(PyObject *module)
5226
/*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/
5227
{
5228
    PyObject *result = PyList_New(0);
5229
    HANDLE find = INVALID_HANDLE_VALUE;
5230
    wchar_t buffer[MAX_PATH + 1];
5231
    if (!result) {
5232
        return NULL;
5233
    }
5234
    if (PySys_Audit("os.listvolumes", NULL) < 0) {
5235
        Py_DECREF(result);
5236
        return NULL;
5237
    }
5238
5239
    int err = 0;
5240
    Py_BEGIN_ALLOW_THREADS;
5241
    find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer));
5242
    if (find == INVALID_HANDLE_VALUE) {
5243
        err = GetLastError();
5244
    }
5245
    Py_END_ALLOW_THREADS;
5246
5247
    while (!err) {
5248
        PyObject *s = PyUnicode_FromWideChar(buffer, -1);
5249
        if (!s || PyList_Append(result, s) < 0) {
5250
            Py_XDECREF(s);
5251
            Py_CLEAR(result);
5252
            break;
5253
        }
5254
        Py_DECREF(s);
5255
5256
        Py_BEGIN_ALLOW_THREADS;
5257
        if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) {
5258
            err = GetLastError();
5259
        }
5260
        Py_END_ALLOW_THREADS;
5261
    }
5262
5263
    if (find != INVALID_HANDLE_VALUE) {
5264
        Py_BEGIN_ALLOW_THREADS;
5265
        FindVolumeClose(find);
5266
        Py_END_ALLOW_THREADS;
5267
    }
5268
    if (err && err != ERROR_NO_MORE_FILES) {
5269
        PyErr_SetFromWindowsErr(err);
5270
        Py_XDECREF(result);
5271
        result = NULL;
5272
    }
5273
    return result;
5274
}
5275
5276
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5277
5278
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
5279
5280
/*[clinic input]
5281
os.listmounts
5282
5283
    volume: path_t
5284
5285
Return a list containing mount points for a particular volume.
5286
5287
'volume' should be a GUID path as returned from os.listvolumes.
5288
5289
[clinic start generated code]*/
5290
5291
static PyObject *
5292
os_listmounts_impl(PyObject *module, path_t *volume)
5293
/*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/
5294
{
5295
    wchar_t default_buffer[MAX_PATH + 1];
5296
    DWORD buflen = Py_ARRAY_LENGTH(default_buffer);
5297
    LPWSTR buffer = default_buffer;
5298
    DWORD attributes;
5299
    PyObject *str = NULL;
5300
    PyObject *nullchar = NULL;
5301
    PyObject *result = NULL;
5302
5303
    /* Ensure we have a valid volume path before continuing */
5304
    Py_BEGIN_ALLOW_THREADS
5305
    attributes = GetFileAttributesW(volume->wide);
5306
    Py_END_ALLOW_THREADS
5307
    if (attributes == INVALID_FILE_ATTRIBUTES &&
5308
        GetLastError() == ERROR_UNRECOGNIZED_VOLUME)
5309
    {
5310
        return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME);
5311
    }
5312
5313
    if (PySys_Audit("os.listmounts", "O", volume->object) < 0) {
5314
        return NULL;
5315
    }
5316
5317
    while (1) {
5318
        BOOL success;
5319
        Py_BEGIN_ALLOW_THREADS
5320
        success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer,
5321
                                                   buflen, &buflen);
5322
        Py_END_ALLOW_THREADS
5323
        if (success) {
5324
            break;
5325
        }
5326
        if (GetLastError() != ERROR_MORE_DATA) {
5327
            PyErr_SetFromWindowsErr(0);
5328
            goto exit;
5329
        }
5330
        if (buffer != default_buffer) {
5331
            PyMem_Free((void *)buffer);
5332
        }
5333
        buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen);
5334
        if (!buffer) {
5335
            PyErr_NoMemory();
5336
            goto exit;
5337
        }
5338
    }
5339
    if (buflen < 2) {
5340
        result = PyList_New(0);
5341
        goto exit;
5342
    }
5343
    // buflen includes two null terminators, one for the last string
5344
    // and one for the array of strings.
5345
    str = PyUnicode_FromWideChar(buffer, buflen - 2);
5346
    nullchar = PyUnicode_FromStringAndSize("\0", 1);
5347
    if (str && nullchar) {
5348
        result = PyUnicode_Split(str, nullchar, -1);
5349
    }
5350
exit:
5351
    if (buffer != default_buffer) {
5352
        PyMem_Free(buffer);
5353
    }
5354
    Py_XDECREF(nullchar);
5355
    Py_XDECREF(str);
5356
    return result;
5357
}
5358
5359
#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
5360
5361
#ifdef MS_WINDOWS
5362
5363
/*[clinic input]
5364
os._path_isdevdrive
5365
5366
    path: path_t
5367
5368
Determines whether the specified path is on a Windows Dev Drive.
5369
5370
[clinic start generated code]*/
5371
5372
static PyObject *
5373
os__path_isdevdrive_impl(PyObject *module, path_t *path)
5374
/*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/
5375
{
5376
#ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME
5377
    /* This flag will be documented at
5378
       https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information
5379
       after release, and will be available in the latest WinSDK.
5380
       We include the flag to avoid a specific version dependency
5381
       on the latest WinSDK. */
5382
    const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000;
5383
#endif
5384
    int err = 0;
5385
    PyObject *r = NULL;
5386
    wchar_t volume[MAX_PATH];
5387
5388
    Py_BEGIN_ALLOW_THREADS
5389
    if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) {
5390
        /* invalid path of some kind */
5391
        /* Note that this also includes the case where a volume is mounted
5392
           in a path longer than 260 characters. This is likely to be rare
5393
           and problematic for other reasons, so a (soft) failure in this
5394
           check seems okay. */
5395
        err = GetLastError();
5396
    } else if (GetDriveTypeW(volume) != DRIVE_FIXED) {
5397
        /* only care about local dev drives */
5398
        r = Py_False;
5399
    } else {
5400
        HANDLE hVolume = CreateFileW(
5401
            volume,
5402
            FILE_READ_ATTRIBUTES,
5403
            FILE_SHARE_READ | FILE_SHARE_WRITE,
5404
            NULL,
5405
            OPEN_EXISTING,
5406
            FILE_FLAG_BACKUP_SEMANTICS,
5407
            NULL
5408
        );
5409
        if (hVolume == INVALID_HANDLE_VALUE) {
5410
            err = GetLastError();
5411
        } else {
5412
            FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0};
5413
            volumeState.Version = 1;
5414
            volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME;
5415
            if (!DeviceIoControl(
5416
                hVolume,
5417
                FSCTL_QUERY_PERSISTENT_VOLUME_STATE,
5418
                &volumeState,
5419
                sizeof(volumeState),
5420
                &volumeState,
5421
                sizeof(volumeState),
5422
                NULL,
5423
                NULL
5424
            )) {
5425
                err = GetLastError();
5426
            }
5427
            CloseHandle(hVolume);
5428
            if (err == ERROR_INVALID_PARAMETER) {
5429
                /* not supported on this platform */
5430
                r = Py_False;
5431
            } else if (!err) {
5432
                r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME)
5433
                    ? Py_True : Py_False;
5434
            }
5435
        }
5436
    }
5437
    Py_END_ALLOW_THREADS
5438
5439
    if (err) {
5440
        PyErr_SetFromWindowsErr(err);
5441
        return NULL;
5442
    }
5443
5444
    if (r) {
5445
        return Py_NewRef(r);
5446
    }
5447
5448
    return NULL;
5449
}
5450
5451
5452
int
5453
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
5454
{
5455
    wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
5456
    DWORD result;
5457
5458
    result = GetFullPathNameW(path,
5459
                              Py_ARRAY_LENGTH(woutbuf), woutbuf,
5460
                              NULL);
5461
    if (!result) {
5462
        return -1;
5463
    }
5464
5465
    if (result >= Py_ARRAY_LENGTH(woutbuf)) {
5466
        if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
5467
            woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
5468
        }
5469
        else {
5470
            woutbufp = NULL;
5471
        }
5472
        if (!woutbufp) {
5473
            *abspath_p = NULL;
5474
            return 0;
5475
        }
5476
5477
        result = GetFullPathNameW(path, result, woutbufp, NULL);
5478
        if (!result) {
5479
            PyMem_RawFree(woutbufp);
5480
            return -1;
5481
        }
5482
    }
5483
5484
    if (woutbufp != woutbuf) {
5485
        *abspath_p = woutbufp;
5486
        return 0;
5487
    }
5488
5489
    *abspath_p = _PyMem_RawWcsdup(woutbufp);
5490
    return 0;
5491
}
5492
5493
5494
/* A helper function for abspath on win32 */
5495
/*[clinic input]
5496
os._getfullpathname
5497
5498
    path: path_t
5499
    /
5500
5501
[clinic start generated code]*/
5502
5503
static PyObject *
5504
os__getfullpathname_impl(PyObject *module, path_t *path)
5505
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
5506
{
5507
    wchar_t *abspath;
5508
5509
    if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
5510
        return win32_error_object("GetFullPathNameW", path->object);
5511
    }
5512
    if (abspath == NULL) {
5513
        return PyErr_NoMemory();
5514
    }
5515
5516
    PyObject *str = PyUnicode_FromWideChar(abspath, -1);
5517
    PyMem_RawFree(abspath);
5518
    if (str == NULL) {
5519
        return NULL;
5520
    }
5521
    if (PyBytes_Check(path->object)) {
5522
        Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
5523
    }
5524
    return str;
5525
}
5526
5527
5528
/*[clinic input]
5529
os._getfinalpathname
5530
5531
    path: path_t
5532
    /
5533
5534
A helper function for samepath on windows.
5535
[clinic start generated code]*/
5536
5537
static PyObject *
5538
os__getfinalpathname_impl(PyObject *module, path_t *path)
5539
/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
5540
{
5541
    HANDLE hFile;
5542
    wchar_t buf[MAXPATHLEN], *target_path = buf;
5543
    int buf_size = Py_ARRAY_LENGTH(buf);
5544
    int result_length;
5545
    PyObject *result;
5546
5547
    Py_BEGIN_ALLOW_THREADS
5548
    hFile = CreateFileW(
5549
        path->wide,
5550
        0, /* desired access */
5551
        0, /* share mode */
5552
        NULL, /* security attributes */
5553
        OPEN_EXISTING,
5554
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
5555
        FILE_FLAG_BACKUP_SEMANTICS,
5556
        NULL);
5557
    Py_END_ALLOW_THREADS
5558
5559
    if (hFile == INVALID_HANDLE_VALUE) {
5560
        return win32_error_object("CreateFileW", path->object);
5561
    }
5562
5563
    /* We have a good handle to the target, use it to determine the
5564
       target path name. */
5565
    while (1) {
5566
        Py_BEGIN_ALLOW_THREADS
5567
        result_length = GetFinalPathNameByHandleW(hFile, target_path,
5568
                                                  buf_size, VOLUME_NAME_DOS);
5569
        Py_END_ALLOW_THREADS
5570
5571
        if (!result_length) {
5572
            result = win32_error_object("GetFinalPathNameByHandleW",
5573
                                         path->object);
5574
            goto cleanup;
5575
        }
5576
5577
        if (result_length < buf_size) {
5578
            break;
5579
        }
5580
5581
        wchar_t *tmp;
5582
        tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
5583
                            result_length * sizeof(*tmp));
5584
        if (!tmp) {
5585
            result = PyErr_NoMemory();
5586
            goto cleanup;
5587
        }
5588
5589
        buf_size = result_length;
5590
        target_path = tmp;
5591
    }
5592
5593
    result = PyUnicode_FromWideChar(target_path, result_length);
5594
    if (result && PyBytes_Check(path->object)) {
5595
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5596
    }
5597
5598
cleanup:
5599
    if (target_path != buf) {
5600
        PyMem_Free(target_path);
5601
    }
5602
    CloseHandle(hFile);
5603
    return result;
5604
}
5605
5606
/*[clinic input]
5607
@permit_long_summary
5608
os._findfirstfile
5609
    path: path_t
5610
    /
5611
A function to get the real file name without accessing the file in Windows.
5612
[clinic start generated code]*/
5613
5614
static PyObject *
5615
os__findfirstfile_impl(PyObject *module, path_t *path)
5616
/*[clinic end generated code: output=106dd3f0779c83dd input=48c319aaa48d05d4]*/
5617
{
5618
    PyObject *result;
5619
    HANDLE hFindFile;
5620
    WIN32_FIND_DATAW wFileData;
5621
    WCHAR *wRealFileName;
5622
5623
    Py_BEGIN_ALLOW_THREADS
5624
    hFindFile = FindFirstFileW(path->wide, &wFileData);
5625
    Py_END_ALLOW_THREADS
5626
5627
    if (hFindFile == INVALID_HANDLE_VALUE) {
5628
        path_error(path);
5629
        return NULL;
5630
    }
5631
5632
    wRealFileName = wFileData.cFileName;
5633
    result = PyUnicode_FromWideChar(wRealFileName, -1);
5634
    FindClose(hFindFile);
5635
    return result;
5636
}
5637
5638
5639
/*[clinic input]
5640
os._getvolumepathname
5641
5642
    path: path_t
5643
5644
A helper function for ismount on Win32.
5645
[clinic start generated code]*/
5646
5647
static PyObject *
5648
os__getvolumepathname_impl(PyObject *module, path_t *path)
5649
/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
5650
{
5651
    PyObject *result;
5652
    wchar_t *mountpath=NULL;
5653
    size_t buflen;
5654
    BOOL ret;
5655
5656
    /* Volume path should be shorter than entire path */
5657
    buflen = Py_MAX(path->length, MAX_PATH);
5658
5659
    if (buflen > PY_DWORD_MAX) {
5660
        PyErr_SetString(PyExc_OverflowError, "path too long");
5661
        return NULL;
5662
    }
5663
5664
    mountpath = PyMem_New(wchar_t, buflen);
5665
    if (mountpath == NULL)
5666
        return PyErr_NoMemory();
5667
5668
    Py_BEGIN_ALLOW_THREADS
5669
    ret = GetVolumePathNameW(path->wide, mountpath,
5670
                             Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
5671
    Py_END_ALLOW_THREADS
5672
5673
    if (!ret) {
5674
        result = win32_error_object("_getvolumepathname", path->object);
5675
        goto exit;
5676
    }
5677
    result = PyUnicode_FromWideChar(mountpath, -1);
5678
    if (PyBytes_Check(path->object))
5679
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
5680
5681
exit:
5682
    PyMem_Free(mountpath);
5683
    return result;
5684
}
5685
5686
5687
/*[clinic input]
5688
os._path_splitroot
5689
5690
    path: path_t
5691
    /
5692
5693
Removes everything after the root on Win32.
5694
[clinic start generated code]*/
5695
5696
static PyObject *
5697
os__path_splitroot_impl(PyObject *module, path_t *path)
5698
/*[clinic end generated code: output=ab7f1a88b654581c input=d356de1edb6050a2]*/
5699
{
5700
    wchar_t *buffer;
5701
    wchar_t *end;
5702
    PyObject *result = NULL;
5703
    HRESULT ret;
5704
5705
    buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
5706
    if (!buffer) {
5707
        return PyErr_NoMemory();
5708
    }
5709
    wcscpy(buffer, path->wide);
5710
    for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
5711
        *p = L'\\';
5712
    }
5713
5714
    Py_BEGIN_ALLOW_THREADS
5715
    ret = PathCchSkipRoot(buffer, &end);
5716
    Py_END_ALLOW_THREADS
5717
    if (FAILED(ret)) {
5718
        result = Py_BuildValue("sO", "", path->object);
5719
    } else if (end != buffer) {
5720
        size_t rootLen = (size_t)(end - buffer);
5721
        result = Py_BuildValue("NN",
5722
            PyUnicode_FromWideChar(path->wide, rootLen),
5723
            PyUnicode_FromWideChar(path->wide + rootLen, -1)
5724
        );
5725
    } else {
5726
        result = Py_BuildValue("Os", path->object, "");
5727
    }
5728
    PyMem_Free(buffer);
5729
5730
    return result;
5731
}
5732
5733
5734
#define PY_IFREG  1 // Regular file
5735
#define PY_IFDIR  2 // Directory
5736
#define PY_IFLNK  4 // Symlink
5737
#define PY_IFMNT  8 // Mount Point (junction)
5738
#define PY_IFLRP 16 // Link Reparse Point (name-surrogate, symlink, junction)
5739
#define PY_IFRRP 32 // Regular Reparse Point
5740
5741
static inline BOOL
5742
_testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType)
5743
{
5744
    switch (testedType) {
5745
    case PY_IFREG:
5746
        return diskDevice && attributes &&
5747
               !(attributes & FILE_ATTRIBUTE_DIRECTORY);
5748
    case PY_IFDIR:
5749
        return attributes & FILE_ATTRIBUTE_DIRECTORY;
5750
    case PY_IFLNK:
5751
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5752
               reparseTag == IO_REPARSE_TAG_SYMLINK;
5753
    case PY_IFMNT:
5754
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5755
               reparseTag == IO_REPARSE_TAG_MOUNT_POINT;
5756
    case PY_IFLRP:
5757
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5758
               IsReparseTagNameSurrogate(reparseTag);
5759
    case PY_IFRRP:
5760
        return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
5761
               reparseTag && !IsReparseTagNameSurrogate(reparseTag);
5762
    }
5763
5764
    return FALSE;
5765
}
5766
5767
static BOOL
5768
_testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly)
5769
{
5770
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5771
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5772
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5773
5774
    BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK;
5775
    if (diskOnly && !diskDevice) {
5776
        return FALSE;
5777
    }
5778
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5779
        FILE_ATTRIBUTE_TAG_INFO info;
5780
        return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info,
5781
                                            sizeof(info)) &&
5782
               _testInfo(info.FileAttributes, info.ReparseTag, diskDevice,
5783
                         testedType);
5784
    }
5785
    FILE_BASIC_INFO info;
5786
    return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info,
5787
                                        sizeof(info)) &&
5788
           _testInfo(info.FileAttributes, 0, diskDevice, testedType);
5789
}
5790
5791
static BOOL
5792
_testFileTypeByName(LPCWSTR path, int testedType)
5793
{
5794
    assert(testedType == PY_IFREG || testedType == PY_IFDIR ||
5795
           testedType == PY_IFLNK || testedType == PY_IFMNT ||
5796
           testedType == PY_IFLRP || testedType == PY_IFRRP);
5797
5798
    FILE_STAT_BASIC_INFORMATION info;
5799
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5800
                                     sizeof(info)))
5801
    {
5802
        BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK ||
5803
                          info.DeviceType == FILE_DEVICE_VIRTUAL_DISK ||
5804
                          info.DeviceType == FILE_DEVICE_CD_ROM;
5805
        BOOL result = _testInfo(info.FileAttributes, info.ReparseTag,
5806
                                diskDevice, testedType);
5807
        if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) ||
5808
            !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
5809
        {
5810
            return result;
5811
        }
5812
    }
5813
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5814
                GetLastError()))
5815
    {
5816
        return FALSE;
5817
    }
5818
5819
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5820
    if (testedType != PY_IFREG && testedType != PY_IFDIR) {
5821
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5822
    }
5823
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5824
                               OPEN_EXISTING, flags, NULL);
5825
    if (hfile != INVALID_HANDLE_VALUE) {
5826
        BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE);
5827
        CloseHandle(hfile);
5828
        return result;
5829
    }
5830
5831
    switch (GetLastError()) {
5832
    case ERROR_ACCESS_DENIED:
5833
    case ERROR_SHARING_VIOLATION:
5834
    case ERROR_CANT_ACCESS_FILE:
5835
    case ERROR_INVALID_PARAMETER:
5836
        int rc;
5837
        STRUCT_STAT st;
5838
        if (testedType == PY_IFREG || testedType == PY_IFDIR) {
5839
            rc = STAT(path, &st);
5840
        }
5841
        else {
5842
            // PY_IFRRP is not generally supported in this case, except for
5843
            // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK.
5844
            rc = LSTAT(path, &st);
5845
        }
5846
        if (!rc) {
5847
            return _testInfo(st.st_file_attributes, st.st_reparse_tag,
5848
                             st.st_mode & S_IFREG, testedType);
5849
        }
5850
    }
5851
5852
    return FALSE;
5853
}
5854
5855
5856
static BOOL
5857
_testFileExistsByName(LPCWSTR path, BOOL followLinks)
5858
{
5859
    FILE_STAT_BASIC_INFORMATION info;
5860
    if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info,
5861
                                     sizeof(info)))
5862
    {
5863
        if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ||
5864
            (!followLinks && IsReparseTagNameSurrogate(info.ReparseTag)))
5865
        {
5866
            return TRUE;
5867
        }
5868
    }
5869
    else if (_Py_GetFileInformationByName_ErrorIsTrustworthy(
5870
                    GetLastError()))
5871
    {
5872
        return FALSE;
5873
    }
5874
5875
    DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
5876
    if (!followLinks) {
5877
        flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5878
    }
5879
    HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL,
5880
                               OPEN_EXISTING, flags, NULL);
5881
    if (hfile != INVALID_HANDLE_VALUE) {
5882
        if (followLinks) {
5883
            CloseHandle(hfile);
5884
            return TRUE;
5885
        }
5886
        // Regular Reparse Points (PY_IFRRP) have to be traversed.
5887
        BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE);
5888
        CloseHandle(hfile);
5889
        if (!result) {
5890
            return TRUE;
5891
        }
5892
        hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
5893
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
5894
        if (hfile != INVALID_HANDLE_VALUE) {
5895
            CloseHandle(hfile);
5896
            return TRUE;
5897
        }
5898
    }
5899
5900
    switch (GetLastError()) {
5901
    case ERROR_ACCESS_DENIED:
5902
    case ERROR_SHARING_VIOLATION:
5903
    case ERROR_CANT_ACCESS_FILE:
5904
    case ERROR_INVALID_PARAMETER:
5905
        STRUCT_STAT _st;
5906
        return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st);
5907
    }
5908
5909
    return FALSE;
5910
}
5911
5912
5913
static BOOL
5914
_testFileExists(path_t *path, BOOL followLinks)
5915
{
5916
    BOOL result = FALSE;
5917
    if (path->value_error) {
5918
        return FALSE;
5919
    }
5920
5921
    Py_BEGIN_ALLOW_THREADS
5922
    if (path->is_fd) {
5923
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5924
        if (hfile != INVALID_HANDLE_VALUE) {
5925
            if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) {
5926
                result = TRUE;
5927
            }
5928
        }
5929
    }
5930
    else if (path->wide) {
5931
        result = _testFileExistsByName(path->wide, followLinks);
5932
    }
5933
    Py_END_ALLOW_THREADS
5934
5935
    return result;
5936
}
5937
5938
5939
static BOOL
5940
_testFileType(path_t *path, int testedType)
5941
{
5942
    BOOL result = FALSE;
5943
    if (path->value_error) {
5944
        return FALSE;
5945
    }
5946
5947
    Py_BEGIN_ALLOW_THREADS
5948
    if (path->is_fd) {
5949
        HANDLE hfile = _Py_get_osfhandle_noraise(path->fd);
5950
        if (hfile != INVALID_HANDLE_VALUE) {
5951
            result = _testFileTypeByHandle(hfile, testedType, TRUE);
5952
        }
5953
    }
5954
    else if (path->wide) {
5955
        result = _testFileTypeByName(path->wide, testedType);
5956
    }
5957
    Py_END_ALLOW_THREADS
5958
5959
    return result;
5960
}
5961
5962
5963
/*[clinic input]
5964
os._path_exists -> bool
5965
5966
    path: path_t(allow_fd=True, suppress_value_error=True)
5967
5968
Test whether a path exists.  Returns False for broken symbolic links.
5969
5970
[clinic start generated code]*/
5971
5972
static int
5973
os__path_exists_impl(PyObject *module, path_t *path)
5974
/*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/
5975
{
5976
    return _testFileExists(path, TRUE);
5977
}
5978
5979
5980
/*[clinic input]
5981
os._path_lexists -> bool
5982
5983
    path: path_t(allow_fd=True, suppress_value_error=True)
5984
5985
Test whether a path exists.  Returns True for broken symbolic links.
5986
5987
[clinic start generated code]*/
5988
5989
static int
5990
os__path_lexists_impl(PyObject *module, path_t *path)
5991
/*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/
5992
{
5993
    return _testFileExists(path, FALSE);
5994
}
5995
5996
5997
/*[clinic input]
5998
os._path_isdir -> bool
5999
6000
    path: path_t(allow_fd=True, suppress_value_error=True)
6001
    /
6002
6003
Return true if the pathname refers to an existing directory.
6004
6005
[clinic start generated code]*/
6006
6007
static int
6008
os__path_isdir_impl(PyObject *module, path_t *path)
6009
/*[clinic end generated code: output=d5786196f9e2fa7a input=b15f9b697a7a759f]*/
6010
{
6011
    return _testFileType(path, PY_IFDIR);
6012
}
6013
6014
6015
/*[clinic input]
6016
os._path_isfile -> bool
6017
6018
    path: path_t(allow_fd=True, suppress_value_error=True)
6019
6020
Test whether a path is a regular file
6021
6022
[clinic start generated code]*/
6023
6024
static int
6025
os__path_isfile_impl(PyObject *module, path_t *path)
6026
/*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/
6027
{
6028
    return _testFileType(path, PY_IFREG);
6029
}
6030
6031
6032
/*[clinic input]
6033
os._path_islink -> bool
6034
6035
    path: path_t(allow_fd=True, suppress_value_error=True)
6036
6037
Test whether a path is a symbolic link
6038
6039
[clinic start generated code]*/
6040
6041
static int
6042
os__path_islink_impl(PyObject *module, path_t *path)
6043
/*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/
6044
{
6045
    return _testFileType(path, PY_IFLNK);
6046
}
6047
6048
6049
/*[clinic input]
6050
os._path_isjunction -> bool
6051
6052
    path: path_t(allow_fd=True, suppress_value_error=True)
6053
6054
Test whether a path is a junction
6055
6056
[clinic start generated code]*/
6057
6058
static int
6059
os__path_isjunction_impl(PyObject *module, path_t *path)
6060
/*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/
6061
{
6062
    return _testFileType(path, PY_IFMNT);
6063
}
6064
6065
#undef PY_IFREG
6066
#undef PY_IFDIR
6067
#undef PY_IFLNK
6068
#undef PY_IFMNT
6069
#undef PY_IFLRP
6070
#undef PY_IFRRP
6071
6072
#endif /* MS_WINDOWS */
6073
6074
6075
/*[clinic input]
6076
os._path_splitroot_ex
6077
6078
    path: path_t(make_wide=True, nonstrict=True)
6079
    /
6080
6081
Split a pathname into drive, root and tail.
6082
6083
The tail contains anything after the root.
6084
[clinic start generated code]*/
6085
6086
static PyObject *
6087
os__path_splitroot_ex_impl(PyObject *module, path_t *path)
6088
/*[clinic end generated code: output=4b0072b6cdf4b611 input=012fbfad14888b2b]*/
6089
132k
{
6090
132k
    Py_ssize_t drvsize, rootsize;
6091
132k
    PyObject *drv = NULL, *root = NULL, *tail = NULL, *result = NULL;
6092
6093
132k
    const wchar_t *buffer = path->wide;
6094
132k
    _Py_skiproot(buffer, path->length, &drvsize, &rootsize);
6095
132k
    drv = PyUnicode_FromWideChar(buffer, drvsize);
6096
132k
    if (drv == NULL) {
6097
0
        goto exit;
6098
0
    }
6099
132k
    root = PyUnicode_FromWideChar(&buffer[drvsize], rootsize);
6100
132k
    if (root == NULL) {
6101
0
        goto exit;
6102
0
    }
6103
132k
    tail = PyUnicode_FromWideChar(&buffer[drvsize + rootsize],
6104
132k
                                  path->length - drvsize - rootsize);
6105
132k
    if (tail == NULL) {
6106
0
        goto exit;
6107
0
    }
6108
132k
    if (PyBytes_Check(path->object)) {
6109
0
        Py_SETREF(drv, PyUnicode_EncodeFSDefault(drv));
6110
0
        if (drv == NULL) {
6111
0
            goto exit;
6112
0
        }
6113
0
        Py_SETREF(root, PyUnicode_EncodeFSDefault(root));
6114
0
        if (root == NULL) {
6115
0
            goto exit;
6116
0
        }
6117
0
        Py_SETREF(tail, PyUnicode_EncodeFSDefault(tail));
6118
0
        if (tail == NULL) {
6119
0
            goto exit;
6120
0
        }
6121
0
    }
6122
132k
    result = PyTuple_Pack(3, drv, root, tail);
6123
132k
exit:
6124
132k
    Py_XDECREF(drv);
6125
132k
    Py_XDECREF(root);
6126
132k
    Py_XDECREF(tail);
6127
132k
    return result;
6128
132k
}
6129
6130
6131
/*[clinic input]
6132
os._path_normpath
6133
6134
    path: path_t(make_wide=True, nonstrict=True)
6135
6136
Normalize path, eliminating double slashes, etc.
6137
[clinic start generated code]*/
6138
6139
static PyObject *
6140
os__path_normpath_impl(PyObject *module, path_t *path)
6141
/*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/
6142
26.8k
{
6143
26.8k
    PyObject *result;
6144
26.8k
    Py_ssize_t norm_len;
6145
26.8k
    wchar_t *norm_path = _Py_normpath_and_size((wchar_t *)path->wide,
6146
26.8k
                                               path->length, &norm_len);
6147
26.8k
    if (!norm_len) {
6148
0
        result = PyUnicode_FromOrdinal('.');
6149
0
    }
6150
26.8k
    else {
6151
26.8k
        result = PyUnicode_FromWideChar(norm_path, norm_len);
6152
26.8k
    }
6153
26.8k
    if (result == NULL) {
6154
0
        return NULL;
6155
0
    }
6156
26.8k
    if (PyBytes_Check(path->object)) {
6157
0
        Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
6158
0
    }
6159
26.8k
    return result;
6160
26.8k
}
6161
6162
/*[clinic input]
6163
os.mkdir
6164
6165
    path : path_t
6166
6167
    mode: int = 0o777
6168
6169
    *
6170
6171
    dir_fd : dir_fd(requires='mkdirat') = None
6172
6173
Create a directory.
6174
6175
If dir_fd is not None, it should be a file descriptor open to
6176
a directory, and path should be relative; path will then be relative to
6177
that directory.
6178
dir_fd may not be implemented on your platform.  If it is unavailable,
6179
using it will raise a NotImplementedError.
6180
6181
The mode argument is ignored on Windows.  Where it is used, the current
6182
umask value is first masked out.
6183
[clinic start generated code]*/
6184
6185
static PyObject *
6186
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
6187
/*[clinic end generated code: output=a70446903abe821f input=30270d369599634b]*/
6188
91.4k
{
6189
91.4k
    int result;
6190
#ifdef MS_WINDOWS
6191
    int error = 0;
6192
    SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
6193
    SECURITY_ATTRIBUTES *pSecAttr = NULL;
6194
#endif
6195
91.4k
#ifdef HAVE_MKDIRAT
6196
91.4k
    int mkdirat_unavailable = 0;
6197
91.4k
#endif
6198
6199
91.4k
    if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
6200
91.4k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6201
0
        return NULL;
6202
0
    }
6203
6204
#ifdef MS_WINDOWS
6205
    Py_BEGIN_ALLOW_THREADS
6206
    // For API sets that don't support these APIs, we have no choice
6207
    // but to silently create a directory with default ACL.
6208
#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
6209
    if (mode == 0700 /* 0o700 */) {
6210
        ULONG sdSize;
6211
        pSecAttr = &secAttr;
6212
        // Set a discretionary ACL (D) that is protected (P) and includes
6213
        // inheritable (OICI) entries that allow (A) full control (FA) to
6214
        // SYSTEM (SY), Administrators (BA), and the owner (OW).
6215
        if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
6216
            L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
6217
            SDDL_REVISION_1,
6218
            &secAttr.lpSecurityDescriptor,
6219
            &sdSize
6220
        )) {
6221
            error = GetLastError();
6222
        }
6223
    }
6224
#endif
6225
    if (!error) {
6226
        result = CreateDirectoryW(path->wide, pSecAttr);
6227
        if (secAttr.lpSecurityDescriptor &&
6228
            // uncommonly, LocalFree returns non-zero on error, but still uses
6229
            // GetLastError() to see what the error code is
6230
            LocalFree(secAttr.lpSecurityDescriptor)) {
6231
            error = GetLastError();
6232
        }
6233
    }
6234
    Py_END_ALLOW_THREADS
6235
6236
    if (error) {
6237
        return PyErr_SetFromWindowsErr(error);
6238
    }
6239
    if (!result) {
6240
        return path_error(path);
6241
    }
6242
#else
6243
91.4k
    Py_BEGIN_ALLOW_THREADS
6244
91.4k
#if HAVE_MKDIRAT
6245
91.4k
    if (dir_fd != DEFAULT_DIR_FD) {
6246
0
      if (HAVE_MKDIRAT_RUNTIME) {
6247
0
        result = mkdirat(dir_fd, path->narrow, mode);
6248
6249
0
      } else {
6250
0
        mkdirat_unavailable = 1;
6251
0
      }
6252
0
    } else
6253
91.4k
#endif
6254
#if defined(__WATCOMC__) && !defined(__QNX__)
6255
        result = mkdir(path->narrow);
6256
#else
6257
91.4k
        result = mkdir(path->narrow, mode);
6258
91.4k
#endif
6259
91.4k
    Py_END_ALLOW_THREADS
6260
6261
91.4k
#if HAVE_MKDIRAT
6262
91.4k
    if (mkdirat_unavailable) {
6263
0
        argument_unavailable_error(NULL, "dir_fd");
6264
0
        return NULL;
6265
0
    }
6266
91.4k
#endif
6267
6268
91.4k
    if (result < 0)
6269
337
        return path_error(path);
6270
91.0k
#endif /* MS_WINDOWS */
6271
91.4k
    Py_RETURN_NONE;
6272
91.4k
}
6273
6274
6275
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
6276
#if defined(HAVE_SYS_RESOURCE_H)
6277
#include <sys/resource.h>
6278
#endif
6279
6280
6281
#ifdef HAVE_NICE
6282
/*[clinic input]
6283
os.nice
6284
6285
    increment: int
6286
    /
6287
6288
Add increment to the priority of process and return the new priority.
6289
[clinic start generated code]*/
6290
6291
static PyObject *
6292
os_nice_impl(PyObject *module, int increment)
6293
/*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
6294
0
{
6295
0
    int value;
6296
6297
    /* There are two flavours of 'nice': one that returns the new
6298
       priority (as required by almost all standards out there) and the
6299
       Linux/FreeBSD one, which returns '0' on success and advices
6300
       the use of getpriority() to get the new priority.
6301
6302
       If we are of the nice family that returns the new priority, we
6303
       need to clear errno before the call, and check if errno is filled
6304
       before calling posix_error() on a returnvalue of -1, because the
6305
       -1 may be the actual new priority! */
6306
6307
0
    errno = 0;
6308
0
    value = nice(increment);
6309
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
6310
    if (value == 0)
6311
        value = getpriority(PRIO_PROCESS, 0);
6312
#endif
6313
0
    if (value == -1 && errno != 0)
6314
        /* either nice() or getpriority() returned an error */
6315
0
        return posix_error();
6316
0
    return PyLong_FromLong((long) value);
6317
0
}
6318
#endif /* HAVE_NICE */
6319
6320
6321
#ifdef HAVE_GETPRIORITY
6322
/*[clinic input]
6323
os.getpriority
6324
6325
    which: int
6326
    who: int
6327
6328
Return program scheduling priority.
6329
[clinic start generated code]*/
6330
6331
static PyObject *
6332
os_getpriority_impl(PyObject *module, int which, int who)
6333
/*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
6334
0
{
6335
0
    int retval;
6336
6337
0
    errno = 0;
6338
0
    retval = getpriority(which, who);
6339
0
    if (errno != 0)
6340
0
        return posix_error();
6341
0
    return PyLong_FromLong((long)retval);
6342
0
}
6343
#endif /* HAVE_GETPRIORITY */
6344
6345
6346
#ifdef HAVE_SETPRIORITY
6347
/*[clinic input]
6348
os.setpriority
6349
6350
    which: int
6351
    who: int
6352
    priority: int
6353
6354
Set program scheduling priority.
6355
[clinic start generated code]*/
6356
6357
static PyObject *
6358
os_setpriority_impl(PyObject *module, int which, int who, int priority)
6359
/*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
6360
0
{
6361
0
    int retval;
6362
6363
0
    retval = setpriority(which, who, priority);
6364
0
    if (retval == -1)
6365
0
        return posix_error();
6366
0
    Py_RETURN_NONE;
6367
0
}
6368
#endif /* HAVE_SETPRIORITY */
6369
6370
6371
static PyObject *
6372
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
6373
145
{
6374
145
    const char *function_name = is_replace ? "replace" : "rename";
6375
145
    int dir_fd_specified;
6376
6377
145
#ifdef HAVE_RENAMEAT
6378
145
    int renameat_unavailable = 0;
6379
145
#endif
6380
6381
#ifdef MS_WINDOWS
6382
    BOOL result;
6383
    int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
6384
#else
6385
145
    int result;
6386
145
#endif
6387
6388
145
    dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
6389
145
                       (dst_dir_fd != DEFAULT_DIR_FD);
6390
#ifndef HAVE_RENAMEAT
6391
    if (dir_fd_specified) {
6392
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6393
        return NULL;
6394
    }
6395
#endif
6396
6397
145
    if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
6398
145
                    src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
6399
145
                    dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
6400
0
        return NULL;
6401
0
    }
6402
6403
#ifdef MS_WINDOWS
6404
    Py_BEGIN_ALLOW_THREADS
6405
    result = MoveFileExW(src->wide, dst->wide, flags);
6406
    Py_END_ALLOW_THREADS
6407
6408
    if (!result)
6409
        return path_error2(src, dst);
6410
6411
#else
6412
145
    Py_BEGIN_ALLOW_THREADS
6413
145
#ifdef HAVE_RENAMEAT
6414
145
    if (dir_fd_specified) {
6415
0
        if (HAVE_RENAMEAT_RUNTIME) {
6416
0
            result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
6417
0
        } else {
6418
0
            renameat_unavailable = 1;
6419
0
        }
6420
0
    } else
6421
145
#endif
6422
145
    result = rename(src->narrow, dst->narrow);
6423
145
    Py_END_ALLOW_THREADS
6424
6425
6426
145
#ifdef HAVE_RENAMEAT
6427
145
    if (renameat_unavailable) {
6428
0
        argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
6429
0
        return NULL;
6430
0
    }
6431
145
#endif
6432
6433
145
    if (result)
6434
0
        return path_error2(src, dst);
6435
145
#endif
6436
145
    Py_RETURN_NONE;
6437
145
}
6438
6439
6440
/*[clinic input]
6441
os.rename
6442
6443
    src : path_t
6444
    dst : path_t
6445
    *
6446
    src_dir_fd : dir_fd = None
6447
    dst_dir_fd : dir_fd = None
6448
6449
Rename a file or directory.
6450
6451
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6452
descriptor open to a directory, and the respective path string (src or
6453
dst) should be relative; the path will then be relative to that
6454
directory.
6455
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6456
If they are unavailable, using them will raise a NotImplementedError.
6457
[clinic start generated code]*/
6458
6459
static PyObject *
6460
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6461
               int dst_dir_fd)
6462
/*[clinic end generated code: output=59e803072cf41230 input=7d320d687c715fd6]*/
6463
5
{
6464
5
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
6465
5
}
6466
6467
6468
/*[clinic input]
6469
os.replace = os.rename
6470
6471
Rename a file or directory, overwriting the destination.
6472
6473
If either src_dir_fd or dst_dir_fd is not None, it should be a file
6474
descriptor open to a directory, and the respective path string (src or
6475
dst) should be relative; the path will then be relative to that
6476
directory.
6477
src_dir_fd and dst_dir_fd, may not be implemented on your platform.
6478
If they are unavailable, using them will raise a NotImplementedError.
6479
[clinic start generated code]*/
6480
6481
static PyObject *
6482
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
6483
                int dst_dir_fd)
6484
/*[clinic end generated code: output=1968c02e7857422b input=44ed6b762d5953fc]*/
6485
140
{
6486
140
    return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
6487
140
}
6488
6489
6490
/*[clinic input]
6491
os.rmdir
6492
6493
    path: path_t
6494
    *
6495
    dir_fd: dir_fd(requires='unlinkat') = None
6496
6497
Remove a directory.
6498
6499
If dir_fd is not None, it should be a file descriptor open to
6500
a directory, and path should be relative; path will then be relative
6501
to that directory.
6502
dir_fd may not be implemented on your platform.
6503
If it is unavailable, using it will raise a NotImplementedError.
6504
[clinic start generated code]*/
6505
6506
static PyObject *
6507
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
6508
/*[clinic end generated code: output=080eb54f506e8301 input=84325211e33a98e0]*/
6509
91.0k
{
6510
91.0k
    int result;
6511
91.0k
#ifdef HAVE_UNLINKAT
6512
91.0k
    int unlinkat_unavailable = 0;
6513
91.0k
#endif
6514
6515
91.0k
    if (PySys_Audit("os.rmdir", "Oi", path->object,
6516
91.0k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6517
0
        return NULL;
6518
0
    }
6519
6520
91.0k
    Py_BEGIN_ALLOW_THREADS
6521
#ifdef MS_WINDOWS
6522
    /* Windows, success=1, UNIX, success=0 */
6523
    result = !RemoveDirectoryW(path->wide);
6524
#else
6525
91.0k
#ifdef HAVE_UNLINKAT
6526
91.0k
    if (dir_fd != DEFAULT_DIR_FD) {
6527
86.9k
      if (HAVE_UNLINKAT_RUNTIME) {
6528
86.9k
        result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
6529
86.9k
      } else {
6530
0
        unlinkat_unavailable = 1;
6531
0
        result = -1;
6532
0
      }
6533
86.9k
    } else
6534
4.11k
#endif
6535
4.11k
        result = rmdir(path->narrow);
6536
91.0k
#endif
6537
91.0k
    Py_END_ALLOW_THREADS
6538
6539
91.0k
#ifdef HAVE_UNLINKAT
6540
91.0k
    if (unlinkat_unavailable) {
6541
0
        argument_unavailable_error("rmdir", "dir_fd");
6542
0
        return NULL;
6543
0
    }
6544
91.0k
#endif
6545
6546
91.0k
    if (result)
6547
5
        return path_error(path);
6548
6549
91.0k
    Py_RETURN_NONE;
6550
91.0k
}
6551
6552
6553
#ifdef HAVE_SYSTEM
6554
#ifdef MS_WINDOWS
6555
/*[clinic input]
6556
os.system -> long
6557
6558
    command: Py_UNICODE
6559
6560
Execute the command in a subshell.
6561
[clinic start generated code]*/
6562
6563
static long
6564
os_system_impl(PyObject *module, const wchar_t *command)
6565
/*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/
6566
{
6567
    long result;
6568
6569
    if (PySys_Audit("os.system", "(u)", command) < 0) {
6570
        return -1;
6571
    }
6572
6573
    Py_BEGIN_ALLOW_THREADS
6574
    _Py_BEGIN_SUPPRESS_IPH
6575
    result = _wsystem(command);
6576
    _Py_END_SUPPRESS_IPH
6577
    Py_END_ALLOW_THREADS
6578
    return result;
6579
}
6580
#else /* MS_WINDOWS */
6581
/*[clinic input]
6582
os.system -> long
6583
6584
    command: unicode_fs_encoded
6585
6586
Execute the command in a subshell.
6587
[clinic start generated code]*/
6588
6589
static long
6590
os_system_impl(PyObject *module, PyObject *command)
6591
/*[clinic end generated code: output=290fc437dd4f33a0 input=47c6f24b6dc92881]*/
6592
0
{
6593
0
    long result;
6594
0
    const char *bytes = PyBytes_AsString(command);
6595
6596
0
    if (PySys_Audit("os.system", "(O)", command) < 0) {
6597
0
        return -1;
6598
0
    }
6599
6600
0
    Py_BEGIN_ALLOW_THREADS
6601
0
    result = system(bytes);
6602
0
    Py_END_ALLOW_THREADS
6603
0
    return result;
6604
0
}
6605
#endif
6606
#endif /* HAVE_SYSTEM */
6607
6608
6609
#ifdef HAVE_UMASK
6610
/*[clinic input]
6611
os.umask
6612
6613
    mask: int
6614
    /
6615
6616
Set the current numeric umask and return the previous umask.
6617
[clinic start generated code]*/
6618
6619
static PyObject *
6620
os_umask_impl(PyObject *module, int mask)
6621
/*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
6622
0
{
6623
0
    int i = (int)umask(mask);
6624
0
    if (i < 0)
6625
0
        return posix_error();
6626
0
    return PyLong_FromLong((long)i);
6627
0
}
6628
#endif
6629
6630
#ifdef MS_WINDOWS
6631
6632
/* override the default DeleteFileW behavior so that directory
6633
symlinks can be removed with this function, the same as with
6634
Unix symlinks */
6635
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
6636
{
6637
    WIN32_FILE_ATTRIBUTE_DATA info;
6638
    WIN32_FIND_DATAW find_data;
6639
    HANDLE find_data_handle;
6640
    int is_directory = 0;
6641
    int is_link = 0;
6642
6643
    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
6644
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
6645
6646
        /* Get WIN32_FIND_DATA structure for the path to determine if
6647
           it is a symlink */
6648
        if(is_directory &&
6649
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
6650
            find_data_handle = FindFirstFileW(lpFileName, &find_data);
6651
6652
            if(find_data_handle != INVALID_HANDLE_VALUE) {
6653
                /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
6654
                   IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
6655
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
6656
                          find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
6657
                FindClose(find_data_handle);
6658
            }
6659
        }
6660
    }
6661
6662
    if (is_directory && is_link)
6663
        return RemoveDirectoryW(lpFileName);
6664
6665
    return DeleteFileW(lpFileName);
6666
}
6667
#endif /* MS_WINDOWS */
6668
6669
6670
/*[clinic input]
6671
os.unlink
6672
6673
    path: path_t
6674
    *
6675
    dir_fd: dir_fd(requires='unlinkat')=None
6676
6677
Remove a file (same as remove()).
6678
6679
If dir_fd is not None, it should be a file descriptor open to
6680
a directory, and path should be relative; path will then be relative to
6681
that directory.
6682
dir_fd may not be implemented on your platform.
6683
If it is unavailable, using it will raise a NotImplementedError.
6684
6685
[clinic start generated code]*/
6686
6687
static PyObject *
6688
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
6689
/*[clinic end generated code: output=621797807b9963b1 input=1a2ef2579207eab1]*/
6690
18.4k
{
6691
18.4k
    int result;
6692
18.4k
#ifdef HAVE_UNLINKAT
6693
18.4k
    int unlinkat_unavailable = 0;
6694
18.4k
#endif
6695
6696
18.4k
    if (PySys_Audit("os.remove", "Oi", path->object,
6697
18.4k
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
6698
0
        return NULL;
6699
0
    }
6700
6701
18.4k
    Py_BEGIN_ALLOW_THREADS
6702
18.4k
    _Py_BEGIN_SUPPRESS_IPH
6703
#ifdef MS_WINDOWS
6704
    /* Windows, success=1, UNIX, success=0 */
6705
    result = !Py_DeleteFileW(path->wide);
6706
#else
6707
18.4k
#ifdef HAVE_UNLINKAT
6708
18.4k
    if (dir_fd != DEFAULT_DIR_FD) {
6709
18.4k
      if (HAVE_UNLINKAT_RUNTIME) {
6710
6711
18.4k
        result = unlinkat(dir_fd, path->narrow, 0);
6712
18.4k
      } else {
6713
0
        unlinkat_unavailable = 1;
6714
0
      }
6715
18.4k
    } else
6716
2
#endif /* HAVE_UNLINKAT */
6717
2
        result = unlink(path->narrow);
6718
18.4k
#endif
6719
18.4k
    _Py_END_SUPPRESS_IPH
6720
18.4k
    Py_END_ALLOW_THREADS
6721
6722
18.4k
#ifdef HAVE_UNLINKAT
6723
18.4k
    if (unlinkat_unavailable) {
6724
0
        argument_unavailable_error(NULL, "dir_fd");
6725
0
        return NULL;
6726
0
    }
6727
18.4k
#endif
6728
6729
18.4k
    if (result)
6730
0
        return path_error(path);
6731
6732
18.4k
    Py_RETURN_NONE;
6733
18.4k
}
6734
6735
6736
/*[clinic input]
6737
os.remove = os.unlink
6738
6739
Remove a file (same as unlink()).
6740
6741
If dir_fd is not None, it should be a file descriptor open to
6742
a directory, and path should be relative; path will then be relative
6743
to that directory.
6744
dir_fd may not be implemented on your platform.
6745
If it is unavailable, using it will raise a NotImplementedError.
6746
[clinic start generated code]*/
6747
6748
static PyObject *
6749
os_remove_impl(PyObject *module, path_t *path, int dir_fd)
6750
/*[clinic end generated code: output=a8535b28f0068883 input=9f6e66912126bd56]*/
6751
0
{
6752
0
    return os_unlink_impl(module, path, dir_fd);
6753
0
}
6754
6755
6756
static PyStructSequence_Field uname_result_fields[] = {
6757
    {"sysname",    "operating system name"},
6758
    {"nodename",   "name of machine on network (implementation-defined)"},
6759
    {"release",    "operating system release"},
6760
    {"version",    "operating system version"},
6761
    {"machine",    "hardware identifier"},
6762
    {NULL}
6763
};
6764
6765
PyDoc_STRVAR(uname_result__doc__,
6766
"uname_result: Result from os.uname().\n\n\
6767
This object may be accessed either as a tuple of\n\
6768
  (sysname, nodename, release, version, machine),\n\
6769
or via the attributes sysname, nodename, release, version, and machine.\n\
6770
\n\
6771
See os.uname for more information.");
6772
6773
static PyStructSequence_Desc uname_result_desc = {
6774
    MODNAME ".uname_result", /* name */
6775
    uname_result__doc__, /* doc */
6776
    uname_result_fields,
6777
    5
6778
};
6779
6780
#ifdef HAVE_UNAME
6781
/*[clinic input]
6782
os.uname
6783
6784
Return an object identifying the current operating system.
6785
6786
The object behaves like a named tuple with the following fields:
6787
  (sysname, nodename, release, version, machine)
6788
6789
[clinic start generated code]*/
6790
6791
static PyObject *
6792
os_uname_impl(PyObject *module)
6793
/*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
6794
4
{
6795
4
    struct utsname u;
6796
4
    int res;
6797
4
    PyObject *value;
6798
6799
4
    Py_BEGIN_ALLOW_THREADS
6800
4
    res = uname(&u);
6801
4
    Py_END_ALLOW_THREADS
6802
4
    if (res < 0)
6803
0
        return posix_error();
6804
6805
4
    PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
6806
4
    value = PyStructSequence_New((PyTypeObject *)UnameResultType);
6807
4
    if (value == NULL)
6808
0
        return NULL;
6809
6810
4
#define SET(i, field) \
6811
20
    { \
6812
20
    PyObject *o = PyUnicode_DecodeFSDefault(field); \
6813
20
    if (!o) { \
6814
0
        Py_DECREF(value); \
6815
0
        return NULL; \
6816
0
    } \
6817
20
    PyStructSequence_SET_ITEM(value, i, o); \
6818
20
    } \
6819
4
6820
8
    SET(0, u.sysname);
6821
8
    SET(1, u.nodename);
6822
4
    SET(2, u.release);
6823
4
    SET(3, u.version);
6824
4
    SET(4, u.machine);
6825
6826
4
#undef SET
6827
6828
4
    return value;
6829
4
}
6830
#endif /* HAVE_UNAME */
6831
6832
6833
6834
typedef struct {
6835
    int    now;
6836
    time_t atime_s;
6837
    long   atime_ns;
6838
    time_t mtime_s;
6839
    long   mtime_ns;
6840
} utime_t;
6841
6842
/*
6843
 * these macros assume that "ut" is a pointer to a utime_t
6844
 * they also intentionally leak the declaration of a pointer named "time"
6845
 */
6846
#define UTIME_TO_TIMESPEC \
6847
0
    struct timespec ts[2]; \
6848
0
    struct timespec *time; \
6849
0
    if (ut->now) \
6850
0
        time = NULL; \
6851
0
    else { \
6852
0
        ts[0].tv_sec = ut->atime_s; \
6853
0
        ts[0].tv_nsec = ut->atime_ns; \
6854
0
        ts[1].tv_sec = ut->mtime_s; \
6855
0
        ts[1].tv_nsec = ut->mtime_ns; \
6856
0
        time = ts; \
6857
0
    } \
6858
6859
#define UTIME_TO_TIMEVAL \
6860
0
    struct timeval tv[2]; \
6861
0
    struct timeval *time; \
6862
0
    if (ut->now) \
6863
0
        time = NULL; \
6864
0
    else { \
6865
0
        tv[0].tv_sec = ut->atime_s; \
6866
0
        tv[0].tv_usec = ut->atime_ns / 1000; \
6867
0
        tv[1].tv_sec = ut->mtime_s; \
6868
0
        tv[1].tv_usec = ut->mtime_ns / 1000; \
6869
0
        time = tv; \
6870
0
    } \
6871
6872
#define UTIME_TO_UTIMBUF \
6873
    struct utimbuf u; \
6874
    struct utimbuf *time; \
6875
    if (ut->now) \
6876
        time = NULL; \
6877
    else { \
6878
        u.actime = ut->atime_s; \
6879
        u.modtime = ut->mtime_s; \
6880
        time = &u; \
6881
    }
6882
6883
#define UTIME_TO_TIME_T \
6884
    time_t timet[2]; \
6885
    time_t *time; \
6886
    if (ut->now) \
6887
        time = NULL; \
6888
    else { \
6889
        timet[0] = ut->atime_s; \
6890
        timet[1] = ut->mtime_s; \
6891
        time = timet; \
6892
    } \
6893
6894
6895
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
6896
6897
static int
6898
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
6899
0
{
6900
#if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
6901
    if (HAVE_UTIMENSAT_RUNTIME) {
6902
        int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6903
        UTIME_TO_TIMESPEC;
6904
        return utimensat(dir_fd, path, time, flags);
6905
    }  else {
6906
        errno = ENOSYS;
6907
        return -1;
6908
    }
6909
#elif defined(HAVE_UTIMENSAT)
6910
0
    int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
6911
0
    UTIME_TO_TIMESPEC;
6912
0
    return utimensat(dir_fd, path, time, flags);
6913
#elif defined(HAVE_FUTIMESAT)
6914
    UTIME_TO_TIMEVAL;
6915
    /*
6916
     * follow_symlinks will never be false here;
6917
     * we only allow !follow_symlinks and dir_fd together
6918
     * if we have utimensat()
6919
     */
6920
    assert(follow_symlinks);
6921
    return futimesat(dir_fd, path, time);
6922
#endif
6923
0
}
6924
6925
0
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
6926
#else
6927
    #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
6928
#endif
6929
6930
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
6931
6932
static int
6933
utime_fd(utime_t *ut, int fd)
6934
0
{
6935
0
#ifdef HAVE_FUTIMENS
6936
6937
0
    if (HAVE_FUTIMENS_RUNTIME) {
6938
6939
0
    UTIME_TO_TIMESPEC;
6940
0
    return futimens(fd, time);
6941
6942
0
    } else
6943
#ifndef HAVE_FUTIMES
6944
    {
6945
        /* Not sure if this can happen */
6946
        PyErr_SetString(
6947
            PyExc_RuntimeError,
6948
            "neither futimens nor futimes are supported"
6949
            " on this system");
6950
        return -1;
6951
    }
6952
#endif
6953
6954
0
#endif
6955
0
#ifdef HAVE_FUTIMES
6956
0
    {
6957
0
    UTIME_TO_TIMEVAL;
6958
0
    return futimes(fd, time);
6959
0
    }
6960
0
#endif
6961
0
}
6962
6963
    #define PATH_UTIME_HAVE_FD 1
6964
#else
6965
    #define PATH_UTIME_HAVE_FD 0
6966
#endif
6967
6968
#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
6969
#  define UTIME_HAVE_NOFOLLOW_SYMLINKS
6970
#endif
6971
6972
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
6973
6974
static int
6975
utime_nofollow_symlinks(utime_t *ut, const char *path)
6976
0
{
6977
0
#ifdef HAVE_UTIMENSAT
6978
0
    if (HAVE_UTIMENSAT_RUNTIME) {
6979
0
        UTIME_TO_TIMESPEC;
6980
0
        return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
6981
0
    } else
6982
#ifndef HAVE_LUTIMES
6983
    {
6984
        /* Not sure if this can happen */
6985
        PyErr_SetString(
6986
            PyExc_RuntimeError,
6987
            "neither utimensat nor lutimes are supported"
6988
            " on this system");
6989
        return -1;
6990
    }
6991
#endif
6992
0
#endif
6993
6994
0
#ifdef HAVE_LUTIMES
6995
0
    {
6996
0
    UTIME_TO_TIMEVAL;
6997
0
    return lutimes(path, time);
6998
0
    }
6999
0
#endif
7000
0
}
7001
7002
#endif
7003
7004
#ifndef MS_WINDOWS
7005
7006
static int
7007
utime_default(utime_t *ut, const char *path)
7008
0
{
7009
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
7010
    if (HAVE_UTIMENSAT_RUNTIME) {
7011
        UTIME_TO_TIMESPEC;
7012
        return utimensat(DEFAULT_DIR_FD, path, time, 0);
7013
    } else {
7014
        UTIME_TO_TIMEVAL;
7015
        return utimes(path, time);
7016
    }
7017
#elif defined(HAVE_UTIMENSAT)
7018
0
    UTIME_TO_TIMESPEC;
7019
0
    return utimensat(DEFAULT_DIR_FD, path, time, 0);
7020
#elif defined(HAVE_UTIMES)
7021
    UTIME_TO_TIMEVAL;
7022
    return utimes(path, time);
7023
#elif defined(HAVE_UTIME_H)
7024
    UTIME_TO_UTIMBUF;
7025
    return utime(path, time);
7026
#else
7027
    UTIME_TO_TIME_T;
7028
    return utime(path, time);
7029
#endif
7030
0
}
7031
7032
#endif
7033
7034
static int
7035
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
7036
0
{
7037
0
    int result = 0;
7038
0
    PyObject *divmod;
7039
0
    divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
7040
0
    if (!divmod)
7041
0
        goto exit;
7042
0
    if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
7043
0
        PyErr_Format(PyExc_TypeError,
7044
0
                     "%.200s.__divmod__() must return a 2-tuple, not %.200s",
7045
0
                     _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
7046
0
        goto exit;
7047
0
    }
7048
0
    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
7049
0
    if ((*s == -1) && PyErr_Occurred())
7050
0
        goto exit;
7051
0
    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
7052
0
    if ((*ns == -1) && PyErr_Occurred())
7053
0
        goto exit;
7054
7055
0
    result = 1;
7056
0
exit:
7057
0
    Py_XDECREF(divmod);
7058
0
    return result;
7059
0
}
7060
7061
7062
/*[clinic input]
7063
os.utime
7064
7065
    path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
7066
    times: object = None
7067
    *
7068
    ns: object = NULL
7069
    dir_fd: dir_fd(requires='futimensat') = None
7070
    follow_symlinks: bool=True
7071
7072
Set the access and modified time of path.
7073
7074
path may always be specified as a string.  On some platforms, path may
7075
also be specified as an open file descriptor.  If this functionality is
7076
unavailable, using it raises an exception.
7077
7078
If times is not None, it must be a tuple (atime, mtime);
7079
atime and mtime should be expressed as float seconds since the epoch.
7080
If ns is specified, it must be a tuple (atime_ns, mtime_ns);
7081
atime_ns and mtime_ns should be expressed as integer nanoseconds
7082
since the epoch.
7083
If times is None and ns is unspecified, utime uses the current time.
7084
Specifying tuples for both times and ns is an error.
7085
7086
If dir_fd is not None, it should be a file descriptor open to
7087
a directory, and path should be relative; path will then be relative to
7088
that directory.
7089
If follow_symlinks is False, and the last element of the path is
7090
a symbolic link, utime will modify the symbolic link itself instead of
7091
the file the link points to.
7092
It is an error to use dir_fd or follow_symlinks when specifying path as
7093
an open file descriptor.
7094
dir_fd and follow_symlinks may not be available on your platform.
7095
If they are unavailable, using them will raise a NotImplementedError.
7096
7097
[clinic start generated code]*/
7098
7099
static PyObject *
7100
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
7101
              int dir_fd, int follow_symlinks)
7102
/*[clinic end generated code: output=cfcac69d027b82cf input=5ab470b2bc250788]*/
7103
0
{
7104
#ifdef MS_WINDOWS
7105
    HANDLE hFile;
7106
    FILETIME atime, mtime;
7107
#else
7108
0
    int result;
7109
0
#endif
7110
7111
0
    utime_t utime;
7112
7113
0
    memset(&utime, 0, sizeof(utime_t));
7114
7115
0
    if (times != Py_None && ns) {
7116
0
        PyErr_SetString(PyExc_ValueError,
7117
0
                     "utime: you may specify either 'times'"
7118
0
                     " or 'ns' but not both");
7119
0
        return NULL;
7120
0
    }
7121
7122
0
    if (times != Py_None) {
7123
0
        time_t a_sec, m_sec;
7124
0
        long a_nsec, m_nsec;
7125
0
        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
7126
0
            PyErr_SetString(PyExc_TypeError,
7127
0
                         "utime: 'times' must be either"
7128
0
                         " a tuple of two numbers or None");
7129
0
            return NULL;
7130
0
        }
7131
0
        utime.now = 0;
7132
0
        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
7133
0
                                     &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
7134
0
            _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
7135
0
                                     &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
7136
0
            return NULL;
7137
0
        }
7138
0
        utime.atime_s = a_sec;
7139
0
        utime.atime_ns = a_nsec;
7140
0
        utime.mtime_s = m_sec;
7141
0
        utime.mtime_ns = m_nsec;
7142
0
    }
7143
0
    else if (ns) {
7144
0
        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
7145
0
            PyErr_SetString(PyExc_TypeError,
7146
0
                         "utime: 'ns' must be a tuple of two ints");
7147
0
            return NULL;
7148
0
        }
7149
0
        utime.now = 0;
7150
0
        if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
7151
0
                                      &utime.atime_s, &utime.atime_ns) ||
7152
0
            !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
7153
0
                                       &utime.mtime_s, &utime.mtime_ns)) {
7154
0
            return NULL;
7155
0
        }
7156
0
    }
7157
0
    else {
7158
        /* times and ns are both None/unspecified. use "now". */
7159
0
        utime.now = 1;
7160
0
    }
7161
7162
#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
7163
    if (follow_symlinks_specified("utime", follow_symlinks))
7164
        return NULL;
7165
#endif
7166
7167
0
    if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
7168
0
        dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
7169
0
        fd_and_follow_symlinks_invalid("utime", path->is_fd, follow_symlinks))
7170
0
        return NULL;
7171
7172
#if !defined(HAVE_UTIMENSAT)
7173
    if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
7174
        PyErr_SetString(PyExc_ValueError,
7175
                     "utime: cannot use dir_fd and follow_symlinks "
7176
                     "together on this platform");
7177
        return NULL;
7178
    }
7179
#endif
7180
7181
0
    if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
7182
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
7183
0
        return NULL;
7184
0
    }
7185
7186
#ifdef MS_WINDOWS
7187
    Py_BEGIN_ALLOW_THREADS
7188
    hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
7189
                        NULL, OPEN_EXISTING,
7190
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
7191
    Py_END_ALLOW_THREADS
7192
    if (hFile == INVALID_HANDLE_VALUE) {
7193
        path_error(path);
7194
        return NULL;
7195
    }
7196
7197
    if (utime.now) {
7198
        GetSystemTimeAsFileTime(&mtime);
7199
        atime = mtime;
7200
    }
7201
    else {
7202
        _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
7203
        _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
7204
    }
7205
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
7206
        path_error(path);
7207
        CloseHandle(hFile);
7208
        return NULL;
7209
    }
7210
    CloseHandle(hFile);
7211
#else /* MS_WINDOWS */
7212
0
    Py_BEGIN_ALLOW_THREADS
7213
7214
0
#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
7215
0
    if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
7216
0
        result = utime_nofollow_symlinks(&utime, path->narrow);
7217
0
    else
7218
0
#endif
7219
7220
0
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
7221
0
    if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
7222
0
        result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
7223
7224
0
    } else
7225
0
#endif
7226
7227
0
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
7228
0
    if (path->is_fd)
7229
0
        result = utime_fd(&utime, path->fd);
7230
0
    else
7231
0
#endif
7232
7233
0
    result = utime_default(&utime, path->narrow);
7234
7235
0
    Py_END_ALLOW_THREADS
7236
7237
#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
7238
    /* See utime_dir_fd implementation */
7239
    if (result == -1 && errno == ENOSYS) {
7240
        argument_unavailable_error(NULL, "dir_fd");
7241
        return NULL;
7242
    }
7243
#endif
7244
7245
0
    if (result < 0) {
7246
0
        path_error(path);
7247
0
        return NULL;
7248
0
    }
7249
7250
0
#endif /* MS_WINDOWS */
7251
7252
0
    Py_RETURN_NONE;
7253
0
}
7254
7255
/* Process operations */
7256
7257
7258
/*[clinic input]
7259
@permit_long_summary
7260
os._exit
7261
7262
    status: int
7263
7264
Exit to the system with specified status, without normal exit processing.
7265
[clinic start generated code]*/
7266
7267
static PyObject *
7268
os__exit_impl(PyObject *module, int status)
7269
/*[clinic end generated code: output=116e52d9c2260d54 input=c35d282acfebe8fd]*/
7270
0
{
7271
0
    _exit(status);
7272
0
    return NULL; /* Make gcc -Wall happy */
7273
0
}
7274
7275
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7276
#define EXECV_CHAR wchar_t
7277
#else
7278
0
#define EXECV_CHAR char
7279
#endif
7280
7281
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
7282
static void
7283
free_string_array(EXECV_CHAR **array, Py_ssize_t count)
7284
0
{
7285
0
    Py_ssize_t i;
7286
0
    for (i = 0; i < count; i++)
7287
0
        PyMem_Free(array[i]);
7288
0
    PyMem_Free(array);
7289
0
}
7290
7291
static int
7292
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
7293
0
{
7294
0
    Py_ssize_t size;
7295
0
    PyObject *ub;
7296
0
    int result = 0;
7297
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7298
    if (!PyUnicode_FSDecoder(o, &ub))
7299
        return 0;
7300
    *out = PyUnicode_AsWideCharString(ub, &size);
7301
    if (*out)
7302
        result = 1;
7303
#else
7304
0
    if (!PyUnicode_FSConverter(o, &ub))
7305
0
        return 0;
7306
0
    size = PyBytes_GET_SIZE(ub);
7307
0
    *out = PyMem_Malloc(size + 1);
7308
0
    if (*out) {
7309
0
        memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
7310
0
        result = 1;
7311
0
    } else
7312
0
        PyErr_NoMemory();
7313
0
#endif
7314
0
    Py_DECREF(ub);
7315
0
    return result;
7316
0
}
7317
#endif
7318
7319
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
7320
static EXECV_CHAR**
7321
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
7322
0
{
7323
0
    Py_ssize_t i, pos, envc;
7324
0
    PyObject *keys = NULL, *vals = NULL;
7325
0
    PyObject *key = NULL, *val = NULL, *key2 = NULL, *val2 = NULL;
7326
0
    EXECV_CHAR **envlist;
7327
7328
0
    i = PyMapping_Size(env);
7329
0
    if (i < 0)
7330
0
        return NULL;
7331
0
    envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
7332
0
    if (envlist == NULL) {
7333
0
        PyErr_NoMemory();
7334
0
        return NULL;
7335
0
    }
7336
0
    envc = 0;
7337
0
    keys = PyMapping_Keys(env);
7338
0
    if (!keys)
7339
0
        goto error;
7340
0
    vals = PyMapping_Values(env);
7341
0
    if (!vals)
7342
0
        goto error;
7343
0
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
7344
0
        PyErr_Format(PyExc_TypeError,
7345
0
                     "env.keys() or env.values() is not a list");
7346
0
        goto error;
7347
0
    }
7348
7349
0
    for (pos = 0; pos < i; pos++) {
7350
        // The 'key' and 'val' must be strong references because of
7351
        // possible side-effects by PyUnicode_FS{Converter,Decoder}().
7352
0
        key = PyList_GetItemRef(keys, pos);
7353
0
        if (key == NULL) {
7354
0
            goto error;
7355
0
        }
7356
0
        val = PyList_GetItemRef(vals, pos);
7357
0
        if (val == NULL) {
7358
0
            goto error;
7359
0
        }
7360
7361
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
7362
        if (!PyUnicode_FSDecoder(key, &key2)) {
7363
            goto error;
7364
        }
7365
        if (!PyUnicode_FSDecoder(val, &val2)) {
7366
            goto error;
7367
        }
7368
        /* Search from index 1 because on Windows starting '=' is allowed for
7369
           defining hidden environment variables. */
7370
        if (PyUnicode_GET_LENGTH(key2) == 0 ||
7371
            PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
7372
        {
7373
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7374
            goto error;
7375
        }
7376
        PyObject *keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
7377
#else
7378
0
        if (!PyUnicode_FSConverter(key, &key2)) {
7379
0
            goto error;
7380
0
        }
7381
0
        if (!PyUnicode_FSConverter(val, &val2)) {
7382
0
            goto error;
7383
0
        }
7384
0
        if (PyBytes_GET_SIZE(key2) == 0 ||
7385
0
            strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
7386
0
        {
7387
0
            PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
7388
0
            goto error;
7389
0
        }
7390
0
        PyObject *keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
7391
0
                                              PyBytes_AS_STRING(val2));
7392
0
#endif
7393
0
        if (!keyval) {
7394
0
            goto error;
7395
0
        }
7396
7397
0
        if (!fsconvert_strdup(keyval, &envlist[envc++])) {
7398
0
            Py_DECREF(keyval);
7399
0
            goto error;
7400
0
        }
7401
7402
0
        Py_CLEAR(key);
7403
0
        Py_CLEAR(val);
7404
0
        Py_CLEAR(key2);
7405
0
        Py_CLEAR(val2);
7406
0
        Py_DECREF(keyval);
7407
0
    }
7408
0
    Py_DECREF(vals);
7409
0
    Py_DECREF(keys);
7410
7411
0
    envlist[envc] = 0;
7412
0
    *envc_ptr = envc;
7413
0
    return envlist;
7414
7415
0
error:
7416
0
    Py_XDECREF(key);
7417
0
    Py_XDECREF(val);
7418
0
    Py_XDECREF(key2);
7419
0
    Py_XDECREF(val2);
7420
0
    Py_XDECREF(keys);
7421
0
    Py_XDECREF(vals);
7422
0
    free_string_array(envlist, envc);
7423
0
    return NULL;
7424
0
}
7425
7426
static EXECV_CHAR**
7427
parse_arglist(PyObject* argv, Py_ssize_t *argc)
7428
0
{
7429
0
    int i;
7430
0
    EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
7431
0
    if (argvlist == NULL) {
7432
0
        PyErr_NoMemory();
7433
0
        return NULL;
7434
0
    }
7435
0
    for (i = 0; i < *argc; i++) {
7436
0
        PyObject* item = PySequence_ITEM(argv, i);
7437
0
        if (item == NULL)
7438
0
            goto fail;
7439
0
        if (!fsconvert_strdup(item, &argvlist[i])) {
7440
0
            Py_DECREF(item);
7441
0
            goto fail;
7442
0
        }
7443
0
        Py_DECREF(item);
7444
0
    }
7445
0
    argvlist[*argc] = NULL;
7446
0
    return argvlist;
7447
0
fail:
7448
0
    *argc = i;
7449
0
    free_string_array(argvlist, *argc);
7450
0
    return NULL;
7451
0
}
7452
7453
#endif
7454
7455
7456
#ifdef HAVE_EXECV
7457
/*[clinic input]
7458
os.execv
7459
7460
    path: path_t
7461
        Path of executable file.
7462
    argv: object
7463
        Tuple or list of strings.
7464
    /
7465
7466
Execute an executable path with arguments, replacing current process.
7467
[clinic start generated code]*/
7468
7469
static PyObject *
7470
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
7471
/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
7472
0
{
7473
0
    EXECV_CHAR **argvlist;
7474
0
    Py_ssize_t argc;
7475
7476
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7477
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7478
0
        PyErr_SetString(PyExc_RuntimeError,
7479
0
                        "exec not supported for isolated subinterpreters");
7480
0
        return NULL;
7481
0
    }
7482
7483
    /* execv has two arguments: (path, argv), where
7484
       argv is a list or tuple of strings. */
7485
7486
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7487
0
        PyErr_SetString(PyExc_TypeError,
7488
0
                        "execv() arg 2 must be a tuple or list");
7489
0
        return NULL;
7490
0
    }
7491
0
    argc = PySequence_Size(argv);
7492
0
    if (argc < 1) {
7493
0
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
7494
0
        return NULL;
7495
0
    }
7496
7497
0
    argvlist = parse_arglist(argv, &argc);
7498
0
    if (argvlist == NULL) {
7499
0
        return NULL;
7500
0
    }
7501
0
    if (!argvlist[0][0]) {
7502
0
        PyErr_SetString(PyExc_ValueError,
7503
0
            "execv() arg 2 first element cannot be empty");
7504
0
        free_string_array(argvlist, argc);
7505
0
        return NULL;
7506
0
    }
7507
7508
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
7509
0
        free_string_array(argvlist, argc);
7510
0
        return NULL;
7511
0
    }
7512
7513
0
    _Py_BEGIN_SUPPRESS_IPH
7514
#ifdef HAVE_WEXECV
7515
    _wexecv(path->wide, argvlist);
7516
#else
7517
0
    execv(path->narrow, argvlist);
7518
0
#endif
7519
0
    _Py_END_SUPPRESS_IPH
7520
7521
    /* If we get here it's definitely an error */
7522
7523
0
    posix_path_error(path);
7524
0
    free_string_array(argvlist, argc);
7525
0
    return NULL;
7526
0
}
7527
7528
7529
/*[clinic input]
7530
os.execve
7531
7532
    path: path_t(allow_fd='PATH_HAVE_FEXECVE')
7533
        Path of executable file.
7534
    argv: object
7535
        Tuple or list of strings.
7536
    env: object
7537
        Dictionary of strings mapping to strings.
7538
7539
Execute an executable path with arguments, replacing current process.
7540
[clinic start generated code]*/
7541
7542
static PyObject *
7543
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
7544
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
7545
0
{
7546
0
    EXECV_CHAR **argvlist = NULL;
7547
0
    EXECV_CHAR **envlist;
7548
0
    Py_ssize_t argc, envc;
7549
7550
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7551
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) {
7552
0
        PyErr_SetString(PyExc_RuntimeError,
7553
0
                        "exec not supported for isolated subinterpreters");
7554
0
        return NULL;
7555
0
    }
7556
7557
    /* execve has three arguments: (path, argv, env), where
7558
       argv is a list or tuple of strings and env is a dictionary
7559
       like posix.environ. */
7560
7561
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7562
0
        PyErr_SetString(PyExc_TypeError,
7563
0
                        "execve: argv must be a tuple or list");
7564
0
        goto fail_0;
7565
0
    }
7566
0
    argc = PySequence_Size(argv);
7567
0
    if (argc < 1) {
7568
0
        PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
7569
0
        return NULL;
7570
0
    }
7571
7572
0
    if (!PyMapping_Check(env)) {
7573
0
        PyErr_SetString(PyExc_TypeError,
7574
0
                        "execve: environment must be a mapping object");
7575
0
        goto fail_0;
7576
0
    }
7577
7578
0
    argvlist = parse_arglist(argv, &argc);
7579
0
    if (argvlist == NULL) {
7580
0
        goto fail_0;
7581
0
    }
7582
0
    if (!argvlist[0][0]) {
7583
0
        PyErr_SetString(PyExc_ValueError,
7584
0
            "execve: argv first element cannot be empty");
7585
0
        goto fail_0;
7586
0
    }
7587
7588
0
    envlist = parse_envlist(env, &envc);
7589
0
    if (envlist == NULL)
7590
0
        goto fail_0;
7591
7592
0
    if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
7593
0
        goto fail_1;
7594
0
    }
7595
7596
0
    _Py_BEGIN_SUPPRESS_IPH
7597
0
#ifdef HAVE_FEXECVE
7598
0
    if (path->is_fd)
7599
0
        fexecve(path->fd, argvlist, envlist);
7600
0
    else
7601
0
#endif
7602
#ifdef HAVE_WEXECV
7603
        _wexecve(path->wide, argvlist, envlist);
7604
#else
7605
0
        execve(path->narrow, argvlist, envlist);
7606
0
#endif
7607
0
    _Py_END_SUPPRESS_IPH
7608
7609
    /* If we get here it's definitely an error */
7610
7611
0
    posix_path_error(path);
7612
0
  fail_1:
7613
0
    free_string_array(envlist, envc);
7614
0
  fail_0:
7615
0
    if (argvlist)
7616
0
        free_string_array(argvlist, argc);
7617
0
    return NULL;
7618
0
}
7619
7620
#endif /* HAVE_EXECV */
7621
7622
#ifdef HAVE_POSIX_SPAWN
7623
7624
enum posix_spawn_file_actions_identifier {
7625
    POSIX_SPAWN_OPEN,
7626
    POSIX_SPAWN_CLOSE,
7627
    POSIX_SPAWN_DUP2
7628
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7629
    ,POSIX_SPAWN_CLOSEFROM
7630
#endif
7631
};
7632
7633
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
7634
static int
7635
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
7636
#endif
7637
7638
static int
7639
parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
7640
                        int resetids, int setsid, PyObject *setsigmask,
7641
                        PyObject *setsigdef, PyObject *scheduler,
7642
                        posix_spawnattr_t *attrp)
7643
0
{
7644
0
    assert(scheduler == NULL || scheduler == Py_None || PyTuple_Check(scheduler));
7645
0
    long all_flags = 0;
7646
7647
0
    errno = posix_spawnattr_init(attrp);
7648
0
    if (errno) {
7649
0
        posix_error();
7650
0
        return -1;
7651
0
    }
7652
7653
0
    if (setpgroup && setpgroup != Py_None) {
7654
0
        pid_t pgid = PyLong_AsPid(setpgroup);
7655
0
        if (pgid == (pid_t)-1 && PyErr_Occurred()) {
7656
0
            goto fail;
7657
0
        }
7658
0
        errno = posix_spawnattr_setpgroup(attrp, pgid);
7659
0
        if (errno) {
7660
0
            posix_error();
7661
0
            goto fail;
7662
0
        }
7663
0
        all_flags |= POSIX_SPAWN_SETPGROUP;
7664
0
    }
7665
7666
0
    if (resetids) {
7667
0
        all_flags |= POSIX_SPAWN_RESETIDS;
7668
0
    }
7669
7670
0
    if (setsid) {
7671
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7672
        if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
7673
#endif
7674
0
#ifdef POSIX_SPAWN_SETSID
7675
0
        all_flags |= POSIX_SPAWN_SETSID;
7676
#elif defined(POSIX_SPAWN_SETSID_NP)
7677
        all_flags |= POSIX_SPAWN_SETSID_NP;
7678
#else
7679
        argument_unavailable_error(func_name, "setsid");
7680
        return -1;
7681
#endif
7682
7683
#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
7684
        } else {
7685
            argument_unavailable_error(func_name, "setsid");
7686
            return -1;
7687
        }
7688
#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
7689
7690
0
    }
7691
7692
0
#ifdef HAVE_SIGSET_T
7693
0
   if (setsigmask) {
7694
0
        sigset_t set;
7695
0
        if (!_Py_Sigset_Converter(setsigmask, &set)) {
7696
0
            goto fail;
7697
0
        }
7698
0
        errno = posix_spawnattr_setsigmask(attrp, &set);
7699
0
        if (errno) {
7700
0
            posix_error();
7701
0
            goto fail;
7702
0
        }
7703
0
        all_flags |= POSIX_SPAWN_SETSIGMASK;
7704
0
    }
7705
7706
0
    if (setsigdef) {
7707
0
        sigset_t set;
7708
0
        if (!_Py_Sigset_Converter(setsigdef, &set)) {
7709
0
            goto fail;
7710
0
        }
7711
0
        errno = posix_spawnattr_setsigdefault(attrp, &set);
7712
0
        if (errno) {
7713
0
            posix_error();
7714
0
            goto fail;
7715
0
        }
7716
0
        all_flags |= POSIX_SPAWN_SETSIGDEF;
7717
0
    }
7718
#else
7719
    if (setsigmask || setsigdef) {
7720
        PyErr_SetString(PyExc_NotImplementedError,
7721
                        "sigset is not supported on this platform");
7722
        goto fail;
7723
    }
7724
#endif
7725
7726
0
    if (scheduler && scheduler != Py_None) {
7727
0
#ifdef POSIX_SPAWN_SETSCHEDULER
7728
0
        PyObject *py_schedpolicy;
7729
0
        PyObject *schedparam_obj;
7730
0
        struct sched_param schedparam;
7731
7732
0
        if (!PyArg_ParseTuple(scheduler, "OO"
7733
0
                        ";A scheduler tuple must have two elements",
7734
0
                        &py_schedpolicy, &schedparam_obj)) {
7735
0
            goto fail;
7736
0
        }
7737
0
        if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
7738
0
            goto fail;
7739
0
        }
7740
0
        if (py_schedpolicy != Py_None) {
7741
0
            int schedpolicy = PyLong_AsInt(py_schedpolicy);
7742
7743
0
            if (schedpolicy == -1 && PyErr_Occurred()) {
7744
0
                goto fail;
7745
0
            }
7746
0
            errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
7747
0
            if (errno) {
7748
0
                posix_error();
7749
0
                goto fail;
7750
0
            }
7751
0
            all_flags |= POSIX_SPAWN_SETSCHEDULER;
7752
0
        }
7753
0
        errno = posix_spawnattr_setschedparam(attrp, &schedparam);
7754
0
        if (errno) {
7755
0
            posix_error();
7756
0
            goto fail;
7757
0
        }
7758
0
        all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
7759
#else
7760
        PyErr_SetString(PyExc_NotImplementedError,
7761
                "The scheduler option is not supported in this system.");
7762
        goto fail;
7763
#endif
7764
0
    }
7765
7766
0
    errno = posix_spawnattr_setflags(attrp, all_flags);
7767
0
    if (errno) {
7768
0
        posix_error();
7769
0
        goto fail;
7770
0
    }
7771
7772
0
    return 0;
7773
7774
0
fail:
7775
0
    (void)posix_spawnattr_destroy(attrp);
7776
0
    return -1;
7777
0
}
7778
7779
static int
7780
parse_file_actions(PyObject *file_actions,
7781
                   posix_spawn_file_actions_t *file_actionsp,
7782
                   PyObject *temp_buffer)
7783
0
{
7784
0
    PyObject *seq;
7785
0
    PyObject *file_action = NULL;
7786
0
    PyObject *tag_obj;
7787
7788
0
    seq = PySequence_Fast(file_actions,
7789
0
                          "file_actions must be a sequence or None");
7790
0
    if (seq == NULL) {
7791
0
        return -1;
7792
0
    }
7793
7794
0
    errno = posix_spawn_file_actions_init(file_actionsp);
7795
0
    if (errno) {
7796
0
        posix_error();
7797
0
        Py_DECREF(seq);
7798
0
        return -1;
7799
0
    }
7800
7801
0
    for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
7802
0
        file_action = PySequence_Fast_GET_ITEM(seq, i);
7803
0
        Py_INCREF(file_action);
7804
0
        if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
7805
0
            PyErr_SetString(PyExc_TypeError,
7806
0
                "Each file_actions element must be a non-empty tuple");
7807
0
            goto fail;
7808
0
        }
7809
0
        long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
7810
0
        if (tag == -1 && PyErr_Occurred()) {
7811
0
            goto fail;
7812
0
        }
7813
7814
        /* Populate the file_actions object */
7815
0
        switch (tag) {
7816
0
            case POSIX_SPAWN_OPEN: {
7817
0
                int fd, oflag;
7818
0
                PyObject *path;
7819
0
                unsigned long mode;
7820
0
                if (!PyArg_ParseTuple(file_action, "OiO&ik"
7821
0
                        ";A open file_action tuple must have 5 elements",
7822
0
                        &tag_obj, &fd, PyUnicode_FSConverter, &path,
7823
0
                        &oflag, &mode))
7824
0
                {
7825
0
                    goto fail;
7826
0
                }
7827
0
                if (PyList_Append(temp_buffer, path)) {
7828
0
                    Py_DECREF(path);
7829
0
                    goto fail;
7830
0
                }
7831
0
                errno = posix_spawn_file_actions_addopen(file_actionsp,
7832
0
                        fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
7833
0
                if (errno) {
7834
0
                    posix_error();
7835
0
                    Py_DECREF(path);
7836
0
                    goto fail;
7837
0
                }
7838
0
                Py_DECREF(path);
7839
0
                break;
7840
0
            }
7841
0
            case POSIX_SPAWN_CLOSE: {
7842
0
                int fd;
7843
0
                if (!PyArg_ParseTuple(file_action, "Oi"
7844
0
                        ";A close file_action tuple must have 2 elements",
7845
0
                        &tag_obj, &fd))
7846
0
                {
7847
0
                    goto fail;
7848
0
                }
7849
0
                errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
7850
0
                if (errno) {
7851
0
                    posix_error();
7852
0
                    goto fail;
7853
0
                }
7854
0
                break;
7855
0
            }
7856
0
            case POSIX_SPAWN_DUP2: {
7857
0
                int fd1, fd2;
7858
0
                if (!PyArg_ParseTuple(file_action, "Oii"
7859
0
                        ";A dup2 file_action tuple must have 3 elements",
7860
0
                        &tag_obj, &fd1, &fd2))
7861
0
                {
7862
0
                    goto fail;
7863
0
                }
7864
0
                errno = posix_spawn_file_actions_adddup2(file_actionsp,
7865
0
                                                         fd1, fd2);
7866
0
                if (errno) {
7867
0
                    posix_error();
7868
0
                    goto fail;
7869
0
                }
7870
0
                break;
7871
0
            }
7872
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
7873
            case POSIX_SPAWN_CLOSEFROM: {
7874
                int fd;
7875
                if (!PyArg_ParseTuple(file_action, "Oi"
7876
                        ";A closefrom file_action tuple must have 2 elements",
7877
                        &tag_obj, &fd))
7878
                {
7879
                    goto fail;
7880
                }
7881
                errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
7882
                                                                 fd);
7883
                if (errno) {
7884
                    posix_error();
7885
                    goto fail;
7886
                }
7887
                break;
7888
            }
7889
#endif
7890
0
            default: {
7891
0
                PyErr_SetString(PyExc_TypeError,
7892
0
                                "Unknown file_actions identifier");
7893
0
                goto fail;
7894
0
            }
7895
0
        }
7896
0
        Py_DECREF(file_action);
7897
0
    }
7898
7899
0
    Py_DECREF(seq);
7900
0
    return 0;
7901
7902
0
fail:
7903
0
    Py_DECREF(seq);
7904
0
    Py_DECREF(file_action);
7905
0
    (void)posix_spawn_file_actions_destroy(file_actionsp);
7906
0
    return -1;
7907
0
}
7908
7909
7910
static PyObject *
7911
py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
7912
               PyObject *env, PyObject *file_actions,
7913
               PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
7914
               PyObject *setsigdef, PyObject *scheduler)
7915
0
{
7916
0
    const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
7917
0
    EXECV_CHAR **argvlist = NULL;
7918
0
    EXECV_CHAR **envlist = NULL;
7919
0
    posix_spawn_file_actions_t file_actions_buf;
7920
0
    posix_spawn_file_actions_t *file_actionsp = NULL;
7921
0
    posix_spawnattr_t attr;
7922
0
    posix_spawnattr_t *attrp = NULL;
7923
0
    Py_ssize_t argc, envc;
7924
0
    PyObject *result = NULL;
7925
0
    PyObject *temp_buffer = NULL;
7926
0
    pid_t pid;
7927
0
    int err_code;
7928
7929
    /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
7930
       argv is a list or tuple of strings and env is a dictionary
7931
       like posix.environ. */
7932
7933
0
    if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
7934
0
        PyErr_Format(PyExc_TypeError,
7935
0
                     "%s: argv must be a tuple or list", func_name);
7936
0
        goto exit;
7937
0
    }
7938
0
    argc = PySequence_Size(argv);
7939
0
    if (argc < 1) {
7940
0
        PyErr_Format(PyExc_ValueError,
7941
0
                     "%s: argv must not be empty", func_name);
7942
0
        goto exit;
7943
0
    }
7944
7945
0
    if (!PyMapping_Check(env) && env != Py_None) {
7946
0
        PyErr_Format(PyExc_TypeError,
7947
0
                     "%s: environment must be a mapping object or None", func_name);
7948
0
        goto exit;
7949
0
    }
7950
7951
0
    if (scheduler && !PyTuple_Check(scheduler) && scheduler != Py_None) {
7952
0
        PyErr_Format(PyExc_TypeError,
7953
0
                     "%s: scheduler must be a tuple or None", func_name);
7954
0
        goto exit;
7955
0
    }
7956
7957
0
    argvlist = parse_arglist(argv, &argc);
7958
0
    if (argvlist == NULL) {
7959
0
        goto exit;
7960
0
    }
7961
0
    if (!argvlist[0][0]) {
7962
0
        PyErr_Format(PyExc_ValueError,
7963
0
                     "%s: argv first element cannot be empty", func_name);
7964
0
        goto exit;
7965
0
    }
7966
7967
#ifdef USE_DARWIN_NS_GET_ENVIRON
7968
    // There is no environ global in this situation.
7969
    char **environ = NULL;
7970
#endif
7971
7972
0
    if (env == Py_None) {
7973
#ifdef USE_DARWIN_NS_GET_ENVIRON
7974
        environ = *_NSGetEnviron();
7975
#endif
7976
0
        envlist = environ;
7977
0
    } else {
7978
0
        envlist = parse_envlist(env, &envc);
7979
0
        if (envlist == NULL) {
7980
0
            goto exit;
7981
0
        }
7982
0
    }
7983
7984
0
    if (file_actions != NULL && file_actions != Py_None) {
7985
        /* There is a bug in old versions of glibc that makes some of the
7986
         * helper functions for manipulating file actions not copy the provided
7987
         * buffers. The problem is that posix_spawn_file_actions_addopen does not
7988
         * copy the value of path for some old versions of glibc (<2.20).
7989
         * The use of temp_buffer here is a workaround that keeps the
7990
         * python objects that own the buffers alive until posix_spawn gets called.
7991
         * Check https://bugs.python.org/issue33630 and
7992
         * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
7993
0
        temp_buffer = PyList_New(0);
7994
0
        if (!temp_buffer) {
7995
0
            goto exit;
7996
0
        }
7997
0
        if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
7998
0
            goto exit;
7999
0
        }
8000
0
        file_actionsp = &file_actions_buf;
8001
0
    }
8002
8003
0
    if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
8004
0
                                setsigmask, setsigdef, scheduler, &attr)) {
8005
0
        goto exit;
8006
0
    }
8007
0
    attrp = &attr;
8008
8009
0
    if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
8010
0
        goto exit;
8011
0
    }
8012
8013
0
    _Py_BEGIN_SUPPRESS_IPH
8014
0
#ifdef HAVE_POSIX_SPAWNP
8015
0
    if (use_posix_spawnp) {
8016
0
        err_code = posix_spawnp(&pid, path->narrow,
8017
0
                                file_actionsp, attrp, argvlist, envlist);
8018
0
    }
8019
0
    else
8020
0
#endif /* HAVE_POSIX_SPAWNP */
8021
0
    {
8022
0
        err_code = posix_spawn(&pid, path->narrow,
8023
0
                               file_actionsp, attrp, argvlist, envlist);
8024
0
    }
8025
0
    _Py_END_SUPPRESS_IPH
8026
8027
0
    if (err_code) {
8028
0
        errno = err_code;
8029
0
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
8030
0
        goto exit;
8031
0
    }
8032
#ifdef _Py_MEMORY_SANITIZER
8033
    __msan_unpoison(&pid, sizeof(pid));
8034
#endif
8035
0
    result = PyLong_FromPid(pid);
8036
8037
0
exit:
8038
0
    if (file_actionsp) {
8039
0
        (void)posix_spawn_file_actions_destroy(file_actionsp);
8040
0
    }
8041
0
    if (attrp) {
8042
0
        (void)posix_spawnattr_destroy(attrp);
8043
0
    }
8044
0
    if (envlist && envlist != environ) {
8045
0
        free_string_array(envlist, envc);
8046
0
    }
8047
0
    if (argvlist) {
8048
0
        free_string_array(argvlist, argc);
8049
0
    }
8050
0
    Py_XDECREF(temp_buffer);
8051
0
    return result;
8052
0
}
8053
8054
8055
/*[clinic input]
8056
8057
os.posix_spawn
8058
    path: path_t
8059
        Path of executable file.
8060
    argv: object
8061
        Tuple or list of strings.
8062
    env: object
8063
        Dictionary of strings mapping to strings.
8064
    /
8065
    *
8066
    file_actions: object(c_default='NULL') = ()
8067
        A sequence of file action tuples.
8068
    setpgroup: object(c_default='NULL') = None
8069
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8070
    resetids: bool = False
8071
        If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
8072
    setsid: bool = False
8073
        If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP
8074
        will be activated.
8075
    setsigmask: object(c_default='NULL') = ()
8076
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8077
    setsigdef: object(c_default='NULL') = ()
8078
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8079
    scheduler: object(c_default='NULL') = None
8080
        A tuple with the scheduler policy (optional) and parameters.
8081
8082
Execute the program specified by path in a new process.
8083
[clinic start generated code]*/
8084
8085
static PyObject *
8086
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
8087
                    PyObject *env, PyObject *file_actions,
8088
                    PyObject *setpgroup, int resetids, int setsid,
8089
                    PyObject *setsigmask, PyObject *setsigdef,
8090
                    PyObject *scheduler)
8091
/*[clinic end generated code: output=14a1098c566bc675 input=c7592dcbc96e8114]*/
8092
0
{
8093
0
    return py_posix_spawn(0, module, path, argv, env, file_actions,
8094
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8095
0
                          scheduler);
8096
0
}
8097
 #endif /* HAVE_POSIX_SPAWN */
8098
8099
8100
8101
#ifdef HAVE_POSIX_SPAWNP
8102
/*[clinic input]
8103
8104
os.posix_spawnp
8105
    path: path_t
8106
        Path of executable file.
8107
    argv: object
8108
        Tuple or list of strings.
8109
    env: object
8110
        Dictionary of strings mapping to strings.
8111
    /
8112
    *
8113
    file_actions: object(c_default='NULL') = ()
8114
        A sequence of file action tuples.
8115
    setpgroup: object(c_default='NULL') = None
8116
        The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
8117
    resetids: bool = False
8118
        If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
8119
    setsid: bool = False
8120
        If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP
8121
        will be activated.
8122
    setsigmask: object(c_default='NULL') = ()
8123
        The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
8124
    setsigdef: object(c_default='NULL') = ()
8125
        The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
8126
    scheduler: object(c_default='NULL') = None
8127
        A tuple with the scheduler policy (optional) and parameters.
8128
8129
Execute the program specified by path in a new process.
8130
[clinic start generated code]*/
8131
8132
static PyObject *
8133
os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
8134
                     PyObject *env, PyObject *file_actions,
8135
                     PyObject *setpgroup, int resetids, int setsid,
8136
                     PyObject *setsigmask, PyObject *setsigdef,
8137
                     PyObject *scheduler)
8138
/*[clinic end generated code: output=7b9aaefe3031238d input=43ccc1452cae2be3]*/
8139
0
{
8140
0
    return py_posix_spawn(1, module, path, argv, env, file_actions,
8141
0
                          setpgroup, resetids, setsid, setsigmask, setsigdef,
8142
0
                          scheduler);
8143
0
}
8144
#endif /* HAVE_POSIX_SPAWNP */
8145
8146
#ifdef HAVE_RTPSPAWN
8147
static intptr_t
8148
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
8149
               const char  *envp[])
8150
{
8151
     RTP_ID rtpid;
8152
     int status;
8153
     pid_t res;
8154
     int async_err = 0;
8155
8156
     /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
8157
        uStackSize=0 cannot be used, the default stack size is too small for
8158
        Python. */
8159
     if (envp) {
8160
         rtpid = rtpSpawn(rtpFileName, argv, envp,
8161
                          100, 0x1000000, 0, VX_FP_TASK);
8162
     }
8163
     else {
8164
         rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
8165
                          100, 0x1000000, 0, VX_FP_TASK);
8166
     }
8167
     if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
8168
         do {
8169
             res = waitpid((pid_t)rtpid, &status, 0);
8170
         } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8171
8172
         if (res < 0)
8173
             return RTP_ID_ERROR;
8174
         return ((intptr_t)status);
8175
     }
8176
     return ((intptr_t)rtpid);
8177
}
8178
#endif
8179
8180
#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
8181
/*[clinic input]
8182
os.spawnv
8183
8184
    mode: int
8185
        Mode of process creation.
8186
    path: path_t
8187
        Path of executable file.
8188
    argv: object
8189
        Tuple or list of strings.
8190
    /
8191
8192
Execute the program specified by path in a new process.
8193
[clinic start generated code]*/
8194
8195
static PyObject *
8196
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
8197
/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
8198
{
8199
    EXECV_CHAR **argvlist;
8200
    int i;
8201
    Py_ssize_t argc;
8202
    intptr_t spawnval;
8203
8204
    /* spawnv has three arguments: (mode, path, argv), where
8205
       argv is a list or tuple of strings. */
8206
8207
    if (PyList_Check(argv)) {
8208
        argc = PyList_Size(argv);
8209
    }
8210
    else if (PyTuple_Check(argv)) {
8211
        argc = PyTuple_Size(argv);
8212
    }
8213
    else {
8214
        PyErr_SetString(PyExc_TypeError,
8215
                        "spawnv() arg 2 must be a tuple or list");
8216
        return NULL;
8217
    }
8218
    if (argc == 0) {
8219
        PyErr_SetString(PyExc_ValueError,
8220
            "spawnv() arg 2 cannot be empty");
8221
        return NULL;
8222
    }
8223
8224
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8225
    if (argvlist == NULL) {
8226
        return PyErr_NoMemory();
8227
    }
8228
    for (i = 0; i < argc; i++) {
8229
        // The item must be a strong reference because of possible
8230
        // side-effects of PyUnicode_FS{Converter,Decoder}() in
8231
        // fsconvert_strdup(): an item's __fspath__() can mutate a list
8232
        // *argv*, releasing the list's reference to the item (gh-151416).
8233
        PyObject *item = PySequence_ITEM(argv, i);
8234
        if (item == NULL) {
8235
            free_string_array(argvlist, i);
8236
            return NULL;
8237
        }
8238
        if (!fsconvert_strdup(item, &argvlist[i])) {
8239
            Py_DECREF(item);
8240
            free_string_array(argvlist, i);
8241
            // Add argument context to the converter's terse TypeError, but
8242
            // let MemoryError, codec errors, embedded-null ValueError, etc.
8243
            // propagate unmasked.
8244
            if (PyErr_ExceptionMatches(PyExc_TypeError)) {
8245
                PyErr_SetString(
8246
                    PyExc_TypeError,
8247
                    "spawnv() arg 2 must contain only strings");
8248
            }
8249
            return NULL;
8250
        }
8251
        Py_DECREF(item);
8252
        if (i == 0 && !argvlist[0][0]) {
8253
            free_string_array(argvlist, i + 1);
8254
            PyErr_SetString(
8255
                PyExc_ValueError,
8256
                "spawnv() arg 2 first element cannot be empty");
8257
            return NULL;
8258
        }
8259
    }
8260
    argvlist[argc] = NULL;
8261
8262
#if !defined(HAVE_RTPSPAWN)
8263
    if (mode == _OLD_P_OVERLAY)
8264
        mode = _P_OVERLAY;
8265
#endif
8266
8267
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
8268
                    Py_None) < 0) {
8269
        free_string_array(argvlist, argc);
8270
        return NULL;
8271
    }
8272
8273
    Py_BEGIN_ALLOW_THREADS
8274
    _Py_BEGIN_SUPPRESS_IPH
8275
#ifdef HAVE_WSPAWNV
8276
    spawnval = _wspawnv(mode, path->wide, argvlist);
8277
#elif defined(HAVE_RTPSPAWN)
8278
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
8279
#else
8280
    spawnval = _spawnv(mode, path->narrow, argvlist);
8281
#endif
8282
    _Py_END_SUPPRESS_IPH
8283
    Py_END_ALLOW_THREADS
8284
8285
    int saved_errno = errno;
8286
    free_string_array(argvlist, argc);
8287
8288
    if (spawnval == -1) {
8289
        errno = saved_errno;
8290
        posix_error();
8291
        return NULL;
8292
    }
8293
    return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8294
}
8295
8296
/*[clinic input]
8297
os.spawnve
8298
8299
    mode: int
8300
        Mode of process creation.
8301
    path: path_t
8302
        Path of executable file.
8303
    argv: object
8304
        Tuple or list of strings.
8305
    env: object
8306
        Dictionary of strings mapping to strings.
8307
    /
8308
8309
Execute the program specified by path in a new process.
8310
[clinic start generated code]*/
8311
8312
static PyObject *
8313
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
8314
                PyObject *env)
8315
/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
8316
{
8317
    EXECV_CHAR **argvlist;
8318
    EXECV_CHAR **envlist;
8319
    PyObject *res = NULL;
8320
    Py_ssize_t argc, i, envc;
8321
    intptr_t spawnval;
8322
    Py_ssize_t lastarg = 0;
8323
8324
    /* spawnve has four arguments: (mode, path, argv, env), where
8325
       argv is a list or tuple of strings and env is a dictionary
8326
       like posix.environ. */
8327
8328
    if (PyList_Check(argv)) {
8329
        argc = PyList_Size(argv);
8330
    }
8331
    else if (PyTuple_Check(argv)) {
8332
        argc = PyTuple_Size(argv);
8333
    }
8334
    else {
8335
        PyErr_SetString(PyExc_TypeError,
8336
                        "spawnve() arg 2 must be a tuple or list");
8337
        goto fail_0;
8338
    }
8339
    if (argc == 0) {
8340
        PyErr_SetString(PyExc_ValueError,
8341
            "spawnve() arg 2 cannot be empty");
8342
        goto fail_0;
8343
    }
8344
    if (!PyMapping_Check(env)) {
8345
        PyErr_SetString(PyExc_TypeError,
8346
                        "spawnve() arg 3 must be a mapping object");
8347
        goto fail_0;
8348
    }
8349
8350
    argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
8351
    if (argvlist == NULL) {
8352
        PyErr_NoMemory();
8353
        goto fail_0;
8354
    }
8355
    for (i = 0; i < argc; i++) {
8356
        // The item must be a strong reference because of possible
8357
        // side-effects of PyUnicode_FS{Converter,Decoder}() in
8358
        // fsconvert_strdup(): an item's __fspath__() can mutate a list
8359
        // *argv*, releasing the list's reference to the item (gh-151416).
8360
        PyObject *item = PySequence_ITEM(argv, i);
8361
        if (item == NULL) {
8362
            lastarg = i;
8363
            goto fail_1;
8364
        }
8365
        if (!fsconvert_strdup(item, &argvlist[i])) {
8366
            Py_DECREF(item);
8367
            lastarg = i;
8368
            goto fail_1;
8369
        }
8370
        Py_DECREF(item);
8371
        if (i == 0 && !argvlist[0][0]) {
8372
            lastarg = i + 1;
8373
            PyErr_SetString(
8374
                PyExc_ValueError,
8375
                "spawnv() arg 2 first element cannot be empty");
8376
            goto fail_1;
8377
        }
8378
    }
8379
    lastarg = argc;
8380
    argvlist[argc] = NULL;
8381
8382
    envlist = parse_envlist(env, &envc);
8383
    if (envlist == NULL)
8384
        goto fail_1;
8385
8386
#if !defined(HAVE_RTPSPAWN)
8387
    if (mode == _OLD_P_OVERLAY)
8388
        mode = _P_OVERLAY;
8389
#endif
8390
8391
    if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
8392
        goto fail_2;
8393
    }
8394
8395
    Py_BEGIN_ALLOW_THREADS
8396
    _Py_BEGIN_SUPPRESS_IPH
8397
#ifdef HAVE_WSPAWNV
8398
    spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
8399
#elif defined(HAVE_RTPSPAWN)
8400
    spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
8401
                           (const char **)envlist);
8402
#else
8403
    spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
8404
#endif
8405
    _Py_END_SUPPRESS_IPH
8406
    Py_END_ALLOW_THREADS
8407
8408
    if (spawnval == -1)
8409
        (void) posix_error();
8410
    else
8411
        res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
8412
8413
  fail_2:
8414
    while (--envc >= 0) {
8415
        PyMem_Free(envlist[envc]);
8416
    }
8417
    PyMem_Free(envlist);
8418
  fail_1:
8419
    free_string_array(argvlist, lastarg);
8420
  fail_0:
8421
    return res;
8422
}
8423
8424
#endif /* HAVE_SPAWNV */
8425
8426
#ifdef HAVE_FORK
8427
8428
/* Helper function to validate arguments.
8429
   Returns 0 on success.  non-zero on failure with a TypeError raised.
8430
   If obj is non-NULL it must be callable.  */
8431
static int
8432
check_null_or_callable(PyObject *obj, const char* obj_name)
8433
60
{
8434
60
    if (obj && !PyCallable_Check(obj)) {
8435
0
        PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
8436
0
                     obj_name, _PyType_Name(Py_TYPE(obj)));
8437
0
        return -1;
8438
0
    }
8439
60
    return 0;
8440
60
}
8441
8442
/*[clinic input]
8443
os.register_at_fork
8444
8445
    *
8446
    before: object=NULL
8447
        A callable to be called in the parent before the fork() syscall.
8448
    after_in_child: object=NULL
8449
        A callable to be called in the child after fork().
8450
    after_in_parent: object=NULL
8451
        A callable to be called in the parent after fork().
8452
8453
Register callables to be called when forking a new process.
8454
8455
'before' callbacks are called in reverse order.
8456
'after_in_child' and 'after_in_parent' callbacks are called in order.
8457
8458
[clinic start generated code]*/
8459
8460
static PyObject *
8461
os_register_at_fork_impl(PyObject *module, PyObject *before,
8462
                         PyObject *after_in_child, PyObject *after_in_parent)
8463
/*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
8464
20
{
8465
20
    PyInterpreterState *interp;
8466
8467
20
    if (!before && !after_in_child && !after_in_parent) {
8468
0
        PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
8469
0
        return NULL;
8470
0
    }
8471
20
    if (check_null_or_callable(before, "before") ||
8472
20
        check_null_or_callable(after_in_child, "after_in_child") ||
8473
20
        check_null_or_callable(after_in_parent, "after_in_parent")) {
8474
0
        return NULL;
8475
0
    }
8476
20
    interp = _PyInterpreterState_GET();
8477
8478
20
    if (register_at_forker(&interp->before_forkers, before)) {
8479
0
        return NULL;
8480
0
    }
8481
20
    if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
8482
0
        return NULL;
8483
0
    }
8484
20
    if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
8485
0
        return NULL;
8486
0
    }
8487
20
    Py_RETURN_NONE;
8488
20
}
8489
#endif /* HAVE_FORK */
8490
8491
#if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK)
8492
// Common code to raise a warning if we detect there is more than one thread
8493
// running in the process. Best effort, silent if unable to count threads.
8494
// Constraint: Quick. Never overcounts. Never leaves an error set.
8495
//
8496
// This MUST only be called from the parent process after
8497
// PyOS_AfterFork_Parent().
8498
static int
8499
warn_about_fork_with_threads(
8500
    const char* name,  // Name of the API to use in the warning message.
8501
    const Py_ssize_t num_os_threads  // Only trusted when >= 1.
8502
)
8503
0
{
8504
    // It's not safe to issue the warning while the world is stopped, because
8505
    // other threads might be holding locks that we need, which would deadlock.
8506
0
    assert(!_PyRuntime.stoptheworld.world_stopped);
8507
8508
0
    Py_ssize_t num_python_threads = num_os_threads;
8509
0
    if (num_python_threads <= 0) {
8510
        // Fall back to just the number our threading module knows about.
8511
        // An incomplete view of the world, but better than nothing.
8512
0
        PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
8513
0
        if (!threading) {
8514
0
            PyErr_Clear();
8515
0
            return 0;
8516
0
        }
8517
0
        PyObject *threading_active =
8518
0
                PyObject_GetAttr(threading, &_Py_ID(_active));
8519
0
        if (!threading_active) {
8520
0
            PyErr_Clear();
8521
0
            Py_DECREF(threading);
8522
0
            return 0;
8523
0
        }
8524
0
        PyObject *threading_limbo =
8525
0
                PyObject_GetAttr(threading, &_Py_ID(_limbo));
8526
0
        if (!threading_limbo) {
8527
0
            PyErr_Clear();
8528
0
            Py_DECREF(threading);
8529
0
            Py_DECREF(threading_active);
8530
0
            return 0;
8531
0
        }
8532
0
        Py_DECREF(threading);
8533
        // Duplicating what threading.active_count() does but without holding
8534
        // threading._active_limbo_lock so our count could be inaccurate if
8535
        // these dicts are mid-update from another thread.  Not a big deal.
8536
        // Worst case if someone replaced threading._active or threading._limbo
8537
        // with non-dicts, we get -1 from *Length() below and undercount.
8538
        // Nobody should, but we're best effort so we clear errors and move on.
8539
0
        num_python_threads = (PyMapping_Length(threading_active)
8540
0
                              + PyMapping_Length(threading_limbo));
8541
0
        PyErr_Clear();
8542
0
        Py_DECREF(threading_active);
8543
0
        Py_DECREF(threading_limbo);
8544
0
    }
8545
0
    if (num_python_threads > 1) {
8546
0
        return PyErr_WarnFormat(
8547
0
                PyExc_DeprecationWarning, 1,
8548
0
#ifdef HAVE_GETPID
8549
0
                "This process (pid=%d) is multi-threaded, "
8550
#else
8551
                "This process is multi-threaded, "
8552
#endif
8553
0
                "use of %s() may lead to deadlocks in the child.",
8554
0
#ifdef HAVE_GETPID
8555
0
                getpid(),
8556
0
#endif
8557
0
                name);
8558
0
    }
8559
0
    return 0;
8560
0
}
8561
8562
// If this returns <= 0, we were unable to successfully use any OS APIs.
8563
// Returns a positive number of threads otherwise.
8564
static Py_ssize_t get_number_of_os_threads(void)
8565
0
{
8566
    // TODO: Consider making an `os` module API to return the current number
8567
    // of threads in the process. That'd presumably use this platform code but
8568
    // raise an error rather than using the inaccurate fallback.
8569
0
    Py_ssize_t num_python_threads = 0;
8570
#if defined(__APPLE__) && defined(HAVE_GETPID)
8571
    mach_port_t macos_self = mach_task_self();
8572
    mach_port_t macos_task;
8573
    if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) {
8574
        thread_array_t macos_threads;
8575
        mach_msg_type_number_t macos_n_threads;
8576
        if (task_threads(macos_task, &macos_threads,
8577
                         &macos_n_threads) == KERN_SUCCESS) {
8578
            num_python_threads = macos_n_threads;
8579
        }
8580
    }
8581
#elif defined(__linux__)
8582
    // Linux /proc/self/stat 20th field is the number of threads.
8583
0
    FILE* proc_stat = fopen("/proc/self/stat", "r");
8584
0
    if (proc_stat) {
8585
0
        size_t n;
8586
        // Size chosen arbitrarily. ~60% more bytes than a 20th column index
8587
        // observed on the author's workstation.
8588
0
        char stat_line[160];
8589
0
        n = fread(&stat_line, 1, 159, proc_stat);
8590
0
        stat_line[n] = '\0';
8591
0
        fclose(proc_stat);
8592
8593
0
        char *saveptr = NULL;
8594
0
        char *field = strtok_r(stat_line, " ", &saveptr);
8595
0
        unsigned int idx;
8596
0
        for (idx = 19; idx && field; --idx) {
8597
0
            field = strtok_r(NULL, " ", &saveptr);
8598
0
        }
8599
0
        if (idx == 0 && field) {  // found the 20th field
8600
0
            num_python_threads = atoi(field);  // 0 on error
8601
0
        }
8602
0
    }
8603
0
#endif
8604
0
    return num_python_threads;
8605
0
}
8606
#endif  // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
8607
8608
#ifdef HAVE_FORK1
8609
/*[clinic input]
8610
os.fork1
8611
8612
Fork a child process with a single multiplexed (i.e., not bound) thread.
8613
8614
Return 0 to child process and PID of child to parent process.
8615
[clinic start generated code]*/
8616
8617
static PyObject *
8618
os_fork1_impl(PyObject *module)
8619
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
8620
{
8621
    pid_t pid;
8622
8623
    PyInterpreterState *interp = _PyInterpreterState_GET();
8624
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8625
        PyErr_SetString(PyExc_PythonFinalizationError,
8626
                        "can't fork at interpreter shutdown");
8627
        return NULL;
8628
    }
8629
    if (!_Py_IsMainInterpreter(interp)) {
8630
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
8631
        return NULL;
8632
    }
8633
    PyOS_BeforeFork();
8634
    pid = fork1();
8635
    int saved_errno = errno;
8636
    if (pid == 0) {
8637
        /* child: this clobbers and resets the import lock. */
8638
        PyOS_AfterFork_Child();
8639
    } else {
8640
        // Called before AfterFork_Parent in case those hooks start threads.
8641
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8642
        /* parent: release the import lock. */
8643
        PyOS_AfterFork_Parent();
8644
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8645
        if (warn_about_fork_with_threads("fork1", num_os_threads) < 0) {
8646
            return NULL;
8647
        }
8648
    }
8649
    if (pid == -1) {
8650
        errno = saved_errno;
8651
        return posix_error();
8652
    }
8653
    return PyLong_FromPid(pid);
8654
}
8655
#endif /* HAVE_FORK1 */
8656
8657
8658
#ifdef HAVE_FORK
8659
/*[clinic input]
8660
os.fork
8661
8662
Fork a child process.
8663
8664
Return 0 to child process and PID of child to parent process.
8665
[clinic start generated code]*/
8666
8667
static PyObject *
8668
os_fork_impl(PyObject *module)
8669
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
8670
0
{
8671
0
    pid_t pid;
8672
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
8673
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
8674
0
        PyErr_SetString(PyExc_PythonFinalizationError,
8675
0
                        "can't fork at interpreter shutdown");
8676
0
        return NULL;
8677
0
    }
8678
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) {
8679
0
        PyErr_SetString(PyExc_RuntimeError,
8680
0
                        "fork not supported for isolated subinterpreters");
8681
0
        return NULL;
8682
0
    }
8683
0
    if (PySys_Audit("os.fork", NULL) < 0) {
8684
0
        return NULL;
8685
0
    }
8686
0
    PyOS_BeforeFork();
8687
0
    pid = fork();
8688
0
    int saved_errno = errno;
8689
0
    if (pid == 0) {
8690
        /* child: this clobbers and resets the import lock. */
8691
0
        PyOS_AfterFork_Child();
8692
0
    } else {
8693
        // Called before AfterFork_Parent in case those hooks start threads.
8694
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
8695
        /* parent: release the import lock. */
8696
0
        PyOS_AfterFork_Parent();
8697
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
8698
0
        if (warn_about_fork_with_threads("fork", num_os_threads) < 0)
8699
0
            return NULL;
8700
0
    }
8701
0
    if (pid == -1) {
8702
0
        errno = saved_errno;
8703
0
        return posix_error();
8704
0
    }
8705
0
    return PyLong_FromPid(pid);
8706
0
}
8707
#endif /* HAVE_FORK */
8708
8709
8710
#ifdef HAVE_SCHED_H
8711
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
8712
/*[clinic input]
8713
os.sched_get_priority_max
8714
8715
    policy: int
8716
8717
Get the maximum scheduling priority for policy.
8718
[clinic start generated code]*/
8719
8720
static PyObject *
8721
os_sched_get_priority_max_impl(PyObject *module, int policy)
8722
/*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
8723
0
{
8724
    /* make sure that errno is cleared before the call */
8725
0
    errno = 0;
8726
0
    int max = sched_get_priority_max(policy);
8727
0
    if (max == -1 && errno)
8728
0
        return posix_error();
8729
0
    return PyLong_FromLong(max);
8730
0
}
8731
8732
8733
/*[clinic input]
8734
os.sched_get_priority_min
8735
8736
    policy: int
8737
8738
Get the minimum scheduling priority for policy.
8739
[clinic start generated code]*/
8740
8741
static PyObject *
8742
os_sched_get_priority_min_impl(PyObject *module, int policy)
8743
/*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
8744
0
{
8745
    /* make sure that errno is cleared before the call */
8746
0
    errno = 0;
8747
0
    int min = sched_get_priority_min(policy);
8748
0
    if (min == -1 && errno)
8749
0
        return posix_error();
8750
0
    return PyLong_FromLong(min);
8751
0
}
8752
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
8753
8754
8755
#ifdef HAVE_SCHED_SETSCHEDULER
8756
/*[clinic input]
8757
os.sched_getscheduler
8758
    pid: pid_t
8759
    /
8760
8761
Get the scheduling policy for the process identified by pid.
8762
8763
Passing 0 for pid returns the scheduling policy for the calling process.
8764
[clinic start generated code]*/
8765
8766
static PyObject *
8767
os_sched_getscheduler_impl(PyObject *module, pid_t pid)
8768
/*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
8769
0
{
8770
0
    int policy;
8771
8772
0
    policy = sched_getscheduler(pid);
8773
0
    if (policy < 0)
8774
0
        return posix_error();
8775
0
    return PyLong_FromLong(policy);
8776
0
}
8777
#endif /* HAVE_SCHED_SETSCHEDULER */
8778
8779
8780
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
8781
/*[clinic input]
8782
class os.sched_param "PyObject *" "SchedParamType"
8783
8784
@classmethod
8785
os.sched_param.__new__
8786
8787
    sched_priority: object
8788
        A scheduling parameter.
8789
8790
Currently has only one field: sched_priority
8791
[clinic start generated code]*/
8792
8793
static PyObject *
8794
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
8795
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
8796
0
{
8797
0
    PyObject *res;
8798
8799
0
    res = PyStructSequence_New(type);
8800
0
    if (!res)
8801
0
        return NULL;
8802
0
    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority));
8803
0
    return res;
8804
0
}
8805
8806
static PyObject *
8807
os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
8808
0
{
8809
0
    return Py_BuildValue("(O(O))", Py_TYPE(self), PyStructSequence_GetItem(self, 0));
8810
0
}
8811
8812
static PyMethodDef os_sched_param_reduce_method = {
8813
    "__reduce__", os_sched_param_reduce, METH_NOARGS | METH_COEXIST, NULL,
8814
};
8815
8816
PyDoc_VAR(os_sched_param__doc__);
8817
8818
static PyStructSequence_Field sched_param_fields[] = {
8819
    {"sched_priority", "the scheduling priority"},
8820
    {0}
8821
};
8822
8823
static PyStructSequence_Desc sched_param_desc = {
8824
    MODNAME ".sched_param", /* name */
8825
    os_sched_param__doc__, /* doc */
8826
    sched_param_fields,
8827
    1
8828
};
8829
8830
static int
8831
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
8832
0
{
8833
0
    long priority;
8834
8835
0
    if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
8836
0
        PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
8837
0
        return 0;
8838
0
    }
8839
0
    priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
8840
0
    if (priority == -1 && PyErr_Occurred())
8841
0
        return 0;
8842
0
    if (priority > INT_MAX || priority < INT_MIN) {
8843
0
        PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
8844
0
        return 0;
8845
0
    }
8846
0
    res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
8847
0
    return 1;
8848
0
}
8849
#endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
8850
8851
8852
#ifdef HAVE_SCHED_SETSCHEDULER
8853
/*[clinic input]
8854
os.sched_setscheduler
8855
8856
    pid: pid_t
8857
    policy: int
8858
    param as param_obj: object
8859
    /
8860
8861
Set the scheduling policy for the process identified by pid.
8862
8863
If pid is 0, the calling process is changed.
8864
param is an instance of sched_param.
8865
[clinic start generated code]*/
8866
8867
static PyObject *
8868
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
8869
                           PyObject *param_obj)
8870
/*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
8871
0
{
8872
0
    struct sched_param param;
8873
0
    if (!convert_sched_param(module, param_obj, &param)) {
8874
0
        return NULL;
8875
0
    }
8876
8877
    /*
8878
    ** sched_setscheduler() returns 0 in Linux, but the previous
8879
    ** scheduling policy under Solaris/Illumos, and others.
8880
    ** On error, -1 is returned in all Operating Systems.
8881
    */
8882
0
    if (sched_setscheduler(pid, policy, &param) == -1)
8883
0
        return posix_error();
8884
0
    Py_RETURN_NONE;
8885
0
}
8886
#endif  /* HAVE_SCHED_SETSCHEDULER*/
8887
8888
8889
#ifdef HAVE_SCHED_SETPARAM
8890
/*[clinic input]
8891
os.sched_getparam
8892
    pid: pid_t
8893
    /
8894
8895
Returns scheduling parameters for the process identified by pid.
8896
8897
If pid is 0, returns parameters for the calling process.
8898
Return value is an instance of sched_param.
8899
[clinic start generated code]*/
8900
8901
static PyObject *
8902
os_sched_getparam_impl(PyObject *module, pid_t pid)
8903
/*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
8904
0
{
8905
0
    struct sched_param param;
8906
0
    PyObject *result;
8907
0
    PyObject *priority;
8908
8909
0
    if (sched_getparam(pid, &param))
8910
0
        return posix_error();
8911
0
    PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
8912
0
    result = PyStructSequence_New((PyTypeObject *)SchedParamType);
8913
0
    if (!result)
8914
0
        return NULL;
8915
0
    priority = PyLong_FromLong(param.sched_priority);
8916
0
    if (!priority) {
8917
0
        Py_DECREF(result);
8918
0
        return NULL;
8919
0
    }
8920
0
    PyStructSequence_SET_ITEM(result, 0, priority);
8921
0
    return result;
8922
0
}
8923
8924
8925
/*[clinic input]
8926
os.sched_setparam
8927
    pid: pid_t
8928
    param as param_obj: object
8929
    /
8930
8931
Set scheduling parameters for the process identified by pid.
8932
8933
If pid is 0, sets parameters for the calling process.
8934
param should be an instance of sched_param.
8935
[clinic start generated code]*/
8936
8937
static PyObject *
8938
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
8939
/*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
8940
0
{
8941
0
    struct sched_param param;
8942
0
    if (!convert_sched_param(module, param_obj, &param)) {
8943
0
        return NULL;
8944
0
    }
8945
8946
0
    if (sched_setparam(pid, &param))
8947
0
        return posix_error();
8948
0
    Py_RETURN_NONE;
8949
0
}
8950
#endif /* HAVE_SCHED_SETPARAM */
8951
8952
8953
#ifdef HAVE_SCHED_RR_GET_INTERVAL
8954
/*[clinic input]
8955
@permit_long_summary
8956
os.sched_rr_get_interval -> double
8957
    pid: pid_t
8958
    /
8959
8960
Return the round-robin quantum for the process identified by pid, in seconds.
8961
8962
Value returned is a float.
8963
[clinic start generated code]*/
8964
8965
static double
8966
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
8967
/*[clinic end generated code: output=7e2d935833ab47dc input=cab0b83586776b10]*/
8968
0
{
8969
0
    struct timespec interval;
8970
0
    if (sched_rr_get_interval(pid, &interval)) {
8971
0
        posix_error();
8972
0
        return -1.0;
8973
0
    }
8974
#ifdef _Py_MEMORY_SANITIZER
8975
    __msan_unpoison(&interval, sizeof(interval));
8976
#endif
8977
0
    return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
8978
0
}
8979
#endif /* HAVE_SCHED_RR_GET_INTERVAL */
8980
8981
8982
/*[clinic input]
8983
os.sched_yield
8984
8985
Voluntarily relinquish the CPU.
8986
[clinic start generated code]*/
8987
8988
static PyObject *
8989
os_sched_yield_impl(PyObject *module)
8990
/*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
8991
0
{
8992
0
    int result;
8993
0
    Py_BEGIN_ALLOW_THREADS
8994
0
    result = sched_yield();
8995
0
    Py_END_ALLOW_THREADS
8996
0
    if (result < 0) {
8997
0
        return posix_error();
8998
0
    }
8999
0
    Py_RETURN_NONE;
9000
0
}
9001
9002
#ifdef HAVE_SCHED_SETAFFINITY
9003
/* The minimum number of CPUs allocated in a cpu_set_t */
9004
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
9005
9006
/*[clinic input]
9007
os.sched_setaffinity
9008
    pid: pid_t
9009
    mask : object
9010
    /
9011
9012
Set the CPU affinity of the process identified by pid to mask.
9013
9014
mask should be an iterable of integers identifying CPUs.
9015
[clinic start generated code]*/
9016
9017
static PyObject *
9018
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
9019
/*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
9020
0
{
9021
0
    int ncpus;
9022
0
    size_t setsize;
9023
0
    cpu_set_t *cpu_set = NULL;
9024
0
    PyObject *iterator = NULL, *item;
9025
9026
0
    iterator = PyObject_GetIter(mask);
9027
0
    if (iterator == NULL)
9028
0
        return NULL;
9029
9030
0
    ncpus = NCPUS_START;
9031
0
    setsize = CPU_ALLOC_SIZE(ncpus);
9032
0
    cpu_set = CPU_ALLOC(ncpus);
9033
0
    if (cpu_set == NULL) {
9034
0
        PyErr_NoMemory();
9035
0
        goto error;
9036
0
    }
9037
0
    CPU_ZERO_S(setsize, cpu_set);
9038
9039
0
    while ((item = PyIter_Next(iterator))) {
9040
0
        long cpu;
9041
0
        if (!PyIndex_Check(item)) {
9042
0
            PyErr_Format(PyExc_TypeError,
9043
0
                        "expected an iterator of ints, "
9044
0
                        "but iterator yielded %R",
9045
0
                        Py_TYPE(item));
9046
0
            Py_DECREF(item);
9047
0
            goto error;
9048
0
        }
9049
0
        cpu = PyLong_AsLong(item);
9050
0
        Py_DECREF(item);
9051
0
        if (cpu < 0) {
9052
0
            if (!PyErr_Occurred())
9053
0
                PyErr_SetString(PyExc_ValueError, "negative CPU number");
9054
0
            goto error;
9055
0
        }
9056
0
        if (cpu > INT_MAX - 1) {
9057
0
            PyErr_SetString(PyExc_OverflowError, "CPU number too large");
9058
0
            goto error;
9059
0
        }
9060
0
        if (cpu >= ncpus) {
9061
            /* Grow CPU mask to fit the CPU number */
9062
0
            int newncpus = ncpus;
9063
0
            cpu_set_t *newmask;
9064
0
            size_t newsetsize;
9065
0
            while (newncpus <= cpu) {
9066
0
                if (newncpus > INT_MAX / 2)
9067
0
                    newncpus = cpu + 1;
9068
0
                else
9069
0
                    newncpus = newncpus * 2;
9070
0
            }
9071
0
            newmask = CPU_ALLOC(newncpus);
9072
0
            if (newmask == NULL) {
9073
0
                PyErr_NoMemory();
9074
0
                goto error;
9075
0
            }
9076
0
            newsetsize = CPU_ALLOC_SIZE(newncpus);
9077
0
            CPU_ZERO_S(newsetsize, newmask);
9078
0
            memcpy(newmask, cpu_set, setsize);
9079
0
            CPU_FREE(cpu_set);
9080
0
            setsize = newsetsize;
9081
0
            cpu_set = newmask;
9082
0
            ncpus = newncpus;
9083
0
        }
9084
0
        CPU_SET_S(cpu, setsize, cpu_set);
9085
0
    }
9086
0
    if (PyErr_Occurred()) {
9087
0
        goto error;
9088
0
    }
9089
0
    Py_CLEAR(iterator);
9090
9091
0
    if (sched_setaffinity(pid, setsize, cpu_set)) {
9092
0
        posix_error();
9093
0
        goto error;
9094
0
    }
9095
0
    CPU_FREE(cpu_set);
9096
0
    Py_RETURN_NONE;
9097
9098
0
error:
9099
0
    if (cpu_set)
9100
0
        CPU_FREE(cpu_set);
9101
0
    Py_XDECREF(iterator);
9102
0
    return NULL;
9103
0
}
9104
9105
9106
/*[clinic input]
9107
@permit_long_summary
9108
os.sched_getaffinity
9109
    pid: pid_t
9110
    /
9111
9112
Return the affinity of the process identified by pid (or the current process if zero).
9113
9114
The affinity is returned as a set of CPU identifiers.
9115
[clinic start generated code]*/
9116
9117
static PyObject *
9118
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
9119
/*[clinic end generated code: output=f726f2c193c17a4f input=cb79ff13579ef091]*/
9120
0
{
9121
0
    int ncpus = NCPUS_START;
9122
0
    size_t setsize;
9123
0
    cpu_set_t *mask;
9124
9125
0
    while (1) {
9126
0
        setsize = CPU_ALLOC_SIZE(ncpus);
9127
0
        mask = CPU_ALLOC(ncpus);
9128
0
        if (mask == NULL) {
9129
0
            return PyErr_NoMemory();
9130
0
        }
9131
0
        if (sched_getaffinity(pid, setsize, mask) == 0) {
9132
0
            break;
9133
0
        }
9134
0
        CPU_FREE(mask);
9135
0
        if (errno != EINVAL) {
9136
0
            return posix_error();
9137
0
        }
9138
0
        if (ncpus > INT_MAX / 2) {
9139
0
            PyErr_SetString(PyExc_OverflowError,
9140
0
                            "could not allocate a large enough CPU set");
9141
0
            return NULL;
9142
0
        }
9143
0
        ncpus *= 2;
9144
0
    }
9145
9146
0
    PyObject *res = PySet_New(NULL);
9147
0
    if (res == NULL) {
9148
0
        goto error;
9149
0
    }
9150
9151
0
    int cpu = 0;
9152
0
    int count = CPU_COUNT_S(setsize, mask);
9153
0
    for (; count; cpu++) {
9154
0
        if (CPU_ISSET_S(cpu, setsize, mask)) {
9155
0
            PyObject *cpu_num = PyLong_FromLong(cpu);
9156
0
            --count;
9157
0
            if (cpu_num == NULL) {
9158
0
                goto error;
9159
0
            }
9160
0
            if (PySet_Add(res, cpu_num)) {
9161
0
                Py_DECREF(cpu_num);
9162
0
                goto error;
9163
0
            }
9164
0
            Py_DECREF(cpu_num);
9165
0
        }
9166
0
    }
9167
0
    CPU_FREE(mask);
9168
0
    return res;
9169
9170
0
error:
9171
0
    if (mask) {
9172
0
        CPU_FREE(mask);
9173
0
    }
9174
0
    Py_XDECREF(res);
9175
0
    return NULL;
9176
0
}
9177
#endif /* HAVE_SCHED_SETAFFINITY */
9178
9179
#endif /* HAVE_SCHED_H */
9180
9181
9182
#ifdef HAVE_POSIX_OPENPT
9183
/*[clinic input]
9184
os.posix_openpt -> int
9185
9186
    oflag: int
9187
    /
9188
9189
Open and return a file descriptor for a master pseudo-terminal device.
9190
9191
Performs a posix_openpt() C function call. The oflag argument is used to
9192
set file status flags and file access modes as specified in the manual
9193
page of posix_openpt() of your system.
9194
[clinic start generated code]*/
9195
9196
static int
9197
os_posix_openpt_impl(PyObject *module, int oflag)
9198
/*[clinic end generated code: output=ee0bc2624305fc79 input=3ce4eb297fa64307]*/
9199
0
{
9200
0
    int fd;
9201
9202
    // OpenBSD posix_openpt() rejects any flag other than O_RDWR and
9203
    // O_NOCTTY; the fd is made non-inheritable below in any case.
9204
0
#if defined(O_CLOEXEC) && !defined(__OpenBSD__)
9205
0
    oflag |= O_CLOEXEC;
9206
0
#endif
9207
9208
0
    fd = posix_openpt(oflag);
9209
0
    if (fd == -1) {
9210
0
        posix_error();
9211
0
        return -1;
9212
0
    }
9213
9214
    // Just in case, likely a no-op given O_CLOEXEC above.
9215
0
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
9216
0
        close(fd);
9217
0
        return -1;
9218
0
    }
9219
9220
0
    return fd;
9221
0
}
9222
#endif /* HAVE_POSIX_OPENPT */
9223
9224
#ifdef HAVE_GRANTPT
9225
/*[clinic input]
9226
os.grantpt
9227
9228
    fd: fildes
9229
        File descriptor of a master pseudo-terminal device.
9230
    /
9231
9232
Grant access to the slave pseudo-terminal device.
9233
9234
Performs a grantpt() C function call.
9235
[clinic start generated code]*/
9236
9237
static PyObject *
9238
os_grantpt_impl(PyObject *module, int fd)
9239
/*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/
9240
0
{
9241
0
    int ret;
9242
0
    int saved_errno;
9243
0
    PyOS_sighandler_t sig_saved;
9244
9245
0
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9246
9247
0
    ret = grantpt(fd);
9248
0
    if (ret == -1)
9249
0
        saved_errno = errno;
9250
9251
0
    PyOS_setsig(SIGCHLD, sig_saved);
9252
9253
0
    if (ret == -1) {
9254
0
        errno = saved_errno;
9255
0
        return posix_error();
9256
0
    }
9257
9258
0
    Py_RETURN_NONE;
9259
0
}
9260
#endif /* HAVE_GRANTPT */
9261
9262
#ifdef HAVE_UNLOCKPT
9263
/*[clinic input]
9264
os.unlockpt
9265
9266
    fd: fildes
9267
        File descriptor of a master pseudo-terminal device.
9268
    /
9269
9270
Unlock a pseudo-terminal master/slave pair.
9271
9272
Performs an unlockpt() C function call.
9273
[clinic start generated code]*/
9274
9275
static PyObject *
9276
os_unlockpt_impl(PyObject *module, int fd)
9277
/*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/
9278
0
{
9279
0
    if (unlockpt(fd) == -1)
9280
0
        return posix_error();
9281
9282
0
    Py_RETURN_NONE;
9283
0
}
9284
#endif /* HAVE_UNLOCKPT */
9285
9286
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
9287
static PyObject *
9288
py_ptsname(int fd)
9289
0
{
9290
0
    // POSIX manpage: Upon failure, ptsname() shall return a null pointer
9291
0
    // and may set errno. Always initialize errno to avoid undefined behavior.
9292
0
    errno = 0;
9293
0
    char *name = ptsname(fd);
9294
0
    if (name == NULL) {
9295
0
        return posix_error();
9296
0
    }
9297
0
    return PyUnicode_DecodeFSDefault(name);
9298
0
}
9299
9300
/*[clinic input]
9301
os.ptsname
9302
9303
    fd: fildes
9304
        File descriptor of a master pseudo-terminal device.
9305
    /
9306
9307
Return the name of the slave pseudo-terminal device.
9308
9309
If the ptsname_r() C function is available, it is called;
9310
otherwise, performs a ptsname() C function call.
9311
[clinic start generated code]*/
9312
9313
static PyObject *
9314
os_ptsname_impl(PyObject *module, int fd)
9315
/*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/
9316
0
{
9317
0
#ifdef HAVE_PTSNAME_R
9318
0
    int ret;
9319
0
    char name[MAXPATHLEN+1];
9320
9321
0
    if (HAVE_PTSNAME_R_RUNTIME) {
9322
0
        ret = ptsname_r(fd, name, sizeof(name));
9323
0
    }
9324
0
    else {
9325
        // fallback to ptsname() if ptsname_r() is not available in runtime.
9326
0
        return py_ptsname(fd);
9327
0
    }
9328
0
    if (ret != 0) {
9329
0
        errno = ret;
9330
0
        return posix_error();
9331
0
    }
9332
9333
0
    return PyUnicode_DecodeFSDefault(name);
9334
#else
9335
    return py_ptsname(fd);
9336
#endif /* HAVE_PTSNAME_R */
9337
0
}
9338
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
9339
9340
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
9341
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
9342
#  define DEV_PTY_FILE "/dev/ptc"
9343
#  define HAVE_DEV_PTMX
9344
#else
9345
#  define DEV_PTY_FILE "/dev/ptmx"
9346
#endif
9347
9348
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
9349
#ifdef HAVE_PTY_H
9350
#include <pty.h>
9351
#elif defined(HAVE_LIBUTIL_H)
9352
#include <libutil.h>
9353
#elif defined(HAVE_UTIL_H)
9354
#include <util.h>
9355
#endif /* HAVE_PTY_H */
9356
#ifdef HAVE_UTMP_H
9357
#include <utmp.h>
9358
#endif /* HAVE_UTMP_H */
9359
#ifdef HAVE_STROPTS_H
9360
#include <stropts.h>
9361
#endif
9362
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
9363
9364
9365
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
9366
/*[clinic input]
9367
os.openpty
9368
9369
Open a pseudo-terminal.
9370
9371
Return a tuple of (master_fd, slave_fd) containing open file descriptors
9372
for both the master and slave ends.
9373
[clinic start generated code]*/
9374
9375
static PyObject *
9376
os_openpty_impl(PyObject *module)
9377
/*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
9378
0
{
9379
0
    int master_fd = -1, slave_fd = -1;
9380
#ifndef HAVE_OPENPTY
9381
    char * slave_name;
9382
#endif
9383
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
9384
    PyOS_sighandler_t sig_saved;
9385
#if defined(__sun) && defined(__SVR4)
9386
    extern char *ptsname(int fildes);
9387
#endif
9388
#endif
9389
9390
0
#ifdef HAVE_OPENPTY
9391
0
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
9392
0
        goto posix_error;
9393
9394
0
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9395
0
        goto error;
9396
0
    if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
9397
0
        goto error;
9398
9399
#elif defined(HAVE__GETPTY)
9400
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
9401
    if (slave_name == NULL)
9402
        goto posix_error;
9403
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9404
        goto error;
9405
9406
    slave_fd = _Py_open(slave_name, O_RDWR);
9407
    if (slave_fd < 0)
9408
        goto error;
9409
9410
#else
9411
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
9412
    if (master_fd < 0)
9413
        goto posix_error;
9414
9415
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
9416
9417
    /* change permission of slave */
9418
    if (grantpt(master_fd) < 0) {
9419
        int saved_errno = errno;
9420
        PyOS_setsig(SIGCHLD, sig_saved);
9421
        errno = saved_errno;
9422
        goto posix_error;
9423
    }
9424
9425
    /* unlock slave */
9426
    if (unlockpt(master_fd) < 0) {
9427
        int saved_errno = errno;
9428
        PyOS_setsig(SIGCHLD, sig_saved);
9429
        errno = saved_errno;
9430
        goto posix_error;
9431
    }
9432
9433
    PyOS_setsig(SIGCHLD, sig_saved);
9434
9435
    slave_name = ptsname(master_fd); /* get name of slave */
9436
    if (slave_name == NULL)
9437
        goto posix_error;
9438
9439
    slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
9440
    if (slave_fd == -1)
9441
        goto error;
9442
9443
    if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
9444
        goto posix_error;
9445
9446
#if defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC)
9447
    // Pushing "ptem" makes the slave a terminal, which a session leader
9448
    // without a controlling terminal then acquires as one despite O_NOCTTY.
9449
    // Note whether we already had one, so a new one can be disowned below.
9450
    int had_ctty = 0;
9451
#ifdef TIOCNOTTY
9452
    int tty_fd = open("/dev/tty", O_RDONLY | O_NOCTTY);
9453
    if (tty_fd >= 0) {
9454
        had_ctty = 1;
9455
        close(tty_fd);
9456
    }
9457
#endif
9458
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
9459
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
9460
#ifndef __hpux
9461
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
9462
#endif /* __hpux */
9463
#ifdef TIOCNOTTY
9464
    if (!had_ctty && getsid(0) == getpid()) {
9465
        // Disown it; TIOCNOTTY sends SIGHUP to the session leader.
9466
        PyOS_sighandler_t sig_saved = PyOS_setsig(SIGHUP, SIG_IGN);
9467
        ioctl(slave_fd, TIOCNOTTY);
9468
        PyOS_setsig(SIGHUP, sig_saved);
9469
    }
9470
#endif
9471
#endif /* defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC) */
9472
#endif /* HAVE_OPENPTY */
9473
9474
0
    return Py_BuildValue("(ii)", master_fd, slave_fd);
9475
9476
0
posix_error:
9477
0
    posix_error();
9478
0
error:
9479
0
    if (master_fd != -1)
9480
0
        close(master_fd);
9481
0
    if (slave_fd != -1)
9482
0
        close(slave_fd);
9483
0
    return NULL;
9484
0
}
9485
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
9486
9487
9488
#if defined(HAVE_SETSID) && defined(TIOCSCTTY)
9489
#define HAVE_FALLBACK_LOGIN_TTY 1
9490
#endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
9491
9492
#if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
9493
/*[clinic input]
9494
@permit_long_summary
9495
os.login_tty
9496
9497
    fd: fildes
9498
    /
9499
9500
Prepare the tty of which fd is a file descriptor for a new login session.
9501
9502
Make the calling process a session leader; make the tty the
9503
controlling tty, the stdin, the stdout, and the stderr of the
9504
calling process; close fd.
9505
[clinic start generated code]*/
9506
9507
static PyObject *
9508
os_login_tty_impl(PyObject *module, int fd)
9509
/*[clinic end generated code: output=495a79911b4cc1bc input=b102a7c36e8baf00]*/
9510
0
{
9511
0
#ifdef HAVE_LOGIN_TTY
9512
0
    if (login_tty(fd) == -1) {
9513
0
        return posix_error();
9514
0
    }
9515
#else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
9516
    /* Establish a new session. */
9517
    if (setsid() == -1) {
9518
        return posix_error();
9519
    }
9520
9521
    /* The tty becomes the controlling terminal. */
9522
    if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
9523
        return posix_error();
9524
    }
9525
9526
    /* The tty becomes stdin/stdout/stderr */
9527
    if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
9528
        return posix_error();
9529
    }
9530
    if (fd > 2) {
9531
        close(fd);
9532
    }
9533
#endif /* HAVE_LOGIN_TTY */
9534
0
    Py_RETURN_NONE;
9535
0
}
9536
#endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
9537
9538
9539
#ifdef HAVE_FORKPTY
9540
/*[clinic input]
9541
os.forkpty
9542
9543
Fork a new process with a new pseudo-terminal as controlling tty.
9544
9545
Returns a tuple of (pid, master_fd).
9546
Like fork(), return pid of 0 to the child process,
9547
and pid of child to the parent process.
9548
To both, return fd of newly opened pseudo-terminal.
9549
The master_fd is non-inheritable.
9550
[clinic start generated code]*/
9551
9552
static PyObject *
9553
os_forkpty_impl(PyObject *module)
9554
/*[clinic end generated code: output=60d0a5c7512e4087 input=24765e0f33275b3b]*/
9555
0
{
9556
0
    int master_fd = -1;
9557
0
    pid_t pid;
9558
9559
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
9560
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
9561
0
        PyErr_SetString(PyExc_PythonFinalizationError,
9562
0
                        "can't fork at interpreter shutdown");
9563
0
        return NULL;
9564
0
    }
9565
0
    if (!_Py_IsMainInterpreter(interp)) {
9566
0
        PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
9567
0
        return NULL;
9568
0
    }
9569
0
    if (PySys_Audit("os.forkpty", NULL) < 0) {
9570
0
        return NULL;
9571
0
    }
9572
0
    PyOS_BeforeFork();
9573
0
    pid = forkpty(&master_fd, NULL, NULL, NULL);
9574
0
    if (pid == 0) {
9575
        /* child: this clobbers and resets the import lock. */
9576
0
        PyOS_AfterFork_Child();
9577
0
    } else {
9578
        // Called before AfterFork_Parent in case those hooks start threads.
9579
0
        Py_ssize_t num_os_threads = get_number_of_os_threads();
9580
        /* parent: release the import lock. */
9581
0
        PyOS_AfterFork_Parent();
9582
        /* set O_CLOEXEC on master_fd */
9583
0
        if (_Py_set_inheritable(master_fd, 0, NULL) < 0) {
9584
0
            PyErr_FormatUnraisable("Exception ignored when setting master_fd "
9585
0
                                   "non-inheritable in forkpty()");
9586
0
        }
9587
9588
        // After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
9589
0
        if (warn_about_fork_with_threads("forkpty", num_os_threads) < 0)
9590
0
            return NULL;
9591
0
    }
9592
0
    if (pid == -1) {
9593
0
        return posix_error();
9594
0
    }
9595
9596
0
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
9597
0
}
9598
#endif /* HAVE_FORKPTY */
9599
9600
9601
#ifdef HAVE_GETEGID
9602
/*[clinic input]
9603
os.getegid
9604
9605
Return the current process's effective group id.
9606
[clinic start generated code]*/
9607
9608
static PyObject *
9609
os_getegid_impl(PyObject *module)
9610
/*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
9611
37
{
9612
37
    return _PyLong_FromGid(getegid());
9613
37
}
9614
#endif /* HAVE_GETEGID */
9615
9616
9617
#ifdef HAVE_GETEUID
9618
/*[clinic input]
9619
os.geteuid
9620
9621
Return the current process's effective user id.
9622
[clinic start generated code]*/
9623
9624
static PyObject *
9625
os_geteuid_impl(PyObject *module)
9626
/*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
9627
37
{
9628
37
    return _PyLong_FromUid(geteuid());
9629
37
}
9630
#endif /* HAVE_GETEUID */
9631
9632
9633
#ifdef HAVE_GETGID
9634
/*[clinic input]
9635
os.getgid
9636
9637
Return the current process's group id.
9638
[clinic start generated code]*/
9639
9640
static PyObject *
9641
os_getgid_impl(PyObject *module)
9642
/*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
9643
37
{
9644
37
    return _PyLong_FromGid(getgid());
9645
37
}
9646
#endif /* HAVE_GETGID */
9647
9648
9649
#if defined(HAVE_GETPID)
9650
/*[clinic input]
9651
os.getpid
9652
9653
Return the current process id.
9654
[clinic start generated code]*/
9655
9656
static PyObject *
9657
os_getpid_impl(PyObject *module)
9658
/*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
9659
4.12k
{
9660
4.12k
#if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
9661
4.12k
    return PyLong_FromPid(getpid());
9662
#else
9663
    return PyLong_FromUnsignedLong(GetCurrentProcessId());
9664
#endif
9665
4.12k
}
9666
#endif /* defined(HAVE_GETPID) */
9667
9668
#ifdef NGROUPS_MAX
9669
0
#define MAX_GROUPS NGROUPS_MAX
9670
#else
9671
    /* defined to be 16 on Solaris7, so this should be a small number */
9672
#define MAX_GROUPS 64
9673
#endif
9674
9675
#ifdef HAVE_GETGROUPLIST
9676
9677
#ifdef __APPLE__
9678
/*[clinic input]
9679
os.getgrouplist
9680
9681
    user: str
9682
        username to lookup
9683
    group as basegid: int
9684
        base group id of the user
9685
    /
9686
9687
Returns a list of groups to which a user belongs.
9688
[clinic start generated code]*/
9689
9690
static PyObject *
9691
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
9692
/*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
9693
#else
9694
/*[clinic input]
9695
os.getgrouplist
9696
9697
    user: str
9698
        username to lookup
9699
    group as basegid: gid_t
9700
        base group id of the user
9701
    /
9702
9703
Returns a list of groups to which a user belongs.
9704
[clinic start generated code]*/
9705
9706
static PyObject *
9707
os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
9708
/*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
9709
#endif
9710
0
{
9711
0
    int i, ngroups;
9712
0
    PyObject *list;
9713
#ifdef __APPLE__
9714
    int *groups;
9715
#else
9716
0
    gid_t *groups;
9717
0
#endif
9718
9719
    /*
9720
     * NGROUPS_MAX is defined by POSIX.1 as the maximum
9721
     * number of supplemental groups a users can belong to.
9722
     * We have to increment it by one because
9723
     * getgrouplist() returns both the supplemental groups
9724
     * and the primary group, i.e. all of the groups the
9725
     * user belongs to.
9726
     */
9727
0
    ngroups = 1 + MAX_GROUPS;
9728
9729
0
    while (1) {
9730
#ifdef __APPLE__
9731
        groups = PyMem_New(int, ngroups);
9732
#else
9733
0
        groups = PyMem_New(gid_t, ngroups);
9734
0
#endif
9735
0
        if (groups == NULL) {
9736
0
            return PyErr_NoMemory();
9737
0
        }
9738
9739
0
        int old_ngroups = ngroups;
9740
0
        if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
9741
            /* Success */
9742
0
            break;
9743
0
        }
9744
9745
        /* getgrouplist() fails if the group list is too small */
9746
0
        PyMem_Free(groups);
9747
9748
0
        if (ngroups > old_ngroups) {
9749
            /* If the group list is too small, the glibc implementation of
9750
               getgrouplist() sets ngroups to the total number of groups and
9751
               returns -1. */
9752
0
        }
9753
0
        else {
9754
            /* Double the group list size */
9755
0
            if (ngroups > INT_MAX / 2) {
9756
0
                return PyErr_NoMemory();
9757
0
            }
9758
0
            ngroups *= 2;
9759
0
        }
9760
9761
        /* Retry getgrouplist() with a larger group list */
9762
0
    }
9763
9764
#ifdef _Py_MEMORY_SANITIZER
9765
    /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
9766
    __msan_unpoison(&ngroups, sizeof(ngroups));
9767
    __msan_unpoison(groups, ngroups*sizeof(*groups));
9768
#endif
9769
9770
0
    list = PyList_New(ngroups);
9771
0
    if (list == NULL) {
9772
0
        PyMem_Free(groups);
9773
0
        return NULL;
9774
0
    }
9775
9776
0
    for (i = 0; i < ngroups; i++) {
9777
#ifdef __APPLE__
9778
        PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
9779
#else
9780
0
        PyObject *o = _PyLong_FromGid(groups[i]);
9781
0
#endif
9782
0
        if (o == NULL) {
9783
0
            Py_DECREF(list);
9784
0
            PyMem_Free(groups);
9785
0
            return NULL;
9786
0
        }
9787
0
        PyList_SET_ITEM(list, i, o);
9788
0
    }
9789
9790
0
    PyMem_Free(groups);
9791
9792
0
    return list;
9793
0
}
9794
#endif /* HAVE_GETGROUPLIST */
9795
9796
9797
#ifdef HAVE_GETGROUPS
9798
/*[clinic input]
9799
os.getgroups
9800
9801
Return list of supplemental group IDs for the process.
9802
[clinic start generated code]*/
9803
9804
static PyObject *
9805
os_getgroups_impl(PyObject *module)
9806
/*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
9807
0
{
9808
    // Call getgroups with length 0 to get the actual number of groups
9809
0
    int n = getgroups(0, NULL);
9810
0
    if (n < 0) {
9811
0
        return posix_error();
9812
0
    }
9813
9814
0
    if (n == 0) {
9815
0
        return PyList_New(0);
9816
0
    }
9817
9818
0
    gid_t *grouplist = PyMem_New(gid_t, n);
9819
0
    if (grouplist == NULL) {
9820
0
        return PyErr_NoMemory();
9821
0
    }
9822
9823
0
    n = getgroups(n, grouplist);
9824
0
    if (n == -1) {
9825
0
        posix_error();
9826
0
        PyMem_Free(grouplist);
9827
0
        return NULL;
9828
0
    }
9829
9830
0
    PyObject *result = PyList_New(n);
9831
0
    if (result == NULL) {
9832
0
        goto error;
9833
0
    }
9834
9835
0
    for (int i = 0; i < n; ++i) {
9836
0
        PyObject *group = _PyLong_FromGid(grouplist[i]);
9837
0
        if (group == NULL) {
9838
0
            goto error;
9839
0
        }
9840
0
        PyList_SET_ITEM(result, i, group);
9841
0
    }
9842
0
    PyMem_Free(grouplist);
9843
9844
0
    return result;
9845
9846
0
error:
9847
0
    PyMem_Free(grouplist);
9848
0
    Py_XDECREF(result);
9849
0
    return NULL;
9850
0
}
9851
#endif /* HAVE_GETGROUPS */
9852
9853
#ifdef HAVE_INITGROUPS
9854
#ifdef __APPLE__
9855
/*[clinic input]
9856
os.initgroups
9857
9858
    username as oname: unicode_fs_encoded
9859
    gid: int
9860
    /
9861
9862
Initialize the group access list.
9863
9864
Call the system initgroups() to initialize the group access list with
9865
all of the groups of which the specified username is a member, plus the
9866
specified group id.
9867
[clinic start generated code]*/
9868
9869
static PyObject *
9870
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
9871
/*[clinic end generated code: output=7f074d30a425fd3a input=35f2d4fb7fcc0bdf]*/
9872
#else
9873
/*[clinic input]
9874
os.initgroups
9875
9876
    username as oname: unicode_fs_encoded
9877
    gid: gid_t
9878
    /
9879
9880
Initialize the group access list.
9881
9882
Call the system initgroups() to initialize the group access list with
9883
all of the groups of which the specified username is a member, plus the
9884
specified group id.
9885
[clinic start generated code]*/
9886
9887
static PyObject *
9888
os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
9889
/*[clinic end generated code: output=59341244521a9e3f input=7e4514dff4526a95]*/
9890
#endif
9891
0
{
9892
#ifdef __ANDROID__
9893
    // On Android, calling this function as a non-root user leads to a process crash
9894
    // rather than returning a permission error.
9895
    if (getuid() != 0) {
9896
        errno = EPERM;
9897
        return posix_error();
9898
    }
9899
#endif
9900
0
    const char *username = PyBytes_AS_STRING(oname);
9901
9902
0
    if (initgroups(username, gid) == -1)
9903
0
        return PyErr_SetFromErrno(PyExc_OSError);
9904
9905
0
    Py_RETURN_NONE;
9906
0
}
9907
#endif /* HAVE_INITGROUPS */
9908
9909
9910
#ifdef HAVE_GETPGID
9911
/*[clinic input]
9912
os.getpgid
9913
9914
    pid: pid_t
9915
9916
Call the system call getpgid(), and return the result.
9917
[clinic start generated code]*/
9918
9919
static PyObject *
9920
os_getpgid_impl(PyObject *module, pid_t pid)
9921
/*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
9922
0
{
9923
0
    pid_t pgid = getpgid(pid);
9924
0
    if (pgid < 0)
9925
0
        return posix_error();
9926
0
    return PyLong_FromPid(pgid);
9927
0
}
9928
#endif /* HAVE_GETPGID */
9929
9930
9931
#ifdef HAVE_GETPGRP
9932
/*[clinic input]
9933
os.getpgrp
9934
9935
Return the current process group id.
9936
[clinic start generated code]*/
9937
9938
static PyObject *
9939
os_getpgrp_impl(PyObject *module)
9940
/*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
9941
0
{
9942
#ifdef GETPGRP_HAVE_ARG
9943
    return PyLong_FromPid(getpgrp(0));
9944
#else /* GETPGRP_HAVE_ARG */
9945
0
    return PyLong_FromPid(getpgrp());
9946
0
#endif /* GETPGRP_HAVE_ARG */
9947
0
}
9948
#endif /* HAVE_GETPGRP */
9949
9950
9951
#ifdef HAVE_SETPGRP
9952
/*[clinic input]
9953
os.setpgrp
9954
9955
Make the current process the leader of its process group.
9956
[clinic start generated code]*/
9957
9958
static PyObject *
9959
os_setpgrp_impl(PyObject *module)
9960
/*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
9961
0
{
9962
#ifdef SETPGRP_HAVE_ARG
9963
    if (setpgrp(0, 0) < 0)
9964
#else /* SETPGRP_HAVE_ARG */
9965
0
    if (setpgrp() < 0)
9966
0
#endif /* SETPGRP_HAVE_ARG */
9967
0
        return posix_error();
9968
0
    Py_RETURN_NONE;
9969
0
}
9970
#endif /* HAVE_SETPGRP */
9971
9972
#ifdef HAVE_GETPPID
9973
9974
#ifdef MS_WINDOWS
9975
#include <winternl.h>
9976
#include <ProcessSnapshot.h>
9977
9978
#ifdef MS_WINDOWS_DESKTOP
9979
// The structure definition in winternl.h may be incomplete.
9980
// This structure is the full version from the MSDN documentation.
9981
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
9982
    NTSTATUS ExitStatus;
9983
    PVOID PebBaseAddress;
9984
    ULONG_PTR AffinityMask;
9985
    LONG BasePriority;
9986
    ULONG_PTR UniqueProcessId;
9987
    ULONG_PTR InheritedFromUniqueProcessId;
9988
} PROCESS_BASIC_INFORMATION_FULL;
9989
9990
typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
9991
    IN    HANDLE           ProcessHandle,
9992
    IN    PROCESSINFOCLASS ProcessInformationClass,
9993
    OUT   PVOID            ProcessInformation,
9994
    IN    ULONG            ProcessInformationLength,
9995
    OUT   PULONG           ReturnLength OPTIONAL);
9996
9997
// This function returns the process ID of the parent process.
9998
// Returns 0 on failure.
9999
static ULONG
10000
win32_getppid_fast(void)
10001
{
10002
    NTSTATUS status;
10003
    HMODULE ntdll;
10004
    PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
10005
    PROCESS_BASIC_INFORMATION_FULL basic_information;
10006
    static ULONG cached_ppid = 0;
10007
10008
    if (cached_ppid) {
10009
        // No need to query the kernel again.
10010
        return cached_ppid;
10011
    }
10012
10013
    ntdll = GetModuleHandleW(L"ntdll.dll");
10014
    if (!ntdll) {
10015
        return 0;
10016
    }
10017
10018
    pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess");
10019
    if (!pNtQueryInformationProcess) {
10020
        return 0;
10021
    }
10022
10023
    status = pNtQueryInformationProcess(GetCurrentProcess(),
10024
                                        ProcessBasicInformation,
10025
                                        &basic_information,
10026
                                        sizeof(basic_information),
10027
                                        NULL);
10028
10029
    if (!NT_SUCCESS(status)) {
10030
        return 0;
10031
    }
10032
10033
    // Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
10034
    // The check covers values which exceed the 32-bit range (if running on x64) as well as
10035
    // zero and (ULONG) -1.
10036
10037
    if (basic_information.InheritedFromUniqueProcessId == 0 ||
10038
        basic_information.InheritedFromUniqueProcessId >= ULONG_MAX)
10039
    {
10040
        return 0;
10041
    }
10042
10043
    // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
10044
    // structure member contains a ULONG_PTR which represents the process ID of our parent
10045
    // process. This process ID will be correctly returned even if the parent process has
10046
    // exited or been terminated.
10047
10048
    cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId;
10049
    return cached_ppid;
10050
}
10051
#endif // MS_WINDOWS_DESKTOP
10052
10053
static PyObject*
10054
win32_getppid(void)
10055
{
10056
    DWORD error;
10057
    PyObject* result = NULL;
10058
    HANDLE process = GetCurrentProcess();
10059
    HPSS snapshot = NULL;
10060
10061
#ifdef MS_WINDOWS_DESKTOP
10062
    ULONG pid = win32_getppid_fast();
10063
    if (pid != 0) {
10064
        return PyLong_FromUnsignedLong(pid);
10065
    }
10066
#endif
10067
10068
    // If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
10069
10070
    error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
10071
    if (error != ERROR_SUCCESS) {
10072
        return PyErr_SetFromWindowsErr(error);
10073
    }
10074
10075
    PSS_PROCESS_INFORMATION info;
10076
    error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info,
10077
                             sizeof(info));
10078
    if (error == ERROR_SUCCESS) {
10079
        result = PyLong_FromUnsignedLong(info.ParentProcessId);
10080
    }
10081
    else {
10082
        result = PyErr_SetFromWindowsErr(error);
10083
    }
10084
10085
    PssFreeSnapshot(process, snapshot);
10086
    return result;
10087
}
10088
#endif /*MS_WINDOWS*/
10089
10090
10091
/*[clinic input]
10092
os.getppid
10093
10094
Return the parent's process id.
10095
10096
If the parent process has already exited, Windows machines will still
10097
return its id; others systems will return the id of the 'init' proces
10098
(1).
10099
[clinic start generated code]*/
10100
10101
static PyObject *
10102
os_getppid_impl(PyObject *module)
10103
/*[clinic end generated code: output=43b2a946a8c603b4 input=e17c1de18f41316b]*/
10104
0
{
10105
#ifdef MS_WINDOWS
10106
    return win32_getppid();
10107
#else
10108
0
    return PyLong_FromPid(getppid());
10109
0
#endif
10110
0
}
10111
#endif /* HAVE_GETPPID */
10112
10113
10114
#ifdef HAVE_GETLOGIN
10115
/*[clinic input]
10116
os.getlogin
10117
10118
Return the actual login name.
10119
[clinic start generated code]*/
10120
10121
static PyObject *
10122
os_getlogin_impl(PyObject *module)
10123
/*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
10124
0
{
10125
0
    PyObject *result = NULL;
10126
#ifdef MS_WINDOWS
10127
    wchar_t user_name[UNLEN + 1];
10128
    DWORD num_chars = Py_ARRAY_LENGTH(user_name);
10129
10130
    if (GetUserNameW(user_name, &num_chars)) {
10131
        /* num_chars is the number of unicode chars plus null terminator */
10132
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
10133
    }
10134
    else
10135
        result = PyErr_SetFromWindowsErr(GetLastError());
10136
#elif defined (HAVE_GETLOGIN_R)
10137
# if defined (HAVE_MAXLOGNAME)
10138
    char name[MAXLOGNAME + 1];
10139
# elif defined (HAVE_UT_NAMESIZE)
10140
    char name[UT_NAMESIZE + 1];
10141
# else
10142
    char name[256];
10143
# endif
10144
0
    int err = getlogin_r(name, sizeof(name));
10145
0
    if (err) {
10146
0
        int old_errno = errno;
10147
0
        errno = err;
10148
0
        posix_error();
10149
0
        errno = old_errno;
10150
0
    }
10151
0
    else {
10152
0
        _Py_MSAN_UNPOISON(name, sizeof(name));
10153
0
        result = PyUnicode_DecodeFSDefault(name);
10154
0
    }
10155
#else
10156
    char *name;
10157
    int old_errno = errno;
10158
10159
    errno = 0;
10160
    name = getlogin();
10161
    if (name == NULL) {
10162
        if (errno)
10163
            posix_error();
10164
        else
10165
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
10166
    }
10167
    else
10168
        result = PyUnicode_DecodeFSDefault(name);
10169
    errno = old_errno;
10170
#endif
10171
0
    return result;
10172
0
}
10173
#endif /* HAVE_GETLOGIN */
10174
10175
10176
#ifdef HAVE_GETUID
10177
/*[clinic input]
10178
os.getuid
10179
10180
Return the current process's user id.
10181
[clinic start generated code]*/
10182
10183
static PyObject *
10184
os_getuid_impl(PyObject *module)
10185
/*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
10186
37
{
10187
37
    return _PyLong_FromUid(getuid());
10188
37
}
10189
#endif /* HAVE_GETUID */
10190
10191
10192
#ifdef MS_WINDOWS
10193
#define HAVE_KILL
10194
#endif /* MS_WINDOWS */
10195
10196
#ifdef HAVE_KILL
10197
/*[clinic input]
10198
os.kill
10199
10200
    pid: pid_t
10201
    signal: Py_ssize_t
10202
    /
10203
10204
Kill a process with a signal.
10205
[clinic start generated code]*/
10206
10207
static PyObject *
10208
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
10209
/*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
10210
0
{
10211
0
    if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
10212
0
        return NULL;
10213
0
    }
10214
0
#ifndef MS_WINDOWS
10215
0
    if (kill(pid, (int)signal) == -1) {
10216
0
        return posix_error();
10217
0
    }
10218
10219
    // Check immediately if the signal was sent to the current process.
10220
    // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
10221
    // is cheap.
10222
0
    if (PyErr_CheckSignals()) {
10223
0
        return NULL;
10224
0
    }
10225
10226
0
    Py_RETURN_NONE;
10227
#else /* !MS_WINDOWS */
10228
    DWORD sig = (DWORD)signal;
10229
10230
#ifdef HAVE_WINDOWS_CONSOLE_IO
10231
    /* Console processes which share a common console can be sent CTRL+C or
10232
       CTRL+BREAK events, provided they handle said events. */
10233
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
10234
        if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
10235
            return PyErr_SetFromWindowsErr(0);
10236
        }
10237
        Py_RETURN_NONE;
10238
    }
10239
#endif /* HAVE_WINDOWS_CONSOLE_IO */
10240
10241
    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
10242
       attempt to open and terminate the process. */
10243
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
10244
    if (handle == NULL) {
10245
        return PyErr_SetFromWindowsErr(0);
10246
    }
10247
10248
    BOOL res = TerminateProcess(handle, sig);
10249
    CloseHandle(handle);
10250
    if (res == 0) {
10251
        return PyErr_SetFromWindowsErr(0);
10252
    }
10253
10254
    Py_RETURN_NONE;
10255
#endif /* !MS_WINDOWS */
10256
0
}
10257
#endif /* HAVE_KILL */
10258
10259
10260
#ifdef HAVE_KILLPG
10261
/*[clinic input]
10262
os.killpg
10263
10264
    pgid: pid_t
10265
    signal: int
10266
    /
10267
10268
Kill a process group with a signal.
10269
[clinic start generated code]*/
10270
10271
static PyObject *
10272
os_killpg_impl(PyObject *module, pid_t pgid, int signal)
10273
/*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
10274
0
{
10275
0
    if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
10276
0
        return NULL;
10277
0
    }
10278
    /* XXX some man pages make the `pgid` parameter an int, others
10279
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
10280
       take the same type. Moreover, pid_t is always at least as wide as
10281
       int (else compilation of this module fails), which is safe. */
10282
0
    if (killpg(pgid, signal) == -1)
10283
0
        return posix_error();
10284
0
    Py_RETURN_NONE;
10285
0
}
10286
#endif /* HAVE_KILLPG */
10287
10288
10289
#ifdef HAVE_PLOCK
10290
#ifdef HAVE_SYS_LOCK_H
10291
#include <sys/lock.h>
10292
#endif
10293
10294
/*[clinic input]
10295
os.plock
10296
    op: int
10297
    /
10298
10299
Lock program segments into memory.");
10300
[clinic start generated code]*/
10301
10302
static PyObject *
10303
os_plock_impl(PyObject *module, int op)
10304
/*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
10305
{
10306
    if (plock(op) == -1)
10307
        return posix_error();
10308
    Py_RETURN_NONE;
10309
}
10310
#endif /* HAVE_PLOCK */
10311
10312
10313
#ifdef HAVE_SETUID
10314
/*[clinic input]
10315
os.setuid
10316
10317
    uid: uid_t
10318
    /
10319
10320
Set the current process's user id.
10321
[clinic start generated code]*/
10322
10323
static PyObject *
10324
os_setuid_impl(PyObject *module, uid_t uid)
10325
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
10326
0
{
10327
#ifdef __ANDROID__
10328
    // On Android, calling this function as a non-root user leads to a process crash
10329
    // rather than returning a permission error.
10330
    if (getuid() != 0) {
10331
        errno = EPERM;
10332
        return posix_error();
10333
    }
10334
#endif
10335
0
    if (setuid(uid) < 0)
10336
0
        return posix_error();
10337
0
    Py_RETURN_NONE;
10338
0
}
10339
#endif /* HAVE_SETUID */
10340
10341
10342
#ifdef HAVE_SETEUID
10343
/*[clinic input]
10344
os.seteuid
10345
10346
    euid: uid_t
10347
    /
10348
10349
Set the current process's effective user id.
10350
[clinic start generated code]*/
10351
10352
static PyObject *
10353
os_seteuid_impl(PyObject *module, uid_t euid)
10354
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
10355
0
{
10356
#ifdef __ANDROID__
10357
    // On Android, calling this function as a non-root user leads to a process crash
10358
    // rather than returning a permission error.
10359
    if (getuid() != 0) {
10360
        errno = EPERM;
10361
        return posix_error();
10362
    }
10363
#endif
10364
0
    if (seteuid(euid) < 0)
10365
0
        return posix_error();
10366
0
    Py_RETURN_NONE;
10367
0
}
10368
#endif /* HAVE_SETEUID */
10369
10370
10371
#ifdef HAVE_SETEGID
10372
/*[clinic input]
10373
os.setegid
10374
10375
    egid: gid_t
10376
    /
10377
10378
Set the current process's effective group id.
10379
[clinic start generated code]*/
10380
10381
static PyObject *
10382
os_setegid_impl(PyObject *module, gid_t egid)
10383
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
10384
0
{
10385
#ifdef __ANDROID__
10386
    // On Android, calling this function as a non-root user leads to a process crash
10387
    // rather than returning a permission error.
10388
    if (getuid() != 0) {
10389
        errno = EPERM;
10390
        return posix_error();
10391
    }
10392
#endif
10393
0
    if (setegid(egid) < 0)
10394
0
        return posix_error();
10395
0
    Py_RETURN_NONE;
10396
0
}
10397
#endif /* HAVE_SETEGID */
10398
10399
10400
#ifdef HAVE_SETREUID
10401
/*[clinic input]
10402
os.setreuid
10403
10404
    ruid: uid_t
10405
    euid: uid_t
10406
    /
10407
10408
Set the current process's real and effective user ids.
10409
[clinic start generated code]*/
10410
10411
static PyObject *
10412
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
10413
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
10414
0
{
10415
#ifdef __ANDROID__
10416
    // On Android, calling this function as a non-root user leads to a process crash
10417
    // rather than returning a permission error.
10418
    if (getuid() != 0) {
10419
        errno = EPERM;
10420
        return posix_error();
10421
    }
10422
#endif
10423
0
    if (setreuid(ruid, euid) < 0) {
10424
0
        return posix_error();
10425
0
    } else {
10426
0
        Py_RETURN_NONE;
10427
0
    }
10428
0
}
10429
#endif /* HAVE_SETREUID */
10430
10431
10432
#ifdef HAVE_SETREGID
10433
/*[clinic input]
10434
os.setregid
10435
10436
    rgid: gid_t
10437
    egid: gid_t
10438
    /
10439
10440
Set the current process's real and effective group ids.
10441
[clinic start generated code]*/
10442
10443
static PyObject *
10444
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
10445
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
10446
0
{
10447
#ifdef __ANDROID__
10448
    // On Android, calling this function as a non-root user leads to a process crash
10449
    // rather than returning a permission error.
10450
    if (getuid() != 0) {
10451
        errno = EPERM;
10452
        return posix_error();
10453
    }
10454
#endif
10455
0
    if (setregid(rgid, egid) < 0)
10456
0
        return posix_error();
10457
0
    Py_RETURN_NONE;
10458
0
}
10459
#endif /* HAVE_SETREGID */
10460
10461
10462
#ifdef HAVE_SETGID
10463
/*[clinic input]
10464
os.setgid
10465
    gid: gid_t
10466
    /
10467
10468
Set the current process's group id.
10469
[clinic start generated code]*/
10470
10471
static PyObject *
10472
os_setgid_impl(PyObject *module, gid_t gid)
10473
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
10474
0
{
10475
#ifdef __ANDROID__
10476
    // On Android, calling this function as a non-root user leads to a process crash
10477
    // rather than returning a permission error.
10478
    if (getuid() != 0) {
10479
        errno = EPERM;
10480
        return posix_error();
10481
    }
10482
#endif
10483
0
    if (setgid(gid) < 0)
10484
0
        return posix_error();
10485
0
    Py_RETURN_NONE;
10486
0
}
10487
#endif /* HAVE_SETGID */
10488
10489
10490
#ifdef HAVE_SETGROUPS
10491
/*[clinic input]
10492
os.setgroups
10493
10494
    groups: object
10495
    /
10496
10497
Set the groups of the current process to list.
10498
[clinic start generated code]*/
10499
10500
static PyObject *
10501
os_setgroups(PyObject *module, PyObject *groups)
10502
/*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
10503
0
{
10504
0
    if (!PySequence_Check(groups)) {
10505
0
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
10506
0
        return NULL;
10507
0
    }
10508
0
    Py_ssize_t len = PySequence_Size(groups);
10509
0
    if (len < 0) {
10510
0
        return NULL;
10511
0
    }
10512
0
    if (len > MAX_GROUPS) {
10513
0
        PyErr_SetString(PyExc_ValueError, "too many groups");
10514
0
        return NULL;
10515
0
    }
10516
10517
0
    gid_t *grouplist = PyMem_New(gid_t, len);
10518
0
    if (grouplist == NULL) {
10519
0
        PyErr_NoMemory();
10520
0
        return NULL;
10521
0
    }
10522
0
    for (Py_ssize_t i = 0; i < len; i++) {
10523
0
        PyObject *elem;
10524
0
        elem = PySequence_GetItem(groups, i);
10525
0
        if (!elem) {
10526
0
            PyMem_Free(grouplist);
10527
0
            return NULL;
10528
0
        }
10529
0
        if (!PyIndex_Check(elem)) {
10530
0
            PyErr_SetString(PyExc_TypeError,
10531
0
                            "groups must be integers");
10532
0
            Py_DECREF(elem);
10533
0
            PyMem_Free(grouplist);
10534
0
            return NULL;
10535
0
        } else {
10536
0
            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
10537
0
                Py_DECREF(elem);
10538
0
                PyMem_Free(grouplist);
10539
0
                return NULL;
10540
0
            }
10541
0
        }
10542
0
        Py_DECREF(elem);
10543
0
    }
10544
10545
0
    if (setgroups(len, grouplist) < 0) {
10546
0
        posix_error();
10547
0
        PyMem_Free(grouplist);
10548
0
        return NULL;
10549
0
    }
10550
0
    PyMem_Free(grouplist);
10551
0
    Py_RETURN_NONE;
10552
0
}
10553
#endif /* HAVE_SETGROUPS */
10554
10555
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
10556
static PyObject *
10557
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
10558
0
{
10559
0
    PyObject *result;
10560
0
    PyObject *struct_rusage;
10561
10562
0
    if (pid == -1)
10563
0
        return posix_error();
10564
10565
    // If wait succeeded but no child was ready to report status, ru will not
10566
    // have been populated.
10567
0
    if (pid == 0) {
10568
0
        memset(ru, 0, sizeof(*ru));
10569
0
    }
10570
10571
0
    struct_rusage = PyImport_ImportModuleAttrString("resource", "struct_rusage");
10572
0
    if (struct_rusage == NULL)
10573
0
        return NULL;
10574
10575
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
10576
0
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
10577
0
    Py_DECREF(struct_rusage);
10578
0
    if (!result)
10579
0
        return NULL;
10580
10581
0
    int pos = 0;
10582
10583
0
#ifndef doubletime
10584
0
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
10585
0
#endif
10586
10587
0
#define SET_RESULT(CALL)                                     \
10588
0
    do {                                                     \
10589
0
        PyObject *item = (CALL);                             \
10590
0
        if (item == NULL) {                                  \
10591
0
            Py_DECREF(result);                               \
10592
0
            return NULL;                                     \
10593
0
        }                                                    \
10594
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10595
0
    } while(0)
10596
10597
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_utime)));
10598
0
    SET_RESULT(PyFloat_FromDouble(doubletime(ru->ru_stime)));
10599
0
    SET_RESULT(PyLong_FromLong(ru->ru_maxrss));
10600
0
    SET_RESULT(PyLong_FromLong(ru->ru_ixrss));
10601
0
    SET_RESULT(PyLong_FromLong(ru->ru_idrss));
10602
0
    SET_RESULT(PyLong_FromLong(ru->ru_isrss));
10603
0
    SET_RESULT(PyLong_FromLong(ru->ru_minflt));
10604
0
    SET_RESULT(PyLong_FromLong(ru->ru_majflt));
10605
0
    SET_RESULT(PyLong_FromLong(ru->ru_nswap));
10606
0
    SET_RESULT(PyLong_FromLong(ru->ru_inblock));
10607
0
    SET_RESULT(PyLong_FromLong(ru->ru_oublock));
10608
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgsnd));
10609
0
    SET_RESULT(PyLong_FromLong(ru->ru_msgrcv));
10610
0
    SET_RESULT(PyLong_FromLong(ru->ru_nsignals));
10611
0
    SET_RESULT(PyLong_FromLong(ru->ru_nvcsw));
10612
0
    SET_RESULT(PyLong_FromLong(ru->ru_nivcsw));
10613
0
#undef SET_RESULT
10614
10615
0
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
10616
0
}
10617
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
10618
10619
10620
#ifdef HAVE_WAIT3
10621
/*[clinic input]
10622
os.wait3
10623
10624
    options: int
10625
Wait for completion of a child process.
10626
10627
Returns a tuple of information about the child process:
10628
  (pid, status, rusage)
10629
[clinic start generated code]*/
10630
10631
static PyObject *
10632
os_wait3_impl(PyObject *module, int options)
10633
/*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
10634
0
{
10635
0
    pid_t pid;
10636
0
    struct rusage ru;
10637
0
    int async_err = 0;
10638
0
    WAIT_TYPE status;
10639
0
    WAIT_STATUS_INT(status) = 0;
10640
10641
0
    do {
10642
0
        Py_BEGIN_ALLOW_THREADS
10643
0
        pid = wait3(&status, options, &ru);
10644
0
        Py_END_ALLOW_THREADS
10645
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10646
0
    if (pid < 0)
10647
0
        return (!async_err) ? posix_error() : NULL;
10648
10649
0
    return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
10650
0
}
10651
#endif /* HAVE_WAIT3 */
10652
10653
10654
#ifdef HAVE_WAIT4
10655
/*[clinic input]
10656
10657
os.wait4
10658
10659
    pid: pid_t
10660
    options: int
10661
10662
Wait for completion of a specific child process.
10663
10664
Returns a tuple of information about the child process:
10665
  (pid, status, rusage)
10666
[clinic start generated code]*/
10667
10668
static PyObject *
10669
os_wait4_impl(PyObject *module, pid_t pid, int options)
10670
/*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
10671
0
{
10672
0
    pid_t res;
10673
0
    struct rusage ru;
10674
0
    int async_err = 0;
10675
0
    WAIT_TYPE status;
10676
0
    WAIT_STATUS_INT(status) = 0;
10677
10678
0
    do {
10679
0
        Py_BEGIN_ALLOW_THREADS
10680
0
        res = wait4(pid, &status, options, &ru);
10681
0
        Py_END_ALLOW_THREADS
10682
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10683
0
    if (res < 0)
10684
0
        return (!async_err) ? posix_error() : NULL;
10685
10686
0
    return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
10687
0
}
10688
#endif /* HAVE_WAIT4 */
10689
10690
10691
#if defined(HAVE_WAITID)
10692
/*[clinic input]
10693
os.waitid
10694
10695
    idtype: idtype_t
10696
        Must be one of be P_PID, P_PGID or P_ALL.
10697
    id: id_t
10698
        The id to wait on.
10699
    options: int
10700
        Constructed from the ORing of one or more of WEXITED, WSTOPPED
10701
        or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
10702
    /
10703
10704
Returns the result of waiting for a process or processes.
10705
10706
Returns either waitid_result or None if WNOHANG is specified and there
10707
are no children in a waitable state.
10708
[clinic start generated code]*/
10709
10710
static PyObject *
10711
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
10712
/*[clinic end generated code: output=5d2e1c0bde61f4d8 input=14956bc8d102b5db]*/
10713
0
{
10714
0
    PyObject *result;
10715
0
    int res;
10716
0
    int async_err = 0;
10717
0
    siginfo_t si;
10718
0
    si.si_pid = 0;
10719
10720
0
    do {
10721
0
        Py_BEGIN_ALLOW_THREADS
10722
0
        res = waitid(idtype, id, &si, options);
10723
0
        Py_END_ALLOW_THREADS
10724
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10725
0
    if (res < 0)
10726
0
        return (!async_err) ? posix_error() : NULL;
10727
10728
0
    if (si.si_pid == 0)
10729
0
        Py_RETURN_NONE;
10730
10731
0
    PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
10732
0
    result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
10733
0
    if (!result)
10734
0
        return NULL;
10735
10736
0
    int pos = 0;
10737
10738
0
#define SET_RESULT(CALL)                                     \
10739
0
    do {                                                     \
10740
0
        PyObject *item = (CALL);                             \
10741
0
        if (item == NULL) {                                  \
10742
0
            Py_DECREF(result);                               \
10743
0
            return NULL;                                     \
10744
0
        }                                                    \
10745
0
        PyStructSequence_SET_ITEM(result, pos++, item);      \
10746
0
    } while(0)
10747
10748
0
    SET_RESULT(PyLong_FromPid(si.si_pid));
10749
0
    SET_RESULT(_PyLong_FromUid(si.si_uid));
10750
0
    SET_RESULT(PyLong_FromLong((long)(si.si_signo)));
10751
0
    SET_RESULT(PyLong_FromLong((long)(si.si_status)));
10752
0
    SET_RESULT(PyLong_FromLong((long)(si.si_code)));
10753
10754
0
#undef SET_RESULT
10755
10756
0
    return result;
10757
0
}
10758
#endif /* defined(HAVE_WAITID) */
10759
10760
10761
#if defined(HAVE_WAITPID)
10762
/*[clinic input]
10763
os.waitpid
10764
    pid: pid_t
10765
    options: int
10766
    /
10767
10768
Wait for completion of a given child process.
10769
10770
Returns a tuple of information regarding the child process:
10771
    (pid, status)
10772
10773
The options argument is ignored on Windows.
10774
[clinic start generated code]*/
10775
10776
static PyObject *
10777
os_waitpid_impl(PyObject *module, pid_t pid, int options)
10778
/*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
10779
0
{
10780
0
    pid_t res;
10781
0
    int async_err = 0;
10782
0
    WAIT_TYPE status;
10783
0
    WAIT_STATUS_INT(status) = 0;
10784
10785
0
    do {
10786
0
        Py_BEGIN_ALLOW_THREADS
10787
0
        res = waitpid(pid, &status, options);
10788
0
        Py_END_ALLOW_THREADS
10789
0
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10790
0
    if (res < 0)
10791
0
        return (!async_err) ? posix_error() : NULL;
10792
10793
0
    return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
10794
0
}
10795
#elif defined(HAVE_CWAIT)
10796
/* MS C has a variant of waitpid() that's usable for most purposes. */
10797
/*[clinic input]
10798
os.waitpid
10799
    pid: intptr_t
10800
    options: int
10801
    /
10802
10803
Wait for completion of a given process.
10804
10805
Returns a tuple of information regarding the process:
10806
    (pid, status << 8)
10807
10808
The options argument is ignored on Windows.
10809
[clinic start generated code]*/
10810
10811
static PyObject *
10812
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
10813
/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
10814
{
10815
    int status;
10816
    intptr_t res;
10817
    int async_err = 0;
10818
10819
    do {
10820
        Py_BEGIN_ALLOW_THREADS
10821
        _Py_BEGIN_SUPPRESS_IPH
10822
        res = _cwait(&status, pid, options);
10823
        _Py_END_SUPPRESS_IPH
10824
        Py_END_ALLOW_THREADS
10825
    } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10826
    if (res < 0)
10827
        return (!async_err) ? posix_error() : NULL;
10828
10829
    unsigned long long ustatus = (unsigned int)status;
10830
10831
    /* shift the status left a byte so this is more like the POSIX waitpid */
10832
    return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
10833
}
10834
#endif
10835
10836
10837
#ifdef HAVE_WAIT
10838
/*[clinic input]
10839
os.wait
10840
10841
Wait for completion of a child process.
10842
10843
Returns a tuple of information about the child process:
10844
    (pid, status)
10845
[clinic start generated code]*/
10846
10847
static PyObject *
10848
os_wait_impl(PyObject *module)
10849
/*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
10850
0
{
10851
0
    pid_t pid;
10852
0
    int async_err = 0;
10853
0
    WAIT_TYPE status;
10854
0
    WAIT_STATUS_INT(status) = 0;
10855
10856
0
    do {
10857
0
        Py_BEGIN_ALLOW_THREADS
10858
0
        pid = wait(&status);
10859
0
        Py_END_ALLOW_THREADS
10860
0
    } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10861
0
    if (pid < 0)
10862
0
        return (!async_err) ? posix_error() : NULL;
10863
10864
0
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
10865
0
}
10866
#endif /* HAVE_WAIT */
10867
10868
10869
// This system call always crashes on older Android versions.
10870
#if defined(HAVE_PIDFD_OPEN) \
10871
    || (defined(__linux__) && defined(__NR_pidfd_open) \
10872
        && !(defined(__ANDROID__) && __ANDROID_API__ < 31))
10873
/*[clinic input]
10874
os.pidfd_open
10875
  pid: pid_t
10876
  flags: unsigned_int = 0
10877
10878
Return a file descriptor referring to the process *pid*.
10879
10880
The descriptor can be used to perform process management without races
10881
and signals.
10882
[clinic start generated code]*/
10883
10884
static PyObject *
10885
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
10886
/*[clinic end generated code: output=5c7252698947dc41 input=03058b32c389f874]*/
10887
4
{
10888
#ifdef HAVE_PIDFD_OPEN
10889
    int fd = pidfd_open(pid, flags);
10890
#else
10891
4
    int fd = syscall(__NR_pidfd_open, pid, flags);
10892
4
#endif
10893
4
    if (fd < 0) {
10894
0
        return posix_error();
10895
0
    }
10896
4
    return PyLong_FromLong(fd);
10897
4
}
10898
#endif
10899
10900
10901
#if defined(HAVE_PIDFD_GETFD) \
10902
    || (defined(__linux__) && defined(__NR_pidfd_getfd) \
10903
        && !(defined(__ANDROID__) && __ANDROID_API__ < 31))
10904
/*[clinic input]
10905
os.pidfd_getfd
10906
  pidfd: int
10907
    A process file descriptor.
10908
  targetfd: int
10909
    The file descriptor to duplicate from the target process.
10910
  *
10911
  flags: unsigned_int = 0
10912
    Reserved, must be 0.
10913
10914
Duplicate a file descriptor from the process referred to by *pidfd*.
10915
[clinic start generated code]*/
10916
10917
static PyObject *
10918
os_pidfd_getfd_impl(PyObject *module, int pidfd, int targetfd,
10919
                    unsigned int flags)
10920
/*[clinic end generated code: output=e1a1415a13c7137f input=ef6417fb10deb1cc]*/
10921
{
10922
#ifdef HAVE_PIDFD_GETFD
10923
    int fd = pidfd_getfd(pidfd, targetfd, flags);
10924
#else
10925
    int fd = syscall(__NR_pidfd_getfd, pidfd, targetfd, flags);
10926
#endif
10927
    if (fd < 0) {
10928
        return posix_error();
10929
    }
10930
    return PyLong_FromLong(fd);
10931
}
10932
#endif
10933
10934
10935
#ifdef HAVE_SETNS
10936
/*[clinic input]
10937
os.setns
10938
  fd: fildes
10939
    A file descriptor to a namespace.
10940
  nstype: int = 0
10941
    Type of namespace.
10942
10943
Move the calling thread into different namespaces.
10944
[clinic start generated code]*/
10945
10946
static PyObject *
10947
os_setns_impl(PyObject *module, int fd, int nstype)
10948
/*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/
10949
0
{
10950
0
    int res;
10951
10952
0
    Py_BEGIN_ALLOW_THREADS
10953
0
    res = setns(fd, nstype);
10954
0
    Py_END_ALLOW_THREADS
10955
10956
0
    if (res != 0) {
10957
0
        return posix_error();
10958
0
    }
10959
10960
0
    Py_RETURN_NONE;
10961
0
}
10962
#endif
10963
10964
10965
#ifdef HAVE_UNSHARE
10966
/*[clinic input]
10967
os.unshare
10968
  flags: int
10969
    Namespaces to be unshared.
10970
10971
Disassociate parts of a process (or thread) execution context.
10972
[clinic start generated code]*/
10973
10974
static PyObject *
10975
os_unshare_impl(PyObject *module, int flags)
10976
/*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/
10977
0
{
10978
0
    int res;
10979
10980
0
    Py_BEGIN_ALLOW_THREADS
10981
0
    res = unshare(flags);
10982
0
    Py_END_ALLOW_THREADS
10983
10984
0
    if (res != 0) {
10985
0
        return posix_error();
10986
0
    }
10987
10988
0
    Py_RETURN_NONE;
10989
0
}
10990
#endif
10991
10992
10993
10994
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
10995
10996
#if (defined(__linux__) || defined(__ANDROID__)) && defined(O_PATH)
10997
// readlinkat(fd, "", ...) reads the symlink that fd refers to.
10998
// supported since Linux 2.6.39 (same version that O_PATH was introduced).
10999
#define _Py_READLINKAT_SUPPORTS_EMPTY_PATH
11000
#endif
11001
11002
/*[clinic input]
11003
os.readlink
11004
11005
    path: path_t(allow_fd=True)
11006
    *
11007
    dir_fd: dir_fd(requires='readlinkat') = None
11008
11009
Return a string representing the path to which the symbolic link points.
11010
11011
If dir_fd is not None, it should be a file descriptor open to
11012
a directory, and path should be relative; path will then be relative to
11013
that directory.
11014
11015
dir_fd may not be implemented on your platform.  If it is unavailable,
11016
using it will raise a NotImplementedError.
11017
11018
On Linux, Android, macOS and iOS, path may be a file descriptor
11019
referring to a symlink. If it is, dir_fd must be None.
11020
[clinic start generated code]*/
11021
11022
static PyObject *
11023
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
11024
/*[clinic end generated code: output=d21b732a2e814030 input=d90bddfeee86f673]*/
11025
6
{
11026
6
#if defined(HAVE_READLINK)
11027
6
    char buffer[MAXPATHLEN+1];
11028
6
    ssize_t length;
11029
11030
6
    if (path_and_dir_fd_invalid("readlink", path, dir_fd)) {
11031
0
        return NULL;
11032
0
    }
11033
11034
6
    if (path->is_fd) {
11035
#if defined(_Py_HAVE_FREADLINK)
11036
        if (HAVE_FREADLINK_RUNTIME) {
11037
            Py_BEGIN_ALLOW_THREADS
11038
            length = freadlink(path->fd, buffer, MAXPATHLEN);
11039
            Py_END_ALLOW_THREADS
11040
        } else
11041
#elif defined(HAVE_READLINKAT) && defined(_Py_READLINKAT_SUPPORTS_EMPTY_PATH)
11042
        // linux/android:
11043
        // readlinkat(fd, "", ...) reads the link that fd refers to.
11044
0
        if (HAVE_READLINKAT_RUNTIME) {
11045
0
            Py_BEGIN_ALLOW_THREADS
11046
0
            length = readlinkat(path->fd, "", buffer, MAXPATHLEN);
11047
0
            Py_END_ALLOW_THREADS
11048
0
        } else
11049
0
#endif
11050
0
        {
11051
0
            PyErr_SetString(PyExc_NotImplementedError,
11052
0
                "readlink cannot read file descriptors on this platform");
11053
0
            return NULL;
11054
0
        }
11055
0
    } else
11056
6
#ifdef HAVE_READLINKAT
11057
6
    if (dir_fd != DEFAULT_DIR_FD) {
11058
0
        if (HAVE_READLINKAT_RUNTIME) {
11059
0
            Py_BEGIN_ALLOW_THREADS
11060
0
            length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
11061
0
            Py_END_ALLOW_THREADS
11062
0
        } else {
11063
0
            argument_unavailable_error(NULL, "dir_fd");
11064
0
            return NULL;
11065
0
        }
11066
0
    } else
11067
6
#endif
11068
6
    {
11069
6
        Py_BEGIN_ALLOW_THREADS
11070
6
        length = readlink(path->narrow, buffer, MAXPATHLEN);
11071
6
        Py_END_ALLOW_THREADS
11072
6
    }
11073
11074
6
    if (length < 0) {
11075
0
        return path_error(path);
11076
0
    }
11077
6
    buffer[length] = '\0';
11078
11079
6
    if (path->is_fd || PyUnicode_Check(path->object)) {
11080
6
        return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
11081
6
    }
11082
0
    else {
11083
0
        return PyBytes_FromStringAndSize(buffer, length);
11084
0
    }
11085
#elif defined(MS_WINDOWS)
11086
    DWORD n_bytes_returned;
11087
    DWORD io_result = 0;
11088
    HANDLE reparse_point_handle;
11089
    char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
11090
    _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
11091
    PyObject *result = NULL;
11092
11093
    if (path->is_fd) {
11094
        PyErr_SetString(PyExc_NotImplementedError,
11095
            "readlink cannot read file descriptors on this platform");
11096
        return NULL;
11097
    }
11098
11099
    /* First get a handle to the reparse point */
11100
    Py_BEGIN_ALLOW_THREADS
11101
    reparse_point_handle = CreateFileW(
11102
        path->wide,
11103
        0,
11104
        0,
11105
        0,
11106
        OPEN_EXISTING,
11107
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
11108
        0);
11109
    if (reparse_point_handle != INVALID_HANDLE_VALUE) {
11110
        /* New call DeviceIoControl to read the reparse point */
11111
        io_result = DeviceIoControl(
11112
            reparse_point_handle,
11113
            FSCTL_GET_REPARSE_POINT,
11114
            0, 0, /* in buffer */
11115
            target_buffer, sizeof(target_buffer),
11116
            &n_bytes_returned,
11117
            0 /* we're not using OVERLAPPED_IO */
11118
            );
11119
        CloseHandle(reparse_point_handle);
11120
    }
11121
    Py_END_ALLOW_THREADS
11122
11123
    if (io_result == 0) {
11124
        return path_error(path);
11125
    }
11126
11127
    wchar_t *name = NULL;
11128
    Py_ssize_t nameLen = 0;
11129
    if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
11130
    {
11131
        name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
11132
                           rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
11133
        nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
11134
    }
11135
    else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
11136
    {
11137
        name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
11138
                           rdb->MountPointReparseBuffer.SubstituteNameOffset);
11139
        nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
11140
    }
11141
    else
11142
    {
11143
        PyErr_SetString(PyExc_ValueError, "not a symbolic link");
11144
    }
11145
    if (name) {
11146
        if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
11147
            /* Our buffer is mutable, so this is okay */
11148
            name[1] = L'\\';
11149
        }
11150
        result = PyUnicode_FromWideChar(name, nameLen);
11151
        if (result && PyBytes_Check(path->object)) {
11152
            Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
11153
        }
11154
    }
11155
    return result;
11156
#endif
11157
6
}
11158
#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
11159
11160
#if defined(MS_WINDOWS)
11161
11162
/* Remove the last portion of the path - return 0 on success */
11163
static int
11164
_dirnameW(WCHAR *path)
11165
{
11166
    WCHAR *ptr;
11167
    size_t length = wcsnlen_s(path, MAX_PATH);
11168
    if (length == MAX_PATH) {
11169
        return -1;
11170
    }
11171
11172
    /* walk the path from the end until a backslash is encountered */
11173
    for(ptr = path + length; ptr != path; ptr--) {
11174
        if (*ptr == L'\\' || *ptr == L'/') {
11175
            break;
11176
        }
11177
    }
11178
    *ptr = 0;
11179
    return 0;
11180
}
11181
11182
#endif
11183
11184
#ifdef HAVE_SYMLINK
11185
11186
#if defined(MS_WINDOWS)
11187
11188
/* Is this path absolute? */
11189
static int
11190
_is_absW(const WCHAR *path)
11191
{
11192
    return path[0] == L'\\' || path[0] == L'/' ||
11193
        (path[0] && path[1] == L':');
11194
}
11195
11196
/* join root and rest with a backslash - return 0 on success */
11197
static int
11198
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
11199
{
11200
    if (_is_absW(rest)) {
11201
        return wcscpy_s(dest_path, MAX_PATH, rest);
11202
    }
11203
11204
    if (wcscpy_s(dest_path, MAX_PATH, root)) {
11205
        return -1;
11206
    }
11207
11208
    if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
11209
        return -1;
11210
    }
11211
11212
    return wcscat_s(dest_path, MAX_PATH, rest);
11213
}
11214
11215
/* Return True if the path at src relative to dest is a directory */
11216
static int
11217
_check_dirW(LPCWSTR src, LPCWSTR dest)
11218
{
11219
    WIN32_FILE_ATTRIBUTE_DATA src_info;
11220
    WCHAR dest_parent[MAX_PATH];
11221
    WCHAR src_resolved[MAX_PATH] = L"";
11222
11223
    /* dest_parent = os.path.dirname(dest) */
11224
    if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
11225
        _dirnameW(dest_parent)) {
11226
        return 0;
11227
    }
11228
    /* src_resolved = os.path.join(dest_parent, src) */
11229
    if (_joinW(src_resolved, dest_parent, src)) {
11230
        return 0;
11231
    }
11232
    return (
11233
        GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
11234
        && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
11235
    );
11236
}
11237
#endif
11238
11239
11240
/*[clinic input]
11241
os.symlink
11242
    src: path_t
11243
    dst: path_t
11244
    target_is_directory: bool = False
11245
    *
11246
    dir_fd: dir_fd(requires='symlinkat')=None
11247
11248
Create a symbolic link pointing to src named dst.
11249
11250
target_is_directory is required on Windows if the target is to be
11251
interpreted as a directory.  (On Windows, symlink requires Windows 6.0
11252
or greater, and raises a NotImplementedError otherwise.)
11253
target_is_directory is ignored on non-Windows platforms.
11254
11255
If dir_fd is not None, it should be a file descriptor open to
11256
a directory, and path should be relative; path will then be relative
11257
to that directory.
11258
dir_fd may not be implemented on your platform.  If it is unavailable,
11259
using it will raise a NotImplementedError.
11260
11261
[clinic start generated code]*/
11262
11263
static PyObject *
11264
os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
11265
                int target_is_directory, int dir_fd)
11266
/*[clinic end generated code: output=08ca9f3f3cf960f6 input=71b75467b31c45f7]*/
11267
0
{
11268
#ifdef MS_WINDOWS
11269
    DWORD result;
11270
    DWORD flags = 0;
11271
11272
    /* Assumed true, set to false if detected to not be available. */
11273
    static int windows_has_symlink_unprivileged_flag = TRUE;
11274
#else
11275
0
    int result;
11276
0
#ifdef HAVE_SYMLINKAT
11277
0
    int symlinkat_unavailable = 0;
11278
0
#endif
11279
0
#endif
11280
11281
0
    if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
11282
0
                    dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
11283
0
        return NULL;
11284
0
    }
11285
11286
#ifdef MS_WINDOWS
11287
11288
    if (windows_has_symlink_unprivileged_flag) {
11289
        /* Allow non-admin symlinks if system allows it. */
11290
        flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
11291
    }
11292
11293
    Py_BEGIN_ALLOW_THREADS
11294
    _Py_BEGIN_SUPPRESS_IPH
11295
    /* if src is a directory, ensure flags==1 (target_is_directory bit) */
11296
    if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
11297
        flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
11298
    }
11299
11300
    result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11301
    _Py_END_SUPPRESS_IPH
11302
    Py_END_ALLOW_THREADS
11303
11304
    if (windows_has_symlink_unprivileged_flag && !result &&
11305
        ERROR_INVALID_PARAMETER == GetLastError()) {
11306
11307
        Py_BEGIN_ALLOW_THREADS
11308
        _Py_BEGIN_SUPPRESS_IPH
11309
        /* This error might be caused by
11310
        SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
11311
        Try again, and update windows_has_symlink_unprivileged_flag if we
11312
        are successful this time.
11313
11314
        NOTE: There is a risk of a race condition here if there are other
11315
        conditions than the flag causing ERROR_INVALID_PARAMETER, and
11316
        another process (or thread) changes that condition in between our
11317
        calls to CreateSymbolicLink.
11318
        */
11319
        flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
11320
        result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
11321
        _Py_END_SUPPRESS_IPH
11322
        Py_END_ALLOW_THREADS
11323
11324
        if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
11325
            windows_has_symlink_unprivileged_flag = FALSE;
11326
        }
11327
    }
11328
11329
    if (!result)
11330
        return path_error2(src, dst);
11331
11332
#else
11333
11334
0
    Py_BEGIN_ALLOW_THREADS
11335
0
#ifdef HAVE_SYMLINKAT
11336
0
    if (dir_fd != DEFAULT_DIR_FD) {
11337
0
        if (HAVE_SYMLINKAT_RUNTIME) {
11338
0
            result = symlinkat(src->narrow, dir_fd, dst->narrow);
11339
0
        } else {
11340
0
            symlinkat_unavailable = 1;
11341
0
        }
11342
0
    } else
11343
0
#endif
11344
0
        result = symlink(src->narrow, dst->narrow);
11345
0
    Py_END_ALLOW_THREADS
11346
11347
0
#ifdef HAVE_SYMLINKAT
11348
0
    if (symlinkat_unavailable) {
11349
0
          argument_unavailable_error(NULL, "dir_fd");
11350
0
          return NULL;
11351
0
    }
11352
0
#endif
11353
11354
0
    if (result)
11355
0
        return path_error2(src, dst);
11356
0
#endif
11357
11358
0
    Py_RETURN_NONE;
11359
0
}
11360
#endif /* HAVE_SYMLINK */
11361
11362
11363
static PyStructSequence_Field times_result_fields[] = {
11364
    {"user",    "user time"},
11365
    {"system",   "system time"},
11366
    {"children_user",    "user time of children"},
11367
    {"children_system",    "system time of children"},
11368
    {"elapsed",    "elapsed time since an arbitrary point in the past"},
11369
    {NULL}
11370
};
11371
11372
PyDoc_STRVAR(times_result__doc__,
11373
"times_result: Result from os.times().\n\n\
11374
This object may be accessed either as a tuple of\n\
11375
  (user, system, children_user, children_system, elapsed),\n\
11376
or via the attributes user, system, children_user, children_system,\n\
11377
and elapsed.\n\
11378
\n\
11379
See os.times for more information.");
11380
11381
static PyStructSequence_Desc times_result_desc = {
11382
    MODNAME ".times_result", /* name */
11383
    times_result__doc__, /* doc */
11384
    times_result_fields,
11385
    5
11386
};
11387
11388
static PyObject *
11389
build_times_result(PyObject *module, double user, double system,
11390
    double children_user, double children_system,
11391
    double elapsed)
11392
0
{
11393
0
    PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
11394
0
    PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
11395
0
    if (value == NULL)
11396
0
        return NULL;
11397
11398
0
#define SET(i, field) \
11399
0
    { \
11400
0
    PyObject *o = PyFloat_FromDouble(field); \
11401
0
    if (!o) { \
11402
0
        Py_DECREF(value); \
11403
0
        return NULL; \
11404
0
    } \
11405
0
    PyStructSequence_SET_ITEM(value, i, o); \
11406
0
    } \
11407
0
11408
0
    SET(0, user);
11409
0
    SET(1, system);
11410
0
    SET(2, children_user);
11411
0
    SET(3, children_system);
11412
0
    SET(4, elapsed);
11413
11414
0
#undef SET
11415
11416
0
    return value;
11417
0
}
11418
11419
11420
/*[clinic input]
11421
os.times
11422
11423
Return a collection containing process timing information.
11424
11425
The object returned behaves like a named tuple with these fields:
11426
  (utime, stime, cutime, cstime, elapsed_time)
11427
All fields are floating-point numbers.
11428
[clinic start generated code]*/
11429
11430
static PyObject *
11431
os_times_impl(PyObject *module)
11432
/*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/
11433
0
{
11434
#ifdef MS_WINDOWS
11435
    FILETIME create, exit, kernel, user;
11436
    HANDLE hProc;
11437
    hProc = GetCurrentProcess();
11438
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
11439
    /* The fields of a FILETIME structure are the hi and lo part
11440
       of a 64-bit value expressed in 100 nanosecond units.
11441
       1e7 is one second in such units; 1e-7 the inverse.
11442
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
11443
    */
11444
    return build_times_result(module,
11445
        (double)(user.dwHighDateTime*429.4967296 +
11446
                 user.dwLowDateTime*1e-7),
11447
        (double)(kernel.dwHighDateTime*429.4967296 +
11448
                 kernel.dwLowDateTime*1e-7),
11449
        (double)0,
11450
        (double)0,
11451
        (double)0);
11452
#else /* MS_WINDOWS */
11453
0
    _posixstate *state = get_posix_state(module);
11454
0
    long ticks_per_second = state->ticks_per_second;
11455
11456
0
    struct tms process;
11457
0
    clock_t elapsed;
11458
0
    errno = 0;
11459
0
    elapsed = times(&process);
11460
0
    if (elapsed == (clock_t) -1) {
11461
0
        return posix_error();
11462
0
    }
11463
11464
0
    return build_times_result(module,
11465
0
        (double)process.tms_utime / ticks_per_second,
11466
0
        (double)process.tms_stime / ticks_per_second,
11467
0
        (double)process.tms_cutime / ticks_per_second,
11468
0
        (double)process.tms_cstime / ticks_per_second,
11469
0
        (double)elapsed / ticks_per_second);
11470
0
#endif /* MS_WINDOWS */
11471
0
}
11472
11473
11474
#if defined(HAVE_TIMERFD_CREATE)
11475
#define ONE_SECOND_IN_NS (1000 * 1000 * 1000)
11476
#define EXTRACT_NSEC(value)  (long)( ( (double)(value) - (time_t)(value) ) * 1e9)
11477
0
#define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) ( (double)(sec) + (double)(nsec) * 1e-9 )
11478
11479
static PyObject *
11480
build_itimerspec(const struct itimerspec* curr_value)
11481
0
{
11482
0
    double _value = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_value.tv_sec,
11483
0
                                                          curr_value->it_value.tv_nsec);
11484
0
    PyObject *value = PyFloat_FromDouble(_value);
11485
0
    if (value == NULL) {
11486
0
        return NULL;
11487
0
    }
11488
0
    double _interval = CONVERT_SEC_AND_NSEC_TO_DOUBLE(curr_value->it_interval.tv_sec,
11489
0
                                                   curr_value->it_interval.tv_nsec);
11490
0
    PyObject *interval = PyFloat_FromDouble(_interval);
11491
0
    if (interval == NULL) {
11492
0
        Py_DECREF(value);
11493
0
        return NULL;
11494
0
    }
11495
0
    return _PyTuple_FromPairSteal(value, interval);
11496
0
}
11497
11498
static PyObject *
11499
build_itimerspec_ns(const struct itimerspec* curr_value)
11500
0
{
11501
0
    PyTime_t value, interval;
11502
0
    if (_PyTime_FromTimespec(&value, &curr_value->it_value) < 0) {
11503
0
        return NULL;
11504
0
    }
11505
0
    if (_PyTime_FromTimespec(&interval, &curr_value->it_interval) < 0) {
11506
0
        return NULL;
11507
0
    }
11508
0
    return Py_BuildValue("LL", value, interval);
11509
0
}
11510
11511
/*[clinic input]
11512
os.timerfd_create
11513
11514
    clockid: int
11515
        A valid clock ID constant as timer file descriptor.
11516
11517
        time.CLOCK_REALTIME
11518
        time.CLOCK_MONOTONIC
11519
        time.CLOCK_BOOTTIME
11520
    /
11521
    *
11522
    flags: int = 0
11523
        0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC.
11524
11525
        os.TFD_NONBLOCK
11526
            If *TFD_NONBLOCK* is set as a flag, read doesn't blocks.
11527
            If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires.
11528
11529
        os.TFD_CLOEXEC
11530
            If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag
11531
11532
Create and return a timer file descriptor.
11533
[clinic start generated code]*/
11534
11535
static PyObject *
11536
os_timerfd_create_impl(PyObject *module, int clockid, int flags)
11537
/*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/
11538
11539
0
{
11540
0
    int fd;
11541
0
    Py_BEGIN_ALLOW_THREADS
11542
0
    flags |= TFD_CLOEXEC;  // PEP 446: always create non-inheritable FD
11543
0
    fd = timerfd_create(clockid, flags);
11544
0
    Py_END_ALLOW_THREADS
11545
0
    if (fd == -1) {
11546
0
        return PyErr_SetFromErrno(PyExc_OSError);
11547
0
    }
11548
0
    return PyLong_FromLong(fd);
11549
0
}
11550
11551
/*[clinic input]
11552
os.timerfd_settime
11553
11554
    fd: fildes
11555
        A timer file descriptor.
11556
    /
11557
    *
11558
    flags: int = 0
11559
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11560
    initial as initial_double: double = 0.0
11561
        The initial expiration time, in seconds.
11562
    interval as interval_double: double = 0.0
11563
        The timer's interval, in seconds.
11564
11565
Alter a timer file descriptor's internal timer in seconds.
11566
[clinic start generated code]*/
11567
11568
static PyObject *
11569
os_timerfd_settime_impl(PyObject *module, int fd, int flags,
11570
                        double initial_double, double interval_double)
11571
/*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/
11572
0
{
11573
0
    PyTime_t initial, interval;
11574
0
    if (_PyTime_FromSecondsDouble(initial_double, _PyTime_ROUND_FLOOR,
11575
0
                                  &initial) < 0) {
11576
0
        return NULL;
11577
0
    }
11578
0
    if (_PyTime_FromSecondsDouble(interval_double, _PyTime_ROUND_FLOOR,
11579
0
                                  &interval) < 0) {
11580
0
        return NULL;
11581
0
    }
11582
11583
0
    struct itimerspec new_value, old_value;
11584
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11585
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11586
0
        return NULL;
11587
0
    }
11588
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11589
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11590
0
        return NULL;
11591
0
    }
11592
11593
0
    int result;
11594
0
    Py_BEGIN_ALLOW_THREADS
11595
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11596
0
    Py_END_ALLOW_THREADS
11597
0
    if (result == -1) {
11598
0
        return PyErr_SetFromErrno(PyExc_OSError);
11599
0
    }
11600
0
    return build_itimerspec(&old_value);
11601
0
}
11602
11603
11604
/*[clinic input]
11605
os.timerfd_settime_ns
11606
11607
    fd: fildes
11608
        A timer file descriptor.
11609
    /
11610
    *
11611
    flags: int = 0
11612
        0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET.
11613
    initial: long_long = 0
11614
        initial expiration timing in nanoseconds.
11615
    interval: long_long = 0
11616
        interval for the timer in nanoseconds.
11617
11618
Alter a timer file descriptor's internal timer in nanoseconds.
11619
[clinic start generated code]*/
11620
11621
static PyObject *
11622
os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags,
11623
                           long long initial, long long interval)
11624
/*[clinic end generated code: output=6273ec7d7b4cc0b3 input=94bdcea7292157eb]*/
11625
0
{
11626
0
    struct itimerspec new_value;
11627
0
    struct itimerspec old_value;
11628
0
    int result;
11629
0
    if (_PyTime_AsTimespec(initial, &new_value.it_value) < 0) {
11630
0
        PyErr_SetString(PyExc_ValueError, "invalid initial value");
11631
0
        return NULL;
11632
0
    }
11633
0
    if (_PyTime_AsTimespec(interval, &new_value.it_interval) < 0) {
11634
0
        PyErr_SetString(PyExc_ValueError, "invalid interval value");
11635
0
        return NULL;
11636
0
    }
11637
0
    Py_BEGIN_ALLOW_THREADS
11638
0
    result = timerfd_settime(fd, flags, &new_value, &old_value);
11639
0
    Py_END_ALLOW_THREADS
11640
0
    if (result == -1) {
11641
0
        return PyErr_SetFromErrno(PyExc_OSError);
11642
0
    }
11643
0
    return build_itimerspec_ns(&old_value);
11644
0
}
11645
11646
/*[clinic input]
11647
@permit_long_summary
11648
os.timerfd_gettime
11649
11650
    fd: fildes
11651
        A timer file descriptor.
11652
    /
11653
11654
Return a tuple of a timer file descriptor's (next expiration, interval) in float seconds.
11655
[clinic start generated code]*/
11656
11657
static PyObject *
11658
os_timerfd_gettime_impl(PyObject *module, int fd)
11659
/*[clinic end generated code: output=ec5a94a66cfe6ab4 input=7b0a7cc61ea9e31a]*/
11660
0
{
11661
0
    struct itimerspec curr_value;
11662
0
    int result;
11663
0
    Py_BEGIN_ALLOW_THREADS
11664
0
    result = timerfd_gettime(fd, &curr_value);
11665
0
    Py_END_ALLOW_THREADS
11666
0
    if (result == -1) {
11667
0
        return PyErr_SetFromErrno(PyExc_OSError);
11668
0
    }
11669
0
    return build_itimerspec(&curr_value);
11670
0
}
11671
11672
11673
/*[clinic input]
11674
@permit_long_summary
11675
os.timerfd_gettime_ns
11676
11677
    fd: fildes
11678
        A timer file descriptor.
11679
    /
11680
11681
Return a tuple of a timer file descriptor's (next expiration, interval) in nanoseconds.
11682
[clinic start generated code]*/
11683
11684
static PyObject *
11685
os_timerfd_gettime_ns_impl(PyObject *module, int fd)
11686
/*[clinic end generated code: output=580633a4465f39fe input=89702268455fa93b]*/
11687
0
{
11688
0
    struct itimerspec curr_value;
11689
0
    int result;
11690
0
    Py_BEGIN_ALLOW_THREADS
11691
0
    result = timerfd_gettime(fd, &curr_value);
11692
0
    Py_END_ALLOW_THREADS
11693
0
    if (result == -1) {
11694
0
        return PyErr_SetFromErrno(PyExc_OSError);
11695
0
    }
11696
0
    return build_itimerspec_ns(&curr_value);
11697
0
}
11698
11699
#undef ONE_SECOND_IN_NS
11700
#undef EXTRACT_NSEC
11701
11702
#endif  /* HAVE_TIMERFD_CREATE */
11703
11704
#ifdef HAVE_GETSID
11705
/*[clinic input]
11706
os.getsid
11707
11708
    pid: pid_t
11709
    /
11710
11711
Call the system call getsid(pid) and return the result.
11712
[clinic start generated code]*/
11713
11714
static PyObject *
11715
os_getsid_impl(PyObject *module, pid_t pid)
11716
/*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
11717
0
{
11718
0
    int sid;
11719
0
    sid = getsid(pid);
11720
0
    if (sid < 0)
11721
0
        return posix_error();
11722
0
    return PyLong_FromLong((long)sid);
11723
0
}
11724
#endif /* HAVE_GETSID */
11725
11726
11727
#ifdef HAVE_SETSID
11728
/*[clinic input]
11729
os.setsid
11730
11731
Call the system call setsid().
11732
[clinic start generated code]*/
11733
11734
static PyObject *
11735
os_setsid_impl(PyObject *module)
11736
/*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
11737
0
{
11738
0
    if (setsid() < 0)
11739
0
        return posix_error();
11740
0
    Py_RETURN_NONE;
11741
0
}
11742
#endif /* HAVE_SETSID */
11743
11744
11745
#ifdef HAVE_SETPGID
11746
/*[clinic input]
11747
os.setpgid
11748
11749
    pid: pid_t
11750
    pgrp: pid_t
11751
    /
11752
11753
Call the system call setpgid(pid, pgrp).
11754
[clinic start generated code]*/
11755
11756
static PyObject *
11757
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
11758
/*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
11759
0
{
11760
0
    if (setpgid(pid, pgrp) < 0)
11761
0
        return posix_error();
11762
0
    Py_RETURN_NONE;
11763
0
}
11764
#endif /* HAVE_SETPGID */
11765
11766
11767
#ifdef HAVE_TCGETPGRP
11768
/*[clinic input]
11769
os.tcgetpgrp
11770
11771
    fd: int
11772
    /
11773
11774
Return the process group associated with the terminal specified by fd.
11775
[clinic start generated code]*/
11776
11777
static PyObject *
11778
os_tcgetpgrp_impl(PyObject *module, int fd)
11779
/*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
11780
0
{
11781
0
    pid_t pgid = tcgetpgrp(fd);
11782
0
    if (pgid < 0)
11783
0
        return posix_error();
11784
0
    return PyLong_FromPid(pgid);
11785
0
}
11786
#endif /* HAVE_TCGETPGRP */
11787
11788
11789
#ifdef HAVE_TCSETPGRP
11790
/*[clinic input]
11791
os.tcsetpgrp
11792
11793
    fd: int
11794
    pgid: pid_t
11795
    /
11796
11797
Set the process group associated with the terminal specified by fd.
11798
[clinic start generated code]*/
11799
11800
static PyObject *
11801
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
11802
/*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
11803
0
{
11804
0
    if (tcsetpgrp(fd, pgid) < 0)
11805
0
        return posix_error();
11806
0
    Py_RETURN_NONE;
11807
0
}
11808
#endif /* HAVE_TCSETPGRP */
11809
11810
/* Functions acting on file descriptors */
11811
11812
#ifdef O_CLOEXEC
11813
extern int _Py_open_cloexec_works;
11814
#endif
11815
11816
11817
/*[clinic input]
11818
os.open -> int
11819
    path: path_t
11820
    flags: int
11821
    mode: int = 0o777
11822
    *
11823
    dir_fd: dir_fd(requires='openat') = None
11824
11825
Open a file for low level IO.  Returns a file descriptor (integer).
11826
11827
If dir_fd is not None, it should be a file descriptor open to
11828
a directory, and path should be relative; path will then be relative to
11829
that directory.
11830
dir_fd may not be implemented on your platform.  If it is unavailable,
11831
using it will raise a NotImplementedError.
11832
[clinic start generated code]*/
11833
11834
static int
11835
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
11836
/*[clinic end generated code: output=abc7227888c8bc73 input=75f7b4eaf92f2225]*/
11837
91.2k
{
11838
91.2k
    int fd;
11839
91.2k
    int async_err = 0;
11840
91.2k
#ifdef HAVE_OPENAT
11841
91.2k
    int openat_unavailable = 0;
11842
91.2k
#endif
11843
11844
91.2k
#ifdef O_CLOEXEC
11845
91.2k
    int *atomic_flag_works = &_Py_open_cloexec_works;
11846
#elif !defined(MS_WINDOWS)
11847
    int *atomic_flag_works = NULL;
11848
#endif
11849
11850
#ifdef MS_WINDOWS
11851
    flags |= O_NOINHERIT;
11852
#elif defined(O_CLOEXEC)
11853
91.2k
    flags |= O_CLOEXEC;
11854
91.2k
#endif
11855
11856
91.2k
    if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
11857
0
        return -1;
11858
0
    }
11859
11860
91.2k
    _Py_BEGIN_SUPPRESS_IPH
11861
91.2k
    do {
11862
91.2k
        Py_BEGIN_ALLOW_THREADS
11863
#ifdef MS_WINDOWS
11864
        fd = _wopen(path->wide, flags, mode);
11865
#else
11866
91.2k
#ifdef HAVE_OPENAT
11867
91.2k
        if (dir_fd != DEFAULT_DIR_FD) {
11868
86.9k
            if (HAVE_OPENAT_RUNTIME) {
11869
86.9k
                fd = openat(dir_fd, path->narrow, flags, mode);
11870
11871
86.9k
            } else {
11872
0
                openat_unavailable = 1;
11873
0
                fd = -1;
11874
0
            }
11875
86.9k
        } else
11876
4.25k
#endif /* HAVE_OPENAT */
11877
4.25k
            fd = open(path->narrow, flags, mode);
11878
91.2k
#endif /* !MS_WINDOWS */
11879
91.2k
        Py_END_ALLOW_THREADS
11880
91.2k
    } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
11881
91.2k
    _Py_END_SUPPRESS_IPH
11882
11883
91.2k
#ifdef HAVE_OPENAT
11884
91.2k
    if (openat_unavailable) {
11885
0
        argument_unavailable_error(NULL, "dir_fd");
11886
0
        return -1;
11887
0
    }
11888
91.2k
#endif
11889
11890
91.2k
    if (fd < 0) {
11891
0
        if (!async_err)
11892
0
            PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
11893
0
        return -1;
11894
0
    }
11895
11896
91.2k
#ifndef MS_WINDOWS
11897
91.2k
    if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
11898
0
        close(fd);
11899
0
        return -1;
11900
0
    }
11901
91.2k
#endif
11902
11903
91.2k
    return fd;
11904
91.2k
}
11905
11906
11907
/*[clinic input]
11908
os.close
11909
11910
    fd: int
11911
11912
Close a file descriptor.
11913
[clinic start generated code]*/
11914
11915
static PyObject *
11916
os_close_impl(PyObject *module, int fd)
11917
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
11918
91.0k
{
11919
91.0k
    int res;
11920
    /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
11921
     * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
11922
     * for more details.
11923
     */
11924
91.0k
    Py_BEGIN_ALLOW_THREADS
11925
91.0k
    _Py_BEGIN_SUPPRESS_IPH
11926
91.0k
    res = close(fd);
11927
91.0k
    _Py_END_SUPPRESS_IPH
11928
91.0k
    Py_END_ALLOW_THREADS
11929
91.0k
    if (res < 0)
11930
0
        return posix_error();
11931
91.0k
    Py_RETURN_NONE;
11932
91.0k
}
11933
11934
/*[clinic input]
11935
os.closerange
11936
11937
    fd_low: int
11938
    fd_high: int
11939
    /
11940
11941
Closes all file descriptors in [fd_low, fd_high), ignoring errors.
11942
[clinic start generated code]*/
11943
11944
static PyObject *
11945
os_closerange_impl(PyObject *module, int fd_low, int fd_high)
11946
/*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
11947
0
{
11948
0
    Py_BEGIN_ALLOW_THREADS
11949
0
    _Py_closerange(fd_low, fd_high - 1);
11950
0
    Py_END_ALLOW_THREADS
11951
0
    Py_RETURN_NONE;
11952
0
}
11953
11954
11955
/*[clinic input]
11956
os.dup -> int
11957
11958
    fd: int
11959
    /
11960
11961
Return a duplicate of a file descriptor.
11962
[clinic start generated code]*/
11963
11964
static int
11965
os_dup_impl(PyObject *module, int fd)
11966
/*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
11967
0
{
11968
0
    return _Py_dup(fd);
11969
0
}
11970
11971
// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
11972
// dup2.c provides working dup2() if and only if F_DUPFD is available.
11973
#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
11974
/*[clinic input]
11975
os.dup2 -> int
11976
    fd: int
11977
    fd2: int
11978
    inheritable: bool=True
11979
11980
Duplicate file descriptor.
11981
[clinic start generated code]*/
11982
11983
static int
11984
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
11985
/*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
11986
0
{
11987
0
    int res = 0;
11988
11989
    /* dup3() is available on Linux 2.6.27+ and glibc 2.9 and macOS 27.0;
11990
     * it needs runtime detection for the case of running on older kernels.
11991
     * Values: -1: unknown; 0: doesn't work; 1: works
11992
     * For thread safety, use a process-global with one read & one store,
11993
     * both relaxed. (It's fine if two threads race and do the detection
11994
     * simultaneously; they should get the same result.)
11995
     */
11996
0
    static int dup3_works_atomic = -1;
11997
0
    (void) dup3_works_atomic;  // unused on some platforms
11998
11999
    /* dup2() can fail with EINTR if the target FD is already open, because it
12000
     * then has to be closed. See os_close_impl() for why we don't handle EINTR
12001
     * upon close(), and therefore below.
12002
     */
12003
#ifdef MS_WINDOWS
12004
    Py_BEGIN_ALLOW_THREADS
12005
    _Py_BEGIN_SUPPRESS_IPH
12006
    res = dup2(fd, fd2);
12007
    _Py_END_SUPPRESS_IPH
12008
    Py_END_ALLOW_THREADS
12009
    if (res < 0) {
12010
        posix_error();
12011
        return -1;
12012
    }
12013
    res = fd2; // msvcrt dup2 returns 0 on success.
12014
12015
    /* Character files like console cannot be make non-inheritable */
12016
    if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
12017
        close(fd2);
12018
        return -1;
12019
    }
12020
12021
#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
12022
    Py_BEGIN_ALLOW_THREADS
12023
    if (!inheritable)
12024
        res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
12025
    else
12026
        res = dup2(fd, fd2);
12027
    Py_END_ALLOW_THREADS
12028
    if (res < 0) {
12029
        posix_error();
12030
        return -1;
12031
    }
12032
12033
#else
12034
12035
0
#ifdef HAVE_DUP3
12036
0
    int dup3_works = FT_ATOMIC_LOAD_INT_RELAXED(dup3_works_atomic);
12037
0
    if (!inheritable && dup3_works != 0) {
12038
0
        if (HAVE_DUP3_RUNTIME) {
12039
0
            Py_BEGIN_ALLOW_THREADS
12040
0
            res = dup3(fd, fd2, O_CLOEXEC);
12041
0
            Py_END_ALLOW_THREADS
12042
0
            if (res < 0) {
12043
0
                if (dup3_works == -1) {
12044
0
                    dup3_works = (errno != ENOSYS);
12045
0
                    FT_ATOMIC_STORE_INT_RELAXED(dup3_works_atomic, dup3_works);
12046
0
                }
12047
0
                if (dup3_works) {
12048
0
                    posix_error();
12049
0
                    return -1;
12050
0
                }
12051
0
            }
12052
0
        }
12053
0
        else {
12054
0
            dup3_works = 0;
12055
0
            FT_ATOMIC_STORE_INT_RELAXED(dup3_works_atomic, dup3_works);
12056
0
        }
12057
0
    }
12058
12059
0
    if (inheritable || dup3_works == 0)
12060
0
    {
12061
0
#endif
12062
0
        Py_BEGIN_ALLOW_THREADS
12063
0
        res = dup2(fd, fd2);
12064
0
        Py_END_ALLOW_THREADS
12065
0
        if (res < 0) {
12066
0
            posix_error();
12067
0
            return -1;
12068
0
        }
12069
12070
0
        if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
12071
0
            close(fd2);
12072
0
            return -1;
12073
0
        }
12074
0
#ifdef HAVE_DUP3
12075
0
    }
12076
0
#endif
12077
12078
0
#endif
12079
12080
0
    return res;
12081
0
}
12082
#endif
12083
12084
12085
#ifdef HAVE_LOCKF
12086
/*[clinic input]
12087
os.lockf
12088
12089
    fd: int
12090
        An open file descriptor.
12091
    command: int
12092
        One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
12093
    length: Py_off_t
12094
        The number of bytes to lock, starting at the current position.
12095
    /
12096
12097
Apply, test or remove a POSIX lock on an open file descriptor.
12098
12099
[clinic start generated code]*/
12100
12101
static PyObject *
12102
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
12103
/*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
12104
0
{
12105
0
    int res;
12106
12107
0
    if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
12108
0
        return NULL;
12109
0
    }
12110
12111
0
    Py_BEGIN_ALLOW_THREADS
12112
0
    res = lockf(fd, command, length);
12113
0
    Py_END_ALLOW_THREADS
12114
12115
0
    if (res < 0)
12116
0
        return posix_error();
12117
12118
0
    Py_RETURN_NONE;
12119
0
}
12120
#endif /* HAVE_LOCKF */
12121
12122
12123
/*[clinic input]
12124
os.lseek -> Py_off_t
12125
12126
    fd: int
12127
        An open file descriptor, as returned by os.open().
12128
    position: Py_off_t
12129
        Position, interpreted relative to 'whence'.
12130
    whence as how: int
12131
        The relative position to seek from. Valid values are:
12132
        - SEEK_SET: seek from the start of the file.
12133
        - SEEK_CUR: seek from the current file position.
12134
        - SEEK_END: seek from the end of the file.
12135
    /
12136
12137
Set the position of a file descriptor.  Return the new position.
12138
12139
The return value is the number of bytes relative to the beginning of
12140
the file.
12141
[clinic start generated code]*/
12142
12143
static Py_off_t
12144
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
12145
/*[clinic end generated code: output=971e1efb6b30bd2f input=32ea0788da7cb44b]*/
12146
0
{
12147
0
    Py_off_t result = -1;
12148
12149
0
#ifdef SEEK_SET
12150
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
12151
0
    switch (how) {
12152
0
        case 0: how = SEEK_SET; break;
12153
0
        case 1: how = SEEK_CUR; break;
12154
0
        case 2: how = SEEK_END; break;
12155
0
    }
12156
0
#endif /* SEEK_END */
12157
12158
0
    Py_BEGIN_ALLOW_THREADS
12159
0
    _Py_BEGIN_SUPPRESS_IPH
12160
#ifdef MS_WINDOWS
12161
    HANDLE h = (HANDLE)_get_osfhandle(fd);
12162
    if (h != INVALID_HANDLE_VALUE && GetFileType(h) == FILE_TYPE_PIPE) {
12163
        errno = ESPIPE;
12164
    }
12165
    else {
12166
        result = _lseeki64(fd, position, how);
12167
    }
12168
#else
12169
0
    result = lseek(fd, position, how);
12170
0
#endif
12171
0
    _Py_END_SUPPRESS_IPH
12172
0
    Py_END_ALLOW_THREADS
12173
0
    if (result < 0) {
12174
0
        posix_error();
12175
0
    }
12176
12177
0
    return result;
12178
0
}
12179
12180
12181
/*[clinic input]
12182
os.read
12183
    fd: int
12184
    length: Py_ssize_t
12185
    /
12186
12187
Read from a file descriptor.  Returns a bytes object.
12188
[clinic start generated code]*/
12189
12190
static PyObject *
12191
os_read_impl(PyObject *module, int fd, Py_ssize_t length)
12192
/*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
12193
0
{
12194
0
    if (length < 0) {
12195
0
        errno = EINVAL;
12196
0
        return posix_error();
12197
0
    }
12198
12199
0
    length = Py_MIN(length, _PY_READ_MAX);
12200
12201
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12202
0
    if (writer == NULL) {
12203
0
        return NULL;
12204
0
    }
12205
12206
0
    Py_ssize_t n = _Py_read(fd, PyBytesWriter_GetData(writer), length);
12207
0
    if (n == -1) {
12208
0
        PyBytesWriter_Discard(writer);
12209
0
        return NULL;
12210
0
    }
12211
12212
0
    return PyBytesWriter_FinishWithSize(writer, n);
12213
0
}
12214
12215
/*[clinic input]
12216
os.readinto -> Py_ssize_t
12217
    fd: int
12218
    buffer: Py_buffer(accept={rwbuffer})
12219
    /
12220
12221
Read into a buffer object from a file descriptor.
12222
12223
The buffer should be mutable and bytes-like.  On success, returns the
12224
number of bytes read.  Less bytes may be read than the size of the
12225
buffer.  The underlying system call will be retried when interrupted by
12226
a signal, unless the signal handler raises an exception.  Other errors
12227
will not be retried and an error will be raised.
12228
12229
Returns 0 if *fd* is at end of file or if the provided *buffer* has
12230
length 0 (which can be used to check for errors without reading data).
12231
Never returns negative.
12232
[clinic start generated code]*/
12233
12234
static Py_ssize_t
12235
os_readinto_impl(PyObject *module, int fd, Py_buffer *buffer)
12236
/*[clinic end generated code: output=8091a3513c683a80 input=2a5f8b212cb5730c]*/
12237
0
{
12238
0
    assert(buffer->len >= 0);
12239
0
    Py_ssize_t result = _Py_read(fd, buffer->buf, buffer->len);
12240
    /* Ensure negative is never returned without an error. Simplifies calling
12241
        code. _Py_read should succeed, possibly reading 0 bytes, _or_ set an
12242
        error. */
12243
0
    assert(result >= 0 || (result == -1 && PyErr_Occurred()));
12244
0
    return result;
12245
0
}
12246
12247
#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
12248
                                || defined(__APPLE__))) \
12249
    || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
12250
    || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
12251
static int
12252
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
12253
0
{
12254
0
    Py_ssize_t i, j;
12255
12256
0
    *iov = PyMem_New(struct iovec, cnt);
12257
0
    if (*iov == NULL) {
12258
0
        PyErr_NoMemory();
12259
0
        return -1;
12260
0
    }
12261
12262
0
    *buf = PyMem_New(Py_buffer, cnt);
12263
0
    if (*buf == NULL) {
12264
0
        PyMem_Free(*iov);
12265
0
        PyErr_NoMemory();
12266
0
        return -1;
12267
0
    }
12268
12269
0
    for (i = 0; i < cnt; i++) {
12270
0
        PyObject *item = PySequence_GetItem(seq, i);
12271
0
        if (item == NULL)
12272
0
            goto fail;
12273
0
        if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
12274
0
            Py_DECREF(item);
12275
0
            goto fail;
12276
0
        }
12277
0
        Py_DECREF(item);
12278
0
        (*iov)[i].iov_base = (*buf)[i].buf;
12279
0
        (*iov)[i].iov_len = (*buf)[i].len;
12280
0
    }
12281
0
    return 0;
12282
12283
0
fail:
12284
0
    PyMem_Free(*iov);
12285
0
    for (j = 0; j < i; j++) {
12286
0
        PyBuffer_Release(&(*buf)[j]);
12287
0
    }
12288
0
    PyMem_Free(*buf);
12289
0
    return -1;
12290
0
}
12291
12292
static void
12293
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
12294
0
{
12295
0
    int i;
12296
0
    PyMem_Free(iov);
12297
0
    for (i = 0; i < cnt; i++) {
12298
0
        PyBuffer_Release(&buf[i]);
12299
0
    }
12300
0
    PyMem_Free(buf);
12301
0
}
12302
#endif
12303
12304
12305
#ifdef HAVE_READV
12306
/*[clinic input]
12307
os.readv -> Py_ssize_t
12308
12309
    fd: int
12310
    buffers: object
12311
    /
12312
12313
Read from a file descriptor fd into an iterable of buffers.
12314
12315
The buffers should be mutable buffers accepting bytes.
12316
readv will transfer data into each buffer until it is full
12317
and then move on to the next buffer in the sequence to hold
12318
the rest of the data.
12319
12320
readv returns the total number of bytes read,
12321
which may be less than the total capacity of all the buffers.
12322
[clinic start generated code]*/
12323
12324
static Py_ssize_t
12325
os_readv_impl(PyObject *module, int fd, PyObject *buffers)
12326
/*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
12327
0
{
12328
0
    Py_ssize_t cnt, n;
12329
0
    int async_err = 0;
12330
0
    struct iovec *iov;
12331
0
    Py_buffer *buf;
12332
12333
0
    if (!PySequence_Check(buffers)) {
12334
0
        PyErr_SetString(PyExc_TypeError,
12335
0
            "readv() arg 2 must be a sequence");
12336
0
        return -1;
12337
0
    }
12338
12339
0
    cnt = PySequence_Size(buffers);
12340
0
    if (cnt < 0)
12341
0
        return -1;
12342
12343
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
12344
0
        return -1;
12345
12346
0
    do {
12347
0
        Py_BEGIN_ALLOW_THREADS
12348
0
        n = readv(fd, iov, cnt);
12349
0
        Py_END_ALLOW_THREADS
12350
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12351
12352
0
    int saved_errno = errno;
12353
0
    iov_cleanup(iov, buf, cnt);
12354
0
    if (n < 0) {
12355
0
        if (!async_err) {
12356
0
            errno = saved_errno;
12357
0
            posix_error();
12358
0
        }
12359
0
        return -1;
12360
0
    }
12361
12362
0
    return n;
12363
0
}
12364
#endif /* HAVE_READV */
12365
12366
12367
#ifdef HAVE_PREAD
12368
/*[clinic input]
12369
@permit_long_summary
12370
os.pread
12371
12372
    fd: int
12373
    length: Py_ssize_t
12374
    offset: Py_off_t
12375
    /
12376
12377
Read a number of bytes from a file descriptor starting at a particular offset.
12378
12379
Read length bytes from file descriptor fd, starting at offset bytes from
12380
the beginning of the file.  The file offset remains unchanged.
12381
[clinic start generated code]*/
12382
12383
static PyObject *
12384
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
12385
/*[clinic end generated code: output=3f875c1eef82e32f input=5943beb009d3da04]*/
12386
0
{
12387
0
    Py_ssize_t n;
12388
0
    int async_err = 0;
12389
12390
0
    if (length < 0) {
12391
0
        errno = EINVAL;
12392
0
        return posix_error();
12393
0
    }
12394
0
    PyBytesWriter *writer = PyBytesWriter_Create(length);
12395
0
    if (writer == NULL) {
12396
0
        return NULL;
12397
0
    }
12398
12399
0
    do {
12400
0
        Py_BEGIN_ALLOW_THREADS
12401
0
        _Py_BEGIN_SUPPRESS_IPH
12402
0
        n = pread(fd, PyBytesWriter_GetData(writer), length, offset);
12403
0
        _Py_END_SUPPRESS_IPH
12404
0
        Py_END_ALLOW_THREADS
12405
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12406
12407
0
    if (n < 0) {
12408
0
        if (!async_err) {
12409
0
            posix_error();
12410
0
        }
12411
0
        PyBytesWriter_Discard(writer);
12412
0
        return NULL;
12413
0
    }
12414
0
    return PyBytesWriter_FinishWithSize(writer, n);
12415
0
}
12416
#endif /* HAVE_PREAD */
12417
12418
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
12419
/*[clinic input]
12420
@permit_long_summary
12421
os.preadv -> Py_ssize_t
12422
12423
    fd: int
12424
    buffers: object
12425
    offset: Py_off_t
12426
    flags: int = 0
12427
    /
12428
12429
Reads from a file descriptor into a number of mutable bytes-like objects.
12430
12431
Combines the functionality of readv() and pread().  As readv(), it will
12432
transfer data into each buffer until it is full and then move on to the
12433
next buffer in the sequence to hold the rest of the data.  Its fourth
12434
argument, specifies the file offset at which the input operation is to
12435
be performed.  It will return the total number of bytes read (which can
12436
be less than the total capacity of all the objects).
12437
12438
The flags argument contains a bitwise OR of zero or more of the
12439
following flags:
12440
12441
- RWF_HIPRI
12442
- RWF_NOWAIT
12443
- RWF_DONTCACHE
12444
12445
Using non-zero flags requires Linux 4.6 or newer.
12446
[clinic start generated code]*/
12447
12448
static Py_ssize_t
12449
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
12450
               int flags)
12451
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=bbc70c63b4f4e877]*/
12452
0
{
12453
0
    Py_ssize_t cnt, n;
12454
0
    int async_err = 0;
12455
0
    struct iovec *iov;
12456
0
    Py_buffer *buf;
12457
12458
0
    if (!PySequence_Check(buffers)) {
12459
0
        PyErr_SetString(PyExc_TypeError,
12460
0
            "preadv2() arg 2 must be a sequence");
12461
0
        return -1;
12462
0
    }
12463
12464
0
    cnt = PySequence_Size(buffers);
12465
0
    if (cnt < 0) {
12466
0
        return -1;
12467
0
    }
12468
12469
#ifndef HAVE_PREADV2
12470
    if(flags != 0) {
12471
        argument_unavailable_error("preadv2", "flags");
12472
        return -1;
12473
    }
12474
#endif
12475
12476
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
12477
0
        return -1;
12478
0
    }
12479
0
#ifdef HAVE_PREADV2
12480
0
    do {
12481
0
        Py_BEGIN_ALLOW_THREADS
12482
0
        _Py_BEGIN_SUPPRESS_IPH
12483
0
        n = preadv2(fd, iov, cnt, offset, flags);
12484
0
        _Py_END_SUPPRESS_IPH
12485
0
        Py_END_ALLOW_THREADS
12486
0
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12487
#else
12488
    do {
12489
#if defined(__APPLE__) && defined(__clang__)
12490
/* This entire function will be removed from the module dict when the API
12491
 * is not available.
12492
 */
12493
#pragma clang diagnostic push
12494
#pragma clang diagnostic ignored "-Wunguarded-availability"
12495
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
12496
#endif
12497
        Py_BEGIN_ALLOW_THREADS
12498
        _Py_BEGIN_SUPPRESS_IPH
12499
        n = preadv(fd, iov, cnt, offset);
12500
        _Py_END_SUPPRESS_IPH
12501
        Py_END_ALLOW_THREADS
12502
    } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12503
12504
#if defined(__APPLE__) && defined(__clang__)
12505
#pragma clang diagnostic pop
12506
#endif
12507
12508
#endif
12509
12510
0
    int saved_errno = errno;
12511
0
    iov_cleanup(iov, buf, cnt);
12512
0
    if (n < 0) {
12513
0
        if (!async_err) {
12514
0
            errno = saved_errno;
12515
0
            posix_error();
12516
0
        }
12517
0
        return -1;
12518
0
    }
12519
12520
0
    return n;
12521
0
}
12522
#endif /* HAVE_PREADV */
12523
12524
12525
/*[clinic input]
12526
os.write -> Py_ssize_t
12527
12528
    fd: int
12529
    data: Py_buffer
12530
    /
12531
12532
Write a bytes object to a file descriptor.
12533
[clinic start generated code]*/
12534
12535
static Py_ssize_t
12536
os_write_impl(PyObject *module, int fd, Py_buffer *data)
12537
/*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
12538
2
{
12539
2
    return _Py_write(fd, data->buf, data->len);
12540
2
}
12541
12542
#ifdef HAVE_SENDFILE
12543
#ifdef __APPLE__
12544
/*[clinic input]
12545
os.sendfile
12546
12547
    out_fd: int
12548
    in_fd: int
12549
    offset: Py_off_t
12550
    count as sbytes: Py_off_t
12551
    headers: object(c_default="NULL") = ()
12552
    trailers: object(c_default="NULL") = ()
12553
    flags: int = 0
12554
12555
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12556
[clinic start generated code]*/
12557
12558
static PyObject *
12559
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12560
                 Py_off_t sbytes, PyObject *headers, PyObject *trailers,
12561
                 int flags)
12562
/*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
12563
#elif defined(__FreeBSD__) || defined(__DragonFly__)
12564
/*[clinic input]
12565
os.sendfile
12566
12567
    out_fd: int
12568
    in_fd: int
12569
    offset: Py_off_t
12570
    count: Py_ssize_t(allow_negative=False)
12571
    headers: object(c_default="NULL") = ()
12572
    trailers: object(c_default="NULL") = ()
12573
    flags: int = 0
12574
12575
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12576
[clinic start generated code]*/
12577
12578
static PyObject *
12579
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
12580
                 Py_ssize_t count, PyObject *headers, PyObject *trailers,
12581
                 int flags)
12582
/*[clinic end generated code: output=329ea009bdd55afc input=dcb026b94effa922]*/
12583
#else
12584
/*[clinic input]
12585
os.sendfile
12586
12587
    out_fd: int
12588
    in_fd: int
12589
    offset as offobj: object
12590
    count: Py_ssize_t(allow_negative=False)
12591
12592
Copy count bytes from file descriptor in_fd to file descriptor out_fd.
12593
[clinic start generated code]*/
12594
12595
static PyObject *
12596
os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
12597
                 Py_ssize_t count)
12598
/*[clinic end generated code: output=ae81216e40f167d8 input=424df0949059ea5b]*/
12599
#endif
12600
0
{
12601
0
    Py_ssize_t ret;
12602
0
    int async_err = 0;
12603
12604
#ifdef __APPLE__
12605
    if(sbytes < 0) {
12606
        PyErr_SetString(PyExc_ValueError,
12607
                        "count cannot be negative");
12608
        return NULL;
12609
    }
12610
#else
12611
0
    assert(count >= 0);
12612
0
#endif
12613
12614
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
12615
#ifndef __APPLE__
12616
    off_t sbytes;
12617
#endif
12618
    Py_buffer *hbuf, *tbuf;
12619
    struct sf_hdtr sf;
12620
12621
    sf.headers = NULL;
12622
    sf.trailers = NULL;
12623
12624
    if (headers != NULL) {
12625
        if (!PySequence_Check(headers)) {
12626
            PyErr_SetString(PyExc_TypeError,
12627
                "sendfile() headers must be a sequence");
12628
            return NULL;
12629
        } else {
12630
            Py_ssize_t i = PySequence_Size(headers);
12631
            if (i < 0)
12632
                return NULL;
12633
            if (i > INT_MAX) {
12634
                PyErr_SetString(PyExc_OverflowError,
12635
                    "sendfile() header is too large");
12636
                return NULL;
12637
            }
12638
            if (i > 0) {
12639
                sf.hdr_cnt = (int)i;
12640
                if (iov_setup(&(sf.headers), &hbuf,
12641
                              headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
12642
                    return NULL;
12643
#ifdef __APPLE__
12644
                for (i = 0; i < sf.hdr_cnt; i++) {
12645
                    Py_ssize_t blen = sf.headers[i].iov_len;
12646
# define OFF_T_MAX 0x7fffffffffffffff
12647
                    if (sbytes >= OFF_T_MAX - blen) {
12648
                        PyErr_SetString(PyExc_OverflowError,
12649
                            "sendfile() header is too large");
12650
                        return NULL;
12651
                    }
12652
                    sbytes += blen;
12653
                }
12654
#endif
12655
            }
12656
        }
12657
    }
12658
    if (trailers != NULL) {
12659
        if (!PySequence_Check(trailers)) {
12660
            PyErr_SetString(PyExc_TypeError,
12661
                "sendfile() trailers must be a sequence");
12662
            return NULL;
12663
        } else {
12664
            Py_ssize_t i = PySequence_Size(trailers);
12665
            if (i < 0)
12666
                return NULL;
12667
            if (i > INT_MAX) {
12668
                PyErr_SetString(PyExc_OverflowError,
12669
                    "sendfile() trailer is too large");
12670
                return NULL;
12671
            }
12672
            if (i > 0) {
12673
                sf.trl_cnt = (int)i;
12674
                if (iov_setup(&(sf.trailers), &tbuf,
12675
                              trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
12676
                    return NULL;
12677
            }
12678
        }
12679
    }
12680
12681
    _Py_BEGIN_SUPPRESS_IPH
12682
    do {
12683
        Py_BEGIN_ALLOW_THREADS
12684
#ifdef __APPLE__
12685
        ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
12686
#else
12687
        ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
12688
#endif
12689
        Py_END_ALLOW_THREADS
12690
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12691
    _Py_END_SUPPRESS_IPH
12692
12693
    int saved_errno = errno;
12694
    if (sf.headers != NULL)
12695
        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
12696
    if (sf.trailers != NULL)
12697
        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
12698
12699
    if (ret < 0) {
12700
        if ((saved_errno == EAGAIN) || (saved_errno == EBUSY)) {
12701
            if (sbytes != 0) {
12702
                // some data has been sent
12703
                goto done;
12704
            }
12705
            // no data has been sent; upper application is supposed
12706
            // to retry on EAGAIN or EBUSY
12707
        }
12708
        if (!async_err) {
12709
            errno = saved_errno;
12710
            posix_error();
12711
        }
12712
        return NULL;
12713
    }
12714
    goto done;
12715
12716
done:
12717
    #if !defined(HAVE_LARGEFILE_SUPPORT)
12718
        return PyLong_FromLong(sbytes);
12719
    #else
12720
        return PyLong_FromLongLong(sbytes);
12721
    #endif
12722
12723
#else
12724
0
#ifdef __linux__
12725
0
    if (offobj == Py_None) {
12726
0
        do {
12727
0
            Py_BEGIN_ALLOW_THREADS
12728
0
            ret = sendfile(out_fd, in_fd, NULL, count);
12729
0
            Py_END_ALLOW_THREADS
12730
0
        } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12731
0
        if (ret < 0)
12732
0
            return (!async_err) ? posix_error() : NULL;
12733
0
        return PyLong_FromSsize_t(ret);
12734
0
    }
12735
0
#endif
12736
0
    off_t offset;
12737
0
    if (!_Py_Off_t_Converter(offobj, &offset))
12738
0
        return NULL;
12739
12740
#if defined(__sun) && defined(__SVR4)
12741
    // On Solaris, sendfile raises EINVAL rather than returning 0
12742
    // when the offset is equal or bigger than the in_fd size.
12743
    struct stat st;
12744
12745
    do {
12746
        Py_BEGIN_ALLOW_THREADS
12747
        ret = fstat(in_fd, &st);
12748
        Py_END_ALLOW_THREADS
12749
    } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12750
    if (ret < 0)
12751
        return (!async_err) ? posix_error() : NULL;
12752
12753
    if (offset >= st.st_size) {
12754
        return PyLong_FromLong(0);
12755
    }
12756
12757
    // sendfile() may perform a partial write and still return -1, so the
12758
    // number of transferred bytes must be taken from the out parameter.
12759
    // sendfile() reports it by adding it to the offset, but does not
12760
    // initialize it when the transfer fails before writing any data, so use
12761
    // sendfilev(), which reports it explicitly.
12762
    sendfilevec_t vec;
12763
    size_t xferred;
12764
12765
    vec.sfv_fd = in_fd;
12766
    vec.sfv_flag = 0;
12767
    vec.sfv_off = offset;
12768
    vec.sfv_len = count;
12769
12770
    do {
12771
        Py_BEGIN_ALLOW_THREADS
12772
        xferred = 0;
12773
        ret = sendfilev(out_fd, &vec, 1, &xferred);
12774
        if (ret < 0 && xferred != 0) {
12775
            ret = (Py_ssize_t)xferred;
12776
        }
12777
        Py_END_ALLOW_THREADS
12778
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12779
#else
12780
0
    do {
12781
0
        Py_BEGIN_ALLOW_THREADS
12782
0
        ret = sendfile(out_fd, in_fd, &offset, count);
12783
0
        Py_END_ALLOW_THREADS
12784
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12785
0
#endif
12786
0
    if (ret < 0)
12787
0
        return (!async_err) ? posix_error() : NULL;
12788
0
    return PyLong_FromSsize_t(ret);
12789
0
#endif
12790
0
}
12791
#endif /* HAVE_SENDFILE */
12792
12793
12794
#if defined(__APPLE__)
12795
/*[clinic input]
12796
@permit_long_summary
12797
os._fcopyfile
12798
12799
    in_fd: int
12800
    out_fd: int
12801
    flags: int
12802
    /
12803
12804
Efficiently copy content or metadata of 2 regular file descriptors (macOS).
12805
[clinic start generated code]*/
12806
12807
static PyObject *
12808
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
12809
/*[clinic end generated code: output=c9d1a35a992e401b input=80b53ad8863c9101]*/
12810
{
12811
    int ret;
12812
12813
    Py_BEGIN_ALLOW_THREADS
12814
    ret = fcopyfile(in_fd, out_fd, NULL, flags);
12815
    Py_END_ALLOW_THREADS
12816
    if (ret < 0)
12817
        return posix_error();
12818
    Py_RETURN_NONE;
12819
}
12820
#endif
12821
12822
12823
/*[clinic input]
12824
os.fstat
12825
12826
    fd : int
12827
12828
Perform a stat system call on the given file descriptor.
12829
12830
Like stat(), but for an open file descriptor.
12831
Equivalent to os.stat(fd).
12832
[clinic start generated code]*/
12833
12834
static PyObject *
12835
os_fstat_impl(PyObject *module, int fd)
12836
/*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
12837
91.0k
{
12838
91.0k
    STRUCT_STAT st;
12839
91.0k
    int res;
12840
91.0k
    int async_err = 0;
12841
12842
91.0k
    do {
12843
91.0k
        Py_BEGIN_ALLOW_THREADS
12844
91.0k
        res = FSTAT(fd, &st);
12845
91.0k
        Py_END_ALLOW_THREADS
12846
91.0k
    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
12847
91.0k
    if (res != 0) {
12848
#ifdef MS_WINDOWS
12849
        return PyErr_SetFromWindowsErr(0);
12850
#else
12851
0
        return (!async_err) ? posix_error() : NULL;
12852
0
#endif
12853
0
    }
12854
12855
91.0k
    return _pystat_fromstructstat(module, &st);
12856
91.0k
}
12857
12858
12859
/*[clinic input]
12860
os.isatty -> bool
12861
    fd: int
12862
    /
12863
12864
Return True if the fd is connected to a terminal.
12865
12866
Return True if the file descriptor is an open file descriptor
12867
connected to the slave end of a terminal.
12868
[clinic start generated code]*/
12869
12870
static int
12871
os_isatty_impl(PyObject *module, int fd)
12872
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
12873
0
{
12874
0
    int return_value;
12875
0
    Py_BEGIN_ALLOW_THREADS
12876
0
    _Py_BEGIN_SUPPRESS_IPH
12877
0
    return_value = isatty(fd);
12878
0
    _Py_END_SUPPRESS_IPH
12879
0
    Py_END_ALLOW_THREADS
12880
0
    return return_value;
12881
0
}
12882
12883
12884
#ifdef HAVE_PIPE
12885
/*[clinic input]
12886
os.pipe
12887
12888
Create a pipe.
12889
12890
Returns a tuple of two file descriptors:
12891
  (read_fd, write_fd)
12892
[clinic start generated code]*/
12893
12894
static PyObject *
12895
os_pipe_impl(PyObject *module)
12896
/*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
12897
0
{
12898
0
    int fds[2];
12899
#ifdef MS_WINDOWS
12900
    HANDLE read, write;
12901
    SECURITY_ATTRIBUTES attr;
12902
    BOOL ok;
12903
#else
12904
0
    int res = -1;
12905
12906
    /* pipe2() is available on some newer linux/glibc & macOS;
12907
     * use the same runtime detection as for dup3 above.
12908
     */
12909
0
    static int pipe2_works_atomic = -1;
12910
0
    (void) pipe2_works_atomic;  // unused on some platforms
12911
0
#endif
12912
12913
#ifdef MS_WINDOWS
12914
    attr.nLength = sizeof(attr);
12915
    attr.lpSecurityDescriptor = NULL;
12916
    attr.bInheritHandle = FALSE;
12917
12918
    Py_BEGIN_ALLOW_THREADS
12919
    ok = CreatePipe(&read, &write, &attr, 0);
12920
    if (ok) {
12921
        fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY | _O_NOINHERIT);
12922
        fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY | _O_NOINHERIT);
12923
        if (fds[0] == -1 || fds[1] == -1) {
12924
            CloseHandle(read);
12925
            CloseHandle(write);
12926
            ok = 0;
12927
        }
12928
    }
12929
    Py_END_ALLOW_THREADS
12930
12931
    if (!ok)
12932
        return PyErr_SetFromWindowsErr(0);
12933
#else
12934
12935
0
#ifdef HAVE_PIPE2
12936
0
    int pipe2_works = FT_ATOMIC_LOAD_INT_RELAXED(pipe2_works_atomic);
12937
0
    if (pipe2_works != 0) {
12938
0
        if (HAVE_PIPE2_RUNTIME) {
12939
0
            Py_BEGIN_ALLOW_THREADS
12940
0
            res = pipe2(fds, O_CLOEXEC);
12941
0
            Py_END_ALLOW_THREADS
12942
0
            if (pipe2_works == -1) {
12943
0
                if (res != 0 && errno == ENOSYS) {
12944
0
                    pipe2_works = 0;
12945
0
                }
12946
0
                else {
12947
                    // pipe2 is present but this call failed
12948
0
                    pipe2_works = 1;
12949
0
                }
12950
0
                FT_ATOMIC_STORE_INT_RELAXED(pipe2_works_atomic, pipe2_works);
12951
0
            }
12952
0
        }
12953
0
        else {
12954
0
            pipe2_works = 0;
12955
0
            FT_ATOMIC_STORE_INT_RELAXED(pipe2_works_atomic, pipe2_works);
12956
0
        }
12957
0
    }
12958
12959
0
    if (pipe2_works == 0)
12960
0
    {
12961
0
#endif
12962
0
        Py_BEGIN_ALLOW_THREADS
12963
0
        res = pipe(fds);
12964
0
        Py_END_ALLOW_THREADS
12965
12966
0
        if (res == 0) {
12967
0
            if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
12968
0
                close(fds[0]);
12969
0
                close(fds[1]);
12970
0
                return NULL;
12971
0
            }
12972
0
            if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
12973
0
                close(fds[0]);
12974
0
                close(fds[1]);
12975
0
                return NULL;
12976
0
            }
12977
0
        }
12978
0
#ifdef HAVE_PIPE2
12979
0
    }
12980
0
#endif
12981
12982
0
    if (res != 0) {
12983
0
        return PyErr_SetFromErrno(PyExc_OSError);
12984
0
    }
12985
0
#endif /* !MS_WINDOWS */
12986
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
12987
0
}
12988
#endif  /* HAVE_PIPE */
12989
12990
12991
#ifdef HAVE_PIPE2
12992
/*[clinic input]
12993
os.pipe2
12994
12995
    flags: int
12996
    /
12997
12998
Create a pipe with flags set atomically.
12999
13000
Returns a tuple of two file descriptors:
13001
  (read_fd, write_fd)
13002
13003
flags can be constructed by ORing together one or more of these values:
13004
O_NONBLOCK, O_CLOEXEC.
13005
[clinic start generated code]*/
13006
13007
static PyObject *
13008
os_pipe2_impl(PyObject *module, int flags)
13009
/*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
13010
0
{
13011
0
    int fds[2];
13012
0
    int res;
13013
13014
0
    if (HAVE_PIPE2_RUNTIME) {
13015
0
        res = pipe2(fds, flags);
13016
0
    }
13017
0
    else {
13018
0
        res = -1;
13019
0
        errno = ENOSYS;
13020
0
    }
13021
0
    if (res != 0) {
13022
0
        return posix_error();
13023
0
    }
13024
13025
0
    return Py_BuildValue("(ii)", fds[0], fds[1]);
13026
0
}
13027
#endif /* HAVE_PIPE2 */
13028
13029
13030
#ifdef HAVE_WRITEV
13031
/*[clinic input]
13032
@permit_long_summary
13033
os.writev -> Py_ssize_t
13034
    fd: int
13035
    buffers: object
13036
    /
13037
13038
Iterate over buffers, and write the contents of each to a file descriptor.
13039
13040
Returns the total number of bytes written.
13041
buffers must be a sequence of bytes-like objects.
13042
[clinic start generated code]*/
13043
13044
static Py_ssize_t
13045
os_writev_impl(PyObject *module, int fd, PyObject *buffers)
13046
/*[clinic end generated code: output=56565cfac3aac15b input=5771a0f0c2b326f2]*/
13047
0
{
13048
0
    Py_ssize_t cnt;
13049
0
    Py_ssize_t result;
13050
0
    int async_err = 0;
13051
0
    struct iovec *iov;
13052
0
    Py_buffer *buf;
13053
13054
0
    if (!PySequence_Check(buffers)) {
13055
0
        PyErr_SetString(PyExc_TypeError,
13056
0
            "writev() arg 2 must be a sequence");
13057
0
        return -1;
13058
0
    }
13059
0
    cnt = PySequence_Size(buffers);
13060
0
    if (cnt < 0)
13061
0
        return -1;
13062
13063
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
13064
0
        return -1;
13065
0
    }
13066
13067
0
    do {
13068
0
        Py_BEGIN_ALLOW_THREADS
13069
0
        result = writev(fd, iov, cnt);
13070
0
        Py_END_ALLOW_THREADS
13071
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13072
13073
0
    if (result < 0 && !async_err)
13074
0
        posix_error();
13075
13076
0
    iov_cleanup(iov, buf, cnt);
13077
0
    return result;
13078
0
}
13079
#endif /* HAVE_WRITEV */
13080
13081
13082
#ifdef HAVE_PWRITE
13083
/*[clinic input]
13084
os.pwrite -> Py_ssize_t
13085
13086
    fd: int
13087
    buffer: Py_buffer
13088
    offset: Py_off_t
13089
    /
13090
13091
Write bytes to a file descriptor starting at a particular offset.
13092
13093
Write buffer to fd, starting at offset bytes from the beginning of
13094
the file.  Returns the number of bytes written.  Does not change the
13095
current file offset.
13096
[clinic start generated code]*/
13097
13098
static Py_ssize_t
13099
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
13100
/*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/
13101
0
{
13102
0
    Py_ssize_t size;
13103
0
    int async_err = 0;
13104
13105
0
    do {
13106
0
        Py_BEGIN_ALLOW_THREADS
13107
0
        _Py_BEGIN_SUPPRESS_IPH
13108
0
        size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
13109
0
        _Py_END_SUPPRESS_IPH
13110
0
        Py_END_ALLOW_THREADS
13111
0
    } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13112
13113
0
    if (size < 0 && !async_err)
13114
0
        posix_error();
13115
0
    return size;
13116
0
}
13117
#endif /* HAVE_PWRITE */
13118
13119
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
13120
/*[clinic input]
13121
@permit_long_summary
13122
os.pwritev -> Py_ssize_t
13123
13124
    fd: int
13125
    buffers: object
13126
    offset: Py_off_t
13127
    flags: int = 0
13128
    /
13129
13130
Writes the contents of bytes-like objects to a file descriptor at a given offset.
13131
13132
Combines the functionality of writev() and pwrite(). All buffers must be
13133
a sequence of bytes-like objects.  Buffers are processed in array order.
13134
Entire contents of first buffer is written before proceeding to second,
13135
and so on. The operating system may set a limit (sysconf() value
13136
SC_IOV_MAX) on the number of buffers that can be used.
13137
This function writes the contents of each object to the file descriptor
13138
and returns the total number of bytes written.
13139
13140
The flags argument contains a bitwise OR of zero or more of the
13141
following flags:
13142
13143
- RWF_DSYNC
13144
- RWF_SYNC
13145
- RWF_APPEND
13146
- RWF_DONTCACHE
13147
- RWF_ATOMIC
13148
- RWF_NOSIGNAL
13149
13150
Using non-zero flags requires Linux 4.7 or newer.
13151
[clinic start generated code]*/
13152
13153
static Py_ssize_t
13154
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
13155
                int flags)
13156
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=c202f24f01fa66c9]*/
13157
0
{
13158
0
    Py_ssize_t cnt;
13159
0
    Py_ssize_t result;
13160
0
    int async_err = 0;
13161
0
    struct iovec *iov;
13162
0
    Py_buffer *buf;
13163
13164
0
    if (!PySequence_Check(buffers)) {
13165
0
        PyErr_SetString(PyExc_TypeError,
13166
0
            "pwritev() arg 2 must be a sequence");
13167
0
        return -1;
13168
0
    }
13169
13170
0
    cnt = PySequence_Size(buffers);
13171
0
    if (cnt < 0) {
13172
0
        return -1;
13173
0
    }
13174
13175
#ifndef HAVE_PWRITEV2
13176
    if(flags != 0) {
13177
        argument_unavailable_error("pwritev2", "flags");
13178
        return -1;
13179
    }
13180
#endif
13181
13182
0
    if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
13183
0
        return -1;
13184
0
    }
13185
0
#ifdef HAVE_PWRITEV2
13186
0
    do {
13187
0
        Py_BEGIN_ALLOW_THREADS
13188
0
        _Py_BEGIN_SUPPRESS_IPH
13189
0
        result = pwritev2(fd, iov, cnt, offset, flags);
13190
0
        _Py_END_SUPPRESS_IPH
13191
0
        Py_END_ALLOW_THREADS
13192
0
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13193
#else
13194
13195
#if defined(__APPLE__) && defined(__clang__)
13196
/* This entire function will be removed from the module dict when the API
13197
 * is not available.
13198
 */
13199
#pragma clang diagnostic push
13200
#pragma clang diagnostic ignored "-Wunguarded-availability"
13201
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
13202
#endif
13203
    do {
13204
        Py_BEGIN_ALLOW_THREADS
13205
        _Py_BEGIN_SUPPRESS_IPH
13206
        result = pwritev(fd, iov, cnt, offset);
13207
        _Py_END_SUPPRESS_IPH
13208
        Py_END_ALLOW_THREADS
13209
    } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13210
13211
#if defined(__APPLE__) && defined(__clang__)
13212
#pragma clang diagnostic pop
13213
#endif
13214
13215
#endif
13216
13217
0
    if (result < 0) {
13218
0
        if (!async_err) {
13219
0
            posix_error();
13220
0
        }
13221
0
        result = -1;
13222
0
    }
13223
0
    iov_cleanup(iov, buf, cnt);
13224
13225
0
    return result;
13226
0
}
13227
#endif /* HAVE_PWRITEV */
13228
13229
#if defined(HAVE_COPY_FILE_RANGE) || \
13230
    (defined(__linux__) && defined(__NR_copy_file_range))
13231
#  define _Py_HAVE_COPY_FILE_RANGE
13232
#endif
13233
13234
#ifdef _Py_HAVE_COPY_FILE_RANGE
13235
/*[clinic input]
13236
13237
os.copy_file_range
13238
    src: int
13239
        Source file descriptor.
13240
    dst: int
13241
        Destination file descriptor.
13242
    count: Py_ssize_t(allow_negative=False)
13243
        Number of bytes to copy.
13244
    offset_src: object = None
13245
        Starting offset in src.
13246
    offset_dst: object = None
13247
        Starting offset in dst.
13248
13249
Copy count bytes from one file descriptor to another.
13250
13251
If offset_src is None, then src is read from the current position;
13252
respectively for offset_dst.
13253
[clinic start generated code]*/
13254
13255
static PyObject *
13256
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13257
                        PyObject *offset_src, PyObject *offset_dst)
13258
/*[clinic end generated code: output=1a91713a1d99fc7a input=08dacb760869b87c]*/
13259
0
{
13260
0
    off_t offset_src_val, offset_dst_val;
13261
0
    off_t *p_offset_src = NULL;
13262
0
    off_t *p_offset_dst = NULL;
13263
0
    Py_ssize_t ret;
13264
0
    int async_err = 0;
13265
    /* The flags argument is provided to allow
13266
     * for future extensions and currently must be to 0. */
13267
0
    int flags = 0;
13268
13269
13270
0
    if (offset_src != Py_None) {
13271
0
        if (!_Py_Off_t_Converter(offset_src, &offset_src_val)) {
13272
0
            return NULL;
13273
0
        }
13274
0
        p_offset_src = &offset_src_val;
13275
0
    }
13276
13277
0
    if (offset_dst != Py_None) {
13278
0
        if (!_Py_Off_t_Converter(offset_dst, &offset_dst_val)) {
13279
0
            return NULL;
13280
0
        }
13281
0
        p_offset_dst = &offset_dst_val;
13282
0
    }
13283
13284
0
    do {
13285
0
        Py_BEGIN_ALLOW_THREADS
13286
0
#ifdef HAVE_COPY_FILE_RANGE
13287
0
        ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
13288
#else
13289
        /* Largefile support makes off_t 64-bit, as the kernel expects. */
13290
        ret = syscall(__NR_copy_file_range, src, p_offset_src, dst, p_offset_dst,
13291
                      count, flags);
13292
#endif
13293
0
        Py_END_ALLOW_THREADS
13294
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13295
13296
0
    if (ret < 0) {
13297
0
        return (!async_err) ? posix_error() : NULL;
13298
0
    }
13299
13300
0
    return PyLong_FromSsize_t(ret);
13301
0
}
13302
#endif /* _Py_HAVE_COPY_FILE_RANGE */
13303
13304
#if (defined(HAVE_SPLICE) && !defined(_AIX))
13305
/*[clinic input]
13306
13307
os.splice
13308
    src: int
13309
        Source file descriptor.
13310
    dst: int
13311
        Destination file descriptor.
13312
    count: Py_ssize_t(allow_negative=False)
13313
        Number of bytes to copy.
13314
    offset_src: object = None
13315
        Starting offset in src.
13316
    offset_dst: object = None
13317
        Starting offset in dst.
13318
    flags: unsigned_int = 0
13319
        Flags to modify the semantics of the call.
13320
13321
Transfer count bytes from one pipe to a descriptor or vice versa.
13322
13323
If offset_src is None, then src is read from the current position;
13324
respectively for offset_dst. The offset associated to the file
13325
descriptor that refers to a pipe must be None.
13326
[clinic start generated code]*/
13327
13328
static PyObject *
13329
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
13330
               PyObject *offset_src, PyObject *offset_dst,
13331
               unsigned int flags)
13332
/*[clinic end generated code: output=d0386f25a8519dc5 input=034852a7b2e7af35]*/
13333
0
{
13334
0
    off_t offset_src_val, offset_dst_val;
13335
0
    off_t *p_offset_src = NULL;
13336
0
    off_t *p_offset_dst = NULL;
13337
0
    Py_ssize_t ret;
13338
0
    int async_err = 0;
13339
13340
13341
0
    if (offset_src != Py_None) {
13342
0
        if (!_Py_Off_t_Converter(offset_src, &offset_src_val)) {
13343
0
            return NULL;
13344
0
        }
13345
0
        p_offset_src = &offset_src_val;
13346
0
    }
13347
13348
0
    if (offset_dst != Py_None) {
13349
0
        if (!_Py_Off_t_Converter(offset_dst, &offset_dst_val)) {
13350
0
            return NULL;
13351
0
        }
13352
0
        p_offset_dst = &offset_dst_val;
13353
0
    }
13354
13355
0
    do {
13356
0
        Py_BEGIN_ALLOW_THREADS
13357
0
        ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
13358
0
        Py_END_ALLOW_THREADS
13359
0
    } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
13360
13361
0
    if (ret < 0) {
13362
0
        return (!async_err) ? posix_error() : NULL;
13363
0
    }
13364
13365
0
    return PyLong_FromSsize_t(ret);
13366
0
}
13367
#endif /* HAVE_SPLICE*/
13368
13369
#ifdef HAVE_MKFIFO
13370
/*[clinic input]
13371
os.mkfifo
13372
13373
    path: path_t
13374
    mode: int=0o666
13375
    *
13376
    dir_fd: dir_fd(requires='mkfifoat')=None
13377
13378
Create a "fifo" (a POSIX named pipe).
13379
13380
If dir_fd is not None, it should be a file descriptor open to
13381
a directory, and path should be relative; path will then be relative to
13382
that directory.
13383
dir_fd may not be implemented on your platform.  If it is unavailable,
13384
using it will raise a NotImplementedError.
13385
[clinic start generated code]*/
13386
13387
static PyObject *
13388
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
13389
/*[clinic end generated code: output=ce41cfad0e68c940 input=d2fb917c01e888d6]*/
13390
0
{
13391
0
    int result;
13392
0
    int async_err = 0;
13393
0
#ifdef HAVE_MKFIFOAT
13394
0
    int mkfifoat_unavailable = 0;
13395
0
#endif
13396
13397
0
    do {
13398
0
        Py_BEGIN_ALLOW_THREADS
13399
0
#ifdef HAVE_MKFIFOAT
13400
0
        if (dir_fd != DEFAULT_DIR_FD) {
13401
0
            if (HAVE_MKFIFOAT_RUNTIME) {
13402
0
                result = mkfifoat(dir_fd, path->narrow, mode);
13403
13404
0
            } else {
13405
0
                mkfifoat_unavailable = 1;
13406
0
                result = 0;
13407
0
            }
13408
0
        } else
13409
0
#endif
13410
0
            result = mkfifo(path->narrow, mode);
13411
0
        Py_END_ALLOW_THREADS
13412
0
    } while (result != 0 && errno == EINTR &&
13413
0
             !(async_err = PyErr_CheckSignals()));
13414
13415
0
#ifdef HAVE_MKFIFOAT
13416
0
    if (mkfifoat_unavailable) {
13417
0
        argument_unavailable_error(NULL, "dir_fd");
13418
0
        return NULL;
13419
0
    }
13420
0
#endif
13421
13422
0
    if (result != 0)
13423
0
        return (!async_err) ? posix_error() : NULL;
13424
13425
0
    Py_RETURN_NONE;
13426
0
}
13427
#endif /* HAVE_MKFIFO */
13428
13429
13430
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
13431
/*[clinic input]
13432
os.mknod
13433
13434
    path: path_t
13435
    mode: int=0o600
13436
    device: dev_t=0
13437
    *
13438
    dir_fd: dir_fd(requires='mknodat')=None
13439
13440
Create a node in the file system.
13441
13442
Create a node in the file system (file, device special file or named
13443
pipe) at path.  mode specifies both the permissions to use and the
13444
type of node to be created, being combined (bitwise OR) with one of
13445
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set
13446
on mode, device defines the newly created device special file (probably
13447
using os.makedev()).  Otherwise device is ignored.
13448
13449
If dir_fd is not None, it should be a file descriptor open to
13450
a directory, and path should be relative; path will then be relative
13451
to that directory.
13452
dir_fd may not be implemented on your platform.  If it is unavailable,
13453
using it will raise a NotImplementedError.
13454
[clinic start generated code]*/
13455
13456
static PyObject *
13457
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
13458
              int dir_fd)
13459
/*[clinic end generated code: output=92e55d3ca8917461 input=7d0099e85c6b4cba]*/
13460
0
{
13461
0
    int result;
13462
0
    int async_err = 0;
13463
0
#ifdef HAVE_MKNODAT
13464
0
    int mknodat_unavailable = 0;
13465
0
#endif
13466
13467
0
    do {
13468
0
        Py_BEGIN_ALLOW_THREADS
13469
0
#ifdef HAVE_MKNODAT
13470
0
        if (dir_fd != DEFAULT_DIR_FD) {
13471
0
            if (HAVE_MKNODAT_RUNTIME) {
13472
0
                result = mknodat(dir_fd, path->narrow, mode, device);
13473
13474
0
            } else {
13475
0
                mknodat_unavailable = 1;
13476
0
                result = 0;
13477
0
            }
13478
0
        } else
13479
0
#endif
13480
0
            result = mknod(path->narrow, mode, device);
13481
0
        Py_END_ALLOW_THREADS
13482
0
    } while (result != 0 && errno == EINTR &&
13483
0
             !(async_err = PyErr_CheckSignals()));
13484
0
#ifdef HAVE_MKNODAT
13485
0
    if (mknodat_unavailable) {
13486
0
        argument_unavailable_error(NULL, "dir_fd");
13487
0
        return NULL;
13488
0
    }
13489
0
#endif
13490
0
    if (result != 0)
13491
0
        return (!async_err) ? posix_error() : NULL;
13492
13493
0
    Py_RETURN_NONE;
13494
0
}
13495
#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
13496
13497
13498
#ifdef HAVE_DEVICE_MACROS
13499
static PyObject *
13500
major_minor_conv(unsigned int value)
13501
0
{
13502
0
#ifdef NODEV
13503
0
    if (value == (unsigned int)NODEV) {
13504
0
        return PyLong_FromLong((int)NODEV);
13505
0
    }
13506
0
#endif
13507
0
    return PyLong_FromUnsignedLong(value);
13508
0
}
13509
13510
static int
13511
major_minor_check(dev_t value)
13512
0
{
13513
0
#ifdef NODEV
13514
0
    if (value == NODEV) {
13515
0
        return 1;
13516
0
    }
13517
0
#endif
13518
0
    return (dev_t)(unsigned int)value == value;
13519
0
}
13520
13521
/*[clinic input]
13522
os.major
13523
13524
    device: dev_t
13525
    /
13526
13527
Extracts a device major number from a raw device number.
13528
[clinic start generated code]*/
13529
13530
static PyObject *
13531
os_major_impl(PyObject *module, dev_t device)
13532
/*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/
13533
0
{
13534
0
    return major_minor_conv(major(device));
13535
0
}
13536
13537
13538
/*[clinic input]
13539
os.minor
13540
13541
    device: dev_t
13542
    /
13543
13544
Extracts a device minor number from a raw device number.
13545
[clinic start generated code]*/
13546
13547
static PyObject *
13548
os_minor_impl(PyObject *module, dev_t device)
13549
/*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/
13550
0
{
13551
0
    return major_minor_conv(minor(device));
13552
0
}
13553
13554
13555
/*[clinic input]
13556
os.makedev -> dev_t
13557
13558
    major: dev_t
13559
    minor: dev_t
13560
    /
13561
13562
Composes a raw device number from the major and minor device numbers.
13563
[clinic start generated code]*/
13564
13565
static dev_t
13566
os_makedev_impl(PyObject *module, dev_t major, dev_t minor)
13567
/*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/
13568
0
{
13569
0
    if (!major_minor_check(major) || !major_minor_check(minor)) {
13570
0
        PyErr_SetString(PyExc_OverflowError,
13571
0
                        "Python int too large to convert to C unsigned int");
13572
0
        return (dev_t)-1;
13573
0
    }
13574
0
    return makedev(major, minor);
13575
0
}
13576
#endif /* HAVE_DEVICE_MACROS */
13577
13578
13579
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
13580
/*[clinic input]
13581
os.ftruncate
13582
13583
    fd: int
13584
    length: Py_off_t
13585
    /
13586
13587
Truncate a file, specified by file descriptor, to a specific length.
13588
[clinic start generated code]*/
13589
13590
static PyObject *
13591
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
13592
/*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
13593
0
{
13594
0
    int result;
13595
0
    int async_err = 0;
13596
13597
0
    if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
13598
0
        return NULL;
13599
0
    }
13600
13601
0
    do {
13602
0
        Py_BEGIN_ALLOW_THREADS
13603
0
        _Py_BEGIN_SUPPRESS_IPH
13604
#ifdef MS_WINDOWS
13605
        result = _chsize_s(fd, length);
13606
#else
13607
0
        result = ftruncate(fd, length);
13608
0
#endif
13609
0
        _Py_END_SUPPRESS_IPH
13610
0
        Py_END_ALLOW_THREADS
13611
0
    } while (result != 0 && errno == EINTR &&
13612
0
             !(async_err = PyErr_CheckSignals()));
13613
0
    if (result != 0)
13614
0
        return (!async_err) ? posix_error() : NULL;
13615
0
    Py_RETURN_NONE;
13616
0
}
13617
#endif /* HAVE_FTRUNCATE || MS_WINDOWS */
13618
13619
13620
#if defined HAVE_TRUNCATE || defined MS_WINDOWS
13621
/*[clinic input]
13622
os.truncate
13623
    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
13624
    length: Py_off_t
13625
13626
Truncate a file, specified by path, to a specific length.
13627
13628
On some platforms, path may also be specified as an open file
13629
descriptor.  If this functionality is unavailable, using it raises
13630
an exception.
13631
[clinic start generated code]*/
13632
13633
static PyObject *
13634
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
13635
/*[clinic end generated code: output=43009c8df5c0a12b input=ce33fd7808a511c4]*/
13636
0
{
13637
0
    int result;
13638
#ifdef MS_WINDOWS
13639
    int fd;
13640
#endif
13641
13642
0
    if (path->is_fd)
13643
0
        return os_ftruncate_impl(module, path->fd, length);
13644
13645
0
    if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
13646
0
        return NULL;
13647
0
    }
13648
13649
0
    Py_BEGIN_ALLOW_THREADS
13650
0
    _Py_BEGIN_SUPPRESS_IPH
13651
#ifdef MS_WINDOWS
13652
    fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
13653
    if (fd < 0)
13654
        result = -1;
13655
    else {
13656
        result = _chsize_s(fd, length);
13657
        close(fd);
13658
        if (result < 0)
13659
            errno = result;
13660
    }
13661
#else
13662
0
    result = truncate(path->narrow, length);
13663
0
#endif
13664
0
    _Py_END_SUPPRESS_IPH
13665
0
    Py_END_ALLOW_THREADS
13666
0
    if (result < 0)
13667
0
        return posix_path_error(path);
13668
13669
0
    Py_RETURN_NONE;
13670
0
}
13671
#endif /* HAVE_TRUNCATE || MS_WINDOWS */
13672
13673
13674
/* GH-111804: Due to posix_fallocate() not having consistent semantics across
13675
   OSs, support was dropped in WASI preview2. */
13676
#if defined(HAVE_POSIX_FALLOCATE) && !defined(__wasi__)
13677
/*[clinic input]
13678
@permit_long_summary
13679
os.posix_fallocate
13680
13681
    fd: int
13682
    offset: Py_off_t
13683
    length: Py_off_t
13684
    /
13685
13686
Ensure a file has allocated at least a particular number of bytes on disk.
13687
13688
Ensure that the file specified by fd encompasses a range of bytes
13689
starting at offset bytes from the beginning and continuing for length
13690
bytes.
13691
[clinic start generated code]*/
13692
13693
static PyObject *
13694
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
13695
                        Py_off_t length)
13696
/*[clinic end generated code: output=73f107139564aa9d input=c718971d18b96896]*/
13697
0
{
13698
0
    int result;
13699
0
    int async_err = 0;
13700
13701
0
    do {
13702
0
        Py_BEGIN_ALLOW_THREADS
13703
0
        result = posix_fallocate(fd, offset, length);
13704
0
        Py_END_ALLOW_THREADS
13705
        // DragonFly BSD returns -1 and sets errno.
13706
0
        if (result == -1) {
13707
0
            result = errno;
13708
0
        }
13709
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13710
13711
0
    if (result == 0)
13712
0
        Py_RETURN_NONE;
13713
13714
0
    if (async_err)
13715
0
        return NULL;
13716
13717
0
    errno = result;
13718
0
    return posix_error();
13719
0
}
13720
#endif /* HAVE_POSIX_FALLOCATE && !defined(__wasi__) */
13721
13722
13723
#if defined(HAVE_POSIX_FADVISE)
13724
/*[clinic input]
13725
os.posix_fadvise
13726
13727
    fd: int
13728
    offset: Py_off_t
13729
    length: Py_off_t
13730
    advice: int
13731
    /
13732
13733
Announce an intention to access data in a specific pattern.
13734
13735
Announce an intention to access data in a specific pattern, thus
13736
allowing the kernel to make optimizations.
13737
The advice applies to the region of the file specified by fd starting at
13738
offset and continuing for length bytes.
13739
advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
13740
POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
13741
POSIX_FADV_DONTNEED.
13742
[clinic start generated code]*/
13743
13744
static PyObject *
13745
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
13746
                      Py_off_t length, int advice)
13747
/*[clinic end generated code: output=412ef4aa70c98642 input=961b01a4518ef727]*/
13748
0
{
13749
0
    int result;
13750
0
    int async_err = 0;
13751
13752
0
    do {
13753
0
        Py_BEGIN_ALLOW_THREADS
13754
0
        result = posix_fadvise(fd, offset, length, advice);
13755
0
        Py_END_ALLOW_THREADS
13756
        // DragonFly BSD returns -1 and sets errno.
13757
0
        if (result == -1) {
13758
0
            result = errno;
13759
0
        }
13760
0
    } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
13761
13762
0
    if (result == 0)
13763
0
        Py_RETURN_NONE;
13764
13765
0
    if (async_err)
13766
0
        return NULL;
13767
13768
0
    errno = result;
13769
0
    return posix_error();
13770
0
}
13771
#endif /* HAVE_POSIX_FADVISE */
13772
13773
13774
#ifdef MS_WINDOWS
13775
static PyObject*
13776
win32_putenv(PyObject *name, PyObject *value)
13777
{
13778
    /* Search from index 1 because on Windows starting '=' is allowed for
13779
       defining hidden environment variables. */
13780
    if (PyUnicode_GET_LENGTH(name) == 0 ||
13781
        PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
13782
    {
13783
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13784
        return NULL;
13785
    }
13786
    PyObject *unicode;
13787
    if (value != NULL) {
13788
        unicode = PyUnicode_FromFormat("%U=%U", name, value);
13789
    }
13790
    else {
13791
        unicode = PyUnicode_FromFormat("%U=", name);
13792
    }
13793
    if (unicode == NULL) {
13794
        return NULL;
13795
    }
13796
13797
    Py_ssize_t size;
13798
    wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
13799
    Py_DECREF(unicode);
13800
13801
    if (env == NULL) {
13802
        return NULL;
13803
    }
13804
    if (size > _MAX_ENV) {
13805
        PyErr_Format(PyExc_ValueError,
13806
                     "the environment variable is longer than %u characters",
13807
                     _MAX_ENV);
13808
        PyMem_Free(env);
13809
        return NULL;
13810
    }
13811
    if (wcslen(env) != (size_t)size) {
13812
        PyErr_SetString(PyExc_ValueError,
13813
                        "embedded null character");
13814
        PyMem_Free(env);
13815
        return NULL;
13816
    }
13817
13818
    /* _wputenv() and SetEnvironmentVariableW() update the environment in the
13819
       Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
13820
       and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
13821
13822
       Prefer _wputenv() to be compatible with C libraries using CRT
13823
       variables and CRT functions using these variables (ex: getenv()). */
13824
    int err = _wputenv(env);
13825
13826
    if (err) {
13827
        posix_error();
13828
        PyMem_Free(env);
13829
        return NULL;
13830
    }
13831
    PyMem_Free(env);
13832
13833
    Py_RETURN_NONE;
13834
}
13835
#endif
13836
13837
13838
#ifdef MS_WINDOWS
13839
/*[clinic input]
13840
os.putenv
13841
13842
    name: unicode
13843
    value: unicode
13844
    /
13845
13846
Change or add an environment variable.
13847
[clinic start generated code]*/
13848
13849
static PyObject *
13850
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13851
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
13852
{
13853
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13854
        return NULL;
13855
    }
13856
    return win32_putenv(name, value);
13857
}
13858
#else
13859
/*[clinic input]
13860
os.putenv
13861
13862
    name: unicode_fs_encoded
13863
    value: unicode_fs_encoded
13864
    /
13865
13866
Change or add an environment variable.
13867
[clinic start generated code]*/
13868
13869
static PyObject *
13870
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
13871
/*[clinic end generated code: output=d29a567d6b2327d2 input=84fcd30f873c8c45]*/
13872
0
{
13873
0
    const char *name_string = PyBytes_AS_STRING(name);
13874
0
    const char *value_string = PyBytes_AS_STRING(value);
13875
13876
0
    if (strchr(name_string, '=') != NULL) {
13877
0
        PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
13878
0
        return NULL;
13879
0
    }
13880
13881
0
    if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
13882
0
        return NULL;
13883
0
    }
13884
13885
0
    if (setenv(name_string, value_string, 1)) {
13886
0
        return posix_error();
13887
0
    }
13888
0
    Py_RETURN_NONE;
13889
0
}
13890
#endif  /* !defined(MS_WINDOWS) */
13891
13892
13893
#ifdef MS_WINDOWS
13894
/*[clinic input]
13895
os.unsetenv
13896
    name: unicode
13897
    /
13898
13899
Delete an environment variable.
13900
[clinic start generated code]*/
13901
13902
static PyObject *
13903
os_unsetenv_impl(PyObject *module, PyObject *name)
13904
/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
13905
{
13906
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13907
        return NULL;
13908
    }
13909
    return win32_putenv(name, NULL);
13910
}
13911
#else
13912
/*[clinic input]
13913
os.unsetenv
13914
    name: unicode_fs_encoded
13915
    /
13916
13917
Delete an environment variable.
13918
[clinic start generated code]*/
13919
13920
static PyObject *
13921
os_unsetenv_impl(PyObject *module, PyObject *name)
13922
/*[clinic end generated code: output=54c4137ab1834f02 input=78ff12e505ade80a]*/
13923
0
{
13924
0
    if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
13925
0
        return NULL;
13926
0
    }
13927
#ifdef HAVE_BROKEN_UNSETENV
13928
    unsetenv(PyBytes_AS_STRING(name));
13929
#else
13930
0
    int err = unsetenv(PyBytes_AS_STRING(name));
13931
0
    if (err) {
13932
0
        return posix_error();
13933
0
    }
13934
0
#endif
13935
13936
0
    Py_RETURN_NONE;
13937
0
}
13938
#endif /* !MS_WINDOWS */
13939
13940
13941
#ifdef HAVE_CLEARENV
13942
/*[clinic input]
13943
os._clearenv
13944
[clinic start generated code]*/
13945
13946
static PyObject *
13947
os__clearenv_impl(PyObject *module)
13948
/*[clinic end generated code: output=2d6705d62c014b51 input=47d2fa7f323c43ca]*/
13949
0
{
13950
0
    if (PySys_Audit("os._clearenv", NULL) < 0) {
13951
0
        return NULL;
13952
0
    }
13953
13954
0
    errno = 0;
13955
0
    int err = clearenv();
13956
0
    if (err) {
13957
0
        return posix_error();
13958
0
    }
13959
0
    Py_RETURN_NONE;
13960
0
}
13961
#endif
13962
13963
13964
/*[clinic input]
13965
os.strerror
13966
13967
    code: int
13968
    /
13969
13970
Translate an error code to a message string.
13971
[clinic start generated code]*/
13972
13973
static PyObject *
13974
os_strerror_impl(PyObject *module, int code)
13975
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
13976
0
{
13977
0
    return _Py_strerror(code);
13978
0
}
13979
13980
13981
#ifdef HAVE_SYS_WAIT_H
13982
#ifdef WCOREDUMP
13983
/*[clinic input]
13984
os.WCOREDUMP -> bool
13985
13986
    status: int
13987
    /
13988
13989
Return True if the process returning status was dumped to a core file.
13990
[clinic start generated code]*/
13991
13992
static int
13993
os_WCOREDUMP_impl(PyObject *module, int status)
13994
/*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
13995
0
{
13996
0
    WAIT_TYPE wait_status;
13997
0
    WAIT_STATUS_INT(wait_status) = status;
13998
0
    return WCOREDUMP(wait_status);
13999
0
}
14000
#endif /* WCOREDUMP */
14001
14002
14003
#ifdef WIFCONTINUED
14004
/*[clinic input]
14005
@permit_long_summary
14006
os.WIFCONTINUED -> bool
14007
14008
    status: int
14009
14010
Return True if a particular process was continued from a job control stop.
14011
14012
Return True if the process returning status was continued from a
14013
job control stop.
14014
[clinic start generated code]*/
14015
14016
static int
14017
os_WIFCONTINUED_impl(PyObject *module, int status)
14018
/*[clinic end generated code: output=1e35295d844364bd input=7b577845a0f8b12f]*/
14019
0
{
14020
0
    WAIT_TYPE wait_status;
14021
0
    WAIT_STATUS_INT(wait_status) = status;
14022
0
    return WIFCONTINUED(wait_status);
14023
0
}
14024
#endif /* WIFCONTINUED */
14025
14026
14027
#ifdef WIFSTOPPED
14028
/*[clinic input]
14029
os.WIFSTOPPED -> bool
14030
14031
    status: int
14032
14033
Return True if the process returning status was stopped.
14034
[clinic start generated code]*/
14035
14036
static int
14037
os_WIFSTOPPED_impl(PyObject *module, int status)
14038
/*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
14039
0
{
14040
0
    WAIT_TYPE wait_status;
14041
0
    WAIT_STATUS_INT(wait_status) = status;
14042
0
    return WIFSTOPPED(wait_status);
14043
0
}
14044
#endif /* WIFSTOPPED */
14045
14046
14047
#ifdef WIFSIGNALED
14048
/*[clinic input]
14049
os.WIFSIGNALED -> bool
14050
14051
    status: int
14052
14053
Return True if the process returning status was terminated by a signal.
14054
[clinic start generated code]*/
14055
14056
static int
14057
os_WIFSIGNALED_impl(PyObject *module, int status)
14058
/*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
14059
0
{
14060
0
    WAIT_TYPE wait_status;
14061
0
    WAIT_STATUS_INT(wait_status) = status;
14062
0
    return WIFSIGNALED(wait_status);
14063
0
}
14064
#endif /* WIFSIGNALED */
14065
14066
14067
#ifdef WIFEXITED
14068
/*[clinic input]
14069
@permit_long_summary
14070
os.WIFEXITED -> bool
14071
14072
    status: int
14073
14074
Return True if the process returning status exited via the exit() system call.
14075
[clinic start generated code]*/
14076
14077
static int
14078
os_WIFEXITED_impl(PyObject *module, int status)
14079
/*[clinic end generated code: output=01c09d6ebfeea397 input=8c24a82148709b30]*/
14080
0
{
14081
0
    WAIT_TYPE wait_status;
14082
0
    WAIT_STATUS_INT(wait_status) = status;
14083
0
    return WIFEXITED(wait_status);
14084
0
}
14085
#endif /* WIFEXITED */
14086
14087
14088
#ifdef WEXITSTATUS
14089
/*[clinic input]
14090
os.WEXITSTATUS -> int
14091
14092
    status: int
14093
14094
Return the process return code from status.
14095
[clinic start generated code]*/
14096
14097
static int
14098
os_WEXITSTATUS_impl(PyObject *module, int status)
14099
/*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
14100
0
{
14101
0
    WAIT_TYPE wait_status;
14102
0
    WAIT_STATUS_INT(wait_status) = status;
14103
0
    return WEXITSTATUS(wait_status);
14104
0
}
14105
#endif /* WEXITSTATUS */
14106
14107
14108
#ifdef WTERMSIG
14109
/*[clinic input]
14110
@permit_long_summary
14111
os.WTERMSIG -> int
14112
14113
    status: int
14114
14115
Return the signal that terminated the process that provided the status value.
14116
[clinic start generated code]*/
14117
14118
static int
14119
os_WTERMSIG_impl(PyObject *module, int status)
14120
/*[clinic end generated code: output=172f7dfc8dcfc3ad input=89072f6cbf3f8050]*/
14121
0
{
14122
0
    WAIT_TYPE wait_status;
14123
0
    WAIT_STATUS_INT(wait_status) = status;
14124
0
    return WTERMSIG(wait_status);
14125
0
}
14126
#endif /* WTERMSIG */
14127
14128
14129
#ifdef WSTOPSIG
14130
/*[clinic input]
14131
@permit_long_summary
14132
os.WSTOPSIG -> int
14133
14134
    status: int
14135
14136
Return the signal that stopped the process that provided the status value.
14137
[clinic start generated code]*/
14138
14139
static int
14140
os_WSTOPSIG_impl(PyObject *module, int status)
14141
/*[clinic end generated code: output=0ab7586396f5d82b input=4698db1a6a320433]*/
14142
0
{
14143
0
    WAIT_TYPE wait_status;
14144
0
    WAIT_STATUS_INT(wait_status) = status;
14145
0
    return WSTOPSIG(wait_status);
14146
0
}
14147
#endif /* WSTOPSIG */
14148
#endif /* HAVE_SYS_WAIT_H */
14149
14150
14151
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
14152
#ifdef _SCO_DS
14153
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
14154
   needed definitions in sys/statvfs.h */
14155
#define _SVID3
14156
#endif
14157
#include <sys/statvfs.h>
14158
14159
#ifdef __APPLE__
14160
/* On macOS struct statvfs uses 32-bit integers for block counts,
14161
 * resulting in overflow when filesystems are larger than 4TB. Therefore
14162
 * os.statvfs is implemented in terms of statfs(2).
14163
 */
14164
14165
static PyObject*
14166
_pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) {
14167
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
14168
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
14169
    if (v == NULL) {
14170
        return NULL;
14171
    }
14172
14173
    long flags = 0;
14174
    if (st.f_flags & MNT_RDONLY) {
14175
        flags |= ST_RDONLY;
14176
    }
14177
    if (st.f_flags & MNT_NOSUID) {
14178
        flags |= ST_NOSUID;
14179
    }
14180
14181
    _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file");
14182
14183
#define SET_ITEM(SEQ, INDEX, EXPR)                       \
14184
    do {                                                 \
14185
        PyObject *obj = (EXPR);                          \
14186
        if (obj == NULL) {                               \
14187
            Py_DECREF((SEQ));                            \
14188
            return NULL;                                 \
14189
        }                                                \
14190
        PyStructSequence_SET_ITEM((SEQ), (INDEX), obj);  \
14191
    } while (0)
14192
14193
    SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize));
14194
    SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize));
14195
    SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
14196
    SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
14197
    SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
14198
    SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
14199
    SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
14200
    SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree));
14201
    SET_ITEM(v, 8, PyLong_FromLong((long) flags));
14202
14203
    SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX));
14204
    SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
14205
14206
#undef SET_ITEM
14207
14208
    return v;
14209
}
14210
14211
#else
14212
14213
14214
14215
static PyObject*
14216
0
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
14217
0
    PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
14218
0
    PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
14219
0
    if (v == NULL)
14220
0
        return NULL;
14221
14222
0
    int pos = 0;
14223
14224
0
#define SET_RESULT(CALL)                                     \
14225
0
    do {                                                     \
14226
0
        PyObject *item = (CALL);                             \
14227
0
        if (item == NULL) {                                  \
14228
0
            Py_DECREF(v);                                    \
14229
0
            return NULL;                                     \
14230
0
        }                                                    \
14231
0
        PyStructSequence_SET_ITEM(v, pos++, item);           \
14232
0
    } while(0)
14233
14234
0
#if !defined(HAVE_LARGEFILE_SUPPORT)
14235
0
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
14236
0
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
14237
0
    SET_RESULT(PyLong_FromLong((long) st.f_blocks));
14238
0
    SET_RESULT(PyLong_FromLong((long) st.f_bfree));
14239
0
    SET_RESULT(PyLong_FromLong((long) st.f_bavail));
14240
0
    SET_RESULT(PyLong_FromLong((long) st.f_files));
14241
0
    SET_RESULT(PyLong_FromLong((long) st.f_ffree));
14242
0
    SET_RESULT(PyLong_FromLong((long) st.f_favail));
14243
0
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
14244
0
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
14245
#else
14246
    SET_RESULT(PyLong_FromLong((long) st.f_bsize));
14247
    SET_RESULT(PyLong_FromLong((long) st.f_frsize));
14248
    SET_RESULT(PyLong_FromLongLong((long long) st.f_blocks));
14249
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bfree));
14250
    SET_RESULT(PyLong_FromLongLong((long long) st.f_bavail));
14251
    SET_RESULT(PyLong_FromLongLong((long long) st.f_files));
14252
    SET_RESULT(PyLong_FromLongLong((long long) st.f_ffree));
14253
    SET_RESULT(PyLong_FromLongLong((long long) st.f_favail));
14254
    SET_RESULT(PyLong_FromLong((long) st.f_flag));
14255
    SET_RESULT(PyLong_FromLong((long) st.f_namemax));
14256
#endif
14257
/* The _ALL_SOURCE feature test macro defines f_fsid as a structure
14258
 * (issue #32390). */
14259
#if defined(_AIX) && defined(_ALL_SOURCE)
14260
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid.val[0]));
14261
#else
14262
0
    SET_RESULT(PyLong_FromUnsignedLong(st.f_fsid));
14263
0
#endif
14264
14265
0
#undef SET_RESULT
14266
14267
0
    return v;
14268
0
}
14269
14270
#endif
14271
14272
14273
/*[clinic input]
14274
os.fstatvfs
14275
    fd: int
14276
    /
14277
14278
Perform an fstatvfs system call on the given fd.
14279
14280
Equivalent to statvfs(fd).
14281
[clinic start generated code]*/
14282
14283
static PyObject *
14284
os_fstatvfs_impl(PyObject *module, int fd)
14285
/*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
14286
0
{
14287
0
    int result;
14288
0
    int async_err = 0;
14289
#ifdef __APPLE__
14290
    struct statfs st;
14291
    /* On macOS os.fstatvfs is implemented using fstatfs(2) because
14292
     * the former uses 32-bit values for block counts.
14293
     */
14294
    do {
14295
        Py_BEGIN_ALLOW_THREADS
14296
        result = fstatfs(fd, &st);
14297
        Py_END_ALLOW_THREADS
14298
    } while (result != 0 && errno == EINTR &&
14299
             !(async_err = PyErr_CheckSignals()));
14300
    if (result != 0)
14301
        return (!async_err) ? posix_error() : NULL;
14302
14303
    return _pystatvfs_fromstructstatfs(module, st);
14304
#else
14305
0
    struct statvfs st;
14306
14307
0
    do {
14308
0
        Py_BEGIN_ALLOW_THREADS
14309
0
        result = fstatvfs(fd, &st);
14310
0
        Py_END_ALLOW_THREADS
14311
0
    } while (result != 0 && errno == EINTR &&
14312
0
             !(async_err = PyErr_CheckSignals()));
14313
0
    if (result != 0)
14314
0
        return (!async_err) ? posix_error() : NULL;
14315
14316
0
    return _pystatvfs_fromstructstatvfs(module, st);
14317
0
#endif
14318
0
}
14319
#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
14320
14321
14322
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
14323
#include <sys/statvfs.h>
14324
/*[clinic input]
14325
os.statvfs
14326
14327
    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
14328
14329
Perform a statvfs system call on the given path.
14330
14331
path may always be specified as a string.
14332
On some platforms, path may also be specified as an open file
14333
descriptor.  If this functionality is unavailable, using it raises
14334
an exception.
14335
[clinic start generated code]*/
14336
14337
static PyObject *
14338
os_statvfs_impl(PyObject *module, path_t *path)
14339
/*[clinic end generated code: output=87106dd1beb8556e input=1cfd9a4fd36f7425]*/
14340
0
{
14341
0
    int result;
14342
14343
#ifdef __APPLE__
14344
    /* On macOS os.statvfs is implemented using statfs(2)/fstatfs(2) because
14345
     * the former uses 32-bit values for block counts.
14346
     */
14347
    struct statfs st;
14348
14349
    Py_BEGIN_ALLOW_THREADS
14350
    if (path->is_fd) {
14351
        result = fstatfs(path->fd, &st);
14352
    }
14353
    else
14354
        result = statfs(path->narrow, &st);
14355
    Py_END_ALLOW_THREADS
14356
14357
    if (result) {
14358
        return path_error(path);
14359
    }
14360
14361
    return _pystatvfs_fromstructstatfs(module, st);
14362
14363
#else
14364
0
    struct statvfs st;
14365
14366
0
    Py_BEGIN_ALLOW_THREADS
14367
0
#ifdef HAVE_FSTATVFS
14368
0
    if (path->is_fd) {
14369
0
        result = fstatvfs(path->fd, &st);
14370
0
    }
14371
0
    else
14372
0
#endif
14373
0
        result = statvfs(path->narrow, &st);
14374
0
    Py_END_ALLOW_THREADS
14375
14376
0
    if (result) {
14377
0
        return path_error(path);
14378
0
    }
14379
14380
0
    return _pystatvfs_fromstructstatvfs(module, st);
14381
0
#endif
14382
0
}
14383
#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
14384
14385
14386
#ifdef MS_WINDOWS
14387
/*[clinic input]
14388
@permit_long_summary
14389
os._getdiskusage
14390
14391
    path: path_t
14392
14393
Return disk usage statistics about the given path as a (total, free) tuple.
14394
[clinic start generated code]*/
14395
14396
static PyObject *
14397
os__getdiskusage_impl(PyObject *module, path_t *path)
14398
/*[clinic end generated code: output=3bd3991f5e5c5dfb input=aee7e38bc3e7fb08]*/
14399
{
14400
    BOOL retval;
14401
    ULARGE_INTEGER _, total, free;
14402
    DWORD err = 0;
14403
14404
    Py_BEGIN_ALLOW_THREADS
14405
    retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
14406
    Py_END_ALLOW_THREADS
14407
    if (retval == 0) {
14408
        if (GetLastError() == ERROR_DIRECTORY) {
14409
            wchar_t *dir_path = NULL;
14410
14411
            dir_path = PyMem_New(wchar_t, path->length + 1);
14412
            if (dir_path == NULL) {
14413
                return PyErr_NoMemory();
14414
            }
14415
14416
            wcscpy_s(dir_path, path->length + 1, path->wide);
14417
14418
            if (_dirnameW(dir_path) != -1) {
14419
                Py_BEGIN_ALLOW_THREADS
14420
                retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
14421
                Py_END_ALLOW_THREADS
14422
            }
14423
            /* Record the last error in case it's modified by PyMem_Free. */
14424
            err = GetLastError();
14425
            PyMem_Free(dir_path);
14426
            if (retval) {
14427
                goto success;
14428
            }
14429
        }
14430
        return PyErr_SetFromWindowsErr(err);
14431
    }
14432
14433
success:
14434
    return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
14435
}
14436
#endif /* MS_WINDOWS */
14437
14438
14439
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
14440
 * It maps strings representing configuration variable names to
14441
 * integer values, allowing those functions to be called with the
14442
 * magic names instead of polluting the module's namespace with tons of
14443
 * rarely-used constants.  There are three separate tables that use
14444
 * these definitions.
14445
 *
14446
 * This code is always included, even if none of the interfaces that
14447
 * need it are included.  The #if hackery needed to avoid it would be
14448
 * sufficiently pervasive that it's not worth the loss of readability.
14449
 */
14450
struct constdef {
14451
    const char *name;
14452
    int value;
14453
};
14454
14455
static int
14456
conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename)
14457
4
{
14458
4
    if (PyUnicode_Check(arg)) {
14459
4
        PyObject *table = PyObject_GetAttrString(module, tablename);
14460
4
        if (table == NULL) {
14461
0
            return 0;
14462
0
        }
14463
14464
4
        arg = PyObject_GetItem(table, arg);
14465
4
        Py_DECREF(table);
14466
4
        if (arg == NULL) {
14467
0
            PyErr_SetString(
14468
0
                PyExc_ValueError, "unrecognized configuration name");
14469
0
            return 0;
14470
0
        }
14471
4
    } else {
14472
0
        Py_INCREF(arg);  // Match the Py_DECREF below.
14473
0
    }
14474
14475
4
    int success = 0;
14476
4
    if (!PyIndex_Check(arg)) {
14477
0
        PyErr_SetString(PyExc_TypeError,
14478
0
            "configuration names must be strings or integers");
14479
4
    } else {
14480
4
        int value = PyLong_AsInt(arg);
14481
4
        if (!(value == -1 && PyErr_Occurred())) {
14482
4
            *valuep = value;
14483
4
            success = 1;
14484
4
        }
14485
4
    }
14486
4
    Py_DECREF(arg);
14487
4
    return success;
14488
4
}
14489
14490
14491
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
14492
static struct constdef  posix_constants_pathconf[] = {
14493
#ifdef _PC_ABI_AIO_XFER_MAX
14494
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
14495
#endif
14496
#ifdef _PC_ABI_ASYNC_IO
14497
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
14498
#endif
14499
#ifdef _PC_ASYNC_IO
14500
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
14501
#endif
14502
#ifdef _PC_CHOWN_RESTRICTED
14503
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
14504
#endif
14505
#ifdef _PC_FILESIZEBITS
14506
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
14507
#endif
14508
#ifdef _PC_LAST
14509
    {"PC_LAST", _PC_LAST},
14510
#endif
14511
#ifdef _PC_LINK_MAX
14512
    {"PC_LINK_MAX",     _PC_LINK_MAX},
14513
#endif
14514
#ifdef _PC_MAX_CANON
14515
    {"PC_MAX_CANON",    _PC_MAX_CANON},
14516
#endif
14517
#ifdef _PC_MAX_INPUT
14518
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
14519
#endif
14520
#ifdef _PC_NAME_MAX
14521
    {"PC_NAME_MAX",     _PC_NAME_MAX},
14522
#endif
14523
#ifdef _PC_NO_TRUNC
14524
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
14525
#endif
14526
#ifdef _PC_PATH_MAX
14527
    {"PC_PATH_MAX",     _PC_PATH_MAX},
14528
#endif
14529
#ifdef _PC_PIPE_BUF
14530
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
14531
#endif
14532
#ifdef _PC_PRIO_IO
14533
    {"PC_PRIO_IO",      _PC_PRIO_IO},
14534
#endif
14535
#ifdef _PC_SOCK_MAXBUF
14536
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
14537
#endif
14538
#ifdef _PC_SYNC_IO
14539
    {"PC_SYNC_IO",      _PC_SYNC_IO},
14540
#endif
14541
#ifdef _PC_VDISABLE
14542
    {"PC_VDISABLE",     _PC_VDISABLE},
14543
#endif
14544
#ifdef _PC_ACL_ENABLED
14545
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
14546
#endif
14547
#ifdef _PC_MIN_HOLE_SIZE
14548
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
14549
#endif
14550
#ifdef _PC_ALLOC_SIZE_MIN
14551
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
14552
#endif
14553
#ifdef _PC_REC_INCR_XFER_SIZE
14554
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
14555
#endif
14556
#ifdef _PC_REC_MAX_XFER_SIZE
14557
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
14558
#endif
14559
#ifdef _PC_REC_MIN_XFER_SIZE
14560
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
14561
#endif
14562
#ifdef _PC_REC_XFER_ALIGN
14563
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
14564
#endif
14565
#ifdef _PC_SYMLINK_MAX
14566
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
14567
#endif
14568
#ifdef _PC_XATTR_ENABLED
14569
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
14570
#endif
14571
#ifdef _PC_XATTR_EXISTS
14572
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
14573
#endif
14574
#ifdef _PC_TIMESTAMP_RESOLUTION
14575
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
14576
#endif
14577
};
14578
#endif
14579
14580
14581
#ifdef HAVE_FPATHCONF
14582
/*[clinic input]
14583
os.fpathconf -> long
14584
14585
    fd: fildes
14586
    name: confname(table="pathconf_names")
14587
    /
14588
14589
Return the configuration limit name for the file descriptor fd.
14590
14591
If there is no limit, return -1.
14592
[clinic start generated code]*/
14593
14594
static long
14595
os_fpathconf_impl(PyObject *module, int fd, int name)
14596
/*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/
14597
0
{
14598
0
    long limit;
14599
14600
0
    errno = 0;
14601
0
    limit = fpathconf(fd, name);
14602
0
    if (limit == -1 && errno != 0)
14603
0
        posix_error();
14604
14605
0
    return limit;
14606
0
}
14607
#endif /* HAVE_FPATHCONF */
14608
14609
14610
#ifdef HAVE_PATHCONF
14611
/*[clinic input]
14612
os.pathconf -> long
14613
    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
14614
    name: confname(table="pathconf_names")
14615
14616
Return the configuration limit name for the file or directory path.
14617
14618
If there is no limit, return -1.
14619
On some platforms, path may also be specified as an open file
14620
descriptor.  If this functionality is unavailable, using it raises
14621
an exception.
14622
[clinic start generated code]*/
14623
14624
static long
14625
os_pathconf_impl(PyObject *module, path_t *path, int name)
14626
/*[clinic end generated code: output=5bedee35b293a089 input=e86f6eacfa006426]*/
14627
0
{
14628
0
    long limit;
14629
14630
0
    errno = 0;
14631
0
#ifdef HAVE_FPATHCONF
14632
0
    if (path->is_fd) {
14633
0
        limit = fpathconf(path->fd, name);
14634
0
    }
14635
0
    else
14636
0
#endif
14637
0
        limit = pathconf(path->narrow, name);
14638
0
    if (limit == -1 && errno != 0) {
14639
0
        if (errno == EINVAL)
14640
            /* could be a path or name problem */
14641
0
            posix_error();
14642
0
        else
14643
0
            path_error(path);
14644
0
    }
14645
14646
0
    return limit;
14647
0
}
14648
#endif /* HAVE_PATHCONF */
14649
14650
#ifdef HAVE_CONFSTR
14651
static struct constdef posix_constants_confstr[] = {
14652
#ifdef _CS_ARCHITECTURE
14653
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
14654
#endif
14655
#ifdef _CS_GNU_LIBC_VERSION
14656
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
14657
#endif
14658
#ifdef _CS_GNU_LIBPTHREAD_VERSION
14659
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
14660
#endif
14661
#ifdef _CS_HOSTNAME
14662
    {"CS_HOSTNAME",     _CS_HOSTNAME},
14663
#endif
14664
#ifdef _CS_HW_PROVIDER
14665
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
14666
#endif
14667
#ifdef _CS_HW_SERIAL
14668
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
14669
#endif
14670
#ifdef _CS_INITTAB_NAME
14671
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
14672
#endif
14673
#ifdef _CS_LFS64_CFLAGS
14674
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
14675
#endif
14676
#ifdef _CS_LFS64_LDFLAGS
14677
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
14678
#endif
14679
#ifdef _CS_LFS64_LIBS
14680
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
14681
#endif
14682
#ifdef _CS_LFS64_LINTFLAGS
14683
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
14684
#endif
14685
#ifdef _CS_LFS_CFLAGS
14686
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
14687
#endif
14688
#ifdef _CS_LFS_LDFLAGS
14689
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
14690
#endif
14691
#ifdef _CS_LFS_LIBS
14692
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
14693
#endif
14694
#ifdef _CS_LFS_LINTFLAGS
14695
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
14696
#endif
14697
#ifdef _CS_MACHINE
14698
    {"CS_MACHINE",      _CS_MACHINE},
14699
#endif
14700
#ifdef _CS_PATH
14701
    {"CS_PATH", _CS_PATH},
14702
#endif
14703
#ifdef _CS_RELEASE
14704
    {"CS_RELEASE",      _CS_RELEASE},
14705
#endif
14706
#ifdef _CS_SRPC_DOMAIN
14707
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
14708
#endif
14709
#ifdef _CS_SYSNAME
14710
    {"CS_SYSNAME",      _CS_SYSNAME},
14711
#endif
14712
#ifdef _CS_VERSION
14713
    {"CS_VERSION",      _CS_VERSION},
14714
#endif
14715
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
14716
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
14717
#endif
14718
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
14719
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
14720
#endif
14721
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
14722
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
14723
#endif
14724
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
14725
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
14726
#endif
14727
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
14728
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
14729
#endif
14730
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
14731
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
14732
#endif
14733
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
14734
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
14735
#endif
14736
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
14737
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
14738
#endif
14739
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
14740
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
14741
#endif
14742
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
14743
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
14744
#endif
14745
#ifdef _CS_XBS5_LP64_OFF64_LIBS
14746
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
14747
#endif
14748
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
14749
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
14750
#endif
14751
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
14752
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
14753
#endif
14754
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
14755
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
14756
#endif
14757
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
14758
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
14759
#endif
14760
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
14761
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
14762
#endif
14763
#ifdef _MIPS_CS_AVAIL_PROCESSORS
14764
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
14765
#endif
14766
#ifdef _MIPS_CS_BASE
14767
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
14768
#endif
14769
#ifdef _MIPS_CS_HOSTID
14770
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
14771
#endif
14772
#ifdef _MIPS_CS_HW_NAME
14773
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
14774
#endif
14775
#ifdef _MIPS_CS_NUM_PROCESSORS
14776
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
14777
#endif
14778
#ifdef _MIPS_CS_OSREL_MAJ
14779
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
14780
#endif
14781
#ifdef _MIPS_CS_OSREL_MIN
14782
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
14783
#endif
14784
#ifdef _MIPS_CS_OSREL_PATCH
14785
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
14786
#endif
14787
#ifdef _MIPS_CS_OS_NAME
14788
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
14789
#endif
14790
#ifdef _MIPS_CS_OS_PROVIDER
14791
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
14792
#endif
14793
#ifdef _MIPS_CS_PROCESSORS
14794
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
14795
#endif
14796
#ifdef _MIPS_CS_SERIAL
14797
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
14798
#endif
14799
#ifdef _MIPS_CS_VENDOR
14800
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
14801
#endif
14802
};
14803
14804
14805
/*[clinic input]
14806
os.confstr
14807
14808
    name: confname(table="confstr_names")
14809
    /
14810
14811
Return a string-valued system configuration variable.
14812
[clinic start generated code]*/
14813
14814
static PyObject *
14815
os_confstr_impl(PyObject *module, int name)
14816
/*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/
14817
4
{
14818
4
    PyObject *result = NULL;
14819
4
    char buffer[255];
14820
4
    size_t len;
14821
14822
4
    errno = 0;
14823
4
    len = confstr(name, buffer, sizeof(buffer));
14824
4
    if (len == 0) {
14825
0
        if (errno) {
14826
0
            posix_error();
14827
0
            return NULL;
14828
0
        }
14829
0
        else {
14830
0
            Py_RETURN_NONE;
14831
0
        }
14832
0
    }
14833
14834
4
    if (len >= sizeof(buffer)) {
14835
0
        size_t len2;
14836
0
        char *buf = PyMem_Malloc(len);
14837
0
        if (buf == NULL)
14838
0
            return PyErr_NoMemory();
14839
0
        len2 = confstr(name, buf, len);
14840
0
        assert(len == len2);
14841
0
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
14842
0
        PyMem_Free(buf);
14843
0
    }
14844
4
    else
14845
4
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
14846
4
    return result;
14847
4
}
14848
#endif /* HAVE_CONFSTR */
14849
14850
14851
#ifdef HAVE_SYSCONF
14852
static struct constdef posix_constants_sysconf[] = {
14853
#ifdef _SC_2_CHAR_TERM
14854
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
14855
#endif
14856
#ifdef _SC_2_C_BIND
14857
    {"SC_2_C_BIND",     _SC_2_C_BIND},
14858
#endif
14859
#ifdef _SC_2_C_DEV
14860
    {"SC_2_C_DEV",      _SC_2_C_DEV},
14861
#endif
14862
#ifdef _SC_2_C_VERSION
14863
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
14864
#endif
14865
#ifdef _SC_2_FORT_DEV
14866
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
14867
#endif
14868
#ifdef _SC_2_FORT_RUN
14869
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
14870
#endif
14871
#ifdef _SC_2_LOCALEDEF
14872
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
14873
#endif
14874
#ifdef _SC_2_SW_DEV
14875
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
14876
#endif
14877
#ifdef _SC_2_UPE
14878
    {"SC_2_UPE",        _SC_2_UPE},
14879
#endif
14880
#ifdef _SC_2_VERSION
14881
    {"SC_2_VERSION",    _SC_2_VERSION},
14882
#endif
14883
#ifdef _SC_ABI_ASYNCHRONOUS_IO
14884
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
14885
#endif
14886
#ifdef _SC_ACL
14887
    {"SC_ACL",  _SC_ACL},
14888
#endif
14889
#ifdef _SC_AIO_LISTIO_MAX
14890
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
14891
#endif
14892
#ifdef _SC_AIO_MAX
14893
    {"SC_AIO_MAX",      _SC_AIO_MAX},
14894
#endif
14895
#ifdef _SC_AIO_PRIO_DELTA_MAX
14896
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
14897
#endif
14898
#ifdef _SC_ARG_MAX
14899
    {"SC_ARG_MAX",      _SC_ARG_MAX},
14900
#endif
14901
#ifdef _SC_ASYNCHRONOUS_IO
14902
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
14903
#endif
14904
#ifdef _SC_ATEXIT_MAX
14905
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
14906
#endif
14907
#ifdef _SC_AUDIT
14908
    {"SC_AUDIT",        _SC_AUDIT},
14909
#endif
14910
#ifdef _SC_AVPHYS_PAGES
14911
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
14912
#endif
14913
#ifdef _SC_BC_BASE_MAX
14914
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
14915
#endif
14916
#ifdef _SC_BC_DIM_MAX
14917
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
14918
#endif
14919
#ifdef _SC_BC_SCALE_MAX
14920
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
14921
#endif
14922
#ifdef _SC_BC_STRING_MAX
14923
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
14924
#endif
14925
#ifdef _SC_CAP
14926
    {"SC_CAP",  _SC_CAP},
14927
#endif
14928
#ifdef _SC_CHARCLASS_NAME_MAX
14929
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
14930
#endif
14931
#ifdef _SC_CHAR_BIT
14932
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
14933
#endif
14934
#ifdef _SC_CHAR_MAX
14935
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
14936
#endif
14937
#ifdef _SC_CHAR_MIN
14938
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
14939
#endif
14940
#ifdef _SC_CHILD_MAX
14941
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
14942
#endif
14943
#ifdef _SC_CLK_TCK
14944
    {"SC_CLK_TCK",      _SC_CLK_TCK},
14945
#endif
14946
#ifdef _SC_COHER_BLKSZ
14947
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
14948
#endif
14949
#ifdef _SC_COLL_WEIGHTS_MAX
14950
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
14951
#endif
14952
#ifdef _SC_DCACHE_ASSOC
14953
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
14954
#endif
14955
#ifdef _SC_DCACHE_BLKSZ
14956
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
14957
#endif
14958
#ifdef _SC_DCACHE_LINESZ
14959
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
14960
#endif
14961
#ifdef _SC_DCACHE_SZ
14962
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
14963
#endif
14964
#ifdef _SC_DCACHE_TBLKSZ
14965
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
14966
#endif
14967
#ifdef _SC_DELAYTIMER_MAX
14968
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
14969
#endif
14970
#ifdef _SC_EQUIV_CLASS_MAX
14971
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
14972
#endif
14973
#ifdef _SC_EXPR_NEST_MAX
14974
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
14975
#endif
14976
#ifdef _SC_FSYNC
14977
    {"SC_FSYNC",        _SC_FSYNC},
14978
#endif
14979
#ifdef _SC_GETGR_R_SIZE_MAX
14980
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
14981
#endif
14982
#ifdef _SC_GETPW_R_SIZE_MAX
14983
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
14984
#endif
14985
#ifdef _SC_ICACHE_ASSOC
14986
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
14987
#endif
14988
#ifdef _SC_ICACHE_BLKSZ
14989
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
14990
#endif
14991
#ifdef _SC_ICACHE_LINESZ
14992
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
14993
#endif
14994
#ifdef _SC_ICACHE_SZ
14995
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
14996
#endif
14997
#ifdef _SC_INF
14998
    {"SC_INF",  _SC_INF},
14999
#endif
15000
#ifdef _SC_INT_MAX
15001
    {"SC_INT_MAX",      _SC_INT_MAX},
15002
#endif
15003
#ifdef _SC_INT_MIN
15004
    {"SC_INT_MIN",      _SC_INT_MIN},
15005
#endif
15006
#ifdef _SC_IOV_MAX
15007
    {"SC_IOV_MAX",      _SC_IOV_MAX},
15008
#endif
15009
#ifdef _SC_IP_SECOPTS
15010
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
15011
#endif
15012
#ifdef _SC_JOB_CONTROL
15013
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
15014
#endif
15015
#ifdef _SC_KERN_POINTERS
15016
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
15017
#endif
15018
#ifdef _SC_KERN_SIM
15019
    {"SC_KERN_SIM",     _SC_KERN_SIM},
15020
#endif
15021
#ifdef _SC_LINE_MAX
15022
    {"SC_LINE_MAX",     _SC_LINE_MAX},
15023
#endif
15024
#ifdef _SC_LOGIN_NAME_MAX
15025
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
15026
#endif
15027
#ifdef _SC_LOGNAME_MAX
15028
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
15029
#endif
15030
#ifdef _SC_LONG_BIT
15031
    {"SC_LONG_BIT",     _SC_LONG_BIT},
15032
#endif
15033
#ifdef _SC_MAC
15034
    {"SC_MAC",  _SC_MAC},
15035
#endif
15036
#ifdef _SC_MAPPED_FILES
15037
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
15038
#endif
15039
#ifdef _SC_MAXPID
15040
    {"SC_MAXPID",       _SC_MAXPID},
15041
#endif
15042
#ifdef _SC_MB_LEN_MAX
15043
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
15044
#endif
15045
#ifdef _SC_MEMLOCK
15046
    {"SC_MEMLOCK",      _SC_MEMLOCK},
15047
#endif
15048
#ifdef _SC_MEMLOCK_RANGE
15049
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
15050
#endif
15051
#ifdef _SC_MEMORY_PROTECTION
15052
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
15053
#endif
15054
#ifdef _SC_MESSAGE_PASSING
15055
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
15056
#endif
15057
#ifdef _SC_MMAP_FIXED_ALIGNMENT
15058
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
15059
#endif
15060
#ifdef _SC_MQ_OPEN_MAX
15061
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
15062
#endif
15063
#ifdef _SC_MQ_PRIO_MAX
15064
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
15065
#endif
15066
#ifdef _SC_NACLS_MAX
15067
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
15068
#endif
15069
#ifdef _SC_NGROUPS_MAX
15070
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
15071
#endif
15072
#ifdef _SC_NL_ARGMAX
15073
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
15074
#endif
15075
#ifdef _SC_NL_LANGMAX
15076
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
15077
#endif
15078
#ifdef _SC_NL_MSGMAX
15079
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
15080
#endif
15081
#ifdef _SC_NL_NMAX
15082
    {"SC_NL_NMAX",      _SC_NL_NMAX},
15083
#endif
15084
#ifdef _SC_NL_SETMAX
15085
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
15086
#endif
15087
#ifdef _SC_NL_TEXTMAX
15088
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
15089
#endif
15090
#ifdef _SC_NPROCESSORS_CONF
15091
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
15092
#endif
15093
#ifdef _SC_NPROCESSORS_ONLN
15094
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
15095
#endif
15096
#ifdef _SC_NPROC_CONF
15097
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
15098
#endif
15099
#ifdef _SC_NPROC_ONLN
15100
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
15101
#endif
15102
#ifdef _SC_NZERO
15103
    {"SC_NZERO",        _SC_NZERO},
15104
#endif
15105
#ifdef _SC_OPEN_MAX
15106
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
15107
#endif
15108
#ifdef _SC_PAGESIZE
15109
    {"SC_PAGESIZE",     _SC_PAGESIZE},
15110
#endif
15111
#ifdef _SC_PAGE_SIZE
15112
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
15113
#endif
15114
#ifdef _SC_AIX_REALMEM
15115
    {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
15116
#endif
15117
#ifdef _SC_PASS_MAX
15118
    {"SC_PASS_MAX",     _SC_PASS_MAX},
15119
#endif
15120
#ifdef _SC_PHYS_PAGES
15121
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
15122
#endif
15123
#ifdef _SC_PII
15124
    {"SC_PII",  _SC_PII},
15125
#endif
15126
#ifdef _SC_PII_INTERNET
15127
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
15128
#endif
15129
#ifdef _SC_PII_INTERNET_DGRAM
15130
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
15131
#endif
15132
#ifdef _SC_PII_INTERNET_STREAM
15133
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
15134
#endif
15135
#ifdef _SC_PII_OSI
15136
    {"SC_PII_OSI",      _SC_PII_OSI},
15137
#endif
15138
#ifdef _SC_PII_OSI_CLTS
15139
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
15140
#endif
15141
#ifdef _SC_PII_OSI_COTS
15142
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
15143
#endif
15144
#ifdef _SC_PII_OSI_M
15145
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
15146
#endif
15147
#ifdef _SC_PII_SOCKET
15148
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
15149
#endif
15150
#ifdef _SC_PII_XTI
15151
    {"SC_PII_XTI",      _SC_PII_XTI},
15152
#endif
15153
#ifdef _SC_POLL
15154
    {"SC_POLL", _SC_POLL},
15155
#endif
15156
#ifdef _SC_PRIORITIZED_IO
15157
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
15158
#endif
15159
#ifdef _SC_PRIORITY_SCHEDULING
15160
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
15161
#endif
15162
#ifdef _SC_REALTIME_SIGNALS
15163
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
15164
#endif
15165
#ifdef _SC_RE_DUP_MAX
15166
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
15167
#endif
15168
#ifdef _SC_RTSIG_MAX
15169
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
15170
#endif
15171
#ifdef _SC_SAVED_IDS
15172
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
15173
#endif
15174
#ifdef _SC_SCHAR_MAX
15175
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
15176
#endif
15177
#ifdef _SC_SCHAR_MIN
15178
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
15179
#endif
15180
#ifdef _SC_SELECT
15181
    {"SC_SELECT",       _SC_SELECT},
15182
#endif
15183
#ifdef _SC_SEMAPHORES
15184
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
15185
#endif
15186
#ifdef _SC_SEM_NSEMS_MAX
15187
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
15188
#endif
15189
#ifdef _SC_SEM_VALUE_MAX
15190
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
15191
#endif
15192
#ifdef _SC_SHARED_MEMORY_OBJECTS
15193
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
15194
#endif
15195
#ifdef _SC_SHRT_MAX
15196
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
15197
#endif
15198
#ifdef _SC_SHRT_MIN
15199
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
15200
#endif
15201
#ifdef _SC_SIGQUEUE_MAX
15202
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
15203
#endif
15204
#ifdef _SC_SIGRT_MAX
15205
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
15206
#endif
15207
#ifdef _SC_SIGRT_MIN
15208
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
15209
#endif
15210
#ifdef _SC_SOFTPOWER
15211
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
15212
#endif
15213
#ifdef _SC_SPLIT_CACHE
15214
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
15215
#endif
15216
#ifdef _SC_SSIZE_MAX
15217
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
15218
#endif
15219
#ifdef _SC_STACK_PROT
15220
    {"SC_STACK_PROT",   _SC_STACK_PROT},
15221
#endif
15222
#ifdef _SC_STREAM_MAX
15223
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
15224
#endif
15225
#ifdef _SC_SYNCHRONIZED_IO
15226
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
15227
#endif
15228
#ifdef _SC_THREADS
15229
    {"SC_THREADS",      _SC_THREADS},
15230
#endif
15231
#ifdef _SC_THREAD_ATTR_STACKADDR
15232
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
15233
#endif
15234
#ifdef _SC_THREAD_ATTR_STACKSIZE
15235
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
15236
#endif
15237
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
15238
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
15239
#endif
15240
#ifdef _SC_THREAD_KEYS_MAX
15241
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
15242
#endif
15243
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
15244
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
15245
#endif
15246
#ifdef _SC_THREAD_PRIO_INHERIT
15247
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
15248
#endif
15249
#ifdef _SC_THREAD_PRIO_PROTECT
15250
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
15251
#endif
15252
#ifdef _SC_THREAD_PROCESS_SHARED
15253
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
15254
#endif
15255
#ifdef _SC_THREAD_SAFE_FUNCTIONS
15256
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
15257
#endif
15258
#ifdef _SC_THREAD_STACK_MIN
15259
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
15260
#endif
15261
#ifdef _SC_THREAD_THREADS_MAX
15262
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
15263
#endif
15264
#ifdef _SC_TIMERS
15265
    {"SC_TIMERS",       _SC_TIMERS},
15266
#endif
15267
#ifdef _SC_TIMER_MAX
15268
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
15269
#endif
15270
#ifdef _SC_TTY_NAME_MAX
15271
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
15272
#endif
15273
#ifdef _SC_TZNAME_MAX
15274
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
15275
#endif
15276
#ifdef _SC_T_IOV_MAX
15277
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
15278
#endif
15279
#ifdef _SC_UCHAR_MAX
15280
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
15281
#endif
15282
#ifdef _SC_UINT_MAX
15283
    {"SC_UINT_MAX",     _SC_UINT_MAX},
15284
#endif
15285
#ifdef _SC_UIO_MAXIOV
15286
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
15287
#endif
15288
#ifdef _SC_ULONG_MAX
15289
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
15290
#endif
15291
#ifdef _SC_USHRT_MAX
15292
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
15293
#endif
15294
#ifdef _SC_VERSION
15295
    {"SC_VERSION",      _SC_VERSION},
15296
#endif
15297
#ifdef _SC_WORD_BIT
15298
    {"SC_WORD_BIT",     _SC_WORD_BIT},
15299
#endif
15300
#ifdef _SC_XBS5_ILP32_OFF32
15301
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
15302
#endif
15303
#ifdef _SC_XBS5_ILP32_OFFBIG
15304
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
15305
#endif
15306
#ifdef _SC_XBS5_LP64_OFF64
15307
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
15308
#endif
15309
#ifdef _SC_XBS5_LPBIG_OFFBIG
15310
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
15311
#endif
15312
#ifdef _SC_XOPEN_CRYPT
15313
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
15314
#endif
15315
#ifdef _SC_XOPEN_ENH_I18N
15316
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
15317
#endif
15318
#ifdef _SC_XOPEN_LEGACY
15319
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
15320
#endif
15321
#ifdef _SC_XOPEN_REALTIME
15322
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
15323
#endif
15324
#ifdef _SC_XOPEN_REALTIME_THREADS
15325
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
15326
#endif
15327
#ifdef _SC_XOPEN_SHM
15328
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
15329
#endif
15330
#ifdef _SC_XOPEN_UNIX
15331
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
15332
#endif
15333
#ifdef _SC_XOPEN_VERSION
15334
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
15335
#endif
15336
#ifdef _SC_XOPEN_XCU_VERSION
15337
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
15338
#endif
15339
#ifdef _SC_XOPEN_XPG2
15340
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
15341
#endif
15342
#ifdef _SC_XOPEN_XPG3
15343
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
15344
#endif
15345
#ifdef _SC_XOPEN_XPG4
15346
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
15347
#endif
15348
#ifdef _SC_MINSIGSTKSZ
15349
    {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
15350
#endif
15351
};
15352
15353
15354
/*[clinic input]
15355
os.sysconf -> long
15356
    name: confname(table="sysconf_names")
15357
    /
15358
15359
Return an integer-valued system configuration variable.
15360
[clinic start generated code]*/
15361
15362
static long
15363
os_sysconf_impl(PyObject *module, int name)
15364
/*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/
15365
0
{
15366
0
    long value;
15367
15368
0
    errno = 0;
15369
0
    value = sysconf(name);
15370
0
    if (value == -1 && errno != 0)
15371
0
        posix_error();
15372
0
    return value;
15373
0
}
15374
#endif /* HAVE_SYSCONF */
15375
15376
15377
static int
15378
setup_confname_table(struct constdef *table, size_t tablesize,
15379
                     const char *tablename, PyObject *module)
15380
111
{
15381
111
    PyObject *d = PyDict_New();
15382
111
    if (d == NULL)
15383
0
        return -1;
15384
15385
6.80k
    for (size_t i=0; i < tablesize; ++i) {
15386
6.69k
        PyObject *o = PyLong_FromLong(table[i].value);
15387
6.69k
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
15388
0
            Py_XDECREF(o);
15389
0
            Py_DECREF(d);
15390
0
            return -1;
15391
0
        }
15392
6.69k
        Py_DECREF(o);
15393
6.69k
    }
15394
111
    return PyModule_Add(module, tablename, d);
15395
111
}
15396
15397
/* Return -1 on failure, 0 on success. */
15398
static int
15399
setup_confname_tables(PyObject *module)
15400
37
{
15401
37
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
15402
37
    if (setup_confname_table(posix_constants_pathconf,
15403
37
                             sizeof(posix_constants_pathconf)
15404
37
                               / sizeof(struct constdef),
15405
37
                             "pathconf_names", module))
15406
0
        return -1;
15407
37
#endif
15408
37
#ifdef HAVE_CONFSTR
15409
37
    if (setup_confname_table(posix_constants_confstr,
15410
37
                             sizeof(posix_constants_confstr)
15411
37
                               / sizeof(struct constdef),
15412
37
                             "confstr_names", module))
15413
0
        return -1;
15414
37
#endif
15415
37
#ifdef HAVE_SYSCONF
15416
37
    if (setup_confname_table(posix_constants_sysconf,
15417
37
                             sizeof(posix_constants_sysconf)
15418
37
                               / sizeof(struct constdef),
15419
37
                             "sysconf_names", module))
15420
0
        return -1;
15421
37
#endif
15422
37
    return 0;
15423
37
}
15424
15425
15426
/*[clinic input]
15427
os.abort
15428
15429
Abort the interpreter immediately.
15430
15431
This function 'dumps core' or otherwise fails in the hardest way
15432
possible on the hosting operating system.  This function never returns.
15433
[clinic start generated code]*/
15434
15435
static PyObject *
15436
os_abort_impl(PyObject *module)
15437
/*[clinic end generated code: output=dcf52586dad2467c input=ee8bd0ed690440ab]*/
15438
0
{
15439
0
    abort();
15440
    /*NOTREACHED*/
15441
#ifndef __clang__
15442
    /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
15443
       GCC emits a warning without "return NULL;" (compiler bug?), but Clang
15444
       is smarter and emits a warning on the return. */
15445
    Py_FatalError("abort() called from Python code didn't abort!");
15446
    return NULL;
15447
#endif
15448
0
}
15449
15450
#ifdef MS_WINDOWS
15451
/* Grab ShellExecute dynamically from shell32 */
15452
static int has_ShellExecute = -1;
15453
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
15454
                                              LPCWSTR, INT);
15455
static int
15456
check_ShellExecute(void)
15457
{
15458
    HINSTANCE hShell32;
15459
15460
    /* only recheck */
15461
    if (-1 == has_ShellExecute) {
15462
        Py_BEGIN_ALLOW_THREADS
15463
        /* Security note: this call is not vulnerable to "DLL hijacking".
15464
           SHELL32 is part of "KnownDLLs" and so Windows always load
15465
           the system SHELL32.DLL, even if there is another SHELL32.DLL
15466
           in the DLL search path. */
15467
        hShell32 = LoadLibraryW(L"SHELL32");
15468
        if (hShell32) {
15469
            *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
15470
                                            "ShellExecuteW");
15471
            has_ShellExecute = Py_ShellExecuteW != NULL;
15472
        } else {
15473
            has_ShellExecute = 0;
15474
        }
15475
        Py_END_ALLOW_THREADS
15476
    }
15477
    return has_ShellExecute;
15478
}
15479
15480
15481
/*[clinic input]
15482
os.startfile
15483
    filepath: path_t
15484
    operation: Py_UNICODE = NULL
15485
    arguments: Py_UNICODE = NULL
15486
    cwd: path_t(nullable=True) = None
15487
    show_cmd: int = 1
15488
15489
Start a file with its associated application.
15490
15491
When "operation" is not specified or "open", this acts like
15492
double-clicking the file in Explorer, or giving the file name as an
15493
argument to the DOS "start" command: the file is opened with whatever
15494
application (if any) its extension is associated.
15495
When another "operation" is given, it specifies what should be done with
15496
the file.  A typical operation is "print".
15497
15498
"arguments" is passed to the application, but should be omitted if the
15499
file is a document.
15500
15501
"cwd" is the working directory for the operation. If "filepath" is
15502
relative, it will be resolved against this directory. This argument
15503
should usually be an absolute path.
15504
15505
"show_cmd" can be used to override the recommended visibility option.
15506
See the Windows ShellExecute documentation for values.
15507
15508
startfile returns as soon as the associated application is launched.
15509
There is no option to wait for the application to close, and no way
15510
to retrieve the application's exit status.
15511
15512
The filepath is relative to the current directory.  If you want to use
15513
an absolute path, make sure the first character is not a slash ("/");
15514
the underlying Win32 ShellExecute function doesn't work if it is.
15515
[clinic start generated code]*/
15516
15517
static PyObject *
15518
os_startfile_impl(PyObject *module, path_t *filepath,
15519
                  const wchar_t *operation, const wchar_t *arguments,
15520
                  path_t *cwd, int show_cmd)
15521
/*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/
15522
{
15523
    HINSTANCE rc;
15524
15525
    if(!check_ShellExecute()) {
15526
        /* If the OS doesn't have ShellExecute, return a
15527
           NotImplementedError. */
15528
        return PyErr_Format(PyExc_NotImplementedError,
15529
            "startfile not available on this platform");
15530
    }
15531
15532
    if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
15533
        return NULL;
15534
    }
15535
    if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
15536
                    arguments, cwd->object ? cwd->object : Py_None,
15537
                    show_cmd) < 0) {
15538
        return NULL;
15539
    }
15540
15541
    Py_BEGIN_ALLOW_THREADS
15542
    rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
15543
                          arguments, cwd->wide, show_cmd);
15544
    Py_END_ALLOW_THREADS
15545
15546
    if (rc <= (HINSTANCE)32) {
15547
        win32_error_object("startfile", filepath->object);
15548
        return NULL;
15549
    }
15550
    Py_RETURN_NONE;
15551
}
15552
#endif /* MS_WINDOWS */
15553
15554
15555
#ifdef HAVE_GETLOADAVG
15556
/*[clinic input]
15557
os.getloadavg
15558
15559
Return average recent system load information.
15560
15561
Return the number of processes in the system run queue averaged over
15562
the last 1, 5, and 15 minutes as a tuple of three floats.
15563
Raises OSError if the load average was unobtainable.
15564
[clinic start generated code]*/
15565
15566
static PyObject *
15567
os_getloadavg_impl(PyObject *module)
15568
/*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
15569
0
{
15570
0
    double loadavg[3];
15571
0
    if (getloadavg(loadavg, 3)!=3) {
15572
0
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
15573
0
        return NULL;
15574
0
    } else
15575
0
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
15576
0
}
15577
#endif /* HAVE_GETLOADAVG */
15578
15579
15580
/*[clinic input]
15581
os.device_encoding
15582
    fd: int
15583
15584
Return a string describing the encoding of a terminal's file descriptor.
15585
15586
The file descriptor must be attached to a terminal.
15587
If the device is not a terminal, return None.
15588
[clinic start generated code]*/
15589
15590
static PyObject *
15591
os_device_encoding_impl(PyObject *module, int fd)
15592
/*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
15593
0
{
15594
0
    return _Py_device_encoding(fd);
15595
0
}
15596
15597
15598
#ifdef HAVE_SETRESUID
15599
/*[clinic input]
15600
os.setresuid
15601
15602
    ruid: uid_t
15603
    euid: uid_t
15604
    suid: uid_t
15605
    /
15606
15607
Set the current process's real, effective, and saved user ids.
15608
[clinic start generated code]*/
15609
15610
static PyObject *
15611
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
15612
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
15613
0
{
15614
#ifdef __ANDROID__
15615
    // On Android, calling this function as a non-root user leads to a process crash
15616
    // rather than returning a permission error.
15617
    if (getuid() != 0) {
15618
        errno = EPERM;
15619
        return posix_error();
15620
    }
15621
#endif
15622
0
    if (setresuid(ruid, euid, suid) < 0)
15623
0
        return posix_error();
15624
0
    Py_RETURN_NONE;
15625
0
}
15626
#endif /* HAVE_SETRESUID */
15627
15628
15629
#ifdef HAVE_SETRESGID
15630
/*[clinic input]
15631
os.setresgid
15632
15633
    rgid: gid_t
15634
    egid: gid_t
15635
    sgid: gid_t
15636
    /
15637
15638
Set the current process's real, effective, and saved group ids.
15639
[clinic start generated code]*/
15640
15641
static PyObject *
15642
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
15643
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
15644
0
{
15645
#ifdef __ANDROID__
15646
    // On Android, calling this function as a non-root user leads to a process crash
15647
    // rather than returning a permission error.
15648
    if (getuid() != 0) {
15649
        errno = EPERM;
15650
        return posix_error();
15651
    }
15652
#endif
15653
0
    if (setresgid(rgid, egid, sgid) < 0)
15654
0
        return posix_error();
15655
0
    Py_RETURN_NONE;
15656
0
}
15657
#endif /* HAVE_SETRESGID */
15658
15659
15660
#ifdef HAVE_GETRESUID
15661
/*[clinic input]
15662
@permit_long_summary
15663
os.getresuid
15664
15665
Return a tuple of the current process's real, effective, and saved user ids.
15666
[clinic start generated code]*/
15667
15668
static PyObject *
15669
os_getresuid_impl(PyObject *module)
15670
/*[clinic end generated code: output=8e0becff5dece5bf input=ddf95881f492cb97]*/
15671
0
{
15672
0
    uid_t ruid, euid, suid;
15673
0
    if (getresuid(&ruid, &euid, &suid) < 0)
15674
0
        return posix_error();
15675
0
    return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
15676
0
                                  _PyLong_FromUid(euid),
15677
0
                                  _PyLong_FromUid(suid));
15678
0
}
15679
#endif /* HAVE_GETRESUID */
15680
15681
15682
#ifdef HAVE_GETRESGID
15683
/*[clinic input]
15684
@permit_long_summary
15685
os.getresgid
15686
15687
Return a tuple of the current process's real, effective, and saved group ids.
15688
[clinic start generated code]*/
15689
15690
static PyObject *
15691
os_getresgid_impl(PyObject *module)
15692
/*[clinic end generated code: output=2719c4bfcf27fb9f input=ad9adadc86fbdb17]*/
15693
0
{
15694
0
    gid_t rgid, egid, sgid;
15695
0
    if (getresgid(&rgid, &egid, &sgid) < 0)
15696
0
        return posix_error();
15697
0
    return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
15698
0
                                  _PyLong_FromGid(egid),
15699
0
                                  _PyLong_FromGid(sgid));
15700
0
}
15701
#endif /* HAVE_GETRESGID */
15702
15703
15704
#ifdef USE_XATTRS
15705
/*[clinic input]
15706
os.getxattr
15707
15708
    path: path_t(allow_fd=True)
15709
    attribute: path_t
15710
    *
15711
    follow_symlinks: bool = True
15712
15713
Return the value of extended attribute attribute on path.
15714
15715
path may be either a string, a path-like object, or an open file
15716
descriptor.
15717
If follow_symlinks is False, and the last element of the path is
15718
a symbolic link, getxattr will examine the symbolic link itself
15719
instead of the file the link points to.
15720
15721
[clinic start generated code]*/
15722
15723
static PyObject *
15724
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15725
                 int follow_symlinks)
15726
/*[clinic end generated code: output=5f2f44200a43cff2 input=db1021ed738d9754]*/
15727
0
{
15728
0
    if (fd_and_follow_symlinks_invalid("getxattr", path->is_fd, follow_symlinks))
15729
0
        return NULL;
15730
15731
0
    if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
15732
0
        return NULL;
15733
0
    }
15734
15735
0
    for (Py_ssize_t i = 0; ; i++) {
15736
0
        ssize_t result;
15737
0
        static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
15738
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15739
0
        if (!buffer_size) {
15740
0
            path_error(path);
15741
0
            return NULL;
15742
0
        }
15743
0
        PyBytesWriter *writer = PyBytesWriter_Create(buffer_size);
15744
0
        if (writer == NULL) {
15745
0
            return NULL;
15746
0
        }
15747
0
        void *ptr = PyBytesWriter_GetData(writer);
15748
15749
0
        Py_BEGIN_ALLOW_THREADS;
15750
0
        if (path->is_fd)
15751
0
            result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
15752
0
        else if (follow_symlinks)
15753
0
            result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15754
0
        else
15755
0
            result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
15756
0
        Py_END_ALLOW_THREADS;
15757
15758
0
        if (result < 0) {
15759
0
            PyBytesWriter_Discard(writer);
15760
0
            if (errno == ERANGE) {
15761
0
                continue;
15762
0
            }
15763
0
            path_error(path);
15764
0
            return NULL;
15765
0
        }
15766
15767
0
        return PyBytesWriter_FinishWithSize(writer, result);
15768
0
    }
15769
0
}
15770
15771
15772
/*[clinic input]
15773
os.setxattr
15774
15775
    path: path_t(allow_fd=True)
15776
    attribute: path_t
15777
    value: Py_buffer
15778
    flags: int = 0
15779
    *
15780
    follow_symlinks: bool = True
15781
15782
Set extended attribute attribute on path to value.
15783
15784
path may be either a string, a path-like object,  or an open file
15785
descriptor.
15786
If follow_symlinks is False, and the last element of the path is
15787
a symbolic link, setxattr will modify the symbolic link itself instead
15788
of the file the link points to.
15789
15790
[clinic start generated code]*/
15791
15792
static PyObject *
15793
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
15794
                 Py_buffer *value, int flags, int follow_symlinks)
15795
/*[clinic end generated code: output=98b83f63fdde26bb input=6c4ee6724e8947a4]*/
15796
0
{
15797
0
    ssize_t result;
15798
15799
0
    if (fd_and_follow_symlinks_invalid("setxattr", path->is_fd, follow_symlinks))
15800
0
        return NULL;
15801
15802
0
    if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
15803
0
                    value->buf, value->len, flags) < 0) {
15804
0
        return NULL;
15805
0
    }
15806
15807
0
    Py_BEGIN_ALLOW_THREADS;
15808
0
    if (path->is_fd)
15809
0
        result = fsetxattr(path->fd, attribute->narrow,
15810
0
                           value->buf, value->len, flags);
15811
0
    else if (follow_symlinks)
15812
0
        result = setxattr(path->narrow, attribute->narrow,
15813
0
                           value->buf, value->len, flags);
15814
0
    else
15815
0
        result = lsetxattr(path->narrow, attribute->narrow,
15816
0
                           value->buf, value->len, flags);
15817
0
    Py_END_ALLOW_THREADS;
15818
15819
0
    if (result) {
15820
0
        path_error(path);
15821
0
        return NULL;
15822
0
    }
15823
15824
0
    Py_RETURN_NONE;
15825
0
}
15826
15827
15828
/*[clinic input]
15829
os.removexattr
15830
15831
    path: path_t(allow_fd=True)
15832
    attribute: path_t
15833
    *
15834
    follow_symlinks: bool = True
15835
15836
Remove extended attribute attribute on path.
15837
15838
path may be either a string, a path-like object, or an open file
15839
descriptor.
15840
If follow_symlinks is False, and the last element of the path is
15841
a symbolic link, removexattr will modify the symbolic link itself
15842
instead of the file the link points to.
15843
15844
[clinic start generated code]*/
15845
15846
static PyObject *
15847
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
15848
                    int follow_symlinks)
15849
/*[clinic end generated code: output=521a51817980cda6 input=a7ec62a86aa83f01]*/
15850
0
{
15851
0
    ssize_t result;
15852
15853
0
    if (fd_and_follow_symlinks_invalid("removexattr", path->is_fd, follow_symlinks))
15854
0
        return NULL;
15855
15856
0
    if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
15857
0
        return NULL;
15858
0
    }
15859
15860
0
    Py_BEGIN_ALLOW_THREADS;
15861
0
    if (path->is_fd)
15862
0
        result = fremovexattr(path->fd, attribute->narrow);
15863
0
    else if (follow_symlinks)
15864
0
        result = removexattr(path->narrow, attribute->narrow);
15865
0
    else
15866
0
        result = lremovexattr(path->narrow, attribute->narrow);
15867
0
    Py_END_ALLOW_THREADS;
15868
15869
0
    if (result) {
15870
0
        return path_error(path);
15871
0
    }
15872
15873
0
    Py_RETURN_NONE;
15874
0
}
15875
15876
15877
/*[clinic input]
15878
os.listxattr
15879
15880
    path: path_t(allow_fd=True, nullable=True) = None
15881
    *
15882
    follow_symlinks: bool = True
15883
15884
Return a list of extended attributes on path.
15885
15886
path may be either None, a string, a path-like object, or an open file
15887
descriptor.  If path is None, listxattr will examine the current
15888
directory.
15889
If follow_symlinks is False, and the last element of the path is
15890
a symbolic link, listxattr will examine the symbolic link itself instead
15891
of the file the link points to.
15892
[clinic start generated code]*/
15893
15894
static PyObject *
15895
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
15896
/*[clinic end generated code: output=bebdb4e2ad0ce435 input=cb4a6414afaa99bd]*/
15897
0
{
15898
0
    Py_ssize_t i;
15899
0
    PyObject *result = NULL;
15900
0
    const char *name;
15901
0
    char *buffer = NULL;
15902
15903
0
    if (fd_and_follow_symlinks_invalid("listxattr", path->is_fd, follow_symlinks))
15904
0
        goto exit;
15905
15906
0
    if (PySys_Audit("os.listxattr", "(O)",
15907
0
                    path->object ? path->object : Py_None) < 0) {
15908
0
        return NULL;
15909
0
    }
15910
15911
0
    name = path->narrow ? path->narrow : ".";
15912
15913
0
    for (i = 0; ; i++) {
15914
0
        const char *start, *trace, *end;
15915
0
        ssize_t length;
15916
0
        static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
15917
0
        Py_ssize_t buffer_size = buffer_sizes[i];
15918
0
        if (!buffer_size) {
15919
            /* ERANGE */
15920
0
            path_error(path);
15921
0
            break;
15922
0
        }
15923
0
        buffer = PyMem_Malloc(buffer_size);
15924
0
        if (!buffer) {
15925
0
            PyErr_NoMemory();
15926
0
            break;
15927
0
        }
15928
15929
0
        Py_BEGIN_ALLOW_THREADS;
15930
0
        if (path->is_fd)
15931
0
            length = flistxattr(path->fd, buffer, buffer_size);
15932
0
        else if (follow_symlinks)
15933
0
            length = listxattr(name, buffer, buffer_size);
15934
0
        else
15935
0
            length = llistxattr(name, buffer, buffer_size);
15936
0
        Py_END_ALLOW_THREADS;
15937
15938
0
        if (length < 0) {
15939
0
            if (errno == ERANGE) {
15940
0
                PyMem_Free(buffer);
15941
0
                buffer = NULL;
15942
0
                continue;
15943
0
            }
15944
0
            path_error(path);
15945
0
            break;
15946
0
        }
15947
15948
0
        result = PyList_New(0);
15949
0
        if (!result) {
15950
0
            goto exit;
15951
0
        }
15952
15953
0
        end = buffer + length;
15954
0
        for (trace = start = buffer; trace != end; trace++) {
15955
0
            if (!*trace) {
15956
0
                int error;
15957
0
                PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
15958
0
                                                                 trace - start);
15959
0
                if (!attribute) {
15960
0
                    Py_SETREF(result, NULL);
15961
0
                    goto exit;
15962
0
                }
15963
0
                error = PyList_Append(result, attribute);
15964
0
                Py_DECREF(attribute);
15965
0
                if (error) {
15966
0
                    Py_SETREF(result, NULL);
15967
0
                    goto exit;
15968
0
                }
15969
0
                start = trace + 1;
15970
0
            }
15971
0
        }
15972
0
    break;
15973
0
    }
15974
0
exit:
15975
0
    if (buffer)
15976
0
        PyMem_Free(buffer);
15977
0
    return result;
15978
0
}
15979
#endif /* USE_XATTRS */
15980
15981
15982
/*[clinic input]
15983
@permit_long_summary
15984
os.urandom
15985
15986
    size: Py_ssize_t(allow_negative=False)
15987
    /
15988
15989
Return a bytes object containing random bytes suitable for cryptographic use.
15990
[clinic start generated code]*/
15991
15992
static PyObject *
15993
os_urandom_impl(PyObject *module, Py_ssize_t size)
15994
/*[clinic end generated code: output=42c5cca9d18068e9 input=58a0def87dbc2c22]*/
15995
0
{
15996
0
    if (size < 0) {
15997
0
        return PyErr_Format(PyExc_ValueError,
15998
0
                            "negative argument not allowed");
15999
0
    }
16000
16001
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
16002
0
    if (writer == NULL) {
16003
0
        return NULL;
16004
0
    }
16005
16006
0
    int result = _PyOS_URandom(PyBytesWriter_GetData(writer), size);
16007
0
    if (result == -1) {
16008
0
        PyBytesWriter_Discard(writer);
16009
0
        return NULL;
16010
0
    }
16011
0
    return PyBytesWriter_Finish(writer);
16012
0
}
16013
16014
#if defined(HAVE_MEMFD_CREATE) || \
16015
    (defined(__linux__) && defined(__NR_memfd_create) && defined(MFD_CLOEXEC))
16016
#  define _Py_HAVE_MEMFD_CREATE
16017
#endif
16018
16019
#ifdef _Py_HAVE_MEMFD_CREATE
16020
/*[clinic input]
16021
os.memfd_create
16022
16023
    name: unicode_fs_encoded
16024
    flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
16025
16026
[clinic start generated code]*/
16027
16028
static PyObject *
16029
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
16030
/*[clinic end generated code: output=6681ede983bdb9a6 input=cd0eb092cfac474b]*/
16031
0
{
16032
0
    int fd;
16033
0
    const char *bytes = PyBytes_AS_STRING(name);
16034
0
    Py_BEGIN_ALLOW_THREADS
16035
0
#ifdef HAVE_MEMFD_CREATE
16036
0
    fd = memfd_create(bytes, flags);
16037
#else
16038
    fd = syscall(__NR_memfd_create, bytes, flags);
16039
#endif
16040
0
    Py_END_ALLOW_THREADS
16041
0
    if (fd == -1) {
16042
0
        return PyErr_SetFromErrno(PyExc_OSError);
16043
0
    }
16044
0
    return PyLong_FromLong(fd);
16045
0
}
16046
#endif
16047
16048
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
16049
/*[clinic input]
16050
os.eventfd
16051
16052
    initval: unsigned_int
16053
    flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
16054
16055
Creates and returns an event notification file descriptor.
16056
[clinic start generated code]*/
16057
16058
static PyObject *
16059
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
16060
/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
16061
16062
0
{
16063
    /* initval is limited to uint32_t, internal counter is uint64_t */
16064
0
    int fd;
16065
0
    Py_BEGIN_ALLOW_THREADS
16066
0
    fd = eventfd(initval, flags);
16067
0
    Py_END_ALLOW_THREADS
16068
0
    if (fd == -1) {
16069
0
        return PyErr_SetFromErrno(PyExc_OSError);
16070
0
    }
16071
0
    return PyLong_FromLong(fd);
16072
0
}
16073
16074
/*[clinic input]
16075
os.eventfd_read
16076
16077
    fd: fildes
16078
16079
Read eventfd value
16080
[clinic start generated code]*/
16081
16082
static PyObject *
16083
os_eventfd_read_impl(PyObject *module, int fd)
16084
/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
16085
0
{
16086
0
    eventfd_t value;
16087
0
    int result;
16088
0
    Py_BEGIN_ALLOW_THREADS
16089
0
    result = eventfd_read(fd, &value);
16090
0
    Py_END_ALLOW_THREADS
16091
0
    if (result == -1) {
16092
0
        return PyErr_SetFromErrno(PyExc_OSError);
16093
0
    }
16094
0
    return PyLong_FromUnsignedLongLong(value);
16095
0
}
16096
16097
/*[clinic input]
16098
os.eventfd_write
16099
16100
    fd: fildes
16101
    value: unsigned_long_long
16102
16103
Write eventfd value.
16104
[clinic start generated code]*/
16105
16106
static PyObject *
16107
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
16108
/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
16109
0
{
16110
0
    int result;
16111
0
    Py_BEGIN_ALLOW_THREADS
16112
0
    result = eventfd_write(fd, value);
16113
0
    Py_END_ALLOW_THREADS
16114
0
    if (result == -1) {
16115
0
        return PyErr_SetFromErrno(PyExc_OSError);
16116
0
    }
16117
0
    Py_RETURN_NONE;
16118
0
}
16119
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
16120
16121
/* Terminal size querying */
16122
16123
PyDoc_STRVAR(TerminalSize_docstring,
16124
    "A tuple of (columns, lines) for holding terminal window size");
16125
16126
static PyStructSequence_Field TerminalSize_fields[] = {
16127
    {"columns", "width of the terminal window in characters"},
16128
    {"lines", "height of the terminal window in characters"},
16129
    {NULL, NULL}
16130
};
16131
16132
static PyStructSequence_Desc TerminalSize_desc = {
16133
    "os.terminal_size",
16134
    TerminalSize_docstring,
16135
    TerminalSize_fields,
16136
    2,
16137
};
16138
16139
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
16140
/*[clinic input]
16141
os.get_terminal_size
16142
16143
    fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
16144
    /
16145
16146
Return the size of the terminal window as (columns, lines).
16147
16148
The optional argument fd (default standard output) specifies
16149
which file descriptor should be queried.
16150
16151
If the file descriptor is not connected to a terminal, an OSError
16152
is thrown.
16153
16154
This function will only be defined if an implementation is
16155
available for this system.
16156
16157
shutil.get_terminal_size is the high-level function which should
16158
normally be used, os.get_terminal_size is the low-level implementation.
16159
[clinic start generated code]*/
16160
16161
static PyObject *
16162
os_get_terminal_size_impl(PyObject *module, int fd)
16163
/*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
16164
0
{
16165
0
    int columns, lines;
16166
0
    PyObject *termsize;
16167
16168
    /* Under some conditions stdout may not be connected and
16169
     * fileno(stdout) may point to an invalid file descriptor. For example
16170
     * GUI apps don't have valid standard streams by default.
16171
     *
16172
     * If this happens, and the optional fd argument is not present,
16173
     * the ioctl below will fail returning EBADF. This is what we want.
16174
     */
16175
16176
0
#ifdef TERMSIZE_USE_IOCTL
16177
0
    {
16178
        // On Android, stdout is probably not connected, and calling TIOCGWINSZ
16179
        // on an invalid file descriptor causes a log message "avc:  denied  {
16180
        // ioctl }". Some common tools such as pytest call get_terminal_size
16181
        // very often, so check it's a TTY first to avoid cluttering the log.
16182
0
        if (!isatty(fd))
16183
0
            return PyErr_SetFromErrno(PyExc_OSError);
16184
16185
0
        struct winsize w;
16186
0
        if (ioctl(fd, TIOCGWINSZ, &w))
16187
0
            return PyErr_SetFromErrno(PyExc_OSError);
16188
0
        columns = w.ws_col;
16189
0
        lines = w.ws_row;
16190
0
    }
16191
0
#endif /* TERMSIZE_USE_IOCTL */
16192
16193
#ifdef TERMSIZE_USE_CONIO
16194
    {
16195
        HANDLE handle;
16196
        CONSOLE_SCREEN_BUFFER_INFO csbi;
16197
        handle = _Py_get_osfhandle(fd);
16198
        if (handle == INVALID_HANDLE_VALUE)
16199
            return NULL;
16200
16201
        if (!GetConsoleScreenBufferInfo(handle, &csbi))
16202
            return PyErr_SetFromWindowsErr(0);
16203
16204
        columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
16205
        lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
16206
    }
16207
#endif /* TERMSIZE_USE_CONIO */
16208
16209
0
    PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
16210
0
    termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
16211
0
    if (termsize == NULL)
16212
0
        return NULL;
16213
16214
0
    int pos = 0;
16215
16216
0
#define SET_TERMSIZE(CALL)                                   \
16217
0
    do {                                                     \
16218
0
        PyObject *item = (CALL);                             \
16219
0
        if (item == NULL) {                                  \
16220
0
            Py_DECREF(termsize);                             \
16221
0
            return NULL;                                     \
16222
0
        }                                                    \
16223
0
        PyStructSequence_SET_ITEM(termsize, pos++, item);    \
16224
0
    } while(0)
16225
16226
0
    SET_TERMSIZE(PyLong_FromLong(columns));
16227
0
    SET_TERMSIZE(PyLong_FromLong(lines));
16228
0
#undef SET_TERMSIZE
16229
16230
0
    return termsize;
16231
0
}
16232
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
16233
16234
/*[clinic input]
16235
os.cpu_count
16236
16237
Return the number of logical CPUs in the system.
16238
16239
Return None if indeterminable.
16240
[clinic start generated code]*/
16241
16242
static PyObject *
16243
os_cpu_count_impl(PyObject *module)
16244
/*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/
16245
0
{
16246
0
    const PyConfig *config = _Py_GetConfig();
16247
0
    if (config->cpu_count > 0) {
16248
0
        return PyLong_FromLong(config->cpu_count);
16249
0
    }
16250
16251
0
    int ncpu = 0;
16252
#ifdef MS_WINDOWS
16253
# ifdef MS_WINDOWS_DESKTOP
16254
    ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
16255
# else
16256
    SYSTEM_INFO sysinfo;
16257
    GetSystemInfo(&sysinfo);
16258
    ncpu = sysinfo.dwNumberOfProcessors;
16259
# endif
16260
16261
#elif defined(__hpux)
16262
    ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
16263
16264
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
16265
0
    ncpu = sysconf(_SC_NPROCESSORS_ONLN);
16266
16267
#elif defined(__VXWORKS__)
16268
    ncpu = _Py_popcount32(vxCpuEnabledGet());
16269
16270
#elif defined(__DragonFly__) || \
16271
      defined(__OpenBSD__)   || \
16272
      defined(__FreeBSD__)   || \
16273
      defined(__NetBSD__)    || \
16274
      defined(__APPLE__)
16275
    ncpu = 0;
16276
    size_t len = sizeof(ncpu);
16277
    int mib[2] = {CTL_HW, HW_NCPU};
16278
    if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) {
16279
        ncpu = 0;
16280
    }
16281
#endif
16282
16283
0
    if (ncpu < 1) {
16284
0
        Py_RETURN_NONE;
16285
0
    }
16286
0
    return PyLong_FromLong(ncpu);
16287
0
}
16288
16289
16290
/*[clinic input]
16291
os.get_inheritable -> bool
16292
16293
    fd: int
16294
    /
16295
16296
Get the close-on-exe flag of the specified file descriptor.
16297
[clinic start generated code]*/
16298
16299
static int
16300
os_get_inheritable_impl(PyObject *module, int fd)
16301
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
16302
0
{
16303
0
    int return_value;
16304
0
    _Py_BEGIN_SUPPRESS_IPH
16305
0
    return_value = _Py_get_inheritable(fd);
16306
0
    _Py_END_SUPPRESS_IPH
16307
0
    return return_value;
16308
0
}
16309
16310
16311
/*[clinic input]
16312
os.set_inheritable
16313
    fd: int
16314
    inheritable: int
16315
    /
16316
16317
Set the inheritable flag of the specified file descriptor.
16318
[clinic start generated code]*/
16319
16320
static PyObject *
16321
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
16322
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
16323
0
{
16324
0
    int result;
16325
16326
0
    _Py_BEGIN_SUPPRESS_IPH
16327
0
    result = _Py_set_inheritable(fd, inheritable, NULL);
16328
0
    _Py_END_SUPPRESS_IPH
16329
0
    if (result < 0)
16330
0
        return NULL;
16331
0
    Py_RETURN_NONE;
16332
0
}
16333
16334
16335
#ifdef MS_WINDOWS
16336
#ifndef HANDLE_FLAG_INHERIT
16337
#define HANDLE_FLAG_INHERIT 0x00000001
16338
#endif
16339
16340
/*[clinic input]
16341
os.get_handle_inheritable -> bool
16342
    handle: intptr_t
16343
    /
16344
16345
Get the close-on-exe flag of the specified file descriptor.
16346
[clinic start generated code]*/
16347
16348
static int
16349
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
16350
/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
16351
{
16352
    DWORD flags;
16353
16354
    if (!GetHandleInformation((HANDLE)handle, &flags)) {
16355
        PyErr_SetFromWindowsErr(0);
16356
        return -1;
16357
    }
16358
16359
    return flags & HANDLE_FLAG_INHERIT;
16360
}
16361
16362
16363
/*[clinic input]
16364
os.set_handle_inheritable
16365
    handle: intptr_t
16366
    inheritable: bool
16367
    /
16368
16369
Set the inheritable flag of the specified handle.
16370
[clinic start generated code]*/
16371
16372
static PyObject *
16373
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
16374
                               int inheritable)
16375
/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
16376
{
16377
    DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
16378
    if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
16379
        PyErr_SetFromWindowsErr(0);
16380
        return NULL;
16381
    }
16382
    Py_RETURN_NONE;
16383
}
16384
#endif /* MS_WINDOWS */
16385
16386
/*[clinic input]
16387
os.get_blocking -> bool
16388
    fd: int
16389
    /
16390
16391
Get the blocking mode of the file descriptor.
16392
16393
Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
16394
[clinic start generated code]*/
16395
16396
static int
16397
os_get_blocking_impl(PyObject *module, int fd)
16398
/*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
16399
0
{
16400
0
    int blocking;
16401
16402
0
    _Py_BEGIN_SUPPRESS_IPH
16403
0
    blocking = _Py_get_blocking(fd);
16404
0
    _Py_END_SUPPRESS_IPH
16405
0
    return blocking;
16406
0
}
16407
16408
/*[clinic input]
16409
os.set_blocking
16410
    fd: int
16411
    blocking: bool
16412
    /
16413
16414
Set the blocking mode of the specified file descriptor.
16415
16416
Set the O_NONBLOCK flag if blocking is False,
16417
clear the O_NONBLOCK flag otherwise.
16418
[clinic start generated code]*/
16419
16420
static PyObject *
16421
os_set_blocking_impl(PyObject *module, int fd, int blocking)
16422
/*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/
16423
0
{
16424
0
    int result;
16425
16426
0
    _Py_BEGIN_SUPPRESS_IPH
16427
0
    result = _Py_set_blocking(fd, blocking);
16428
0
    _Py_END_SUPPRESS_IPH
16429
0
    if (result < 0)
16430
0
        return NULL;
16431
0
    Py_RETURN_NONE;
16432
0
}
16433
16434
16435
/*[clinic input]
16436
class os.DirEntry "DirEntry *" "DirEntryType"
16437
class os.ScandirIterator "PyObject *" "ScandirIteratorType"
16438
[clinic start generated code]*/
16439
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b845e502eb4a0406]*/
16440
16441
typedef struct {
16442
    PyObject_HEAD
16443
    PyObject *name;
16444
    PyObject *path;
16445
    PyObject *stat;
16446
    PyObject *lstat;
16447
#ifdef MS_WINDOWS
16448
    struct _Py_stat_struct win32_lstat;
16449
    uint64_t win32_file_index;
16450
    uint64_t win32_file_index_high;
16451
    int got_file_index;
16452
#else /* POSIX */
16453
#ifdef HAVE_DIRENT_D_TYPE
16454
    unsigned char d_type;
16455
#endif
16456
    ino_t d_ino;
16457
    int dir_fd;
16458
#endif
16459
} DirEntry;
16460
16461
105k
#define DirEntry_CAST(op)   ((DirEntry *)(op))
16462
16463
static void
16464
DirEntry_dealloc(PyObject *op)
16465
105k
{
16466
105k
    DirEntry *entry = DirEntry_CAST(op);
16467
105k
    PyTypeObject *tp = Py_TYPE(entry);
16468
105k
    Py_XDECREF(entry->name);
16469
105k
    Py_XDECREF(entry->path);
16470
105k
    Py_XDECREF(entry->stat);
16471
105k
    Py_XDECREF(entry->lstat);
16472
105k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
16473
105k
    free_func(entry);
16474
105k
    Py_DECREF(tp);
16475
105k
}
16476
16477
/* Forward reference */
16478
static int
16479
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16480
                   int follow_symlinks, unsigned short mode_bits);
16481
16482
/*[clinic input]
16483
os.DirEntry.is_symlink -> bool
16484
    defining_class: defining_class
16485
    /
16486
16487
Return True if the entry is a symbolic link; cached per entry.
16488
[clinic start generated code]*/
16489
16490
static int
16491
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
16492
/*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
16493
0
{
16494
#ifdef MS_WINDOWS
16495
    return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16496
#elif defined(HAVE_DIRENT_D_TYPE)
16497
    /* POSIX */
16498
0
    if (self->d_type != DT_UNKNOWN)
16499
0
        return self->d_type == DT_LNK;
16500
0
    else
16501
0
        return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16502
#else
16503
    /* POSIX without d_type */
16504
    return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
16505
#endif
16506
0
}
16507
16508
/*[clinic input]
16509
os.DirEntry.is_junction -> bool
16510
16511
Return True if the entry is a junction; cached per entry.
16512
[clinic start generated code]*/
16513
16514
static int
16515
os_DirEntry_is_junction_impl(DirEntry *self)
16516
/*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/
16517
0
{
16518
#ifdef MS_WINDOWS
16519
    return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
16520
#else
16521
0
    return 0;
16522
0
#endif
16523
0
}
16524
16525
static PyObject *
16526
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
16527
86.9k
{
16528
86.9k
    int result;
16529
86.9k
    STRUCT_STAT st;
16530
86.9k
    PyObject *ub;
16531
16532
#ifdef MS_WINDOWS
16533
    if (!PyUnicode_FSDecoder(self->path, &ub))
16534
        return NULL;
16535
    wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
16536
    Py_DECREF(ub);
16537
#else /* POSIX */
16538
86.9k
    if (!PyUnicode_FSConverter(self->path, &ub))
16539
0
        return NULL;
16540
86.9k
    const char *path = PyBytes_AS_STRING(ub);
16541
86.9k
    if (self->dir_fd != DEFAULT_DIR_FD) {
16542
86.9k
#ifdef HAVE_FSTATAT
16543
86.9k
      if (HAVE_FSTATAT_RUNTIME) {
16544
86.9k
        Py_BEGIN_ALLOW_THREADS
16545
86.9k
        result = fstatat(self->dir_fd, path, &st,
16546
86.9k
                         follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
16547
86.9k
        Py_END_ALLOW_THREADS
16548
86.9k
      } else
16549
16550
0
#endif /* HAVE_FSTATAT */
16551
0
      {
16552
0
        Py_DECREF(ub);
16553
0
        PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
16554
0
        return NULL;
16555
0
      }
16556
86.9k
    }
16557
0
    else
16558
0
#endif
16559
0
    {
16560
0
        Py_BEGIN_ALLOW_THREADS
16561
0
        if (follow_symlinks) {
16562
0
            result = STAT(path, &st);
16563
0
        }
16564
0
        else {
16565
0
            result = LSTAT(path, &st);
16566
0
        }
16567
0
        Py_END_ALLOW_THREADS
16568
0
    }
16569
16570
86.9k
    int saved_errno = errno;
16571
#if defined(MS_WINDOWS)
16572
    PyMem_Free(path);
16573
#else
16574
86.9k
    Py_DECREF(ub);
16575
86.9k
#endif
16576
16577
86.9k
    if (result != 0) {
16578
0
        errno = saved_errno;
16579
0
        path_object_error(self->path);
16580
0
        return NULL;
16581
0
    }
16582
16583
86.9k
    return _pystat_fromstructstat(module, &st);
16584
86.9k
}
16585
16586
static PyObject *
16587
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
16588
86.9k
{
16589
86.9k
    if (!self->lstat) {
16590
86.9k
        PyObject *module = PyType_GetModule(defining_class);
16591
#ifdef MS_WINDOWS
16592
        self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
16593
#else /* POSIX */
16594
86.9k
        self->lstat = DirEntry_fetch_stat(module, self, 0);
16595
86.9k
#endif
16596
86.9k
    }
16597
86.9k
    return Py_XNewRef(self->lstat);
16598
86.9k
}
16599
16600
/*[clinic input]
16601
os.DirEntry.stat
16602
    defining_class: defining_class
16603
    /
16604
    *
16605
    follow_symlinks: bool = True
16606
16607
Return stat_result object for the entry; cached per entry.
16608
[clinic start generated code]*/
16609
16610
static PyObject *
16611
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
16612
                      int follow_symlinks)
16613
/*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
16614
86.9k
{
16615
86.9k
    if (!follow_symlinks) {
16616
86.9k
        return DirEntry_get_lstat(defining_class, self);
16617
86.9k
    }
16618
16619
0
    if (!self->stat) {
16620
0
        int result = os_DirEntry_is_symlink_impl(self, defining_class);
16621
0
        if (result == -1) {
16622
0
            return NULL;
16623
0
        }
16624
0
        if (result) {
16625
0
            PyObject *module = PyType_GetModule(defining_class);
16626
0
            self->stat = DirEntry_fetch_stat(module, self, 1);
16627
0
        }
16628
0
        else {
16629
0
            self->stat = DirEntry_get_lstat(defining_class, self);
16630
0
        }
16631
0
    }
16632
16633
0
    return Py_XNewRef(self->stat);
16634
0
}
16635
16636
/* Set exception and return -1 on error, 0 for False, 1 for True */
16637
static int
16638
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
16639
                   int follow_symlinks, unsigned short mode_bits)
16640
105k
{
16641
105k
    PyObject *stat = NULL;
16642
105k
    PyObject *st_mode = NULL;
16643
105k
    long mode;
16644
105k
    int result;
16645
105k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16646
105k
    int is_symlink;
16647
105k
    int need_stat;
16648
105k
#endif
16649
#ifdef MS_WINDOWS
16650
    unsigned long dir_bits;
16651
#endif
16652
16653
#ifdef MS_WINDOWS
16654
    is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
16655
    need_stat = follow_symlinks && is_symlink;
16656
#elif defined(HAVE_DIRENT_D_TYPE)
16657
105k
    is_symlink = self->d_type == DT_LNK;
16658
105k
    need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
16659
105k
#endif
16660
16661
105k
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16662
105k
    if (need_stat) {
16663
0
#endif
16664
0
        stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
16665
0
        if (!stat) {
16666
0
            if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
16667
                /* If file doesn't exist (anymore), then return False
16668
                   (i.e., say it's not a file/directory) */
16669
0
                PyErr_Clear();
16670
0
                return 0;
16671
0
            }
16672
0
            goto error;
16673
0
        }
16674
0
        _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
16675
0
        st_mode = PyObject_GetAttr(stat, state->st_mode);
16676
0
        if (!st_mode)
16677
0
            goto error;
16678
16679
0
        mode = PyLong_AsLong(st_mode);
16680
0
        if (mode == -1 && PyErr_Occurred())
16681
0
            goto error;
16682
0
        Py_CLEAR(st_mode);
16683
0
        Py_CLEAR(stat);
16684
0
        result = (mode & S_IFMT) == mode_bits;
16685
0
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
16686
0
    }
16687
105k
    else if (is_symlink) {
16688
0
        assert(mode_bits != S_IFLNK);
16689
0
        result = 0;
16690
0
    }
16691
105k
    else {
16692
105k
        assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
16693
#ifdef MS_WINDOWS
16694
        dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
16695
        if (mode_bits == S_IFDIR)
16696
            result = dir_bits != 0;
16697
        else
16698
            result = dir_bits == 0;
16699
#else /* POSIX */
16700
105k
        if (mode_bits == S_IFDIR)
16701
105k
            result = self->d_type == DT_DIR;
16702
0
        else
16703
0
            result = self->d_type == DT_REG;
16704
105k
#endif
16705
105k
    }
16706
105k
#endif
16707
16708
105k
    return result;
16709
16710
0
error:
16711
0
    Py_XDECREF(st_mode);
16712
0
    Py_XDECREF(stat);
16713
0
    return -1;
16714
105k
}
16715
16716
/*[clinic input]
16717
os.DirEntry.is_dir -> bool
16718
    defining_class: defining_class
16719
    /
16720
    *
16721
    follow_symlinks: bool = True
16722
16723
Return True if the entry is a directory; cached per entry.
16724
[clinic start generated code]*/
16725
16726
static int
16727
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
16728
                        int follow_symlinks)
16729
/*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
16730
105k
{
16731
105k
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
16732
105k
}
16733
16734
/*[clinic input]
16735
os.DirEntry.is_file -> bool
16736
    defining_class: defining_class
16737
    /
16738
    *
16739
    follow_symlinks: bool = True
16740
16741
Return True if the entry is a file; cached per entry.
16742
[clinic start generated code]*/
16743
16744
static int
16745
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
16746
                         int follow_symlinks)
16747
/*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
16748
0
{
16749
0
    return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
16750
0
}
16751
16752
/*[clinic input]
16753
os.DirEntry.inode
16754
16755
Return inode of the entry; cached per entry.
16756
[clinic start generated code]*/
16757
16758
static PyObject *
16759
os_DirEntry_inode_impl(DirEntry *self)
16760
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
16761
0
{
16762
#ifdef MS_WINDOWS
16763
    if (!self->got_file_index) {
16764
        PyObject *unicode;
16765
        STRUCT_STAT stat;
16766
        int result;
16767
16768
        if (!PyUnicode_FSDecoder(self->path, &unicode))
16769
            return NULL;
16770
        wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
16771
        Py_DECREF(unicode);
16772
        result = LSTAT(path, &stat);
16773
16774
        int saved_errno = errno;
16775
        PyMem_Free(path);
16776
16777
        if (result != 0) {
16778
            errno = saved_errno;
16779
            return path_object_error(self->path);
16780
        }
16781
16782
        self->win32_file_index = stat.st_ino;
16783
        self->win32_file_index_high = stat.st_ino_high;
16784
        self->got_file_index = 1;
16785
    }
16786
    return _pystat_l128_from_l64_l64(self->win32_file_index, self->win32_file_index_high);
16787
#else /* POSIX */
16788
0
    static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
16789
0
                  "DirEntry.d_ino is larger than unsigned long long");
16790
0
    return PyLong_FromUnsignedLongLong(self->d_ino);
16791
0
#endif
16792
0
}
16793
16794
static PyObject *
16795
DirEntry_repr(PyObject *op)
16796
0
{
16797
0
    DirEntry *self = DirEntry_CAST(op);
16798
0
    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
16799
0
}
16800
16801
/*[clinic input]
16802
os.DirEntry.__fspath__
16803
16804
Returns the path for the entry.
16805
[clinic start generated code]*/
16806
16807
static PyObject *
16808
os_DirEntry___fspath___impl(DirEntry *self)
16809
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
16810
0
{
16811
0
    return Py_NewRef(self->path);
16812
0
}
16813
16814
static PyMemberDef DirEntry_members[] = {
16815
    {"name", Py_T_OBJECT_EX, offsetof(DirEntry, name), Py_READONLY,
16816
     "the entry's base filename, relative to scandir() \"path\" argument"},
16817
    {"path", Py_T_OBJECT_EX, offsetof(DirEntry, path), Py_READONLY,
16818
     "the entry's full path name; equivalent to\nos.path.join(scandir_path, entry.name)"},
16819
    {NULL}
16820
};
16821
16822
#include "clinic/posixmodule.c.h"
16823
16824
static PyMethodDef DirEntry_methods[] = {
16825
    OS_DIRENTRY_IS_DIR_METHODDEF
16826
    OS_DIRENTRY_IS_FILE_METHODDEF
16827
    OS_DIRENTRY_IS_SYMLINK_METHODDEF
16828
    OS_DIRENTRY_IS_JUNCTION_METHODDEF
16829
    OS_DIRENTRY_STAT_METHODDEF
16830
    OS_DIRENTRY_INODE_METHODDEF
16831
    OS_DIRENTRY___FSPATH___METHODDEF
16832
    {"__class_getitem__",       Py_GenericAlias,
16833
    METH_O|METH_CLASS,          PyDoc_STR("DirEntry is generic over the type of the path (str or bytes)")},
16834
    {NULL}
16835
};
16836
16837
static PyType_Slot DirEntryType_slots[] = {
16838
    {Py_tp_dealloc, DirEntry_dealloc},
16839
    {Py_tp_repr, DirEntry_repr},
16840
    {Py_tp_methods, DirEntry_methods},
16841
    {Py_tp_members, DirEntry_members},
16842
    {0, 0},
16843
};
16844
16845
static PyType_Spec DirEntryType_spec = {
16846
    .name = MODNAME ".DirEntry",
16847
    .basicsize = sizeof(DirEntry),
16848
    .flags = (
16849
        Py_TPFLAGS_DEFAULT
16850
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
16851
        | Py_TPFLAGS_IMMUTABLETYPE
16852
    ),
16853
    .slots = DirEntryType_slots
16854
};
16855
16856
16857
#ifdef MS_WINDOWS
16858
16859
static wchar_t *
16860
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename,
16861
                    int normalize)
16862
{
16863
    Py_ssize_t path_len;
16864
    wchar_t *result;
16865
    wchar_t *path_allocated = NULL;
16866
16867
    if (!path_wide) { /* Default arg: "." */
16868
        path_wide = L".";
16869
        path_len = 1;
16870
    }
16871
    else {
16872
        path_len = wcslen(path_wide);
16873
    }
16874
16875
    if (path_len == 0) {
16876
        result = PyMem_New(wchar_t, 1);
16877
        if (result == NULL) {
16878
            PyErr_NoMemory();
16879
            return NULL;
16880
        }
16881
        result[0] = L'\0';
16882
        return result;
16883
    }
16884
16885
    if (normalize && !is_extended_path(path_wide)) {
16886
        int err = _PyOS_getfullpathname(path_wide, &path_allocated);
16887
        if (err < 0) {
16888
            PyErr_SetFromWindowsErr(0);
16889
            return NULL;
16890
        }
16891
        if (path_allocated == NULL) {
16892
            PyErr_NoMemory();
16893
            return NULL;
16894
        }
16895
        path_wide = path_allocated;
16896
        path_len = wcslen(path_wide);
16897
    }
16898
16899
    size_t size = (size_t)path_len + 1 + wcslen(filename) + 1;
16900
    result = PyMem_New(wchar_t, size);
16901
    if (result == NULL) {
16902
        PyMem_RawFree(path_allocated);
16903
        PyErr_NoMemory();
16904
        return NULL;
16905
    }
16906
    wcscpy(result, path_wide);
16907
    wchar_t ch = result[path_len - 1];
16908
    if (ch != SEP && ch != ALTSEP && ch != L':') {
16909
        result[path_len++] = SEP;
16910
    }
16911
    wcscpy(result + path_len, filename);
16912
    PyMem_RawFree(path_allocated);
16913
    return result;
16914
}
16915
16916
static PyObject *
16917
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
16918
{
16919
    DirEntry *entry;
16920
    FILE_BASIC_INFO basic_info;
16921
    FILE_STANDARD_INFO standard_info;
16922
    ULONG reparse_tag;
16923
    wchar_t *joined_path;
16924
16925
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
16926
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
16927
    if (!entry)
16928
        return NULL;
16929
    entry->name = NULL;
16930
    entry->path = NULL;
16931
    entry->stat = NULL;
16932
    entry->lstat = NULL;
16933
    entry->got_file_index = 0;
16934
16935
    entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
16936
    if (!entry->name)
16937
        goto error;
16938
    int return_bytes = path->wide && PyBytes_Check(path->object);
16939
    if (return_bytes) {
16940
        Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
16941
        if (!entry->name)
16942
            goto error;
16943
    }
16944
16945
    joined_path = join_path_filenameW(path->wide, dataW->cFileName, 0);
16946
    if (!joined_path)
16947
        goto error;
16948
16949
    entry->path = PyUnicode_FromWideChar(joined_path, -1);
16950
    PyMem_Free(joined_path);
16951
    if (!entry->path)
16952
        goto error;
16953
    if (return_bytes) {
16954
        Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
16955
        if (!entry->path)
16956
            goto error;
16957
    }
16958
16959
    find_data_to_file_info(dataW, &basic_info, &standard_info, &reparse_tag);
16960
    _Py_attribute_data_to_stat(&standard_info, reparse_tag, &basic_info, NULL, &entry->win32_lstat);
16961
16962
    /* ctime is only deprecated from 3.12, so we copy birthtime across */
16963
    entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
16964
    entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec;
16965
16966
    return (PyObject *)entry;
16967
16968
error:
16969
    Py_DECREF(entry);
16970
    return NULL;
16971
}
16972
16973
#else /* POSIX */
16974
16975
static char *
16976
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
16977
0
{
16978
0
    Py_ssize_t path_len;
16979
0
    Py_ssize_t size;
16980
0
    char *result;
16981
16982
0
    if (!path_narrow) { /* Default arg: "." */
16983
0
        path_narrow = ".";
16984
0
        path_len = 1;
16985
0
    }
16986
0
    else {
16987
0
        path_len = strlen(path_narrow);
16988
0
    }
16989
16990
0
    if (filename_len == -1)
16991
0
        filename_len = strlen(filename);
16992
16993
    /* The +1's are for the path separator and the NUL */
16994
0
    size = path_len + 1 + filename_len + 1;
16995
0
    result = PyMem_New(char, size);
16996
0
    if (!result) {
16997
0
        PyErr_NoMemory();
16998
0
        return NULL;
16999
0
    }
17000
0
    strcpy(result, path_narrow);
17001
0
    if (path_len > 0 && result[path_len - 1] != '/')
17002
0
        result[path_len++] = '/';
17003
0
    strcpy(result + path_len, filename);
17004
0
    return result;
17005
0
}
17006
17007
static PyObject *
17008
DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
17009
                         Py_ssize_t name_len, ino_t d_ino
17010
#ifdef HAVE_DIRENT_D_TYPE
17011
                         , unsigned char d_type
17012
#endif
17013
                         )
17014
105k
{
17015
105k
    DirEntry *entry;
17016
105k
    char *joined_path;
17017
17018
105k
    PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
17019
105k
    entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
17020
105k
    if (!entry)
17021
0
        return NULL;
17022
105k
    entry->name = NULL;
17023
105k
    entry->path = NULL;
17024
105k
    entry->stat = NULL;
17025
105k
    entry->lstat = NULL;
17026
17027
105k
    if (path->is_fd) {
17028
105k
        entry->dir_fd = path->fd;
17029
105k
        joined_path = NULL;
17030
105k
    }
17031
0
    else {
17032
0
        entry->dir_fd = DEFAULT_DIR_FD;
17033
0
        joined_path = join_path_filename(path->narrow, name, name_len);
17034
0
        if (!joined_path)
17035
0
            goto error;
17036
0
    }
17037
17038
105k
    if (!path->narrow || !PyBytes_Check(path->object)) {
17039
105k
        entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
17040
105k
        if (joined_path)
17041
0
            entry->path = PyUnicode_DecodeFSDefault(joined_path);
17042
105k
    }
17043
0
    else {
17044
0
        entry->name = PyBytes_FromStringAndSize(name, name_len);
17045
0
        if (joined_path)
17046
0
            entry->path = PyBytes_FromString(joined_path);
17047
0
    }
17048
105k
    PyMem_Free(joined_path);
17049
105k
    if (!entry->name)
17050
0
        goto error;
17051
17052
105k
    if (path->is_fd) {
17053
105k
        entry->path = Py_NewRef(entry->name);
17054
105k
    }
17055
0
    else if (!entry->path)
17056
0
        goto error;
17057
17058
105k
#ifdef HAVE_DIRENT_D_TYPE
17059
105k
    entry->d_type = d_type;
17060
105k
#endif
17061
105k
    entry->d_ino = d_ino;
17062
17063
105k
    return (PyObject *)entry;
17064
17065
0
error:
17066
0
    Py_XDECREF(entry);
17067
0
    return NULL;
17068
105k
}
17069
17070
#endif
17071
17072
17073
typedef struct {
17074
    PyObject_HEAD
17075
    path_t path;
17076
#ifdef MS_WINDOWS
17077
    HANDLE handle;
17078
    WIN32_FIND_DATAW file_data;
17079
    int first_time;
17080
#else /* POSIX */
17081
    DIR *dirp;
17082
#endif
17083
#ifdef HAVE_FDOPENDIR
17084
    int fd;
17085
#endif
17086
    // Sharing the iterator between threads is subject to race conditions:
17087
    // which entries each thread receives is unspecified.  It must not
17088
    // corrupt the iterator or crash.  Since we don't want close() to be
17089
    // held up by a blocking directory read, we set the 'closed' flag if
17090
    // there are reads in progress.
17091
    PyMutex read_mutex;
17092
    uint8_t closed;
17093
} ScandirIterator;
17094
17095
378k
#define ScandirIterator_CAST(op)    ((ScandirIterator *)(op))
17096
17097
#ifdef MS_WINDOWS
17098
17099
static int
17100
ScandirIterator_is_closed(ScandirIterator *iterator)
17101
{
17102
    return _Py_atomic_load_uint8(&iterator->closed);
17103
}
17104
17105
static void
17106
ScandirIterator_closedir(ScandirIterator *iterator)
17107
{
17108
    HANDLE handle = INVALID_HANDLE_VALUE;
17109
17110
    _Py_atomic_store_uint8(&iterator->closed, 1);
17111
    if (PyMutex_LockFast(&iterator->read_mutex)) {
17112
        // no reads in progress, we can close the handle
17113
        handle = iterator->handle;
17114
        iterator->handle = INVALID_HANDLE_VALUE;
17115
        PyMutex_Unlock(&iterator->read_mutex);
17116
    }
17117
17118
    if (handle != INVALID_HANDLE_VALUE) {
17119
        Py_BEGIN_ALLOW_THREADS
17120
        FindClose(handle);
17121
        Py_END_ALLOW_THREADS
17122
    }
17123
}
17124
17125
static PyObject *
17126
ScandirIterator_iternext(PyObject *op)
17127
{
17128
    ScandirIterator *iterator = ScandirIterator_CAST(op);
17129
    WIN32_FIND_DATAW file_data;
17130
    BOOL success;
17131
    DWORD error = ERROR_SUCCESS;
17132
    int found = 0;
17133
17134
    PyMutex_Lock(&iterator->read_mutex);
17135
    /* Happens if the iterator is iterated twice, or closed explicitly */
17136
    while (iterator->handle != INVALID_HANDLE_VALUE &&
17137
           !_Py_atomic_load_uint8_relaxed(&iterator->closed))
17138
    {
17139
        if (!iterator->first_time) {
17140
            Py_BEGIN_ALLOW_THREADS
17141
            success = FindNextFileW(iterator->handle, &iterator->file_data);
17142
            if (!success) {
17143
                error = GetLastError();
17144
            }
17145
            Py_END_ALLOW_THREADS
17146
            if (!success) {
17147
                break;
17148
            }
17149
        }
17150
        iterator->first_time = 0;
17151
17152
        /* Skip over . and .. */
17153
        if (wcscmp(iterator->file_data.cFileName, L".") != 0 &&
17154
            wcscmp(iterator->file_data.cFileName, L"..") != 0)
17155
        {
17156
            file_data = iterator->file_data;
17157
            found = 1;
17158
            break;
17159
        }
17160
17161
        /* Loop till we get a non-dot directory or finish iterating */
17162
    }
17163
    PyMutex_Unlock(&iterator->read_mutex);
17164
17165
    if (found && ScandirIterator_is_closed(iterator)) {
17166
        ScandirIterator_closedir(iterator); // deferred close
17167
    }
17168
17169
    if (found) {
17170
        PyObject *module = PyType_GetModule(Py_TYPE(iterator));
17171
        PyObject *entry = DirEntry_from_find_data(module, &iterator->path, &file_data);
17172
        if (entry != NULL) {
17173
            return entry;
17174
        }
17175
    }
17176
    else if (error != ERROR_SUCCESS && error != ERROR_NO_MORE_FILES) {
17177
        SetLastError(error);
17178
        path_error(&iterator->path);
17179
    }
17180
17181
    /* Error or no more files */
17182
    ScandirIterator_closedir(iterator);
17183
    return NULL;
17184
}
17185
17186
#else /* POSIX */
17187
17188
static int
17189
ScandirIterator_is_closed(ScandirIterator *iterator)
17190
196k
{
17191
196k
    return _Py_atomic_load_uint8(&iterator->closed);
17192
196k
}
17193
17194
static void
17195
ScandirIterator_closedir(ScandirIterator *iterator)
17196
273k
{
17197
273k
    DIR *dirp = NULL;
17198
17199
273k
    _Py_atomic_store_uint8(&iterator->closed, 1);
17200
273k
    if (PyMutex_LockFast(&iterator->read_mutex)) {
17201
        // no reads in progress, we can close dirp
17202
273k
        dirp = iterator->dirp;
17203
273k
        iterator->dirp = NULL;
17204
273k
        PyMutex_Unlock(&iterator->read_mutex);
17205
273k
    }
17206
17207
273k
    if (dirp != NULL) {
17208
91.0k
        Py_BEGIN_ALLOW_THREADS
17209
91.0k
#ifdef HAVE_FDOPENDIR
17210
91.0k
        if (iterator->path.is_fd) {
17211
91.0k
            rewinddir(dirp);
17212
91.0k
        }
17213
91.0k
#endif
17214
91.0k
        closedir(dirp);
17215
91.0k
        Py_END_ALLOW_THREADS
17216
91.0k
    }
17217
273k
}
17218
17219
static PyObject *
17220
ScandirIterator_iternext(PyObject *op)
17221
196k
{
17222
196k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
17223
196k
    struct dirent *direntp;
17224
196k
    Py_ssize_t name_len = 0;
17225
196k
    int is_dot;
17226
196k
    int found = 0;
17227
196k
    int error = 0;
17228
196k
    int no_memory = 0;
17229
196k
    char namebuf[256];
17230
196k
    char *name = namebuf;
17231
196k
    ino_t d_ino = 0;
17232
196k
#ifdef HAVE_DIRENT_D_TYPE
17233
196k
    unsigned char d_type = 0;
17234
196k
#endif
17235
17236
196k
    PyMutex_Lock(&iterator->read_mutex);
17237
    /* Happens if the iterator is iterated twice, or closed explicitly */
17238
378k
    while (iterator->dirp != NULL &&
17239
378k
           !_Py_atomic_load_uint8_relaxed(&iterator->closed))
17240
378k
    {
17241
378k
        Py_BEGIN_ALLOW_THREADS
17242
378k
        errno = 0;
17243
378k
        direntp = readdir(iterator->dirp);
17244
378k
        if (direntp == NULL) {
17245
91.0k
            error = errno;
17246
91.0k
        }
17247
378k
        Py_END_ALLOW_THREADS
17248
17249
378k
        if (!direntp) {
17250
91.0k
            break;
17251
91.0k
        }
17252
17253
        /* Skip over . and .. */
17254
287k
        name_len = NAMLEN(direntp);
17255
287k
        is_dot = direntp->d_name[0] == '.' &&
17256
183k
                 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
17257
287k
        if (!is_dot) {
17258
105k
            if ((size_t)name_len >= sizeof(namebuf)) {
17259
0
                name = PyMem_RawMalloc(name_len + 1);
17260
0
                if (name == NULL) {
17261
0
                    no_memory = 1;
17262
0
                    break;
17263
0
                }
17264
0
            }
17265
105k
            memcpy(name, direntp->d_name, name_len);
17266
105k
            name[name_len] = '\0';
17267
105k
            d_ino = direntp->d_ino;
17268
105k
#ifdef HAVE_DIRENT_D_TYPE
17269
105k
            d_type = direntp->d_type;
17270
105k
#endif
17271
105k
            found = 1;
17272
105k
            break;
17273
105k
        }
17274
17275
        /* Loop till we get a non-dot directory or finish iterating */
17276
287k
    }
17277
196k
    PyMutex_Unlock(&iterator->read_mutex);
17278
17279
196k
    if (found && ScandirIterator_is_closed(iterator)) {
17280
0
        ScandirIterator_closedir(iterator); // deferred close
17281
0
    }
17282
17283
196k
    if (found) {
17284
105k
        PyObject *module = PyType_GetModule(Py_TYPE(iterator));
17285
105k
        PyObject *entry = DirEntry_from_posix_info(module,
17286
105k
                                                   &iterator->path, name,
17287
105k
                                                   name_len, d_ino
17288
105k
#ifdef HAVE_DIRENT_D_TYPE
17289
105k
                                                   , d_type
17290
105k
#endif
17291
105k
                                                  );
17292
105k
        if (name != namebuf) {
17293
0
            PyMem_RawFree(name);
17294
0
        }
17295
105k
        if (entry != NULL) {
17296
105k
            return entry;
17297
105k
        }
17298
105k
    }
17299
91.0k
    else if (no_memory) {
17300
0
        PyErr_NoMemory();
17301
0
    }
17302
91.0k
    else if (error != 0) {
17303
0
        errno = error;
17304
0
        path_error(&iterator->path);
17305
0
    }
17306
17307
    /* Error or no more files */
17308
91.0k
    ScandirIterator_closedir(iterator);
17309
91.0k
    return NULL;
17310
196k
}
17311
17312
#endif
17313
17314
static PyObject *
17315
ScandirIterator_close(PyObject *op, PyObject *Py_UNUSED(dummy))
17316
0
{
17317
0
    ScandirIterator *self = ScandirIterator_CAST(op);
17318
0
    ScandirIterator_closedir(self);
17319
0
    Py_RETURN_NONE;
17320
0
}
17321
17322
static PyObject *
17323
ScandirIterator_enter(PyObject *self, PyObject *Py_UNUSED(dummy))
17324
91.0k
{
17325
91.0k
    return Py_NewRef(self);
17326
91.0k
}
17327
17328
/*[clinic input]
17329
os.ScandirIterator.__exit__
17330
17331
    *exc_info: array
17332
17333
Close the scandir iterator.
17334
[clinic start generated code]*/
17335
17336
static PyObject *
17337
os_ScandirIterator___exit___impl(PyObject *self, PyObject * const *exc_info,
17338
                                 Py_ssize_t exc_info_length)
17339
/*[clinic end generated code: output=5d3941725a7c97c7 input=ff3ffe83ae605a36]*/
17340
91.0k
{
17341
91.0k
    ScandirIterator_closedir(ScandirIterator_CAST(self));
17342
91.0k
    Py_RETURN_NONE;
17343
91.0k
}
17344
17345
static void
17346
ScandirIterator_finalize(PyObject *op)
17347
91.0k
{
17348
91.0k
    ScandirIterator *iterator = ScandirIterator_CAST(op);
17349
    /* Save the current exception, if any. */
17350
91.0k
    PyObject *exc = PyErr_GetRaisedException();
17351
17352
91.0k
    int was_closed = ScandirIterator_is_closed(iterator);
17353
17354
91.0k
    ScandirIterator_closedir(iterator);
17355
17356
91.0k
    if (!was_closed) {
17357
0
        if (PyErr_ResourceWarning(op, 1,
17358
0
                                  "unclosed scandir iterator %R", iterator))
17359
0
        {
17360
            /* Spurious errors can appear at shutdown */
17361
0
            if (PyErr_ExceptionMatches(PyExc_Warning)) {
17362
0
                PyErr_FormatUnraisable("Exception ignored while finalizing "
17363
0
                                       "scandir iterator %R", iterator);
17364
0
            }
17365
0
        }
17366
0
    }
17367
17368
91.0k
    path_cleanup(&iterator->path);
17369
17370
    /* Restore the saved exception. */
17371
91.0k
    PyErr_SetRaisedException(exc);
17372
91.0k
}
17373
17374
static void
17375
ScandirIterator_dealloc(PyObject *op)
17376
91.0k
{
17377
91.0k
    PyTypeObject *tp = Py_TYPE(op);
17378
91.0k
    if (PyObject_CallFinalizerFromDealloc(op) < 0)
17379
0
        return;
17380
17381
91.0k
    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
17382
91.0k
    free_func(op);
17383
91.0k
    Py_DECREF(tp);
17384
91.0k
}
17385
17386
static PyMethodDef ScandirIterator_methods[] = {
17387
    {"__enter__", ScandirIterator_enter, METH_NOARGS},
17388
    OS_SCANDIRITERATOR___EXIT___METHODDEF
17389
    {"close", ScandirIterator_close, METH_NOARGS},
17390
    {NULL}
17391
};
17392
17393
static PyType_Slot ScandirIteratorType_slots[] = {
17394
    {Py_tp_dealloc, ScandirIterator_dealloc},
17395
    {Py_tp_finalize, ScandirIterator_finalize},
17396
    {Py_tp_iter, PyObject_SelfIter},
17397
    {Py_tp_iternext, ScandirIterator_iternext},
17398
    {Py_tp_methods, ScandirIterator_methods},
17399
    {0, 0},
17400
};
17401
17402
static PyType_Spec ScandirIteratorType_spec = {
17403
    .name = MODNAME ".ScandirIterator",
17404
    .basicsize = sizeof(ScandirIterator),
17405
    // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
17406
    // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
17407
    .flags = (
17408
        Py_TPFLAGS_DEFAULT
17409
        | Py_TPFLAGS_HAVE_FINALIZE
17410
        | Py_TPFLAGS_DISALLOW_INSTANTIATION
17411
        | Py_TPFLAGS_IMMUTABLETYPE
17412
    ),
17413
    .slots = ScandirIteratorType_slots
17414
};
17415
17416
/*[clinic input]
17417
os.scandir
17418
17419
    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
17420
17421
Return an iterator of DirEntry objects for given path.
17422
17423
path can be specified as either str, bytes, or a path-like object.  If
17424
path is bytes, the names of yielded DirEntry objects will also be bytes;
17425
in all other circumstances they will be str.
17426
17427
If path is None, uses the path='.'.
17428
[clinic start generated code]*/
17429
17430
static PyObject *
17431
os_scandir_impl(PyObject *module, path_t *path)
17432
/*[clinic end generated code: output=6eb2668b675ca89e input=6ab9600993f51577]*/
17433
91.0k
{
17434
91.0k
    ScandirIterator *iterator;
17435
#ifdef MS_WINDOWS
17436
    wchar_t *path_strW;
17437
#else
17438
91.0k
    const char *path_str;
17439
91.0k
#ifdef HAVE_FDOPENDIR
17440
91.0k
    int fd = -1;
17441
91.0k
#endif
17442
91.0k
#endif
17443
17444
91.0k
    if (PySys_Audit("os.scandir", "O",
17445
91.0k
                    path->object ? path->object : Py_None) < 0) {
17446
0
        return NULL;
17447
0
    }
17448
17449
91.0k
    PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
17450
91.0k
    iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
17451
91.0k
    if (!iterator)
17452
0
        return NULL;
17453
17454
91.0k
    iterator->read_mutex = (PyMutex){0};
17455
91.0k
    iterator->closed = 1;
17456
#ifdef MS_WINDOWS
17457
    iterator->handle = INVALID_HANDLE_VALUE;
17458
#else
17459
91.0k
    iterator->dirp = NULL;
17460
91.0k
#endif
17461
17462
    /* Move the ownership to iterator->path */
17463
91.0k
    memcpy(&iterator->path, path, sizeof(path_t));
17464
91.0k
    memset(path, 0, sizeof(path_t));
17465
17466
#ifdef MS_WINDOWS
17467
    iterator->first_time = 1;
17468
17469
    path_strW = join_path_filenameW(iterator->path.wide, L"*.*", 1);
17470
    if (!path_strW)
17471
        goto error;
17472
17473
    Py_BEGIN_ALLOW_THREADS
17474
    iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
17475
    Py_END_ALLOW_THREADS
17476
17477
    if (iterator->handle == INVALID_HANDLE_VALUE) {
17478
        path_error(&iterator->path);
17479
        PyMem_Free(path_strW);
17480
        goto error;
17481
    }
17482
    PyMem_Free(path_strW);
17483
#else /* POSIX */
17484
91.0k
    errno = 0;
17485
91.0k
#ifdef HAVE_FDOPENDIR
17486
91.0k
    if (iterator->path.is_fd) {
17487
91.0k
      if (HAVE_FDOPENDIR_RUNTIME) {
17488
        /* closedir() closes the FD, so we duplicate it */
17489
91.0k
        fd = _Py_dup(iterator->path.fd);
17490
91.0k
        if (fd == -1)
17491
0
            goto error;
17492
17493
91.0k
        Py_BEGIN_ALLOW_THREADS
17494
91.0k
        iterator->dirp = fdopendir(fd);
17495
91.0k
        Py_END_ALLOW_THREADS
17496
91.0k
      } else {
17497
0
        PyErr_SetString(PyExc_TypeError,
17498
0
            "scandir: path should be string, bytes, os.PathLike or None, not int");
17499
0
        return NULL;
17500
0
      }
17501
91.0k
    }
17502
0
    else
17503
0
#endif
17504
0
    {
17505
0
        if (iterator->path.narrow)
17506
0
            path_str = iterator->path.narrow;
17507
0
        else
17508
0
            path_str = ".";
17509
17510
0
        Py_BEGIN_ALLOW_THREADS
17511
0
        iterator->dirp = opendir(path_str);
17512
0
        Py_END_ALLOW_THREADS
17513
0
    }
17514
17515
91.0k
    if (!iterator->dirp) {
17516
0
        path_error(&iterator->path);
17517
0
#ifdef HAVE_FDOPENDIR
17518
0
        if (fd != -1) {
17519
0
            Py_BEGIN_ALLOW_THREADS
17520
0
            close(fd);
17521
0
            Py_END_ALLOW_THREADS
17522
0
        }
17523
0
#endif
17524
0
        goto error;
17525
0
    }
17526
91.0k
#endif
17527
17528
91.0k
    iterator->closed = 0;
17529
91.0k
    return (PyObject *)iterator;
17530
17531
0
error:
17532
0
    Py_DECREF(iterator);
17533
0
    return NULL;
17534
91.0k
}
17535
17536
/*
17537
    Return the file system path representation of the object.
17538
17539
    If the object is str or bytes, then allow it to pass through with
17540
    an incremented refcount. If the object defines __fspath__(), then
17541
    return the result of that method. All other types raise a TypeError.
17542
*/
17543
PyObject *
17544
PyOS_FSPath(PyObject *path)
17545
928k
{
17546
    /* For error message reasons, this function is manually inlined in
17547
       path_converter(). */
17548
928k
    PyObject *func = NULL;
17549
928k
    PyObject *path_repr = NULL;
17550
17551
928k
    if (PyUnicode_Check(path) || PyBytes_Check(path)) {
17552
927k
        return Py_NewRef(path);
17553
927k
    }
17554
17555
425
    func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
17556
425
    if ((NULL == func) || (func == Py_None)) {
17557
0
        return PyErr_Format(PyExc_TypeError,
17558
0
                            "expected str, bytes or os.PathLike object, "
17559
0
                            "not %.200s",
17560
0
                            _PyType_Name(Py_TYPE(path)));
17561
0
    }
17562
17563
425
    path_repr = _PyObject_CallNoArgs(func);
17564
425
    Py_DECREF(func);
17565
425
    if (NULL == path_repr) {
17566
0
        return NULL;
17567
0
    }
17568
17569
425
    if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
17570
0
        PyErr_Format(PyExc_TypeError,
17571
0
                     "expected %.200s.__fspath__() to return str or bytes, "
17572
0
                     "not %.200s", _PyType_Name(Py_TYPE(path)),
17573
0
                     _PyType_Name(Py_TYPE(path_repr)));
17574
0
        Py_DECREF(path_repr);
17575
0
        return NULL;
17576
0
    }
17577
17578
425
    return path_repr;
17579
425
}
17580
17581
/*[clinic input]
17582
os.fspath
17583
17584
    path: object
17585
17586
Return the file system path representation of the object.
17587
17588
If the object is str or bytes, then allow it to pass through as-is.  If
17589
the object defines __fspath__(), then return the result of that method.
17590
All other types raise a TypeError.
17591
[clinic start generated code]*/
17592
17593
static PyObject *
17594
os_fspath_impl(PyObject *module, PyObject *path)
17595
/*[clinic end generated code: output=c3c3b78ecff2914f input=d3c54404240d5da0]*/
17596
675k
{
17597
675k
    return PyOS_FSPath(path);
17598
675k
}
17599
17600
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
17601
/*[clinic input]
17602
os.getrandom
17603
17604
    size: Py_ssize_t
17605
    flags: unsigned_int(bitwise=True) = 0
17606
17607
Obtain a series of random bytes.
17608
[clinic start generated code]*/
17609
17610
static PyObject *
17611
os_getrandom_impl(PyObject *module, Py_ssize_t size, unsigned int flags)
17612
/*[clinic end generated code: output=c2163c05f0e1d0a1 input=e0174983f5703f82]*/
17613
0
{
17614
0
    if (size < 0) {
17615
0
        errno = EINVAL;
17616
0
        return posix_error();
17617
0
    }
17618
17619
0
    PyBytesWriter *writer = PyBytesWriter_Create(size);
17620
0
    if (writer == NULL) {
17621
0
        return NULL;
17622
0
    }
17623
0
    void *data = PyBytesWriter_GetData(writer);
17624
17625
0
    Py_ssize_t n;
17626
0
    while (1) {
17627
0
#ifdef HAVE_GETRANDOM
17628
0
        n = getrandom(data, size, flags);
17629
#else
17630
        n = syscall(SYS_getrandom, data, size, flags);
17631
#endif
17632
0
        if (n < 0 && errno == EINTR) {
17633
0
            if (PyErr_CheckSignals() < 0) {
17634
0
                goto error;
17635
0
            }
17636
17637
            /* getrandom() was interrupted by a signal: retry */
17638
0
            continue;
17639
0
        }
17640
0
        break;
17641
0
    }
17642
17643
0
    if (n < 0) {
17644
0
        PyErr_SetFromErrno(PyExc_OSError);
17645
0
        goto error;
17646
0
    }
17647
17648
0
    _Py_MSAN_UNPOISON(data, size);
17649
17650
0
    return PyBytesWriter_FinishWithSize(writer, n);
17651
17652
0
error:
17653
0
    PyBytesWriter_Discard(writer);
17654
0
    return NULL;
17655
0
}
17656
#endif   /* HAVE_GETRANDOM_SYSCALL */
17657
17658
#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
17659
17660
/* bpo-36085: Helper functions for managing DLL search directories
17661
 * on win32
17662
 */
17663
17664
/*[clinic input]
17665
os._add_dll_directory
17666
17667
    path: path_t
17668
17669
Add a path to the DLL search path.
17670
17671
This search path is used when resolving dependencies for imported
17672
extension modules (the module itself is resolved through sys.path),
17673
and also by ctypes.
17674
17675
Returns an opaque value that may be passed to os.remove_dll_directory
17676
to remove this directory from the search path.
17677
[clinic start generated code]*/
17678
17679
static PyObject *
17680
os__add_dll_directory_impl(PyObject *module, path_t *path)
17681
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
17682
{
17683
    DLL_DIRECTORY_COOKIE cookie = 0;
17684
    DWORD err = 0;
17685
17686
    if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
17687
        return NULL;
17688
    }
17689
17690
    Py_BEGIN_ALLOW_THREADS
17691
    if (!(cookie = AddDllDirectory(path->wide))) {
17692
        err = GetLastError();
17693
    }
17694
    Py_END_ALLOW_THREADS
17695
17696
    if (err) {
17697
        return win32_error_object_err("add_dll_directory",
17698
                                      path->object, err);
17699
    }
17700
17701
    return PyCapsule_New(cookie, "DLL directory cookie", NULL);
17702
}
17703
17704
/*[clinic input]
17705
os._remove_dll_directory
17706
17707
    cookie: object
17708
17709
Removes a path from the DLL search path.
17710
17711
The parameter is an opaque value that was returned from
17712
os.add_dll_directory. You can only remove directories that you added
17713
yourself.
17714
[clinic start generated code]*/
17715
17716
static PyObject *
17717
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
17718
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
17719
{
17720
    DLL_DIRECTORY_COOKIE cookieValue;
17721
    DWORD err = 0;
17722
17723
    if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
17724
        PyErr_SetString(PyExc_TypeError,
17725
            "Provided cookie was not returned from os.add_dll_directory");
17726
        return NULL;
17727
    }
17728
17729
    cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
17730
        cookie, "DLL directory cookie");
17731
17732
    Py_BEGIN_ALLOW_THREADS
17733
    if (!RemoveDllDirectory(cookieValue)) {
17734
        err = GetLastError();
17735
    }
17736
    Py_END_ALLOW_THREADS
17737
17738
    if (err) {
17739
        return win32_error_object_err("remove_dll_directory",
17740
                                      NULL, err);
17741
    }
17742
17743
    if (PyCapsule_SetName(cookie, NULL)) {
17744
        return NULL;
17745
    }
17746
17747
    Py_RETURN_NONE;
17748
}
17749
17750
#endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */
17751
17752
17753
/* Only check if WIFEXITED is available: expect that it comes
17754
   with WEXITSTATUS, WIFSIGNALED, etc.
17755
17756
   os.waitstatus_to_exitcode() is implemented in C and not in Python, so
17757
   subprocess can safely call it during late Python finalization without
17758
   risking that used os attributes were set to None by finalize_modules(). */
17759
#if defined(WIFEXITED) || defined(MS_WINDOWS)
17760
/*[clinic input]
17761
os.waitstatus_to_exitcode
17762
17763
    status as status_obj: object
17764
17765
Convert a wait status to an exit code.
17766
17767
On Unix:
17768
17769
* If WIFEXITED(status) is true, return WEXITSTATUS(status).
17770
* If WIFSIGNALED(status) is true, return -WTERMSIG(status).
17771
* Otherwise, raise a ValueError.
17772
17773
On Windows, return status shifted right by 8 bits.
17774
17775
On Unix, if the process is being traced or if waitpid() was called with
17776
WUNTRACED option, the caller must first check if WIFSTOPPED(status) is
17777
true.  This function must not be called if WIFSTOPPED(status) is true.
17778
[clinic start generated code]*/
17779
17780
static PyObject *
17781
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
17782
/*[clinic end generated code: output=db50b1b0ba3c7153 input=3b44a23f5090006c]*/
17783
0
{
17784
0
#ifndef MS_WINDOWS
17785
0
    int status = PyLong_AsInt(status_obj);
17786
0
    if (status == -1 && PyErr_Occurred()) {
17787
0
        return NULL;
17788
0
    }
17789
17790
0
    WAIT_TYPE wait_status;
17791
0
    WAIT_STATUS_INT(wait_status) = status;
17792
0
    int exitcode;
17793
0
    if (WIFEXITED(wait_status)) {
17794
0
        exitcode = WEXITSTATUS(wait_status);
17795
        /* Sanity check to provide warranty on the function behavior.
17796
           It should not occur in practice */
17797
0
        if (exitcode < 0) {
17798
0
            PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
17799
0
            return NULL;
17800
0
        }
17801
0
    }
17802
0
    else if (WIFSIGNALED(wait_status)) {
17803
0
        int signum = WTERMSIG(wait_status);
17804
        /* Sanity check to provide warranty on the function behavior.
17805
           It should not occurs in practice */
17806
0
        if (signum <= 0) {
17807
0
            PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
17808
0
            return NULL;
17809
0
        }
17810
0
        exitcode = -signum;
17811
0
    } else if (WIFSTOPPED(wait_status)) {
17812
        /* Status only received if the process is being traced
17813
           or if waitpid() was called with WUNTRACED option. */
17814
0
        int signum = WSTOPSIG(wait_status);
17815
0
        PyErr_Format(PyExc_ValueError,
17816
0
                     "process stopped by delivery of signal %i",
17817
0
                     signum);
17818
0
        return NULL;
17819
0
    }
17820
0
    else {
17821
0
        PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
17822
0
        return NULL;
17823
0
    }
17824
0
    return PyLong_FromLong(exitcode);
17825
#else
17826
    /* Windows implementation: see os.waitpid() implementation
17827
       which uses _cwait(). */
17828
    unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
17829
    if (status == (unsigned long long)-1 && PyErr_Occurred()) {
17830
        return NULL;
17831
    }
17832
17833
    unsigned long long exitcode = (status >> 8);
17834
    /* ExitProcess() accepts an UINT type:
17835
       reject exit code which doesn't fit in an UINT */
17836
    if (exitcode > UINT_MAX) {
17837
        PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
17838
        return NULL;
17839
    }
17840
    return PyLong_FromUnsignedLong((unsigned long)exitcode);
17841
#endif
17842
0
}
17843
#endif
17844
17845
#if defined(MS_WINDOWS)
17846
/*[clinic input]
17847
os._supports_virtual_terminal
17848
17849
Checks if virtual terminal is supported in windows
17850
[clinic start generated code]*/
17851
17852
static PyObject *
17853
os__supports_virtual_terminal_impl(PyObject *module)
17854
/*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/
17855
{
17856
#ifdef HAVE_WINDOWS_CONSOLE_IO
17857
    DWORD mode = 0;
17858
    HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
17859
    if (!GetConsoleMode(handle, &mode)) {
17860
        Py_RETURN_FALSE;
17861
    }
17862
    return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING);
17863
#else
17864
    Py_RETURN_FALSE;
17865
#endif /* HAVE_WINDOWS_CONSOLE_IO */
17866
}
17867
#endif
17868
17869
/*[clinic input]
17870
os._inputhook
17871
17872
Calls PyOS_InputHook dropping the GIL first
17873
[clinic start generated code]*/
17874
17875
static PyObject *
17876
os__inputhook_impl(PyObject *module)
17877
/*[clinic end generated code: output=525aca4ef3c6149f input=b5018fa1ec3aa440]*/
17878
0
{
17879
0
     int result = 0;
17880
0
     if (PyOS_InputHook) {
17881
0
         Py_BEGIN_ALLOW_THREADS;
17882
0
         result = PyOS_InputHook();
17883
0
         Py_END_ALLOW_THREADS;
17884
0
     }
17885
0
     return PyLong_FromLong(result);
17886
0
}
17887
17888
/*[clinic input]
17889
os._is_inputhook_installed
17890
17891
Checks if PyOS_InputHook is set
17892
[clinic start generated code]*/
17893
17894
static PyObject *
17895
os__is_inputhook_installed_impl(PyObject *module)
17896
/*[clinic end generated code: output=3b3eab4f672c689a input=757820f79f48820c]*/
17897
0
{
17898
0
    return PyBool_FromLong(PyOS_InputHook != NULL);
17899
0
}
17900
17901
/*[clinic input]
17902
os._create_environ
17903
17904
Create the environment dictionary.
17905
[clinic start generated code]*/
17906
17907
static PyObject *
17908
os__create_environ_impl(PyObject *module)
17909
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
17910
0
{
17911
0
    return convertenviron();
17912
0
}
17913
17914
17915
#ifdef __EMSCRIPTEN__
17916
/*[clinic input]
17917
os._emscripten_debugger
17918
17919
Create a breakpoint for the JavaScript debugger. Emscripten only.
17920
[clinic start generated code]*/
17921
17922
static PyObject *
17923
os__emscripten_debugger_impl(PyObject *module)
17924
/*[clinic end generated code: output=ad47dc3bf0661343 input=d814b1877fb6083a]*/
17925
{
17926
    emscripten_debugger();
17927
    Py_RETURN_NONE;
17928
}
17929
17930
EM_JS(void, emscripten_log_impl_js, (const char* arg), {
17931
    console.warn(UTF8ToString(arg));
17932
});
17933
17934
/*[clinic input]
17935
os._emscripten_log
17936
   arg: str
17937
17938
Log something to the JS console. Emscripten only.
17939
[clinic start generated code]*/
17940
17941
static PyObject *
17942
os__emscripten_log_impl(PyObject *module, const char *arg)
17943
/*[clinic end generated code: output=9749e5e293c42784 input=350aa1f70bc1e905]*/
17944
{
17945
    emscripten_log_impl_js(arg);
17946
    Py_RETURN_NONE;
17947
}
17948
#endif /* __EMSCRIPTEN__ */
17949
17950
17951
static PyMethodDef posix_methods[] = {
17952
    OS_STAT_METHODDEF
17953
    OS_STATX_METHODDEF
17954
    OS_ACCESS_METHODDEF
17955
    OS_TTYNAME_METHODDEF
17956
    OS_CHDIR_METHODDEF
17957
    OS_CHFLAGS_METHODDEF
17958
    OS_CHMOD_METHODDEF
17959
    OS_FCHMOD_METHODDEF
17960
    OS_LCHMOD_METHODDEF
17961
    OS_CHOWN_METHODDEF
17962
    OS_FCHOWN_METHODDEF
17963
    OS_LCHOWN_METHODDEF
17964
    OS_LCHFLAGS_METHODDEF
17965
    OS_CHROOT_METHODDEF
17966
    OS_CTERMID_METHODDEF
17967
    OS_GETCWD_METHODDEF
17968
    OS_GETCWDB_METHODDEF
17969
    OS_LINK_METHODDEF
17970
    OS_LISTDIR_METHODDEF
17971
    OS_LISTDRIVES_METHODDEF
17972
    OS_LISTMOUNTS_METHODDEF
17973
    OS_LISTVOLUMES_METHODDEF
17974
    OS_LSTAT_METHODDEF
17975
    OS_MKDIR_METHODDEF
17976
    OS_NICE_METHODDEF
17977
    OS_GETPRIORITY_METHODDEF
17978
    OS_SETPRIORITY_METHODDEF
17979
    OS_POSIX_SPAWN_METHODDEF
17980
    OS_POSIX_SPAWNP_METHODDEF
17981
    OS_READLINK_METHODDEF
17982
    OS_COPY_FILE_RANGE_METHODDEF
17983
    OS_SPLICE_METHODDEF
17984
    OS_RENAME_METHODDEF
17985
    OS_REPLACE_METHODDEF
17986
    OS_RMDIR_METHODDEF
17987
    OS_SYMLINK_METHODDEF
17988
    OS_SYSTEM_METHODDEF
17989
    OS_UMASK_METHODDEF
17990
    OS_UNAME_METHODDEF
17991
    OS_UNLINK_METHODDEF
17992
    OS_REMOVE_METHODDEF
17993
    OS_UTIME_METHODDEF
17994
    OS_TIMES_METHODDEF
17995
    OS__EXIT_METHODDEF
17996
    OS__FCOPYFILE_METHODDEF
17997
    OS_EXECV_METHODDEF
17998
    OS_EXECVE_METHODDEF
17999
    OS_SPAWNV_METHODDEF
18000
    OS_SPAWNVE_METHODDEF
18001
    OS_FORK1_METHODDEF
18002
    OS_FORK_METHODDEF
18003
    OS_REGISTER_AT_FORK_METHODDEF
18004
    OS_SCHED_GET_PRIORITY_MAX_METHODDEF
18005
    OS_SCHED_GET_PRIORITY_MIN_METHODDEF
18006
    OS_SCHED_GETPARAM_METHODDEF
18007
    OS_SCHED_GETSCHEDULER_METHODDEF
18008
    OS_SCHED_RR_GET_INTERVAL_METHODDEF
18009
    OS_SCHED_SETPARAM_METHODDEF
18010
    OS_SCHED_SETSCHEDULER_METHODDEF
18011
    OS_SCHED_YIELD_METHODDEF
18012
    OS_SCHED_SETAFFINITY_METHODDEF
18013
    OS_SCHED_GETAFFINITY_METHODDEF
18014
    OS_POSIX_OPENPT_METHODDEF
18015
    OS_GRANTPT_METHODDEF
18016
    OS_UNLOCKPT_METHODDEF
18017
    OS_PTSNAME_METHODDEF
18018
    OS_OPENPTY_METHODDEF
18019
    OS_LOGIN_TTY_METHODDEF
18020
    OS_FORKPTY_METHODDEF
18021
    OS_GETEGID_METHODDEF
18022
    OS_GETEUID_METHODDEF
18023
    OS_GETGID_METHODDEF
18024
    OS_GETGROUPLIST_METHODDEF
18025
    OS_GETGROUPS_METHODDEF
18026
    OS_GETPID_METHODDEF
18027
    OS_GETPGRP_METHODDEF
18028
    OS_GETPPID_METHODDEF
18029
    OS_GETUID_METHODDEF
18030
    OS_GETLOGIN_METHODDEF
18031
    OS_KILL_METHODDEF
18032
    OS_KILLPG_METHODDEF
18033
    OS_PLOCK_METHODDEF
18034
    OS_STARTFILE_METHODDEF
18035
    OS_SETUID_METHODDEF
18036
    OS_SETEUID_METHODDEF
18037
    OS_SETREUID_METHODDEF
18038
    OS_SETGID_METHODDEF
18039
    OS_SETEGID_METHODDEF
18040
    OS_SETREGID_METHODDEF
18041
    OS_SETGROUPS_METHODDEF
18042
    OS_INITGROUPS_METHODDEF
18043
    OS_GETPGID_METHODDEF
18044
    OS_SETPGRP_METHODDEF
18045
    OS_WAIT_METHODDEF
18046
    OS_WAIT3_METHODDEF
18047
    OS_WAIT4_METHODDEF
18048
    OS_WAITID_METHODDEF
18049
    OS_WAITPID_METHODDEF
18050
    OS_PIDFD_OPEN_METHODDEF
18051
    OS_PIDFD_GETFD_METHODDEF
18052
    OS_GETSID_METHODDEF
18053
    OS_SETSID_METHODDEF
18054
    OS_SETPGID_METHODDEF
18055
    OS_TCGETPGRP_METHODDEF
18056
    OS_TCSETPGRP_METHODDEF
18057
    OS_OPEN_METHODDEF
18058
    OS_CLOSE_METHODDEF
18059
    OS_CLOSERANGE_METHODDEF
18060
    OS_DEVICE_ENCODING_METHODDEF
18061
    OS_DUP_METHODDEF
18062
    OS_DUP2_METHODDEF
18063
    OS_LOCKF_METHODDEF
18064
    OS_LSEEK_METHODDEF
18065
    OS_READ_METHODDEF
18066
    OS_READINTO_METHODDEF
18067
    OS_READV_METHODDEF
18068
    OS_PREAD_METHODDEF
18069
    OS_PREADV_METHODDEF
18070
    OS_WRITE_METHODDEF
18071
    OS_WRITEV_METHODDEF
18072
    OS_PWRITE_METHODDEF
18073
    OS_PWRITEV_METHODDEF
18074
    OS_SENDFILE_METHODDEF
18075
    OS_FSTAT_METHODDEF
18076
    OS_ISATTY_METHODDEF
18077
    OS_PIPE_METHODDEF
18078
    OS_PIPE2_METHODDEF
18079
    OS_MKFIFO_METHODDEF
18080
    OS_MKNOD_METHODDEF
18081
    OS_MAJOR_METHODDEF
18082
    OS_MINOR_METHODDEF
18083
    OS_MAKEDEV_METHODDEF
18084
    OS_FTRUNCATE_METHODDEF
18085
    OS_TRUNCATE_METHODDEF
18086
    OS_POSIX_FALLOCATE_METHODDEF
18087
    OS_POSIX_FADVISE_METHODDEF
18088
    OS_PUTENV_METHODDEF
18089
    OS_UNSETENV_METHODDEF
18090
    OS__CLEARENV_METHODDEF
18091
    OS_STRERROR_METHODDEF
18092
    OS_FCHDIR_METHODDEF
18093
    OS_FSYNC_METHODDEF
18094
    OS_SYNC_METHODDEF
18095
    OS_FDATASYNC_METHODDEF
18096
    OS_WCOREDUMP_METHODDEF
18097
    OS_WIFCONTINUED_METHODDEF
18098
    OS_WIFSTOPPED_METHODDEF
18099
    OS_WIFSIGNALED_METHODDEF
18100
    OS_WIFEXITED_METHODDEF
18101
    OS_WEXITSTATUS_METHODDEF
18102
    OS_WTERMSIG_METHODDEF
18103
    OS_WSTOPSIG_METHODDEF
18104
    OS_FSTATVFS_METHODDEF
18105
    OS_STATVFS_METHODDEF
18106
    OS_CONFSTR_METHODDEF
18107
    OS_SYSCONF_METHODDEF
18108
    OS_FPATHCONF_METHODDEF
18109
    OS_PATHCONF_METHODDEF
18110
    OS_ABORT_METHODDEF
18111
    OS__GETFULLPATHNAME_METHODDEF
18112
    OS__GETDISKUSAGE_METHODDEF
18113
    OS__GETFINALPATHNAME_METHODDEF
18114
    OS__FINDFIRSTFILE_METHODDEF
18115
    OS__GETVOLUMEPATHNAME_METHODDEF
18116
    OS__PATH_SPLITROOT_METHODDEF
18117
    OS__PATH_SPLITROOT_EX_METHODDEF
18118
    OS__PATH_NORMPATH_METHODDEF
18119
    OS_GETLOADAVG_METHODDEF
18120
    OS_URANDOM_METHODDEF
18121
    OS_SETRESUID_METHODDEF
18122
    OS_SETRESGID_METHODDEF
18123
    OS_GETRESUID_METHODDEF
18124
    OS_GETRESGID_METHODDEF
18125
18126
    OS_GETXATTR_METHODDEF
18127
    OS_SETXATTR_METHODDEF
18128
    OS_REMOVEXATTR_METHODDEF
18129
    OS_LISTXATTR_METHODDEF
18130
18131
    OS_GET_TERMINAL_SIZE_METHODDEF
18132
    OS_CPU_COUNT_METHODDEF
18133
    OS_GET_INHERITABLE_METHODDEF
18134
    OS_SET_INHERITABLE_METHODDEF
18135
    OS_GET_HANDLE_INHERITABLE_METHODDEF
18136
    OS_SET_HANDLE_INHERITABLE_METHODDEF
18137
    OS_GET_BLOCKING_METHODDEF
18138
    OS_SET_BLOCKING_METHODDEF
18139
    OS_SCANDIR_METHODDEF
18140
    OS_FSPATH_METHODDEF
18141
    OS_GETRANDOM_METHODDEF
18142
    OS_MEMFD_CREATE_METHODDEF
18143
    OS_EVENTFD_METHODDEF
18144
    OS_EVENTFD_READ_METHODDEF
18145
    OS_EVENTFD_WRITE_METHODDEF
18146
    OS__ADD_DLL_DIRECTORY_METHODDEF
18147
    OS__REMOVE_DLL_DIRECTORY_METHODDEF
18148
    OS_WAITSTATUS_TO_EXITCODE_METHODDEF
18149
    OS_SETNS_METHODDEF
18150
    OS_UNSHARE_METHODDEF
18151
    OS_TIMERFD_CREATE_METHODDEF
18152
    OS_TIMERFD_SETTIME_METHODDEF
18153
    OS_TIMERFD_SETTIME_NS_METHODDEF
18154
    OS_TIMERFD_GETTIME_METHODDEF
18155
    OS_TIMERFD_GETTIME_NS_METHODDEF
18156
18157
    OS__PATH_ISDEVDRIVE_METHODDEF
18158
    OS__PATH_ISDIR_METHODDEF
18159
    OS__PATH_ISFILE_METHODDEF
18160
    OS__PATH_ISLINK_METHODDEF
18161
    OS__PATH_ISJUNCTION_METHODDEF
18162
    OS__PATH_EXISTS_METHODDEF
18163
    OS__PATH_LEXISTS_METHODDEF
18164
18165
    OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
18166
    OS__INPUTHOOK_METHODDEF
18167
    OS__IS_INPUTHOOK_INSTALLED_METHODDEF
18168
    OS__CREATE_ENVIRON_METHODDEF
18169
    OS__EMSCRIPTEN_DEBUGGER_METHODDEF
18170
    OS__EMSCRIPTEN_LOG_METHODDEF
18171
    {NULL,              NULL}            /* Sentinel */
18172
};
18173
18174
static int
18175
all_ins(PyObject *m)
18176
37
{
18177
37
#ifdef F_OK
18178
37
    if (PyModule_AddIntMacro(m, F_OK)) return -1;
18179
37
#endif
18180
37
#ifdef R_OK
18181
37
    if (PyModule_AddIntMacro(m, R_OK)) return -1;
18182
37
#endif
18183
37
#ifdef W_OK
18184
37
    if (PyModule_AddIntMacro(m, W_OK)) return -1;
18185
37
#endif
18186
37
#ifdef X_OK
18187
37
    if (PyModule_AddIntMacro(m, X_OK)) return -1;
18188
37
#endif
18189
37
#ifdef NGROUPS_MAX
18190
37
    if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
18191
37
#endif
18192
37
#ifdef TMP_MAX
18193
37
    if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
18194
37
#endif
18195
37
#ifdef WCONTINUED
18196
37
    if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
18197
37
#endif
18198
37
#ifdef WNOHANG
18199
37
    if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
18200
37
#endif
18201
37
#ifdef WUNTRACED
18202
37
    if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
18203
37
#endif
18204
37
#ifdef O_RDONLY
18205
37
    if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
18206
37
#endif
18207
37
#ifdef O_WRONLY
18208
37
    if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
18209
37
#endif
18210
37
#ifdef O_RDWR
18211
37
    if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
18212
37
#endif
18213
37
#ifdef O_NDELAY
18214
37
    if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
18215
37
#endif
18216
37
#ifdef O_NONBLOCK
18217
37
    if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
18218
37
#endif
18219
37
#ifdef O_APPEND
18220
37
    if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
18221
37
#endif
18222
37
#ifdef O_DSYNC
18223
37
    if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
18224
37
#endif
18225
37
#ifdef O_RSYNC
18226
37
    if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
18227
37
#endif
18228
37
#ifdef O_SYNC
18229
37
    if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
18230
37
#endif
18231
37
#ifdef O_NOCTTY
18232
37
    if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
18233
37
#endif
18234
37
#ifdef O_CREAT
18235
37
    if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
18236
37
#endif
18237
37
#ifdef O_EXCL
18238
37
    if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
18239
37
#endif
18240
37
#ifdef O_TRUNC
18241
37
    if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
18242
37
#endif
18243
#ifdef O_BINARY
18244
    if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
18245
#endif
18246
#ifdef O_TEXT
18247
    if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
18248
#endif
18249
#ifdef O_XATTR
18250
    if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
18251
#endif
18252
37
#ifdef O_LARGEFILE
18253
37
    if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
18254
37
#endif
18255
37
#ifndef __GNU__
18256
#ifdef O_SHLOCK
18257
    if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
18258
#endif
18259
#ifdef O_EXLOCK
18260
    if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
18261
#endif
18262
37
#endif
18263
#ifdef O_EXEC
18264
    if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
18265
#endif
18266
#ifdef O_SEARCH
18267
    if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
18268
#endif
18269
37
#ifdef O_PATH
18270
37
    if (PyModule_AddIntMacro(m, O_PATH)) return -1;
18271
37
#endif
18272
#ifdef O_TTY_INIT
18273
    if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
18274
#endif
18275
37
#ifdef O_TMPFILE
18276
37
    if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
18277
37
#endif
18278
37
#ifdef PRIO_PROCESS
18279
37
    if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
18280
37
#endif
18281
37
#ifdef PRIO_PGRP
18282
37
    if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
18283
37
#endif
18284
37
#ifdef PRIO_USER
18285
37
    if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
18286
37
#endif
18287
#ifdef PRIO_DARWIN_THREAD
18288
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1;
18289
#endif
18290
#ifdef PRIO_DARWIN_PROCESS
18291
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1;
18292
#endif
18293
#ifdef PRIO_DARWIN_BG
18294
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1;
18295
#endif
18296
#ifdef PRIO_DARWIN_NONUI
18297
    if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1;
18298
#endif
18299
37
#ifdef O_CLOEXEC
18300
37
    if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
18301
37
#endif
18302
37
#ifdef O_ACCMODE
18303
37
    if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
18304
37
#endif
18305
#ifdef O_EVTONLY
18306
    if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
18307
#endif
18308
37
#ifdef O_FSYNC
18309
37
    if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
18310
37
#endif
18311
#ifdef O_SYMLINK
18312
    if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
18313
#endif
18314
18315
37
#ifdef SEEK_HOLE
18316
37
    if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
18317
37
#endif
18318
37
#ifdef SEEK_DATA
18319
37
    if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
18320
37
#endif
18321
18322
/* MS Windows */
18323
#ifdef O_NOINHERIT
18324
    /* Don't inherit in child processes. */
18325
    if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
18326
#endif
18327
#ifdef _O_SHORT_LIVED
18328
    /* Optimize for short life (keep in memory). */
18329
    /* MS forgot to define this one with a non-underscore form too. */
18330
    if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
18331
#endif
18332
#ifdef O_TEMPORARY
18333
    /* Automatically delete when last handle is closed. */
18334
    if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
18335
#endif
18336
#ifdef O_RANDOM
18337
    /* Optimize for random access. */
18338
    if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
18339
#endif
18340
#ifdef O_SEQUENTIAL
18341
    /* Optimize for sequential access. */
18342
    if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
18343
#endif
18344
18345
/* GNU extensions. */
18346
37
#ifdef O_ASYNC
18347
    /* Send a SIGIO signal whenever input or output
18348
       becomes available on file descriptor */
18349
37
    if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
18350
37
#endif
18351
37
#ifdef O_DIRECT
18352
    /* Direct disk access. */
18353
37
    if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
18354
37
#endif
18355
37
#ifdef O_DIRECTORY
18356
    /* Must be a directory.      */
18357
37
    if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
18358
37
#endif
18359
37
#ifdef O_NOFOLLOW
18360
    /* Do not follow links.      */
18361
37
    if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
18362
37
#endif
18363
#ifdef O_NOFOLLOW_ANY
18364
    if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
18365
#endif
18366
#ifdef O_NOLINKS
18367
    /* Fails if link count of the named file is greater than 1 */
18368
    if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
18369
#endif
18370
37
#ifdef O_NOATIME
18371
    /* Do not update the access time. */
18372
37
    if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
18373
37
#endif
18374
18375
    /* These come from sysexits.h */
18376
37
#ifdef EX_OK
18377
37
    if (PyModule_AddIntMacro(m, EX_OK)) return -1;
18378
37
#endif /* EX_OK */
18379
37
#ifdef EX_USAGE
18380
37
    if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
18381
37
#endif /* EX_USAGE */
18382
37
#ifdef EX_DATAERR
18383
37
    if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
18384
37
#endif /* EX_DATAERR */
18385
37
#ifdef EX_NOINPUT
18386
37
    if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
18387
37
#endif /* EX_NOINPUT */
18388
37
#ifdef EX_NOUSER
18389
37
    if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
18390
37
#endif /* EX_NOUSER */
18391
37
#ifdef EX_NOHOST
18392
37
    if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
18393
37
#endif /* EX_NOHOST */
18394
37
#ifdef EX_UNAVAILABLE
18395
37
    if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
18396
37
#endif /* EX_UNAVAILABLE */
18397
37
#ifdef EX_SOFTWARE
18398
37
    if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
18399
37
#endif /* EX_SOFTWARE */
18400
37
#ifdef EX_OSERR
18401
37
    if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
18402
37
#endif /* EX_OSERR */
18403
37
#ifdef EX_OSFILE
18404
37
    if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
18405
37
#endif /* EX_OSFILE */
18406
37
#ifdef EX_CANTCREAT
18407
37
    if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
18408
37
#endif /* EX_CANTCREAT */
18409
37
#ifdef EX_IOERR
18410
37
    if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
18411
37
#endif /* EX_IOERR */
18412
37
#ifdef EX_TEMPFAIL
18413
37
    if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
18414
37
#endif /* EX_TEMPFAIL */
18415
37
#ifdef EX_PROTOCOL
18416
37
    if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
18417
37
#endif /* EX_PROTOCOL */
18418
37
#ifdef EX_NOPERM
18419
37
    if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
18420
37
#endif /* EX_NOPERM */
18421
37
#ifdef EX_CONFIG
18422
37
    if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
18423
37
#endif /* EX_CONFIG */
18424
#ifdef EX_NOTFOUND
18425
    if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
18426
#endif /* EX_NOTFOUND */
18427
18428
    /* statvfs */
18429
37
#ifdef ST_RDONLY
18430
37
    if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
18431
37
#endif /* ST_RDONLY */
18432
37
#ifdef ST_NOSUID
18433
37
    if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
18434
37
#endif /* ST_NOSUID */
18435
18436
       /* GNU extensions */
18437
37
#ifdef ST_NODEV
18438
37
    if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
18439
37
#endif /* ST_NODEV */
18440
37
#ifdef ST_NOEXEC
18441
37
    if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
18442
37
#endif /* ST_NOEXEC */
18443
37
#ifdef ST_SYNCHRONOUS
18444
37
    if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
18445
37
#endif /* ST_SYNCHRONOUS */
18446
37
#ifdef ST_MANDLOCK
18447
37
    if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
18448
37
#endif /* ST_MANDLOCK */
18449
37
#ifdef ST_WRITE
18450
37
    if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
18451
37
#endif /* ST_WRITE */
18452
37
#ifdef ST_APPEND
18453
37
    if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
18454
37
#endif /* ST_APPEND */
18455
37
#ifdef ST_NOATIME
18456
37
    if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
18457
37
#endif /* ST_NOATIME */
18458
37
#ifdef ST_NODIRATIME
18459
37
    if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
18460
37
#endif /* ST_NODIRATIME */
18461
37
#ifdef ST_RELATIME
18462
37
    if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
18463
37
#endif /* ST_RELATIME */
18464
18465
    /* FreeBSD sendfile() constants */
18466
#ifdef SF_NODISKIO
18467
    if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
18468
#endif
18469
    /* is obsolete since the 11.x release */
18470
#ifdef SF_MNOWAIT
18471
    if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
18472
#endif
18473
#ifdef SF_SYNC
18474
    if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
18475
#endif
18476
#ifdef SF_NOCACHE
18477
    if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
18478
#endif
18479
18480
37
#ifdef TFD_NONBLOCK
18481
37
    if (PyModule_AddIntMacro(m, TFD_NONBLOCK)) return -1;
18482
37
#endif
18483
37
#ifdef TFD_CLOEXEC
18484
37
    if (PyModule_AddIntMacro(m, TFD_CLOEXEC)) return -1;
18485
37
#endif
18486
37
#ifdef TFD_TIMER_ABSTIME
18487
37
    if (PyModule_AddIntMacro(m, TFD_TIMER_ABSTIME)) return -1;
18488
37
#endif
18489
37
#ifdef TFD_TIMER_CANCEL_ON_SET
18490
37
    if (PyModule_AddIntMacro(m, TFD_TIMER_CANCEL_ON_SET)) return -1;
18491
37
#endif
18492
18493
    /* constants for posix_fadvise */
18494
37
#ifdef POSIX_FADV_NORMAL
18495
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
18496
37
#endif
18497
37
#ifdef POSIX_FADV_SEQUENTIAL
18498
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
18499
37
#endif
18500
37
#ifdef POSIX_FADV_RANDOM
18501
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
18502
37
#endif
18503
37
#ifdef POSIX_FADV_NOREUSE
18504
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
18505
37
#endif
18506
37
#ifdef POSIX_FADV_WILLNEED
18507
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
18508
37
#endif
18509
37
#ifdef POSIX_FADV_DONTNEED
18510
37
    if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
18511
37
#endif
18512
18513
    /* constants for waitid */
18514
37
#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
18515
37
    if (PyModule_AddIntMacro(m, P_PID)) return -1;
18516
37
    if (PyModule_AddIntMacro(m, P_PGID)) return -1;
18517
37
    if (PyModule_AddIntMacro(m, P_ALL)) return -1;
18518
37
#ifdef P_PIDFD
18519
37
    if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
18520
37
#endif
18521
#ifdef PIDFD_NONBLOCK
18522
    if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
18523
#endif
18524
37
#endif
18525
37
#ifdef WEXITED
18526
37
    if (PyModule_AddIntMacro(m, WEXITED)) return -1;
18527
37
#endif
18528
37
#ifdef WNOWAIT
18529
37
    if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
18530
37
#endif
18531
37
#ifdef WSTOPPED
18532
37
    if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
18533
37
#endif
18534
37
#ifdef CLD_EXITED
18535
37
    if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
18536
37
#endif
18537
37
#ifdef CLD_KILLED
18538
37
    if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
18539
37
#endif
18540
37
#ifdef CLD_DUMPED
18541
37
    if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
18542
37
#endif
18543
37
#ifdef CLD_TRAPPED
18544
37
    if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
18545
37
#endif
18546
37
#ifdef CLD_STOPPED
18547
37
    if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
18548
37
#endif
18549
37
#ifdef CLD_CONTINUED
18550
37
    if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
18551
37
#endif
18552
18553
    /* constants for lockf */
18554
37
#ifdef F_LOCK
18555
37
    if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
18556
37
#endif
18557
37
#ifdef F_TLOCK
18558
37
    if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
18559
37
#endif
18560
37
#ifdef F_ULOCK
18561
37
    if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
18562
37
#endif
18563
37
#ifdef F_TEST
18564
37
    if (PyModule_AddIntMacro(m, F_TEST)) return -1;
18565
37
#endif
18566
18567
37
#ifdef RWF_DSYNC
18568
37
    if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
18569
37
#endif
18570
37
#ifdef RWF_HIPRI
18571
37
    if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
18572
37
#endif
18573
37
#ifdef RWF_SYNC
18574
37
    if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
18575
37
#endif
18576
37
#ifdef RWF_NOWAIT
18577
37
    if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
18578
37
#endif
18579
#ifdef RWF_DONTCACHE
18580
    if (PyModule_AddIntConstant(m, "RWF_DONTCACHE", RWF_DONTCACHE)) return -1;
18581
#endif
18582
#ifdef RWF_ATOMIC
18583
    if (PyModule_AddIntConstant(m, "RWF_ATOMIC", RWF_ATOMIC)) return -1;
18584
#endif
18585
37
#ifdef RWF_APPEND
18586
37
    if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
18587
37
#endif
18588
#ifdef RWF_NOSIGNAL
18589
    if (PyModule_AddIntConstant(m, "RWF_NOSIGNAL", RWF_NOSIGNAL)) return -1;
18590
#endif
18591
18592
/* constants for splice */
18593
37
#if defined(HAVE_SPLICE) && defined(__linux__)
18594
37
    if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
18595
37
    if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
18596
37
    if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
18597
37
#endif
18598
18599
/* constants for posix_spawn */
18600
37
#ifdef HAVE_POSIX_SPAWN
18601
37
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
18602
37
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
18603
37
    if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
18604
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
18605
    if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
18606
#endif
18607
37
#endif
18608
18609
#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
18610
    if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
18611
    if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
18612
    if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
18613
#endif
18614
#ifdef HAVE_SPAWNV
18615
    if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
18616
    if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
18617
#endif
18618
18619
37
#ifdef HAVE_SCHED_H
18620
37
#ifdef SCHED_OTHER
18621
37
    if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
18622
37
#endif
18623
37
#ifdef SCHED_DEADLINE
18624
37
    if (PyModule_AddIntMacro(m, SCHED_DEADLINE)) return -1;
18625
37
#endif
18626
37
#ifdef SCHED_FIFO
18627
37
    if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
18628
37
#endif
18629
37
#ifdef SCHED_NORMAL
18630
37
    if (PyModule_AddIntMacro(m, SCHED_NORMAL)) return -1;
18631
37
#endif
18632
37
#ifdef SCHED_RR
18633
37
    if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
18634
37
#endif
18635
#ifdef SCHED_SPORADIC
18636
    if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
18637
#endif
18638
37
#ifdef SCHED_BATCH
18639
37
    if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
18640
37
#endif
18641
37
#ifdef SCHED_IDLE
18642
37
    if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
18643
37
#endif
18644
37
#ifdef SCHED_RESET_ON_FORK
18645
37
    if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
18646
37
#endif
18647
#ifdef SCHED_SYS
18648
    if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
18649
#endif
18650
#ifdef SCHED_IA
18651
    if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
18652
#endif
18653
#ifdef SCHED_FSS
18654
    if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
18655
#endif
18656
#ifdef SCHED_FX
18657
    if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
18658
#endif
18659
18660
/* constants for namespaces */
18661
37
#if defined(HAVE_SETNS) || defined(HAVE_UNSHARE)
18662
37
#ifdef CLONE_FS
18663
37
    if (PyModule_AddIntMacro(m, CLONE_FS)) return -1;
18664
37
#endif
18665
37
#ifdef CLONE_FILES
18666
37
    if (PyModule_AddIntMacro(m, CLONE_FILES)) return -1;
18667
37
#endif
18668
37
#ifdef CLONE_NEWNS
18669
37
    if (PyModule_AddIntMacro(m, CLONE_NEWNS)) return -1;
18670
37
#endif
18671
37
#ifdef CLONE_NEWCGROUP
18672
37
    if (PyModule_AddIntMacro(m, CLONE_NEWCGROUP)) return -1;
18673
37
#endif
18674
37
#ifdef CLONE_NEWUTS
18675
37
    if (PyModule_AddIntMacro(m, CLONE_NEWUTS)) return -1;
18676
37
#endif
18677
37
#ifdef CLONE_NEWIPC
18678
37
    if (PyModule_AddIntMacro(m, CLONE_NEWIPC)) return -1;
18679
37
#endif
18680
37
#ifdef CLONE_NEWUSER
18681
37
    if (PyModule_AddIntMacro(m, CLONE_NEWUSER)) return -1;
18682
37
#endif
18683
37
#ifdef CLONE_NEWPID
18684
37
    if (PyModule_AddIntMacro(m, CLONE_NEWPID)) return -1;
18685
37
#endif
18686
37
#ifdef CLONE_NEWNET
18687
37
    if (PyModule_AddIntMacro(m, CLONE_NEWNET)) return -1;
18688
37
#endif
18689
#ifdef CLONE_NEWTIME
18690
    if (PyModule_AddIntMacro(m, CLONE_NEWTIME)) return -1;
18691
#endif
18692
37
#ifdef CLONE_SYSVSEM
18693
37
    if (PyModule_AddIntMacro(m, CLONE_SYSVSEM)) return -1;
18694
37
#endif
18695
37
#ifdef CLONE_THREAD
18696
37
    if (PyModule_AddIntMacro(m, CLONE_THREAD)) return -1;
18697
37
#endif
18698
37
#ifdef CLONE_SIGHAND
18699
37
    if (PyModule_AddIntMacro(m, CLONE_SIGHAND)) return -1;
18700
37
#endif
18701
37
#ifdef CLONE_VM
18702
37
    if (PyModule_AddIntMacro(m, CLONE_VM)) return -1;
18703
37
#endif
18704
37
#endif
18705
18706
37
#endif
18707
18708
37
#ifdef USE_XATTRS
18709
37
    if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
18710
37
    if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
18711
37
    if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
18712
37
#endif
18713
18714
37
#if HAVE_DECL_RTLD_LAZY
18715
37
    if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
18716
37
#endif
18717
37
#if HAVE_DECL_RTLD_NOW
18718
37
    if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
18719
37
#endif
18720
37
#if HAVE_DECL_RTLD_GLOBAL
18721
37
    if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
18722
37
#endif
18723
37
#if HAVE_DECL_RTLD_LOCAL
18724
37
    if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
18725
37
#endif
18726
37
#if HAVE_DECL_RTLD_NODELETE
18727
37
    if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
18728
37
#endif
18729
37
#if HAVE_DECL_RTLD_NOLOAD
18730
37
    if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
18731
37
#endif
18732
37
#if HAVE_DECL_RTLD_DEEPBIND
18733
37
    if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
18734
37
#endif
18735
#if HAVE_DECL_RTLD_MEMBER
18736
    if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
18737
#endif
18738
18739
37
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
18740
37
    if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
18741
37
    if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
18742
37
#endif
18743
37
#ifdef _Py_HAVE_MEMFD_CREATE
18744
37
    if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
18745
37
    if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
18746
37
#ifdef MFD_HUGETLB
18747
37
    if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
18748
37
#endif
18749
37
#ifdef MFD_HUGE_SHIFT
18750
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
18751
37
#endif
18752
37
#ifdef MFD_HUGE_MASK
18753
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
18754
37
#endif
18755
37
#ifdef MFD_HUGE_64KB
18756
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
18757
37
#endif
18758
37
#ifdef MFD_HUGE_512KB
18759
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
18760
37
#endif
18761
37
#ifdef MFD_HUGE_1MB
18762
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
18763
37
#endif
18764
37
#ifdef MFD_HUGE_2MB
18765
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
18766
37
#endif
18767
37
#ifdef MFD_HUGE_8MB
18768
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
18769
37
#endif
18770
37
#ifdef MFD_HUGE_16MB
18771
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
18772
37
#endif
18773
37
#ifdef MFD_HUGE_32MB
18774
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
18775
37
#endif
18776
37
#ifdef MFD_HUGE_256MB
18777
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
18778
37
#endif
18779
37
#ifdef MFD_HUGE_512MB
18780
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
18781
37
#endif
18782
37
#ifdef MFD_HUGE_1GB
18783
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
18784
37
#endif
18785
37
#ifdef MFD_HUGE_2GB
18786
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
18787
37
#endif
18788
37
#ifdef MFD_HUGE_16GB
18789
37
    if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
18790
37
#endif
18791
37
#endif /* _Py_HAVE_MEMFD_CREATE */
18792
18793
37
#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
18794
37
    if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
18795
37
#ifdef EFD_NONBLOCK
18796
37
    if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
18797
37
#endif
18798
37
#ifdef EFD_SEMAPHORE
18799
37
    if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
18800
37
#endif
18801
37
#endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
18802
18803
37
#ifdef NODEV
18804
37
    if (PyModule_Add(m, "NODEV", _PyLong_FromDev(NODEV))) return -1;
18805
37
#endif
18806
18807
37
#ifdef AT_NO_AUTOMOUNT
18808
37
    if (PyModule_AddIntMacro(m, AT_NO_AUTOMOUNT)) return -1;
18809
37
#endif
18810
18811
37
#ifdef HAVE_STATX
18812
37
    if (PyModule_AddIntMacro(m, STATX_TYPE)) return -1;
18813
37
    if (PyModule_AddIntMacro(m, STATX_MODE)) return -1;
18814
37
    if (PyModule_AddIntMacro(m, STATX_NLINK)) return -1;
18815
37
    if (PyModule_AddIntMacro(m, STATX_UID)) return -1;
18816
37
    if (PyModule_AddIntMacro(m, STATX_GID)) return -1;
18817
37
    if (PyModule_AddIntMacro(m, STATX_ATIME)) return -1;
18818
37
    if (PyModule_AddIntMacro(m, STATX_MTIME)) return -1;
18819
37
    if (PyModule_AddIntMacro(m, STATX_CTIME)) return -1;
18820
37
    if (PyModule_AddIntMacro(m, STATX_INO)) return -1;
18821
37
    if (PyModule_AddIntMacro(m, STATX_SIZE)) return -1;
18822
37
    if (PyModule_AddIntMacro(m, STATX_BLOCKS)) return -1;
18823
37
    if (PyModule_AddIntMacro(m, STATX_BASIC_STATS)) return -1;
18824
37
    if (PyModule_AddIntMacro(m, STATX_BTIME)) return -1;
18825
#ifdef STATX_MNT_ID
18826
    if (PyModule_AddIntMacro(m, STATX_MNT_ID)) return -1;
18827
#endif
18828
#ifdef STATX_DIOALIGN
18829
    if (PyModule_AddIntMacro(m, STATX_DIOALIGN)) return -1;
18830
#endif
18831
#ifdef STATX_MNT_ID_UNIQUE
18832
    if (PyModule_AddIntMacro(m, STATX_MNT_ID_UNIQUE)) return -1;
18833
#endif
18834
#ifdef STATX_SUBVOL
18835
    if (PyModule_AddIntMacro(m, STATX_SUBVOL)) return -1;
18836
#endif
18837
#ifdef STATX_WRITE_ATOMIC
18838
    if (PyModule_AddIntMacro(m, STATX_WRITE_ATOMIC)) return -1;
18839
#endif
18840
#ifdef STATX_DIO_READ_ALIGN
18841
    if (PyModule_AddIntMacro(m, STATX_DIO_READ_ALIGN)) return -1;
18842
#endif
18843
    /* STATX_ALL intentionally omitted because it is deprecated */
18844
37
    if (PyModule_AddIntMacro(m, AT_STATX_SYNC_AS_STAT)) return -1;
18845
37
    if (PyModule_AddIntMacro(m, AT_STATX_FORCE_SYNC)) return -1;
18846
37
    if (PyModule_AddIntMacro(m, AT_STATX_DONT_SYNC)) return -1;
18847
    /* STATX_ATTR_* constants are in the stat module */
18848
37
#endif /* HAVE_STATX */
18849
18850
#if defined(__APPLE__)
18851
    if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
18852
    if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
18853
    if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
18854
    if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
18855
#endif
18856
18857
#ifdef MS_WINDOWS
18858
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
18859
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
18860
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
18861
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
18862
    if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
18863
#endif
18864
18865
37
    return 0;
18866
37
}
18867
18868
18869
18870
#define PROBE(name, test) \
18871
   static int name(void)  \
18872
629
   {                      \
18873
629
      if (test) {        \
18874
629
          return 1;       \
18875
629
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
629
   }
posixmodule.c:probe_faccessat
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_fchmodat
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_fchownat
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_fdopendir
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_fstatat
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_futimens
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_linkat
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_mkdirat
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_mkfifoat
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_mknodat
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_openat
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_readlinkat
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_renameat
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_symlinkat
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_unlinkat
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_utimensat
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
posixmodule.c:probe_ptsname_r
Line
Count
Source
18872
37
   {                      \
18873
37
      if (test) {        \
18874
37
          return 1;       \
18875
37
      } else {            \
18876
0
          return 0;       \
18877
0
      }                   \
18878
37
   }
18879
18880
#ifdef HAVE_FSTATAT
18881
PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
18882
#endif
18883
18884
#ifdef HAVE_FACCESSAT
18885
PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
18886
#endif
18887
18888
#ifdef HAVE_FCHMODAT
18889
PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
18890
#endif
18891
18892
#ifdef HAVE_FCHOWNAT
18893
PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
18894
#endif
18895
18896
#ifdef HAVE_LINKAT
18897
PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
18898
#endif
18899
18900
#ifdef HAVE_FDOPENDIR
18901
PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
18902
#endif
18903
18904
#ifdef HAVE_MKDIRAT
18905
PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
18906
#endif
18907
18908
#ifdef HAVE_MKFIFOAT
18909
PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
18910
#endif
18911
18912
#ifdef HAVE_MKNODAT
18913
PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
18914
#endif
18915
18916
#ifdef HAVE_RENAMEAT
18917
PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
18918
#endif
18919
18920
#ifdef HAVE_UNLINKAT
18921
PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
18922
#endif
18923
18924
#ifdef HAVE_OPENAT
18925
PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
18926
#endif
18927
18928
#ifdef HAVE_READLINKAT
18929
PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
18930
#endif
18931
18932
#ifdef _Py_HAVE_FREADLINK
18933
PROBE(probe_freadlink, HAVE_FREADLINK_RUNTIME)
18934
#endif
18935
18936
#ifdef HAVE_SYMLINKAT
18937
PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
18938
#endif
18939
18940
#ifdef HAVE_FUTIMENS
18941
PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
18942
#endif
18943
18944
#ifdef HAVE_UTIMENSAT
18945
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
18946
#endif
18947
18948
#ifdef HAVE_PTSNAME_R
18949
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
18950
#endif
18951
18952
18953
18954
static const struct have_function {
18955
    const char * const label;
18956
    int (*probe)(void);
18957
} have_functions[] = {
18958
18959
#ifdef HAVE_EVENTFD
18960
    {"HAVE_EVENTFD", NULL},
18961
#endif
18962
18963
#ifdef HAVE_TIMERFD_CREATE
18964
    {"HAVE_TIMERFD_CREATE", NULL},
18965
#endif
18966
18967
#ifdef HAVE_FACCESSAT
18968
    { "HAVE_FACCESSAT", probe_faccessat },
18969
#endif
18970
18971
#ifdef HAVE_FCHDIR
18972
    { "HAVE_FCHDIR", NULL },
18973
#endif
18974
18975
#ifdef HAVE_FCHMOD
18976
    { "HAVE_FCHMOD", NULL },
18977
#endif
18978
18979
#ifdef HAVE_FCHMODAT
18980
    { "HAVE_FCHMODAT", probe_fchmodat },
18981
#endif
18982
18983
#ifdef HAVE_FCHOWN
18984
    { "HAVE_FCHOWN", NULL },
18985
#endif
18986
18987
#ifdef HAVE_FCHOWNAT
18988
    { "HAVE_FCHOWNAT", probe_fchownat },
18989
#endif
18990
18991
#ifdef HAVE_FEXECVE
18992
    { "HAVE_FEXECVE", NULL },
18993
#endif
18994
18995
#ifdef HAVE_FDOPENDIR
18996
    { "HAVE_FDOPENDIR", probe_fdopendir },
18997
#endif
18998
18999
#ifdef HAVE_FPATHCONF
19000
    { "HAVE_FPATHCONF", NULL },
19001
#endif
19002
19003
#ifdef _Py_HAVE_FREADLINK
19004
    { "HAVE_FREADLINK", probe_freadlink },
19005
#endif
19006
19007
#ifdef HAVE_FSTATAT
19008
    { "HAVE_FSTATAT", probe_fstatat },
19009
#endif
19010
19011
#ifdef HAVE_FSTATVFS
19012
    { "HAVE_FSTATVFS", NULL },
19013
#endif
19014
19015
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
19016
    { "HAVE_FTRUNCATE", NULL },
19017
#endif
19018
19019
#ifdef HAVE_FUTIMENS
19020
    { "HAVE_FUTIMENS", probe_futimens },
19021
#endif
19022
19023
#ifdef HAVE_FUTIMES
19024
    { "HAVE_FUTIMES", NULL },
19025
#endif
19026
19027
#ifdef HAVE_FUTIMESAT
19028
    { "HAVE_FUTIMESAT", NULL },
19029
#endif
19030
19031
#ifdef HAVE_LINKAT
19032
    { "HAVE_LINKAT", probe_linkat },
19033
#endif
19034
19035
#ifdef HAVE_LCHFLAGS
19036
    { "HAVE_LCHFLAGS", NULL },
19037
#endif
19038
19039
#ifdef HAVE_LCHMOD
19040
    { "HAVE_LCHMOD", NULL },
19041
#endif
19042
19043
#ifdef HAVE_LCHOWN
19044
    { "HAVE_LCHOWN", NULL },
19045
#endif
19046
19047
#ifdef HAVE_LSTAT
19048
    { "HAVE_LSTAT", NULL },
19049
#endif
19050
19051
#ifdef HAVE_LUTIMES
19052
    { "HAVE_LUTIMES", NULL },
19053
#endif
19054
19055
#ifdef _Py_HAVE_MEMFD_CREATE
19056
    { "HAVE_MEMFD_CREATE", NULL },
19057
#endif
19058
19059
#ifdef HAVE_MKDIRAT
19060
    { "HAVE_MKDIRAT", probe_mkdirat },
19061
#endif
19062
19063
#ifdef HAVE_MKFIFOAT
19064
    { "HAVE_MKFIFOAT", probe_mkfifoat },
19065
#endif
19066
19067
#ifdef HAVE_MKNODAT
19068
    { "HAVE_MKNODAT", probe_mknodat },
19069
#endif
19070
19071
#ifdef HAVE_OPENAT
19072
    { "HAVE_OPENAT", probe_openat },
19073
#endif
19074
19075
#ifdef HAVE_READLINKAT
19076
    { "HAVE_READLINKAT", probe_readlinkat },
19077
#endif
19078
19079
#ifdef HAVE_RENAMEAT
19080
    { "HAVE_RENAMEAT", probe_renameat },
19081
#endif
19082
19083
#ifdef HAVE_SYMLINKAT
19084
    { "HAVE_SYMLINKAT", probe_symlinkat },
19085
#endif
19086
19087
#ifdef HAVE_UNLINKAT
19088
    { "HAVE_UNLINKAT", probe_unlinkat },
19089
#endif
19090
19091
#ifdef HAVE_UTIMENSAT
19092
    { "HAVE_UTIMENSAT", probe_utimensat },
19093
#endif
19094
19095
#ifdef HAVE_PTSNAME_R
19096
    { "HAVE_PTSNAME_R", probe_ptsname_r },
19097
#endif
19098
19099
#ifdef MS_WINDOWS
19100
    { "MS_WINDOWS", NULL },
19101
#endif
19102
19103
    { NULL, NULL }
19104
};
19105
19106
19107
static int
19108
posixmodule_exec(PyObject *m)
19109
37
{
19110
37
    _posixstate *state = get_posix_state(m);
19111
19112
37
#if defined(HAVE_PWRITEV)
19113
37
    if (HAVE_PWRITEV_RUNTIME) {} else {
19114
0
        PyObject* dct = PyModule_GetDict(m);
19115
19116
0
        if (dct == NULL) {
19117
0
            return -1;
19118
0
        }
19119
19120
0
        if (PyDict_PopString(dct, "pwritev", NULL) < 0) {
19121
0
            return -1;
19122
0
        }
19123
0
        if (PyDict_PopString(dct, "preadv", NULL) < 0) {
19124
0
            return -1;
19125
0
        }
19126
0
    }
19127
37
#endif
19128
19129
37
#ifdef HAVE_STATX
19130
37
    if (statx == NULL) {
19131
0
        PyObject* dct = PyModule_GetDict(m);
19132
0
        if (dct == NULL) {
19133
0
            return -1;
19134
0
        }
19135
0
        if (PyDict_PopString(dct, "statx", NULL) < 0) {
19136
0
            return -1;
19137
0
        }
19138
0
    }
19139
37
    else {
19140
37
        state->StatxResultType = PyType_FromModuleAndSpec(m, &pystatx_result_spec, NULL);
19141
37
        if (PyModule_AddObjectRef(m, "statx_result", state->StatxResultType) < 0) {
19142
0
            return -1;
19143
0
        }
19144
37
    }
19145
37
#endif
19146
19147
37
#if HAVE_PIPE2
19148
37
    if (HAVE_PIPE2_RUNTIME) {
19149
        // Do nothing. (`__builtin_available` doesn't allow `!`; see
19150
        // "using negations" in a comment above.)
19151
37
    }
19152
0
    else {
19153
0
        PyObject* dct = PyModule_GetDict(m);
19154
0
        if (dct == NULL) {
19155
0
            return -1;
19156
0
        }
19157
0
        if (PyDict_PopString(dct, "pipe2", NULL) < 0) {
19158
0
            return -1;
19159
0
        }
19160
0
    }
19161
37
#endif
19162
19163
    /* Initialize environ dictionary */
19164
37
    if (PyModule_Add(m, "environ", convertenviron()) != 0) {
19165
0
        return -1;
19166
0
    }
19167
19168
37
    if (all_ins(m))
19169
0
        return -1;
19170
19171
37
    if (setup_confname_tables(m))
19172
0
        return -1;
19173
19174
37
    if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) {
19175
0
        return -1;
19176
0
    }
19177
19178
37
#if defined(HAVE_WAITID)
19179
37
    state->WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
19180
37
    if (PyModule_AddObjectRef(m, "waitid_result", state->WaitidResultType) < 0) {
19181
0
        return -1;
19182
0
    }
19183
37
#endif
19184
19185
37
    stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
19186
37
    stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
19187
37
    stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
19188
37
    state->StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
19189
37
    if (PyModule_AddObjectRef(m, "stat_result", state->StatResultType) < 0) {
19190
0
        return -1;
19191
0
    }
19192
37
    state->statresult_new_orig = ((PyTypeObject *)state->StatResultType)->tp_new;
19193
37
    ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new;
19194
19195
37
    state->StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
19196
37
    if (PyModule_AddObjectRef(m, "statvfs_result", state->StatVFSResultType) < 0) {
19197
0
        return -1;
19198
0
    }
19199
19200
37
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
19201
37
    state->SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
19202
37
    if (PyModule_AddObjectRef(m, "sched_param", state->SchedParamType) < 0) {
19203
0
        return -1;
19204
0
    }
19205
37
    ((PyTypeObject *)state->SchedParamType)->tp_new = os_sched_param;
19206
37
    if (_PyType_AddMethod((PyTypeObject *)state->SchedParamType,
19207
37
                          &os_sched_param_reduce_method) < 0)
19208
0
    {
19209
0
        return -1;
19210
0
    }
19211
37
    PyType_Modified((PyTypeObject *)state->SchedParamType);
19212
37
#endif
19213
19214
    /* initialize TerminalSize_info */
19215
37
    state->TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
19216
37
    if (PyModule_AddObjectRef(m, "terminal_size", state->TerminalSizeType) < 0) {
19217
0
        return -1;
19218
0
    }
19219
19220
    /* initialize scandir types */
19221
37
    PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
19222
37
    if (ScandirIteratorType == NULL) {
19223
0
        return -1;
19224
0
    }
19225
37
    state->ScandirIteratorType = ScandirIteratorType;
19226
19227
37
    state->DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
19228
37
    if (PyModule_AddObjectRef(m, "DirEntry", state->DirEntryType) < 0) {
19229
0
        return -1;
19230
0
    }
19231
19232
37
    state->TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
19233
37
    if (PyModule_AddObjectRef(m, "times_result", state->TimesResultType) < 0) {
19234
0
        return -1;
19235
0
    }
19236
19237
37
    state->UnameResultType = (PyObject *)PyStructSequence_NewType(&uname_result_desc);
19238
37
    if (PyModule_AddObjectRef(m, "uname_result", state->UnameResultType) < 0) {
19239
0
        return -1;
19240
0
    }
19241
19242
37
    if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
19243
0
        return -1;
19244
37
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
19245
37
    state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
19246
37
    if (state->struct_rusage == NULL)
19247
0
        return -1;
19248
37
#endif
19249
37
    state->st_mode = PyUnicode_InternFromString("st_mode");
19250
37
    if (state->st_mode == NULL)
19251
0
        return -1;
19252
19253
    /* suppress "function not used" warnings */
19254
37
    {
19255
37
    int ignored;
19256
37
    fd_specified("", -1);
19257
37
    follow_symlinks_specified("", 1);
19258
37
    dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
19259
37
    dir_fd_converter(Py_None, &ignored);
19260
37
    dir_fd_unavailable(Py_None, &ignored);
19261
37
    }
19262
19263
    /*
19264
     * provide list of locally available functions
19265
     * so os.py can populate support_* lists
19266
     */
19267
37
    PyObject *list = PyList_New(0);
19268
37
    if (!list) {
19269
0
        return -1;
19270
0
    }
19271
1.22k
    for (const struct have_function *trace = have_functions; trace->label; trace++) {
19272
1.18k
        PyObject *unicode;
19273
1.18k
        if (trace->probe && !trace->probe()) continue;
19274
1.18k
        unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
19275
1.18k
        if (!unicode)
19276
0
            return -1;
19277
1.18k
        if (PyList_Append(list, unicode))
19278
0
            return -1;
19279
1.18k
        Py_DECREF(unicode);
19280
1.18k
    }
19281
19282
37
#ifndef MS_WINDOWS
19283
37
    if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
19284
0
        PyErr_SetString(PyExc_RuntimeError,
19285
0
                        "cannot read ticks_per_second");
19286
0
        return -1;
19287
0
    }
19288
37
    assert(state->ticks_per_second >= 1);
19289
37
#endif
19290
19291
37
    return PyModule_Add(m, "_have_functions", list);
19292
37
}
19293
19294
19295
static PyModuleDef_Slot posixmodile_slots[] = {
19296
    _Py_ABI_SLOT,
19297
    {Py_mod_exec, posixmodule_exec},
19298
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
19299
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
19300
    {0, NULL}
19301
};
19302
19303
static struct PyModuleDef posixmodule = {
19304
    PyModuleDef_HEAD_INIT,
19305
    .m_name = MODNAME,
19306
    .m_doc = posix__doc__,
19307
    .m_size = sizeof(_posixstate),
19308
    .m_methods = posix_methods,
19309
    .m_slots = posixmodile_slots,
19310
    .m_traverse = _posix_traverse,
19311
    .m_clear = _posix_clear,
19312
    .m_free = _posix_free,
19313
};
19314
19315
PyMODINIT_FUNC
19316
INITFUNC(void)
19317
37
{
19318
37
    return PyModuleDef_Init(&posixmodule);
19319
37
}